fix: PageHead header alignment, analytics proxy, and infra improvements (#64)
🤖 Pull request created from `various-fixes` containing PageHead
breadcrumbs and navigation alignment fixes, Umami analytics proxy, and
infrastructure updates.
This commit is contained in:
1 parent
ff5a50bad8
commit
9ee672504f
110 files changed
+2649
-1760
No files matched your search
@@ -7,29 +7,29 @@ cascade:
|
||||
type: docs
|
||||
---
|
||||
|
||||
**Quetza** — это модульный фреймворк для Discord-ботов, построенный на TypeScript, который позволяет разработчикам создавать многофункциональные приложения для Discord с помощью самодостаточных, композитных модулей.
|
||||
**Quetza** — модульный фреймворк на TypeScript для Discord-ботов. Он позволяет собирать приложения из самодостаточных независимых модулей.
|
||||
|
||||
Фреймворк обеспечивает архитектурный фундамент, который превращает разработку функций из модификации ядра в добавление модулей.
|
||||
Архитектура Quetza переносит разработку новой функциональности из модификации ядра в добавление отдельных модулей.
|
||||
|
||||
## Основные возможности
|
||||
|
||||
- **Обнаружение модулей на основе соглашений**: Просто создайте папку, и Quetza загрузит ее как функциональный модуль.
|
||||
- **Изоляция контроллеров**: Управляйте состоянием на уровне сервера (guild), предотвращая утечки данных между серверами.
|
||||
- **Декларативные команды**: Определяйте Slash-команды Discord с помощью простого, типизированного интерфейса.
|
||||
- **Реактивные события**: Подписывайтесь на любые события Discord.js внутри ваших модулей.
|
||||
- **Обнаружение модулей по соглашениям:** создайте папку, и Quetza автоматически загрузит её как модуль.
|
||||
- **Изоляция контроллеров:** управление состоянием происходит на уровне сервера (guild), что исключает утечки данных между серверами.
|
||||
- **Декларативные команды:** определение слэш-команд Discord через типизированный интерфейс.
|
||||
- **Реактивные события:** подписка на любые события Discord.js внутри модулей.
|
||||
|
||||
## Разделы
|
||||
|
||||
{{% cards %}}
|
||||
{{< card link="getting-started" title="Начало работы" icon="lightning-bolt" subtitle="Поймите философию и архитектуру Quetza." >}}
|
||||
{{< card link="concepts" title="Концепции" icon="light-bulb" subtitle="Глубокое погружение в модульную систему и структуру контроллеров." >}}
|
||||
{{< card link="getting-started" title="Начало работы" icon="lightning-bolt" subtitle="Философия и архитектура Quetza." >}}
|
||||
{{< card link="concepts" title="Концепции" icon="light-bulb" subtitle="Модульная система и структура контроллеров." >}}
|
||||
{{< card link="guides" title="Руководства" icon="book-open" subtitle="Пошаговые инструкции по разработке модулей и деплою." >}}
|
||||
{{< card link="troubleshooting" title="Устранение неполадок" icon="shield-exclamation" subtitle="Диагностика распространенных проблем в разработке модулей." >}}
|
||||
{{< card link="troubleshooting" title="Устранение неполадок" icon="shield-exclamation" subtitle="Диагностика частых проблем при разработке модулей." >}}
|
||||
{{% /cards %}}
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
## См. также
|
||||
|
||||
- [GitHub: Quetza](https://github.com/deytenit/Quetza)
|
||||
- [Discord.js Documentation](https://discord.js.org/)
|
||||
- [Документация Discord.js](https://discord.js.org/)
|
||||
@@ -3,4 +3,4 @@ title: Концепции
|
||||
weight: 2
|
||||
---
|
||||
|
||||
В этом разделе описываются архитектурные принципы, на которых построена Quetza. Понимание этих концепций поможет вам проектировать более надежные и поддерживаемые модули.
|
||||
Здесь описаны ключевые архитектурные принципы Quetza. Понимание этих концепций помогает проектировать надёжные и легко поддерживаемые модули.
|
||||
@@ -1,45 +1,45 @@
|
||||
---
|
||||
title: Архитектура и Философия
|
||||
title: Архитектура и философия
|
||||
weight: 1
|
||||
---
|
||||
|
||||
**Цель:** Понять основные принципы проектирования, лежащие в основе модульности Quetza.
|
||||
**Цель:** изучить принципы проектирования, определяющие модульную структуру Quetza.
|
||||
|
||||
## Философия проектирования
|
||||
|
||||
### Соглашение важнее конфигурации (Convention Over Configuration)
|
||||
### Соглашение важнее конфигурации (Convention over Configuration)
|
||||
|
||||
Quetza минимизирует шаблонный код, полагаясь на строгую структуру папок.
|
||||
Quetza сокращает шаблонный код за счёт строгой структуры каталогов.
|
||||
|
||||
- **Никакого центрального реестра:** Сама файловая система _является_ реестром.
|
||||
- **Результат:** Вам не нужно обновлять файл конфигурации, чтобы добавить модуль; вы просто создаете папку.
|
||||
- **Без центрального реестра:** файловая система сама выступает реестром.
|
||||
- **Результат:** чтобы подключить модуль, не нужно редактировать конфигурационные файлы — достаточно создать каталог.
|
||||
|
||||
### Композиция важнее наследования (Composition Over Inheritance)
|
||||
### Композиция важнее наследования (Composition over Inheritance)
|
||||
|
||||
Модули состоят из возможностей (capabilities), а не наследуются от базового класса.
|
||||
Модули собираются из набора возможностей (capabilities), а не наследуются от базового класса.
|
||||
|
||||
- **Гибкость:** Модули могут использовать любую внутреннюю архитектуру (Функциональную, ООП), пока они экспортируют необходимые интерфейсы.
|
||||
- **Гибкость:** внутри модуля можно использовать любую архитектуру (функциональную или ООП), если модуль экспортирует обязательные интерфейсы.
|
||||
|
||||
### Изоляция важнее интеграции (Isolation Over Integration)
|
||||
### Изоляция важнее интеграции (Isolation over Integration)
|
||||
|
||||
Модули не могут напрямую вызывать друг друга.
|
||||
Модули не вызывают друг друга напрямую.
|
||||
|
||||
- **Почему:** Это предотвращает сильную связность (tight coupling).
|
||||
- **Преимущество:** Вы можете удалить любой модуль, не сломав остальную часть бота.
|
||||
- **Причина:** исключает сильную связанность (tight coupling).
|
||||
- **Преимущество:** любой модуль можно удалить без риска сломать остального бота.
|
||||
|
||||
## Основные сущности
|
||||
|
||||
| Сущность | Роль | Жизненный цикл |
|
||||
| :--- | :--- | :--- |
|
||||
| **Client** | Локатор сервисов и оркестратор | Синглтон. Руководит всем. |
|
||||
| **Module** | Пространство имен для функций | Загружается при запуске. |
|
||||
| **Command** | Конечная точка взаимодействия с пользователем | Без состояния (Stateless). Запрос/Ответ. |
|
||||
| **Event** | Реактивный наблюдатель (Observer) | Подписывается при запуске. |
|
||||
| **Controller** | Менеджер состояния | Сохраняется между взаимодействиями. |
|
||||
| **Client** | Локатор сервисов и оркестратор | Синглтон. Управляет всеми компонентами системы. |
|
||||
| **Module** | Пространство имён для функций | Загружается при старте. |
|
||||
| **Command** | Точка взаимодействия с пользователем | Без состояния (stateless). Запрос — ответ. |
|
||||
| **Event** | Реактивный наблюдатель (observer) | Регистрируется при старте. |
|
||||
| **Controller** | Менеджер состояния | Сохраняет состояние между запросами. |
|
||||
|
||||
---
|
||||
|
||||
**См. также:**
|
||||
## См. также
|
||||
|
||||
- [Паттерн Service Locator](https://ru.wikipedia.org/wiki/Локатор_служб)
|
||||
- [Паттерн Observer](https://ru.wikipedia.org/wiki/Наблюдатель_(шаблон_проектирования))
|
||||
@@ -3,13 +3,13 @@ title: Модульная система
|
||||
weight: 2
|
||||
---
|
||||
|
||||
**Цель:** Определить словарь и механизмы основной абстрактной единицы Quetza.
|
||||
**Цель:** разобрать терминологию и механику работы базовой единицы Quetza — модуля.
|
||||
|
||||
## Системный словарь
|
||||
## Терминология
|
||||
|
||||
### Объявление модуля (Module Declaration)
|
||||
|
||||
Файл `module.ts` выступает в качестве манифеста. Это точка входа для обнаружения.
|
||||
Файл `module.ts` служит манифестом и точкой входа при поиске модулей.
|
||||
|
||||
```typescript
|
||||
export const name = 'my-module'; // ID
|
||||
@@ -18,50 +18,50 @@ export const description = '...'; // Документация
|
||||
|
||||
### Регистрация команд (Command Registration)
|
||||
|
||||
Происходит во время события `ready`.
|
||||
Выполняется при наступлении события `ready`:
|
||||
|
||||
1. Quetza сканирует все папки `commands/`.
|
||||
2. Компилирует `ApplicationCommandData`.
|
||||
3. Отправляет (PUT) данные в API Discord.
|
||||
1. Quetza сканирует каталоги `commands/`.
|
||||
2. Формирует структуру `ApplicationCommandData`.
|
||||
3. Отправляет данные (PUT-запрос) в API Discord.
|
||||
|
||||
### Внедрение контроллера (Controller Injection)
|
||||
|
||||
Состояние внедряется (injected), а не импортируется.
|
||||
Экземпляр контроллера передаётся аргументом при вызове (injected), а не импортируется модулем напрямую:
|
||||
|
||||
```typescript
|
||||
// Фреймворк вызывает это:
|
||||
execute(client, interaction, controller);
|
||||
```
|
||||
|
||||
- **Зачем?** Позволяет фреймворку управлять жизненным циклом контроллера (синглтон на каждый модуль).
|
||||
- **Зачем:** фреймворк берёт на себя управление жизненным циклом контроллера (один синглтон на модуль).
|
||||
|
||||
## Философия управления состоянием
|
||||
## Управление состоянием
|
||||
|
||||
### Эфемерность по умолчанию
|
||||
|
||||
Quetza **не предоставляет встроенной базы данных**.
|
||||
В Quetza **нет встроенной базы данных**.
|
||||
|
||||
- **Память:** Контроллеры хранят состояние в JS объектах `Map` или `Set`.
|
||||
- **Перезапуск:** Все состояние теряется при завершении процесса.
|
||||
- **Постоянство:** Должно быть реализовано вручную (например, SQLite, Redis) внутри Контроллера.
|
||||
- **Память:** контроллеры сохраняют данные в стандартных JavaScript-коллекциях `Map` или `Set`.
|
||||
- **Перезапуск:** при остановке процесса всё состояние в памяти сбрасывается.
|
||||
- **Постоянное хранение:** если данные нужно сохранять между запусками, подключите внешнюю СУБД (например, SQLite или Redis) внутри контроллера.
|
||||
|
||||
### Область видимости как ключ
|
||||
|
||||
Состояние должно быть ключировано по его границам.
|
||||
Ключи состояния должны соответствовать области его видимости:
|
||||
|
||||
- `Map<GuildID, ...>` - Специфично для сервера (Наиболее частое).
|
||||
- `Map<UserID, ...>` - Специфично для пользователя (Боты для личных сообщений - DM).
|
||||
- `Map<GuildID, ...>` — уровень сервера (основной сценарий).
|
||||
- `Map<UserID, ...>` — уровень пользователя (боты для личных сообщений, DM).
|
||||
|
||||
## Модель обработки ошибок
|
||||
|
||||
**Быстрый и дружелюбный отказ (Fail Fast & Friendly).**
|
||||
**Быстрый и понятный отказ (Fail Fast & Friendly).**
|
||||
|
||||
- **Валидация:** Проверяйте права/вводы немедленно.
|
||||
- **Для пользователя:** "У вас нет прав" (а не "Ошибка: 403").
|
||||
- **Изоляция:** Сбой в `/ping` перехватывается сам по себе и не "убивает" бота.
|
||||
- **Валидация:** проверяйте права и входные параметры сразу.
|
||||
- **Сообщения для пользователя:** «У вас нет прав» вместо сухого кода вроде «Ошибка: 403».
|
||||
- **Изоляция:** сбой внутри `/ping` перехватывается локально и не роняет процесс бота.
|
||||
|
||||
---
|
||||
|
||||
**См. также:**
|
||||
## См. также
|
||||
|
||||
- [Жизненный цикл взаимодействия Discord (Interaction Lifecycle)](https://discord.com/developers/docs/interactions/receiving-and-responding)
|
||||
@@ -3,64 +3,64 @@ title: Начало работы
|
||||
weight: 1
|
||||
---
|
||||
|
||||
**Quetza** — это модульный фреймворк для Discord-ботов, построенный на TypeScript, который позволяет разработчикам создавать многофункциональные приложения для Discord с помощью самодостаточных, композитных модулей.
|
||||
**Quetza** — модульный фреймворк на TypeScript для Discord-ботов. Он позволяет собирать ботов из самодостаточных независимых модулей.
|
||||
|
||||
## Что такое Quetza?
|
||||
|
||||
Quetza предоставляет архитектурный фундамент, который превращает разработку функций из модификации ядра в добавление модулей. Он решает проблему жесткого дизайна ботов за счет инверсии структур зависимостей: ядро ничего не знает о модулях, однако модули имеют полный доступ к возможностям через определенные контракты.
|
||||
Quetza даёт архитектурный каркас, где разработка новой функциональности сводится к добавлению модулей, а не правке ядра. Это решает проблему жёсткой архитектуры за счёт инверсии зависимостей: ядро ничего не знает о модулях, а модули взаимодействуют с системой через типизированные контракты.
|
||||
|
||||
## Основная философия
|
||||
|
||||
### Проблема
|
||||
|
||||
Традиционные монолитные боты страдают от хрупкости. Добавление функций требует изменения логики ядра, переплетения зависимостей и управления растущими базами кода, которые трудно тестировать или изменять.
|
||||
Традиционные монолитные боты хрупки: каждая новая функция требует правок в ядре, запутывает зависимости и раздувает кодовую базу, которую со временем становится сложно тестировать и поддерживать.
|
||||
|
||||
### Решение
|
||||
|
||||
Quetza рассматривает модули как плагины.
|
||||
Quetza работает с модулями как с плагинами:
|
||||
|
||||
- **Расширение без правки ядра:** Добавляйте функции, создавая папку. Модификация кода ядра не требуется.
|
||||
- **Изоляция:** Модули работают независимо.
|
||||
- **Композиция:** Включайте или выключайте функции, просто добавляя или удаляя папки модулей.
|
||||
- **Расширение без правки ядра:** добавьте каталог с модулем, и функция подключена. Менять исходный код ядра не нужно.
|
||||
- **Изоляция:** модули выполняются независимо друг от друга.
|
||||
- **Композиция:** подключайте и отключайте возможности, добавляя или удаляя каталоги модулей.
|
||||
|
||||
## Высокоуровневая архитектура
|
||||
|
||||
Quetza состоит из трех основных уровней:
|
||||
Quetza состоит из трёх уровней:
|
||||
|
||||
1. **Базовый уровень (Foundation Layer)**: Клиент `Discord.js`, расширенный реестрами модулей (команды, события, модули). Он действует как сервис-локатор.
|
||||
2. **Модульный уровень (Module Layer)**: Самодостаточные пакеты функций. Каждый модуль предоставляет собственные команды и события через стандартизированную структуру файлов.
|
||||
3. **Сервисный уровень (Service Layer)**: Опциональные **Контроллеры**, которые управляют состоянием бизнес-логики (например, аудиоплееры, контекст разговора) на разных серверах (guilds).
|
||||
1. **Базовый уровень (Foundation Layer):** клиент `Discord.js`, расширенный реестрами команд, событий и модулей. Выступает в роли сервис-локатора.
|
||||
2. **Модульный уровень (Module Layer):** изолированные наборы функций. Модуль объявляет собственные команды и события через стандартизированную структуру файлов.
|
||||
3. **Сервисный уровень (Service Layer):** контроллеры для управления состоянием бизнес-логики (например, аудиоплеером или контекстом диалога) на разных серверах (guilds).
|
||||
|
||||
## Ключевые концепции
|
||||
|
||||
### Ментальная модель
|
||||
|
||||
Для эффективной работы с Quetza примите следующую парадигму:
|
||||
При работе с Quetza полезна следующая аналогия:
|
||||
|
||||
- **Модули — это плагины:** Независимые папки, обнаруживаемые во время выполнения.
|
||||
- **Команды — это конечные точки (Endpoints):** Обработчики без сохранения состояния, действующие подобно эндпоинтам REST API.
|
||||
- **События — это наблюдатели (Observers):** Реактивная логика, подписывающаяся на события жизненного цикла Discord.
|
||||
- **Контроллеры — это сервисы:** Менеджеры состояния, восполняющие пробел между командами без состояния и постоянным поведением.
|
||||
- **Модули — плагины:** независимые каталоги, обнаруживаемые во время запуска.
|
||||
- **Команды — эндпоинты:** обработчики без состояния, работающие аналогично конечным точкам REST API.
|
||||
- **События — наблюдатели (observers):** реактивная логика, подписанная на события жизненного цикла Discord.
|
||||
- **Контроллеры — сервисы:** менеджеры состояния, связывающие команды без состояния с долговременной логикой бота.
|
||||
|
||||
### Границы системы
|
||||
|
||||
Понимание ограничений критически важно для проектирования:
|
||||
Ограничения, которые важно учитывать при проектировании:
|
||||
|
||||
- **Отсутствие постоянства (Persistence):** Состояние в памяти теряется при перезагрузке. Для постоянного хранения требуется внешняя база данных.
|
||||
- **Отсутствие межмодульного взаимодействия:** Модули не могут напрямую вызывать друг друга, что обеспечивает слабую связанность.
|
||||
- **Отсутствие динамической загрузки:** Модули загружаются только при запуске.
|
||||
- **Нет встроенного постоянного хранилища (persistence):** состояние в памяти сбрасывается при перезапуске. Для долговременного хранения нужна внешняя база данных.
|
||||
- **Нет межмодульного взаимодействия:** модули не вызывают друг друга напрямую, что гарантирует слабую связанность.
|
||||
- **Нет динамической перезагрузки:** модули загружаются один раз при старте процесса.
|
||||
|
||||
## Архитектурные инварианты
|
||||
|
||||
Quetza жертвует гибкостью ради предсказуемости с помощью строгих соглашений:
|
||||
Quetza ставит предсказуемость выше избыточной гибкости за счёт строгих соглашений:
|
||||
|
||||
- **Обнаружение на основе соглашений:** Модули _обязаны_ следовать структуре директорий (`module.ts`, `commands/`, `events/`) для загрузки.
|
||||
- **Однофазная инициализация:** Вся загрузка происходит до установления соединения с Discord.
|
||||
- **Соблюдение интерфейсов:** Все команды и события должны экспортировать специфические интерфейсы для их регистрации.
|
||||
- **Обнаружение по соглашениям:** чтобы модуль загрузился, структура его каталога _обязана_ содержать `module.ts`, `commands/` и `events/`.
|
||||
- **Однофазная инициализация:** все модули загружаются до установки соединения с Discord.
|
||||
- **Соблюдение контрактов:** команды и события должны экспортировать типизированные интерфейсы, необходимые для регистрации.
|
||||
|
||||
---
|
||||
|
||||
**See also:**
|
||||
## См. также
|
||||
|
||||
- [Discord.js Documentation](https://discord.js.org/)
|
||||
- [TypeScript Documentation](https://www.typescriptlang.org/)
|
||||
- [Документация Discord.js](https://discord.js.org/)
|
||||
- [Документация TypeScript](https://www.typescriptlang.org/)
|
||||
@@ -3,4 +3,4 @@ title: Руководства
|
||||
weight: 3
|
||||
---
|
||||
|
||||
Пошаговые инструкции и руководства по реализации функций в Quetza.
|
||||
Пошаговые руководства и инструкции по разработке и настройке возможностей Quetza.
|
||||
@@ -3,34 +3,34 @@ title: Интеграция разговорного ИИ
|
||||
weight: 4
|
||||
---
|
||||
|
||||
**Цель:** Интегрировать большие языковые модели (LLM), управляя контекстом и ограничениями тайм-аута Discord.
|
||||
**Цель:** подключить большие языковые модели (LLM), настроить управление контекстом и уложиться в тайм-ауты Discord.
|
||||
|
||||
## 1. Стратегия управления контекстом
|
||||
|
||||
Разговоры требуют истории, чтобы быть связными.
|
||||
Чтобы диалог оставался связным, модели нужна история сообщений:
|
||||
|
||||
- **Область видимости (Scoping):** `Map<GuildID, Map<UserID, Message[]>>`
|
||||
- **Ключ гильдии (Guild Key):** Предотвращает утечки между серверами.
|
||||
- **Ключ пользователя (User Key):** Предотвращает путаницу между пользователями в публичных каналах.
|
||||
- **Жизненный цикл:** Реализуйте "скользящее окно" (например, последние 50 сообщений) для предотвращения разрастания контекста.
|
||||
- **Ключ сервера (Guild Key):** изолирует контекст и защищает от утечек данных между серверами.
|
||||
- **Ключ пользователя (User Key):** разделяет реплики разных участников в публичных каналах.
|
||||
- **Жизненный цикл:** настройте «скользящее окно» (например, последние 50 сообщений), чтобы контекст не разрастался.
|
||||
|
||||
## 2. Потоковая передача ответов
|
||||
|
||||
LLM работают медленно, а Discord требует быстрых ответов (тайм-аут 3 секунды).
|
||||
LLM генерируют ответ постепенно, а Discord ждёт реакции не дольше 3 секунд.
|
||||
|
||||
{{% steps %}}
|
||||
|
||||
### Шаг 1: Отложенное взаимодействие (Defer Interaction)
|
||||
### Шаг 1: Отложенный ответ (Defer Interaction)
|
||||
|
||||
Немедленно вызовите `interaction.deferReply()`. Это даст вам 15 минут.
|
||||
Сразу вызовите `interaction.deferReply()`. Это продлит время ожидания ответа до 15 минут.
|
||||
|
||||
### Шаг 2: Вызов LLM
|
||||
### Шаг 2: Запрос к LLM
|
||||
|
||||
Асинхронно вызовите ваш ИИ-сервис.
|
||||
Асинхронно отправьте запрос к ИИ-сервису.
|
||||
|
||||
### Шаг 3: Редактирование ответа
|
||||
### Шаг 3: Отправка ответа
|
||||
|
||||
Когда данные поступят, используйте `interaction.editReply(content)`.
|
||||
Когда ответ готов, вызовите `interaction.editReply(content)`.
|
||||
{{% /steps %}}
|
||||
|
||||
## 3. Пример реализации
|
||||
@@ -52,5 +52,5 @@ export async function execute(interaction, controller) {
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> **Затраты на API:**
|
||||
> API ИИ часто тарифицируются по токенам. Внедрите строгие лимиты запросов (rate limits) для пользователей в вашем Контроллере, чтобы предотвратить злоупотребления.
|
||||
> **Расходы на API:**
|
||||
> Провайдеры ИИ обычно тарифицируют запросы по токенам. Настройте в контроллере строгие лимиты запросов (rate limits) для пользователей, чтобы избежать лишних расходов.
|
||||
@@ -1,25 +1,25 @@
|
||||
---
|
||||
title: Развертывание и эксплуатация
|
||||
title: Развёртывание и эксплуатация
|
||||
weight: 2
|
||||
---
|
||||
|
||||
**Цель:** Настроить, развернуть и мониторить экземпляр бота Quetza.
|
||||
**Цель:** настроить, развернуть и контролировать работу бота Quetza.
|
||||
|
||||
## 1. Подготовка окружения
|
||||
|
||||
Quetza полагается на переменные окружения для конфигурации. **Никогда** не сохраняйте их в систему контроля версий.
|
||||
Quetza настраивается через переменные окружения. **Никогда** не сохраняйте их в систему контроля версий.
|
||||
|
||||
| Переменная | Описание | Обязательно |
|
||||
| :--- | :--- | :--- |
|
||||
| `DISCORD_TOKEN` | Токен бота из Discord Developer Portal | **Да** |
|
||||
| `CLIENT_ID` | ID приложения для регистрации slash-команд | **Да** |
|
||||
| `LLAMA_API_KEY` | Требуется при использовании модуля ИИ | Нет |
|
||||
| `DISCORD_TOKEN` | Токен бота из Discord Developer Portal | **Да** |
|
||||
| `CLIENT_ID` | Идентификатор приложения для регистрации слэш-команд | **Да** |
|
||||
| `LLAMA_API_KEY` | Требуется для модуля ИИ | Нет |
|
||||
|
||||
## 2. Стратегии развертывания
|
||||
## 2. Способы развёртывания
|
||||
|
||||
{{< tabs >}}
|
||||
{{< tab name="Docker (Рекомендуется)" >}}
|
||||
**Docker** обеспечивает стабильное окружение выполнения.
|
||||
{{< tab name="Docker (рекомендуется)" >}}
|
||||
**Docker** обеспечивает предсказуемое и изолированное окружение.
|
||||
|
||||
1. **Сборка** образа:
|
||||
|
||||
@@ -35,8 +35,8 @@ Quetza полагается на переменные окружения для
|
||||
quetza-bot
|
||||
```
|
||||
{{< /tab >}}
|
||||
{{< tab name="Из исходников (Source)" >}}
|
||||
Развертывание **из исходников** полезно для разработки.
|
||||
{{< tab name="Из исходного кода" >}}
|
||||
Развёртывание **из исходного кода** подходит для разработки и отладки.
|
||||
|
||||
1. **Установка** зависимостей:
|
||||
|
||||
@@ -57,17 +57,17 @@ Quetza полагается на переменные окружения для
|
||||
{{< /tab >}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## 3. Операционный мониторинг
|
||||
## 3. Мониторинг
|
||||
|
||||
После запуска используйте следующие механизмы для проверки работоспособности:
|
||||
После запуска проверьте состояние бота:
|
||||
|
||||
- **Логи:** Проверьте стандартный вывод (логи Docker) на наличие ошибок инициализации.
|
||||
- **Команда `/ping`:** Проверяет задержку сети и отзывчивость API.
|
||||
- **Команда `/modules`:** Перечисляет все загруженные модули, чтобы подтвердить доступность функций.
|
||||
- **Логи:** проверьте стандартный вывод (логи Docker) на ошибки инициализации.
|
||||
- **Команда `/ping`:** измеряет задержку сети и отзывчивость API.
|
||||
- **Команда `/modules`:** выводит список загруженных модулей, подтверждая доступность функций.
|
||||
|
||||
> [!WARNING]
|
||||
> **Ограничение масштабирования:**
|
||||
> Quetza следует модели "один экземпляр на один токен". Не запускайте несколько экземпляров с одним и тем же токеном, так как это вызовет конфликты WebSocket.
|
||||
> Quetza работает по модели «один экземпляр на один токен». Не запускайте несколько копий бота с одним токеном: это вызовет конфликты соединений WebSocket.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
---
|
||||
title: Процесс разработки модуля
|
||||
title: Разработка модуля
|
||||
weight: 1
|
||||
---
|
||||
|
||||
**Цель:** Создать новую функцию для бота Quetza путем реализации самодостаточного модуля.
|
||||
**Цель:** добавить новую возможность в бота Quetza в виде изолированного модуля.
|
||||
|
||||
## 1. Фаза концептуализации
|
||||
## 1. Проектирование модуля
|
||||
|
||||
Перед написанием кода определите архитектуру модуля:
|
||||
Перед написанием кода выберите подходящую структуру модуля:
|
||||
|
||||
- **Простая команда:** Требуется только папка `commands/` (например, служебные команды).
|
||||
- **Реактивная логика:** Нужна папка `events/` для прослушивания жизненного цикла Discord (например, приветственные сообщения).
|
||||
- **Функция с состоянием:** Требуется **Контроллер** (Controller) для управления состоянием на разных серверах (например, музыкальный плеер).
|
||||
- **Простая команда:** достаточно каталога `commands/` (например, для служебных команд).
|
||||
- **Реактивная логика:** нужен каталог `events/` для обработки событий Discord (например, приветственных сообщений).
|
||||
- **Логика с состоянием:** понадобится контроллер (`Controller`) для управления состоянием между серверами (например, для музыкального плеера).
|
||||
|
||||
## 2. Создание структуры
|
||||
## 2. Структура каталогов
|
||||
|
||||
Создайте структуру директорий модуля. Наличие этих файлов запускает автоматическое обнаружение.
|
||||
Создайте дерево каталогов модуля. Quetza автоматически найдёт и загрузит нужные файлы:
|
||||
|
||||
{{< filetree/container >}}
|
||||
{{< filetree/folder name="src" state="open" >}}
|
||||
@@ -30,13 +30,13 @@ weight: 1
|
||||
{{< /filetree/folder >}}
|
||||
{{< /filetree/container >}}
|
||||
|
||||
## 3. Шаги реализации
|
||||
## 3. Порядок реализации
|
||||
|
||||
{{% steps %}}
|
||||
|
||||
### Шаг 1: Создание манифеста
|
||||
### Шаг 1: Манифест модуля
|
||||
|
||||
Создайте `module.ts` для объявления модуля.
|
||||
Создайте `module.ts` с описанием модуля:
|
||||
|
||||
```typescript
|
||||
// src/modules/my-feature/module.ts
|
||||
@@ -45,9 +45,9 @@ export const description = 'Добавляет крутые возможност
|
||||
// Опционально: export const controller = new MyFeatureController();
|
||||
```
|
||||
|
||||
### Шаг 2: Реализация команд
|
||||
### Шаг 2: Команды
|
||||
|
||||
Создайте файлы команд в папке `commands/`. Каждый файл экспортирует данные и функцию-исполнитель (executor).
|
||||
Создайте файлы команд в каталоге `commands/`. Каждый файл экспортирует описание команды и функцию выполнения (`execute`).
|
||||
|
||||
```typescript
|
||||
// src/modules/my-feature/commands/ping.ts
|
||||
@@ -60,9 +60,9 @@ export async function execute(interaction) {
|
||||
}
|
||||
```
|
||||
|
||||
### Шаг 3: Реализация событий (Опционально)
|
||||
### Шаг 3: Обработчики событий (опционально)
|
||||
|
||||
Создайте обработчики событий в `events/` для отслеживания состояния Discord.
|
||||
Создайте обработчики в каталоге `events/`, чтобы реагировать на события Discord:
|
||||
|
||||
```typescript
|
||||
// src/modules/my-feature/events/ready.ts
|
||||
@@ -76,30 +76,30 @@ export function execute(client) {
|
||||
}
|
||||
```
|
||||
|
||||
### Шаг 4: Определение контроллера (Опционально)
|
||||
### Шаг 4: Контроллер (опционально)
|
||||
|
||||
Для логики, требующей сохранения состояния, реализуйте контроллер в папке `lib/` и экспортируйте его в `module.ts`.
|
||||
Если модулю нужно хранить состояние, создайте класс контроллера в каталоге `lib/` и экспортируйте его в `module.ts`.
|
||||
|
||||
### Шаг 5: Валидация
|
||||
### Шаг 5: Проверка
|
||||
|
||||
Перезапустите бота.
|
||||
Перезапустите бота:
|
||||
|
||||
1. Проверьте логи на наличие "Loaded module: my-feature".
|
||||
2. Убедитесь, что команда `/ping` появилась в Discord.
|
||||
1. Найдите в логах строку «Loaded module: my-feature».
|
||||
2. Убедитесь, что команда `/ping` появилась и работает в Discord.
|
||||
|
||||
{{% /steps %}}
|
||||
|
||||
## Шаблоны интеграции
|
||||
|
||||
| Паттерн | Сценарий использования | Компоненты |
|
||||
| Шаблон | Назначение | Состав |
|
||||
| :--- | :--- | :--- |
|
||||
| **Простая команда** | Утилиты без состояния (Ping, Бросок кубиков) | Только `commands/` |
|
||||
| **Сервис с состоянием** | Музыка, RPG, Экономика | `commands/` + `lib/Controller` |
|
||||
| **Событийно-ориентированный** | Автомодерация, Логирование | Только `events/` |
|
||||
| **Гибридный** | Сложные функции (ИИ-чат) | Все компоненты |
|
||||
| **Простая команда** | Утилиты без сохранения состояния (`/ping`, бросок кубика) | Только `commands/` |
|
||||
| **Сервис с состоянием** | Музыка, ролевые игры, экономика | `commands/` + `lib/Controller` |
|
||||
| **Событийная логика** | Автомодерация, логирование | Только `events/` |
|
||||
| **Гибридный модуль** | Сложные сценарии (например, ИИ-чат) | Все компоненты |
|
||||
|
||||
---
|
||||
|
||||
**См. также:**
|
||||
|
||||
- [Руководство Discord.js: Slash-команды](https://discordjs.guide/creating-your-bot/slash-commands.html)
|
||||
- [Руководство Discord.js: слэш-команды](https://discordjs.guide/creating-your-bot/slash-commands.html)
|
||||
@@ -1,39 +1,39 @@
|
||||
---
|
||||
title: Интерактивные голосовые функции
|
||||
title: Голосовые функции
|
||||
weight: 3
|
||||
---
|
||||
|
||||
**Цель:** Реализовать сложные голосовые взаимодействия, которые учитывают границы серверов (гильдий) и управляют временными ресурсами.
|
||||
**Цель:** реализовать голосовое взаимодействие с изоляцией ресурсов по серверам (гильдиям) и корректным управлением аудиосессиями.
|
||||
|
||||
## 1. Стратегия ограничения ресурсов
|
||||
## 1. Изоляция ресурсов
|
||||
|
||||
Голосовые функции **ОБЯЗАТЕЛЬНО** должны быть ограничены рамками Гильдии (Guild).
|
||||
Голосовые функции бота **обязательно** изолируются на уровне отдельного сервера (гильдии):
|
||||
|
||||
- **Паттерн:** Контроллер поддерживает `Map<GuildID, Player>`.
|
||||
- **Архитектурный шаблон:** контроллер хранит соответствие `Map<GuildID, Player>`.
|
||||
- **Поведение:**
|
||||
- **Подключение (Join):** Создать Player для `Гильдии A`, если он еще не существует.
|
||||
- **Отключение (Leave):** Уничтожить Player и освободить соединения.
|
||||
- **Изоляция:** Команды в `Гильдии B` никогда не влияют на `Гильдию A`.
|
||||
- **Подключение (Join):** создать `Player` для сервера A, если он ещё не существует.
|
||||
- **Отключение (Leave):** удалить `Player` и освободить соединение.
|
||||
- **Изоляция:** команды на сервере B никак не влияют на сервер A.
|
||||
|
||||
## 2. Оркестрация команд
|
||||
## 2. Маршрутизация команд
|
||||
|
||||
Голосовые функции требуют набора команд, координируемых через Контроллер.
|
||||
Голосовые функции опираются на набор команд, работу которых координирует контроллер:
|
||||
|
||||
| Команда | Действие | Логика Контроллера |
|
||||
| Команда | Действие | Логика контроллера |
|
||||
| :--- | :--- | :--- |
|
||||
| `/join` | Подключиться к каналу | `createPlayer(guildId, channelId)` |
|
||||
| `/play` | Добавить трек в очередь | `getPlayer(guildId).enqueue(track)` |
|
||||
| `/stop` | Отключиться | `destroyPlayer(guildId)` |
|
||||
| `/join` | Подключиться к голосовому каналу | `createPlayer(guildId, channelId)` |
|
||||
| `/play` | Добавить трек в очередь | `getPlayer(guildId).enqueue(track)` |
|
||||
| `/stop` | Отключиться от канала | `destroyPlayer(guildId)` |
|
||||
|
||||
## 3. Сохранение состояния
|
||||
## 3. Управление состоянием
|
||||
|
||||
Аудиосессии эфемерны.
|
||||
Аудиосессии по своей природе эфемерны:
|
||||
|
||||
- **Временное состояние:** Активный аудиопоток (Теряется при отключении).
|
||||
- **Постоянное состояние:** Очередь / Плейлист (Сохраняется в Контроллере до перезапуска).
|
||||
- **Временное состояние:** активный аудиопоток (сбрасывается при отключении).
|
||||
- **Долговременное состояние:** очередь воспроизведения или плейлист (хранится в контроллере до перезапуска бота).
|
||||
|
||||
> [!TIP]
|
||||
> **Устойчивость:** Разделяйте логику _Очереди_ и логику _Голосового соединения_. Это позволяет боту переподключаться без потери плейлиста пользователя.
|
||||
> **Надёжность:** разделяйте логику очереди воспроизведения и логику голосового соединения. Тогда бот сможет переподключиться без потери пользовательского плейлиста.
|
||||
|
||||
## 4. Пример реализации
|
||||
|
||||
@@ -60,4 +60,4 @@ class MusicController {
|
||||
|
||||
**См. также:**
|
||||
|
||||
- [Руководство Discord.js Voice](https://discordjs.guide/voice/)
|
||||
- [Руководство Discord.js по голосовым функциям](https://discordjs.guide/voice/)
|
||||
@@ -3,10 +3,10 @@ title: Устранение неполадок
|
||||
weight: 5
|
||||
---
|
||||
|
||||
Устранение неполадок в **Quetza** фокусируется на диагностике структурных и концептуальных проблем. Из-за его природы, основанной на соглашениях (convention-based), большинство ошибок протекают бесшумно (отсутствующие файлы), а не с шумом (трассировка стека/stack traces).
|
||||
Диагностика неполадок в **Quetza** в основном касается структуры файлов и концептуальных ошибок. Поскольку фреймворк опирается на соглашения (convention-based), многие сбои происходят «молча» — например, модуль не загружается из-за неверного пути к файлу, не вызывая явных ошибок и трассировок стека.
|
||||
|
||||
## Основные категории проблем
|
||||
|
||||
{{% cards %}}
|
||||
{{< card link="diagnostics" title="Руководство по диагностике" icon="exclamation" subtitle="Решения для обнаружения модулей, регистрации команд и утечек состояния." >}}
|
||||
{{< card link="diagnostics" title="Руководство по диагностике" icon="exclamation" subtitle="Решение проблем с загрузкой модулей, регистрацией команд и утечками состояния." >}}
|
||||
{{% /cards %}}
|
||||
@@ -3,39 +3,39 @@ title: Диагностика
|
||||
weight: 1
|
||||
---
|
||||
|
||||
**Цель:** Определить и устранить распространенные ловушки при разработке Quetza.
|
||||
**Цель:** выявить и устранить частые ошибки при разработке под Quetza.
|
||||
|
||||
## 1. Сбои при обнаружении модулей
|
||||
|
||||
**Симптом:** Бот запускается, но ваш модуль игнорируется.
|
||||
**Причина:** Нарушение соглашений файловой системы.
|
||||
**Симптом:** бот запускается, но модуль не подхватывается.
|
||||
**Причина:** нарушена структура файлов или соглашения об именах.
|
||||
|
||||
{{% details title="Чек-лист: Структура директорий" closed="false" %}}
|
||||
|
||||
- [ ] Существует ли `src/modules/<name>/`?
|
||||
- [ ] Экспортирует ли `module.ts` переменную `name`?
|
||||
- [ ] Находятся ли команды в `commands/` (а не в `cmds/`)?
|
||||
- [ ] Запустили ли вы `pnpm build`? (Quetza запускается из `dist/`).
|
||||
- [ ] Каталог модуля существует: `src/modules/<name>/`.
|
||||
- [ ] Файл `module.ts` экспортирует переменную `name`.
|
||||
- [ ] Каталог команд называется именно `commands/` (а не `cmds/`).
|
||||
- [ ] Выполнена сборка `pnpm build` (Quetza работает из `dist/`).
|
||||
{{% /details %}}
|
||||
|
||||
## 2. Проблемы с регистрацией команд
|
||||
|
||||
**Симптом:** Команда `/command` не появляется в Discord.
|
||||
**Симптом:** команда `/command` не появляется в Discord.
|
||||
|
||||
### Глобальная регистрация против регистрации в тестовой гильдии (Guild)
|
||||
### Глобальная регистрация и регистрация на тестовом сервере
|
||||
|
||||
- **Глобальная:** Команды, отправленные в приложение глобально, могут обновляться до 1 часа и подчиняются более строгим ограничениям скорости (rate limits).
|
||||
- **Тестовая гильдия:** Quetza автоматически отправляет команды в конкретную гильдию в режиме разработки для мгновенного обновления.
|
||||
- **Требование:** Убедитесь, что `NODE_ENV=development` и `DEV_GUILD_ID` корректно установлены в вашем `.env`.
|
||||
- **Глобальная регистрация:** команды, зарегистрированные глобально, могут обновляться до 1 часа и подпадают под жёсткие лимиты Discord по частоте запросов (rate limits).
|
||||
- **Тестовый сервер (guild):** в режиме разработки Quetza публикует команды на указанном сервере мгновенно.
|
||||
- **Настройка:** проверьте, что в `.env` установлены переменные `NODE_ENV=development` и `DEV_GUILD_ID`.
|
||||
|
||||
### Ограничения скорости (Rate Limits)
|
||||
### Лимиты частоты запросов (Rate Limits)
|
||||
|
||||
Частые обновления глобальных команд могут вызвать ограничения скорости со стороны Discord. Используйте тестовую гильдию для итеративной разработки.
|
||||
Частая повторная публикация глобальных команд приводит к превышению лимитов Discord. Для итеративной разработки всегда используйте тестовый сервер.
|
||||
|
||||
## 3. Ошибки взаимодействия (Interaction Failures)
|
||||
|
||||
**Симптом:** «Приложение не отвечает».
|
||||
**Причина:** Выполнение команды заняло более 3 секунд без отложенного ответа (deferral).
|
||||
**Симптом:** сообщение «Приложение не отвечает».
|
||||
**Причина:** обработка команды длилась дольше 3 секунд без отложенного ответа (deferReply).
|
||||
|
||||
**Решение:**
|
||||
|
||||
@@ -52,22 +52,22 @@ await interaction.editReply('Готово');
|
||||
|
||||
## 4. Утечки состояния
|
||||
|
||||
**Симптом:** Потребление памяти ботом растет; странности во взаимодействии между серверами.
|
||||
**Причина:** Хранение состояния глобально вместо уровня гильдии.
|
||||
**Симптом:** потребление памяти растёт, данные перемешиваются между разными серверами.
|
||||
**Причина:** состояние хранится глобально, а не изолированно для каждого сервера.
|
||||
|
||||
**Диагностика:**
|
||||
Проверьте ваш контроллер.
|
||||
Проверьте код контроллера:
|
||||
|
||||
- ❌ `private player: AudioPlayer;` (Общий для всех!)
|
||||
- ✅ `private players = new Map<string, AudioPlayer>();` (Разделен по ID гильдии).
|
||||
- ❌ `private player: AudioPlayer;` (состояние общее для всех серверов)
|
||||
- ✅ `private players = new Map<string, AudioPlayer>();` (состояние изолировано по ID сервера)
|
||||
|
||||
## 5. Обработка событий
|
||||
|
||||
**Симптом:** События срабатывают несколько раз или не срабатывают вовсе.
|
||||
**Симптом:** обработчик срабатывает несколько раз или не вызывается вовсе.
|
||||
|
||||
- **Несколько раз:** События являются аддитивными. Не зарегистрировали ли вы один и тот же обработчик в двух модулях?
|
||||
- **Ни разу:** Правильно ли вы экспортировали `name` и `execute`?
|
||||
- **Срабатывает несколько раз:** слушатели событий суммируются. Проверьте, не зарегистрирован ли один и тот же обработчик в двух разных модулях.
|
||||
- **Не срабатывает:** убедитесь, что обработчик корректно экспортирует `name` и `execute`.
|
||||
|
||||
> [!TIP]
|
||||
> **Debug Mode:**
|
||||
> Включите подробное логирование, чтобы точно увидеть, какие модули и команды загружаются при запуске.
|
||||
> **Режим отладки (Debug Mode):**
|
||||
> включите подробное логирование, чтобы видеть список всех модулей и команд, загружаемых на этапе старта бота.
|
||||
Reference in new issue
Block a user