mirror of
https://github.com/sciwhiz12/Janitor.git
synced 2024-11-12 21:31:26 +00:00
Refactor, remove translations, add guild config system
This commit is contained in:
parent
df831da94d
commit
42adb8238c
|
@ -44,11 +44,6 @@ public class BotConsole {
|
|||
case "reload": {
|
||||
if (parts.length >= 2)
|
||||
switch (parts[1]) {
|
||||
case "translations": {
|
||||
CONSOLE.info("Reloading translations");
|
||||
bot.getTranslations().loadTranslations();
|
||||
break outer;
|
||||
}
|
||||
case "messages": {
|
||||
CONSOLE.info("Reloading messages");
|
||||
bot.getMessages().loadMessages();
|
||||
|
|
|
@ -8,8 +8,8 @@ import net.dv8tion.jda.api.entities.PrivateChannel;
|
|||
import net.dv8tion.jda.api.entities.User;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.config.BotConfig;
|
||||
import sciwhiz12.janitor.config.ConfigManager;
|
||||
import sciwhiz12.janitor.msg.Messages;
|
||||
import sciwhiz12.janitor.msg.TranslationMap;
|
||||
import sciwhiz12.janitor.msg.emote.ReactionManager;
|
||||
import sciwhiz12.janitor.msg.substitution.SubstitutionMap;
|
||||
import sciwhiz12.janitor.storage.GuildStorage;
|
||||
|
@ -27,8 +27,8 @@ public class JanitorBot {
|
|||
private final BotConsole console;
|
||||
private final GuildStorage storage;
|
||||
private final GuildStorage.SavingThread storageSavingThread;
|
||||
private final ConfigManager configManager;
|
||||
private final CommandRegistry cmdRegistry;
|
||||
private final TranslationMap translations;
|
||||
private final SubstitutionMap substitutions;
|
||||
private final Messages messages;
|
||||
private final ReactionManager reactions;
|
||||
|
@ -38,10 +38,10 @@ public class JanitorBot {
|
|||
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.translations = new TranslationMap(this, config.getTranslationsFile());
|
||||
this.configManager = new ConfigManager(this, config.getConfigsFolder());
|
||||
this.cmdRegistry = new CommandRegistry(this);
|
||||
this.substitutions = new SubstitutionMap(this);
|
||||
this.messages = new Messages(this, config.getTranslationsFile());
|
||||
this.messages = new Messages(this, config.getMessagesFolder());
|
||||
this.reactions = new ReactionManager(this);
|
||||
// TODO: find which of these can be loaded in parallel before the bot JDA is ready
|
||||
discord.addEventListener(cmdRegistry, reactions);
|
||||
|
@ -78,14 +78,12 @@ public class JanitorBot {
|
|||
|
||||
public GuildStorage getStorage() { return this.storage; }
|
||||
|
||||
public ConfigManager getConfigManager() { return configManager; }
|
||||
|
||||
public CommandRegistry getCommandRegistry() {
|
||||
return this.cmdRegistry;
|
||||
}
|
||||
|
||||
public TranslationMap getTranslations() {
|
||||
return this.translations;
|
||||
}
|
||||
|
||||
public ReactionManager getReactionManager() {
|
||||
return this.reactions;
|
||||
}
|
||||
|
@ -113,6 +111,8 @@ public class JanitorBot {
|
|||
discord.shutdown();
|
||||
storageSavingThread.stopThread();
|
||||
storage.save();
|
||||
configManager.save();
|
||||
configManager.close();
|
||||
console.stop();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package sciwhiz12.janitor.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
import sciwhiz12.janitor.config.BotConfig;
|
||||
import sciwhiz12.janitor.config.GuildConfig;
|
||||
import sciwhiz12.janitor.msg.Messages;
|
||||
|
||||
public abstract class BaseCommand {
|
||||
|
@ -25,9 +26,11 @@ public abstract class BaseCommand {
|
|||
return getBot().getMessages();
|
||||
}
|
||||
|
||||
protected BotConfig config() {
|
||||
return getBot().getConfig();
|
||||
}
|
||||
protected GuildConfig config(MessageReceivedEvent event) { return config(event.getGuild().getIdLong()); }
|
||||
|
||||
protected GuildConfig config(Guild guild) { return config(guild.getIdLong()); }
|
||||
|
||||
protected GuildConfig config(long guildID) { return getBot().getConfigManager().getConfig(guildID); }
|
||||
|
||||
public abstract LiteralArgumentBuilder<MessageReceivedEvent> getNode();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import sciwhiz12.janitor.commands.moderation.UnbanCommand;
|
|||
import sciwhiz12.janitor.commands.moderation.UnwarnCommand;
|
||||
import sciwhiz12.janitor.commands.moderation.WarnCommand;
|
||||
import sciwhiz12.janitor.commands.moderation.WarnListCommand;
|
||||
import sciwhiz12.janitor.config.GuildConfig;
|
||||
import sciwhiz12.janitor.utils.Util;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -30,13 +31,11 @@ import static sciwhiz12.janitor.Logging.JANITOR;
|
|||
|
||||
public class CommandRegistry implements EventListener {
|
||||
private final JanitorBot bot;
|
||||
private final String prefix;
|
||||
private final Map<String, BaseCommand> registry = new HashMap<>();
|
||||
private final CommandDispatcher<MessageReceivedEvent> dispatcher;
|
||||
|
||||
public CommandRegistry(JanitorBot bot, String prefix) {
|
||||
public CommandRegistry(JanitorBot bot) {
|
||||
this.bot = bot;
|
||||
this.prefix = prefix;
|
||||
this.dispatcher = new CommandDispatcher<>();
|
||||
|
||||
addCommand(new PingCommand(this, "ping", "Pong!"));
|
||||
|
@ -69,17 +68,28 @@ public class CommandRegistry implements EventListener {
|
|||
public void onEvent(@NotNull GenericEvent genericEvent) {
|
||||
if (!(genericEvent instanceof MessageReceivedEvent)) return;
|
||||
MessageReceivedEvent event = (MessageReceivedEvent) genericEvent;
|
||||
if (event.getAuthor().isBot()) return;
|
||||
final String prefix;
|
||||
if (event.isFromGuild()) {
|
||||
prefix = getBot().getConfigManager().getConfig(event.getGuild().getIdLong())
|
||||
.forGuild(GuildConfig.COMMAND_PREFIX);
|
||||
} else {
|
||||
prefix = getBot().getConfig().getCommandPrefix();
|
||||
}
|
||||
|
||||
String msg = event.getMessage().getContentRaw();
|
||||
if (!msg.startsWith(this.prefix)) return;
|
||||
if (!msg.startsWith(prefix)) return;
|
||||
JANITOR.debug(COMMANDS, "Received message starting with valid command prefix. Author: {}, full message: {}",
|
||||
Util.toString(event.getAuthor()), msg);
|
||||
try {
|
||||
StringReader command = new StringReader(msg.substring(this.prefix.length()));
|
||||
StringReader command = new StringReader(msg.substring(prefix.length()));
|
||||
ParseResults<MessageReceivedEvent> 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
|
||||
JANITOR.error(COMMANDS, "Error while parsing command: {}", parseResults.getExceptions().values());
|
||||
if (parseResults.getExceptions().isEmpty()) {
|
||||
JANITOR.info(COMMANDS, "Command not found.");
|
||||
} else {
|
||||
JANITOR.error(COMMANDS, "Error while parsing command: {}", parseResults.getExceptions().values());
|
||||
}
|
||||
return;
|
||||
}
|
||||
JANITOR.debug(COMMANDS, "Executing command.");
|
||||
|
|
|
@ -124,7 +124,7 @@ public class BanCommand extends BaseCommand {
|
|||
.flatMap(v -> messages().getRegularMessage("moderation/ban/info")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(MessageHelper.member("target", target))
|
||||
.with("private_message", () -> res.isSuccess() ? "✅" : "❌")
|
||||
.with("private_message", () -> res.isSuccess() ? "\u2705" : "\u274C")
|
||||
.with("delete_duration", () -> String.valueOf(days))
|
||||
.with("reason", () -> reason)
|
||||
.send(getBot(), channel)
|
||||
|
|
|
@ -110,7 +110,7 @@ public class KickCommand extends BaseCommand {
|
|||
.flatMap(v -> messages().getRegularMessage("moderation/kick/info")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(MessageHelper.member("target", target))
|
||||
.with("private_message", () -> res.isSuccess() ? "✅" : "❌")
|
||||
.with("private_message", () -> res.isSuccess() ? "\u2705" : "\u274C")
|
||||
.with("reason", () -> reason)
|
||||
.send(getBot(), channel)
|
||||
)
|
||||
|
|
|
@ -34,6 +34,8 @@ import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
|||
import static sciwhiz12.janitor.commands.moderation.NoteCommand.ModeratorFilter.*;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.config.GuildConfig.ENABLE_NOTES;
|
||||
import static sciwhiz12.janitor.config.GuildConfig.MAX_NOTES_PER_MOD;
|
||||
import static sciwhiz12.janitor.msg.MessageHelper.*;
|
||||
|
||||
public class NoteCommand extends BaseCommand {
|
||||
|
@ -46,7 +48,7 @@ public class NoteCommand extends BaseCommand {
|
|||
@Override
|
||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||
return literal("note")
|
||||
.requires(ctx -> config().NOTES_ENABLE.get())
|
||||
.requires(event -> config(event).forGuild(ENABLE_NOTES))
|
||||
.then(literal("add")
|
||||
.then(argument("target", member())
|
||||
.then(argument("contents", greedyString())
|
||||
|
@ -126,7 +128,7 @@ public class NoteCommand extends BaseCommand {
|
|||
|
||||
} else {
|
||||
final NoteStorage storage = NoteStorage.get(getBot().getStorage(), guild);
|
||||
final int maxAmount = config().NOTES_MAX_AMOUNT_PER_MOD.get();
|
||||
final int maxAmount = config(ctx.getSource()).forGuild(MAX_NOTES_PER_MOD);
|
||||
if (storage.getAmountOfNotes(target.getUser()) >= maxAmount) {
|
||||
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
|
@ -201,13 +203,8 @@ public class NoteCommand extends BaseCommand {
|
|||
} else {
|
||||
messages().<Map.Entry<Integer, NoteEntry>>getListingMessage("moderation/note/list")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.amountPerPage(8)
|
||||
.setEntryApplier((entry, subs) -> subs
|
||||
.with("note_entry.note_id", () -> String.valueOf(entry.getKey()))
|
||||
.apply(user("note_entry.performer", entry.getValue().getPerformer()))
|
||||
.apply(user("note_entry.target", entry.getValue().getTarget()))
|
||||
.with("note_entry.date_time", () -> entry.getValue().getDateTime().format(DATE_TIME_FORMAT))
|
||||
.with("note_entry.contents", entry.getValue()::getContents)
|
||||
.apply(noteEntry("note_entry", entry.getKey(), entry.getValue()))
|
||||
)
|
||||
.build(channel, getBot(), ctx.getSource().getMessage(),
|
||||
NoteStorage.get(getBot().getStorage(), guild)
|
||||
|
|
|
@ -10,6 +10,7 @@ import net.dv8tion.jda.api.entities.MessageChannel;
|
|||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.config.GuildConfig;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
||||
import sciwhiz12.janitor.msg.MessageHelper;
|
||||
|
@ -20,6 +21,7 @@ import javax.annotation.Nullable;
|
|||
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.config.GuildConfig.*;
|
||||
|
||||
public class UnwarnCommand extends BaseCommand {
|
||||
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||
|
@ -31,7 +33,7 @@ public class UnwarnCommand extends BaseCommand {
|
|||
@Override
|
||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||
return literal("unwarn")
|
||||
.requires(ctx -> getBot().getConfig().WARNINGS_ENABLE.get())
|
||||
.requires(ctx -> config(ctx).forGuild(ENABLE_WARNS))
|
||||
.then(argument("caseId", IntegerArgumentType.integer(1))
|
||||
.executes(this::run)
|
||||
);
|
||||
|
@ -73,13 +75,13 @@ public class UnwarnCommand extends BaseCommand {
|
|||
.send(getBot(), channel).queue();
|
||||
|
||||
} else if (entry.getWarned().getIdLong() == performer.getIdLong()
|
||||
&& !config().WARNINGS_REMOVE_SELF_WARNINGS.get()) {
|
||||
&& !config(guild).forGuild(ALLOW_REMOVE_SELF_WARNINGS)) {
|
||||
messages().getRegularMessage("moderation/error/unwarn/cannot_unwarn_self")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(MessageHelper.warningEntry("warning_entry", caseID, entry))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
} else if (config().WARNINGS_RESPECT_MOD_ROLES.get()
|
||||
} else if (config(guild).forGuild(WARNS_RESPECT_MOD_ROLES)
|
||||
&& (temp = guild.getMember(entry.getPerformer())) != null && !performer.canInteract(temp)) {
|
||||
messages().getRegularMessage("moderation/error/unwarn/cannot_remove_higher_mod")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
|
|
|
@ -10,6 +10,7 @@ import net.dv8tion.jda.api.entities.MessageChannel;
|
|||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.config.GuildConfig;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
||||
import sciwhiz12.janitor.msg.MessageHelper;
|
||||
|
@ -26,6 +27,7 @@ import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMember
|
|||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.config.GuildConfig.ALLOW_WARN_OTHER_MODERATORS;
|
||||
|
||||
public class WarnCommand extends BaseCommand {
|
||||
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||
|
@ -37,7 +39,7 @@ public class WarnCommand extends BaseCommand {
|
|||
@Override
|
||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||
return literal("warn")
|
||||
.requires(ctx -> getBot().getConfig().WARNINGS_ENABLE.get())
|
||||
.requires(ctx -> config(ctx).forGuild(GuildConfig.ENABLE_WARNS))
|
||||
.then(argument("member", member())
|
||||
.then(argument("reason", greedyString())
|
||||
.executes(ctx -> this.run(ctx, getString(ctx, "reason")))
|
||||
|
@ -84,7 +86,7 @@ public class WarnCommand extends BaseCommand {
|
|||
.apply(MessageHelper.member("target", target))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
} else if (target.hasPermission(WARN_PERMISSION) && config().WARNINGS_PREVENT_WARNING_MODS.get()) {
|
||||
} else if (target.hasPermission(WARN_PERMISSION) && config(guild).forGuild(ALLOW_WARN_OTHER_MODERATORS)) {
|
||||
messages().getRegularMessage("moderation/error/warn/cannot_warn_mods")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(MessageHelper.member("target", target))
|
||||
|
@ -104,7 +106,7 @@ public class WarnCommand extends BaseCommand {
|
|||
.flatMap(res -> messages().getRegularMessage("moderation/warn/info")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(MessageHelper.warningEntry("warning_entry", caseId, entry))
|
||||
.with("private_message", () -> res.isSuccess() ? "✅" : "❌")
|
||||
.with("private_message", () -> res.isSuccess() ? "\u2705" : "\u274C")
|
||||
.send(getBot(), channel)
|
||||
)
|
||||
.queue();
|
||||
|
|
|
@ -26,8 +26,7 @@ import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMember
|
|||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.msg.MessageHelper.DATE_TIME_FORMAT;
|
||||
import static sciwhiz12.janitor.msg.MessageHelper.user;
|
||||
import static sciwhiz12.janitor.config.GuildConfig.ENABLE_WARNS;
|
||||
|
||||
public class WarnListCommand extends BaseCommand {
|
||||
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||
|
@ -39,7 +38,7 @@ public class WarnListCommand extends BaseCommand {
|
|||
@Override
|
||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||
return literal("warnlist")
|
||||
.requires(ctx -> getBot().getConfig().WARNINGS_ENABLE.get())
|
||||
.requires(ctx -> config(ctx).forGuild(ENABLE_WARNS))
|
||||
.then(literal("target")
|
||||
.then(argument("target", member())
|
||||
.then(literal("mod")
|
||||
|
@ -100,13 +99,8 @@ public class WarnListCommand extends BaseCommand {
|
|||
} else {
|
||||
messages().<Map.Entry<Integer, WarningEntry>>getListingMessage("moderation/warn/list")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.amountPerPage(8)
|
||||
.setEntryApplier((entry, subs) -> subs
|
||||
.with("warning_entry.case_id", () -> String.valueOf(entry.getKey()))
|
||||
.apply(user("warning_entry.performer", entry.getValue().getPerformer()))
|
||||
.apply(user("warning_entry.warned", entry.getValue().getWarned()))
|
||||
.with("warning_entry.date_time", () -> entry.getValue().getDateTime().format(DATE_TIME_FORMAT))
|
||||
.with("warning_entry.reason", entry.getValue()::getReason)
|
||||
.setEntryApplier((entry, subs) ->
|
||||
subs.apply(MessageHelper.warningEntry("warning_entry", entry.getKey(), entry.getValue()))
|
||||
)
|
||||
.build(channel, getBot(), ctx.getSource().getMessage(),
|
||||
WarningStorage.get(getBot().getStorage(), guild)
|
||||
|
|
|
@ -19,22 +19,15 @@ public class BotConfig {
|
|||
private final CommentedConfigSpec.ConfigValue<String> CLIENT_TOKEN;
|
||||
private final CommentedConfigSpec.LongValue OWNER_ID;
|
||||
|
||||
public final CommentedConfigSpec.ConfigValue<String> CONFIGS_PATH;
|
||||
|
||||
public final CommentedConfigSpec.ConfigValue<String> STORAGE_PATH;
|
||||
public final CommentedConfigSpec.IntValue AUTOSAVE_INTERVAL;
|
||||
|
||||
public final CommentedConfigSpec.ConfigValue<String> CUSTOM_TRANSLATION_FILE;
|
||||
public final CommentedConfigSpec.ConfigValue<String> CUSTOM_MESSAGES_DIRECTORY;
|
||||
|
||||
public final CommentedConfigSpec.ConfigValue<String> COMMAND_PREFIX;
|
||||
|
||||
public final CommentedConfigSpec.BooleanValue WARNINGS_ENABLE;
|
||||
public final CommentedConfigSpec.BooleanValue WARNINGS_RESPECT_MOD_ROLES;
|
||||
public final CommentedConfigSpec.BooleanValue WARNINGS_PREVENT_WARNING_MODS;
|
||||
public final CommentedConfigSpec.BooleanValue WARNINGS_REMOVE_SELF_WARNINGS;
|
||||
|
||||
public final CommentedConfigSpec.IntValue NOTES_MAX_AMOUNT_PER_MOD;
|
||||
public final CommentedConfigSpec.BooleanValue NOTES_ENABLE;
|
||||
|
||||
private final BotOptions options;
|
||||
private final Path configPath;
|
||||
private final CommentedConfigSpec spec;
|
||||
|
@ -55,6 +48,10 @@ public class BotConfig {
|
|||
.defineInRange("owner_id", 0L, Long.MIN_VALUE, Long.MAX_VALUE);
|
||||
builder.pop();
|
||||
|
||||
CONFIGS_PATH = builder
|
||||
.comment("The folder where guild configs are kept.")
|
||||
.define("configs_path", "configs");
|
||||
|
||||
builder.push("storage");
|
||||
STORAGE_PATH = builder
|
||||
.comment("The folder where per-guild storage is kept.")
|
||||
|
@ -64,10 +61,6 @@ public class BotConfig {
|
|||
.defineInRange("autosave_internal", 20, 1, Integer.MAX_VALUE);
|
||||
builder.pop();
|
||||
|
||||
CUSTOM_TRANSLATION_FILE = builder
|
||||
.comment("A file which contains custom translation keys to load for messages.",
|
||||
"If blank, no file shall be loaded.")
|
||||
.define("messages.custom_translations", "");
|
||||
CUSTOM_MESSAGES_DIRECTORY = builder
|
||||
.comment("A folder containing custom messages, with a 'messages.json' key file.",
|
||||
"If blank, no folder shall be loaded and defaults will be used.")
|
||||
|
@ -77,36 +70,6 @@ public class BotConfig {
|
|||
.comment("The prefix for commands.")
|
||||
.define("commands.prefix", "!");
|
||||
|
||||
builder.comment("Moderation settings").push("moderation");
|
||||
{
|
||||
builder.comment("Settings for the warnings system").push("warnings");
|
||||
WARNINGS_ENABLE = builder
|
||||
.comment("Whether to enable the warnings system. If disabled, the related commands are force-disabled.")
|
||||
.define("enable", true);
|
||||
WARNINGS_RESPECT_MOD_ROLES = builder
|
||||
.comment(
|
||||
"Whether to prevent lower-ranked moderators (in the role hierarchy) from removing warnings issued by " +
|
||||
"higher-ranked moderators.")
|
||||
.define("respect_mod_roles", false);
|
||||
WARNINGS_PREVENT_WARNING_MODS = builder
|
||||
.comment("Whether to prevent moderators from issuing warnings against other moderators.")
|
||||
.define("warn_other_moderators", false);
|
||||
WARNINGS_REMOVE_SELF_WARNINGS = builder
|
||||
.comment("Whether to allow moderators to remove warnings from themselves.")
|
||||
.define("remove_self_warnings", false);
|
||||
builder.pop();
|
||||
|
||||
builder.comment("Settings for the notes system").push("notes");
|
||||
NOTES_ENABLE = builder
|
||||
.comment("Whether to enable the notes system. If disabled, the related commands are force-disabled.")
|
||||
.define("enable", true);
|
||||
NOTES_MAX_AMOUNT_PER_MOD = builder
|
||||
.comment("The max amount of notes for a user per moderator.")
|
||||
.defineInRange("max_amount", Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
|
||||
builder.pop();
|
||||
}
|
||||
builder.pop();
|
||||
|
||||
spec = builder.build();
|
||||
|
||||
this.configPath = options.getConfigPath().orElse(DEFAULT_CONFIG_PATH);
|
||||
|
@ -129,15 +92,6 @@ public class BotConfig {
|
|||
return config;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Path getTranslationsFile() {
|
||||
return options.getTranslationsFile().
|
||||
or(() -> CUSTOM_TRANSLATION_FILE.get().isBlank() ?
|
||||
Optional.empty() :
|
||||
Optional.of(Path.of(CUSTOM_TRANSLATION_FILE.get())))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Path getMessagesFolder() {
|
||||
return options.getMessagesFolder().
|
||||
|
@ -147,6 +101,15 @@ public class BotConfig {
|
|||
.orElse(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Path getConfigsFolder() {
|
||||
return options.getConfigsFolder().
|
||||
or(() -> CONFIGS_PATH.get().isBlank() ?
|
||||
Optional.empty() :
|
||||
Optional.of(Path.of(CONFIGS_PATH.get())))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
return options.getToken().orElse(CLIENT_TOKEN.get());
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ import static joptsimple.util.PathProperties.*;
|
|||
public class BotOptions {
|
||||
private final OptionSet options;
|
||||
private final ArgumentAcceptingOptionSpec<Path> configPath;
|
||||
private final ArgumentAcceptingOptionSpec<Path> translationsPath;
|
||||
private final ArgumentAcceptingOptionSpec<Path> messagesFolder;
|
||||
private final ArgumentAcceptingOptionSpec<Path> configsFolder;
|
||||
private final ArgumentAcceptingOptionSpec<String> token;
|
||||
private final ArgumentAcceptingOptionSpec<String> prefix;
|
||||
private final ArgumentAcceptingOptionSpec<Long> owner;
|
||||
|
@ -25,12 +25,12 @@ public class BotOptions {
|
|||
.accepts("config", "The path to the config file; defaults to 'config.toml'")
|
||||
.withRequiredArg()
|
||||
.withValuesConvertedBy(new PathConverter(FILE_EXISTING, READABLE, WRITABLE));
|
||||
this.translationsPath = parser
|
||||
.accepts("translations", "The path to the translations file")
|
||||
.withRequiredArg()
|
||||
.withValuesConvertedBy(new PathConverter(FILE_EXISTING, READABLE));
|
||||
this.messagesFolder = parser
|
||||
.accepts("translations", "The path to the custom messages folder")
|
||||
.accepts("messages", "The path to the custom messages folder")
|
||||
.withRequiredArg()
|
||||
.withValuesConvertedBy(new PathConverter(DIRECTORY_EXISTING, READABLE));
|
||||
this.configsFolder = parser
|
||||
.accepts("guildConfigs", "The path to the guild configs folder")
|
||||
.withRequiredArg()
|
||||
.withValuesConvertedBy(new PathConverter(DIRECTORY_EXISTING, READABLE));
|
||||
this.token = parser
|
||||
|
@ -50,14 +50,14 @@ public class BotOptions {
|
|||
return configPath.valueOptional(options);
|
||||
}
|
||||
|
||||
public Optional<Path> getTranslationsFile() {
|
||||
return translationsPath.valueOptional(options);
|
||||
}
|
||||
|
||||
public Optional<Path> getMessagesFolder() {
|
||||
return messagesFolder.valueOptional(options);
|
||||
}
|
||||
|
||||
public Optional<Path> getConfigsFolder() {
|
||||
return configsFolder.valueOptional(options);
|
||||
}
|
||||
|
||||
public Optional<String> getToken() {
|
||||
return token.valueOptional(options);
|
||||
}
|
||||
|
|
44
src/main/java/sciwhiz12/janitor/config/ConfigManager.java
Normal file
44
src/main/java/sciwhiz12/janitor/config/ConfigManager.java
Normal file
|
@ -0,0 +1,44 @@
|
|||
package sciwhiz12.janitor.config;
|
||||
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public class ConfigManager {
|
||||
private final JanitorBot bot;
|
||||
private final Path configPath;
|
||||
private final Map<Long, GuildConfig> configMap = new HashMap<>();
|
||||
|
||||
public ConfigManager(JanitorBot bot, Path configPath) {
|
||||
this.bot = bot;
|
||||
this.configPath = configPath;
|
||||
}
|
||||
|
||||
public GuildConfig getConfig(long guildID) {
|
||||
return configMap.computeIfAbsent(guildID, (id) -> new GuildConfig(id, getFile(guildID)));
|
||||
}
|
||||
|
||||
public JanitorBot getBot() {
|
||||
return bot;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
configMap.values().forEach(GuildConfig::save);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
configMap.values().forEach(GuildConfig::close);
|
||||
for (Iterator<GuildConfig> iterator = configMap.values().iterator(); iterator.hasNext(); ) {
|
||||
iterator.next().close();
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
private Path getFile(long guildID) {
|
||||
final Path file = Path.of(Long.toHexString(guildID) + ".toml");
|
||||
return configPath.resolve(file);
|
||||
}
|
||||
}
|
183
src/main/java/sciwhiz12/janitor/config/GuildConfig.java
Normal file
183
src/main/java/sciwhiz12/janitor/config/GuildConfig.java
Normal file
|
@ -0,0 +1,183 @@
|
|||
package sciwhiz12.janitor.config;
|
||||
|
||||
import com.electronwill.nightconfig.core.CommentedConfig;
|
||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||
import com.electronwill.nightconfig.core.file.FileNotFoundAction;
|
||||
import com.electronwill.nightconfig.core.file.FileWatcher;
|
||||
import com.electronwill.nightconfig.toml.TomlFormat;
|
||||
import com.google.common.base.Joiner;
|
||||
import net.dv8tion.jda.api.entities.GuildChannel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static sciwhiz12.janitor.Logging.CONFIG;
|
||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||
|
||||
public class GuildConfig {
|
||||
private static final Joiner NEWLINE = Joiner.on("\n");
|
||||
|
||||
private final long guild;
|
||||
private final CommentedFileConfig config;
|
||||
private boolean closed = false;
|
||||
|
||||
public static final ConfigNode<Boolean> ENABLE = new ConfigNode<>(
|
||||
"enable", () -> true,
|
||||
"Whether the bot is enabled for this guild.",
|
||||
"Can be used to temporarily disable the bot in emergency situations.");
|
||||
|
||||
public static final ConfigNode<String> COMMAND_PREFIX = new ConfigNode<>(
|
||||
"commands.prefix", () -> "!",
|
||||
"The prefix for all commands.");
|
||||
|
||||
public static final ConfigNode<Boolean> ENABLE_WARNS = new ConfigNode<>(
|
||||
"moderation.warns.enable", () -> true,
|
||||
"Whether to enable the warnings system. If disabled, the related commands are force-disabled.");
|
||||
|
||||
public static final ConfigNode<Boolean> WARNS_RESPECT_MOD_ROLES = new ConfigNode<>(
|
||||
"moderation.warns.respect_mod_roles", () -> false,
|
||||
"Whether to prevent lower-ranked moderators (in the role hierarchy) from removing warnings " +
|
||||
"issued by higher-ranked moderators.");
|
||||
public static final ConfigNode<Boolean> ALLOW_WARN_OTHER_MODERATORS = new ConfigNode<>(
|
||||
"moderation.warns.warn_other_moderators", () -> true,
|
||||
"Whether to allow moderators to issue warnings against other moderators.");
|
||||
public static final ConfigNode<Boolean> ALLOW_REMOVE_SELF_WARNINGS = new ConfigNode<>(
|
||||
"moderation.warns.remove_self_warnings", () -> false,
|
||||
"Whether to allow moderators to remove warnings from themselves.");
|
||||
|
||||
public static final ConfigNode<Boolean> ENABLE_NOTES = new ConfigNode<>(
|
||||
"moderation.notes.enable", () -> true,
|
||||
"Whether to enable the notes system. If disabled, the related commands are force-disabled.");
|
||||
public static final ConfigNode<Integer> MAX_NOTES_PER_MOD = new ConfigNode<>(
|
||||
"moderation.notes.max_amount", () -> Integer.MAX_VALUE,
|
||||
"The max amount of notes for a user per moderator.");
|
||||
|
||||
GuildConfig(long guild, Path configPath) {
|
||||
this.guild = guild;
|
||||
this.config = CommentedFileConfig.builder(configPath, TomlFormat.instance())
|
||||
.onFileNotFound(FileNotFoundAction.CREATE_EMPTY)
|
||||
.preserveInsertionOrder()
|
||||
.autosave()
|
||||
.build();
|
||||
try {
|
||||
CONFIG.info("Building guild config for {} from {}", Long.toHexString(this.guild), configPath);
|
||||
config.load();
|
||||
FileWatcher.defaultInstance().addWatch(configPath, this::onFileChange);
|
||||
ConfigNode.nodes.forEach(this::forGuild);
|
||||
save();
|
||||
} catch (IOException ex) {
|
||||
JANITOR.error("Error while building config from file {}", configPath, ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected CommentedConfig getChannelOverrides() {
|
||||
final String channelOverridesID = "channel_overrides";
|
||||
CommentedConfig channelConfigs = config.get(channelOverridesID);
|
||||
if (channelConfigs == null) {
|
||||
channelConfigs = config.createSubConfig();
|
||||
config.set(channelOverridesID, channelConfigs);
|
||||
config.setComment(channelOverridesID, "Channel overrides for certain configuration options");
|
||||
}
|
||||
return channelConfigs;
|
||||
}
|
||||
|
||||
public CommentedConfig getChannelConfig(GuildChannel channel) {
|
||||
final String id = channel.getId();
|
||||
CommentedConfig overrides = getChannelOverrides();
|
||||
CommentedConfig channelOverride = overrides.get(id);
|
||||
if (channelOverride == null) {
|
||||
channelOverride = overrides.createSubConfig();
|
||||
overrides.set(id, channelOverride);
|
||||
overrides.setComment(id, "Channel overrides for channel with name " + channel.getName());
|
||||
}
|
||||
return channelOverride;
|
||||
}
|
||||
|
||||
private static void ensureComment(CommentedConfig config, String path, String expectedComment) {
|
||||
if (!Objects.equals(config.getComment(path), expectedComment)) {
|
||||
config.setComment(path, expectedComment);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T forGuild(ConfigNode<T> node) {
|
||||
ensureComment(config, node.path, node.comment);
|
||||
T value = config.get(node.path);
|
||||
if (value == null) {
|
||||
value = node.defaultValue.get();
|
||||
config.set(node.path, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public <T> void forGuild(ConfigNode<T> node, T newValue) {
|
||||
ensureComment(config, node.path, node.comment);
|
||||
config.set(node.path, newValue);
|
||||
}
|
||||
|
||||
public <T> T forChannel(GuildChannel channel, ConfigNode<T> node) {
|
||||
CommentedConfig channelConfig = getChannelConfig(channel);
|
||||
ensureComment(channelConfig, node.path, node.comment);
|
||||
T value = channelConfig.getRaw(node.path);
|
||||
if (value == null) {
|
||||
value = node.defaultValue.get();
|
||||
channelConfig.set(node.path, node.defaultValue.get());
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public <T> void forChannel(GuildChannel channel, ConfigNode<T> node, T newValue) {
|
||||
CommentedConfig channelConfig = getChannelConfig(channel);
|
||||
ensureComment(channelConfig, node.path, node.comment);
|
||||
channelConfig.set(node.path, newValue);
|
||||
}
|
||||
|
||||
public long getGuildID() {
|
||||
return guild;
|
||||
}
|
||||
|
||||
public CommentedFileConfig getRawConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
if (!closed) {
|
||||
config.save();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if (!closed) {
|
||||
closed = true;
|
||||
config.close();
|
||||
}
|
||||
}
|
||||
|
||||
void onFileChange() {
|
||||
if (closed) return;
|
||||
try {
|
||||
CONFIG.info("Reloading config due to file change {}", config.getNioPath());
|
||||
config.load();
|
||||
} catch (Exception ex) {
|
||||
CONFIG.error("Error while reloading config from {}", config.getNioPath(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConfigNode<T> {
|
||||
static final List<ConfigNode<?>> nodes = new ArrayList<>();
|
||||
|
||||
public final String path;
|
||||
final String comment;
|
||||
final Supplier<T> defaultValue;
|
||||
|
||||
ConfigNode(String path, Supplier<T> defaultValue, String... comment) {
|
||||
this.path = path;
|
||||
this.defaultValue = defaultValue;
|
||||
this.comment = NEWLINE.join(comment);
|
||||
nodes.add(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ import net.dv8tion.jda.api.entities.MessageEmbed;
|
|||
import sciwhiz12.janitor.JanitorBot;
|
||||
import sciwhiz12.janitor.msg.json.ListingMessage;
|
||||
import sciwhiz12.janitor.msg.substitution.CustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.IHasCustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.ICustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.SubstitutionMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -20,10 +20,10 @@ import java.util.function.Consumer;
|
|||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ListingMessageBuilder<T> implements IHasCustomSubstitutions<ListingMessageBuilder<T>> {
|
||||
public class ListingMessageBuilder<T> implements ICustomSubstitutions<ListingMessageBuilder<T>> {
|
||||
private final ListingMessage message;
|
||||
private final Map<String, Supplier<String>> customSubstitutions;
|
||||
private int amountPerPage = 10;
|
||||
private int amountPerPage = 6;
|
||||
private BiConsumer<T, CustomSubstitutions> entryApplier = (entry, sub) -> {};
|
||||
|
||||
public ListingMessageBuilder(ListingMessage message, Map<String, Supplier<String>> customSubstitutions) {
|
||||
|
@ -55,22 +55,24 @@ public class ListingMessageBuilder<T> implements IHasCustomSubstitutions<Listing
|
|||
return this;
|
||||
}
|
||||
|
||||
public void build(MessageChannel channel, TranslationMap translations, SubstitutionMap globalSubstitutions,
|
||||
Message triggerMessage, List<T> entries) {
|
||||
public void build(MessageChannel channel,
|
||||
SubstitutionMap globalSubstitutions,
|
||||
Message triggerMessage,
|
||||
List<T> entries) {
|
||||
|
||||
final CustomSubstitutions customSubs = globalSubstitutions.with(customSubstitutions);
|
||||
final ImmutableList<T> list = ImmutableList.copyOf(entries);
|
||||
final PagedMessage pagedMessage = new PagedMessage(message, list, amountPerPage);
|
||||
|
||||
channel.sendMessage(pagedMessage.createMessage(translations, customSubs, entryApplier))
|
||||
.queue(listMsg -> translations.getBot().getReactionManager().newMessage(listMsg)
|
||||
channel.sendMessage(pagedMessage.createMessage(customSubs, entryApplier))
|
||||
.queue(listMsg -> globalSubstitutions.getBot().getReactionManager().newMessage(listMsg)
|
||||
.owner(triggerMessage.getAuthor().getIdLong())
|
||||
.removeEmotes(true)
|
||||
.add("\u2b05", (msg, event) -> { // PREVIOUS
|
||||
if (pagedMessage.advancePage(PageDirection.PREVIOUS)) {
|
||||
event.retrieveMessage()
|
||||
.flatMap(eventMsg -> eventMsg.editMessage(
|
||||
pagedMessage.createMessage(translations, customSubs, entryApplier))
|
||||
pagedMessage.createMessage(customSubs, entryApplier))
|
||||
)
|
||||
.queue();
|
||||
}
|
||||
|
@ -88,7 +90,7 @@ public class ListingMessageBuilder<T> implements IHasCustomSubstitutions<Listing
|
|||
if (pagedMessage.advancePage(PageDirection.NEXT)) {
|
||||
event.retrieveMessage()
|
||||
.flatMap(eventMsg -> eventMsg.editMessage(
|
||||
pagedMessage.createMessage(translations, customSubs, entryApplier))
|
||||
pagedMessage.createMessage(customSubs, entryApplier))
|
||||
)
|
||||
.queue();
|
||||
}
|
||||
|
@ -98,7 +100,7 @@ public class ListingMessageBuilder<T> implements IHasCustomSubstitutions<Listing
|
|||
}
|
||||
|
||||
public void build(MessageChannel channel, JanitorBot bot, Message triggerMessage, List<T> entries) {
|
||||
build(channel, bot.getTranslations(), bot.getSubstitutions(), triggerMessage, entries);
|
||||
build(channel, bot.getSubstitutions(), triggerMessage, entries);
|
||||
}
|
||||
|
||||
class PagedMessage {
|
||||
|
@ -136,11 +138,10 @@ public class ListingMessageBuilder<T> implements IHasCustomSubstitutions<Listing
|
|||
return false;
|
||||
}
|
||||
|
||||
public MessageEmbed createMessage(TranslationMap translations, CustomSubstitutions substitutions,
|
||||
public MessageEmbed createMessage(CustomSubstitutions substitutions,
|
||||
BiConsumer<T, CustomSubstitutions> applier) {
|
||||
if (currentPage != lastPage) {
|
||||
cachedMessage = message.create(
|
||||
translations,
|
||||
substitutions.with(new HashMap<>())
|
||||
.with("page.max", () -> String.valueOf(maxPages + 1))
|
||||
.with("page.current", () -> String.valueOf(currentPage + 1)),
|
||||
|
|
|
@ -8,10 +8,11 @@ import net.dv8tion.jda.api.entities.Role;
|
|||
import net.dv8tion.jda.api.entities.User;
|
||||
import sciwhiz12.janitor.moderation.notes.NoteEntry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||
import sciwhiz12.janitor.msg.substitution.IHasCustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.ICustomSubstitutions;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static java.time.temporal.ChronoField.*;
|
||||
|
@ -19,19 +20,19 @@ import static java.time.temporal.ChronoField.*;
|
|||
public class MessageHelper {
|
||||
private MessageHelper() {}
|
||||
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> snowflake(String head, ISnowflake snowflake) {
|
||||
public static <T extends ICustomSubstitutions<?>> Consumer<T> snowflake(String head, ISnowflake snowflake) {
|
||||
return builder -> builder
|
||||
.with(head + ".id", snowflake::getId)
|
||||
.with(head + ".creation_datetime", () -> snowflake.getTimeCreated().format(DATE_TIME_FORMAT));
|
||||
}
|
||||
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> mentionable(String head, IMentionable mentionable) {
|
||||
return builder -> builder
|
||||
public static <T extends ICustomSubstitutions<?>> Consumer<T> mentionable(String head, IMentionable mentionable) {
|
||||
return builder -> builder
|
||||
.apply(snowflake(head, mentionable))
|
||||
.with(head + ".mention", mentionable::getAsMention);
|
||||
}
|
||||
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> role(String head, Role role) {
|
||||
public static <T extends ICustomSubstitutions<?>> Consumer<T> role(String head, Role role) {
|
||||
return builder -> builder
|
||||
.apply(mentionable(head, role))
|
||||
.with(head + ".color_hex", () -> Integer.toHexString(role.getColorRaw()))
|
||||
|
@ -39,7 +40,7 @@ public class MessageHelper {
|
|||
.with(head + ".permissions", role.getPermissions()::toString);
|
||||
}
|
||||
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> user(String head, User user) {
|
||||
public static <T extends ICustomSubstitutions<?>> Consumer<T> user(String head, User user) {
|
||||
return builder -> builder
|
||||
.apply(mentionable(head, user))
|
||||
.with(head + ".name", user::getName)
|
||||
|
@ -48,7 +49,7 @@ public class MessageHelper {
|
|||
.with(head + ".flags", user.getFlags()::toString);
|
||||
}
|
||||
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> guild(String head, Guild guild) {
|
||||
public static <T extends ICustomSubstitutions<?>> Consumer<T> guild(String head, Guild guild) {
|
||||
return builder -> builder
|
||||
.apply(snowflake(head, guild))
|
||||
.with(head + ".name", guild::getName)
|
||||
|
@ -58,10 +59,10 @@ public class MessageHelper {
|
|||
.with(head + ".boost.count", () -> String.valueOf(guild.getBoostCount()))
|
||||
.with(head + ".locale", guild.getLocale()::toString)
|
||||
.with(head + ".verification_level", guild.getVerificationLevel()::toString)
|
||||
.with(head + ".icon_url", guild::getIconUrl);
|
||||
.with(head + ".icon_url", () -> Objects.toString(guild.getIconUrl(), ""));
|
||||
}
|
||||
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> member(String head, Member member) {
|
||||
public static <T extends ICustomSubstitutions<?>> Consumer<T> member(String head, Member member) {
|
||||
return builder -> builder
|
||||
.apply(user(head, member.getUser()))
|
||||
.apply(guild(head + ".guild", member.getGuild()))
|
||||
|
@ -71,7 +72,7 @@ public class MessageHelper {
|
|||
.with(head + ".color", () -> String.valueOf(member.getColorRaw()));
|
||||
}
|
||||
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> warningEntry(String head, int caseID, WarningEntry entry) {
|
||||
public static <T extends ICustomSubstitutions<?>> Consumer<T> warningEntry(String head, int caseID, WarningEntry entry) {
|
||||
return builder -> builder
|
||||
.with(head + ".case_id", () -> String.valueOf(caseID))
|
||||
.apply(user(head + ".performer", entry.getPerformer()))
|
||||
|
@ -80,7 +81,7 @@ public class MessageHelper {
|
|||
.with(head + ".reason", entry::getReason);
|
||||
}
|
||||
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> noteEntry(String head, int noteID, NoteEntry entry) {
|
||||
public static <T extends ICustomSubstitutions<?>> Consumer<T> noteEntry(String head, int noteID, NoteEntry entry) {
|
||||
return builder -> builder
|
||||
.with(head + ".note_id", () -> String.valueOf(noteID))
|
||||
.apply(user(head + ".performer", entry.getPerformer()))
|
||||
|
|
|
@ -127,8 +127,8 @@ public class Messages {
|
|||
public static final RegularMessage UNKNOWN_REGULAR_MESSAGE = new RegularMessage(
|
||||
"UNKNOWN MESSAGE!",
|
||||
null,
|
||||
"A regular message was tried to be looked up, but was not found. Please report this to your bot " +
|
||||
"maintainer/administrator.",
|
||||
"A regular message was tried to be looked up, but was not found. " +
|
||||
"Please report this to your bot maintainer/administrator.",
|
||||
String.valueOf(0xFF0000),
|
||||
null,
|
||||
null,
|
||||
|
|
|
@ -5,7 +5,7 @@ import net.dv8tion.jda.api.entities.MessageEmbed;
|
|||
import net.dv8tion.jda.api.requests.restaction.MessageAction;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
import sciwhiz12.janitor.msg.json.RegularMessage;
|
||||
import sciwhiz12.janitor.msg.substitution.IHasCustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.ICustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.SubstitutionMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -13,7 +13,7 @@ import java.util.Map;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class RegularMessageBuilder implements IHasCustomSubstitutions<RegularMessageBuilder> {
|
||||
public class RegularMessageBuilder implements ICustomSubstitutions<RegularMessageBuilder> {
|
||||
private final RegularMessage message;
|
||||
private final Map<String, Supplier<String>> customSubstitutions;
|
||||
|
||||
|
@ -26,10 +26,6 @@ public class RegularMessageBuilder implements IHasCustomSubstitutions<RegularMes
|
|||
this(message, new HashMap<>());
|
||||
}
|
||||
|
||||
public RegularMessageBuilder(RegularMessageBuilder copy) {
|
||||
this(copy.message, new HashMap<>(copy.customSubstitutions));
|
||||
}
|
||||
|
||||
public RegularMessageBuilder apply(Consumer<RegularMessageBuilder> consumer) {
|
||||
consumer.accept(this);
|
||||
return this;
|
||||
|
@ -40,12 +36,12 @@ public class RegularMessageBuilder implements IHasCustomSubstitutions<RegularMes
|
|||
return this;
|
||||
}
|
||||
|
||||
public MessageEmbed build(TranslationMap translations, SubstitutionMap substitutions) {
|
||||
return message.create(translations, substitutions.with(customSubstitutions)).build();
|
||||
public MessageEmbed build(SubstitutionMap substitutions) {
|
||||
return message.create(substitutions.with(customSubstitutions)).build();
|
||||
}
|
||||
|
||||
public MessageEmbed build(JanitorBot bot) {
|
||||
return build(bot.getTranslations(), bot.getSubstitutions());
|
||||
return build(bot.getSubstitutions());
|
||||
}
|
||||
|
||||
public MessageAction send(JanitorBot bot, MessageChannel channel) {
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
package sciwhiz12.janitor.msg;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.io.Resources;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
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;
|
||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.Logging.TRANSLATIONS;
|
||||
|
||||
public class TranslationMap {
|
||||
public static final Pattern TRANSLATION_REGEX = Pattern.compile("<(.+?)>", CASE_INSENSITIVE);
|
||||
private static final String DEFAULT_TRANSLATIONS_RESOURCE = "english.json";
|
||||
private static final TypeReference<Map<String, String>> MAP_TYPE = new TypeReference<>() {};
|
||||
|
||||
private final JanitorBot bot;
|
||||
private final Path translationsFile;
|
||||
private final Map<String, String> translations = new HashMap<>();
|
||||
private final ObjectMapper jsonMapper = new ObjectMapper();
|
||||
|
||||
public TranslationMap(JanitorBot bot, Path translationsFile) {
|
||||
this.bot = bot;
|
||||
this.translationsFile = translationsFile;
|
||||
loadTranslations();
|
||||
}
|
||||
|
||||
public void loadTranslations() {
|
||||
if (translationsFile == null) {
|
||||
JANITOR.info(TRANSLATIONS, "No translation file given, using default english translations");
|
||||
loadDefaultTranslations();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
JANITOR.debug(TRANSLATIONS, "Loading translations from file {}", translationsFile);
|
||||
Map<String, String> trans = jsonMapper.readValue(Files.newBufferedReader(translationsFile), MAP_TYPE);
|
||||
translations.clear();
|
||||
translations.putAll(trans);
|
||||
JANITOR.info(TRANSLATIONS, "Loaded {} translations from file {}", translations.size(), translationsFile);
|
||||
} catch (Exception e) {
|
||||
JANITOR.error(TRANSLATIONS, "Error while loading translations from file {}", translationsFile, e);
|
||||
loadDefaultTranslations();
|
||||
}
|
||||
}
|
||||
|
||||
void loadDefaultTranslations() {
|
||||
try {
|
||||
JANITOR.debug(TRANSLATIONS, "Loading default english translations");
|
||||
// noinspection UnstableApiUsage
|
||||
Map<String, String> trans = jsonMapper.readValue(
|
||||
new InputStreamReader(Resources.getResource(DEFAULT_TRANSLATIONS_RESOURCE).openStream()),
|
||||
MAP_TYPE);
|
||||
translations.clear();
|
||||
translations.putAll(trans);
|
||||
JANITOR.info(TRANSLATIONS, "Loaded {} default english translations", translations.size());
|
||||
} catch (Exception e) {
|
||||
JANITOR.error(TRANSLATIONS, "Error while loading default english translations", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> getTranslationMap() {
|
||||
return Collections.unmodifiableMap(translations);
|
||||
}
|
||||
|
||||
public String translate(String text) {
|
||||
final Matcher matcher = TRANSLATION_REGEX.matcher(text);
|
||||
return matcher.replaceAll(
|
||||
matchResult -> quoteReplacement(translations.getOrDefault(matchResult.group(1), matchResult.group(0))));
|
||||
}
|
||||
|
||||
public JanitorBot getBot() {
|
||||
return bot;
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ import joptsimple.internal.Strings;
|
|||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import sciwhiz12.janitor.msg.TranslationMap;
|
||||
import sciwhiz12.janitor.msg.substitution.CustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.ISubstitutor;
|
||||
|
||||
|
@ -142,27 +141,25 @@ public class ListingMessage {
|
|||
}
|
||||
|
||||
public <T> EmbedBuilder create(
|
||||
TranslationMap translations,
|
||||
ISubstitutor global,
|
||||
Iterable<T> iterable,
|
||||
BiConsumer<T, CustomSubstitutions> entryApplier
|
||||
) {
|
||||
final Function<String, String> func = str -> str != null ? global.substitute(translations.translate(str)) : null;
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.setTitle(func.apply(title), func.apply(url));
|
||||
builder.setTitle(global.substitute(title), global.substitute(url));
|
||||
builder.setColor(parseColor(global.substitute(color)));
|
||||
builder.setAuthor(func.apply(authorName), func.apply(authorUrl), func.apply(authorIconUrl));
|
||||
builder.setDescription(func.apply(description));
|
||||
builder.setImage(func.apply(imageUrl));
|
||||
builder.setThumbnail(func.apply(thumbnailUrl));
|
||||
builder.setAuthor(global.substitute(authorName), global.substitute(authorUrl), global.substitute(authorIconUrl));
|
||||
builder.setDescription(global.substitute(description));
|
||||
builder.setImage(global.substitute(imageUrl));
|
||||
builder.setThumbnail(global.substitute(thumbnailUrl));
|
||||
builder.setTimestamp(OffsetDateTime.now(ZoneOffset.UTC));
|
||||
builder.setFooter(func.apply(footerText), func.apply(footerIconUrl));
|
||||
builder.setFooter(global.substitute(footerText), global.substitute(footerIconUrl));
|
||||
for (MessageEmbed.Field field : beforeFields) {
|
||||
builder.addField(func.apply(field.getName()), func.apply(field.getValue()), field.isInline());
|
||||
builder.addField(global.substitute(field.getName()), global.substitute(field.getValue()), field.isInline());
|
||||
}
|
||||
|
||||
final CustomSubstitutions entrySubs = new CustomSubstitutions();
|
||||
final Function<String, String> entryFunc = str -> str != null ? entrySubs.substitute(func.apply(str)) : null;
|
||||
final Function<String, String> entryFunc = str -> str != null ? entrySubs.substitute(global.substitute(str)) : null;
|
||||
int count = 0;
|
||||
for (T listEntry : iterable) {
|
||||
entryApplier.accept(listEntry, entrySubs);
|
||||
|
@ -181,11 +178,11 @@ public class ListingMessage {
|
|||
count++;
|
||||
}
|
||||
if (count < 1) {
|
||||
builder.getDescriptionBuilder().append(func.apply(emptyText));
|
||||
builder.getDescriptionBuilder().append(global.substitute(emptyText));
|
||||
}
|
||||
|
||||
for (MessageEmbed.Field field : afterFields) {
|
||||
builder.addField(func.apply(field.getName()), func.apply(field.getValue()), field.isInline());
|
||||
builder.addField(global.substitute(field.getName()), global.substitute(field.getValue()), field.isInline());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import joptsimple.internal.Strings;
|
|||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import sciwhiz12.janitor.msg.TranslationMap;
|
||||
import sciwhiz12.janitor.msg.substitution.ISubstitutor;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
|
@ -16,7 +15,6 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@JsonDeserialize(using = RegularMessageDeserializer.class)
|
||||
|
@ -176,19 +174,18 @@ public class RegularMessage {
|
|||
thumbnailUrl, fields);
|
||||
}
|
||||
|
||||
public EmbedBuilder create(TranslationMap translations, ISubstitutor substitutions) {
|
||||
final Function<String, String> func = str -> str != null ? substitutions.substitute(translations.translate(str)) : null;
|
||||
public EmbedBuilder create(ISubstitutor subs) {
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.setTitle(func.apply(title), func.apply(url));
|
||||
builder.setColor(parseColor(substitutions.substitute(color)));
|
||||
builder.setAuthor(func.apply(authorName), func.apply(authorUrl), func.apply(authorIconUrl));
|
||||
builder.setDescription(func.apply(description));
|
||||
builder.setImage(func.apply(imageUrl));
|
||||
builder.setThumbnail(func.apply(thumbnailUrl));
|
||||
builder.setTitle(subs.substitute(title), subs.substitute(url));
|
||||
builder.setColor(parseColor(subs.substitute(color)));
|
||||
builder.setAuthor(subs.substitute(authorName), subs.substitute(authorUrl), subs.substitute(authorIconUrl));
|
||||
builder.setDescription(subs.substitute(description));
|
||||
builder.setImage(subs.substitute(imageUrl));
|
||||
builder.setThumbnail(subs.substitute(thumbnailUrl));
|
||||
builder.setTimestamp(OffsetDateTime.now(ZoneOffset.UTC));
|
||||
builder.setFooter(func.apply(footerText), func.apply(footerIconUrl));
|
||||
builder.setFooter(subs.substitute(footerText), subs.substitute(footerIconUrl));
|
||||
for (MessageEmbed.Field field : fields) {
|
||||
builder.addField(func.apply(field.getName()), func.apply(field.getValue()), field.isInline());
|
||||
builder.addField(subs.substitute(field.getName()), subs.substitute(field.getValue()), field.isInline());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
|
|
@ -7,8 +7,9 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class CustomSubstitutions implements ISubstitutor, IHasCustomSubstitutions<CustomSubstitutions> {
|
||||
public class CustomSubstitutions implements ISubstitutor, ICustomSubstitutions<CustomSubstitutions> {
|
||||
private final Map<String, Supplier<String>> map;
|
||||
|
||||
public CustomSubstitutions(Map<String, Supplier<String>> map) {
|
||||
|
@ -20,7 +21,8 @@ public class CustomSubstitutions implements ISubstitutor, IHasCustomSubstitution
|
|||
}
|
||||
|
||||
@Override
|
||||
public String substitute(String text) {
|
||||
@Nullable
|
||||
public String substitute(@Nullable String text) {
|
||||
return SubstitutionMap.substitute(text, map);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ package sciwhiz12.janitor.msg.substitution;
|
|||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface IHasCustomSubstitutions<T extends IHasCustomSubstitutions<?>> {
|
||||
public interface ICustomSubstitutions<T extends ICustomSubstitutions<?>> {
|
||||
T with(String argument, Supplier<String> value);
|
||||
|
||||
T apply(Consumer<T> consumer);
|
|
@ -1,5 +1,8 @@
|
|||
package sciwhiz12.janitor.msg.substitution;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface ISubstitutor {
|
||||
String substitute(String text);
|
||||
@Nullable
|
||||
String substitute(@Nullable String text);
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ import java.util.Map;
|
|||
import java.util.function.Supplier;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static java.util.regex.Matcher.quoteReplacement;
|
||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||
import static sciwhiz12.janitor.msg.MessageHelper.DATE_TIME_FORMAT;
|
||||
|
||||
|
@ -20,18 +20,24 @@ public class SubstitutionMap implements ISubstitutor {
|
|||
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<String, Supplier<String>> arguments) {
|
||||
private static String quote(@Nullable String input) {
|
||||
return input != null ? Matcher.quoteReplacement(input) : "";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String substitute(@Nullable String text, Map<String, Supplier<String>> arguments) {
|
||||
if (text == null || text.isBlank()) return null;
|
||||
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 grp1 = nullMatcher.group(1);
|
||||
final String str = arguments.containsKey(grp1) ? arguments.get(grp1).get() : null;
|
||||
return str != null ?
|
||||
quoteReplacement(str) :
|
||||
quoteReplacement(arguments.getOrDefault(nullMatcher.group(2), () -> nullMatcher.group(2)).get());
|
||||
return quote(arguments.getOrDefault(
|
||||
grp1,
|
||||
() -> arguments.getOrDefault(nullMatcher.group(2), () -> nullMatcher.group(2)).get()
|
||||
).get());
|
||||
}
|
||||
return quoteReplacement(arguments.getOrDefault(matchResult.group(1), () -> matchResult.group(0)).get());
|
||||
return quote(arguments.getOrDefault(matchResult.group(1), () -> matchResult.group(0)).get());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -51,7 +57,8 @@ public class SubstitutionMap implements ISubstitutor {
|
|||
return bot;
|
||||
}
|
||||
|
||||
public String substitute(String text) {
|
||||
@Nullable
|
||||
public String substitute(@Nullable String text) {
|
||||
return SubstitutionMap.substitute(text, defaultSubstitutions);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
{
|
||||
"general.error.guild_only_command.title": "Guild only command!",
|
||||
"general.error.guild_only_command.description": "This command can only be run in a guild channel.",
|
||||
"general.error.ambiguous_member.title": "Ambiguous member argument!",
|
||||
"general.error.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.error.insufficient_permissions.title": "I have insufficient permissions!",
|
||||
"general.error.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.error.insufficient_permissions.field.permissions": "Required permissions",
|
||||
"general.error.cannot_interact.title": "Member is higher than me!",
|
||||
"general.error.cannot_interact.description": "Cannot perform action on the given member, likely due to me being lower in the role hierarchy.",
|
||||
"general.error.cannot_interact.field.target": "Target",
|
||||
"general.error.cannot_action_self.title": "Cannot act against myself!",
|
||||
"general.error.cannot_action_self.description": "Cannot perform action against myself, as that would be counter-intuitive.",
|
||||
"general.error.cannot_action_performer.title": "Performer cannot act against self!",
|
||||
"general.error.cannot_action_performer.description": "You cannot perform this action against yourself.",
|
||||
"general.error.cannot_action_performer.field.performer": "Performer/Target",
|
||||
"moderation.insufficient_permissions.title": "Insufficient permissions.",
|
||||
"moderation.insufficient_permissions.description": "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.cannot_interact.title": "Cannot moderate 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": "Performer",
|
||||
"moderation.cannot_interact.field.target": "Target",
|
||||
"moderation.kick.info.author": "Kicked user from server.",
|
||||
"moderation.kick.info.field.performer": "Performer",
|
||||
"moderation.kick.info.field.target": "Target",
|
||||
"moderation.kick.info.field.private_message": "Sent DM",
|
||||
"moderation.kick.info.field.reason.name": "Reason",
|
||||
"moderation.kick.info.field.reason.value": "${nullcheck;reason;_No reason specified._}",
|
||||
"moderation.kick.dm.title": "You were kicked from this server.",
|
||||
"moderation.kick.dm.field.performer": "Moderator",
|
||||
"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.private_message": "Sent DM",
|
||||
"moderation.ban.info.field.delete_duration.name": "Message Deletion",
|
||||
"moderation.ban.info.field.delete_duration.value": "${delete_duration} day(s)",
|
||||
"moderation.ban.info.field.reason.name": "Reason",
|
||||
"moderation.ban.info.field.reason.value": "${nullcheck;reason;_No reason specified._}",
|
||||
"moderation.ban.dm.title": "You were banned from this server.",
|
||||
"moderation.ban.dm.field.performer": "Moderator",
|
||||
"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.warn.info.author": "Warned user.",
|
||||
"moderation.warn.info.field.performer": "Performer",
|
||||
"moderation.warn.info.field.target": "Target",
|
||||
"moderation.warn.info.field.case_id": "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 DM",
|
||||
"moderation.warn.info.field.date_time": "Date & Time",
|
||||
"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.name": "Reason",
|
||||
"moderation.warn.dm.field.reason.value": "${nullcheck;warning_entry.reason;_No reason specified._}",
|
||||
"moderation.unwarn.info.author": "Removed warning from user.",
|
||||
"moderation.unwarn.info.field.performer": "Performer",
|
||||
"moderation.unwarn.info.field.original_target": "Original Target",
|
||||
"moderation.unwarn.info.field.original_performer": "Original Performer",
|
||||
"moderation.unwarn.info.field.case_id": "Case ID",
|
||||
"moderation.unwarn.info.field.date_time": "Date & Time",
|
||||
"moderation.unwarn.info.field.reason.name": "Reason",
|
||||
"moderation.unwarn.info.field.reason.value": "${nullcheck;warning_entry.reason;_No reason specified._}",
|
||||
"moderation.unwarn.no_case_found.title": "No warning found.",
|
||||
"moderation.unwarn.no_case_found.description": "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.cannot_unwarn_self.title": "Cannot remove warning from self.",
|
||||
"moderation.unwarn.cannot_unwarn_self.description": "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.warn.cannot_warn_mods.title": "Cannot warn moderators.",
|
||||
"moderation.warn.cannot_warn_mods.description": "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_remove_higher_mod.title": "Cannot remove warning issued by higher-ranked moderator.",
|
||||
"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": "Performer",
|
||||
"moderation.warn.cannot_remove_higher_mod.field.original_performer": "Original Performer",
|
||||
"moderation.warn.cannot_remove_higher_mod.field.case_id": "Case ID",
|
||||
"moderation.note.max_amount_of_notes.title": "Max notes reached.",
|
||||
"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": "Performer",
|
||||
"moderation.note.max_amount_of_notes.field.target": "Target",
|
||||
"moderation.note.max_amount_of_notes.field.amount": "(Max.) Amount",
|
||||
"moderation.note.no_note_found.title": "No note found.",
|
||||
"moderation.note.no_note_found.description": "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.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.remove.author": "Removed note.",
|
||||
"moderation.note.remove.field.performer": "Performer",
|
||||
"moderation.note.remove.field.original_performer": "Original Performer",
|
||||
"moderation.note.remove.field.original_target": "Original Target",
|
||||
"moderation.note.remove.field.note_id": "Note ID",
|
||||
"moderation.note.remove.field.date_time": "Date & Time",
|
||||
"moderation.note.remove.field.contents": "Text",
|
||||
"moderation.warnlist.author": "Listing of Warnings",
|
||||
"moderation.warnlist.empty": "**_No warnings logged matching your query._**",
|
||||
"moderation.warnlist.entry": "**Case #${warning_entry.case_id}**: Warned ${warning_entry.warned.mention} by ${warning_entry.performer.mention} \n - _Date & Time:_ ${warning_entry.date_time} \n - _Reason:_ ${nullcheck;warning_entry.reason;_No reason specified._}",
|
||||
"moderation.note.list.author": "Listing of Notes (Page ${page.current}/${page.max})",
|
||||
"moderation.note.list.empty": "**_No recorded notes matching your query._**",
|
||||
"moderation.note.list.entry": "**#${note_entry.note_id}**: for ${note_entry.target.mention} by ${note_entry.performer.mention} \n - _Date & Time:_ ${note_entry.date_time} \n - _Text:_ ${note_entry.contents}"
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<general.error.ambiguous_member.title>",
|
||||
"description": "<general.error.ambiguous_member.description>"
|
||||
"title": "Ambiguous member argument!",
|
||||
"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."
|
||||
}
|
|
@ -1,12 +1,4 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<general.error.cannot_action_performer.title>",
|
||||
"description": "<general.error.cannot_action_performer.description>",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<general.error.cannot_action_performer.field.performer>",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
}
|
||||
]
|
||||
"title": "Performer cannot act against self."
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<general.error.cannot_action_self.title>",
|
||||
"description": "<general.error.cannot_action_self.description>"
|
||||
"title": "Cannot perform this action against myself."
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<general.error.cannot_interact.title>",
|
||||
"description": "<general.error.cannot_interact.description>",
|
||||
"description": "Cannot perform action on the given member, likely due to me being lower in the role hierarchy.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<general.error.cannot_interact.field.target>",
|
||||
"name": "Target",
|
||||
"value": "${target.mention}",
|
||||
"inline": true
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<general.error.guild_only_command.title>",
|
||||
"description": "<general.error.guild_only_command.description>"
|
||||
"title": "Guild only command!"
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<general.error.insufficient_permissions.title>",
|
||||
"description": "<general.error.insufficient_permissions.description>",
|
||||
"description": "I do not have sufficient permissions to carry out this action.\nPlease contact your server administrators if you believe this is in error.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<general.error.insufficient_permissions.field.permissions>",
|
||||
"name": "Required permissions",
|
||||
"value": "${required_permissions}",
|
||||
"inline": true
|
||||
}
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
"name": "${performer.guild.name}",
|
||||
"icon_url": "${performer.guild.icon_url}"
|
||||
},
|
||||
"title": "<moderation.ban.dm.title>",
|
||||
"title": "You were banned from this server.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.ban.dm.field.performer>",
|
||||
"name": "Moderator",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.ban.dm.field.reason.name>",
|
||||
"value": "<moderation.ban.dm.field.reason.value>",
|
||||
"name": "Reason",
|
||||
"value": "${nullcheck;reason;_No reason specified._}",
|
||||
"inline": true
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,33 +1,33 @@
|
|||
{
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "<moderation.ban.info.author>",
|
||||
"name": "Banned user from server.",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.ban.info.field.performer>",
|
||||
"name": "Performer",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.ban.info.field.target>",
|
||||
"name": "Target",
|
||||
"value": "${target.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.ban.info.field.private_message>",
|
||||
"name": "Sent DM",
|
||||
"value": "${private_message}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.ban.info.field.delete_duration.name>",
|
||||
"value": "<moderation.ban.info.field.delete_duration.value>",
|
||||
"name": "Message Deletion",
|
||||
"value": "${delete_duration} day(s)",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.ban.info.field.reason.name>",
|
||||
"value": "<moderation.ban.info.field.reason.value>",
|
||||
"name": "Reason",
|
||||
"value": "${nullcheck;reason;_No reason specified._}",
|
||||
"inline": false
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<moderation.cannot_interact.title>",
|
||||
"description": "<moderation.cannot_interact.description>",
|
||||
"description": "The performer of this command cannot moderate the target user, likely due to being lower in the role hierarchy.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.cannot_interact.field.performer>",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.cannot_interact.field.target>",
|
||||
"name": "Target",
|
||||
"value": "${target.mention}",
|
||||
"inline": true
|
||||
}
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<moderation.insufficient_permissions.title>",
|
||||
"description": "<moderation.insufficient_permissions.description>",
|
||||
"description": "The performer of this command has insufficient permissions to use this command.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.insufficient_permissions.field.performer>",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.insufficient_permissions.field.permissions>",
|
||||
"name": "Required permissions",
|
||||
"value": "${required_permissions}",
|
||||
"inline": true
|
||||
}
|
||||
|
|
|
@ -1,20 +1,14 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<moderation.note.max_amount_of_notes.title>",
|
||||
"description": "<moderation.note.max_amount_of_notes.description>",
|
||||
"description": "The performer has reached the maximum amount of notes for the target user.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.note.max_amount_of_notes.field.performer>",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.note.max_amount_of_notes.field.target>",
|
||||
"name": "Target",
|
||||
"value": "${target.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.note.max_amount_of_notes.field.amount>",
|
||||
"name": "(Max.) Amount",
|
||||
"value": "${notes_amount}",
|
||||
"inline": true
|
||||
}
|
||||
|
|
|
@ -1,17 +1,4 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<moderation.note.no_note_found.title>",
|
||||
"description": "<moderation.note.no_note_found.description>",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.note.no_note_found.field.performer>",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.note.no_note_found.field.note_id>",
|
||||
"value": "${note_id}",
|
||||
"inline": true
|
||||
}
|
||||
]
|
||||
"description": "No note with that note ID was found."
|
||||
}
|
|
@ -1,22 +1,16 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<moderation.warn.cannot_remove_higher_mod.title>",
|
||||
"description": "<moderation.warn.cannot_remove_higher_mod.description>",
|
||||
"title": "Cannot remove warning issued by higher-ranked moderator.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.warn.cannot_remove_higher_mod.field.performer>",
|
||||
"name": "Performer",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.warn.cannot_remove_higher_mod.field.original_performer>",
|
||||
"name": "Issuer",
|
||||
"value": "${warning_entry.performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.warn.cannot_remove_higher_mod.field.case_id>",
|
||||
"value": "${warning_entry.case_id}",
|
||||
"inline": true
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,22 +1,16 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<moderation.unwarn.cannot_unwarn_self.title>",
|
||||
"description": "<moderation.unwarn.cannot_unwarn_self.description>",
|
||||
"title": "Cannot remove warning from self.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.unwarn.cannot_unwarn_self.field.performer>",
|
||||
"name": "Performer/Target",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.unwarn.cannot_unwarn_self.field.original_performer>",
|
||||
"name": "Issuer",
|
||||
"value": "${warning_entry.performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.unwarn.cannot_unwarn_self.field.case_id>",
|
||||
"value": "${warning_entry.case_id}",
|
||||
"inline": true
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,17 +1,4 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<moderation.unwarn.no_case_found.title>",
|
||||
"description": "<moderation.unwarn.no_case_found.description>",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.unwarn.no_case_found.field.performer>",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.unwarn.no_case_found.field.case_id>",
|
||||
"value": "${case_id}",
|
||||
"inline": true
|
||||
}
|
||||
]
|
||||
"description": "No warning with that case ID was found."
|
||||
}
|
|
@ -1,15 +1,9 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "<moderation.warn.cannot_warn_mods.title>",
|
||||
"description": "<moderation.warn.cannot_warn_mods.description>",
|
||||
"title": "Cannot warn other moderators.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.warn.cannot_warn_mods.field.performer>",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.warn.cannot_warn_mods.field.target>",
|
||||
"name": "Target",
|
||||
"value": "${target.mention}",
|
||||
"inline": true
|
||||
}
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
"name": "${performer.guild.name}",
|
||||
"icon_url": "${performer.guild.icon_url}"
|
||||
},
|
||||
"title": "<moderation.kick.dm.title>",
|
||||
"title": "You were kicked from this server.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.kick.dm.field.performer>",
|
||||
"name": "Moderator",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.kick.dm.field.reason.name>",
|
||||
"value": "<moderation.kick.dm.field.reason.value>",
|
||||
"name": "Reason",
|
||||
"value": "${nullcheck;reason;_No reason specified._}",
|
||||
"inline": true
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
{
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "<moderation.kick.info.author>",
|
||||
"name": "Kicked user from server.",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.kick.info.field.performer>",
|
||||
"name": "Performer",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.kick.info.field.target>",
|
||||
"name": "Target",
|
||||
"value": "${target.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.kick.info.field.private_message>",
|
||||
"name": "Sent DM",
|
||||
"value": "${private_message}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.kick.info.field.reason.name>",
|
||||
"value": "<moderation.kick.info.field.reason.value>",
|
||||
"name": "Reason",
|
||||
"value": "${nullcheck;reason;_No reason specified._}",
|
||||
"inline": false
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
{
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "<moderation.note.add.author>",
|
||||
"name": "Recorded note for user.",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.note.add.field.performer>",
|
||||
"name": "Performer",
|
||||
"value": "${note_entry.performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.note.add.field.target>",
|
||||
"name": "Target",
|
||||
"value": "${note_entry.target.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.note.add.field.note_id>",
|
||||
"name": "Note ID",
|
||||
"value": "${note_entry.note_id}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.note.add.field.date_time>",
|
||||
"name": "Date & Time",
|
||||
"value": "${note_entry.date_time}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.note.add.field.contents>",
|
||||
"name": "Text",
|
||||
"value": "${note_entry.contents}",
|
||||
"inline": false
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
"type": "listing",
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "<moderation.note.list.author>",
|
||||
"name": "Listing of Notes (Page ${page.current}/${page.max})",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"entry": {
|
||||
"type": "description",
|
||||
"text": "<moderation.note.list.entry>"
|
||||
"text": "**#${note_entry.note_id}**: ${note_entry.target.mention} by ${note_entry.performer.mention}\n - _${note_entry.date_time}_\n${note_entry.contents}"
|
||||
},
|
||||
"empty": "<moderation.note.list.empty>"
|
||||
"empty": "**_No recorded notes matching your query._**"
|
||||
}
|
|
@ -1,37 +1,37 @@
|
|||
{
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "<moderation.note.remove.author>",
|
||||
"name": "Removed note.",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.note.remove.field.performer>",
|
||||
"name": "Performer",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.note.remove.field.original_performer>",
|
||||
"name": "Original Performer",
|
||||
"value": "${note_entry.performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.note.remove.field.original_target>",
|
||||
"name": "Original Target",
|
||||
"value": "${note_entry.target.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.note.remove.field.note_id>",
|
||||
"name": "Note ID",
|
||||
"value": "${note_entry.note_id}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.note.remove.field.date_time>",
|
||||
"name": "Date & Time",
|
||||
"value": "${note_entry.date_time}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.note.remove.field.contents>",
|
||||
"name": "Text",
|
||||
"value": "${note_entry.contents}",
|
||||
"inline": false
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
{
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "<moderation.unban.info.author>",
|
||||
"name": "Unbanned user from server.",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.unban.info.field.performer>",
|
||||
"name": "Performer",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.unban.info.field.target>",
|
||||
"name": "Target",
|
||||
"value": "${target.mention}",
|
||||
"inline": true
|
||||
}
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
{
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "<moderation.unwarn.info.author>",
|
||||
"name": "Removed warning from user.",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.unwarn.info.field.performer>",
|
||||
"name": "Performer",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.unwarn.info.field.original_target>",
|
||||
"name": "Original Target",
|
||||
"value": "${warning_entry.target.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.unwarn.info.field.original_performer>",
|
||||
"name": "Original Performer",
|
||||
"value": "${warning_entry.performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.unwarn.info.field.case_id>",
|
||||
"name": "Case ID",
|
||||
"value": "${warning_entry.case_id}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.unwarn.info.field.date_time>",
|
||||
"name": "Date & Time",
|
||||
"value": "${warning_entry.date_time}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.unwarn.info.field.reason.name>",
|
||||
"value": "<moderation.unwarn.info.field.reason.value>",
|
||||
"name": "Reason",
|
||||
"value": "${nullcheck;warning_entry.reason;_No reason specified._}",
|
||||
"inline": false
|
||||
}
|
||||
]
|
||||
|
|
|
@ -4,21 +4,21 @@
|
|||
"name": "${performer.guild.name}",
|
||||
"icon_url": "${performer.guild.icon_url}"
|
||||
},
|
||||
"title": "<moderation.warn.dm.title>",
|
||||
"title": "You were warned by a moderator.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.warn.dm.field.performer>",
|
||||
"name": "Moderator",
|
||||
"value": "${warning_entry.performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.warn.dm.field.date_time>",
|
||||
"name": "Date & Time",
|
||||
"value": "${warning_entry.date_time}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.warn.dm.field.reason.name>",
|
||||
"value": "<moderation.warn.dm.field.reason.value>",
|
||||
"name": "Reason",
|
||||
"value": "${nullcheck;warning_entry.reason;_No reason specified._}",
|
||||
"inline": false
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
{
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "<moderation.warn.info.author>",
|
||||
"name": "Warned user.",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "<moderation.warn.info.field.performer>",
|
||||
"name": "Performer",
|
||||
"value": "${warning_entry.performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.warn.info.field.target>",
|
||||
"name": "Target",
|
||||
"value": "${warning_entry.target.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.warn.info.field.case_id>",
|
||||
"name": "Case ID",
|
||||
"value": "${warning_entry.case_id}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.warn.info.field.private_message>",
|
||||
"name": "Sent DM",
|
||||
"value": "${private_message}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.warn.info.field.date_time>",
|
||||
"name": "Date & Time",
|
||||
"value": "${warning_entry.date_time}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "<moderation.warn.info.field.reason.name>",
|
||||
"value": "<moderation.warn.info.field.reason.value>",
|
||||
"name": "Reason",
|
||||
"value": "${nullcheck;warning_entry.reason;_No reason specified._}",
|
||||
"inline": false
|
||||
}
|
||||
]
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
"type": "listing",
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "<moderation.warnlist.author>",
|
||||
"name": "Listing of Warnings (Page ${page.current}/${page.max})",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"entry": {
|
||||
"type": "description",
|
||||
"text": "<moderation.warnlist.entry>"
|
||||
"text": "**Case #${warning_entry.case_id}**: Warned ${warning_entry.target.mention} by ${warning_entry.performer.mention} \n - _Date & Time:_ ${warning_entry.date_time} \n - _Reason:_ ${warning_entry.reason}"
|
||||
},
|
||||
"empty": "<moderation.warnlist.empty>"
|
||||
"empty": "**_No warnings logged matching your query._**"
|
||||
}
|
Loading…
Reference in New Issue
Block a user