Join a game
Create a lobby with!create or /create. The host message has Join & Play, Spectate instead, and Allow DMs from this bot.
1
Allow direct messages
Press Allow DMs from this bot if the join DM does not arrive. That button is the failsafe. Night actions and your role are still sent as DMs.Allow DMs from this bot is a user install:
integration_type=1 and scope=applications.commands. The bot does not receive or store that OAuth grant.2
Share the lobby code
Codes look like
MM-7F2A. Other people join with !join MM-7F2A or /join. Use !list or /list to see open codes.3
Stay in one lobby
A person can only be in one lobby, and only once. Use
!leave before you join another.-overwriteAdminWarning when joining, for example !join MM-7F2A -overwriteAdminWarning.
The host can force-start with !forceStart (!ownerstart or !fs). Slash: /force-start. Starting a specific code with !startGame or /start-game is limited to the lobby host or someone with admin.game.startGame. The full list is on the commands page.
Where messages go
Public status stays in the server’s setup channel, or in the channel where the lobby was created. The bot does not create a channel, category, role, or voice channel per game. Each status message is tagged with the lobby code and shows the phase, day, player count, weather, and moon. Private roles, night menus, shop use, and whispers are DMs. Joining also sends a DM. If Discord blocks that DM, the status channel mentions the player and shows Allow DMs from this bot.Day
1
Open the day
The status channel announces the new day. Private night results stay in DMs.
2
Report overnight deaths
If someone died overnight, the status channel says so without revealing secret roles.
3
Pay gold
Gold per day starts at 1, increases by 1 every 3 days, and increases again when 5 or fewer players remain. Everyone receives that day’s gold.
4
Vote
Vote with
!vote or /vote. The player with the most votes is executed. Executing the murderer wins the game for the town.5
Move to night
The status channel shows the coming weather and moon. Night prompts go out by DM. The status channel only says that night has started.
Night
Shop with!shop and !buy, or /shop and /buy, in your DM. Item costs are on the items page.
Role abilities use a menu in the DM. Typing the option number still works. When the murderer or werewolf attacks someone, the doctor gets Heal them and Let them die.
Leveling
!level and /level show XP for this server. A finished game grants 5 × day count XP, plus 20 for a murderer, werewolf, or fool win, or 10 for a villager win. The next level costs (level + 1) × 5 × level XP.
Add the bot to a server
Guild install. Replace the application id if you self-host: https://discord.com/oauth2/authorize?client_id=1452886075621249024&permissions=137439332416&integration_type=0&scope=applications.commands+botclient_id is the Discord application id. The scope includes applications.commands. Enable the Message Content and Server Members intents.
The invite grants Add Reactions, Send Messages, Embed Links, Attach Files, Read Message History, Use External Emojis, and Use External Sounds. It does not ask for Manage Channels, Manage Roles, Manage Messages, or Move Members.
Support server: discord.gg/kriti.
Run it yourself
Requirements
- Docker, or Python 3.11+
- A Discord application with the Message Content and Server Members intents enabled
- A bot token
Quick start
1
Clone the repository
The public source is Krithiv-7/Murder-Mystery-Bot-main. More projects are on justkrithiv.
2
Add the token
Put your token in
.env:3
Start the bot
Data on disk
Persistent files live in./data (the SQLite database and heartbeat). The database uses WAL mode and an in-memory cache so many servers can read settings without waiting on disk. Backups are written to ./backups. Logs are written to ./logs. Those directories are mounted into the container, so docker compose down does not delete them.
Write a backup:
backups/backup-YYYY-MM-DD.sqlite. To restore, stop the bot, replace data/bot.sqlite with that file, and start the bot again.
Import an older data.json without deleting it:
data.json automatically when the database has no guilds yet.
Configuration
Environment defaults live in.env. Each server can override the prefix and the game timers from !settings or the settings panel. See server settings.
MongoDB is optional. Install it with
pip install pymongo dnspython and set MMB_STORAGE=mongo. The default Docker setup does not run MongoDB.
Local development
make run uses the local Python environment. make docker starts Compose. Tests do not connect to Discord.
If something fails
ERROR: DISCORD_TOKEN is missing.Add the token to.envand rundocker compose up -dagain.- The bot is online but ignores
!commands. Enable the Message Content intent, and check that an admin has not disabled the command in the settings panel. - The invite scope includes
applications.commands. Enable the Message Content and Server Members intents before you invite the bot. - A player never receives role DMs. Joining sends a DM. If Discord blocks it, the status channel mentions that player and shows Allow DMs from this bot.
docker compose psshows the container as unhealthy. Wait for the start period, then checkdocker compose logs -f bot. The health check only looks at a heartbeat file written by the running bot.- Discord administrators join with
-overwriteAdminWarning, for example!join MM-7F2A -overwriteAdminWarning. !startGame <code>and/start-gameare for the lobby host or someone withadmin.game.startGame. The host can force-start the active lobby with!forceStart(!ownerstartor!fs). A person can only be in one lobby. Use!leavebefore joining another.