How sessions work
Every voice state change fires thevoiceStateUpdate handler:
- Join — opens a new session row in
voice_sessionswithleft_at = NULL. - Leave — closes the open session, writing
left_atandduration_seconds. - Move — closes the old-channel session and opens a new one for the new channel.
- Mute / deafen / stream — no session change.
Configuration
Voice tracking is configured at the guild level under thevoice key. Defaults are applied when the key is absent.
config.json
| Field | Default | Description |
|---|---|---|
enabled | false | Enable voice session tracking |
xpPerMinute | 2 | XP awarded per minute in voice (if reputation is also enabled) |
dailyXpCap | 120 | Maximum XP from voice per day |
logChannel | null | Channel ID for voice join/leave log messages |
Join and leave events are always tracked (to close open sessions) even when
enabled is false. This prevents orphaned in-memory sessions if the feature is toggled off while members are already in voice.Periodic flush
Every 5 minutes, the bot writes the currentduration_seconds of all open sessions to the database without closing them. This is a heartbeat that limits data loss to at most 5 minutes if the process crashes while members are in voice.
Leaderboard periods
The voice leaderboard supports three time windows:| Period | SQL filter |
|---|---|
week | Sessions started in the last 7 days |
month | Sessions started in the last 30 days |
all | All completed sessions |
Commands
/voice stats [user]
/voice stats [user]
Shows voice activity for yourself or another member:
Available to all members.
- Total time in voice (formatted as
1h 30m,45m, or30s) - Number of completed sessions
- Favourite voice channel
| Option | Required | Description |
|---|---|---|
user | No | Member to look up. Defaults to yourself |
/voice leaderboard [period]
/voice leaderboard [period]
Ranks the top 10 members by total voice time. Supports three time windows:
Available to all members.
| Choice | Value | Description |
|---|---|---|
| This week | week | Default — sessions from the last 7 days |
| This month | month | Sessions from the last 30 days |
| All time | all | All completed sessions |
/voice export [period]
/voice export [period]
Exports raw voice session data as a CSV file attachment (up to 5,000 rows). The CSV includes columns:
Permission: Requires the Manage Server Discord permission.
id, user_id, channel_id, joined_at, left_at, duration_seconds.| Option | Required | Description |
|---|---|---|
period | No | Time range to export: week, month, or all (default: all) |
Duration formatting
Durations are formatted as follows:| Duration | Display |
|---|---|
| Less than 60 seconds | 30s |
| Minutes only | 45m |
| Hours only | 2h |
| Hours and minutes | 1h 30m |
Database schema
Sessions are stored in thevoice_sessions table:
| Column | Type | Description |
|---|---|---|
id | serial | Primary key |
guild_id | text | Guild snowflake |
user_id | text | User snowflake |
channel_id | text | Voice channel snowflake |
joined_at | timestamptz | Session start time |
left_at | timestamptz | Session end time (NULL while open) |
duration_seconds | integer | Computed duration on close (updated by periodic flush for open sessions) |