""" check_maps.py — is GOOGLE_MAPS_API_KEY wired up, and what does a search return? By default this does nothing but check key presence (free). A live search costs against the Places API (New) free credit / your billing account, so it only runs when you pass --query. uv run python scripts/check_maps.py uv run python scripts/check_maps.py --query "custom golf cart dealers in Texas" --max 5 uv run python scripts/check_maps.py --query "yacht dealers in Miami" --max 10 --raw uv run python scripts/check_maps.py --query "custom golf carts Austin" --call-only --call-only also keeps rows that have a phone but no website (what the "call-only" checkbox in Lead Finder does) and shows how many rows carry a phone at all. Exit 0 means the key authenticates and returned at least one row with a website. A row with no website is dropped by maps_source.find_businesses() (it can't be scanned/qualified downstream) and only counted, not printed. """ from __future__ import annotations import argparse import json import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) # Imported for its side effect: app.config is the ONLY place that calls # load_dotenv(), so .env is never read into os.environ unless something # imports this module first (directly or transitively). maps_source / # secrets do not import it, so without this line a key that is genuinely # in .env would still read back as "not configured". from app.config import settings # noqa: E402,F401 from app.services import maps_source # noqa: E402 from app.services.secrets import get_google_maps_key # noqa: E402 def main() -> int: ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) ap.add_argument("--query", default="", help="Places text search, e.g. 'custom golf cart dealers in Texas'") ap.add_argument("--max", type=int, default=5, help="max results with a website (default 5)") ap.add_argument("--raw", action="store_true", help="dump the raw row list as JSON") ap.add_argument("--call-only", action="store_true", help="also keep rows with a phone but no website") args = ap.parse_args() key = get_google_maps_key() print(f"1. key configured : {'yes' if key else 'NO — GOOGLE_MAPS_API_KEY is empty'}") if not key: return 1 if not args.query: print("\nNo --query given — pass one to actually call the API (spends against your") print("Places API (New) free credit / billing account).") return 0 print(f"\n2. searchText: {args.query!r} (max {args.max})") rows, dropped = maps_source.find_businesses( args.query, args.max, require_website=not args.call_only ) with_phone = sum(1 for r in rows if r.get("phone")) no_site = sum(1 for r in rows if not r["company_website"]) print( f" {len(rows)} row(s) kept ({with_phone} with a phone, {no_site} with no website), " f"{dropped} dropped" ) for r in rows: print( f" - {r['company_name']:32.32} | {r['company_website']:40.40} | " f"{r.get('phone') or '-'}" ) if args.raw: print("\n raw:", json.dumps(rows, indent=2)) if not rows: print("\n -> nothing usable came back. Check the key is restricted to \"Places API") print(" (New)\", billing is enabled on the Cloud project, and the query is broad enough.") return 1 return 0 if __name__ == "__main__": sys.exit(main())