Skip to content

Commit

Permalink
Discord: Add belting ceremony on solve
Browse files Browse the repository at this point in the history
  • Loading branch information
ConnorNelson committed Nov 30, 2023
1 parent fbc232f commit fcaad8e
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 4 deletions.
35 changes: 35 additions & 0 deletions dojo_plugin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
from CTFd.plugins.challenges import CHALLENGE_CLASSES, BaseChallenge
from CTFd.plugins.flags import FLAG_CLASSES, BaseFlag, FlagException

from .models import Dojos, DojoChallenges
from .config import DOJO_HOST, bootstrap
from .utils import unserialize_user_flag, render_markdown
from .utils.discord import get_discord_user, get_discord_roles, add_role, send_message
from .pages.dojos import dojos, dojos_override
from .pages.dojo import dojo
from .pages.workspace import workspace
Expand All @@ -35,6 +37,39 @@ class DojoChallenge(BaseChallenge):
name = "dojo"
challenge_model = Challenges

@classmethod
def solve(cls, user, team, challenge, request):
super().solve(user, team, challenge, request)

discord_user = get_discord_user(user.id)
if not discord_user:
return

# TODO: Get this from dojo.yml
belts = {
"CSE 365 - Spring 2023": "Orange Belt",
"CSE 466 - Fall 2022": "Yellow Belt",
"CSE 494 - Spring 2023": "Blue Belt",
}
discord_roles = get_discord_roles()

dojos = Dojos.query.join(DojoChallenges).filter(Dojos.official, DojoChallenges.challenge == challenge)
for dojo in dojos:
belt = belts.get(dojo.name)
if not belt:
continue
if not dojo.completed(user):
continue
if discord_roles.get(belt) in discord_user["roles"]:
continue

user_mention = f"<@{discord_user['user']['id']}>"
message = f"{user_mention} earned their {belt}! :tada:"
print(message, flush=True)
# TODO: Discord instead of print
# add_role(discord_user["user"]["id"], belt)
# send_message(message, "belting-ceremony")


class DojoFlag(BaseFlag):
name = "dojo"
Expand Down
3 changes: 3 additions & 0 deletions dojo_plugin/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,9 @@ def viewable(cls, id=None, user=None):
def solves(self, **kwargs):
return DojoChallenges.solves(dojo=self, **kwargs)

def completed(self, user):
return self.solves(user=user).count() == len(self.challenges)

def is_admin(self, user=None):
if user is None:
user = get_current_user()
Expand Down
11 changes: 7 additions & 4 deletions dojo_plugin/utils/discord.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,21 @@
API_ENDPOINT = "https://discord.com/api/v9"


def guild_request(endpoint, method="GET", **json):
guild_endpoint = f"{API_ENDPOINT}/guilds/{DISCORD_GUILD_ID}"
def discord_request(endpoint, method="GET", **json):
headers = {"Authorization": f"Bot {DISCORD_BOT_TOKEN}"}
json = json or None
response = requests.request(method, f"{guild_endpoint}{endpoint}", headers=headers, json=json)
response = requests.request(method, f"{API_ENDPOINT}{endpoint}", headers=headers, json=json)
response.raise_for_status()
if "application/json" in response.headers.get("Content-Type", ""):
return response.json()
else:
return response.content


def guild_request(endpoint, method="GET", **json):
return discord_request(f"/guilds/{DISCORD_GUILD_ID}{endpoint}", method=method, **json)


def get_bot_join_server_url():
# "Server Members Intent" also required
params = dict(client_id=DISCORD_CLIENT_ID, scope="bot", permissions=268437504, guild_id=DISCORD_GUILD_ID)
Expand Down Expand Up @@ -86,7 +89,7 @@ def send_message(message, channel_name):
channel_ids = [channel["id"] for channel in guild_request("/channels") if channel["name"] == channel_name]
assert len(channel_ids) == 1
channel_id = channel_ids[0]
guild_request(f"/channels/{channel_id}/messages", method="POST", json=dict(content=message))
discord_request(f"/channels/{channel_id}/messages", method="POST", content=message)


def add_role(discord_id, role_name):
Expand Down

0 comments on commit fcaad8e

Please sign in to comment.