34 KiB
TODO - План реализации функций
Правила разработки
Архитектура и код:
- KISS, DRY, SOLID принципы
- Файлы максимум 150-200 строк, стараться делать 100 строк
- В одной папке не больше 6 файлов
- Не создавать новые MD файлы без необходимости
- Разделение по доменам, а не по типам артефактов
Принципы структуры:
- Пакет = домен/фича, а не тип файла (не "команды/листенеры", а "profile/level/voice")
- Каждая фича содержит свои команды, сервисы, репозитории
- Единый слой персистентности через repository/
- Интеграции в отдельном пакете integration/
Рефакторинг структуры проекта
Целевая оценка: 7/10
Проблемы:
util/- мусорная корзина (CooldownManager, RateLimiter, NekosLifeApi)- Два механизма персистентности (data/ и database/) без абстракции
command/impl/entertainment/- 23 файла в одном пакетеexception/- избыточный пакет для 2 файловembed/- presentation layer оторван от domainlistener/- смешаны разные ответственности- Техническое разделение вместо доменного
- LevelSystem - God Class (5/10):
- Нарушение SRP: хранение + кэширование + формулы + лидерборды + прогресс-бары
- Прямая зависимость от JsonDataStore (нет интерфейса Repository)
- O(n) на каждое сообщение (читает/пишет весь JSON)
- Кэш messageTimestamps не персистентный (теряется при рестарте)
- Рассогласование формул: комментарий говорит 200, код использует 100
- LevelUpResult и LevelProgress - вложенные классы вместо отдельных
- getAllStats() возвращает mutable map (можно сломать консистентность)
- UserStats - анемичная модель (6/10):
- Сеттеры позволяют нарушить инварианты (setLevel(999) без XP)
- incrementMessages() скрыто меняет lastMessageTime (side effect)
- Поля lastMessageTime и lastVoiceJoin не используются системой
- Нет equals/hashCode для использования в коллекциях
Целевая структура (по доменам):
src/main/java/creator/loki/
├── App.java # Точка входа (временно, потом в bootstrap/)
│
├── core/ # Ядро системы
│ ├── BotInitializer
│ ├── EventDispatcher
│ ├── registry/ # Регистрация команд
│ │ ├── CommandRegistry
│ │ ├── SlashCommandRegistry
│ │ ├── PrefixCommandRegistrar
│ │ └── SlashCommandRegistrar
│ ├── security/ # Безопасность и ограничения
│ │ ├── RateLimiter # (из util/)
│ │ └── CooldownManager # (из util/)
│ └── exception/ # Глобальная обработка ошибок
│ └── CommandExceptionHandler
│
├── command/ # Базовые интерфейсы команд
│ ├── Command.java
│ ├── CommandContext.java
│ ├── CommandException.java # (из exception/)
│ ├── SlashCommand.java
│ ├── moderation/ # Модерация (3 файла)
│ │ ├── BanCommand
│ │ ├── KickCommand
│ │ └── ClearCommand
│ ├── entertainment/ # Развлечения
│ │ ├── games/ # Игры (12 файлов)
│ │ └── social/ # Взаимодействия (11 файлов)
│ ├── utility/ # Утилиты (5 файлов)
│ │ ├── HelpCommand
│ │ ├── PingCommand
│ │ ├── InfoCommand
│ │ ├── AvatarCommand
│ │ └── PollCommand
│ └── system/ # Системные команды
│ └── MetricsCommand # (из utility/)
│
├── feature/ # Крупные фичи/домены
│ ├── level/ # Система уровней
│ │ ├── LevelSystem
│ │ ├── UserStats
│ │ ├── LevelUtils # (из profile/)
│ │ ├── RankCommand # (из command/stats/)
│ │ ├── StatsCommand # (из command/stats/)
│ │ ├── LevelUpNotifier # (из listener/)
│ │ └── VoiceTracker # (из listener/)
│ │
│ ├── profile/ # Профили пользователей
│ │ ├── ProfileService
│ │ ├── ProfileGenerator
│ │ ├── ProfileData
│ │ ├── ProfileCommand # (из command/utility/)
│ │ └── ProfileEmbedFactory # (из embed/)
│ │
│ ├── reputation/ # Система репутации
│ │ ├── ReputationService # (логика из RepCommand)
│ │ ├── RepCommand # (из command/stats/)
│ │ ├── MinusRepCommand # (из command/stats/)
│ │ └── RepTopCommand # (из command/stats/)
│ │
│ ├── leaderboard/ # Таблица лидеров
│ │ ├── LeaderboardCommand # (NewLeaderboardCommand)
│ │ ├── LeaderboardService # (логика из команды)
│ │ ├── LeaderboardFormatter
│ │ ├── LeaderboardButtons
│ │ └── LeaderboardButtonListener
│ │
│ ├── voice/ # Личные голосовые каналы
│ │ ├── VoiceChannelManager
│ │ ├── VoiceChannelData
│ │ ├── VoicePreset
│ │ ├── VoiceSetupCommand # (из command/setup/)
│ │ ├── VoiceChannelListener # (из listener/)
│ │ └── VoiceButtonHandler # (из listener/)
│ │
│ ├── counter/ # Счетчик участников
│ │ ├── CounterManager
│ │ ├── DailyStats
│ │ ├── CounterSetupCommand # (из command/setup/)
│ │ └── MemberCounterListener # (из listener/)
│ │
│ └── role/ # Кастомные роли
│ ├── CustomRoleManager
│ ├── CreateRoleCommand # (из command/roles/)
│ ├── DeleteRoleCommand # (из command/roles/)
│ ├── EditRoleCommand # (из command/roles/)
│ ├── MyRolesCommand # (из command/roles/)
│ └── RoleCommandValidator # (из command/roles/)
│
├── event/ # Обработчики событий Discord
│ ├── ReadyListener # (из listener/)
│ ├── MessageListener # (из listener/)
│ ├── SlashCommandListener # (из listener/)
│ ├── HelpMenuHandler # (из listener/)
│ └── ModerationLogger # (из listener/)
│
├── repository/ # Единый слой данных
│ ├── UserRepository # Интерфейс
│ ├── GuildConfigRepository # Интерфейс
│ └── impl/
│ ├── JsonUserRepository # (из data/)
│ └── SqliteConfigRepository # (из database/)
│
├── database/ # Инфраструктура БД
│ ├── Database
│ ├── DatabaseSchema
│ └── DatabaseMigration
│
├── integration/ # Внешние API
│ └── nekos/
│ └── NekosLifeApi # (из util/)
│
├── config/ # Конфигурация
│ ├── BotConfig
│ └── ConfigLoader
│
├── embed/ # Общие шаблоны embed
│ ├── EmbedFactory
│ └── EmbedTemplates
│
├── metrics/ # Метрики
│ └── MetricsCollector
│
└── di/ # Dependency Injection
└── BotModule
План действий (этапы):
Этап 1: Фундамент (делаем первым)
1. Создать repository/ (средний → высокий приоритет)
- Создать
repository/ - Создать интерфейс
repository/UserStatsRepository.java - Создать
repository/impl/ - Создать
repository/impl/JsonUserStatsRepository.java(обёртка над JsonDataStore) - Создать интерфейс
repository/GuildConfigRepository.java - Рефакторить
database/ConfigRepository→ использовать интерфейс
2. Реорганизовать util/ (мусорная корзина)
- Создать
core/security/ - Переместить
util/CooldownManager→core/security/CooldownManager - Переместить
util/GlobalRateLimiter→core/security/RateLimiter - Создать
integration/nekos/ - Переместить
util/NekosLifeApi→integration/nekos/NekosLifeApi - Удалить пустую папку
util/ - Обновить все импорты в командах
- Добавить
UserStatsRepositoryвBotModule
3. Удалить импорты AudioManager и мертвые ссылки
- Удалить
import creator.loki.audio.AudioManagerизBotInitializer - Удалить
import creator.loki.audio.AudioManagerизPrefixCommandRegistrar - Удалить
import creator.loki.audio.AudioManagerизSlashCommandRegistrar - Удалить параметр
AudioManager audioManagerиз конструкторов - Удалить поля
private final AudioManager audioManager - Удалить
registry.register(new TtsCommand(...))изPrefixCommandRegistrar - Удалить
registry.register(new TtsSlashCommand(...))изSlashCommandRegistrar - Исправить
registry.register(new NewLeaderboardCommand(...))→ использовать новый путь - Удалить все
registry.register(new *SlashCommand(...))изSlashCommandRegistrar - Удалить
import creator.loki.command.slash.*изSlashCommandRegistrar - Проверить компиляцию:
gradle build
Этап 2: feature/level/ (зависит от Этапа 1)
4. Создать feature/level/domain/
- Создать
feature/level/ - Создать
feature/level/domain/ - Создать
feature/level/domain/XpFormula.java:public class XpFormula { private static final int XP_PER_LEVEL = 200; // Исправленная формула: 200 * n * (n+1) / 2 public int getTotalXPForLevel(int level) { return XP_PER_LEVEL * level * (level + 1) / 2; } // Обратная формула с использованием XP_PER_LEVEL public int calculateLevel(int xp) { double discriminant = 1 + 8.0 * xp / XP_PER_LEVEL; return (int) Math.floor((-1 + Math.sqrt(discriminant)) / 2.0); } } - Вынести
LevelUpResultизLevelSystem→feature/level/domain/LevelUpResult.java - Вынести
LevelProgressизLevelSystem→feature/level/domain/LevelProgress.java - Переместить
level/UserStats→feature/level/domain/UserStats.java - НЕ делать immutable сейчас (Gson требует сеттеры, сделаем после Repository)
- Добавить
equals()иhashCode()вUserStats - Переименовать
incrementMessages()→recordMessage(long timestamp)
5. Создать feature/level/service/
- Создать
feature/level/service/ - Создать
feature/level/service/MessageCooldownService.java:- Персистентный кулдаун через
UserStats.lastMessageTime - Убрать
ConcurrentHashMap messageTimestamps
- Персистентный кулдаун через
- Создать
feature/level/service/LeaderboardService.java:- Вынести методы
getTopByLevel,getTopByMessages,getTopByVoice - Обобщить через
Comparator<UserStats>
- Вынести методы
- Рефакторить
level/LevelSystem→feature/level/service/LevelService.java:- Убрать God Class: только бизнес-логика начисления XP
- Использовать
UserStatsRepositoryвместоJsonDataStore - Использовать
XpFormulaдля вычислений - Использовать
MessageCooldownServiceдля кулдаунов - Убрать методы лидерборда (в
LeaderboardService) - Убрать
getAllStats()(в Repository)
6. Переместить команды и листенеры в feature/level/
- Переместить
command/impl/stats/RankCommand→feature/level/RankCommand - Переместить
command/impl/stats/StatsCommand→feature/level/StatsCommand - Переместить
listener/LevelUpNotifier→feature/level/LevelUpNotifier - Переместить
listener/VoiceTracker→feature/level/VoiceTracker - Переместить
profile/LevelUtils→feature/level/LevelUtils(если нужен) - Удалить пустую папку
level/ - Обновить все импорты
- Обновить
BotInitializer,BotModule,PrefixCommandRegistrar
7. Создать команду сброса уровней (миграция на новую систему)
- Создать
feature/level/ResetLevelsCommand.java:- Только для администраторов
- Подтверждение через кнопки (Да/Нет)
- Сброс всех уровней и XP
- Очистка таблицы
user_statsв БД - Логирование действия
- Уведомление в канал логов
- Embed с предупреждением о необратимости
- Зарегистрировать команду в
PrefixCommandRegistrar - Добавить в категорию "Настройка" (только админы)
Этап 3: Остальные feature/ (параллельно, независимо)
7. Создать feature/voice/ (голосовые каналы)
- Создать
feature/voice/ - Переместить
voice/VoiceChannelManager→feature/voice/ - Переместить
voice/VoiceChannelData→feature/voice/ - Переместить
voice/VoicePreset→feature/voice/ - Переместить
command/impl/setup/VoiceSetupCommand→feature/voice/ - Переместить
listener/VoiceChannelListener→feature/voice/ - Переместить
listener/VoiceButtonHandler→feature/voice/ - Удалить пустую папку
voice/ - Обновить импорты
8. Создать feature/counter/ (счетчик участников)
- Создать
feature/counter/ - Переместить
counter/CounterManager→feature/counter/ - Переместить
counter/DailyStats→feature/counter/ - Переместить
command/impl/setup/CounterSetupCommand→feature/counter/ - Переместить
listener/MemberCounterListener→feature/counter/ - Удалить пустую папку
counter/ - Обновить импорты
9. Создать feature/role/ (кастомные роли)
- Создать
feature/role/ - Переместить
role/CustomRoleManager→feature/role/ - Переместить
command/impl/roles/CreateRoleCommand→feature/role/ - Переместить
command/impl/roles/DeleteRoleCommand→feature/role/ - Переместить
command/impl/roles/EditRoleCommand→feature/role/ - Переместить
command/impl/roles/MyRolesCommand→feature/role/ - Переместить
command/impl/roles/RoleCommandValidator→feature/role/ - Удалить пустые папки
role/иcommand/impl/roles/ - Обновить импорты
10. Создать feature/reputation/ (система репутации)
- Создать
feature/reputation/ - Создать
feature/reputation/ReputationService.java(вынести логику из команд) - Переместить
command/impl/stats/RepCommand→feature/reputation/ - Переместить
command/impl/stats/MinusRepCommand→feature/reputation/ - Переместить
command/impl/stats/RepTopCommand→feature/reputation/ - Рефакторить команды: использовать
ReputationService - Обновить импорты
11. Создать feature/leaderboard/ (таблица лидеров)
- Создать
feature/leaderboard/ - Переместить
command/impl/stats/leaderboard/NewLeaderboardCommand→feature/leaderboard/LeaderboardCommand - Переместить
command/impl/stats/leaderboard/LeaderboardFormatter→feature/leaderboard/ - Переместить
command/impl/stats/leaderboard/LeaderboardButtons→feature/leaderboard/ - Переместить
command/impl/stats/leaderboard/LeaderboardButtonListener→feature/leaderboard/ - Создать
feature/leaderboard/LeaderboardService.java(использовать из level/) - Удалить пустую папку
command/impl/stats/ - Обновить импорты
12. Создать feature/profile/ (профили пользователей)
- Создать
feature/profile/ - Переместить
profile/ProfileService→feature/profile/ - Переместить
profile/ProfileGenerator→feature/profile/ - Переместить
profile/ProfileData→feature/profile/ - Переместить
command/impl/utility/ProfileCommand→feature/profile/ - Создать
feature/profile/ProfileEmbedFactory.java(вынести из команды) - Удалить пустую папку
profile/ - Обновить импорты
13. Создать feature/metrics/ (метрики системы)
- Создать
feature/metrics/ - Переместить
metrics/MetricsCollector→feature/metrics/ - Переместить
command/impl/utility/MetricsCommand→feature/metrics/ - Создать
feature/metrics/MetricsService.java(если нужна логика) - Удалить пустую папку
metrics/ - Обновить импорты
Этап 4: Инфраструктура (после feature/)
14. Реорганизовать event/ (listener)
- Создать
event/ - Создать
event/gateway/(JDA Gateway events) - Переместить
listener/ReadyListener→event/gateway/ - Переместить
listener/MessageListener→event/gateway/ - Создать
event/gateway/GuildListener.java(member join/leave + moderation) - Переместить
listener/ModerationLogger→event/gateway/GuildListener(или отдельно) - Создать
event/interaction/(Button/Menu interactions) - Переместить
listener/SlashCommandListener→event/interaction/ - Переместить
listener/HelpMenuHandler→event/interaction/ - Удалить пустую папку
listener/ - Обновить импорты
15. Реорганизовать core/
- Создать
core/registry/ - Переместить
core/CommandRegistry→core/registry/ - Переместить
core/SlashCommandRegistry→core/registry/ - Переместить
core/PrefixCommandRegistrar→core/registry/ - Переместить
core/SlashCommandRegistrar→core/registry/ - Создать
core/exception/ - Переместить
exception/CommandExceptionHandler→core/exception/ - Переместить
exception/CommandException→command/CommandException - Удалить пустую папку
exception/ - Обновить импорты
16. Почистить command/
- Переименовать
command/impl/entertainment/interaction/→command/entertainment/social/ - Удалить
command/impl/setup/(команды перенесены в feature/) - Удалить
command/impl/utility/SwapCommand.java(не используется) - Оставить в
command/только:- Интерфейсы:
Command.java,CommandContext.java,SlashCommand.java,CommandException.java command/moderation/(если не выносим в feature/)command/entertainment/(кросс-доменные развлечения)command/utility/(HelpCommand, PingCommand, InfoCommand, AvatarCommand, PollCommand)
- Интерфейсы:
17. Вынести App.java из корня
- Создать
bootstrap/ - Создать
bootstrap/App.java - Переместить логику инициализации из корневого
App.java - Удалить корневой
App.java - Обновить
build.gradle(mainClass)
Этап 5: Финальная полировка (опционально)
18. UserStats immutable (после Repository)
- Создать
UserStats.Builder - Убрать public сеттеры (оставить package-private для Gson)
- Добавить методы
addXP(),recordMessage(),addVoiceTime() - Добавить
getLevel(XpFormula)вместо внешних вычислений - Обновить
JsonUserStatsRepositoryдля работы с immutable
19. Обновить документацию
- Обновить
FEATURES.md(убрать TTS, добавить новые фичи) - Обновить
README.md(новая структура проекта) - Создать
ARCHITECTURE.md(описание доменов и feature/) - Обновить комментарии в коде
20. Финальная проверка
gradle build- компиляция без ошибок- Проверить все импорты
- Проверить что нет папок с >6 файлами
- Проверить что нет файлов >200 строк
- Запустить бота и протестировать основные команды
Основные задачи
1. ⚡ Переделать систему опыта (XP System Rework)
Текущая проблема:
- Формула:
XP = 100 * level^1.5(слишком сложная) - XP за сообщение: 10 XP
- XP за минуту в войсе: 5 XP
- Cooldown на сообщения: 60 секунд
Новая система (из FEATURES.md):
-
✅ Формула прогрессии:
XP для следующего уровня = 200 * текущий_уровень- Пример: уровень 1 → 2 требует 200 XP
- Уровень 5 → 6 требует 1000 XP
- Уровень 10 → 11 требует 2000 XP
-
✅ Голосовая активность:
- 1 XP каждую минуту нахождения в голосовом канале
- Автоматическое отслеживание через
VoiceXpListener - Уведомление при повышении уровня в войс-канале
Файлы для изменения:
src/main/java/creator/loki/level/LevelSystem.java- изменить формулуsrc/main/java/creator/loki/listener/VoiceTracker.java- изменить начисление XP- Добавить уведомления о level up в войсе
Статус: ✅ ГОТОВО
2. 🎤 Система личных голосовых каналов (Voice Management System)
Концепция: Пользователь заходит в специальный канал-триггер → бот автоматически создает личный войс-канал → перемещает пользователя туда → пишет сообщение в чат войса с настройками
Функционал:
2.1 Автоматическое создание каналов
- ✅ Создать
VoiceChannelManagerкласс - ✅ Listener на вход в канал-триггер (например, "➕ Создать канал")
- ✅ Автоматическое создание канала с именем пользователя
- ✅ Перемещение пользователя в созданный канал
- ✅ Выдача прав управления владельцу канала
- ✅ Автоматическое удаление канала когда он пустой
2.2 Сообщение с настройками в чате войса
При создании канала бот отправляет embed с кнопками:
- 🔒 Закрыть/Открыть - переключение приватности
- 👥 Лимит - установить лимит пользователей (0-99)
- ✏️ Переименовать - изменить название канала
- 🎨 Битрейт - изменить качество звука
- 🚫 Удалить - удалить канал
2.3 Система пресетов
- ✅ Сохранение настроек как пресет
- ✅ Быстрое применение сохраненных настроек
- ✅ Хранение в
data/voice_presets.json
Структура данных:
{
"voice_channels": {
"channel_id": {
"owner_id": "user_id",
"created_at": 1234567890,
"settings": {
"name": "Канал пользователя",
"limit": 5,
"bitrate": 64000,
"locked": false
}
}
},
"presets": {
"user_id": [
{
"name": "Gaming",
"limit": 4,
"bitrate": 96000
}
]
}
}
Файлы для создания:
src/main/java/creator/loki/voice/VoiceChannelManager.javasrc/main/java/creator/loki/voice/VoiceChannelData.javasrc/main/java/creator/loki/voice/VoicePreset.javasrc/main/java/creator/loki/listener/VoiceChannelListener.javasrc/main/java/creator/loki/command/impl/voice/VoiceSettingsCommand.java(для кнопок)
Статус: ✅ ГОТОВО (базовая реализация, кнопки управления требуют обработчиков)
3. 📊 Счетчик участников (Member Counter)
Функционал:
- ✅ Обновление названия голосового канала с количеством участников
- ✅ Формат:
【👥】Участники: 123 - ✅ Отслеживание дневной статистики:
- Количество присоединившихся за день
- Количество покинувших за день
- Разница за 24 часа
- ✅ Обновление каждые 5 минут
- ✅ Сохранение статистики в
data/counter_data.json
Структура данных:
{
"counter_channel_id": "1234567890",
"daily_stats": {
"date": "2026-05-11",
"joined": 15,
"left": 8,
"difference": 7
},
"history": [
{
"date": "2026-05-10",
"joined": 20,
"left": 12,
"difference": 8
}
]
}
Файлы для создания:
src/main/java/creator/loki/listener/MemberCounterListener.javasrc/main/java/creator/loki/counter/CounterManager.javasrc/main/java/creator/loki/counter/DailyStats.java
Статус: 🔴 Не начато
✅ Что уже сделано
✅ Система опыта переделана
- Новая формула:
XP для уровня N = 200 * N - 1 XP за минуту в войсе
- Обновление каждую минуту вместо 5 минут
- Метод
addVoiceTimeтеперь возвращаетLevelUpResultдля уведомлений
✅ Система личных войс-каналов (базовая)
VoiceChannelManager- управление каналамиVoiceChannelListener- автоматическое создание/удалениеVoiceChannelDataиVoicePreset- модели данных- Автоматическое создание при входе в триггер-канал
- Автоматическое удаление пустых каналов
- Панель управления с кнопками (требуется обработчик кнопок)
✅ Счетчик участников
CounterManager- управление счетчикомMemberCounterListener- отслеживание входов/выходовDailyStats- дневная статистика- Обновление каждые 5 минут
- История за 30 дней
✅ SQLite база данных + автомиграция
Database- менеджер SQLiteDatabaseMigration- автоматическая миграция из JSONConfigRepository- работа с конфигурацией- Все таблицы созданы автоматически
- Миграция данных при первом запуске
✅ Команды настройки
/voice-setup trigger- установить канал-триггер/voice-setup category- установить категорию/voice-setup text-channel- установить текстовый канал/voice-setup info- показать конфигурацию/counter-setup channel- установить канал счетчика/counter-setup format- установить формат/counter-setup info- показать конфигурацию
🔧 Дополнительные улучшения
4. 🎨 Улучшение уведомлений о level up
- ✅ Красивые embed сообщения при повышении уровня
- ✅ Отправка в тот же канал где получен XP
- ✅ Для войса - отправка в текстовый канал связанный с войсом
- ✅ Показывать прогресс до следующего уровня
Статус: 🔴 Не начато
5. 🛠️ Команды для настройки систем (Admin Commands)
Voice System Setup:
/voice-setup trigger <channel>- установить канал-триггер/voice-setup category <category>- установить категорию для личных каналов/voice-setup text-channel <channel>- установить текстовый канал для уведомлений
Counter Setup:
/counter-setup channel <voice-channel>- установить канал для счетчика/counter-setup format <format>- изменить формат отображения/counter stats- показать статистику за период
Статус: 🔴 Не начато
📝 Приоритеты реализации
Высокий приоритет (сделать в первую очередь):
- ⚡ Переделать систему опыта (простая формула)
- 🎤 Базовая система личных войс-каналов (создание/удаление)
- 📊 Счетчик участников
Средний приоритет:
- 🎤 Настройки войс-каналов через кнопки
- 🎨 Улучшение уведомлений о level up
- 🎤 Система пресетов для войс-каналов
Низкий приоритет:
- 🛠️ Админ команды для настройки
🐛 Известные проблемы (Bugs to Fix)
Критические:
- Проверить корректность начисления XP в войсе
- Убедиться что VoiceTracker правильно отслеживает время
Некритические:
- Удалить неиспользуемый logger в LevelSystem.java
- Убрать ненужный @SuppressWarnings в LevelSystem.java
📚 Технические детали
Зависимости:
- JDA 5.0.0 (уже есть)
- Guice для DI (уже есть)
- Gson для JSON (уже есть)
Конфигурация (добавить в config):
voice:
trigger_channel_id: 1234567890
category_id: 1234567890
text_channel_id: 1234567890
auto_delete_empty: true
counter:
channel_id: 1234567890
update_interval: 300 # секунды
format: "【👥】Участники: {count}"
✅ Чеклист перед релизом
- Все функции протестированы
- Логирование работает корректно
- Нет утечек памяти (проверить scheduler'ы)
- Graceful shutdown для всех scheduler'ов
- Документация обновлена
- FEATURES.md актуализирован
Дата создания: 2026-05-11
Версия: 1.0
Автор: Loki Bot Team