A self-hosted Discord bot that keeps a live project / to-do board in a channel: one message (or a few, auto-paginated) that everyone edits with buttons. No database, no dashboard, just a JSON file and a token.
Un bot de Discord auto-hospedado que mantiene un tablero de proyectos / to-do vivo en un canal: un mensaje (o varios, auto-paginados) que todos editan con botones. Sin base de datos, sin panel: un archivo JSON y un token.
- One pinned-style board per channel, rebuilt live as people act on it.
- Buttons for everyone: Add · Take · Leave · Status · Priority · Edit. Admin-only: Lead · Delete.
- Statuses (🔨 In progress · 🆕 Up for grabs · ✅ Done), priorities (🔴 High · ⏸️ Stand by · 🔽 Low) that sort the list, categories, a lead and multiple helpers per project, a location field and a link.
- Auto emoji per card (from the name, a
:shortcode:, or a pasted emoji). - Done tasks strike through and auto-delete after N days (configurable).
- Slash commands:
/add,/take,/mine,/boardpost. - Run one board or several (e.g. Build + Decoration) from one bot.
- Optional HTTP webhook to add tasks from outside Discord (off by default).
- Optional channel guard that deletes stray chatter in a board channel.
git clone <this-repo> discord-board-bot
cd discord-board-bot
cp .env.example .env # then edit it (token + channel id)
docker compose up -dpip install -r requirements.txt
cp .env.example .env # edit it
python bot.py- Bot token — Discord Developer Portal → your app → Bot → Reset Token. Invite the bot with the bot + applications.commands scopes and permission to send messages / embed links in the channel.
- Channel ID — in Discord, Settings → Advanced → Developer Mode on, then right-click the channel → Copy Channel ID.
Put both in .env (DISCORD_TOKEN, BOARD_CHANNEL_ID) and start the bot. It
posts the board on its own.
All via environment variables (see .env.example):
| Variable | Default | What |
|---|---|---|
DISCORD_TOKEN |
– (required) | Bot token |
BOARD_CHANNEL_ID |
– | Channel for the single board |
BOARD_TITLE |
Projects |
Board heading |
BOARD_COLOR |
0x3BA7FF |
Accent color (hex) |
BOARD_BLURB |
… | Intro line under the title |
BOARDS_CONFIG |
– | Path to a JSON file for multiple boards |
DONE_TTL_DAYS |
5 |
Auto-delete done tasks after N days (0 = never) |
DATA_DIR |
./data |
Where the JSON state lives |
GUARD_ENABLED |
false |
Delete stray messages in board channels |
MEMBERS_INTENT |
false |
Needed for the Lead search + @mentions |
WEBHOOK_SECRET |
– | Set to enable the HTTP webhook |
WEBHOOK_HOST / WEBHOOK_PORT |
0.0.0.0 / 8099 |
Webhook bind |
Set BOARDS_CONFIG=boards.json and describe each board (see
boards.example.json):
{
"build": { "title": "🏗️ Build Projects", "color": "0xE0533D", "channel_id": 111... },
"deco": { "title": "🎨 Decoration", "color": "0xC792EA", "channel_id": 222... }
}Each key becomes part of the button IDs, so keep it lowercase a-z0-9_.
Set WEBHOOK_SECRET to a long random string to turn it on. Then:
curl -X POST http://your-host:8099/task \
-H "Authorization: Bearer YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{"name": "Fix the piston bolt", "priority": "high", "desc": "north wall"}'Target a specific board with POST /task/<board-key>. Anyone with the secret
can add tasks, so only expose it behind HTTPS and rotate it if it leaks.
- The bot needs Send Messages and Embed Links in the board channel.
- Lead and clickable member @mentions need the Server Members privileged
intent: set
MEMBERS_INTENT=trueand toggle it on in the Dev Portal. - Channel guard (
GUARD_ENABLED=true) needs Manage Messages in those channels.
- Un tablero fijo por canal, que se reconstruye en vivo cuando la gente actúa.
- Botones para todos: Add · Take · Leave · Status · Priority · Edit. Solo admins: Lead · Delete.
- Estados (🔨 En progreso · 🆕 Libre · ✅ Hecho), prioridades (🔴 Alta · ⏸️ En espera · 🔽 Baja) que ordenan la lista, categorías, un líder y varios ayudantes por proyecto, ubicación y link.
- Emoji automático por tarjeta (del nombre, un
:shortcode:o un emoji pegado). - Lo hecho se tacha y se auto-borra a los N días (configurable).
- Slash commands:
/add,/take,/mine,/boardpost. - Corré un tablero o varios (ej: Construcción + Decoración) con un bot.
- Webhook HTTP opcional para agregar tareas desde fuera de Discord (apagado por defecto).
- Guardia de canal opcional que borra el chat suelto en el canal del tablero.
git clone <este-repo> discord-board-bot
cd discord-board-bot
cp .env.example .env # editá: token + id del canal
docker compose up -dpip install -r requirements.txt
cp .env.example .env # editalo
python bot.py- Token del bot — Discord Developer Portal → tu app → Bot → Reset Token. Invitá al bot con los scopes bot + applications.commands y permiso para mandar mensajes / embeds en el canal.
- ID del canal — en Discord, Ajustes → Avanzado → Modo desarrollador, y clic derecho en el canal → Copiar ID del canal.
Ponés ambos en .env (DISCORD_TOKEN, BOARD_CHANNEL_ID) y arrancás. El bot
postea el tablero solo.
Todo por variables de entorno (mirá .env.example):
| Variable | Default | Qué |
|---|---|---|
DISCORD_TOKEN |
– (obligatorio) | Token del bot |
BOARD_CHANNEL_ID |
– | Canal del tablero único |
BOARD_TITLE |
Projects |
Título del tablero |
BOARD_COLOR |
0x3BA7FF |
Color de acento (hex) |
BOARD_BLURB |
… | Línea de intro bajo el título |
BOARDS_CONFIG |
– | Ruta a un JSON para varios tableros |
DONE_TTL_DAYS |
5 |
Auto-borrar lo hecho a los N días (0 = nunca) |
DATA_DIR |
./data |
Dónde vive el estado JSON |
GUARD_ENABLED |
false |
Borra mensajes sueltos en los canales del tablero |
MEMBERS_INTENT |
false |
Necesario para la búsqueda de Lead + @menciones |
WEBHOOK_SECRET |
– | Ponelo para prender el webhook HTTP |
WEBHOOK_HOST / WEBHOOK_PORT |
0.0.0.0 / 8099 |
Bind del webhook |
Poné BOARDS_CONFIG=boards.json y describí cada tablero (ver
boards.example.json). Cada clave entra en los IDs de los botones, así que
usá minúsculas a-z0-9_.
Poné WEBHOOK_SECRET con un texto largo y aleatorio para prenderlo:
curl -X POST http://tu-host:8099/task \
-H "Authorization: Bearer TU_SECRETO" \
-H "Content-Type: application/json" \
-d '{"name": "Arreglar el piston bolt", "priority": "high", "desc": "pared norte"}'Apuntá a un tablero puntual con POST /task/<clave>. Cualquiera con el secreto
puede agregar tareas, así que exponelo solo detrás de HTTPS y rotalo si se filtra.
- El bot necesita Enviar mensajes y Insertar enlaces en el canal.
- Lead y las @menciones clicables necesitan el intent privilegiado
Server Members: poné
MEMBERS_INTENT=truey activalo en el Dev Portal. - La guardia de canal (
GUARD_ENABLED=true) necesita Gestionar mensajes en esos canales.
MIT. Built from the project board that runs on the MineWave Minecraft SMP.
