Create the Discord app
Every judgebot is its own Discord application, owned by whoever runs it. This page takes
you from nothing to /judge answering in your server. Discord’s own walkthrough of the
portal, Building your first Discord Bot,
covers the same screens in general terms. The steps below say what to choose for this bot.
The bot is slash-command only. It needs no privileged gateway intents and no channel permissions, because it receives only its own commands and button presses and replies through the interaction. You never grant it the ability to read messages.
Before you start
Section titled “Before you start”- The first run done up to the point where the web page answers. The database is up and the data is loaded. Discord is the last thing to add, and nothing here spends money.
- Manage Server in the Discord server you are adding the bot to. Adding an app to a server requires that permission (Installation Context).
- A Discord account with email verified, which the developer portal requires.
1. Create the application
Section titled “1. Create the application”Open the Developer Portal and choose New
Application. The name is what members see beside /judge in the command picker and on
the bot’s profile, so name it for your server (“Rules Judge”, “Club Judge”).
The App Icon is the bot’s avatar. The project’s icon is
a 512×512 PNG (assets/icon.png in the repository) if you want it, and
any image works. Nothing else on the General Information page matters to the bot. The install link in
step 3 carries the Application ID shown there.
2. Bot user and token
Section titled “2. Bot user and token”Under Bot:
- Reset Token and copy the result into
.envasDISCORD_TOKEN. Discord shows a token once. If you lose it, reset again. The token is a credential for the application, and every binary that reads it holds it as a redacted secret. SetJUDGE_OPERATOR_DISCORDin.envto your own Discord username at the same time. The bot does not start without it, and/helpand/licenseshow it. - Leave all three Privileged Gateway Intents (Presence, Server Members, Message Content) off. The bot connects with no intents (Gateway Intents explains what they are). Turning one on changes nothing in the bot and, past 100 servers, would trigger Discord’s verification process for nothing.
- Public Bot can be off. It controls whether other people can use your install link. A bot you run for your own servers has no reason to allow that.
3. The install link
Section titled “3. The install link”Under OAuth2 → URL Generator:
- Tick the scopes
botandapplications.commands.botputs a bot user in the server.applications.commandslets it register slash commands there (OAuth2 scopes). - Under Bot Permissions, tick nothing. Replies, buttons and the “did you mean?” row
all travel through the interaction, which needs no permission in the channel. The URL
ends in
permissions=0. - Open the generated URL in your browser, pick the server, and Authorize. This is
Discord’s bot authorization flow.
The URL has the shape
https://discord.com/oauth2/authorize?client_id=<application id>&scope=bot%20applications.commands&permissions=0. You can reuse it for every server you administer.
The newer Installation page in the portal (installation contexts and a Discord-provided install link) does the same job. If you use it instead, keep Guild Install as the only context, the same two scopes, and no permissions. The bot has no user-install behaviour.
4. Command registration and GUILD_ID
Section titled “4. Command registration and GUILD_ID”The running bot registers its slash commands, per application. It registers them either in one server (instant) or globally (every server the bot is in, up to an hour to appear). See Registering a command. For a bot in one or two servers, register in the server:
- In Discord, User Settings → Advanced → Developer Mode on.
- Right-click the server icon → Copy Server ID (Discord’s help article Where can I find my User/Server/Message ID?).
- Put it in
.envasGUILD_ID.
Leave GUILD_ID unset to register globally. Avoid switching back and forth. The bot
registers the set it is configured for and does not remove the other, so members would see
two identical /judge entries from the same bot until the stale set is cleared. The
portal does not clear it. Overwriting a set with an empty list does
(Bulk Overwrite Guild Application Commands).
It needs the bot token, the Application ID from step 1 and, for a server’s set, the
server id that GUILD_ID held before you blanked it:
DISCORD_TOKEN=... # as in .envAPPLICATION_ID=... # General Information → Application IDGUILD_ID=... # the server the stale set was registered in
# clear the server's set (after moving to global registration)curl -X PUT -H "Authorization: Bot $DISCORD_TOKEN" -H "Content-Type: application/json" -d '[]' \ "https://discord.com/api/v10/applications/$APPLICATION_ID/guilds/$GUILD_ID/commands"# clear the global set (after moving to GUILD_ID)curl -X PUT -H "Authorization: Bot $DISCORD_TOKEN" -H "Content-Type: application/json" -d '[]' \ "https://discord.com/api/v10/applications/$APPLICATION_ID/commands"Clear only the set the bot is no longer configured for. The bot registers its own set again at every start.
5. Start it
Section titled “5. Start it”docker compose up -d bot # or: cargo run --release -p judge-botThe log line registered /judge, /card, /rule, /help, /license and /forget in one guild (or … globally)
confirms registration. /help in the server confirms it end to end. Discord’s command
picker shows your bot’s icon beside its commands, so another bot’s /judge in the same
server does not conflict with yours.
6. Card symbol emoji
Section titled “6. Card symbol emoji”Run this once:
docker compose run --rm refresh emoji # or: cargo run --release -p judge-ingest -- emojiIt uploads Scryfall’s mana and card symbols as application emoji. These belong to the
application rather than to any server and need no emoji permission to use
(Application-owned emoji).
Without them answers render the literal {W}. The command is idempotent, reads
DISCORD_TOKEN and needs no database.
Keeping it to one channel
Section titled “Keeping it to one channel”The bot answers wherever its commands can be used, and that is Discord’s setting, not the
bot’s. In Server Settings → Integrations, open your application and restrict /judge
(or every command) to the channels, roles or members you choose
(application command permissions).
A rules-questions channel keeps follow-ups together, because history is per channel.
Two limits are the bot’s own: JUDGE_USER_LIMIT questions per member per
JUDGE_USER_WINDOW_SECS (six per ten minutes by default, 0 turns it off), and
JUDGE_CONCURRENCY runs in flight at once. Neither applies to /card and /rule.
An Incorrect rating tells the rater to contact you, and links the Wrong or unhelpful
ruling issue form of the repository JUDGE_SOURCE_URL names when that is on GitHub. A
fork has Issues off until you enable them under the repository’s Settings → General →
Features.
The judge role
Section titled “The judge role”Members holding a role whose name matches JUDGE_ROLE (default Judge) rate as judges.
Their rating overrides the crowd’s smoothed average for that answer. Create the role in
your server under Server Settings → Roles (Discord’s
Role Management 101 covers it)
and give it to the people whose rulings you trust. The name comparison is exact, and the
role needs no permissions of its own.
Several servers
Section titled “Several servers”One application can be in every server you administer. Reuse the install link from step 3
and register commands globally. The servers then share the process: one spend cap
(JUDGE_MAX_USD), one concurrency limit and one judge role name. That is by design
(D16).
A community that wants its own budget runs its own instance, which is a second copy of the
same compose file with a second application’s token.
Discord’s rules for the bot
Section titled “Discord’s rules for the bot”Your application is bound by the Discord Developer Policy
and Terms of Service like any other. Two points matter for a judgebot. It must not
collect more data than it needs. This one stores questions per channel and ratings per
user, and /forget deletes the latter. Magic content is used under Wizards of the
Coast’s Fan Content Policy, which your instance’s /help
already states.
MTG Judgebot is unofficial Fan Content permitted under the Fan Content Policy. Not approved or endorsed by Wizards of the Coast. Portions of the materials used are property of Wizards of the Coast. ©Wizards of the Coast LLC.
The Comprehensive Rules come from Wizards of the Coast. Card data, rulings and card symbols come from Scryfall, which is not affiliated with this project. Rule links go to the Yawgatog mirror. License and attribution.