refactor: KISS/DRY/SOLID раунд + багфиксы радио/voice/message

Что сделано:
- RatingService (getDeterministicValue + cooldown — одна точка)
- ModerationHelper (trunc/err — одна точка)
- VoiceHelper (waitForCondition с таймаутом)
- SocialCommand (7 файлов → 1 Flavor enum)
- SwapCommand + CaseLookupCommand (Split SRP)
- PlayCommand 219→150, BotInitializer 182→135, RankCardGenerator (1→4)
- MetricsCollector 182→143, TrackScheduler 202→146, VoiceChannelManager 187→150
- QueueCommands 207→149, VoiceSetupPrefixCommand 183→146, ServerStatsService 187→150
- GuildMusicManager 167→150, SqlEconomyRepository 169→149, GenerateRatingsCommand 172→147
- RadioManager: таймауты, volume при старте, защита от утечки
- VoiceTracker: race condition fix + LevelUpNotifier
- MessageCooldownService: in-memory cache
- MessageListener: LevelUpNotifier вместо inline embed
- ResetLevelsButtonHandler: правильный парсинг кнопки
- OkHttp: java.net.http → OkHttp 5.4.0
- SlowmodeCommandTest: SelfMember fix
Всё: 415 tests, 2 pre-existing, checkstyle чисто
This commit is contained in:
loki5512344 2026-07-04 18:46:27 +02:00
parent 42948520e8
commit 0d916fbd96
79 changed files with 2639 additions and 3245 deletions

145
TODO.md
View file

