diff --git a/NOTICE.txt b/NOTICE.txt new file mode 100644 index 0000000..4a2a46f --- /dev/null +++ b/NOTICE.txt @@ -0,0 +1,3 @@ +Apache Commons Lang Copyright 2001-2022 The Apache Software Foundation + +This product includes software developed at The Apache Software Foundation (https://www.apache.org/). diff --git a/README.md b/README.md index e4cbd62..c65acd8 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,27 @@ Discord bot by qsef1256 * /폭발 - :explosion: -## License - -Apache Commons Lang Copyright 2001-2022 The Apache Software Foundation +## Library + +* 코어 라이브러리 + * [JDA](https://github.com/DV8FromTheWorld/JDA): `Apache-2.0` + * [Chewtils](https://github.com/Chew/JDA-Chewtils): `Apache-2.0` +* DB 라이브러리 + * [Hibernate ORM](https://hibernate.org/orm/): `LGPL-2.1` + * [HikariCP](https://github.com/brettwooldridge/HikariCP): `Apache-2.0` + * [MariaDB Connector/J](https://mariadb.com/kb/en/mariadb-connector-j/): `LGPL-2.1-or-later` +* 유틸 라이브러리 + * [Lombok](https://projectlombok.org/): `MIT` + * [Apache Commons Lang3](https://github.com/apache/commons-lang): `Apache-2.0` + * [Guava](https://github.com/google/guava): `Apache-2.0` + * [Gson](https://github.com/google/gson): `Apache-2.0` + * [SnakeYAML](https://bitbucket.org/snakeyaml/snakeyaml/src/master/): `Apache-2.0` + * [Reflections](https://github.com/ronmamo/reflections): `WTFPL` +* 테스트/로깅 라이브러리 + * [JUnit 5](https://junit.org/junit5/): `EPL-2.0` + * [SLF4J](https://www.slf4j.org/): `MIT` + * [Logback](https://logback.qos.ch/): `EPL-1.0 & LGPL-2.1` -This product includes software developed at The Apache Software Foundation (https://www.apache.org/). +## License +Copyright 2022. qsef1256 All rights reserved. diff --git a/pom.xml b/pom.xml index 62fc9f7..5b84c56 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ net.qsef1256 DiaBot - 1.0-SNAPSHOT + 1.0 jar DiaBot @@ -113,7 +113,7 @@ pw.chew jda-chewtils - 1.23.0 + 1.24.1 compile pom diff --git a/src/main/java/net/qsef1256/diabot/DiaBot.java b/src/main/java/net/qsef1256/diabot/DiaBot.java index 81bda9d..16d61d3 100644 --- a/src/main/java/net/qsef1256/diabot/DiaBot.java +++ b/src/main/java/net/qsef1256/diabot/DiaBot.java @@ -1,5 +1,6 @@ package net.qsef1256.diabot; +import com.jagrosh.jdautilities.command.Command; import com.jagrosh.jdautilities.command.CommandClient; import com.jagrosh.jdautilities.command.CommandClientBuilder; import com.jagrosh.jdautilities.command.SlashCommand; @@ -7,19 +8,24 @@ import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.entities.Activity; -import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.requests.GatewayIntent; import net.dv8tion.jda.api.utils.ChunkingFilter; import net.dv8tion.jda.api.utils.cache.CacheFlag; import net.qsef1256.diabot.command.HelpCommand; import net.qsef1256.diabot.database.HibernateManager; +import net.qsef1256.diabot.util.GenericUtil; +import org.jetbrains.annotations.NotNull; import org.reflections.Reflections; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.security.auth.login.LoginException; +import java.io.File; +import java.io.IOException; +import java.lang.management.ManagementFactory; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; import java.util.Set; import static org.reflections.scanners.Scanners.SubTypes; @@ -28,15 +34,19 @@ public class DiaBot { public static final Logger logger = LoggerFactory.getLogger(DiaBot.class.getSimpleName()); @Getter + private static final Reflections reflections = new Reflections("net.qsef1256.diabot"); + @Getter private static JDA jda; @Getter private static CommandClient commandClient; + private static String[] args; public static void main(final String[] args) throws LoginException { if (args == null) { System.out.println("Please start bot with Discord Bot Token."); return; } + DiaBot.args = args; logger.info("DiaBot is Starting!"); final CommandClientBuilder commandClientBuilder = new CommandClientBuilder(); @@ -61,28 +71,23 @@ public static void main(final String[] args) throws LoginException { final JDABuilder builder = JDABuilder.createDefault(args[0]); configureMemoryUsage(builder); - builder.addEventListeners( - commandClient); + builder.addEventListeners(commandClient); try { registerListeners(builder); } catch (final ReflectiveOperationException e) { - logger.error("Error on loading commands"); + logger.error("Error on loading listeners"); e.printStackTrace(); System.exit(1); } jda = builder.build(); - final Guild guild = jda.getGuildById(commandClient.forcedGuildId()); - if (guild != null) { - guild.updateCommands().queue(); - } HelpCommand.initCommands(); HibernateManager.getSessionFactoryFromJPA().openSession(); } - public static void configureMemoryUsage(final JDABuilder builder) { + public static void configureMemoryUsage(final @NotNull JDABuilder builder) { builder.disableCache(CacheFlag.VOICE_STATE); builder.setChunkingFilter(ChunkingFilter.ALL); // 모든 길드의 유저 캐싱하기 (권한 필요) builder.enableIntents(GatewayIntent.GUILD_MEMBERS); // 유저 캐싱 권한 얻기 (권한 필요) @@ -91,34 +96,75 @@ public static void configureMemoryUsage(final JDABuilder builder) { private static void registerCommands(final CommandClientBuilder commandClientBuilder) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { logger.info("Loading Commands"); - final Reflections classes = new Reflections("net.qsef1256.diabot"); - final Set> commands = classes.get(SubTypes.of(SlashCommand.class).asClass()); + final Set> commands = reflections.get(SubTypes.of(Command.class).asClass()); if (commands.size() == 0) logger.warn("There is no command in the registered package. No commands were loaded."); for (final Class command : commands) { if (command.isMemberClass()) continue; - - SlashCommand slashCommand = (SlashCommand) command.getConstructor().newInstance(); - commandClientBuilder.addSlashCommand(slashCommand); - logger.info("Loaded " + command.getSimpleName() + " successfully"); + if (command.isInterface()) continue; + if (Modifier.isAbstract(command.getModifiers())) continue; + + String typeDisplay = "Unknown"; + if (GenericUtil.typeOf(command.getSuperclass(), Command.class)) { + typeDisplay = "Command"; + Command instance = (Command) command.getConstructor().newInstance(); + commandClientBuilder.addCommand(instance); + } + if (GenericUtil.typeOf(command.getSuperclass(), SlashCommand.class)) { + typeDisplay = "Slash"; + SlashCommand instance = (SlashCommand) command.getConstructor().newInstance(); + commandClientBuilder.addSlashCommand(instance); + } + + logger.info("Loaded %s %s successfully".formatted(typeDisplay, command.getSimpleName())); } } private static void registerListeners(final JDABuilder builder) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { logger.info("Loading Listeners"); - final Reflections classes = new Reflections("net.qsef1256.diabot"); - final Set> listeners = classes.get(SubTypes.of(ListenerAdapter.class).asClass()); + final Set> listeners = reflections.get(SubTypes.of(ListenerAdapter.class).asClass()); if (listeners.size() == 0) - logger.warn("There is no command in the registered package. No commands were loaded."); + logger.warn("There is no listener in the registered package. No listeners were loaded."); for (final Class listener : listeners) { - if (listener.isMemberClass()) continue; - ListenerAdapter slashCommand = (ListenerAdapter) listener.getConstructor().newInstance(); builder.addEventListeners(slashCommand); logger.info("Loaded " + listener.getSimpleName() + " successfully"); } } + public static void shutdown() { + jda.shutdown(); + HibernateManager.shutdown(); + } + + // Warn: 새로 만든 봇은 추적되지 않음 (직접 닫아야 함) + public static void restart() { + StringBuilder cmd = new StringBuilder(); + cmd.append(System.getProperty("java.home")) + .append(File.separator) + .append("bin") + .append(File.separator) + .append("java "); + for (String jvmArg : ManagementFactory.getRuntimeMXBean().getInputArguments()) { + cmd.append(jvmArg).append(" "); + } + cmd.append("-cp ") + .append(ManagementFactory.getRuntimeMXBean().getClassPath()) + .append(" ") + .append(DiaBot.class.getName()) + .append(" "); + for (String arg : DiaBot.args) { + cmd.append(arg).append(" "); + } + try { + Runtime.getRuntime().exec(cmd.toString()); + } catch (IOException e) { + logger.error("Failed to start bot: " + e.getMessage()); + e.printStackTrace(); + } + shutdown(); + } + } diff --git a/src/main/java/net/qsef1256/diabot/command/AdminCommand.java b/src/main/java/net/qsef1256/diabot/command/AdminCommand.java index eea5143..e53c7cb 100644 --- a/src/main/java/net/qsef1256/diabot/command/AdminCommand.java +++ b/src/main/java/net/qsef1256/diabot/command/AdminCommand.java @@ -1,11 +1,16 @@ package net.qsef1256.diabot.command; import com.jagrosh.jdautilities.command.SlashCommand; +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.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; -import net.qsef1256.diabot.database.HibernateManager; +import net.qsef1256.diabot.DiaBot; +import net.qsef1256.diabot.enums.DiaEmbed; +import net.qsef1256.diabot.enums.DiaMessage; +import org.jetbrains.annotations.NotNull; import java.util.Collections; @@ -21,13 +26,17 @@ public AdminCommand() { children = new SlashCommand[]{ new StopCommand(), - new SayCommand() + new SayCommand(), + new ClearCommand(), + new RestartCommand() }; } @Override - public void execute(final SlashCommandEvent event) { - event.reply("추가 명령어를 입력하세요! : " + getHelp()).queue(); + public void execute(final @NotNull SlashCommandEvent event) { + SlashCommand[] children = getChildren(); + + event.reply(DiaMessage.needSubCommand(children, event.getMember())).queue(); } private static class StopCommand extends SlashCommand { @@ -37,12 +46,10 @@ public StopCommand() { } @Override - public void execute(final SlashCommandEvent event) { + public void execute(final @NotNull SlashCommandEvent event) { logger.info("Shutting down with command"); - event.reply("끄는 중....").setEphemeral(true).queue((msg) -> { - event.getJDA().shutdown(); - HibernateManager.shutdown(); - }); + event.reply("끄는 중....").setEphemeral(true).queue((msg) -> + DiaBot.shutdown()); } } @@ -54,7 +61,7 @@ public SayCommand() { } @Override - public void execute(final SlashCommandEvent event) { + public void execute(final @NotNull SlashCommandEvent event) { final OptionMapping option = event.getOption("메시지"); if (option == null) { event.reply("메시지를 입력해주세요.").setEphemeral(true).queue(); @@ -65,4 +72,51 @@ public void execute(final SlashCommandEvent event) { } } + private static class ClearCommand extends SlashCommand { + + public ClearCommand() { + name = "초기화"; + help = "명령어를 초기화 하고 종료 합니다."; + } + + @Override + protected void execute(SlashCommandEvent event) { + JDA jda = DiaBot.getJda(); + String forcedGuildId = DiaBot.getCommandClient().forcedGuildId(); + + try { + jda.awaitReady(); + } catch (InterruptedException e) { + event.replyEmbeds(DiaEmbed.error(null, null, e, null).build()).queue(); + e.printStackTrace(); + return; + } + + final Guild guild = jda.getGuildById(forcedGuildId); + if (guild != null) { + logger.info("Cleaning Commands"); + guild.updateCommands().queue(); + } else { + logger.warn("forced Guild is null"); + } + + event.reply("초기화가 완료 되었습니다. 길드 ID: " + forcedGuildId).setEphemeral(true).queue(); + DiaBot.shutdown(); + } + } + + private static class RestartCommand extends SlashCommand { + + public RestartCommand() { + name = "재시작"; + help = "다봇을 재시작 합니다."; + } + + @Override + protected void execute(@NotNull SlashCommandEvent event) { + event.reply("재시작 진행 중... 새 봇은 개발 툴에서 추적되지 않으니 주의하세요.").setEphemeral(true).queue(); + DiaBot.restart(); + } + } + } diff --git a/src/main/java/net/qsef1256/diabot/command/CreditCommand.java b/src/main/java/net/qsef1256/diabot/command/CreditCommand.java index 4fd408c..1a46caa 100644 --- a/src/main/java/net/qsef1256/diabot/command/CreditCommand.java +++ b/src/main/java/net/qsef1256/diabot/command/CreditCommand.java @@ -4,11 +4,10 @@ import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.qsef1256.diabot.DiaBot; -import net.qsef1256.diabot.enums.DiaColor; -import net.qsef1256.diabot.enums.DiaImage; -import net.qsef1256.diabot.enums.DiaInfo; +import net.qsef1256.diabot.enums.*; import net.qsef1256.diabot.util.CommonUtil; import org.apache.commons.lang3.time.DurationFormatUtils; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.lang.management.ManagementFactory; @@ -27,11 +26,13 @@ public CreditCommand() { } @Override - protected void execute(final SlashCommandEvent event) { - event.reply("추가 명령어를 입력하세요! : " + getHelp()).queue(); + protected void execute(@NotNull SlashCommandEvent event) { + SlashCommand[] children = getChildren(); + + event.reply(DiaMessage.needSubCommand(children, event.getMember())).queue(); } - public static class MainInfoCommand extends SlashCommand { + private static class MainInfoCommand extends SlashCommand { public MainInfoCommand() { name = "보기"; @@ -39,17 +40,12 @@ public MainInfoCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { final Properties properties = new Properties(); try { properties.load(this.getClass().getClassLoader().getResourceAsStream("project.properties")); } catch (final IOException | RuntimeException e) { - event.replyEmbeds(new EmbedBuilder() - .setColor(DiaColor.FAIL) - .setTitle("정보 확인 실패") - .setDescription("봇 정보 확인에 실패했습니다.") - .setFooter("문제가 계속 발생할 경우 관리자를 불러주세요.") - .build()).queue(); + event.replyEmbeds(DiaEmbed.error("정보 확인 실패", "봇 정보 확인에 실패했습니다.", null, null).build()).queue(); e.printStackTrace(); return; } @@ -84,7 +80,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class LibraryCommand extends SlashCommand { + private static class LibraryCommand extends SlashCommand { public LibraryCommand() { name = "라이브러리"; @@ -92,7 +88,7 @@ public LibraryCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { event.replyEmbeds(new EmbedBuilder() .setColor(DiaColor.MAIN_COLOR) .setAuthor(DiaInfo.BOT_NAME, null, DiaImage.MAIN_THUMBNAIL) diff --git a/src/main/java/net/qsef1256/diabot/command/HelpCommand.java b/src/main/java/net/qsef1256/diabot/command/HelpCommand.java index 798fd99..733d530 100644 --- a/src/main/java/net/qsef1256/diabot/command/HelpCommand.java +++ b/src/main/java/net/qsef1256/diabot/command/HelpCommand.java @@ -3,17 +3,15 @@ import com.jagrosh.jdautilities.command.SlashCommand; import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.qsef1256.diabot.DiaBot; -import net.qsef1256.diabot.enums.DiaColor; -import net.qsef1256.diabot.enums.DiaImage; -import net.qsef1256.diabot.enums.DiaInfo; +import net.qsef1256.diabot.enums.*; import net.qsef1256.diabot.util.CommonUtil; import net.qsef1256.diabot.util.GenericUtil; +import net.qsef1256.diabot.util.JDAUtil; import org.jetbrains.annotations.NotNull; import org.yaml.snakeyaml.Yaml; @@ -74,27 +72,13 @@ private static void initHelp(@NotNull Map map) { } @Override - protected void execute(SlashCommandEvent event) { - event.reply("추가 명령어를 입력하세요! : " + getHelp()).queue(); - } + protected void execute(@NotNull SlashCommandEvent event) { + SlashCommand[] children = getChildren(); - private static boolean canExecute(SlashCommand slashCommand, Member member) { - if (slashCommand.isOwnerCommand()) { - return DiaBot.getCommandClient().getOwnerIdLong() == member.getIdLong(); - } - if (slashCommand.getEnabledRoles().length != 0) { - for (Role role : member.getRoles()) { - if (Arrays.asList(slashCommand.getEnabledRoles()).contains(role.getId())) return true; - } - return false; - } - if (slashCommand.getEnabledUsers().length != 0) { - return Arrays.asList(slashCommand.getEnabledUsers()).contains(member.getId()); - } - return true; + event.reply(DiaMessage.needSubCommand(children, event.getMember())).queue(); } - public static class MainMenuCommand extends SlashCommand { + private static class MainMenuCommand extends SlashCommand { public MainMenuCommand() { name = "전체"; @@ -102,7 +86,7 @@ public MainMenuCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { Member member = event.getMember(); if (member == null) return; @@ -119,18 +103,13 @@ protected void execute(SlashCommandEvent event) { event.replyEmbeds(embedBuilder.build()) .queue(); } catch (RuntimeException e) { - event.replyEmbeds(new EmbedBuilder() - .setTitle("오류 발생") - .setColor(DiaColor.FAIL) - .setDescription("설정 파일을 로드하는데 실패했습니다.") - .setFooter("문제가 계속될 시 관리자를 불러주세요.") - .build()).queue(); + event.replyEmbeds(DiaEmbed.error(null, "설정 파일을 로드하는데 실패했습니다.", null, null).build()).queue(); e.printStackTrace(); } } } - public static class FindCommand extends SlashCommand { + private static class FindCommand extends SlashCommand { public FindCommand() { name = "찾기"; @@ -140,7 +119,7 @@ public FindCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { Member member = event.getMember(); if (member == null) return; @@ -150,7 +129,7 @@ protected void execute(SlashCommandEvent event) { return; } EmbedBuilder embedBuilder = new EmbedBuilder(); - embedBuilder.setAuthor(DiaInfo.BOT_NAME,null,DiaImage.MAIN_THUMBNAIL); + embedBuilder.setAuthor(DiaInfo.BOT_NAME, null, DiaImage.MAIN_THUMBNAIL); Map map = categories.get(option.getAsString()); if (map == null) { @@ -168,11 +147,7 @@ protected void execute(SlashCommandEvent event) { event.replyEmbeds(embedBuilder.build()).queue(); } catch (RuntimeException e) { logger.warn(e.getMessage()); - event.replyEmbeds(new EmbedBuilder() - .setTitle("오류 발생") - .setColor(DiaColor.FAIL) - .setDescription(option.getAsString() + " 카테고리 로딩중 오류가 발생했어요.") - .setFooter("문제가 계속될 시 관리자를 불러주세요.") + event.replyEmbeds(DiaEmbed.error(null, option.getAsString() + " 카테고리 로딩중 오류가 발생했어요.", null, null) .build()).queue(); } } @@ -192,7 +167,7 @@ private static void buildEmbed(@NotNull EmbedBuilder embedBuilder, @NotNull Map< if (value instanceof Map values) { String subTitle = Optional.ofNullable(values.get("TITLE").toString()).orElse("제목 없음"); String subDesc = Optional.ofNullable(values.get("DESC").toString()).orElse("내용 없음"); - embedBuilder.addField("-" + subTitle,subDesc,false); + embedBuilder.addField("-" + subTitle, subDesc, false); } }); } @@ -200,7 +175,7 @@ private static void buildEmbed(@NotNull EmbedBuilder embedBuilder, @NotNull Map< ArrayList list = GenericUtil.getArrayList(map.get("LIST")); list.forEach(className -> { SlashCommand command = slashCommandMap.get(className.toString()); - if (!canExecute(command, member)) return; + if (!JDAUtil.canExecute(command, member)) return; String commandName = command.getName(); String commandHelp = command.getHelp(); embedBuilder.addField("/" + commandName, commandHelp, false); diff --git a/src/main/java/net/qsef1256/diabot/command/PingCommand.java b/src/main/java/net/qsef1256/diabot/command/PingCommand.java index 0fb1692..b62d700 100644 --- a/src/main/java/net/qsef1256/diabot/command/PingCommand.java +++ b/src/main/java/net/qsef1256/diabot/command/PingCommand.java @@ -2,6 +2,7 @@ import com.jagrosh.jdautilities.command.SlashCommand; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import org.jetbrains.annotations.NotNull; public class PingCommand extends SlashCommand { public PingCommand() { @@ -10,7 +11,7 @@ public PingCommand() { } @Override - public void execute(SlashCommandEvent event) { + public void execute(@NotNull SlashCommandEvent event) { long time = System.currentTimeMillis(); event.deferReply() .queue(response -> response.editOriginal(String.format("퐁! `%d ms`", System.currentTimeMillis() - time)).queue()); diff --git a/src/main/java/net/qsef1256/diabot/command/RuleCommand.java b/src/main/java/net/qsef1256/diabot/command/RuleCommand.java index 33e1bd5..b90c653 100644 --- a/src/main/java/net/qsef1256/diabot/command/RuleCommand.java +++ b/src/main/java/net/qsef1256/diabot/command/RuleCommand.java @@ -6,6 +6,7 @@ import net.qsef1256.diabot.enums.DiaColor; import net.qsef1256.diabot.enums.DiaImage; import net.qsef1256.diabot.enums.DiaInfo; +import org.jetbrains.annotations.NotNull; public class RuleCommand extends SlashCommand { @@ -15,7 +16,7 @@ public RuleCommand() { } @Override - protected void execute(final SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { event.replyEmbeds(new EmbedBuilder() .setAuthor(DiaInfo.BOT_NAME, null, DiaImage.MAIN_THUMBNAIL) .setColor(DiaColor.MAIN_COLOR) @@ -24,7 +25,9 @@ protected void execute(final SlashCommandEvent event) { .appendDescription(":two: 버그 악용 금지, 발견하면 DM 으로 연락해주세요.\n") .appendDescription(":three: 언제든지 데이터는 손실/초기화/삭제 될 수 있어요.\n") .appendDescription(":four: 곡괭이 자꾸 들이대면 폭탄 터트릴꺼에요.\n") - .appendDescription(":five: 재밌게 노세요!\n") + .appendDescription(":five: 본체는 아무 생각이 없어요.\n") + .appendDescription(":six: 사용자 식별을 위해 디코 ID를 저장하고 있습니다.") // TODO: 개인정보 처리방침 + .appendDescription(":seven: 재밌게 노세요!\n") .setFooter("사실 규칙은 반쯤 장식이에요.") .build()).queue(); } diff --git a/src/main/java/net/qsef1256/diabot/command/fun/AnvilCommand.java b/src/main/java/net/qsef1256/diabot/command/fun/AnvilCommand.java index b40cdad..0abc0ab 100644 --- a/src/main/java/net/qsef1256/diabot/command/fun/AnvilCommand.java +++ b/src/main/java/net/qsef1256/diabot/command/fun/AnvilCommand.java @@ -7,6 +7,7 @@ import net.qsef1256.diabot.enums.DiaImage; import net.qsef1256.diabot.model.CmdStatistic; import net.qsef1256.diabot.util.CommonUtil; +import org.jetbrains.annotations.NotNull; import java.awt.*; @@ -18,7 +19,7 @@ public AnvilCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { if (event.getMember() == null) return; User user = event.getUser(); CmdStatistic statistic = new CmdStatistic(getClass()); diff --git a/src/main/java/net/qsef1256/diabot/command/fun/AsdfCommand.java b/src/main/java/net/qsef1256/diabot/command/fun/AsdfCommand.java index 81a3fba..cdb5f04 100644 --- a/src/main/java/net/qsef1256/diabot/command/fun/AsdfCommand.java +++ b/src/main/java/net/qsef1256/diabot/command/fun/AsdfCommand.java @@ -8,6 +8,7 @@ import net.qsef1256.diabot.model.CmdStatistic; import net.qsef1256.diabot.util.ColorUtil; import net.qsef1256.diabot.util.CommonUtil; +import org.jetbrains.annotations.NotNull; import java.util.Arrays; @@ -19,7 +20,7 @@ public AsdfCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { CmdStatistic statistic = new CmdStatistic(getClass()); diff --git a/src/main/java/net/qsef1256/diabot/command/fun/StupudCommand.java b/src/main/java/net/qsef1256/diabot/command/fun/StupudCommand.java index b7b5217..63845ae 100644 --- a/src/main/java/net/qsef1256/diabot/command/fun/StupudCommand.java +++ b/src/main/java/net/qsef1256/diabot/command/fun/StupudCommand.java @@ -5,9 +5,9 @@ import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.qsef1256.diabot.enums.DiaColor; -import net.qsef1256.diabot.enums.DiaImage; import net.qsef1256.diabot.model.CmdStatistic; import net.qsef1256.diabot.util.CommonUtil; +import org.jetbrains.annotations.NotNull; import java.util.Arrays; @@ -19,7 +19,7 @@ public StupudCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { if (event.getMember() == null) return; User user = event.getUser(); CmdStatistic statistic = new CmdStatistic(getClass()); diff --git a/src/main/java/net/qsef1256/diabot/command/fun/emoji/CreeperCommand.java b/src/main/java/net/qsef1256/diabot/command/fun/emoji/CreeperCommand.java index 24880a6..ae8c37f 100644 --- a/src/main/java/net/qsef1256/diabot/command/fun/emoji/CreeperCommand.java +++ b/src/main/java/net/qsef1256/diabot/command/fun/emoji/CreeperCommand.java @@ -2,6 +2,7 @@ import com.jagrosh.jdautilities.command.SlashCommand; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import org.jetbrains.annotations.NotNull; public class CreeperCommand extends SlashCommand { @@ -11,7 +12,7 @@ public CreeperCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { String creeperArt = """ 🟩✳️🟩🟩⬜🟩🟩⬛ diff --git a/src/main/java/net/qsef1256/diabot/command/fun/encrypt/MD5Command.java b/src/main/java/net/qsef1256/diabot/command/fun/encrypt/MD5Command.java index 9f07d8f..47dcc5b 100644 --- a/src/main/java/net/qsef1256/diabot/command/fun/encrypt/MD5Command.java +++ b/src/main/java/net/qsef1256/diabot/command/fun/encrypt/MD5Command.java @@ -8,6 +8,8 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.qsef1256.diabot.enums.DiaColor; +import net.qsef1256.diabot.enums.DiaEmbed; +import org.jetbrains.annotations.NotNull; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -23,7 +25,8 @@ public MD5Command() { options = Collections.singletonList(new OptionData(OptionType.STRING, "메시지", "시킬 말").setRequired(true)); } - public static String toMD5(String content) throws NoSuchAlgorithmException { + @NotNull + public static String toMD5(@NotNull String content) throws NoSuchAlgorithmException { MessageDigest md = MessageDigest.getInstance("MD5"); md.update(content.getBytes()); byte[] byteData = md.digest(); @@ -35,7 +38,7 @@ public static String toMD5(String content) throws NoSuchAlgorithmException { } @Override - public void execute(final SlashCommandEvent event) { + public void execute(final @NotNull SlashCommandEvent event) { if (event.getMember() == null) return; User user = event.getUser(); @@ -54,10 +57,7 @@ public void execute(final SlashCommandEvent event) { .build()).queue(); } catch (RuntimeException | NoSuchAlgorithmException e) { logger.warn(e.getMessage()); - event.replyEmbeds(new EmbedBuilder() - .setColor(DiaColor.FAIL) - .setTitle("문제 발생") - .setDescription("주어진 문자열을 MD5로 변환하던 도중 문제가 생겼습니다.") + event.replyEmbeds(DiaEmbed.error(null, "주어진 문자열을 MD5로 변환하던 도중 문제가 생겼습니다.", null, null) .setFooter("뭘 넣었길래...") .build()).queue(); } diff --git a/src/main/java/net/qsef1256/diabot/command/fun/encrypt/SHA256Command.java b/src/main/java/net/qsef1256/diabot/command/fun/encrypt/SHA256Command.java index f566fd9..8be4230 100644 --- a/src/main/java/net/qsef1256/diabot/command/fun/encrypt/SHA256Command.java +++ b/src/main/java/net/qsef1256/diabot/command/fun/encrypt/SHA256Command.java @@ -8,6 +8,8 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.qsef1256.diabot.enums.DiaColor; +import net.qsef1256.diabot.enums.DiaEmbed; +import org.jetbrains.annotations.NotNull; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; @@ -24,7 +26,8 @@ public SHA256Command() { options = Collections.singletonList(new OptionData(OptionType.STRING, "메시지", "시킬 말").setRequired(true)); } - public static String toSHA256(String content) throws NoSuchAlgorithmException { + @NotNull + public static String toSHA256(@NotNull String content) throws NoSuchAlgorithmException { MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hash = digest.digest(content.getBytes(StandardCharsets.UTF_8)); StringBuilder hexString = new StringBuilder(); @@ -37,7 +40,7 @@ public static String toSHA256(String content) throws NoSuchAlgorithmException { } @Override - public void execute(final SlashCommandEvent event) { + public void execute(final @NotNull SlashCommandEvent event) { if (event.getMember() == null) return; User user = event.getUser(); @@ -56,10 +59,7 @@ public void execute(final SlashCommandEvent event) { .build()).queue(); } catch (RuntimeException | NoSuchAlgorithmException e) { logger.warn(e.getMessage()); - event.replyEmbeds(new EmbedBuilder() - .setColor(DiaColor.FAIL) - .setTitle("문제 발생") - .setDescription("주어진 문자열을 SHA-256로 변환하던 도중 문제가 생겼습니다.") + event.replyEmbeds(DiaEmbed.error(null, "주어진 문자열을 SHA-256로 변환하던 도중 문제가 생겼습니다.", null, null) .setFooter("뭘 넣었길래...") .build()).queue(); } diff --git a/src/main/java/net/qsef1256/diabot/database/HikariPoolManager.java b/src/main/java/net/qsef1256/diabot/database/HikariPoolManager.java deleted file mode 100644 index a5a877e..0000000 --- a/src/main/java/net/qsef1256/diabot/database/HikariPoolManager.java +++ /dev/null @@ -1,74 +0,0 @@ -package net.qsef1256.diabot.database; - -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; - -// Hibernate 로 변경됨 -@Deprecated -public class HikariPoolManager { - - /*@Getter - private static final HikariPoolManager instance;*/ - private final HikariDataSource dataSource; - - private static final Logger log = LoggerFactory.getLogger(HikariPoolManager.class.getSimpleName()); - private static final HikariConfig config = new HikariConfig(); - - private String hostname; - private int port; - private String database; - private String username; - private String password; - - /*static { - instance = new HikariPoolManager(); - }*/ - - private HikariPoolManager() { - setJdbcInfo(); - - config.setJdbcUrl( - "jdbc:mysql://" + hostname + ":" + port + "/" + database - ); - - config.setDriverClassName("com.mysql.cj.jdbc.Driver"); - config.setUsername(username); - config.setPassword(password); - dataSource = new HikariDataSource(config); - } - - private void setJdbcInfo() { - hostname = "localhost"; - port = 3306; - database = "diabot"; - username = "root"; - password = "1234"; - } - - public Connection getConnection() throws SQLException { - return dataSource.getConnection(); - } - - public void close(Connection conn, PreparedStatement ps, ResultSet res) { - if (conn != null) try { - conn.close(); - } catch (SQLException ignored) { - } - if (ps != null) try { - ps.close(); - } catch (SQLException ignored) { - } - if (res != null) try { - res.close(); - } catch (SQLException ignored) { - } - } - -} diff --git a/src/main/java/net/qsef1256/diabot/enums/DiaMessage.java b/src/main/java/net/qsef1256/diabot/enums/DiaMessage.java new file mode 100644 index 0000000..a4a79d3 --- /dev/null +++ b/src/main/java/net/qsef1256/diabot/enums/DiaMessage.java @@ -0,0 +1,34 @@ +package net.qsef1256.diabot.enums; + +import com.jagrosh.jdautilities.command.SlashCommand; +import net.dv8tion.jda.api.entities.Member; +import net.qsef1256.diabot.util.JDAUtil; +import org.jetbrains.annotations.NotNull; + +public class DiaMessage { + + /** + * 추가 명령어 필요 안내 메시지를 얻습니다. + * + * @param children sub commands + * @param member executing member + * @return 추가 명령어를 입력하세요! : 추가, 삭제 + */ + @NotNull + public static String needSubCommand(SlashCommand @NotNull [] children, Member member) { + String[] childNames = new String[children.length]; + + int i = 0; + for (SlashCommand child : children) { + if (JDAUtil.canExecute(child, member)) childNames[i] = child.getName(); + i++; + } + return "추가 명령어를 입력하세요! : " + String.join(", ", childNames); + } + + @NotNull + public static String underConstruction() { + return ":construction: 공사중..."; + } + +} diff --git a/src/main/java/net/qsef1256/diabot/game/explosion/command/ExplosionCommand.java b/src/main/java/net/qsef1256/diabot/game/explosion/command/ExplosionCommand.java index 48eae5f..d9dfb62 100644 --- a/src/main/java/net/qsef1256/diabot/game/explosion/command/ExplosionCommand.java +++ b/src/main/java/net/qsef1256/diabot/game/explosion/command/ExplosionCommand.java @@ -2,6 +2,8 @@ import com.jagrosh.jdautilities.command.SlashCommand; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.qsef1256.diabot.enums.DiaMessage; +import org.jetbrains.annotations.NotNull; public class ExplosionCommand extends SlashCommand { @@ -13,8 +15,8 @@ public ExplosionCommand() { } @Override - protected void execute(final SlashCommandEvent event) { - event.reply("준비 중! : " + getHelp()).queue(); + protected void execute(@NotNull SlashCommandEvent event) { + event.reply(DiaMessage.underConstruction()).queue(); } } diff --git a/src/main/java/net/qsef1256/diabot/game/explosion/command/InventoryCommand.java b/src/main/java/net/qsef1256/diabot/game/explosion/command/InventoryCommand.java index 40614b5..2a5c296 100644 --- a/src/main/java/net/qsef1256/diabot/game/explosion/command/InventoryCommand.java +++ b/src/main/java/net/qsef1256/diabot/game/explosion/command/InventoryCommand.java @@ -4,11 +4,21 @@ import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; +import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData; +import net.dv8tion.jda.api.utils.data.DataObject; import net.qsef1256.diabot.enums.DiaColor; +import net.qsef1256.diabot.enums.DiaEmbed; +import net.qsef1256.diabot.enums.DiaMessage; import net.qsef1256.diabot.game.explosion.data.ItemTypeEntity; +import net.qsef1256.diabot.game.explosion.model.Cash; import net.qsef1256.diabot.game.explosion.model.Inventory; import org.jetbrains.annotations.NotNull; +import java.util.List; + public class InventoryCommand extends SlashCommand { public InventoryCommand() { @@ -17,16 +27,20 @@ public InventoryCommand() { children = new SlashCommand[]{ new SeeCommand(), - new ItemCommand() + new ItemInfoCommand(), + new ItemAddCommand(), + new ItemRemoveCommand() }; + + subcommandGroup = new ItemCommandGroup(); } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { event.reply("추가 명령어를 입력하세요! : " + getHelp()).queue(); } - public static class SeeCommand extends SlashCommand { + private static class SeeCommand extends SlashCommand { public SeeCommand() { name = "보기"; @@ -34,40 +48,124 @@ public SeeCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { User user = event.getUser(); - event.replyEmbeds(getEmbedBuilder(user).build()).queue(); + try { + event.replyEmbeds(getInventoryEmbed(user).build()).queue(); + } catch (RuntimeException e) { + event.replyEmbeds(DiaEmbed.error("인벤토리 로드 실패", null, e, user).build()).queue(); + } } @NotNull - private EmbedBuilder getEmbedBuilder(User user) { + private EmbedBuilder getInventoryEmbed(@NotNull User user) { + final Cash cash = new Cash(user.getIdLong()); + EmbedBuilder embedBuilder = new EmbedBuilder() .setAuthor(user.getName(), null, user.getEffectiveAvatarUrl()) .setColor(DiaColor.INFO) .setTitle("%s의 인벤토리".formatted(user.getName())); - new Inventory(user.getIdLong()).getItems().forEach((id, item) -> { + StringBuilder items = new StringBuilder(); + Inventory.fromUser(user.getIdLong()).getItems().forEach((id, item) -> { ItemTypeEntity itemType = item.getItemType(); - + String itemInfo = "%s : %s > %s개".formatted(itemType.getItemName(), itemType.getItemRank(), item.getAmount()); + items.append(itemInfo); + items.append("\n"); }); + embedBuilder.addField("아이템 목록", items.toString(), false); + embedBuilder.addField(":moneybag:돈", cash.getCash() + " 캐시", true); + embedBuilder.addField(":gem:보유 다이아", cash.getPickaxeCount() + " 개", true); + return embedBuilder; } } - public static class ItemCommand extends SlashCommand { + private static class ItemCommandGroup extends SubcommandGroupData { + + public ItemCommandGroup() { + super("아이템", "아이템의 정보를 확인하거나 사용합니다."); + + addSubcommands(SubcommandData.fromData(new ItemInfoCommand().getData())); + addSubcommands(SubcommandData.fromData(new ItemAddCommand().getData())); + addSubcommands(SubcommandData.fromData(new ItemRemoveCommand().getData())); + } + } + + private static class ItemInfoCommand extends SlashCommand { + public ItemInfoCommand() { + name = "정보"; + help = "아이템 정보를 확인합니다."; - public ItemCommand() { - name = "아이템"; - help = "아이템의 정보를 확인하거나 사용합니다."; + options = List.of( + new OptionData(OptionType.STRING, "이름", "아이템 이름") + ); } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { + event.reply(DiaMessage.underConstruction()).queue(); + } + + @NotNull + public DataObject getData() { + return buildCommandData().toData(); + } + } + + private static class ItemAddCommand extends SlashCommand { + + public ItemAddCommand() { + name = "추가"; + help = "관리용 치트"; + ownerCommand = true; + } + @Override + protected void execute(@NotNull SlashCommandEvent event) { + User user = event.getUser(); + + try { + Inventory.fromUser(user.getIdLong()).addItem(1); + } catch (RuntimeException e) { + e.printStackTrace(); + event.replyEmbeds(DiaEmbed.error(null, null, e, user).build()).queue(); + } + } + + @NotNull + public DataObject getData() { + return buildCommandData().toData(); } } + private static class ItemRemoveCommand extends SlashCommand { + + public ItemRemoveCommand() { + name = "삭제"; + help = "관리용 치트"; + ownerCommand = true; + } + + @Override + protected void execute(SlashCommandEvent event) { + User user = event.getUser(); + + try { + Inventory.fromUser(user.getIdLong()).removeItem(1); + } catch (RuntimeException e) { + e.printStackTrace(); + event.replyEmbeds(DiaEmbed.error(null, null, e, user).build()).queue(); + } + + } + + @NotNull + public DataObject getData() { + return buildCommandData().toData(); + } + } } diff --git a/src/main/java/net/qsef1256/diabot/game/explosion/command/PickaxeCommand.java b/src/main/java/net/qsef1256/diabot/game/explosion/command/PickaxeCommand.java index 67d5522..e49a1f7 100644 --- a/src/main/java/net/qsef1256/diabot/game/explosion/command/PickaxeCommand.java +++ b/src/main/java/net/qsef1256/diabot/game/explosion/command/PickaxeCommand.java @@ -5,6 +5,7 @@ import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.qsef1256.diabot.game.explosion.model.Cash; import net.qsef1256.diabot.util.CommonUtil; +import org.jetbrains.annotations.NotNull; import java.util.NoSuchElementException; @@ -16,12 +17,12 @@ public PickaxeCommand() { } @Override - protected void execute(final SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { final User user = event.getUser(); event.deferReply().queue(callback -> { try { - final Cash explosionUser = new Cash(user.getIdLong()); + final Cash cash = new Cash(user.getIdLong()); final String status; final int pickaxeCount; @@ -50,10 +51,10 @@ protected void execute(final SlashCommandEvent event) { } } - explosionUser.addPickaxeCount(pickaxeCount); + cash.addPickaxeCount(pickaxeCount); String pickaxeCountDisplay = (pickaxeCount > 0) ? "+" + pickaxeCount : String.valueOf(pickaxeCount); - callback.editOriginal(status + "`" + pickaxeCountDisplay + "` 다이아 보유량: `" + explosionUser.getPickaxeCount() + "` 개").queue(); + callback.editOriginal(status + "`" + pickaxeCountDisplay + "` 다이아 보유량: `" + cash.getPickaxeCount() + "` 개").queue(); } catch (RuntimeException e) { String message = ":warning: " + user.getAsTag() + " 는 손이 미끄러져 다이아를 캐지 못했습니다!\n\n오류: " + e.getMessage(); diff --git a/src/main/java/net/qsef1256/diabot/game/explosion/command/ShopCommand.java b/src/main/java/net/qsef1256/diabot/game/explosion/command/ShopCommand.java index 70f6e30..71b7280 100644 --- a/src/main/java/net/qsef1256/diabot/game/explosion/command/ShopCommand.java +++ b/src/main/java/net/qsef1256/diabot/game/explosion/command/ShopCommand.java @@ -2,6 +2,8 @@ import com.jagrosh.jdautilities.command.SlashCommand; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; +import net.qsef1256.diabot.enums.DiaMessage; +import org.jetbrains.annotations.NotNull; public class ShopCommand extends SlashCommand { @@ -11,10 +13,8 @@ public ShopCommand() { } @Override - protected void execute(SlashCommandEvent event) { - event.reply(":construction: 공사중...").queue(); - - + protected void execute(@NotNull SlashCommandEvent event) { + event.reply(DiaMessage.underConstruction()).queue(); } } diff --git a/src/main/java/net/qsef1256/diabot/game/explosion/data/InventoryEntity.java b/src/main/java/net/qsef1256/diabot/game/explosion/data/InventoryEntity.java index acdf112..97e1c19 100644 --- a/src/main/java/net/qsef1256/diabot/game/explosion/data/InventoryEntity.java +++ b/src/main/java/net/qsef1256/diabot/game/explosion/data/InventoryEntity.java @@ -2,16 +2,20 @@ import lombok.Getter; import lombok.Setter; +import lombok.experimental.Accessors; import net.qsef1256.diabot.system.account.data.AccountEntity; import org.hibernate.Hibernate; +import org.jetbrains.annotations.NotNull; import javax.persistence.*; import java.io.Serializable; +import java.util.HashMap; import java.util.Map; import java.util.Objects; @Getter @Setter +@Accessors(chain = true) @Entity @Table(name = "user_inventory") public class InventoryEntity implements Serializable { @@ -24,18 +28,18 @@ public class InventoryEntity implements Serializable { @JoinColumn(name = "discord_id") private AccountEntity discordUser; - @OneToMany - private Map items; + @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) + private Map items = new HashMap<>(); public ItemEntity getItem(int itemId) { return items.get(itemId); } - public void setItem(ItemEntity item) { + public void putItem(ItemEntity item) { items.put(item.getItemId(), item); } - public void removeItem(ItemEntity item) { + public void removeItem(@NotNull ItemEntity item) { items.remove(item.getItemId()); } diff --git a/src/main/java/net/qsef1256/diabot/game/explosion/data/ItemEntity.java b/src/main/java/net/qsef1256/diabot/game/explosion/data/ItemEntity.java index e6c8858..be13ec3 100644 --- a/src/main/java/net/qsef1256/diabot/game/explosion/data/ItemEntity.java +++ b/src/main/java/net/qsef1256/diabot/game/explosion/data/ItemEntity.java @@ -21,14 +21,11 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class ItemEntity implements Serializable { - @ManyToOne - private InventoryEntity userInventory; - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; - @OneToOne(fetch = FetchType.LAZY) + @OneToOne(fetch = FetchType.EAGER) private ItemTypeEntity itemType; @Column diff --git a/src/main/java/net/qsef1256/diabot/game/explosion/model/Inventory.java b/src/main/java/net/qsef1256/diabot/game/explosion/model/Inventory.java index 9ef3bc5..b4ad0de 100644 --- a/src/main/java/net/qsef1256/diabot/game/explosion/model/Inventory.java +++ b/src/main/java/net/qsef1256/diabot/game/explosion/model/Inventory.java @@ -7,18 +7,35 @@ import net.qsef1256.diabot.game.explosion.data.ItemEntity; import net.qsef1256.diabot.game.explosion.data.ItemTypeEntity; import net.qsef1256.diabot.system.account.data.AccountEntity; +import net.qsef1256.diabot.system.account.model.AccountManager; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; import java.util.Map; public class Inventory { - protected final DaoCommon dao = new DaoCommonImpl<>(InventoryEntity.class); + protected static final DaoCommon dao = new DaoCommonImpl<>(AccountEntity.class); @Getter private final InventoryEntity data; public Inventory(long discord_id) { - data = dao.findById(discord_id); + AccountEntity account = AccountManager.getAccount(discord_id); + + InventoryEntity inventory = account.getInventory(); + if (inventory == null) { + inventory = new InventoryEntity().setDiscordUser(account); + + account.setInventory(inventory); + dao.update(account); + } + data = inventory; + } + + @Contract("_ -> new") + public static @NotNull Inventory fromUser(long discord_id) { + return new Inventory(discord_id); } public AccountEntity getUser() { @@ -38,7 +55,7 @@ public ItemEntity getItem(int itemId) { } public void setItem(ItemEntity item) { - data.setItem(item); + data.putItem(item); } public void addItem(int itemId) { @@ -49,14 +66,28 @@ public void addItem(int itemId, int amount) { ItemEntity userItem = data.getItem(itemId); Item item = Item.fromId(itemId, amount); + if (userItem == null) { + createItem(itemId, amount); + return; + } int maxAmount = item.getMaxAmount(); int stock = userItem.getAmount(); - int result = stock + amount; - if (result < maxAmount) - throw new IllegalArgumentException("%s 아이템을 더 보유할 수 없습니다. 최대: %s".formatted(item.getName(), maxAmount)); + if (result > maxAmount) + throw new IllegalArgumentException("%s 아이템을 더 보유할 수 없습니다. 현재: %s, 최대: %s".formatted(item.getName(), result, maxAmount)); - data.setItem(Item.fromId(itemId).getItemEntity()); + userItem.setAmount(result); + data.putItem(userItem); + update(); + } + + private void createItem(int itemId) { + createItem(itemId, 1); + } + + private void createItem(int itemId, int amount) { + ItemEntity itemEntity = Item.fromId(itemId, amount).getItemEntity(); + data.putItem(itemEntity); update(); } @@ -76,7 +107,7 @@ public void removeItem(int itemId, int amount) { if (result == 0) clearItem(itemId); else { userItem.setAmount(result); - data.setItem(userItem); + data.putItem(userItem); update(); } } @@ -93,7 +124,10 @@ private ItemTypeEntity getItemType(Integer itemId) { } private void update() { - dao.update(data); + AccountEntity account = data.getDiscordUser(); + + account.setInventory(data); + dao.update(account); } } diff --git a/src/main/java/net/qsef1256/diabot/game/explosion/model/Shop.java b/src/main/java/net/qsef1256/diabot/game/explosion/model/Shop.java index afc6529..4a3bb6f 100644 --- a/src/main/java/net/qsef1256/diabot/game/explosion/model/Shop.java +++ b/src/main/java/net/qsef1256/diabot/game/explosion/model/Shop.java @@ -3,6 +3,7 @@ import net.qsef1256.diabot.database.DaoCommon; import net.qsef1256.diabot.database.DaoCommonImpl; import net.qsef1256.diabot.game.explosion.data.ShopEntity; +import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.Map; @@ -11,7 +12,7 @@ public class Shop { protected static final DaoCommon dao = new DaoCommonImpl<>(ShopEntity.class); - public static long getPrice(Item item) { + public static long getPrice(@NotNull Item item) { Map constraint = new HashMap<>(); constraint.put("ownerId", item.getItemId()); ShopEntity shopEntity = dao.findBy(constraint).get(0); diff --git a/src/main/java/net/qsef1256/diabot/game/omok/command/OmokCommand.java b/src/main/java/net/qsef1256/diabot/game/omok/command/OmokCommand.java index 782637f..dedf33f 100644 --- a/src/main/java/net/qsef1256/diabot/game/omok/command/OmokCommand.java +++ b/src/main/java/net/qsef1256/diabot/game/omok/command/OmokCommand.java @@ -8,11 +8,9 @@ import net.dv8tion.jda.api.interactions.commands.OptionMapping; import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; -import net.qsef1256.diabot.enums.DiaColor; -import net.qsef1256.diabot.enums.DiaEmbed; -import net.qsef1256.diabot.enums.DiaImage; -import net.qsef1256.diabot.enums.DiaInfo; +import net.qsef1256.diabot.enums.*; import net.qsef1256.diabot.game.omok.model.OmokManager; +import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.concurrent.TimeUnit; @@ -34,11 +32,13 @@ public OmokCommand() { } @Override - protected void execute(SlashCommandEvent event) { - event.reply("추가 명령어를 입력하세요! : " + getHelp()).queue(); + protected void execute(@NotNull SlashCommandEvent event) { + SlashCommand[] children = getChildren(); + + event.reply(DiaMessage.needSubCommand(children, event.getMember())).queue(); } - public static class GameRuleCommand extends SlashCommand { + private static class GameRuleCommand extends SlashCommand { public GameRuleCommand() { name = "규칙"; @@ -46,7 +46,7 @@ public GameRuleCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { event.replyEmbeds(new EmbedBuilder() .setColor(DiaColor.MAIN_COLOR) .setAuthor(DiaInfo.BOT_NAME, null, DiaImage.MAIN_THUMBNAIL) @@ -58,7 +58,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class StartCommand extends SlashCommand { + private static class StartCommand extends SlashCommand { public StartCommand() { name = "시작"; @@ -70,7 +70,7 @@ public StartCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { OptionMapping userOption = event.getOption("상대"); if (userOption == null) { event.reply("대국을 신청할 유저를 입력해주세요!").queue(); @@ -96,7 +96,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class PlaceCommand extends SlashCommand { + private static class PlaceCommand extends SlashCommand { public PlaceCommand() { name = "놓기"; @@ -109,7 +109,7 @@ public PlaceCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { User user = event.getUser(); OptionMapping optionX = event.getOption("x"); OptionMapping optionY = event.getOption("y"); @@ -132,7 +132,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class ResignCommand extends SlashCommand { + private static class ResignCommand extends SlashCommand { public ResignCommand() { name = "기권"; @@ -140,7 +140,7 @@ public ResignCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { User user = event.getUser(); try { @@ -153,7 +153,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class PullCommand extends SlashCommand { + private static class PullCommand extends SlashCommand { public PullCommand() { name = "끌올"; @@ -161,7 +161,7 @@ public PullCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { User user = event.getUser(); MessageChannel channel = event.getChannel(); @@ -175,7 +175,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class LogCommand extends SlashCommand { + private static class LogCommand extends SlashCommand { public LogCommand() { name = "로그"; @@ -183,7 +183,7 @@ public LogCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { User user = event.getUser(); try { diff --git a/src/main/java/net/qsef1256/diabot/game/paint/command/GalleryCommand.java b/src/main/java/net/qsef1256/diabot/game/paint/command/GalleryCommand.java index 3533304..0fed5be 100644 --- a/src/main/java/net/qsef1256/diabot/game/paint/command/GalleryCommand.java +++ b/src/main/java/net/qsef1256/diabot/game/paint/command/GalleryCommand.java @@ -8,13 +8,12 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.dv8tion.jda.api.interactions.components.Button; -import net.qsef1256.diabot.enums.DiaColor; -import net.qsef1256.diabot.enums.DiaImage; -import net.qsef1256.diabot.enums.DiaInfo; +import net.qsef1256.diabot.enums.*; import net.qsef1256.diabot.game.paint.data.PaintEntity; import net.qsef1256.diabot.game.paint.model.PaintManagerImpl; import net.qsef1256.diabot.game.paint.model.painter.Painter; import net.qsef1256.diabot.game.paint.model.painter.PainterContainer; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -35,7 +34,7 @@ public GalleryCommand() { }; } - private static void printPaint(SlashCommandEvent event, String paintName, Painter painter) { + private static void printPaint(@NotNull SlashCommandEvent event, String paintName, @NotNull Painter painter) { event.replyEmbeds(new EmbedBuilder() .setAuthor(DiaInfo.BOT_NAME, null, DiaImage.MAIN_THUMBNAIL) .setColor(DiaColor.MAIN_COLOR) @@ -52,29 +51,23 @@ private static void applyPainter(SlashCommandEvent event, User user, String pain printPaint(event, paintName, painter); } catch (IllegalArgumentException e) { - event.replyEmbeds(new EmbedBuilder() - .setTitle("오류 발생") - .setColor(DiaColor.FAIL) - .setDescription("오류: " + e.getMessage()) + event.replyEmbeds(DiaEmbed.error(null, null, e, user) .setFooter("그림이 없거나 권한이 없을 수 있어요.") .build()).queue(); } catch (RuntimeException e) { logger.warn(e.getMessage()); - event.replyEmbeds(new EmbedBuilder() - .setColor(DiaColor.FAIL) - .setTitle("오류 발생") - .setDescription("그림을 저장하던 도중 문제가 발생했습니다.") - .setFooter("문제가 계속될 시 관리자를 불러주세요.") - .build()).queue(); + event.replyEmbeds(DiaEmbed.error(null, "그림을 저장하던 도중 문제가 발생했습니다.", e, user).build()).queue(); } } @Override - protected void execute(SlashCommandEvent event) { - event.reply("추가 명령어를 입력하세요! : " + getHelp()).queue(); + protected void execute(@NotNull SlashCommandEvent event) { + SlashCommand[] children = getChildren(); + + event.reply(DiaMessage.needSubCommand(children, event.getMember())).queue(); } - public static class ShowCommand extends SlashCommand { + private static class ShowCommand extends SlashCommand { public ShowCommand() { name = "보기"; @@ -86,7 +79,7 @@ public ShowCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { OptionMapping paintNameOption = event.getOption("이름"); User user = event.getUser(); @@ -102,7 +95,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class SaveCommand extends SlashCommand { + private static class SaveCommand extends SlashCommand { public SaveCommand() { name = "저장"; @@ -114,7 +107,7 @@ public SaveCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { OptionMapping paintNameOption = event.getOption("이름"); User user = event.getUser(); @@ -148,17 +141,12 @@ protected void execute(SlashCommandEvent event) { .queue(); } catch (RuntimeException e) { logger.warn(e.getMessage()); - event.replyEmbeds(new EmbedBuilder() - .setColor(DiaColor.FAIL) - .setTitle("오류 발생") - .setDescription("그림을 저장하던 도중 문제가 발생했습니다.") - .setFooter("문제가 계속될 시 관리자를 불러주세요.") - .build()).queue(); + event.replyEmbeds(DiaEmbed.error(null, "그림을 저장하던 도중 문제가 발생했습니다.", e, user).build()).queue(); } } } - public static class DeleteCommand extends SlashCommand { + private static class DeleteCommand extends SlashCommand { public DeleteCommand() { name = "삭제"; @@ -170,7 +158,7 @@ public DeleteCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { OptionMapping paintNameOption = event.getOption("이름"); User user = event.getUser(); @@ -183,32 +171,21 @@ protected void execute(SlashCommandEvent event) { try { new PaintManagerImpl().delete(user.getIdLong(), paintName); - event.replyEmbeds(new EmbedBuilder() - .setColor(DiaColor.SUCCESS) - .setTitle("삭제 성공") - .setDescription(paintName + "그림이 성공적으로 삭제 되었습니다.") + event.replyEmbeds(DiaEmbed.success("삭제 성공", paintName + "그림이 성공적으로 삭제 되었습니다.", user) .setFooter("하드 용량 절약 성공") .build()).queue(); } catch (IllegalArgumentException e) { - event.replyEmbeds(new EmbedBuilder() - .setColor(DiaColor.FAIL) - .setTitle("삭제 실패") - .setDescription(paintName + "그림을 삭제 하는데 실패 했습니다: " + e.getMessage()) + event.replyEmbeds(DiaEmbed.fail("삭제 실패", paintName + "그림을 삭제 하는데 실패 했습니다: " + e.getMessage(), user) .setFooter("하드 용량 절약 실패") .build()).queue(); } catch (RuntimeException e) { logger.warn(e.getMessage()); - event.replyEmbeds(new EmbedBuilder() - .setColor(DiaColor.FAIL) - .setTitle("오류 발생") - .setDescription("그림을 삭제하던 도중 문제가 발생했습니다.") - .setFooter("문제가 계속될 시 관리자를 불러주세요.") - .build()).queue(); + event.replyEmbeds(DiaEmbed.error(null, "그림을 삭제하던 도중 문제가 발생했습니다.", e, user).build()).queue(); } } } - public static class LoadCommand extends SlashCommand { + private static class LoadCommand extends SlashCommand { public LoadCommand() { name = "로드"; @@ -220,7 +197,7 @@ public LoadCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { OptionMapping paintNameOption = event.getOption("이름"); User user = event.getUser(); @@ -237,7 +214,7 @@ protected void execute(SlashCommandEvent event) { } - public static class ListCommand extends SlashCommand { + private static class ListCommand extends SlashCommand { public ListCommand() { name = "목록"; @@ -245,7 +222,7 @@ public ListCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { User user = event.getUser(); List paintNames = new PaintManagerImpl().getOwnedPaint(user.getIdLong()); diff --git a/src/main/java/net/qsef1256/diabot/game/paint/command/PaintCommand.java b/src/main/java/net/qsef1256/diabot/game/paint/command/PaintCommand.java index 06f1985..ded4961 100644 --- a/src/main/java/net/qsef1256/diabot/game/paint/command/PaintCommand.java +++ b/src/main/java/net/qsef1256/diabot/game/paint/command/PaintCommand.java @@ -8,9 +8,7 @@ import net.dv8tion.jda.api.interactions.commands.OptionType; import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.dv8tion.jda.api.interactions.components.Button; -import net.qsef1256.diabot.enums.DiaColor; -import net.qsef1256.diabot.enums.DiaImage; -import net.qsef1256.diabot.enums.DiaInfo; +import net.qsef1256.diabot.enums.*; import net.qsef1256.diabot.game.paint.enums.PixelColor; import net.qsef1256.diabot.game.paint.model.PaintDrawer; import net.qsef1256.diabot.game.paint.model.painter.Painter; @@ -41,7 +39,7 @@ public PaintCommand() { }; } - private static void printPallet(SlashCommandEvent event, Painter paint) { + private static void printPallet(@NotNull SlashCommandEvent event, Painter paint) { User user = event.getUser(); try { @@ -85,11 +83,13 @@ public static List parsePixelColor(@NotNull String colorString) { } @Override - protected void execute(SlashCommandEvent event) { - event.reply("추가 명령어를 입력하세요! : " + getHelp()).queue(); + protected void execute(@NotNull SlashCommandEvent event) { + SlashCommand[] children = getChildren(); + + event.reply(DiaMessage.needSubCommand(children, event.getMember())).queue(); } - public static class ShowCommand extends SlashCommand { + private static class ShowCommand extends SlashCommand { public ShowCommand() { name = "보기"; @@ -97,7 +97,7 @@ public ShowCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { User user = event.getUser(); Painter paint = PainterContainer.getPainter(user.getIdLong()); @@ -105,7 +105,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class PixelCommand extends SlashCommand { + private static class PixelCommand extends SlashCommand { public PixelCommand() { name = "찍기"; @@ -119,7 +119,7 @@ public PixelCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { OptionMapping optionX = event.getOption("x"); OptionMapping optionY = event.getOption("y"); OptionMapping optionColor = event.getOption("색깔"); @@ -148,12 +148,7 @@ protected void execute(SlashCommandEvent event) { return; } catch (RuntimeException e) { logger.warn(e.getMessage()); - event.replyEmbeds(new EmbedBuilder() - .setColor(DiaColor.FAIL) - .setTitle("오류 발생") - .setDescription("그림을 그리던 도중 문제가 발생했습니다.") - .setFooter("문제가 계속될 시 관리자를 불러주세요.") - .build()).queue(); + event.replyEmbeds(DiaEmbed.error(null, "그림을 그리던 도중 문제가 발생했습니다.", null, user).build()).queue(); return; } @@ -162,7 +157,7 @@ protected void execute(SlashCommandEvent event) { } - public static class ColumnCommand extends SlashCommand { + private static class ColumnCommand extends SlashCommand { public ColumnCommand() { name = "줄"; @@ -175,7 +170,7 @@ public ColumnCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { OptionMapping optionY = event.getOption("번호"); OptionMapping optionColumn = event.getOption("내용"); @@ -207,12 +202,7 @@ protected void execute(SlashCommandEvent event) { return; } catch (RuntimeException e) { logger.warn(e.getMessage()); - event.replyEmbeds(new EmbedBuilder() - .setColor(DiaColor.FAIL) - .setTitle("오류 발생") - .setDescription("그림을 그리던 도중 문제가 발생했습니다.") - .setFooter("문제가 계속될 시 관리자를 불러주세요.") - .build()).queue(); + event.replyEmbeds(DiaEmbed.error(null, "그림을 그리던 도중 문제가 발생했습니다.", null, user).build()).queue(); return; } @@ -220,7 +210,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class DrawAllCommand extends SlashCommand { + private static class DrawAllCommand extends SlashCommand { public DrawAllCommand() { name = "한줄로"; @@ -232,7 +222,7 @@ public DrawAllCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { OptionMapping optionColumn = event.getOption("내용"); if (optionColumn == null) { event.reply("내용을 입력해주세요.").queue(); @@ -254,12 +244,7 @@ protected void execute(SlashCommandEvent event) { return; } catch (RuntimeException e) { logger.warn(e.getMessage()); - event.replyEmbeds(new EmbedBuilder() - .setColor(DiaColor.FAIL) - .setTitle("오류 발생") - .setDescription("그림을 그리던 도중 문제가 발생했습니다.") - .setFooter("문제가 계속될 시 관리자를 불러주세요.") - .build()).queue(); + event.replyEmbeds(DiaEmbed.error(null, "그림을 그리던 도중 문제가 발생했습니다.", null, user).build()).queue(); return; } @@ -275,7 +260,7 @@ public EraseCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { User user = event.getUser(); Painter painter = PainterContainer.getPainter(user.getIdLong()); @@ -294,7 +279,7 @@ protected void execute(SlashCommandEvent event) { } - public static class ResizeCommand extends SlashCommand { + private static class ResizeCommand extends SlashCommand { public ResizeCommand() { name = "크기"; @@ -307,7 +292,7 @@ public ResizeCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { OptionMapping optionX = event.getOption("x"); OptionMapping optionY = event.getOption("y"); @@ -337,12 +322,7 @@ protected void execute(SlashCommandEvent event) { return; } catch (RuntimeException e) { logger.warn(e.getMessage()); - event.replyEmbeds(new EmbedBuilder() - .setColor(DiaColor.FAIL) - .setTitle("오류 발생") - .setDescription("사이즈를 바꾸던 도중 문제가 발생했습니다.") - .setFooter("문제가 계속될 시 관리자를 불러주세요.") - .build()).queue(); + event.replyEmbeds(DiaEmbed.error(null, "크기를 바꾸던 도중 문제가 발생했습니다.", null, user).build()).queue(); return; } @@ -351,7 +331,7 @@ protected void execute(SlashCommandEvent event) { } - public static class FillCommand extends SlashCommand { + private static class FillCommand extends SlashCommand { public FillCommand() { name = "채우기"; @@ -365,7 +345,7 @@ public FillCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { OptionMapping optionX = event.getOption("x"); OptionMapping optionY = event.getOption("y"); OptionMapping optionColor = event.getOption("색깔"); @@ -408,7 +388,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class DrawerCommand extends SlashCommand { + private static class DrawerCommand extends SlashCommand { public DrawerCommand() { name = "그림판"; @@ -421,7 +401,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class ColorCommand extends SlashCommand { + private static class ColorCommand extends SlashCommand { public ColorCommand() { name = "색깔"; diff --git a/src/main/java/net/qsef1256/diabot/game/paint/model/PaintDrawer.java b/src/main/java/net/qsef1256/diabot/game/paint/model/PaintDrawer.java index 217eda3..b88937e 100644 --- a/src/main/java/net/qsef1256/diabot/game/paint/model/PaintDrawer.java +++ b/src/main/java/net/qsef1256/diabot/game/paint/model/PaintDrawer.java @@ -114,7 +114,7 @@ public static void setDrawer(@NotNull ButtonClickEvent event, int dx, int dy, bo } @NotNull - private static MessageEmbed getDrawerEmbed(User user, Painter painter, int x, int y) { + private static MessageEmbed getDrawerEmbed(@NotNull User user, @NotNull Painter painter, int x, int y) { return new EmbedBuilder() .setAuthor(user.getName(), null, user.getEffectiveAvatarUrl()) .setColor(DiaColor.MAIN_COLOR) @@ -126,7 +126,7 @@ private static MessageEmbed getDrawerEmbed(User user, Painter painter, int x, in .build(); } - public static void initDrawer(SlashCommandEvent event) { + public static void initDrawer(@NotNull SlashCommandEvent event) { User user = event.getUser(); event.reply("그림판은 비싸니까 많이 띄우지 마세요. 그리고 천천히 그리세요... 디코가 싫대요.").setEphemeral(true).queue(); diff --git a/src/main/java/net/qsef1256/diabot/game/paint/model/PaintManagerImpl.java b/src/main/java/net/qsef1256/diabot/game/paint/model/PaintManagerImpl.java index e6ad8f3..db52ef8 100644 --- a/src/main/java/net/qsef1256/diabot/game/paint/model/PaintManagerImpl.java +++ b/src/main/java/net/qsef1256/diabot/game/paint/model/PaintManagerImpl.java @@ -7,6 +7,7 @@ import net.qsef1256.diabot.game.paint.model.painter.Painter; import net.qsef1256.diabot.game.paint.model.painter.PainterContainer; import net.qsef1256.diabot.util.DiscordUtil; +import org.jetbrains.annotations.NotNull; import javax.management.openmbean.KeyAlreadyExistsException; import java.util.ArrayList; @@ -38,7 +39,7 @@ public void delete(long discord_id, String paintName) { dao.deleteById(paintName); } - private PaintEntity findPaint(String paintName, long discord_id) { + private @NotNull PaintEntity findPaint(String paintName, long discord_id) { PaintEntity paintData; if (!dao.isExist(paintName)) throw new IllegalArgumentException(paintName + " 이름의 그림은 없습니다."); @@ -91,7 +92,7 @@ public void overwrite(long discord_id, String paintName) { } } - private void setPaintData(PaintEntity paintData, String paintName, Painter painter, long discord_id) { + private void setPaintData(@NotNull PaintEntity paintData, String paintName, @NotNull Painter painter, long discord_id) { paintData .setPaintName(paintName) .setXSize(painter.getWidth()) diff --git a/src/main/java/net/qsef1256/diabot/game/paint/model/painter/Painter.java b/src/main/java/net/qsef1256/diabot/game/paint/model/painter/Painter.java index 5487868..ed2233f 100644 --- a/src/main/java/net/qsef1256/diabot/game/paint/model/painter/Painter.java +++ b/src/main/java/net/qsef1256/diabot/game/paint/model/painter/Painter.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; // x and y from 1 @@ -150,4 +151,18 @@ private void validate(int x, int y) { } } + @Override + public int hashCode() { + return Arrays.deepHashCode(pallet); + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (this.getClass() != o.getClass()) return false; + + if (o.hashCode() == this.hashCode()) return true; + return false; + } + } diff --git a/src/main/java/net/qsef1256/diabot/listener/MessageHandler.java b/src/main/java/net/qsef1256/diabot/listener/MessageHandler.java index 7436b85..5b0c660 100644 --- a/src/main/java/net/qsef1256/diabot/listener/MessageHandler.java +++ b/src/main/java/net/qsef1256/diabot/listener/MessageHandler.java @@ -6,14 +6,13 @@ import org.jetbrains.annotations.NotNull; public class MessageHandler extends ListenerAdapter { + @Override public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) { - } @Override public void onSlashCommand(@NotNull SlashCommandEvent event) { - } } diff --git a/src/main/java/net/qsef1256/diabot/model/CmdStatistic.java b/src/main/java/net/qsef1256/diabot/model/CmdStatistic.java index ae9915b..dd3db37 100644 --- a/src/main/java/net/qsef1256/diabot/model/CmdStatistic.java +++ b/src/main/java/net/qsef1256/diabot/model/CmdStatistic.java @@ -7,6 +7,7 @@ import net.qsef1256.diabot.database.DaoCommon; import net.qsef1256.diabot.database.DaoCommonImpl; import net.qsef1256.diabot.util.LocalDateUtil; +import org.jetbrains.annotations.NotNull; import java.time.LocalDateTime; import java.util.NoSuchElementException; @@ -38,7 +39,7 @@ public CmdStatistic(Class command) { } } - private void createStatistic(Class command) { + private void createStatistic(@NotNull Class command) { CmdStatisticEntity data = new CmdStatisticEntity(); data.setCommandName(command.getSimpleName()); data.setLastUseTime(LocalDateTime.now()); diff --git a/src/main/java/net/qsef1256/diabot/struct/NestedMap.java b/src/main/java/net/qsef1256/diabot/struct/NestedMap.java index f99b27c..695bd71 100644 --- a/src/main/java/net/qsef1256/diabot/struct/NestedMap.java +++ b/src/main/java/net/qsef1256/diabot/struct/NestedMap.java @@ -3,7 +3,7 @@ import java.util.*; import java.util.function.BiConsumer; -// TODO: Map 또는 Iterable 구현하기 또는 새로운 인터페이스 만들기, equals && hashCode() 구현하기 +// TODO: Map 또는 Iterable 구현하기 또는 새로운 인터페이스 만들기 /** * {@code Map<T, Map<S, ?>>} 꼴의 중첩된 맵입니다. @@ -18,6 +18,8 @@ * NestedMap table = new NestedMap<>(); * } * + *

Non Thread-Safe + * * @param Type of main Key * @param Type of sub Key * @see Map @@ -128,18 +130,20 @@ public V get(T key, S subKey) { * table.put("b", "asdf", true); * } * + * @param Type of value * @param key main Key * @param subKey sub Key * @param value value - * @param Type of value + * @return put value * @see #putAll(T, Map) */ - public void put(T key, S subKey, V value) { + public V put(T key, S subKey, V value) { Map subMap = keyMap.containsKey(key) ? (Map) keyMap.get(key) : new HashMap<>(); - subMap.put(subKey, value); + V replaced = subMap.put(subKey, value); if (keyMap.containsKey(key)) keyMap.replace(key, subMap); else keyMap.put(key, subMap); + return replaced; } /** @@ -147,10 +151,11 @@ public void put(T key, S subKey, V value) { * * @param key main Key * @param subMap subMap with subKey, value + * @return put subMap * @see #put(T, S, Object) */ - public void putAll(T key, Map subMap) { - keyMap.put(key, subMap); + public Map putAll(T key, Map subMap) { + return keyMap.put(key, subMap); } /** @@ -193,10 +198,11 @@ public V remove(T key, S subKey) { * * @param key main Key * @param subMap sub Key-value Map + * @return replaced subMap * @see #replace(T, S, Object) */ - public void replace(T key, Map subMap) { - keyMap.replace(key, subMap); + public Map replace(T key, Map subMap) { + return keyMap.replace(key, subMap); } /** @@ -206,14 +212,16 @@ public void replace(T key, Map subMap) { * @param subKey sub Key * @param value value * @param Type of value + * @return replaced Value * @see #replace(T, Map) */ - public void replace(T key, S subKey, V value) { + public V replace(T key, S subKey, V value) { Map subMap = keyMap.containsKey(key) ? (Map) keyMap.get(key) : new HashMap<>(); - subMap.replace(subKey, value); + V replaced = subMap.replace(subKey, value); if (keyMap.containsKey(key)) keyMap.replace(key, subMap); else keyMap.put(key, subMap); + return replaced; } /** @@ -306,4 +314,32 @@ public void forEach(BiConsumer> action) { return keyMap.entrySet().spliterator(); } + /** + * keyMap 의 hashCode 를 반환합니다. + * + * @return haseCode + * @see #equals(Object) + */ + @Override + public int hashCode() { + return keyMap.hashCode(); + } + + /** + * 동일성을 비교합니다. + *

주의: 기본적인 {@link #hashCode()} 를 사용하기 때문에, {@link Object#equals(Object)} 를 재정의 하지 않는 객체가 들어온 경우 + * * (ex: 배열) false 가 반환 될 수 있습니다.

+ * + * @param o object to compare + * @return true if equal + */ + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (this.getClass() != o.getClass()) return false; + + if (o.hashCode() == this.hashCode()) return true; + return false; + } + } diff --git a/src/main/java/net/qsef1256/diabot/system/account/command/AccountCommand.java b/src/main/java/net/qsef1256/diabot/system/account/command/AccountCommand.java index 054a63c..1b4f0e2 100644 --- a/src/main/java/net/qsef1256/diabot/system/account/command/AccountCommand.java +++ b/src/main/java/net/qsef1256/diabot/system/account/command/AccountCommand.java @@ -6,14 +6,13 @@ import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.interactions.components.Button; -import net.qsef1256.diabot.enums.DiaColor; -import net.qsef1256.diabot.enums.DiaImage; -import net.qsef1256.diabot.enums.DiaInfo; +import net.qsef1256.diabot.enums.*; import net.qsef1256.diabot.game.explosion.model.Cash; import net.qsef1256.diabot.game.explosion.model.UserManager; import net.qsef1256.diabot.system.account.data.AccountEntity; import net.qsef1256.diabot.system.account.model.Account; import net.qsef1256.diabot.system.account.model.AccountManager; +import org.jetbrains.annotations.NotNull; import java.time.format.DateTimeFormatter; import java.util.NoSuchElementException; @@ -32,8 +31,10 @@ public AccountCommand() { } @Override - protected void execute(final SlashCommandEvent event) { - event.reply("추가 명령어를 입력하세요! : " + getHelp()).queue(); + protected void execute(final @NotNull SlashCommandEvent event) { + SlashCommand[] children = getChildren(); + + event.reply(DiaMessage.needSubCommand(children, event.getMember())).queue(); } private static class RegisterCommand extends SlashCommand { @@ -44,7 +45,7 @@ public RegisterCommand() { } @Override - protected void execute(final SlashCommandEvent event) { + protected void execute(final @NotNull SlashCommandEvent event) { final User user = event.getUser(); event.deferReply().queue(callback -> { @@ -60,12 +61,7 @@ protected void execute(final SlashCommandEvent event) { .setFooter("/폭발 커맨드로 게임을 시작하세요!") .build()).queue(); } catch (RuntimeException e) { - callback.editOriginalEmbeds(new EmbedBuilder() - .setTitle("등록 실패") - .setColor(DiaColor.FAIL) - .setAuthor(user.getAsTag(), null, user.getEffectiveAvatarUrl()) - .setDescription(e.getMessage()) - .build()).queue(); + callback.editOriginalEmbeds(DiaEmbed.error("등록 실패", null, e, user).build()).queue(); if (e instanceof DuplicateRequestException) return; e.printStackTrace(); @@ -82,7 +78,7 @@ public StatusCommand() { } @Override - protected void execute(final SlashCommandEvent event) { + protected void execute(final @NotNull SlashCommandEvent event) { final User user = event.getUser(); try { @@ -106,11 +102,7 @@ protected void execute(final SlashCommandEvent event) { .build()).queue(); } catch (RuntimeException e) { - event.replyEmbeds(new EmbedBuilder() - .setTitle("계정 정보 확인 실패") - .setColor(DiaColor.FAIL) - .setAuthor(user.getAsTag(), null, user.getEffectiveAvatarUrl()) - .setDescription(e.getMessage()) + event.replyEmbeds(DiaEmbed.error("계정 정보 확인 실패", null, e, user) .setFooter("계정 신청은 /계정 등록") .build()).queue(); @@ -138,7 +130,7 @@ public ResetCommand() { } @Override - protected void execute(final SlashCommandEvent event) { + protected void execute(final @NotNull SlashCommandEvent event) { final User user = event.getUser(); event.replyEmbeds(new EmbedBuilder() diff --git a/src/main/java/net/qsef1256/diabot/system/account/command/AttendCommand.java b/src/main/java/net/qsef1256/diabot/system/account/command/AttendCommand.java index f41bc59..ed5169d 100644 --- a/src/main/java/net/qsef1256/diabot/system/account/command/AttendCommand.java +++ b/src/main/java/net/qsef1256/diabot/system/account/command/AttendCommand.java @@ -10,6 +10,7 @@ import net.qsef1256.diabot.system.account.data.AccountEntity; import net.qsef1256.diabot.system.account.model.Account; import net.qsef1256.diabot.util.LocalDateUtil; +import org.jetbrains.annotations.NotNull; import java.time.LocalDateTime; import java.util.NoSuchElementException; @@ -22,7 +23,7 @@ public AttendCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { if (event.getMember() == null) return; User eventUser = event.getUser(); diff --git a/src/main/java/net/qsef1256/diabot/system/account/listener/AccountButtonListener.java b/src/main/java/net/qsef1256/diabot/system/account/listener/AccountButtonListener.java index 650d52c..87cede9 100644 --- a/src/main/java/net/qsef1256/diabot/system/account/listener/AccountButtonListener.java +++ b/src/main/java/net/qsef1256/diabot/system/account/listener/AccountButtonListener.java @@ -6,9 +6,11 @@ import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.qsef1256.diabot.enums.DiaColor; +import net.qsef1256.diabot.enums.DiaEmbed; import net.qsef1256.diabot.game.explosion.model.UserManager; import net.qsef1256.diabot.system.account.command.AccountCommand; import net.qsef1256.diabot.system.account.model.AccountManager; +import org.jetbrains.annotations.NotNull; import java.util.NoSuchElementException; @@ -20,7 +22,7 @@ public class AccountButtonListener extends ListenerAdapter { * @see AccountCommand */ @Override - public void onButtonClick(final ButtonClickEvent event) { + public void onButtonClick(final @NotNull ButtonClickEvent event) { switch (event.getComponentId()) { case "account_reset" -> { @@ -40,11 +42,7 @@ public void onButtonClick(final ButtonClickEvent event) { if (event.getButton() == null) return; event.editButton(event.getButton().asDisabled()).queue(); } catch (RuntimeException ex) { - event.replyEmbeds(new EmbedBuilder() - .setTitle("계정 초기화 실패") - .setColor(DiaColor.FAIL) - .setAuthor(user.getAsTag(), null, user.getEffectiveAvatarUrl()) - .setDescription(ex.getMessage()) + event.replyEmbeds(DiaEmbed.error("계정 초기화 실패", null, ex, user) .setFooter("예술의 끝으로 계정을 대폭발 시키려고 하지만 누군가가 막고 있군요...") .build() ).queue(); @@ -75,11 +73,7 @@ public void onButtonClick(final ButtonClickEvent event) { if (event.getButton() == null) return; event.editButton(event.getButton().asDisabled()).queue(); } catch (RuntimeException ex) { - event.replyEmbeds(new EmbedBuilder() - .setTitle("계정 삭제 실패") - .setColor(DiaColor.FAIL) - .setAuthor(user.getAsTag(), null, user.getEffectiveAvatarUrl()) - .setDescription(ex.getMessage()) + event.replyEmbeds(DiaEmbed.error("계정 삭제 실패", null, ex, user) .setFooter("문제가 있을시 관리자를 불러주세요.") .build() ).queue(); diff --git a/src/main/java/net/qsef1256/diabot/system/account/model/AccountManager.java b/src/main/java/net/qsef1256/diabot/system/account/model/AccountManager.java index 3e9565e..161514f 100644 --- a/src/main/java/net/qsef1256/diabot/system/account/model/AccountManager.java +++ b/src/main/java/net/qsef1256/diabot/system/account/model/AccountManager.java @@ -54,4 +54,8 @@ public static void delete(final long discord_id) { } } + public static AccountEntity getAccount(long discord_id) { + return dao.findById(discord_id); + } + } diff --git a/src/main/java/net/qsef1256/diabot/system/request/command/RequestCommand.java b/src/main/java/net/qsef1256/diabot/system/request/command/RequestCommand.java index a8c9f81..673b84d 100644 --- a/src/main/java/net/qsef1256/diabot/system/request/command/RequestCommand.java +++ b/src/main/java/net/qsef1256/diabot/system/request/command/RequestCommand.java @@ -6,9 +6,11 @@ import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.qsef1256.diabot.enums.DiaColor; import net.qsef1256.diabot.enums.DiaEmbed; +import net.qsef1256.diabot.enums.DiaMessage; import net.qsef1256.diabot.system.request.model.Request; import net.qsef1256.diabot.system.request.model.RequestManager; import net.qsef1256.diabot.util.DiscordUtil; +import org.jetbrains.annotations.NotNull; public class RequestCommand extends SlashCommand { @@ -25,11 +27,13 @@ public RequestCommand() { } @Override - protected void execute(SlashCommandEvent event) { - event.reply("추가 명령어를 입력하세요! : " + getHelp()).queue(); + protected void execute(@NotNull SlashCommandEvent event) { + SlashCommand[] children = getChildren(); + + event.reply(DiaMessage.needSubCommand(children, event.getMember())).queue(); } - public static class CheckCommand extends SlashCommand { + private static class CheckCommand extends SlashCommand { public CheckCommand() { name = "확인"; @@ -37,7 +41,7 @@ public CheckCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { User user = event.getUser(); try { @@ -58,7 +62,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class AcceptCommand extends SlashCommand { + private static class AcceptCommand extends SlashCommand { public AcceptCommand() { name = "수락"; @@ -66,7 +70,7 @@ public AcceptCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { User user = event.getUser(); try { @@ -77,7 +81,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class DenyCommand extends SlashCommand { + private static class DenyCommand extends SlashCommand { public DenyCommand() { name = "거절"; @@ -85,7 +89,7 @@ public DenyCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { User user = event.getUser(); try { @@ -96,7 +100,7 @@ protected void execute(SlashCommandEvent event) { } } - public static class CancelCommand extends SlashCommand { + private static class CancelCommand extends SlashCommand { public CancelCommand() { name = "취소"; @@ -104,7 +108,7 @@ public CancelCommand() { } @Override - protected void execute(SlashCommandEvent event) { + protected void execute(@NotNull SlashCommandEvent event) { User user = event.getUser(); try { diff --git a/src/main/java/net/qsef1256/diabot/system/request/model/RequestManager.java b/src/main/java/net/qsef1256/diabot/system/request/model/RequestManager.java index 3643216..11d7335 100644 --- a/src/main/java/net/qsef1256/diabot/system/request/model/RequestManager.java +++ b/src/main/java/net/qsef1256/diabot/system/request/model/RequestManager.java @@ -76,7 +76,8 @@ public static void addRequest(@NotNull T requestObject) { public static void cancel(long userId) { Long messageId = getMessageId(userId); - if (messageId == null) throw new NoSuchElementException(DiscordUtil.getNameAsTag(userId) + " 의 신청을 찾을 수 없습니다."); + if (messageId == null) + throw new NoSuchElementException(DiscordUtil.getNameAsTag(userId) + " 의 신청을 찾을 수 없습니다."); cancel(userId, messageId); } @@ -126,7 +127,9 @@ public static void accept(long messageId, long userId) { public static void deny(long userId) { Long messageId = getMessageId(userId); - if (messageId == null) throw new NoSuchElementException(DiscordUtil.getNameAsTag(userId) + " 의 신청을 찾을 수 없습니다."); + if (messageId == null) + throw new NoSuchElementException(DiscordUtil.getNameAsTag(userId) + " 의 신청을 찾을 수 없습니다."); + deny(messageId, userId); } diff --git a/src/main/java/net/qsef1256/diabot/util/CommonUtil.java b/src/main/java/net/qsef1256/diabot/util/CommonUtil.java index 818eada..e8f2fd1 100644 --- a/src/main/java/net/qsef1256/diabot/util/CommonUtil.java +++ b/src/main/java/net/qsef1256/diabot/util/CommonUtil.java @@ -13,7 +13,7 @@ public int randomInt(int min, int max) { return ThreadLocalRandom.current().nextInt(min, max + 1); } - public void swap(T[] toSwap, int a, int b) { + public void swap(T @NotNull [] toSwap, int a, int b) { T temp = toSwap[a]; toSwap[a] = toSwap[b]; toSwap[b] = temp; diff --git a/src/main/java/net/qsef1256/diabot/util/GenericUtil.java b/src/main/java/net/qsef1256/diabot/util/GenericUtil.java index ccb6d81..1f7c5f7 100644 --- a/src/main/java/net/qsef1256/diabot/util/GenericUtil.java +++ b/src/main/java/net/qsef1256/diabot/util/GenericUtil.java @@ -27,9 +27,29 @@ public ArrayList getArrayList(Object toCheck) { return list; } + /** + * 클래스의 인스턴스인지를 체크합니다. + * + * @param clazz class + * @param targetClass target class + * @return true if class is instanceOf target + * @see #typeOf(Class, Class) + */ @Contract(value = "_, null -> false", pure = true) public static boolean instanceOf(@NotNull Class clazz, Class targetClass) { return clazz.isInstance(targetClass); } + /** + * 타입 이름을 비교합니다. + * + * @param clazz class + * @param targetClass target class + * @return true if type name is same + * @see #instanceOf(Class, Class) + */ + public static boolean typeOf(@NotNull Class clazz, @NotNull Class targetClass) { + return clazz.getTypeName().equals(targetClass.getTypeName()); + } + } diff --git a/src/main/java/net/qsef1256/diabot/util/JDAUtil.java b/src/main/java/net/qsef1256/diabot/util/JDAUtil.java new file mode 100644 index 0000000..5a1cd33 --- /dev/null +++ b/src/main/java/net/qsef1256/diabot/util/JDAUtil.java @@ -0,0 +1,31 @@ +package net.qsef1256.diabot.util; + +import com.jagrosh.jdautilities.command.SlashCommand; +import lombok.experimental.UtilityClass; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Role; +import net.qsef1256.diabot.DiaBot; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; + +@UtilityClass +public class JDAUtil { + + public static boolean canExecute(@NotNull SlashCommand slashCommand, Member member) { + if (slashCommand.isOwnerCommand()) { + return DiaBot.getCommandClient().getOwnerIdLong() == member.getIdLong(); + } + if (slashCommand.getEnabledRoles().length != 0) { + for (Role role : member.getRoles()) { + if (Arrays.asList(slashCommand.getEnabledRoles()).contains(role.getId())) return true; + } + return false; + } + if (slashCommand.getEnabledUsers().length != 0) { + return Arrays.asList(slashCommand.getEnabledUsers()).contains(member.getId()); + } + return true; + } + +} diff --git a/src/main/java/net/qsef1256/diabot/util/LocalDateUtil.java b/src/main/java/net/qsef1256/diabot/util/LocalDateUtil.java index cb014b3..992aa53 100644 --- a/src/main/java/net/qsef1256/diabot/util/LocalDateUtil.java +++ b/src/main/java/net/qsef1256/diabot/util/LocalDateUtil.java @@ -1,7 +1,9 @@ package net.qsef1256.diabot.util; import lombok.experimental.UtilityClass; +import org.jetbrains.annotations.NotNull; +import java.time.Duration; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -15,10 +17,10 @@ public class LocalDateUtil { * 첫번째와 두번째 시간이 같은 날짜인지 확인합니다. * * @param first first Date - * @param second second Data + * @param second second Date * @return true if same Day */ - public boolean isSameDay(LocalDateTime first, LocalDateTime second) { + public boolean isSameDay(@NotNull LocalDateTime first, @NotNull LocalDateTime second) { return first.toLocalDate().isEqual(second.toLocalDate()); } @@ -28,7 +30,7 @@ public boolean isSameDay(LocalDateTime first, LocalDateTime second) { * @param time Time to check is today * @return true if today */ - public boolean isToday(LocalDateTime time) { + public boolean isToday(@NotNull LocalDateTime time) { return time.toLocalDate().isEqual(LocalDateTime.now().toLocalDate()); } @@ -38,8 +40,19 @@ public boolean isToday(LocalDateTime time) { * @param time Time to convert * @return ISO LocalDateTime without space */ - public String getTimeString(LocalDateTime time) { + public String getTimeString(@NotNull LocalDateTime time) { return time.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME).replace('T', ' '); } + /** + * 날짜 차이를 {@link Duration} 으로 반환합니다. + * + * @param first first Date + * @param second second Date + * @return difference between first and second + */ + public Duration getDiff(@NotNull LocalDateTime first, @NotNull LocalDateTime second) { + return Duration.between(first, second); + } + } diff --git a/src/test/java/CommonUtilTest.java b/src/test/java/CommonUtilTest.java index a8e4621..f0dc6df 100644 --- a/src/test/java/CommonUtilTest.java +++ b/src/test/java/CommonUtilTest.java @@ -1,19 +1,22 @@ import net.qsef1256.diabot.game.paint.model.painter.Painter; import net.qsef1256.diabot.struct.NestedMap; import net.qsef1256.diabot.util.CommonUtil; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; public class CommonUtilTest { - private void testRandom() { + @Test + public void testRandom() { for (int i = 0; i < 25; i++) { - System.out.println(CommonUtil.randomInt(-6, -3)); + System.out.println(CommonUtil.randomInt(-6, 1)); } } - private void testDiff() { + @Test + public void testDiff() { assertEquals(2, CommonUtil.getDiff(1, 3)); assertEquals(3, CommonUtil.getDiff(4, 1)); assertEquals(2, CommonUtil.getDiff(-1, -3)); @@ -73,14 +76,13 @@ public void testMatch() { @Test public void testNestedMap() { NestedMap table = new NestedMap<>(); + NestedMap sameTable = new NestedMap<>(); + NestedMap diffTable = new NestedMap<>(); - table.put("c", "user", "c"); - table.put("c", "asdf", "c"); - table.put("a", "painter", new Painter()); - table.put("a", "user", "a"); - table.put("a", "asdf", "a"); - table.put("b", "asdf", "b"); - table.put("b", "user", "b"); + putData(table); + putData(sameTable); + putData(diffTable); + diffTable.put("d", "test", "c"); Painter painter = table.get("a", "painter"); if (painter != null) { @@ -90,6 +92,26 @@ public void testNestedMap() { System.out.println(table.keySet("a")); table.forEach((mainKey, valueMap) -> valueMap.forEach((subKey, value) -> System.out.println(mainKey + " " + subKey + " " + value))); + + System.out.printf("hashCodes: %s %s %s\n", table.hashCode(), sameTable.hashCode(), diffTable.hashCode()); + System.out.println("sameTable equals: " + table.equals(sameTable)); + System.out.println("diffTable equals: " + table.equals(diffTable)); + + table.remove("c", "asdf"); + assertFalse(table.contains("c", "asdf")); + + table.replace("asd", "test", "aa"); + assertFalse(table.contains("asd", "test")); + } + + private void putData(@NotNull NestedMap table) { + table.put("c", "user", "c"); + table.put("c", "asdf", "c"); + table.put("a", "painter", new Painter()); + table.put("a", "user", "a"); + table.put("a", "asdf", "a"); + table.put("b", "asdf", "b"); + table.put("b", "user", "b"); } }