Discord player lookups
This commit is contained in:
parent
e6a12c3675
commit
0ba927b7d1
@ -11,10 +11,11 @@
|
||||
|
||||
<!-- Properties -->
|
||||
<properties>
|
||||
<java.version>8</java.version>
|
||||
<java.version>17</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<slf4j.version>2.1.0-alpha1</slf4j.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
@ -100,6 +101,8 @@
|
||||
<version>1.18.32</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Libraries -->
|
||||
<dependency>
|
||||
<groupId>net.dv8tion</groupId>
|
||||
<artifactId>JDA</artifactId>
|
||||
@ -117,5 +120,19 @@
|
||||
<version>1.0.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -1,8 +1,62 @@
|
||||
package cc.restfulmc.bot;
|
||||
|
||||
import cc.restfulmc.bot.command.CommandManager;
|
||||
import cc.restfulmc.sdk.client.ClientConfig;
|
||||
import cc.restfulmc.sdk.client.RESTfulMCClient;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.SelfUser;
|
||||
|
||||
/**
|
||||
* @author Braydon
|
||||
*/
|
||||
@Slf4j(topic = "RESTfulMC Bot") @Getter
|
||||
public final class DiscordBot {
|
||||
public static void main(String[] args) { }
|
||||
/**
|
||||
* The JDA bot instance.
|
||||
*/
|
||||
private JDA jda;
|
||||
|
||||
@SneakyThrows
|
||||
public DiscordBot() {
|
||||
String token = System.getenv("BOT_TOKEN");
|
||||
if (token == null) { // Missing BOT_TOKEN
|
||||
throw new NullPointerException("Missing BOT_TOKEN environment variable");
|
||||
}
|
||||
jda = JDABuilder.createLight(token)
|
||||
.setActivity(Activity.watching("Minecraft servers"))
|
||||
.build();
|
||||
jda.awaitReady(); // Wait for JDA to become ready
|
||||
|
||||
// Setup the API SDK
|
||||
RESTfulMCClient apiClient = new RESTfulMCClient(ClientConfig.defaultConfig());
|
||||
|
||||
// Commands
|
||||
new CommandManager(this, apiClient);
|
||||
|
||||
SelfUser self = jda.getSelfUser();
|
||||
log.info("Logged in as bot {} ({})", self.getAsTag(), self.getId());
|
||||
|
||||
// Add a cleanup hook to cleanup the bot when the JVM shuts down
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(this::cleanup));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the bot.
|
||||
*/
|
||||
public void cleanup() {
|
||||
log.info("Cleaning up...");
|
||||
jda.shutdown();
|
||||
jda = null;
|
||||
log.info("Goodbye!");
|
||||
}
|
||||
|
||||
public static void main(@NonNull String[] args) {
|
||||
new DiscordBot();
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package cc.restfulmc.bot.command;
|
||||
|
||||
import cc.restfulmc.bot.DiscordBot;
|
||||
import cc.restfulmc.bot.command.impl.PlayerCommand;
|
||||
import cc.restfulmc.sdk.client.RESTfulMCClient;
|
||||
import lombok.NonNull;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.Commands;
|
||||
import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Braydon
|
||||
*/
|
||||
public final class CommandManager extends ListenerAdapter {
|
||||
private final List<SlashCommand> commands = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
public CommandManager(@NonNull DiscordBot bot, @NonNull RESTfulMCClient apiClient) {
|
||||
registerCommand(new PlayerCommand(apiClient));
|
||||
|
||||
// Update the commands on Discord
|
||||
CommandListUpdateAction updateCommands = bot.getJda().updateCommands();
|
||||
for (SlashCommand command : commands) {
|
||||
updateCommands.addCommands(Commands.slash(command.getName(), command.getDescription()).addOptions(command.getOptions()));
|
||||
}
|
||||
updateCommands.queue();
|
||||
|
||||
// Handle registered events
|
||||
bot.getJda().addEventListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSlashCommandInteraction(@NonNull SlashCommandInteractionEvent event) {
|
||||
for (SlashCommand command : commands) {
|
||||
if (command.getName().equals(event.getName())) {
|
||||
event.deferReply().queue(); // Inform Discord we received the command
|
||||
command.onExecute(event.getUser(), event.getMember(), event); // Invoke the command
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a slash command.
|
||||
*
|
||||
* @param command the command to register
|
||||
*/
|
||||
public void registerCommand(@NonNull SlashCommand command) {
|
||||
commands.add(command);
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package cc.restfulmc.bot.command;
|
||||
|
||||
import cc.restfulmc.sdk.exception.RESTfulMCAPIException;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||
|
||||
/**
|
||||
* A wrapper for slash commands.
|
||||
*
|
||||
* @author Braydon
|
||||
*/
|
||||
@Getter
|
||||
public abstract class SlashCommand {
|
||||
/**
|
||||
* The name of this command.
|
||||
*/
|
||||
@NonNull private final String name;
|
||||
|
||||
/**
|
||||
* The description of this command.
|
||||
*/
|
||||
@NonNull private final String description;
|
||||
|
||||
/**
|
||||
* Optional options for this command.
|
||||
*/
|
||||
private final OptionData[] options;
|
||||
|
||||
public SlashCommand(@NonNull String name, @NonNull String description, OptionData... options) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when this command is executed.
|
||||
*
|
||||
* @param user the executing user
|
||||
* @param member the executing member, null if in dms
|
||||
* @param event the event that triggered this command
|
||||
*/
|
||||
public abstract void onExecute(@NonNull User user, Member member, @NonNull SlashCommandInteractionEvent event);
|
||||
|
||||
/**
|
||||
* Reply to an interaction with an API error.
|
||||
*
|
||||
* @param event the event to reply to
|
||||
* @param apiError the api error to reply with
|
||||
*/
|
||||
protected final void replyWithApiError(@NonNull SlashCommandInteractionEvent event, @NonNull RESTfulMCAPIException apiError) {
|
||||
event.getHook().sendMessageEmbeds(new EmbedBuilder()
|
||||
.setColor(0xAA0000)
|
||||
.setTitle(apiError.getCode() + " | API Error")
|
||||
.setDescription(apiError.getMessage())
|
||||
.build()).queue();
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package cc.restfulmc.bot.command.impl;
|
||||
|
||||
import cc.restfulmc.bot.command.SlashCommand;
|
||||
import cc.restfulmc.sdk.client.RESTfulMCClient;
|
||||
import cc.restfulmc.sdk.exception.RESTfulMCAPIException;
|
||||
import cc.restfulmc.sdk.response.Player;
|
||||
import lombok.NonNull;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Braydon
|
||||
*/
|
||||
public final class PlayerCommand extends SlashCommand {
|
||||
/**
|
||||
* The API client to use for lookups.
|
||||
*/
|
||||
@NonNull private final RESTfulMCClient apiClient;
|
||||
|
||||
public PlayerCommand(@NonNull RESTfulMCClient apiClient) {
|
||||
super("player", "Lookup a player by their username or UUID",
|
||||
new OptionData(OptionType.STRING, "query", "The player username or UUID").setRequired(true)
|
||||
);
|
||||
this.apiClient = apiClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when this command is executed.
|
||||
*
|
||||
* @param user the executing user
|
||||
* @param member the executing member, null if in dms
|
||||
* @param event the event that triggered this command
|
||||
*/
|
||||
@Override
|
||||
public void onExecute(@NonNull User user, Member member, @NonNull SlashCommandInteractionEvent event) {
|
||||
OptionMapping query = event.getOption("query"); // Get the query
|
||||
assert query != null;
|
||||
String queryValue = query.getAsString(); // Get the query value
|
||||
|
||||
// Lookup the requested player by the given query
|
||||
apiClient.async().getPlayer(queryValue).whenComplete((player, ex) -> {
|
||||
// Failed to lookup the player, handle the error
|
||||
if (ex != null) {
|
||||
if (ex.getCause() instanceof RESTfulMCAPIException apiError) {
|
||||
replyWithApiError(event, apiError);
|
||||
} else { // Only print real errors
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Respond with the player
|
||||
long cached = player.getCached(); // The timestamp the player was cached
|
||||
event.getHook().sendMessageEmbeds(new EmbedBuilder()
|
||||
.setColor(0x55FF55)
|
||||
.setTitle("<:grass_block:1232798337300828181> Player Response", "https://api.restfulmc.cc/player/" + queryValue)
|
||||
.addField("Unique ID", player.getUniqueId().toString(), true)
|
||||
.addField("Username", player.getUsername(), true)
|
||||
.addField("Legacy", player.isLegacy() ? "Yes" : "No", true)
|
||||
.addField("Cached", cached == -1L ? "No" : "Yes, <t:" + (cached / 1000L) + ":R>", true)
|
||||
.setThumbnail(player.getSkin().getParts().get(Player.SkinPart.HEAD))
|
||||
.setFooter("Requested by " + user.getName() + " | " + user.getId(), user.getEffectiveAvatarUrl())
|
||||
.build()).queue();
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user