fix: cyrillic fonts, dev certs, page head, and ru-text typography (#67)
🤖 PR generated for branch `fix/cyrillic-fonts-dev-certs-and-page-head`.
### Changes Summary
- **Fonts**: Add Cyrillic glyph subsets for Lato, EB Garamond, and Fira
Code.
- **Dev**: Support remote Root CA and encrypted dev CA key in
`.env.dev`.
- **UI & Kits**: Add size variant to `Breadcrumbs` component and enlarge
`PageHead` breadcrumbs with tuned collapse scroll threshold.
- **ESLint**: Add `no-hanging-particles` i18n & markdown typography rule
with auto-fixer.
- **Content & i18n**: Apply `ru-text` editorial and typography polish
(em dashes, number ranges, «ё» restoration, non-breaking spaces) across
`services/www` and `services/docs`.
This commit is contained in:
1 parent
c6487dc258
commit
b3638f4d63
111 files changed
+2350
-1512
No files matched your search
@@ -6,11 +6,11 @@ cascade:
|
||||
type: docs
|
||||
---
|
||||
|
||||
**Quetza** is a modular Discord bot framework built with TypeScript and Discord.js. It transforms feature development from core modification into independent module addition.
|
||||
**Quetza** is a modular Discord bot framework built with TypeScript and Discord.js. It transforms feature development from core modification into independent module addition.
|
||||
|
||||
## Project Vision
|
||||
|
||||
The framework addresses the fundamental challenge of extensible bot design: providing a scalable architecture where functionality can be added without increasing system complexity or coupling.
|
||||
The framework addresses the fundamental challenge of extensible bot design: providing a scalable architecture where functionality can be added without increasing system complexity or coupling.
|
||||
|
||||
## Documentation Sections
|
||||
|
||||
@@ -25,6 +25,6 @@ The framework addresses the fundamental challenge of extensible bot design: prov
|
||||
## Key Features
|
||||
|
||||
- **Modular Architecture:** Features are plugins, not core modifications.
|
||||
- **TypeScript First:** Built for type safety and developer experience.
|
||||
- **TypeScript First:** Built for type safety and developer experience.
|
||||
- **Zero-Config Discovery:** Filesystem-based module registration.
|
||||
- **State Management:** Built-in patterns for guild-scoped services.
|
||||
- **State Management:** Built-in patterns for guild-scoped services.
|
||||
@@ -3,7 +3,7 @@ title: Concepts
|
||||
weight: 4
|
||||
---
|
||||
|
||||
**Quetza** concepts explain the _Why_ and _How_ behind the framework's design. These documents cover the underlying philosophy and architectural decisions.
|
||||
**Quetza** concepts explain the _Why_ and _How_ behind the framework's design. These documents cover the underlying philosophy and architectural decisions.
|
||||
|
||||
## Key Topics
|
||||
|
||||
|
||||
@@ -3,38 +3,38 @@ title: Architecture & Philosophy
|
||||
weight: 1
|
||||
---
|
||||
|
||||
**Goal:** Understand the core design principles that drive Quetza's modularity.
|
||||
**Goal:** Understand the core design principles that drive Quetza's modularity.
|
||||
|
||||
## Design Philosophies
|
||||
|
||||
### Convention Over Configuration
|
||||
|
||||
Quetza minimizes boilerplate by relying on strict folder structures.
|
||||
Quetza minimizes boilerplate by relying on strict folder structures.
|
||||
|
||||
- **No central registry:** The filesystem _is_ the registry.
|
||||
- **Result:** You don't update a config file to add a module; you just create the folder.
|
||||
- **No central registry:** The filesystem _is_ the registry.
|
||||
- **Result:** You don't update a config file to add a module; you just create the folder.
|
||||
|
||||
### Composition Over Inheritance
|
||||
|
||||
Modules are composed of capabilities, not inherited from a base class.
|
||||
Modules are composed of capabilities, not inherited from a base class.
|
||||
|
||||
- **Flexibility:** Modules can use any internal architecture (Functional, OOP) as long as they export the required interfaces.
|
||||
- **Flexibility:** Modules can use any internal architecture (Functional, OOP) as long as they export the required interfaces.
|
||||
|
||||
### Isolation Over Integration
|
||||
|
||||
Modules cannot directly invoke each other.
|
||||
|
||||
- **Why:** Prevents tight coupling.
|
||||
- **Benefit:** You can delete any module without breaking the rest of the bot.
|
||||
- **Benefit:** You can delete any module without breaking the rest of the bot.
|
||||
|
||||
## Core Entities
|
||||
|
||||
| Entity | Role | Lifecycle |
|
||||
| :------------- | :----------------------------- | :---------------------------- |
|
||||
| **Client** | Service Locator & Orchestrator | Singleton. Runs the show. |
|
||||
| **Module** | Namespace for features | Loaded at startup. |
|
||||
| **Client** | Service Locator & Orchestrator | Singleton. Runs the show. |
|
||||
| **Module** | Namespace for features | Loaded at startup. |
|
||||
| **Command** | User Interaction Endpoint | Stateless. Request/Response. |
|
||||
| **Event** | Reactive Observer | Subscribed at startup. |
|
||||
| **Event** | Reactive Observer | Subscribed at startup. |
|
||||
| **Controller** | State Manager | Persists across interactions. |
|
||||
|
||||
---
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
---
|
||||
title: The Module System
|
||||
title: The Module System
|
||||
weight: 2
|
||||
---
|
||||
|
||||
**Goal:** Define the vocabulary and mechanics of Quetza's primary abstraction unit.
|
||||
**Goal:** Define the vocabulary and mechanics of Quetza's primary abstraction unit.
|
||||
|
||||
## System Vocabulary
|
||||
|
||||
### Module Declaration
|
||||
|
||||
The `module.ts` file acts as the manifest. It is the entry point for discovery.
|
||||
The `module.ts` file acts as the manifest. It is the entry point for discovery.
|
||||
|
||||
```typescript
|
||||
export const name = 'my-module'; // ID
|
||||
@@ -18,36 +18,36 @@ export const description = '...'; // Doc
|
||||
|
||||
### Command Registration
|
||||
|
||||
Occurs during the `ready` event.
|
||||
Occurs during the `ready` event.
|
||||
|
||||
1. Quetza scans all `commands/` folders.
|
||||
2. Compiles `ApplicationCommandData`.
|
||||
3. PUTs the payload to Discord's API.
|
||||
3. PUTs the payload to Discord's API.
|
||||
|
||||
### Controller Injection
|
||||
|
||||
State is injected, not imported.
|
||||
State is injected, not imported.
|
||||
|
||||
```typescript
|
||||
// The framework calls this:
|
||||
execute(client, interaction, controller);
|
||||
```
|
||||
|
||||
- **Why?** Allows the framework to manage the controller's lifecycle (singleton per module).
|
||||
- **Why?** Allows the framework to manage the controller's lifecycle (singleton per module).
|
||||
|
||||
## State Management Philosophy
|
||||
|
||||
### Ephemeral by Default
|
||||
### Ephemeral by Default
|
||||
|
||||
Quetza provides **no built-in database**.
|
||||
|
||||
- **Memory:** Controllers store state in JS `Map` or `Set` objects.
|
||||
- **Restart:** All state is lost when the process exits.
|
||||
- **Persistence:** Must be implemented manually (e.g., SQLite, Redis) inside the Controller.
|
||||
- **Memory:** Controllers store state in JS `Map` or `Set` objects.
|
||||
- **Restart:** All state is lost when the process exits.
|
||||
- **Persistence:** Must be implemented manually (e.g., SQLite, Redis) inside the Controller.
|
||||
|
||||
### Scope as Key
|
||||
### Scope as Key
|
||||
|
||||
State must be keyed by its boundary.
|
||||
State must be keyed by its boundary.
|
||||
|
||||
- `Map<GuildID, ...>` - Server specific (Most common).
|
||||
- `Map<UserID, ...>` - User specific (DM bots).
|
||||
@@ -58,7 +58,7 @@ State must be keyed by its boundary.
|
||||
|
||||
- **Validation:** Check permissions/inputs immediately.
|
||||
- **User-Facing:** "You don't have permission" (Not "Error: 403").
|
||||
- **Isolation:** A crash in `/ping` catches itself and doesn't kill the bot.
|
||||
- **Isolation:** A crash in `/ping` catches itself and doesn't kill the bot.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -3,60 +3,60 @@ title: Getting Started
|
||||
weight: 1
|
||||
---
|
||||
|
||||
**Quetza** is a modular Discord bot framework built with TypeScript that enables developers to build feature-rich Discord applications through self-contained, composable modules.
|
||||
**Quetza** is a modular Discord bot framework built with TypeScript that enables developers to build feature-rich Discord applications through self-contained, composable modules.
|
||||
|
||||
## What is Quetza?
|
||||
## What is Quetza?
|
||||
|
||||
Quetza provides an architectural foundation that transforms feature development from core modification into module addition. It solves the problem of rigid bot design by inverting dependency structures—the core knows nothing about modules, yet modules have full access to capabilities through defined contracts.
|
||||
Quetza provides an architectural foundation that transforms feature development from core modification into module addition. It solves the problem of rigid bot design by inverting dependency structures—the core knows nothing about modules, yet modules have full access to capabilities through defined contracts.
|
||||
|
||||
## The Core Philosophy
|
||||
## The Core Philosophy
|
||||
|
||||
### The Problem
|
||||
### The Problem
|
||||
|
||||
Traditional monolithic bots suffer from brittleness. Adding features requires modifying core logic, intertwining dependencies, and managing growing codebases that are difficult to test or change.
|
||||
Traditional monolithic bots suffer from brittleness. Adding features requires modifying core logic, intertwining dependencies, and managing growing codebases that are difficult to test or change.
|
||||
|
||||
### The Solution
|
||||
### The Solution
|
||||
|
||||
Quetza treats modules as plugins.
|
||||
Quetza treats modules as plugins.
|
||||
|
||||
- **Zero-Touch Extension:** Add features by creating a folder. No core code modification required.
|
||||
- **Zero-Touch Extension:** Add features by creating a folder. No core code modification required.
|
||||
- **Isolation:** Modules operate independently.
|
||||
- **Composition:** Enable/disable features by simply adding or removing module folders.
|
||||
- **Composition:** Enable/disable features by simply adding or removing module folders.
|
||||
|
||||
## High-Level Architecture
|
||||
|
||||
Quetza consists of three primary layers:
|
||||
Quetza consists of three primary layers:
|
||||
|
||||
1. **Foundation Layer**: The `Discord.js` client extended with module-aware registries (Commands, Events, Modules). It acts as a service locator.
|
||||
2. **Module Layer**: Self-contained feature packages. Each module exposes its own commands and events via a standardized file structure.
|
||||
1. **Foundation Layer**: The `Discord.js` client extended with module-aware registries (Commands, Events, Modules). It acts as a service locator.
|
||||
2. **Module Layer**: Self-contained feature packages. Each module exposes its own commands and events via a standardized file structure.
|
||||
3. **Service Layer**: Optional **Controllers** that manage stateful business logic (e.g., audio players, conversation context) across guilds.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
### Mental Model
|
||||
|
||||
To work effectively with Quetza, adopt this framework:
|
||||
To work effectively with Quetza, adopt this framework:
|
||||
|
||||
- **Modules are Plugins:** Independent folders discovered at runtime.
|
||||
- **Modules are Plugins:** Independent folders discovered at runtime.
|
||||
- **Commands are Endpoints:** Stateless handlers acting like REST API endpoints.
|
||||
- **Events are Observers:** Reactive logic subscribing to Discord lifecycle events.
|
||||
- **Controllers are Services:** Stateful managers bridging the gap between stateless commands and persistent behavior.
|
||||
- **Events are Observers:** Reactive logic subscribing to Discord lifecycle events.
|
||||
- **Controllers are Services:** Stateful managers bridging the gap between stateless commands and persistent behavior.
|
||||
|
||||
### System Boundaries
|
||||
|
||||
Understanding constraints is critical for design:
|
||||
Understanding constraints is critical for design:
|
||||
|
||||
- **No Persistence:** In-memory state is lost on restart. External storage is required for persistence.
|
||||
- **No Persistence:** In-memory state is lost on restart. External storage is required for persistence.
|
||||
- **No Inter-Module Communication:** Modules cannot directly invoke each other, ensuring loose coupling.
|
||||
- **No Dynamic Loading:** Modules are loaded only at startup.
|
||||
- **No Dynamic Loading:** Modules are loaded only at startup.
|
||||
|
||||
## Architectural Invariants
|
||||
|
||||
Quetza trades flexibility for predictability through strict conventions:
|
||||
Quetza trades flexibility for predictability through strict conventions:
|
||||
|
||||
- **Convention-Based Discovery:** Modules _must_ follow the directory structure (`module.ts`, `commands/`, `events/`) to be loaded.
|
||||
- **Single-Phase Initialization:** All loading happens before the Discord connection is established.
|
||||
- **Interface Compliance:** All commands and events must export specific interfaces to be registered.
|
||||
- **Convention-Based Discovery:** Modules _must_ follow the directory structure (`module.ts`, `commands/`, `events/`) to be loaded.
|
||||
- **Single-Phase Initialization:** All loading happens before the Discord connection is established.
|
||||
- **Interface Compliance:** All commands and events must export specific interfaces to be registered.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -3,15 +3,15 @@ title: Guides
|
||||
weight: 2
|
||||
---
|
||||
|
||||
**Quetza** guides provide step-by-step instructions for common tasks and workflows. These documents focus on practical application of the framework's concepts.
|
||||
**Quetza** guides provide step-by-step instructions for common tasks and workflows. These documents focus on practical application of the framework's concepts.
|
||||
|
||||
## Core Workflows
|
||||
|
||||
The development and operation of Quetza bots revolve around three primary workflows:
|
||||
The development and operation of Quetza bots revolve around three primary workflows:
|
||||
|
||||
1. **Module Development:** Creating new features by adding self-contained modules.
|
||||
2. **Deployment & Operations:** Running the bot in various environments (Docker, Source).
|
||||
3. **Lifecycle Management:** Maintaining modules from creation to deprecation.
|
||||
1. **Module Development:** Creating new features by adding self-contained modules.
|
||||
2. **Deployment & Operations:** Running the bot in various environments (Docker, Source).
|
||||
3. **Lifecycle Management:** Maintaining modules from creation to deprecation.
|
||||
|
||||
## Available Guides
|
||||
|
||||
|
||||
@@ -3,26 +3,26 @@ title: Conversational AI Integration
|
||||
weight: 4
|
||||
---
|
||||
|
||||
**Goal:** Integrate Large Language Models (LLMs) while managing context and Discord's timeout constraints.
|
||||
**Goal:** Integrate Large Language Models (LLMs) while managing context and Discord's timeout constraints.
|
||||
|
||||
## 1. Context Management Strategy
|
||||
|
||||
Conversations require history to be coherent.
|
||||
Conversations require history to be coherent.
|
||||
|
||||
- **Scoping:** `Map<GuildID, Map<UserID, Message[]>>`
|
||||
- **Guild Key:** Prevents cross-server leaks.
|
||||
- **User Key:** Prevents cross-user confusion in public channels.
|
||||
- **Lifecycle:** Implement a rolling window (e.g., last 50 messages) to prevent context bloat.
|
||||
- **User Key:** Prevents cross-user confusion in public channels.
|
||||
- **Lifecycle:** Implement a rolling window (e.g., last 50 messages) to prevent context bloat.
|
||||
|
||||
## 2. Response Streaming
|
||||
|
||||
LLMs are slow; Discord is fast (3s timeout).
|
||||
LLMs are slow; Discord is fast (3s timeout).
|
||||
|
||||
{{% steps %}}
|
||||
|
||||
### Step 1: Defer Interaction
|
||||
|
||||
Immediately call `interaction.deferReply()`. This buys you 15 minutes.
|
||||
Immediately call `interaction.deferReply()`. This buys you 15 minutes.
|
||||
|
||||
### Step 2: Invoke LLM
|
||||
|
||||
@@ -53,4 +53,4 @@ export async function execute(interaction, controller) {
|
||||
|
||||
> [!WARNING]
|
||||
> **API Costs:**
|
||||
> AI APIs are often billed by token. Implement strict user-based rate limits in your Controller to prevent abuse.
|
||||
> AI APIs are often billed by token. Implement strict user-based rate limits in your Controller to prevent abuse.
|
||||
@@ -3,31 +3,31 @@ title: Deployment & Operations
|
||||
weight: 2
|
||||
---
|
||||
|
||||
**Goal:** Configure, deploy, and monitor a Quetza bot instance.
|
||||
**Goal:** Configure, deploy, and monitor a Quetza bot instance.
|
||||
|
||||
## 1. Environment Preparation
|
||||
|
||||
Quetza relies on environment variables for configuration. **Never** commit these to version control.
|
||||
Quetza relies on environment variables for configuration. **Never** commit these to version control.
|
||||
|
||||
| Variable | Description | Required |
|
||||
| :-------------- | :-------------------------------------------- | :------- |
|
||||
| `DISCORD_TOKEN` | Bot token from Discord Developer Portal | **Yes** |
|
||||
| `CLIENT_ID` | Application ID for slash command registration | **Yes** |
|
||||
| `LLAMA_API_KEY` | Required if using the AI module | No |
|
||||
| `DISCORD_TOKEN` | Bot token from Discord Developer Portal | **Yes** |
|
||||
| `CLIENT_ID` | Application ID for slash command registration | **Yes** |
|
||||
| `LLAMA_API_KEY` | Required if using the AI module | No |
|
||||
|
||||
## 2. Deployment Strategies
|
||||
|
||||
{{< tabs >}}
|
||||
{{< tab name="Docker (Recommended)" >}}
|
||||
**Docker** ensures a consistent runtime environment.
|
||||
**Docker** ensures a consistent runtime environment.
|
||||
|
||||
1. **Build** the image:
|
||||
1. **Build** the image:
|
||||
|
||||
```bash
|
||||
docker build -t quetza-bot .
|
||||
```
|
||||
|
||||
2. **Run** the container:
|
||||
2. **Run** the container:
|
||||
`bash
|
||||
docker run -d \
|
||||
--env-file .env \
|
||||
@@ -36,7 +36,7 @@ docker run -d \
|
||||
`
|
||||
{{< /tab >}}
|
||||
{{< tab name="Source" >}}
|
||||
**Source** deployment is useful for development.
|
||||
**Source** deployment is useful for development.
|
||||
|
||||
3. **Install** dependencies:
|
||||
|
||||
@@ -44,13 +44,13 @@ docker run -d \
|
||||
pnpm install
|
||||
```
|
||||
|
||||
4. **Build** the project:
|
||||
4. **Build** the project:
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
5. **Start** the bot:
|
||||
5. **Start** the bot:
|
||||
`bash
|
||||
pnpm start
|
||||
`
|
||||
@@ -59,15 +59,15 @@ pnpm start
|
||||
|
||||
## 3. Operational Monitoring
|
||||
|
||||
Once running, use these mechanisms to check health:
|
||||
Once running, use these mechanisms to check health:
|
||||
|
||||
- **Logs:** Check standard output (Docker logs) for initialization errors.
|
||||
- **`/ping` Command:** Verifies network latency and API responsiveness.
|
||||
- **`/modules` Command:** Lists all loaded modules to confirm feature availability.
|
||||
- **Logs:** Check standard output (Docker logs) for initialization errors.
|
||||
- **`/ping` Command:** Verifies network latency and API responsiveness.
|
||||
- **`/modules` Command:** Lists all loaded modules to confirm feature availability.
|
||||
|
||||
> [!WARNING]
|
||||
> **Scaling Constraint:**
|
||||
> Quetza follows a single-instance-per-token model. Do not run multiple instances with the same token, as this will cause WebSocket conflicts.
|
||||
> Quetza follows a single-instance-per-token model. Do not run multiple instances with the same token, as this will cause WebSocket conflicts.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -3,19 +3,19 @@ title: Module Development Workflow
|
||||
weight: 1
|
||||
---
|
||||
|
||||
**Goal:** Create a new feature for the Quetza bot by implementing a self-contained module.
|
||||
**Goal:** Create a new feature for the Quetza bot by implementing a self-contained module.
|
||||
|
||||
## 1. Conceptualization Phase
|
||||
|
||||
Before writing code, determine the module's architecture:
|
||||
Before writing code, determine the module's architecture:
|
||||
|
||||
- **Simple Command:** Needs only a `commands/` folder (e.g., utility commands).
|
||||
- **Reactive Logic:** Needs `events/` to listen to Discord lifecycles (e.g., welcome messages).
|
||||
- **Stateful Feature:** Needs a **Controller** to manage state across guilds (e.g., music player).
|
||||
- **Simple Command:** Needs only a `commands/` folder (e.g., utility commands).
|
||||
- **Reactive Logic:** Needs `events/` to listen to Discord lifecycles (e.g., welcome messages).
|
||||
- **Stateful Feature:** Needs a **Controller** to manage state across guilds (e.g., music player).
|
||||
|
||||
## 2. Structure Establishment
|
||||
|
||||
Create the module directory structure. The presence of these files triggers automatic discovery.
|
||||
Create the module directory structure. The presence of these files triggers automatic discovery.
|
||||
|
||||
{{< filetree/container >}}
|
||||
{{< filetree/folder name="src" state="open" >}}
|
||||
@@ -34,9 +34,9 @@ Create the module directory structure. The presence of these files triggers auto
|
||||
|
||||
{{% steps %}}
|
||||
|
||||
### Step 1: Create the Manifest
|
||||
### Step 1: Create the Manifest
|
||||
|
||||
Create `module.ts` to declare the module.
|
||||
Create `module.ts` to declare the module.
|
||||
|
||||
```typescript
|
||||
// src/modules/my-feature/module.ts
|
||||
@@ -47,7 +47,7 @@ export const description = 'Adds cool feature capabilities';
|
||||
|
||||
### Step 2: Implement Commands
|
||||
|
||||
Create command files in `commands/`. Each file exports data and an executor.
|
||||
Create command files in `commands/`. Each file exports data and an executor.
|
||||
|
||||
```typescript
|
||||
// src/modules/my-feature/commands/ping.ts
|
||||
@@ -62,7 +62,7 @@ export async function execute(interaction) {
|
||||
|
||||
### Step 3: Implement Events (Optional)
|
||||
|
||||
Create event handlers in `events/` to observe Discord state.
|
||||
Create event handlers in `events/` to observe Discord state.
|
||||
|
||||
```typescript
|
||||
// src/modules/my-feature/events/ready.ts
|
||||
@@ -78,14 +78,14 @@ export function execute(client) {
|
||||
|
||||
### Step 4: Define Controller (Optional)
|
||||
|
||||
For stateful logic, implement a controller in `lib/` and export it in `module.ts`.
|
||||
For stateful logic, implement a controller in `lib/` and export it in `module.ts`.
|
||||
|
||||
### Step 5: Validate
|
||||
|
||||
Restart the bot.
|
||||
Restart the bot.
|
||||
|
||||
1. Check logs for "Loaded module: my-feature".
|
||||
2. Verify the command `/ping` appears in Discord.
|
||||
1. Check logs for "Loaded module: my-feature".
|
||||
2. Verify the command `/ping` appears in Discord.
|
||||
|
||||
{{% /steps %}}
|
||||
|
||||
|
||||
@@ -3,37 +3,37 @@ title: Interactive Voice Features
|
||||
weight: 3
|
||||
---
|
||||
|
||||
**Goal:** Implement sophisticated voice interactions that respect guild boundaries and manage ephemeral resources.
|
||||
**Goal:** Implement sophisticated voice interactions that respect guild boundaries and manage ephemeral resources.
|
||||
|
||||
## 1. Resource Scoping Strategy
|
||||
|
||||
Voice features **MUST** be scoped to the Guild.
|
||||
Voice features **MUST** be scoped to the Guild.
|
||||
|
||||
- **Pattern:** The Controller maintains a `Map<GuildID, Player>`.
|
||||
- **Pattern:** The Controller maintains a `Map<GuildID, Player>`.
|
||||
- **Behavior:**
|
||||
- **Join:** Create a Player for `Guild A` if none exists.
|
||||
- **Leave:** Destroy the Player and release connections.
|
||||
- **Isolation:** Commands in `Guild B` never affect `Guild A`.
|
||||
- **Join:** Create a Player for `Guild A` if none exists.
|
||||
- **Leave:** Destroy the Player and release connections.
|
||||
- **Isolation:** Commands in `Guild B` never affect `Guild A`.
|
||||
|
||||
## 2. Command Orchestration
|
||||
|
||||
Voice features require a suite of commands coordinated via the Controller.
|
||||
Voice features require a suite of commands coordinated via the Controller.
|
||||
|
||||
| Command | Action | Controller Logic |
|
||||
| :------ | :----------------- | :---------------------------------- |
|
||||
| `/join` | Connect to channel | `createPlayer(guildId, channelId)` |
|
||||
| `/play` | Add track to queue | `getPlayer(guildId).enqueue(track)` |
|
||||
| `/join` | Connect to channel | `createPlayer(guildId, channelId)` |
|
||||
| `/play` | Add track to queue | `getPlayer(guildId).enqueue(track)` |
|
||||
| `/stop` | Disconnect | `destroyPlayer(guildId)` |
|
||||
|
||||
## 3. State Persistence
|
||||
|
||||
Audio sessions are ephemeral.
|
||||
|
||||
- **Transient State:** Active audio stream (Lost on disconnect).
|
||||
- **Durable State:** Queue/Playlist (Persisted in Controller until restart).
|
||||
- **Transient State:** Active audio stream (Lost on disconnect).
|
||||
- **Durable State:** Queue/Playlist (Persisted in Controller until restart).
|
||||
|
||||
> [!TIP]
|
||||
> **Resilience:** Separate the _Queue_ logic from the _Voice Connection_ logic. This allows the bot to reconnect without losing the user's playlist.
|
||||
> **Resilience:** Separate the _Queue_ logic from the _Voice Connection_ logic. This allows the bot to reconnect without losing the user's playlist.
|
||||
|
||||
## 4. Implementation Sketch
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ title: Troubleshooting
|
||||
weight: 5
|
||||
---
|
||||
|
||||
**Quetza** troubleshooting focuses on diagnosing structural and conceptual issues. Because of its convention-based nature, most errors are silent (missing files) rather than noisy (stack traces).
|
||||
**Quetza** troubleshooting focuses on diagnosing structural and conceptual issues. Because of its convention-based nature, most errors are silent (missing files) rather than noisy (stack traces).
|
||||
|
||||
## Common Issue Categories
|
||||
|
||||
|
||||
@@ -3,39 +3,39 @@ title: Diagnostics Guide
|
||||
weight: 1
|
||||
---
|
||||
|
||||
**Goal:** Identify and fix common pitfalls in Quetza development.
|
||||
**Goal:** Identify and fix common pitfalls in Quetza development.
|
||||
|
||||
## 1. Module Discovery Failures
|
||||
|
||||
**Symptom:** The bot starts, but my module is ignored.
|
||||
**Cause:** Violation of filesystem conventions.
|
||||
**Symptom:** The bot starts, but my module is ignored.
|
||||
**Cause:** Violation of filesystem conventions.
|
||||
|
||||
{{% details title="Checklist: Directory Structure" closed="false" %}}
|
||||
|
||||
- [ ] Does `src/modules/<name>/` exist?
|
||||
- [ ] Does `module.ts` export `name`?
|
||||
- [ ] Are commands in `commands/` (not `cmds/`)?
|
||||
- [ ] Did you run `pnpm build`? (Quetza runs from `dist/`).
|
||||
- [ ] Are commands in `commands/` (not `cmds/`)?
|
||||
- [ ] Did you run `pnpm build`? (Quetza runs from `dist/`).
|
||||
{{% /details %}}
|
||||
|
||||
## 2. Command Registration Issues
|
||||
|
||||
**Symptom:** `/command` does not appear in Discord.
|
||||
**Symptom:** `/command` does not appear in Discord.
|
||||
|
||||
### Global vs. Test Guild Registration
|
||||
|
||||
- **Global:** Commands pushed to the application globally can take up to 1 hour to propagate and are subject to stricter rate limits.
|
||||
- **Test Guild:** Quetza automatically pushes commands to a specific guild in development mode for instant updates.
|
||||
- **Requirement:** Ensure `NODE_ENV=development` and `DEV_GUILD_ID` is correctly set in your `.env`.
|
||||
- **Global:** Commands pushed to the application globally can take up to 1 hour to propagate and are subject to stricter rate limits.
|
||||
- **Test Guild:** Quetza automatically pushes commands to a specific guild in development mode for instant updates.
|
||||
- **Requirement:** Ensure `NODE_ENV=development` and `DEV_GUILD_ID` is correctly set in your `.env`.
|
||||
|
||||
### Rate Limits
|
||||
|
||||
Frequent updates to global commands may trigger Discord's rate limits. Use a test guild for iterative development.
|
||||
Frequent updates to global commands may trigger Discord's rate limits. Use a test guild for iterative development.
|
||||
|
||||
## 3. Interaction Failures
|
||||
|
||||
**Symptom:** "The application did not respond".
|
||||
**Cause:** Command took > 3 seconds without deferral.
|
||||
**Symptom:** "The application did not respond".
|
||||
**Cause:** Command took > 3 seconds without deferral.
|
||||
|
||||
**Solution:**
|
||||
|
||||
@@ -53,21 +53,21 @@ await interaction.editReply('Done');
|
||||
## 4. State Management Leaks
|
||||
|
||||
**Symptom:** Bot memory usage grows; cross-server weirdness.
|
||||
**Cause:** Storing state globally instead of per-guild.
|
||||
**Cause:** Storing state globally instead of per-guild.
|
||||
|
||||
**Diagnostic:**
|
||||
Check your Controller.
|
||||
|
||||
- ❌ `private player: AudioPlayer;` (Shared by everyone!)
|
||||
- ✅ `private players = new Map<string, AudioPlayer>();` (Scoped by ID).
|
||||
- ❌ `private player: AudioPlayer;` (Shared by everyone!)
|
||||
- ✅ `private players = new Map<string, AudioPlayer>();` (Scoped by ID).
|
||||
|
||||
## 5. Event Handling
|
||||
|
||||
**Symptom:** Events fire multiple times or not at all.
|
||||
**Symptom:** Events fire multiple times or not at all.
|
||||
|
||||
- **Multiple:** Events are additive. Did you register the same handler in two modules?
|
||||
- **None:** Did you export `name` and `execute` correctly?
|
||||
- **Multiple:** Events are additive. Did you register the same handler in two modules?
|
||||
- **None:** Did you export `name` and `execute` correctly?
|
||||
|
||||
> [!TIP]
|
||||
> **Debug Mode:**
|
||||
> Enable verbose logging to see exactly which modules and commands are loaded at startup.
|
||||
> Enable verbose logging to see exactly which modules and commands are loaded at startup.
|
||||
Reference in new issue
Block a user