From a92cdb48b5c7ec07d10d2c5e5d3401ef322521c7 Mon Sep 17 00:00:00 2001 From: Arnold Alejo Nunag Date: Wed, 9 Sep 2020 01:23:28 +0800 Subject: [PATCH] Move to javacord --- build.gradle | 17 ++-- gradle.properties | 3 +- .../java/sciwhiz12/janitor/BotConsole.java | 2 +- .../java/sciwhiz12/janitor/BotStartup.java | 20 ++--- .../java/sciwhiz12/janitor/JanitorBot.java | 79 ++++++++++--------- .../janitor/commands/BaseCommand.java | 4 +- .../janitor/commands/CommandRegistry.java | 27 +++---- .../janitor/commands/bot/ShutdownCommand.java | 17 ++-- .../janitor/commands/misc/OKCommand.java | 17 ++-- .../janitor/commands/misc/PingCommand.java | 13 ++- .../janitor/listeners/BaseListener.java | 12 --- .../janitor/listeners/StatusListener.java | 35 -------- .../janitor/utils/CommandHelper.java | 4 +- .../java/sciwhiz12/janitor/utils/Util.java | 39 +++++---- 14 files changed, 122 insertions(+), 167 deletions(-) delete mode 100644 src/main/java/sciwhiz12/janitor/listeners/BaseListener.java delete mode 100644 src/main/java/sciwhiz12/janitor/listeners/StatusListener.java diff --git a/build.gradle b/build.gradle index e557df9..b2f0eaf 100644 --- a/build.gradle +++ b/build.gradle @@ -31,15 +31,16 @@ version = getVersion() println("Version: ${version}") dependencies { - implementation "net.dv8tion:JDA:${jda_version}" - implementation "com.electronwill.night-config:toml:${nightconfig_version}" - implementation "net.sf.jopt-simple:jopt-simple:${jopt_version}" - implementation "com.google.guava:guava:${guava_version}" - implementation "com.google.code.gson:gson:${gson_version}" - implementation "ch.qos.logback:logback-classic:${logback_version}" - implementation "com.mojang:brigadier:${brigadier_version}" + implementation group: 'org.javacord', name: 'javacord', version: javacord_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 + implementation group: 'com.google.code.gson', name: 'gson', version: gson_version + implementation group: 'org.apache.logging.log4j', name: 'log4j-to-slf4j', version: log4j_bridge_version + implementation group: 'ch.qos.logback', name: 'logback-classic', version: logback_version + implementation group: 'com.mojang', name: 'brigadier', version: brigadier_version - testImplementation "junit:junit:${junit_version}" + testImplementation group: 'junit', name: 'junit', version: junit_version } application { diff --git a/gradle.properties b/gradle.properties index 31b7b6a..4b7622e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,11 +1,12 @@ grgit_version=4.0.2 shadow_version=6.0.0 -jda_version=4.2.0_199 +javacord_version=3.0.6 nightconfig_version=3.6.3 jopt_version=6.0-alpha-3 guava_version=29.0-jre gson_version=2.8.6 +log4j_bridge_version=2.13.3 logback_version=1.3.0-alpha5 brigadier_version=1.0.17 junit_version=4.13 diff --git a/src/main/java/sciwhiz12/janitor/BotConsole.java b/src/main/java/sciwhiz12/janitor/BotConsole.java index 58719ca..68c331d 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.shutdown(); + bot.disconnect(); break; } default: diff --git a/src/main/java/sciwhiz12/janitor/BotStartup.java b/src/main/java/sciwhiz12/janitor/BotStartup.java index 0627e65..22b1898 100644 --- a/src/main/java/sciwhiz12/janitor/BotStartup.java +++ b/src/main/java/sciwhiz12/janitor/BotStartup.java @@ -1,11 +1,10 @@ package sciwhiz12.janitor; -import com.google.common.base.Preconditions; -import net.dv8tion.jda.api.JDABuilder; -import net.dv8tion.jda.api.Permission; +import org.javacord.api.DiscordApiBuilder; import sciwhiz12.janitor.config.BotConfig; import sciwhiz12.janitor.config.BotOptions; +import static com.google.common.base.Preconditions.checkArgument; import static sciwhiz12.janitor.Logging.JANITOR; public class BotStartup { @@ -14,20 +13,15 @@ public class BotStartup { BotOptions options = new BotOptions(args); BotConfig config = new BotConfig(options); + checkArgument(config.getToken().isPresent(), + "Token is not supplied through config or command line"); JANITOR.info("Building bot instance and connecting to Discord..."); - JDABuilder builder; - JanitorBot bot; try { - Preconditions.checkArgument(config.getToken().isPresent(), - "Token is not supplied through config or command line"); - builder = JDABuilder.createDefault(config.getToken().get()); - bot = new JanitorBot(builder, config); - - bot.getJDA().awaitReady(); - String inviteURL = bot.getJDA().getInviteUrl(Permission.ADMINISTRATOR); - JANITOR.info("Invite URL (gives ADMIN permission): " + inviteURL); + DiscordApiBuilder builder = new DiscordApiBuilder().setToken(config.getToken().get()); + builder.login() + .thenAccept(api -> new JanitorBot(api, config)); } 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 36aba6a..a4b7b5f 100644 --- a/src/main/java/sciwhiz12/janitor/JanitorBot.java +++ b/src/main/java/sciwhiz12/janitor/JanitorBot.java @@ -1,44 +1,47 @@ package sciwhiz12.janitor; -import net.dv8tion.jda.api.JDA; -import net.dv8tion.jda.api.JDABuilder; -import net.dv8tion.jda.api.OnlineStatus; -import net.dv8tion.jda.api.entities.Activity; +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 sciwhiz12.janitor.commands.CommandRegistry; import sciwhiz12.janitor.config.BotConfig; -import sciwhiz12.janitor.listeners.StatusListener; import sciwhiz12.janitor.utils.Util; -import javax.security.auth.login.LoginException; - import static sciwhiz12.janitor.Logging.JANITOR; import static sciwhiz12.janitor.Logging.STATUS; public class JanitorBot { - private final JDA jda; + private final DiscordApi discord; private final BotConfig config; private final BotConsole console; private final CommandRegistry cmdRegistry; - public JanitorBot(JDABuilder jdaBuilder, BotConfig config) throws LoginException { + public JanitorBot(DiscordApi discord, BotConfig config) { this.config = config; this.console = new BotConsole(this, System.in); this.cmdRegistry = new CommandRegistry(this, config.getCommandPrefix()); - jdaBuilder - .setActivity(Activity.playing("the Readying game...")) - .setStatus(OnlineStatus.DO_NOT_DISTURB) - .setAutoReconnect(true) - .addEventListeners( - cmdRegistry, - new StatusListener(this) + this.discord = discord; + discord.addMessageCreateListener(cmdRegistry); + discord.updateStatus(UserStatus.ONLINE); + discord.updateActivity(ActivityType.PLAYING, " n' sweeping n' testing!"); + JANITOR.info("Ready!"); + config.getOwnerID() + .map(ownerId -> getDiscord().getUserById(ownerId)) + .ifPresent(retrieveUser -> + retrieveUser + .thenCompose(User::openPrivateChannel) + .thenCompose(channel -> channel.sendMessage("Started up and ready!")) + .whenCompleteAsync(Util.handle( + msg -> JANITOR.debug(STATUS, "Sent ready message to owner!"), + error -> JANITOR.error(STATUS, "Error while sending ready message to owner", error)) + ) ); - this.jda = jdaBuilder.build(); - JANITOR.info(STATUS, "Bot is built"); -// console.start(); + console.start(); } - public JDA getJDA() { - return this.jda; + public DiscordApi getDiscord() { + return this.discord; } public BotConfig getConfig() { @@ -49,24 +52,24 @@ public class JanitorBot { return this.cmdRegistry; } - public void shutdown() { + public void disconnect() { JANITOR.info(STATUS, "Shutting down!"); console.stop(); - getJDA().getRegisteredListeners().forEach(listener -> getJDA().removeEventListener(listener)); - 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(); + 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(); } } diff --git a/src/main/java/sciwhiz12/janitor/commands/BaseCommand.java b/src/main/java/sciwhiz12/janitor/commands/BaseCommand.java index e953bac..c578ae3 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 net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import org.javacord.api.event.message.MessageCreateEvent; 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 9f46e15..013e00c 100644 --- a/src/main/java/sciwhiz12/janitor/commands/CommandRegistry.java +++ b/src/main/java/sciwhiz12/janitor/commands/CommandRegistry.java @@ -4,31 +4,30 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.ParseResults; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import net.dv8tion.jda.api.events.message.MessageReceivedEvent; -import org.jetbrains.annotations.NotNull; +import org.javacord.api.event.message.MessageCreateEvent; +import org.javacord.api.listener.message.MessageCreateListener; import sciwhiz12.janitor.JanitorBot; import sciwhiz12.janitor.commands.bot.ShutdownCommand; import sciwhiz12.janitor.commands.misc.OKCommand; import sciwhiz12.janitor.commands.misc.PingCommand; -import sciwhiz12.janitor.listeners.BaseListener; import sciwhiz12.janitor.utils.Util; import java.util.HashMap; import java.util.Map; -import java.util.regex.Pattern; import static sciwhiz12.janitor.Logging.COMMANDS; import static sciwhiz12.janitor.Logging.JANITOR; -public class CommandRegistry extends BaseListener { - private final Pattern pattern; +public class CommandRegistry implements MessageCreateListener { + 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) { - super(bot); - this.pattern = Pattern.compile("^" + prefix + "([A-Za-z0-9]+).*$"); + this.bot = bot; +// this.pattern = Pattern.compile("^" + prefix + "([A-Za-z0-9]+).*$"); this.prefix = prefix; this.dispatcher = new CommandDispatcher<>(); @@ -41,7 +40,7 @@ public class CommandRegistry extends BaseListener { } - public CommandDispatcher getDispatcher() { + public CommandDispatcher getDispatcher() { return this.dispatcher; } @@ -54,18 +53,18 @@ public class CommandRegistry extends BaseListener { } @Override - public void onMessageReceived(@NotNull MessageReceivedEvent event) { - String msg = event.getMessage().getContentDisplay(); + public void onMessageCreate(MessageCreateEvent event) { + String msg = event.getMessage().getContent(); if (!msg.startsWith(this.prefix)) return; 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 return; } - JANITOR.debug(COMMANDS, "Received command and executing. Author: {}, full message: {}", Util.toString(event.getAuthor()), msg); + JANITOR.debug(COMMANDS, "Received command and executing. Author: {}, full message: {}", Util.toString(event.getMessageAuthor().asUser().orElse(null)), msg); dispatcher.execute(parseResults); } catch (CommandSyntaxException ex) { JANITOR.error(COMMANDS, "Error while parsing message and executing command", ex); diff --git a/src/main/java/sciwhiz12/janitor/commands/bot/ShutdownCommand.java b/src/main/java/sciwhiz12/janitor/commands/bot/ShutdownCommand.java index f19ff61..cd8cd69 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 net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import org.javacord.api.event.message.MessageCreateEvent; import sciwhiz12.janitor.commands.BaseCommand; import sciwhiz12.janitor.commands.CommandRegistry; import sciwhiz12.janitor.utils.Util; @@ -19,24 +19,23 @@ public class ShutdownCommand extends BaseCommand { } @Override - public LiteralArgumentBuilder getNode() { + public LiteralArgumentBuilder getNode() { return literal("shutdown") - .requires(ctx -> ctx.getAuthor().getIdLong() == ownerID) + .requires(ctx -> ctx.getMessageAuthor().getId() == 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!") - .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())) + .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())) ) ).join(); - getBot().shutdown(); + getBot().disconnect(); 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 7a99a6d..2a32f5f 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 net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import org.javacord.api.event.message.MessageCreateEvent; import sciwhiz12.janitor.commands.BaseCommand; import sciwhiz12.janitor.commands.CommandRegistry; import sciwhiz12.janitor.utils.Util; @@ -15,25 +15,20 @@ 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") - .submit() - .whenComplete(Util.handle( - 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())) + .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())) ) ); return 1; } - - public void onCommand(MessageReceivedEvent event) { - event.getMessage().addReaction("\uD83D\uDC4C").queue(); - } } diff --git a/src/main/java/sciwhiz12/janitor/commands/misc/PingCommand.java b/src/main/java/sciwhiz12/janitor/commands/misc/PingCommand.java index 11032fe..803cdac 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 net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import org.javacord.api.event.message.MessageCreateEvent; 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) - .submit() - .whenComplete(Util.handle( - 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())) + .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())) ) ); return 1; diff --git a/src/main/java/sciwhiz12/janitor/listeners/BaseListener.java b/src/main/java/sciwhiz12/janitor/listeners/BaseListener.java deleted file mode 100644 index 0748f34..0000000 --- a/src/main/java/sciwhiz12/janitor/listeners/BaseListener.java +++ /dev/null @@ -1,12 +0,0 @@ -package sciwhiz12.janitor.listeners; - -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import sciwhiz12.janitor.JanitorBot; - -public abstract class BaseListener extends ListenerAdapter { - protected final JanitorBot bot; - - public BaseListener(JanitorBot bot) { - this.bot = bot; - } -} diff --git a/src/main/java/sciwhiz12/janitor/listeners/StatusListener.java b/src/main/java/sciwhiz12/janitor/listeners/StatusListener.java deleted file mode 100644 index 5e288d8..0000000 --- a/src/main/java/sciwhiz12/janitor/listeners/StatusListener.java +++ /dev/null @@ -1,35 +0,0 @@ -package sciwhiz12.janitor.listeners; - -import net.dv8tion.jda.api.OnlineStatus; -import net.dv8tion.jda.api.entities.Activity; -import net.dv8tion.jda.api.events.ReadyEvent; -import org.jetbrains.annotations.NotNull; -import sciwhiz12.janitor.JanitorBot; -import sciwhiz12.janitor.utils.Util; - -import static sciwhiz12.janitor.Logging.JANITOR; -import static sciwhiz12.janitor.Logging.STATUS; - -public class StatusListener extends BaseListener { - public StatusListener(JanitorBot bot) { - super(bot); - } - - @Override - public void onReady(@NotNull ReadyEvent event) { - event.getJDA().getPresence() - .setPresence(OnlineStatus.ONLINE, Activity.playing("n' sweeping n' testing!")); - JANITOR.info("Ready!"); - bot.getConfig().getOwnerID() - .map(ownerId -> bot.getJDA().retrieveUserById(ownerId)) - .ifPresent(retrieveUser -> - retrieveUser.submit() - .thenCompose(user -> user.openPrivateChannel().submit()) - .thenCompose(channel -> channel.sendMessage("Started up and ready!").submit()) - .whenComplete(Util.handle( - msg -> JANITOR.debug(STATUS, "Sent ready message to owner!"), - error -> JANITOR.error(STATUS, "Error while sending ready message to owner", error)) - ) - ); - } -} diff --git a/src/main/java/sciwhiz12/janitor/utils/CommandHelper.java b/src/main/java/sciwhiz12/janitor/utils/CommandHelper.java index f7ebc97..c795da6 100644 --- a/src/main/java/sciwhiz12/janitor/utils/CommandHelper.java +++ b/src/main/java/sciwhiz12/janitor/utils/CommandHelper.java @@ -1,10 +1,10 @@ package sciwhiz12.janitor.utils; import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import net.dv8tion.jda.api.events.message.MessageReceivedEvent; +import org.javacord.api.event.message.MessageCreateEvent; public class CommandHelper { - public static LiteralArgumentBuilder literal(String command) { + public static LiteralArgumentBuilder literal(String command) { return LiteralArgumentBuilder.literal(command); } } diff --git a/src/main/java/sciwhiz12/janitor/utils/Util.java b/src/main/java/sciwhiz12/janitor/utils/Util.java index e797ef3..39ccdbc 100644 --- a/src/main/java/sciwhiz12/janitor/utils/Util.java +++ b/src/main/java/sciwhiz12/janitor/utils/Util.java @@ -1,7 +1,14 @@ package sciwhiz12.janitor.utils; -import net.dv8tion.jda.api.entities.*; +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 javax.annotation.Nullable; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; @@ -13,32 +20,36 @@ public class Util { return obj; } - public static String toString(final User user) { - return String.format("{User,%s#%s}:%s", user.getName(), user.getDiscriminator(), getID(user)); + 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 MessageChannel channel) { - if (channel instanceof GuildChannel) { - GuildChannel gc = (GuildChannel) channel; - return String.format("[Channel:%s,%s@%s]%s", gc.getType(), gc.getName(), toString(gc.getGuild()), getID(channel)); + 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)); } - return String.format("[Channel:%s,%s]:%s", channel.getType(), channel.getName(), getID(channel)); + return String.format("[Channel:%s]:%s", channel.getType(), getID(channel)); } - public static String toString(final Guild guild) { + public static String toString(final Server guild) { return String.format("(Guild:%s):%s", guild.getName(), getID(guild)); } - public static String getID(final ISnowflake snowflake) { + public static String getID(final DiscordEntity entity) { String prefix = "?"; - if (snowflake instanceof User) { + if (entity instanceof User) { prefix = "@&"; - } else if (snowflake instanceof Role) { + } else if (entity instanceof Role) { prefix = "@!"; - } else if (snowflake instanceof MessageChannel) { + } else if (entity instanceof Channel) { prefix = "#"; } - return String.format("<%s%s>", prefix, snowflake.getIdLong()); + return String.format("<%s%s>", prefix, entity.getId()); } public static BiConsumer handle(final Consumer success,