Skip to content

Commit 76be383

Browse files
committed
initial router placeholder
1 parent 27e8eee commit 76be383

File tree

4 files changed

+160
-30
lines changed

4 files changed

+160
-30
lines changed

intbot/core/bot/channel_router.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"""
2+
Channel router that decides where to send particular message
3+
"""
4+
5+
from dataclasses import dataclass
6+
from core.models import Webhook
7+
8+
from core.integrations.github import GithubProjects, GithubRepositories
9+
from core.integrations.github import GithubWebhook
10+
from django.conf import settings
11+
12+
@dataclass
13+
class DiscordChannel:
14+
channel_id: int
15+
channel_name: str
16+
17+
18+
19+
dont_send_it = DiscordChannel(channel_id=0, channel_name="/dev/null")
20+
21+
class Channels:
22+
test_channel = DiscordChannel(
23+
channel_id=settings.DISCORD_TEST_CHANNEL_ID,
24+
channel_name=settings.DISCORD_TEST_CHANNEL_NAME,
25+
)
26+
27+
board_channel = DiscordChannel(channel_id=..., channel_name=...)
28+
ep2025_channel = DiscordChannel(channel_id=..., channel_name=...)
29+
em_channel = DiscordChannel(channel_id=..., channel_name=...)
30+
website_channel = DiscordChannel(channel_id=..., channel_name=...)
31+
bot_channel = DiscordChannel(channel_id=..., channel_name=...)
32+
33+
34+
def discord_channel_router(wh: Webhook) -> DiscordChannel:
35+
36+
if wh.source == "github":
37+
return github_router(wh)
38+
39+
elif wh.source == "internal":
40+
return internal_router(wh)
41+
42+
return dont_send_it
43+
44+
45+
def github_router(wh: Webhook) -> DiscordChannel:
46+
47+
gwh = GithubWebhook.from_webhook(wh)
48+
project = gwh.get_project()
49+
repository = gwh.get_repository()
50+
51+
# We have three github projects, that we want to route to three different
52+
# channels - one for ep2025, one for EM, and one for the board.
53+
if project == GithubProjects.board_project:
54+
return Channels.board_channel
55+
56+
elif project == GithubProjects.ep2025_project:
57+
return Channels.ep2025_channel
58+
59+
elif project == GithubProjects.em_project:
60+
return Channels.em_channel
61+
62+
else:
63+
...
64+
65+
# Then we have our open source repositories, like website, this bot, and
66+
# some others, that we also might want to route to different channels
67+
if repository == GithubRepositories.website_repo:
68+
return Channels.website_channel
69+
70+
elif repository == GithubRepositories.bot_repo:
71+
return Channels.bot_channel
72+
73+
elif repository == ...:
74+
...
75+
76+
# Finally, we can use this to drop notifications that we don't want to
77+
# support, by routing them to /dev/null
78+
return dont_send_it
79+
80+
81+
def internal_router(wh: Webhook) -> DiscordChannel:
82+
# For now just send all the internal messages to a test channel
83+
return Channels.test_channel

intbot/core/integrations/github.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,39 @@
33
import httpx
44
from django.conf import settings
55

6+
from core.models import Webhook
7+
68
GITHUB_API_URL = "https://api.github.com/graphql"
79

