diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs
index f7f3856..5422632 100644
--- a/.settings/org.eclipse.buildship.core.prefs
+++ b/.settings/org.eclipse.buildship.core.prefs
@@ -1,4 +1,4 @@
-arguments=--init-script /home/loki/.cache/opencode/bin/jdtls/config_linux/org.eclipse.osgi/57/0/.cp/gradle/init/init.gradle
+arguments=--init-script /home/loki/.eclipse/2139989682_linux_gtk_x86_64/configuration/org.eclipse.osgi/57/0/.cp/gradle/init/init.gradle
auto.sync=false
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
diff --git a/config/pmd/ruleset.xml b/config/pmd/ruleset.xml
new file mode 100644
index 0000000..5eaeaba
--- /dev/null
+++ b/config/pmd/ruleset.xml
@@ -0,0 +1,95 @@
+
+
+
+ PMD rules for Loki Discord Bot
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/creator/loki/command/CommandCategories.java b/src/main/java/creator/loki/command/CommandCategories.java
index 2da17d1..330ca57 100644
--- a/src/main/java/creator/loki/command/CommandCategories.java
+++ b/src/main/java/creator/loki/command/CommandCategories.java
@@ -6,8 +6,11 @@ public final class CommandCategories {
/** Команды с GIF (nekos.life): hug, slap, poke и т.п. */
public static final String GIF_INTERACTIVE = "GIF-интерактив";
- /** Команды для поиска изображений (e621, r34) — только в NSFW-каналах. */
+ /** Команды для поиска изображений (e621, gelbooru, yande.re) — только в NSFW-каналах. */
public static final String NSFW_IMAGES = "NSFW";
+ /** Команды измерений: pp, fat, aura и подобные. */
+ public static final String MEASUREMENTS = "Измерения";
+
private CommandCategories() {}
}
diff --git a/src/main/java/creator/loki/config/BotConfig.java b/src/main/java/creator/loki/config/BotConfig.java
index fdc1827..ef37a09 100644
--- a/src/main/java/creator/loki/config/BotConfig.java
+++ b/src/main/java/creator/loki/config/BotConfig.java
@@ -18,8 +18,6 @@ public class BotConfig {
private final int aiDossierUpdateHours;
private final String aiDebateChannelId;
private final LavalinkConfig lavalinkConfig;
- private final String r34ApiKey;
- private final String r34UserId;
public BotConfig(
String mainToken,
@@ -38,9 +36,7 @@ public class BotConfig {
int aiDossierMsgs,
int aiDossierUpdateHours,
String aiDebateChannelId,
- LavalinkConfig lavalinkConfig,
- String r34ApiKey,
- String r34UserId) {
+ LavalinkConfig lavalinkConfig) {
this.mainToken = mainToken;
this.musicToken = musicToken;
this.radioToken = radioToken;
@@ -58,8 +54,6 @@ public class BotConfig {
this.aiDossierUpdateHours = aiDossierUpdateHours;
this.aiDebateChannelId = aiDebateChannelId;
this.lavalinkConfig = lavalinkConfig;
- this.r34ApiKey = r34ApiKey;
- this.r34UserId = r34UserId;
}
public String getMainToken() {
@@ -133,12 +127,4 @@ public class BotConfig {
public LavalinkConfig getLavalinkConfig() {
return lavalinkConfig;
}
-
- public String getR34ApiKey() {
- return r34ApiKey;
- }
-
- public String getR34UserId() {
- return r34UserId;
- }
}
diff --git a/src/main/java/creator/loki/config/ConfigLoader.java b/src/main/java/creator/loki/config/ConfigLoader.java
index 1e0a36e..e9d76a8 100644
--- a/src/main/java/creator/loki/config/ConfigLoader.java
+++ b/src/main/java/creator/loki/config/ConfigLoader.java
@@ -83,9 +83,6 @@ public final class ConfigLoader {
int aiDossierUpdateHours = Integer.parseInt(getEnv(dotenv, "AI_DOSSIER_UPDATE_HOURS", "24"));
String aiDebateChannelId = dotenv.get("AI_DEBATE_CHANNEL_ID");
- String r34ApiKey = getEnv(dotenv, "R34_API_KEY", "");
- String r34UserId = getEnv(dotenv, "R34_USER_ID", "");
-
LavalinkConfig lavalinkConfig = getLavalinkConfig();
LoggerDecorator.success(logger, "Конфигурация загружена успешно");
return new BotConfig(
@@ -105,8 +102,6 @@ public final class ConfigLoader {
aiDossierMsgs,
aiDossierUpdateHours,
aiDebateChannelId,
- lavalinkConfig,
- r34ApiKey,
- r34UserId);
+ lavalinkConfig);
}
}
diff --git a/src/main/java/creator/loki/core/BotInitializer.java b/src/main/java/creator/loki/core/BotInitializer.java
index 4801a38..2962281 100644
--- a/src/main/java/creator/loki/core/BotInitializer.java
+++ b/src/main/java/creator/loki/core/BotInitializer.java
@@ -3,15 +3,15 @@ package creator.loki.core;
import com.google.inject.Inject;
import creator.loki.config.BotConfig;
import creator.loki.core.registry.PrefixCommandRegistrar;
-import creator.loki.feature.counter.service.MemberCounterListener;
+import creator.loki.feature.counter.service.listener.MemberCounterListener;
import creator.loki.feature.metrics.HealthHttpServer;
import creator.loki.feature.moderation.MuteScheduler;
import creator.loki.feature.music.core.LavalinkManager;
import creator.loki.feature.music.core.PlayerManager;
import creator.loki.feature.music.listener.MusicBotListener;
import creator.loki.feature.music.repository.QueueRepository;
-import creator.loki.feature.radio.RadioBotListener;
-import creator.loki.feature.radio.RadioManager;
+import creator.loki.feature.radio.listener.RadioBotListener;
+import creator.loki.feature.radio.service.RadioManager;
import creator.loki.util.LoggerDecorator;
import dev.arbjerg.lavalink.libraries.jda.JDAVoiceUpdateListener;
import net.dv8tion.jda.api.JDA;
diff --git a/src/main/java/creator/loki/core/ListenerAggregator.java b/src/main/java/creator/loki/core/ListenerAggregator.java
index 5a420b9..e9ed883 100644
--- a/src/main/java/creator/loki/core/ListenerAggregator.java
+++ b/src/main/java/creator/loki/core/ListenerAggregator.java
@@ -3,21 +3,21 @@ package creator.loki.core;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import creator.loki.bootstrap.ReadyListener;
-import creator.loki.feature.counter.service.MemberCounterListener;
+import creator.loki.feature.counter.service.listener.MemberCounterListener;
import creator.loki.feature.economy.FishMessageListener;
import creator.loki.feature.help.HelpMenuHandler;
-import creator.loki.feature.reactroles.ReactionRoleListener;
-import creator.loki.feature.image.ImageNavigationHandler;
+import creator.loki.feature.reactroles.listener.ReactionRoleListener;
+import creator.loki.feature.image.listener.ImageNavigationHandler;
import creator.loki.feature.leaderboard.LeaderboardButtonListener;
import creator.loki.feature.level.listener.MessageListener;
import creator.loki.feature.level.listener.ResetLevelsButtonHandler;
-import creator.loki.feature.level.service.VoiceTracker;
+import creator.loki.feature.level.service.tracker.VoiceTracker;
import creator.loki.feature.moderation.commands.utils.ClearSlashCommands;
import creator.loki.feature.moderation.log.ModerationLogger;
import creator.loki.feature.config.SetupSlashHandler;
import creator.loki.feature.music.MusicSlashCommands;
import creator.loki.feature.music.listener.PlaySelectHandler;
-import creator.loki.feature.ticket.TicketListener;
+import creator.loki.feature.ticket.listener.TicketListener;
import creator.loki.feature.roast.AndrertListener;
import creator.loki.feature.roast.HelperListener;
import creator.loki.feature.voice.handler.VoiceButtonHandler;
diff --git a/src/main/java/creator/loki/core/ShutdownManager.java b/src/main/java/creator/loki/core/ShutdownManager.java
index 963259f..f79278f 100644
--- a/src/main/java/creator/loki/core/ShutdownManager.java
+++ b/src/main/java/creator/loki/core/ShutdownManager.java
@@ -6,7 +6,7 @@ import java.util.Set;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import creator.loki.database.Database;
-import creator.loki.feature.radio.RadioManager;
+import creator.loki.feature.radio.service.RadioManager;
import creator.loki.util.LoggerDecorator;
import net.dv8tion.jda.api.JDA;
import org.slf4j.Logger;
diff --git a/src/main/java/creator/loki/di/LifecycleModule.java b/src/main/java/creator/loki/di/LifecycleModule.java
index f610029..5083cdb 100644
--- a/src/main/java/creator/loki/di/LifecycleModule.java
+++ b/src/main/java/creator/loki/di/LifecycleModule.java
@@ -7,8 +7,8 @@ import creator.loki.core.Lifecycle;
import creator.loki.core.security.CooldownManager;
import creator.loki.core.security.RateLimiter;
import creator.loki.database.Database;
-import creator.loki.feature.counter.service.MemberCounterListener;
-import creator.loki.feature.level.service.VoiceTracker;
+import creator.loki.feature.counter.service.listener.MemberCounterListener;
+import creator.loki.feature.level.service.tracker.VoiceTracker;
import creator.loki.feature.metrics.HealthHttpServer;
import creator.loki.feature.moderation.MuteScheduler;
diff --git a/src/main/java/creator/loki/feature/counter/repository/CounterStatsRepository.java b/src/main/java/creator/loki/feature/counter/repository/CounterStatsRepository.java
index 9df169b..f053b99 100644
--- a/src/main/java/creator/loki/feature/counter/repository/CounterStatsRepository.java
+++ b/src/main/java/creator/loki/feature/counter/repository/CounterStatsRepository.java
@@ -8,7 +8,7 @@ import java.util.ArrayList;
import java.util.List;
import creator.loki.database.Database;
-import creator.loki.feature.counter.service.DailyStats;
+import creator.loki.feature.counter.service.format.DailyStats;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/src/main/java/creator/loki/feature/counter/service/CounterManager.java b/src/main/java/creator/loki/feature/counter/service/CounterManager.java
index db7e13b..3a79140 100644
--- a/src/main/java/creator/loki/feature/counter/service/CounterManager.java
+++ b/src/main/java/creator/loki/feature/counter/service/CounterManager.java
@@ -9,6 +9,7 @@ import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import creator.loki.feature.counter.service.format.DailyStats;
/** Менеджер счетчика участников */
public class CounterManager {
diff --git a/src/main/java/creator/loki/feature/counter/service/CounterSetupPrefixCommand.java b/src/main/java/creator/loki/feature/counter/service/CounterSetupPrefixCommand.java
index 2c0e07c..0a6c0e3 100644
--- a/src/main/java/creator/loki/feature/counter/service/CounterSetupPrefixCommand.java
+++ b/src/main/java/creator/loki/feature/counter/service/CounterSetupPrefixCommand.java
@@ -8,6 +8,7 @@ import creator.loki.feature.config.repository.ConfigRepository;
import creator.loki.util.GuildChannelResolve;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
+import creator.loki.feature.counter.service.format.CounterConfigFormatter;
public class CounterSetupPrefixCommand implements Command {
private final CounterManager counterManager;
diff --git a/src/main/java/creator/loki/feature/counter/service/CounterConfigFormatter.java b/src/main/java/creator/loki/feature/counter/service/format/CounterConfigFormatter.java
similarity index 98%
rename from src/main/java/creator/loki/feature/counter/service/CounterConfigFormatter.java
rename to src/main/java/creator/loki/feature/counter/service/format/CounterConfigFormatter.java
index 180c547..07c3882 100644
--- a/src/main/java/creator/loki/feature/counter/service/CounterConfigFormatter.java
+++ b/src/main/java/creator/loki/feature/counter/service/format/CounterConfigFormatter.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.counter.service;
+package creator.loki.feature.counter.service.format;
import java.awt.Color;
diff --git a/src/main/java/creator/loki/feature/counter/service/DailyStats.java b/src/main/java/creator/loki/feature/counter/service/format/DailyStats.java
similarity index 96%
rename from src/main/java/creator/loki/feature/counter/service/DailyStats.java
rename to src/main/java/creator/loki/feature/counter/service/format/DailyStats.java
index 122b652..2651478 100644
--- a/src/main/java/creator/loki/feature/counter/service/DailyStats.java
+++ b/src/main/java/creator/loki/feature/counter/service/format/DailyStats.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.counter.service;
+package creator.loki.feature.counter.service.format;
import java.time.LocalDate;
diff --git a/src/main/java/creator/loki/feature/counter/service/MemberCounterListener.java b/src/main/java/creator/loki/feature/counter/service/listener/MemberCounterListener.java
similarity index 96%
rename from src/main/java/creator/loki/feature/counter/service/MemberCounterListener.java
rename to src/main/java/creator/loki/feature/counter/service/listener/MemberCounterListener.java
index 43c6215..6c77c1a 100644
--- a/src/main/java/creator/loki/feature/counter/service/MemberCounterListener.java
+++ b/src/main/java/creator/loki/feature/counter/service/listener/MemberCounterListener.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.counter.service;
+package creator.loki.feature.counter.service.listener;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -13,6 +13,7 @@ import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import creator.loki.feature.counter.service.CounterManager;
/** Listener для счетчика участников */
public class MemberCounterListener extends ListenerAdapter implements Lifecycle {
diff --git a/src/main/java/creator/loki/feature/economy/EconomyCommandRegistrar.java b/src/main/java/creator/loki/feature/economy/EconomyCommandRegistrar.java
index 5753682..4ed7ba4 100644
--- a/src/main/java/creator/loki/feature/economy/EconomyCommandRegistrar.java
+++ b/src/main/java/creator/loki/feature/economy/EconomyCommandRegistrar.java
@@ -11,15 +11,15 @@ import creator.loki.feature.economy.command.core.DailyCommand;
import creator.loki.feature.economy.command.core.PayCommand;
import creator.loki.feature.economy.command.minigame.BlackjackCommand;
import creator.loki.feature.economy.command.minigame.FishCommand;
-import creator.loki.feature.economy.command.minigame.JobCommand;
+import creator.loki.feature.economy.command.job.JobCommand;
import creator.loki.feature.economy.command.minigame.SlotCommand;
-import creator.loki.feature.economy.command.minigame.WorkCommand;
+import creator.loki.feature.economy.command.job.WorkCommand;
import creator.loki.feature.economy.command.social.RobCommand;
-import creator.loki.feature.economy.service.BlackjackService;
+import creator.loki.feature.economy.service.game.BlackjackService;
import creator.loki.feature.economy.service.EconomyService;
import creator.loki.feature.economy.service.FishingService;
-import creator.loki.feature.economy.service.JobService;
-import creator.loki.feature.economy.service.SlotService;
+import creator.loki.feature.economy.service.game.JobService;
+import creator.loki.feature.economy.service.game.SlotService;
public class EconomyCommandRegistrar implements CommandRegistrar {
private final EconomyService economyService;
diff --git a/src/main/java/creator/loki/feature/economy/EconomyModule.java b/src/main/java/creator/loki/feature/economy/EconomyModule.java
index 0f3c84e..103efce 100644
--- a/src/main/java/creator/loki/feature/economy/EconomyModule.java
+++ b/src/main/java/creator/loki/feature/economy/EconomyModule.java
@@ -9,11 +9,11 @@ import creator.loki.core.security.CooldownManager;
import creator.loki.database.Database;
import creator.loki.feature.economy.repository.EconomyRepository;
import creator.loki.feature.economy.repository.SqlEconomyRepository;
-import creator.loki.feature.economy.service.BlackjackService;
+import creator.loki.feature.economy.service.game.BlackjackService;
import creator.loki.feature.economy.service.EconomyService;
import creator.loki.feature.economy.service.FishingService;
-import creator.loki.feature.economy.service.JobService;
-import creator.loki.feature.economy.service.SlotService;
+import creator.loki.feature.economy.service.game.JobService;
+import creator.loki.feature.economy.service.game.SlotService;
public class EconomyModule extends AbstractModule {
diff --git a/src/main/java/creator/loki/feature/economy/command/minigame/JobCommand.java b/src/main/java/creator/loki/feature/economy/command/job/JobCommand.java
similarity index 96%
rename from src/main/java/creator/loki/feature/economy/command/minigame/JobCommand.java
rename to src/main/java/creator/loki/feature/economy/command/job/JobCommand.java
index da44557..095f1c0 100644
--- a/src/main/java/creator/loki/feature/economy/command/minigame/JobCommand.java
+++ b/src/main/java/creator/loki/feature/economy/command/job/JobCommand.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.economy.command.minigame;
+package creator.loki.feature.economy.command.job;
import java.awt.Color;
@@ -6,7 +6,8 @@ import creator.loki.command.Command;
import creator.loki.command.CommandContext;
import creator.loki.embed.EmbedFactory;
import creator.loki.embed.EmbedTemplates;
-import creator.loki.feature.economy.service.JobService;
+import creator.loki.feature.economy.service.game.JobService;
+import creator.loki.feature.economy.service.game.JobService;
public class JobCommand implements Command {
diff --git a/src/main/java/creator/loki/feature/economy/command/minigame/WorkCommand.java b/src/main/java/creator/loki/feature/economy/command/job/WorkCommand.java
similarity index 93%
rename from src/main/java/creator/loki/feature/economy/command/minigame/WorkCommand.java
rename to src/main/java/creator/loki/feature/economy/command/job/WorkCommand.java
index 73b32a8..5fe2b91 100644
--- a/src/main/java/creator/loki/feature/economy/command/minigame/WorkCommand.java
+++ b/src/main/java/creator/loki/feature/economy/command/job/WorkCommand.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.economy.command.minigame;
+package creator.loki.feature.economy.command.job;
import java.awt.Color;
@@ -6,7 +6,8 @@ import creator.loki.command.Command;
import creator.loki.command.CommandContext;
import creator.loki.embed.EmbedFactory;
import creator.loki.embed.EmbedTemplates;
-import creator.loki.feature.economy.service.JobService;
+import creator.loki.feature.economy.service.game.JobService;
+import creator.loki.feature.economy.service.game.JobService;
public class WorkCommand implements Command {
diff --git a/src/main/java/creator/loki/feature/economy/command/minigame/BlackjackCommand.java b/src/main/java/creator/loki/feature/economy/command/minigame/BlackjackCommand.java
index 4406efc..22b4297 100644
--- a/src/main/java/creator/loki/feature/economy/command/minigame/BlackjackCommand.java
+++ b/src/main/java/creator/loki/feature/economy/command/minigame/BlackjackCommand.java
@@ -8,7 +8,7 @@ import creator.loki.command.Command;
import creator.loki.command.CommandContext;
import creator.loki.embed.EmbedFactory;
import creator.loki.embed.EmbedTemplates;
-import creator.loki.feature.economy.service.BlackjackService;
+import creator.loki.feature.economy.service.game.BlackjackService;
import creator.loki.feature.economy.service.EconomyService;
import net.dv8tion.jda.api.entities.MessageEmbed;
diff --git a/src/main/java/creator/loki/feature/economy/command/minigame/SlotCommand.java b/src/main/java/creator/loki/feature/economy/command/minigame/SlotCommand.java
index b1a98da..9d54e2d 100644
--- a/src/main/java/creator/loki/feature/economy/command/minigame/SlotCommand.java
+++ b/src/main/java/creator/loki/feature/economy/command/minigame/SlotCommand.java
@@ -7,7 +7,7 @@ import creator.loki.command.CommandContext;
import creator.loki.embed.EmbedFactory;
import creator.loki.embed.EmbedTemplates;
import creator.loki.feature.economy.service.EconomyService;
-import creator.loki.feature.economy.service.SlotService;
+import creator.loki.feature.economy.service.game.SlotService;
public class SlotCommand implements Command {
diff --git a/src/main/java/creator/loki/feature/economy/service/BlackjackService.java b/src/main/java/creator/loki/feature/economy/service/game/BlackjackService.java
similarity index 98%
rename from src/main/java/creator/loki/feature/economy/service/BlackjackService.java
rename to src/main/java/creator/loki/feature/economy/service/game/BlackjackService.java
index 5b31817..accfb0c 100644
--- a/src/main/java/creator/loki/feature/economy/service/BlackjackService.java
+++ b/src/main/java/creator/loki/feature/economy/service/game/BlackjackService.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.economy.service;
+package creator.loki.feature.economy.service.game;
import java.util.ArrayList;
import java.util.List;
diff --git a/src/main/java/creator/loki/feature/economy/service/JobService.java b/src/main/java/creator/loki/feature/economy/service/game/JobService.java
similarity index 98%
rename from src/main/java/creator/loki/feature/economy/service/JobService.java
rename to src/main/java/creator/loki/feature/economy/service/game/JobService.java
index 82010b4..90b773a 100644
--- a/src/main/java/creator/loki/feature/economy/service/JobService.java
+++ b/src/main/java/creator/loki/feature/economy/service/game/JobService.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.economy.service;
+package creator.loki.feature.economy.service.game;
import java.util.ArrayList;
import java.util.List;
diff --git a/src/main/java/creator/loki/feature/economy/service/SlotService.java b/src/main/java/creator/loki/feature/economy/service/game/SlotService.java
similarity index 97%
rename from src/main/java/creator/loki/feature/economy/service/SlotService.java
rename to src/main/java/creator/loki/feature/economy/service/game/SlotService.java
index cd954c3..afc47ce 100644
--- a/src/main/java/creator/loki/feature/economy/service/SlotService.java
+++ b/src/main/java/creator/loki/feature/economy/service/game/SlotService.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.economy.service;
+package creator.loki.feature.economy.service.game;
import java.util.concurrent.ThreadLocalRandom;
diff --git a/src/main/java/creator/loki/feature/entertainment/EntertainmentCommandRegistrar.java b/src/main/java/creator/loki/feature/entertainment/EntertainmentCommandRegistrar.java
index 51aa87c..6b432ed 100644
--- a/src/main/java/creator/loki/feature/entertainment/EntertainmentCommandRegistrar.java
+++ b/src/main/java/creator/loki/feature/entertainment/EntertainmentCommandRegistrar.java
@@ -10,7 +10,7 @@ import creator.loki.feature.entertainment.commands.MemeCommand;
import creator.loki.feature.entertainment.commands.random.CoinCommand;
import creator.loki.feature.entertainment.commands.random.DiceCommand;
import creator.loki.feature.entertainment.commands.random.EightBallCommand;
-import creator.loki.feature.entertainment.commands.random.RandomChoiceCommand;
+import creator.loki.feature.entertainment.commands.choice.RandomChoiceCommand;
import creator.loki.feature.entertainment.service.RatingService;
import creator.loki.feature.rating.commands.AuraCommand;
import creator.loki.feature.rating.commands.BoykisserCommand;
diff --git a/src/main/java/creator/loki/feature/entertainment/commands/random/RandomChoiceCommand.java b/src/main/java/creator/loki/feature/entertainment/commands/choice/RandomChoiceCommand.java
similarity index 96%
rename from src/main/java/creator/loki/feature/entertainment/commands/random/RandomChoiceCommand.java
rename to src/main/java/creator/loki/feature/entertainment/commands/choice/RandomChoiceCommand.java
index 1e5f932..5c115d5 100644
--- a/src/main/java/creator/loki/feature/entertainment/commands/random/RandomChoiceCommand.java
+++ b/src/main/java/creator/loki/feature/entertainment/commands/choice/RandomChoiceCommand.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.entertainment.commands.random;
+package creator.loki.feature.entertainment.commands.choice;
import java.awt.Color;
import java.util.List;
@@ -9,6 +9,8 @@ import creator.loki.command.CommandContext;
import creator.loki.config.BotConfig;
import creator.loki.embed.EmbedTemplates;
import net.dv8tion.jda.api.EmbedBuilder;
+import creator.loki.feature.utility.ChoiceOptionParser;
+import creator.loki.feature.utility.ChoiceOptionParser;
/** Случайный выбор из вариантов. Разбор строки - {@link ChoiceOptionParser}. */
public class RandomChoiceCommand implements Command {
diff --git a/src/main/java/creator/loki/feature/image/ImageModule.java b/src/main/java/creator/loki/feature/image/ImageModule.java
index f697093..b29b377 100644
--- a/src/main/java/creator/loki/feature/image/ImageModule.java
+++ b/src/main/java/creator/loki/feature/image/ImageModule.java
@@ -6,6 +6,10 @@ import com.google.inject.Singleton;
import com.google.inject.multibindings.Multibinder;
import creator.loki.config.BotConfig;
import creator.loki.core.registry.CommandRegistrar;
+import creator.loki.feature.image.listener.ImageNavigationHandler;
+import creator.loki.feature.image.service.ImageService;
+import creator.loki.feature.image.service.ImageSessionManager;
+import creator.loki.feature.image.util.ImageCommandRegistrar;
public class ImageModule extends AbstractModule {
diff --git a/src/main/java/creator/loki/feature/image/commands/AbstractImageCommand.java b/src/main/java/creator/loki/feature/image/commands/AbstractImageCommand.java
index 85a3430..a13ec51 100644
--- a/src/main/java/creator/loki/feature/image/commands/AbstractImageCommand.java
+++ b/src/main/java/creator/loki/feature/image/commands/AbstractImageCommand.java
@@ -6,10 +6,10 @@ import java.util.List;
import creator.loki.command.Command;
import creator.loki.command.CommandContext;
import creator.loki.embed.EmbedTemplates;
-import creator.loki.feature.image.ImageEmbedHelper;
-import creator.loki.feature.image.ImageService;
-import creator.loki.feature.image.ImageSession;
-import creator.loki.feature.image.ImageSessionManager;
+import creator.loki.feature.image.util.ImageEmbedHelper;
+import creator.loki.feature.image.service.ImageService;
+import creator.loki.feature.image.service.ImageSession;
+import creator.loki.feature.image.service.ImageSessionManager;
import net.dv8tion.jda.api.entities.channel.attribute.IAgeRestrictedChannel;
/**
diff --git a/src/main/java/creator/loki/feature/image/commands/R34Command.java b/src/main/java/creator/loki/feature/image/commands/R34Command.java
deleted file mode 100644
index 43f2f4d..0000000
--- a/src/main/java/creator/loki/feature/image/commands/R34Command.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package creator.loki.feature.image.commands;
-
-import java.awt.Color;
-import java.util.List;
-
-import creator.loki.command.CommandCategories;
-import creator.loki.feature.image.ImageService;
-import creator.loki.feature.image.ImageSessionManager;
-
-public class R34Command extends AbstractImageCommand {
-
- public R34Command(ImageService imageService, ImageSessionManager sessionManager) {
- super(imageService, sessionManager);
- }
-
- @Override
- public String getName() {
- return "r34";
- }
-
- @Override
- public String getDescription() {
- return "Поиск изображений на Rule34";
- }
-
- @Override
- public String getUsage() {
- return "r34 <кол-во до 50> <теги>";
- }
-
- @Override
- public String getCategory() {
- return CommandCategories.NSFW_IMAGES;
- }
-
- @Override
- protected String siteName() {
- return "rule34.xxx";
- }
-
- @Override
- protected String siteDisplayName() {
- return "Rule34";
- }
-
- @Override
- protected Color siteColor() {
- return new Color(200, 100, 0);
- }
-
- @Override
- protected List fetchUrls(String tags, int limit) {
- return imageService.fetchR34(tags, limit);
- }
-}
diff --git a/src/main/java/creator/loki/feature/image/commands/GelbooruCommand.java b/src/main/java/creator/loki/feature/image/commands/booru/GelbooruCommand.java
similarity index 81%
rename from src/main/java/creator/loki/feature/image/commands/GelbooruCommand.java
rename to src/main/java/creator/loki/feature/image/commands/booru/GelbooruCommand.java
index 0b845de..02a87c0 100644
--- a/src/main/java/creator/loki/feature/image/commands/GelbooruCommand.java
+++ b/src/main/java/creator/loki/feature/image/commands/booru/GelbooruCommand.java
@@ -1,11 +1,12 @@
-package creator.loki.feature.image.commands;
+package creator.loki.feature.image.commands.booru;
import java.awt.Color;
import java.util.List;
import creator.loki.command.CommandCategories;
-import creator.loki.feature.image.ImageService;
-import creator.loki.feature.image.ImageSessionManager;
+import creator.loki.feature.image.service.ImageService;
+import creator.loki.feature.image.service.ImageSessionManager;
+import creator.loki.feature.image.commands.AbstractImageCommand;
public class GelbooruCommand extends AbstractImageCommand {
diff --git a/src/main/java/creator/loki/feature/image/commands/YandereCommand.java b/src/main/java/creator/loki/feature/image/commands/booru/YandereCommand.java
similarity index 81%
rename from src/main/java/creator/loki/feature/image/commands/YandereCommand.java
rename to src/main/java/creator/loki/feature/image/commands/booru/YandereCommand.java
index f6069a3..0d5e684 100644
--- a/src/main/java/creator/loki/feature/image/commands/YandereCommand.java
+++ b/src/main/java/creator/loki/feature/image/commands/booru/YandereCommand.java
@@ -1,11 +1,12 @@
-package creator.loki.feature.image.commands;
+package creator.loki.feature.image.commands.booru;
import java.awt.Color;
import java.util.List;
import creator.loki.command.CommandCategories;
-import creator.loki.feature.image.ImageService;
-import creator.loki.feature.image.ImageSessionManager;
+import creator.loki.feature.image.service.ImageService;
+import creator.loki.feature.image.service.ImageSessionManager;
+import creator.loki.feature.image.commands.AbstractImageCommand;
public class YandereCommand extends AbstractImageCommand {
diff --git a/src/main/java/creator/loki/feature/image/commands/E621Command.java b/src/main/java/creator/loki/feature/image/commands/e621/E621Command.java
similarity index 81%
rename from src/main/java/creator/loki/feature/image/commands/E621Command.java
rename to src/main/java/creator/loki/feature/image/commands/e621/E621Command.java
index 60bd3a9..62aff3b 100644
--- a/src/main/java/creator/loki/feature/image/commands/E621Command.java
+++ b/src/main/java/creator/loki/feature/image/commands/e621/E621Command.java
@@ -1,11 +1,12 @@
-package creator.loki.feature.image.commands;
+package creator.loki.feature.image.commands.e621;
import java.awt.Color;
import java.util.List;
import creator.loki.command.CommandCategories;
-import creator.loki.feature.image.ImageService;
-import creator.loki.feature.image.ImageSessionManager;
+import creator.loki.feature.image.service.ImageService;
+import creator.loki.feature.image.service.ImageSessionManager;
+import creator.loki.feature.image.commands.AbstractImageCommand;
public class E621Command extends AbstractImageCommand {
diff --git a/src/main/java/creator/loki/feature/image/commands/E621RandomCommand.java b/src/main/java/creator/loki/feature/image/commands/e621/E621RandomCommand.java
similarity index 90%
rename from src/main/java/creator/loki/feature/image/commands/E621RandomCommand.java
rename to src/main/java/creator/loki/feature/image/commands/e621/E621RandomCommand.java
index e27d2fb..44f7e13 100644
--- a/src/main/java/creator/loki/feature/image/commands/E621RandomCommand.java
+++ b/src/main/java/creator/loki/feature/image/commands/e621/E621RandomCommand.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.image.commands;
+package creator.loki.feature.image.commands.e621;
import java.awt.Color;
import java.util.List;
@@ -6,10 +6,11 @@ import java.util.List;
import creator.loki.command.CommandCategories;
import creator.loki.command.CommandContext;
import creator.loki.embed.EmbedTemplates;
-import creator.loki.feature.image.ImageEmbedHelper;
-import creator.loki.feature.image.ImageService;
-import creator.loki.feature.image.ImageSession;
-import creator.loki.feature.image.ImageSessionManager;
+import creator.loki.feature.image.util.ImageEmbedHelper;
+import creator.loki.feature.image.service.ImageService;
+import creator.loki.feature.image.service.ImageSession;
+import creator.loki.feature.image.service.ImageSessionManager;
+import creator.loki.feature.image.commands.AbstractImageCommand;
public class E621RandomCommand extends AbstractImageCommand {
diff --git a/src/main/java/creator/loki/feature/image/ImageNavigationHandler.java b/src/main/java/creator/loki/feature/image/listener/ImageNavigationHandler.java
similarity index 95%
rename from src/main/java/creator/loki/feature/image/ImageNavigationHandler.java
rename to src/main/java/creator/loki/feature/image/listener/ImageNavigationHandler.java
index fda5829..7474299 100644
--- a/src/main/java/creator/loki/feature/image/ImageNavigationHandler.java
+++ b/src/main/java/creator/loki/feature/image/listener/ImageNavigationHandler.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.image;
+package creator.loki.feature.image.listener;
import java.util.List;
@@ -8,6 +8,10 @@ import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import creator.loki.feature.image.service.ImageService;
+import creator.loki.feature.image.service.ImageSession;
+import creator.loki.feature.image.service.ImageSessionManager;
+import creator.loki.feature.image.util.ImageEmbedHelper;
@Singleton
public class ImageNavigationHandler extends ListenerAdapter {
@@ -104,7 +108,6 @@ public class ImageNavigationHandler extends ListenerAdapter {
private List fetchPage(String site, String tags, int apiPage) {
return switch (site) {
case "e621.net" -> imageService.fetchE621(tags, PAGE_FETCH, apiPage);
- case "rule34.xxx" -> imageService.fetchR34(tags, PAGE_FETCH, apiPage);
case "gelbooru.com" -> imageService.fetchGelbooru(tags, PAGE_FETCH, apiPage);
case "yande.re" -> imageService.fetchYandere(tags, PAGE_FETCH, apiPage);
default -> List.of();
diff --git a/src/main/java/creator/loki/feature/image/ImageService.java b/src/main/java/creator/loki/feature/image/service/ImageService.java
similarity index 86%
rename from src/main/java/creator/loki/feature/image/ImageService.java
rename to src/main/java/creator/loki/feature/image/service/ImageService.java
index 6591bff..a62ab6f 100644
--- a/src/main/java/creator/loki/feature/image/ImageService.java
+++ b/src/main/java/creator/loki/feature/image/service/ImageService.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.image;
+package creator.loki.feature.image.service;
import java.io.IOException;
import java.util.ArrayList;
@@ -22,17 +22,11 @@ import org.slf4j.LoggerFactory;
public class ImageService {
private static final Logger logger = LoggerFactory.getLogger(ImageService.class);
private static final String E621_API = "https://e621.net/posts.json";
- private static final String R34_API =
- "https://api.rule34.xxx/index.php?page=dapi&s=post&q=index&json=1";
private final OkHttpClient client;
- private final String r34ApiKey;
- private final String r34UserId;
@Inject
public ImageService(BotConfig config) {
- this.r34ApiKey = config.getR34ApiKey();
- this.r34UserId = config.getR34UserId();
this.client =
new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
@@ -81,19 +75,6 @@ public class ImageService {
}
}
- public List fetchR34(String tags, int limit) {
- return fetchR34(tags, limit, 1);
- }
-
- public List fetchR34(String tags, int limit, int page) {
- int capped = Math.min(limit, 100);
- String url = R34_API + "&tags=" + encodeTags(tags) + "&limit=" + capped + "&pid=" + (page - 1);
- if (!r34ApiKey.isEmpty() && !r34UserId.isEmpty()) {
- url += "&api_key=" + r34ApiKey + "&user_id=" + r34UserId;
- }
- return fetchBooruJson(url, limit);
- }
-
public List fetchGelbooru(String tags, int limit) {
return fetchGelbooru(tags, limit, 1);
}
diff --git a/src/main/java/creator/loki/feature/image/ImageSession.java b/src/main/java/creator/loki/feature/image/service/ImageSession.java
similarity index 98%
rename from src/main/java/creator/loki/feature/image/ImageSession.java
rename to src/main/java/creator/loki/feature/image/service/ImageSession.java
index ace72fb..9cdc81b 100644
--- a/src/main/java/creator/loki/feature/image/ImageSession.java
+++ b/src/main/java/creator/loki/feature/image/service/ImageSession.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.image;
+package creator.loki.feature.image.service;
import java.util.ArrayList;
import java.util.List;
diff --git a/src/main/java/creator/loki/feature/image/ImageSessionManager.java b/src/main/java/creator/loki/feature/image/service/ImageSessionManager.java
similarity index 96%
rename from src/main/java/creator/loki/feature/image/ImageSessionManager.java
rename to src/main/java/creator/loki/feature/image/service/ImageSessionManager.java
index 754ed75..4ce6951 100644
--- a/src/main/java/creator/loki/feature/image/ImageSessionManager.java
+++ b/src/main/java/creator/loki/feature/image/service/ImageSessionManager.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.image;
+package creator.loki.feature.image.service;
import java.awt.Color;
import java.util.Map;
diff --git a/src/main/java/creator/loki/feature/image/ImageCommandRegistrar.java b/src/main/java/creator/loki/feature/image/util/ImageCommandRegistrar.java
similarity index 67%
rename from src/main/java/creator/loki/feature/image/ImageCommandRegistrar.java
rename to src/main/java/creator/loki/feature/image/util/ImageCommandRegistrar.java
index 2b2851a..6e5cb51 100644
--- a/src/main/java/creator/loki/feature/image/ImageCommandRegistrar.java
+++ b/src/main/java/creator/loki/feature/image/util/ImageCommandRegistrar.java
@@ -1,13 +1,14 @@
-package creator.loki.feature.image;
+package creator.loki.feature.image.util;
import com.google.inject.Inject;
import creator.loki.core.registry.CommandRegistrar;
import creator.loki.core.registry.CommandRegistry;
-import creator.loki.feature.image.commands.E621Command;
-import creator.loki.feature.image.commands.E621RandomCommand;
-import creator.loki.feature.image.commands.GelbooruCommand;
-import creator.loki.feature.image.commands.R34Command;
-import creator.loki.feature.image.commands.YandereCommand;
+import creator.loki.feature.image.commands.booru.GelbooruCommand;
+import creator.loki.feature.image.commands.booru.YandereCommand;
+import creator.loki.feature.image.commands.e621.E621Command;
+import creator.loki.feature.image.commands.e621.E621RandomCommand;
+import creator.loki.feature.image.service.ImageService;
+import creator.loki.feature.image.service.ImageSessionManager;
public class ImageCommandRegistrar implements CommandRegistrar {
private final ImageService imageService;
@@ -23,7 +24,6 @@ public class ImageCommandRegistrar implements CommandRegistrar {
public void register(CommandRegistry registry) {
registry.register(new E621Command(imageService, sessionManager));
registry.register(new E621RandomCommand(imageService, sessionManager));
- registry.register(new R34Command(imageService, sessionManager));
registry.register(new GelbooruCommand(imageService, sessionManager));
registry.register(new YandereCommand(imageService, sessionManager));
}
diff --git a/src/main/java/creator/loki/feature/image/ImageEmbedHelper.java b/src/main/java/creator/loki/feature/image/util/ImageEmbedHelper.java
similarity index 97%
rename from src/main/java/creator/loki/feature/image/ImageEmbedHelper.java
rename to src/main/java/creator/loki/feature/image/util/ImageEmbedHelper.java
index 8cf30fa..5365faf 100644
--- a/src/main/java/creator/loki/feature/image/ImageEmbedHelper.java
+++ b/src/main/java/creator/loki/feature/image/util/ImageEmbedHelper.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.image;
+package creator.loki.feature.image.util;
import java.util.ArrayList;
import java.util.List;
@@ -8,6 +8,7 @@ import creator.loki.embed.EmbedFactory;
import net.dv8tion.jda.api.components.actionrow.ActionRow;
import net.dv8tion.jda.api.components.buttons.Button;
import net.dv8tion.jda.api.entities.MessageEmbed;
+import creator.loki.feature.image.service.ImageSession;
public final class ImageEmbedHelper {
diff --git a/src/main/java/creator/loki/feature/level/LevelModule.java b/src/main/java/creator/loki/feature/level/LevelModule.java
index 29cceed..d56322e 100644
--- a/src/main/java/creator/loki/feature/level/LevelModule.java
+++ b/src/main/java/creator/loki/feature/level/LevelModule.java
@@ -9,7 +9,7 @@ import creator.loki.database.Database;
import creator.loki.feature.config.repository.ConfigRepository;
import creator.loki.feature.config.repository.GuildConfigRepository;
import creator.loki.feature.level.commands.LevelCommandRegistrar;
-import creator.loki.feature.level.commands.ResetLevelsCommand;
+import creator.loki.feature.level.commands.admin.ResetLevelsCommand;
import creator.loki.feature.level.domain.XpFormula;
import creator.loki.feature.level.listener.ResetLevelsButtonHandler;
import creator.loki.feature.level.repository.SqlUserStatsRepository;
@@ -17,9 +17,9 @@ import creator.loki.feature.level.repository.UserStatsRepository;
import creator.loki.feature.level.service.LeaderboardService;
import creator.loki.feature.level.service.LevelRoleService;
import creator.loki.feature.level.service.LevelService;
-import creator.loki.feature.level.service.LevelUpNotifier;
-import creator.loki.feature.level.service.MessageCooldownService;
-import creator.loki.feature.level.service.VoiceTracker;
+import creator.loki.feature.level.service.tracker.LevelUpNotifier;
+import creator.loki.feature.level.service.cooldown.MessageCooldownService;
+import creator.loki.feature.level.service.tracker.VoiceTracker;
public class LevelModule extends AbstractModule {
diff --git a/src/main/java/creator/loki/feature/level/commands/LevelCommandRegistrar.java b/src/main/java/creator/loki/feature/level/commands/LevelCommandRegistrar.java
index cd0aa55..33e2b44 100644
--- a/src/main/java/creator/loki/feature/level/commands/LevelCommandRegistrar.java
+++ b/src/main/java/creator/loki/feature/level/commands/LevelCommandRegistrar.java
@@ -9,6 +9,8 @@ import creator.loki.feature.level.service.LeaderboardService;
import creator.loki.feature.level.service.LevelRoleService;
import creator.loki.feature.profile.command.ProfileCommand;
import creator.loki.feature.profile.service.ProfileService;
+import creator.loki.feature.level.commands.admin.ResetLevelsCommand;
+import creator.loki.feature.level.commands.admin.StatsCommand;
public class LevelCommandRegistrar implements CommandRegistrar {
private final LeaderboardService leaderboardService;
diff --git a/src/main/java/creator/loki/feature/level/commands/LevelRoleCommand.java b/src/main/java/creator/loki/feature/level/commands/LevelRoleCommand.java
index 350f9b5..1303427 100644
--- a/src/main/java/creator/loki/feature/level/commands/LevelRoleCommand.java
+++ b/src/main/java/creator/loki/feature/level/commands/LevelRoleCommand.java
@@ -9,6 +9,7 @@ import creator.loki.embed.EmbedTemplates;
import creator.loki.feature.config.repository.ConfigRepository;
import creator.loki.feature.level.service.LevelRoleService;
import net.dv8tion.jda.api.Permission;
+import creator.loki.feature.level.commands.util.LevelRoleFormatter;
public class LevelRoleCommand implements Command {
private final LevelRoleService levelRoleService;
diff --git a/src/main/java/creator/loki/feature/level/commands/ResetLevelsCommand.java b/src/main/java/creator/loki/feature/level/commands/admin/ResetLevelsCommand.java
similarity index 99%
rename from src/main/java/creator/loki/feature/level/commands/ResetLevelsCommand.java
rename to src/main/java/creator/loki/feature/level/commands/admin/ResetLevelsCommand.java
index 01dd418..53c7c4d 100644
--- a/src/main/java/creator/loki/feature/level/commands/ResetLevelsCommand.java
+++ b/src/main/java/creator/loki/feature/level/commands/admin/ResetLevelsCommand.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.level.commands;
+package creator.loki.feature.level.commands.admin;
import java.awt.Color;
diff --git a/src/main/java/creator/loki/feature/level/commands/StatsCommand.java b/src/main/java/creator/loki/feature/level/commands/admin/StatsCommand.java
similarity index 98%
rename from src/main/java/creator/loki/feature/level/commands/StatsCommand.java
rename to src/main/java/creator/loki/feature/level/commands/admin/StatsCommand.java
index 7095aaa..e2c4133 100644
--- a/src/main/java/creator/loki/feature/level/commands/StatsCommand.java
+++ b/src/main/java/creator/loki/feature/level/commands/admin/StatsCommand.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.level.commands;
+package creator.loki.feature.level.commands.admin;
import java.awt.Color;
diff --git a/src/main/java/creator/loki/feature/level/commands/LevelRoleFormatter.java b/src/main/java/creator/loki/feature/level/commands/util/LevelRoleFormatter.java
similarity index 97%
rename from src/main/java/creator/loki/feature/level/commands/LevelRoleFormatter.java
rename to src/main/java/creator/loki/feature/level/commands/util/LevelRoleFormatter.java
index 74b5b0e..c60abdf 100644
--- a/src/main/java/creator/loki/feature/level/commands/LevelRoleFormatter.java
+++ b/src/main/java/creator/loki/feature/level/commands/util/LevelRoleFormatter.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.level.commands;
+package creator.loki.feature.level.commands.util;
import java.util.Map;
import java.util.stream.Collectors;
diff --git a/src/main/java/creator/loki/feature/level/listener/MessageListener.java b/src/main/java/creator/loki/feature/level/listener/MessageListener.java
index 97d247d..6db8042 100644
--- a/src/main/java/creator/loki/feature/level/listener/MessageListener.java
+++ b/src/main/java/creator/loki/feature/level/listener/MessageListener.java
@@ -8,7 +8,7 @@ import creator.loki.core.EventDispatcher;
import creator.loki.feature.economy.service.EconomyService;
import creator.loki.feature.level.domain.LevelUpResult;
import creator.loki.feature.level.service.LevelService;
-import creator.loki.feature.level.service.LevelUpNotifier;
+import creator.loki.feature.level.service.tracker.LevelUpNotifier;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.slf4j.Logger;
diff --git a/src/main/java/creator/loki/feature/level/listener/ResetLevelsButtonHandler.java b/src/main/java/creator/loki/feature/level/listener/ResetLevelsButtonHandler.java
index eefed91..be7ae47 100644
--- a/src/main/java/creator/loki/feature/level/listener/ResetLevelsButtonHandler.java
+++ b/src/main/java/creator/loki/feature/level/listener/ResetLevelsButtonHandler.java
@@ -5,7 +5,7 @@ import java.awt.Color;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import creator.loki.embed.EmbedFactory;
-import creator.loki.feature.level.commands.ResetLevelsCommand;
+import creator.loki.feature.level.commands.admin.ResetLevelsCommand;
import creator.loki.util.LoggerDecorator;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
diff --git a/src/main/java/creator/loki/feature/level/service/LevelService.java b/src/main/java/creator/loki/feature/level/service/LevelService.java
index d527d28..146ce54 100644
--- a/src/main/java/creator/loki/feature/level/service/LevelService.java
+++ b/src/main/java/creator/loki/feature/level/service/LevelService.java
@@ -5,6 +5,7 @@ import creator.loki.feature.level.domain.LevelUpResult;
import creator.loki.feature.level.domain.UserStats;
import creator.loki.feature.level.domain.XpFormula;
import creator.loki.feature.level.repository.UserStatsRepository;
+import creator.loki.feature.level.service.cooldown.MessageCooldownService;
/**
* Сервис для управления системой уровней Рефакторинг LevelSystem - только бизнес-логика начисления
diff --git a/src/main/java/creator/loki/feature/level/service/MessageCooldownService.java b/src/main/java/creator/loki/feature/level/service/cooldown/MessageCooldownService.java
similarity index 96%
rename from src/main/java/creator/loki/feature/level/service/MessageCooldownService.java
rename to src/main/java/creator/loki/feature/level/service/cooldown/MessageCooldownService.java
index 2d312a0..7fc8a36 100644
--- a/src/main/java/creator/loki/feature/level/service/MessageCooldownService.java
+++ b/src/main/java/creator/loki/feature/level/service/cooldown/MessageCooldownService.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.level.service;
+package creator.loki.feature.level.service.cooldown;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
diff --git a/src/main/java/creator/loki/feature/level/service/LevelUpNotifier.java b/src/main/java/creator/loki/feature/level/service/tracker/LevelUpNotifier.java
similarity index 96%
rename from src/main/java/creator/loki/feature/level/service/LevelUpNotifier.java
rename to src/main/java/creator/loki/feature/level/service/tracker/LevelUpNotifier.java
index d7a4700..27a95b9 100644
--- a/src/main/java/creator/loki/feature/level/service/LevelUpNotifier.java
+++ b/src/main/java/creator/loki/feature/level/service/tracker/LevelUpNotifier.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.level.service;
+package creator.loki.feature.level.service.tracker;
import java.awt.Color;
@@ -11,6 +11,8 @@ import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import creator.loki.feature.level.service.LevelRoleService;
+import creator.loki.feature.level.service.LevelService;
/** Уведомления о повышении уровня */
public class LevelUpNotifier {
diff --git a/src/main/java/creator/loki/feature/level/service/VoiceTracker.java b/src/main/java/creator/loki/feature/level/service/tracker/VoiceTracker.java
similarity index 97%
rename from src/main/java/creator/loki/feature/level/service/VoiceTracker.java
rename to src/main/java/creator/loki/feature/level/service/tracker/VoiceTracker.java
index 9e3842e..c04d9b0 100644
--- a/src/main/java/creator/loki/feature/level/service/VoiceTracker.java
+++ b/src/main/java/creator/loki/feature/level/service/tracker/VoiceTracker.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.level.service;
+package creator.loki.feature.level.service.tracker;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -16,6 +16,7 @@ import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import creator.loki.feature.level.service.LevelService;
@Singleton
public class VoiceTracker extends ListenerAdapter implements Lifecycle {
diff --git a/src/main/java/creator/loki/feature/moderation/ModerationModule.java b/src/main/java/creator/loki/feature/moderation/ModerationModule.java
index 2aa8106..a74c6b9 100644
--- a/src/main/java/creator/loki/feature/moderation/ModerationModule.java
+++ b/src/main/java/creator/loki/feature/moderation/ModerationModule.java
@@ -9,9 +9,9 @@ import creator.loki.database.Database;
import creator.loki.feature.config.repository.GuildConfigRepository;
import creator.loki.feature.moderation.repository.ActiveMuteRepository;
import creator.loki.feature.moderation.repository.ModerationCaseRepository;
-import creator.loki.feature.moderation.repository.SqlActiveMuteRepository;
-import creator.loki.feature.moderation.repository.SqlModerationCaseRepository;
-import creator.loki.feature.moderation.repository.SqlWarningRepository;
+import creator.loki.feature.moderation.repository.sql.SqlActiveMuteRepository;
+import creator.loki.feature.moderation.repository.sql.SqlModerationCaseRepository;
+import creator.loki.feature.moderation.repository.sql.SqlWarningRepository;
import creator.loki.feature.moderation.repository.WarningRepository;
public class ModerationModule extends AbstractModule {
diff --git a/src/main/java/creator/loki/feature/moderation/repository/SqlActiveMuteRepository.java b/src/main/java/creator/loki/feature/moderation/repository/sql/SqlActiveMuteRepository.java
similarity index 96%
rename from src/main/java/creator/loki/feature/moderation/repository/SqlActiveMuteRepository.java
rename to src/main/java/creator/loki/feature/moderation/repository/sql/SqlActiveMuteRepository.java
index 4abfb04..2f883fa 100644
--- a/src/main/java/creator/loki/feature/moderation/repository/SqlActiveMuteRepository.java
+++ b/src/main/java/creator/loki/feature/moderation/repository/sql/SqlActiveMuteRepository.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.moderation.repository;
+package creator.loki.feature.moderation.repository.sql;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -10,6 +10,7 @@ import java.util.Optional;
import creator.loki.database.Database;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import creator.loki.feature.moderation.repository.ActiveMuteRepository;
public class SqlActiveMuteRepository implements ActiveMuteRepository {
private static final Logger logger = LoggerFactory.getLogger(SqlActiveMuteRepository.class);
diff --git a/src/main/java/creator/loki/feature/moderation/repository/SqlModerationCaseRepository.java b/src/main/java/creator/loki/feature/moderation/repository/sql/SqlModerationCaseRepository.java
similarity index 96%
rename from src/main/java/creator/loki/feature/moderation/repository/SqlModerationCaseRepository.java
rename to src/main/java/creator/loki/feature/moderation/repository/sql/SqlModerationCaseRepository.java
index 5189729..b5c2964 100644
--- a/src/main/java/creator/loki/feature/moderation/repository/SqlModerationCaseRepository.java
+++ b/src/main/java/creator/loki/feature/moderation/repository/sql/SqlModerationCaseRepository.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.moderation.repository;
+package creator.loki.feature.moderation.repository.sql;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -10,6 +10,7 @@ import java.util.Optional;
import creator.loki.database.Database;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import creator.loki.feature.moderation.repository.ModerationCaseRepository;
public class SqlModerationCaseRepository implements ModerationCaseRepository {
private static final Logger logger = LoggerFactory.getLogger(SqlModerationCaseRepository.class);
diff --git a/src/main/java/creator/loki/feature/moderation/repository/SqlWarningRepository.java b/src/main/java/creator/loki/feature/moderation/repository/sql/SqlWarningRepository.java
similarity index 97%
rename from src/main/java/creator/loki/feature/moderation/repository/SqlWarningRepository.java
rename to src/main/java/creator/loki/feature/moderation/repository/sql/SqlWarningRepository.java
index 296d30d..0758dc6 100644
--- a/src/main/java/creator/loki/feature/moderation/repository/SqlWarningRepository.java
+++ b/src/main/java/creator/loki/feature/moderation/repository/sql/SqlWarningRepository.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.moderation.repository;
+package creator.loki.feature.moderation.repository.sql;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -13,6 +13,7 @@ import java.util.Optional;
import creator.loki.database.Database;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import creator.loki.feature.moderation.repository.WarningRepository;
public class SqlWarningRepository implements WarningRepository {
private static final Logger logger = LoggerFactory.getLogger(SqlWarningRepository.class);
diff --git a/src/main/java/creator/loki/feature/music/listener/PlaySelectHandler.java b/src/main/java/creator/loki/feature/music/listener/PlaySelectHandler.java
index c6cb160..7dc3562 100644
--- a/src/main/java/creator/loki/feature/music/listener/PlaySelectHandler.java
+++ b/src/main/java/creator/loki/feature/music/listener/PlaySelectHandler.java
@@ -6,7 +6,7 @@ import creator.loki.embed.EmbedTemplates;
import creator.loki.feature.music.core.PlayerManager;
import creator.loki.feature.music.core.SearchManager;
import creator.loki.feature.music.play.SearchHandler;
-import creator.loki.util.VoiceHelper;
+import creator.loki.feature.utility.VoiceHelper;
import dev.arbjerg.lavalink.client.player.Track;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
diff --git a/src/main/java/creator/loki/feature/music/play/PlayCommand.java b/src/main/java/creator/loki/feature/music/play/PlayCommand.java
index 3f17958..b711645 100644
--- a/src/main/java/creator/loki/feature/music/play/PlayCommand.java
+++ b/src/main/java/creator/loki/feature/music/play/PlayCommand.java
@@ -10,7 +10,7 @@ import creator.loki.feature.music.core.LavalinkManager;
import creator.loki.feature.music.core.PlayerManager;
import creator.loki.feature.music.core.SearchManager;
import creator.loki.feature.music.manage.GuildMusicManager;
-import creator.loki.util.VoiceHelper;
+import creator.loki.feature.utility.VoiceHelper;
import dev.arbjerg.lavalink.client.player.Track;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
diff --git a/src/main/java/creator/loki/feature/music/repository/FilterRepository.java b/src/main/java/creator/loki/feature/music/repository/FilterRepository.java
new file mode 100644
index 0000000..85e9124
--- /dev/null
+++ b/src/main/java/creator/loki/feature/music/repository/FilterRepository.java
@@ -0,0 +1,65 @@
+package creator.loki.feature.music.repository;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import creator.loki.database.Database;
+import creator.loki.util.LoggerDecorator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import creator.loki.feature.music.manage.FilterState;
+
+@Singleton
+public class FilterRepository {
+ private static final Logger logger = LoggerFactory.getLogger(FilterRepository.class);
+ private final Database db;
+
+ @Inject
+ public FilterRepository(final Database db) {
+ this.db = db;
+ }
+
+ public void save(
+ final String guildId, final int bassboost, final boolean nightcore, final boolean vaporwave) {
+ String sql =
+ "INSERT OR REPLACE INTO music_filters (guild_id, bassboost, nightcore, vaporwave) "
+ + "VALUES (?, ?, ?, ?)";
+ try (PreparedStatement stmt = db.prepare(sql)) {
+ stmt.setString(1, guildId);
+ stmt.setInt(2, bassboost);
+ stmt.setInt(3, nightcore ? 1 : 0);
+ stmt.setInt(4, vaporwave ? 1 : 0);
+ stmt.executeUpdate();
+ } catch (SQLException e) {
+ LoggerDecorator.error(logger, "Error saving filter state for guild " + guildId, e);
+ }
+ }
+
+ public FilterState load(final String guildId) {
+ String sql = "SELECT bassboost, nightcore, vaporwave FROM music_filters WHERE guild_id = ?";
+ try (PreparedStatement stmt = db.prepare(sql)) {
+ stmt.setString(1, guildId);
+ try (ResultSet rs = stmt.executeQuery()) {
+ if (rs.next()) { return new FilterState(rs.getInt("bassboost"), rs.getInt("nightcore") == 1, rs.getInt("vaporwave") == 1); }
+ }
+ } catch (SQLException e) {
+ LoggerDecorator.error(logger, "Error loading filter state for guild " + guildId, e);
+ }
+ return new FilterState(0, false, false);
+ }
+
+ public void delete(final String guildId) {
+ String sql = "DELETE FROM music_filters WHERE guild_id = ?";
+ try (PreparedStatement stmt = db.prepare(sql)) {
+ stmt.setString(1, guildId);
+ stmt.executeUpdate();
+ } catch (SQLException e) {
+ LoggerDecorator.error(logger, "Error deleting filter state for guild " + guildId, e);
+ }
+ }
+
+ public record FilterState(int bassboost, boolean nightcore, boolean vaporwave) {}
+}
diff --git a/src/main/java/creator/loki/feature/radio/RadioModule.java b/src/main/java/creator/loki/feature/radio/RadioModule.java
index bc9c48a..a70a956 100644
--- a/src/main/java/creator/loki/feature/radio/RadioModule.java
+++ b/src/main/java/creator/loki/feature/radio/RadioModule.java
@@ -4,6 +4,7 @@ import com.google.inject.AbstractModule;
import com.google.inject.Singleton;
import com.google.inject.multibindings.Multibinder;
import creator.loki.core.registry.CommandRegistrar;
+import creator.loki.feature.radio.service.RadioManager;
public class RadioModule extends AbstractModule {
@Override
diff --git a/src/main/java/creator/loki/feature/radio/commands/RadioCommand.java b/src/main/java/creator/loki/feature/radio/commands/RadioCommand.java
index 903bbaf..4e2c2d0 100644
--- a/src/main/java/creator/loki/feature/radio/commands/RadioCommand.java
+++ b/src/main/java/creator/loki/feature/radio/commands/RadioCommand.java
@@ -6,7 +6,7 @@ import com.google.inject.Inject;
import creator.loki.command.Command;
import creator.loki.command.CommandContext;
import creator.loki.embed.EmbedTemplates;
-import creator.loki.feature.radio.RadioManager;
+import creator.loki.feature.radio.service.RadioManager;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
diff --git a/src/main/java/creator/loki/feature/radio/RadioBotListener.java b/src/main/java/creator/loki/feature/radio/listener/RadioBotListener.java
similarity index 97%
rename from src/main/java/creator/loki/feature/radio/RadioBotListener.java
rename to src/main/java/creator/loki/feature/radio/listener/RadioBotListener.java
index 3355042..745646a 100644
--- a/src/main/java/creator/loki/feature/radio/RadioBotListener.java
+++ b/src/main/java/creator/loki/feature/radio/listener/RadioBotListener.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.radio;
+package creator.loki.feature.radio.listener;
import java.util.List;
@@ -11,6 +11,8 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import creator.loki.feature.radio.service.RadioManager;
+import creator.loki.feature.radio.service.RadioManager;
public class RadioBotListener extends ListenerAdapter {
private static final Logger logger = LoggerFactory.getLogger(RadioBotListener.class);
diff --git a/src/main/java/creator/loki/feature/radio/RadioManager.java b/src/main/java/creator/loki/feature/radio/service/RadioManager.java
similarity index 99%
rename from src/main/java/creator/loki/feature/radio/RadioManager.java
rename to src/main/java/creator/loki/feature/radio/service/RadioManager.java
index 56d251a..d48775d 100644
--- a/src/main/java/creator/loki/feature/radio/RadioManager.java
+++ b/src/main/java/creator/loki/feature/radio/service/RadioManager.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.radio;
+package creator.loki.feature.radio.service;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
diff --git a/src/main/java/creator/loki/feature/rating/commands/body/FatCommand.java b/src/main/java/creator/loki/feature/rating/commands/body/FatCommand.java
new file mode 100644
index 0000000..cbfd4bf
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/body/FatCommand.java
@@ -0,0 +1,71 @@
+package creator.loki.feature.rating.commands.body;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import creator.loki.feature.rating.config.RatingConfig;
+import creator.loki.feature.rating.config.RatingLevel;
+import net.dv8tion.jda.api.entities.Member;
+
+public class FatCommand implements Command {
+
+ private final RatingService ratingService;
+
+ @Inject
+ public FatCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "fat";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Проверка на жирность (результат всегда одинаковый)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "fat [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "fat")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ int fatLevel = ratingService.getDeterministicValue(target.getId(), 999, 0, 100);
+ StringBuilder bar = new StringBuilder();
+ int filled = fatLevel / 10;
+ for (int i = 0; i < filled; i++) { bar.append("🟩"); }
+
+ for (int i = filled; i < 10; i++) { bar.append("⬜"); }
+
+ RatingLevel level = RatingLevel.findLevel(fatLevel, RatingConfig.getFatLevels());
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("🐷 Fat Метр")
+ .withDescription(target.getAsMention())
+ .addField(
+ "Жирность", bar + "\n**" + fatLevel + "%** - " + level.getComment(), false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(level.getColor())
+ .withFooter("💡 Детерминировано вашим Discord ID")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/rating/commands/body/MustacheCommand.java b/src/main/java/creator/loki/feature/rating/commands/body/MustacheCommand.java
new file mode 100644
index 0000000..e23f869
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/body/MustacheCommand.java
@@ -0,0 +1,79 @@
+package creator.loki.feature.rating.commands.body;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import creator.loki.feature.rating.config.RatingConfig;
+import creator.loki.feature.rating.config.RatingLevel;
+import net.dv8tion.jda.api.entities.Member;
+
+public class MustacheCommand implements Command {
+
+ private final RatingService ratingService;
+
+ @Inject
+ public MustacheCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "mustache";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Проверка на усатость (результат всегда одинаковый)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "mustache [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "mustache")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ int mustacheLevel;
+ if (target.getUser().isBot() || target.getId().equals("1414975197269987471")) {
+ mustacheLevel = 0;
+ } else if (target.getId().equals("678283217094180915")) {
+ mustacheLevel = 1000;
+ } else {
+ mustacheLevel = ratingService.getDeterministicValue(target.getId(), 888, 0, 100);
+ }
+
+ StringBuilder bar = new StringBuilder();
+ int filled = Math.min(mustacheLevel / 10, 10);
+ for (int i = 0; i < filled; i++) { bar.append("🧔"); }
+
+ for (int i = filled; i < 10; i++) { bar.append("⬜"); }
+
+ RatingLevel level = RatingConfig.findLevel(mustacheLevel, "mustache");
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("🧔 Mustache Метр")
+ .withDescription(target.getAsMention())
+ .addField(
+ "Усатость", bar + "\n**" + mustacheLevel + "%** - " + level.getComment(), false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(level.getColor())
+ .withFooter("💡 Детерминировано вашим Discord ID")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/rating/commands/body/PpCommand.java b/src/main/java/creator/loki/feature/rating/commands/body/PpCommand.java
new file mode 100644
index 0000000..1c9295f
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/body/PpCommand.java
@@ -0,0 +1,80 @@
+package creator.loki.feature.rating.commands.body;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import creator.loki.feature.rating.config.RatingConfig;
+import creator.loki.feature.rating.config.RatingLevel;
+import net.dv8tion.jda.api.entities.Member;
+
+public class PpCommand implements Command {
+
+ private final RatingService ratingService;
+
+ @Inject
+ public PpCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "pp";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Измеритель pp (результат всегда одинаковый)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "pp [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "pp")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ if (target.getUser().isBot()) { context.getChannel().sendMessage("❌ У ботов нет pp!").queue(); return; }
+
+ int size;
+ if (target.getId().equals("1414975197269987471")) {
+ size = 100;
+ } else {
+ size = ratingService.getDeterministicValue(target.getId(), 6969, 0, 30);
+ }
+
+ StringBuilder ppVisual = new StringBuilder("8");
+ for (int i = 0; i < size; i++) { ppVisual.append("="); }
+
+ ppVisual.append("D");
+
+ RatingLevel level = RatingConfig.findLevel(size, "pp");
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("🍆 PP Размер")
+ .withDescription(target.getAsMention())
+ .addField(
+ "Размер",
+ "```" + ppVisual + "```\n**" + size + " см** - " + level.getComment(),
+ false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(level.getColor())
+ .withFooter("💡 Детерминировано вашим Discord ID")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/rating/commands/fortune/AuraCommand.java b/src/main/java/creator/loki/feature/rating/commands/fortune/AuraCommand.java
new file mode 100644
index 0000000..746dfcd
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/fortune/AuraCommand.java
@@ -0,0 +1,91 @@
+package creator.loki.feature.rating.commands.fortune;
+
+import java.awt.Color;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import net.dv8tion.jda.api.entities.Member;
+
+public class AuraCommand implements Command {
+
+ private final RatingService ratingService;
+
+ @Inject
+ public AuraCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "aura";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Проверить свою ауру (результат всегда одинаковый)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "aura [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "aura")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ int aura = ratingService.getDeterministicValue(target.getId(), 999, -50, 100);
+ String emoji;
+ Color color;
+ if (aura >= 80) {
+ emoji = "🌟";
+ color = new Color(255, 215, 0);
+ } else if (aura >= 50) {
+ emoji = "✨";
+ color = new Color(100, 255, 150);
+ } else if (aura >= 20) {
+ emoji = "😐";
+ color = new Color(52, 152, 219);
+ } else if (aura >= 0) {
+ emoji = "💫";
+ color = new Color(128, 128, 128);
+ } else if (aura >= -25) {
+ emoji = "🌑";
+ color = new Color(231, 76, 60);
+ } else {
+ emoji = "💀";
+ color = new Color(100, 0, 0);
+ }
+
+ StringBuilder bar = new StringBuilder();
+ int filled = Math.max(0, Math.min(10, (aura + 50) / 15));
+ for (int i = 0; i < filled; i++) { bar.append("✧"); }
+
+ for (int i = filled; i < 10; i++) { bar.append("◇"); }
+
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("✨ Аура")
+ .withDescription(target.getAsMention())
+ .addField("Сила", emoji + " **" + aura + "**\n" + bar, false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(color)
+ .withFooter("💡 Детерминировано вашим Discord ID")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/rating/commands/fortune/LuckCommand.java b/src/main/java/creator/loki/feature/rating/commands/fortune/LuckCommand.java
new file mode 100644
index 0000000..b06abb6
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/fortune/LuckCommand.java
@@ -0,0 +1,70 @@
+package creator.loki.feature.rating.commands.fortune;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import creator.loki.feature.rating.config.RatingConfig;
+import creator.loki.feature.rating.config.RatingLevel;
+import net.dv8tion.jda.api.entities.Member;
+
+public class LuckCommand implements Command {
+
+ private final RatingService ratingService;
+
+ @Inject
+ public LuckCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "luck";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Проверить свою удачу (результат всегда одинаковый)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "luck [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "luck")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ int luck = ratingService.getDeterministicValue(target.getId(), 777, 0, 100);
+ StringBuilder bar = new StringBuilder();
+ int filled = luck / 10;
+ for (int i = 0; i < filled; i++) { bar.append("🍀"); }
+
+ for (int i = filled; i < 10; i++) { bar.append("⬜"); }
+
+ RatingLevel level = RatingLevel.findLevel(luck, RatingConfig.getLuckLevels());
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("🍀 Удача")
+ .withDescription(target.getAsMention())
+ .addField("Везение", bar + "\n**" + luck + "%** - " + level.getComment(), false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(level.getColor())
+ .withFooter("💡 Детерминировано вашим Discord ID")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/rating/commands/fortune/RizzCommand.java b/src/main/java/creator/loki/feature/rating/commands/fortune/RizzCommand.java
new file mode 100644
index 0000000..fb1f5eb
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/fortune/RizzCommand.java
@@ -0,0 +1,70 @@
+package creator.loki.feature.rating.commands.fortune;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import creator.loki.feature.rating.config.RatingConfig;
+import creator.loki.feature.rating.config.RatingLevel;
+import net.dv8tion.jda.api.entities.Member;
+
+public class RizzCommand implements Command {
+
+ private final RatingService ratingService;
+
+ @Inject
+ public RizzCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "rizz";
+ }
+
+ @Override
+ public String getDescription() {
+ return "На сколько у тебя ризз (харизма)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "rizz [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "rizz")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ int rizz = ratingService.getDeterministicValue(target.getId(), 555, 0, 100);
+ StringBuilder bar = new StringBuilder();
+ int filled = rizz / 10;
+ for (int i = 0; i < filled; i++) { bar.append("🗿"); }
+
+ for (int i = filled; i < 10; i++) { bar.append("⬜"); }
+
+ RatingLevel level = RatingLevel.findLevel(rizz, RatingConfig.getRizzLevels());
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("🗿 Rizz Метр")
+ .withDescription(target.getAsMention())
+ .addField("Харизма", bar + "\n**" + rizz + "%** - " + level.getComment(), false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(level.getColor())
+ .withFooter("💡 Детерминировано вашим Discord ID")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/rating/commands/mind/BoykisserCommand.java b/src/main/java/creator/loki/feature/rating/commands/mind/BoykisserCommand.java
new file mode 100644
index 0000000..94d5148
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/mind/BoykisserCommand.java
@@ -0,0 +1,73 @@
+package creator.loki.feature.rating.commands.mind;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import creator.loki.feature.rating.config.RatingConfig;
+import creator.loki.feature.rating.config.RatingLevel;
+import net.dv8tion.jda.api.entities.Member;
+
+public class BoykisserCommand implements Command {
+
+ private final RatingService ratingService;
+
+ @Inject
+ public BoykisserCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "boykisser";
+ }
+
+ @Override
+ public String getDescription() {
+ return "На сколько ты boykisser (результат всегда одинаковый)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "boykisser [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "boykisser")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ if (target.getUser().isBot()) { context.getChannel().sendMessage("❌ Боты не целуют мальчиков!").queue(); return; }
+
+ int boykisserLevel = ratingService.getDeterministicValue(target.getId(), 777, 0, 100);
+ StringBuilder bar = new StringBuilder();
+ int filled = boykisserLevel / 10;
+ for (int i = 0; i < filled; i++) { bar.append("💋"); }
+
+ for (int i = filled; i < 10; i++) { bar.append("⬜"); }
+
+ RatingLevel level = RatingLevel.findLevel(boykisserLevel, RatingConfig.getBoykisserLevels());
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("💋 Boykisser Метр")
+ .withDescription(target.getAsMention())
+ .addField(
+ "Уровень", bar + "\n**" + boykisserLevel + "%** - " + level.getComment(), false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(level.getColor())
+ .withFooter("💡 Детерминировано вашим Discord ID")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/rating/commands/mind/GayCommand.java b/src/main/java/creator/loki/feature/rating/commands/mind/GayCommand.java
new file mode 100644
index 0000000..5b51b21
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/mind/GayCommand.java
@@ -0,0 +1,72 @@
+package creator.loki.feature.rating.commands.mind;
+
+import java.awt.Color;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import net.dv8tion.jda.api.entities.Member;
+
+public class GayCommand implements Command {
+
+ private final RatingService ratingService;
+
+ @Inject
+ public GayCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "gay";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Гей-метр (результат всегда одинаковый)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "gay [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "gay")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ if (target.getUser().isBot()) { context.getChannel().sendMessage("❌ Боты не имеют ориентации!").queue(); return; }
+
+ int gayLevel = ratingService.getDeterministicValue(target.getId(), 456, 0, 100);
+ String[] rainbow = {"🟥", "🟧", "🟨", "🟩", "🟦", "🟪"};
+ StringBuilder bar = new StringBuilder();
+ int filled = Math.min(gayLevel / 17 + 1, 6);
+ for (int i = 0; i < filled; i++) { bar.append(rainbow[i]); }
+
+ for (int i = filled; i < 6; i++) { bar.append("⬜"); }
+
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("🏳️🌈 Гей-метр")
+ .withDescription(target.getAsMention())
+ .addField("Уровень", bar + "\n**" + gayLevel + "%**", false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(new Color(255, 0, 255))
+ .withFooter("💡 Это просто мем, не воспринимайте серьезно")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/rating/commands/mind/IqCommand.java b/src/main/java/creator/loki/feature/rating/commands/mind/IqCommand.java
new file mode 100644
index 0000000..3158003
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/mind/IqCommand.java
@@ -0,0 +1,72 @@
+package creator.loki.feature.rating.commands.mind;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import creator.loki.feature.rating.config.RatingConfig;
+import creator.loki.feature.rating.config.RatingLevel;
+import net.dv8tion.jda.api.entities.Member;
+
+public class IqCommand implements Command {
+
+ private final RatingService ratingService;
+
+ @Inject
+ public IqCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "iq";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Тест IQ (результат всегда одинаковый)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "iq [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "iq")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ int iq;
+ if (target.getUser().isBot()) {
+ iq = 9000;
+ } else if (target.getId().equals("1414975197269987471")) {
+ iq = 1000;
+ } else {
+ iq = ratingService.getDeterministicValue(target.getId(), 123, 0, 140);
+ }
+
+ RatingLevel level = RatingConfig.findLevel(iq, "iq");
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("🧠 Тест IQ")
+ .withDescription("Результат для " + target.getAsMention())
+ .addField("IQ Уровень", "**" + iq + "** - " + level.getComment(), false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(level.getColor())
+ .withFooter("💡 Научно доказано вашим ID")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/rating/commands/vibe/GlazeCommand.java b/src/main/java/creator/loki/feature/rating/commands/vibe/GlazeCommand.java
new file mode 100644
index 0000000..e959312
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/vibe/GlazeCommand.java
@@ -0,0 +1,69 @@
+package creator.loki.feature.rating.commands.vibe;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import creator.loki.feature.rating.config.RatingConfig;
+import creator.loki.feature.rating.config.RatingLevel;
+import net.dv8tion.jda.api.entities.Member;
+
+public class GlazeCommand implements Command {
+ private final RatingService ratingService;
+
+ @Inject
+ public GlazeCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "glaze";
+ }
+
+ @Override
+ public String getDescription() {
+ return "На сколько ты глазированный (результат всегда одинаковый)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "glaze [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "glaze")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ int level = ratingService.getDeterministicValue(target.getId(), 333, 0, 100);
+ StringBuilder bar = new StringBuilder();
+ int filled = level / 10;
+ for (int i = 0; i < filled; i++) { bar.append("🍩"); }
+
+ for (int i = filled; i < 10; i++) { bar.append("⬜"); }
+
+ RatingLevel rl = RatingLevel.findLevel(level, RatingConfig.getGlazeLevels());
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("🍩 Глазурь-метр")
+ .withDescription(target.getAsMention())
+ .addField("Глазурь", bar + "\n**" + level + "%** - " + rl.getComment(), false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(rl.getColor())
+ .withFooter("💡 Детерминировано вашим Discord ID")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/rating/commands/vibe/GoonCommand.java b/src/main/java/creator/loki/feature/rating/commands/vibe/GoonCommand.java
new file mode 100644
index 0000000..b0cf0ea
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/vibe/GoonCommand.java
@@ -0,0 +1,72 @@
+package creator.loki.feature.rating.commands.vibe;
+
+import java.awt.Color;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import net.dv8tion.jda.api.entities.Member;
+
+public class GoonCommand implements Command {
+ private final RatingService ratingService;
+
+ @Inject
+ public GoonCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "goon";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Гуон-детектор (результат всегда одинаковый)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "goon [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "goon")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ int level = ratingService.getDeterministicValue(target.getId(), 444, 0, 100);
+ StringBuilder bar = new StringBuilder();
+ int filled = level / 10;
+ for (int i = 0; i < filled; i++) { bar.append("💀"); }
+
+ for (int i = filled; i < 10; i++) { bar.append("⬜"); }
+
+ Color color =
+ level >= 70
+ ? new Color(180, 0, 0)
+ : level >= 40 ? new Color(128, 0, 128) : new Color(100, 100, 100);
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("💀 Goon-детектор")
+ .withDescription(target.getAsMention())
+ .addField("Уровень", bar + "\n**" + level + "%**", false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(color)
+ .withFooter("💡 Детерминировано вашим Discord ID")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/rating/commands/vibe/SimpCommand.java b/src/main/java/creator/loki/feature/rating/commands/vibe/SimpCommand.java
new file mode 100644
index 0000000..9391e21
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/vibe/SimpCommand.java
@@ -0,0 +1,69 @@
+package creator.loki.feature.rating.commands.vibe;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import creator.loki.feature.rating.config.RatingConfig;
+import creator.loki.feature.rating.config.RatingLevel;
+import net.dv8tion.jda.api.entities.Member;
+
+public class SimpCommand implements Command {
+ private final RatingService ratingService;
+
+ @Inject
+ public SimpCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "simp";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Симп-детектор (результат всегда одинаковый)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "simp [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "simp")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ int level = ratingService.getDeterministicValue(target.getId(), 111, 0, 100);
+ StringBuilder bar = new StringBuilder();
+ int filled = level / 10;
+ for (int i = 0; i < filled; i++) { bar.append("💀"); }
+
+ for (int i = filled; i < 10; i++) { bar.append("⬜"); }
+
+ RatingLevel rl = RatingLevel.findLevel(level, RatingConfig.getSimpLevels());
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("😭 Симп-детектор")
+ .withDescription(target.getAsMention())
+ .addField("Уровень", bar + "\n**" + level + "%** - " + rl.getComment(), false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(rl.getColor())
+ .withFooter("💡 Детерминировано вашим Discord ID")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/rating/commands/vibe/VibeCommand.java b/src/main/java/creator/loki/feature/rating/commands/vibe/VibeCommand.java
new file mode 100644
index 0000000..be82ec8
--- /dev/null
+++ b/src/main/java/creator/loki/feature/rating/commands/vibe/VibeCommand.java
@@ -0,0 +1,69 @@
+package creator.loki.feature.rating.commands.vibe;
+
+import com.google.inject.Inject;
+import creator.loki.command.Command;
+import creator.loki.command.CommandCategories;
+import creator.loki.command.CommandContext;
+import creator.loki.embed.EmbedFactory;
+import creator.loki.feature.entertainment.service.RatingService;
+import creator.loki.feature.rating.config.RatingConfig;
+import creator.loki.feature.rating.config.RatingLevel;
+import net.dv8tion.jda.api.entities.Member;
+
+public class VibeCommand implements Command {
+ private final RatingService ratingService;
+
+ @Inject
+ public VibeCommand(RatingService ratingService) {
+ this.ratingService = ratingService;
+ }
+
+ @Override
+ public String getName() {
+ return "vibe";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Проверить свой вайб (результат всегда одинаковый)";
+ }
+
+ @Override
+ public String getUsage() {
+ return "vibe [@user]";
+ }
+
+ @Override
+ public String getCategory() {
+ return CommandCategories.MEASUREMENTS;
+ }
+
+ @Override
+ public void execute(CommandContext context) {
+ if (!ratingService.checkAndApplyCooldown(context, "vibe")) { return; }
+
+ Member target = ratingService.resolveTarget(context);
+ if (target == null) { return; }
+
+ int level = ratingService.getDeterministicValue(target.getId(), 222, 0, 100);
+ StringBuilder bar = new StringBuilder();
+ int filled = level / 10;
+ for (int i = 0; i < filled; i++) { bar.append("🎵"); }
+
+ for (int i = filled; i < 10; i++) { bar.append("⬜"); }
+
+ RatingLevel rl = RatingLevel.findLevel(level, RatingConfig.getVibeLevels());
+ context
+ .getChannel()
+ .sendMessageEmbeds(
+ EmbedFactory.create()
+ .withTitle("🎵 Вайб-чек")
+ .withDescription(target.getAsMention())
+ .addField("Вайб", bar + "\n**" + level + "%** - " + rl.getComment(), false)
+ .withThumbnail(target.getUser().getAvatarUrl())
+ .withColor(rl.getColor())
+ .withFooter("💡 Детерминировано вашим Discord ID")
+ .build())
+ .queue();
+ }
+}
diff --git a/src/main/java/creator/loki/feature/reactroles/ReactionRolesCommandRegistrar.java b/src/main/java/creator/loki/feature/reactroles/ReactionRolesCommandRegistrar.java
index 35eb17e..4afe057 100644
--- a/src/main/java/creator/loki/feature/reactroles/ReactionRolesCommandRegistrar.java
+++ b/src/main/java/creator/loki/feature/reactroles/ReactionRolesCommandRegistrar.java
@@ -3,6 +3,8 @@ package creator.loki.feature.reactroles;
import com.google.inject.Inject;
import creator.loki.core.registry.CommandRegistrar;
import creator.loki.core.registry.CommandRegistry;
+import creator.loki.feature.reactroles.commands.ReactionRoleCommand;
+import creator.loki.feature.reactroles.repository.ReactionRoleRepository;
public class ReactionRolesCommandRegistrar implements CommandRegistrar {
private final ReactionRoleRepository repository;
diff --git a/src/main/java/creator/loki/feature/reactroles/ReactionRolesModule.java b/src/main/java/creator/loki/feature/reactroles/ReactionRolesModule.java
index fe82b42..e533e19 100644
--- a/src/main/java/creator/loki/feature/reactroles/ReactionRolesModule.java
+++ b/src/main/java/creator/loki/feature/reactroles/ReactionRolesModule.java
@@ -4,6 +4,8 @@ import com.google.inject.AbstractModule;
import com.google.inject.Singleton;
import com.google.inject.multibindings.Multibinder;
import creator.loki.core.registry.CommandRegistrar;
+import creator.loki.feature.reactroles.listener.ReactionRoleListener;
+import creator.loki.feature.reactroles.repository.ReactionRoleRepository;
public class ReactionRolesModule extends AbstractModule {
@Override
diff --git a/src/main/java/creator/loki/feature/reactroles/ReactionRoleCommand.java b/src/main/java/creator/loki/feature/reactroles/commands/ReactionRoleCommand.java
similarity index 96%
rename from src/main/java/creator/loki/feature/reactroles/ReactionRoleCommand.java
rename to src/main/java/creator/loki/feature/reactroles/commands/ReactionRoleCommand.java
index 6d1e33d..587347f 100644
--- a/src/main/java/creator/loki/feature/reactroles/ReactionRoleCommand.java
+++ b/src/main/java/creator/loki/feature/reactroles/commands/ReactionRoleCommand.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.reactroles;
+package creator.loki.feature.reactroles.commands;
import java.util.List;
@@ -8,6 +8,8 @@ import creator.loki.command.Command;
import creator.loki.command.CommandContext;
import creator.loki.embed.EmbedTemplates;
import net.dv8tion.jda.api.Permission;
+import creator.loki.feature.reactroles.repository.ReactionRoleRepository;
+import creator.loki.feature.reactroles.repository.ReactionRoleRepository;
public class ReactionRoleCommand implements Command {
private final ReactionRoleRepository repository;
diff --git a/src/main/java/creator/loki/feature/reactroles/ReactionRoleListener.java b/src/main/java/creator/loki/feature/reactroles/listener/ReactionRoleListener.java
similarity index 93%
rename from src/main/java/creator/loki/feature/reactroles/ReactionRoleListener.java
rename to src/main/java/creator/loki/feature/reactroles/listener/ReactionRoleListener.java
index 870b9f5..39d2dd3 100644
--- a/src/main/java/creator/loki/feature/reactroles/ReactionRoleListener.java
+++ b/src/main/java/creator/loki/feature/reactroles/listener/ReactionRoleListener.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.reactroles;
+package creator.loki.feature.reactroles.listener;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -10,6 +10,8 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import creator.loki.feature.reactroles.repository.ReactionRoleRepository;
+import creator.loki.feature.reactroles.repository.ReactionRoleRepository;
@Singleton
public class ReactionRoleListener extends ListenerAdapter {
diff --git a/src/main/java/creator/loki/feature/reactroles/ReactionRoleRepository.java b/src/main/java/creator/loki/feature/reactroles/repository/ReactionRoleRepository.java
similarity index 98%
rename from src/main/java/creator/loki/feature/reactroles/ReactionRoleRepository.java
rename to src/main/java/creator/loki/feature/reactroles/repository/ReactionRoleRepository.java
index dfec185..51e5d84 100644
--- a/src/main/java/creator/loki/feature/reactroles/ReactionRoleRepository.java
+++ b/src/main/java/creator/loki/feature/reactroles/repository/ReactionRoleRepository.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.reactroles;
+package creator.loki.feature.reactroles.repository;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
diff --git a/src/main/java/creator/loki/feature/serverstats/ServerStatsService.java b/src/main/java/creator/loki/feature/serverstats/ServerStatsService.java
index dca21a4..aeac7a3 100644
--- a/src/main/java/creator/loki/feature/serverstats/ServerStatsService.java
+++ b/src/main/java/creator/loki/feature/serverstats/ServerStatsService.java
@@ -12,7 +12,7 @@ import java.util.List;
import javax.imageio.ImageIO;
import creator.loki.feature.counter.repository.CounterStatsRepository;
-import creator.loki.feature.counter.service.DailyStats;
+import creator.loki.feature.counter.service.format.DailyStats;
import net.dv8tion.jda.api.OnlineStatus;
import net.dv8tion.jda.api.entities.Guild;
diff --git a/src/main/java/creator/loki/feature/ticket/TicketCommandRegistrar.java b/src/main/java/creator/loki/feature/ticket/TicketCommandRegistrar.java
index f6e454f..cae3ed0 100644
--- a/src/main/java/creator/loki/feature/ticket/TicketCommandRegistrar.java
+++ b/src/main/java/creator/loki/feature/ticket/TicketCommandRegistrar.java
@@ -3,6 +3,7 @@ package creator.loki.feature.ticket;
import com.google.inject.Inject;
import creator.loki.core.registry.CommandRegistrar;
import creator.loki.core.registry.CommandRegistry;
+import creator.loki.feature.ticket.commands.TicketSetupCommand;
public class TicketCommandRegistrar implements CommandRegistrar {
private final TicketSetupCommand ticketSetupCommand;
diff --git a/src/main/java/creator/loki/feature/ticket/TicketModule.java b/src/main/java/creator/loki/feature/ticket/TicketModule.java
index d59cce2..6c519f8 100644
--- a/src/main/java/creator/loki/feature/ticket/TicketModule.java
+++ b/src/main/java/creator/loki/feature/ticket/TicketModule.java
@@ -4,6 +4,8 @@ import com.google.inject.AbstractModule;
import com.google.inject.Singleton;
import com.google.inject.multibindings.Multibinder;
import creator.loki.core.registry.CommandRegistrar;
+import creator.loki.feature.ticket.listener.TicketListener;
+import creator.loki.feature.ticket.repository.TicketRepository;
public class TicketModule extends AbstractModule {
@Override
diff --git a/src/main/java/creator/loki/feature/ticket/TicketSetupCommand.java b/src/main/java/creator/loki/feature/ticket/commands/TicketSetupCommand.java
similarity index 90%
rename from src/main/java/creator/loki/feature/ticket/TicketSetupCommand.java
rename to src/main/java/creator/loki/feature/ticket/commands/TicketSetupCommand.java
index 57399db..937dbd8 100644
--- a/src/main/java/creator/loki/feature/ticket/TicketSetupCommand.java
+++ b/src/main/java/creator/loki/feature/ticket/commands/TicketSetupCommand.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.ticket;
+package creator.loki.feature.ticket.commands;
import com.google.inject.Inject;
import creator.loki.command.Command;
@@ -9,6 +9,8 @@ import net.dv8tion.jda.api.components.buttons.Button;
import net.dv8tion.jda.api.components.actionrow.ActionRow;
import java.awt.Color;
+import creator.loki.feature.ticket.repository.TicketRepository;
+import creator.loki.feature.ticket.repository.TicketRepository;
public class TicketSetupCommand implements Command {
private final TicketRepository ticketRepository;
diff --git a/src/main/java/creator/loki/feature/ticket/TicketListener.java b/src/main/java/creator/loki/feature/ticket/listener/TicketListener.java
similarity index 96%
rename from src/main/java/creator/loki/feature/ticket/TicketListener.java
rename to src/main/java/creator/loki/feature/ticket/listener/TicketListener.java
index a39bb37..dd6a6db 100644
--- a/src/main/java/creator/loki/feature/ticket/TicketListener.java
+++ b/src/main/java/creator/loki/feature/ticket/listener/TicketListener.java
@@ -1,8 +1,8 @@
-package creator.loki.feature.ticket;
+package creator.loki.feature.ticket.listener;
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import creator.loki.feature.ticket.TicketRepository.Ticket;
+import creator.loki.feature.ticket.repository.TicketRepository.Ticket;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
@@ -18,6 +18,7 @@ import net.dv8tion.jda.api.components.actionrow.ActionRow;
import java.awt.Color;
import java.util.EnumSet;
+import creator.loki.feature.ticket.repository.TicketRepository;
@Singleton
public class TicketListener extends ListenerAdapter {
diff --git a/src/main/java/creator/loki/feature/ticket/TicketRepository.java b/src/main/java/creator/loki/feature/ticket/repository/TicketRepository.java
similarity index 98%
rename from src/main/java/creator/loki/feature/ticket/TicketRepository.java
rename to src/main/java/creator/loki/feature/ticket/repository/TicketRepository.java
index c7e0148..6ebe19c 100644
--- a/src/main/java/creator/loki/feature/ticket/TicketRepository.java
+++ b/src/main/java/creator/loki/feature/ticket/repository/TicketRepository.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.ticket;
+package creator.loki.feature.ticket.repository;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
diff --git a/src/main/java/creator/loki/feature/entertainment/commands/random/ChoiceOptionParser.java b/src/main/java/creator/loki/feature/utility/ChoiceOptionParser.java
similarity index 97%
rename from src/main/java/creator/loki/feature/entertainment/commands/random/ChoiceOptionParser.java
rename to src/main/java/creator/loki/feature/utility/ChoiceOptionParser.java
index 703e021..035a018 100644
--- a/src/main/java/creator/loki/feature/entertainment/commands/random/ChoiceOptionParser.java
+++ b/src/main/java/creator/loki/feature/utility/ChoiceOptionParser.java
@@ -1,4 +1,4 @@
-package creator.loki.feature.entertainment.commands.random;
+package creator.loki.feature.utility;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/src/main/java/creator/loki/util/VoiceHelper.java b/src/main/java/creator/loki/feature/utility/VoiceHelper.java
similarity index 98%
rename from src/main/java/creator/loki/util/VoiceHelper.java
rename to src/main/java/creator/loki/feature/utility/VoiceHelper.java
index 9740df4..0fec7c0 100644
--- a/src/main/java/creator/loki/util/VoiceHelper.java
+++ b/src/main/java/creator/loki/feature/utility/VoiceHelper.java
@@ -1,4 +1,4 @@
-package creator.loki.util;
+package creator.loki.feature.utility;
import java.util.concurrent.TimeUnit;
import java.util.function.BooleanSupplier;
diff --git a/src/test/java/creator/loki/core/registry/SmokeCommandRegistrationTest.java b/src/test/java/creator/loki/core/registry/SmokeCommandRegistrationTest.java
index 3728fe0..36888c2 100644
--- a/src/test/java/creator/loki/core/registry/SmokeCommandRegistrationTest.java
+++ b/src/test/java/creator/loki/core/registry/SmokeCommandRegistrationTest.java
@@ -17,7 +17,7 @@ import creator.loki.feature.economy.service.*;
import creator.loki.feature.entertainment.EntertainmentCommandRegistrar;
import creator.loki.feature.entertainment.service.RatingService;
import creator.loki.feature.level.commands.LevelCommandRegistrar;
-import creator.loki.feature.level.commands.ResetLevelsCommand;
+import creator.loki.feature.level.commands.admin.ResetLevelsCommand;
import creator.loki.feature.level.repository.UserStatsRepository;
import creator.loki.feature.level.service.LeaderboardService;
import creator.loki.feature.level.service.LevelRoleService;
@@ -44,6 +44,9 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
+import creator.loki.feature.economy.service.game.BlackjackService;
+import creator.loki.feature.economy.service.game.JobService;
+import creator.loki.feature.economy.service.game.SlotService;
@ExtendWith(MockitoExtension.class)
class SmokeCommandRegistrationTest {
diff --git a/src/test/java/creator/loki/feature/economy/service/BlackjackServiceTest.java b/src/test/java/creator/loki/feature/economy/service/BlackjackServiceTest.java
index acddbfa..a57b915 100644
--- a/src/test/java/creator/loki/feature/economy/service/BlackjackServiceTest.java
+++ b/src/test/java/creator/loki/feature/economy/service/BlackjackServiceTest.java
@@ -15,6 +15,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
+import creator.loki.feature.economy.service.game.BlackjackService;
@ExtendWith(MockitoExtension.class)
class BlackjackServiceTest {
diff --git a/src/test/java/creator/loki/feature/economy/service/JobServiceTest.java b/src/test/java/creator/loki/feature/economy/service/JobServiceTest.java
index 8351bd3..1b7f039 100644
--- a/src/test/java/creator/loki/feature/economy/service/JobServiceTest.java
+++ b/src/test/java/creator/loki/feature/economy/service/JobServiceTest.java
@@ -17,6 +17,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
+import creator.loki.feature.economy.service.game.JobService;
@ExtendWith(MockitoExtension.class)
class JobServiceTest {
diff --git a/src/test/java/creator/loki/feature/economy/service/SlotServiceTest.java b/src/test/java/creator/loki/feature/economy/service/SlotServiceTest.java
index d68897e..ff5471f 100644
--- a/src/test/java/creator/loki/feature/economy/service/SlotServiceTest.java
+++ b/src/test/java/creator/loki/feature/economy/service/SlotServiceTest.java
@@ -15,6 +15,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
+import creator.loki.feature.economy.service.game.SlotService;
@ExtendWith(MockitoExtension.class)
class SlotServiceTest {
diff --git a/src/test/java/creator/loki/feature/entertainment/commands/ChoiceOptionParserTest.java b/src/test/java/creator/loki/feature/entertainment/commands/ChoiceOptionParserTest.java
index 2028b53..b9521ed 100644
--- a/src/test/java/creator/loki/feature/entertainment/commands/ChoiceOptionParserTest.java
+++ b/src/test/java/creator/loki/feature/entertainment/commands/ChoiceOptionParserTest.java
@@ -4,7 +4,7 @@ import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
-import creator.loki.feature.entertainment.commands.random.ChoiceOptionParser;
+import creator.loki.feature.utility.ChoiceOptionParser;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
diff --git a/src/test/java/creator/loki/feature/level/service/LevelServiceTest.java b/src/test/java/creator/loki/feature/level/service/LevelServiceTest.java
index 8dd3071..593e2ee 100644
--- a/src/test/java/creator/loki/feature/level/service/LevelServiceTest.java
+++ b/src/test/java/creator/loki/feature/level/service/LevelServiceTest.java
@@ -17,6 +17,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
+import creator.loki.feature.level.service.cooldown.MessageCooldownService;
@ExtendWith(MockitoExtension.class)
class LevelServiceTest {
diff --git a/src/test/java/creator/loki/feature/level/service/MessageCooldownServiceTest.java b/src/test/java/creator/loki/feature/level/service/MessageCooldownServiceTest.java
index eb88365..3d492e9 100644
--- a/src/test/java/creator/loki/feature/level/service/MessageCooldownServiceTest.java
+++ b/src/test/java/creator/loki/feature/level/service/MessageCooldownServiceTest.java
@@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
+import creator.loki.feature.level.service.cooldown.MessageCooldownService;
@ExtendWith(MockitoExtension.class)
class MessageCooldownServiceTest {
diff --git a/src/test/java/creator/loki/feature/moderation/repository/ActiveMuteRepositoryTest.java b/src/test/java/creator/loki/feature/moderation/repository/ActiveMuteRepositoryTest.java
index 3f7db65..2c910c7 100644
--- a/src/test/java/creator/loki/feature/moderation/repository/ActiveMuteRepositoryTest.java
+++ b/src/test/java/creator/loki/feature/moderation/repository/ActiveMuteRepositoryTest.java
@@ -14,6 +14,7 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
+import creator.loki.feature.moderation.repository.sql.SqlActiveMuteRepository;
class ActiveMuteRepositoryTest {
private Database database;
diff --git a/src/test/java/creator/loki/feature/moderation/repository/WarningRepositoryTest.java b/src/test/java/creator/loki/feature/moderation/repository/WarningRepositoryTest.java
index cc53511..bad914d 100644
--- a/src/test/java/creator/loki/feature/moderation/repository/WarningRepositoryTest.java
+++ b/src/test/java/creator/loki/feature/moderation/repository/WarningRepositoryTest.java
@@ -14,6 +14,7 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
+import creator.loki.feature.moderation.repository.sql.SqlWarningRepository;
class WarningRepositoryTest {
private Database database;
diff --git a/src/test/java/creator/loki/feature/radio/RadioManagerTest.java b/src/test/java/creator/loki/feature/radio/RadioManagerTest.java
index c052515..924021a 100644
--- a/src/test/java/creator/loki/feature/radio/RadioManagerTest.java
+++ b/src/test/java/creator/loki/feature/radio/RadioManagerTest.java
@@ -6,6 +6,7 @@ import static org.mockito.Mockito.*;
import creator.loki.feature.music.repository.QueueRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import creator.loki.feature.radio.service.RadioManager;
class RadioManagerTest {
diff --git a/src/test/java/creator/loki/feature/utility/ChoiceOptionParserTest.java b/src/test/java/creator/loki/feature/utility/ChoiceOptionParserTest.java
new file mode 100644
index 0000000..07e926b
--- /dev/null
+++ b/src/test/java/creator/loki/feature/utility/ChoiceOptionParserTest.java
@@ -0,0 +1,144 @@
+package creator.loki.feature.entertainment.commands;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.List;
+
+import creator.loki.feature.utility.ChoiceOptionParser;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import creator.loki.feature.utility.ChoiceOptionParser;
+
+class ChoiceOptionParserTest {
+
+ @Test
+ void tailAfterCommandPipe() {
+ assertEquals(
+ "a | b | c", ChoiceOptionParser.tailAfterCommand("!choose a | b | c", "!", "choose"));
+ }
+
+ @Test
+ void tailAfterCommandOr() {
+ assertEquals("a или b", ChoiceOptionParser.tailAfterCommand("!выбери a или b", "!", "выбери"));
+ }
+
+ @Test
+ void tailAfterCommandComma() {
+ assertEquals(
+ "apple,banana,cherry",
+ ChoiceOptionParser.tailAfterCommand("!pick apple,banana,cherry", "!", "pick"));
+ }
+
+ @Test
+ void tailAfterCommandSlash() {
+ assertEquals("a/b/c", ChoiceOptionParser.tailAfterCommand("!choice a/b/c", "!", "choice"));
+ }
+
+ @Test
+ void tailAfterCommandSpaces() {
+ assertEquals("a b c", ChoiceOptionParser.tailAfterCommand("!pick a b c", "!", "pick"));
+ }
+
+ void tailAfterCommand(String raw, String prefix, String command, String expected) {
+ assertEquals(expected, ChoiceOptionParser.tailAfterCommand(raw, prefix, command));
+ }
+
+ @Test
+ void tailAfterCommandReturnsEmptyWhenNoPrefix() {
+ assertTrue(ChoiceOptionParser.tailAfterCommand("hello", "!", "choose").isEmpty());
+ }
+
+ @Test
+ void tailAfterCommandReturnsEmptyWhenNoArg() {
+ assertTrue(ChoiceOptionParser.tailAfterCommand("!choose", "!", "choose").isEmpty());
+ }
+
+ @Test
+ void tailAfterCommandReturnsEmptyWhenWrongCommand() {
+ assertTrue(ChoiceOptionParser.tailAfterCommand("!help", "!", "choose").isEmpty());
+ }
+
+ @Test
+ void tailAfterCommandCaseInsensitive() {
+ assertEquals("a b", ChoiceOptionParser.tailAfterCommand("!ChOoSe a b", "!", "choose"));
+ }
+
+ @Test
+ void parseOptionsSplitsByPipe() {
+ List result = ChoiceOptionParser.parseOptions("a | b | c");
+ assertEquals(List.of("a", "b", "c"), result);
+ }
+
+ @Test
+ void parseOptionsSplitsByComma() {
+ List result = ChoiceOptionParser.parseOptions("apple, banana, cherry");
+ assertEquals(List.of("apple", "banana", "cherry"), result);
+ }
+
+ @Test
+ void parseOptionsSplitsByOr() {
+ List result = ChoiceOptionParser.parseOptions("кофе или чай");
+ assertEquals(List.of("кофе", "чай"), result);
+ }
+
+ @Test
+ void parseOptionsSplitsBySlash() {
+ List result = ChoiceOptionParser.parseOptions("да/нет/может быть");
+ assertEquals(List.of("да", "нет", "может быть"), result);
+ }
+
+ @Test
+ void parseOptionsSplitsBySpace() {
+ List result = ChoiceOptionParser.parseOptions("a b c d");
+ assertEquals(List.of("a", "b", "c", "d"), result);
+ }
+
+ @Test
+ void parseOptionsDeduplicatesIgnoreCase() {
+ List result = ChoiceOptionParser.parseOptions("A | a | B | b");
+ assertEquals(List.of("A", "B"), result);
+ }
+
+ @Test
+ void parseOptionsRemovesEmptyParts() {
+ List result = ChoiceOptionParser.parseOptions("a || b");
+ assertEquals(List.of("a", "b"), result);
+ }
+
+ @Test
+ void parseOptionsTrimsWhitespace() {
+ List result = ChoiceOptionParser.parseOptions(" a , b , c ");
+ assertEquals(List.of("a", "b", "c"), result);
+ }
+
+ @Test
+ void parseOptionsPriorityOrder() {
+ // pipe has highest priority
+ List result = ChoiceOptionParser.parseOptions("a,b|c,d");
+ assertEquals(List.of("a,b", "c,d"), result);
+ }
+
+ @ValueSource(strings = {"", " ", "a"})
+ @ParameterizedTest
+ void parseOptionsEdgeCases(String input) {
+ List result = ChoiceOptionParser.parseOptions(input);
+ if (input.isBlank()) {
+ assertTrue(result.isEmpty());
+ } else {
+ assertEquals(List.of("a"), result);
+ }
+ }
+
+ @Test
+ void parseOptionsPipeWithTrailingEmpty() {
+ List result = ChoiceOptionParser.parseOptions("a|");
+ assertEquals(List.of("a"), result);
+ }
+
+ @Test
+ void parseOptionsMultipleCommas() {
+ List result = ChoiceOptionParser.parseOptions("a,,b,,c");
+ assertEquals(List.of("a", "b", "c"), result);
+ }
+}