From 8e972ba96a30394e24e7a5bfa0c0a25fc1719d84 Mon Sep 17 00:00:00 2001 From: Arnold Alejo Nunag Date: Tue, 6 Oct 2020 14:57:14 +0800 Subject: [PATCH] Improve messages system (WIP) Now uses a builder format, and allows for substitutions in the translation keys (WIP) the Listing commands are unimplemented yet. This is in preparation for moving to JSON-based messages in the future --- .../java/sciwhiz12/janitor/JanitorBot.java | 13 +- .../commands/moderation/BanCommand.java | 22 +- .../commands/moderation/KickCommand.java | 24 +- .../commands/moderation/NoteCommand.java | 53 +- .../commands/moderation/UnbanCommand.java | 15 +- .../commands/moderation/UnwarnCommand.java | 16 +- .../commands/moderation/WarnCommand.java | 25 +- .../commands/moderation/WarnListCommand.java | 22 +- .../java/sciwhiz12/janitor/msg/General.java | 100 ++- .../sciwhiz12/janitor/msg/MessageBuilder.java | 103 ++++ .../java/sciwhiz12/janitor/msg/Messages.java | 79 ++- .../sciwhiz12/janitor/msg/Moderation.java | 567 +++++++++--------- .../sciwhiz12/janitor/msg/Substitutions.java | 59 ++ src/main/resources/english.json | 229 ++++--- 14 files changed, 836 insertions(+), 491 deletions(-) create mode 100644 src/main/java/sciwhiz12/janitor/msg/MessageBuilder.java create mode 100644 src/main/java/sciwhiz12/janitor/msg/Substitutions.java diff --git a/src/main/java/sciwhiz12/janitor/JanitorBot.java b/src/main/java/sciwhiz12/janitor/JanitorBot.java index 4f59553..9e60dfa 100644 --- a/src/main/java/sciwhiz12/janitor/JanitorBot.java +++ b/src/main/java/sciwhiz12/janitor/JanitorBot.java @@ -9,6 +9,7 @@ import net.dv8tion.jda.api.entities.User; import sciwhiz12.janitor.commands.CommandRegistry; import sciwhiz12.janitor.config.BotConfig; import sciwhiz12.janitor.msg.Messages; +import sciwhiz12.janitor.msg.Substitutions; import sciwhiz12.janitor.msg.Translations; import sciwhiz12.janitor.utils.Util; @@ -25,17 +26,19 @@ public class JanitorBot { private BotConsole console; private final GuildStorage storage; private final GuildStorage.SavingThread storageSavingThread; - private CommandRegistry cmdRegistry; - private Translations translations; + private final CommandRegistry cmdRegistry; + private final Translations translations; + private final Substitutions substitutions; public JanitorBot(JDA discord, BotConfig config) { this.config = config; + this.discord = discord; this.console = new BotConsole(this, System.in); this.storage = new GuildStorage(this, Path.of(config.STORAGE_PATH.get())); this.cmdRegistry = new CommandRegistry(this, config.getCommandPrefix()); - this.discord = discord; this.translations = new Translations(this, config.getTranslationsFile()); this.messages = new Messages(this); + this.substitutions = new Substitutions(this); discord.addEventListener(cmdRegistry); discord.getPresence().setPresence(OnlineStatus.ONLINE, Activity.playing(" n' sweeping n' testing!")); discord.getGuilds().forEach(Guild::loadMembers); @@ -101,4 +104,8 @@ public class JanitorBot { storage.save(); console.stop(); } + + public Substitutions getSubstitutions() { + return substitutions; + } } diff --git a/src/main/java/sciwhiz12/janitor/commands/moderation/BanCommand.java b/src/main/java/sciwhiz12/janitor/commands/moderation/BanCommand.java index fdeab26..172fc39 100644 --- a/src/main/java/sciwhiz12/janitor/commands/moderation/BanCommand.java +++ b/src/main/java/sciwhiz12/janitor/commands/moderation/BanCommand.java @@ -68,7 +68,7 @@ public class BanCommand extends BaseCommand { void realRun(CommandContext ctx, int days, @Nullable String reason) throws CommandSyntaxException { MessageChannel channel = ctx.getSource().getChannel(); if (!ctx.getSource().isFromGuild()) { - messages().GENERAL.guildOnlyCommand(channel).queue(); + channel.sendMessage(messages().GENERAL.guildOnlyCommand(ctx.getSource().getAuthor()).build(getBot())).queue(); return; } final Guild guild = ctx.getSource().getGuild(); @@ -79,24 +79,26 @@ public class BanCommand extends BaseCommand { final Member target = members.get(0); if (guild.getSelfMember().equals(target)) - messages().GENERAL.cannotActionSelf(channel).queue(); + channel.sendMessage(messages().GENERAL.cannotActionSelf(performer).build(getBot())).queue(); else if (performer.equals(target)) - messages().GENERAL.cannotActionPerformer(channel, performer).queue(); + channel.sendMessage(messages().GENERAL.cannotActionPerformer(performer).build(getBot())).queue(); else if (!guild.getSelfMember().hasPermission(BAN_PERMISSION)) - messages().GENERAL.insufficientPermissions(channel, BAN_PERMISSION).queue(); + channel.sendMessage(messages().GENERAL.insufficientPermissions(performer, BAN_PERMISSION).build(getBot())).queue(); else if (!guild.getSelfMember().canInteract(target)) - messages().GENERAL.cannotInteract(channel, target).queue(); + channel.sendMessage(messages().GENERAL.cannotInteract(performer, target).build(getBot())).queue(); else if (!performer.hasPermission(BAN_PERMISSION)) - messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, BAN_PERMISSION).queue(); + channel.sendMessage( + messages().MODERATION.ERRORS.performerInsufficientPermissions(performer, BAN_PERMISSION).build(getBot())) + .queue(); else if (!performer.canInteract(target)) - messages().MODERATION.ERRORS.cannotModerate(channel, performer, target).queue(); + channel.sendMessage(messages().MODERATION.ERRORS.cannotInteract(performer, target).build(getBot())).queue(); else target.getUser().openPrivateChannel() - .flatMap(dm -> messages().MODERATION.bannedDM(dm, performer, reason)) + .flatMap(dm -> dm.sendMessage(messages().MODERATION.bannedDM(performer, target, reason).build(getBot()))) .mapToResult() .flatMap(res -> ModerationHelper.banUser(target.getGuild(), performer, target, days, reason) - .flatMap( - v -> messages().MODERATION.banUser(channel, performer, target, reason, days, res.isSuccess()))) + .flatMap(v -> channel.sendMessage( + messages().MODERATION.banUser(performer, target, reason, days, res.isSuccess()).build(getBot())))) .queue(); } } diff --git a/src/main/java/sciwhiz12/janitor/commands/moderation/KickCommand.java b/src/main/java/sciwhiz12/janitor/commands/moderation/KickCommand.java index 5996907..bbcb852 100644 --- a/src/main/java/sciwhiz12/janitor/commands/moderation/KickCommand.java +++ b/src/main/java/sciwhiz12/janitor/commands/moderation/KickCommand.java @@ -50,7 +50,7 @@ public class KickCommand extends BaseCommand { private int runWithReason(CommandContext ctx, @Nullable String reason) throws CommandSyntaxException { MessageChannel channel = ctx.getSource().getChannel(); if (!ctx.getSource().isFromGuild()) { - messages().GENERAL.guildOnlyCommand(channel).queue(); + channel.sendMessage(messages().GENERAL.guildOnlyCommand(ctx.getSource().getAuthor()).build(getBot())).queue(); return 1; } final Guild guild = ctx.getSource().getGuild(); @@ -61,24 +61,28 @@ public class KickCommand extends BaseCommand { } final Member target = members.get(0); if (guild.getSelfMember().equals(target)) - messages().GENERAL.cannotActionSelf(channel).queue(); + channel.sendMessage(messages().GENERAL.cannotActionSelf(performer).build(getBot())).queue(); else if (performer.equals(target)) - messages().GENERAL.cannotActionPerformer(channel, performer).queue(); + channel.sendMessage(messages().GENERAL.cannotActionSelf(performer).build(getBot())).queue(); else if (!guild.getSelfMember().hasPermission(KICK_PERMISSION)) - messages().GENERAL.insufficientPermissions(channel, KICK_PERMISSION).queue(); + channel.sendMessage(messages().GENERAL.insufficientPermissions(performer, KICK_PERMISSION).build(getBot())).queue(); else if (!guild.getSelfMember().canInteract(target)) - messages().GENERAL.cannotInteract(channel, target).queue(); + channel.sendMessage(messages().GENERAL.cannotInteract(performer, target).build(getBot())).queue(); else if (!performer.hasPermission(KICK_PERMISSION)) - messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, KICK_PERMISSION).queue(); + channel.sendMessage( + messages().MODERATION.ERRORS.performerInsufficientPermissions(performer, KICK_PERMISSION).build(getBot())) + .queue(); else if (!performer.canInteract(target)) - messages().MODERATION.ERRORS.cannotModerate(channel, performer, target).queue(); + channel.sendMessage(messages().MODERATION.ERRORS.cannotInteract(performer, target).build(getBot())).queue(); else target.getUser().openPrivateChannel() - .flatMap(dm -> messages().MODERATION.kickedDM(dm, performer, target, reason)) + .flatMap(dm -> dm.sendMessage(messages().MODERATION.kickedDM(performer, target, reason).build(getBot()))) .mapToResult() .flatMap(res -> ModerationHelper.kickUser(target.getGuild(), performer, target, reason) - .flatMap( - v -> messages().MODERATION.kickUser(channel, performer, target, reason, res.isSuccess()))) + .flatMap(v -> channel.sendMessage( + messages().MODERATION.kickUser(performer, target, reason, res.isSuccess()).build(getBot())) + ) + ) .queue(); return 1; } diff --git a/src/main/java/sciwhiz12/janitor/commands/moderation/NoteCommand.java b/src/main/java/sciwhiz12/janitor/commands/moderation/NoteCommand.java index d73ff39..dca1e23 100644 --- a/src/main/java/sciwhiz12/janitor/commands/moderation/NoteCommand.java +++ b/src/main/java/sciwhiz12/janitor/commands/moderation/NoteCommand.java @@ -90,32 +90,36 @@ public class NoteCommand extends BaseCommand { } private int addNote(CommandContext ctx, String noteContents) throws CommandSyntaxException { + final MessageChannel channel = ctx.getSource().getChannel(); if (!ctx.getSource().isFromGuild()) { - messages().GENERAL.guildOnlyCommand(ctx.getSource().getChannel()); + channel.sendMessage(messages().GENERAL.guildOnlyCommand(ctx.getSource().getAuthor()).build(getBot())).queue(); return 1; } final Member performer = Objects.requireNonNull(ctx.getSource().getMember()); final Guild guild = performer.getGuild(); - final MessageChannel channel = ctx.getSource().getChannel(); final List members = getMembers("target", ctx).fromGuild(guild); if (members.size() < 1) return 1; final Member target = members.get(0); final OffsetDateTime dateTime = OffsetDateTime.now(ZoneOffset.UTC); if (guild.getSelfMember().equals(target)) - messages().GENERAL.cannotActionSelf(channel).queue(); + channel.sendMessage(messages().GENERAL.cannotActionSelf(performer).build(getBot())).queue(); else if (performer.equals(target)) - messages().GENERAL.cannotActionPerformer(channel, performer).queue(); + channel.sendMessage(messages().GENERAL.cannotActionPerformer(performer).build(getBot())).queue(); else if (!performer.hasPermission(NOTE_PERMISSION)) - messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, NOTE_PERMISSION).queue(); + channel.sendMessage( + messages().MODERATION.ERRORS.performerInsufficientPermissions(performer, NOTE_PERMISSION).build(getBot())) + .queue(); else { final NoteStorage storage = NoteStorage.get(getBot().getStorage(), guild); final int maxAmount = config().NOTES_MAX_AMOUNT_PER_MOD.get(); if (storage.getAmountOfNotes(target.getUser()) >= maxAmount) { - messages().MODERATION.ERRORS.maxAmountOfNotes(channel, performer, target, maxAmount).queue(); + channel.sendMessage(messages().MODERATION.ERRORS.maxAmountOfNotes(performer, target, maxAmount).build(getBot())) + .queue(); } else { - int noteID = storage.addNote(new NoteEntry(performer.getUser(), target.getUser(), dateTime, noteContents)); - messages().MODERATION.addNote(channel, performer, target, noteContents, dateTime, noteID).queue(); + final NoteEntry entry = new NoteEntry(performer.getUser(), target.getUser(), dateTime, noteContents); + int noteID = storage.addNote(entry); + channel.sendMessage(messages().MODERATION.addNote(performer, noteID, entry).build(getBot())).queue(); } } return 1; @@ -127,9 +131,9 @@ public class NoteCommand extends BaseCommand { private int listNotes(CommandContext ctx, boolean filterTarget, ModeratorFilter modFilter) throws CommandSyntaxException { - MessageChannel channel = ctx.getSource().getChannel(); + final MessageChannel channel = ctx.getSource().getChannel(); if (!ctx.getSource().isFromGuild()) { - messages().GENERAL.guildOnlyCommand(channel).queue(); + channel.sendMessage(messages().GENERAL.guildOnlyCommand(ctx.getSource().getAuthor()).build(getBot())).queue(); return 1; } final Guild guild = ctx.getSource().getGuild(); @@ -141,7 +145,7 @@ public class NoteCommand extends BaseCommand { if (members.size() < 1) return 1; final Member target = members.get(0); if (guild.getSelfMember().equals(target)) { - messages().GENERAL.cannotActionSelf(channel).queue(); + channel.sendMessage(messages().GENERAL.cannotActionSelf(performer).build(getBot())).queue(); return 1; } predicate = predicate.and(e -> e.getValue().getTarget().getIdLong() == target.getIdLong()); @@ -161,21 +165,24 @@ public class NoteCommand extends BaseCommand { final OffsetDateTime dateTime = OffsetDateTime.now(); if (!performer.hasPermission(NOTE_PERMISSION)) - messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, NOTE_PERMISSION).queue(); + channel.sendMessage( + messages().MODERATION.ERRORS.performerInsufficientPermissions(performer, NOTE_PERMISSION).build(getBot())) + .queue(); else - messages().MODERATION.noteList(channel, NoteStorage.get(getBot().getStorage(), guild) - .getNotes() - .entrySet().stream() - .filter(predicate) - .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)) - ).queue(); + channel.sendMessage(messages().MODERATION.noteList( + NoteStorage.get(getBot().getStorage(), guild) + .getNotes() + .entrySet().stream() + .filter(predicate) + .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)) + ).build(getBot())).queue(); return 1; } private int removeNote(CommandContext ctx, int noteID) { MessageChannel channel = ctx.getSource().getChannel(); if (!ctx.getSource().isFromGuild()) { - messages().GENERAL.guildOnlyCommand(channel).queue(); + channel.sendMessage(messages().GENERAL.guildOnlyCommand(ctx.getSource().getAuthor()).build(getBot())).queue(); return 1; } final Guild guild = ctx.getSource().getGuild(); @@ -184,16 +191,18 @@ public class NoteCommand extends BaseCommand { final OffsetDateTime dateTime = OffsetDateTime.now(); if (!performer.hasPermission(NOTE_PERMISSION)) - messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, NOTE_PERMISSION).queue(); + channel.sendMessage( + messages().MODERATION.ERRORS.performerInsufficientPermissions(performer, NOTE_PERMISSION).build(getBot())) + .queue(); else { final NoteStorage storage = NoteStorage.get(getBot().getStorage(), guild); @Nullable final NoteEntry entry = storage.getNote(noteID); if (entry == null) - messages().MODERATION.ERRORS.noNoteFound(channel, performer, noteID).queue(); + channel.sendMessage(messages().MODERATION.ERRORS.noNoteFound(performer, noteID).build(getBot())).queue(); else { storage.removeNote(noteID); - messages().MODERATION.removeNote(channel, performer, noteID, entry).queue(); + channel.sendMessage(messages().MODERATION.removeNote(performer, noteID, entry).build(getBot())).queue(); } } return 1; diff --git a/src/main/java/sciwhiz12/janitor/commands/moderation/UnbanCommand.java b/src/main/java/sciwhiz12/janitor/commands/moderation/UnbanCommand.java index e909e7c..3dcee75 100644 --- a/src/main/java/sciwhiz12/janitor/commands/moderation/UnbanCommand.java +++ b/src/main/java/sciwhiz12/janitor/commands/moderation/UnbanCommand.java @@ -49,7 +49,7 @@ public class UnbanCommand extends BaseCommand { void realNamedRun(CommandContext ctx) { MessageChannel channel = ctx.getSource().getChannel(); if (!ctx.getSource().isFromGuild()) { - messages().GENERAL.guildOnlyCommand(channel).queue(); + channel.sendMessage(messages().GENERAL.guildOnlyCommand(ctx.getSource().getAuthor()).build(getBot())).queue(); return; } final Guild guild = ctx.getSource().getGuild(); @@ -63,7 +63,7 @@ public class UnbanCommand extends BaseCommand { .collect(Collectors.toList())) .queue(bans -> { if (bans.size() > 1) - messages().GENERAL.ambiguousMember(channel).queue(); + channel.sendMessage(messages().GENERAL.ambiguousMember(performer).build(getBot())).queue(); else if (bans.size() == 1) tryUnban(channel, guild, performer, bans.get(0).getUser()); }); @@ -77,7 +77,7 @@ public class UnbanCommand extends BaseCommand { void realIdRun(CommandContext ctx) { MessageChannel channel = ctx.getSource().getChannel(); if (!ctx.getSource().isFromGuild()) { - messages().GENERAL.guildOnlyCommand(channel).queue(); + channel.sendMessage(messages().GENERAL.guildOnlyCommand(ctx.getSource().getAuthor()).build(getBot())).queue(); return; } final Guild guild = ctx.getSource().getGuild(); @@ -98,12 +98,15 @@ public class UnbanCommand extends BaseCommand { void tryUnban(MessageChannel channel, Guild guild, Member performer, User target) { if (!guild.getSelfMember().hasPermission(UNBAN_PERMISSION)) - messages().GENERAL.insufficientPermissions(channel, UNBAN_PERMISSION).queue(); + channel.sendMessage(messages().GENERAL.insufficientPermissions(performer, UNBAN_PERMISSION).build(getBot())) + .queue(); else if (!performer.hasPermission(UNBAN_PERMISSION)) - messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, UNBAN_PERMISSION).queue(); + channel.sendMessage( + messages().MODERATION.ERRORS.performerInsufficientPermissions(performer, UNBAN_PERMISSION).build(getBot())) + .queue(); else ModerationHelper.unbanUser(guild, target) - .flatMap(v -> messages().MODERATION.unbanUser(channel, performer, target)) + .flatMap(v -> channel.sendMessage(messages().MODERATION.unbanUser(performer, target).build(getBot()))) .queue(); } } diff --git a/src/main/java/sciwhiz12/janitor/commands/moderation/UnwarnCommand.java b/src/main/java/sciwhiz12/janitor/commands/moderation/UnwarnCommand.java index 27eb3ec..86d4a61 100644 --- a/src/main/java/sciwhiz12/janitor/commands/moderation/UnwarnCommand.java +++ b/src/main/java/sciwhiz12/janitor/commands/moderation/UnwarnCommand.java @@ -45,7 +45,7 @@ public class UnwarnCommand extends BaseCommand { void realRun(CommandContext ctx) { MessageChannel channel = ctx.getSource().getChannel(); if (!ctx.getSource().isFromGuild()) { - messages().GENERAL.guildOnlyCommand(channel).queue(); + channel.sendMessage(messages().GENERAL.guildOnlyCommand(ctx.getSource().getAuthor()).build(getBot())).queue(); return; } final Guild guild = ctx.getSource().getGuild(); @@ -55,24 +55,28 @@ public class UnwarnCommand extends BaseCommand { final OffsetDateTime dateTime = OffsetDateTime.now(); if (!performer.hasPermission(WARN_PERMISSION)) - messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, WARN_PERMISSION).queue(); + channel.sendMessage( + messages().MODERATION.ERRORS.performerInsufficientPermissions(performer, WARN_PERMISSION).build(getBot())) + .queue(); else { final WarningStorage storage = WarningStorage.get(getBot().getStorage(), guild); @Nullable final WarningEntry entry = storage.getWarning(caseID); Member temp; if (entry == null) - messages().MODERATION.ERRORS.noWarnWithID(channel, performer, caseID).queue(); + channel.sendMessage(messages().MODERATION.ERRORS.noWarnWithID(performer, caseID).build(getBot())).queue(); else if (entry.getWarned().getIdLong() == performer.getIdLong() && !config().WARNINGS_REMOVE_SELF_WARNINGS.get()) - messages().MODERATION.ERRORS.cannotUnwarnSelf(channel, performer, caseID, entry).queue(); + channel.sendMessage(messages().MODERATION.ERRORS.cannotUnwarnSelf(performer, caseID, entry).build(getBot())) + .queue(); else if (config().WARNINGS_RESPECT_MOD_ROLES.get() && (temp = guild.getMember(entry.getPerformer())) != null && !performer.canInteract(temp)) - messages().MODERATION.ERRORS.cannotRemoveHigherModerated(channel, performer, caseID, entry).queue(); + channel.sendMessage( + messages().MODERATION.ERRORS.cannotRemoveHigherModerated(performer, caseID, entry).build(getBot())).queue(); else { storage.removeWarning(caseID); - messages().MODERATION.unwarn(channel, performer, caseID, entry).queue(); + channel.sendMessage(messages().MODERATION.unwarn(performer, caseID, entry).build(getBot())).queue(); } } } diff --git a/src/main/java/sciwhiz12/janitor/commands/moderation/WarnCommand.java b/src/main/java/sciwhiz12/janitor/commands/moderation/WarnCommand.java index 70199fc..3353d93 100644 --- a/src/main/java/sciwhiz12/janitor/commands/moderation/WarnCommand.java +++ b/src/main/java/sciwhiz12/janitor/commands/moderation/WarnCommand.java @@ -52,7 +52,7 @@ public class WarnCommand extends BaseCommand { void realRun(CommandContext ctx, String reason) throws CommandSyntaxException { MessageChannel channel = ctx.getSource().getChannel(); if (!ctx.getSource().isFromGuild()) { - messages().GENERAL.guildOnlyCommand(channel).queue(); + channel.sendMessage(messages().GENERAL.guildOnlyCommand(ctx.getSource().getAuthor()).build(getBot())).queue(); return; } final Guild guild = ctx.getSource().getGuild(); @@ -64,24 +64,27 @@ public class WarnCommand extends BaseCommand { final OffsetDateTime dateTime = OffsetDateTime.now(ZoneOffset.UTC); if (guild.getSelfMember().equals(target)) - messages().GENERAL.cannotActionSelf(channel).queue(); + channel.sendMessage(messages().GENERAL.cannotActionSelf(performer).build(getBot())).queue(); else if (performer.equals(target)) - messages().GENERAL.cannotActionPerformer(channel, performer).queue(); + channel.sendMessage(messages().GENERAL.cannotActionPerformer(performer).build(getBot())).queue(); else if (!performer.hasPermission(WARN_PERMISSION)) - messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, WARN_PERMISSION).queue(); + channel.sendMessage( + messages().MODERATION.ERRORS.performerInsufficientPermissions(performer, WARN_PERMISSION).build(getBot())) + .queue(); else if (!performer.canInteract(target)) - messages().MODERATION.ERRORS.cannotModerate(channel, performer, target).queue(); + channel.sendMessage(messages().MODERATION.ERRORS.cannotInteract(performer, target).build(getBot())).queue(); else if (target.hasPermission(WARN_PERMISSION) && config().WARNINGS_PREVENT_WARNING_MODS.get()) - messages().MODERATION.ERRORS.cannotWarnMods(channel, performer, target).queue(); + channel.sendMessage(messages().MODERATION.ERRORS.cannotWarnMods(performer, target).build(getBot())).queue(); else target.getUser().openPrivateChannel() - .flatMap(dm -> messages().MODERATION.warnDM(dm, performer, target, reason, dateTime)) + .flatMap( + dm -> dm.sendMessage(messages().MODERATION.warnedDM(performer, target, reason, dateTime).build(getBot()))) .mapToResult() .flatMap(res -> { - int caseId = WarningStorage.get(getBot().getStorage(), guild) - .addWarning(new WarningEntry(target.getUser(), performer.getUser(), dateTime, reason)); - return messages().MODERATION - .warnUser(channel, performer, target, reason, dateTime, caseId, res.isSuccess()); + WarningEntry entry = new WarningEntry(target.getUser(), performer.getUser(), dateTime, reason); + int caseId = WarningStorage.get(getBot().getStorage(), guild).addWarning(entry); + return channel + .sendMessage(messages().MODERATION.warnUser(performer, caseId, entry, res.isSuccess()).build(getBot())); }) .queue(); } diff --git a/src/main/java/sciwhiz12/janitor/commands/moderation/WarnListCommand.java b/src/main/java/sciwhiz12/janitor/commands/moderation/WarnListCommand.java index bfa4daf..18799d3 100644 --- a/src/main/java/sciwhiz12/janitor/commands/moderation/WarnListCommand.java +++ b/src/main/java/sciwhiz12/janitor/commands/moderation/WarnListCommand.java @@ -64,7 +64,7 @@ public class WarnListCommand extends BaseCommand { throws CommandSyntaxException { MessageChannel channel = ctx.getSource().getChannel(); if (!ctx.getSource().isFromGuild()) { - messages().GENERAL.guildOnlyCommand(channel).queue(); + channel.sendMessage(messages().GENERAL.guildOnlyCommand(ctx.getSource().getAuthor()).build(getBot())).queue(); return; } final Guild guild = ctx.getSource().getGuild(); @@ -76,7 +76,7 @@ public class WarnListCommand extends BaseCommand { if (members.size() < 1) return; final Member target = members.get(0); if (guild.getSelfMember().equals(target)) { - messages().GENERAL.cannotActionSelf(channel).queue(); + channel.sendMessage(messages().GENERAL.cannotActionSelf(performer).build(getBot())).queue(); return; } predicate = predicate.and(e -> e.getValue().getWarned().getIdLong() == target.getIdLong()); @@ -91,13 +91,17 @@ public class WarnListCommand extends BaseCommand { final OffsetDateTime dateTime = OffsetDateTime.now(); if (!performer.hasPermission(WARN_PERMISSION)) - messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, WARN_PERMISSION).queue(); + channel.sendMessage( + messages().MODERATION.ERRORS.performerInsufficientPermissions(performer, WARN_PERMISSION).build(getBot())) + .queue(); else - messages().MODERATION.warnList(channel, WarningStorage.get(getBot().getStorage(), guild) - .getWarnings() - .entrySet().stream() - .filter(predicate) - .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)) - ).queue(); + channel.sendMessage(messages().MODERATION.warnList( + WarningStorage.get(getBot().getStorage(), guild) + .getWarnings() + .entrySet().stream() + .filter(predicate) + .collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue)) + ).build(getBot())).queue(); + } } diff --git a/src/main/java/sciwhiz12/janitor/msg/General.java b/src/main/java/sciwhiz12/janitor/msg/General.java index 2ad3a95..9ab322b 100644 --- a/src/main/java/sciwhiz12/janitor/msg/General.java +++ b/src/main/java/sciwhiz12/janitor/msg/General.java @@ -2,10 +2,7 @@ package sciwhiz12.janitor.msg; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.MessageChannel; -import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.requests.RestAction; +import net.dv8tion.jda.api.entities.User; import java.util.EnumSet; import java.util.stream.Collectors; @@ -17,63 +14,62 @@ public final class General { this.messages = messages; } - private String translate(String key, Object... args) { - return messages.translate(key, args); + public MessageBuilder guildOnlyCommand(final User performer) { + return messages.failure() + .apply(builder -> messages.user(builder, "performer", performer)) + .embed(embed -> embed + .setTitle("general.guild_only_command.title") + .setDescription("general.guild_only_command.description") + ); } - public RestAction guildOnlyCommand(MessageChannel channel) { - return channel.sendMessage( - messages.failureEmbed(translate("general.guild_only_command.title")) - .setDescription(translate("general.guild_only_command.desc")) - .build() - ); + public MessageBuilder ambiguousMember(final Member performer) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .embed(embed -> embed + .setTitle("general.ambiguous_member.title") + .setDescription("general.ambiguous_member.description") + ); } - public RestAction insufficientPermissions(MessageChannel channel, EnumSet permissions) { - return channel.sendMessage( - messages.failureEmbed(translate("general.insufficient_permissions.title")) - .setDescription(translate("general.insufficient_permissions.desc")) - .addField(new MessageEmbed.Field( - translate("general.insufficient_permissions.field.permissions"), - permissions.stream().map(Permission::getName).collect(Collectors.joining(", ")), - false)) - .build() - ); + public MessageBuilder insufficientPermissions(final Member performer, final EnumSet permissions) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .with("required_permissions", () -> permissions.stream().map(Permission::getName).collect(Collectors.joining(", "))) + .embed(embed -> embed + .setTitle("general.insufficient_permissions.title") + .setDescription("general.insufficient_permissions.description") + ) + .field("general.insufficient_permissions.field.permissions", true); } - public RestAction ambiguousMember(MessageChannel channel) { - return channel.sendMessage( - messages.failureEmbed(translate("general.ambiguous_member.title")) - .setDescription(translate("general.ambiguous_member.desc")) - .build() - ); + public MessageBuilder cannotInteract(final Member performer, final Member target) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> messages.member(builder, "target", target)) + .embed(embed -> embed + .setTitle("general.cannot_interact.title") + .setDescription("general.cannot_interact.description") + ) + .field("general.cannot_interact.field.target", true); } - public RestAction cannotInteract(MessageChannel channel, Member target) { - return channel.sendMessage( - messages.failureEmbed(translate("general.cannot_interact.title")) - .setDescription(translate("general.cannot_interact.desc")) - .addField(translate("general.cannot_interact.field.target"), target.getAsMention(), true) - .build() - ); + public MessageBuilder cannotActionSelf(final Member performer) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .embed(embed -> embed + .setTitle("general.cannot_action_self.title") + .setDescription("general.cannot_action_self.description") + ); } - public RestAction cannotActionSelf(MessageChannel channel) { - return channel.sendMessage( - messages.failureEmbed(translate("general.cannot_action_self.title")) - .setDescription(translate("general.cannot_action_self.desc")) - .build() - ); - } - - public RestAction cannotActionPerformer(MessageChannel channel, Member performer) { - return channel.sendMessage( - messages.failureEmbed(translate("general.cannot_action_performer.title")) - .setDescription(translate("general.cannot_action_performer.desc")) - .addField(translate("general.cannot_action_performer.field.performer"), - performer.getUser().getAsMention(), - true) - .build() - ); + public MessageBuilder cannotActionPerformer(final Member performer) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .embed(embed -> embed + .setTitle("general.cannot_action_performer.title") + .setDescription("general.cannot_action_performer.description") + ) + .field("general.cannot_action_performer.field.performer", true); } } diff --git a/src/main/java/sciwhiz12/janitor/msg/MessageBuilder.java b/src/main/java/sciwhiz12/janitor/msg/MessageBuilder.java new file mode 100644 index 0000000..0a4fe73 --- /dev/null +++ b/src/main/java/sciwhiz12/janitor/msg/MessageBuilder.java @@ -0,0 +1,103 @@ +package sciwhiz12.janitor.msg; + +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.MessageEmbed; +import sciwhiz12.janitor.JanitorBot; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.function.UnaryOperator; + +import static sciwhiz12.janitor.msg.Substitutions.substitute; + +public class MessageBuilder { + private final EmbedBuilder embedBuilder; + private final Map> substitutions; + + public MessageBuilder(EmbedBuilder embedBuilder, Map> substitutions) { + this.embedBuilder = embedBuilder; + this.substitutions = substitutions; + } + + public MessageBuilder() { + this(new EmbedBuilder(), new HashMap<>()); + } + + @SuppressWarnings("CopyConstructorMissesField") + public MessageBuilder(MessageBuilder copy) { + this(new EmbedBuilder(copy.embedBuilder), new HashMap<>(copy.substitutions)); + } + + public EmbedBuilder embed() { + return embedBuilder; + } + + public MessageBuilder embed(Consumer operator) { + operator.accept(embed()); + return this; + } + + public MessageBuilder apply(Consumer consumer) { + consumer.accept(this); + return this; + } + + public MessageBuilder with(final String argument, final Supplier value) { + substitutions.put(argument, value); + return this; + } + + public MessageBuilder field(final String head, final boolean inline) { + embedBuilder.addField(head + ".name", head + ".value", inline); + return this; + } + + public MessageBuilder blankField(final boolean inline) { + embedBuilder.addBlankField(inline); + return this; + } + + public MessageEmbed build(Translations translations, Substitutions substitutions) { + EmbedBuilder realEmbed = new EmbedBuilder(); + MessageEmbed tempEmbed = embed().build(); + final Map> replaceMap = substitutions.createDefaultedMap(this.substitutions); + final UnaryOperator replacer = str -> substitute(translations.translate(str), replaceMap); + + realEmbed.setColor(tempEmbed.getColorRaw()); + realEmbed.setTimestamp(tempEmbed.getTimestamp()); + if (tempEmbed.getTitle() != null) + realEmbed.setTitle(replacer.apply(tempEmbed.getTitle()), tempEmbed.getUrl()); + if (tempEmbed.getThumbnail() != null) + realEmbed.setThumbnail(tempEmbed.getThumbnail().getUrl()); + if (tempEmbed.getAuthor() != null) + realEmbed.setAuthor( + replacer.apply(tempEmbed.getAuthor().getName()), + tempEmbed.getAuthor().getUrl(), + tempEmbed.getAuthor().getIconUrl() + ); + if (tempEmbed.getFooter() != null) + realEmbed.setFooter( + replacer.apply(tempEmbed.getFooter().getText()), + tempEmbed.getFooter().getIconUrl() + ); + if (tempEmbed.getImage() != null) + realEmbed.setImage(tempEmbed.getImage().getUrl()); + if (tempEmbed.getDescription() != null) + realEmbed.setDescription(replacer.apply(tempEmbed.getDescription())); + + for (MessageEmbed.Field field : tempEmbed.getFields()) + realEmbed.addField( + replacer.apply(field.getName()), + replacer.apply(field.getValue()), + field.isInline() + ); + + return realEmbed.build(); + } + + public MessageEmbed build(JanitorBot bot) { + return build(bot.getTranslations(), bot.getSubstitutions()); + } +} diff --git a/src/main/java/sciwhiz12/janitor/msg/Messages.java b/src/main/java/sciwhiz12/janitor/msg/Messages.java index 9b509d1..03b4f53 100644 --- a/src/main/java/sciwhiz12/janitor/msg/Messages.java +++ b/src/main/java/sciwhiz12/janitor/msg/Messages.java @@ -1,11 +1,18 @@ package sciwhiz12.janitor.msg; -import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.IMentionable; +import net.dv8tion.jda.api.entities.ISnowflake; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.User; import sciwhiz12.janitor.JanitorBot; import java.time.OffsetDateTime; import java.time.ZoneOffset; +import static java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME; + public class Messages { public static final int FAILURE_COLOR = 0xF73132; @@ -19,14 +26,72 @@ public class Messages { this.MODERATION = new Moderation(this); } - public String translate(String key, Object... args) { - return bot.getTranslations().translate(key, args); + public JanitorBot getBot() { + return bot; } - public EmbedBuilder failureEmbed(String title) { - return new EmbedBuilder() - .setTitle(title) - .setColor(FAILURE_COLOR) + public MessageBuilder message() { + final MessageBuilder builder = new MessageBuilder(); + builder.embed() .setTimestamp(OffsetDateTime.now(ZoneOffset.UTC)); + return builder; + } + + public MessageBuilder failure() { + final MessageBuilder builder = message(); + builder.embed() + .setColor(FAILURE_COLOR); + return builder; + } + + public MessageBuilder snowflake(MessageBuilder builder, String head, ISnowflake snowflake) { + return builder + .with(head + ".id", snowflake::getId) + .with(head + ".creation_datetime", () -> snowflake.getTimeCreated().format(RFC_1123_DATE_TIME)); + } + + public MessageBuilder mentionable(MessageBuilder builder, String head, IMentionable mentionable) { + return builder + .apply(b -> snowflake(b, head, mentionable)) + .with(head + ".mention", mentionable::getAsMention); + } + + public MessageBuilder role(MessageBuilder builder, String head, Role role) { + return builder + .apply(b -> mentionable(b, head, role)) + .with(head + ".color_hex", () -> Integer.toHexString(role.getColorRaw())) + .with(head + ".name", role::getName) + .with(head + ".permissions", role.getPermissions()::toString); + } + + public MessageBuilder user(MessageBuilder builder, String head, User user) { + return builder + .apply(b -> mentionable(b, head, user)) + .with(head + ".name", user::getName) + .with(head + ".discriminator", user::getDiscriminator) + .with(head + ".tag", user::getAsTag) + .with(head + ".flags", user.getFlags()::toString); + } + + public MessageBuilder guild(MessageBuilder builder, String head, Guild guild) { + return builder + .apply(b -> snowflake(b, head, guild)) + .with(head + ".name", guild::getName) + .with(head + ".description", guild::getDescription) + .with(head + ".voice_region", guild.getRegion()::toString) + .with(head + ".boost.tier", guild.getBoostTier()::toString) + .with(head + ".boost.count", () -> String.valueOf(guild.getBoostCount())) + .with(head + ".locale", guild.getLocale()::toString) + .with(head + ".verification_level", guild.getVerificationLevel()::toString); + } + + public MessageBuilder member(MessageBuilder builder, String head, Member member) { + return builder + .apply(b -> user(b, head, member.getUser())) + .apply(b -> guild(b, head + ".guild", member.getGuild())) + .with(head + ".nickname", member::getNickname) + .with(head + ".effective_name", member::getEffectiveName) + .with(head + ".join_datetime", () -> member.getTimeJoined().format(RFC_1123_DATE_TIME)) + .with(head + ".color", () -> String.valueOf(member.getColorRaw())); } } diff --git a/src/main/java/sciwhiz12/janitor/msg/Moderation.java b/src/main/java/sciwhiz12/janitor/msg/Moderation.java index f903876..3fe302b 100644 --- a/src/main/java/sciwhiz12/janitor/msg/Moderation.java +++ b/src/main/java/sciwhiz12/janitor/msg/Moderation.java @@ -1,20 +1,14 @@ package sciwhiz12.janitor.msg; -import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.MessageChannel; -import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.requests.restaction.MessageAction; import org.checkerframework.checker.nullness.qual.Nullable; import sciwhiz12.janitor.moderation.notes.NoteEntry; import sciwhiz12.janitor.moderation.warns.WarningEntry; import java.time.OffsetDateTime; import java.time.ZoneOffset; -import java.util.Collections; -import java.util.Comparator; import java.util.EnumSet; import java.util.Map; import java.util.stream.Collectors; @@ -34,285 +28,306 @@ public final class Moderation { ERRORS = new Errors(); } - private String translate(String key, Object... args) { - return messages.translate(key, args); + public MessageBuilder moderation() { + return messages.message() + .embed(embed -> embed + .setColor(MODERATION_COLOR) + .setTimestamp(OffsetDateTime.now(ZoneOffset.UTC)) + ); } - public EmbedBuilder moderationEmbed() { - return new EmbedBuilder() - .setColor(MODERATION_COLOR) - .setTimestamp(OffsetDateTime.now(ZoneOffset.UTC)); - } - - public EmbedBuilder moderationEmbed(String author) { - return moderationEmbed() - .setAuthor(author, null, GAVEL_ICON_URL); + public MessageBuilder moderation(String author) { + return moderation() + .embed(embed -> embed.setAuthor(author, null, GAVEL_ICON_URL)); } public class Errors { private Errors() {} - public MessageAction performerInsufficientPermissions(MessageChannel channel, Member performer, - EnumSet permissions) { - return channel.sendMessage( - messages.failureEmbed(translate("moderation.insufficient_permissions.title")) - .setDescription(translate("moderation.insufficient_permissions.desc")) - .addField( - translate("moderation.insufficient_permissions.field.performer"), - performer.getAsMention(), - true) - .addField(new MessageEmbed.Field( - translate("moderation.insufficient_permissions.field.permissions"), - permissions.stream().map(Permission::getName).collect(Collectors.joining(", ")), true)) - .build() - ); - } - - public MessageAction cannotModerate(MessageChannel channel, Member performer, Member target) { - return channel.sendMessage( - messages.failureEmbed(translate("moderation.cannot_interact.title")) - .setDescription(translate("moderation.cannot_interact.desc")) - .addField(translate("moderation.cannot_interact.field.performer"), performer.getAsMention(), true) - .addField(translate("moderation.cannot_interact.field.target"), target.getAsMention(), true) - .build() - ); - } - - public MessageAction cannotWarnMods(MessageChannel channel, Member performer, Member target) { - return channel.sendMessage( - messages.failureEmbed(translate("moderation.warn.cannot_warn_mods.title")) - .setDescription(translate("moderation.warn.cannot_warn_mods.desc")) - .addField(translate("moderation.warn.cannot_warn_mods.field.performer"), performer.getAsMention(), true) - .addField(translate("moderation.warn.cannot_warn_mods.field.target"), target.getAsMention(), true).build() - ); - } - - public MessageAction cannotRemoveHigherModerated(MessageChannel channel, Member performer, int caseID, - WarningEntry entry) { - return channel.sendMessage( - messages.failureEmbed(translate("moderation.unwarn.cannot_remove_higher_mod.title")) - .setDescription(translate("moderation.unwarn.cannot_remove_higher_mod.desc")) - .addField(translate("moderation.unwarn.cannot_remove_higher_mod.field.performer"), performer.getAsMention(), - true) - .addField(translate("moderation.unwarn.cannot_remove_higher_mod.field.original_performer"), - entry.getPerformer().getAsMention(), true) - .addField(translate("moderation.unwarn.cannot_remove_higher_mod.field.case_id"), String.valueOf(caseID), - true) - .build() - ); - } - - public MessageAction maxAmountOfNotes(MessageChannel channel, Member performer, Member target, int amount) { - return channel.sendMessage( - messages.failureEmbed(translate("moderation.note.max_amount_of_notes.title")) - .setDescription(translate("moderation.note.max_amount_of_notes.desc")) - .addField(translate("moderation.note.max_amount_of_notes.field.performer"), performer.getAsMention(), true) - .addField(translate("moderation.note.max_amount_of_notes.field.target"), target.getAsMention(), true) - .addField(translate("moderation.note.max_amount_of_notes.field.amount"), String.valueOf(amount), true) - .build() - ); - } - - public MessageAction noNoteFound(MessageChannel channel, Member performer, int noteID) { - return channel.sendMessage( - messages.failureEmbed(translate("moderation.note.no_note_found.title")) - .setDescription(translate("moderation.note.no_note_found.desc")) - .addField(translate("moderation.note.no_note_found.field.performer"), performer.getAsMention(), true) - .addField(translate("moderation.note.no_note_found.field.note_id"), String.valueOf(noteID), true) - .build() - ); - } - - public MessageAction noWarnWithID(MessageChannel channel, Member performer, int caseID) { - return channel.sendMessage( - messages.failureEmbed(translate("moderation.unwarn.no_case_found.title")) - .setDescription(translate("moderation.unwarn.no_case_found.desc")) - .addField(translate("moderation.unwarn.no_case_found.field.performer"), performer.getAsMention(), true) - .addField(translate("moderation.unwarn.no_case_found.field.case_id"), String.valueOf(caseID), true).build() - ); - } - - public MessageAction cannotUnwarnSelf(MessageChannel channel, Member performer, int caseID, WarningEntry entry) { - return channel.sendMessage( - messages.failureEmbed(translate("moderation.unwarn.cannot_unwarn_self.title")) - .setDescription(translate("moderation.unwarn.cannot_unwarn_self.desc")) - .addField(translate("moderation.unwarn.cannot_unwarn_self.field.performer"), performer.getAsMention(), - true) - .addField(translate("moderation.unwarn.cannot_unwarn_self.field.original_performer"), - entry.getPerformer().getAsMention(), true) - .addField(translate("moderation.unwarn.cannot_unwarn_self.field.case_id"), String.valueOf(caseID), true) - .build() - ); - } - } - - public MessageAction kickUser(MessageChannel channel, Member performer, Member target, @Nullable String reason, - boolean sentDM) { - return channel.sendMessage( - moderationEmbed(translate("moderation.kick.info.author")) - .addField(translate("moderation.kick.info.field.performer"), performer.getAsMention(), true) - .addField(translate("moderation.kick.info.field.target"), target.getAsMention(), true) - .addField(translate("moderation.kick.info.field.sent_private_message"), sentDM ? "✅" : "❌", true) - .addField(reason != null ? translate("moderation.kick.info.field.reason") : null, reason, false) - .build() - ); - } - - public MessageAction kickedDM(MessageChannel channel, Member performer, Member target, @Nullable String reason) { - return channel.sendMessage( - moderationEmbed() - .setAuthor(performer.getGuild().getName(), null, performer.getGuild().getIconUrl()) - .setTitle(translate("moderation.kick.dm.title")) - .addField(translate("moderation.kick.dm.field.performer"), performer.getUser().getAsMention(), true) - .addField(reason != null ? translate("moderation.kick.dm.field.reason") : null, reason, false) - .build() - ); - } - - public MessageAction banUser(MessageChannel channel, Member performer, Member target, @Nullable String reason, - int deletionDays, boolean sentDM) { - return channel.sendMessage( - moderationEmbed(translate("moderation.ban.info.author")) - .addField(translate("moderation.ban.info.field.performer"), performer.getAsMention(), true) - .addField(translate("moderation.ban.info.field.target"), target.getAsMention(), true) - .addField(translate("moderation.ban.info.field.sent_private_message"), sentDM ? "✅" : "❌", true) - .addField(deletionDays != 0 ? - new MessageEmbed.Field(translate("moderation.ban.info.field.delete_duration"), - translate("moderation.ban.info.field.delete_duration.value", String.valueOf(deletionDays)), true) - : null) - .addField(reason != null ? translate("moderation.ban.info.field.reason") : null, reason, false) - .build() - ); - } - - public MessageAction bannedDM(MessageChannel channel, Member performer, @Nullable String reason) { - return channel.sendMessage( - moderationEmbed() - .setAuthor(performer.getGuild().getName(), null, performer.getGuild().getIconUrl()) - .setTitle(translate("moderation.ban.dm.title")) - .addField(translate("moderation.ban.dm.field.performer"), performer.getAsMention(), true) - .addField(reason != null ? translate("moderation.ban.dm.field.reason") : null, reason, false) - .build() - ); - } - - public MessageAction unbanUser(MessageChannel channel, Member performer, User target) { - return channel.sendMessage( - moderationEmbed(translate("moderation.unban.info.author")) - .addField(translate("moderation.unban.info.field.performer"), performer.getAsMention(), true) - .addField(translate("moderation.unban.info.field.target"), target.getAsMention(), true) - .build() - ); - } - - public MessageAction warnUser(MessageChannel channel, Member performer, Member target, String reason, - OffsetDateTime dateTime, int caseID, boolean sentDM) { - return channel.sendMessage( - moderationEmbed(translate("moderation.warn.info.author")) - .addField(translate("moderation.warn.info.field.performer"), performer.getAsMention(), true) - .addField(translate("moderation.warn.info.field.target"), target.getAsMention(), true) - .addField(translate("moderation.warn.info.field.sent_private_message"), sentDM ? "✅" : "❌", true) - .addField(translate("moderation.warn.info.field.case_id"), String.valueOf(caseID), true) - .addField(translate("moderation.warn.info.field.date_time"), - dateTime.format(RFC_1123_DATE_TIME), true) - .addField(translate("moderation.warn.info.field.reason"), reason, false).build() - ); - } - - public MessageAction warnDM(MessageChannel channel, Member performer, Member target, String reason, - OffsetDateTime dateTime) { - return channel.sendMessage( - moderationEmbed() - .setAuthor(performer.getGuild().getName(), null, performer.getGuild().getIconUrl()) - .setTitle(translate("moderation.warn.dm.title")) - .addField(translate("moderation.warn.dm.field.performer"), performer.getUser().getAsMention(), true) - .addField(translate("moderation.warn.dm.field.date_time"), - dateTime.format(RFC_1123_DATE_TIME), true) - .addField(translate("moderation.warn.dm.field.reason"), reason, false) - .build() - ); - } - - public MessageAction warnList(MessageChannel channel, Map displayWarnings) { - return channel.sendMessage( - moderationEmbed(translate("moderation.warnlist.author")) - .setDescription(displayWarnings.size() > 0 ? displayWarnings.entrySet().stream() - .sorted(Collections.reverseOrder(Comparator.comparingInt(Map.Entry::getKey))) - .limit(10) - .map(entry -> - translate("moderation.warnlist.entry", - entry.getKey(), - entry.getValue().getWarned().getAsMention(), - entry.getValue().getPerformer().getAsMention(), - entry.getValue().getDateTime().format(RFC_1123_DATE_TIME), - entry.getValue().getReason() != null - ? entry.getValue().getReason() - : translate("moderation.warnlist.entry.no_reason")) - ) - .collect(Collectors.joining("\n")) - : translate("moderation.warnlist.empty")) - .build() - ); - } - - public MessageAction unwarn(MessageChannel channel, Member performer, int caseID, WarningEntry entry) { - return channel.sendMessage( - moderationEmbed(translate("moderation.unwarn.author")) - .addField(translate("moderation.unwarn.field.performer"), performer.getAsMention(), true) - .addField(translate("moderation.unwarn.field.case_id"), String.valueOf(caseID), true) - .addField(translate("moderation.unwarn.field.original_target"), entry.getWarned().getAsMention(), true) - .addField(translate("moderation.unwarn.field.original_performer"), entry.getPerformer().getAsMention(), true) - .addField(translate("moderation.unwarn.field.date_time"), entry.getDateTime().format(RFC_1123_DATE_TIME), true) - .addField(entry.getReason() != null ? translate("moderation.unwarn.field.reason") : null, entry.getReason(), - false) - .build() - ); - } - - public MessageAction addNote(MessageChannel channel, Member performer, Member target, String contents, - OffsetDateTime dateTime, int noteID) { - return channel.sendMessage( - moderationEmbed(translate("moderation.note.add.author")) - .addField(translate("moderation.note.add.field.performer"), performer.getUser().getAsMention(), true) - .addField(translate("moderation.note.add.field.target"), target.getUser().getAsMention(), true) - .addField(translate("moderation.note.add.field.note_id"), String.valueOf(noteID), true) - .addField(translate("moderation.note.add.field.date_time"), dateTime.format(RFC_1123_DATE_TIME), true) - .addField(translate("moderation.note.add.field.contents"), contents, false) - .build() - ); - } - - public MessageAction noteList(MessageChannel channel, Map displayNotes) { - return channel.sendMessage(moderationEmbed(translate("moderation.note.list.author")) - .setDescription(displayNotes.size() > 0 ? displayNotes.entrySet().stream() - .sorted(Collections.reverseOrder(Comparator.comparingInt(Map.Entry::getKey))) - .limit(10) - .map(entry -> - translate("moderation.note.list.entry", - entry.getKey(), - entry.getValue().getTarget().getAsMention(), - entry.getValue().getPerformer().getAsMention(), - entry.getValue().getDateTime().format(RFC_1123_DATE_TIME), - entry.getValue().getContents()) + public MessageBuilder performerInsufficientPermissions(final Member performer, final EnumSet permissions) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .with("required_permissions", + () -> permissions.stream().map(Permission::getName).collect(Collectors.joining(", "))) + .embed(embed -> embed + .setTitle("moderation.insufficient_permissions.title") + .setDescription("moderation.insufficient_permissions.description") ) - .collect(Collectors.joining("\n")) - : translate("moderation.note.list.empty")) - .build() - ); + .field("moderation.insufficient_permissions.field.performer", true) + .field("moderation.insufficient_permissions.field.required_permissions", true); + } + + public MessageBuilder cannotInteract(final Member performer, final Member target) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> messages.member(builder, "target", target)) + .embed(embed -> embed + .setTitle("moderation.cannot_interact.title") + .setDescription("moderation.cannot_interact.description") + ) + .field("moderation.cannot_interact.field.performer", true) + .field("moderation.cannot_interact.field.target", true); + } + + public MessageBuilder cannotWarnMods(final Member performer, final Member target) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> messages.member(builder, "target", target)) + .embed(embed -> embed + .setTitle("moderation.warn.cannot_warn_mods.title") + .setDescription("moderation.warn.cannot_warn_mods.description") + ) + .field("moderation.warn.cannot_warn_mods.field.performer", true) + .field("moderation.warn.cannot_warn_mods.field.target", true); + } + + public MessageBuilder cannotRemoveHigherModerated(final Member performer, final int caseID, final WarningEntry entry) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> warningEntry(builder, "warning_entry", caseID, entry)) + .embed(embed -> embed + .setTitle("moderation.unwarn.cannot_remove_higher_mod.title") + .setDescription("moderation.unwarn.cannot_remove_higher_mod.description") + ) + .field("moderation.unwarn.cannot_remove_higher_mod.field.performer", true) + .field("moderation.unwarn.cannot_remove_higher_mod.field.target", true); + } + + public MessageBuilder maxAmountOfNotes(final Member performer, final Member target, final int amount) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> messages.member(builder, "target", target)) + .with("notes_amount", () -> String.valueOf(amount)) + .embed(embed -> embed + .setTitle("moderation.note.max_amount_of_notes.title") + .setDescription("moderation.note.max_amount_of_notes.description") + ) + .field("moderation.note.max_amount_of_notes.field.performer", true) + .field("moderation.note.max_amount_of_notes.field.target", true) + .field("moderation.note.max_amount_of_notes.field.amount", true); + } + + public MessageBuilder noNoteFound(final Member performer, final int noteID) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .with("note_id", () -> String.valueOf(noteID)) + .embed(embed -> embed + .setTitle("moderation.note.no_note_found.title") + .setDescription("moderation.note.no_note_found.description") + ) + .field("moderation.note.no_note_found.field.performer", true) + .field("moderation.note.no_note_found.field.note_id", true); + } + + public MessageBuilder noWarnWithID(final Member performer, final int caseID) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .with("case_id", () -> String.valueOf(caseID)) + .embed(embed -> embed + .setTitle("moderation.unwarn.no_case_found.title") + .setDescription("moderation.unwarn.no_case_found.description") + ) + .field("moderation.unwarn.no_case_found.field.performer", true) + .field("moderation.unwarn.no_case_found.field.note_id", true); + } + + public MessageBuilder cannotUnwarnSelf(final Member performer, final int caseID, final WarningEntry entry) { + return messages.failure() + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> warningEntry(builder, "warning_entry", caseID, entry)) + .embed(embed -> embed + .setTitle("moderation.unwarn.cannot_unwarn_self.title") + .setDescription("moderation.unwarn.cannot_unwarn_self.description") + ) + .field("moderation.unwarn.cannot_unwarn_self.field.performer", true) + .field("moderation.unwarn.cannot_unwarn_self.field.original_performer", true) + .field("moderation.unwarn.cannot_unwarn_self.field.target", true); + } } - public MessageAction removeNote(MessageChannel channel, Member performer, int noteID, NoteEntry entry) { - return channel.sendMessage( - moderationEmbed(translate("moderation.note.remove.author")) - .addField(translate("moderation.note.remove.field.performer"), performer.getAsMention(), true) - .addField(translate("moderation.note.remove.field.note_id"), String.valueOf(noteID), true) - .addField(translate("moderation.note.remove.field.original_target"), entry.getTarget().getAsMention(), true) - .addField(translate("moderation.note.remove.field.original_performer"), entry.getPerformer().getAsMention(), - true) - .addField(translate("moderation.note.remove.field.date_time"), entry.getDateTime().format(RFC_1123_DATE_TIME), - true) - .addField(translate("moderation.note.remove.field.contents"), entry.getContents(), false) - .build() - ); + public MessageBuilder kickUser(final Member performer, final Member target, final @Nullable String reason, + final boolean sentDM) { + return moderation("moderation.kick.info.author") + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> messages.member(builder, "target", target)) + .with("reason", () -> reason) + .field("moderation.kick.info.field.performer", true) + .field("moderation.kick.info.field.target", true) + .field("moderation.kick.info.field.private_message." + (sentDM ? "sent" : "unsent"), true) + .field("moderation.kick.info.field.reason", true); + } + + public MessageBuilder kickedDM(final Member performer, final Member target, final @Nullable String reason) { + return moderation() + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> messages.member(builder, "target", target)) + .with("reason", () -> reason) + .embed(embed -> embed + .setTitle("moderation.kick.dm.title") + .setAuthor("moderation.kick.dm.author", null, performer.getGuild().getIconUrl()) + ) + .field("moderation.kick.dm.field.performer", true) + .field("moderation.kick.dm.field.reason", true); + } + + public MessageBuilder banUser(final Member performer, final Member target, final @Nullable String reason, + final int deletionDays, final boolean sentDM) { + return moderation("moderation.ban.info.author") + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> messages.member(builder, "target", target)) + .with("delete_duration", () -> String.valueOf(deletionDays)) + .with("reason", () -> reason) + .field("moderation.ban.info.field.performer", true) + .field("moderation.ban.info.field.target", true) + .field("moderation.ban.info.field.private_message." + (sentDM ? "sent" : "unsent"), true) + .field("moderation.ban.info.field.delete_duration", true) + .field("moderation.ban.info.field.reason", true); + } + + public MessageBuilder bannedDM(final Member performer, final Member target, @Nullable final String reason) { + return moderation() + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> messages.member(builder, "target", target)) + .with("reason", () -> reason) + .embed(embed -> embed + .setTitle("moderation.ban.dm.title") + .setAuthor("moderation.ban.dm.author", null, performer.getGuild().getIconUrl()) + ) + .field("moderation.ban.dm.field.performer", true) + .field("moderation.ban.dm.field.reason", true); + } + + public MessageBuilder unbanUser(final Member performer, final User target) { + return moderation("moderation.unban.info.author") + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> messages.user(builder, "target", target)) + .field("moderation.unban.info.field.performer", true) + .field("moderation.unban.info.field.target", true); + } + + public void warningEntry(MessageBuilder builder, String head, int caseID, WarningEntry entry) { + builder + .with(head + ".case_id", () -> String.valueOf(caseID)) + .apply(b -> messages.user(b, head + ".performer", entry.getPerformer())) + .apply(b -> messages.user(b, head + ".target", entry.getWarned())) + .with(head + ".date_time", () -> entry.getDateTime().format(RFC_1123_DATE_TIME)) + .with(head + ".reason", entry::getReason); + } + + public MessageBuilder warnUser(final Member performer, final int caseID, final WarningEntry entry, final boolean sentDM) { + return moderation("moderation.warn.info.author") + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> warningEntry(builder, "warning_entry", caseID, entry)) + .field("moderation.warn.info.field.performer", true) + .field("moderation.warn.info.field.target", true) + .field("moderation.warn.info.field.private_message." + (sentDM ? "sent" : "unsent"), true) + .field("moderation.warn.info.field.date_time", true) + .field("moderation.warn.info.field.case_id", true) + .field("moderation.warn.info.field.reason", true); + } + + public MessageBuilder warnedDM(final Member performer, final Member target, final String reason, + final OffsetDateTime dateTime) { + return moderation() + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> messages.member(builder, "target", target)) + .with("date_time", () -> dateTime.format(RFC_1123_DATE_TIME)) + .with("reason", () -> reason) + .embed(embed -> embed + .setTitle("moderation.warn.dm.title") + .setAuthor("moderation.warn.dm.author", null, performer.getGuild().getIconUrl()) + ) + .field("moderation.warn.dm.field.performer", true) + .field("moderation.warn.dm.field.date_time", true) + .field("moderation.warn.dm.field.reason", true); + } + + public MessageBuilder warnList(final Map displayWarnings) { + // return channel.sendMessage( + // moderationEmbed(translate("moderation.warnlist.author")) + // .setDescription(displayWarnings.size() > 0 ? displayWarnings.entrySet().stream() + // .sorted(Collections.reverseOrder(Comparator.comparingInt(Map.Entry::getKey))) + // .limit(10) + // .map(entry -> + // translate("moderation.warnlist.entry", + // entry.getKey(), + // entry.getValue().getWarned().getAsMention(), + // entry.getValue().getPerformer().getAsMention(), + // entry.getValue().getDateTime().format(RFC_1123_DATE_TIME), + // entry.getValue().getReason() != null + // ? entry.getValue().getReason() + // : translate("moderation.warnlist.entry.no_reason")) + // ) + // .collect(Collectors.joining("\n")) + // : translate("moderation.warnlist.empty")) + // .build() + // ); + return moderation() + .embed(embed -> embed.setTitle("NO OP, CURRENTLY IN PROGRESS")); + } + + public MessageBuilder unwarn(final Member performer, final int caseID, final WarningEntry entry) { + return moderation("moderation.unwarn.author") + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> warningEntry(builder, "warning_entry", caseID, entry)) + .field("moderation.unwarn.field.performer", true) + .field("moderation.unwarn.field.case_id", true) + .field("moderation.unwarn.field.original_performer", true) + .field("moderation.unwarn.field.original_target", true) + .field("moderation.unwarn.field.date_time", true) + .field("moderation.unwarn.field.reason", true); + } + + public void noteEntry(MessageBuilder builder, String head, int noteID, NoteEntry entry) { + builder + .with(head + ".note_id", () -> String.valueOf(noteID)) + .apply(b -> messages.user(b, head + ".performer", entry.getPerformer())) + .apply(b -> messages.user(b, head + ".target", entry.getTarget())) + .with(head + ".date_time", () -> entry.getDateTime().format(RFC_1123_DATE_TIME)) + .with(head + ".contents", entry::getContents); + } + + public MessageBuilder addNote(final Member performer, final int noteID, final NoteEntry entry) { + return moderation("moderation.note.add.author") + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> noteEntry(builder, "note", noteID, entry)) + .field("moderation.note.add.field.performer", true) + .field("moderation.note.add.field.target", true) + .field("moderation.note.add.field.note_id", true) + .field("moderation.note.add.field.date_time", true) + .field("moderation.note.add.field.contents", true); + } + + public MessageBuilder noteList(final Map displayNotes) { + // return channel.sendMessage(moderationEmbed(translate("moderation.note.list.author")) + // .setDescription(displayNotes.size() > 0 ? displayNotes.entrySet().stream() + // .sorted(Collections.reverseOrder(Comparator.comparingInt(Map.Entry::getKey))) + // .limit(10) + // .map(entry -> + // translate("moderation.note.list.entry", + // entry.getKey(), + // entry.getValue().getTarget().getAsMention(), + // entry.getValue().getPerformer().getAsMention(), + // entry.getValue().getDateTime().format(RFC_1123_DATE_TIME), + // entry.getValue().getContents()) + // ) + // .collect(Collectors.joining("\n")) + // : translate("moderation.note.list.empty")) + // .build() + // ); + return moderation() + .embed(embed -> embed.setTitle("NO OP, CURRENTLY IN PROGRESS")); + } + + public MessageBuilder removeNote(final Member performer, final int noteID, final NoteEntry entry) { + return moderation("moderation.note.remove.author") + .apply(builder -> messages.member(builder, "performer", performer)) + .apply(builder -> noteEntry(builder, "note", noteID, entry)) + .field("moderation.note.remove.field.performer", true) + .field("moderation.note.remove.field.case_id", true) + .field("moderation.note.remove.field.original_performer", true) + .field("moderation.note.remove.field.original_target", true) + .field("moderation.note.remove.field.date_time", true) + .field("moderation.note.remove.field.contents", true); } } diff --git a/src/main/java/sciwhiz12/janitor/msg/Substitutions.java b/src/main/java/sciwhiz12/janitor/msg/Substitutions.java new file mode 100644 index 0000000..75fa7eb --- /dev/null +++ b/src/main/java/sciwhiz12/janitor/msg/Substitutions.java @@ -0,0 +1,59 @@ +package sciwhiz12.janitor.msg; + +import org.apache.commons.collections4.TransformerUtils; +import org.apache.commons.collections4.map.DefaultedMap; +import sciwhiz12.janitor.JanitorBot; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.util.regex.Matcher.quoteReplacement; +import static java.util.regex.Pattern.CASE_INSENSITIVE; + +public class Substitutions { + public static final Pattern ARGUMENT_REGEX = Pattern.compile("\\$\\{(.+?)}", CASE_INSENSITIVE); + public static final Pattern NULL_ARGUMENT_REGEX = Pattern.compile("nullcheck;(.+?);(.+)", CASE_INSENSITIVE); + + public static String substitute(String text, Map> arguments) { + final Matcher matcher = ARGUMENT_REGEX.matcher(text); + return matcher.replaceAll(matchResult -> { + final Matcher nullMatcher = NULL_ARGUMENT_REGEX.matcher(matchResult.group(1)); + if (nullMatcher.matches()) { + final String str = arguments.get(nullMatcher.group(1)).get(); + return str != null ? + quoteReplacement(str) : + quoteReplacement(arguments.getOrDefault(nullMatcher.group(2), () -> nullMatcher.group(2)).get()); + } + return quoteReplacement(arguments.getOrDefault(matchResult.group(1), () -> matchResult.group(0)).get()); + }); + } + + private final JanitorBot bot; + private final Map> defaultSubstitutions = new HashMap<>(); + + public Substitutions(JanitorBot bot) { + this.bot = bot; + } + + public JanitorBot getBot() { + return bot; + } + + public String substitute(String text) { + return Substitutions.substitute(text, defaultSubstitutions); + } + + public String with(String text, Map> substitutions) { + return Substitutions.substitute( + text, + DefaultedMap.defaultedMap(substitutions, TransformerUtils.mapTransformer(defaultSubstitutions)) + ); + } + + public Map> createDefaultedMap(Map> custom) { + return DefaultedMap.defaultedMap(custom, TransformerUtils.mapTransformer(defaultSubstitutions)); + } +} diff --git a/src/main/resources/english.json b/src/main/resources/english.json index 4de540a..abc3289 100644 --- a/src/main/resources/english.json +++ b/src/main/resources/english.json @@ -1,111 +1,182 @@ { "general.guild_only_command.title": "Guild only command!", - "general.guild_only_command.desc": "This command can only be run in a guild channel.", - "general.insufficient_permissions.title": "I have insufficient permissions!", - "general.insufficient_permissions.desc": "I do not have sufficient permissions to carry out this action!\nPlease contact your server admins if you believe this is in error.", - "general.insufficient_permissions.field.permissions": "Required permissions", + "general.guild_only_command.description": "This command can only be run in a guild channel.", "general.ambiguous_member.title": "Ambiguous member argument!", - "general.ambiguous_member.desc": "The name you have specified is too ambiguous (leads to more than 1 member)!\nPlease narrow down the specified name until it can uniquely identify a member of this guild.", + "general.ambiguous_member.description": "The name you have specified is too ambiguous (leads to more than 1 member)!\nPlease narrow down the specified name until it can uniquely identify a member of this guild.", + "general.insufficient_permissions.title": "I have insufficient permissions!", + "general.insufficient_permissions.description": "I do not have sufficient permissions to carry out this action!\nPlease contact your server admins if you believe this is in error.", + "general.insufficient_permissions.field.permissions.name": "Required permissions", + "general.insufficient_permissions.field.permissions.value": "${required_permissions}", "general.cannot_interact.title": "Member is higher than me!", - "general.cannot_interact.desc": "Cannot perform action on the given member, likely due to me being lower in the role hierarchy.", - "general.cannot_interact.field.target": "Target", + "general.cannot_interact.description": "Cannot perform action on the given member, likely due to me being lower in the role hierarchy.", + "general.cannot_interact.field.target.name": "Target", + "general.cannot_interact.field.target.value": "${target.mention}", "general.cannot_action_self.title": "Cannot act against myself!", - "general.cannot_action_self.desc": "Cannot perform action against myself, as that would be counter-intuitive.", + "general.cannot_action_self.description": "Cannot perform action against myself, as that would be counter-intuitive.", "general.cannot_action_performer.title": "Performer cannot act against self!", - "general.cannot_action_performer.desc": "You cannot perform this action against yourself.", - "general.cannot_action_performer.field.performer": "Performer/Target", + "general.cannot_action_performer.description": "You cannot perform this action against yourself.", + "general.cannot_action_performer.field.performer.name": "Performer/Target", + "general.cannot_action_performer.field.performer.value": "${performer.mention}", "moderation.insufficient_permissions.title": "Insufficient permissions.", - "moderation.insufficient_permissions.desc": "The performer of this command has insufficient permissions to use this command.", - "moderation.insufficient_permissions.field.performer": "Performer", - "moderation.insufficient_permissions.field.permissions": "Required permissions", + "moderation.insufficient_permissions.description": "The performer of this command has insufficient permissions to use this command.", + "moderation.insufficient_permissions.field.performer.name": "Performer", + "moderation.insufficient_permissions.field.performer.value": "${performer.mention}", + "moderation.insufficient_permissions.field.permissions.name": "Required permissions", + "moderation.insufficient_permissions.field.permissions.value": "${required_permissions}", "moderation.cannot_interact.title": "Cannot moderate Target.", - "moderation.cannot_interact.desc": "The performer of this command cannot moderate the target user, likely due to being lower in the role hierarchy.", - "moderation.cannot_interact.field.performer": "Performer", - "moderation.cannot_interact.field.target": "Target", + "moderation.cannot_interact.description": "The performer of this command cannot moderate the target user, likely due to being lower in the role hierarchy.", + "moderation.cannot_interact.field.performer.name": "Performer", + "moderation.cannot_interact.field.performer.value": "${performer.mention}", + "moderation.cannot_interact.field.target.name": "Target", + "moderation.cannot_interact.field.target.value": "${target.mention}", "moderation.kick.info.author": "Kicked user from server.", - "moderation.kick.info.field.performer": "Performer", - "moderation.kick.info.field.target": "Target", - "moderation.kick.info.field.reason": "Reason", - "moderation.kick.info.field.sent_private_message": "Sent DM", + "moderation.kick.info.field.performer.name": "Performer", + "moderation.kick.info.field.performer.value": "${performer.mention}", + "moderation.kick.info.field.target.name": "Target", + "moderation.kick.info.field.target.value": "${target.mention}", + "moderation.kick.info.field.reason.name": "Reason", + "moderation.kick.info.field.reason.value": "${nullcheck;reason;_No reason specified._}", + "moderation.kick.info.field.private_message.sent.name": "Sent DM", + "moderation.kick.info.field.private_message.sent.value": "✅", + "moderation.kick.info.field.private_message.unsent.name": "Sent DM", + "moderation.kick.info.field.private_message.unsent.value": "❌", + "moderation.kick.dm.author": "${performer.guild.name}", "moderation.kick.dm.title": "You were kicked from this server.", - "moderation.kick.dm.field.performer": "Moderator", - "moderation.kick.dm.field.reason": "Reason", + "moderation.kick.dm.field.performer.name": "Moderator", + "moderation.kick.dm.field.performer.value": "${performer.mention}", + "moderation.kick.dm.field.reason.name": "Reason", + "moderation.kick.dm.field.reason.value": "${nullcheck;reason;_No reason specified._}", "moderation.ban.info.author": "Banned user from server.", - "moderation.ban.info.field.performer": "Performer", - "moderation.ban.info.field.target": "Target", - "moderation.ban.info.field.reason": "Reason", - "moderation.ban.info.field.sent_private_message": "Sent DM", - "moderation.ban.info.field.delete_duration": "Message Deletion", - "moderation.ban.info.field.delete_duration.value": "%s day(s)", + "moderation.ban.info.field.performer.name": "Performer", + "moderation.ban.info.field.performer.value": "${performer.mention}", + "moderation.ban.info.field.target.name": "Target", + "moderation.ban.info.field.target.value": "${target.mention}", + "moderation.ban.info.field.reason.name": "Reason", + "moderation.ban.info.field.reason.value": "${nullcheck;reason;_No reason specified._}", + "moderation.ban.info.field.private_message.sent.name": "Sent DM", + "moderation.ban.info.field.private_message.sent.value": "✅", + "moderation.ban.info.field.private_message.unsent.name": "Sent DM", + "moderation.ban.info.field.private_message.unsent.value": "❌", + "moderation.ban.info.field.delete_duration.name": "Message Deletion", + "moderation.ban.info.field.delete_duration.value": "${delete_duration} day(s)", + "moderation.ban.dm.author": "${performer.guild.name}", "moderation.ban.dm.title": "You were banned from this server.", - "moderation.ban.dm.field.performer": "Moderator", - "moderation.ban.dm.field.reason": "Reason", + "moderation.ban.dm.field.performer.name": "Moderator", + "moderation.ban.dm.field.performer.value": "${performer.mention}", + "moderation.ban.dm.field.reason.name": "Reason", + "moderation.ban.dm.field.reason.value": "${nullcheck;reason;_No reason specified._}", "moderation.unban.info.author": "Unbanned user from server.", - "moderation.unban.info.field.performer": "Performer", - "moderation.unban.info.field.target": "Target", + "moderation.unban.info.field.performer.name": "Performer", + "moderation.unban.info.field.performer.value": "${performer.mention}", + "moderation.unban.info.field.target.name": "Target", + "moderation.unban.info.field.target.value": "${target.mention}", "moderation.warn.info.author": "Warned user.", - "moderation.warn.info.field.performer": "Performer", - "moderation.warn.info.field.target": "Target", - "moderation.warn.info.field.sent_private_message": "Sent DM", - "moderation.warn.info.field.case_id": "Case ID", - "moderation.warn.info.field.date_time": "Date & Time", - "moderation.warn.info.field.reason": "Reason", + "moderation.warn.info.field.performer.name": "Performer", + "moderation.warn.info.field.performer.value": "${warning_entry.performer.mention}", + "moderation.warn.info.field.target.name": "Target", + "moderation.warn.info.field.target.value": "${warning_entry.target.mention}", + "moderation.warn.info.field.case_id.name": "Case ID", + "moderation.warn.info.field.case_id.value": "${warning_entry.case_id}", + "moderation.warn.info.field.reason.name": "Reason", + "moderation.warn.info.field.reason.value": "${nullcheck;warning_entry.reason;_No reason specified._}", + "moderation.warn.info.field.private_message.sent.name": "Sent DM", + "moderation.warn.info.field.private_message.sent.value": "✅", + "moderation.warn.info.field.private_message.unsent.name": "Sent DM", + "moderation.warn.info.field.private_message.unsent.value": "❌", + "moderation.warn.info.field.date_time.name": "Date & Time", + "moderation.warn.info.field.date_time.value": "${warning_entry.date_time}", + "moderation.warn.dm.author": "${performer.guild.name}", "moderation.warn.dm.title": "You were warned by a moderator.", - "moderation.warn.dm.field.performer": "Moderator", - "moderation.warn.dm.field.date_time": "Date & Time", - "moderation.warn.dm.field.reason": "Reason", + "moderation.warn.dm.field.performer.name": "Moderator", + "moderation.warn.dm.field.performer.value": "${performer.mention}", + "moderation.warn.dm.field.date_time.name": "Date & Time", + "moderation.warn.dm.field.date_time.value": "${date_time}", + "moderation.warn.dm.field.reason.name": "Reason", + "moderation.warn.dm.field.reason.value": "${nullcheck;reason;_No reason specified._}", "moderation.warnlist.author": "Listing of Warnings", "moderation.warnlist.empty": "**_No warnings logged matching your query._**", "moderation.warnlist.entry": "**Case #%1$s**: Warned %2$s by %3$s %n - _Date & Time:_ %4$s %n - _Reason:_ %5$s", "moderation.warnlist.entry.no_reason": "_no reason specified_", "moderation.unwarn.author": "Removed warning from user.", - "moderation.unwarn.field.performer": "Performer", - "moderation.unwarn.field.original_target": "Original Target", - "moderation.unwarn.field.original_performer": "Original Performer", - "moderation.unwarn.field.case_id": "Case ID", - "moderation.unwarn.field.date_time": "Date & Time", - "moderation.unwarn.field.reason": "Reason", + "moderation.unwarn.field.performer.name": "Performer", + "moderation.unwarn.field.performer.value": "${performer.mention}", + "moderation.unwarn.field.original_target.name": "Original Target", + "moderation.unwarn.field.original_target.value": "${warning_entry.target.mention}", + "moderation.unwarn.field.original_performer.name": "Original Performer", + "moderation.unwarn.field.original_performer.value": "${warning_entry.performer.mention}", + "moderation.unwarn.field.case_id.name": "Case ID", + "moderation.unwarn.field.case_id.value": "${warning_entry.case_id}", + "moderation.unwarn.field.date_time.name": "Date & Time", + "moderation.unwarn.field.date_time.value": "${warning_entry.date_time}", + "moderation.unwarn.field.reason.name": "Reason", + "moderation.unwarn.field.reason.value": "${nullcheck;warning_entry.reason;_No reason specified._}", "moderation.unwarn.no_case_found.title": "No warning found.", - "moderation.unwarn.no_case_found.desc": "No warning with that case ID was found.", - "moderation.unwarn.no_case_found.field.performer": "Performer", - "moderation.unwarn.no_case_found.field.case_id": "Case ID", + "moderation.unwarn.no_case_found.description": "No warning with that case ID was found.", + "moderation.unwarn.no_case_found.field.performer.name": "Performer", + "moderation.unwarn.no_case_found.field.performer.value": "${performer.mention}", + "moderation.unwarn.no_case_found.field.case_id.name": "Case ID", + "moderation.unwarn.no_case_found.field.case_id.value": "${case_id}", "moderation.unwarn.cannot_unwarn_self.title": "Cannot remove warning from self.", - "moderation.unwarn.cannot_unwarn_self.desc": "Performer cannot remove a warning from themselves.", - "moderation.unwarn.cannot_unwarn_self.field.performer": "Performer/Original Target", - "moderation.unwarn.cannot_unwarn_self.field.original_performer": "Original Performer", - "moderation.unwarn.cannot_unwarn_self.field.case_id": "Case ID", + "moderation.unwarn.cannot_unwarn_self.description": "Performer cannot remove a warning from themselves.", + "moderation.unwarn.cannot_unwarn_self.field.performer.name": "Performer/Original Target", + "moderation.unwarn.cannot_unwarn_self.field.performer.value": "${performer.mention}", + "moderation.unwarn.cannot_unwarn_self.field.original_performer.name": "Original Performer", + "moderation.unwarn.cannot_unwarn_self.field.original_performer.value": "${warning_entry.performer.mention}", + "moderation.unwarn.cannot_unwarn_self.field.case_id.name": "Case ID", + "moderation.unwarn.cannot_unwarn_self.field.case_id.value": "${warning_entry.case_id}", "moderation.warn.cannot_warn_mods.title": "Cannot warn moderators.", - "moderation.warn.cannot_warn_mods.desc": "Moderators cannot issue warnings to other moderators.", - "moderation.warn.cannot_warn_mods.field.performer": "Performer", - "moderation.warn.cannot_warn_mods.field.target": "Target", + "moderation.warn.cannot_warn_mods.description": "Moderators cannot issue warnings to other moderators.", + "moderation.warn.cannot_warn_mods.field.performer.name": "Performer", + "moderation.warn.cannot_warn_mods.field.performer.value": "${performer.mention}", + "moderation.warn.cannot_warn_mods.field.target.name": "Target", + "moderation.warn.cannot_warn_mods.field.target.value": "${target.mention}", "moderation.warn.cannot_remove_higher_mod.title": "Cannot remove warning issued by higher-ranked moderator.", - "moderation.warn.cannot_remove_higher_mod.desc": "The performer cannot remove this warning, as this was issued by a higher-ranking moderator.", - "moderation.warn.cannot_remove_higher_mod.field.performer": "Performer", - "moderation.warn.cannot_remove_higher_mod.field.original_performer": "Original Performer", - "moderation.warn.cannot_remove_higher_mod.field.case_id": "Case ID", + "moderation.warn.cannot_remove_higher_mod.description": "The performer cannot remove this warning, as this was issued by a higher-ranking moderator.", + "moderation.warn.cannot_remove_higher_mod.field.performer.name": "Performer", + "moderation.warn.cannot_remove_higher_mod.field.performer.value": "${performer.mention}", + "moderation.warn.cannot_remove_higher_mod.field.original_performer.name": "Original Performer", + "moderation.warn.cannot_remove_higher_mod.field.original_performer.value": "${warning_entry.performer.mention}", + "moderation.warn.cannot_remove_higher_mod.field.case_id.name": "Case ID", + "moderation.warn.cannot_remove_higher_mod.field.case_id.value": "${warning_entry.case_id}", "moderation.note.max_amount_of_notes.title": "Max notes reached.", - "moderation.note.max_amount_of_notes.desc": "The performer has reached the maximum amount of notes for the target user.", - "moderation.note.max_amount_of_notes.field.performer": "Performer", - "moderation.note.max_amount_of_notes.field.target": "Target", - "moderation.note.max_amount_of_notes.field.amount": "(Max.) Amount", + "moderation.note.max_amount_of_notes.description": "The performer has reached the maximum amount of notes for the target user.", + "moderation.note.max_amount_of_notes.field.performer.name": "Performer", + "moderation.note.max_amount_of_notes.field.performer.value": "${performer.mention}", + "moderation.note.max_amount_of_notes.field.target.name": "Target", + "moderation.note.max_amount_of_notes.field.target.value": "${target.mention}", + "moderation.note.max_amount_of_notes.field.amount.name": "(Max.) Amount", + "moderation.note.max_amount_of_notes.field.amount.value": "${notes_amount}", "moderation.note.no_note_found.title": "No note found.", - "moderation.note.no_note_found.desc": "No note with that note ID was found.", - "moderation.note.no_note_found.field.performer": "Performer", - "moderation.note.no_note_found.field.note_id": "Note ID", + "moderation.note.no_note_found.description": "No note with that note ID was found.", + "moderation.note.no_note_found.field.performer.name": "Performer", + "moderation.note.no_note_found.field.performer.value": "${performer.mention}", + "moderation.note.no_note_found.field.note_id.name": "Note ID", + "moderation.note.no_note_found.field.note_id.value": "${note_id}", "moderation.note.list.author": "Listing of Notes", "moderation.note.list.empty": "**_No recorded notes matching your query._**", "moderation.note.list.entry": "**#%1$s**: for %2$s by %3$s %n - _Date & Time:_ %4$s %n - _Text:_ %5$s", "moderation.note.add.author": "Recorded note for user.", - "moderation.note.add.field.performer": "Performer", - "moderation.note.add.field.target": "Target", - "moderation.note.add.field.note_id": "Note ID", - "moderation.note.add.field.date_time": "Date & Time", - "moderation.note.add.field.contents": "Text", + "moderation.note.add.field.performer.name": "Performer", + "moderation.note.add.field.performer.value": "${note.performer.mention}", + "moderation.note.add.field.target.name": "Target", + "moderation.note.add.field.target.value": "${note.target.mention}", + "moderation.note.add.field.note_id.name": "Note ID", + "moderation.note.add.field.note_id.value": "${note.note_id}", + "moderation.note.add.field.date_time.name": "Date & Time", + "moderation.note.add.field.date_time.value": "${note.date_time}", + "moderation.note.add.field.contents.name": "Text", + "moderation.note.add.field.contents.value": "${note.contents}", "moderation.note.remove.author": "Removed note.", - "moderation.note.remove.field.performer": "Performer", - "moderation.note.remove.field.original_target": "Original Target", - "moderation.note.remove.field.original_performer": "Original Performer", - "moderation.note.remove.field.note_id": "Note ID", - "moderation.note.remove.field.date_time": "Date & Time", - "moderation.note.remove.field.contents": "Text" + "moderation.note.remove.field.performer.name": "Performer", + "moderation.note.remove.field.performer.value": "${performer.mention}", + "moderation.note.remove.field.original_performer.name": "Original Performer", + "moderation.note.remove.field.original_performer.value": "${note.performer.mention}", + "moderation.note.remove.field.original_target.name": "Original Target", + "moderation.note.remove.field.original_target.value": "${note.target.mention}", + "moderation.note.remove.field.note_id.name": "Note ID", + "moderation.note.remove.field.note_id.value": "${note.note_id}", + "moderation.note.remove.field.date_time.name": "Date & Time", + "moderation.note.remove.field.date_time.value": "${note.date_time}", + "moderation.note.remove.field.contents.name": "Text", + "moderation.note.remove.field.contents.value": "${note.contents}" } \ No newline at end of file