A Russian-language personality Discord bot backed by any OpenAI-compatible inference API. It only reacts when @-mentioned, only serves members holding configured role IDs, chats in a configurable persona, and runs fact-check and roast commands on replied-to messages.
No local model, no GPU: one small Python process, one container, outbound connections only (Discord gateway + your inference endpoint).
- Chat: mention the bot with text and it replies in Russian, short, PG-13, and text-only. Persona is a garnish — it answers first, snarks second.
- Fact-check: reply to a message, mention the bot, and include
фактчек; the bot answers in free Russian prose with a soft lead (Правда:,Скорее ложь:,Не проверить:…), grounded by web search when enabled. - Roast: reply to a message, mention the bot, and say
прожарь/роаст/разнеси; the bot burns the quoted message in character. - Other replies: a reply with text but no keyword is auto-routed (a cheap intent classify picks fact-check / roast / chat).
- Current facts: optional web search grounds stale or post-cutoff claims
when
SEARCH_ENABLED=true— Tavily (keyed) with a keyless DuckDuckGo fallback, orSEARCH_PROVIDER=ddgfor keyless-only. - Images: optional vision support passes Discord image attachment URLs to a
vision-capable model when
VISION_ENABLED=true. - Controls: role allow-list, per-user cooldown, global concurrency cap, input-size guard, per-role daily quotas, and a startup API health probe.
The character is configuration: set PERSONA to a one-line Russian description
(e.g. ворчливый повар, который всё сводит к еде). The hard content rules — no
slurs, no threats, no code, no breaking character — live in bot/prompts.py
and are deliberately not overridable by config.
make venv install
cp .env.example .env
# fill DISCORD_TOKEN, ALLOWED_ROLE_IDS, API_BASE_URL, API_KEY, MODEL_ID
make test
set -a && . ./.env && set +a
python -m botdocker compose up -d --build
docker compose logs -fThe compose stack exposes no inbound ports. Runtime state lives in the
bot-data:/data volume when quota/profile persistence is enabled.
Inference is remote: message text being chatted about, fact-checked, or roasted
is sent to your configured inference provider, and search queries reach your
search provider. Full message text is never written to logs. Learned per-user
profiles (PROFILE_ENABLED, off by default) persist chat-derived summaries to
disk.
See DEPLOY.md for deployment details and .env.example for the full list of configuration options.
MIT — see LICENSE.