New
Apps 1,106Makers 1,104This week 1,106
Promote your app−30%
discord-server screenshot 1
1views in
the last 30 days

discord-server

A Discord gaming server run as code: Front Desk, a self-hosted discord.py bot (squads...

Built with Claude Code

by gr8monk3ys · from CHSwitzerland · added Oct 29, 2026
no ratings0 comments

Everything for Lorenzo's Server in one place:

  1. Client theme: the Field Notebook look, matching lscaturchio.xyz. Night or paper ground, forest-green ink, Fraunces headings and IBM Plex Mono wall labels.
  2. Server setup (server/): roles, channels, Onboarding and AutoMod as code.
  3. Front Desk (bot/): the server's own bot, with squad-up, stats and more.

Roadmap and design: docs/superpowers/specs/2026-10-01-front-desk-bot-design.md.

1. Client theme (theme/field-notebook.theme.css)

Works with Vencord (recommended) or BetterDiscord.

  • Vencord: Settings → Vencord → Themes → Open Themes Folder, drop the file in, then toggle it on.
  • BetterDiscord: Settings → Themes → Open Themes Folder, drop the file in, then toggle it on.

Discord's own Appearance setting picks the variant: Dark, Darker or Midnight gives the night notebook, and Light gives the paper one.

Heads up: both mods break Discord's Terms of Service. Bans for themes alone are very rare, but it's your call. Discord renames its internal classes every few months. If a detail stops applying (for example the mono category labels), the colours and fonts still work because they're driven by CSS variables.

2. Server makeover (server/)

This is a one-shot bot run. It creates or renames roles, categories and channels, makes the front-desk channels read-only, sets the join-message and AFK channels, and posts rules and welcome embeds. It never deletes anything. Anything not in layout.py gets listed so you can clean it up by hand.

One-time setup

  1. Go to https://discord.com/developers/applications → New Application → Bot → Reset Token, and copy the token.
  2. Copy .env.example to .env and paste the token and your server ID into it.
  3. Invite the bot with Administrator (replace APP_ID with the Application ID from the General Information page): https://discord.com/oauth2/authorize?client_id=APP_ID&scope=bot&permissions=8
  4. Server Settings → Roles: drag the bot's role to the very top.

Run it

cd server
python -m venv .venv
.venv\Scripts\pip install -r requirements.txt
.venv\Scripts\python setup_server.py          # dry run: shows the plan
.venv\Scripts\python setup_server.py --apply  # do it

Edit layout.py first. GAMES at the top holds your group's actual games, and each one gets a ping role plus a channel. RETIRED_GAMES under it holds games the server used to list: their roles stay, they are no longer offered, and public_mode.py archives their channels. The script is safe to re-run: it matches existing channels and roles by plain name, so #general becomes #💬・general instead of a duplicate.

Second pass: Discord's built-in features

.venv\Scripts\python polish_server.py          # dry run
.venv\Scripts\python polish_server.py --apply

This turns on Community and Onboarding, so new members pick their own game roles on join. It also sets up AutoMod (spam, mention raids and slurs, with alerts to the mod channel), defaults notifications to @mentions only, and removes the empty channels listed in TRIM. Everything is configured at the bottom of layout.py. The bot's role must be at the top for Onboarding to assign roles.

The server icon comes from assets/make_icon.py (pip install pillow).

Hosted bots (always online, set up in their dashboards)

Bot Job Setup
Captcha.bot DMs new members a web captcha; passing gives @Verified Verification channel #💬・general, role @Verified (Add role). Its role must sit above @Verified.
Lurkr Replaced by Front Desk Levels Turn leveling off in its dashboard, then kick it and delete its role, so members don't get two level numbers and two sets of level-up pings.
GiveawayBot Giveaways Nothing to set up: /gstart <time> <winners> <prize>.

MEE6 was tried and dropped: its Levels and Welcome plugins now need Premium.

polish_server.py also handles the media lock: @everyone can't post images, files or link embeds until they have one of the MEDIA_ROLES (Captcha.bot's @Verified covers new members). The lock is off for now (layout.MEDIA_LOCK = False, captcha paused since 2026-10-28), so polish_server.py gives @everyone media instead; set it back to True when Captcha.bot returns. The bot roles are ordered by the keep entries in layout.ROLES, and every bot gets @Bots so they're grouped in the member list.

