GMaps API searchText

This commit is contained in:
itskovacs 2025-11-01 19:32:22 +01:00
parent bd8e0c2578
commit 028b9ab64f
3 changed files with 38 additions and 25 deletions

View File

@ -97,13 +97,13 @@ class PendingTOTP(BaseModel):
class GooglePlaceResult(BaseModel):
id: str | None = None
name: str | None = None
lat: float | None = None
lng: float | None = None
price: float | None = None
allowsdog: bool | None = None
description: str | None = None
types: list[str] = []
allows_dogs: bool | None = None
class ImageBase(SQLModel):
@ -198,6 +198,7 @@ class UserUpdate(UserBase):
map_lng: float | None = None
currency: str | None = None
do_not_display: list[str] | None = None
google_apikey: str | None = None
class UserRead(UserBase):
@ -219,7 +220,7 @@ class UserRead(UserBase):
mode_dark=obj.mode_dark,
mode_gpx_in_place=obj.mode_gpx_in_place,
totp_enabled=obj.totp_enabled,
google_apikey=True if obj.google_apikey else False
google_apikey=True if obj.google_apikey else False,
)

View File

@ -6,12 +6,14 @@ from sqlmodel import select
from ..config import settings
from ..deps import SessionDep, get_current_username
from ..models.models import (Category, Image, GooglePlaceResult, Place, PlaceCreate,
PlaceRead, PlacesCreate, PlaceUpdate)
from ..models.models import (Category, GooglePlaceResult, Image, Place,
PlaceCreate, PlaceRead, PlacesCreate, PlaceUpdate,
User)
from ..security import verify_exists_and_owns
from ..utils.gmaps import (compute_avg_price, compute_description,
gmaps_textsearch)
from ..utils.utils import (b64img_decode, download_file, patch_image,
save_image_to_file)
from ..utils.gmaps import compute_avg_price, gmaps_textsearch
router = APIRouter(prefix="/api/places", tags=["places"])
@ -111,25 +113,26 @@ async def create_places(
return [PlaceRead.serialize(p) for p in new_places]
@router.get("/google-search", response_model=list[GooglePlaceResult])
async def google_search_text(q: str, session: SessionDep, current_user: Annotated[str, Depends(get_current_username)]) -> list[GooglePlaceResult]:
@router.get("/google-search")
async def google_search_text(
q: str, session: SessionDep, current_user: Annotated[str, Depends(get_current_username)]
):
db_user = session.get(User, current_user)
if not db_user or not db_user.google_apikey:
raise HTTPException(status_code=400, detail="Google Maps API key not configured")
data = await gmaps_textsearch(q, db_user.google_apikey)
results = []
for place in data:
loc = place.get("location", {})
result = GooglePlaceResult(
id=place.get("id"),
name=place.get("displayName", {}).get('text'),
lat=loc.get("latitude"),
lng=loc.get("longitude"),
name=place.get("displayName", {}).get("text"),
lat=loc.get("latitude", None),
lng=loc.get("longitude", None),
price=compute_avg_price(place.get("priceRange")),
types=place.get("types", []),
allow_dogs=place.get("allowDogs")
allowdog=place.get("allowDogs"),
description=compute_description(place),
)
results.append(result)

View File

@ -1,9 +1,5 @@
# https://developers.google.com/maps/documentation/places/web-service/nearby-search
# https://developers.google.com/maps/documentation/places/web-service/text-search
# https://developers.google.com/maps/documentation/places/web-service/place-details
# https://developers.google.com/maps/documentation/places/web-service/place-photos
from typing import Any
import httpx
from fastapi import HTTPException
@ -25,15 +21,28 @@ def compute_avg_price(price_range: dict | None) -> float | None:
return None
def compute_description(place: dict[str, Any]):
description = ""
address = place.get("formattedAddress")
phone = place.get("internationalPhoneNumber")
website = place.get("websiteUri")
if address:
description += f"{address}\n"
if phone:
description += f"Phone: {phone}\n"
if website:
description += f"Website: {website}"
return description.rstrip()
async def gmaps_textsearch(search: str, api_key: str) -> list[dict[str, Any]]:
url = "https://places.googleapis.com/v1/places:searchText"
body = {
"textQuery": search
}
body = {"textQuery": search}
headers = {
"Content-Type": "application/json",
"X-Goog-Api-Key": api_key,
"X-Goog-FieldMask": "places.id,places.types,places.location,places.priceRange,places.displayName,places.allowsDogs"
"X-Goog-FieldMask": "places.id,places.types,places.location,places.priceRange,places.formattedAddress,places.websiteUri,places.internationalPhoneNumber,places.displayName,places.allowsDogs",
}
try:
@ -41,6 +50,6 @@ async def gmaps_textsearch(search: str, api_key: str) -> list[dict[str, Any]]:
response = await client.post(url, json=body, headers=headers)
response.raise_for_status()
data = response.json()
return data.get('places', [])
return data.get("places", [])
except Exception:
raise HTTPException(status_code=400, detail="Bad Request")