| .dockerignore | ||
| .env.deploy.example | ||
| .env.example | ||
| .gitignore | ||
| compose.local.yaml | ||
| compose.yaml | ||
| dashboard.html | ||
| Dockerfile | ||
| preview.html | ||
| README.md | ||
| services.example.json | ||
| status_bot.py | ||
Archive Bot
An AIO Discord bot foundation for The Mithral Archive. The first module is status monitoring: it checks configured URLs and keeps one live status message updated in the Discord status channel.
The message uses a summary embed plus one small embed per service, so each service gets its own green or red Discord color bar.
It does not need Discord gateway intents or slash commands for the status module. It only needs a bot token, the status channel ID, and permission to send/edit its own messages.
The bot also includes a small web dashboard for editing monitored services and forcing immediate Discord refreshes.
Discord Bot Setup
Create a Discord application and bot in the Discord Developer Portal, then invite it with:
https://discord.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&permissions=84992&scope=bot
Required channel permissions:
- View Channel
- Send Messages
- Embed Links
- Read Message History
The current status channel ID is:
1504278732070981683
Local Setup
cp .env.example .env
cp services.example.json services.json
Edit .env and set:
DISCORD_BOT_TOKENDASHBOARD_USERNAMEDASHBOARD_PASSWORD_HASH
Use the raw Discord bot token value. Do not include a Bot prefix.
Generate the dashboard password hash:
python3 status_bot.py --hash-password
Paste the output into DASHBOARD_PASSWORD_HASH. The dashboard does not store a reusable browser token; it uses an HttpOnly session cookie and CSRF token after login.
Dashboard auth includes:
- PBKDF2-SHA256 password hashing
- HttpOnly
SameSite=Strictsession cookie - CSRF token required for write actions
- basic failed-login throttling
Edit services.json with the URLs you want displayed. Keep private/internal URLs out of Git if they should not be shared.
Preview the Discord embed payload:
ARCHIVE_STATUS_CONFIG=services.json python3 status_bot.py --preview
Open preview.html in a browser to see an approximate Discord-style render. Paste the JSON from --preview into the textarea and render it to test changes before sending anything to Discord.
Run it:
python3 status_bot.py
Local runs automatically read .env from the current directory.
For dashboard testing without touching Discord, set:
DISCORD_DRY_RUN=true
ARCHIVE_STATUS_STATE=state/status-message.json
Open the dashboard:
http://127.0.0.1:8787
Sign in with DASHBOARD_USERNAME and the password you used when generating DASHBOARD_PASSWORD_HASH.
Docker Setup
cp .env.deploy.example .env
cp services.example.json services.json
python3 status_bot.py --hash-password
docker compose up -d --build
Paste the generated password hash into .env before starting the container.
Make sure Docker can read the service config and write runtime state:
chmod 600 .env
chmod 644 services.json
mkdir -p state
chmod 755 state
The bot stores the Discord message ID in state/status-message.json. Keep that file mounted so the bot edits the same message after restarts.
The deploy compose joins your existing reverse-proxy network:
networks:
mediaserver_default:
external: true
If that network does not already exist on the deploy host, create it once:
docker network create mediaserver_default
The dashboard is exposed inside Docker on port 8787 for your reverse proxy. It is not published directly to the host by default.
Use this target from your proxy:
http://archive-status-bot:8787
For HTTPS behind a reverse proxy, set:
DASHBOARD_COOKIE_SECURE=true
Leave it false only for direct localhost HTTP testing.
For direct local Docker testing without a proxy:
docker compose -f compose.yaml -f compose.local.yaml up -d --build
Then open:
http://127.0.0.1:8787
Dashboard
The dashboard currently supports:
- viewing monitored services
- adding/removing service rows
- editing check URL, display URL, expected statuses, timeout, and keyword
- saving
services.json - forcing an immediate check and Discord message update
The sidebar leaves room for future modules like polls, webhooks, automations, and service integrations without changing the bot shape later.
Service Config
Each service supports:
name: label shown in Discordurl: URL checked by the botdisplayUrl: URL linked in the embedmethod: optional, defaults toGETtimeoutSeconds: optional, defaults to10expectedStatuses: optional list such as["200-399"]or[200, 204]keyword: optional text that must appear in the response body
Example:
{
"name": "Jellyfin",
"url": "https://jellyfin.mithraic.cloud/health",
"displayUrl": "https://jellyfin.mithraic.cloud",
"expectedStatuses": ["200-399"]
}