Afterwards

  • Give yourself @Keeper and your friends @Squad.
  • Take Administrator back off the bot's role. Front Desk now stays as the server's permanent bot (section 3) with only the permissions it needs.
  • For later changes use public_mode.py: it never reorders or deletes, so it works with Front Desk sitting below the staff roles. It adds what is missing, with one exception: a game in RETIRED_GAMES leaves the "What do you play?" question and its channel moves into the staff-only 99 · archive category (messages and the role are kept; the dry run lists every channel it would hide).
  • To give newcomers a short channel list, run focus_mode.py (--plan prints the plan from layout.py alone, no arguments is a dry run against the server, then --apply). The Onboarding default channels become the nine in ONBOARDING_DEFAULT_CHANNELS, and the other public channels become answers to one optional question, "What else do you want to see?". No permission changes and nothing is deleted: every channel stays open to @everyone and current members keep the list they have. --revert makes every channel a default again.
  • Reset the bot token in the portal if you shared .env anywhere.
  • Optional: set ICON_PATH in layout.py to a square image for the server icon.

Emoji & sounds

The server has its own emoji pack (20 emoji, such as :gg:, :take_w:, :clutch:, :touchgrass: and :frontdesk:) and 8 soundboard sounds. Code generates all of them from scratch: Pillow draws the emoji and numpy synthesizes the sounds. No samples or outside art are used. The emoji share the look of the server icon: a night-paper stamp with one mark in one ink (pen green for wins and hype, near-white for neutral words, muted for losses), drawn to read at 22 to 48 px on both Discord themes. assets/expressions/contact-sheet.png shows the whole set at those sizes. The lettering is set in Bahnschrift Bold, so make_emoji.py needs Windows 10 or 11; the font itself is not in this repo.

.venv\Scripts\pip install pillow numpy                     # ffmpeg must be on PATH for the MP3s
.venv\Scripts\python ..\assets\expressions\make_emoji.py   # -> assets/expressions/emoji/*.png
.venv\Scripts\python ..\assets\expressions\make_sounds.py  # -> assets/expressions/sounds/*.mp3
.venv\Scripts\python expressions.py                        # dry run: what fits in your slots
.venv\Scripts\python expressions.py --apply                # upload
.venv\Scripts\python expressions.py --replace              # dry run: which emoji have new art
.venv\Scripts\python expressions.py --replace --apply      # swap them, one at a time

The bot's role needs Create Expressions. Names that already exist are skipped, and anything over the emoji or soundboard slot limit (8 sounds unboosted) is listed rather than uploaded. Sounds are MP3 because discord.py only accepts MP3 for the soundboard.

--replace is for emoji that were redrawn. Discord cannot change an emoji's picture, so each emoji whose local art differs from the server's is uploaded again under the same name and the old one is deleted (upload first when a slot is free; --delete-first turns that round). The emoji gets a new ID: typing :name: shows the new art, but messages and reactions that already used the old one do not change. It needs Manage Expressions as well, unless the bot uploaded every emoji it deletes. A touch-up too small for the comparison to notice can be named with --force NAME. Nothing in the bot refers to these emoji, by name or by ID.

Snapshot

snapshot_server.py is read-only. It writes the live server's config to server/snapshot/ (server, roles, channels, onboarding, automod and welcome .json). It uses names, not IDs, and sorts its output, so git diff server/snapshot shows exactly what changed since the last snapshot you committed. It never records members, messages, invites or the token.

cd server
.venv/Scripts/python snapshot_server.py            # write the snapshot
.venv/Scripts/python snapshot_server.py --compare  # also list roles/channels that differ from layout.py
.venv/Scripts/python -m pytest tests               # unit tests

If the bot lacks a permission for a fetch (AutoMod rules need Manage Server), that file gets an "error" note instead and the rest is still written.

3. Front Desk bot (bot/)

Front Desk is the server's own bot. It runs on LORENZO-COMPUTE around the clock and needs no day-to-day attention. Design and history: docs/superpowers/specs/2026-10-01-front-desk-bot-design.md. Privacy: PRIVACY.md.

What it does

