diff --git a/README.md b/README.md index c9a4db2..95f3483 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ If not you can report it [here](https://github.com/Nyvil/Nyjava/issues) # Author(s) * **[Alexandros(@Nyvil)](https://github.com/Nyvil)** - initial work +* **[@Technosword](https://github.com/Technosword)** - buttons # License This project is licensed under the Apache 2.0 License - see the [LICENSE](https://github.com/Nyvil/Nyjava/blob/stable/LICENSE) file for details. diff --git a/src/main/java/uk/co/nyvil/Bot.java b/src/main/java/uk/co/nyvil/Bot.java index 6bed6dc..fa78c3b 100644 --- a/src/main/java/uk/co/nyvil/Bot.java +++ b/src/main/java/uk/co/nyvil/Bot.java @@ -11,6 +11,7 @@ import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.*; import uk.co.nyvil.bot.BotConnection; +import uk.co.nyvil.bot.buttons.manager.ButtonHandler; import uk.co.nyvil.bot.commands.manager.CommandHandler; import uk.co.nyvil.database.DatabaseConnection; import uk.co.nyvil.database.utils.DatabaseUtils; @@ -46,6 +47,8 @@ public class Bot { @Getter private CommandHandler commandHandler; @Getter + private ButtonHandler buttonhandler; + @Getter private DatabaseConnection databaseConnection; @Getter private BotConnection botConnection; @@ -83,6 +86,7 @@ private void start() { FileUtils.setToken(token); botConnection = new BotConnection(); commandHandler = new CommandHandler(); + buttonhandler = new ButtonHandler(); if (getInstance().dbStart) { databaseConnection = new DatabaseConnection(); } else { diff --git a/src/main/java/uk/co/nyvil/bot/buttons/manager/ButtonAnnotation.java b/src/main/java/uk/co/nyvil/bot/buttons/manager/ButtonAnnotation.java new file mode 100644 index 0000000..bf9f46d --- /dev/null +++ b/src/main/java/uk/co/nyvil/bot/buttons/manager/ButtonAnnotation.java @@ -0,0 +1,10 @@ +package uk.co.nyvil.bot.buttons.manager; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(value = RetentionPolicy.RUNTIME) +public @interface ButtonAnnotation { + + String id(); +} diff --git a/src/main/java/uk/co/nyvil/bot/buttons/manager/ButtonClickHandler.java b/src/main/java/uk/co/nyvil/bot/buttons/manager/ButtonClickHandler.java new file mode 100644 index 0000000..b3cacbd --- /dev/null +++ b/src/main/java/uk/co/nyvil/bot/buttons/manager/ButtonClickHandler.java @@ -0,0 +1,35 @@ +package uk.co.nyvil.bot.buttons.manager; + +import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import org.jetbrains.annotations.NotNull; +import uk.co.nyvil.Bot; +import uk.co.nyvil.bot.buttons.status.ButtonClickInfo; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; + + +public class ButtonClickHandler extends ListenerAdapter { + + @Override + public void onButtonClick(@NotNull ButtonClickEvent event) { + if(event.getGuild() == null) return; + if(event.getUser().isBot()) return; + if(event.getMember() == null) return; + + String componentID = event.getComponentId(); + Map buttonMap = Bot.getInstance().getButtonhandler().getButtonMap(); + if (Bot.getInstance().getButtonhandler().getButtonMap().containsKey(componentID)) { + ButtonMethods buttonMethod = Bot.getInstance().getButtonhandler().getButtonMap().get(componentID); + final Method method = buttonMethod.getMethod(); + + try { + method.invoke(buttonMethod.getObj(), new ButtonClickInfo(event, event.getMember(), event.getTextChannel(), componentID)); + } catch (IllegalAccessException | InvocationTargetException ex) { + ex.printStackTrace(); + } + } + } +} diff --git a/src/main/java/uk/co/nyvil/bot/buttons/manager/ButtonHandler.java b/src/main/java/uk/co/nyvil/bot/buttons/manager/ButtonHandler.java new file mode 100644 index 0000000..4a10038 --- /dev/null +++ b/src/main/java/uk/co/nyvil/bot/buttons/manager/ButtonHandler.java @@ -0,0 +1,47 @@ +package uk.co.nyvil.bot.buttons.manager; + +import lombok.Getter; +import uk.co.nyvil.bot.buttons.status.ButtonClickInfo; +import uk.co.nyvil.bot.commands.commands.PingCommand; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; + +public class ButtonHandler { + @Getter + public final Map buttonMap = new HashMap<>(); + + /** + * Declare all classes that contain buttons in this class + */ + public ButtonHandler(){ + registerButtons(PingCommand.class); + } + private void registerButtons(Object... objs) { + for (Object obj : objs) { + final Class cls = obj.getClass(); + + Arrays.stream(cls.getDeclaredMethods()) + .filter(method -> + (method.getModifiers() & (Modifier.PROTECTED | Modifier.PRIVATE)) == 0 + && method.isAnnotationPresent(ButtonAnnotation.class) + && method.getParameterCount() == 1 + && method.getParameterTypes()[0] == ButtonClickInfo.class + ) + .sorted(Comparator.comparing(Method::getName)) + .forEach(method -> { + final String id = method.getAnnotation(ButtonAnnotation.class).id(); + + if (!id.isEmpty()) { + buttonMap.put(id, new ButtonMethods(cls, method)); + } else { + System.err.println("No declared buttons found in " + cls.getName() + "."); + } + }); + } + } +} diff --git a/src/main/java/uk/co/nyvil/bot/buttons/manager/ButtonMethods.java b/src/main/java/uk/co/nyvil/bot/buttons/manager/ButtonMethods.java new file mode 100644 index 0000000..04a5a6f --- /dev/null +++ b/src/main/java/uk/co/nyvil/bot/buttons/manager/ButtonMethods.java @@ -0,0 +1,16 @@ +package uk.co.nyvil.bot.buttons.manager; + +import lombok.Getter; + +import java.lang.reflect.Method; + +@Getter +public class ButtonMethods { + private final Object obj; + private final Method method; + + ButtonMethods(Object obj, Method method) { + this.obj = obj; + this.method = method; + } +} diff --git a/src/main/java/uk/co/nyvil/bot/buttons/status/ButtonClickInfo.java b/src/main/java/uk/co/nyvil/bot/buttons/status/ButtonClickInfo.java new file mode 100644 index 0000000..1afe790 --- /dev/null +++ b/src/main/java/uk/co/nyvil/bot/buttons/status/ButtonClickInfo.java @@ -0,0 +1,23 @@ +package uk.co.nyvil.bot.buttons.status; + +import lombok.Getter; +import lombok.Setter; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.TextChannel; +import net.dv8tion.jda.api.events.interaction.ButtonClickEvent; + +@Getter +@Setter +public class ButtonClickInfo { + private final ButtonClickEvent event; + private final Member clicker; + private final TextChannel textChannel; + private final String id; + + public ButtonClickInfo(ButtonClickEvent event, Member clicker, TextChannel textChannel, String id) { + this.event = event; + this.clicker = clicker; + this.textChannel = textChannel; + this.id = id; + } +} diff --git a/src/main/java/uk/co/nyvil/bot/commands/commands/PingCommand.java b/src/main/java/uk/co/nyvil/bot/commands/commands/PingCommand.java index 75277c9..2ed0e1d 100644 --- a/src/main/java/uk/co/nyvil/bot/commands/commands/PingCommand.java +++ b/src/main/java/uk/co/nyvil/bot/commands/commands/PingCommand.java @@ -1,20 +1,33 @@ package uk.co.nyvil.bot.commands.commands; import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.interactions.components.Button; import uk.co.nyvil.bot.BotConnection; +import uk.co.nyvil.bot.buttons.manager.ButtonAnnotation; +import uk.co.nyvil.bot.buttons.status.ButtonClickInfo; import uk.co.nyvil.bot.commands.manager.*; import uk.co.nyvil.bot.commands.status.SlashCommandExecutionInfo; import uk.co.nyvil.utils.MessageUtils; +import java.util.Objects; + public class PingCommand implements SlashCommand { @Override @SlashCommandAnnotation(name = "ping") public void execute(SlashCommandExecutionInfo info) { final long time = System.currentTimeMillis(); - info.getEvent().replyEmbeds(MessageUtils.createInfoEmbed("Current Gateaway latency: " + BotConnection.getJda().getGatewayPing() + "ms\nResponse time: measuring...").build()).queue(message -> { - message.editOriginalEmbeds(MessageUtils.createInfoEmbed("Current Gateaway latency: " + BotConnection.getJda().getGatewayPing() + "ms\nResponse time: " + (System.currentTimeMillis() - time) + "ms").build()).queue(); - }); + info.getEvent().replyEmbeds(MessageUtils.createInfoEmbed("Current Gateaway latency: " + BotConnection.getJda().getGatewayPing() + "ms\nResponse time: measuring...").build()) + .addActionRow(Button.primary("ping", "Refresh")) + .queue(message -> message.editOriginalEmbeds(MessageUtils.createInfoEmbed("Current Gateaway latency: " + BotConnection.getJda().getGatewayPing() + "ms\nResponse time: " + (System.currentTimeMillis() - time) + "ms").build()).queue()); + } + + @ButtonAnnotation(id ="ping") + public void onButtonClick(ButtonClickInfo info) { + final long time = System.currentTimeMillis(); + Objects.requireNonNull(info.getEvent().getMessage()).editMessage(MessageUtils.createInfoEmbed("Current Gateaway latency: " + BotConnection.getJda().getGatewayPing() + "ms\nResponse time: measuring...").build()) + .queue(message -> message.editMessage(MessageUtils.createInfoEmbed("Current Gateaway latency: " + BotConnection.getJda().getGatewayPing() + "ms\nResponse time: " + (System.currentTimeMillis() - time) + "ms").build()).queue()); + info.getEvent().reply("Updated the ping!").setEphemeral(true).queue(); } @Override