mirror of
https://github.com/sciwhiz12/Janitor.git
synced 2024-11-10 02:21:25 +00:00
Merge in better_messages, reformat code, remove .idea folder
This commit is contained in:
commit
0855569ad3
3
.idea/.gitignore
vendored
3
.idea/.gitignore
vendored
|
@ -1,3 +0,0 @@
|
||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
|
@ -1,5 +0,0 @@
|
||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<state>
|
|
||||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="SciWhiz12" />
|
|
||||||
</state>
|
|
||||||
</component>
|
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="CompilerConfiguration">
|
|
||||||
<bytecodeTargetLevel target="11" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
|
@ -1,19 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="GradleSettings">
|
|
||||||
<option name="linkedExternalProjectsSettings">
|
|
||||||
<GradleProjectSettings>
|
|
||||||
<option name="delegatedBuild" value="true" />
|
|
||||||
<option name="testRunner" value="GRADLE" />
|
|
||||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
|
||||||
<option name="gradleJvm" value="11" />
|
|
||||||
<option name="modules">
|
|
||||||
<set>
|
|
||||||
<option value="$PROJECT_DIR$" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</GradleProjectSettings>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
|
@ -1,30 +0,0 @@
|
||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<profile version="1.0">
|
|
||||||
<option name="myName" value="Project Default" />
|
|
||||||
<inspection_tool class="NotNullFieldNotInitialized" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="NullableProblems" enabled="false" level="WARNING" enabled_by_default="false">
|
|
||||||
<option name="REPORT_NULLABLE_METHOD_OVERRIDES_NOTNULL" value="true" />
|
|
||||||
<option name="REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL" value="true" />
|
|
||||||
<option name="REPORT_NOTNULL_PARAMETER_OVERRIDES_NULLABLE" value="true" />
|
|
||||||
<option name="REPORT_NOT_ANNOTATED_PARAMETER_OVERRIDES_NOTNULL" value="true" />
|
|
||||||
<option name="REPORT_NOT_ANNOTATED_GETTER" value="true" />
|
|
||||||
<option name="REPORT_NOT_ANNOTATED_SETTER_PARAMETER" value="true" />
|
|
||||||
<option name="REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS" value="true" />
|
|
||||||
<option name="REPORT_NULLS_PASSED_TO_NON_ANNOTATED_METHOD" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="unused" enabled="false" level="WARNING" enabled_by_default="false">
|
|
||||||
<option name="LOCAL_VARIABLE" value="true" />
|
|
||||||
<option name="FIELD" value="true" />
|
|
||||||
<option name="METHOD" value="true" />
|
|
||||||
<option name="CLASS" value="true" />
|
|
||||||
<option name="PARAMETER" value="true" />
|
|
||||||
<option name="REPORT_PARAMETER_FOR_PUBLIC_METHODS" value="true" />
|
|
||||||
<option name="ADD_MAINS_TO_ENTRIES" value="true" />
|
|
||||||
<option name="ADD_APPLET_TO_ENTRIES" value="true" />
|
|
||||||
<option name="ADD_SERVLET_TO_ENTRIES" value="true" />
|
|
||||||
<option name="ADD_NONJAVA_TO_ENTRIES" value="true" />
|
|
||||||
<option name="selected" value="true" />
|
|
||||||
<option name="MIXIN_ENTRY_POINT" value="true" />
|
|
||||||
</inspection_tool>
|
|
||||||
</profile>
|
|
||||||
</component>
|
|
|
@ -1,25 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="RemoteRepositoriesConfiguration">
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="central" />
|
|
||||||
<option name="name" value="Maven Central repository" />
|
|
||||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="jboss.community" />
|
|
||||||
<option name="name" value="JBoss Community repository" />
|
|
||||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="MavenRepo" />
|
|
||||||
<option name="name" value="MavenRepo" />
|
|
||||||
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
|
||||||
</remote-repository>
|
|
||||||
<remote-repository>
|
|
||||||
<option name="id" value="BintrayJCenter" />
|
|
||||||
<option name="name" value="BintrayJCenter" />
|
|
||||||
<option name="url" value="https://jcenter.bintray.com/" />
|
|
||||||
</remote-repository>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK" />
|
|
||||||
</project>
|
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
|
@ -40,7 +40,9 @@ dependencies {
|
||||||
implementation group: 'com.electronwill.night-config', name: 'toml', version: nightconfig_version
|
implementation group: 'com.electronwill.night-config', name: 'toml', version: nightconfig_version
|
||||||
implementation group: 'net.sf.jopt-simple', name: 'jopt-simple', version: jopt_version
|
implementation group: 'net.sf.jopt-simple', name: 'jopt-simple', version: jopt_version
|
||||||
implementation group: 'com.google.guava', name: 'guava', version: guava_version
|
implementation group: 'com.google.guava', name: 'guava', version: guava_version
|
||||||
implementation group: 'com.google.code.gson', name: 'gson', version: gson_version
|
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: jackson_version
|
||||||
|
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: jackson_version
|
||||||
|
implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: jackson_version
|
||||||
implementation group: 'org.apache.logging.log4j', name: 'log4j-to-slf4j', version: log4j_bridge_version
|
implementation group: 'org.apache.logging.log4j', name: 'log4j-to-slf4j', version: log4j_bridge_version
|
||||||
implementation group: 'ch.qos.logback', name: 'logback-classic', version: logback_version
|
implementation group: 'ch.qos.logback', name: 'logback-classic', version: logback_version
|
||||||
implementation group: 'com.mojang', name: 'brigadier', version: brigadier_version
|
implementation group: 'com.mojang', name: 'brigadier', version: brigadier_version
|
||||||
|
|
|
@ -5,7 +5,7 @@ jda_version=4.2.0_207
|
||||||
nightconfig_version=3.6.3
|
nightconfig_version=3.6.3
|
||||||
jopt_version=6.0-alpha-3
|
jopt_version=6.0-alpha-3
|
||||||
guava_version=29.0-jre
|
guava_version=29.0-jre
|
||||||
gson_version=2.8.6
|
jackson_version=2.11.2
|
||||||
log4j_bridge_version=2.13.3
|
log4j_bridge_version=2.13.3
|
||||||
logback_version=1.3.0-alpha5
|
logback_version=1.3.0-alpha5
|
||||||
brigadier_version=1.0.17
|
brigadier_version=1.0.17
|
||||||
|
|
|
@ -49,6 +49,11 @@ public class BotConsole {
|
||||||
bot.getTranslations().loadTranslations();
|
bot.getTranslations().loadTranslations();
|
||||||
break outer;
|
break outer;
|
||||||
}
|
}
|
||||||
|
case "messages": {
|
||||||
|
CONSOLE.info("Reloading messages");
|
||||||
|
bot.getMessages().loadMessages();
|
||||||
|
break outer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -71,8 +76,7 @@ public class BotConsole {
|
||||||
while (!scanner.hasNextLine()) {
|
while (!scanner.hasNextLine()) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(150);
|
Thread.sleep(150);
|
||||||
}
|
} catch (InterruptedException e) {
|
||||||
catch (InterruptedException e) {
|
|
||||||
CONSOLE.warn("Console thread is interrupted");
|
CONSOLE.warn("Console thread is interrupted");
|
||||||
continue outer;
|
continue outer;
|
||||||
}
|
}
|
||||||
|
@ -84,8 +88,7 @@ public class BotConsole {
|
||||||
}
|
}
|
||||||
CONSOLE.debug("Received command: {}", input);
|
CONSOLE.debug("Received command: {}", input);
|
||||||
BotConsole.this.parseCommand(input);
|
BotConsole.this.parseCommand(input);
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e) {
|
|
||||||
CONSOLE.error("Error while running console thread", e);
|
CONSOLE.error("Error while running console thread", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package sciwhiz12.janitor;
|
package sciwhiz12.janitor;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
import net.dv8tion.jda.api.JDABuilder;
|
import net.dv8tion.jda.api.JDABuilder;
|
||||||
import net.dv8tion.jda.api.OnlineStatus;
|
import net.dv8tion.jda.api.OnlineStatus;
|
||||||
import net.dv8tion.jda.api.entities.Activity;
|
import net.dv8tion.jda.api.entities.Activity;
|
||||||
|
@ -12,7 +13,6 @@ import sciwhiz12.janitor.config.BotOptions;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||||
|
|
||||||
public class BotStartup {
|
public class BotStartup {
|
||||||
|
@ -21,7 +21,7 @@ public class BotStartup {
|
||||||
|
|
||||||
BotOptions options = new BotOptions(args);
|
BotOptions options = new BotOptions(args);
|
||||||
BotConfig config = new BotConfig(options);
|
BotConfig config = new BotConfig(options);
|
||||||
checkArgument(!config.getToken().isEmpty(), "Supply a client token through config or command line");
|
Preconditions.checkArgument(!config.getToken().isEmpty(), "Supply a client token through config or command line");
|
||||||
|
|
||||||
JANITOR.info("Building bot instance and connecting to Discord...");
|
JANITOR.info("Building bot instance and connecting to Discord...");
|
||||||
|
|
||||||
|
@ -37,8 +37,7 @@ public class BotStartup {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
}
|
} catch (Exception ex) {
|
||||||
catch (Exception ex) {
|
|
||||||
JANITOR.error("Error while building Discord connection", ex);
|
JANITOR.error("Error while building Discord connection", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,9 @@ import net.dv8tion.jda.api.entities.User;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||||
import sciwhiz12.janitor.config.BotConfig;
|
import sciwhiz12.janitor.config.BotConfig;
|
||||||
import sciwhiz12.janitor.msg.Messages;
|
import sciwhiz12.janitor.msg.Messages;
|
||||||
import sciwhiz12.janitor.msg.Translations;
|
import sciwhiz12.janitor.msg.TranslationMap;
|
||||||
|
import sciwhiz12.janitor.msg.emote.ReactionManager;
|
||||||
|
import sciwhiz12.janitor.msg.substitution.SubstitutionMap;
|
||||||
import sciwhiz12.janitor.storage.GuildStorage;
|
import sciwhiz12.janitor.storage.GuildStorage;
|
||||||
import sciwhiz12.janitor.utils.Util;
|
import sciwhiz12.janitor.utils.Util;
|
||||||
|
|
||||||
|
@ -22,22 +24,27 @@ import static sciwhiz12.janitor.Logging.STATUS;
|
||||||
public class JanitorBot {
|
public class JanitorBot {
|
||||||
private final JDA discord;
|
private final JDA discord;
|
||||||
private final BotConfig config;
|
private final BotConfig config;
|
||||||
private final Messages messages;
|
private final BotConsole console;
|
||||||
private BotConsole console;
|
|
||||||
private final GuildStorage storage;
|
private final GuildStorage storage;
|
||||||
private final GuildStorage.SavingThread storageSavingThread;
|
private final GuildStorage.SavingThread storageSavingThread;
|
||||||
private CommandRegistry cmdRegistry;
|
private final CommandRegistry cmdRegistry;
|
||||||
private Translations translations;
|
private final TranslationMap translations;
|
||||||
|
private final SubstitutionMap substitutions;
|
||||||
|
private final Messages messages;
|
||||||
|
private final ReactionManager reactions;
|
||||||
|
|
||||||
public JanitorBot(JDA discord, BotConfig config) {
|
public JanitorBot(JDA discord, BotConfig config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
this.discord = discord;
|
||||||
this.console = new BotConsole(this, System.in);
|
this.console = new BotConsole(this, System.in);
|
||||||
this.storage = new GuildStorage(this, Path.of(config.STORAGE_PATH.get()));
|
this.storage = new GuildStorage(this, Path.of(config.STORAGE_PATH.get()));
|
||||||
this.cmdRegistry = new CommandRegistry(this, config.getCommandPrefix());
|
this.cmdRegistry = new CommandRegistry(this, config.getCommandPrefix());
|
||||||
this.discord = discord;
|
this.translations = new TranslationMap(this, config.getTranslationsFile());
|
||||||
this.translations = new Translations(this, config.getTranslationsFile());
|
this.substitutions = new SubstitutionMap(this);
|
||||||
this.messages = new Messages(this);
|
this.messages = new Messages(this, config.getTranslationsFile());
|
||||||
discord.addEventListener(cmdRegistry);
|
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);
|
||||||
discord.getPresence().setPresence(OnlineStatus.ONLINE, Activity.playing(" n' sweeping n' testing!"));
|
discord.getPresence().setPresence(OnlineStatus.ONLINE, Activity.playing(" n' sweeping n' testing!"));
|
||||||
discord.getGuilds().forEach(Guild::loadMembers);
|
discord.getGuilds().forEach(Guild::loadMembers);
|
||||||
JANITOR.info("Ready!");
|
JANITOR.info("Ready!");
|
||||||
|
@ -65,7 +72,9 @@ public class JanitorBot {
|
||||||
return this.config;
|
return this.config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Messages getMessages() { return this.messages; }
|
public Messages getMessages() {
|
||||||
|
return messages;
|
||||||
|
}
|
||||||
|
|
||||||
public GuildStorage getStorage() { return this.storage; }
|
public GuildStorage getStorage() { return this.storage; }
|
||||||
|
|
||||||
|
@ -73,10 +82,14 @@ public class JanitorBot {
|
||||||
return this.cmdRegistry;
|
return this.cmdRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Translations getTranslations() {
|
public TranslationMap getTranslations() {
|
||||||
return this.translations;
|
return this.translations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReactionManager getReactionManager() {
|
||||||
|
return this.reactions;
|
||||||
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
JANITOR.info(STATUS, "Shutting down!");
|
JANITOR.info(STATUS, "Shutting down!");
|
||||||
getConfig().getOwnerID()
|
getConfig().getOwnerID()
|
||||||
|
@ -102,4 +115,8 @@ public class JanitorBot {
|
||||||
storage.save();
|
storage.save();
|
||||||
console.stop();
|
console.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SubstitutionMap getSubstitutions() {
|
||||||
|
return substitutions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ public class Logging {
|
||||||
public static final Marker STATUS = MarkerFactory.getMarker("STATUS");
|
public static final Marker STATUS = MarkerFactory.getMarker("STATUS");
|
||||||
public static final Marker COMMANDS = MarkerFactory.getMarker("COMMANDS");
|
public static final Marker COMMANDS = MarkerFactory.getMarker("COMMANDS");
|
||||||
public static final Marker TRANSLATIONS = MarkerFactory.getMarker("TRANSLATIONS");
|
public static final Marker TRANSLATIONS = MarkerFactory.getMarker("TRANSLATIONS");
|
||||||
|
public static final Marker MESSAGES = MarkerFactory.getMarker("MESSAGES");
|
||||||
public static final Marker STORAGE = MarkerFactory.getMarker("STORAGE");
|
public static final Marker STORAGE = MarkerFactory.getMarker("STORAGE");
|
||||||
|
|
||||||
public static final Logger JANITOR = LoggerFactory.getLogger("janitor");
|
public static final Logger JANITOR = LoggerFactory.getLogger("janitor");
|
||||||
|
|
|
@ -84,8 +84,7 @@ public class CommandRegistry implements EventListener {
|
||||||
}
|
}
|
||||||
JANITOR.debug(COMMANDS, "Executing command.");
|
JANITOR.debug(COMMANDS, "Executing command.");
|
||||||
dispatcher.execute(parseResults);
|
dispatcher.execute(parseResults);
|
||||||
}
|
} catch (CommandSyntaxException ex) {
|
||||||
catch (CommandSyntaxException ex) {
|
|
||||||
JANITOR.error(COMMANDS, "Error while parsing message and executing command", ex);
|
JANITOR.error(COMMANDS, "Error while parsing message and executing command", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,10 @@ import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class GuildMemberArgument implements ArgumentType<GuildMemberArgument.IMemberProvider> {
|
public class GuildMemberArgument implements ArgumentType<GuildMemberArgument.IMemberProvider> {
|
||||||
public static final SimpleCommandExceptionType UNKNOWN_MEMBER_IDENTIFIER = new SimpleCommandExceptionType(new LiteralMessage("Unknown user identifier"));
|
public static final SimpleCommandExceptionType UNKNOWN_MEMBER_IDENTIFIER = new SimpleCommandExceptionType(
|
||||||
public static final SimpleCommandExceptionType MULTIPLE_MEMBERS = new SimpleCommandExceptionType(new LiteralMessage("Too many users, when only one is needed"));
|
new LiteralMessage("Unknown user identifier"));
|
||||||
|
public static final SimpleCommandExceptionType MULTIPLE_MEMBERS = new SimpleCommandExceptionType(
|
||||||
|
new LiteralMessage("Too many users, when only one is needed"));
|
||||||
|
|
||||||
public static final Pattern USER_IDENTIFIER_PATTERN = Pattern.compile("<@!?([0-9]+)>");
|
public static final Pattern USER_IDENTIFIER_PATTERN = Pattern.compile("<@!?([0-9]+)>");
|
||||||
|
|
||||||
|
@ -105,7 +107,8 @@ public class GuildMemberArgument implements ArgumentType<GuildMemberArgument.IMe
|
||||||
public List<Member> fromGuild(Guild guild) throws CommandSyntaxException {
|
public List<Member> fromGuild(Guild guild) throws CommandSyntaxException {
|
||||||
final String nameLowercase = name.toLowerCase(Locale.ROOT);
|
final String nameLowercase = name.toLowerCase(Locale.ROOT);
|
||||||
final List<Member> members = guild.getMembers().stream()
|
final List<Member> members = guild.getMembers().stream()
|
||||||
.filter(member -> member.getUser().getAsTag().replaceAll("\\s", "").toLowerCase(Locale.ROOT).startsWith(nameLowercase))
|
.filter(member -> member.getUser().getAsTag().replaceAll("\\s", "").toLowerCase(Locale.ROOT)
|
||||||
|
.startsWith(nameLowercase))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
if (!multiple && members.size() > 1) {
|
if (!multiple && members.size() > 1) {
|
||||||
throw MULTIPLE_MEMBERS.create();
|
throw MULTIPLE_MEMBERS.create();
|
||||||
|
|
|
@ -24,9 +24,8 @@ public class HelloCommand extends BaseCommand {
|
||||||
|
|
||||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||||
return literal("greet")
|
return literal("greet")
|
||||||
.then(
|
.then(argument("member", GuildMemberArgument.member())
|
||||||
argument("member", GuildMemberArgument.member())
|
.executes(this::run)
|
||||||
.executes(this::run)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,11 +34,22 @@ public class HelloCommand extends BaseCommand {
|
||||||
final List<Member> memberList = getMembers("member", ctx).fromGuild(ctx.getSource().getGuild());
|
final List<Member> memberList = getMembers("member", ctx).fromGuild(ctx.getSource().getGuild());
|
||||||
if (memberList.size() == 1) {
|
if (memberList.size() == 1) {
|
||||||
final Member member = memberList.get(0);
|
final Member member = memberList.get(0);
|
||||||
ctx.getSource().getChannel().sendMessage("Hello " + member.getAsMention() + "!")
|
ctx.getSource().getChannel().sendMessage("Hello " + member.getAsMention() + "!").queue(
|
||||||
.queue(
|
success -> {
|
||||||
success -> JANITOR.debug("Sent greeting message to {}, on cmd of {}", Util.toString(member.getUser()), Util.toString(ctx.getSource().getAuthor())),
|
JANITOR.debug("Sent greeting message to {}, on cmd of {}", Util.toString(member.getUser()),
|
||||||
err -> JANITOR.error("Error while sending greeting message to {}, on cmd of {}", Util.toString(member.getUser()), Util.toString(ctx.getSource().getAuthor()))
|
Util.toString(ctx.getSource().getAuthor()));
|
||||||
);
|
getBot().getReactionManager().newMessage(success)
|
||||||
|
.add("\u274C", (msg, event) -> success.delete()
|
||||||
|
.flatMap(v -> event.getChannel()
|
||||||
|
.deleteMessageById(ctx.getSource().getMessageIdLong()))
|
||||||
|
.queue()
|
||||||
|
)
|
||||||
|
.owner(ctx.getSource().getAuthor().getIdLong())
|
||||||
|
.create();
|
||||||
|
},
|
||||||
|
err -> JANITOR.error("Error while sending greeting message to {}, on cmd of {}",
|
||||||
|
Util.toString(member.getUser()), Util.toString(ctx.getSource().getAuthor()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -26,7 +26,8 @@ public class OKCommand extends BaseCommand {
|
||||||
.addReaction("\uD83D\uDC4C")
|
.addReaction("\uD83D\uDC4C")
|
||||||
.queue(
|
.queue(
|
||||||
success -> JANITOR.debug("Reacted :ok_hand: to {}'s message", Util.toString(ctx.getSource().getAuthor())),
|
success -> JANITOR.debug("Reacted :ok_hand: to {}'s message", Util.toString(ctx.getSource().getAuthor())),
|
||||||
err -> JANITOR.error("Error while reacting :ok_hand: to {}'s message", Util.toString(ctx.getSource().getAuthor()))
|
err -> JANITOR
|
||||||
|
.error("Error while reacting :ok_hand: to {}'s message", Util.toString(ctx.getSource().getAuthor()))
|
||||||
);
|
);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,14 +8,15 @@ import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
import sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.commands.BaseCommand;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||||
import sciwhiz12.janitor.commands.util.ModerationHelper;
|
import sciwhiz12.janitor.commands.util.ModerationHelper;
|
||||||
|
import sciwhiz12.janitor.msg.MessageHelper;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
|
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
|
||||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||||
|
@ -60,43 +61,77 @@ public class BanCommand extends BaseCommand {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int run(CommandContext<MessageReceivedEvent> ctx, int days, @Nullable String reason) throws CommandSyntaxException {
|
int run(CommandContext<MessageReceivedEvent> ctx, int days, @Nullable String reason) throws CommandSyntaxException {
|
||||||
realRun(ctx, days, reason);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void realRun(CommandContext<MessageReceivedEvent> ctx, int days, @Nullable String reason) throws CommandSyntaxException {
|
|
||||||
MessageChannel channel = ctx.getSource().getChannel();
|
MessageChannel channel = ctx.getSource().getChannel();
|
||||||
if (!ctx.getSource().isFromGuild()) {
|
if (!ctx.getSource().isFromGuild()) {
|
||||||
messages().GENERAL.guildOnlyCommand(channel).queue();
|
messages().getRegularMessage("general/error/guild_only_command")
|
||||||
return;
|
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
final Guild guild = ctx.getSource().getGuild();
|
final Guild guild = ctx.getSource().getGuild();
|
||||||
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
||||||
|
|
||||||
final List<Member> members = getMembers("member", ctx).fromGuild(performer.getGuild());
|
final List<Member> members = getMembers("member", ctx).fromGuild(performer.getGuild());
|
||||||
if (members.size() < 1) return;
|
if (members.size() < 1) { return 1; }
|
||||||
final Member target = members.get(0);
|
final Member target = members.get(0);
|
||||||
|
|
||||||
if (guild.getSelfMember().equals(target))
|
if (guild.getSelfMember().equals(target)) {
|
||||||
messages().GENERAL.cannotActionSelf(channel).queue();
|
messages().getRegularMessage("general/error/cannot_action_self")
|
||||||
else if (performer.equals(target))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
messages().GENERAL.cannotActionPerformer(channel, performer).queue();
|
.send(getBot(), channel).queue();
|
||||||
else if (!guild.getSelfMember().hasPermission(BAN_PERMISSION))
|
|
||||||
messages().GENERAL.insufficientPermissions(channel, BAN_PERMISSION).queue();
|
} else if (performer.equals(target)) {
|
||||||
else if (!guild.getSelfMember().canInteract(target))
|
messages().getRegularMessage("general/error/cannot_action_performer")
|
||||||
messages().GENERAL.cannotInteract(channel, target).queue();
|
.apply(MessageHelper.member("performer", performer))
|
||||||
else if (!performer.hasPermission(BAN_PERMISSION))
|
.send(getBot(), channel).queue();
|
||||||
messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, BAN_PERMISSION).queue();
|
|
||||||
else if (!performer.canInteract(target))
|
} else if (!guild.getSelfMember().hasPermission(BAN_PERMISSION)) {
|
||||||
messages().MODERATION.ERRORS.cannotModerate(channel, performer, target).queue();
|
messages().getRegularMessage("general/error/insufficient_permissions")
|
||||||
else
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.with("required_permissions", BAN_PERMISSION::toString)
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else if (!guild.getSelfMember().canInteract(target)) {
|
||||||
|
messages().getRegularMessage("general/error/cannot_interact")
|
||||||
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else if (!performer.hasPermission(BAN_PERMISSION)) {
|
||||||
|
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.with("required_permissions", BAN_PERMISSION::toString)
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else if (!performer.canInteract(target)) {
|
||||||
|
messages().getRegularMessage("moderation/error/cannot_interact")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else {
|
||||||
target.getUser().openPrivateChannel()
|
target.getUser().openPrivateChannel()
|
||||||
.flatMap(dm -> messages().MODERATION.bannedDM(dm, performer, reason))
|
.flatMap(dm -> messages().getRegularMessage("moderation/ban/dm")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.with("reason", () -> reason)
|
||||||
|
.send(getBot(), dm)
|
||||||
|
)
|
||||||
.mapToResult()
|
.mapToResult()
|
||||||
.flatMap(res -> ModerationHelper.banUser(target.getGuild(), performer, target, days, reason)
|
.flatMap(res ->
|
||||||
.flatMap(
|
ModerationHelper.banUser(target.getGuild(), performer, target, days, reason)
|
||||||
v -> messages().MODERATION.banUser(channel, performer, target, reason, days, res.isSuccess())))
|
.flatMap(v -> messages().getRegularMessage("moderation/ban/info")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.with("private_message", () -> res.isSuccess() ? "✅" : "❌")
|
||||||
|
.with("delete_duration", () -> String.valueOf(days))
|
||||||
|
.with("reason", () -> reason)
|
||||||
|
.send(getBot(), channel)
|
||||||
|
)
|
||||||
|
)
|
||||||
.queue();
|
.queue();
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,16 @@ import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
import sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.commands.BaseCommand;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||||
import sciwhiz12.janitor.commands.util.CommandHelper;
|
import sciwhiz12.janitor.commands.util.CommandHelper;
|
||||||
import sciwhiz12.janitor.commands.util.ModerationHelper;
|
import sciwhiz12.janitor.commands.util.ModerationHelper;
|
||||||
|
import sciwhiz12.janitor.msg.MessageHelper;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||||
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
|
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
|
||||||
|
@ -50,36 +51,72 @@ public class KickCommand extends BaseCommand {
|
||||||
private int runWithReason(CommandContext<MessageReceivedEvent> ctx, @Nullable String reason) throws CommandSyntaxException {
|
private int runWithReason(CommandContext<MessageReceivedEvent> ctx, @Nullable String reason) throws CommandSyntaxException {
|
||||||
MessageChannel channel = ctx.getSource().getChannel();
|
MessageChannel channel = ctx.getSource().getChannel();
|
||||||
if (!ctx.getSource().isFromGuild()) {
|
if (!ctx.getSource().isFromGuild()) {
|
||||||
messages().GENERAL.guildOnlyCommand(channel).queue();
|
messages().getRegularMessage("general/error/guild_only_command")
|
||||||
|
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
final Guild guild = ctx.getSource().getGuild();
|
final Guild guild = ctx.getSource().getGuild();
|
||||||
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
||||||
|
|
||||||
final List<Member> members = getMembers("member", ctx).fromGuild(performer.getGuild());
|
final List<Member> members = getMembers("member", ctx).fromGuild(performer.getGuild());
|
||||||
if (members.size() < 1) {
|
if (members.size() < 1) { return 1; }
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
final Member target = members.get(0);
|
final Member target = members.get(0);
|
||||||
if (guild.getSelfMember().equals(target))
|
|
||||||
messages().GENERAL.cannotActionSelf(channel).queue();
|
if (guild.getSelfMember().equals(target)) {
|
||||||
else if (performer.equals(target))
|
messages().getRegularMessage("general/error/cannot_action_self")
|
||||||
messages().GENERAL.cannotActionPerformer(channel, performer).queue();
|
.apply(MessageHelper.member("performer", performer))
|
||||||
else if (!guild.getSelfMember().hasPermission(KICK_PERMISSION))
|
.send(getBot(), channel).queue();
|
||||||
messages().GENERAL.insufficientPermissions(channel, KICK_PERMISSION).queue();
|
|
||||||
else if (!guild.getSelfMember().canInteract(target))
|
} else if (performer.equals(target)) {
|
||||||
messages().GENERAL.cannotInteract(channel, target).queue();
|
messages().getRegularMessage("general/error/cannot_action_performer")
|
||||||
else if (!performer.hasPermission(KICK_PERMISSION))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, KICK_PERMISSION).queue();
|
.send(getBot(), channel).queue();
|
||||||
else if (!performer.canInteract(target))
|
|
||||||
messages().MODERATION.ERRORS.cannotModerate(channel, performer, target).queue();
|
} else if (!guild.getSelfMember().hasPermission(KICK_PERMISSION)) {
|
||||||
else
|
messages().getRegularMessage("general/error/insufficient_permissions")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.with("required_permissions", KICK_PERMISSION::toString)
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else if (!guild.getSelfMember().canInteract(target)) {
|
||||||
|
messages().getRegularMessage("general/error/cannot_interact")
|
||||||
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else if (!performer.hasPermission(KICK_PERMISSION)) {
|
||||||
|
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.with("required_permissions", KICK_PERMISSION::toString)
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else if (!performer.canInteract(target)) {
|
||||||
|
messages().getRegularMessage("moderation/error/cannot_interact")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else {
|
||||||
target.getUser().openPrivateChannel()
|
target.getUser().openPrivateChannel()
|
||||||
.flatMap(dm -> messages().MODERATION.kickedDM(dm, performer, target, reason))
|
.flatMap(dm -> messages().getRegularMessage("moderation/kick/dm")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.with("reason", () -> reason)
|
||||||
|
.send(getBot(), dm)
|
||||||
|
)
|
||||||
.mapToResult()
|
.mapToResult()
|
||||||
.flatMap(res -> ModerationHelper.kickUser(target.getGuild(), performer, target, reason)
|
.flatMap(res -> ModerationHelper.kickUser(target.getGuild(), performer, target, reason)
|
||||||
.flatMap(
|
.flatMap(v -> messages().getRegularMessage("moderation/kick/info")
|
||||||
v -> messages().MODERATION.kickUser(channel, performer, target, reason, res.isSuccess())))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.with("private_message", () -> res.isSuccess() ? "✅" : "❌")
|
||||||
|
.with("reason", () -> reason)
|
||||||
|
.send(getBot(), channel)
|
||||||
|
)
|
||||||
|
)
|
||||||
.queue();
|
.queue();
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package sciwhiz12.janitor.commands.moderation;
|
package sciwhiz12.janitor.commands.moderation;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
@ -9,19 +9,21 @@ import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
import sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.commands.BaseCommand;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||||
import sciwhiz12.janitor.moderation.notes.NoteEntry;
|
import sciwhiz12.janitor.moderation.notes.NoteEntry;
|
||||||
import sciwhiz12.janitor.moderation.notes.NoteStorage;
|
import sciwhiz12.janitor.moderation.notes.NoteStorage;
|
||||||
|
import sciwhiz12.janitor.msg.MessageHelper;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
|
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
|
||||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||||
|
@ -32,6 +34,7 @@ import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
||||||
import static sciwhiz12.janitor.commands.moderation.NoteCommand.ModeratorFilter.*;
|
import static sciwhiz12.janitor.commands.moderation.NoteCommand.ModeratorFilter.*;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||||
|
import static sciwhiz12.janitor.msg.MessageHelper.*;
|
||||||
|
|
||||||
public class NoteCommand extends BaseCommand {
|
public class NoteCommand extends BaseCommand {
|
||||||
public static EnumSet<Permission> NOTE_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
public static EnumSet<Permission> NOTE_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||||
|
@ -90,32 +93,56 @@ public class NoteCommand extends BaseCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int addNote(CommandContext<MessageReceivedEvent> ctx, String noteContents) throws CommandSyntaxException {
|
private int addNote(CommandContext<MessageReceivedEvent> ctx, String noteContents) throws CommandSyntaxException {
|
||||||
|
final MessageChannel channel = ctx.getSource().getChannel();
|
||||||
if (!ctx.getSource().isFromGuild()) {
|
if (!ctx.getSource().isFromGuild()) {
|
||||||
messages().GENERAL.guildOnlyCommand(ctx.getSource().getChannel());
|
messages().getRegularMessage("general/error/guild_only_command")
|
||||||
|
.apply(user("performer", ctx.getSource().getAuthor()))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
||||||
final Guild guild = performer.getGuild();
|
final Guild guild = performer.getGuild();
|
||||||
final MessageChannel channel = ctx.getSource().getChannel();
|
|
||||||
final List<Member> members = getMembers("target", ctx).fromGuild(guild);
|
final List<Member> members = getMembers("target", ctx).fromGuild(guild);
|
||||||
if (members.size() < 1) return 1;
|
if (members.size() < 1) return 1;
|
||||||
final Member target = members.get(0);
|
final Member target = members.get(0);
|
||||||
final OffsetDateTime dateTime = OffsetDateTime.now(ZoneOffset.UTC);
|
final OffsetDateTime dateTime = OffsetDateTime.now(ZoneOffset.UTC);
|
||||||
|
|
||||||
if (guild.getSelfMember().equals(target))
|
if (guild.getSelfMember().equals(target)) {
|
||||||
messages().GENERAL.cannotActionSelf(channel).queue();
|
messages().getRegularMessage("general/error/cannot_action_self")
|
||||||
else if (performer.equals(target))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
messages().GENERAL.cannotActionPerformer(channel, performer).queue();
|
.send(getBot(), channel).queue();
|
||||||
else if (!performer.hasPermission(NOTE_PERMISSION))
|
|
||||||
messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, NOTE_PERMISSION).queue();
|
} else if (performer.equals(target)) {
|
||||||
else {
|
messages().getRegularMessage("general/error/cannot_action_performer")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else if (!performer.hasPermission(NOTE_PERMISSION)) {
|
||||||
|
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.with("required_permissions", NOTE_PERMISSION::toString)
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else {
|
||||||
final NoteStorage storage = NoteStorage.get(getBot().getStorage(), guild);
|
final NoteStorage storage = NoteStorage.get(getBot().getStorage(), guild);
|
||||||
final int maxAmount = config().NOTES_MAX_AMOUNT_PER_MOD.get();
|
final int maxAmount = config().NOTES_MAX_AMOUNT_PER_MOD.get();
|
||||||
if (storage.getAmountOfNotes(target.getUser()) >= maxAmount) {
|
if (storage.getAmountOfNotes(target.getUser()) >= maxAmount) {
|
||||||
messages().MODERATION.ERRORS.maxAmountOfNotes(channel, performer, target, maxAmount).queue();
|
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.with("notes_amount", () -> String.valueOf(maxAmount))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
int noteID = storage.addNote(new NoteEntry(performer.getUser(), target.getUser(), dateTime, noteContents));
|
final NoteEntry entry = new NoteEntry(performer.getUser(), target.getUser(), dateTime, noteContents);
|
||||||
messages().MODERATION.addNote(channel, performer, target, noteContents, dateTime, noteID).queue();
|
int noteID = storage.addNote(entry);
|
||||||
|
|
||||||
|
messages().getRegularMessage("moderation/note/add")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(noteEntry("note_entry", noteID, entry))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -127,9 +154,12 @@ public class NoteCommand extends BaseCommand {
|
||||||
|
|
||||||
private int listNotes(CommandContext<MessageReceivedEvent> ctx, boolean filterTarget, ModeratorFilter modFilter)
|
private int listNotes(CommandContext<MessageReceivedEvent> ctx, boolean filterTarget, ModeratorFilter modFilter)
|
||||||
throws CommandSyntaxException {
|
throws CommandSyntaxException {
|
||||||
MessageChannel channel = ctx.getSource().getChannel();
|
final MessageChannel channel = ctx.getSource().getChannel();
|
||||||
if (!ctx.getSource().isFromGuild()) {
|
if (!ctx.getSource().isFromGuild()) {
|
||||||
messages().GENERAL.guildOnlyCommand(channel).queue();
|
messages().getRegularMessage("general/error/guild_only_command")
|
||||||
|
.apply(user("performer", ctx.getSource().getAuthor()))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
final Guild guild = ctx.getSource().getGuild();
|
final Guild guild = ctx.getSource().getGuild();
|
||||||
|
@ -141,7 +171,10 @@ public class NoteCommand extends BaseCommand {
|
||||||
if (members.size() < 1) return 1;
|
if (members.size() < 1) return 1;
|
||||||
final Member target = members.get(0);
|
final Member target = members.get(0);
|
||||||
if (guild.getSelfMember().equals(target)) {
|
if (guild.getSelfMember().equals(target)) {
|
||||||
messages().GENERAL.cannotActionSelf(channel).queue();
|
messages().getRegularMessage("general/error/cannot_interact")
|
||||||
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
predicate = predicate.and(e -> e.getValue().getTarget().getIdLong() == target.getIdLong());
|
predicate = predicate.and(e -> e.getValue().getTarget().getIdLong() == target.getIdLong());
|
||||||
|
@ -156,44 +189,73 @@ public class NoteCommand extends BaseCommand {
|
||||||
case PERFORMER: {
|
case PERFORMER: {
|
||||||
predicate = predicate.and(e -> e.getValue().getPerformer().getIdLong() == performer.getIdLong());
|
predicate = predicate.and(e -> e.getValue().getPerformer().getIdLong() == performer.getIdLong());
|
||||||
}
|
}
|
||||||
|
case NONE: {}
|
||||||
}
|
}
|
||||||
|
|
||||||
final OffsetDateTime dateTime = OffsetDateTime.now();
|
if (!performer.hasPermission(NOTE_PERMISSION)) {
|
||||||
|
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.with("required_permissions", NOTE_PERMISSION::toString)
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
if (!performer.hasPermission(NOTE_PERMISSION))
|
} else {
|
||||||
messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, NOTE_PERMISSION).queue();
|
messages().<Map.Entry<Integer, NoteEntry>>getListingMessage("moderation/note/list")
|
||||||
else
|
.apply(MessageHelper.member("performer", performer))
|
||||||
messages().MODERATION.noteList(channel, NoteStorage.get(getBot().getStorage(), guild)
|
.amountPerPage(8)
|
||||||
.getNotes()
|
.setEntryApplier((entry, subs) -> subs
|
||||||
.entrySet().stream()
|
.with("note_entry.note_id", () -> String.valueOf(entry.getKey()))
|
||||||
.filter(predicate)
|
.apply(user("note_entry.performer", entry.getValue().getPerformer()))
|
||||||
.collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue))
|
.apply(user("note_entry.target", entry.getValue().getTarget()))
|
||||||
).queue();
|
.with("note_entry.date_time", () -> entry.getValue().getDateTime().format(DATE_TIME_FORMAT))
|
||||||
|
.with("note_entry.contents", entry.getValue()::getContents)
|
||||||
|
)
|
||||||
|
.build(channel, getBot(), ctx.getSource().getMessage(),
|
||||||
|
NoteStorage.get(getBot().getStorage(), guild)
|
||||||
|
.getNotes()
|
||||||
|
.entrySet().stream()
|
||||||
|
.filter(predicate)
|
||||||
|
.sorted(Comparator.<Map.Entry<Integer, NoteEntry>>comparingInt(Map.Entry::getKey).reversed())
|
||||||
|
.collect(ImmutableList.toImmutableList())
|
||||||
|
);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int removeNote(CommandContext<MessageReceivedEvent> ctx, int noteID) {
|
private int removeNote(CommandContext<MessageReceivedEvent> ctx, int noteID) {
|
||||||
MessageChannel channel = ctx.getSource().getChannel();
|
MessageChannel channel = ctx.getSource().getChannel();
|
||||||
if (!ctx.getSource().isFromGuild()) {
|
if (!ctx.getSource().isFromGuild()) {
|
||||||
messages().GENERAL.guildOnlyCommand(channel).queue();
|
messages().getRegularMessage("general/error/guild_only_command")
|
||||||
|
.apply(user("performer", ctx.getSource().getAuthor()))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
final Guild guild = ctx.getSource().getGuild();
|
final Guild guild = ctx.getSource().getGuild();
|
||||||
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
||||||
|
|
||||||
final OffsetDateTime dateTime = OffsetDateTime.now();
|
if (!performer.hasPermission(NOTE_PERMISSION)) {
|
||||||
|
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.with("required_permissions", NOTE_PERMISSION::toString)
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
if (!performer.hasPermission(NOTE_PERMISSION))
|
} else {
|
||||||
messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, NOTE_PERMISSION).queue();
|
|
||||||
else {
|
|
||||||
final NoteStorage storage = NoteStorage.get(getBot().getStorage(), guild);
|
final NoteStorage storage = NoteStorage.get(getBot().getStorage(), guild);
|
||||||
@Nullable
|
@Nullable
|
||||||
final NoteEntry entry = storage.getNote(noteID);
|
final NoteEntry entry = storage.getNote(noteID);
|
||||||
if (entry == null)
|
if (entry == null) {
|
||||||
messages().MODERATION.ERRORS.noNoteFound(channel, performer, noteID).queue();
|
messages().getRegularMessage("moderation/note/add")
|
||||||
else {
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.with("note_id", () -> String.valueOf(noteID))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else {
|
||||||
storage.removeNote(noteID);
|
storage.removeNote(noteID);
|
||||||
messages().MODERATION.removeNote(channel, performer, noteID, entry).queue();
|
|
||||||
|
messages().getRegularMessage("moderation/note/remove")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(noteEntry("note_entry", noteID, entry))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
import sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.commands.BaseCommand;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||||
import sciwhiz12.janitor.commands.util.ModerationHelper;
|
import sciwhiz12.janitor.commands.util.ModerationHelper;
|
||||||
|
import sciwhiz12.janitor.msg.MessageHelper;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -49,7 +50,10 @@ public class UnbanCommand extends BaseCommand {
|
||||||
void realNamedRun(CommandContext<MessageReceivedEvent> ctx) {
|
void realNamedRun(CommandContext<MessageReceivedEvent> ctx) {
|
||||||
MessageChannel channel = ctx.getSource().getChannel();
|
MessageChannel channel = ctx.getSource().getChannel();
|
||||||
if (!ctx.getSource().isFromGuild()) {
|
if (!ctx.getSource().isFromGuild()) {
|
||||||
messages().GENERAL.guildOnlyCommand(channel).queue();
|
messages().getRegularMessage("general/error/guild_only_command")
|
||||||
|
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Guild guild = ctx.getSource().getGuild();
|
final Guild guild = ctx.getSource().getGuild();
|
||||||
|
@ -62,10 +66,14 @@ public class UnbanCommand extends BaseCommand {
|
||||||
.startsWith(username))
|
.startsWith(username))
|
||||||
.collect(Collectors.toList()))
|
.collect(Collectors.toList()))
|
||||||
.queue(bans -> {
|
.queue(bans -> {
|
||||||
if (bans.size() > 1)
|
if (bans.size() > 1) {
|
||||||
messages().GENERAL.ambiguousMember(channel).queue();
|
messages().getRegularMessage("general/error/ambiguous_member")
|
||||||
else if (bans.size() == 1)
|
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else if (bans.size() == 1) {
|
||||||
tryUnban(channel, guild, performer, bans.get(0).getUser());
|
tryUnban(channel, guild, performer, bans.get(0).getUser());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +85,10 @@ public class UnbanCommand extends BaseCommand {
|
||||||
void realIdRun(CommandContext<MessageReceivedEvent> ctx) {
|
void realIdRun(CommandContext<MessageReceivedEvent> ctx) {
|
||||||
MessageChannel channel = ctx.getSource().getChannel();
|
MessageChannel channel = ctx.getSource().getChannel();
|
||||||
if (!ctx.getSource().isFromGuild()) {
|
if (!ctx.getSource().isFromGuild()) {
|
||||||
messages().GENERAL.guildOnlyCommand(channel).queue();
|
messages().getRegularMessage("general/error/guild_only_command")
|
||||||
|
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Guild guild = ctx.getSource().getGuild();
|
final Guild guild = ctx.getSource().getGuild();
|
||||||
|
@ -97,13 +108,26 @@ public class UnbanCommand extends BaseCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
void tryUnban(MessageChannel channel, Guild guild, Member performer, User target) {
|
void tryUnban(MessageChannel channel, Guild guild, Member performer, User target) {
|
||||||
if (!guild.getSelfMember().hasPermission(UNBAN_PERMISSION))
|
if (!guild.getSelfMember().hasPermission(UNBAN_PERMISSION)) {
|
||||||
messages().GENERAL.insufficientPermissions(channel, UNBAN_PERMISSION).queue();
|
messages().getRegularMessage("general/error/insufficient_permissions")
|
||||||
else if (!performer.hasPermission(UNBAN_PERMISSION))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, UNBAN_PERMISSION).queue();
|
.with("required_permissions", UNBAN_PERMISSION::toString)
|
||||||
else
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else if (!performer.hasPermission(UNBAN_PERMISSION)) {
|
||||||
|
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.with("required_permissions", UNBAN_PERMISSION::toString)
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else {
|
||||||
ModerationHelper.unbanUser(guild, target)
|
ModerationHelper.unbanUser(guild, target)
|
||||||
.flatMap(v -> messages().MODERATION.unbanUser(channel, performer, target))
|
.flatMap(v -> messages().getRegularMessage("moderation/unban/info")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.user("target", target))
|
||||||
|
.send(getBot(), channel)
|
||||||
|
)
|
||||||
.queue();
|
.queue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,15 +8,15 @@ import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
import sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.commands.BaseCommand;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
||||||
|
import sciwhiz12.janitor.msg.MessageHelper;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||||
|
@ -45,34 +45,54 @@ public class UnwarnCommand extends BaseCommand {
|
||||||
void realRun(CommandContext<MessageReceivedEvent> ctx) {
|
void realRun(CommandContext<MessageReceivedEvent> ctx) {
|
||||||
MessageChannel channel = ctx.getSource().getChannel();
|
MessageChannel channel = ctx.getSource().getChannel();
|
||||||
if (!ctx.getSource().isFromGuild()) {
|
if (!ctx.getSource().isFromGuild()) {
|
||||||
messages().GENERAL.guildOnlyCommand(channel).queue();
|
messages().getRegularMessage("general/error/guild_only_command")
|
||||||
|
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final Guild guild = ctx.getSource().getGuild();
|
final Guild guild = ctx.getSource().getGuild();
|
||||||
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
||||||
int caseID = IntegerArgumentType.getInteger(ctx, "caseId");
|
int caseID = IntegerArgumentType.getInteger(ctx, "caseId");
|
||||||
|
|
||||||
final OffsetDateTime dateTime = OffsetDateTime.now();
|
if (!performer.hasPermission(WARN_PERMISSION)) {
|
||||||
|
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.with("required_permissions", WARN_PERMISSION::toString)
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
if (!performer.hasPermission(WARN_PERMISSION))
|
} else {
|
||||||
messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, WARN_PERMISSION).queue();
|
|
||||||
else {
|
|
||||||
final WarningStorage storage = WarningStorage.get(getBot().getStorage(), guild);
|
final WarningStorage storage = WarningStorage.get(getBot().getStorage(), guild);
|
||||||
@Nullable
|
@Nullable
|
||||||
final WarningEntry entry = storage.getWarning(caseID);
|
final WarningEntry entry = storage.getWarning(caseID);
|
||||||
Member temp;
|
Member temp;
|
||||||
if (entry == null)
|
if (entry == null) {
|
||||||
messages().MODERATION.ERRORS.noWarnWithID(channel, performer, caseID).queue();
|
messages().getRegularMessage("moderation/error/unwarn/no_case_found")
|
||||||
else if (entry.getWarned().getIdLong() == performer.getIdLong()
|
.apply(MessageHelper.member("performer", performer))
|
||||||
&& !config().WARNINGS_REMOVE_SELF_WARNINGS.get())
|
.with("case_id", () -> String.valueOf(caseID))
|
||||||
messages().MODERATION.ERRORS.cannotUnwarnSelf(channel, performer, caseID, entry).queue();
|
.send(getBot(), channel).queue();
|
||||||
else if (config().WARNINGS_RESPECT_MOD_ROLES.get()
|
|
||||||
&& (temp = guild.getMember(entry.getPerformer())) != null
|
} else if (entry.getWarned().getIdLong() == performer.getIdLong()
|
||||||
&& !performer.canInteract(temp))
|
&& !config().WARNINGS_REMOVE_SELF_WARNINGS.get()) {
|
||||||
messages().MODERATION.ERRORS.cannotRemoveHigherModerated(channel, performer, caseID, entry).queue();
|
messages().getRegularMessage("moderation/error/unwarn/cannot_unwarn_self")
|
||||||
else {
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.warningEntry("warning_entry", caseID, entry))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else if (config().WARNINGS_RESPECT_MOD_ROLES.get()
|
||||||
|
&& (temp = guild.getMember(entry.getPerformer())) != null && !performer.canInteract(temp)) {
|
||||||
|
messages().getRegularMessage("moderation/error/unwarn/cannot_remove_higher_mod")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.warningEntry("warning_entry", caseID, entry))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else {
|
||||||
storage.removeWarning(caseID);
|
storage.removeWarning(caseID);
|
||||||
messages().MODERATION.unwarn(channel, performer, caseID, entry).queue();
|
messages().getRegularMessage("moderation/unwarn/info")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.warningEntry("warning_entry", caseID, entry))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import sciwhiz12.janitor.commands.BaseCommand;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
||||||
|
import sciwhiz12.janitor.msg.MessageHelper;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
@ -44,45 +45,70 @@ public class WarnCommand extends BaseCommand {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int run(CommandContext<MessageReceivedEvent> ctx, String reason) throws CommandSyntaxException {
|
int run(CommandContext<MessageReceivedEvent> ctx, String reason) throws CommandSyntaxException {
|
||||||
realRun(ctx, reason);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void realRun(CommandContext<MessageReceivedEvent> ctx, String reason) throws CommandSyntaxException {
|
|
||||||
MessageChannel channel = ctx.getSource().getChannel();
|
MessageChannel channel = ctx.getSource().getChannel();
|
||||||
if (!ctx.getSource().isFromGuild()) {
|
if (!ctx.getSource().isFromGuild()) {
|
||||||
messages().GENERAL.guildOnlyCommand(channel).queue();
|
messages().getRegularMessage("general/error/guild_only_command")
|
||||||
return;
|
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
final Guild guild = ctx.getSource().getGuild();
|
final Guild guild = ctx.getSource().getGuild();
|
||||||
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
||||||
|
|
||||||
final List<Member> members = getMembers("member", ctx).fromGuild(performer.getGuild());
|
final List<Member> members = getMembers("member", ctx).fromGuild(performer.getGuild());
|
||||||
if (members.size() < 1) return;
|
if (members.size() < 1) { return 1; }
|
||||||
final Member target = members.get(0);
|
final Member target = members.get(0);
|
||||||
|
|
||||||
final OffsetDateTime dateTime = OffsetDateTime.now(ZoneOffset.UTC);
|
final OffsetDateTime dateTime = OffsetDateTime.now(ZoneOffset.UTC);
|
||||||
if (guild.getSelfMember().equals(target))
|
if (guild.getSelfMember().equals(target)) {
|
||||||
messages().GENERAL.cannotActionSelf(channel).queue();
|
messages().getRegularMessage("general/error/cannot_action_self")
|
||||||
else if (performer.equals(target))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
messages().GENERAL.cannotActionPerformer(channel, performer).queue();
|
.send(getBot(), channel).queue();
|
||||||
else if (!performer.hasPermission(WARN_PERMISSION))
|
|
||||||
messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, WARN_PERMISSION).queue();
|
} else if (performer.equals(target)) {
|
||||||
else if (!performer.canInteract(target))
|
messages().getRegularMessage("general/error/cannot_action_performer")
|
||||||
messages().MODERATION.ERRORS.cannotModerate(channel, performer, target).queue();
|
.apply(MessageHelper.member("performer", performer))
|
||||||
else if (target.hasPermission(WARN_PERMISSION) && config().WARNINGS_PREVENT_WARNING_MODS.get())
|
.send(getBot(), channel).queue();
|
||||||
messages().MODERATION.ERRORS.cannotWarnMods(channel, performer, target).queue();
|
|
||||||
else
|
} else if (!performer.hasPermission(WARN_PERMISSION)) {
|
||||||
|
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.with("required_permissions", WARN_PERMISSION::toString)
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else if (!performer.canInteract(target)) {
|
||||||
|
messages().getRegularMessage("moderation/error/cannot_interact")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else if (target.hasPermission(WARN_PERMISSION) && config().WARNINGS_PREVENT_WARNING_MODS.get()) {
|
||||||
|
messages().getRegularMessage("moderation/error/warn/cannot_warn_mods")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
WarningEntry entry = new WarningEntry(target.getUser(), performer.getUser(), dateTime, reason);
|
||||||
|
int caseId = WarningStorage.get(getBot().getStorage(), guild).addWarning(entry);
|
||||||
|
|
||||||
target.getUser().openPrivateChannel()
|
target.getUser().openPrivateChannel()
|
||||||
.flatMap(dm -> messages().MODERATION.warnDM(dm, performer, target, reason, dateTime))
|
.flatMap(dm -> messages().getRegularMessage("moderation/warn/dm")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.apply(MessageHelper.warningEntry("warning_entry", caseId, entry))
|
||||||
|
.send(getBot(), dm)
|
||||||
|
)
|
||||||
.mapToResult()
|
.mapToResult()
|
||||||
.flatMap(res -> {
|
.flatMap(res -> messages().getRegularMessage("moderation/warn/info")
|
||||||
int caseId = WarningStorage.get(getBot().getStorage(), guild)
|
.apply(MessageHelper.member("performer", performer))
|
||||||
.addWarning(new WarningEntry(target.getUser(), performer.getUser(), dateTime, reason));
|
.apply(MessageHelper.warningEntry("warning_entry", caseId, entry))
|
||||||
return messages().MODERATION
|
.with("private_message", () -> res.isSuccess() ? "✅" : "❌")
|
||||||
.warnUser(channel, performer, target, reason, dateTime, caseId, res.isSuccess());
|
.send(getBot(), channel)
|
||||||
})
|
)
|
||||||
.queue();
|
.queue();
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package sciwhiz12.janitor.commands.moderation;
|
package sciwhiz12.janitor.commands.moderation;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
@ -13,8 +13,9 @@ import sciwhiz12.janitor.commands.BaseCommand;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
||||||
|
import sciwhiz12.janitor.msg.MessageHelper;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.util.Comparator;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -25,6 +26,8 @@ import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMember
|
||||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||||
|
import static sciwhiz12.janitor.msg.MessageHelper.DATE_TIME_FORMAT;
|
||||||
|
import static sciwhiz12.janitor.msg.MessageHelper.user;
|
||||||
|
|
||||||
public class WarnListCommand extends BaseCommand {
|
public class WarnListCommand extends BaseCommand {
|
||||||
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||||
|
@ -54,18 +57,15 @@ public class WarnListCommand extends BaseCommand {
|
||||||
.executes(ctx -> this.run(ctx, false, false));
|
.executes(ctx -> this.run(ctx, false, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int run(CommandContext<MessageReceivedEvent> ctx, boolean filterTarget, boolean filterModerator)
|
int run(CommandContext<MessageReceivedEvent> ctx, boolean filterTarget, boolean filterModerator)
|
||||||
throws CommandSyntaxException {
|
|
||||||
realRun(ctx, filterTarget, filterModerator);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void realRun(CommandContext<MessageReceivedEvent> ctx, boolean filterTarget, boolean filterModerator)
|
|
||||||
throws CommandSyntaxException {
|
throws CommandSyntaxException {
|
||||||
MessageChannel channel = ctx.getSource().getChannel();
|
MessageChannel channel = ctx.getSource().getChannel();
|
||||||
if (!ctx.getSource().isFromGuild()) {
|
if (!ctx.getSource().isFromGuild()) {
|
||||||
messages().GENERAL.guildOnlyCommand(channel).queue();
|
messages().getRegularMessage("general/error/guild_only_command")
|
||||||
return;
|
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
final Guild guild = ctx.getSource().getGuild();
|
final Guild guild = ctx.getSource().getGuild();
|
||||||
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
final Member performer = Objects.requireNonNull(ctx.getSource().getMember());
|
||||||
|
@ -73,31 +73,50 @@ public class WarnListCommand extends BaseCommand {
|
||||||
|
|
||||||
if (filterTarget) {
|
if (filterTarget) {
|
||||||
final List<Member> members = getMembers("target", ctx).fromGuild(performer.getGuild());
|
final List<Member> members = getMembers("target", ctx).fromGuild(performer.getGuild());
|
||||||
if (members.size() < 1) return;
|
if (members.size() < 1) return 1;
|
||||||
final Member target = members.get(0);
|
final Member target = members.get(0);
|
||||||
if (guild.getSelfMember().equals(target)) {
|
if (guild.getSelfMember().equals(target)) {
|
||||||
messages().GENERAL.cannotActionSelf(channel).queue();
|
messages().getRegularMessage("general/error/cannot_interact")
|
||||||
return;
|
.apply(MessageHelper.member("target", target))
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
predicate = predicate.and(e -> e.getValue().getWarned().getIdLong() == target.getIdLong());
|
predicate = predicate.and(e -> e.getValue().getWarned().getIdLong() == target.getIdLong());
|
||||||
}
|
}
|
||||||
if (filterModerator) {
|
if (filterModerator) {
|
||||||
final List<Member> members = getMembers("moderator", ctx).fromGuild(performer.getGuild());
|
final List<Member> members = getMembers("moderator", ctx).fromGuild(performer.getGuild());
|
||||||
if (members.size() < 1) return;
|
if (members.size() < 1) return 1;
|
||||||
final Member mod = members.get(0);
|
final Member mod = members.get(0);
|
||||||
predicate = predicate.and(e -> e.getValue().getPerformer().getIdLong() == mod.getIdLong());
|
predicate = predicate.and(e -> e.getValue().getPerformer().getIdLong() == mod.getIdLong());
|
||||||
}
|
}
|
||||||
|
|
||||||
final OffsetDateTime dateTime = OffsetDateTime.now();
|
if (!performer.hasPermission(WARN_PERMISSION)) {
|
||||||
|
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||||
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
.with("required_permissions", WARN_PERMISSION::toString)
|
||||||
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
if (!performer.hasPermission(WARN_PERMISSION))
|
} else {
|
||||||
messages().MODERATION.ERRORS.performerInsufficientPermissions(channel, performer, WARN_PERMISSION).queue();
|
messages().<Map.Entry<Integer, WarningEntry>>getListingMessage("moderation/warn/list")
|
||||||
else
|
.apply(MessageHelper.member("performer", performer))
|
||||||
messages().MODERATION.warnList(channel, WarningStorage.get(getBot().getStorage(), guild)
|
.amountPerPage(8)
|
||||||
.getWarnings()
|
.setEntryApplier((entry, subs) -> subs
|
||||||
.entrySet().stream()
|
.with("warning_entry.case_id", () -> String.valueOf(entry.getKey()))
|
||||||
.filter(predicate)
|
.apply(user("warning_entry.performer", entry.getValue().getPerformer()))
|
||||||
.collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue))
|
.apply(user("warning_entry.warned", entry.getValue().getWarned()))
|
||||||
).queue();
|
.with("warning_entry.date_time", () -> entry.getValue().getDateTime().format(DATE_TIME_FORMAT))
|
||||||
|
.with("warning_entry.reason", entry.getValue()::getReason)
|
||||||
|
)
|
||||||
|
.build(channel, getBot(), ctx.getSource().getMessage(),
|
||||||
|
WarningStorage.get(getBot().getStorage(), guild)
|
||||||
|
.getWarnings()
|
||||||
|
.entrySet().stream()
|
||||||
|
.filter(predicate)
|
||||||
|
.sorted(Comparator.<Map.Entry<Integer, WarningEntry>>comparingInt(Map.Entry::getKey).reversed())
|
||||||
|
.collect(ImmutableList.toImmutableList())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,12 @@ import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
import net.dv8tion.jda.api.requests.restaction.AuditableRestAction;
|
import net.dv8tion.jda.api.requests.restaction.AuditableRestAction;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
import java.time.format.DateTimeFormatter;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import static sciwhiz12.janitor.msg.MessageHelper.DATE_TIME_FORMAT;
|
||||||
import static sciwhiz12.janitor.utils.Util.nameFor;
|
import static sciwhiz12.janitor.utils.Util.nameFor;
|
||||||
|
|
||||||
public class ModerationHelper {
|
public class ModerationHelper {
|
||||||
|
@ -18,7 +18,7 @@ public class ModerationHelper {
|
||||||
auditReason.append("Kicked by ")
|
auditReason.append("Kicked by ")
|
||||||
.append(nameFor(performer.getUser()))
|
.append(nameFor(performer.getUser()))
|
||||||
.append(" on ")
|
.append(" on ")
|
||||||
.append(Instant.now().atOffset(ZoneOffset.UTC).format(DateTimeFormatter.RFC_1123_DATE_TIME));
|
.append(Instant.now().atOffset(ZoneOffset.UTC).format(DATE_TIME_FORMAT));
|
||||||
if (reason != null)
|
if (reason != null)
|
||||||
auditReason.append(" for reason: ").append(reason);
|
auditReason.append(" for reason: ").append(reason);
|
||||||
return guild.kick(target, auditReason.toString());
|
return guild.kick(target, auditReason.toString());
|
||||||
|
@ -30,7 +30,7 @@ public class ModerationHelper {
|
||||||
auditReason.append("Banned by ")
|
auditReason.append("Banned by ")
|
||||||
.append(nameFor(performer.getUser()))
|
.append(nameFor(performer.getUser()))
|
||||||
.append(" on ")
|
.append(" on ")
|
||||||
.append(Instant.now().atOffset(ZoneOffset.UTC).format(DateTimeFormatter.RFC_1123_DATE_TIME));
|
.append(Instant.now().atOffset(ZoneOffset.UTC).format(DATE_TIME_FORMAT));
|
||||||
if (reason != null)
|
if (reason != null)
|
||||||
auditReason.append(" for reason: ").append(reason);
|
auditReason.append(" for reason: ").append(reason);
|
||||||
return guild.ban(target, deleteDuration, auditReason.toString());
|
return guild.ban(target, deleteDuration, auditReason.toString());
|
||||||
|
|
|
@ -4,11 +4,11 @@ import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||||
import com.electronwill.nightconfig.core.file.FileNotFoundAction;
|
import com.electronwill.nightconfig.core.file.FileNotFoundAction;
|
||||||
import com.electronwill.nightconfig.core.file.FileWatcher;
|
import com.electronwill.nightconfig.core.file.FileWatcher;
|
||||||
import com.electronwill.nightconfig.toml.TomlFormat;
|
import com.electronwill.nightconfig.toml.TomlFormat;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static sciwhiz12.janitor.Logging.CONFIG;
|
import static sciwhiz12.janitor.Logging.CONFIG;
|
||||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||||
|
@ -23,6 +23,7 @@ public class BotConfig {
|
||||||
public final CommentedConfigSpec.IntValue AUTOSAVE_INTERVAL;
|
public final CommentedConfigSpec.IntValue AUTOSAVE_INTERVAL;
|
||||||
|
|
||||||
public final CommentedConfigSpec.ConfigValue<String> CUSTOM_TRANSLATION_FILE;
|
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.ConfigValue<String> COMMAND_PREFIX;
|
||||||
|
|
||||||
|
@ -67,6 +68,10 @@ public class BotConfig {
|
||||||
.comment("A file which contains custom translation keys to load for messages.",
|
.comment("A file which contains custom translation keys to load for messages.",
|
||||||
"If blank, no file shall be loaded.")
|
"If blank, no file shall be loaded.")
|
||||||
.define("messages.custom_translations", "");
|
.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.")
|
||||||
|
.define("messages.custom_messages", "");
|
||||||
|
|
||||||
COMMAND_PREFIX = builder
|
COMMAND_PREFIX = builder
|
||||||
.comment("The prefix for commands.")
|
.comment("The prefix for commands.")
|
||||||
|
@ -115,8 +120,7 @@ public class BotConfig {
|
||||||
spec.setConfig(config);
|
spec.setConfig(config);
|
||||||
// TODO: config spec
|
// TODO: config spec
|
||||||
FileWatcher.defaultInstance().addWatch(configPath, this::onFileChange);
|
FileWatcher.defaultInstance().addWatch(configPath, this::onFileChange);
|
||||||
}
|
} catch (IOException ex) {
|
||||||
catch (IOException ex) {
|
|
||||||
JANITOR.error("Error while building config from file {}", configPath, ex);
|
JANITOR.error("Error while building config from file {}", configPath, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,6 +138,15 @@ public class BotConfig {
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Path getMessagesFolder() {
|
||||||
|
return options.getMessagesFolder().
|
||||||
|
or(() -> CUSTOM_MESSAGES_DIRECTORY.get().isBlank() ?
|
||||||
|
Optional.empty() :
|
||||||
|
Optional.of(Path.of(CUSTOM_MESSAGES_DIRECTORY.get())))
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
public String getToken() {
|
public String getToken() {
|
||||||
return options.getToken().orElse(CLIENT_TOKEN.get());
|
return options.getToken().orElse(CLIENT_TOKEN.get());
|
||||||
}
|
}
|
||||||
|
@ -157,8 +170,7 @@ public class BotConfig {
|
||||||
CONFIG.info("Reloading config due to file change {}", configPath);
|
CONFIG.info("Reloading config due to file change {}", configPath);
|
||||||
config.load();
|
config.load();
|
||||||
spec.setConfig(config);
|
spec.setConfig(config);
|
||||||
}
|
} catch (Exception ex) {
|
||||||
catch (Exception ex) {
|
|
||||||
CONFIG.error("Error while reloading config from {}", configPath, ex);
|
CONFIG.error("Error while reloading config from {}", configPath, ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ public class BotOptions {
|
||||||
private final OptionSet options;
|
private final OptionSet options;
|
||||||
private final ArgumentAcceptingOptionSpec<Path> configPath;
|
private final ArgumentAcceptingOptionSpec<Path> configPath;
|
||||||
private final ArgumentAcceptingOptionSpec<Path> translationsPath;
|
private final ArgumentAcceptingOptionSpec<Path> translationsPath;
|
||||||
|
private final ArgumentAcceptingOptionSpec<Path> messagesFolder;
|
||||||
private final ArgumentAcceptingOptionSpec<String> token;
|
private final ArgumentAcceptingOptionSpec<String> token;
|
||||||
private final ArgumentAcceptingOptionSpec<String> prefix;
|
private final ArgumentAcceptingOptionSpec<String> prefix;
|
||||||
private final ArgumentAcceptingOptionSpec<Long> owner;
|
private final ArgumentAcceptingOptionSpec<Long> owner;
|
||||||
|
@ -28,6 +29,10 @@ public class BotOptions {
|
||||||
.accepts("translations", "The path to the translations file")
|
.accepts("translations", "The path to the translations file")
|
||||||
.withRequiredArg()
|
.withRequiredArg()
|
||||||
.withValuesConvertedBy(new PathConverter(FILE_EXISTING, READABLE));
|
.withValuesConvertedBy(new PathConverter(FILE_EXISTING, READABLE));
|
||||||
|
this.messagesFolder = parser
|
||||||
|
.accepts("translations", "The path to the custom messages folder")
|
||||||
|
.withRequiredArg()
|
||||||
|
.withValuesConvertedBy(new PathConverter(DIRECTORY_EXISTING, READABLE));
|
||||||
this.token = parser
|
this.token = parser
|
||||||
.accepts("token", "The Discord token for the bot user")
|
.accepts("token", "The Discord token for the bot user")
|
||||||
.withRequiredArg();
|
.withRequiredArg();
|
||||||
|
@ -49,6 +54,10 @@ public class BotOptions {
|
||||||
return translationsPath.valueOptional(options);
|
return translationsPath.valueOptional(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<Path> getMessagesFolder() {
|
||||||
|
return messagesFolder.valueOptional(options);
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<String> getToken() {
|
public Optional<String> getToken() {
|
||||||
return token.valueOptional(options);
|
return token.valueOptional(options);
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,8 +134,7 @@ public class CommentedConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableC
|
||||||
try {
|
try {
|
||||||
isCorrecting = true;
|
isCorrecting = true;
|
||||||
ret = correct(this.config, config, parentPath, Collections.unmodifiableList(parentPath), listener, false);
|
ret = correct(this.config, config, parentPath, Collections.unmodifiableList(parentPath), listener, false);
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
isCorrecting = false;
|
isCorrecting = false;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -420,8 +419,7 @@ public class CommentedConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableC
|
||||||
try {
|
try {
|
||||||
//noinspection SuspiciousMethodCalls
|
//noinspection SuspiciousMethodCalls
|
||||||
return acceptableValues.contains(converter.get(obj, defaultValue.getClass()));
|
return acceptableValues.contains(converter.get(obj, defaultValue.getClass()));
|
||||||
}
|
} catch (IllegalArgumentException | ClassCastException e) {
|
||||||
catch (IllegalArgumentException | ClassCastException e) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
package sciwhiz12.janitor.moderation.notes;
|
package sciwhiz12.janitor.moderation.notes;
|
||||||
|
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
import com.google.gson.JsonDeserializer;
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
import com.google.gson.JsonElement;
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
import com.google.gson.JsonObject;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.google.gson.JsonParseException;
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
import com.google.gson.JsonSerializationContext;
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||||
import com.google.gson.JsonSerializer;
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||||
import net.dv8tion.jda.api.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.JanitorBot;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.io.IOException;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class NoteEntry {
|
public class NoteEntry {
|
||||||
private final User performer;
|
private final User performer;
|
||||||
|
@ -59,32 +60,42 @@ public class NoteEntry {
|
||||||
return Objects.hash(getPerformer(), getTarget(), getDateTime(), getContents());
|
return Objects.hash(getPerformer(), getTarget(), getDateTime(), getContents());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Serializer implements JsonDeserializer<NoteEntry>, JsonSerializer<NoteEntry> {
|
public static class Serializer extends StdSerializer<NoteEntry> {
|
||||||
private final JanitorBot bot;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public Serializer(JanitorBot bot) {
|
public Serializer() {
|
||||||
|
super(NoteEntry.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(NoteEntry value, JsonGenerator gen, SerializerProvider provider) throws IOException {
|
||||||
|
gen.writeStartObject();
|
||||||
|
gen.writeNumberField("performer", value.getPerformer().getIdLong());
|
||||||
|
gen.writeNumberField("target", value.getTarget().getIdLong());
|
||||||
|
gen.writeStringField("dateTime", value.getDateTime().toString());
|
||||||
|
gen.writeStringField("contents", value.getContents());
|
||||||
|
gen.writeEndObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Deserializer extends StdDeserializer<NoteEntry> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final Supplier<JanitorBot> bot;
|
||||||
|
|
||||||
|
public Deserializer(Supplier<JanitorBot> bot) {
|
||||||
|
super(NoteEntry.class);
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NoteEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
public NoteEntry deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
|
||||||
throws JsonParseException {
|
final JsonNode obj = ctx.readTree(p);
|
||||||
final JsonObject obj = json.getAsJsonObject();
|
User performer = bot.get().getDiscord().retrieveUserById(obj.get("performer").asLong()).complete();
|
||||||
final User performer = bot.getDiscord().retrieveUserById(obj.get("performer").getAsLong()).complete();
|
User target = bot.get().getDiscord().retrieveUserById(obj.get("target").asLong()).complete();
|
||||||
final User target = bot.getDiscord().retrieveUserById(obj.get("target").getAsLong()).complete();
|
OffsetDateTime dateTime = OffsetDateTime.parse(obj.get("dateTime").asText());
|
||||||
final OffsetDateTime dateTime = OffsetDateTime.parse(obj.get("dateTime").getAsString());
|
String contents = obj.get("contents").asText();
|
||||||
final String reason = obj.get("contents").getAsString();
|
return new NoteEntry(performer, target, dateTime, contents);
|
||||||
return new NoteEntry(performer, target, dateTime, reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonElement serialize(NoteEntry src, Type typeOfSrc, JsonSerializationContext context) {
|
|
||||||
final JsonObject obj = new JsonObject();
|
|
||||||
obj.addProperty("performer", src.getPerformer().getId());
|
|
||||||
obj.addProperty("target", src.getTarget().getId());
|
|
||||||
obj.addProperty("dateTime", src.getDateTime().toString());
|
|
||||||
obj.addProperty("contents", src.getContents());
|
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package sciwhiz12.janitor.moderation.notes;
|
package sciwhiz12.janitor.moderation.notes;
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.utils.ObservedMap;
|
import com.electronwill.nightconfig.core.utils.ObservedMap;
|
||||||
import com.google.gson.Gson;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.google.gson.JsonElement;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.gson.JsonObject;
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
@ -14,28 +14,24 @@ import sciwhiz12.janitor.storage.GuildStorage;
|
||||||
import sciwhiz12.janitor.storage.JsonStorage;
|
import sciwhiz12.janitor.storage.JsonStorage;
|
||||||
import sciwhiz12.janitor.storage.StorageKey;
|
import sciwhiz12.janitor.storage.StorageKey;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class NoteStorage extends JsonStorage {
|
public class NoteStorage extends JsonStorage {
|
||||||
private static final Type NOTE_MAP_TYPE = new TypeToken<Map<Integer, NoteEntry>>() {}.getType();
|
private static final TypeReference<Map<Integer, NoteEntry>> NOTE_MAP_TYPE = new TypeReference<>() {};
|
||||||
public static final StorageKey<NoteStorage> KEY = new StorageKey<>("notes", NoteStorage.class);
|
public static final StorageKey<NoteStorage> KEY = new StorageKey<>("notes", NoteStorage.class);
|
||||||
|
|
||||||
public static NoteStorage get(GuildStorage storage, Guild guild) {
|
public static NoteStorage get(GuildStorage storage, Guild guild) {
|
||||||
return storage.getOrCreate(guild, KEY, () -> new NoteStorage(storage.getBot()));
|
return storage.getOrCreate(guild, KEY, () -> new NoteStorage(storage.getBot()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Gson gson;
|
|
||||||
private final JanitorBot bot;
|
private final JanitorBot bot;
|
||||||
private int lastID = 1;
|
private int lastID = 1;
|
||||||
private final Map<Integer, NoteEntry> notes = new ObservedMap<>(new HashMap<>(), this::markDirty);
|
private final Map<Integer, NoteEntry> notes = new ObservedMap<>(new HashMap<>(), this::markDirty);
|
||||||
|
|
||||||
public NoteStorage(JanitorBot bot) {
|
public NoteStorage(JanitorBot bot) {
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
this.gson = new GsonBuilder()
|
|
||||||
.registerTypeAdapter(NoteEntry.class, new NoteEntry.Serializer(bot))
|
|
||||||
.create();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JanitorBot getBot() {
|
public JanitorBot getBot() {
|
||||||
|
@ -53,14 +49,14 @@ public class NoteStorage extends JsonStorage {
|
||||||
return notes.get(noteID);
|
return notes.get(noteID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NoteEntry removeNote(int noteID) {
|
public void removeNote(int noteID) {
|
||||||
return notes.remove(noteID);
|
notes.remove(noteID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAmountOfNotes(User target) {
|
public int getAmountOfNotes(User target) {
|
||||||
return (int) notes.values().stream()
|
return (int) notes.values().stream()
|
||||||
.filter(entry -> entry.getTarget() == target)
|
.filter(entry -> entry.getTarget() == target)
|
||||||
.count();
|
.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Integer, NoteEntry> getNotes() {
|
public Map<Integer, NoteEntry> getNotes() {
|
||||||
|
@ -68,18 +64,27 @@ public class NoteStorage extends JsonStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonElement save() {
|
protected void initialize(ObjectMapper mapper) {
|
||||||
JsonObject obj = new JsonObject();
|
super.initialize(mapper);
|
||||||
obj.addProperty("lastNoteID", lastID);
|
mapper.registerModule(
|
||||||
obj.add("notes", gson.toJsonTree(notes));
|
new SimpleModule()
|
||||||
|
.addSerializer(NoteEntry.class, new NoteEntry.Serializer())
|
||||||
|
.addDeserializer(NoteEntry.class, new NoteEntry.Deserializer(this::getBot))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonNode save(ObjectMapper mapper) {
|
||||||
|
final ObjectNode obj = mapper.createObjectNode();
|
||||||
|
obj.put("lastNoteID", lastID);
|
||||||
|
obj.set("notes", mapper.valueToTree(notes));
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(JsonElement in) {
|
public void load(JsonNode in, ObjectMapper mapper) throws IOException {
|
||||||
final JsonObject obj = in.getAsJsonObject();
|
lastID = in.get("lastNoteID").asInt();
|
||||||
lastID = obj.get("lastNoteID").getAsInt();
|
final Map<Integer, NoteEntry> loaded = mapper.readerFor(NOTE_MAP_TYPE).readValue(in.get("notes"));
|
||||||
final Map<Integer, NoteEntry> loaded = gson.fromJson(obj.get("notes"), NOTE_MAP_TYPE);
|
|
||||||
notes.clear();
|
notes.clear();
|
||||||
notes.putAll(loaded);
|
notes.putAll(loaded);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
package sciwhiz12.janitor.moderation.warns;
|
package sciwhiz12.janitor.moderation.warns;
|
||||||
|
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
import com.google.gson.JsonDeserializer;
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
import com.google.gson.JsonElement;
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
import com.google.gson.JsonObject;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.google.gson.JsonParseException;
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
import com.google.gson.JsonSerializationContext;
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||||
import com.google.gson.JsonSerializer;
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||||
import net.dv8tion.jda.api.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.JanitorBot;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.io.IOException;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class WarningEntry {
|
public class WarningEntry {
|
||||||
|
@ -62,35 +63,42 @@ public class WarningEntry {
|
||||||
return Objects.hash(getPerformer(), getWarned(), getDateTime(), getReason());
|
return Objects.hash(getPerformer(), getWarned(), getDateTime(), getReason());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Serializer implements JsonDeserializer<WarningEntry>, JsonSerializer<WarningEntry> {
|
public static class Serializer extends StdSerializer<WarningEntry> {
|
||||||
private final JanitorBot bot;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public Serializer(JanitorBot bot) {
|
public Serializer() {
|
||||||
|
super(WarningEntry.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(WarningEntry value, JsonGenerator gen, SerializerProvider provider) throws IOException {
|
||||||
|
gen.writeStartObject();
|
||||||
|
gen.writeNumberField("performer", value.getPerformer().getIdLong());
|
||||||
|
gen.writeNumberField("warned", value.getWarned().getIdLong());
|
||||||
|
gen.writeStringField("dateTime", value.getDateTime().toString());
|
||||||
|
gen.writeStringField("reason", value.getReason());
|
||||||
|
gen.writeEndObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Deserializer extends StdDeserializer<WarningEntry> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final Supplier<JanitorBot> bot;
|
||||||
|
|
||||||
|
public Deserializer(Supplier<JanitorBot> bot) {
|
||||||
|
super(WarningEntry.class);
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public WarningEntry deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
public WarningEntry deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
|
||||||
throws JsonParseException {
|
final JsonNode obj = ctx.readTree(p);
|
||||||
final JsonObject obj = json.getAsJsonObject();
|
User performer = bot.get().getDiscord().retrieveUserById(obj.get("performer").asLong()).complete();
|
||||||
final User warned = bot.getDiscord().retrieveUserById(obj.get("warned").getAsLong()).complete();
|
User warned = bot.get().getDiscord().retrieveUserById(obj.get("warned").asLong()).complete();
|
||||||
final User performer = bot.getDiscord().retrieveUserById(obj.get("performer").getAsLong()).complete();
|
OffsetDateTime dateTime = OffsetDateTime.parse(obj.get("dateTime").asText());
|
||||||
final OffsetDateTime dateTime = OffsetDateTime.parse(obj.get("dateTime").getAsString());
|
String contents = obj.get("reason").asText();
|
||||||
@Nullable
|
return new WarningEntry(performer, warned, dateTime, contents);
|
||||||
final String reason = obj.has("reason") ? obj.get("reason").getAsString() : null;
|
|
||||||
return new WarningEntry(warned, performer, dateTime, reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonElement serialize(WarningEntry src, Type typeOfSrc, JsonSerializationContext context) {
|
|
||||||
final JsonObject obj = new JsonObject();
|
|
||||||
obj.addProperty("warned", src.getWarned().getId());
|
|
||||||
obj.addProperty("performer", src.getPerformer().getId());
|
|
||||||
obj.addProperty("dateTime", src.getDateTime().toString());
|
|
||||||
if (src.getReason() != null) {
|
|
||||||
obj.addProperty("reason", src.getReason());
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package sciwhiz12.janitor.moderation.warns;
|
package sciwhiz12.janitor.moderation.warns;
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.utils.ObservedMap;
|
import com.electronwill.nightconfig.core.utils.ObservedMap;
|
||||||
import com.google.gson.Gson;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.google.gson.JsonElement;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.gson.JsonObject;
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.JanitorBot;
|
||||||
|
@ -13,28 +13,23 @@ import sciwhiz12.janitor.storage.GuildStorage;
|
||||||
import sciwhiz12.janitor.storage.JsonStorage;
|
import sciwhiz12.janitor.storage.JsonStorage;
|
||||||
import sciwhiz12.janitor.storage.StorageKey;
|
import sciwhiz12.janitor.storage.StorageKey;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class WarningStorage extends JsonStorage {
|
public class WarningStorage extends JsonStorage {
|
||||||
private static final Type WARNING_MAP_TYPE = new TypeToken<Map<Integer, WarningEntry>>() {}.getType();
|
private static final TypeReference<Map<Integer, WarningEntry>> WARNING_MAP_TYPE = new TypeReference<>() {};
|
||||||
public static final StorageKey<WarningStorage> KEY = new StorageKey<>("warnings", WarningStorage.class);
|
public static final StorageKey<WarningStorage> KEY = new StorageKey<>("warnings", WarningStorage.class);
|
||||||
|
|
||||||
public static WarningStorage get(GuildStorage storage, Guild guild) {
|
public static WarningStorage get(GuildStorage storage, Guild guild) {
|
||||||
return storage.getOrCreate(guild, KEY, () -> new WarningStorage(storage.getBot()));
|
return storage.getOrCreate(guild, KEY, () -> new WarningStorage(storage.getBot()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Gson gson;
|
|
||||||
private final JanitorBot bot;
|
private final JanitorBot bot;
|
||||||
private int lastID = 1;
|
private int lastID = 1;
|
||||||
private final Map<Integer, WarningEntry> warnings = new ObservedMap<>(new HashMap<>(), this::markDirty);
|
private final Map<Integer, WarningEntry> warnings = new ObservedMap<>(new HashMap<>(), this::markDirty);
|
||||||
|
|
||||||
public WarningStorage(JanitorBot bot) {
|
public WarningStorage(JanitorBot bot) {
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
this.gson = new GsonBuilder()
|
|
||||||
.registerTypeAdapter(WarningEntry.class, new WarningEntry.Serializer(bot))
|
|
||||||
.create();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JanitorBot getBot() {
|
public JanitorBot getBot() {
|
||||||
|
@ -52,8 +47,8 @@ public class WarningStorage extends JsonStorage {
|
||||||
return warnings.get(caseID);
|
return warnings.get(caseID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WarningEntry removeWarning(int caseID) {
|
public void removeWarning(int caseID) {
|
||||||
return warnings.remove(caseID);
|
warnings.remove(caseID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<Integer, WarningEntry> getWarnings() {
|
public Map<Integer, WarningEntry> getWarnings() {
|
||||||
|
@ -61,18 +56,27 @@ public class WarningStorage extends JsonStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonElement save() {
|
protected void initialize(ObjectMapper mapper) {
|
||||||
JsonObject obj = new JsonObject();
|
super.initialize(mapper);
|
||||||
obj.addProperty("lastCaseID", lastID);
|
mapper.registerModule(
|
||||||
obj.add("warnings", gson.toJsonTree(warnings));
|
new SimpleModule()
|
||||||
|
.addSerializer(WarningEntry.class, new WarningEntry.Serializer())
|
||||||
|
.addDeserializer(WarningEntry.class, new WarningEntry.Deserializer(this::getBot))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JsonNode save(ObjectMapper mapper) {
|
||||||
|
final ObjectNode obj = mapper.createObjectNode();
|
||||||
|
obj.put("lastCaseID", lastID);
|
||||||
|
obj.set("warnings", mapper.valueToTree(warnings));
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(JsonElement in) {
|
public void load(JsonNode in, ObjectMapper mapper) {
|
||||||
final JsonObject obj = in.getAsJsonObject();
|
lastID = in.get("lastCaseID").asInt();
|
||||||
lastID = obj.get("lastCaseID").getAsInt();
|
final Map<Integer, WarningEntry> loaded = mapper.convertValue(in.get("warnings"), WARNING_MAP_TYPE);
|
||||||
final Map<Integer, WarningEntry> loaded = gson.fromJson(obj.get("warnings"), WARNING_MAP_TYPE);
|
|
||||||
warnings.clear();
|
warnings.clear();
|
||||||
warnings.putAll(loaded);
|
warnings.putAll(loaded);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
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 java.util.EnumSet;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public final class General {
|
|
||||||
private final Messages messages;
|
|
||||||
|
|
||||||
General(Messages messages) {
|
|
||||||
this.messages = messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String translate(String key, Object... args) {
|
|
||||||
return messages.translate(key, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestAction<Message> guildOnlyCommand(MessageChannel channel) {
|
|
||||||
return channel.sendMessage(
|
|
||||||
messages.failureEmbed(translate("general.guild_only_command.title"))
|
|
||||||
.setDescription(translate("general.guild_only_command.desc"))
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestAction<Message> insufficientPermissions(MessageChannel channel, EnumSet<Permission> 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 RestAction<Message> ambiguousMember(MessageChannel channel) {
|
|
||||||
return channel.sendMessage(
|
|
||||||
messages.failureEmbed(translate("general.ambiguous_member.title"))
|
|
||||||
.setDescription(translate("general.ambiguous_member.desc"))
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestAction<Message> 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 RestAction<Message> cannotActionSelf(MessageChannel channel) {
|
|
||||||
return channel.sendMessage(
|
|
||||||
messages.failureEmbed(translate("general.cannot_action_self.title"))
|
|
||||||
.setDescription(translate("general.cannot_action_self.desc"))
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RestAction<Message> 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()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
161
src/main/java/sciwhiz12/janitor/msg/ListingMessageBuilder.java
Normal file
161
src/main/java/sciwhiz12/janitor/msg/ListingMessageBuilder.java
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
package sciwhiz12.janitor.msg;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder;
|
||||||
|
import net.dv8tion.jda.api.Permission;
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||||
|
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.SubstitutionMap;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ListingMessageBuilder<T> implements IHasCustomSubstitutions<ListingMessageBuilder<T>> {
|
||||||
|
private final ListingMessage message;
|
||||||
|
private final Map<String, Supplier<String>> customSubstitutions;
|
||||||
|
private int amountPerPage = 10;
|
||||||
|
private BiConsumer<T, CustomSubstitutions> entryApplier = (entry, sub) -> {};
|
||||||
|
|
||||||
|
public ListingMessageBuilder(ListingMessage message, Map<String, Supplier<String>> customSubstitutions) {
|
||||||
|
this.message = message;
|
||||||
|
this.customSubstitutions = customSubstitutions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListingMessageBuilder(ListingMessage message) {
|
||||||
|
this(message, new HashMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListingMessageBuilder<T> amountPerPage(int amountPerPage) {
|
||||||
|
this.amountPerPage = amountPerPage;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListingMessageBuilder<T> setEntryApplier(BiConsumer<T, CustomSubstitutions> entryApplier) {
|
||||||
|
this.entryApplier = entryApplier;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListingMessageBuilder<T> apply(Consumer<ListingMessageBuilder<T>> consumer) {
|
||||||
|
consumer.accept(this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListingMessageBuilder<T> with(final String argument, final Supplier<String> value) {
|
||||||
|
this.customSubstitutions.put(argument, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void build(MessageChannel channel, TranslationMap translations, 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)
|
||||||
|
.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))
|
||||||
|
)
|
||||||
|
.queue();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.add("\u274c", (msg, event) -> { // CLOSE
|
||||||
|
event.getChannel().deleteMessageById(event.getMessageIdLong())
|
||||||
|
.flatMap(v -> !triggerMessage.isFromGuild() ||
|
||||||
|
event.getGuild().getSelfMember()
|
||||||
|
.hasPermission(triggerMessage.getTextChannel(),
|
||||||
|
Permission.MESSAGE_MANAGE),
|
||||||
|
v -> triggerMessage.delete())
|
||||||
|
.queue();
|
||||||
|
})
|
||||||
|
.add("\u27a1", (msg, event) -> { // NEXT
|
||||||
|
if (pagedMessage.advancePage(PageDirection.NEXT)) {
|
||||||
|
event.retrieveMessage()
|
||||||
|
.flatMap(eventMsg -> eventMsg.editMessage(
|
||||||
|
pagedMessage.createMessage(translations, customSubs, entryApplier))
|
||||||
|
)
|
||||||
|
.queue();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.create()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void build(MessageChannel channel, JanitorBot bot, Message triggerMessage, List<T> entries) {
|
||||||
|
build(channel, bot.getTranslations(), bot.getSubstitutions(), triggerMessage, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PagedMessage {
|
||||||
|
private final ListingMessage message;
|
||||||
|
private final ImmutableList<T> list;
|
||||||
|
private final int maxPages;
|
||||||
|
private final int amountPerPage;
|
||||||
|
private int currentPage = 0;
|
||||||
|
private int lastPage = -1;
|
||||||
|
private EmbedBuilder cachedMessage;
|
||||||
|
|
||||||
|
PagedMessage(ListingMessage message, ImmutableList<T> list, int amountPerPage) {
|
||||||
|
this.message = message;
|
||||||
|
this.list = list;
|
||||||
|
this.amountPerPage = amountPerPage;
|
||||||
|
this.maxPages = Math.floorDiv(list.size(), ListingMessageBuilder.this.amountPerPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxPages() {
|
||||||
|
return maxPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCurrentPage() {
|
||||||
|
return currentPage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean advancePage(PageDirection direction) {
|
||||||
|
if (direction == PageDirection.PREVIOUS && currentPage > 0) {
|
||||||
|
currentPage -= 1;
|
||||||
|
return true;
|
||||||
|
} else if (direction == PageDirection.NEXT && currentPage < maxPages) {
|
||||||
|
currentPage += 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageEmbed createMessage(TranslationMap translations, 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)),
|
||||||
|
list.stream()
|
||||||
|
.skip(currentPage * amountPerPage)
|
||||||
|
.limit(amountPerPage)
|
||||||
|
.collect(Collectors.toList()),
|
||||||
|
applier);
|
||||||
|
lastPage = currentPage;
|
||||||
|
}
|
||||||
|
return cachedMessage.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PageDirection {
|
||||||
|
PREVIOUS, NEXT
|
||||||
|
}
|
||||||
|
}
|
111
src/main/java/sciwhiz12/janitor/msg/MessageHelper.java
Normal file
111
src/main/java/sciwhiz12/janitor/msg/MessageHelper.java
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
package sciwhiz12.janitor.msg;
|
||||||
|
|
||||||
|
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.moderation.notes.NoteEntry;
|
||||||
|
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||||
|
import sciwhiz12.janitor.msg.substitution.IHasCustomSubstitutions;
|
||||||
|
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeFormatterBuilder;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import static java.time.temporal.ChronoField.*;
|
||||||
|
|
||||||
|
public class MessageHelper {
|
||||||
|
private MessageHelper() {}
|
||||||
|
|
||||||
|
public static <T extends IHasCustomSubstitutions<?>> 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
|
||||||
|
.apply(snowflake(head, mentionable))
|
||||||
|
.with(head + ".mention", mentionable::getAsMention);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> role(String head, Role role) {
|
||||||
|
return builder -> builder
|
||||||
|
.apply(mentionable(head, role))
|
||||||
|
.with(head + ".color_hex", () -> Integer.toHexString(role.getColorRaw()))
|
||||||
|
.with(head + ".name", role::getName)
|
||||||
|
.with(head + ".permissions", role.getPermissions()::toString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> user(String head, User user) {
|
||||||
|
return builder -> builder
|
||||||
|
.apply(mentionable(head, user))
|
||||||
|
.with(head + ".name", user::getName)
|
||||||
|
.with(head + ".discriminator", user::getDiscriminator)
|
||||||
|
.with(head + ".tag", user::getAsTag)
|
||||||
|
.with(head + ".flags", user.getFlags()::toString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> guild(String head, Guild guild) {
|
||||||
|
return builder -> builder
|
||||||
|
.apply(snowflake(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)
|
||||||
|
.with(head + ".icon_url", guild::getIconUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> member(String head, Member member) {
|
||||||
|
return builder -> builder
|
||||||
|
.apply(user(head, member.getUser()))
|
||||||
|
.apply(guild(head + ".guild", member.getGuild()))
|
||||||
|
.with(head + ".nickname", member::getNickname)
|
||||||
|
.with(head + ".effective_name", member::getEffectiveName)
|
||||||
|
.with(head + ".join_datetime", () -> member.getTimeJoined().format(DATE_TIME_FORMAT))
|
||||||
|
.with(head + ".color", () -> String.valueOf(member.getColorRaw()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends IHasCustomSubstitutions<?>> 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()))
|
||||||
|
.apply(user(head + ".target", entry.getWarned()))
|
||||||
|
.with(head + ".date_time", () -> entry.getDateTime().format(DATE_TIME_FORMAT))
|
||||||
|
.with(head + ".reason", entry::getReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends IHasCustomSubstitutions<?>> 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()))
|
||||||
|
.apply(user(head + ".target", entry.getTarget()))
|
||||||
|
.with(head + ".date_time", () -> entry.getDateTime().format(DATE_TIME_FORMAT))
|
||||||
|
.with(head + ".contents", entry::getContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final DateTimeFormatter DATE_TIME_FORMAT = new DateTimeFormatterBuilder()
|
||||||
|
.parseCaseInsensitive()
|
||||||
|
.parseLenient()
|
||||||
|
.appendValue(YEAR, 4) // 2 digit year not handled
|
||||||
|
.appendLiteral('-')
|
||||||
|
.appendValue(MONTH_OF_YEAR, 2)
|
||||||
|
.appendLiteral('-')
|
||||||
|
.appendValue(DAY_OF_MONTH, 2)
|
||||||
|
.appendLiteral(' ')
|
||||||
|
.appendValue(HOUR_OF_DAY, 2)
|
||||||
|
.appendLiteral(':')
|
||||||
|
.appendValue(MINUTE_OF_HOUR, 2)
|
||||||
|
.optionalStart()
|
||||||
|
.appendLiteral(':')
|
||||||
|
.appendValue(SECOND_OF_MINUTE, 2)
|
||||||
|
.optionalEnd()
|
||||||
|
.appendLiteral(' ')
|
||||||
|
.appendOffset("+HHMM", "GMT")
|
||||||
|
.toFormatter();
|
||||||
|
}
|
|
@ -1,32 +1,161 @@
|
||||||
package sciwhiz12.janitor.msg;
|
package sciwhiz12.janitor.msg;
|
||||||
|
|
||||||
import net.dv8tion.jda.api.EmbedBuilder;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.JanitorBot;
|
||||||
|
import sciwhiz12.janitor.msg.json.ListingMessage;
|
||||||
|
import sciwhiz12.janitor.msg.json.RegularMessage;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.io.IOException;
|
||||||
import java.time.ZoneOffset;
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.nio.file.FileSystems;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.google.common.io.Resources.getResource;
|
||||||
|
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||||
|
import static sciwhiz12.janitor.Logging.MESSAGES;
|
||||||
|
|
||||||
public class Messages {
|
public class Messages {
|
||||||
public static final int FAILURE_COLOR = 0xF73132;
|
public static final String JSON_FILE_SUFFIX = ".json";
|
||||||
|
public static final String MESSAGES_FILENAME = "messages";
|
||||||
|
public static final String DEFAULT_MESSAGES_FOLDER = "messages/";
|
||||||
|
public static final TypeReference<List<String>> LIST_TYPE = new TypeReference<>() {};
|
||||||
|
|
||||||
private final JanitorBot bot;
|
private final JanitorBot bot;
|
||||||
public final General GENERAL;
|
private final Path messagesFolder;
|
||||||
public final Moderation MODERATION;
|
private final Map<String, RegularMessage> regularMessages = new HashMap<>();
|
||||||
|
private final Map<String, ListingMessage> listingMessages = new HashMap<>();
|
||||||
|
private final ObjectMapper jsonMapper = new ObjectMapper();
|
||||||
|
|
||||||
public Messages(JanitorBot bot) {
|
public Messages(JanitorBot bot, Path messagesFolder) {
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
this.GENERAL = new General(this);
|
this.messagesFolder = messagesFolder;
|
||||||
this.MODERATION = new Moderation(this);
|
loadMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String translate(String key, Object... args) {
|
public JanitorBot getBot() {
|
||||||
return bot.getTranslations().translate(key, args);
|
return bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmbedBuilder failureEmbed(String title) {
|
public void loadMessages() {
|
||||||
return new EmbedBuilder()
|
boolean success = false;
|
||||||
.setTitle(title)
|
|
||||||
.setColor(FAILURE_COLOR)
|
if (messagesFolder != null) {
|
||||||
.setTimestamp(OffsetDateTime.now(ZoneOffset.UTC));
|
JANITOR.debug(MESSAGES, "Loading messages from folder {}", messagesFolder);
|
||||||
|
success = loadMessages(
|
||||||
|
path -> Files.newBufferedReader(messagesFolder.resolve(path + JSON_FILE_SUFFIX))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
JANITOR.info(MESSAGES, "No custom messages folder specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
JANITOR.info(MESSAGES, "Loading default messages");
|
||||||
|
//noinspection UnstableApiUsage
|
||||||
|
loadMessages(
|
||||||
|
file -> new InputStreamReader(getResource(DEFAULT_MESSAGES_FOLDER + file + JSON_FILE_SUFFIX).openStream())
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean loadMessages(FileOpener files) {
|
||||||
|
try (Reader keyReader = files.open(MESSAGES_FILENAME)) {
|
||||||
|
List<String> keysList = jsonMapper.readValue(keyReader, LIST_TYPE);
|
||||||
|
regularMessages.clear();
|
||||||
|
for (String messageKey : keysList) {
|
||||||
|
final String path = messageKey.replace("/", FileSystems.getDefault().getSeparator());
|
||||||
|
try (Reader reader = files.open(path)) {
|
||||||
|
final JsonNode tree = jsonMapper.readTree(reader);
|
||||||
|
final String type = tree.path("type").asText("regular");
|
||||||
|
if ("regular".equals(type)) {
|
||||||
|
regularMessages.put(messageKey, jsonMapper.convertValue(tree, RegularMessage.class));
|
||||||
|
} else if ("listing".equals(type)) {
|
||||||
|
listingMessages.put(messageKey, jsonMapper.convertValue(tree, ListingMessage.class));
|
||||||
|
} else {
|
||||||
|
JANITOR.warn(MESSAGES, "Unknown message type {} for {}", tree.path("type").asText(), messageKey);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
JANITOR.error(MESSAGES, "Error while loading message {}", path, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JANITOR.info(MESSAGES, "Loaded {} messages", regularMessages.size());
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
JANITOR.error(MESSAGES, "Error while loading messages", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, RegularMessage> getRegularMessages() {
|
||||||
|
return Collections.unmodifiableMap(regularMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegularMessageBuilder getRegularMessage(String messageKey) {
|
||||||
|
final RegularMessage msg = regularMessages.get(messageKey);
|
||||||
|
if (msg == null) {
|
||||||
|
JANITOR.warn(MESSAGES, "Attempted to get unknown regular message with key {}", messageKey);
|
||||||
|
return new RegularMessageBuilder(UNKNOWN_REGULAR_MESSAGE).with("key", () -> messageKey);
|
||||||
|
}
|
||||||
|
return new RegularMessageBuilder(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, ListingMessage> getListingMessages() {
|
||||||
|
return listingMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> ListingMessageBuilder<T> getListingMessage(String messageKey) {
|
||||||
|
final ListingMessage msg = listingMessages.get(messageKey);
|
||||||
|
if (msg == null) {
|
||||||
|
JANITOR.warn(MESSAGES, "Attempted to get unknown listing message with key {}", messageKey);
|
||||||
|
return new ListingMessageBuilder<T>(UNKNOWN_LISTING_MESSAGE).with("key", () -> messageKey);
|
||||||
|
}
|
||||||
|
return new ListingMessageBuilder<>(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FileOpener {
|
||||||
|
Reader open(String filePath) throws IOException;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.",
|
||||||
|
String.valueOf(0xFF0000),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
Collections.singletonList(new MessageEmbed.Field("Message Key", "${key}", false))
|
||||||
|
);
|
||||||
|
|
||||||
|
public static final ListingMessage UNKNOWN_LISTING_MESSAGE = new ListingMessage(
|
||||||
|
"UNKNOWN MESSAGE!",
|
||||||
|
null,
|
||||||
|
"A listing message was tried to be looked up, but was not found. " +
|
||||||
|
"Please report this to your bot maintainer/administrator.",
|
||||||
|
String.valueOf(0xFF0000),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
new ListingMessage.DescriptionEntry(null, ""),
|
||||||
|
Collections.singletonList(new MessageEmbed.Field("Message Key", "${key}", false)),
|
||||||
|
Collections.emptyList()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,318 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
||||||
import static java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME;
|
|
||||||
|
|
||||||
public final class Moderation {
|
|
||||||
public static final int MODERATION_COLOR = 0xF1BD25;
|
|
||||||
public static final String GAVEL_ICON_URL = "https://cdn.discordapp.com/attachments/738478941760782526" +
|
|
||||||
"/760463743330549760/gavel.png";
|
|
||||||
|
|
||||||
private final Messages messages;
|
|
||||||
public final Errors ERRORS;
|
|
||||||
|
|
||||||
Moderation(Messages messages) {
|
|
||||||
this.messages = messages;
|
|
||||||
ERRORS = new Errors();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String translate(String key, Object... args) {
|
|
||||||
return messages.translate(key, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 class Errors {
|
|
||||||
private Errors() {}
|
|
||||||
|
|
||||||
public MessageAction performerInsufficientPermissions(MessageChannel channel, Member performer,
|
|
||||||
EnumSet<Permission> 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<Integer, WarningEntry> 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<Integer, NoteEntry> 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()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package sciwhiz12.janitor.msg;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||||
|
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.SubstitutionMap;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class RegularMessageBuilder implements IHasCustomSubstitutions<RegularMessageBuilder> {
|
||||||
|
private final RegularMessage message;
|
||||||
|
private final Map<String, Supplier<String>> customSubstitutions;
|
||||||
|
|
||||||
|
public RegularMessageBuilder(RegularMessage message, Map<String, Supplier<String>> customSubstitutions) {
|
||||||
|
this.message = message;
|
||||||
|
this.customSubstitutions = customSubstitutions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegularMessageBuilder(RegularMessage message) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegularMessageBuilder with(final String argument, final Supplier<String> value) {
|
||||||
|
customSubstitutions.put(argument, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageEmbed build(TranslationMap translations, SubstitutionMap substitutions) {
|
||||||
|
return message.create(translations, substitutions.with(customSubstitutions)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageEmbed build(JanitorBot bot) {
|
||||||
|
return build(bot.getTranslations(), bot.getSubstitutions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageAction send(JanitorBot bot, MessageChannel channel) {
|
||||||
|
return channel.sendMessage(build(bot));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +1,35 @@
|
||||||
package sciwhiz12.janitor.msg;
|
package sciwhiz12.janitor.msg;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.common.io.Resources;
|
import com.google.common.io.Resources;
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.JanitorBot;
|
||||||
|
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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.JANITOR;
|
||||||
import static sciwhiz12.janitor.Logging.TRANSLATIONS;
|
import static sciwhiz12.janitor.Logging.TRANSLATIONS;
|
||||||
|
|
||||||
public class Translations {
|
public class TranslationMap {
|
||||||
private static final Gson GSON = new GsonBuilder().create();
|
public static final Pattern TRANSLATION_REGEX = Pattern.compile("<(.+?)>", CASE_INSENSITIVE);
|
||||||
private static final String DEFAULT_TRANSLATIONS_RESOURCE = "english.json";
|
private static final String DEFAULT_TRANSLATIONS_RESOURCE = "english.json";
|
||||||
private static final Type MAP_TYPE = new TypeToken<Map<String, String>>() {}.getType();
|
private static final TypeReference<Map<String, String>> MAP_TYPE = new TypeReference<>() {};
|
||||||
|
|
||||||
private final JanitorBot bot;
|
private final JanitorBot bot;
|
||||||
private final Path translationsFile;
|
private final Path translationsFile;
|
||||||
private final Map<String, String> translations = new HashMap<>();
|
private final Map<String, String> translations = new HashMap<>();
|
||||||
|
private final ObjectMapper jsonMapper = new ObjectMapper();
|
||||||
|
|
||||||
public Translations(JanitorBot bot, Path translationsFile) {
|
public TranslationMap(JanitorBot bot, Path translationsFile) {
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
this.translationsFile = translationsFile;
|
this.translationsFile = translationsFile;
|
||||||
loadTranslations();
|
loadTranslations();
|
||||||
|
@ -40,12 +43,11 @@ public class Translations {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
JANITOR.debug(TRANSLATIONS, "Loading translations from file {}", translationsFile);
|
JANITOR.debug(TRANSLATIONS, "Loading translations from file {}", translationsFile);
|
||||||
Map<String, String> trans = GSON.fromJson(Files.newBufferedReader(translationsFile), MAP_TYPE);
|
Map<String, String> trans = jsonMapper.readValue(Files.newBufferedReader(translationsFile), MAP_TYPE);
|
||||||
translations.clear();
|
translations.clear();
|
||||||
translations.putAll(trans);
|
translations.putAll(trans);
|
||||||
JANITOR.info(TRANSLATIONS, "Loaded {} translations from file {}", translations.size(), translationsFile);
|
JANITOR.info(TRANSLATIONS, "Loaded {} translations from file {}", translations.size(), translationsFile);
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e) {
|
|
||||||
JANITOR.error(TRANSLATIONS, "Error while loading translations from file {}", translationsFile, e);
|
JANITOR.error(TRANSLATIONS, "Error while loading translations from file {}", translationsFile, e);
|
||||||
loadDefaultTranslations();
|
loadDefaultTranslations();
|
||||||
}
|
}
|
||||||
|
@ -55,14 +57,13 @@ public class Translations {
|
||||||
try {
|
try {
|
||||||
JANITOR.debug(TRANSLATIONS, "Loading default english translations");
|
JANITOR.debug(TRANSLATIONS, "Loading default english translations");
|
||||||
// noinspection UnstableApiUsage
|
// noinspection UnstableApiUsage
|
||||||
Map<String, String> trans = GSON.fromJson(
|
Map<String, String> trans = jsonMapper.readValue(
|
||||||
new InputStreamReader(Resources.getResource(DEFAULT_TRANSLATIONS_RESOURCE).openStream()),
|
new InputStreamReader(Resources.getResource(DEFAULT_TRANSLATIONS_RESOURCE).openStream()),
|
||||||
MAP_TYPE);
|
MAP_TYPE);
|
||||||
translations.clear();
|
translations.clear();
|
||||||
translations.putAll(trans);
|
translations.putAll(trans);
|
||||||
JANITOR.info(TRANSLATIONS, "Loaded {} default english translations", translations.size());
|
JANITOR.info(TRANSLATIONS, "Loaded {} default english translations", translations.size());
|
||||||
}
|
} catch (Exception e) {
|
||||||
catch (Exception e) {
|
|
||||||
JANITOR.error(TRANSLATIONS, "Error while loading default english translations", e);
|
JANITOR.error(TRANSLATIONS, "Error while loading default english translations", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,7 +72,13 @@ public class Translations {
|
||||||
return Collections.unmodifiableMap(translations);
|
return Collections.unmodifiableMap(translations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String translate(String key, Object... args) {
|
public String translate(String text) {
|
||||||
return String.format(translations.getOrDefault(key, key), args);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package sciwhiz12.janitor.msg.emote;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import net.dv8tion.jda.api.events.message.MessageDeleteEvent;
|
||||||
|
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||||
|
import sciwhiz12.janitor.JanitorBot;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
public class ReactionManager extends ListenerAdapter {
|
||||||
|
private final JanitorBot bot;
|
||||||
|
private final Map<Long, ReactionMessage> messageMap = new HashMap<>();
|
||||||
|
|
||||||
|
public ReactionManager(JanitorBot bot) {
|
||||||
|
this.bot = bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReactionMessage newMessage(Message message) {
|
||||||
|
if (messageMap.containsKey(message.getIdLong())) {
|
||||||
|
throw new IllegalArgumentException("Reaction message already exists for message with id " + message.getIdLong());
|
||||||
|
}
|
||||||
|
final ReactionMessage msg = new ReactionMessage(bot, message);
|
||||||
|
messageMap.put(message.getIdLong(), msg);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeMessage(long messageID) {
|
||||||
|
bot.getDiscord().removeEventListener(messageMap.remove(messageID));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Long, ReactionMessage> getRegisteredMessages() {
|
||||||
|
return messageMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessageDelete(@Nonnull MessageDeleteEvent event) {
|
||||||
|
if (messageMap.containsKey(event.getMessageIdLong())) {
|
||||||
|
bot.getDiscord().removeEventListener(messageMap.get(event.getMessageIdLong()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
112
src/main/java/sciwhiz12/janitor/msg/emote/ReactionMessage.java
Normal file
112
src/main/java/sciwhiz12/janitor/msg/emote/ReactionMessage.java
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
package sciwhiz12.janitor.msg.emote;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Emote;
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import net.dv8tion.jda.api.entities.MessageReaction.ReactionEmote;
|
||||||
|
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
|
||||||
|
import net.dv8tion.jda.api.exceptions.ErrorHandler;
|
||||||
|
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||||
|
import net.dv8tion.jda.api.requests.ErrorResponse;
|
||||||
|
import sciwhiz12.janitor.JanitorBot;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
import static net.dv8tion.jda.api.Permission.MESSAGE_MANAGE;
|
||||||
|
|
||||||
|
public class ReactionMessage extends ListenerAdapter {
|
||||||
|
private final JanitorBot bot;
|
||||||
|
private final Message message;
|
||||||
|
private final Map<ReactionEmote, IReactionListener> emotes = new LinkedHashMap<>();
|
||||||
|
private boolean removeEmotes = true;
|
||||||
|
private long ownerID;
|
||||||
|
private boolean onlyOwner;
|
||||||
|
|
||||||
|
public ReactionMessage(JanitorBot bot, Message message, boolean onlyOwner, long ownerID) {
|
||||||
|
this.bot = bot;
|
||||||
|
this.message = message;
|
||||||
|
this.ownerID = ownerID;
|
||||||
|
this.onlyOwner = onlyOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReactionMessage(JanitorBot bot, Message message) {
|
||||||
|
this(bot, message, false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReactionMessage add(ReactionEmote emote, IReactionListener listener) {
|
||||||
|
emotes.put(emote, listener);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReactionMessage add(String emote, IReactionListener listener) {
|
||||||
|
return add(ReactionEmote.fromUnicode(emote, bot.getDiscord()), listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReactionMessage add(Emote emote, IReactionListener listener) {
|
||||||
|
return add(ReactionEmote.fromCustom(emote), listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReactionMessage removeEmotes(boolean remove) {
|
||||||
|
this.removeEmotes = remove;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReactionMessage owner(long ownerID) {
|
||||||
|
this.ownerID = ownerID;
|
||||||
|
this.onlyOwner = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void create() {
|
||||||
|
for (ReactionEmote reaction : emotes.keySet()) {
|
||||||
|
if (reaction.isEmote()) {
|
||||||
|
message.addReaction(reaction.getEmote()).queue();
|
||||||
|
} else {
|
||||||
|
message.addReaction(reaction.getEmoji()).queue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bot.getDiscord().addEventListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessageReactionAdd(@Nonnull MessageReactionAddEvent event) {
|
||||||
|
if (event.getMessageIdLong() != message.getIdLong()) return;
|
||||||
|
if (event.getUserIdLong() == bot.getDiscord().getSelfUser().getIdLong()) return;
|
||||||
|
if (onlyOwner && event.getUserIdLong() != ownerID) return;
|
||||||
|
|
||||||
|
emotes.keySet().stream()
|
||||||
|
.filter(emote -> event.getReactionEmote().equals(emote))
|
||||||
|
.forEach(emote -> emotes.get(emote).accept(this, event));
|
||||||
|
|
||||||
|
if (removeEmotes && (!event.isFromGuild()
|
||||||
|
|| event.getGuild().getSelfMember().hasPermission(event.getTextChannel(), MESSAGE_MANAGE))) {
|
||||||
|
event.retrieveUser()
|
||||||
|
.flatMap(user -> event.getReaction().removeReaction(user))
|
||||||
|
.queue(null, new ErrorHandler().ignore(ErrorResponse.UNKNOWN_MESSAGE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JanitorBot getBot() {
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getOwnerID() {
|
||||||
|
return ownerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOwnerOnly() {
|
||||||
|
return onlyOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<ReactionEmote, IReactionListener> getListeners() {
|
||||||
|
return Collections.unmodifiableMap(emotes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface IReactionListener extends BiConsumer<ReactionMessage, MessageReactionAddEvent> {
|
||||||
|
void accept(ReactionMessage message, MessageReactionAddEvent event);
|
||||||
|
}
|
||||||
|
}
|
254
src/main/java/sciwhiz12/janitor/msg/json/ListingMessage.java
Normal file
254
src/main/java/sciwhiz12/janitor/msg/json/ListingMessage.java
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
package sciwhiz12.janitor.msg.json;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
|
import com.google.common.primitives.Ints;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@JsonDeserialize(using = ListingMessageDeserializer.class)
|
||||||
|
public class ListingMessage {
|
||||||
|
@Nullable protected final String title;
|
||||||
|
@Nullable protected final String url;
|
||||||
|
@Nullable protected final String description;
|
||||||
|
@Nullable protected final String color;
|
||||||
|
@Nullable protected final String authorName;
|
||||||
|
@Nullable protected final String authorUrl;
|
||||||
|
@Nullable protected final String authorIconUrl;
|
||||||
|
@Nullable protected final String footerText;
|
||||||
|
@Nullable protected final String footerIconUrl;
|
||||||
|
@Nullable protected final String imageUrl;
|
||||||
|
@Nullable protected final String thumbnailUrl;
|
||||||
|
@Nullable protected final String emptyText;
|
||||||
|
protected final Entry entry;
|
||||||
|
protected final List<MessageEmbed.Field> beforeFields;
|
||||||
|
protected final List<MessageEmbed.Field> afterFields;
|
||||||
|
|
||||||
|
public ListingMessage(
|
||||||
|
@Nullable String title,
|
||||||
|
@Nullable String url,
|
||||||
|
@Nullable String description,
|
||||||
|
@Nullable String color,
|
||||||
|
@Nullable String authorName,
|
||||||
|
@Nullable String authorUrl,
|
||||||
|
@Nullable String authorIconUrl,
|
||||||
|
@Nullable String footerText,
|
||||||
|
@Nullable String footerIconUrl,
|
||||||
|
@Nullable String imageUrl,
|
||||||
|
@Nullable String thumbnailUrl,
|
||||||
|
@Nullable String emptyText,
|
||||||
|
Entry entry,
|
||||||
|
List<MessageEmbed.Field> beforeFields,
|
||||||
|
List<MessageEmbed.Field> afterFields
|
||||||
|
) {
|
||||||
|
this.title = title;
|
||||||
|
this.url = url;
|
||||||
|
this.description = description;
|
||||||
|
this.color = color;
|
||||||
|
this.authorName = authorName;
|
||||||
|
this.authorUrl = authorUrl;
|
||||||
|
this.authorIconUrl = authorIconUrl;
|
||||||
|
this.footerText = footerText;
|
||||||
|
this.footerIconUrl = footerIconUrl;
|
||||||
|
this.imageUrl = imageUrl;
|
||||||
|
this.thumbnailUrl = thumbnailUrl;
|
||||||
|
this.emptyText = emptyText;
|
||||||
|
this.entry = entry;
|
||||||
|
this.beforeFields = beforeFields;
|
||||||
|
this.afterFields = afterFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getAuthorName() {
|
||||||
|
return authorName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getAuthorUrl() {
|
||||||
|
return authorUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getAuthorIconUrl() {
|
||||||
|
return authorIconUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getFooterText() {
|
||||||
|
return footerText;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getFooterIconUrl() {
|
||||||
|
return footerIconUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getImageUrl() {
|
||||||
|
return imageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getThumbnailUrl() {
|
||||||
|
return thumbnailUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getEmptyText() {
|
||||||
|
return emptyText;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entry getEntry() {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MessageEmbed.Field> getBeforeFields() {
|
||||||
|
return beforeFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MessageEmbed.Field> getAfterFields() {
|
||||||
|
return afterFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.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.setTimestamp(OffsetDateTime.now(ZoneOffset.UTC));
|
||||||
|
builder.setFooter(func.apply(footerText), func.apply(footerIconUrl));
|
||||||
|
for (MessageEmbed.Field field : beforeFields) {
|
||||||
|
builder.addField(func.apply(field.getName()), func.apply(field.getValue()), field.isInline());
|
||||||
|
}
|
||||||
|
|
||||||
|
final CustomSubstitutions entrySubs = new CustomSubstitutions();
|
||||||
|
final Function<String, String> entryFunc = str -> str != null ? entrySubs.substitute(func.apply(str)) : null;
|
||||||
|
int count = 0;
|
||||||
|
for (T listEntry : iterable) {
|
||||||
|
entryApplier.accept(listEntry, entrySubs);
|
||||||
|
if (entry instanceof FieldEntry) {
|
||||||
|
FieldEntry fieldEntry = (FieldEntry) entry;
|
||||||
|
builder.addField(
|
||||||
|
entryFunc.apply(fieldEntry.getFieldName()),
|
||||||
|
entryFunc.apply(fieldEntry.getFieldValue()),
|
||||||
|
fieldEntry.isInline()
|
||||||
|
);
|
||||||
|
} else if (entry instanceof DescriptionEntry) {
|
||||||
|
DescriptionEntry descEntry = (DescriptionEntry) entry;
|
||||||
|
builder.getDescriptionBuilder().append(entryFunc.apply(descEntry.getDescription()));
|
||||||
|
builder.getDescriptionBuilder().append(descEntry.getJoiner());
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (count < 1) {
|
||||||
|
builder.getDescriptionBuilder().append(func.apply(emptyText));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MessageEmbed.Field field : afterFields) {
|
||||||
|
builder.addField(func.apply(field.getName()), func.apply(field.getValue()), field.isInline());
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int parseColor(String str) {
|
||||||
|
if (Strings.isNullOrEmpty(str)) return Role.DEFAULT_COLOR_RAW;
|
||||||
|
if (str.startsWith("0x")) {
|
||||||
|
// noinspection UnstableApiUsage
|
||||||
|
final Integer res = Ints.tryParse(str.substring(2), 16);
|
||||||
|
if (res != null) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// noinspection UnstableApiUsage
|
||||||
|
final Integer res = Ints.tryParse(str, 10);
|
||||||
|
if (res != null) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return Role.DEFAULT_COLOR_RAW;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Entry {}
|
||||||
|
|
||||||
|
public static class DescriptionEntry implements Entry {
|
||||||
|
public static final String DEFAULT_JOINER = "\n";
|
||||||
|
private final String joiner;
|
||||||
|
private final String descriptionEntry;
|
||||||
|
|
||||||
|
public DescriptionEntry(@Nullable String joiner, String descriptionEntry) {
|
||||||
|
this.joiner = joiner != null ? joiner : DEFAULT_JOINER;
|
||||||
|
this.descriptionEntry = descriptionEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJoiner() {
|
||||||
|
return joiner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return descriptionEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FieldEntry implements Entry {
|
||||||
|
private final String fieldName;
|
||||||
|
private final String fieldValue;
|
||||||
|
private final boolean inline;
|
||||||
|
|
||||||
|
public FieldEntry(String fieldName, String fieldValue, boolean inline) {
|
||||||
|
this.fieldName = fieldName;
|
||||||
|
this.fieldValue = fieldValue;
|
||||||
|
this.inline = inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldName() {
|
||||||
|
return fieldName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFieldValue() {
|
||||||
|
return fieldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInline() {
|
||||||
|
return inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
package sciwhiz12.janitor.msg.json;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder;
|
||||||
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class ListingMessageDeserializer extends StdDeserializer<ListingMessage> {
|
||||||
|
public ListingMessageDeserializer() {
|
||||||
|
super(ListingMessage.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListingMessage deserialize(JsonParser p, DeserializationContext ctx)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
final JsonNode root = ctx.readTree(p);
|
||||||
|
|
||||||
|
String title = null;
|
||||||
|
String url = null;
|
||||||
|
String description = root.path("description").asText(null);
|
||||||
|
String color = root.path("color").asText(null);
|
||||||
|
String authorName = null;
|
||||||
|
String authorUrl = null;
|
||||||
|
String authorIconUrl = null;
|
||||||
|
String footerText = null;
|
||||||
|
String footerIconUrl = null;
|
||||||
|
String imageUrl = root.path("image").asText(null);
|
||||||
|
String thumbnailUrl = root.path("thumbnail").asText(null);
|
||||||
|
String emptyText = root.path("empty").asText(null);
|
||||||
|
List<MessageEmbed.Field> beforeFields = readFields(root.path("fields").path("before"));
|
||||||
|
List<MessageEmbed.Field> afterFields = readFields(root.path("fields").path("after"));
|
||||||
|
|
||||||
|
// Title
|
||||||
|
if (root.path("title").isTextual()) {
|
||||||
|
title = root.path("title").asText();
|
||||||
|
} else if (root.path("title").path("text").isTextual()) {
|
||||||
|
title = root.path("title").path("text").asText();
|
||||||
|
url = root.path("title").path("url").asText(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Author
|
||||||
|
if (root.path("author").isTextual()) {
|
||||||
|
authorName = root.path("author").asText();
|
||||||
|
} else if (root.path("author").path("name").isTextual()) {
|
||||||
|
authorName = root.path("author").path("name").asText();
|
||||||
|
authorUrl = root.path("author").path("url").asText(null);
|
||||||
|
authorIconUrl = root.path("author").path("icon_url").asText(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
if (root.path("footer").isTextual()) {
|
||||||
|
footerText = root.path("footer").asText();
|
||||||
|
} else if (root.path("footer").path("text").isTextual()) {
|
||||||
|
footerText = root.path("footer").path("text").asText();
|
||||||
|
footerIconUrl = root.path("footer").path("icon_url").asText(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ENTRY
|
||||||
|
final ListingMessage.Entry entry = readEntry(root.path("entry"));
|
||||||
|
|
||||||
|
return new ListingMessage(title, url, description, color, authorName, authorUrl, authorIconUrl, footerText,
|
||||||
|
footerIconUrl, imageUrl, thumbnailUrl, emptyText, entry, beforeFields, afterFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ListingMessage.Entry readEntry(JsonNode root) {
|
||||||
|
switch (root.path("type").asText()) {
|
||||||
|
case "field": {
|
||||||
|
return new ListingMessage.FieldEntry(
|
||||||
|
root.path("name").asText(EmbedBuilder.ZERO_WIDTH_SPACE),
|
||||||
|
root.path("value").asText(EmbedBuilder.ZERO_WIDTH_SPACE),
|
||||||
|
root.path("inline").asBoolean(false)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
case "description": {
|
||||||
|
return new ListingMessage.DescriptionEntry(
|
||||||
|
root.path("joiner").asText(null),
|
||||||
|
root.path("text").asText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MessageEmbed.Field> readFields(JsonNode node) {
|
||||||
|
if (node.isArray()) {
|
||||||
|
final ArrayList<MessageEmbed.Field> fields = new ArrayList<>();
|
||||||
|
for (int i = 0; i < node.size(); i++) {
|
||||||
|
final MessageEmbed.Field field = readField(node.path(i));
|
||||||
|
if (field != null) {
|
||||||
|
fields.add(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static MessageEmbed.Field readField(JsonNode fieldNode) {
|
||||||
|
if (fieldNode.path("name").isTextual() && fieldNode.path("value").isTextual()) {
|
||||||
|
return new MessageEmbed.Field(
|
||||||
|
fieldNode.path("name").asText(),
|
||||||
|
fieldNode.path("value").asText(),
|
||||||
|
fieldNode.path("inline").asBoolean(false)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
212
src/main/java/sciwhiz12/janitor/msg/json/RegularMessage.java
Normal file
212
src/main/java/sciwhiz12/janitor/msg/json/RegularMessage.java
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
package sciwhiz12.janitor.msg.json;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
|
import com.google.common.primitives.Ints;
|
||||||
|
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;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
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)
|
||||||
|
public class RegularMessage {
|
||||||
|
@Nullable
|
||||||
|
protected final String title;
|
||||||
|
@Nullable
|
||||||
|
protected final String url;
|
||||||
|
@Nullable
|
||||||
|
protected final String description;
|
||||||
|
@Nullable
|
||||||
|
protected final String color;
|
||||||
|
@Nullable
|
||||||
|
protected final String authorName;
|
||||||
|
@Nullable
|
||||||
|
protected final String authorUrl;
|
||||||
|
@Nullable
|
||||||
|
protected final String authorIconUrl;
|
||||||
|
@Nullable
|
||||||
|
protected final String footerText;
|
||||||
|
@Nullable
|
||||||
|
protected final String footerIconUrl;
|
||||||
|
@Nullable
|
||||||
|
protected final String imageUrl;
|
||||||
|
@Nullable
|
||||||
|
protected final String thumbnailUrl;
|
||||||
|
protected final List<MessageEmbed.Field> fields;
|
||||||
|
|
||||||
|
public RegularMessage(
|
||||||
|
@Nullable String title,
|
||||||
|
@Nullable String url,
|
||||||
|
@Nullable String description,
|
||||||
|
@Nullable String color,
|
||||||
|
@Nullable String authorName,
|
||||||
|
@Nullable String authorUrl,
|
||||||
|
@Nullable String authorIconUrl,
|
||||||
|
@Nullable String footerText,
|
||||||
|
@Nullable String footerIconUrl,
|
||||||
|
@Nullable String imageUrl,
|
||||||
|
@Nullable String thumbnailUrl,
|
||||||
|
List<MessageEmbed.Field> fields
|
||||||
|
) {
|
||||||
|
this.title = title;
|
||||||
|
this.url = url;
|
||||||
|
this.description = description;
|
||||||
|
this.color = color;
|
||||||
|
this.authorName = authorName;
|
||||||
|
this.authorUrl = authorUrl;
|
||||||
|
this.authorIconUrl = authorIconUrl;
|
||||||
|
this.footerText = footerText;
|
||||||
|
this.footerIconUrl = footerIconUrl;
|
||||||
|
this.imageUrl = imageUrl;
|
||||||
|
this.thumbnailUrl = thumbnailUrl;
|
||||||
|
this.fields = new ArrayList<>(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getAuthorName() {
|
||||||
|
return authorName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getAuthorUrl() {
|
||||||
|
return authorUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getAuthorIconUrl() {
|
||||||
|
return authorIconUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getFooterText() {
|
||||||
|
return footerText;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getFooterIconUrl() {
|
||||||
|
return footerIconUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getImageUrl() {
|
||||||
|
return imageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getThumbnailUrl() {
|
||||||
|
return thumbnailUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MessageEmbed.Field> getFields() {
|
||||||
|
return Collections.unmodifiableList(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new StringJoiner(", ", RegularMessage.class.getSimpleName() + "[", "]")
|
||||||
|
.add("title='" + title + "'")
|
||||||
|
.add("url='" + url + "'")
|
||||||
|
.add("description='" + description + "'")
|
||||||
|
.add("color='" + color + "'")
|
||||||
|
.add("authorName='" + authorName + "'")
|
||||||
|
.add("authorUrl='" + authorUrl + "'")
|
||||||
|
.add("authorIconUrl='" + authorIconUrl + "'")
|
||||||
|
.add("footerText='" + footerText + "'")
|
||||||
|
.add("footerIconUrl='" + footerIconUrl + "'")
|
||||||
|
.add("imageUrl='" + imageUrl + "'")
|
||||||
|
.add("thumbnailUrl='" + thumbnailUrl + "'")
|
||||||
|
.add("fields=" + fields)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
RegularMessage that = (RegularMessage) o;
|
||||||
|
return Objects.equals(title, that.title) &&
|
||||||
|
Objects.equals(url, that.url) &&
|
||||||
|
Objects.equals(description, that.description) &&
|
||||||
|
Objects.equals(color, that.color) &&
|
||||||
|
Objects.equals(authorName, that.authorName) &&
|
||||||
|
Objects.equals(authorUrl, that.authorUrl) &&
|
||||||
|
Objects.equals(authorIconUrl, that.authorIconUrl) &&
|
||||||
|
Objects.equals(footerText, that.footerText) &&
|
||||||
|
Objects.equals(footerIconUrl, that.footerIconUrl) &&
|
||||||
|
Objects.equals(imageUrl, that.imageUrl) &&
|
||||||
|
Objects.equals(thumbnailUrl, that.thumbnailUrl) &&
|
||||||
|
fields.equals(that.fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects
|
||||||
|
.hash(title, url, description, color, authorName, authorUrl, authorIconUrl, footerText, footerIconUrl, imageUrl,
|
||||||
|
thumbnailUrl, fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmbedBuilder create(TranslationMap translations, ISubstitutor substitutions) {
|
||||||
|
final Function<String, String> func = str -> str != null ? substitutions.substitute(translations.translate(str)) : null;
|
||||||
|
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.setTimestamp(OffsetDateTime.now(ZoneOffset.UTC));
|
||||||
|
builder.setFooter(func.apply(footerText), func.apply(footerIconUrl));
|
||||||
|
for (MessageEmbed.Field field : fields) {
|
||||||
|
builder.addField(func.apply(field.getName()), func.apply(field.getValue()), field.isInline());
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int parseColor(String str) {
|
||||||
|
if (Strings.isNullOrEmpty(str)) return Role.DEFAULT_COLOR_RAW;
|
||||||
|
if (str.startsWith("0x")) {
|
||||||
|
// noinspection UnstableApiUsage
|
||||||
|
final Integer res = Ints.tryParse(str.substring(2), 16);
|
||||||
|
if (res != null) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// noinspection UnstableApiUsage
|
||||||
|
final Integer res = Ints.tryParse(str, 10);
|
||||||
|
if (res != null) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return Role.DEFAULT_COLOR_RAW;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
package sciwhiz12.janitor.msg.json;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||||
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class RegularMessageDeserializer extends StdDeserializer<RegularMessage> {
|
||||||
|
public RegularMessageDeserializer() {
|
||||||
|
super(RegularMessage.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RegularMessage deserialize(JsonParser p, DeserializationContext ctx)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
final JsonNode node = ctx.readTree(p);
|
||||||
|
|
||||||
|
String title = null;
|
||||||
|
String url = null;
|
||||||
|
String description = node.path("description").asText(null);
|
||||||
|
String color = node.path("color").asText(null);
|
||||||
|
String authorName = null;
|
||||||
|
String authorUrl = null;
|
||||||
|
String authorIconUrl = null;
|
||||||
|
String footerText = null;
|
||||||
|
String footerIconUrl = null;
|
||||||
|
String imageUrl = node.path("image").asText(null);
|
||||||
|
String thumbnailUrl = node.path("thumbnail").asText(null);
|
||||||
|
List<MessageEmbed.Field> fields = readFields(node);
|
||||||
|
|
||||||
|
// Title
|
||||||
|
if (node.path("title").isTextual()) {
|
||||||
|
title = node.path("title").asText();
|
||||||
|
} else if (node.path("title").path("text").isTextual()) {
|
||||||
|
title = node.path("title").path("text").asText();
|
||||||
|
url = node.path("title").path("url").asText(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Author
|
||||||
|
if (node.path("author").isTextual()) {
|
||||||
|
authorName = node.path("author").asText();
|
||||||
|
} else if (node.path("author").path("name").isTextual()) {
|
||||||
|
authorName = node.path("author").path("name").asText();
|
||||||
|
authorUrl = node.path("author").path("url").asText(null);
|
||||||
|
authorIconUrl = node.path("author").path("icon_url").asText(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Footer
|
||||||
|
if (node.path("footer").isTextual()) {
|
||||||
|
footerText = node.path("footer").asText();
|
||||||
|
} else if (node.path("footer").path("text").isTextual()) {
|
||||||
|
footerText = node.path("footer").path("text").asText();
|
||||||
|
footerIconUrl = node.path("footer").path("icon_url").asText(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RegularMessage(title, url, description, color, authorName, authorUrl,
|
||||||
|
authorIconUrl, footerText, footerIconUrl, imageUrl, thumbnailUrl, fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<MessageEmbed.Field> readFields(JsonNode node) {
|
||||||
|
if (node.path("fields").isArray()) {
|
||||||
|
final ArrayList<MessageEmbed.Field> fields = new ArrayList<>();
|
||||||
|
for (int i = 0; i < node.path("fields").size(); i++) {
|
||||||
|
final MessageEmbed.Field field = readField(node.path("fields").path(i));
|
||||||
|
if (field != null) {
|
||||||
|
fields.add(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static MessageEmbed.Field readField(JsonNode fieldNode) {
|
||||||
|
if (fieldNode.path("name").isTextual() && fieldNode.path("value").isTextual()) {
|
||||||
|
return new MessageEmbed.Field(
|
||||||
|
fieldNode.path("name").asText(),
|
||||||
|
fieldNode.path("value").asText(),
|
||||||
|
fieldNode.path("inline").asBoolean(false)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package sciwhiz12.janitor.msg.substitution;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.TransformerUtils;
|
||||||
|
import org.apache.commons.collections4.map.DefaultedMap;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class CustomSubstitutions implements ISubstitutor, IHasCustomSubstitutions<CustomSubstitutions> {
|
||||||
|
private final Map<String, Supplier<String>> map;
|
||||||
|
|
||||||
|
public CustomSubstitutions(Map<String, Supplier<String>> map) {
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomSubstitutions() {
|
||||||
|
this(new HashMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String substitute(String text) {
|
||||||
|
return SubstitutionMap.substitute(text, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomSubstitutions apply(Consumer<CustomSubstitutions> consumer) {
|
||||||
|
consumer.accept(this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomSubstitutions with(final String argument, final Supplier<String> value) {
|
||||||
|
map.put(argument, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomSubstitutions with(Map<String, Supplier<String>> customSubstitutions) {
|
||||||
|
return new CustomSubstitutions(createDefaultedMap(customSubstitutions));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Supplier<String>> createDefaultedMap(Map<String, Supplier<String>> custom) {
|
||||||
|
return DefaultedMap.defaultedMap(custom, TransformerUtils.mapTransformer(map));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Supplier<String>> getMap() {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package sciwhiz12.janitor.msg.substitution;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public interface IHasCustomSubstitutions<T extends IHasCustomSubstitutions<?>> {
|
||||||
|
T with(String argument, Supplier<String> value);
|
||||||
|
|
||||||
|
T apply(Consumer<T> consumer);
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package sciwhiz12.janitor.msg.substitution;
|
||||||
|
|
||||||
|
public interface ISubstitutor {
|
||||||
|
String substitute(String text);
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package sciwhiz12.janitor.msg.substitution;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.TransformerUtils;
|
||||||
|
import org.apache.commons.collections4.map.DefaultedMap;
|
||||||
|
import sciwhiz12.janitor.JanitorBot;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
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;
|
||||||
|
import static sciwhiz12.janitor.msg.MessageHelper.DATE_TIME_FORMAT;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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 quoteReplacement(arguments.getOrDefault(matchResult.group(1), () -> matchResult.group(0)).get());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private final JanitorBot bot;
|
||||||
|
private final Map<String, Supplier<String>> defaultSubstitutions = new HashMap<>();
|
||||||
|
|
||||||
|
public SubstitutionMap(JanitorBot bot) {
|
||||||
|
this.bot = bot;
|
||||||
|
defaultSubstitutions.put("time.now", () -> OffsetDateTime.now(ZoneOffset.UTC).format(DATE_TIME_FORMAT));
|
||||||
|
defaultSubstitutions.put("moderation.color", () -> "0xF1BD25");
|
||||||
|
defaultSubstitutions.put("moderation.icon_url",
|
||||||
|
() -> "https://cdn.discordapp.com/attachments/738478941760782526/760463743330549760/gavel.png");
|
||||||
|
defaultSubstitutions.put("general.error.color", () -> "0xF73132");
|
||||||
|
}
|
||||||
|
|
||||||
|
public JanitorBot getBot() {
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String substitute(String text) {
|
||||||
|
return SubstitutionMap.substitute(text, defaultSubstitutions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String with(String text, Map<String, Supplier<String>> substitutions) {
|
||||||
|
return SubstitutionMap.substitute(text, createDefaultedMap(substitutions));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomSubstitutions with(Map<String, Supplier<String>> customSubstitutions) {
|
||||||
|
return new CustomSubstitutions(createDefaultedMap(customSubstitutions));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Supplier<String>> createDefaultedMap(Map<String, Supplier<String>> custom) {
|
||||||
|
return DefaultedMap.defaultedMap(custom, TransformerUtils.mapTransformer(defaultSubstitutions));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
package sciwhiz12.janitor.storage;
|
package sciwhiz12.janitor.storage;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.JanitorBot;
|
||||||
import sciwhiz12.janitor.Logging;
|
import sciwhiz12.janitor.Logging;
|
||||||
|
@ -22,8 +20,6 @@ import static java.nio.file.StandardOpenOption.*;
|
||||||
* A storage system for guild-specific data.
|
* A storage system for guild-specific data.
|
||||||
*/
|
*/
|
||||||
public class GuildStorage {
|
public class GuildStorage {
|
||||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().serializeNulls().create();
|
|
||||||
|
|
||||||
private final JanitorBot bot;
|
private final JanitorBot bot;
|
||||||
private final Path mainFolder;
|
private final Path mainFolder;
|
||||||
private final Map<Long, Map<String, InnerStorage<?>>> guildStorages = new HashMap<>();
|
private final Map<Long, Map<String, InnerStorage<?>>> guildStorages = new HashMap<>();
|
||||||
|
@ -45,7 +41,7 @@ public class GuildStorage {
|
||||||
public <S extends IStorage> S getOrCreate(long guildID, StorageKey<S> key, Supplier<S> defaultSupplier) {
|
public <S extends IStorage> S getOrCreate(long guildID, StorageKey<S> key, Supplier<S> defaultSupplier) {
|
||||||
final Map<String, InnerStorage<?>> storageMappy = guildStorages.computeIfAbsent(guildID, id -> new HashMap<>());
|
final Map<String, InnerStorage<?>> storageMappy = guildStorages.computeIfAbsent(guildID, id -> new HashMap<>());
|
||||||
return key.getType().cast(storageMappy.computeIfAbsent(key.getStorageID(),
|
return key.getType().cast(storageMappy.computeIfAbsent(key.getStorageID(),
|
||||||
k -> new InnerStorage<>(key, load(guildID, key.getStorageID(), defaultSupplier.get()))).getStorage());
|
k -> new InnerStorage<>(key, load(guildID, key.getStorageID(), defaultSupplier.get()))).getStorage());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Path getFile(long guildID, String key) {
|
private Path getFile(long guildID, String key) {
|
||||||
|
@ -85,7 +81,7 @@ public class GuildStorage {
|
||||||
if (Files.notExists(file.getParent())) Files.createDirectories(file.getParent());
|
if (Files.notExists(file.getParent())) Files.createDirectories(file.getParent());
|
||||||
if (Files.notExists(file)) Files.createFile(file);
|
if (Files.notExists(file)) Files.createFile(file);
|
||||||
try (Writer writer = Files
|
try (Writer writer = Files
|
||||||
.newBufferedWriter(file, CREATE, WRITE, TRUNCATE_EXISTING)) {
|
.newBufferedWriter(file, CREATE, WRITE, TRUNCATE_EXISTING)) {
|
||||||
inner.getStorage().write(writer);
|
inner.getStorage().write(writer);
|
||||||
anySaved = true;
|
anySaved = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package sciwhiz12.janitor.storage;
|
package sciwhiz12.janitor.storage;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
|
||||||
|
@ -7,7 +8,7 @@ public interface IStorage {
|
||||||
|
|
||||||
boolean dirty();
|
boolean dirty();
|
||||||
|
|
||||||
void write(Writer output);
|
void write(Writer output) throws IOException;
|
||||||
|
|
||||||
void read(Reader input);
|
void read(Reader input) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,35 @@
|
||||||
package sciwhiz12.janitor.storage;
|
package sciwhiz12.janitor.storage;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.gson.JsonElement;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
|
||||||
public abstract class JsonStorage extends AbstractStorage {
|
public abstract class JsonStorage extends AbstractStorage {
|
||||||
public static final Gson GSON = new GsonBuilder()
|
protected final ObjectMapper jsonMapper = new ObjectMapper()
|
||||||
.serializeNulls()
|
.enable(SerializationFeature.INDENT_OUTPUT)
|
||||||
.setPrettyPrinting()
|
.enable(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
|
||||||
.create();
|
|
||||||
|
|
||||||
public abstract JsonElement save();
|
protected JsonStorage() {
|
||||||
|
initialize(jsonMapper);
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void load(JsonElement object);
|
protected void initialize(ObjectMapper mapper) {}
|
||||||
|
|
||||||
|
public abstract JsonNode save(ObjectMapper mapper);
|
||||||
|
|
||||||
|
public abstract void load(JsonNode object, ObjectMapper mapper) throws IOException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(Writer input) {
|
public void write(Writer input) throws IOException {
|
||||||
GSON.toJson(save(), input);
|
jsonMapper.writeTree(jsonMapper.createGenerator(input), save(jsonMapper));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(Reader input) {
|
public void read(Reader input) throws IOException {
|
||||||
load(JsonParser.parseReader(input));
|
load(jsonMapper.readTree(input), jsonMapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ public class StorageKey<S extends IStorage> {
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
StorageKey<?> that = (StorageKey<?>) o;
|
StorageKey<?> that = (StorageKey<?>) o;
|
||||||
return storageID.equals(that.storageID) &&
|
return storageID.equals(that.storageID) &&
|
||||||
type.equals(that.type);
|
type.equals(that.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -37,8 +37,7 @@ public class StringReaderUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final char SYNTAX_ESCAPE = '\\';
|
private static final char SYNTAX_ESCAPE = '\\';
|
||||||
private static final char SYNTAX_DOUBLE_QUOTE = '"';
|
|
||||||
private static final char SYNTAX_SINGLE_QUOTE = '\'';
|
|
||||||
public static String readStringUntil(StringReader reader, char terminator) throws CommandSyntaxException {
|
public static String readStringUntil(StringReader reader, char terminator) throws CommandSyntaxException {
|
||||||
final StringBuilder result = new StringBuilder();
|
final StringBuilder result = new StringBuilder();
|
||||||
boolean escaped = false;
|
boolean escaped = false;
|
||||||
|
@ -50,7 +49,8 @@ public class StringReaderUtil {
|
||||||
escaped = false;
|
escaped = false;
|
||||||
} else {
|
} else {
|
||||||
reader.setCursor(reader.getCursor() - 1);
|
reader.setCursor(reader.getCursor() - 1);
|
||||||
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.readerInvalidEscape().createWithContext(reader, String.valueOf(c));
|
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.readerInvalidEscape()
|
||||||
|
.createWithContext(reader, String.valueOf(c));
|
||||||
}
|
}
|
||||||
} else if (c == SYNTAX_ESCAPE) {
|
} else if (c == SYNTAX_ESCAPE) {
|
||||||
escaped = true;
|
escaped = true;
|
||||||
|
|
|
@ -55,8 +55,8 @@ public class Util {
|
||||||
return user.getName().concat("#").concat(user.getDiscriminator());
|
return user.getName().concat("#").concat(user.getDiscriminator());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <Success, Error> BiConsumer<Success, Error> handle(final Consumer<Success> success,
|
public static <Success, Err> BiConsumer<Success, Err> handle(final Consumer<Success> success,
|
||||||
final Consumer<Error> exceptionally) {
|
final Consumer<Err> exceptionally) {
|
||||||
return (suc, ex) -> {
|
return (suc, ex) -> {
|
||||||
if (ex == null) {
|
if (ex == null) {
|
||||||
success.accept(suc);
|
success.accept(suc);
|
||||||
|
|
|
@ -1,100 +1,100 @@
|
||||||
{
|
{
|
||||||
"general.guild_only_command.title": "Guild only command!",
|
"general.error.guild_only_command.title": "Guild only command!",
|
||||||
"general.guild_only_command.desc": "This command can only be run in a guild channel.",
|
"general.error.guild_only_command.description": "This command can only be run in a guild channel.",
|
||||||
"general.insufficient_permissions.title": "I have insufficient permissions!",
|
"general.error.ambiguous_member.title": "Ambiguous member argument!",
|
||||||
"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.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.insufficient_permissions.field.permissions": "Required permissions",
|
"general.error.insufficient_permissions.title": "I have insufficient permissions!",
|
||||||
"general.ambiguous_member.title": "Ambiguous member argument!",
|
"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.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.error.insufficient_permissions.field.permissions": "Required permissions",
|
||||||
"general.cannot_interact.title": "Member is higher than me!",
|
"general.error.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.error.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": "Target",
|
"general.error.cannot_interact.field.target": "Target",
|
||||||
"general.cannot_action_self.title": "Cannot act against myself!",
|
"general.error.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.error.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.error.cannot_action_performer.title": "Performer cannot act against self!",
|
||||||
"general.cannot_action_performer.desc": "You cannot perform this action against yourself.",
|
"general.error.cannot_action_performer.description": "You cannot perform this action against yourself.",
|
||||||
"general.cannot_action_performer.field.performer": "Performer/Target",
|
"general.error.cannot_action_performer.field.performer": "Performer/Target",
|
||||||
"moderation.insufficient_permissions.title": "Insufficient permissions.",
|
"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.description": "The performer of this command has insufficient permissions to use this command.",
|
||||||
"moderation.insufficient_permissions.field.performer": "Performer",
|
"moderation.insufficient_permissions.field.performer": "Performer",
|
||||||
"moderation.insufficient_permissions.field.permissions": "Required permissions",
|
"moderation.insufficient_permissions.field.permissions": "Required permissions",
|
||||||
"moderation.cannot_interact.title": "Cannot moderate Target.",
|
"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.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.performer": "Performer",
|
||||||
"moderation.cannot_interact.field.target": "Target",
|
"moderation.cannot_interact.field.target": "Target",
|
||||||
"moderation.kick.info.author": "Kicked user from server.",
|
"moderation.kick.info.author": "Kicked user from server.",
|
||||||
"moderation.kick.info.field.performer": "Performer",
|
"moderation.kick.info.field.performer": "Performer",
|
||||||
"moderation.kick.info.field.target": "Target",
|
"moderation.kick.info.field.target": "Target",
|
||||||
"moderation.kick.info.field.reason": "Reason",
|
"moderation.kick.info.field.private_message": "Sent DM",
|
||||||
"moderation.kick.info.field.sent_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.title": "You were kicked from this server.",
|
||||||
"moderation.kick.dm.field.performer": "Moderator",
|
"moderation.kick.dm.field.performer": "Moderator",
|
||||||
"moderation.kick.dm.field.reason": "Reason",
|
"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.author": "Banned user from server.",
|
||||||
"moderation.ban.info.field.performer": "Performer",
|
"moderation.ban.info.field.performer": "Performer",
|
||||||
"moderation.ban.info.field.target": "Target",
|
"moderation.ban.info.field.target": "Target",
|
||||||
"moderation.ban.info.field.reason": "Reason",
|
"moderation.ban.info.field.private_message": "Sent DM",
|
||||||
"moderation.ban.info.field.sent_private_message": "Sent DM",
|
"moderation.ban.info.field.delete_duration.name": "Message Deletion",
|
||||||
"moderation.ban.info.field.delete_duration": "Message Deletion",
|
"moderation.ban.info.field.delete_duration.value": "${delete_duration} day(s)",
|
||||||
"moderation.ban.info.field.delete_duration.value": "%s 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.title": "You were banned from this server.",
|
||||||
"moderation.ban.dm.field.performer": "Moderator",
|
"moderation.ban.dm.field.performer": "Moderator",
|
||||||
"moderation.ban.dm.field.reason": "Reason",
|
"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.author": "Unbanned user from server.",
|
||||||
"moderation.unban.info.field.performer": "Performer",
|
"moderation.unban.info.field.performer": "Performer",
|
||||||
"moderation.unban.info.field.target": "Target",
|
"moderation.unban.info.field.target": "Target",
|
||||||
"moderation.warn.info.author": "Warned user.",
|
"moderation.warn.info.author": "Warned user.",
|
||||||
"moderation.warn.info.field.performer": "Performer",
|
"moderation.warn.info.field.performer": "Performer",
|
||||||
"moderation.warn.info.field.target": "Target",
|
"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.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.info.field.date_time": "Date & Time",
|
||||||
"moderation.warn.info.field.reason": "Reason",
|
|
||||||
"moderation.warn.dm.title": "You were warned by a moderator.",
|
"moderation.warn.dm.title": "You were warned by a moderator.",
|
||||||
"moderation.warn.dm.field.performer": "Moderator",
|
"moderation.warn.dm.field.performer": "Moderator",
|
||||||
"moderation.warn.dm.field.date_time": "Date & Time",
|
"moderation.warn.dm.field.date_time": "Date & Time",
|
||||||
"moderation.warn.dm.field.reason": "Reason",
|
"moderation.warn.dm.field.reason.name": "Reason",
|
||||||
"moderation.warnlist.author": "Listing of Warnings",
|
"moderation.warn.dm.field.reason.value": "${nullcheck;warning_entry.reason;_No reason specified._}",
|
||||||
"moderation.warnlist.empty": "**_No warnings logged matching your query._**",
|
"moderation.unwarn.info.author": "Removed warning from user.",
|
||||||
"moderation.warnlist.entry": "**Case #%1$s**: Warned %2$s by %3$s %n - _Date & Time:_ %4$s %n - _Reason:_ %5$s",
|
"moderation.unwarn.info.field.performer": "Performer",
|
||||||
"moderation.warnlist.entry.no_reason": "_no reason specified_",
|
"moderation.unwarn.info.field.original_target": "Original Target",
|
||||||
"moderation.unwarn.author": "Removed warning from user.",
|
"moderation.unwarn.info.field.original_performer": "Original Performer",
|
||||||
"moderation.unwarn.field.performer": "Performer",
|
"moderation.unwarn.info.field.case_id": "Case ID",
|
||||||
"moderation.unwarn.field.original_target": "Original Target",
|
"moderation.unwarn.info.field.date_time": "Date & Time",
|
||||||
"moderation.unwarn.field.original_performer": "Original Performer",
|
"moderation.unwarn.info.field.reason.name": "Reason",
|
||||||
"moderation.unwarn.field.case_id": "Case ID",
|
"moderation.unwarn.info.field.reason.value": "${nullcheck;warning_entry.reason;_No reason specified._}",
|
||||||
"moderation.unwarn.field.date_time": "Date & Time",
|
|
||||||
"moderation.unwarn.field.reason": "Reason",
|
|
||||||
"moderation.unwarn.no_case_found.title": "No warning found.",
|
"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.description": "No warning with that case ID was found.",
|
||||||
"moderation.unwarn.no_case_found.field.performer": "Performer",
|
"moderation.unwarn.no_case_found.field.performer": "Performer",
|
||||||
"moderation.unwarn.no_case_found.field.case_id": "Case ID",
|
"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.title": "Cannot remove warning from self.",
|
||||||
"moderation.unwarn.cannot_unwarn_self.desc": "Performer cannot remove a warning from themselves.",
|
"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.performer": "Performer/Original Target",
|
||||||
"moderation.unwarn.cannot_unwarn_self.field.original_performer": "Original Performer",
|
"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.field.case_id": "Case ID",
|
||||||
"moderation.warn.cannot_warn_mods.title": "Cannot warn moderators.",
|
"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.description": "Moderators cannot issue warnings to other moderators.",
|
||||||
"moderation.warn.cannot_warn_mods.field.performer": "Performer",
|
"moderation.warn.cannot_warn_mods.field.performer": "Performer",
|
||||||
"moderation.warn.cannot_warn_mods.field.target": "Target",
|
"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.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.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.performer": "Performer",
|
||||||
"moderation.warn.cannot_remove_higher_mod.field.original_performer": "Original 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.field.case_id": "Case ID",
|
||||||
"moderation.note.max_amount_of_notes.title": "Max notes reached.",
|
"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.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.performer": "Performer",
|
||||||
"moderation.note.max_amount_of_notes.field.target": "Target",
|
"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.field.amount": "(Max.) Amount",
|
||||||
"moderation.note.no_note_found.title": "No note found.",
|
"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.description": "No note with that note ID was found.",
|
||||||
"moderation.note.no_note_found.field.performer": "Performer",
|
"moderation.note.no_note_found.field.performer": "Performer",
|
||||||
"moderation.note.no_note_found.field.note_id": "Note ID",
|
"moderation.note.no_note_found.field.note_id": "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.author": "Recorded note for user.",
|
||||||
"moderation.note.add.field.performer": "Performer",
|
"moderation.note.add.field.performer": "Performer",
|
||||||
"moderation.note.add.field.target": "Target",
|
"moderation.note.add.field.target": "Target",
|
||||||
|
@ -103,9 +103,15 @@
|
||||||
"moderation.note.add.field.contents": "Text",
|
"moderation.note.add.field.contents": "Text",
|
||||||
"moderation.note.remove.author": "Removed note.",
|
"moderation.note.remove.author": "Removed note.",
|
||||||
"moderation.note.remove.field.performer": "Performer",
|
"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.original_performer": "Original Performer",
|
||||||
|
"moderation.note.remove.field.original_target": "Original Target",
|
||||||
"moderation.note.remove.field.note_id": "Note ID",
|
"moderation.note.remove.field.note_id": "Note ID",
|
||||||
"moderation.note.remove.field.date_time": "Date & Time",
|
"moderation.note.remove.field.date_time": "Date & Time",
|
||||||
"moderation.note.remove.field.contents": "Text"
|
"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}"
|
||||||
}
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "<general.error.ambiguous_member.title>",
|
||||||
|
"description": "<general.error.ambiguous_member.description>"
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "<general.error.cannot_action_self.title>",
|
||||||
|
"description": "<general.error.cannot_action_self.description>"
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "<general.error.cannot_interact.title>",
|
||||||
|
"description": "<general.error.cannot_interact.description>",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<general.error.cannot_interact.field.target>",
|
||||||
|
"value": "${target.mention}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "<general.error.guild_only_command.title>",
|
||||||
|
"description": "<general.error.guild_only_command.description>"
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "<general.error.insufficient_permissions.title>",
|
||||||
|
"description": "<general.error.insufficient_permissions.description>",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<general.error.insufficient_permissions.field.permissions>",
|
||||||
|
"value": "${required_permissions}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
28
src/main/resources/messages/messages.json
Normal file
28
src/main/resources/messages/messages.json
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
[
|
||||||
|
"general/error/ambiguous_member",
|
||||||
|
"general/error/guild_only_command",
|
||||||
|
"general/error/insufficient_permissions",
|
||||||
|
"general/error/cannot_interact",
|
||||||
|
"general/error/cannot_action_self",
|
||||||
|
"general/error/cannot_action_performer",
|
||||||
|
"moderation/error/cannot_interact",
|
||||||
|
"moderation/error/insufficient_permissions",
|
||||||
|
"moderation/kick/info",
|
||||||
|
"moderation/kick/dm",
|
||||||
|
"moderation/ban/info",
|
||||||
|
"moderation/ban/dm",
|
||||||
|
"moderation/unban/info",
|
||||||
|
"moderation/warn/info",
|
||||||
|
"moderation/warn/dm",
|
||||||
|
"moderation/warn/list",
|
||||||
|
"moderation/unwarn/info",
|
||||||
|
"moderation/error/unwarn/no_case_found",
|
||||||
|
"moderation/error/unwarn/cannot_unwarn_self",
|
||||||
|
"moderation/error/unwarn/cannot_remove_higher_mod",
|
||||||
|
"moderation/error/warn/cannot_warn_mods",
|
||||||
|
"moderation/error/note/max_amount_of_notes",
|
||||||
|
"moderation/error/note/no_note_found",
|
||||||
|
"moderation/note/add",
|
||||||
|
"moderation/note/remove",
|
||||||
|
"moderation/note/list"
|
||||||
|
]
|
20
src/main/resources/messages/moderation/ban/dm.json
Normal file
20
src/main/resources/messages/moderation/ban/dm.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"color": "${moderation.color}",
|
||||||
|
"author": {
|
||||||
|
"name": "${performer.guild.name}",
|
||||||
|
"icon_url": "${performer.guild.icon_url}"
|
||||||
|
},
|
||||||
|
"title": "<moderation.ban.dm.title>",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.ban.dm.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.ban.dm.field.reason.name>",
|
||||||
|
"value": "<moderation.ban.dm.field.reason.value>",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
34
src/main/resources/messages/moderation/ban/info.json
Normal file
34
src/main/resources/messages/moderation/ban/info.json
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"color": "${moderation.color}",
|
||||||
|
"author": {
|
||||||
|
"name": "<moderation.ban.info.author>",
|
||||||
|
"icon_url": "${moderation.icon_url}"
|
||||||
|
},
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.ban.info.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.ban.info.field.target>",
|
||||||
|
"value": "${target.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.ban.info.field.private_message>",
|
||||||
|
"value": "${private_message}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.ban.info.field.delete_duration.name>",
|
||||||
|
"value": "<moderation.ban.info.field.delete_duration.value>",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.ban.info.field.reason.name>",
|
||||||
|
"value": "<moderation.ban.info.field.reason.value>",
|
||||||
|
"inline": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "<moderation.cannot_interact.title>",
|
||||||
|
"description": "<moderation.cannot_interact.description>",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.cannot_interact.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.cannot_interact.field.target>",
|
||||||
|
"value": "${target.mention}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "<moderation.insufficient_permissions.title>",
|
||||||
|
"description": "<moderation.insufficient_permissions.description>",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.insufficient_permissions.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.insufficient_permissions.field.permissions>",
|
||||||
|
"value": "${required_permissions}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "<moderation.note.max_amount_of_notes.title>",
|
||||||
|
"description": "<moderation.note.max_amount_of_notes.description>",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.max_amount_of_notes.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.max_amount_of_notes.field.target>",
|
||||||
|
"value": "${target.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.max_amount_of_notes.field.amount>",
|
||||||
|
"value": "${notes_amount}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "<moderation.warn.cannot_remove_higher_mod.title>",
|
||||||
|
"description": "<moderation.warn.cannot_remove_higher_mod.description>",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.cannot_remove_higher_mod.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.cannot_remove_higher_mod.field.original_performer>",
|
||||||
|
"value": "${warning_entry.performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.cannot_remove_higher_mod.field.case_id>",
|
||||||
|
"value": "${warning_entry.case_id}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "<moderation.unwarn.cannot_unwarn_self.title>",
|
||||||
|
"description": "<moderation.unwarn.cannot_unwarn_self.description>",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.unwarn.cannot_unwarn_self.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.unwarn.cannot_unwarn_self.field.original_performer>",
|
||||||
|
"value": "${warning_entry.performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.unwarn.cannot_unwarn_self.field.case_id>",
|
||||||
|
"value": "${warning_entry.case_id}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "<moderation.warn.cannot_warn_mods.title>",
|
||||||
|
"description": "<moderation.warn.cannot_warn_mods.description>",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.cannot_warn_mods.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.cannot_warn_mods.field.target>",
|
||||||
|
"value": "${target.mention}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
20
src/main/resources/messages/moderation/kick/dm.json
Normal file
20
src/main/resources/messages/moderation/kick/dm.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"color": "${moderation.color}",
|
||||||
|
"author": {
|
||||||
|
"name": "${performer.guild.name}",
|
||||||
|
"icon_url": "${performer.guild.icon_url}"
|
||||||
|
},
|
||||||
|
"title": "<moderation.kick.dm.title>",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.kick.dm.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.kick.dm.field.reason.name>",
|
||||||
|
"value": "<moderation.kick.dm.field.reason.value>",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
29
src/main/resources/messages/moderation/kick/info.json
Normal file
29
src/main/resources/messages/moderation/kick/info.json
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"color": "${moderation.color}",
|
||||||
|
"author": {
|
||||||
|
"name": "<moderation.kick.info.author>",
|
||||||
|
"icon_url": "${moderation.icon_url}"
|
||||||
|
},
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.kick.info.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.kick.info.field.target>",
|
||||||
|
"value": "${target.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.kick.info.field.private_message>",
|
||||||
|
"value": "${private_message}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.kick.info.field.reason.name>",
|
||||||
|
"value": "<moderation.kick.info.field.reason.value>",
|
||||||
|
"inline": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
34
src/main/resources/messages/moderation/note/add.json
Normal file
34
src/main/resources/messages/moderation/note/add.json
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"color": "${moderation.color}",
|
||||||
|
"author": {
|
||||||
|
"name": "<moderation.note.add.author>",
|
||||||
|
"icon_url": "${moderation.icon_url}"
|
||||||
|
},
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.add.field.performer>",
|
||||||
|
"value": "${note_entry.performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.add.field.target>",
|
||||||
|
"value": "${note_entry.target.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.add.field.note_id>",
|
||||||
|
"value": "${note_entry.note_id}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.add.field.date_time>",
|
||||||
|
"value": "${note_entry.date_time}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.add.field.contents>",
|
||||||
|
"value": "${note_entry.contents}",
|
||||||
|
"inline": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
13
src/main/resources/messages/moderation/note/list.json
Normal file
13
src/main/resources/messages/moderation/note/list.json
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"type": "listing",
|
||||||
|
"color": "${moderation.color}",
|
||||||
|
"author": {
|
||||||
|
"name": "<moderation.note.list.author>",
|
||||||
|
"icon_url": "${moderation.icon_url}"
|
||||||
|
},
|
||||||
|
"entry": {
|
||||||
|
"type": "description",
|
||||||
|
"text": "<moderation.note.list.entry>"
|
||||||
|
},
|
||||||
|
"empty": "<moderation.note.list.empty>"
|
||||||
|
}
|
39
src/main/resources/messages/moderation/note/remove.json
Normal file
39
src/main/resources/messages/moderation/note/remove.json
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"color": "${moderation.color}",
|
||||||
|
"author": {
|
||||||
|
"name": "<moderation.note.remove.author>",
|
||||||
|
"icon_url": "${moderation.icon_url}"
|
||||||
|
},
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.remove.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.remove.field.original_performer>",
|
||||||
|
"value": "${note_entry.performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.remove.field.original_target>",
|
||||||
|
"value": "${note_entry.target.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.remove.field.note_id>",
|
||||||
|
"value": "${note_entry.note_id}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.remove.field.date_time>",
|
||||||
|
"value": "${note_entry.date_time}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.note.remove.field.contents>",
|
||||||
|
"value": "${note_entry.contents}",
|
||||||
|
"inline": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
19
src/main/resources/messages/moderation/unban/info.json
Normal file
19
src/main/resources/messages/moderation/unban/info.json
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"color": "${moderation.color}",
|
||||||
|
"author": {
|
||||||
|
"name": "<moderation.unban.info.author>",
|
||||||
|
"icon_url": "${moderation.icon_url}"
|
||||||
|
},
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.unban.info.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.unban.info.field.target>",
|
||||||
|
"value": "${target.mention}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
39
src/main/resources/messages/moderation/unwarn/info.json
Normal file
39
src/main/resources/messages/moderation/unwarn/info.json
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"color": "${moderation.color}",
|
||||||
|
"author": {
|
||||||
|
"name": "<moderation.unwarn.info.author>",
|
||||||
|
"icon_url": "${moderation.icon_url}"
|
||||||
|
},
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.unwarn.info.field.performer>",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.unwarn.info.field.original_target>",
|
||||||
|
"value": "${warning_entry.target.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.unwarn.info.field.original_performer>",
|
||||||
|
"value": "${warning_entry.performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.unwarn.info.field.case_id>",
|
||||||
|
"value": "${warning_entry.case_id}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.unwarn.info.field.date_time>",
|
||||||
|
"value": "${warning_entry.date_time}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.unwarn.info.field.reason.name>",
|
||||||
|
"value": "<moderation.unwarn.info.field.reason.value>",
|
||||||
|
"inline": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
25
src/main/resources/messages/moderation/warn/dm.json
Normal file
25
src/main/resources/messages/moderation/warn/dm.json
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"color": "${moderation.color}",
|
||||||
|
"author": {
|
||||||
|
"name": "${performer.guild.name}",
|
||||||
|
"icon_url": "${performer.guild.icon_url}"
|
||||||
|
},
|
||||||
|
"title": "<moderation.warn.dm.title>",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.dm.field.performer>",
|
||||||
|
"value": "${warning_entry.performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.dm.field.date_time>",
|
||||||
|
"value": "${warning_entry.date_time}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.dm.field.reason.name>",
|
||||||
|
"value": "<moderation.warn.dm.field.reason.value>",
|
||||||
|
"inline": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
39
src/main/resources/messages/moderation/warn/info.json
Normal file
39
src/main/resources/messages/moderation/warn/info.json
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"color": "${moderation.color}",
|
||||||
|
"author": {
|
||||||
|
"name": "<moderation.warn.info.author>",
|
||||||
|
"icon_url": "${moderation.icon_url}"
|
||||||
|
},
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.info.field.performer>",
|
||||||
|
"value": "${warning_entry.performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.info.field.target>",
|
||||||
|
"value": "${warning_entry.target.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.info.field.case_id>",
|
||||||
|
"value": "${warning_entry.case_id}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.info.field.private_message>",
|
||||||
|
"value": "${private_message}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.info.field.date_time>",
|
||||||
|
"value": "${warning_entry.date_time}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "<moderation.warn.info.field.reason.name>",
|
||||||
|
"value": "<moderation.warn.info.field.reason.value>",
|
||||||
|
"inline": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
13
src/main/resources/messages/moderation/warn/list.json
Normal file
13
src/main/resources/messages/moderation/warn/list.json
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"type": "listing",
|
||||||
|
"color": "${moderation.color}",
|
||||||
|
"author": {
|
||||||
|
"name": "<moderation.warnlist.author>",
|
||||||
|
"icon_url": "${moderation.icon_url}"
|
||||||
|
},
|
||||||
|
"entry": {
|
||||||
|
"type": "description",
|
||||||
|
"text": "<moderation.warnlist.entry>"
|
||||||
|
},
|
||||||
|
"empty": "<moderation.warnlist.empty>"
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user