|
|
from dotenv import load_dotenv |
|
|
import os |
|
|
import googlemaps |
|
|
import re |
|
|
import gradio as gr |
|
|
from datetime import datetime |
|
|
|
|
|
|
|
|
dotenv_path = os.getenv('DOTENV_PATH', None) |
|
|
if dotenv_path: |
|
|
load_dotenv(dotenv_path) |
|
|
else: |
|
|
load_dotenv() |
|
|
|
|
|
api_key = os.getenv("GOOGLE_API_KEY") |
|
|
if not api_key: |
|
|
raise EnvironmentError("GOOGLE_API_KEY not found in environment variables.") |
|
|
|
|
|
gmaps = googlemaps.Client(key=api_key) |
|
|
|
|
|
|
|
|
def get_places(trip_type: str, location: str) -> list[str]: |
|
|
""" |
|
|
Fetches up to 5 popular tourist attractions matching the trip_type in the given location. |
|
|
""" |
|
|
query = f"{trip_type} places in {location}" |
|
|
results = gmaps.places(query=query, type="tourist_attraction") |
|
|
places = results.get("results", [])[:5] |
|
|
return [place.get("name") for place in places] |
|
|
|
|
|
|
|
|
def get_restaurants(location: str, prefs: str) -> list[str]: |
|
|
""" |
|
|
Fetches up to 3 restaurants near the given location matching the user preferences. |
|
|
""" |
|
|
query = f"{prefs} restaurants near {location}" |
|
|
results = gmaps.places(query=query, type="restaurant") |
|
|
restaurants = results.get("results", [])[:3] |
|
|
return [r.get("name") for r in restaurants] |
|
|
|
|
|
|
|
|
def get_directions( |
|
|
source: str, |
|
|
destination: str, |
|
|
mode: str, |
|
|
departure_time: str, |
|
|
waypoints: str = "" |
|
|
) -> str: |
|
|
""" |
|
|
Returns a Markdown-formatted string with step-by-step directions and a static map URL. |
|
|
|
|
|
Args: |
|
|
source: Starting address or place name. |
|
|
destination: Ending address or place name. |
|
|
mode: Transport mode: driving, walking, bicycling, or transit. |
|
|
departure_time: Trip start time in "YYYY-MM-DD HH:MM" format. |
|
|
waypoints: Optional comma-separated list of waypoints. |
|
|
|
|
|
Returns: |
|
|
A single Markdown string summarizing the route or an error message. |
|
|
""" |
|
|
|
|
|
try: |
|
|
dt = datetime.strptime(departure_time.strip(), "%Y-%m-%d %H:%M") |
|
|
except ValueError: |
|
|
return ( |
|
|
"**⚠️ Invalid time format.** Please enter departure time as YYYY-MM-DD HH:MM." |
|
|
) |
|
|
|
|
|
|
|
|
wp_list = [w.strip() for w in waypoints.split(",")] if waypoints else None |
|
|
|
|
|
|
|
|
directions = gmaps.directions( |
|
|
origin=source, |
|
|
destination=destination, |
|
|
mode=mode.lower(), |
|
|
departure_time=dt, |
|
|
waypoints=wp_list, |
|
|
optimize_waypoints=False, |
|
|
) |
|
|
|
|
|
if not directions: |
|
|
return "**No route found.**" |
|
|
|
|
|
|
|
|
route = directions[0] |
|
|
leg = route["legs"][0] |
|
|
|
|
|
|
|
|
summary = f"**Trip from '{leg['start_address']}' to '{leg['end_address']}'**\n" |
|
|
summary += f"- Total distance: {leg['distance']['text']}\n" |
|
|
summary += f"- Estimated duration: {leg['duration']['text']}\n\n" |
|
|
summary += "### Step-by-Step Directions:\n" |
|
|
|
|
|
for i, step in enumerate(leg["steps"], start=1): |
|
|
travel_mode = step.get("travel_mode", "").upper() |
|
|
if travel_mode == "TRANSIT": |
|
|
details = step.get("transit_details", {}) |
|
|
line = details.get("line", {}) |
|
|
vehicle = line.get("vehicle", {}).get("type", "Transit") |
|
|
line_name = line.get("short_name") or line.get("name", "") |
|
|
dep = details.get("departure_stop", {}).get("name", "") |
|
|
arr = details.get("arrival_stop", {}).get("name", "") |
|
|
stops = details.get("num_stops", "") |
|
|
instr = f"Take {vehicle} {line_name} from {dep} to {arr} ({stops} stops)" |
|
|
dist = step.get("distance", {}).get("text", "") |
|
|
else: |
|
|
raw = step.get("html_instructions", "") |
|
|
instr = re.sub(r"<[^>]+>", "", raw) |
|
|
dist = step.get("distance", {}).get("text", "") |
|
|
|
|
|
summary += f"{i}. {instr} ({dist})\n" |
|
|
|
|
|
|
|
|
poly = route.get("overview_polyline", {}).get("points") |
|
|
if poly: |
|
|
static_map_url = ( |
|
|
"https://maps.googleapis.com/maps/api/staticmap" |
|
|
f"?size=600x400&path=enc:{poly}&key={api_key}" |
|
|
) |
|
|
summary += "\n---\n" |
|
|
summary += ("Here’s a **static map snapshot** of this route:\n" + static_map_url) |
|
|
|
|
|
return summary |
|
|
|
|
|
|
|
|
|
|
|
demo = gr.Interface( |
|
|
fn=get_directions, |
|
|
inputs=[ |
|
|
gr.Textbox(label="Source Location", placeholder="e.g. New York City"), |
|
|
gr.Textbox(label="Destination Location", placeholder="e.g. Los Angeles"), |
|
|
gr.Radio( |
|
|
["driving", "walking", "bicycling", "transit"], |
|
|
label="Travel Mode", |
|
|
value="driving" |
|
|
), |
|
|
gr.Textbox( |
|
|
label="Departure Time (YYYY-MM-DD HH:MM)", |
|
|
placeholder="e.g. 2025-06-08 14:30" |
|
|
), |
|
|
gr.Textbox( |
|
|
label="Waypoints (optional, comma-separated)", |
|
|
placeholder="e.g. museum, coffee shop" |
|
|
), |
|
|
], |
|
|
outputs=gr.Markdown(label="Directions Summary"), |
|
|
title="Google Maps Directions", |
|
|
description="Get step-by-step directions between two locations using the Google Maps API." |
|
|
) |
|
|
|
|
|
|
|
|
demo.launch(mcp_server=True, share=True) |
|
|
|