Skip to content

Commit

Permalink
camply - 0.1.6 (#28)
Browse files Browse the repository at this point in the history
* docker-compose.yml example

* feature/booking nights (#25)

* feature progress

* campsite compilation

* silent notification dash

* flaking

* polish

* README.md tidy

* test update
  • Loading branch information
juftin authored Jun 24, 2021
1 parent 55b76fa commit 3d48cac
Show file tree
Hide file tree
Showing 27 changed files with 601 additions and 138 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@ jobs:
camply campgrounds --search "Fire Tower Lookout" --state CA
camply campsites --rec-area 2991 --start-date 2021-09-15 --end-date 2021-09-16
camply campsites --campground 252037 --start-date 2021-09-15 --end-date 2021-09-16
camply campsites --provider yellowstone --start-date 2021-09-10 --end-date 2021-09-15 --campground YLYC:RV
camply campsites --yml-config tests/yml/example_search.yml
camply campsites --yml-config tests/yml/example_search.yml
camply campsites --campground 232045 --start-date 2021-07-15 --end-date 2021-09-30 --nights 5
camply campsites --provider yellowstone --start-date 2021-10-10 --end-date 2021-10-15 --nights 2
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ To request new features or bugfixes the
[Camply Feedback for v1.0.0 Discussion](https://github.com/juftin/camply/discussions/12) is the best
place to go.

## [0.1.6] - 2021-06-24

### Added

- Ability to search for campsites by number of consecutive night stays.

## [0.1.5] - 2021-06-02

### Added
Expand Down Expand Up @@ -76,6 +82,8 @@ place to go.

[unreleased]: https://github.com/juftin/camply/compare/main...integration

[0.1.6]: https://github.com/juftin/camply/compare/v0.1.5...v0.1.6

[0.1.5]: https://github.com/juftin/camply/compare/v0.1.4...v0.1.5

[0.1.4]: https://github.com/juftin/camply/compare/v0.1.3...v0.1.4
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM python:3.8-slim

MAINTAINER Justin Flannery <[email protected]>
LABEL version="0.1.5"
LABEL version="0.1.6"
LABEL description="camply, the campsite finder"

COPY . /tmp/camply
Expand Down
79 changes: 60 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ ___________
+ [Searching for a Campsite by Campground ID](#searching-for-a-campsite-by-campground-id)
+ [Continuously Searching for A Campsite](#continuously-searching-for-a-campsite)
+ [Continue Looking After The First Match Is Found](#continue-looking-after-the-first-match-is-found)
+ [Send a Push Notification](#send-a-push-notification)
+ [Send a Push Notification](#send-a-push-notification)
+ [Look for Weekend Campsite Availabilities](#look-for-weekend-campsite-availabilities)
+ [Look for Consecutive Nights at the Same Campsite](#look-for-consecutive-nights-at-the-same-campsite)
+ [Look for a Campsite Inside of Yellowstone](#look-for-a-campsite-inside-of-yellowstone)
+ [Look for a Campsite Across Multiple Recreation areas](#look-for-a-campsite-across-multiple-recreation-areas)
+ [Using a YML Configuration file to search for campsites](#using-a-yml-configuration-file-to-search-for-campsites)
Expand Down Expand Up @@ -125,40 +126,55 @@ and a link to make the booking. Required parameters include `--start-date`, `--e
#### Arguments:

* `--rec-area`: `RECREATION_AREA_ID`
+ Add Recreation Areas (comprised of campgrounds) by ID. [**_example_](#searching-for-a-campsite)
+ Add Recreation Areas (comprised of campgrounds) by ID.
[**_example_](#searching-for-a-campsite)
* `--campground`: `CAMPGROUND_ID`
+ Add individual Campgrounds by ID. [**_example_](#searching-for-a-campsite-by-campground-id)
+ Add individual Campgrounds by ID.
[**_example_](#searching-for-a-campsite-by-campground-id)
* `--start-date`: `START_DATE`
+ `YYYY-MM-DD`: Start of Search window. You will be arriving this day. [**_example_](#searching-for-a-campsite)
+ `YYYY-MM-DD`: Start of Search window. You will be arriving this day.
[**_example_](#searching-for-a-campsite)
* `--end-date`: `END_DATE`
+ `YYYY-MM-DD`: End of Search window. You will be leaving the following day. [**_example_](#searching-for-a-campsite)
+ `YYYY-MM-DD`: End of Search window. You will be leaving the following day.
[**_example_](#searching-for-a-campsite)
* `--weekends`
+ Only search for weekend bookings (Fri/Sat nights). [**_example_](#look-for-weekend-campsite-availabilities)
+ Only search for weekend bookings (Fri/Sat nights).
[**_example_](#look-for-weekend-campsite-availabilities)
* `--nights`
+ Search for campsite stays with consecutive nights. Defaults to 1 which returns all campsites
found.
[**_example_](#look-for-consecutive-nights-at-the-same-campsite)
* `--provider`: `PROVIDER`
+ Camping Search Provider. Options available are 'Yellowstone' and 'RecreationDotGov'. Defaults
to 'RecreationDotGov', not case-sensitive. [**_example_](#look-for-a-campsite-inside-of-yellowstone)
to 'RecreationDotGov', not case-sensitive.
[**_example_](#look-for-a-campsite-inside-of-yellowstone)
* `--continuous`
+ Continuously check for a campsite to become available, and quit once at least one campsite is
found. [**_example_](#continuously-searching-for-a-campsite)
found.
[**_example_](#continuously-searching-for-a-campsite)
* `--polling-interval`: `POLLING_INTERVAL`
+ If `--continuous` is activated, how often to wait in between checks (in minutes). Defaults to
10, cannot be less than 5. [**_example_](#look-for-weekend-campsite-availabilities)
10, cannot be less than 5.
[**_example_](#look-for-weekend-campsite-availabilities)
* `--notifications`: `NOTIFICATIONS`
+ If `--continuous` is activated, types of notifications to receive. Options available are
`email`, `pushover`, `pushbullet`, or `silent`. Defaults to `silent` - which just logs
messages to console. [**_example_](#send-a-push-notification)
+ If `--continuous` is activated, types of notifications to receive. Options available
are`email`, `pushover`, `pushbullet`, or `silent`. Defaults to `silent` - which just logs
messages to console.
[**_example_](#send-a-push-notification)
* `--notify-first-try`
+ If `--continuous` is activated, whether to send all non-silent notifications if more than 5
matching campsites are found on the first try. Defaults to false which only sends
the first 5. [**_example_](#continuously-searching-for-a-campsite)
matching campsites are found on the first try. Defaults to false which only sends the first5.
[**_example_](#continuously-searching-for-a-campsite)
* `--search-forever`
+ If `--continuous` is activated, this method continues to search after the first availability
has been found. The one caveat is that it will never notify about the same identical campsite
for the same booking date. [**_example_](#continue-looking-after-the-first-match-is-found)
for the same booking date.
[**_example_](#continue-looking-after-the-first-match-is-found)
* `--yml-config`
+ Rather than provide arguments to the command line utility, instead pass a file path to a YAML
configuration file. See the documentation for more information on how to structure your
configuration file. [**_example_](#using-a-yml-configuration-file-to-search-for-campsites)
configuration file.
[**_example_](#using-a-yml-configuration-file-to-search-for-campsites)

```text
camply campsites \
Expand Down Expand Up @@ -336,6 +352,24 @@ camply campsites \
--polling-interval 5
```

#### Look for Consecutive Nights at the Same Campsite

A lot of times you need to search for consecutive nights at the same campsite. By default, any and
all campsites with a single nights booking are returned by camply. To search for campsites with
consecutive night stays, pass the `--nights` argument.

Note, the `--nights` argument handles issues with improper search parameters. For example, if you
set the `--weekends` parameter the maximum number of consecutive nights possible is 2. If you supply
more than this your `--nights` parameter will be overwritten to 2.

```text
camply campsites \
--rec-area 2991 \
--start-date 2021-05-01 \
--end-date 2021-07-31 \
--nights 4
```

#### Look for a Campsite Inside of Yellowstone

Yellowstone doesn't use https://recreation.gov to manage its campgrounds, instead it uses its own
Expand Down Expand Up @@ -364,7 +398,8 @@ camply campsites \
--rec-area 2991 \
--rec-area 1074 \
--start-date 2021-07-09 \
--end-date 2021-07-16
--end-date 2021-07-16 \
--nights 5
```

#### Using a YML Configuration file to search for campsites
Expand All @@ -381,6 +416,7 @@ campgrounds: null # ENTIRE FIELD CAN BE OMITTED IF NOT USED. # (LIST OR SIN
start_date: 2021-09-12 # YYYY-MM-DD
end_date: 2021-09-12 # YYYY-MM-DD
weekends: False # FALSE BY DEFAULT
nights: 1 # 1 BY DEFAULT
continuous: True # DEFAULTS TO TRUE
polling_interval: 5 # DEFAULTS TO 10 , CAN'T BE LESS THAN 5
notifications: email # (silent, email, pushover, pushbullet), DEFAULTS TO `silent`
Expand Down Expand Up @@ -459,7 +495,8 @@ month_of_june = SearchWindow(start_date=datetime(year=2021, month=6, day=1),
end_date=datetime(year=2021, month=6, day=30))
camping_finder = SearchRecreationDotGov(search_window=month_of_june,
recreation_area=2725, # Glacier Ntl Park
weekends_only=False)
weekends_only=False,
nights=1)
matches: List[AvailableCampsite] = camping_finder.get_matching_campsites(log=True, verbose=True,
continuous=False)
```
Expand Down Expand Up @@ -503,7 +540,8 @@ month_of_june = SearchWindow(start_date=datetime(year=2021, month=6, day=1),
end_date=datetime(year=2021, month=6, day=30))
camping_finder = SearchRecreationDotGov(search_window=month_of_june,
recreation_area=[2991, 1074], # Multiple Rec Areas
weekends_only=False)
weekends_only=False,
nights=3)
camping_finder.get_matching_campsites(log=True, verbose=True,
continuous=True,
polling_interval=5,
Expand Down Expand Up @@ -585,6 +623,9 @@ docker run -d \
--yml-config /home/camply/example_search.yml
```

A [docker-compose example](docs/examples/docker-compose.yml) of the above YML Config is also
available.

## Dependencies

`camply` is compatible with any Python version >= `3.6`. Currently, there are four required
Expand Down
2 changes: 1 addition & 1 deletion camply/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
camply __init__ file
"""

__version__ = "0.1.5"
__version__ = "0.1.6"
2 changes: 1 addition & 1 deletion camply/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from .api_config import RecreationBookingConfig, RIDBConfig, STANDARD_HEADERS, USER_AGENTS
from .cli_config import CommandLineConfig
from .data_columns import DataColumns
from .data_columns import CampsiteContainerFields, DataColumns
from .file_config import FileConfig
from .notification_config import EmailConfig, PushbulletConfig, PushoverConfig
from .search_config import SearchConfig
Expand Down
25 changes: 12 additions & 13 deletions camply/config/api_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"""
API Searching Configuration
"""

from os import getenv
from random import uniform
from typing import List

from dotenv import load_dotenv
Expand Down Expand Up @@ -94,18 +94,15 @@ class RecreationBookingConfig:
API_REFERRERS: dict = {
"Referer": "https://www.recreation.gov/"
}
# WAIT BETWEEN 1.01 - 1.51 SECONDS BETWEEN REQUESTS - EXACT RATE LIMIT UNKNOWN
RATE_LIMITING: float = round(uniform(1.01, 1.51), 2)

CAMPSITE_UNAVAILABLE_STRINGS: list = [
"Reserved"
, "Not Available"
, "Not Reservable"
, "Not Reservable Management"
, "Not Available Cutoff"
, "Lottery"
, "Open"
]

CAMPSITE_UNAVAILABLE_STRINGS: list = ["Reserved",
"Not Available",
"Not Reservable",
"Not Reservable Management",
"Not Available Cutoff",
"Lottery",
"Open"
]

CAMPSITE_BASE: str = "campsites"
CAMPSITE_AVAILABILITIES_BASE: str = "availabilities"
Expand All @@ -122,3 +119,5 @@ class RecreationBookingConfig:
CAMPSITE_INFO_TYPE_OF_USE: str = "type_of_use"

CAMPSITE_BOOKING_URL: str = "https://www.recreation.gov/camping/campsites"

RATE_LIMITING = (1.01, 1.51)
6 changes: 6 additions & 0 deletions camply/config/cli_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ class CommandLineArguments:
WEEKENDS_DESTINATION: str = "weekends"
WEEKENDS_HELP: str = "Only search for weekend bookings (Fri/Sat nights)."

NIGHTS_ARGUMENT: str = "--nights"
NIGHTS_DESTINATION: str = "nights"
NIGHTS_DEFAULT: int = 1
NIGHTS_HELP: str = ("Search for campsite stays with consecutive nights. "
"Defaults to 1 which returns all campsites found.")

PROVIDER_ARGUMENT: str = "--provider"
PROVIDER_DESTINATION: str = "provider"
PROVIDER_DEFAULT: str = "RecreationDotGov"
Expand Down
14 changes: 14 additions & 0 deletions camply/config/data_columns.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class DataColumns:
"""
CAMPSITE_ID_COLUMN: str = "campsite_code"
BOOKING_DATE_COLUMN: str = "booking_date"
BOOKING_END_DATE_COLUMN: str = "booking_end_date"
BOOKING_NIGHTS_COLUMN: str = "booking_nights"
CAMPSITE_SITE_NAME_COLUMN: str = "campsite_title"
CAMPSITE_TYPE_COLUMN: str = "campsite_type"
CAMPSITE_OCCUPANCY_COLUMN: str = "capacity"
Expand All @@ -22,3 +24,15 @@ class DataColumns:
FACILITY_NAME_COLUMN: str = "facility_name"
FACILITY_ID_COLUMN: str = "facility_id"
BOOKING_URL_COLUMN: str = "booking_url"


class CampsiteContainerFields:
"""
String Variable Storage Class
"""
CAMPSITE_ID: str = "campsite_id"
CAMPGROUND_ID: str = "facility_id"
BOOKING_DATE: str = "booking_date"
CAMPSITE_GROUP: str = "campsite_group"
BOOKING_END_DATE: str = "booking_end_date"
BOOKING_URL: str = "booking_url"
2 changes: 2 additions & 0 deletions camply/containers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class AvailableCampsite(NamedTuple):
"""
campsite_id: int
booking_date: datetime
booking_end_date: datetime
booking_nights: int
campsite_site_name: str
campsite_loop_name: str
campsite_type: str
Expand Down
7 changes: 4 additions & 3 deletions camply/notifications/email_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from smtplib import SMTP_SSL
from typing import List

from camply.config import EmailConfig
from camply.config import CampsiteContainerFields, EmailConfig
from camply.containers import AvailableCampsite
from camply.notifications.base_notifications import BaseNotifications

Expand Down Expand Up @@ -119,9 +119,10 @@ def send_campsites(campsites: List[AvailableCampsite], **kwargs) -> None:
f"{campsite.booking_date.strftime('%Y-%m-%d')}:")
fields.append(message_title)
for key, value in campsite._asdict().items():
if key == "booking_date":
if key in [CampsiteContainerFields.BOOKING_DATE,
CampsiteContainerFields.BOOKING_END_DATE]:
value: datetime = value.strftime("%Y-%m-%d")
elif key == "booking_url":
elif key == CampsiteContainerFields.BOOKING_URL:
key = "booking_link"
formatted_key = key.replace("_", " ").title()
fields.append(f"\t{formatted_key}: {value}")
Expand Down
10 changes: 5 additions & 5 deletions camply/notifications/pushbullet.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import requests

from camply.config import FileConfig, PushbulletConfig
from camply.config import CampsiteContainerFields, PushbulletConfig
from .base_notifications import BaseNotifications
from ..containers import AvailableCampsite

Expand All @@ -31,7 +31,6 @@ def __init__(self):
warning_message = ("Pushbullet is not configured properly. To send Pushbullet messages "
"make sure to run `camply configure` or set the "
"proper environment variable: `PUSHBULLET_API_TOKEN`.")
logger.critical(FileConfig.DOT_CAMPLY_FILE)
logger.error(warning_message)
raise EnvironmentError(warning_message)

Expand Down Expand Up @@ -78,9 +77,10 @@ def send_campsites(campsites: List[AvailableCampsite], **kwargs):
for campsite in campsites:
fields = list()
for key, value in campsite._asdict().items():
if key == "booking_url":
key = "Booking Link"
elif key == "booking_date":
if key == CampsiteContainerFields.BOOKING_URL:
key = "booking_link"
elif key in [CampsiteContainerFields.BOOKING_DATE,
CampsiteContainerFields.BOOKING_END_DATE]:
value: datetime = value.strftime("%Y-%m-%d")
formatted_key = key.replace("_", " ").title()
fields.append(f"{formatted_key}: {value}")
Expand Down
8 changes: 4 additions & 4 deletions camply/notifications/pushover.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import requests

from camply.config import FileConfig, PushoverConfig
from camply.config import CampsiteContainerFields, PushoverConfig
from .base_notifications import BaseNotifications
from ..containers import AvailableCampsite

Expand All @@ -34,7 +34,6 @@ def __init__(self, level: Optional[int] = logging.INFO):
"make sure to run `camply configure` or set the "
"proper environment variables: `PUSHOVER_PUSH_TOKEN`, "
"`PUSHOVER_PUSH_USER`.")
logger.critical(FileConfig.DOT_CAMPLY_FILE)
logger.error(warning_message)
raise EnvironmentError(warning_message)

Expand Down Expand Up @@ -92,10 +91,11 @@ def send_campsites(campsites: List[AvailableCampsite], **kwargs):
for campsite in campsites:
fields = list()
for key, value in campsite._asdict().items():
if key == "booking_url":
if key == CampsiteContainerFields.BOOKING_URL:
key = "Booking Link"
value = f"<a href='{value}'>{value}"
elif key == "booking_date":
elif key in [CampsiteContainerFields.BOOKING_DATE,
CampsiteContainerFields.BOOKING_END_DATE]:
value: datetime = value.strftime("%Y-%m-%d")
formatted_key = key.replace("_", " ").title()
fields.append(f"<b>{formatted_key}:</b> {value}")
Expand Down
Loading

0 comments on commit 3d48cac

Please sign in to comment.