diff --git a/build.gradle b/build.gradle index b2f0eaf..be5573d 100644 --- a/build.gradle +++ b/build.gradle @@ -31,7 +31,7 @@ version = getVersion() println("Version: ${version}") dependencies { - implementation group: 'org.javacord', name: 'javacord', version: javacord_version + implementation group: 'net.dv8tion', name: 'JDA', version: jda_version implementation group: 'com.electronwill.night-config', name: 'toml', version: nightconfig_version implementation group: 'net.sf.jopt-simple', name: 'jopt-simple', version: jopt_version implementation group: 'com.google.guava', name: 'guava', version: guava_version diff --git a/gradle.properties b/gradle.properties index 4b7622e..7d02ac1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ grgit_version=4.0.2 shadow_version=6.0.0 -javacord_version=3.0.6 +jda_version=4.2.0_168 nightconfig_version=3.6.3 jopt_version=6.0-alpha-3 guava_version=29.0-jre diff --git a/src/main/java/sciwhiz12/janitor/BotConsole.java b/src/main/java/sciwhiz12/janitor/BotConsole.java index c2e368f..7399717 100644 --- a/src/main/java/sciwhiz12/janitor/BotConsole.java +++ b/src/main/java/sciwhiz12/janitor/BotConsole.java @@ -36,7 +36,7 @@ public class BotConsole { String[] parts = input.split(" "); switch (parts[0]) { case "shutdown": { - bot.disconnect(); + bot.shutdown(); break; } default: diff --git a/src/main/java/sciwhiz12/janitor/BotStartup.java b/src/main/java/sciwhiz12/janitor/BotStartup.java index 22b1898..919884a 100644 --- a/src/main/java/sciwhiz12/janitor/BotStartup.java +++ b/src/main/java/sciwhiz12/janitor/BotStartup.java @@ -1,6 +1,12 @@ package sciwhiz12.janitor; -import org.javacord.api.DiscordApiBuilder; +import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.OnlineStatus; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.events.ReadyEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.requests.GatewayIntent; +import org.jetbrains.annotations.NotNull; import sciwhiz12.janitor.config.BotConfig; import sciwhiz12.janitor.config.BotOptions; @@ -19,9 +25,18 @@ public class BotStartup { JANITOR.info("Building bot instance and connecting to Discord..."); try { - DiscordApiBuilder builder = new DiscordApiBuilder().setToken(config.getToken().get()); - builder.login() - .thenAccept(api -> new JanitorBot(api, config)); + JDABuilder builder = JDABuilder.createDefault(config.getToken().get()); + builder.enableIntents(GatewayIntent.GUILD_MESSAGES, GatewayIntent.DIRECT_MESSAGES, GatewayIntent.GUILD_MEMBERS) + .setStatus(OnlineStatus.DO_NOT_DISTURB) + .setAutoReconnect(true) + .setActivity(Activity.listening("for the ready call...")) + .addEventListeners(new ListenerAdapter() { + @Override + public void onReady(@NotNull ReadyEvent event) { + new JanitorBot(event.getJDA(), config); + } + }) + .build(); } catch (Exception ex) { JANITOR.error("Error while building Discord connection", ex); } diff --git a/src/main/java/sciwhiz12/janitor/JanitorBot.java b/src/main/java/sciwhiz12/janitor/JanitorBot.java index a4b7b5f..ea532e4 100644 --- a/src/main/java/sciwhiz12/janitor/JanitorBot.java +++ b/src/main/java/sciwhiz12/janitor/JanitorBot.java @@ -1,9 +1,10 @@ package sciwhiz12.janitor; -import org.javacord.api.DiscordApi; -import org.javacord.api.entity.activity.ActivityType; -import org.javacord.api.entity.user.User; -import org.javacord.api.entity.user.UserStatus; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.OnlineStatus; +import net.dv8tion.jda.api.entities.Activity; +import net.dv8tion.jda.api.entities.PrivateChannel; +import net.dv8tion.jda.api.entities.User; import sciwhiz12.janitor.commands.CommandRegistry; import sciwhiz12.janitor.config.BotConfig; import sciwhiz12.janitor.utils.Util; @@ -12,35 +13,34 @@ import static sciwhiz12.janitor.Logging.JANITOR; import static sciwhiz12.janitor.Logging.STATUS; public class JanitorBot { - private final DiscordApi discord; + private final JDA discord; private final BotConfig config; private final BotConsole console; private final CommandRegistry cmdRegistry; - public JanitorBot(DiscordApi discord, BotConfig config) { + public JanitorBot(JDA discord, BotConfig config) { this.config = config; this.console = new BotConsole(this, System.in); this.cmdRegistry = new CommandRegistry(this, config.getCommandPrefix()); this.discord = discord; - discord.addMessageCreateListener(cmdRegistry); - discord.updateStatus(UserStatus.ONLINE); - discord.updateActivity(ActivityType.PLAYING, " n' sweeping n' testing!"); + discord.addEventListener(cmdRegistry); + discord.getPresence().setPresence(OnlineStatus.ONLINE, Activity.playing(" n' sweeping n' testing!")); JANITOR.info("Ready!"); config.getOwnerID() - .map(ownerId -> getDiscord().getUserById(ownerId)) + .map(discord::retrieveUserById) .ifPresent(retrieveUser -> retrieveUser - .thenCompose(User::openPrivateChannel) - .thenCompose(channel -> channel.sendMessage("Started up and ready!")) - .whenCompleteAsync(Util.handle( + .flatMap(User::openPrivateChannel) + .flatMap(channel -> channel.sendMessage("Started up and ready!")) + .queue( msg -> JANITOR.debug(STATUS, "Sent ready message to owner!"), - error -> JANITOR.error(STATUS, "Error while sending ready message to owner", error)) + error -> JANITOR.error(STATUS, "Error while sending ready message to owner", error) ) ); console.start(); } - public DiscordApi getDiscord() { + public JDA getDiscord() { return this.discord; } @@ -52,24 +52,28 @@ public class JanitorBot { return this.cmdRegistry; } - public void disconnect() { + public void shutdown() { JANITOR.info(STATUS, "Shutting down!"); console.stop(); - discord.disconnect(); -// getConfig().getOwnerID() -// .map(id -> getJDA().getUserById(id)) -// .ifPresent(owner -> owner.openPrivateChannel().submit() -// .thenCompose(channel -> channel.sendMessage( -// "Shutting down, in accordance with your orders. Goodbye!") -// .submit()) -// .whenComplete(Util.handle( -// msg -> JANITOR -// .debug(STATUS, "Sent shutdown message to owner: {}", -// Util.toString(owner)), -// err -> JANITOR -// .error(STATUS, "Error while sending shutdown message to owner", err) -// )) -// .join()); -// getJDA().shutdown(); + getConfig().getOwnerID() + .map(discord::retrieveUserById) + .map(owner -> + owner + .flatMap(User::openPrivateChannel) + .flatMap(channel -> + channel.sendMessage("Shutting down, in accordance with your orders. Goodbye!")) + .submit() + .whenComplete(Util.handle( + msg -> + JANITOR + .debug(STATUS, "Sent shutdown message to owner: {}", + Util.toString(((PrivateChannel) msg.getChannel()).getUser())), + err -> + JANITOR + .error(STATUS, "Error while sending shutdown message to owner", err) + )) + .join() + ); + discord.shutdown(); } } diff --git a/src/main/java/sciwhiz12/janitor/commands/BaseCommand.java b/src/main/java/sciwhiz12/janitor/commands/BaseCommand.java index c578ae3..e953bac 100644 --- a/src/main/java/sciwhiz12/janitor/commands/BaseCommand.java +++ b/src/main/java/sciwhiz12/janitor/commands/BaseCommand.java @@ -1,7 +1,7 @@ package sciwhiz12.janitor.commands; import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import org.javacord.api.event.message.MessageCreateEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import sciwhiz12.janitor.JanitorBot; public abstract class BaseCommand { @@ -19,5 +19,5 @@ public abstract class BaseCommand { return registry.getBot(); } - public abstract LiteralArgumentBuilder getNode(); + public abstract LiteralArgumentBuilder getNode(); } diff --git a/src/main/java/sciwhiz12/janitor/commands/CommandRegistry.java b/src/main/java/sciwhiz12/janitor/commands/CommandRegistry.java index d971a9a..38c7800 100644 --- a/src/main/java/sciwhiz12/janitor/commands/CommandRegistry.java +++ b/src/main/java/sciwhiz12/janitor/commands/CommandRegistry.java @@ -4,8 +4,10 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.ParseResults; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import org.javacord.api.event.message.MessageCreateEvent; -import org.javacord.api.listener.message.MessageCreateListener; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import net.dv8tion.jda.api.hooks.EventListener; +import org.jetbrains.annotations.NotNull; import sciwhiz12.janitor.JanitorBot; import sciwhiz12.janitor.commands.bot.ShutdownCommand; import sciwhiz12.janitor.commands.misc.HelloCommand; @@ -19,16 +21,14 @@ import java.util.Map; import static sciwhiz12.janitor.Logging.COMMANDS; import static sciwhiz12.janitor.Logging.JANITOR; -public class CommandRegistry implements MessageCreateListener { +public class CommandRegistry implements EventListener { private final JanitorBot bot; - // private final Pattern pattern; private final String prefix; private final Map registry = new HashMap<>(); - private final CommandDispatcher dispatcher; + private final CommandDispatcher dispatcher; public CommandRegistry(JanitorBot bot, String prefix) { this.bot = bot; -// this.pattern = Pattern.compile("^" + prefix + "([A-Za-z0-9]+).*$"); this.prefix = prefix; this.dispatcher = new CommandDispatcher<>(); @@ -41,7 +41,7 @@ public class CommandRegistry implements MessageCreateListener { } } - public CommandDispatcher getDispatcher() { + public CommandDispatcher getDispatcher() { return this.dispatcher; } @@ -54,14 +54,16 @@ public class CommandRegistry implements MessageCreateListener { } @Override - public void onMessageCreate(MessageCreateEvent event) { - String msg = event.getMessage().getContent(); + public void onEvent(@NotNull GenericEvent genericEvent) { + if (!(genericEvent instanceof MessageReceivedEvent)) return; + MessageReceivedEvent event = (MessageReceivedEvent) genericEvent; + String msg = event.getMessage().getContentRaw(); if (!msg.startsWith(this.prefix)) return; JANITOR.debug(COMMANDS, "Received message starting with valid command prefix. Author: {}, full message: {}", - Util.toString(event.getMessageAuthor().asUser().orElse(null)), msg); + Util.toString(event.getAuthor()), msg); try { StringReader command = new StringReader(msg.substring(this.prefix.length())); - ParseResults parseResults = this.dispatcher.parse(command, event); + ParseResults parseResults = this.dispatcher.parse(command, event); if (parseResults.getReader().canRead()) { // Parsing did not succeed, i.e. command not found // TODO: add separate code path when insufficient permissions / requires fails diff --git a/src/main/java/sciwhiz12/janitor/commands/arguments/UserArgument.java b/src/main/java/sciwhiz12/janitor/commands/arguments/UserArgument.java index 3d23e9a..772ca18 100644 --- a/src/main/java/sciwhiz12/janitor/commands/arguments/UserArgument.java +++ b/src/main/java/sciwhiz12/janitor/commands/arguments/UserArgument.java @@ -7,11 +7,11 @@ import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import org.javacord.api.DiscordApi; -import org.javacord.api.entity.user.User; +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.requests.RestAction; import java.util.Collection; -import java.util.concurrent.CompletableFuture; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -62,7 +62,7 @@ public class UserArgument implements ArgumentType { } public interface IUserProvider { - CompletableFuture getUsers(DiscordApi api); + RestAction getUsers(JDA api); } static class NumericalProvider implements IUserProvider { @@ -73,8 +73,8 @@ public class UserArgument implements ArgumentType { } @Override - public CompletableFuture getUsers(DiscordApi api) { - return api.getUserById(snowflakeID); + public RestAction getUsers(JDA api) { + return api.retrieveUserById(snowflakeID); } } } diff --git a/src/main/java/sciwhiz12/janitor/commands/bot/ShutdownCommand.java b/src/main/java/sciwhiz12/janitor/commands/bot/ShutdownCommand.java index cd8cd69..81d45a9 100644 --- a/src/main/java/sciwhiz12/janitor/commands/bot/ShutdownCommand.java +++ b/src/main/java/sciwhiz12/janitor/commands/bot/ShutdownCommand.java @@ -2,7 +2,7 @@ package sciwhiz12.janitor.commands.bot; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; -import org.javacord.api.event.message.MessageCreateEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import sciwhiz12.janitor.commands.BaseCommand; import sciwhiz12.janitor.commands.CommandRegistry; import sciwhiz12.janitor.utils.Util; @@ -19,23 +19,25 @@ public class ShutdownCommand extends BaseCommand { } @Override - public LiteralArgumentBuilder getNode() { + public LiteralArgumentBuilder getNode() { return literal("shutdown") - .requires(ctx -> ctx.getMessageAuthor().getId() == ownerID) + .requires(ctx -> ctx.getAuthor().getIdLong() == ownerID) .executes(this::run); } - int run(final CommandContext ctx) { + int run(final CommandContext ctx) { ctx.getSource() .getMessage() .getChannel() .sendMessage("Shutting down, in accordance with the owner's command. Goodbye all!") - .whenCompleteAsync(Util.handle( - success -> JANITOR.debug("Sent shutdown message to channel {}", Util.toString(ctx.getSource().getMessageAuthor())), - err -> JANITOR.error("Error while sending ping message to bot owner {}", Util.toString(ctx.getSource().getMessageAuthor())) + .submit() + .whenComplete(Util.handle( + success -> JANITOR.debug("Sent shutdown message to channel {}", Util.toString(ctx.getSource().getAuthor())), + err -> JANITOR.error("Error while sending ping message to bot owner {}", Util.toString(ctx.getSource().getAuthor())) ) - ).join(); - getBot().disconnect(); + ) + .join(); + getBot().shutdown(); return 1; } } diff --git a/src/main/java/sciwhiz12/janitor/commands/misc/HelloCommand.java b/src/main/java/sciwhiz12/janitor/commands/misc/HelloCommand.java index 8c3f025..45d5ead 100644 --- a/src/main/java/sciwhiz12/janitor/commands/misc/HelloCommand.java +++ b/src/main/java/sciwhiz12/janitor/commands/misc/HelloCommand.java @@ -2,7 +2,7 @@ package sciwhiz12.janitor.commands.misc; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; -import org.javacord.api.event.message.MessageCreateEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import sciwhiz12.janitor.commands.BaseCommand; import sciwhiz12.janitor.commands.CommandRegistry; import sciwhiz12.janitor.commands.arguments.UserArgument; @@ -17,7 +17,7 @@ public class HelloCommand extends BaseCommand { super(registry); } - public LiteralArgumentBuilder getNode() { + public LiteralArgumentBuilder getNode() { return literal("greet") .then( argument("user", UserArgument.user()) @@ -25,18 +25,13 @@ public class HelloCommand extends BaseCommand { ); } - int run(final CommandContext ctx) { - UserArgument.getUser("user", ctx).getUsers(ctx.getSource().getApi()) - .thenCompose(user -> - ctx.getSource() - .getMessage() - .getChannel() - .sendMessage("Hello " + user.getMentionTag() + " !") - ) - .whenCompleteAsync(Util.handle( - success -> JANITOR.debug("Sent greeting message to {}", Util.toString(ctx.getSource().getMessageAuthor())), - err -> JANITOR.error("Error while sending greeting message to {}", Util.toString(ctx.getSource().getMessageAuthor())) - ) + int run(final CommandContext ctx) { + UserArgument.getUser("user", ctx) + .getUsers(getBot().getDiscord()) + .flatMap(user -> ctx.getSource().getChannel().sendMessage("Hello " + user.getAsMention() + "!")) + .queue( + success -> JANITOR.debug("Sent greeting message to {}", Util.toString(ctx.getSource().getAuthor())), + err -> JANITOR.error("Error while sending greeting message to {}", Util.toString(ctx.getSource().getAuthor())) ); return 1; } diff --git a/src/main/java/sciwhiz12/janitor/commands/misc/OKCommand.java b/src/main/java/sciwhiz12/janitor/commands/misc/OKCommand.java index 2a32f5f..5ce9f78 100644 --- a/src/main/java/sciwhiz12/janitor/commands/misc/OKCommand.java +++ b/src/main/java/sciwhiz12/janitor/commands/misc/OKCommand.java @@ -2,7 +2,7 @@ package sciwhiz12.janitor.commands.misc; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; -import org.javacord.api.event.message.MessageCreateEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import sciwhiz12.janitor.commands.BaseCommand; import sciwhiz12.janitor.commands.CommandRegistry; import sciwhiz12.janitor.utils.Util; @@ -15,19 +15,18 @@ public class OKCommand extends BaseCommand { super(registry); } - public LiteralArgumentBuilder getNode() { + public LiteralArgumentBuilder getNode() { return literal("ok") .executes(this::run); } - int run(final CommandContext ctx) { + int run(final CommandContext ctx) { ctx.getSource() .getMessage() .addReaction("\uD83D\uDC4C") - .whenCompleteAsync(Util.handle( - success -> JANITOR.debug("Reacted :ok_hand: to {}'s message", Util.toString(ctx.getSource().getMessageAuthor())), - err -> JANITOR.error("Error while reacting :ok_hand: to {}'s message", Util.toString(ctx.getSource().getMessageAuthor())) - ) + .queue( + success -> JANITOR.debug("Reacted :ok_hand: to {}'s message", Util.toString(ctx.getSource().getAuthor())), + err -> JANITOR.error("Error while reacting :ok_hand: to {}'s message", Util.toString(ctx.getSource().getAuthor())) ); return 1; } diff --git a/src/main/java/sciwhiz12/janitor/commands/misc/PingCommand.java b/src/main/java/sciwhiz12/janitor/commands/misc/PingCommand.java index 803cdac..d6ab9b0 100644 --- a/src/main/java/sciwhiz12/janitor/commands/misc/PingCommand.java +++ b/src/main/java/sciwhiz12/janitor/commands/misc/PingCommand.java @@ -2,7 +2,7 @@ package sciwhiz12.janitor.commands.misc; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; -import org.javacord.api.event.message.MessageCreateEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import sciwhiz12.janitor.commands.BaseCommand; import sciwhiz12.janitor.commands.CommandRegistry; import sciwhiz12.janitor.utils.Util; @@ -20,20 +20,19 @@ public class PingCommand extends BaseCommand { this.reply = reply; } - public LiteralArgumentBuilder getNode() { + public LiteralArgumentBuilder getNode() { return literal(command) .executes(this::run); } - int run(final CommandContext ctx) { + int run(final CommandContext ctx) { ctx.getSource() .getMessage() .getChannel() .sendMessage(reply) - .whenCompleteAsync(Util.handle( - success -> JANITOR.debug("Sent ping message to {}: {}", Util.toString(ctx.getSource().getMessageAuthor()), reply), - err -> JANITOR.error("Error while sending ping message to {}", Util.toString(ctx.getSource().getMessageAuthor())) - ) + .queue( + success -> JANITOR.debug("Sent ping message to {}: {}", Util.toString(ctx.getSource().getAuthor()), reply), + err -> JANITOR.error("Error while sending ping message to {}", Util.toString(ctx.getSource().getAuthor())) ); return 1; } diff --git a/src/main/java/sciwhiz12/janitor/utils/CommandHelper.java b/src/main/java/sciwhiz12/janitor/utils/CommandHelper.java index e2bd524..00480b1 100644 --- a/src/main/java/sciwhiz12/janitor/utils/CommandHelper.java +++ b/src/main/java/sciwhiz12/janitor/utils/CommandHelper.java @@ -3,14 +3,14 @@ package sciwhiz12.janitor.utils; import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import org.javacord.api.event.message.MessageCreateEvent; +import net.dv8tion.jda.api.events.message.MessageReceivedEvent; public class CommandHelper { - public static LiteralArgumentBuilder literal(String command) { + public static LiteralArgumentBuilder literal(String command) { return LiteralArgumentBuilder.literal(command); } - public static RequiredArgumentBuilder argument(String command, ArgumentType argument) { + public static RequiredArgumentBuilder argument(String command, ArgumentType argument) { return RequiredArgumentBuilder.argument(command, argument); } } diff --git a/src/main/java/sciwhiz12/janitor/utils/Util.java b/src/main/java/sciwhiz12/janitor/utils/Util.java index 39ccdbc..a193111 100644 --- a/src/main/java/sciwhiz12/janitor/utils/Util.java +++ b/src/main/java/sciwhiz12/janitor/utils/Util.java @@ -1,12 +1,6 @@ package sciwhiz12.janitor.utils; -import org.javacord.api.entity.DiscordEntity; -import org.javacord.api.entity.channel.Channel; -import org.javacord.api.entity.channel.ServerChannel; -import org.javacord.api.entity.message.MessageAuthor; -import org.javacord.api.entity.permission.Role; -import org.javacord.api.entity.server.Server; -import org.javacord.api.entity.user.User; +import net.dv8tion.jda.api.entities.*; import javax.annotation.Nullable; import java.util.function.BiConsumer; @@ -20,33 +14,34 @@ public class Util { return obj; } - public static String toString(final MessageAuthor author) { - return author.asUser().map(Util::toString).orElseGet(() -> String.format("{MessageAuthor,%s}:%s", author.getDiscriminatedName(), author.getId())); - } +// public static String toString(final MessageAuthor author) { +// return author.asUser().map(Util::toString).orElseGet(() -> String.format("{MessageAuthor,%s}:%s", author.getDiscriminatedName(), author.getId())); +// } public static String toString(@Nullable final User user) { return user != null ? String.format("{User,%s#%s}:%s", user.getName(), user.getDiscriminator(), getID(user)) : "unknown"; } - public static String toString(final Channel channel) { - if (channel instanceof ServerChannel) { - ServerChannel gc = (ServerChannel) channel; - return String.format("[Channel:%s,%s@%s]%s", gc.getType(), gc.getName(), toString(gc.getServer()), getID(channel)); + public static String toString(final MessageChannel channel) { + if (channel instanceof GuildChannel) { + GuildChannel gc = (GuildChannel) channel; + return String.format("[GuildChannel:%s,%s@%s]%s", gc.getType(), gc.getName(), toString(gc.getGuild()), getID(channel)); } - return String.format("[Channel:%s]:%s", channel.getType(), getID(channel)); + // TextChannel vs PrivateChannel + return String.format("[MessageChannel]:%s", getID(channel)); } - public static String toString(final Server guild) { + public static String toString(final Guild guild) { return String.format("(Guild:%s):%s", guild.getName(), getID(guild)); } - public static String getID(final DiscordEntity entity) { + public static String getID(final ISnowflake entity) { String prefix = "?"; if (entity instanceof User) { - prefix = "@&"; + prefix = "@"; } else if (entity instanceof Role) { - prefix = "@!"; - } else if (entity instanceof Channel) { + prefix = "@&"; + } else if (entity instanceof GuildChannel) { prefix = "#"; } return String.format("<%s%s>", prefix, entity.getId());