Area Commands and automatic jobs
Squad-up /lfg posts in 🎮・lfg with Join/Leave/Close buttons; posts close after 3 h; a host's posts ping the game roles at most once per 30 min (later ones post without pings)
Stats /stats, /leaderboard, /privacy; weekly MVP Sundays 18:00 (accounts 30+ days old; fresh accounts don't count as voice company for it; if 💬・general is missing at that time the week is retried, not skipped)
Growth /invites, /recruiters (Recruiter role), /bumpers, /bumpping; Disboard bump reminders
Community welcome after Onboarding, /report and "Report message", mod log
Hall of fame 3 ⭐ from other members (accounts 30+ days old) reposts to ⭐・hall-of-fame (public channels only)
Clips clip of the week poll Sundays 18:05 (retried, not skipped, while 📸・clips is missing); winner gets Clip of the Week (only votes from accounts 30+ days old count, and not the clip author's own)
Voice join ➕ New Squad for your own channel; /squad name, /squad limit, /squad claim
Events /gamenight; /watchparty (a Stage event in 🎙・stage, or a voice event in the Lobby when the bot can't schedule on the stage; accounts 30+ days old; shares the game-night limits; its reminder pings the Game Night role only when staff host it); a Town Hall on the first Saturday of each month at 12:00 (TOWNHALL_TIME), created a week ahead and announced once; 15-min reminders; free Epic/Steam games Thursdays 18:00
Economy /daily, /balance, /give (accounts 30+ days old), /coinflip, /richest; coins for voice, chat, clips, squads
Games /slots, /blackjack, /trivia, /predict
Shop and seasons /shop, /buy (colour role, Hype, shoutout), /season; monthly champions
Engagement question of the day 12:00 and this-or-that poll 18:00 (each pauses while nobody answers it: see Quiet rooms), 🔢・counting, auto game night Fridays, /birthday
Moderation /warn, /timeout, /untimeout, /cases, /purge (shown only to members with Timeout Members, like /xp and /suggestion); /ban (staff who also hold Ban Members; DMs the reason first, plus the appeal code when appeals are set up; one line in 📋・mod-log per ban); auto-escalation, anti-spam, anti-raid
Operations daily DB backup 04:00, error alerts, back-online note, weekly config drift check, /status; permission self-check a minute after start and daily at 09:00 (every channel, permission and role the loaded modules need: one mod-log note when something is missing, one when it is fixed, and a line in /status)
Utility /remind, /reminders, /afk, suggestion voting, member/online stat channels, tickets in 🆘・help
Welcome cards an image card in 👋・welcome when someone finishes Onboarding (names them without a ping; the #general welcome is the one ping); a card that fails to post is retried every 10 minutes for up to 24 hours while the member is still here
Tournaments /tournament create/start/cancel/bracket; sign-up buttons, brackets with byes, both players confirm results, 1000/400 coin prizes, Tournament Champ role
Achievements 23 badges, /profile, /badges; checked on activity and hourly; Founding Member is granted without a post
Creators /creator link/verify/unlink/list (members prove ownership with a code in their channel description), staff /creator approve/remove; YouTube uploads and Twitch go-live in 📺・creators
Levels XP from chat (60 s cooldown) and voice; Regular/Veteran/Elite/Legend/Mythic at levels 5/10/20/30/50; /rank card, /levels, staff /xp; level-ups are announced from level 5 (the first reward role)
Recap weekly recap in 📣・announcements Mondays 10:00, owner digest by DM 10:05, member milestones, monthly invite contest (1500/750/300 coins) on the 1st. The digest has a "Games list" field that compares the last 28 days of play with GAMES: worth adding (an unlisted game that 3+ members played for 5+ hours combined, a retired one included) and worth retiring (a listed game nobody played); game names, player counts and hours only, and it never changes the list. Its "Newcomers" field says whether the people who join stick: for the week and for the last 28 days, how many joined, left since, picked roles, said something and joined voice; of the week before's joiners, how many are still here and how many came back in week 2; and one sentence of reading. Counts only, never a name. Members with tracking off count as joined and left and in nothing else; the other steps are "of the N with stats on", so the field shows how many recent joiners have tracking off. No field when nobody joined in 28 days
Self roles button panel in 🎭・roles (platform, region, play time, pings, games), /roles; Game Night role pinged when a game night starts, SMP Ping when 3+ are on Monkey SMP
Partners /partner apply → staff review card in 📋・mod-log → 🤝・partners; weekly dead-invite sweep; staff /partner remove
Starter quest /quest: pick roles, say hi, join a squad, claim /daily, join voice; the Settled In badge, plus 500 coins for new members (account 30+ days old, finished within 30 days of joining); one nudge DM after a day
Heartbeat writes bot/data/heartbeat every minute while connected to the gateway (stops during a reconnect loop, so the watchdog alerts); logs a warning when the event loop stalls for 1 s+
Auto tournaments first Monday of the month: a 16-player bracket for the most-played game (if 🏆・tournaments is missing it waits for the channel, until it is too late to open sign-ups), Discord event, Saturday 19:00 auto-start (4+ entrants), 1 h reminder, nudges for unreported matches; matches still undecided after 48 h (including a report the opponent never confirmed) go to staff in mod-log
Weekly challenges 3 rotating goals each week (150/250/400 coins + 300 bonus), board in 🎲・games Mondays 09:00, /challenges with Claim button, hourly auto-claim; squads and voice company only count from accounts 30+ days old, a game night counts once it starts (not if cancelled), a tournament entry once it starts
Daily Word /word guess/today/stats/leaderboard: one 5-letter word a day (order salted with a private secret kept in the database), spoiler-free results in 🎲・games, coins for wins, streaks
Vibes conversation starter when 💬・general is quiet for 3 h (not within an hour of the Tonight voice line), join anniversaries, booster thanks + 1000 coins and a monthly stipend, member of the month (squads = joining someone else's post)
Matchmaking /queue join/leave/status: pick a game, mode and size; when the queue fills, a voice channel is made and the players are pinged in 🎲・games; entries expire after 60 min
Economy extras /raffle buy/info (weekly draw Sundays 20:00, 80% of the pot to the winner, 20% burned), Gift Hype, Spotlight (pinned shoutout for 24 h); staff /economy for supply and minted vs burned. Audit: docs/ECONOMY.md
Help /help (categories built from the live command list, staff commands hidden from members, "Start here" button), /about; the bot's status rotates every 5 min
Game news official Steam announcements and verified feeds (bot/assets/news_sources.json) posted in each game's channel every 30 min, no pings; staff /news test
Staff applications /apply staff (30+ days in the server, 90+ day account, clean record), /apply status; review card in 📋・mod-log with Approve/Deny (Keepers) and Interview; the Moderator role is then given by hand, since it sits above Front Desk
Text filter slurs (with evasion spellings) and other servers' invite links are refused in member text the bot reposts: /lfg and /gamenight notes, shoutouts and Spotlight, tournament names, partner applications
Seasonal events Halloween (Oct 20 to Nov 1) and Winter Fest (Dec 15 to Jan 2) from bot/assets/events.json, every year: 6-10 drops a day in 💬・general while chat is active (Grab button, 25-75 coins + 1 point, gone after 10 min, max 12 a day each), a daily quest (+3 points, 100 coins), /event with your points and the top 10; at the end the top 3 win 2000/1000/500 coins, first place gets the Event Champ role and 10+ points earns the event badge; accounts under 30 days old earn nothing
Game accounts /link steam + /link verify (members prove ownership with a code in their Steam profile summary), /unlink, /accounts; staff /link approve/remove; persona, Steam link and hours in the server's games show on /profile, refreshed daily. No API key
Vote hub /vote (private): Disboard with your bump count and when the next bump is ready, discord.me, top.gg ("coming soon" until listed) and the share link discord.lscaturchio.xyz/join; Sundays 17:00 the week's top 3 Disboard bumpers are thanked in 🎲・games and paid 300/200/100 coins (accounts 30+ days old)
Catch-up /catchup [channel] [hours]: a private AI summary (5-8 bullets plus a "good moment to jump in") of a public channel's last 1-48 hours (default 12). Two providers: a local Ollama model on the bot's own machine (OLLAMA_MODEL, default llama3.2:3b; nothing leaves the machine, one summary at a time) or the Anthropic API (ANTHROPIC_API_KEY); CATCHUP_PROVIDER picks one, otherwise the key wins and Ollama is the fallback, and with neither it says summaries aren't set up. Accounts 30+ days old, 3 a day per member and 60 a day server-wide; bots and members with tracking off are left out; staff /catchup-usage shows the provider, requests and tokens
Houses three houses (Fern, Kestrel, Otter): established members are sorted into the smallest one every 10 min and get its role (one introduction post in 📣・announcements the first time; the permission self-check lists the house roles until public_mode.py --apply has made them); /house me/standings/join/leave/history (leaving starts a 30-day wait), staff /house-admin move; points come from what the other modules already record, capped at 100 per member a week and scored per member of the house; House Cup Mondays 10:10 in 📣・announcements (100 coins to each member of the winning house with 10+ points, once 2 qualify); a season trophy each calendar quarter
Welcome Crew /crew with Join/Leave buttons (accounts 30+ days old, 14 days here, no moderation case in 30 days; a new case takes the role back); one crew ping in 💬・general per 30 min for first-time joins (CREW_PING_MINUTES; someone who left and came back is not announced again), never 22:00 to 09:00 (CREW_QUIET_HOURS), during a raid or with no crew member online; 40 coins when a newcomer answers you (once per newcomer, 3 paid a day), the Welcoming Committee badg

Description taken from the repository README.

Ratings

–
0 ratings
5 0
4 0
3 0
2 0
1 0

Rate this app

Sign in to rate

Comments 0

Sign in to comment

No comments yet.

Related apps

#discord-bot · #games · #social