Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Makeathon Demon

makeathon-demon

A Discord bot for running a Greek-language hackathon — team channels, registration tracking, and submission follow-ups.


Built with discord.py. User-facing strings (questions in team channels, error messages) are in Greek; this README is in English so others can adapt it for their own event.

Features

  • !assign_channels (DAY 1) — reads the registration sheet, creates one private text channel per team, and grants view permission to each registered member.
  • !export_status (DAY 1–3) — merges raw registration form responses with live Discord state and writes a CSV (in_server, discord_id, discord_handle, channels_joined, team_match). Mirror the CSV to a Google Sheet to feed !check_missing.
  • !check_missing (DAY 2–3) — for each team channel, walks the team through a short interactive flow asking about absent members and whether to add anyone not yet in the channel. Replies containing ναι add the user; per-prompt timeouts (15 min nudge, 30 min abort).
  • !ping_unsubmitted (SUBMISSION) — pings each registered team that hasn't yet appeared in the submissions sheet (SUBMIT_URL), reminding them to submit.
  • !confirm_submitted (SUBMISSION) — confirms receipt in the channels of teams whose names are in the submissions sheet.
  • !purge_bot (CLEANUP) — bulk-deletes the bot's own recent messages (current channel or all). Subject to Discord's 14-day bulk-delete window.
  • !find_mystery (CLEANUP) — lists humans on the server who have no roles and aren't in the registration source. Useful for spotting lurkers.

All admin commands require administrator permission on the guild.

Architecture

Two distinct data sources feed three different cogs — do not conflate them.

                         ┌───────────────────────────────────┐
                         │ cogs/assignments.py               │──▶ creates #<team-slug> channels
                         │ !assign_channels                  │
                         └───────────────────────────────────┘
                                       ▲
SHEET_REGISTRATION_URL ────────────────┤
(raw form responses)                   ▼
                         ┌───────────────────────────────┐
                         │ cogs/export.py !export_status │──▶ registration_with_status.csv
                         └───────────────────────────────┘            │
                                                                      │  (mirror to Google Sheet)
                                                                      ▼
                                                              SHEET_URL (merged)
                                                                      │
                                                                      ▼
                                                   ┌──────────────────────────────────┐
                                                   │ cogs/check_missing.py            │
                                                   │ !check_missing                   │
                                                   └──────────────────────────────────┘

See CLAUDE.md for a deeper write-up of conventions (Greek column names with trailing spaces, channel slugging, the username-matching ladder, etc.).

Setup

python -m venv python_env
source python_env/bin/activate
pip install -r requirements.txt
cp .env.example .env
# fill in DISCORD_TOKEN, GUILD_ID, and SHEET_REGISTRATION_URL

Then provide your registration data — either a Google Sheet (SHEET_REGISTRATION_URL, recommended) or a local xlsx (REGISTRATION_FILE, fallback). See samples/registration.sample.csv for the expected columns.

Run the bot:

python bot.py

Using a local Excel file instead of Google Sheets

If you'd rather not host the registration data on Google Sheets:

  1. Leave SHEET_REGISTRATION_URL empty in .env.
  2. Set REGISTRATION_FILE to the path of an .xlsx whose columns match samples/registration.sample.csv — including the trailing spaces in Greek headers like Όνομα Ομάδας .

All three consumers (!assign_channels, !export_status, !find_mystery) go through the same loader at utils/data_sources.py, so the same Excel file works for every command.

Discord setup

The bot needs the following gateway intents (enabled in the Discord developer portal and in bot.py, both already configured):

  • members
  • message_content

And these guild permissions on the team channels (or via a server role):

  • Manage Channels — to create per-team channels
  • Manage Permissions — to grant view-access to specific members
  • Read Message History + Manage Messages — for !purge_bot
  • Send Messages — to post intros, questions, and confirmations

Commands

Command Purpose Key flags
!assign_channels Create team channels from the registration sheet and grant access --dry-run
!export_status Merge registration data with live Discord state
!check_missing Walk each team through absent / outside-channel members --dry-run
!ping_unsubmitted Remind teams missing from the submissions sheet --dry-run
!confirm_submitted Confirm receipt in channels of teams that submitted --dry-run
!purge_bot Bulk-delete the bot's own recent messages --all, --limit N, --dry-run
!find_mystery List roleless humans not in the registration source

Environment variables

Variable Required? Default Notes
DISCORD_TOKEN yes Bot token from the Discord developer portal
GUILD_ID yes Numeric ID of the target server
SHEET_REGISTRATION_URL one of these two Google Sheet with raw form responses
REGISTRATION_FILE one of these two Registration_2026.xlsx Local xlsx fallback when sheet URL is unset
SHEET_URL for !check_missing Merged sheet (the output of !export_status mirrored to Google)
SUBMIT_URL for !ping_unsubmitted / !confirm_submitted Google Sheet of submissions; must contain a Team: column
PRIVATE_CHANNEL_CATEGORY no Category for created channels; created if missing
MERGED_OUTPUT_FILE no registration_with_status.csv Output path for !export_status

Project layout

bot.py                      # entry point; loads all cogs
config.py                   # reads .env, exposes constants and Greek column names
cogs/
  assignments.py            # !assign_channels
  check_missing.py          # !check_missing
  export.py                 # !export_status
  mystery.py                # !find_mystery
  purge.py                  # !purge_bot
  submissions.py            # !ping_unsubmitted, !confirm_submitted
utils/
  data_sources.py           # registration loader (Google Sheet OR local xlsx)
  discord_helpers.py        # member index, channels map, channel creation
  parsing.py                # username parsing, slugify, normalize
  sheets.py                 # Google Sheet URL → CSV export URL
samples/                    # anonymised shape examples for the input files
CLAUDE.md                   # architectural notes / conventions

License

Apache 2.0 — see LICENSE.

About

From registration to submission: the Discord bot that ran makeathon

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages