- Rust 96.4%
- Shell 2.8%
- Dockerfile 0.4%
- Nix 0.4%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
Some checks failed
Rust, Docker, Code Coverage / fmt (push) Failing after 16s
Rust, Docker, Code Coverage / clippy () (push) Failing after 1m30s
Rust, Docker, Code Coverage / clippy (--all-features) (push) Failing after 1m42s
Rust, Docker, Code Coverage / clippy (--features "opentelemetry ai-openrouter util-download") (push) Failing after 1m31s
Rust, Docker, Code Coverage / build () (push) Successful in 1m43s
Rust, Docker, Code Coverage / build (--all-features) (push) Successful in 2m25s
Rust, Docker, Code Coverage / build (--features "opentelemetry ai-openrouter util-download") (push) Successful in 2m18s
Rust, Docker, Code Coverage / docker (push) Failing after 2s
Rust, Docker, Code Coverage / test (push) Failing after 4m29s
origin is a Forgejo instance (git.hu-tao.dev), so CI now lives where the
code does. .forgejo/workflows/ci.yml mirrors .github/workflows/full.yml —
fmt, clippy and build across the empty/deploy/all feature matrix, tests
against Postgres + Redis service containers, and a Dockerfile build.
Three deviations, all forced by Forgejo running jobs inside a container
rather than on a VM: third-party actions are referenced by full github.com
URL (the runner's default registry is code.forgejo.org), services are
reached by service name instead of localhost with an explicit TCP wait loop
(the runner ignores `options:` health-checks), and the coverage report is
kept as a run artifact instead of pushed to Codecov.
Also syncs the GitHub matrix's deploy feature string with
scripts/deploy-features.sh, which gained util-download in
|
||
| .cargo | ||
| .forgejo/workflows | ||
| .githooks | ||
| .github | ||
| .sqlx | ||
| assets | ||
| database | ||
| deploy/supervisor | ||
| docs | ||
| grafana/provisioning/datasources | ||
| migrations | ||
| scripts | ||
| serenity_discord_bot_derive | ||
| src | ||
| .dockerignore | ||
| .env.example | ||
| .gitattributes | ||
| .gitignore | ||
| .gitlab-ci.yml | ||
| AGENTS.md | ||
| build.rs | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| CONTRIBUTORS.md | ||
| docker-compose.infra.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| flake.lock | ||
| flake.nix | ||
| LICENSE | ||
| README.md | ||
| SECURITY.md | ||
| tempo.yaml | ||
Serenity Discord Bot
A Hu Tao-themed Discord bot built with Serenity and Poise. Responds to both slash and prefix commands (hu, ht), with persistent XP levelling backed by PostgreSQL and an optional AI persona that stays in character across a full channel conversation window.
The minimal build needs only a Discord token and PostgreSQL; AI, Redis, and telemetry are opt-in Cargo features. Run it with:
cargo run --release
For deeper detail, see the documentation: architecture, configuration, deployment, AI features, and observability.
Features
/help— lists every registered command- Embed interaction commands: tieup, pat, hug, kiss, slap, punch, bonk, nom, kill, kick, bury, selfbury, peek, avatar, drive, chair, boom, quote
- XP levelling with a 60-second cooldown, stored in PostgreSQL —
/levelfor a member's level,/toplevelsfor the server leaderboard /reminder— schedule a DM for later (create/list/search/delete), with a saveable default timezone (/reminder timezone, per-server or global) and browsable, paginated history/util— utility commands:/util avatar,/util uptime,/util age, and/util download(whenutil-downloadfeature is enabled)/age— your or another member's account creation date/cookie— give someone a cookie/uptime— bot uptime/custom reaction add url:<url> pattern:<regex> [anywhere:<bool>]— register an image + Rust regex; whenever a guild message matches, the bot replies with the image in an embed.anywhere: false(default) anchors to the full message;anywhere: truematches anywhere. The confirmation shows the reaction's per-guild number (#1,#2, … within the server). Tenor/Giphy page links (tenor.com/view/…,giphy.com/gifs/…) are rejected — paste the direct media URL (media.tenor.com/....gif) instead. Requires Manage Channels. Per-guild cap: 25/custom reaction list— list the server's reactions (ephemeral) with their per-guild numbers, patterns, andanywhereflags (Manage Channels)/custom reaction remove name:<autocomplete>— soft-delete the reaction picked by its per-guild number from autocomplete (Manage Channels, cache-backed). Numbers are positional, so removing one renumbers the rest- Levenshtein-distance typo correction on unrecognised prefix commands
Optional features
Everything optional is a Cargo feature. ai is a meta-feature — enabling it
also enables redis — and it requires picking exactly one ai-<backend>.
| Feature | What it adds | Notes |
|---|---|---|
| (core) | Commands, XP, reminders, custom reactions | Needs only BOT_TOKEN + PostgreSQL. |
redis |
Cross-instance AI context, locks, rate limits | Standalone. Single instance works without it. |
ai |
The AI persona chat | Meta-feature: also enables redis. Needs a backend (below). |
ai-<backend> |
The AI provider | Exactly one of ai-deepseek, ai-ollama, ai-anthropic, ai-openai, ai-google, ai-groq, ai-openrouter. Mandatory when ai is on. |
opentelemetry |
OTLP trace export | Point at any OTLP collector; compose ships Tempo + Grafana. |
util-download |
/util download — yt-dlp + ffmpeg 2-pass encode targeting 8 MB |
Needs yt-dlp and ffmpeg (with ffprobe) on PATH. |
tokio_console |
Tokio Console runtime inspection | Needs RUSTFLAGS="--cfg tokio_unstable". |
Building with --features ai and no backend stops at a compile_error! by
design. See docs/configuration.md for the
environment variables each feature reads.
AI
An in-character Hu Tao persona powered by the llm crate, which supports every mainstream provider. The backend is chosen at compile time — enable exactly one of: ai-deepseek, ai-ollama, ai-anthropic, ai-openai, ai-google, ai-groq, ai-openrouter.
Set AI_MODEL and AI_API_KEY (hosted backends) in .env — see .env.example for all variables.
/ai— one-off prompt in any channel or DM/aichannel— toggle a channel where the bot auto-replies to every message (requires Manage Channels)/custom prompt add|show|remove— set a per-server instruction block appended to the AI's system prompt, applied to both/aiand auto-replies (requires Manage Channels)- Set
REDIS_URLto keep conversation context in Redis and to share AI locks and rate limits across bot instances; without it the bot re-fetches recent messages from Discord on every reply and coordination is per-instance
Tokio Console
Task-level async runtime inspection via Tokio Console:
RUSTFLAGS="--cfg tokio_unstable" cargo run --features tokio_console
Telemetry
Distributed tracing via OpenTelemetry — backend-agnostic, so you can point it at any OTLP-compatible collector. The compose setup ships with Grafana Tempo and Grafana pre-wired as the UI. See docs/observability.md for the tracing layers and the category span field. To run Tempo manually (create /var/tempo once with your user as owner):
sudo mkdir -p /var/tempo && sudo chown $USER /var/tempo
tempo -config.file=./tempo.yaml
Setting up
- Copy
.env.exampleto.envand fill in the values. - Have PostgreSQL running and reachable at
DATABASE_URL— migrations run automatically at startup. - Run:
cargo run --release
# or, to enable specific features:
cargo run --release --features='<your-features>'
To run the telemetry stack (Grafana Tempo + Grafana) in containers while running the bot natively:
docker-compose -f docker-compose.infra.yml up -d
Docker Compose
The compose file brings up PostgreSQL, Redis, Grafana Tempo, and Grafana alongside the bot:
docker-compose up -d
Important
Make sure you aren't running PostgreSQL or Grafana Tempo locally due to port conflicts!
Note
The
Dockerfilebuilds with the features listed in itsFEATURESarg (defaults toai-deepseek opentelemetry tokio_console). Override via the compose build args to change provider or feature set.
Documentation
- docs/architecture.md — crate layout, startup, message flow, the two AI paths, and the Redis-optional model.
- docs/configuration.md — full environment-variable reference.
- docs/deployment.md — native, Docker Compose, sharding, and the production topology.
- docs/ai.md — enabling AI and the context window.
- docs/observability.md — tracing, Tokio Console, and OpenTelemetry.
See SECURITY.md for the secrets inventory, and CONTRIBUTORS.md to set up a dev environment.







