Skip to content

Commit 85f9a0c

Browse files
committed
✨ Discord notification provider
1 parent f807634 commit 85f9a0c

10 files changed

+131
-2
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ camply campgrounds --search "Fire Lookout Towers" --state CA
5353
Search for available campsites, get a notification whenever one becomes
5454
available, and continue searching after the first one is found. The below command
5555
is using `silent` notifications as an example but camply also supports `Email`,
56-
`Slack`, `Twilio` (SMS), `Pushover`, `Pushbullet`, `Ntfy`, `Apprise`, and `Telegram`.
56+
`Slack`, `Discord`, `Twilio` (SMS), `Pushover`, `Pushbullet`, `Ntfy`, `Apprise`, and `Telegram`.
5757

5858
```commandline
5959
camply campsites \

camply/config/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from .file_config import FileConfig
88
from .notification_config import (
99
AppriseConfig,
10+
DiscordConfig,
1011
EmailConfig,
1112
NtfyConfig,
1213
PushbulletConfig,
@@ -31,6 +32,7 @@
3132
"PushbulletConfig",
3233
"PushoverConfig",
3334
"SlackConfig",
35+
"DiscordConfig",
3436
"TelegramConfig",
3537
"TwilioConfig",
3638
"SearchConfig",

camply/config/file_config.py

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class FileConfig:
2727
"notes": "Enables Pushbullet Notifications",
2828
},
2929
SLACK_WEBHOOK={"default": "", "notes": "Enables Slack Notifications"},
30+
DISCORD_WEBHOOK={"default": "", "notes": "Enables Discord Notifications"},
3031
TELEGRAM_BOT_TOKEN={"default": "", "notes": "Enables Telegram Notifications"},
3132
TELEGRAM_CHAT_ID={
3233
"default": "",

camply/config/notification_config.py

+7
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ class SlackConfig:
104104

105105
SLACK_WEBHOOK: Optional[str] = getenv("SLACK_WEBHOOK", None)
106106

107+
class DiscordConfig:
108+
"""
109+
Discord Notification Config Class
110+
"""
111+
112+
DISCORD_WEBHOOK: Optional[str] = getenv("DISCORD_WEBHOOK", None)
113+
107114

108115
class TelegramConfig:
109116
"""

camply/notifications/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
from .apprise import AppriseNotifications
6+
from .discord import DiscordNotifications
67
from .email_notifications import EmailNotifications
78
from .multi_provider_notifications import CAMPSITE_NOTIFICATIONS, MultiNotifierProvider
89
from .pushbullet import PushbulletNotifications
@@ -17,6 +18,7 @@
1718
"PushbulletNotifications",
1819
"PushoverNotifications",
1920
"TelegramNotifications",
21+
"DiscordNotifications",
2022
"TwilioNotifications",
2123
"EmailNotifications",
2224
"SilentNotifications",

camply/notifications/discord.py

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
"""
2+
Push Notifications via Discord
3+
"""
4+
5+
import logging
6+
from typing import List
7+
8+
import requests
9+
10+
from camply.config import DiscordConfig
11+
from camply.containers import AvailableCampsite
12+
from camply.notifications.base_notifications import BaseNotifications
13+
14+
logger = logging.getLogger(__name__)
15+
16+
17+
class DiscordNotifications(BaseNotifications):
18+
"""
19+
Push Notifications via Discord
20+
"""
21+
22+
def __init__(self):
23+
super().__init__()
24+
self.session.headers.update({"Content-Type": "application/json"})
25+
if any([DiscordConfig.DISCORD_WEBHOOK is None, DiscordConfig.DISCORD_WEBHOOK == ""]):
26+
warning_message = (
27+
"Discord is not configured properly. To send Discord messages "
28+
"make sure to run `camply configure` or set the "
29+
"proper environment variable: `DISCORD_WEBHOOK`."
30+
)
31+
logger.error(warning_message)
32+
raise EnvironmentError(warning_message)
33+
34+
def send_message(self, message: str, **kwargs) -> requests.Response:
35+
"""
36+
Send a message via Discord - if environment variables are configured.
37+
38+
Parameters
39+
----------
40+
message: str
41+
42+
Returns
43+
-------
44+
requests.Response
45+
"""
46+
message_json = kwargs
47+
if message:
48+
message_json["content"] = message
49+
50+
logger.debug(message_json)
51+
response = self.session.post(
52+
url=DiscordConfig.DISCORD_WEBHOOK,
53+
json=message_json,
54+
)
55+
try:
56+
response.raise_for_status()
57+
except requests.HTTPError as he:
58+
logger.warning(
59+
"Notifications weren't able to be sent to Discord. "
60+
"Your configuration might be incorrect."
61+
)
62+
raise ConnectionError(response.text) from he
63+
return response
64+
65+
def block_for_campsite(self, campsite: AvailableCampsite):
66+
message_title, formatted_dict = self.format_standard_campsites(
67+
campsite=campsite,
68+
)
69+
70+
# Remove items that will be templated as part of the embed.
71+
del formatted_dict["Recreation Area"]
72+
del formatted_dict["Booking Date"]
73+
del formatted_dict["Booking End Date"]
74+
del formatted_dict["Facility Name"]
75+
del formatted_dict["Booking Link"]
76+
del formatted_dict["Campsite Site Name"]
77+
del formatted_dict["Campsite Loop Name"]
78+
79+
return {
80+
"author": {
81+
"name": f"🏕 {campsite.recreation_area}"
82+
},
83+
"title": f"{campsite.facility_name} {campsite.campsite_loop_name} #{campsite.campsite_site_name}",
84+
"description": f"{campsite.booking_date} to {campsite.booking_end_date}",
85+
"url": campsite.booking_url,
86+
"color": 2375436,
87+
"fields": [
88+
{
89+
"name": key,
90+
"value": str(value)
91+
} for key, value in formatted_dict.items()
92+
],
93+
"footer": {
94+
"text": "camply, the campsite finder ⛺️"
95+
}
96+
}
97+
98+
def send_campsites(self, campsites: List[AvailableCampsite], **kwargs):
99+
"""
100+
Send a message with a campsite object
101+
102+
Parameters
103+
----------
104+
campsites: AvailableCampsite
105+
"""
106+
self.send_message(
107+
message="",
108+
embeds=[self.block_for_campsite(campsite) for campsite in campsites],
109+
)

camply/notifications/multi_provider_notifications.py

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from typing import Dict, List, Type, Union
88

99
from camply.containers import AvailableCampsite
10+
from camply.notifications import DiscordNotifications
1011
from camply.notifications.apprise import AppriseNotifications
1112
from camply.notifications.base_notifications import BaseNotifications, NotificationError
1213
from camply.notifications.email_notifications import EmailNotifications
@@ -27,6 +28,7 @@
2728
"apprise": AppriseNotifications,
2829
"pushbullet": PushbulletNotifications,
2930
"slack": SlackNotifications,
31+
"discord": DiscordNotifications,
3032
"telegram": TelegramNotifications,
3133
"twilio": TwilioNotifications,
3234
"silent": SilentNotifications,

docs/command_line_usage.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ and a link to make the booking. Required parameters include `--start-date`, `--e
144144
[\*\*_example_](#continue-looking-after-the-first-match-is-found)
145145
- `--notifications`: `NOTIFICATIONS`
146146
- Enables continuous searching. Types of notifications to receive. Options available
147-
are `pushover`, `email`, `ntfy`, `apprise`, `pushbullet`, `slack`, `telegram`, `twilio`, `silent`.
147+
are `pushover`, `email`, `ntfy`, `apprise`, `pushbullet`, `slack`, `discord`, `telegram`, `twilio`, `silent`.
148148
Defaults to `silent` - which just logs messages to console.
149149
[\*\*_example_](#send-a-push-notification)
150150
- `--equipment`
@@ -457,6 +457,7 @@ camply supports notifications via a number of services:
457457
- [Apprise](https://github.com/caronc/apprise)
458458
- [Pushbullet](https://www.pushbullet.com/#settings/account)
459459
- [Slack](https://slack.com)
460+
- [Discord](https://discord.com)
460461
- [Telegram](https://core.telegram.org/bots)
461462
- [Twilio (SMS)](https://www.twilio.com)
462463
- Silent

docs/examples/example.camply

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ PUSHBULLET_API_TOKEN=""
1010
# REQUIRED TO SEND SLACK NOTIFICATIONS
1111
SLACK_WEBHOOK=""
1212

13+
# REQUIRED TO SEND DISCORD NOTIFICATIONS
14+
DISCORD_WEBHOOK=""
15+
1316
# REQUIRED TO SEND TELEGRAM NOTIFICATIONS
1417
TELEGRAM_BOT_TOKEN=""
1518
TELEGRAM_CHAT_ID=""

docs/how_to_run.md

+2
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ available.
139139
- `TWILIO_DEST_NUMBERS`
140140
- Slack Notifications
141141
- `SLACK_WEBHOOK`
142+
- Discord Notifications
143+
- `DISCORD_WEBHOOK`
142144
- Telegram Notifications
143145
- `TELEGRAM_BOT_TOKEN`
144146
- `TELEGRAM_CHAT_ID`

0 commit comments

Comments
 (0)