Reserve California doesn't work for me.
Describe the bug
When attempting to fetch campsites from the provider "ReserveCalifornia" using the camply campsites command a KeyError is thrown, specifically "KeyError: 'reservecalifornia' ". It appears that the software is unable to correctly process the specified provider name.
Original Camply Command (with --debug)
camply --debug campsites \
--provider ReserveCalifornia \
--campground 641 \
--start-date 2023-08-30 \
--end-date 2023-09-01 \
--nights 2 \
--notifications pushover \
--polling-interval 5 \
--search-forever \
--continuous
Expected behavior <I expected the program to fetch available campsites for the specified campground (641) from the ReserveCalifornia provider for the specified date range. It should then continuously monitor for availability at this campground and notify via Pushover whenever availability is found.. >
Console Output (with --debug)
<With debug: Error: no such option: --debug>
<Without debug: KeyError: 'reservecalifornia'>
Additional context
< Add any other context about the problem here. >
I'm not able to replicate your issue. Could you include the full output with the traceback?
camply --debug campsites \
--provider ReserveCalifornia \
--campground 641 \
--start-date 2023-08-30 \
--end-date 2023-09-01 \
--nights 2 \
--notifications pushover \
--polling-interval 5 \
--search-forever \
--continuous
[2023-06-18 18:20:44] CAMPLY camply, the campsite finder ⛺️
[2023-06-18 18:20:44] DEBUG Setting up camply debugging
[2023-06-18 18:20:44] DEBUG Camply Version: 0.24.2
[2023-06-18 18:20:44] DEBUG Python Version: 3.11.3
[2023-06-18 18:20:44] DEBUG Platform: darwin
[2023-06-18 18:20:44] INFO Using Camply Provider: "ReserveCalifornia"
[2023-06-18 18:20:44] INFO 2 booking nights selected for search, ranging from 2023-08-30 to 2023-08-31
[2023-06-18 18:20:44] INFO Searching for availabilities with 2 consecutive night stays.
[2023-06-18 18:20:44] ERROR No Campsites Found Matching Your Search Criteria
[2023-06-18 18:20:44] CAMPLY Exiting camply 👋
Your command is giving me a different output, it seems like ReserveCalifornia doesn't have a campground with ID # 641. Could you by chance be searching for Rec Area # 641 (Emerald Bay State Park) @aniketde ? When you change --campground to --rec-area your command works.
I used the command you shared and I also tries it with rec-area. In both cases, I get the same error - KeyError: 'reservecalifornia'
Currently I have version 0.4.9 installed. Is there something else I should try?
Detailed error:
[2023-06-18 18:02:00] DEBUG Setting up camply debugging
[2023-06-18 18:02:00] DEBUG Camply Version: 0.4.9
[2023-06-18 18:02:00] DEBUG Python Version: 3.6.9
[2023-06-18 18:02:00] DEBUG Platform: linux
[2023-06-18 18:02:00] CAMPLY Exiting camply 👋
╭─────────────────────── Traceback (most recent call last) ────────────────────────╮
│ /home/user/.local/bin/camply:8 in main.""" │
│ ❱ 1128 │ │ return self.main(*args, **kwargs) │
│ 1129 │
│ 1130 │
│ 1131 class Command(BaseCommand): │
│ │
│ ╭─────────────── locals ───────────────╮ │
│ │ args = () │ │
│ │ kwargs = {} │ │
│ │ self = <Group camply-command-line> │ │
│ ╰──────────────────────────────────────╯ │
│ │
│ /home/user/.local/pipx/venvs/camply/lib/python3.6/site-packages/click/core.py: │
│ 1053 in main │
│ │
│ 1050 │ │ try: │
│ 1051 │ │ │ try: │
│ 1052 │ │ │ │ with self.make_context(prog_name, args, **extra) as ctx: │
│ ❱ 1053 │ │ │ │ │ rv = self.invoke(ctx) │
│ 1054 │ │ │ │ │ if not standalone_mode: │
│ 1055 │ │ │ │ │ │ return rv │
│ 1056 │ │ │ │ │ # it's not safe to ctx.exit(rv) here! │
│ │
│ ╭────────────────────────────── locals ───────────────────────────────╮ │
│ │ args = [ │ │
│ │ │ 'campsites', │ │
│ │ │ '--provider', │ │
│ │ │ 'ReserveCalifornia', │ │
│ │ │ '--rec-area', │ │
│ │ │ '641', │ │
│ │ │ '--start-date', │ │
│ │ │ '2023-08-30', │ │
│ │ │ '--end-date', │ │
│ │ │ '2023-09-01', │ │
│ │ │ '--nights', │ │
│ │ │ ... +7 │ │
│ │ ] │ │
│ │ complete_var = None │ │
│ │ ctx = <click.core.Context object at 0x7fa4e4f13828> │ │
│ │ extra = {} │ │
│ │ prog_name = 'camply' │ │
│ │ self = <Group camply-command-line> │ │
│ │ standalone_mode = True │ │
│ │ windows_expand_args = True │ │
│ ╰─────────────────────────────────────────────────────────────────────╯ │
│ │
│ /home/user/.local/pipx/venvs/camply/lib/python3.6/site-packages/click/core.py: │
│ 1659 in invoke │
│ │
│ 1656 │ │ │ │ super().invoke(ctx) │
│ 1657 │ │ │ │ sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) │
│ 1658 │ │ │ │ with sub_ctx: │
│ ❱ 1659 │ │ │ │ │ return _process_result(sub_ctx.command.invoke(sub_ctx │
│ 1660 │ │ │
│ 1661 │ │ # In chain mode we create the contexts step by step, but after th │
│ 1662 │ │ # base command has been invoked. Because at that point we do not │
│ │
│ ╭─────────────────────────────────── locals ───────────────────────────────────╮ │
│ │ class = <class 'click.core.MultiCommand'> │ │
│ │ _process_result = <function MultiCommand.invoke.
I am using Ubuntu 18.04.
It looks like most up to date version for camply is 0.24.2 but not sure why do I have 0.4.9 When I try pip install camply==0.24.2, I get the following error:
ERROR: Could not find a version that satisfies the requirement camply==0.24.2 (from versions: 0.1.0, 0.1.1, 0.1.2, 0.1.3, 0.1.4, 0.1.5, 0.1.6, 0.1.7, 0.1.8, 0.1.9, 0.1.10, 0.1.12, 0.1.13, 0.1.14, 0.1.15, 0.2.0, 0.2.1, 0.2.2, 0.2.3, 0.2.4, 0.3.0, 0.3.1, 0.4.0, 0.4.1, 0.4.2, 0.4.3, 0.4.4, 0.4.5, 0.4.6, 0.4.7, 0.4.8, 0.4.9) ERROR: No matching distribution found for camply==0.24.2
@aniketde you're using Python 3.6 which camply no longer supports since it was EOL'd back in 2021 - that's why PyPI isn't listing any recent versions of camply. Use Python 3.8 or greater to use the latest and greatest camply features.
I recommend pipx to manage the installation / virtualenv as well: https://pypa.github.io/pipx/
Thank you! This resolves the issue. But reservecalifornia doesn't look stable. It works for sometime and then gives the following error:
/home/user/.local/lib/python3.8/site-packages/camply/search/base_search.py:574 in │ │ get_matching_campsites │ │ │ │ 571 │ │ """ │ │ 572 │ │ if continuous is True or search_once is True: │ │ 573 │ │ │ try: │ │ ❱ 574 │ │ │ │ self._search_campsites_continuous( │ │ 575 │ │ │ │ │ log=log, │ │ 576 │ │ │ │ │ verbose=verbose, │ │ 577 │ │ │ │ │ polling_interval=polling_interval, │ │ │ │ /home/user/.local/lib/python3.8/site-packages/camply/search/base_search.py:508 in │ │ _search_campsites_continuous │ │ │ │ 505 │ │ continuous_search_attempts = 1 │ │ 506 │ │ while continuous_search is True: │ │ 507 │ │ │ starting_count = len(self.campsites_found) │ │ ❱ 508 │ │ │ self._continuous_search_retry( │ │ 509 │ │ │ │ log=log, │ │ 510 │ │ │ │ verbose=verbose, │ │ 511 │ │ │ │ polling_interval=polling_interval, │ │ │ │ /home/user/.local/lib/python3.8/site-packages/camply/search/base_search.py:354 in │ │ _continuous_search_retry │ │ │ │ 351 │ │ │ retry=tenacity.retry_if_exception_type(CampsiteNotFoundError), │ │ 352 │ │ │ wait=tenacity.wait.wait_fixed(int(polling_interval_minutes) * 60), │ │ 353 │ │ ) │ │ ❱ 354 │ │ matching_campsites = retryer.call( │ │ 355 │ │ │ fn=self._search_matching_campsites_available, │ │ 356 │ │ │ log=False, │ │ 357 │ │ │ verbose=False, │ │ │ │ /home/user/.local/lib/python3.8/site-packages/tenacity/init.py:379 in call │ │ │ │ 376 │ │ │ │ 377 │ │ retry_state = RetryCallState(retry_object=self, fn=fn, args=args, kwargs=kwargs) │ │ 378 │ │ while True: │ │ ❱ 379 │ │ │ do = self.iter(retry_state=retry_state) │ │ 380 │ │ │ if isinstance(do, DoAttempt): │ │ 381 │ │ │ │ try: │ │ 382 │ │ │ │ │ result = fn(*args, **kwargs) │ │ │ │ /home/user/.local/lib/python3.8/site-packages/tenacity/init.py:314 in iter │ │ │ │ 311 │ │ │ │ 312 │ │ is_explicit_retry = fut.failed and isinstance(fut.exception(), TryAgain) │ │ 313 │ │ if not (is_explicit_retry or self.retry(retry_state)): │ │ ❱ 314 │ │ │ return fut.result() │ │ 315 │ │ │ │ 316 │ │ if self.after is not None: │ │ 317 │ │ │ self.after(retry_state) │ │ │ │ /usr/lib/python3.8/concurrent/futures/_base.py:437 in result │ │ │ │ 434 │ │ │ │ if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]: │ │ 435 │ │ │ │ │ raise CancelledError() │ │ 436 │ │ │ │ elif self._state == FINISHED: │ │ ❱ 437 │ │ │ │ │ return self.__get_result() │ │ 438 │ │ │ │ │ │ 439 │ │ │ │ self._condition.wait(timeout) │ │ 440 │ │ │ │ /usr/lib/python3.8/concurrent/futures/_base.py:389 in __get_result │ │ │ │ 386 │ def __get_result(self): │ │ 387 │ │ if self._exception: │ │ 388 │ │ │ try: │ │ ❱ 389 │ │ │ │ raise self._exception │ │ 390 │ │ │ finally: │ │ 391 │ │ │ │ # Break a reference cycle with the exception in self._exception │ │ 392 │ │ │ │ self = None │ │ │ │ /home/user/.local/lib/python3.8/site-packages/tenacity/init.py:382 in call │ │ │ │ 379 │ │ │ do = self.iter(retry_state=retry_state) │ │ 380 │ │ │ if isinstance(do, DoAttempt): │ │ 381 │ │ │ │ try: │ │ ❱ 382 │ │ │ │ │ result = fn(*args, **kwargs) │ │ 383 │ │ │ │ except BaseException: # noqa: B902 │ │ 384 │ │ │ │ │ retry_state.set_exception(sys.exc_info()) # type: ignore[arg-type] │ │ 385 │ │ │ │ else: │ │ │ │ /home/user/.local/lib/python3.8/site-packages/camply/search/base_search.py:246 in │ │ _search_matching_campsites_available │ │ │ │ 243 │ │ List[AvailableCampsite] │ │ 244 │ │ """ │ │ 245 │ │ matching_campgrounds = [] │ │ ❱ 246 │ │ for camp in self.get_all_campsites(): │ │ 247 │ │ │ if all( │ │ 248 │ │ │ │ [ │ │ 249 │ │ │ │ │ self._compare_date_overlap(campsite=camp) is True, │ │ │ │ /home/user/.local/lib/python3.8/site-packages/camply/search/search_usedirect.py:139 in │ │ get_all_campsites │ │ │ │ 136 │ │ │ │ │ f"{month.strftime('%B, %Y')}" │ │ 137 │ │ │ │ ) │ │ 138 │ │ │ │ end_date = month + relativedelta(months=1) - timedelta(days=1) │ │ ❱ 139 │ │ │ │ campsites = self.campsite_finder.get_campsites( │ │ 140 │ │ │ │ │ campground_id=campground.facility_id, │ │ 141 │ │ │ │ │ start_date=month, │ │ 142 │ │ │ │ │ end_date=end_date, │ │ │ │ /home/user/.local/lib/python3.8/site-packages/camply/providers/usedirect/usedirect.py:388 in │ │ get_campsites │ │ │ │ 385 │ │ List[AvailableCampsite] │ │ 386 │ │ """ │ │ 387 │ │ self.refresh_metadata() │ │ ❱ 388 │ │ availability_response = self.get_campsites_response( │ │ 389 │ │ │ campground_id=campground_id, │ │ 390 │ │ │ start_date=start_date, │ │ 391 │ │ │ end_date=end_date, │ │ │ │ /home/user/.local/lib/python3.8/site-packages/ratelimit/decorators.py:113 in wrapper │ │ │ │ 110 │ │ ''' │ │ 111 │ │ while True: │ │ 112 │ │ │ try: │ │ ❱ 113 │ │ │ │ return func(*args, **kargs) │ │ 114 │ │ │ except RateLimitException as exception: │ │ 115 │ │ │ │ time.sleep(exception.period_remaining) │ │ 116 │ return wrapper │ │ │ │ /home/user/.local/lib/python3.8/site-packages/ratelimit/decorators.py:80 in wrapper │ │ │ │ 77 │ │ │ │ │ │ raise RateLimitException('too many calls', period_remaining) │ │ 78 │ │ │ │ │ return │ │ 79 │ │ │ │ │ ❱ 80 │ │ │ return func(*args, **kargs) │ │ 81 │ │ return wrapper │ │ 82 │ │ │ 83 │ def __period_remaining(self): │ │ │ │ /home/user/.local/lib/python3.8/site-packages/camply/providers/usedirect/usedirect.py:330 in │ │ get_campsites_response │ │ │ │ 327 │ │ response.raise_for_status() │ │ 328 │ │ response_json = response.json() │ │ 329 │ │ try: │ │ ❱ 330 │ │ │ return UseDirectAvailabilityResponse(**response.json()) │ │ 331 │ │ except ValidationError as e: │ │ 332 │ │ │ raise │ │ 333 │ │ │ error_message = ( │ │ │ │ in pydantic.main.BaseModel.init:341 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ ValidationError: 3 validation errors for UseDirectAvailabilityResponse Filters none is not an allowed value (type=type_error.none.not_allowed) Facility -> SeasonDates none is not an allowed value (type=type_error.none.not_allowed) Facility -> TrafficStatuses none is not an allowed value (type=type_error.none.not_allowed)
The above exception was the direct cause of the following exception:
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /home/user/.local/bin/camply:8 in
@aniketde try again, I just released a fix for that moments ago as part of a different issue actually. You'll need to upgrade camply, again 🙃
Thank you. I missed this comment. I tried the same thing again but it exists after checking once (does not search forever).
camply --debug campsites
--provider ReserveCalifornia
--campground 641
--start-date 2023-08-30
--end-date 2023-09-01
--nights 2
--notifications pushover
--polling-interval 5
--search-forever
--continuous
[2023-07-10 17:31:49] CAMPLY camply, the campsite finder ⛺️
[2023-07-10 17:31:49] DEBUG Setting up camply debugging
[2023-07-10 17:31:49] DEBUG Camply Version: 0.27.0
[2023-07-10 17:31:49] DEBUG Python Version: 3.8.3
[2023-07-10 17:31:49] DEBUG Platform: linux
[2023-07-10 17:31:49] INFO Using Camply Provider: "ReserveCalifornia"
[2023-07-10 17:31:49] INFO 2 booking nights selected for search, ranging from 2023-08-30 to 2023-08-31
[2023-07-10 17:31:49] INFO Searching for availabilities with 2 consecutive night stays.
[2023-07-10 17:31:49] ERROR No Campsites Found Matching Your Search Criteria
[2023-07-10 17:31:49] CAMPLY Exiting camply 👋
Circling back to an earlier comment on this thread
it seems like ReserveCalifornia doesn't have a campground with ID # 641. Could you by chance be searching for Rec Area # 641 (Emerald Bay State Park) @aniketde ? When you change --campground to --rec-area your command works.
Let me know if that resolves it for you.
I was able to run when I change --campground to --rec-area. It works :). I ran it overnight but the script fails after 5-6 hours. For example error was: "504 Server Error: Gateaway Time-out for url: https://calirdr.usedirect.com/rdr/rdr/search/grid". May be it's an issue from reservecalifornia side?
Alright, camply wasn't actually handling server exit codes at all for UseDirect providers (ReserveCalifornia and more). I've released camply v0.29.0 which should make ReserveCalifornia a whole lot more reliable. When it encounters a server status code, like a 503 response, it will retry for up to 100 minutes using exponential backoff.
This should be good to go🤞
👀 any word on this? I'm thinking ReserveCalifornia is looking more resilient?
Sorry for the delayed response! It is now stable and works!
The only issue now is that the script shows what's available but not what's cancelled and will be available at 8 am next day. Reserve California works differently compared to recreation.gov. When there are cancellations, the site is locked until 8am next day. It turns green/available at 8 am and stays green until someone books it. May be you just need to check for locked sites apart from green/available sites? Does this make sense?
P.S. Site could also be locked if the campground or campsite itself is closed.