Skip to content

Add geo-based campsite search and campsite-type exclusion#414

Open
winfij wants to merge 15 commits into
juftin:mainfrom
winfij:geo-search
Open

Add geo-based campsite search and campsite-type exclusion#414
winfij wants to merge 15 commits into
juftin:mainfrom
winfij:geo-search

Conversation

@winfij

@winfij winfij commented Jun 11, 2026

Copy link
Copy Markdown

Summary

Adds geo-based campsite search and campsite-type exclusion to camply.

  • Geo search: new --near / --latitude / --longitude / --radius CLI flags on the campsites command and matching YAML config fields, backed by a new SearchGeo multi-provider orchestrator using Nominatim geocoding (geopy) and haversine distance.
  • Type exclusion: excluded_campsite_types (YAML) / --exclude-type (CLI) filtering in BaseCampingSearch, with comma-separated list support.
  • Provider coordinates: populate RecreationArea/CampgroundFacility coordinates in UseDirect providers; allow RecreationDotGov.find_campgrounds to accept geo lat/lon/radius kwargs.
  • Distance is now shown in geo search results.

Fixes

  • Handle SMTP auth errors gracefully instead of crashing.
  • Skip UseDirect providers whose metadata endpoint is unavailable.
  • Implement list_campsite_units on SearchGeo to satisfy the abstract method.
  • Correct isort ordering and a CamplyError f-string in the usedirect provider.

Test Plan

  • New tests: tests/utils/test_geo_utils.py, tests/search_providers/test_geo_search.py, tests/cli/test_campsites.py.
  • pytest passes.
  • Manual smoke test of camply campsites --near "..." --radius 50.

winfij and others added 15 commits June 10, 2026 20:19
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…mpsites command

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wraps provider.refresh_metadata() in try/except in _build_usedirect_search
so that providers returning empty or malformed HTTP responses (JSONDecodeError)
are logged as warnings and skipped rather than crashing the entire geo search.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…omma list support

- AvailableCampsite gains distance_miles field (optional, None for non-geo searches)
- SearchGeo builds facility_id→distance map during provider fan-out and annotates
  each result in get_all_campsites() via pydantic .copy()
- RecreationDotGov CampgroundFacility now captures FacilityLatitude/Longitude from
  RIDB API response so geo distances can be computed for recdotgov campgrounds
- _log_availabilities appends "(X.X mi)" to each campground line when distance is set
- exclude-type filter now also checks facility_name so --exclude-type horse removes
  campgrounds named "Horse Camp" (not just campsites typed HORSE)
- --exclude-type accepts comma-separated values: --exclude-type group,horse

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
EmailNotifications.__init__ now catches SMTPException and raises CamplyError
with a user-friendly message. CamplyError is now caught at the CLI top level
and logged cleanly (no traceback) before exiting with code 1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant