From 703d0b7e4996d9fd18ac1ad6a9038993e1144acb Mon Sep 17 00:00:00 2001 From: loki5512344 Date: Mon, 11 May 2026 14:27:50 +0200 Subject: [PATCH] Refactor Stage 1.1-1.3: Create repository layer, move util to core/security and integration/nekos --- .../entertainment/games/BoykisserCommand.java | 2 +- .../impl/entertainment/games/FatCommand.java | 2 +- .../impl/entertainment/games/GayCommand.java | 2 +- .../impl/entertainment/games/IqCommand.java | 2 +- .../entertainment/games/MustacheCommand.java | 2 +- .../impl/entertainment/games/PpCommand.java | 2 +- .../impl/entertainment/games/RateCommand.java | 2 +- .../interaction/CuddleCommand.java | 4 +- .../interaction/FeedCommand.java | 4 +- .../entertainment/interaction/HugCommand.java | 2 +- .../interaction/KissCommand.java | 4 +- .../entertainment/interaction/PatCommand.java | 2 +- .../interaction/PokeCommand.java | 4 +- .../interaction/SlapCommand.java | 4 +- .../interaction/TickleCommand.java | 4 +- .../command/impl/stats/MinusRepCommand.java | 2 +- .../loki/command/impl/stats/RepCommand.java | 2 +- .../creator/loki/core/BotInitializer.java | 8 +-- .../creator/loki/core/EventDispatcher.java | 6 +-- .../loki/core/PrefixCommandRegistrar.java | 2 +- .../security}/CooldownManager.java | 2 +- .../security/RateLimiter.java} | 16 +++--- src/main/java/creator/loki/di/BotModule.java | 18 +++++-- .../nekos}/NekosLifeApi.java | 2 +- .../loki/listener/SlashCommandListener.java | 6 +-- .../loki/repository/UserStatsRepository.java | 32 ++++++++++++ .../impl/JsonUserStatsRepository.java | 50 +++++++++++++++++++ .../loki/util/GlobalRateLimiterTest.java | 6 +-- 28 files changed, 142 insertions(+), 52 deletions(-) rename src/main/java/creator/loki/{util => core/security}/CooldownManager.java (98%) rename src/main/java/creator/loki/{util/GlobalRateLimiter.java => core/security/RateLimiter.java} (92%) rename src/main/java/creator/loki/{util => integration/nekos}/NekosLifeApi.java (98%) create mode 100644 src/main/java/creator/loki/repository/UserStatsRepository.java create mode 100644 src/main/java/creator/loki/repository/impl/JsonUserStatsRepository.java diff --git a/src/main/java/creator/loki/command/impl/entertainment/games/BoykisserCommand.java b/src/main/java/creator/loki/command/impl/entertainment/games/BoykisserCommand.java index ea5d037..fa9f34d 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/games/BoykisserCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/games/BoykisserCommand.java @@ -3,7 +3,7 @@ package creator.loki.command.impl.entertainment.games; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; +import creator.loki.core.security.CooldownManager; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/games/FatCommand.java b/src/main/java/creator/loki/command/impl/entertainment/games/FatCommand.java index a17339b..1c9e6c4 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/games/FatCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/games/FatCommand.java @@ -3,7 +3,7 @@ package creator.loki.command.impl.entertainment.games; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; +import creator.loki.core.security.CooldownManager; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/games/GayCommand.java b/src/main/java/creator/loki/command/impl/entertainment/games/GayCommand.java index 38a0a34..9cdd212 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/games/GayCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/games/GayCommand.java @@ -3,7 +3,7 @@ package creator.loki.command.impl.entertainment.games; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; +import creator.loki.core.security.CooldownManager; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/games/IqCommand.java b/src/main/java/creator/loki/command/impl/entertainment/games/IqCommand.java index 7ee4533..dc0df82 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/games/IqCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/games/IqCommand.java @@ -3,7 +3,7 @@ package creator.loki.command.impl.entertainment.games; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; +import creator.loki.core.security.CooldownManager; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/games/MustacheCommand.java b/src/main/java/creator/loki/command/impl/entertainment/games/MustacheCommand.java index c84637e..afde8f0 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/games/MustacheCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/games/MustacheCommand.java @@ -3,7 +3,7 @@ package creator.loki.command.impl.entertainment.games; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; +import creator.loki.core.security.CooldownManager; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/games/PpCommand.java b/src/main/java/creator/loki/command/impl/entertainment/games/PpCommand.java index 4879c6a..b6fcb82 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/games/PpCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/games/PpCommand.java @@ -3,7 +3,7 @@ package creator.loki.command.impl.entertainment.games; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; +import creator.loki.core.security.CooldownManager; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/games/RateCommand.java b/src/main/java/creator/loki/command/impl/entertainment/games/RateCommand.java index 9c4f008..ad317e6 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/games/RateCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/games/RateCommand.java @@ -3,7 +3,7 @@ package creator.loki.command.impl.entertainment.games; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; +import creator.loki.core.security.CooldownManager; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/interaction/CuddleCommand.java b/src/main/java/creator/loki/command/impl/entertainment/interaction/CuddleCommand.java index de826b2..5367a1a 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/interaction/CuddleCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/interaction/CuddleCommand.java @@ -3,8 +3,8 @@ package creator.loki.command.impl.entertainment.interaction; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; -import creator.loki.util.NekosLifeApi; +import creator.loki.core.security.CooldownManager; +import creator.loki.integration.nekos.NekosLifeApi; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/interaction/FeedCommand.java b/src/main/java/creator/loki/command/impl/entertainment/interaction/FeedCommand.java index 0f8ded1..777440e 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/interaction/FeedCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/interaction/FeedCommand.java @@ -3,8 +3,8 @@ package creator.loki.command.impl.entertainment.interaction; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; -import creator.loki.util.NekosLifeApi; +import creator.loki.core.security.CooldownManager; +import creator.loki.integration.nekos.NekosLifeApi; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/interaction/HugCommand.java b/src/main/java/creator/loki/command/impl/entertainment/interaction/HugCommand.java index 26d9d2a..c484efe 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/interaction/HugCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/interaction/HugCommand.java @@ -3,7 +3,7 @@ package creator.loki.command.impl.entertainment.interaction; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.NekosLifeApi; +import creator.loki.integration.nekos.NekosLifeApi; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/interaction/KissCommand.java b/src/main/java/creator/loki/command/impl/entertainment/interaction/KissCommand.java index 19fab28..91b0f97 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/interaction/KissCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/interaction/KissCommand.java @@ -3,8 +3,8 @@ package creator.loki.command.impl.entertainment.interaction; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; -import creator.loki.util.NekosLifeApi; +import creator.loki.core.security.CooldownManager; +import creator.loki.integration.nekos.NekosLifeApi; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/interaction/PatCommand.java b/src/main/java/creator/loki/command/impl/entertainment/interaction/PatCommand.java index 4495969..bb2415a 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/interaction/PatCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/interaction/PatCommand.java @@ -2,7 +2,7 @@ package creator.loki.command.impl.entertainment.interaction; import creator.loki.command.Command; import creator.loki.command.CommandContext; -import creator.loki.util.CooldownManager; +import creator.loki.core.security.CooldownManager; import net.dv8tion.jda.api.entities.Member; import java.util.List; diff --git a/src/main/java/creator/loki/command/impl/entertainment/interaction/PokeCommand.java b/src/main/java/creator/loki/command/impl/entertainment/interaction/PokeCommand.java index bfe7154..b3685bb 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/interaction/PokeCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/interaction/PokeCommand.java @@ -3,8 +3,8 @@ package creator.loki.command.impl.entertainment.interaction; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; -import creator.loki.util.NekosLifeApi; +import creator.loki.core.security.CooldownManager; +import creator.loki.integration.nekos.NekosLifeApi; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/interaction/SlapCommand.java b/src/main/java/creator/loki/command/impl/entertainment/interaction/SlapCommand.java index 7caf256..82c373e 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/interaction/SlapCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/interaction/SlapCommand.java @@ -3,8 +3,8 @@ package creator.loki.command.impl.entertainment.interaction; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; -import creator.loki.util.NekosLifeApi; +import creator.loki.core.security.CooldownManager; +import creator.loki.integration.nekos.NekosLifeApi; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/entertainment/interaction/TickleCommand.java b/src/main/java/creator/loki/command/impl/entertainment/interaction/TickleCommand.java index 1eee42b..f6fb767 100644 --- a/src/main/java/creator/loki/command/impl/entertainment/interaction/TickleCommand.java +++ b/src/main/java/creator/loki/command/impl/entertainment/interaction/TickleCommand.java @@ -3,8 +3,8 @@ package creator.loki.command.impl.entertainment.interaction; import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; -import creator.loki.util.NekosLifeApi; +import creator.loki.core.security.CooldownManager; +import creator.loki.integration.nekos.NekosLifeApi; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/stats/MinusRepCommand.java b/src/main/java/creator/loki/command/impl/stats/MinusRepCommand.java index d5e187e..0d493ac 100644 --- a/src/main/java/creator/loki/command/impl/stats/MinusRepCommand.java +++ b/src/main/java/creator/loki/command/impl/stats/MinusRepCommand.java @@ -5,7 +5,7 @@ import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.data.JsonDataStore; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; +import creator.loki.core.security.CooldownManager; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/command/impl/stats/RepCommand.java b/src/main/java/creator/loki/command/impl/stats/RepCommand.java index 99c6c69..a3d60e8 100644 --- a/src/main/java/creator/loki/command/impl/stats/RepCommand.java +++ b/src/main/java/creator/loki/command/impl/stats/RepCommand.java @@ -5,7 +5,7 @@ import creator.loki.command.Command; import creator.loki.command.CommandContext; import creator.loki.data.JsonDataStore; import creator.loki.embed.EmbedFactory; -import creator.loki.util.CooldownManager; +import creator.loki.core.security.CooldownManager; import net.dv8tion.jda.api.entities.Member; import java.awt.Color; diff --git a/src/main/java/creator/loki/core/BotInitializer.java b/src/main/java/creator/loki/core/BotInitializer.java index 0b1f464..5c34b46 100644 --- a/src/main/java/creator/loki/core/BotInitializer.java +++ b/src/main/java/creator/loki/core/BotInitializer.java @@ -16,8 +16,8 @@ import creator.loki.listener.*; import creator.loki.metrics.MetricsCollector; import creator.loki.profile.ProfileService; import creator.loki.role.CustomRoleManager; -import creator.loki.util.CooldownManager; -import creator.loki.util.GlobalRateLimiter; +import creator.loki.core.security.CooldownManager; +import creator.loki.core.security.RateLimiter; import creator.loki.voice.VoiceChannelManager; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; @@ -37,7 +37,7 @@ public class BotInitializer { private final JsonDataStore dataStore; private final CustomRoleManager roleManager; private final CooldownManager cooldownManager; - private final GlobalRateLimiter rateLimiter; + private final RateLimiter rateLimiter; private final MetricsCollector metrics; private final AudioManager audioManager; private final LevelSystem levelSystem; @@ -66,7 +66,7 @@ public class BotInitializer { JsonDataStore dataStore, CustomRoleManager roleManager, CooldownManager cooldownManager, - GlobalRateLimiter rateLimiter, + RateLimiter rateLimiter, MetricsCollector metrics, AudioManager audioManager, LevelSystem levelSystem, diff --git a/src/main/java/creator/loki/core/EventDispatcher.java b/src/main/java/creator/loki/core/EventDispatcher.java index 8ef0c51..e6f5b35 100644 --- a/src/main/java/creator/loki/core/EventDispatcher.java +++ b/src/main/java/creator/loki/core/EventDispatcher.java @@ -6,7 +6,7 @@ import creator.loki.config.BotConfig; import creator.loki.embed.EmbedTemplates; import creator.loki.exception.CommandExceptionHandler; import creator.loki.metrics.MetricsCollector; -import creator.loki.util.GlobalRateLimiter; +import creator.loki.core.security.RateLimiter; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,10 +22,10 @@ public class EventDispatcher { private final BotConfig config; private final CommandRegistry registry; private final ExecutorService executorService; - private final GlobalRateLimiter rateLimiter; + private final RateLimiter rateLimiter; private final MetricsCollector metrics; - public EventDispatcher(BotConfig config, CommandRegistry registry, GlobalRateLimiter rateLimiter, MetricsCollector metrics) { + public EventDispatcher(BotConfig config, CommandRegistry registry, RateLimiter rateLimiter, MetricsCollector metrics) { this.config = config; this.registry = registry; this.executorService = Executors.newCachedThreadPool(); diff --git a/src/main/java/creator/loki/core/PrefixCommandRegistrar.java b/src/main/java/creator/loki/core/PrefixCommandRegistrar.java index 2257b27..77f5749 100644 --- a/src/main/java/creator/loki/core/PrefixCommandRegistrar.java +++ b/src/main/java/creator/loki/core/PrefixCommandRegistrar.java @@ -13,7 +13,7 @@ import creator.loki.level.LevelSystem; import creator.loki.metrics.MetricsCollector; import creator.loki.profile.ProfileService; import creator.loki.role.CustomRoleManager; -import creator.loki.util.CooldownManager; +import creator.loki.core.security.CooldownManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/creator/loki/util/CooldownManager.java b/src/main/java/creator/loki/core/security/CooldownManager.java similarity index 98% rename from src/main/java/creator/loki/util/CooldownManager.java rename to src/main/java/creator/loki/core/security/CooldownManager.java index 669031d..cdbbad0 100644 --- a/src/main/java/creator/loki/util/CooldownManager.java +++ b/src/main/java/creator/loki/core/security/CooldownManager.java @@ -1,4 +1,4 @@ -package creator.loki.util; +package creator.loki.core.security; import java.time.Instant; import java.util.concurrent.ConcurrentHashMap; diff --git a/src/main/java/creator/loki/util/GlobalRateLimiter.java b/src/main/java/creator/loki/core/security/RateLimiter.java similarity index 92% rename from src/main/java/creator/loki/util/GlobalRateLimiter.java rename to src/main/java/creator/loki/core/security/RateLimiter.java index 4a6f0d4..2af9792 100644 --- a/src/main/java/creator/loki/util/GlobalRateLimiter.java +++ b/src/main/java/creator/loki/core/security/RateLimiter.java @@ -1,4 +1,4 @@ -package creator.loki.util; +package creator.loki.core.security; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -10,11 +10,11 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** - * Глобальный rate limiter для защиты от спама + * Rate limiter для защиты от спама * Использует алгоритм Token Bucket */ -public class GlobalRateLimiter { - private static final Logger logger = LoggerFactory.getLogger(GlobalRateLimiter.class); +public class RateLimiter { + private static final Logger logger = LoggerFactory.getLogger(RateLimiter.class); // Лимиты по умолчанию private static final int DEFAULT_USER_CAPACITY = 10; // Максимум токенов на пользователя @@ -26,10 +26,10 @@ public class GlobalRateLimiter { private final ConcurrentHashMap guildBuckets = new ConcurrentHashMap<>(); private final ScheduledExecutorService cleanupExecutor = Executors.newSingleThreadScheduledExecutor(); - public GlobalRateLimiter() { + public RateLimiter() { // Очистка старых bucket'ов каждые 5 минут cleanupExecutor.scheduleAtFixedRate(this::cleanup, 5, 5, TimeUnit.MINUTES); - logger.info("GlobalRateLimiter инициализирован"); + logger.info("RateLimiter инициализирован"); } /** @@ -90,7 +90,7 @@ public class GlobalRateLimiter { * Завершает работу rate limiter */ public void shutdown() { - logger.info("Завершение работы GlobalRateLimiter..."); + logger.info("Завершение работы RateLimiter..."); cleanupExecutor.shutdown(); try { if (!cleanupExecutor.awaitTermination(5, TimeUnit.SECONDS)) { @@ -100,7 +100,7 @@ public class GlobalRateLimiter { cleanupExecutor.shutdownNow(); Thread.currentThread().interrupt(); } - logger.info("GlobalRateLimiter завершён"); + logger.info("RateLimiter завершён"); } /** diff --git a/src/main/java/creator/loki/di/BotModule.java b/src/main/java/creator/loki/di/BotModule.java index a5da943..f4a2e48 100644 --- a/src/main/java/creator/loki/di/BotModule.java +++ b/src/main/java/creator/loki/di/BotModule.java @@ -8,6 +8,9 @@ import creator.loki.config.ConfigLoader; import creator.loki.core.CommandRegistry; import creator.loki.core.EventDispatcher; import creator.loki.core.SlashCommandRegistry; +import creator.loki.core.security.CooldownManager; +import creator.loki.core.security.RateLimiter; +import creator.loki.counter.CounterManager; import creator.loki.data.JsonDataStore; import creator.loki.database.ConfigRepository; import creator.loki.database.Database; @@ -18,11 +21,10 @@ import creator.loki.listener.LevelUpNotifier; import creator.loki.listener.VoiceTracker; import creator.loki.metrics.MetricsCollector; import creator.loki.profile.ProfileService; +import creator.loki.repository.UserStatsRepository; +import creator.loki.repository.impl.JsonUserStatsRepository; import creator.loki.role.CustomRoleManager; -import creator.loki.util.CooldownManager; -import creator.loki.util.GlobalRateLimiter; import creator.loki.voice.VoiceChannelManager; -import creator.loki.counter.CounterManager; /** * Главный модуль Guice для конфигурации Dependency Injection @@ -35,7 +37,7 @@ public class BotModule extends AbstractModule { bind(CommandRegistry.class).in(Singleton.class); bind(SlashCommandRegistry.class).in(Singleton.class); bind(CooldownManager.class).in(Singleton.class); - bind(GlobalRateLimiter.class).in(Singleton.class); + bind(RateLimiter.class).in(Singleton.class); bind(MetricsCollector.class).in(Singleton.class); } @@ -82,7 +84,7 @@ public class BotModule extends AbstractModule { EventDispatcher provideEventDispatcher( BotConfig config, CommandRegistry registry, - GlobalRateLimiter rateLimiter, + RateLimiter rateLimiter, MetricsCollector metrics ) { return new EventDispatcher(config, registry, rateLimiter, metrics); @@ -123,6 +125,12 @@ public class BotModule extends AbstractModule { return new VoiceChannelManager(dataStore, configRepo); } + @Provides + @Singleton + UserStatsRepository provideUserStatsRepository(JsonDataStore dataStore) { + return new JsonUserStatsRepository(dataStore); + } + @Provides @Singleton CounterManager provideCounterManager(JsonDataStore dataStore, ConfigRepository configRepo) { diff --git a/src/main/java/creator/loki/util/NekosLifeApi.java b/src/main/java/creator/loki/integration/nekos/NekosLifeApi.java similarity index 98% rename from src/main/java/creator/loki/util/NekosLifeApi.java rename to src/main/java/creator/loki/integration/nekos/NekosLifeApi.java index 79f8823..33bd6ad 100644 --- a/src/main/java/creator/loki/util/NekosLifeApi.java +++ b/src/main/java/creator/loki/integration/nekos/NekosLifeApi.java @@ -1,4 +1,4 @@ -package creator.loki.util; +package creator.loki.integration.nekos; import com.google.gson.JsonObject; import com.google.gson.JsonParser; diff --git a/src/main/java/creator/loki/listener/SlashCommandListener.java b/src/main/java/creator/loki/listener/SlashCommandListener.java index 35c55e7..0d8448c 100644 --- a/src/main/java/creator/loki/listener/SlashCommandListener.java +++ b/src/main/java/creator/loki/listener/SlashCommandListener.java @@ -3,7 +3,7 @@ package creator.loki.listener; import creator.loki.core.SlashCommandRegistry; import creator.loki.exception.CommandExceptionHandler; import creator.loki.metrics.MetricsCollector; -import creator.loki.util.GlobalRateLimiter; +import creator.loki.core.security.RateLimiter; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.slf4j.Logger; @@ -15,10 +15,10 @@ import org.slf4j.LoggerFactory; public class SlashCommandListener extends ListenerAdapter { private static final Logger logger = LoggerFactory.getLogger(SlashCommandListener.class); private final SlashCommandRegistry registry; - private final GlobalRateLimiter rateLimiter; + private final RateLimiter rateLimiter; private final MetricsCollector metrics; - public SlashCommandListener(SlashCommandRegistry registry, GlobalRateLimiter rateLimiter, MetricsCollector metrics) { + public SlashCommandListener(SlashCommandRegistry registry, RateLimiter rateLimiter, MetricsCollector metrics) { this.registry = registry; this.rateLimiter = rateLimiter; this.metrics = metrics; diff --git a/src/main/java/creator/loki/repository/UserStatsRepository.java b/src/main/java/creator/loki/repository/UserStatsRepository.java new file mode 100644 index 0000000..8e4fc77 --- /dev/null +++ b/src/main/java/creator/loki/repository/UserStatsRepository.java @@ -0,0 +1,32 @@ +package creator.loki.repository; + +import creator.loki.level.UserStats; + +import java.util.Map; +import java.util.Optional; + +/** + * Repository для работы с статистикой пользователей + */ +public interface UserStatsRepository { + + /** + * Найти статистику пользователя по ID + */ + Optional findById(String userId); + + /** + * Сохранить статистику пользователя + */ + void save(UserStats stats); + + /** + * Получить всю статистику (для лидерборда) + */ + Map findAll(); + + /** + * Проверить существование пользователя + */ + boolean exists(String userId); +} diff --git a/src/main/java/creator/loki/repository/impl/JsonUserStatsRepository.java b/src/main/java/creator/loki/repository/impl/JsonUserStatsRepository.java new file mode 100644 index 0000000..508a106 --- /dev/null +++ b/src/main/java/creator/loki/repository/impl/JsonUserStatsRepository.java @@ -0,0 +1,50 @@ +package creator.loki.repository.impl; + +import com.google.gson.reflect.TypeToken; +import creator.loki.data.JsonDataStore; +import creator.loki.level.UserStats; +import creator.loki.repository.UserStatsRepository; + +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +/** + * Реализация UserStatsRepository через JsonDataStore + */ +public class JsonUserStatsRepository implements UserStatsRepository { + + private static final String DATA_KEY = "userStats"; + private static final Type TYPE = new TypeToken>(){}.getType(); + + private final JsonDataStore dataStore; + + public JsonUserStatsRepository(JsonDataStore dataStore) { + this.dataStore = dataStore; + } + + @Override + public Optional findById(String userId) { + Map allStats = findAll(); + return Optional.ofNullable(allStats.get(userId)); + } + + @Override + public void save(UserStats stats) { + Map allStats = findAll(); + allStats.put(stats.getUserId(), stats); + dataStore.setData(DATA_KEY, allStats); + } + + @Override + public Map findAll() { + Map stats = dataStore.getData(DATA_KEY, TYPE); + return stats != null ? stats : new HashMap<>(); + } + + @Override + public boolean exists(String userId) { + return findAll().containsKey(userId); + } +} diff --git a/src/test/java/creator/loki/util/GlobalRateLimiterTest.java b/src/test/java/creator/loki/util/GlobalRateLimiterTest.java index 98d7133..5c28942 100644 --- a/src/test/java/creator/loki/util/GlobalRateLimiterTest.java +++ b/src/test/java/creator/loki/util/GlobalRateLimiterTest.java @@ -6,12 +6,12 @@ import org.junit.jupiter.api.AfterEach; import static org.junit.jupiter.api.Assertions.*; -class GlobalRateLimiterTest { - private GlobalRateLimiter rateLimiter; +class RateLimiterTest { + private RateLimiter rateLimiter; @BeforeEach void setUp() { - rateLimiter = new GlobalRateLimiter(); + rateLimiter = new RateLimiter(); } @AfterEach