Discord player lookups
This commit is contained in:
parent
e6a12c3675
commit
0ba927b7d1
@ -11,10 +11,11 @@
|
|||||||
|
|
||||||
<!-- Properties -->
|
<!-- Properties -->
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>8</java.version>
|
<java.version>17</java.version>
|
||||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<slf4j.version>2.1.0-alpha1</slf4j.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
@ -100,6 +101,8 @@
|
|||||||
<version>1.18.32</version>
|
<version>1.18.32</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Libraries -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.dv8tion</groupId>
|
<groupId>net.dv8tion</groupId>
|
||||||
<artifactId>JDA</artifactId>
|
<artifactId>JDA</artifactId>
|
||||||
@ -117,5 +120,19 @@
|
|||||||
<version>1.0.0</version>
|
<version>1.0.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</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>
|
</dependencies>
|
||||||
</project>
|
</project>
|
@ -1,8 +1,62 @@
|
|||||||
package cc.restfulmc.bot;
|
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
|
* @author Braydon
|
||||||
*/
|
*/
|
||||||
|
@Slf4j(topic = "RESTfulMC Bot") @Getter
|
||||||
public final class DiscordBot {
|
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…
x
Reference in New Issue
Block a user