diff --git a/pom.xml b/pom.xml
index ec4c2ec..969c5cb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,40 +16,60 @@
+
net.dv8tion
JDA
5.0.0-beta.19
+
io.github.lycoon
clash-api
- 5.1.4
+ 5.1.5
+
com.google.code.gson
gson
2.9.0
+
- com.zaxxer
- HikariCP
- 5.0.1
+ org.projectlombok
+ lombok
+ 1.18.30
+ provided
+
- org.mariadb.jdbc
- mariadb-java-client
- 3.0.6
+ org.hibernate.orm
+ hibernate-core
+ 6.4.2.Final
- ch.qos.logback
- logback-classic
- 1.4.14
+ org.hibernate
+ hibernate-hikaricp
+ 6.4.2.Final
+ pom
+
+
+
+
+ org.slf4j
+ slf4j-api
+ 2.0.11
+
+
+
+ org.slf4j
+ slf4j-simple
+ 2.0.11
diff --git a/src/main/java/com/lycoon/clashbot/commands/CommandConfig.java b/src/main/java/com/lycoon/clashbot/commands/CommandConfig.java
index e96d1b3..62ddcca 100644
--- a/src/main/java/com/lycoon/clashbot/commands/CommandConfig.java
+++ b/src/main/java/com/lycoon/clashbot/commands/CommandConfig.java
@@ -4,10 +4,12 @@
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.interactions.commands.OptionType;
-import net.dv8tion.jda.api.interactions.commands.build.CommandData;
+import net.dv8tion.jda.api.interactions.commands.build.Commands;
+import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
-public class CommandConfig {
+public class CommandConfig
+{
private final JDA jda;
private final Guild guild;
private final String CLASHBOT_GUILD = "817384284507209768";
@@ -22,23 +24,23 @@ public void createCommands()
ClashBotMain.LOGGER.info("Creating commands...");
// Miscellaneous
- CommandData infoCommand = new CommandData("info", "Shows bot information");
+ SlashCommandData infoCommand = Commands.slash("info", "Shows bot information");
jda.upsertCommand(infoCommand).complete();
- CommandData inviteCommand = new CommandData("invite", "Shows bot's invite link");
+ SlashCommandData inviteCommand = Commands.slash("invite", "Shows bot's invite link");
jda.upsertCommand(inviteCommand).complete();
- CommandData langCommand = new CommandData("lang", "Shows your current language");
+ SlashCommandData langCommand = Commands.slash("lang", "Shows your current language");
jda.upsertCommand(langCommand).complete();
- CommandData helpCommand = new CommandData("help", "Shows commands and their usage");
+ SlashCommandData helpCommand = Commands.slash("help", "Shows commands and their usage");
jda.upsertCommand(helpCommand).complete();
// Settings
- CommandData clearCommand = new CommandData("clear", "Deletes all the data the bot database has about you");
+ SlashCommandData clearCommand = Commands.slash("clear", "Deletes all the data the bot database has about you");
jda.upsertCommand(clearCommand).complete();
- CommandData setCommand = new CommandData("set", "Shows clan profile");
+ SlashCommandData setCommand = Commands.slash("set", "Shows clan profile");
SubcommandData setClanSubcommand = new SubcommandData("clan", "Sets default clan tag");
setClanSubcommand.addOption(OptionType.STRING, "clan_tag", "Clan tag from the profile starting with a #", true);
@@ -52,27 +54,27 @@ public void createCommands()
jda.upsertCommand(setCommand).complete();
// Clan
- CommandData clanCommand = new CommandData("clan", "Shows clan profile");
+ SlashCommandData clanCommand = Commands.slash("clan", "Shows clan profile");
clanCommand.addOption(OptionType.STRING, "clan_tag", "Clan tag from the profile starting with a #", false);
jda.upsertCommand(clanCommand).complete();
- CommandData warCommand = new CommandData("war", "Shows current war occurring in the clan");
+ SlashCommandData warCommand = Commands.slash("war", "Shows current war occurring in the clan");
warCommand.addOption(OptionType.INTEGER, "page", "Page number you want to access", true);
warCommand.addOption(OptionType.STRING, "clan_tag", "Clan tag from the profile starting with a #", false);
jda.upsertCommand(warCommand).complete();
- CommandData warlogCommand = new CommandData("warlog", "Shows clan warlog");
+ SlashCommandData warlogCommand = Commands.slash("warlog", "Shows clan warlog");
warlogCommand.addOption(OptionType.INTEGER, "page", "Page number you want to access", true);
warlogCommand.addOption(OptionType.STRING, "clan_tag", "Clan tag from the profile starting with a #", false);
jda.upsertCommand(warlogCommand).complete();
- CommandData warleagueCommand = new CommandData("warleague", "Shows current warleague occurring in the clan");
+ SlashCommandData warleagueCommand = Commands.slash("warleague", "Shows current warleague occurring in the clan");
warleagueCommand.addOption(OptionType.INTEGER, "page", "Page number you want to access", true);
warleagueCommand.addOption(OptionType.STRING, "clan_tag", "Clan tag from the profile starting with a #", false);
jda.upsertCommand(warleagueCommand).complete();
// Player
- CommandData playerCommand = new CommandData("player", "Shows player profile");
+ SlashCommandData playerCommand = Commands.slash("player", "Shows player profile");
playerCommand.addOption(OptionType.STRING, "player_tag", "Player tag from the profile starting with a #", false);
jda.upsertCommand(playerCommand).complete();
diff --git a/src/main/java/com/lycoon/clashbot/commands/Command.java b/src/main/java/com/lycoon/clashbot/commands/CommandData.java
similarity index 84%
rename from src/main/java/com/lycoon/clashbot/commands/Command.java
rename to src/main/java/com/lycoon/clashbot/commands/CommandData.java
index 563e323..bac93a0 100644
--- a/src/main/java/com/lycoon/clashbot/commands/Command.java
+++ b/src/main/java/com/lycoon/clashbot/commands/CommandData.java
@@ -1,60 +1,58 @@
-package com.lycoon.clashbot.commands;
-
-public enum Command
-{
- INVITE(CommandCategory.MISC, "invite", "cmd.invite.desc"),
- LANG(CommandCategory.MISC, "lang", "cmd.lang.desc"),
- INFO(CommandCategory.MISC, "info", "cmd.info.desc"),
- HELP(CommandCategory.MISC, "help", "cmd.help.desc"),
- CLEAR(CommandCategory.SETTINGS, "clear", "cmd.clear.desc"),
- SET_PLAYER(CommandCategory.SETTINGS, "set", "cmd.setplayer.desc", "player "),
- SET_CLAN(CommandCategory.SETTINGS, "set", "cmd.setclan.desc", "clan "),
- SET_LANG(CommandCategory.SETTINGS, "set", "cmd.setlang.desc", "lang "),
- CLAN(CommandCategory.CLAN, "clan", "cmd.clan.desc", "[clanTag]"),
- WARLEAGUE(CommandCategory.CLAN, "warleague", "cmd.warleague.round.desc", " [clanTag]"),
- //WARLEAGUE_ALL (CommandCategory.CLAN, "warleague", "cmd.warleague.all.desc", "all [clanTag]"),
- //WARLEAGUE_CLAN (CommandCategory.CLAN, "warleague", "cmd.warleague.clan.desc", "[clanTag]"),
- WARLOG(CommandCategory.CLAN, "warlog", "cmd.warlog.desc", " [clanTag]"),
- WAR(CommandCategory.CLAN, "war", "cmd.war.desc", " [clanTag]"),
- PLAYER(CommandCategory.PLAYER, "player", "cmd.player.desc", "[playerTag]");
-
- final CommandCategory category;
- final String name, desc;
- String usage;
-
- Command(CommandCategory category, String name, String desc, String usage)
- {
- this.category = category;
- this.name = name;
- this.desc = desc;
- this.usage = usage;
- }
-
- Command(CommandCategory category, String name, String desc)
- {
- this.category = category;
- this.name = name;
- this.desc = desc;
- }
-
- @Override
- public String toString()
- {
- return name;
- }
-
- public String getDescription()
- {
- return desc;
- }
-
- public CommandCategory getCategory()
- {
- return category;
- }
-
- public String formatCommand()
- {
- return "/" + name + (usage == null ? "" : " " + usage);
- }
-}
+package com.lycoon.clashbot.commands;
+
+public enum CommandData
+{
+ INVITE(CommandCategory.MISC, "invite", "cmd.invite.desc"),
+ LANG(CommandCategory.MISC, "lang", "cmd.lang.desc"),
+ INFO(CommandCategory.MISC, "info", "cmd.info.desc"),
+ HELP(CommandCategory.MISC, "help", "cmd.help.desc"),
+ CLEAR(CommandCategory.SETTINGS, "clear", "cmd.clear.desc"),
+ SET_PLAYER(CommandCategory.SETTINGS, "set", "cmd.setplayer.desc", "player "),
+ SET_CLAN(CommandCategory.SETTINGS, "set", "cmd.setclan.desc", "clan "),
+ SET_LANG(CommandCategory.SETTINGS, "set", "cmd.setlang.desc", "lang "),
+ CLAN(CommandCategory.CLAN, "clan", "cmd.clan.desc", "[clanTag]"),
+ WARLEAGUE(CommandCategory.CLAN, "warleague", "cmd.warleague.round.desc", " [clanTag]"),
+ //WARLEAGUE_ALL (CommandCategory.CLAN, "warleague", "cmd.warleague.all.desc", "all [clanTag]"),
+ //WARLEAGUE_CLAN (CommandCategory.CLAN, "warleague", "cmd.warleague.clan.desc", "[clanTag]"),
+ WARLOG(CommandCategory.CLAN, "warlog", "cmd.warlog.desc", " [clanTag]"),
+ WAR(CommandCategory.CLAN, "war", "cmd.war.desc", " [clanTag]"),
+ PLAYER(CommandCategory.PLAYER, "player", "cmd.player.desc", "[playerTag]");
+
+ final CommandCategory category;
+ final String name, desc;
+ final String usage;
+
+ CommandData(CommandCategory category, String name, String desc, String usage)
+ {
+ this.category = category;
+ this.name = name;
+ this.desc = desc;
+ this.usage = usage;
+ }
+
+ CommandData(CommandCategory category, String name, String desc)
+ {
+ this(category, name, desc, null);
+ }
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+
+ public String getDescription()
+ {
+ return desc;
+ }
+
+ public CommandCategory getCategory()
+ {
+ return category;
+ }
+
+ public String formatCommand()
+ {
+ return "/" + name + (usage == null ? "" : " " + usage);
+ }
+}
diff --git a/src/main/java/com/lycoon/clashbot/commands/clan/ClanCommand.java b/src/main/java/com/lycoon/clashbot/commands/clan/ClanCommand.java
index c1bf056..044b893 100644
--- a/src/main/java/com/lycoon/clashbot/commands/clan/ClanCommand.java
+++ b/src/main/java/com/lycoon/clashbot/commands/clan/ClanCommand.java
@@ -3,7 +3,7 @@
import static com.lycoon.clashbot.utils.DrawUtils.*;
import static com.lycoon.clashbot.utils.FileUtils.*;
import static com.lycoon.clashbot.utils.ErrorUtils.*;
-import static com.lycoon.clashbot.utils.DatabaseUtils.*;
+import static com.lycoon.clashbot.utils.database.DatabaseUtils.*;
import static com.lycoon.clashbot.utils.CoreUtils.*;
import com.lycoon.clashapi.core.exceptions.ClashAPIException;
@@ -11,13 +11,14 @@
import com.lycoon.clashapi.models.clan.Clan;
import com.lycoon.clashapi.models.common.Label;
import com.lycoon.clashapi.models.player.enums.Role;
-import com.lycoon.clashbot.commands.Command;
+import com.lycoon.clashbot.commands.CommandData;
import com.lycoon.clashbot.core.ClashBotMain;
import com.lycoon.clashbot.lang.LangUtils;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import java.awt.*;
import java.awt.image.BufferedImage;
+import java.io.IOException;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.util.List;
@@ -97,16 +98,16 @@ public static Clan getClan(SlashCommandInteractionEvent event, Locale lang, Stri
if (tag == null) {
sendError(event, i18n.getString("set.clan.error"),
- MessageFormat.format(i18n.getString("cmd.general.tip"), Command.SET_CLAN.formatCommand()));
+ MessageFormat.format(i18n.getString("cmd.general.tip"), CommandData.SET_CLAN.formatCommand()));
return null;
}
- try {
- clan = ClashBotMain.clashAPI.getClan(tag);
- } catch (ClashAPIException e) {
+ try { clan = ClashBotMain.clashAPI.getClan(tag); }
+ catch (ClashAPIException | IOException e) {
sendExceptionError(event, i18n, e, tag, "clan");
return null;
}
+
return clan;
}
diff --git a/src/main/java/com/lycoon/clashbot/commands/clan/WarCommand.java b/src/main/java/com/lycoon/clashbot/commands/clan/WarCommand.java
index 3296818..16301b5 100644
--- a/src/main/java/com/lycoon/clashbot/commands/clan/WarCommand.java
+++ b/src/main/java/com/lycoon/clashbot/commands/clan/WarCommand.java
@@ -3,23 +3,19 @@
import static com.lycoon.clashbot.utils.DrawUtils.*;
import static com.lycoon.clashbot.utils.FileUtils.*;
import static com.lycoon.clashbot.utils.ErrorUtils.*;
-import static com.lycoon.clashbot.utils.DatabaseUtils.*;
+import static com.lycoon.clashbot.utils.database.DatabaseUtils.*;
import static com.lycoon.clashbot.utils.CoreUtils.*;
import static com.lycoon.clashbot.utils.GameUtils.*;
-import com.lycoon.clashapi.core.ClashAPI;
import com.lycoon.clashapi.core.exceptions.ClashAPIException;
import com.lycoon.clashapi.models.war.WarAttack;
import com.lycoon.clashapi.models.war.WarMember;
import com.lycoon.clashapi.models.war.War;
-import com.lycoon.clashapi.core.exception.ClashAPIException;
import com.lycoon.clashapi.models.war.enums.WarState;
-import com.lycoon.clashbot.commands.Command;
+import com.lycoon.clashbot.commands.CommandData;
import com.lycoon.clashbot.core.CacheComponents;
import com.lycoon.clashbot.core.ClashBotMain;
import com.lycoon.clashbot.lang.LangUtils;
-import net.dv8tion.jda.api.entities.MessageChannel;
-import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import java.awt.*;
@@ -50,14 +46,16 @@ public class WarCommand {
private final static Color notUsedAttackColor = new Color(0xfbbf70);
private final static Color attackColor = new Color(0x4c493a);
- static class SortMemberByOrder implements Comparator {
+ static class SortMemberByOrder implements Comparator
+ {
@Override
public int compare(WarMember a, WarMember b) {
return a.getMapPosition() - b.getMapPosition();
}
}
- static class SortAttackByOrder implements Comparator {
+ static class SortAttackByOrder implements Comparator
+ {
@Override
public int compare(WarAttack a, WarAttack b) {
return a.getOrder() - b.getOrder();
@@ -92,8 +90,7 @@ public static List getAttacksByOrder(List members) {
List sortedAttacks = new ArrayList<>();
for (WarMember member : members) {
List attacks = member.getAttacks();
- if (attacks != null)
- sortedAttacks.addAll(attacks);
+ sortedAttacks.addAll(attacks);
}
sortedAttacks.sort(new SortAttackByOrder());
return sortedAttacks;
@@ -127,7 +124,7 @@ public static int drawMemberResults(Graphics2D g2d, WarMember member, List {
if (event.getOptions().isEmpty())
@@ -86,8 +83,9 @@ public static void drawRound(Graphics2D g2d, SlashCommandInteractionEvent event,
int[] timeLeft;
War firstWar = wars.get(0);
- switch (firstWar.getState()) {
- case "preparation" -> {
+ switch (firstWar.getState())
+ {
+ case PREPARATION -> {
timeLeft = getTimeLeft(firstWar.getStartTime());
g2d.drawImage(getImageFromFile("backgrounds/cwl/cwl-preparation.png"), 0, 0, null);
drawSimpleCenteredString(g2d,
@@ -96,7 +94,7 @@ public static void drawRound(Graphics2D g2d, SlashCommandInteractionEvent event,
timeRect, 19f, Color.BLACK);
drawCenteredString(g2d, stateLabel, font.deriveFont(24f), i18n.getString("war.preparation"));
}
- case "warEnded" -> {
+ case ENDED -> {
timeLeft = getTimeLeft(firstWar.getEndTime());
g2d.drawImage(getImageFromFile("backgrounds/cwl/cwl-ended.png"), 0, 0, null);
drawSimpleCenteredString(g2d,
@@ -105,7 +103,7 @@ public static void drawRound(Graphics2D g2d, SlashCommandInteractionEvent event,
timeRect, 19f, Color.BLACK);
drawCenteredString(g2d, stateLabel, font.deriveFont(24f), i18n.getString("war.ended"));
}
- case "notInWar" -> {
+ case NOT_IN_WAR -> {
sendError(event, i18n.getString("exception.warleague.notinwar"));
return;
}
@@ -128,9 +126,9 @@ public static void drawRound(Graphics2D g2d, SlashCommandInteractionEvent event,
WarClan clan1 = war.getClan();
WarClan clan2 = war.getOpponent();
- if (war.getState().equals("warEnded")) {
- if (clan2.getStars() > clan1.getStars() ||
- (clan2.getStars() == clan1.getStars() &&
+ if (war.getState() == WarState.ENDED)
+ {
+ if (clan2.getStars() > clan1.getStars() || (clan2.getStars() == clan1.getStars() &&
clan2.getDestructionPercentage() > clan1.getDestructionPercentage())) {
WarClan tmp = clan1;
clan1 = clan2;
@@ -145,7 +143,8 @@ public static void drawRound(Graphics2D g2d, SlashCommandInteractionEvent event,
drawCenteredString(g2d, rectStarClan1, font.deriveFont(18f), String.valueOf(clan1.getStars()));
drawCenteredString(g2d, rectStarClan2, font.deriveFont(18f), String.valueOf(clan2.getStars()));
- if (firstWar.getState().equals("inWar")) {
+ if (firstWar.getState() == WarState.IN_WAR)
+ {
// Drawing clan names
drawShadowedStringLeft(g2d, clan1.getName(), 255, 113 + i * 60, 16f, Color.WHITE);
drawShadowedString(g2d, clan2.getName(), 670, 113 + i * 60, 16f);
@@ -157,7 +156,9 @@ public static void drawRound(Graphics2D g2d, SlashCommandInteractionEvent event,
// Drawing clan attacks
drawShadowedString(g2d, String.valueOf(clan2.getAttacks()), 350, 109 + i * 60, 12f);
drawShadowedString(g2d, String.valueOf(clan1.getAttacks()), 569, 109 + i * 60, 12f);
- } else {
+ }
+ else
+ {
// Drawing clan names
drawShadowedStringLeft(g2d, clan1.getName(), 300, 113 + i * 60, 16f, Color.WHITE);
drawShadowedString(g2d, clan2.getName(), 625, 113 + i * 60, 16f);
@@ -170,8 +171,10 @@ public static void drawRound(Graphics2D g2d, SlashCommandInteractionEvent event,
}
}
- public static void updateStats(WarClan clan, HashMap stats) {
- if (clan != null) {
+ public static void updateStats(WarClan clan, HashMap stats)
+ {
+ if (clan != null)
+ {
if (stats.containsKey(clan.getTag())) {
ClanWarStats stats1 = stats.get(clan.getTag());
stats1.addStars(clan.getStars());
@@ -182,10 +185,13 @@ public static void updateStats(WarClan clan, HashMap stats
}
}
- public static void drawStats(List rounds) {
+ public static void drawStats(List rounds)
+ {
HashMap stats = new HashMap<>();
- for (RoundWarInfo roundWars : rounds) {
- for (int j = 0; j < roundWars.getWars().size(); j++) {
+ for (RoundWarInfo roundWars : rounds)
+ {
+ for (int j = 0; j < roundWars.getWars().size(); j++)
+ {
War warInfo = roundWars.getWars().get(j);
updateStats(warInfo.getClan(), stats);
updateStats(warInfo.getOpponent(), stats);
@@ -193,7 +199,8 @@ public static void drawStats(List rounds) {
}
}
- public static WarLeagueGroup getLeagueGroup(SlashCommandInteractionEvent event, Locale lang, String[] args) {
+ public static WarLeagueGroup getLeagueGroup(SlashCommandInteractionEvent event, Locale lang, String[] args)
+ {
// If rate limitation has exceeded
if (!checkThrottle(event, lang))
return null;
@@ -204,20 +211,21 @@ public static WarLeagueGroup getLeagueGroup(SlashCommandInteractionEvent event,
if (tag == null) {
sendError(event, i18n.getString("set.clan.error"),
- MessageFormat.format(i18n.getString("cmd.general.tip"), Command.SET_CLAN.formatCommand()));
+ MessageFormat.format(i18n.getString("cmd.general.tip"), CommandData.SET_CLAN.formatCommand()));
return null;
}
try {
leagueGroup = ClashBotMain.clashAPI.getWarLeagueGroup(tag);
- } catch (ClashAPIException e) {
+ } catch (ClashAPIException | IOException e) {
sendExceptionError(event, i18n, e, tag, "warleague");
return null;
}
return leagueGroup;
}
- public static void executeRound(SlashCommandInteractionEvent event, String... args) {
+ public static void executeRound(SlashCommandInteractionEvent event, String... args)
+ {
Locale lang = LangUtils.getLanguage(event.getMember().getIdLong());
ResourceBundle i18n = LangUtils.getTranslations(lang);
@@ -263,11 +271,12 @@ else if (clan1.getDestructionPercentage() < clan2.getDestructionPercentage())
return clan2;
}
- public static int getWinStars(WarClan clan1, WarClan clan2, War war) {
- if (!war.getState().equals("warEnded")) {
+ public static int getWinStars(WarClan clan1, WarClan clan2, War war)
+ {
+ if (war.getState() != WarState.ENDED)
+ {
if (getWinner(clan1, clan2) == null)
return 0;
-
if (Objects.equals(getWinner(clan1, clan2), clan1))
return 10;
}
diff --git a/src/main/java/com/lycoon/clashbot/commands/clan/WarlogCommand.java b/src/main/java/com/lycoon/clashbot/commands/clan/WarlogCommand.java
index 85f1252..b0fd189 100644
--- a/src/main/java/com/lycoon/clashbot/commands/clan/WarlogCommand.java
+++ b/src/main/java/com/lycoon/clashbot/commands/clan/WarlogCommand.java
@@ -3,20 +3,18 @@
import static com.lycoon.clashbot.utils.DrawUtils.*;
import static com.lycoon.clashbot.utils.FileUtils.*;
import static com.lycoon.clashbot.utils.ErrorUtils.*;
-import static com.lycoon.clashbot.utils.DatabaseUtils.*;
+import static com.lycoon.clashbot.utils.database.DatabaseUtils.*;
import static com.lycoon.clashbot.utils.CoreUtils.*;
import static com.lycoon.clashbot.utils.GameUtils.*;
import com.lycoon.clashapi.core.exceptions.ClashAPIException;
import com.lycoon.clashapi.models.war.WarlogClan;
import com.lycoon.clashapi.models.war.WarlogEntry;
-import com.lycoon.clashapi.core.exception.ClashAPIException;
import com.lycoon.clashapi.models.war.enums.WarResult;
-import com.lycoon.clashbot.commands.Command;
+import com.lycoon.clashbot.commands.CommandData;
import com.lycoon.clashbot.core.CacheComponents;
import com.lycoon.clashbot.core.ClashBotMain;
import com.lycoon.clashbot.lang.LangUtils;
-import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import java.awt.*;
@@ -48,7 +46,8 @@ public class WarlogCommand {
private final static Color versusColor = new Color(0xffffc0);
private final static Color percentageColor = new Color(0x5e5d60);
- public static void call(SlashCommandInteractionEvent event) {
+ public static void call(SlashCommandInteractionEvent event)
+ {
CompletableFuture.runAsync(() -> {
if (event.getOptions().isEmpty())
{
@@ -139,17 +138,17 @@ public static List getWarlog(SlashCommandInteractionEvent event, Lo
if (tag == null) {
sendError(event, i18n.getString("set.clan.error"),
- MessageFormat.format(i18n.getString("cmd.general.tip"), Command.SET_CLAN.formatCommand()));
+ MessageFormat.format(i18n.getString("cmd.general.tip"), CommandData.SET_CLAN.formatCommand()));
return null;
}
- try {
- warlog = ClashBotMain.clashAPI.getWarlog(tag);
- } catch (IOException ignored) {
- } catch (ClashAPIException e) {
+ try { warlog = ClashBotMain.clashAPI.getWarlog(tag, null); }
+ catch (ClashAPIException | IOException e)
+ {
sendExceptionError(event, i18n, e, tag, "warlog");
return null;
}
+
return warlog;
}
diff --git a/src/main/java/com/lycoon/clashbot/commands/misc/ClearCommand.java b/src/main/java/com/lycoon/clashbot/commands/misc/ClearCommand.java
index 14c387f..52db5b1 100644
--- a/src/main/java/com/lycoon/clashbot/commands/misc/ClearCommand.java
+++ b/src/main/java/com/lycoon/clashbot/commands/misc/ClearCommand.java
@@ -2,7 +2,7 @@
import com.lycoon.clashbot.lang.LangUtils;
import com.lycoon.clashbot.utils.CoreUtils;
-import com.lycoon.clashbot.utils.DatabaseUtils;
+import com.lycoon.clashbot.utils.database.DatabaseUtils;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
diff --git a/src/main/java/com/lycoon/clashbot/commands/misc/HelpCommand.java b/src/main/java/com/lycoon/clashbot/commands/misc/HelpCommand.java
index dff9faf..9c31172 100644
--- a/src/main/java/com/lycoon/clashbot/commands/misc/HelpCommand.java
+++ b/src/main/java/com/lycoon/clashbot/commands/misc/HelpCommand.java
@@ -1,6 +1,6 @@
package com.lycoon.clashbot.commands.misc;
-import com.lycoon.clashbot.commands.Command;
+import com.lycoon.clashbot.commands.CommandData;
import com.lycoon.clashbot.commands.CommandCategory;
import com.lycoon.clashbot.lang.LangUtils;
import com.lycoon.clashbot.utils.CoreUtils;
@@ -20,10 +20,10 @@ public static void call(SlashCommandInteractionEvent event)
execute(event);
}
- public static void drawCategory(CommandCategory category, Command[] commands)
+ public static void drawCategory(CommandCategory category, CommandData[] commands)
{
StringBuilder categoryField = new StringBuilder();
- for (Command cmd : commands)
+ for (CommandData cmd : commands)
if (cmd.getCategory().equals(category)) {
categoryField.append("▫ `").append(cmd.formatCommand()).append("` ");
categoryField.append(i18n.getString(cmd.getDescription())).append("\n");
@@ -42,7 +42,7 @@ public static void execute(SlashCommandInteractionEvent event)
CommandCategory[] categories = CommandCategory.values();
for (CommandCategory category : categories)
- drawCategory(category, Command.values());
+ drawCategory(category, CommandData.values());
CoreUtils.sendMessage(event, i18n, builder);
}
diff --git a/src/main/java/com/lycoon/clashbot/commands/misc/InfoCommand.java b/src/main/java/com/lycoon/clashbot/commands/misc/InfoCommand.java
index fb8766d..d214a0a 100644
--- a/src/main/java/com/lycoon/clashbot/commands/misc/InfoCommand.java
+++ b/src/main/java/com/lycoon/clashbot/commands/misc/InfoCommand.java
@@ -4,7 +4,9 @@
import com.lycoon.clashbot.lang.LangUtils;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
+import net.dv8tion.jda.api.interactions.components.buttons.Button;
import java.awt.*;
import java.text.NumberFormat;
@@ -15,7 +17,7 @@
public class InfoCommand
{
private static final String TWITTER = "@LycoonMC";
- private static final String DISCORD = "Lycoon#7542";
+ private static final String AUTHOR = "@lycoon";
private static final String WEBSITE = "https://clashbot.app/";
private static final String DISCORD_INVITE = "https://discord.gg/Cy86PDA";
private static final String PATREON = "https://www.patreon.com/clashbot";
@@ -43,15 +45,15 @@ public static void execute(SlashCommandInteractionEvent event)
builder.addField("Version", ClashBotMain.VERSION, true);
builder.addField("Library", "Discord JDA", true);
- builder.addField("Author", "Lycoon#7542", true);
+ builder.addField("Author", AUTHOR, true);
builder.addField("Members", nf.format(guilds.stream().mapToInt(Guild::getMemberCount).sum()), true);
builder.addField("Servers", nf.format(guilds.size()), true);
builder.addField("Ping", nf.format(ClashBotMain.jda.getRestPing().complete()) + "ms", true);
event.getHook().sendMessageEmbeds(builder.build()).addActionRow(
- Button.link(WEBSITE, "Official Website").withEmoji(Emoji.fromMarkdown(CLASHBOT_EMOJI)),
- Button.link(DISCORD_INVITE, "Official Discord").withEmoji(Emoji.fromMarkdown(DISCORD_EMOJI)),
- Button.link(PATREON, "Contribute").withEmoji(Emoji.fromMarkdown(PATREON_EMOJI))
+ Button.link(WEBSITE, "Official Website").withEmoji(Emoji.fromFormatted(CLASHBOT_EMOJI)),
+ Button.link(DISCORD_INVITE, "Official Discord").withEmoji(Emoji.fromFormatted(DISCORD_EMOJI)),
+ Button.link(PATREON, "Contribute").withEmoji(Emoji.fromFormatted(PATREON_EMOJI))
).queue();
}
}
diff --git a/src/main/java/com/lycoon/clashbot/commands/misc/InviteCommand.java b/src/main/java/com/lycoon/clashbot/commands/misc/InviteCommand.java
index 06d43fd..478a99e 100644
--- a/src/main/java/com/lycoon/clashbot/commands/misc/InviteCommand.java
+++ b/src/main/java/com/lycoon/clashbot/commands/misc/InviteCommand.java
@@ -25,9 +25,7 @@ public static void execute(SlashCommandInteractionEvent event)
EmbedBuilder builder = new EmbedBuilder();
builder.setColor(Color.GRAY);
- builder.setDescription(INVITE_EMOJI + " " + MessageFormat.format(
- i18n.getString("cmd.invite.panel"),
- ClashBotMain.INVITE));
+ builder.setDescription(INVITE_EMOJI + " " + MessageFormat.format(i18n.getString("cmd.invite.panel"), ClashBotMain.INVITE));
CoreUtils.sendMessage(event, i18n, builder);
}
diff --git a/src/main/java/com/lycoon/clashbot/commands/misc/LangCommand.java b/src/main/java/com/lycoon/clashbot/commands/misc/LangCommand.java
index c69a754..5894fdf 100644
--- a/src/main/java/com/lycoon/clashbot/commands/misc/LangCommand.java
+++ b/src/main/java/com/lycoon/clashbot/commands/misc/LangCommand.java
@@ -1,6 +1,6 @@
package com.lycoon.clashbot.commands.misc;
-import com.lycoon.clashbot.commands.Command;
+import com.lycoon.clashbot.commands.CommandData;
import com.lycoon.clashbot.lang.LangUtils;
import com.lycoon.clashbot.utils.CoreUtils;
import net.dv8tion.jda.api.EmbedBuilder;
@@ -29,7 +29,7 @@ public static void execute(SlashCommandInteractionEvent event)
i18n.getString("lang.flag") + " " + MessageFormat.format(
i18n.getString("lang.current"), lang.getDisplayLanguage(lang)));
builder.setDescription(MessageFormat.format(
- i18n.getString("lang.info.other"), Command.SET_LANG.formatCommand()));
+ i18n.getString("lang.info.other"), CommandData.SET_LANG.formatCommand()));
CoreUtils.sendMessage(event, i18n, builder);
}
diff --git a/src/main/java/com/lycoon/clashbot/commands/PlayerCommand.java b/src/main/java/com/lycoon/clashbot/commands/player/PlayerCommand.java
similarity index 96%
rename from src/main/java/com/lycoon/clashbot/commands/PlayerCommand.java
rename to src/main/java/com/lycoon/clashbot/commands/player/PlayerCommand.java
index 5a5c6dc..06ddca6 100644
--- a/src/main/java/com/lycoon/clashbot/commands/PlayerCommand.java
+++ b/src/main/java/com/lycoon/clashbot/commands/player/PlayerCommand.java
@@ -1,249 +1,251 @@
-package com.lycoon.clashbot.commands;
-
-import static com.lycoon.clashbot.utils.DrawUtils.*;
-import static com.lycoon.clashbot.utils.FileUtils.*;
-import static com.lycoon.clashbot.utils.ErrorUtils.*;
-import static com.lycoon.clashbot.utils.DatabaseUtils.*;
-import static com.lycoon.clashbot.utils.CoreUtils.*;
-import static com.lycoon.clashbot.utils.GameUtils.*;
-
-import com.lycoon.clashapi.core.exceptions.ClashAPIException;
-import com.lycoon.clashapi.models.player.Player;
-import com.lycoon.clashapi.models.player.Troop;
-import com.lycoon.clashbot.core.CacheComponents;
-import com.lycoon.clashbot.core.ClashBotMain;
-import com.lycoon.clashbot.lang.LangUtils;
-import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
-
-import java.awt.*;
-import java.awt.image.BufferedImage;
-import java.io.IOException;
-import java.text.MessageFormat;
-import java.text.NumberFormat;
-import java.util.List;
-import java.util.Locale;
-import java.util.ResourceBundle;
-import java.util.concurrent.CompletableFuture;
-
-public class PlayerCommand {
- private final static int WIDTH = 932;
- private final static int HEIGHT = 559;
- private final static float FONT_SIZE = 12f;
-
- private final static int COLUMNS = 4;
- private final static int ARMY_TOPLINE = 238;
- private final static int ARMY_BOTLINE = 436;
-
- private final static String[] TROOPS = {"Barbarian", "Archer", "Giant", "Goblin", "Wall Breaker", "Balloon",
- "Wizard", "Healer", "Dragon", "P.E.K.K.A", "Baby Dragon", "Miner", "Electro Dragon", "Yeti", "Minion",
- "Hog Rider", "Valkyrie", "Golem", "Witch", "Lava Hound", "Bowler", "Ice Golem", "Headhunter", "Dragon Rider"};
- private final static String[] SPELLS = {"Lightning Spell", "Healing Spell", "Rage Spell", "Jump Spell",
- "Freeze Spell", "Clone Spell", "Invisibility Spell", "Poison Spell", "Earthquake Spell", "Haste Spell",
- "Skeleton Spell", "Bat Spell"};
- private final static String[] BUILDER_TROOPS = {"Raged Barbarian", "Sneaky Archer", "Boxer Giant", "Beta Minion",
- "Bomber", "Baby Dragon", "Cannon Cart", "Night Witch", "Drop Ship", "Super P.E.K.K.A", "Hog Glider"};
- private final static String[] SUPER_TROOPS = {"Super Barbarian", "Super Archer", "Super Giant", "Sneaky Goblin",
- "Super Wall Breaker", "Super Wizard", "Inferno Dragon", "Super Minion", "Super Valkyrie", "Super Witch",
- "Ice Hound", "Rocket Balloon", "Super Dragon", "Super Bowler"};
- private final static String[] HEROES = {"Barbarian King", "Archer Queen", "Grand Warden", "Royal Champion",
- "Battle Machine"};
- private final static String[] MACHINES = {"Wall Wrecker", "Battle Blimp", "Stone Slammer", "Siege Barracks",
- "Log Launcher", "Flame Flinger"};
- private final static String[] PETS = {"L.A.S.S.I", "Electro Owl", "Mighty Yak", "Unicorn"};
-
- public static void call(SlashCommandInteractionEvent event) {
- CompletableFuture.runAsync(() -> {
- if (event.getOptions().isEmpty())
- execute(event);
- else
- execute(event, event.getOption("player_tag").getAsString());
- });
- }
-
- public static void drawSuperTroop(Graphics2D g2d, Troop troop, String troopName, int x, int y) {
- if (troop == null || !troop.getSuperTroopIsActive())
- g2d.drawImage(getImageFromFile("troops/locked/" + troopName + ".png"), x, y, 44, 44, null);
- else
- g2d.drawImage(getImageFromFile("troops/" + troop.getName() + ".png"), x, y, 44, 44, null);
- }
-
- public static void drawTroop(Graphics2D g2d, Font font, Troop troop, String troopName, int x, int y) {
- // If the player has not unlocked the troop yet
- if (troop == null)
- g2d.drawImage(getImageFromFile("troops/locked/" + troopName + ".png"), x, y, 44, 44, null);
- else {
- g2d.drawImage(getImageFromFile("troops/" + troop.getName() + ".png"), x, y, 44, 44, null);
- if (troop.getLevel() == troop.getMaxLevel())
- g2d.drawImage(getImageFromFile("icons/level-label-max.png"), x + 1, y + 22, 20, 20, null);
- else if (troop.getLevel() != 1)
- g2d.drawImage(getImageFromFile("icons/level-label.png"), x + 1, y + 22, 20, 20, null);
-
- if (troop.getLevel() != 1) {
- Rectangle levelRect = new Rectangle(x + 1, y + 22, 20, 20);
- drawCenteredString(g2d, levelRect, font.deriveFont(font.getSize() - 2f), String.valueOf(troop.getLevel()));
- }
- }
- }
-
- public static void drawTroops(Graphics2D g2d, Font font, List troops, int y) {
- for (int i = 0, j = 0; i < TROOPS.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
- drawTroop(g2d, font, getHomeTroopByName(troops, TROOPS[i]), TROOPS[i], (i % COLUMNS) * 50 + 20, y + j * 50);
- }
-
- public static void drawSpells(Graphics2D g2d, Font font, List spells, int y) {
- for (int i = 0, j = 0; i < SPELLS.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
- drawTroop(g2d, font, getTroopByName(spells, SPELLS[i]), SPELLS[i], (i % COLUMNS) * 50 + 250, y + j * 50);
- }
-
- public static void drawBuilderTroops(Graphics2D g2d, Font font, List builderTroops, int y) {
- for (int i = 0, j = 0; i < BUILDER_TROOPS.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
- drawTroop(g2d, font, getBuilderTroopByName(builderTroops, BUILDER_TROOPS[i]), BUILDER_TROOPS[i], (i % COLUMNS) * 50 + 480, y + j * 50);
- }
-
- public static void drawSuperTroops(Graphics2D g2d, List superTroops, int y) {
- for (int i = 0, j = 0; i < SUPER_TROOPS.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
- drawSuperTroop(g2d, getTroopByName(superTroops, SUPER_TROOPS[i]), SUPER_TROOPS[i], (i % COLUMNS) * 50 + 710, y + j * 50);
- }
-
- public static void drawHeroes(Graphics2D g2d, Font font, List heroes, int y) {
- for (int i = 0, j = 0; i < HEROES.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
- drawTroop(g2d, font, getTroopByName(heroes, HEROES[i]), HEROES[i], (i % COLUMNS) * 50 + 250, y + j * 50);
- }
-
- public static void drawMachines(Graphics2D g2d, Font font, List machines, int y) {
- for (int i = 0, j = 0; i < MACHINES.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
- drawTroop(g2d, font, getTroopByName(machines, MACHINES[i]), MACHINES[i], (i % COLUMNS) * 50 + 480, y + j * 50);
- }
-
- public static void drawPets(Graphics2D g2d, Font font, List pets, int y) {
- for (int i = 0, j = 0; i < PETS.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
- drawTroop(g2d, font, getTroopByName(pets, PETS[i]), PETS[i], (i % COLUMNS) * 50 + 710, y + j * 50);
- }
-
- public static void execute(SlashCommandInteractionEvent event, String... args) {
- Locale lang = LangUtils.getLanguage(event.getMember().getIdLong());
- ResourceBundle i18n = LangUtils.getTranslations(lang);
- NumberFormat nf = NumberFormat.getInstance(lang);
-
- // Checking rate limitation
- if (!checkThrottle(event, lang))
- return;
-
- Player player;
- String tag = args.length > 0 ? args[0] : getPlayerTag(event.getMember().getIdLong());
-
- if (tag == null) {
- sendError(event, i18n.getString("set.player.error"),
- MessageFormat.format(i18n.getString("cmd.general.tip"), Command.SET_PLAYER.formatCommand()));
- return;
- }
-
- try {
- player = ClashBotMain.clashAPI.getPlayer(tag);
- } catch (ClashAPIException e) {
- sendExceptionError(event, i18n, e, tag, "player");
- return;
- }
-
- // Initializing image
- BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
- Graphics2D g2d = initGraphics(WIDTH, HEIGHT, image);
-
- Font font = getFont("Supercell.ttf").deriveFont(FONT_SIZE);
- g2d.setFont(font);
-
- g2d.drawImage(getImageFromFile("backgrounds/player-profile.png"), 0, 0, null);
-
- // Experience level
- g2d.drawImage(getImageFromFile("icons/exp-star.png"), 20, 18, 45, 45, null);
- Rectangle level = new Rectangle(23, 30, 40, 20);
- drawCenteredString(g2d, level, font.deriveFont(FONT_SIZE + 5f), String.valueOf(player.getExpLevel()));
-
- // Nickname
- drawShadowedString(g2d, player.getName(), 75, 36, FONT_SIZE + 8f);
-
- // Player tag
- drawShadowedString(g2d, player.getTag(), 75, 55, FONT_SIZE - 1f);
-
- // Townhall
- g2d.drawImage(CacheComponents.getTownHallImage(player.getTownHallLevel()), 80, 80, 100, 100, null);
- drawShadowedString(g2d, i18n.getString("townhall"), 25, 125, FONT_SIZE - 2f);
- drawShadowedString(g2d, i18n.getString("level") + " " + player.getTownHallLevel(), 25, 150, FONT_SIZE + 8f);
-
- // Builder hall
- if (player.getBuilderHallLevel() != 0) {
- g2d.drawImage(CacheComponents.getBuilderHallImage(player.getBuilderHallLevel()), 265, 85, 95, 95, null);
- drawShadowedString(g2d, i18n.getString("level") + " " + player.getBuilderHallLevel(), 200, 150, FONT_SIZE + 8f);
- } else {
- // In case the player has not built the builder hall yet
- drawShadowedString(g2d, i18n.getString("no.builderhall"), 200, 150, FONT_SIZE + 8f);
- }
- drawShadowedString(g2d, i18n.getString("builderhall"), 200, 125, FONT_SIZE - 2f);
-
- // League
- if (player.getLeague() != null)
- g2d.drawImage(getImageFromUrl(player.getLeague().getIconUrls().getMedium()), 383, 30, 90, 90, null);
- else {
- g2d.drawImage(getImageFromFile("icons/noleague.png"), 383, 30, 90, 90, null);
- Rectangle noLeagueRect = new Rectangle(375, 60, 105, 20);
- drawCenteredString(g2d, noLeagueRect, font.deriveFont(FONT_SIZE - 4f), i18n.getString("no.league"));
- }
-
- // Clan
- if (player.getClan() != null) {
- g2d.drawImage(getImageFromUrl(player.getClan().getBadgeUrls().getLarge()), 800, 30, 105, 105, null);
-
- Rectangle clanNameRect = new Rectangle(775, 130, 148, 30);
- Rectangle clanRoleRect = new Rectangle(775, 151, 148, 30);
- drawCenteredString(g2d, clanNameRect, font.deriveFont(FONT_SIZE + 2f), player.getClan().getName());
- drawCenteredString(g2d, clanRoleRect, font.deriveFont(FONT_SIZE - 2f), i18n.getString(String.valueOf(player.getRole())));
- } else {
- Rectangle noClanRect = new Rectangle(775, 130, 148, 30);
- drawCenteredString(g2d, noClanRect, font.deriveFont(FONT_SIZE + 2f), i18n.getString("no.clan"));
- g2d.drawImage(getImageFromFile("icons/noclan.png"), 812, 40, 75, 75, null);
- }
-
- // Trophies
- Rectangle trophiesRect = new Rectangle(375, 148, 75, 24);
- drawCenteredString(g2d, trophiesRect, font.deriveFont(FONT_SIZE + 4f), nf.format(player.getTrophies()));
-
- // Statistics
- drawShadowedString(g2d, i18n.getString("season") + " " + getCurrentSeason(lang), 486, 45, FONT_SIZE + 3f);
- drawShadowedString(g2d, i18n.getString("attacks.won"), 486, 77, FONT_SIZE - 1.5f);
- drawShadowedString(g2d, i18n.getString("defenses.won"), 486, 107, FONT_SIZE - 1.5f);
- drawShadowedString(g2d, i18n.getString("donations"), 486, 143, FONT_SIZE - 1.5f);
- drawShadowedString(g2d, i18n.getString("donations.received"), 486, 173, FONT_SIZE - 1.5f);
-
- drawSimpleString(g2d, nf.format(player.getAttackWins()), 693, 79, FONT_SIZE, new Color(0x444545));
- drawSimpleString(g2d, nf.format(player.getDefenseWins()), 693, 109, FONT_SIZE, new Color(0x444545));
- drawSimpleString(g2d, nf.format(player.getDonations()), 693, 144, FONT_SIZE, new Color(0x444545));
- drawSimpleString(g2d, nf.format(player.getDonationsReceived()), 693, 174, FONT_SIZE, new Color(0x444545));
-
- // Army
- drawShadowedString(g2d, i18n.getString("troops"), 21, ARMY_TOPLINE - 12, FONT_SIZE + 2f);
- drawShadowedString(g2d, i18n.getString("spells"), 251, ARMY_TOPLINE - 12, FONT_SIZE + 2f);
- drawShadowedString(g2d, i18n.getString("label.builderbase"), 481, ARMY_TOPLINE - 12, FONT_SIZE + 2f);
- drawShadowedString(g2d, i18n.getString("super.troops"), 711, ARMY_TOPLINE - 12, FONT_SIZE + 2f);
- drawShadowedString(g2d, i18n.getString("heroes"), 251, ARMY_BOTLINE - 12, FONT_SIZE + 2f);
- drawShadowedString(g2d, i18n.getString("machines"), 481, ARMY_BOTLINE - 12, FONT_SIZE + 2f);
- drawShadowedString(g2d, i18n.getString("pets"), 711, ARMY_BOTLINE + 38, FONT_SIZE + 2f);
-
- // Troops
- List troops = player.getTroops();
- List heroes = player.getHeroes();
- List spells = player.getSpells();
-
- drawTroops(g2d, font, troops, ARMY_TOPLINE);
- drawSpells(g2d, font, spells, ARMY_TOPLINE);
- drawBuilderTroops(g2d, font, troops, ARMY_TOPLINE);
- drawSuperTroops(g2d, troops, ARMY_TOPLINE);
-
- drawHeroes(g2d, font, heroes, ARMY_BOTLINE);
- drawMachines(g2d, font, troops, ARMY_BOTLINE);
- drawPets(g2d, font, troops, ARMY_BOTLINE + 50);
-
- sendImage(event, image);
-
- g2d.dispose();
- }
-}
+package com.lycoon.clashbot.commands.player;
+
+import static com.lycoon.clashbot.utils.DrawUtils.*;
+import static com.lycoon.clashbot.utils.FileUtils.*;
+import static com.lycoon.clashbot.utils.ErrorUtils.*;
+import static com.lycoon.clashbot.utils.database.DatabaseUtils.*;
+import static com.lycoon.clashbot.utils.CoreUtils.*;
+import static com.lycoon.clashbot.utils.GameUtils.*;
+
+import com.lycoon.clashapi.core.exceptions.ClashAPIException;
+import com.lycoon.clashapi.models.player.Player;
+import com.lycoon.clashapi.models.player.Troop;
+import com.lycoon.clashbot.commands.CommandData;
+import com.lycoon.clashbot.core.CacheComponents;
+import com.lycoon.clashbot.core.ClashBotMain;
+import com.lycoon.clashbot.lang.LangUtils;
+import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.text.NumberFormat;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.concurrent.CompletableFuture;
+
+public class PlayerCommand
+{
+ private final static int WIDTH = 932;
+ private final static int HEIGHT = 559;
+ private final static float FONT_SIZE = 12f;
+
+ private final static int COLUMNS = 4;
+ private final static int ARMY_TOPLINE = 238;
+ private final static int ARMY_BOTLINE = 436;
+
+ private final static String[] TROOPS = {"Barbarian", "Archer", "Giant", "Goblin", "Wall Breaker", "Balloon",
+ "Wizard", "Healer", "Dragon", "P.E.K.K.A", "Baby Dragon", "Miner", "Electro Dragon", "Yeti", "Minion",
+ "Hog Rider", "Valkyrie", "Golem", "Witch", "Lava Hound", "Bowler", "Ice Golem", "Headhunter", "Dragon Rider"};
+ private final static String[] SPELLS = {"Lightning Spell", "Healing Spell", "Rage Spell", "Jump Spell",
+ "Freeze Spell", "Clone Spell", "Invisibility Spell", "Poison Spell", "Earthquake Spell", "Haste Spell",
+ "Skeleton Spell", "Bat Spell"};
+ private final static String[] BUILDER_TROOPS = {"Raged Barbarian", "Sneaky Archer", "Boxer Giant", "Beta Minion",
+ "Bomber", "Baby Dragon", "Cannon Cart", "Night Witch", "Drop Ship", "Super P.E.K.K.A", "Hog Glider"};
+ private final static String[] SUPER_TROOPS = {"Super Barbarian", "Super Archer", "Super Giant", "Sneaky Goblin",
+ "Super Wall Breaker", "Super Wizard", "Inferno Dragon", "Super Minion", "Super Valkyrie", "Super Witch",
+ "Ice Hound", "Rocket Balloon", "Super Dragon", "Super Bowler"};
+ private final static String[] HEROES = {"Barbarian King", "Archer Queen", "Grand Warden", "Royal Champion",
+ "Battle Machine"};
+ private final static String[] MACHINES = {"Wall Wrecker", "Battle Blimp", "Stone Slammer", "Siege Barracks",
+ "Log Launcher", "Flame Flinger"};
+ private final static String[] PETS = {"L.A.S.S.I", "Electro Owl", "Mighty Yak", "Unicorn"};
+
+ public static void call(SlashCommandInteractionEvent event) {
+ CompletableFuture.runAsync(() -> {
+ if (event.getOptions().isEmpty())
+ execute(event);
+ else
+ execute(event, event.getOption("player_tag").getAsString());
+ });
+ }
+
+ public static void drawSuperTroop(Graphics2D g2d, Troop troop, String troopName, int x, int y) {
+ if (troop == null || !troop.getSuperTroopIsActive())
+ g2d.drawImage(getImageFromFile("troops/locked/" + troopName + ".png"), x, y, 44, 44, null);
+ else
+ g2d.drawImage(getImageFromFile("troops/" + troop.getName() + ".png"), x, y, 44, 44, null);
+ }
+
+ public static void drawTroop(Graphics2D g2d, Font font, Troop troop, String troopName, int x, int y) {
+ // If the player has not unlocked the troop yet
+ if (troop == null)
+ g2d.drawImage(getImageFromFile("troops/locked/" + troopName + ".png"), x, y, 44, 44, null);
+ else {
+ g2d.drawImage(getImageFromFile("troops/" + troop.getName() + ".png"), x, y, 44, 44, null);
+ if (troop.getLevel() == troop.getMaxLevel())
+ g2d.drawImage(getImageFromFile("icons/level-label-max.png"), x + 1, y + 22, 20, 20, null);
+ else if (troop.getLevel() != 1)
+ g2d.drawImage(getImageFromFile("icons/level-label.png"), x + 1, y + 22, 20, 20, null);
+
+ if (troop.getLevel() != 1) {
+ Rectangle levelRect = new Rectangle(x + 1, y + 22, 20, 20);
+ drawCenteredString(g2d, levelRect, font.deriveFont(font.getSize() - 2f), String.valueOf(troop.getLevel()));
+ }
+ }
+ }
+
+ public static void drawTroops(Graphics2D g2d, Font font, List troops, int y) {
+ for (int i = 0, j = 0; i < TROOPS.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
+ drawTroop(g2d, font, getHomeTroopByName(troops, TROOPS[i]), TROOPS[i], (i % COLUMNS) * 50 + 20, y + j * 50);
+ }
+
+ public static void drawSpells(Graphics2D g2d, Font font, List spells, int y) {
+ for (int i = 0, j = 0; i < SPELLS.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
+ drawTroop(g2d, font, getTroopByName(spells, SPELLS[i]), SPELLS[i], (i % COLUMNS) * 50 + 250, y + j * 50);
+ }
+
+ public static void drawBuilderTroops(Graphics2D g2d, Font font, List builderTroops, int y) {
+ for (int i = 0, j = 0; i < BUILDER_TROOPS.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
+ drawTroop(g2d, font, getBuilderTroopByName(builderTroops, BUILDER_TROOPS[i]), BUILDER_TROOPS[i], (i % COLUMNS) * 50 + 480, y + j * 50);
+ }
+
+ public static void drawSuperTroops(Graphics2D g2d, List superTroops, int y) {
+ for (int i = 0, j = 0; i < SUPER_TROOPS.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
+ drawSuperTroop(g2d, getTroopByName(superTroops, SUPER_TROOPS[i]), SUPER_TROOPS[i], (i % COLUMNS) * 50 + 710, y + j * 50);
+ }
+
+ public static void drawHeroes(Graphics2D g2d, Font font, List heroes, int y) {
+ for (int i = 0, j = 0; i < HEROES.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
+ drawTroop(g2d, font, getTroopByName(heroes, HEROES[i]), HEROES[i], (i % COLUMNS) * 50 + 250, y + j * 50);
+ }
+
+ public static void drawMachines(Graphics2D g2d, Font font, List machines, int y) {
+ for (int i = 0, j = 0; i < MACHINES.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
+ drawTroop(g2d, font, getTroopByName(machines, MACHINES[i]), MACHINES[i], (i % COLUMNS) * 50 + 480, y + j * 50);
+ }
+
+ public static void drawPets(Graphics2D g2d, Font font, List pets, int y) {
+ for (int i = 0, j = 0; i < PETS.length; i++, j += i % COLUMNS == 0 ? 1 : 0)
+ drawTroop(g2d, font, getTroopByName(pets, PETS[i]), PETS[i], (i % COLUMNS) * 50 + 710, y + j * 50);
+ }
+
+ public static void execute(SlashCommandInteractionEvent event, String... args) {
+ Locale lang = LangUtils.getLanguage(event.getMember().getIdLong());
+ ResourceBundle i18n = LangUtils.getTranslations(lang);
+ NumberFormat nf = NumberFormat.getInstance(lang);
+
+ // Checking rate limitation
+ if (!checkThrottle(event, lang))
+ return;
+
+ Player player;
+ String tag = args.length > 0 ? args[0] : getPlayerTag(event.getMember().getIdLong());
+
+ if (tag == null) {
+ sendError(event, i18n.getString("set.player.error"),
+ MessageFormat.format(i18n.getString("cmd.general.tip"), CommandData.SET_PLAYER.formatCommand()));
+ return;
+ }
+
+ try {
+ player = ClashBotMain.clashAPI.getPlayer(tag);
+ } catch (ClashAPIException | IOException e) {
+ sendExceptionError(event, i18n, e, tag, "player");
+ return;
+ }
+
+ // Initializing image
+ BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g2d = initGraphics(WIDTH, HEIGHT, image);
+
+ Font font = getFont("Supercell.ttf").deriveFont(FONT_SIZE);
+ g2d.setFont(font);
+
+ g2d.drawImage(getImageFromFile("backgrounds/player-profile.png"), 0, 0, null);
+
+ // Experience level
+ g2d.drawImage(getImageFromFile("icons/exp-star.png"), 20, 18, 45, 45, null);
+ Rectangle level = new Rectangle(23, 30, 40, 20);
+ drawCenteredString(g2d, level, font.deriveFont(FONT_SIZE + 5f), String.valueOf(player.getExpLevel()));
+
+ // Nickname
+ drawShadowedString(g2d, player.getName(), 75, 36, FONT_SIZE + 8f);
+
+ // Player tag
+ drawShadowedString(g2d, player.getTag(), 75, 55, FONT_SIZE - 1f);
+
+ // Townhall
+ g2d.drawImage(CacheComponents.getTownHallImage(player.getTownHallLevel()), 80, 80, 100, 100, null);
+ drawShadowedString(g2d, i18n.getString("townhall"), 25, 125, FONT_SIZE - 2f);
+ drawShadowedString(g2d, i18n.getString("level") + " " + player.getTownHallLevel(), 25, 150, FONT_SIZE + 8f);
+
+ // Builder hall
+ if (player.getBuilderHallLevel() != 0) {
+ g2d.drawImage(CacheComponents.getBuilderHallImage(player.getBuilderHallLevel()), 265, 85, 95, 95, null);
+ drawShadowedString(g2d, i18n.getString("level") + " " + player.getBuilderHallLevel(), 200, 150, FONT_SIZE + 8f);
+ } else {
+ // In case the player has not built the builder hall yet
+ drawShadowedString(g2d, i18n.getString("no.builderhall"), 200, 150, FONT_SIZE + 8f);
+ }
+ drawShadowedString(g2d, i18n.getString("builderhall"), 200, 125, FONT_SIZE - 2f);
+
+ // League
+ if (player.getLeague() != null)
+ g2d.drawImage(getImageFromUrl(player.getLeague().getIconUrls().getMedium()), 383, 30, 90, 90, null);
+ else {
+ g2d.drawImage(getImageFromFile("icons/noleague.png"), 383, 30, 90, 90, null);
+ Rectangle noLeagueRect = new Rectangle(375, 60, 105, 20);
+ drawCenteredString(g2d, noLeagueRect, font.deriveFont(FONT_SIZE - 4f), i18n.getString("no.league"));
+ }
+
+ // Clan
+ if (player.getClan() != null) {
+ g2d.drawImage(getImageFromUrl(player.getClan().getBadgeUrls().getLarge()), 800, 30, 105, 105, null);
+
+ Rectangle clanNameRect = new Rectangle(775, 130, 148, 30);
+ Rectangle clanRoleRect = new Rectangle(775, 151, 148, 30);
+ drawCenteredString(g2d, clanNameRect, font.deriveFont(FONT_SIZE + 2f), player.getClan().getName());
+ drawCenteredString(g2d, clanRoleRect, font.deriveFont(FONT_SIZE - 2f), i18n.getString(String.valueOf(player.getRole())));
+ } else {
+ Rectangle noClanRect = new Rectangle(775, 130, 148, 30);
+ drawCenteredString(g2d, noClanRect, font.deriveFont(FONT_SIZE + 2f), i18n.getString("no.clan"));
+ g2d.drawImage(getImageFromFile("icons/noclan.png"), 812, 40, 75, 75, null);
+ }
+
+ // Trophies
+ Rectangle trophiesRect = new Rectangle(375, 148, 75, 24);
+ drawCenteredString(g2d, trophiesRect, font.deriveFont(FONT_SIZE + 4f), nf.format(player.getTrophies()));
+
+ // Statistics
+ drawShadowedString(g2d, i18n.getString("season") + " " + getCurrentSeason(lang), 486, 45, FONT_SIZE + 3f);
+ drawShadowedString(g2d, i18n.getString("attacks.won"), 486, 77, FONT_SIZE - 1.5f);
+ drawShadowedString(g2d, i18n.getString("defenses.won"), 486, 107, FONT_SIZE - 1.5f);
+ drawShadowedString(g2d, i18n.getString("donations"), 486, 143, FONT_SIZE - 1.5f);
+ drawShadowedString(g2d, i18n.getString("donations.received"), 486, 173, FONT_SIZE - 1.5f);
+
+ drawSimpleString(g2d, nf.format(player.getAttackWins()), 693, 79, FONT_SIZE, new Color(0x444545));
+ drawSimpleString(g2d, nf.format(player.getDefenseWins()), 693, 109, FONT_SIZE, new Color(0x444545));
+ drawSimpleString(g2d, nf.format(player.getDonations()), 693, 144, FONT_SIZE, new Color(0x444545));
+ drawSimpleString(g2d, nf.format(player.getDonationsReceived()), 693, 174, FONT_SIZE, new Color(0x444545));
+
+ // Army
+ drawShadowedString(g2d, i18n.getString("troops"), 21, ARMY_TOPLINE - 12, FONT_SIZE + 2f);
+ drawShadowedString(g2d, i18n.getString("spells"), 251, ARMY_TOPLINE - 12, FONT_SIZE + 2f);
+ drawShadowedString(g2d, i18n.getString("label.builderbase"), 481, ARMY_TOPLINE - 12, FONT_SIZE + 2f);
+ drawShadowedString(g2d, i18n.getString("super.troops"), 711, ARMY_TOPLINE - 12, FONT_SIZE + 2f);
+ drawShadowedString(g2d, i18n.getString("heroes"), 251, ARMY_BOTLINE - 12, FONT_SIZE + 2f);
+ drawShadowedString(g2d, i18n.getString("machines"), 481, ARMY_BOTLINE - 12, FONT_SIZE + 2f);
+ drawShadowedString(g2d, i18n.getString("pets"), 711, ARMY_BOTLINE + 38, FONT_SIZE + 2f);
+
+ // Troops
+ List troops = player.getTroops();
+ List heroes = player.getHeroes();
+ List spells = player.getSpells();
+
+ drawTroops(g2d, font, troops, ARMY_TOPLINE);
+ drawSpells(g2d, font, spells, ARMY_TOPLINE);
+ drawBuilderTroops(g2d, font, troops, ARMY_TOPLINE);
+ drawSuperTroops(g2d, troops, ARMY_TOPLINE);
+
+ drawHeroes(g2d, font, heroes, ARMY_BOTLINE);
+ drawMachines(g2d, font, troops, ARMY_BOTLINE);
+ drawPets(g2d, font, troops, ARMY_BOTLINE + 50);
+
+ sendImage(event, image);
+
+ g2d.dispose();
+ }
+}
diff --git a/src/main/java/com/lycoon/clashbot/commands/settings/SetCommand.java b/src/main/java/com/lycoon/clashbot/commands/settings/SetCommand.java
index a87c471..e6984ca 100644
--- a/src/main/java/com/lycoon/clashbot/commands/settings/SetCommand.java
+++ b/src/main/java/com/lycoon/clashbot/commands/settings/SetCommand.java
@@ -1,11 +1,11 @@
package com.lycoon.clashbot.commands.settings;
import com.lycoon.clashapi.core.exceptions.ClashAPIException;
-import com.lycoon.clashbot.commands.Command;
+import com.lycoon.clashbot.commands.CommandData;
import com.lycoon.clashbot.core.ClashBotMain;
import com.lycoon.clashbot.lang.LangUtils;
import com.lycoon.clashbot.utils.CoreUtils;
-import com.lycoon.clashbot.utils.DatabaseUtils;
+import com.lycoon.clashbot.utils.database.DatabaseUtils;
import com.lycoon.clashbot.utils.ErrorUtils;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
@@ -19,15 +19,15 @@ public class SetCommand
{
public static void call(SlashCommandInteractionEvent event)
{
- if (event.getSubcommandName() == null) {
+ String type = event.getSubcommandName();
+ if (type == null)
+ {
ResourceBundle i18n = LangUtils.getTranslations(event.getMember().getIdLong());
- ErrorUtils.sendError(event,
- i18n.getString("wrong.usage"),
+ ErrorUtils.sendError(event, i18n.getString("wrong.usage"),
MessageFormat.format(i18n.getString("info.help"), "prefix"));
return;
}
- String type = event.getSubcommandName();
switch (type)
{
case "player" -> executePlayer(event, event.getOption("player_tag").getAsString());
@@ -35,14 +35,14 @@ public static void call(SlashCommandInteractionEvent event)
case "lang" -> executeLang(event, event.getOption("language").getAsString());
default -> {
ResourceBundle i18n = LangUtils.getTranslations(event.getMember().getIdLong());
- ErrorUtils.sendError(event,
- i18n.getString("wrong.usage"),
+ ErrorUtils.sendError(event, i18n.getString("wrong.usage"),
MessageFormat.format(i18n.getString("info.help"), "prefix"));
}
}
}
- public static void executePlayer(SlashCommandInteractionEvent event, String tag) {
+ public static void executePlayer(SlashCommandInteractionEvent event, String tag)
+ {
ResourceBundle i18n = LangUtils.getTranslations(event.getMember().getIdLong());
try {
@@ -69,7 +69,7 @@ public static void executeClan(SlashCommandInteractionEvent event, String tag)
try {
// Checks if the clan exists
ClashBotMain.clashAPI.getClan(tag);
- } catch (ClashAPIException e) {
+ } catch (ClashAPIException | IOException e) {
ErrorUtils.sendExceptionError(event, i18n, e, tag, "clan");
return;
}
@@ -98,7 +98,7 @@ public static void executeLang(SlashCommandInteractionEvent event, String langua
MessageFormat.format(i18n.getString("lang.success"), lang.getDisplayLanguage(lang)));
builder.setDescription(
MessageFormat.format(i18n.getString("lang.info.other"),
- Command.SET_LANG.formatCommand()));
+ CommandData.SET_LANG.formatCommand()));
CoreUtils.sendMessage(event, i18n, builder);
}
diff --git a/src/main/java/com/lycoon/clashbot/core/CacheComponents.java b/src/main/java/com/lycoon/clashbot/core/CacheComponents.java
index 14bac42..aef5c82 100644
--- a/src/main/java/com/lycoon/clashbot/core/CacheComponents.java
+++ b/src/main/java/com/lycoon/clashbot/core/CacheComponents.java
@@ -6,7 +6,8 @@
import com.lycoon.clashbot.utils.FileUtils;
-public class CacheComponents {
+public class CacheComponents
+{
public static Image alreadyStar = FileUtils.getImageFromFile("icons/clanwar/alreadyclan-star.png");
public static Image newStar = FileUtils.getImageFromFile("icons/clanwar/clan-star.png");
public static Image noStar = FileUtils.getImageFromFile("icons/clanwar/noclan-star.png");
@@ -22,7 +23,8 @@ public class CacheComponents {
private static final CacheComponents singleton = new CacheComponents();
- private CacheComponents() {
+ private CacheComponents()
+ {
for (int i = 0; i < 14; i++)
townhalls.add(FileUtils.getImageFromFile("buildings/townhalls/home/th" + (i + 1) + ".png"));
for (int i = 0; i < 9; i++)
diff --git a/src/main/java/com/lycoon/clashbot/core/ClashBotMain.java b/src/main/java/com/lycoon/clashbot/core/ClashBotMain.java
index 36ac737..7a6ee88 100644
--- a/src/main/java/com/lycoon/clashbot/core/ClashBotMain.java
+++ b/src/main/java/com/lycoon/clashbot/core/ClashBotMain.java
@@ -8,7 +8,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.security.auth.login.LoginException;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
@@ -16,12 +15,12 @@
public class ClashBotMain
{
private static final String CONFIG = "tokens.properties";
- private static Properties tokens;
+ private static final Properties tokens = new Properties();
public static long[] owners = {138282927502000128L, 198485955701768192L};
public static final String VERSION = "2.0.0";
public static final String INVITE = "https://discord.com/api/oauth2/authorize?client_id=734481969630543883&permissions=2147534848&scope=bot%20applications.commands";
- public static Logger LOGGER = LoggerFactory.getLogger(ClashBotMain.class.getName());
+ public static Logger LOGGER = LoggerFactory.getLogger(ClashBotMain.class);
// Following attributes are initialized on launch
public static ClashAPI clashAPI;
@@ -34,7 +33,8 @@ public class ClashBotMain
* All rights reserved 2024
* ######################################################################
*/
- public static void main(String[] args) throws InterruptedException {
+ public static void main(String[] args) throws InterruptedException
+ {
loadTokensFromConfig();
buildDiscordInstance();
diff --git a/src/main/java/com/lycoon/clashbot/core/EventListener.java b/src/main/java/com/lycoon/clashbot/core/EventListener.java
index b93a24e..e0d1364 100644
--- a/src/main/java/com/lycoon/clashbot/core/EventListener.java
+++ b/src/main/java/com/lycoon/clashbot/core/EventListener.java
@@ -6,10 +6,10 @@
import com.lycoon.clashbot.commands.clan.WarLeagueCommand;
import com.lycoon.clashbot.commands.clan.WarlogCommand;
import com.lycoon.clashbot.commands.misc.*;
+import com.lycoon.clashbot.commands.player.PlayerCommand;
import com.lycoon.clashbot.commands.settings.SetCommand;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageEmbed;
-import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.unions.DefaultGuildChannelUnion;
import net.dv8tion.jda.api.events.guild.GuildJoinEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
@@ -21,7 +21,7 @@
public class EventListener extends ListenerAdapter
{
- static boolean isCommand(String arg, Command cmd) {
+ static boolean isCommand(String arg, CommandData cmd) {
return arg.equalsIgnoreCase(cmd.toString());
}
@@ -37,9 +37,9 @@ static MessageEmbed warnNotInGuild()
}
@Override
- public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
- if (!event.isFromGuild())
- {
+ public void onSlashCommandInteraction(SlashCommandInteractionEvent event)
+ {
+ if (!event.isFromGuild()){
event.replyEmbeds(warnNotInGuild()).queue();
return;
}
@@ -47,27 +47,27 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
event.deferReply().queue();
String cmd = event.getName();
- if (isCommand(cmd, Command.SET_LANG))
+ if (isCommand(cmd, CommandData.SET_LANG))
SetCommand.call(event);
- else if (isCommand(cmd, Command.PLAYER))
+ else if (isCommand(cmd, CommandData.PLAYER))
PlayerCommand.call(event);
- else if (isCommand(cmd, Command.CLAN))
+ else if (isCommand(cmd, CommandData.CLAN))
ClanCommand.call(event);
- else if (isCommand(cmd, Command.WAR))
+ else if (isCommand(cmd, CommandData.WAR))
WarCommand.call(event);
- else if (isCommand(cmd, Command.WARLOG))
+ else if (isCommand(cmd, CommandData.WARLOG))
WarlogCommand.call(event);
- else if (isCommand(cmd, Command.WARLEAGUE))
+ else if (isCommand(cmd, CommandData.WARLEAGUE))
WarLeagueCommand.call(event);
- else if (isCommand(cmd, Command.LANG))
+ else if (isCommand(cmd, CommandData.LANG))
LangCommand.call(event);
- else if (isCommand(cmd, Command.INFO))
+ else if (isCommand(cmd, CommandData.INFO))
InfoCommand.call(event);
- else if (isCommand(cmd, Command.HELP))
+ else if (isCommand(cmd, CommandData.HELP))
HelpCommand.call(event);
- else if (isCommand(cmd, Command.CLEAR))
+ else if (isCommand(cmd, CommandData.CLEAR))
ClearCommand.call(event);
- else if (isCommand(cmd, Command.INVITE))
+ else if (isCommand(cmd, CommandData.INVITE))
InviteCommand.call(event);
else {
event.getHook().deleteOriginal().queue();
@@ -86,7 +86,7 @@ public void onGuildJoin(GuildJoinEvent event)
builder.setTitle("Hi, thanks for inviting me!");
builder.setDescription("Run `/help` to get the list of all available commands :scroll:");
- try { Objects.requireNonNull(defaultChannel).asTextChannel().sendMessage(builder.build()).queue(); }
+ try { Objects.requireNonNull(defaultChannel).asTextChannel().sendMessageEmbeds(builder.build()).queue(); }
catch (MissingAccessException ignored) {}
}
}
diff --git a/src/main/java/com/lycoon/clashbot/lang/LangUtils.java b/src/main/java/com/lycoon/clashbot/lang/LangUtils.java
index c90342a..c938810 100644
--- a/src/main/java/com/lycoon/clashbot/lang/LangUtils.java
+++ b/src/main/java/com/lycoon/clashbot/lang/LangUtils.java
@@ -1,6 +1,6 @@
package com.lycoon.clashbot.lang;
-import com.lycoon.clashbot.utils.DatabaseUtils;
+import com.lycoon.clashbot.utils.database.DatabaseUtils;
import java.util.Locale;
import java.util.ResourceBundle;
diff --git a/src/main/java/com/lycoon/clashbot/lang/UTF16Control.java b/src/main/java/com/lycoon/clashbot/lang/UTF16Control.java
index 68a8c1f..134759f 100644
--- a/src/main/java/com/lycoon/clashbot/lang/UTF16Control.java
+++ b/src/main/java/com/lycoon/clashbot/lang/UTF16Control.java
@@ -11,7 +11,8 @@
import java.util.ResourceBundle;
import java.util.ResourceBundle.Control;
-public class UTF16Control extends Control {
+public class UTF16Control extends Control
+{
public ResourceBundle newBundle
(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
throws IOException {
diff --git a/src/main/java/com/lycoon/clashbot/utils/CoreUtils.java b/src/main/java/com/lycoon/clashbot/utils/CoreUtils.java
index d03bfff..5c7af54 100644
--- a/src/main/java/com/lycoon/clashbot/utils/CoreUtils.java
+++ b/src/main/java/com/lycoon/clashbot/utils/CoreUtils.java
@@ -6,9 +6,6 @@
import com.lycoon.clashbot.lang.LangUtils;
import net.dv8tion.jda.api.EmbedBuilder;
-import net.dv8tion.jda.api.JDA;
-import net.dv8tion.jda.api.entities.Guild;
-import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.exceptions.InsufficientPermissionException;
@@ -19,11 +16,11 @@
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.HashMap;
-import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
-public class CoreUtils {
+public class CoreUtils
+{
public static final Color validColor = new Color(0x48bd73);
public static final Color invalidColor = new Color(0xc24646);
public static final String INFO_EMOJI = "<:info:825346959514533928>";
diff --git a/src/main/java/com/lycoon/clashbot/utils/DatabaseUtils.java b/src/main/java/com/lycoon/clashbot/utils/DatabaseUtils.java
deleted file mode 100644
index 14ee568..0000000
--- a/src/main/java/com/lycoon/clashbot/utils/DatabaseUtils.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package com.lycoon.clashbot.utils;
-
-import com.zaxxer.hikari.HikariConfig;
-import com.zaxxer.hikari.HikariDataSource;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-public class DatabaseUtils
-{
- private static final HikariDataSource ds;
-
- static
- {
- HikariConfig cfg = new HikariConfig("database.properties");
- ds = new HikariDataSource(cfg);
- }
-
- private DatabaseUtils() {}
-
- public static Connection getConnection() throws SQLException
- {
- return ds.getConnection();
- }
-
- public static String getUserLang(long id)
- {
- String req = "SELECT lang FROM user WHERE id=?;";
- try (Connection conn = getConnection();
- PreparedStatement statement = conn.prepareStatement(req))
- {
- statement.setLong(1, id);
- ResultSet res = statement.executeQuery();
-
- statement.close();
- conn.close();
-
- if (res.next())
- return res.getString("lang");
- }
- catch (SQLException ignored) {}
- return "en";
- }
-
- public static String getPlayerTag(long id)
- {
- String req = "SELECT player FROM user WHERE id=?;";
- try (Connection conn = getConnection();
- PreparedStatement statement = conn.prepareStatement(req))
- {
- statement.setLong(1, id);
- ResultSet res = statement.executeQuery();
-
- statement.close();
- conn.close();
-
- if (res.next())
- return res.getString("player");
- }
- catch (SQLException ignored) {}
- return null;
- }
-
- public static String getClanTag(long id)
- {
- String req = "SELECT clan FROM user WHERE id=?;";
- try (Connection conn = getConnection();
- PreparedStatement statement = conn.prepareStatement(req))
- {
- statement.setLong(1, id);
- ResultSet res = statement.executeQuery();
-
- statement.close();
- conn.close();
-
- if (res.next())
- return res.getString("clan");
- }
- catch (SQLException ignored) {}
- return null;
- }
-
- public static String getServerPrefix(long id)
- {
- String req = "SELECT prefix FROM server WHERE id=?;";
- try (Connection conn = getConnection();
- PreparedStatement statement = conn.prepareStatement(req))
- {
- statement.setLong(1, id);
- ResultSet res = statement.executeQuery();
-
- statement.close();
- conn.close();
-
- if (res.next())
- return res.getString("prefix");
- }
- catch (SQLException ignored) {}
- return "!";
- }
-
- public static void setUserLang(long id, String lang)
- {
- String req = "INSERT INTO user(id, lang) VALUES(?, ?) ON DUPLICATE KEY UPDATE lang=?;";
- try (Connection conn = getConnection();
- PreparedStatement statement = conn.prepareStatement(req))
- {
- statement.setLong(1, id);
- statement.setString(2, lang);
- statement.setString(3, lang);
- statement.executeUpdate();
- }
- catch (SQLException ignored) {}
- }
-
- public static void setPlayerTag(long id, String playerTag)
- {
- String req = "INSERT INTO user(id, player) VALUES(?, ?) ON DUPLICATE KEY UPDATE player=?;";
- try (Connection conn = getConnection();
- PreparedStatement statement = conn.prepareStatement(req))
- {
- statement.setLong(1, id);
- statement.setString(2, playerTag);
- statement.setString(3, playerTag);
- statement.executeUpdate();
- }
- catch (SQLException ignored) {}
- }
-
- public static void setClanTag(long id, String clanTag)
- {
- String req = "INSERT INTO user(id, clan) VALUES(?, ?) ON DUPLICATE KEY UPDATE clan=?;";
- try (Connection conn = getConnection();
- PreparedStatement statement = conn.prepareStatement(req))
- {
- statement.setLong(1, id);
- statement.setString(2, clanTag);
- statement.setString(3, clanTag);
- statement.executeUpdate();
- }
- catch (SQLException ignored) {}
- }
-
- public static void setServerPrefix(long id, String prefix)
- {
- String req = "INSERT INTO server(id, prefix) VALUES(?, ?) ON DUPLICATE KEY UPDATE prefix=?;";
- try (Connection conn = getConnection();
- PreparedStatement statement = conn.prepareStatement(req))
- {
- statement.setLong(1, id);
- statement.setString(2, prefix);
- statement.setString(3, prefix);
- statement.executeUpdate();
- }
- catch (SQLException ignored) {}
- }
-
- public static void deleteUser(long id)
- {
- String req = "DELETE FROM user WHERE id=?;";
- try (Connection conn = getConnection();
- PreparedStatement statement = conn.prepareStatement(req))
- {
- statement.setLong(1, id);
- statement.executeUpdate();
- }
- catch (SQLException ignored) {}
- }
-}
diff --git a/src/main/java/com/lycoon/clashbot/utils/DrawUtils.java b/src/main/java/com/lycoon/clashbot/utils/DrawUtils.java
index e28f841..883840d 100644
--- a/src/main/java/com/lycoon/clashbot/utils/DrawUtils.java
+++ b/src/main/java/com/lycoon/clashbot/utils/DrawUtils.java
@@ -2,13 +2,13 @@
import java.awt.*;
import java.awt.font.FontRenderContext;
-import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
-import java.text.AttributedString;
import java.util.Objects;
+import static com.lycoon.clashbot.core.ClashBotMain.LOGGER;
+
public class DrawUtils
{
private final static Color DEFAULT_COLOR = Color.WHITE;
@@ -34,7 +34,7 @@ public static Font getFont(String file)
InputStream stream = ClassLoader.getSystemClassLoader().getResourceAsStream("fonts/" + file);
font = Font.createFont(Font.TRUETYPE_FONT, Objects.requireNonNull(stream));
}
- catch (FontFormatException | IOException e) {e.printStackTrace();}
+ catch (FontFormatException | IOException e) { LOGGER.error("Error while loading font: " + file, e); }
return font;
}
diff --git a/src/main/java/com/lycoon/clashbot/utils/ErrorUtils.java b/src/main/java/com/lycoon/clashbot/utils/ErrorUtils.java
index 2ddc79e..deb01f4 100644
--- a/src/main/java/com/lycoon/clashbot/utils/ErrorUtils.java
+++ b/src/main/java/com/lycoon/clashbot/utils/ErrorUtils.java
@@ -58,7 +58,8 @@ public static void throwCommandError(MessageChannel channel, ResourceBundle i18n
}
*/
- public static void sendError(SlashCommandInteractionEvent event, String title, String... args) {
+ public static void sendError(SlashCommandInteractionEvent event, String title, String... args)
+ {
EmbedBuilder error = new EmbedBuilder();
error.setColor(CoreUtils.invalidColor);
error.setTitle(title);
diff --git a/src/main/java/com/lycoon/clashbot/utils/FileUtils.java b/src/main/java/com/lycoon/clashbot/utils/FileUtils.java
index c327c66..1af3280 100644
--- a/src/main/java/com/lycoon/clashbot/utils/FileUtils.java
+++ b/src/main/java/com/lycoon/clashbot/utils/FileUtils.java
@@ -1,8 +1,8 @@
package com.lycoon.clashbot.utils;
import net.dv8tion.jda.api.entities.Message;
-import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
+import net.dv8tion.jda.api.utils.FileUpload;
import static com.lycoon.clashbot.core.ClashBotMain.LOGGER;
import static com.lycoon.clashbot.utils.CoreUtils.addUserToGenerating;
@@ -40,8 +40,11 @@ public static void sendImage(SlashCommandInteractionEvent event, BufferedImage i
removeUserFromGenerating(id);
};
- event.getHook().sendFile(bos.toByteArray(), "clashbot.png").queue(sendingCallback);
- LOGGER.info("Picture sent to " + event.getMember().getUser().getAsTag() + " on " + event.getGuild().getIdLong());
+
+ FileUpload file = FileUpload.fromData(bos.toByteArray(), "clashbot.png");
+ event.getHook().sendFiles(file).queue(sendingCallback);
+
+ LOGGER.info("Picture sent to " + event.getMember().getUser().getName() + " on " + event.getGuild().getIdLong());
}
public static Image getImageFromFile(String file)
diff --git a/src/main/java/com/lycoon/clashbot/utils/GameUtils.java b/src/main/java/com/lycoon/clashbot/utils/GameUtils.java
index 36340f3..2e037cd 100644
--- a/src/main/java/com/lycoon/clashbot/utils/GameUtils.java
+++ b/src/main/java/com/lycoon/clashbot/utils/GameUtils.java
@@ -9,19 +9,23 @@
import java.util.Locale;
import com.lycoon.clashapi.models.player.Troop;
+import com.lycoon.clashapi.models.player.enums.Village;
-public class GameUtils {
+public class GameUtils
+{
public static int getPositive(float value) {
return (int) (value * (value < 0 ? -1 : 1));
}
- public static String getCurrentSeason(Locale lang) {
+ public static String getCurrentSeason(Locale lang)
+ {
ZonedDateTime utcDateZoned = ZonedDateTime.now(ZoneId.of("Etc/UTC"));
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("MMMM yyyy").withLocale(lang);
return utcDateZoned.format(pattern);
}
- public static int[] getTimeLeft(String toParse) {
+ public static int[] getTimeLeft(String toParse)
+ {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss.SSS'Z'");
LocalDateTime endDate = LocalDateTime.parse(toParse, formatter);
ZonedDateTime zonedTime = endDate.atZone(ZoneId.of("UTC"));
@@ -36,27 +40,27 @@ public static int[] getTimeLeft(String toParse) {
return new int[]{getPositive(hours), getPositive(minutes), getPositive(seconds)};
}
- public static Troop getTroopByName(List troops, String name) {
- for (Troop troop : troops)
- if (troop.getName().equals(name))
- return troop;
-
- return null;
+ public static Troop getTroopByName(List troops, String name)
+ {
+ return troops.stream()
+ .filter(troop -> troop.getName().equals(name))
+ .findFirst()
+ .orElse(null);
}
- public static Troop getBuilderTroopByName(List troops, String name) {
- for (Troop troop : troops)
- if (troop.getVillage().equals("builderBase") && troop.getName().equals(name))
- return troop;
-
- return null;
+ public static Troop getBuilderTroopByName(List troops, String name)
+ {
+ return troops.stream()
+ .filter(troop -> troop.getVillage() == Village.BUILDER_BASE && troop.getName().equals(name))
+ .findFirst()
+ .orElse(null);
}
- public static Troop getHomeTroopByName(List troops, String name) {
- for (Troop troop : troops)
- if (troop.getVillage().equals("home") && troop.getName().equals(name))
- return troop;
-
- return null;
+ public static Troop getHomeTroopByName(List troops, String name)
+ {
+ return troops.stream()
+ .filter(troop -> troop.getVillage() == Village.HOME_VILLAGE && troop.getName().equals(name))
+ .findFirst()
+ .orElse(null);
}
}
diff --git a/src/main/java/com/lycoon/clashbot/utils/database/DatabaseHandler.java b/src/main/java/com/lycoon/clashbot/utils/database/DatabaseHandler.java
new file mode 100644
index 0000000..ba5c263
--- /dev/null
+++ b/src/main/java/com/lycoon/clashbot/utils/database/DatabaseHandler.java
@@ -0,0 +1,71 @@
+package com.lycoon.clashbot.utils.database;
+
+import com.lycoon.clashbot.core.ClashBotMain;
+import com.lycoon.clashbot.utils.database.entities.User;
+import jakarta.persistence.EntityNotFoundException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.boot.MetadataSources;
+import org.hibernate.boot.registry.StandardServiceRegistry;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+
+import java.util.Optional;
+
+public class DatabaseHandler
+{
+ private static final StandardServiceRegistry registry;
+ private static final SessionFactory sessionFactory;
+
+ static
+ {
+ registry = new StandardServiceRegistryBuilder().build();
+
+ try
+ {
+ sessionFactory = new MetadataSources(registry)
+ .addAnnotatedClasses(User.class)
+ .buildMetadata()
+ .buildSessionFactory();
+ }
+ catch (Exception e)
+ {
+ StandardServiceRegistryBuilder.destroy(registry);
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ protected static Optional getUser(long id)
+ {
+ try (Session session = sessionFactory.openSession())
+ {
+ User user = session.get(User.class, id);
+ return Optional.ofNullable(user);
+ }
+ catch (EntityNotFoundException e) { return Optional.empty(); }
+ catch (Exception e) { ClashBotMain.LOGGER.error(e.getMessage()); return Optional.empty(); }
+ }
+
+ protected static void saveUser(User user)
+ {
+ try (Session session = sessionFactory.openSession())
+ {
+ Transaction transaction = session.beginTransaction();
+ session.merge(user);
+ transaction.commit();
+ }
+ catch (Exception e) { ClashBotMain.LOGGER.error(e.getMessage()); }
+ }
+
+ protected static void removeUser(long id)
+ {
+ try (Session session = sessionFactory.openSession())
+ {
+ Transaction transaction = session.beginTransaction();
+ session.remove(new User(id));
+ transaction.commit();
+ }
+ catch (EntityNotFoundException ignored) {}
+ catch (Exception e) { ClashBotMain.LOGGER.error(e.getMessage()); }
+ }
+}
diff --git a/src/main/java/com/lycoon/clashbot/utils/database/DatabaseUtils.java b/src/main/java/com/lycoon/clashbot/utils/database/DatabaseUtils.java
new file mode 100644
index 0000000..b902de0
--- /dev/null
+++ b/src/main/java/com/lycoon/clashbot/utils/database/DatabaseUtils.java
@@ -0,0 +1,48 @@
+package com.lycoon.clashbot.utils.database;
+
+import com.lycoon.clashbot.utils.database.entities.User;
+import java.util.Optional;
+
+public class DatabaseUtils extends DatabaseHandler
+{
+ public static String getPlayerTag(long id)
+ {
+ Optional user = getUser(id);
+ return user.map(User::getPlayerTag).orElse(null);
+ }
+
+ public static String getClanTag(long id)
+ {
+ Optional user = getUser(id);
+ return user.map(User::getClanTag).orElse(null);
+ }
+
+ public static String getUserLang(long id)
+ {
+ Optional user = getUser(id);
+ return user.map(User::getLang).orElse(null);
+ }
+
+ public static void setUserLang(long id, String lang)
+ {
+ User user = new User(id).withLang(lang);
+ saveUser(user);
+ }
+
+ public static void setPlayerTag(long id, String playerTag)
+ {
+ User user = new User(id).withPlayerTag(playerTag);
+ saveUser(user);
+ }
+
+ public static void setClanTag(long id, String clanTag)
+ {
+ User user = new User(id).withClanTag(clanTag);
+ saveUser(user);
+ }
+
+ public static void deleteUser(long id)
+ {
+ removeUser(id);
+ }
+}
diff --git a/src/main/java/com/lycoon/clashbot/utils/database/entities/User.java b/src/main/java/com/lycoon/clashbot/utils/database/entities/User.java
new file mode 100644
index 0000000..ccdd24a
--- /dev/null
+++ b/src/main/java/com/lycoon/clashbot/utils/database/entities/User.java
@@ -0,0 +1,36 @@
+package com.lycoon.clashbot.utils.database.entities;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.Getter;
+import lombok.Setter;
+
+@Entity
+@Table(name = "user")
+public class User
+{
+ public User(long id) { this.id = id; }
+
+ @Id
+ @Column(name = "id")
+ @Getter @Setter
+ private Long id;
+
+ @Column(name = "lang")
+ @Getter @Setter
+ private String lang;
+
+ @Column(name = "player_tag")
+ @Getter @Setter
+ private String playerTag;
+
+ @Column(name = "clan_tag")
+ @Getter @Setter
+ private String clanTag;
+
+ public User withLang(String lang) { this.lang = lang; return this; }
+ public User withPlayerTag(String playerTag) { this.playerTag = playerTag; return this; }
+ public User withClanTag(String clanTag) { this.clanTag = clanTag; return this; }
+}
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
deleted file mode 100644
index 846f8d8..0000000
--- a/src/main/resources/logback.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
- %d{dd/MM/yyyy - HH:mm:ss} %boldGreen(%-15.-15logger{0}) %highlight(%-6level) %msg%n
-
-
-
-
- logs/logs.txt
- true
-
- %d{dd/MM/yyyy - HH:mm:ss} %-15.-15logger{0} %-6level %msg%n
-
-
-
-
-
-
-
-
-
\ No newline at end of file