Skip to content

Commit

Permalink
Interaction Rework (#1971)
Browse files Browse the repository at this point in the history
Co-authored-by: Austin Keener <keeneraustin@yahoo.com>
Co-authored-by: caneleex <git@mlnr.dev>
  • Loading branch information
3 people committed Jan 29, 2022
1 parent f46b278 commit e5b80dc
Show file tree
Hide file tree
Showing 122 changed files with 6,756 additions and 2,883 deletions.
20 changes: 8 additions & 12 deletions README.md
Expand Up @@ -256,7 +256,7 @@ public class Bot extends ListenerAdapter
}

@Override
public void onSlashCommand(SlashCommandEvent event)
public void onSlashCommandInteraction(SlashCommandInteractionEvent event)
{
if (!event.getName().equals("ping")) return; // make sure we handle the right command
long time = System.currentTimeMillis();
Expand Down Expand Up @@ -592,13 +592,11 @@ Created and maintained by [MinnDevelopment](https://github.com/MinnDevelopment).

```kotlin
fun main() {
val jda = JDABuilder.createDefault(BOT_TOKEN)
.injectKTX()
.build()
val jda = light(BOT_TOKEN)

jda.onCommand("ping") { event ->
val time = measureTime {
event.reply("Pong!").await()
event.reply("Pong!").await() // suspending
}.inWholeMilliseconds

event.hook.editOriginal("Pong: $time ms").queue()
Expand All @@ -625,18 +623,16 @@ More information can be found at the wiki page [Contributing](https://github.com
When a feature is introduced to replace or enhance existing functionality we might deprecate old functionality.

A deprecated method/class usually has a replacement mentioned in its documentation which should be switched to. Deprecated
functionality might or might not exist in the next minor release. (Hint: The minor version is the `MM` of `XX.MM.RR_BB` in our version format)
functionality might or might not exist in the next minor release. (Hint: The minor version is the `MM` of `XX.MM.RR` in our version format)

It is possible that some features are deprecated without replacement, in this case the functionality is no longer supported by either the JDA structure
due to fundamental changes (for example automation of a feature) or due to discord API changes that cause it to be removed.
due to fundamental changes (for example automation of a feature) or due to Discord API changes that cause it to be removed.

We highly recommend to discontinue usage of deprecated functionality and update by going through each minor release instead of jumping.
We highly recommend discontinuing usage of deprecated functionality and update by going through each minor release instead of jumping.
For instance, when updating from version 3.3.0 to version 3.5.1 you should do the following:

- Update to `3.4.RR_BB` and check for deprecation, replace
- Update to `3.5.1_BB` and check for deprecation, replace

The `BB` indicates the build number specified in the release details.
- Update to `3.4.RR` and check for deprecation, replace
- Update to `3.5.1` and check for deprecation, replace

The `RR` in version `3.4.RR` should be replaced by the latest version that was published for `3.4`, you can find out which the latest
version was by looking at the [release page](https://github.com/DV8FromTheWorld/JDA/releases)
Expand Down
13 changes: 7 additions & 6 deletions build.gradle.kts
Expand Up @@ -39,6 +39,7 @@ plugins {
id("com.github.johnrengelman.shadow") version "7.1.0"
}

val javaVersion = JavaVersion.current()
val versionObj = Version(major = "5", minor = "0", revision = "0", classifier = "alpha.4")
val isCI = System.getProperty("BUILD_NUMBER") != null // jenkins
|| System.getenv("BUILD_NUMBER") != null
Expand Down Expand Up @@ -228,7 +229,7 @@ tasks.withType<JavaCompile> {
val arguments = mutableListOf("-Xlint:deprecation", "-Xlint:unchecked")
options.encoding = "UTF-8"
options.isIncremental = true
if (JavaVersion.current().isJava9Compatible) doFirst {
if (javaVersion.isJava9Compatible) doFirst {
arguments += "--release"
arguments += "8"
}
Expand All @@ -254,19 +255,19 @@ javadoc.apply {
options.memberLevel = JavadocMemberLevel.PUBLIC
options.encoding = "UTF-8"

if (options is StandardJavadocDocletOptions) {
val opt = options as StandardJavadocDocletOptions
(options as? StandardJavadocDocletOptions)?.let { opt ->
opt.author()
opt.tags("incubating:a:Incubating:")
opt.links(
"https://docs.oracle.com/javase/8/docs/api/",
"https://takahikokawasaki.github.io/nv-websocket-client/",
"https://square.github.io/okhttp/3.x/okhttp/")
if (JavaVersion.current().isJava9Compatible) {
opt.addBooleanOption("html5", true)
if (JavaVersion.VERSION_1_8 < javaVersion) {
opt.addBooleanOption("html5", true) // Adds search bar
opt.addStringOption("-release", "8")
}
if (JavaVersion.current().isJava11Compatible) {
// Fix for https://stackoverflow.com/questions/52326318/maven-javadoc-search-redirects-to-undefined-url
if (javaVersion in JavaVersion.VERSION_11..JavaVersion.VERSION_12) {
opt.addBooleanOption("-no-module-directories", true)
}
}
Expand Down
42 changes: 20 additions & 22 deletions src/examples/java/SlashBotExample.java
Expand Up @@ -20,14 +20,14 @@
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.interaction.ButtonClickEvent;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.interactions.InteractionHook;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.components.Button;
import net.dv8tion.jda.api.interactions.components.buttons.Button;
import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction;

Expand All @@ -49,27 +49,26 @@ public static void main(String[] args) throws LoginException

// Moderation commands with required options
commands.addCommands(
new CommandData("ban", "Ban a user from this server. Requires permission to ban users.")
Commands.slash("ban", "Ban a user from this server. Requires permission to ban users.")
.addOptions(new OptionData(USER, "user", "The user to ban") // USER type allows to include members of the server or other users by id
.setRequired(true)) // This command requires a parameter
.addOptions(new OptionData(INTEGER, "del_days", "Delete messages from the past days.")) // This is optional
);

// Simple reply commands
commands.addCommands(
new CommandData("say", "Makes the bot say what you tell it to")
.addOptions(new OptionData(STRING, "content", "What the bot should say")
.setRequired(true))
Commands.slash("say", "Makes the bot say what you tell it to")
.addOption(STRING, "content", "What the bot should say", true) // you can add required options like this too
);

// Commands without any inputs
commands.addCommands(
new CommandData("leave", "Make the bot leave the server")
Commands.slash("leave", "Make the bot leave the server")
);

commands.addCommands(
new CommandData("prune", "Prune messages from this channel")
.addOptions(new OptionData(INTEGER, "amount", "How many messages to prune (Default 100)"))
Commands.slash("prune", "Prune messages from this channel")
.addOption(INTEGER, "amount", "How many messages to prune (Default 100)") // simple optional argument
);

// Send the new set of commands to discord, this will override any existing global commands with the new set provided here
Expand All @@ -78,15 +77,15 @@ public static void main(String[] args) throws LoginException


@Override
public void onSlashCommand(SlashCommandEvent event)
public void onSlashCommandInteraction(SlashCommandInteractionEvent event)
{
// Only accept commands from guilds
if (event.getGuild() == null)
return;
switch (event.getName())
{
case "ban":
Member member = event.getOption("user").getAsMember(); // the "user" option is required so it doesn't need a null-check here
Member member = event.getOption("user").getAsMember(); // the "user" option is required, so it doesn't need a null-check here
User user = event.getOption("user").getAsUser();
ban(event, user, member);
break;
Expand All @@ -105,13 +104,12 @@ public void onSlashCommand(SlashCommandEvent event)
}

@Override
public void onButtonClick(ButtonClickEvent event)
public void onButtonInteraction(ButtonInteractionEvent event)
{
// users can spoof this id so be careful what you do with this
String[] id = event.getComponentId().split(":"); // this is the custom id we specified in our button
String authorId = id[0];
String type = id[1];
// When storing state like this is it is highly recommended to do some kind of verification that it was generated by you, for instance a signature or local cache
// Check that the button is for the user that clicked it, otherwise just ignore the event (let interaction fail)
if (!authorId.equals(event.getUser().getId()))
return;
event.deferEdit().queue(); // acknowledge the button was clicked, otherwise the interaction will fail
Expand All @@ -131,7 +129,7 @@ public void onButtonClick(ButtonClickEvent event)
}
}

public void ban(SlashCommandEvent event, User user, Member member)
public void ban(SlashCommandInteractionEvent event, User user, Member member)
{
event.deferReply(true).queue(); // Let the user know we received the command before doing anything else
InteractionHook hook = event.getHook(); // This is a special webhook that allows you to send messages without having permissions in the channel and also allows ephemeral messages
Expand Down Expand Up @@ -165,12 +163,12 @@ public void ban(SlashCommandEvent event, User user, Member member)
.queue();
}

public void say(SlashCommandEvent event, String content)
public void say(SlashCommandInteractionEvent event, String content)
{
event.reply(content).queue(); // This requires no permissions!
}

public void leave(SlashCommandEvent event)
public void leave(SlashCommandInteractionEvent event)
{
if (!event.getMember().hasPermission(Permission.KICK_MEMBERS))
event.reply("You do not have permissions to kick me.").setEphemeral(true).queue();
Expand All @@ -180,17 +178,17 @@ public void leave(SlashCommandEvent event)
.queue();
}

public void prune(SlashCommandEvent event)
public void prune(SlashCommandInteractionEvent event)
{
OptionMapping amountOption = event.getOption("amount"); // This is configured to be optional so check for null
int amount = amountOption == null
? 100 // default 100
: (int) Math.min(200, Math.max(2, amountOption.getAsLong())); // enforcement: must be between 2-200
String userId = event.getUser().getId();
event.reply("This will delete " + amount + " messages.\nAre you sure?") // prompt the user with a button menu
.addActionRow(// this means "<style>(<id>, <label>)" the id can be spoofed by the user so setup some kinda verification system
.addActionRow(// this means "<style>(<id>, <label>)", you can encode anything you want in the id (up to 100 characters)
Button.secondary(userId + ":delete", "Nevermind!"),
Button.danger(userId + ":prune:" + amount, "Yes!")) // the first parameter is the component id we use in onButtonClick above
Button.danger(userId + ":prune:" + amount, "Yes!")) // the first parameter is the component id we use in onButtonInteraction above
.queue();
}
}

0 comments on commit e5b80dc

Please sign in to comment.