@ -251,7 +251,150 @@ feature/economy/
---
**Версия:** 2.3 | **Последнее обновление:** 2026-07-02 | **Java 21 ✅, God Constructor ✅, Critical баги ✅, Economy ✅, Level Roles ✅, Lavalink Music ✅, SpotBugs ✅, Checkstyle ✅, CI/CD ✅**
---
## 🔴 Результаты аудита KISS/DRY/SOLID (2026-07-04)
### DRY — дублирование кода (критично)
| # | Что дублируется | Где | Сколько раз | Статус |
|---|----------------|-----|-------------|--------|
| D1 | `getDeterministicValue()` — целиком | GayCommand, FatCommand, IqCommand, PpCommand, BoykisserCommand, MustacheCommand, RateCommand | 7 | ✅ RatingService |
| D2 | Cooldown check boilerplate (5 строк) | Все entertainment команды | 10+ | ✅ RatingService |
| D3 | `trunc()` / `err()` helpers | MuteCommand, WarnCommand, SwapAndCaseCommand, UnmuteCommand, PunishCommand | 5 | ✅ ModerationHelper |
| D4 | Voice connect retry loop (цикл 10×200ms) | PlayCommand, RadioManager | 2 |
| D5 | RatingConfig — 6 методов с идентичной структурой | RatingConfig.java | 6 |
| D6 | Social команды (hug/kiss/slap/poke/tickle/cuddle/feed/pat) — шаблон | 10 файлов | 10 |
### SOLID
| # | Нарушение | Файл | Описание |
|---|-----------|------|----------|
| S1 | SRP | BotModule.java | Биндит всё приложение |
| S2 | SRP | SwapAndCaseCommand.java | Две разные команды в одном файле |
| S3 | SRP | BotInitializer.java | Инициализирует 3 JDA, Lavalink, mutes, counters, health |
| S4 | SRP | ShutdownManager.java | 9 зависимостей в конструкторе |
| S5 | SRP | PlayCommand.java | execute() на 145 строк |
| S6 | OCP | Meter-команды (gay/fat/iq/pp) | Добавить новую = копировать 90 строк | ✅ RatingService |
| S7 | DIP | MuteCommand, WarnCommand | >5 конкретных репозиториев вместо интерфейсов |
### Файлы >150 строк
| # | Файл | Строк |
|---|------|-------|
| F1 | PlayCommand.java | 219 |
| F2 | QueueSlashHandler.java | 207 |
| F3 | MusicBotControlHandler.java | 207 |
| F4 | QueueCommands.java | 207 |
| F5 | TrackScheduler.java | 202 |
| F6 | MuteCommand.java | 199 |
| F7 | ModerationLogger.java | 199 |
| F8 | FeatureTables.java | 193 |
| F9 | DatabaseMigration.java | 193 |
| F10 | VoiceChannelManager.java | 187 |
| F11 | ServerStatsService.java | 187 |
| F12 | VoiceSetupPrefixCommand.java | 183 |
| F13 | RadioManager.java | 182 |
| F14 | MetricsCollector.java | 182 |
| F15 | WarnCommand.java | 184 |
| F16 | BotInitializer.java | 182 |
| F17 | SlashHandler's (Queue/Filter) | >100 |
| F18 | GenerateRatingsCommand.java | 172 |
| F19 | BlackjackService.java | 172 |
| F20 | SqlEconomyRepository.java | 169 |
| F21 | GuildMusicManager.java | 167 |
| F22 | ProfileCommand/RankCardGen | >150 |
### >3 файла в папке
| # | Папка | Файлов |
|---|-------|--------|
| P1 | feature/entertainment/commands/ | 15 |
| P2 | feature/social/commands/ | 10 |
| P3 | feature/economy/command/minigame/ | 7 |
| P4 | feature/level/ (все субпапки) | 21 |
| P5 | feature/moderation/ (все субпакеты) | 18 |
| P6 | feature/music/ (все субпакеты) | 22 |
| P7 | feature/voice/ (все субпакеты) | 12 |
### Нет тестов
| # | Фича | Файлов |
|---|------|--------|
| T1 | music | 20+ |
| T2 | voice | 12 |
| T3 | social | 10 |
| T4 | role | 9 |
| T5 | radio | 5 |
| T6 | reputation | 4 |
| T7 | counter | 7 |
| T8 | admin | 1 |
| T9 | help | 2 |
| T10 | utility | 2 |
| T11 | welcome | 2 |
| T12 | profile | 5 |
| T13 | serverstats | 1 |
## 📋 План рефакторинга (KISS/DRY/SOLID)
### Этап 8: Убить дублирование (DRY) — в процессе
- [x] D1/D2: `RatingService` с `getDeterministicValue()`, cooldown, member parsing — 7 команд переписаны
- [x] D3: `ModerationHelper` с `trunc()`/`err()` — MuteCommand, UnmuteCommand, WarnCommand, SwapAndCaseCommand, PunishCommand
- [ ] D4: Вынести voice connect retry в утилиту
- [ ] D5: RatingConfig — заменить 6 методов на data-driven (Map или config)
- [ ] D6: Social команды — единый `SocialCommand` с параметром action
### Этап 9: SOLID
- [ ] S1: Разбить `BotModule` на per-feature модули (FeatureModule → install в BotModule)
- [ ] S2: Разделить `SwapAndCaseCommand` на два отдельных файла
- [ ] S3: Выделить `MusicBotFactory`, `RadioBotFactory` из `BotInitializer`
- [ ] S4: Уменьшить кол-во зависимостей `ShutdownManager` через события (EventBus)
- [ ] S5: Разбить `PlayCommand.execute()` на методы
- [ ] S6: Meter-команды сделать data-driven через `RatingService`
- [ ] S7: Выделить интерфейсы для репозиториев/сервисов (DIP)
### Этап 10: Файлы ≤150 строк
- [ ] F01: PlayCommand.java — разбить на методы/классы
- [ ] F02-04: QueueSlashHandler, MusicBotControlHandler, QueueCommands — вынести общие части
- [ ] F05: TrackScheduler.java — вывести FilterState в отд. файл или утилиту
- [ ] F06: MuteCommand.java — разбить на subcommand handler'ы
- [ ] F07: ModerationLogger.java — разбить по типам событий
- [ ] F08-09: FeatureTables, DatabaseMigration — разбить по фичам
- [ ] F10-12: Voice* — вынести логику в сервисы
- [ ] F13: RadioManager.java — вынести voice connect в утилиту
- [ ] F14: MetricsCollector.java — разбить по типам метрик
- [ ] F15: WarnCommand.java — вынести auto-mute в отдельный сервис
- [ ] F16: BotInitializer.java — вынести фабрики ботов
- [ ] Остальные: разбить по SOLID
### Этап 11: ≤6 файлов в папке
- [ ] P1: Entertainment команды — группировать по смыслу (coin/dice → `random/`, gay/iq/pp → `rating/`)
- [ ] P2: Social команды — объединить в `SocialCommand` с параметром
- [ ] P4: Level — разбить на commands/, service/, repository/
- [ ] P5: Moderation — разбить по поддоменам (commands/punish, commands/utils, warn)
- [ ] P6: Music — разбить на commands/, player/, lavalink/
### Этап 12: Тесты
- [ ] T1: Music — написать тесты на LavalinkManager, TrackScheduler, PlayCommand
- [ ] T2: Voice — VoiceChannelManager, VoiceButtonHandler
- [ ] T3: Social — интеграционные тесты с NekosLifeApi (мок)
- [ ] T4: Radio — RadioManager, RadioCommand
- [ ] T5: Role — CustomRoleManager, RoleCommandValidator
- [ ] T6-13: Остальные фичи — минимум smoke test
### Техдолг (баги)
- [ ] B1: EmbedFactoryTest — 2 падающих теста (`withTitle`, `withColor`) — IllegalStateException
- [ ] B2: SlowmodeCommandTest — починен (было 7 ошибок компиляции из-за JDA 6.4 SelfMember)
---
**Версия:** 2.3 | **Последнее обновление:** 2026-07-04 | **Java 21 ✅, God Constructor ✅, Critical баги ✅, Economy ✅, Level Roles ✅, Lavalink Music ✅, SpotBugs ✅, Checkstyle ✅, CI/CD ✅**
## ✅ Что добавлено в v2.3