示例#1
0
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
示例#2
0
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
示例#3
0
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
示例#4
0
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
示例#5
0
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
示例#6
0
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
示例#7
0
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