def query_traveltime_api(startloc: Union[str, LatLonTuple], endloc: Union[str, LatLonTuple], mode: str = "walking") -> Optional[Dict]: """ Look up travel time between two places, given a particular mode of transportation, i.e. one of the modes in _TRAVEL_MODES. The location arguments can be names, to be resolved by the API, or a tuple of coordinates, e.g. (64.156742, -21.949426) Uses Google Maps' Distance Matrix API. For more info, see: https://developers.google.com/maps/documentation/distance-matrix/intro """ assert mode in _TRAVEL_MODES # Load API key key = google_api_key() if not key: # No key, can't query the API logging.warning("No API key for travel time lookup") return None # Format query string args p1 = "{0},{1}".format( *startloc) if isinstance(startloc, tuple) else startloc p2 = "{0},{1}".format(*endloc) if isinstance(endloc, tuple) else endloc # Send API request url = _MAPS_API_TRAVELTIME_URL.format(p1, p2, mode, key) res = query_json_api(url) return res
def get_staticmap_image( latitude: float, longitude: float, zoom: int = 6, width: int = 180, height: int = 180, ) -> Optional[BytesIO]: """ Request image from Google Static Maps API, return image data as bytes """ key = google_api_key() if not key: return None url = STATICMAP_URL.format(zoom, width, height, key, latitude, longitude) # TODO: Use urllib instead of requests here try: r = requests.get(url, stream=True) except Exception as e: logging.warning(str(e)) return None if r.status_code == 200: r.raw.decode_content = True return BytesIO(r.raw.data) logging.warning("Status {0} when requesting static map image".format(r.status_code)) return None
def query_geocode_api_coords(lat: float, lon: float) -> Optional[Dict]: """ Look up coordinates in Google's geocode API. """ # Load API key key = google_api_key() if not key: # No key, can't query Google location API logging.warning("No API key for coordinates lookup") return None # Send API request res = query_json_api(_MAPS_API_COORDS_URL.format(lat, lon, key)) return res
def query_geocode_api_addr(addr: str) -> Optional[Dict]: """ Look up address in Google's geocode API. """ # Load API key key = google_api_key() if not key: # No key, can't query the API logging.warning("No API key for address lookup") return None # Send API request url = _MAPS_API_ADDR_URL.format(addr, key) res = query_json_api(url) return res
def query_places_api( placename: str, userloc: Optional[LatLonTuple] = None, radius: float = _PLACES_LOCBIAS_RADIUS, fields: Optional[str] = None, ) -> Optional[Dict]: """ Look up a placename in Google's Places API. For details, see: https://developers.google.com/places/web-service/search """ if not fields: # Default fields requested from API fields = "place_id,opening_hours,geometry/location,formatted_address" # Load API key key = google_api_key() if not key: # No key, can't query the API logging.warning("No API key for Google Places lookup") return None # Generate query string qdict = { "input": placename, "inputtype": "textquery", "fields": fields, "key": key, "language": "is", "region": "is", } if userloc: qdict["locationbias"] = "circle:{0}@{1},{2}".format( radius, userloc[0], userloc[1]) qstr = urlencode(qdict) # Send API request url = _PLACES_API_URL.format(qstr) res = query_json_api(url) return res
def query_place_details(place_id: str, fields: Optional[str] = None) -> Optional[Dict]: """ Look up place details by ID in Google's Place Details API. If "fields" parameter is omitted, *all* fields are returned. For details, see https://developers.google.com/places/web-service/details """ # Load API key key = google_api_key() if not key: # No key, can't query the API logging.warning("No API key for Google Place Details lookup") return None # Generate query string qdict = {"place_id": place_id, "key": key, "language": "is"} if fields: qdict["fields"] = fields qstr = urlencode(qdict) # Send API request url = _PLACEDETAILS_API_URL.format(qstr) res = query_json_api(url) return res
def get_image_url( name: str, *, hints: List = [], size: str = "large", thumb: bool = False, enclosing_session: Optional[SessionContext] = None, cache_only: bool = False, ): """ Use Google Custom Search API to obtain an image corresponding to a (person) name """ jdoc = None ctype = _CTYPE + size with SessionContext(commit=True, session=enclosing_session) as session: q = ( session.query(Link.content, Link.timestamp) .filter(Link.ctype == ctype) .filter(Link.key == name) .one_or_none() ) if q is not None: # Found in cache. If the result is old, purge it period = timedelta(days=_CACHE_EXPIRATION_DAYS) expired = datetime.utcnow() - q.timestamp > period if expired and not cache_only: _purge_single(name, ctype=ctype, enclosing_session=session) else: jdoc = q.content if not jdoc and cache_only: return None if not jdoc: # Not found in cache: prepare to ask Google key = google_api_key() if not key: # No API key: can't ask for an image logging.warning("No API key for image lookup") return None # Assemble the query parameters search_str = '"{0}" {1}'.format(name, " ".join(hints)).strip() q = dict( q=search_str, num=_NUM_IMG_URLS, start=1, imgSize=size, # imgType = "face", # Only images with faces lr="lang_is", # Higher priority for Icelandic language pages gl="is", # Higher priority for .is results searchType="image", cx=_CX, key=key, ) if Settings.DEBUG: print( "Sending Google image search request for '{0}'".format(search_str) ) jdoc = _server_query("https://www.googleapis.com/customsearch/v1", q) if Settings.DEBUG: print("Back from Google image search for '{0}'".format(search_str)) if jdoc: # Store in the cache lnk = Link( ctype=ctype, key=name, content=jdoc, timestamp=datetime.utcnow() ) session.add(lnk) if not jdoc: return None answer = json.loads(jdoc) if ( answer and "items" in answer and answer["items"] and "link" in answer["items"][0] ): blacklist = _blacklisted_urls_for_key(name, enclosing_session=session) for item in answer["items"]: k = item["link"] if not thumb else item["image"]["thumbnailLink"] if k and item["link"] not in blacklist: image = item["image"] h = image["height"] if not thumb else image["thumbnailHeight"] w = image["width"] if not thumb else image["thumbnailWidth"] return Img(k, w, h, image["contextLink"], item["displayLink"], name) # No answer that makes sense return None