1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
# senator-sperma-rust — Agent Guide
## Project Map
```
src/
├── main.rs — Entry: init tracing, dotenvy, build Config/Data, start poise+serenity
├── config.rs — Config struct (env-driven), pub const TEMP_PATH
├── error.rs — Unified Error enum + From impls, pub type Result<T>
├── commands/
│ ├── mod.rs — all_commands() aggregates every submodule
│ ├── ai.rs — /senator (OpenRouter chat + optional TTS)
│ ├── cron.rs — /cron group (6 subcommands)
│ ├── math.rs — /math (qalc subprocess)
│ ├── music.rs — /play (🟡 stub), /stop, /join, /loop_toggle
│ ├── qr.rs — /qr encode + decode
│ ├── trigger.rs — /trigger group (6 subcommands)
│ ├── tts.rs — /tts (Google TTS → file/vc), /log_volume
│ ├── utilities.rs — compress🟡, convert🟡, upload, search, download, say
│ └── web.rs — /web (DuckDuckGo scrape)
├── copyparty/mod.rs — CopypartyClient (search, upload)
├── database/mod.rs — DbPool, 21 query fns, 6 tables, migration
├── events/mod.rs — handle_ready, handle_voice_state_update, handle_message
├── openrouter/mod.rs — OpenRouterClient (chat, chat_with_history)
├── tasks/mod.rs — cron_scheduler_loop (30s polling, stub exec bodies)
└── voice/mod.rs — VoiceManager (connect, disconnect, get_call), mp3_to_input
```
## Key Conventions
- **Framework**: poise 0.6 + serenity 0.12 + songbird 0.6
- **DB**: sqlx 0.9 async SQLite (pool stored in `Data.db_pool`)
- **Errors**: `crate::error::Error` enum with `?` propagation; use `Error::Custom(string)` for ad-hoc
- **Shared state**: `Data` struct in `main.rs` — passed as poise `user_data`
- **Commands**: each submodule exports `pub fn commands() -> Vec<poise::Command<Data, Error>>`
- **Temp path**: always use `crate::config::TEMP_PATH` (resolves to `/tmp/senator_sperma`)
## Stubs to Fill (see COMPARISON.md)
- `commands/music.rs` — `/play` is placeholder
- `commands/utilities.rs` — `/compress`, `/convert`, `/download` upload part
- `tasks/mod.rs` — cron execution bodies are `info!` only, no actual action
## Database Tables
`settings` (key/value), `voice_activity`, `cron_jobs`, `triggers`, `trigger_keywords`, `trigger_responses`
## All Commands (26 total)
`/senator`, `/cron` (6), `/math`, `/play`, `/stop`, `/join`, `/loop_toggle`, `/qr` (2), `/trigger` (6), `/tts`, `/log_volume`, `/compress`, `/convert`, `/upload`, `/search`, `/download`, `/say`, `/web`
|