From 33f0ab31b1043400f6d812013517ae3d07af577e Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Thu, 25 Aug 2022 11:21:01 -0400 Subject: v7 --- src/main/java/net/tylermurphy/ken/Ken.java | 5 +- .../java/net/tylermurphy/ken/command/Register.java | 18 +- .../net/tylermurphy/ken/command/Responder.java | 297 +++++++++++++++++++++ .../java/net/tylermurphy/ken/command/Response.java | 26 ++ .../ken/command/annotation/ButtonCallback.java | 12 + .../ken/command/annotation/Command.java | 13 + .../tylermurphy/ken/command/annotation/Option.java | 16 ++ .../ken/command/annotation/Options.java | 12 + .../ken/command/annotation/Requirement.java | 12 + .../ken/command/annotation/SelectMenuCallback.java | 12 + .../ken/command/annotation/Selection.java | 16 ++ .../ken/command/annotation/Selections.java | 12 + .../net/tylermurphy/ken/command/fun/Coinflip.java | 2 +- .../java/net/tylermurphy/ken/command/fun/Dice.java | 4 +- .../net/tylermurphy/ken/command/fun/Eject.java | 4 +- .../net/tylermurphy/ken/command/main/AddRole.java | 33 ++- .../tylermurphy/ken/command/main/AddRolesPage.java | 23 +- .../tylermurphy/ken/command/main/DeleteRole.java | 19 +- .../ken/command/main/DeleteRolesPage.java | 31 +++ .../net/tylermurphy/ken/command/main/Help.java | 4 +- .../net/tylermurphy/ken/command/main/Purge.java | 6 +- .../net/tylermurphy/ken/command/main/Roles.java | 92 +++++++ .../tylermurphy/ken/command/music/ForceSkip.java | 2 +- .../net/tylermurphy/ken/command/music/Join.java | 2 +- .../net/tylermurphy/ken/command/music/Leave.java | 2 +- .../net/tylermurphy/ken/command/music/Loop.java | 2 +- .../tylermurphy/ken/command/music/LoopQueue.java | 2 +- .../tylermurphy/ken/command/music/NowPlaying.java | 2 +- .../net/tylermurphy/ken/command/music/Pause.java | 2 +- .../net/tylermurphy/ken/command/music/Play.java | 4 +- .../net/tylermurphy/ken/command/music/Queue.java | 4 +- .../net/tylermurphy/ken/command/music/Remove.java | 4 +- .../net/tylermurphy/ken/command/music/Resume.java | 2 +- .../net/tylermurphy/ken/command/music/Skip.java | 2 +- .../net/tylermurphy/ken/command/music/Stop.java | 2 +- .../net/tylermurphy/ken/command/nsfw/Danbooru.java | 4 +- .../net/tylermurphy/ken/command/nsfw/E621.java | 4 +- .../net/tylermurphy/ken/command/nsfw/Gelbooru.java | 4 +- .../net/tylermurphy/ken/command/nsfw/Hentai.java | 4 +- .../net/tylermurphy/ken/command/nsfw/Konachan.java | 4 +- .../net/tylermurphy/ken/command/nsfw/Rule34.java | 4 +- .../net/tylermurphy/ken/command/nsfw/Yandere.java | 4 +- .../net/tylermurphy/ken/command/nsfw/nHentai.java | 6 +- .../java/net/tylermurphy/ken/event/Responder.java | 234 ---------------- .../ken/event/annotation/ButtonCallback.java | 12 - .../tylermurphy/ken/event/annotation/Command.java | 13 - .../tylermurphy/ken/event/annotation/Option.java | 16 -- .../tylermurphy/ken/event/annotation/Options.java | 12 - .../ken/event/annotation/Requirement.java | 12 - .../ken/event/annotation/Selection.java | 16 -- .../ken/event/annotation/Selections.java | 12 - 51 files changed, 660 insertions(+), 402 deletions(-) create mode 100644 src/main/java/net/tylermurphy/ken/command/Responder.java create mode 100644 src/main/java/net/tylermurphy/ken/command/annotation/ButtonCallback.java create mode 100644 src/main/java/net/tylermurphy/ken/command/annotation/Command.java create mode 100644 src/main/java/net/tylermurphy/ken/command/annotation/Option.java create mode 100644 src/main/java/net/tylermurphy/ken/command/annotation/Options.java create mode 100644 src/main/java/net/tylermurphy/ken/command/annotation/Requirement.java create mode 100644 src/main/java/net/tylermurphy/ken/command/annotation/SelectMenuCallback.java create mode 100644 src/main/java/net/tylermurphy/ken/command/annotation/Selection.java create mode 100644 src/main/java/net/tylermurphy/ken/command/annotation/Selections.java delete mode 100644 src/main/java/net/tylermurphy/ken/event/Responder.java delete mode 100644 src/main/java/net/tylermurphy/ken/event/annotation/ButtonCallback.java delete mode 100644 src/main/java/net/tylermurphy/ken/event/annotation/Command.java delete mode 100644 src/main/java/net/tylermurphy/ken/event/annotation/Option.java delete mode 100644 src/main/java/net/tylermurphy/ken/event/annotation/Options.java delete mode 100644 src/main/java/net/tylermurphy/ken/event/annotation/Requirement.java delete mode 100644 src/main/java/net/tylermurphy/ken/event/annotation/Selection.java delete mode 100644 src/main/java/net/tylermurphy/ken/event/annotation/Selections.java (limited to 'src') diff --git a/src/main/java/net/tylermurphy/ken/Ken.java b/src/main/java/net/tylermurphy/ken/Ken.java index b9b7a97..b03ea3d 100644 --- a/src/main/java/net/tylermurphy/ken/Ken.java +++ b/src/main/java/net/tylermurphy/ken/Ken.java @@ -7,10 +7,11 @@ import net.dv8tion.jda.api.EmbedBuilder; 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.Role; import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.requests.GatewayIntent; import net.dv8tion.jda.api.utils.MemberCachePolicy; -import net.tylermurphy.ken.event.Responder; +import net.tylermurphy.ken.command.Responder; import net.tylermurphy.ken.database.Database; import net.tylermurphy.ken.music.PlayerManager; import org.jetbrains.annotations.NotNull; @@ -90,6 +91,8 @@ public class Ken { public Database getDatabase() { return database; } + public Role getRoleById(long id) { return api.getRoleById(id); } + public EmbedBuilder getDefaultEmbed() { EmbedBuilder builder = new EmbedBuilder(); builder.setColor(new Color( diff --git a/src/main/java/net/tylermurphy/ken/command/Register.java b/src/main/java/net/tylermurphy/ken/command/Register.java index 24c7860..800200e 100644 --- a/src/main/java/net/tylermurphy/ken/command/Register.java +++ b/src/main/java/net/tylermurphy/ken/command/Register.java @@ -5,7 +5,7 @@ import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.interactions.commands.build.Commands; import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; -import net.tylermurphy.ken.event.annotation.*; +import net.tylermurphy.ken.command.annotation.*; import java.lang.reflect.Method; import java.util.*; @@ -15,6 +15,7 @@ public class Register { private final Map HANDLES; private final Map COMMAND_CALLBACKS; private final Map BUTTON_CALLBACKS; + private final Map SELECT_MENU_CALLBACKS; private final Map PERMISSIONS; private final JDA api; @@ -23,6 +24,7 @@ public class Register { HANDLES = new HashMap<>(); COMMAND_CALLBACKS = new HashMap<>(); BUTTON_CALLBACKS = new HashMap<>(); + SELECT_MENU_CALLBACKS = new HashMap<>(); PERMISSIONS = new HashMap<>(); this.api = api; @@ -32,10 +34,12 @@ public class Register { if(HANDLES.containsKey(handle.getClass().getName())) return; List commands = Arrays.stream(handle.getClass().getMethods()).filter(method -> method.isAnnotationPresent(Command.class)).toList(); List buttons = Arrays.stream(handle.getClass().getMethods()).filter(method -> method.isAnnotationPresent(ButtonCallback.class)).toList(); - if(commands.isEmpty() && buttons.isEmpty()) return; + List selectMenus = Arrays.stream(handle.getClass().getMethods()).filter(method -> method.isAnnotationPresent(SelectMenuCallback.class)).toList(); + if(commands.isEmpty() && buttons.isEmpty() && selectMenus.isEmpty()) return; HANDLES.put(handle.getClass().getName(), handle); commands.forEach(this::registerCommand); buttons.forEach(this::registerButton); + selectMenus.forEach(this::registerSelectMenu); } private void registerCommand(Method method){ @@ -77,6 +81,12 @@ public class Register { BUTTON_CALLBACKS.put(callback.name(), method); } + private void registerSelectMenu(Method method){ + SelectMenuCallback callback = method.getAnnotation(SelectMenuCallback.class); + if(SELECT_MENU_CALLBACKS.containsKey(callback.name())) return; + SELECT_MENU_CALLBACKS.put(callback.name(), method); + } + public Method getCommand(String name){ return COMMAND_CALLBACKS.get(name); } @@ -85,6 +95,10 @@ public class Register { return BUTTON_CALLBACKS.get(name); } + public Method getSelectMenuCallback(String name){ + return SELECT_MENU_CALLBACKS.get(name); + } + public Permission getPermission(String name){ return PERMISSIONS.get(name); } diff --git a/src/main/java/net/tylermurphy/ken/command/Responder.java b/src/main/java/net/tylermurphy/ken/command/Responder.java new file mode 100644 index 0000000..75f685b --- /dev/null +++ b/src/main/java/net/tylermurphy/ken/command/Responder.java @@ -0,0 +1,297 @@ +package net.tylermurphy.ken.command; + +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.GuildMessageChannel; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent; +import net.dv8tion.jda.api.events.interaction.component.SelectMenuInteractionEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.interactions.InteractionHook; +import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.components.ActionComponent; +import net.dv8tion.jda.api.interactions.components.ActionRow; +import net.dv8tion.jda.api.interactions.components.LayoutComponent; +import net.dv8tion.jda.api.interactions.components.buttons.Button; +import net.dv8tion.jda.api.interactions.components.selections.SelectMenu; +import net.dv8tion.jda.api.interactions.components.selections.SelectOption; +import net.dv8tion.jda.api.requests.restaction.WebhookMessageEditAction; +import net.dv8tion.jda.api.requests.restaction.interactions.ReplyCallbackAction; +import net.dv8tion.jda.api.utils.FileUpload; +import net.tylermurphy.ken.Ken; +import net.tylermurphy.ken.command.Register; +import net.tylermurphy.ken.command.Response; +import net.tylermurphy.ken.command.fun.*; +import net.tylermurphy.ken.command.main.*; +import net.tylermurphy.ken.command.music.*; +import net.tylermurphy.ken.command.music.Queue; +import net.tylermurphy.ken.command.nsfw.*; + +import java.awt.*; +import java.lang.reflect.Method; +import java.util.*; +import java.util.List; + +public class Responder extends ListenerAdapter { + + private final Register register; + + public Responder(JDA api) { + this.register = new Register(api); + } + + public void registerCommands(){ + Object[] objects = new Object[]{ + new Coinflip(), + new Dice(), + new Eject(), + new AddRole(), + new DeleteRole(), + new AddRolesPage(), + new DeleteRolesPage(), + new Roles(), + new Help(), + new Purge(), + new ForceSkip(), + new Join(), + new Leave(), + new Loop(), + new LoopQueue(), + new NowPlaying(), + new Pause(), + new Play(), + new Queue(), + new Remove(), + new Resume(), + new Skip(), + new Stop(), + new Danbooru(), + new E621(), + new Gelbooru(), + new Hentai(), + new Konachan(), + new nHentai(), + new Rule34(), + new Yandere(), + }; + Arrays.stream(objects).forEach(register::register); + } + + public void onSlashCommandInteraction(SlashCommandInteractionEvent event) { + + // Make sure the Bot can Talk + if(!event.getChannel().canTalk()) return; + + // Bots are not allowed to use commands + if (event.getMember() == null || event.getUser().isBot()) return; + + // Get Command Information From Invoke + final String invoke = event.getName().toLowerCase(Locale.ROOT); + + Method method = register.getCommand(invoke); + + // Check Permissions + if(!event.getMember().hasPermission(register.getPermission(invoke))) { + EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() + .appendDescription(":x: **Invalid Permissions**\n") + .appendDescription("You require the "+ register.getPermission(invoke)+" permission to use this command."); + event.getHook().sendMessageEmbeds(builder.build()).queue(); + return; + } + + // Get slash command options if there are any + List args = getOptions(event.getOptions()); + + // Get parameters to send to Method + Object[] parameters = new Object[method.getParameterTypes().length]; + Class[] types = method.getParameterTypes(); + for(int i = 0; i < types.length; i++){ + if(types[i] == Member.class){ + parameters[i] = event.getMember(); + } else if(types[i] == GuildMessageChannel.class){ + parameters[i] = event.getGuildChannel(); + } else if(types[i] == Guild.class) { + parameters[i] = event.getGuild(); + } else if(types[i] == List.class) { + parameters[i] = args; + } else { + parameters[i] = null; + } + } + + // Invoke Method and Respond to User + try { + Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters); + Response response = (Response)temp; + reply(response, event); + } catch (Exception e) { + EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() + .setColor(Color.RED) + .setTitle(":x: **Error**") + .setDescription(e.getCause() != null ? e.getCause().getMessage() : e.getMessage()); + event.replyEmbeds(builder.build()).setEphemeral(true).queue(); + e.printStackTrace(); + } + } + + public void onButtonInteraction(ButtonInteractionEvent event) { + + // Make sure the Bot can Talk + if(!event.getChannel().canTalk()) return; + // Bots are not allowed to use commands + if (event.getMember() == null || event.getUser().isBot()) return; + + // Get Command Information From Invoke + final String invoke = event.getComponentId().toLowerCase(Locale.ROOT).split("_")[0]; + Method method = register.getButtonCallback(invoke); + + // Get parameters to send to Method + Object[] parameters = new Object[method.getParameterTypes().length]; + Class[] types = method.getParameterTypes(); + for(int i = 0; i < types.length; i++){ + if(types[i] == Member.class){ + parameters[i] = event.getMember(); + } else if(types[i] == GuildMessageChannel.class){ + parameters[i] = event.getGuildChannel(); + } else if(types[i] == Guild.class) { + parameters[i] = event.getGuild(); + } else if(types[i] == Button.class) { + parameters[i] = event.getButton(); + } else if(types[i] == Message.class) { + parameters[i] = event.getMessage(); + } else if(types[i] == String.class) { + parameters[i] = event.getComponentId().substring(invoke.length()+1); + } else { + parameters[i] = null; + } + } + + // Invoke Method and Respond to User + try { + Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters); + Response response = (Response) temp; + event.deferEdit().queue(); + edit(response, event.getHook()); + } catch (Exception e) { + EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() + .setColor(Color.RED) + .setTitle(":x: **Error**") + .setDescription(e.getCause().getMessage()); + event.getHook().editOriginalEmbeds(builder.build()).queue(); + } + + } + + public void onSelectMenuInteraction(SelectMenuInteractionEvent event) { + + // Make sure the Bot can Talk + if(!event.getChannel().canTalk()) return; + // Bots are not allowed to use commands + if (event.getMember() == null || event.getUser().isBot()) return; + + // Get Command Information From Invoke + final String invoke = event.getComponentId().toLowerCase(Locale.ROOT).split("_")[0]; + Method method = register.getSelectMenuCallback(invoke); + + // Get parameters to send to Method + Object[] parameters = new Object[method.getParameterTypes().length]; + Class[] types = method.getParameterTypes(); + for(int i = 0; i < types.length; i++){ + if(types[i] == Member.class){ + parameters[i] = event.getMember(); + } else if(types[i] == GuildMessageChannel.class){ + parameters[i] = event.getGuildChannel(); + } else if(types[i] == Guild.class) { + parameters[i] = event.getGuild(); + } else if(types[i] == SelectMenu.class) { + parameters[i] = event.getSelectMenu(); + } else if(types[i] == Message.class) { + parameters[i] = event.getMessage(); + } else if(types[i] == String.class){ + parameters[i] = event.getValues().get(0); + } else { + parameters[i] = null; + } + } + + // Invoke Method and Respond to User + try { + Object temp = method.invoke(register.getHandle(method.getDeclaringClass().getName()), parameters); + Response response = (Response) temp; + reply(response, event); + } catch (Exception e) { + EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() + .setColor(Color.RED) + .setTitle(":x: **Error**") + .setDescription(e.getCause().getMessage()); + event.getHook().editOriginalEmbeds(builder.build()).queue(); + } + + } + + private void reply(Response response, IReplyCallback event){ + if(response.error()) { + EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() + .setColor(Color.RED) + .setDescription(response.getMessage()); + event.replyEmbeds(builder.build()).setEphemeral(true).queue(); + } else { + ReplyCallbackAction message; + if(response.hasEmbed()) { + message = event.replyEmbeds(response.getEmbeds()); + } else { + message = event.reply(response.getMessage()); + } + if(response.hasButtons()) message = message.addActionRow(response.getButtons()); + if(response.hasSelectMenu()) message = message.addActionRow(response.getSelectMenu()); + if(response.hasFile()) message = message.addFiles(FileUpload.fromData(response.getFile())); + message.setEphemeral(response.isHidden()).queue(); + } + } + + private void edit(Response response, InteractionHook hook){ + if(response.error()) { + EmbedBuilder builder = Ken.getInstance().getDefaultEmbed() + .setColor(Color.RED) + .setDescription(response.getMessage()); + hook.sendMessageEmbeds(builder.build()).queue(); + } else if(response.remove()) { + hook.deleteOriginal().queue(); + } else { + if(response.hasEmbed()) { + hook.editOriginalEmbeds(response.getEmbeds()).queue(); + } else { + hook.editOriginal(response.getMessage()).queue(); + } + if(response.hasSelectMenu() || response.hasButtons()) { + List components = new ArrayList<>(); + if(response.hasButtons()) components.add(ActionRow.of(response.getButtons())); + if(response.hasSelectMenu()) components.add(ActionRow.of(response.getSelectMenu())); + hook.editOriginalComponents(components).queue(); + } + } + } + + private List getOptions(List options){ + List args = new ArrayList<>(); + options.forEach(option -> { + switch (option.getType()) { + case STRING -> args.add(option.getAsString()); + case INTEGER -> args.add(option.getAsInt()); + case BOOLEAN -> args.add(option.getAsBoolean()); + case USER -> args.add(option.getAsMember()); + case CHANNEL -> args.add(option.getAsChannel()); + case ROLE -> args.add(option.getAsRole()); + case MENTIONABLE -> args.add(option.getAsMentionable()); + default -> { + } + } + }); + return args; + } + +} diff --git a/src/main/java/net/tylermurphy/ken/command/Response.java b/src/main/java/net/tylermurphy/ken/command/Response.java index 6f6b339..ff69cda 100644 --- a/src/main/java/net/tylermurphy/ken/command/Response.java +++ b/src/main/java/net/tylermurphy/ken/command/Response.java @@ -2,6 +2,7 @@ package net.tylermurphy.ken.command; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.interactions.components.buttons.Button; +import net.dv8tion.jda.api.interactions.components.selections.SelectMenu; import java.io.File; import java.util.ArrayList; @@ -14,14 +15,18 @@ public class Response { private final String type; private final MessageEmbed[] embeds; private final List