10+
11+
class GithubRepositories:
12+
website_repo = ...
13+
bot_repo = ...
14+
15+
16+
class GithubProjects:
17+
board_project = ...
18+
ep2025_project = ...
19+
em_project = ...
20+
21+
22+
class GithubWebhook:
23+
24+
def __init__(self, headers, content):
25+
self.headers = headers
26+
self.content = content
27+
28+
@classmethod
29+
def from_webhook(cls, wh: Webhook):
30+
return cls(headers=wh.meta, content=wh.content)
31+
32+
def get_project(self):
33+
...
34+
35+
def get_repository(self):
36+
...
37+
38+
839
# GraphQL query
940
query = """
1041
query($itemId: ID!) {

intbot/core/tasks.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import logging
22

33
from core.integrations.github import parse_github_webhook
4+
from core.bot.channel_router import discord_channel_router
45
from core.models import DiscordMessage, Webhook
5-
from django.conf import settings
66
from django.utils import timezone
77
from django_tasks import task
88

@@ -27,9 +27,13 @@ def process_internal_webhook(wh: Webhook):
2727
if wh.source != "internal":
2828
raise ValueError("Incorrect wh.source = {wh.source}")
2929

30+
channel = discord_channel_router(wh)
31+
3032
DiscordMessage.objects.create(
31-
channel_id=settings.DISCORD_TEST_CHANNEL_ID,
32-
channel_name=settings.DISCORD_TEST_CHANNEL_NAME,
33+
channel_id=channel.channel_id,
34+
channel_name=channel.channel_name,
35+
# channel_id=settings.DISCORD_TEST_CHANNEL_ID,
36+
# channel_name=settings.DISCORD_TEST_CHANNEL_NAME,
3337
content=f"Webhook content: {wh.content}",
3438
# Mark as not sent - to be sent with the next batch
3539
sent_at=None,
@@ -51,10 +55,13 @@ def process_github_webhook(wh: Webhook):
5155
logger.info(f"Not processing Github Webhook {wh.uuid}: {e}")
5256
return
5357

54-
# NOTE WHERE SHOULD WE GET THE CHANNEL ID FROM?
58+
channel = discord_channel_router(wh)
59+
5560
DiscordMessage.objects.create(
56-
channel_id=settings.DISCORD_TEST_CHANNEL_ID,
57-
channel_name=settings.DISCORD_TEST_CHANNEL_NAME,
61+
channel_id=channel.channel_id,
62+
channel_name=channel.channel_name,
63+
# channel_id=settings.DISCORD_TEST_CHANNEL_ID,
64+
# channel_name=settings.DISCORD_TEST_CHANNEL_NAME,
5865
content=f"GitHub: {message}",
5966
# Mark as unsend - to be sent with the next batch
6067
sent_at=None,

intbot/intbot/settings.py

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,39 @@
116116
# Just to make mypy happy
117117
TASKS: dict[str, Any]
118118

119+
120+
# There are bunch of settings that we can skip on dev/testing environments if
121+
# are not used, but should be present on prod/staging deployments.
122+
# Instead of repeating them per-env below, they go here.
123+
def get(name) -> str:
124+
value = os.environ.get(name)
125+
126+
if DJANGO_ENV == "prod":
127+
if value is None:
128+
raise ValueError(f"{name} is not set")
129+
130+
elif DJANGO_ENV == "test":
131+
pass
132+
else:
133+
warnings.warn(f"{name} not set")
134+
135+
return value or ""
136+
137+
# Discord
138+
# This is only needed if you end up running the bot locally, hence it
139+
# doesn't fail explicilty – however it does emit a warning.
140+
# Please check the documentation and/or current online guides how to get
141+
# one from the developer portal.
142+
# If you run it locally, you probably want to run it against your own test
143+
# bot and a test server.
144+
DISCORD_TEST_CHANNEL_ID = get("DISCORD_TEST_CHANNEL_ID")
145+
DISCORD_TEST_CHANNEL_NAME = get("DISCORD_TEST_CHANNEL_NAME")
146+
DISCORD_BOT_TOKEN = get("DISCORD_BOT_TOKEN")
147+
148+
# Github
149+
GITHUB_API_TOKEN = get("GITHUB_API_TOKEN")
150+
GITHUB_WEBHOOK_SECRET_TOKEN = get("GITHUB_WEBHOOK_SECRET_TOKEN")
151+
119152
if DJANGO_ENV == "dev":
120153
DEBUG = True
121154
ALLOWED_HOSTS = ["127.0.0.1", "localhost"]
@@ -141,23 +174,6 @@
141174

142175
WEBHOOK_INTERNAL_TOKEN = "dev-token"
143176

144-
# This is only needed if you end up running the bot locally, hence it
145-
# doesn't fail explicilty – however it does emit a warning.
146-
# Please check the documentation and/or current online guides how to get
147-
# one from the developer portal.
148-
# If you run it locally, you probably want to run it against your own test
149-
# bot and a test server.
150-
151-
def warn_if_missing(name, default=""):
152-
value = os.environ.get(name, default)
153-
if not value:
154-
warnings.warn(f"{name} not set")
155-
156-
DISCORD_TEST_CHANNEL_ID = warn_if_missing("DISCORD_TEST_CHANNEL_ID", "")
157-
DISCORD_TEST_CHANNEL_NAME = warn_if_missing("DISCORD_TEST_CHANNEL_NAME", "")
158-
DISCORD_BOT_TOKEN = warn_if_missing("DISCORD_BOT_TOKEN", "")
159-
GITHUB_API_TOKEN = warn_if_missing("GITHUB_API_TOKEN", "")
160-
GITHUB_WEBHOOK_SECRET_TOKEN = warn_if_missing("GITHUB_WEBHOOK_SECRET_TOKEN", "")
161177

162178

163179
elif DJANGO_ENV == "test":
@@ -293,17 +309,10 @@ def warn_if_missing(name, default=""):
293309
},
294310
}
295311

296-
DISCORD_BOT_TOKEN = os.environ["DISCORD_BOT_TOKEN"]
297-
DISCORD_TEST_CHANNEL_ID = os.environ["DISCORD_TEST_CHANNEL_ID"]
298-
DISCORD_TEST_CHANNEL_NAME = os.environ["DISCORD_TEST_CHANNEL_NAME"]
299-
300312
CSRF_TRUSTED_ORIGINS = [
301313
"https://internal.europython.eu",
302314
]
303315

304-
WEBHOOK_INTERNAL_TOKEN = os.environ["WEBHOOK_INTERNAL_TOKEN"]
305-
GITHUB_API_TOKEN = os.environ["GITHUB_API_TOKEN"]
306-
GITHUB_WEBHOOK_SECRET_TOKEN = os.environ["GITHUB_WEBHOOK_SECRET_TOKEN"]
307316

308317

309318
elif DJANGO_ENV == "build":

0 commit comments

Comments
 (0)