From ee7e8b64c5ed508cf7d87d559a7ecfd6c9e8fc4d Mon Sep 17 00:00:00 2001 From: Liam Date: Sat, 6 Jul 2024 05:34:50 +0100 Subject: [PATCH] add minecraft server and player lookups --- pom.xml | 10 ++ .../cc/fascinated/bat/features/Feature.java | 2 + .../features/minecraft/MinecraftFeature.java | 23 ++++ .../command/LookupPlayerCommand.java | 65 +++++++++++ .../command/LookupServerCommand.java | 104 ++++++++++++++++++ .../minecraft/command/MinecraftCommand.java | 26 +++++ .../fascinated/bat/service/EventService.java | 1 + 7 files changed, 231 insertions(+) create mode 100644 src/main/java/cc/fascinated/bat/features/minecraft/MinecraftFeature.java create mode 100644 src/main/java/cc/fascinated/bat/features/minecraft/command/LookupPlayerCommand.java create mode 100644 src/main/java/cc/fascinated/bat/features/minecraft/command/LookupServerCommand.java create mode 100644 src/main/java/cc/fascinated/bat/features/minecraft/command/MinecraftCommand.java diff --git a/pom.xml b/pom.xml index 150a23b..19bd24b 100644 --- a/pom.xml +++ b/pom.xml @@ -75,6 +75,11 @@ jitpack.io https://jitpack.io + + fascinated-repo-public + Fascinated's Repository + https://repo.fascinated.cc/public + @@ -181,5 +186,10 @@ commons-text 1.12.0 + + xyz.mcutils + mcutils-java-library + 1.2.4 + diff --git a/src/main/java/cc/fascinated/bat/features/Feature.java b/src/main/java/cc/fascinated/bat/features/Feature.java index d5b1607..1ff4316 100644 --- a/src/main/java/cc/fascinated/bat/features/Feature.java +++ b/src/main/java/cc/fascinated/bat/features/Feature.java @@ -7,6 +7,8 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; +import java.lang.reflect.Member; + /** * @author Fascinated (fascinated7) */ diff --git a/src/main/java/cc/fascinated/bat/features/minecraft/MinecraftFeature.java b/src/main/java/cc/fascinated/bat/features/minecraft/MinecraftFeature.java new file mode 100644 index 0000000..dba7acd --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/minecraft/MinecraftFeature.java @@ -0,0 +1,23 @@ +package cc.fascinated.bat.features.minecraft; + +import cc.fascinated.bat.features.Feature; +import cc.fascinated.bat.features.FeatureProfile; +import cc.fascinated.bat.features.minecraft.command.MinecraftCommand; +import cc.fascinated.bat.service.CommandService; +import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component +public class MinecraftFeature extends Feature { + @Autowired + public MinecraftFeature(@NonNull ApplicationContext context, @NonNull CommandService commandService) { + super("Minecraft", FeatureProfile.FeatureState.DISABLED, true); + + super.registerCommand(commandService, context.getBean(MinecraftCommand.class)); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/minecraft/command/LookupPlayerCommand.java b/src/main/java/cc/fascinated/bat/features/minecraft/command/LookupPlayerCommand.java new file mode 100644 index 0000000..5ba6f36 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/minecraft/command/LookupPlayerCommand.java @@ -0,0 +1,65 @@ +package cc.fascinated.bat.features.minecraft.command; + +import cc.fascinated.bat.command.BatCommand; +import cc.fascinated.bat.command.CommandInfo; +import cc.fascinated.bat.common.EmbedDescriptionBuilder; +import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.model.BatGuild; +import cc.fascinated.bat.model.BatUser; +import lombok.NonNull; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; +import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import org.springframework.stereotype.Component; +import xyz.mcutils.McUtilsAPI; +import xyz.mcutils.models.cache.CachedPlayer; +import xyz.mcutils.models.player.Skin; + +/** + * @author Fascinated (fascinated7) + */ +@Component +@CommandInfo( + name = "lookup-player", + description = "Lookup a Minecraft player" +) +public class LookupPlayerCommand extends BatCommand { + public LookupPlayerCommand() { + super.addOptions( + new OptionData(OptionType.STRING, "player", "The player to lookup", true) + ); + } + + @Override + public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { + OptionMapping playerOption = event.getOption("player"); + if (playerOption == null) { + return; + } + String player = playerOption.getAsString(); + + CachedPlayer cachedPlayer = McUtilsAPI.getPlayer(player); + if (cachedPlayer == null) { + event.reply("The player `%s` could not be found".formatted(player)).queue(); + return; + } + + String headUrl = cachedPlayer.getSkin() != null ? cachedPlayer.getSkin().getParts().get(Skin.SkinPart.HEAD.getName()) : null; + EmbedDescriptionBuilder description = new EmbedDescriptionBuilder("Player Lookup") + .appendLine("Username: `%s`".formatted(cachedPlayer.getUsername()), true) + .appendLine("UUID: `%s`".formatted(cachedPlayer.getUniqueId().toString()), true); + if (cachedPlayer.getSkin() != null) { + description.appendLine("Skin: [Click Here](%s)".formatted(headUrl), true); + } + if (cachedPlayer.getCape() != null) { + description.appendLine("Cape: [Click Here](%s)".formatted(cachedPlayer.getCape().getUrl()), true); + } + event.replyEmbeds(EmbedUtils.successEmbed() + .setDescription(description.build()) + .setThumbnail(headUrl) + .build()).queue(); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/minecraft/command/LookupServerCommand.java b/src/main/java/cc/fascinated/bat/features/minecraft/command/LookupServerCommand.java new file mode 100644 index 0000000..2ca253c --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/minecraft/command/LookupServerCommand.java @@ -0,0 +1,104 @@ +package cc.fascinated.bat.features.minecraft.command; + +import cc.fascinated.bat.command.BatCommand; +import cc.fascinated.bat.command.CommandInfo; +import cc.fascinated.bat.common.EmbedDescriptionBuilder; +import cc.fascinated.bat.common.EmbedUtils; +import cc.fascinated.bat.model.BatGuild; +import cc.fascinated.bat.model.BatUser; +import lombok.NonNull; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; +import net.dv8tion.jda.api.interactions.commands.OptionMapping; +import net.dv8tion.jda.api.interactions.commands.OptionType; +import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction; +import net.dv8tion.jda.api.interactions.commands.build.OptionData; +import org.springframework.stereotype.Component; +import xyz.mcutils.McUtilsAPI; +import xyz.mcutils.models.cache.CachedBedrockMinecraftServer; +import xyz.mcutils.models.cache.CachedJavaMinecraftServer; +import xyz.mcutils.models.server.MinecraftServer; + +/** + * @author Fascinated (fascinated7) + */ +@Component +@CommandInfo( + name = "lookup-server", + description = "Lookup a Minecraft server" +) +public class LookupServerCommand extends BatCommand { + public LookupServerCommand() { + super.addOptions( + new OptionData(OptionType.STRING, "platform", "The platform of the server to lookup", true) + .addChoice("Java", "java") + .addChoice("Bedrock", "bedrock"), + new OptionData(OptionType.STRING, "host", "The host/ip of the server to lookup", true) + ); + } + + @Override + public void execute(BatGuild guild, @NonNull BatUser user, @NonNull MessageChannel channel, Member member, @NonNull SlashCommandInteraction event) { + OptionMapping platformOption = event.getOption("platform"); + OptionMapping hostOption = event.getOption("host"); + if (platformOption == null || hostOption == null) { + return; + } + String platform = platformOption.getAsString(); + String host = hostOption.getAsString(); + + MinecraftServer server; + try { + if (platform.equalsIgnoreCase("java")) { + server = McUtilsAPI.getJavaServer(host); + } else { + server = McUtilsAPI.getBedrockServer(host); + } + } catch (Exception ex) { + event.replyEmbeds(EmbedUtils.errorEmbed() + .setDescription("The server `%s` is invalid or offline".formatted(host)) + .build()).queue(); + return; + } + + int platformDefaultPort = platform.equalsIgnoreCase("java") ? 25565 : 19132; + String hostname = server.getHostname() + (server.getPort() != platformDefaultPort ? ":" + server.getPort() : ""); + EmbedDescriptionBuilder description = new EmbedDescriptionBuilder("Server Lookup [(Raw Data)](%s)".formatted( + "https://api.mcutils.xyz/server/%s/%s".formatted(platform, hostname) + )); + description.appendLine("Host: `%s`".formatted(hostname), true); + + MinecraftServer.GeoLocation location = server.getLocation(); + if (server instanceof CachedJavaMinecraftServer javaServer) { + description.appendLine("Version: `%s`".formatted(javaServer.getVersion().getName()), true); + if (javaServer.getForgeData() != null) { + description.appendLine("Forge Mods: `%s`".formatted(javaServer.getForgeData().getMods().length), true); + } + if (javaServer.isMojangBlocked()) { + description.appendLine("Mojang Blocked: `Yes`", true); + } + if (javaServer.isEnforcesSecureChat()) { + description.appendLine("Enforces Secure Chat: `Yes`", true); + } + if (javaServer.isPreventsChatReports()) { + description.appendLine("Prevents Chat Reports: `Yes`", true); + } + } + if (server instanceof CachedBedrockMinecraftServer bedrockServer) { + description.appendLine("Version: `%s`".formatted(bedrockServer.getVersion().getName()), true); + } + if (location != null) { + description.appendLine("Location: [%s](%s)".formatted( + (location.getCity() == null ? "" : location.getCity() + ", ") + location.getCountry(), + "https://www.google.com/maps/search/?api=1&query=%s,%s".formatted(location.getLatitude(), location.getLongitude()) + ), true); + } + + event.replyEmbeds(EmbedUtils.successEmbed() + .setDescription(description.build()) + .setThumbnail("https://api.mcutils.xyz/server/icon/%s".formatted(hostname)) + .setImage(server.getMotd().getPreview()) + .setFooter("Powered by mcutils.xyz") + .build()).queue(); + } +} diff --git a/src/main/java/cc/fascinated/bat/features/minecraft/command/MinecraftCommand.java b/src/main/java/cc/fascinated/bat/features/minecraft/command/MinecraftCommand.java new file mode 100644 index 0000000..f7d6a07 --- /dev/null +++ b/src/main/java/cc/fascinated/bat/features/minecraft/command/MinecraftCommand.java @@ -0,0 +1,26 @@ +package cc.fascinated.bat.features.minecraft.command; + +import cc.fascinated.bat.command.BatCommand; +import cc.fascinated.bat.command.CommandInfo; +import lombok.NonNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +/** + * @author Fascinated (fascinated7) + */ +@Component +@CommandInfo( + name = "minecraft", + description = "Minecraft related commands" +) +public class MinecraftCommand extends BatCommand { + @Autowired + public MinecraftCommand(@NonNull ApplicationContext context) { + super.addSubCommands( + context.getBean(LookupPlayerCommand.class), + context.getBean(LookupServerCommand.class) + ); + } +} diff --git a/src/main/java/cc/fascinated/bat/service/EventService.java b/src/main/java/cc/fascinated/bat/service/EventService.java index c9e3e55..40c2c4d 100644 --- a/src/main/java/cc/fascinated/bat/service/EventService.java +++ b/src/main/java/cc/fascinated/bat/service/EventService.java @@ -18,6 +18,7 @@ import net.dv8tion.jda.api.events.emoji.EmojiRemovedEvent; import net.dv8tion.jda.api.events.emoji.update.EmojiUpdateNameEvent; import net.dv8tion.jda.api.events.guild.GuildBanEvent; import net.dv8tion.jda.api.events.guild.GuildUnbanEvent; +import net.dv8tion.jda.api.events.guild.invite.GenericGuildInviteEvent; import net.dv8tion.jda.api.events.guild.invite.GuildInviteCreateEvent; import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent;