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
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Quetza Bot
|
||||
description: Модульный фреймворк для Discord-ботов.
|
||||
description: Модульный фреймворк для Discord-ботов.
|
||||
weight: 1
|
||||
type: docs
|
||||
cascade:
|
||||
@@ -13,9 +13,9 @@ cascade:
|
||||
|
||||
## Основные возможности
|
||||
|
||||
- **Обнаружение модулей по соглашениям:** создайте папку, и Quetza автоматически загрузит её как модуль.
|
||||
- **Изоляция контроллеров:** управление состоянием происходит на уровне сервера (guild), что исключает утечки данных между серверами.
|
||||
- **Декларативные команды:** определение слэш-команд Discord через типизированный интерфейс.
|
||||
- **Обнаружение модулей по соглашениям:** создайте папку, и Quetza автоматически загрузит её как модуль.
|
||||
- **Изоляция контроллеров:** управление состоянием происходит на уровне сервера (guild), что исключает утечки данных между серверами.
|
||||
- **Декларативные команды:** определение слэш-команд Discord через типизированный интерфейс.
|
||||
- **Реактивные события:** подписка на любые события Discord.js внутри модулей.
|
||||
|
||||
## Разделы
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Архитектура и философия
|
||||
title: Архитектура и философия
|
||||
weight: 1
|
||||
---
|
||||
|
||||
@@ -16,9 +16,9 @@ Quetza сокращает шаблонный код за счёт строго
|
||||
|
||||
### Композиция важнее наследования (Composition over Inheritance)
|
||||
|
||||
Модули собираются из набора возможностей (capabilities), а не наследуются от базового класса.
|
||||
Модули собираются из набора возможностей (capabilities), а не наследуются от базового класса.
|
||||
|
||||
- **Гибкость:** внутри модуля можно использовать любую архитектуру (функциональную или ООП), если модуль экспортирует обязательные интерфейсы.
|
||||
- **Гибкость:** внутри модуля можно использовать любую архитектуру (функциональную или ООП), если модуль экспортирует обязательные интерфейсы.
|
||||
|
||||
### Изоляция важнее интеграции (Isolation over Integration)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ weight: 2
|
||||
|
||||
### Объявление модуля (Module Declaration)
|
||||
|
||||
Файл `module.ts` служит манифестом и точкой входа при поиске модулей.
|
||||
Файл `module.ts` служит манифестом и точкой входа при поиске модулей.
|
||||
|
||||
```typescript
|
||||
export const name = 'my-module'; // ID
|
||||
@@ -18,7 +18,7 @@ export const description = '...'; // Документация
|
||||
|
||||
### Регистрация команд (Command Registration)
|
||||
|
||||
Выполняется при наступлении события `ready`:
|
||||
Выполняется при наступлении события `ready`:
|
||||
|
||||
1. Quetza сканирует каталоги `commands/`.
|
||||
2. Формирует структуру `ApplicationCommandData`.
|
||||
@@ -26,7 +26,7 @@ export const description = '...'; // Документация
|
||||
|
||||
### Внедрение контроллера (Controller Injection)
|
||||
|
||||
Экземпляр контроллера передаётся аргументом при вызове (injected), а не импортируется модулем напрямую:
|
||||
Экземпляр контроллера передаётся аргументом при вызове (injected), а не импортируется модулем напрямую:
|
||||
|
||||
```typescript
|
||||
// Фреймворк вызывает это:
|
||||
@@ -37,15 +37,15 @@ execute(client, interaction, controller);
|
||||
|
||||
## Управление состоянием
|
||||
|
||||
### Эфемерность по умолчанию
|
||||
### Эфемерность по умолчанию
|
||||
|
||||
В Quetza **нет встроенной базы данных**.
|
||||
|
||||
- **Память:** контроллеры сохраняют данные в стандартных JavaScript-коллекциях `Map` или `Set`.
|
||||
- **Перезапуск:** при остановке процесса всё состояние в памяти сбрасывается.
|
||||
- **Постоянное хранение:** если данные нужно сохранять между запусками, подключите внешнюю СУБД (например, SQLite или Redis) внутри контроллера.
|
||||
- **Память:** контроллеры сохраняют данные в стандартных JavaScript-коллекциях `Map` или `Set`.
|
||||
- **Перезапуск:** при остановке процесса всё состояние в памяти сбрасывается.
|
||||
- **Постоянное хранение:** если данные нужно сохранять между запусками, подключите внешнюю СУБД (например, SQLite или Redis) внутри контроллера.
|
||||
|
||||
### Область видимости как ключ
|
||||
### Область видимости как ключ
|
||||
|
||||
Ключи состояния должны соответствовать области его видимости:
|
||||
|
||||
@@ -58,7 +58,7 @@ execute(client, interaction, controller);
|
||||
|
||||
- **Валидация:** проверяйте права и входные параметры сразу.
|
||||
- **Сообщения для пользователя:** «У вас нет прав» вместо сухого кода вроде «Ошибка: 403».
|
||||
- **Изоляция:** сбой внутри `/ping` перехватывается локально и не роняет процесс бота.
|
||||
- **Изоляция:** сбой внутри `/ping` перехватывается локально и не роняет процесс бота.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@ weight: 1
|
||||
|
||||
**Quetza** — модульный фреймворк на TypeScript для Discord-ботов. Он позволяет собирать ботов из самодостаточных независимых модулей.
|
||||
|
||||
## Что такое Quetza?
|
||||
## Что такое Quetza?
|
||||
|
||||
Quetza даёт архитектурный каркас, где разработка новой функциональности сводится к добавлению модулей, а не правке ядра. Это решает проблему жёсткой архитектуры за счёт инверсии зависимостей: ядро ничего не знает о модулях, а модули взаимодействуют с системой через типизированные контракты.
|
||||
Quetza даёт архитектурный каркас, где разработка новой функциональности сводится к добавлению модулей, а не правке ядра. Это решает проблему жёсткой архитектуры за счёт инверсии зависимостей: ядро ничего не знает о модулях, а модули взаимодействуют с системой через типизированные контракты.
|
||||
|
||||
## Основная философия
|
||||
|
||||
@@ -17,25 +17,25 @@ Quetza даёт архитектурный каркас, где разработ
|
||||
|
||||
### Решение
|
||||
|
||||
Quetza работает с модулями как с плагинами:
|
||||
Quetza работает с модулями как с плагинами:
|
||||
|
||||
- **Расширение без правки ядра:** добавьте каталог с модулем, и функция подключена. Менять исходный код ядра не нужно.
|
||||
- **Расширение без правки ядра:** добавьте каталог с модулем, и функция подключена. Менять исходный код ядра не нужно.
|
||||
- **Изоляция:** модули выполняются независимо друг от друга.
|
||||
- **Композиция:** подключайте и отключайте возможности, добавляя или удаляя каталоги модулей.
|
||||
- **Композиция:** подключайте и отключайте возможности, добавляя или удаляя каталоги модулей.
|
||||
|
||||
## Высокоуровневая архитектура
|
||||
|
||||
Quetza состоит из трёх уровней:
|
||||
|
||||
1. **Базовый уровень (Foundation Layer):** клиент `Discord.js`, расширенный реестрами команд, событий и модулей. Выступает в роли сервис-локатора.
|
||||
2. **Модульный уровень (Module Layer):** изолированные наборы функций. Модуль объявляет собственные команды и события через стандартизированную структуру файлов.
|
||||
3. **Сервисный уровень (Service Layer):** контроллеры для управления состоянием бизнес-логики (например, аудиоплеером или контекстом диалога) на разных серверах (guilds).
|
||||
2. **Модульный уровень (Module Layer):** изолированные наборы функций. Модуль объявляет собственные команды и события через стандартизированную структуру файлов.
|
||||
3. **Сервисный уровень (Service Layer):** контроллеры для управления состоянием бизнес-логики (например, аудиоплеером или контекстом диалога) на разных серверах (guilds).
|
||||
|
||||
## Ключевые концепции
|
||||
|
||||
### Ментальная модель
|
||||
|
||||
При работе с Quetza полезна следующая аналогия:
|
||||
При работе с Quetza полезна следующая аналогия:
|
||||
|
||||
- **Модули — плагины:** независимые каталоги, обнаруживаемые во время запуска.
|
||||
- **Команды — эндпоинты:** обработчики без состояния, работающие аналогично конечным точкам REST API.
|
||||
@@ -44,11 +44,11 @@ Quetza состоит из трёх уровней:
|
||||
|
||||
### Границы системы
|
||||
|
||||
Ограничения, которые важно учитывать при проектировании:
|
||||
Ограничения, которые важно учитывать при проектировании:
|
||||
|
||||
- **Нет встроенного постоянного хранилища (persistence):** состояние в памяти сбрасывается при перезапуске. Для долговременного хранения нужна внешняя база данных.
|
||||
- **Нет межмодульного взаимодействия:** модули не вызывают друг друга напрямую, что гарантирует слабую связанность.
|
||||
- **Нет динамической перезагрузки:** модули загружаются один раз при старте процесса.
|
||||
- **Нет встроенного постоянного хранилища (persistence):** состояние в памяти сбрасывается при перезапуске. Для долговременного хранения нужна внешняя база данных.
|
||||
- **Нет межмодульного взаимодействия:** модули не вызывают друг друга напрямую, что гарантирует слабую связанность.
|
||||
- **Нет динамической перезагрузки:** модули загружаются один раз при старте процесса.
|
||||
|
||||
## Архитектурные инварианты
|
||||
|
||||
|
||||
@@ -53,4 +53,4 @@ export async function execute(interaction, controller) {
|
||||
|
||||
> [!WARNING]
|
||||
> **Расходы на API:**
|
||||
> Провайдеры ИИ обычно тарифицируют запросы по токенам. Настройте в контроллере строгие лимиты запросов (rate limits) для пользователей, чтобы избежать лишних расходов.
|
||||
> Провайдеры ИИ обычно тарифицируют запросы по токенам. Настройте в контроллере строгие лимиты запросов (rate limits) для пользователей, чтобы избежать лишних расходов.
|
||||
@@ -7,13 +7,13 @@ weight: 2
|
||||
|
||||
## 1. Подготовка окружения
|
||||
|
||||
Quetza настраивается через переменные окружения. **Никогда** не сохраняйте их в систему контроля версий.
|
||||
Quetza настраивается через переменные окружения. **Никогда** не сохраняйте их в систему контроля версий.
|
||||
|
||||
| Переменная | Описание | Обязательно |
|
||||
| :--- | :--- | :--- |
|
||||
| `DISCORD_TOKEN` | Токен бота из Discord Developer Portal | **Да** |
|
||||
| `CLIENT_ID` | Идентификатор приложения для регистрации слэш-команд | **Да** |
|
||||
| `LLAMA_API_KEY` | Требуется для модуля ИИ | Нет |
|
||||
| `CLIENT_ID` | Идентификатор приложения для регистрации слэш-команд | **Да** |
|
||||
| `LLAMA_API_KEY` | Требуется для модуля ИИ | Нет |
|
||||
|
||||
## 2. Способы развёртывания
|
||||
|
||||
@@ -36,7 +36,7 @@ Quetza настраивается через переменные окружен
|
||||
```
|
||||
{{< /tab >}}
|
||||
{{< tab name="Из исходного кода" >}}
|
||||
Развёртывание **из исходного кода** подходит для разработки и отладки.
|
||||
Развёртывание **из исходного кода** подходит для разработки и отладки.
|
||||
|
||||
1. **Установка** зависимостей:
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ weight: 1
|
||||
|
||||
## 1. Проектирование модуля
|
||||
|
||||
Перед написанием кода выберите подходящую структуру модуля:
|
||||
Перед написанием кода выберите подходящую структуру модуля:
|
||||
|
||||
- **Простая команда:** достаточно каталога `commands/` (например, для служебных команд).
|
||||
- **Реактивная логика:** нужен каталог `events/` для обработки событий Discord (например, приветственных сообщений).
|
||||
- **Логика с состоянием:** понадобится контроллер (`Controller`) для управления состоянием между серверами (например, для музыкального плеера).
|
||||
- **Простая команда:** достаточно каталога `commands/` (например, для служебных команд).
|
||||
- **Реактивная логика:** нужен каталог `events/` для обработки событий Discord (например, приветственных сообщений).
|
||||
- **Логика с состоянием:** понадобится контроллер (`Controller`) для управления состоянием между серверами (например, для музыкального плеера).
|
||||
|
||||
## 2. Структура каталогов
|
||||
|
||||
@@ -85,7 +85,7 @@ export function execute(client) {
|
||||
Перезапустите бота:
|
||||
|
||||
1. Найдите в логах строку «Loaded module: my-feature».
|
||||
2. Убедитесь, что команда `/ping` появилась и работает в Discord.
|
||||
2. Убедитесь, что команда `/ping` появилась и работает в Discord.
|
||||
|
||||
{{% /steps %}}
|
||||
|
||||
@@ -93,7 +93,7 @@ export function execute(client) {
|
||||
|
||||
| Шаблон | Назначение | Состав |
|
||||
| :--- | :--- | :--- |
|
||||
| **Простая команда** | Утилиты без сохранения состояния (`/ping`, бросок кубика) | Только `commands/` |
|
||||
| **Простая команда** | Утилиты без сохранения состояния (`/ping`, бросок кубика) | Только `commands/` |
|
||||
| **Сервис с состоянием** | Музыка, ролевые игры, экономика | `commands/` + `lib/Controller` |
|
||||
| **Событийная логика** | Автомодерация, логирование | Только `events/` |
|
||||
| **Гибридный модуль** | Сложные сценарии (например, ИИ-чат) | Все компоненты |
|
||||
|
||||
@@ -11,7 +11,7 @@ weight: 3
|
||||
|
||||
- **Архитектурный шаблон:** контроллер хранит соответствие `Map<GuildID, Player>`.
|
||||
- **Поведение:**
|
||||
- **Подключение (Join):** создать `Player` для сервера A, если он ещё не существует.
|
||||
- **Подключение (Join):** создать `Player` для сервера A, если он ещё не существует.
|
||||
- **Отключение (Leave):** удалить `Player` и освободить соединение.
|
||||
- **Изоляция:** команды на сервере B никак не влияют на сервер A.
|
||||
|
||||
@@ -29,11 +29,11 @@ weight: 3
|
||||
|
||||
Аудиосессии по своей природе эфемерны:
|
||||
|
||||
- **Временное состояние:** активный аудиопоток (сбрасывается при отключении).
|
||||
- **Долговременное состояние:** очередь воспроизведения или плейлист (хранится в контроллере до перезапуска бота).
|
||||
- **Временное состояние:** активный аудиопоток (сбрасывается при отключении).
|
||||
- **Долговременное состояние:** очередь воспроизведения или плейлист (хранится в контроллере до перезапуска бота).
|
||||
|
||||
> [!TIP]
|
||||
> **Надёжность:** разделяйте логику очереди воспроизведения и логику голосового соединения. Тогда бот сможет переподключиться без потери пользовательского плейлиста.
|
||||
> **Надёжность:** разделяйте логику очереди воспроизведения и логику голосового соединения. Тогда бот сможет переподключиться без потери пользовательского плейлиста.
|
||||
|
||||
## 4. Пример реализации
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ title: Устранение неполадок
|
||||
weight: 5
|
||||
---
|
||||
|
||||
Диагностика неполадок в **Quetza** в основном касается структуры файлов и концептуальных ошибок. Поскольку фреймворк опирается на соглашения (convention-based), многие сбои происходят «молча» — например, модуль не загружается из-за неверного пути к файлу, не вызывая явных ошибок и трассировок стека.
|
||||
Диагностика неполадок в **Quetza** в основном касается структуры файлов и концептуальных ошибок. Поскольку фреймворк опирается на соглашения (convention-based), многие сбои происходят «молча» — например, модуль не загружается из-за неверного пути к файлу, не вызывая явных ошибок и трассировок стека.
|
||||
|
||||
## Основные категории проблем
|
||||
|
||||
|
||||
@@ -3,34 +3,34 @@ title: Диагностика
|
||||
weight: 1
|
||||
---
|
||||
|
||||
**Цель:** выявить и устранить частые ошибки при разработке под Quetza.
|
||||
**Цель:** выявить и устранить частые ошибки при разработке под Quetza.
|
||||
|
||||
## 1. Сбои при обнаружении модулей
|
||||
## 1. Сбои при обнаружении модулей
|
||||
|
||||
**Симптом:** бот запускается, но модуль не подхватывается.
|
||||
**Причина:** нарушена структура файлов или соглашения об именах.
|
||||
**Симптом:** бот запускается, но модуль не подхватывается.
|
||||
**Причина:** нарушена структура файлов или соглашения об именах.
|
||||
|
||||
{{% details title="Чек-лист: Структура директорий" closed="false" %}}
|
||||
|
||||
- [ ] Каталог модуля существует: `src/modules/<name>/`.
|
||||
- [ ] Файл `module.ts` экспортирует переменную `name`.
|
||||
- [ ] Каталог команд называется именно `commands/` (а не `cmds/`).
|
||||
- [ ] Каталог команд называется именно `commands/` (а не `cmds/`).
|
||||
- [ ] Выполнена сборка `pnpm build` (Quetza работает из `dist/`).
|
||||
{{% /details %}}
|
||||
|
||||
## 2. Проблемы с регистрацией команд
|
||||
## 2. Проблемы с регистрацией команд
|
||||
|
||||
**Симптом:** команда `/command` не появляется в Discord.
|
||||
|
||||
### Глобальная регистрация и регистрация на тестовом сервере
|
||||
### Глобальная регистрация и регистрация на тестовом сервере
|
||||
|
||||
- **Глобальная регистрация:** команды, зарегистрированные глобально, могут обновляться до 1 часа и подпадают под жёсткие лимиты Discord по частоте запросов (rate limits).
|
||||
- **Тестовый сервер (guild):** в режиме разработки Quetza публикует команды на указанном сервере мгновенно.
|
||||
- **Настройка:** проверьте, что в `.env` установлены переменные `NODE_ENV=development` и `DEV_GUILD_ID`.
|
||||
- **Настройка:** проверьте, что в `.env` установлены переменные `NODE_ENV=development` и `DEV_GUILD_ID`.
|
||||
|
||||
### Лимиты частоты запросов (Rate Limits)
|
||||
|
||||
Частая повторная публикация глобальных команд приводит к превышению лимитов Discord. Для итеративной разработки всегда используйте тестовый сервер.
|
||||
Частая повторная публикация глобальных команд приводит к превышению лимитов Discord. Для итеративной разработки всегда используйте тестовый сервер.
|
||||
|
||||
## 3. Ошибки взаимодействия (Interaction Failures)
|
||||
|
||||
@@ -53,7 +53,7 @@ await interaction.editReply('Готово');
|
||||
## 4. Утечки состояния
|
||||
|
||||
**Симптом:** потребление памяти растёт, данные перемешиваются между разными серверами.
|
||||
**Причина:** состояние хранится глобально, а не изолированно для каждого сервера.
|
||||
**Причина:** состояние хранится глобально, а не изолированно для каждого сервера.
|
||||
|
||||
**Диагностика:**
|
||||
Проверьте код контроллера:
|
||||
@@ -63,10 +63,10 @@ await interaction.editReply('Готово');
|
||||
|
||||
## 5. Обработка событий
|
||||
|
||||
**Симптом:** обработчик срабатывает несколько раз или не вызывается вовсе.
|
||||
**Симптом:** обработчик срабатывает несколько раз или не вызывается вовсе.
|
||||
|
||||
- **Срабатывает несколько раз:** слушатели событий суммируются. Проверьте, не зарегистрирован ли один и тот же обработчик в двух разных модулях.
|
||||
- **Не срабатывает:** убедитесь, что обработчик корректно экспортирует `name` и `execute`.
|
||||
- **Срабатывает несколько раз:** слушатели событий суммируются. Проверьте, не зарегистрирован ли один и тот же обработчик в двух разных модулях.
|
||||
- **Не срабатывает:** убедитесь, что обработчик корректно экспортирует `name` и `execute`.
|
||||
|
||||
> [!TIP]
|
||||
> **Режим отладки (Debug Mode):**
|
||||
|
||||
Reference in new issue
Block a user