User Session & State Management
Relevant source files
The following files were used as context for generating this wiki page:User session and state management is a critical component of the Discord Live Translator bot. It is responsible for tracking individual user preferences for translation, primarily their target language. This system ensures that when a user speaks in a voice channel, the bot knows whether to translate their speech and into which language. The state is persisted externally, allowing user settings to survive bot restarts and redeployments.
The core of the state management is built around a SettingsStorage class that interfaces with a Redis database. Users manage their session state through a set of slash commands: /start, /stop, and /status. The bot's voice connection state is managed in-memory per guild, and the audio processing pipeline relies on the persisted user settings to trigger translations.
Architecture
The state management architecture is centered around the SettingsStorage class, which acts as an abstraction layer over a Redis data store.
Components
| Component | Description | Source File |
|---|---|---|
SettingsStorage | A class that handles all CRUD operations for user settings in Redis. | src/utils/settingsStorage.ts |
ioredis | The Redis client library used to connect to and interact with the Redis server. | src/utils/settingsStorage.ts:3 |
| Redis | The in-memory data store used for persisting user settings. The connection is configured via the REDIS_URL environment variable. | src/utils/settingsStorage.ts:11, src/env.ts:16 |
| Slash Commands | User-facing commands (/start, /stop, /status) that trigger state changes and queries. | src/commands/start.ts, src/commands/stop.ts, src/commands/status.ts |
Data Storage
User settings are stored in Redis as JSON strings. A unique key is generated for each user within a specific guild.
Key Schema
The Redis key is formatted using the guild ID and user ID to ensure uniqueness. The formatKey method is responsible for this.
// src/utils/settingsStorage.ts:14-16
private formatKey(guild: string, user: string) {
return `settings.${guild}.${user}`;
}
This results in keys such as settings.123456789012345678.987654321098765432.
Data Model
The data stored for each user is a simple JSON object conforming to the UserSettings type, which currently only contains the user's selected target language.
// src/utils/settingsStorage.ts:8-10
type UserSettings = {
target: keyof typeof languages;
};
Sources: src/utils/settingsStorage.ts:8-10
The following diagram illustrates the relationship between the components and the data stored in Redis.
This diagram shows the key-value structure for user settings as stored in Redis.
Sources: src/utils/settingsStorage.ts:14-26
SettingsStorage Class
This class encapsulates all logic for interacting with the Redis store.
This class diagram shows the methods available in the SettingsStorage class for managing user settings.
Sources: src/utils/settingsStorage.ts:12-29
Methods
| Method | Description |
|---|---|
get(guild, user) | Retrieves and parses the UserSettings JSON object for a given user and guild. Returns undefined if no settings are found. |
set(guild, user, target) | Creates or updates the settings for a user by storing a JSON string with the specified target language. |
delete(guild, user) | Removes the settings key for a user, effectively deactivating their translation session. |
Sources: src/utils/settingsStorage.ts:18-29
Session Lifecycle Management
The user session lifecycle is controlled by Discord slash commands. These commands interact with the settingsStorage instance to modify or retrieve a user's translation state.
Starting a Translation Session (/start)
A user starts a translation session by invoking the /start command and specifying a target language.
- The command handler receives the interaction.
- It retrieves the
targetlanguage from the command options. - It validates that the selected language is supported.
- It calls
settingsStorage.set()with the guild ID, user ID, and target language. - A confirmation message is sent to the user.
Sources: src/commands/start.ts:26-42
The following sequence diagram illustrates this flow:
This diagram shows the sequence of events when a user executes the /start command.
Sources: src/commands/start.ts:26-42, src/utils/settingsStorage.ts:23-26
Stopping a Translation Session (/stop)
A user stops their session using the /stop command.
- The command handler receives the interaction.
- It calls
settingsStorage.delete()with the guild ID and user ID. - A confirmation message is sent to the user.
Sources: src/commands/stop.ts:16-20
Checking Session Status (/status)
A user can check their current settings with the /status command.
- The command handler receives the interaction.
- It calls
settingsStorage.get()with the guild ID and user ID. - If settings are found, it replies with the user's current target language.
- If no settings are found, it informs the user that translation is not active.
Sources: src/commands/status.ts:15-25
State Usage in Audio Processing
The persisted user state is consumed during the audio processing pipeline, which is initiated when the bot is in a voice channel.
The core logic resides in the speaking event listener set up within the joinCommandHandler. When a user starts speaking, the bot checks if that user has an active translation session.
This flowchart shows the decision-making process when a user speaks in a channel with the bot. Translation is only performed if the user has active settings.
Sources: src/commands/join.ts:88-103
- The
connection.receiver.speaking.on('start', ...)event fires with theuserIdof the speaker. settingsStorage.get(guildId, userId)is called to fetch the user's settings.- If
userSettingsexist, the subsequent processing steps (recording, speech-to-text, translation, text-to-speech) are executed. - If
userSettingsareundefined, the process is aborted for that user's speech, and no translation occurs.
This ensures that the bot only translates for users who have explicitly opted in via the /start command.
Sources: src/commands/join.ts:91-94
Summary
The User Session & State Management system effectively decouples user preferences from the bot's runtime memory. By leveraging Redis through the SettingsStorage class, it provides a persistent, scalable way to manage individual user translation settings. The lifecycle of a user's session is controlled via simple slash commands, and the persisted state is a key factor in the conditional logic of the audio processing pipeline, enabling per-user translation within a shared voice channel.