public static SearchResult searchByGeocodes(final Set<String> geocodes) { final SearchResult result = new SearchResult(); final Set<String> filteredGeocodes = GCConnector.getInstance().handledGeocodes(geocodes); if (filteredGeocodes.isEmpty()) { return result; } final String geocodeList = StringUtils.join(filteredGeocodes.toArray(), "|"); try { final Parameters params = new Parameters("i", geocodeList, "_", String.valueOf(System.currentTimeMillis())); params.add("app", "cgeo"); final String referer = GCConstants.URL_LIVE_MAP_DETAILS; final String data = Tile.requestMapInfo(referer, params, referer).toBlocking().value(); // Example JSON information // {"status":"success", // "data":[{"name":"Mission: // Impossible","gc":"GC1234","g":"34c2e609-5246-4f91-9029-d6c02b0f2a82","available":true,"archived":false,"subrOnly":false,"li":false,"fp":"5","difficulty":{"text":3.5,"value":"3_5"},"terrain":{"text":1.0,"value":"1"},"hidden":"7/23/2001","container":{"text":"Regular","value":"regular.gif"},"type":{"text":"Unknown Cache","value":8},"owner":{"text":"Ca$h_Cacher","value":"2db18e69-6877-402a-848d-6362621424f6"}}, // {"name":"HP: Hannover - // Sahlkamp","gc":"GC2Q97X","g":"a09149ca-00e0-4aa2-b332-db2b4dfb18d2","available":true,"archived":false,"subrOnly":false,"li":false,"fp":"0","difficulty":{"text":1.0,"value":"1"},"terrain":{"text":1.5,"value":"1_5"},"hidden":"5/29/2011","container":{"text":"Small","value":"small.gif"},"type":{"text":"Traditional Cache","value":2},"owner":{"text":"GeoM@n","value":"1deaa69e-6bcc-421d-95a1-7d32b468cb82"}}] // } final ObjectNode json = (ObjectNode) JsonUtils.reader.readTree(data); final String status = json.path("status").asText(); if (StringUtils.isBlank(status)) { throw new ParserException("No status inside JSON"); } if ("success".compareTo(status) != 0) { throw new ParserException("Wrong status inside JSON"); } final ArrayNode dataArray = (ArrayNode) json.get("data"); if (dataArray == null) { throw new ParserException("No data inside JSON"); } final List<Geocache> caches = new ArrayList<>(); for (final JsonNode dataObject : dataArray) { final Geocache cache = new Geocache(); cache.setName(dataObject.path("name").asText()); cache.setGeocode(dataObject.path("gc").asText()); cache.setGuid(dataObject.path("g").asText()); // 34c2e609-5246-4f91-9029-d6c02b0f2a82" cache.setDisabled(!dataObject.path("available").asBoolean()); cache.setArchived(dataObject.path("archived").asBoolean()); cache.setPremiumMembersOnly(dataObject.path("subrOnly").asBoolean()); // "li" seems to be "false" always cache.setFavoritePoints(Integer.parseInt(dataObject.path("fp").asText())); cache.setDifficulty( Float.parseFloat(dataObject.path("difficulty").path("text").asText())); // 3.5 cache.setTerrain(Float.parseFloat(dataObject.path("terrain").path("text").asText())); // 1.5 cache.setHidden( GCLogin.parseGcCustomDate( dataObject.path("hidden").asText(), "MM/dd/yyyy")); // 7/23/2001 cache.setSize( CacheSize.getById(dataObject.path("container").path("text").asText())); // Regular cache.setType( CacheType.getByPattern( dataObject.path("type").path("text").asText())); // Traditional Cache cache.setOwnerDisplayName(dataObject.path("owner").path("text").asText()); caches.add(cache); } result.addAndPutInCache(caches); } catch (ParserException | ParseException | IOException | NumberFormatException ignored) { result.setError(StatusCode.UNKNOWN_ERROR); } return result; }
/** * Searches the view port on the live map for caches. The strategy dictates if only live map * information is used or if an additional searchByCoordinates query is issued. * * @param viewport Area to search * @param tokens Live map tokens * @param strategy Strategy for data retrieval and parsing, @see Strategy */ @NonNull private static SearchResult searchByViewport( final Viewport viewport, final MapTokens tokens, final LivemapStrategy strategy) { Log.d("GCMap.searchByViewport" + viewport.toString()); final SearchResult searchResult = new SearchResult(); if (Settings.isDebug()) { searchResult.setUrl(viewport.getCenter().format(Format.LAT_LON_DECMINUTE)); } if (strategy.flags.contains(LivemapStrategy.Flag.LOAD_TILES)) { final Set<Tile> tiles = Tile.getTilesForViewport(viewport); if (Settings.isDebug()) { searchResult.setUrl( new StringBuilder() .append(tiles.iterator().next().getZoomLevel()) .append(Formatter.SEPARATOR) .append(searchResult.getUrl()) .toString()); } for (final Tile tile : tiles) { if (!Tile.cache.contains(tile)) { final Parameters params = new Parameters( "x", String.valueOf(tile.getX()), "y", String.valueOf(tile.getY()), "z", String.valueOf(tile.getZoomLevel()), "ep", "1", "app", "cgeo"); if (tokens != null) { params.put("k", tokens.getUserSession(), "st", tokens.getSessionToken()); } if (Settings.isExcludeMyCaches()) { // works only for PM params.put("hf", "1", "hh", "1"); // hide found, hide hidden } // ect: exclude cache type (probably), comma separated list if (Settings.getCacheType() != CacheType.ALL) { params.put("ect", getCacheTypeFilter(Settings.getCacheType())); } if (tile.getZoomLevel() != 14) { params.put("_", String.valueOf(System.currentTimeMillis())); } // The PNG must be requested first, otherwise the following request would always return // with 204 - No Content final Single<Bitmap> bitmapObs = Tile.requestMapTile(params).onErrorResumeNext(Single.<Bitmap>just(null)); final Single<String> dataObs = Tile.requestMapInfo(GCConstants.URL_MAP_INFO, params, GCConstants.URL_LIVE_MAP) .onErrorResumeNext(Single.just("")); try { Single.zip( bitmapObs, dataObs, new Func2<Bitmap, String, Void>() { @Override public Void call(final Bitmap bitmap, final String data) { final boolean validBitmap = bitmap != null && bitmap.getWidth() == Tile.TILE_SIZE && bitmap.getHeight() == Tile.TILE_SIZE; if (StringUtils.isEmpty(data)) { Log.w( "GCMap.searchByViewport: No data from server for tile (" + tile.getX() + "/" + tile.getY() + ")"); } else { final SearchResult search = parseMapJSON(data, tile, validBitmap ? bitmap : null, strategy); if (CollectionUtils.isEmpty(search.getGeocodes())) { Log.e( "GCMap.searchByViewport: No cache parsed for viewport " + viewport); } else { synchronized (searchResult) { searchResult.addSearchResult(search); } } synchronized (Tile.cache) { Tile.cache.add(tile); } } // release native bitmap memory if (bitmap != null) { bitmap.recycle(); } return null; } }) .toBlocking() .value(); } catch (final Exception e) { Log.e("GCMap.searchByViewPort: connection error"); } } } // Check for vanished found caches if (tiles.iterator().next().getZoomLevel() >= Tile.ZOOMLEVEL_MIN_PERSONALIZED) { searchResult.addFilteredGeocodes( DataStore.getCachedMissingFromSearch( searchResult, tiles, GCConnector.getInstance(), Tile.ZOOMLEVEL_MIN_PERSONALIZED - 1)); } } if (strategy.flags.contains(Flag.SEARCH_NEARBY) && Settings.isGCPremiumMember()) { final Geopoint center = viewport.getCenter(); if ((lastSearchViewport == null) || !lastSearchViewport.contains(center)) { // FIXME We don't have a RecaptchaReceiver!? final SearchResult search = GCParser.searchByCoords(center, Settings.getCacheType(), false, null); if (search != null && !search.isEmpty()) { final Set<String> geocodes = search.getGeocodes(); lastSearchViewport = DataStore.getBounds(geocodes); searchResult.addGeocodes(geocodes); } } } return searchResult; }