mirror of
https://github.com/sciwhiz12/Janitor.git
synced 2024-11-09 16:11:27 +00:00
Compare commits
2 Commits
df831da94d
...
199b40b160
Author | SHA1 | Date | |
---|---|---|---|
199b40b160 | |||
42adb8238c |
132
build.gradle
132
build.gradle
|
@ -9,15 +9,6 @@ buildscript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
jcenter()
|
|
||||||
maven {
|
|
||||||
name = "Minecraft Libraries"
|
|
||||||
url = "https://libraries.minecraft.net"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
apply plugin: 'com.github.johnrengelman.shadow'
|
apply plugin: 'com.github.johnrengelman.shadow'
|
||||||
apply plugin: 'org.ajoberstar.grgit'
|
apply plugin: 'org.ajoberstar.grgit'
|
||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
|
@ -25,8 +16,6 @@ apply plugin: 'java'
|
||||||
apply plugin: 'application'
|
apply plugin: 'application'
|
||||||
apply plugin: 'maven-publish'
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
group = 'sciwhiz12.janitor'
|
|
||||||
archivesBaseName = 'janitor_bot'
|
|
||||||
version = getVersion()
|
version = getVersion()
|
||||||
println("Version: ${version}")
|
println("Version: ${version}")
|
||||||
|
|
||||||
|
@ -40,34 +29,117 @@ tasks.withType(JavaCompile) {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation group: 'net.dv8tion', name: 'JDA', version: jda_version
|
implementation project(':core')
|
||||||
implementation group: 'com.electronwill.night-config', name: 'toml', version: nightconfig_version
|
implementation project(path: ':core', configuration: 'api')
|
||||||
implementation group: 'net.sf.jopt-simple', name: 'jopt-simple', version: jopt_version
|
runtimeOnly project(':moderation')
|
||||||
implementation group: 'com.google.guava', name: 'guava', version: guava_version
|
runtimeOnly project(path: ':moderation', configuration: 'api')
|
||||||
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: 'ch.qos.logback', name: 'logback-classic', version: logback_version
|
|
||||||
implementation group: 'com.mojang', name: 'brigadier', version: brigadier_version
|
|
||||||
|
|
||||||
testImplementation group: 'junit', name: 'junit', version: junit_version
|
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
mainClassName = 'sciwhiz12.janitor.BotStartup'
|
mainClassName = 'sciwhiz12.janitor.BotStartup'
|
||||||
}
|
}
|
||||||
|
jar.finalizedBy 'shadowJar'
|
||||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
shadowJar {
|
||||||
from sourceSets.main.allSource
|
exclude 'META-INF/NOTICE**'
|
||||||
classifier "sources"
|
exclude 'META-INF/LICENSE**'
|
||||||
|
exclude 'META-INF/DEPENDENCIES'
|
||||||
|
exclude 'META-INF/proguard/**'
|
||||||
|
exclude 'META-INF/maven/**'
|
||||||
|
classifier ''
|
||||||
|
includeEmptyDirs false
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
apply plugin: 'java'
|
||||||
|
group = 'sciwhiz12.janitor'
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
jcenter()
|
||||||
|
maven {
|
||||||
|
name = "Minecraft Libraries"
|
||||||
|
url = "https://libraries.minecraft.net"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
sourceSets { api }
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
apiImplementation.extendsFrom apiDependency
|
||||||
|
api {
|
||||||
|
canBeConsumed = true
|
||||||
|
canBeResolved = true
|
||||||
|
extendsFrom apiDependency
|
||||||
|
}
|
||||||
|
implementation.extendsFrom apiImplementation, api
|
||||||
|
'default' {
|
||||||
|
extendsFrom api, apiDependency
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api sourceSets.api.output
|
||||||
|
testImplementation group: 'junit', name: 'junit', version: junit_version
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
from sourceSets.api.output
|
||||||
|
finalizedBy 'apiJar', 'sourcesJar'
|
||||||
|
}
|
||||||
|
|
||||||
|
task apiJar(type: Jar, dependsOn: apiClasses) {
|
||||||
|
from sourceSets.api.allJava
|
||||||
|
classifier "api"
|
||||||
|
}
|
||||||
|
|
||||||
|
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||||
|
from sourceSets.main.allSource
|
||||||
|
from sourceSets.api.allSource
|
||||||
|
classifier "sources"
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project(':core') {
|
||||||
|
apply plugin: 'com.github.johnrengelman.shadow'
|
||||||
|
archivesBaseName = 'janitor-core'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
apiDependency group: 'net.dv8tion', name: 'JDA', version: jda_version
|
||||||
|
apiDependency group: 'com.electronwill.night-config', name: 'toml', version: nightconfig_version
|
||||||
|
apiDependency group: 'net.sf.jopt-simple', name: 'jopt-simple', version: jopt_version
|
||||||
|
apiDependency group: 'com.google.guava', name: 'guava', version: guava_version
|
||||||
|
apiDependency group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: jackson_version
|
||||||
|
apiDependency group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: jackson_version
|
||||||
|
apiDependency group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: jackson_version
|
||||||
|
apiDependency group: 'org.apache.logging.log4j', name: 'log4j-to-slf4j', version: log4j_bridge_version
|
||||||
|
apiDependency group: 'ch.qos.logback', name: 'logback-classic', version: logback_version
|
||||||
|
apiDependency group: 'com.mojang', name: 'brigadier', version: brigadier_version
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowJar.configurations = [project.configurations.api]
|
||||||
|
|
||||||
|
jar.finalizedBy 'shadowJar'
|
||||||
|
}
|
||||||
|
|
||||||
|
project(':moderation') {
|
||||||
|
archivesBaseName = 'janitor-moderation'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
apiDependency project(path: ':core', configuration: 'api')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
jar.finalizedBy('sourcesJar')
|
|
||||||
jar.finalizedBy('shadowJar')
|
|
||||||
|
|
||||||
def getVersion() {
|
def getVersion() {
|
||||||
try {
|
try {
|
||||||
def raw_version = grgit.describe(longDescr: true, tags: true)
|
String raw_version = grgit.describe(longDescr: true, tags: true)
|
||||||
def versionSep = raw_version.split "-"
|
def versionSep = raw_version.split "-"
|
||||||
def startVer = versionSep[0].substring(1)
|
def startVer = versionSep[0].substring(1)
|
||||||
return startVer + "." + versionSep[1]
|
return startVer + "." + versionSep[1]
|
||||||
|
|
33
core/src/api/java/sciwhiz12/janitor/api/JanitorBot.java
Normal file
33
core/src/api/java/sciwhiz12/janitor/api/JanitorBot.java
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
package sciwhiz12.janitor.api;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.JDA;
|
||||||
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
|
import sciwhiz12.janitor.api.config.BotConfig;
|
||||||
|
import sciwhiz12.janitor.api.config.ConfigManager;
|
||||||
|
import sciwhiz12.janitor.api.messages.Messages;
|
||||||
|
import sciwhiz12.janitor.api.messages.emote.ReactionManager;
|
||||||
|
import sciwhiz12.janitor.api.messages.substitution.SubstitutionsMap;
|
||||||
|
import sciwhiz12.janitor.api.module.ModuleManager;
|
||||||
|
import sciwhiz12.janitor.api.storage.GuildStorageManager;
|
||||||
|
|
||||||
|
public interface JanitorBot {
|
||||||
|
BotConfig getBotConfig();
|
||||||
|
|
||||||
|
CommandRegistry getCommands();
|
||||||
|
|
||||||
|
GuildStorageManager getGuildStorage();
|
||||||
|
|
||||||
|
ConfigManager getConfigs();
|
||||||
|
|
||||||
|
SubstitutionsMap getSubstitutions();
|
||||||
|
|
||||||
|
ReactionManager getReactions();
|
||||||
|
|
||||||
|
Messages getMessages();
|
||||||
|
|
||||||
|
ModuleManager getModuleManager();
|
||||||
|
|
||||||
|
void shutdown();
|
||||||
|
|
||||||
|
JDA getDiscord();
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor;
|
package sciwhiz12.janitor.api;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -8,11 +8,10 @@ import org.slf4j.MarkerFactory;
|
||||||
public class Logging {
|
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 MESSAGES = MarkerFactory.getMarker("MESSAGES");
|
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 Marker MODULE = MarkerFactory.getMarker("MODULE");
|
||||||
|
|
||||||
public static final Logger JANITOR = LoggerFactory.getLogger("janitor");
|
public static final Logger JANITOR = LoggerFactory.getLogger("janitor");
|
||||||
public static final Logger CONSOLE = LoggerFactory.getLogger("janitor.console");
|
|
||||||
public static final Logger CONFIG = LoggerFactory.getLogger("janitor.config");
|
public static final Logger CONFIG = LoggerFactory.getLogger("janitor.config");
|
||||||
}
|
}
|
|
@ -1,12 +1,10 @@
|
||||||
package sciwhiz12.janitor.commands;
|
package sciwhiz12.janitor.api.command;
|
||||||
|
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
import sciwhiz12.janitor.config.BotConfig;
|
|
||||||
import sciwhiz12.janitor.msg.Messages;
|
|
||||||
|
|
||||||
public abstract class BaseCommand {
|
public abstract class BaseCommand implements Command {
|
||||||
private final CommandRegistry registry;
|
private final CommandRegistry registry;
|
||||||
|
|
||||||
public BaseCommand(CommandRegistry registry) {
|
public BaseCommand(CommandRegistry registry) {
|
||||||
|
@ -21,13 +19,5 @@ public abstract class BaseCommand {
|
||||||
return registry.getBot();
|
return registry.getBot();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Messages messages() {
|
|
||||||
return getBot().getMessages();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected BotConfig config() {
|
|
||||||
return getBot().getConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract LiteralArgumentBuilder<MessageReceivedEvent> getNode();
|
public abstract LiteralArgumentBuilder<MessageReceivedEvent> getNode();
|
||||||
}
|
}
|
30
core/src/api/java/sciwhiz12/janitor/api/command/Command.java
Normal file
30
core/src/api/java/sciwhiz12/janitor/api/command/Command.java
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package sciwhiz12.janitor.api.command;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
import sciwhiz12.janitor.api.config.GuildConfig;
|
||||||
|
import sciwhiz12.janitor.api.messages.Messages;
|
||||||
|
|
||||||
|
public interface Command {
|
||||||
|
LiteralArgumentBuilder<MessageReceivedEvent> getNode();
|
||||||
|
|
||||||
|
JanitorBot getBot();
|
||||||
|
|
||||||
|
default Messages messages() {
|
||||||
|
return getBot().getMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
default GuildConfig config(MessageReceivedEvent event) {
|
||||||
|
return config(event.getGuild().getIdLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
default GuildConfig config(Guild guild) {
|
||||||
|
return config(guild.getIdLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
default GuildConfig config(long guildID) {
|
||||||
|
return getBot().getConfigs().get(guildID);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package sciwhiz12.janitor.api.command;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public interface CommandRegistry {
|
||||||
|
CommandDispatcher<MessageReceivedEvent> getDispatcher();
|
||||||
|
|
||||||
|
void addCommand(Function<CommandRegistry, Command> command);
|
||||||
|
|
||||||
|
JanitorBot getBot();
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package sciwhiz12.janitor.commands.arguments;
|
package sciwhiz12.janitor.api.command.arguments;
|
||||||
|
|
||||||
import com.mojang.brigadier.StringReader;
|
import com.mojang.brigadier.StringReader;
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import sciwhiz12.janitor.utils.StringReaderUtil;
|
import sciwhiz12.janitor.api.utils.StringReaderUtil;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@ -17,18 +17,15 @@ public class CustomStringArgumentType implements ArgumentType<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CustomStringArgumentType word() {
|
public static CustomStringArgumentType word() {
|
||||||
return new CustomStringArgumentType(
|
return new CustomStringArgumentType(StringArgumentType.StringType.SINGLE_WORD);
|
||||||
StringArgumentType.StringType.SINGLE_WORD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CustomStringArgumentType string() {
|
public static CustomStringArgumentType string() {
|
||||||
return new CustomStringArgumentType(
|
return new CustomStringArgumentType(StringArgumentType.StringType.QUOTABLE_PHRASE);
|
||||||
StringArgumentType.StringType.QUOTABLE_PHRASE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CustomStringArgumentType greedyString() {
|
public static CustomStringArgumentType greedyString() {
|
||||||
return new CustomStringArgumentType(
|
return new CustomStringArgumentType(StringArgumentType.StringType.GREEDY_PHRASE);
|
||||||
StringArgumentType.StringType.GREEDY_PHRASE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getString(final CommandContext<?> context, final String name) {
|
public static String getString(final CommandContext<?> context, final String name) {
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor.commands.arguments;
|
package sciwhiz12.janitor.api.command.arguments;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.mojang.brigadier.LiteralMessage;
|
import com.mojang.brigadier.LiteralMessage;
|
||||||
|
@ -9,7 +9,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import sciwhiz12.janitor.utils.StringReaderUtil;
|
import sciwhiz12.janitor.api.utils.StringReaderUtil;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -71,6 +71,11 @@ public class GuildMemberArgument implements ArgumentType<GuildMemberArgument.IMe
|
||||||
throw UNKNOWN_MEMBER_IDENTIFIER.create();
|
throw UNKNOWN_MEMBER_IDENTIFIER.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "member()";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<String> getExamples() {
|
public Collection<String> getExamples() {
|
||||||
return ImmutableList.of("<@!607058472709652501>", "<@750291676764962816>");
|
return ImmutableList.of("<@!607058472709652501>", "<@750291676764962816>");
|
|
@ -0,0 +1,18 @@
|
||||||
|
package sciwhiz12.janitor.api.config;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Optional;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public interface BotConfig {
|
||||||
|
@Nullable
|
||||||
|
Path getMessagesFolder();
|
||||||
|
|
||||||
|
Path getConfigsFolder();
|
||||||
|
|
||||||
|
String getToken();
|
||||||
|
|
||||||
|
String getCommandPrefix();
|
||||||
|
|
||||||
|
Optional<Long> getOwnerID();
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package sciwhiz12.janitor.api.config;
|
||||||
|
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
|
||||||
|
public interface ConfigManager {
|
||||||
|
GuildConfig get(long guildID);
|
||||||
|
|
||||||
|
void save();
|
||||||
|
|
||||||
|
void close();
|
||||||
|
|
||||||
|
void registerNode(ConfigNode<?> node);
|
||||||
|
|
||||||
|
default void registerNodes(ConfigNode<?>... nodes) {
|
||||||
|
for (ConfigNode<?> node : nodes) {
|
||||||
|
registerNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JanitorBot getBot();
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package sciwhiz12.janitor.api.config;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class ConfigNode<T> {
|
||||||
|
private static final Joiner NEWLINE = Joiner.on('\n');
|
||||||
|
|
||||||
|
private final String path;
|
||||||
|
private final String comment;
|
||||||
|
private final Supplier<T> defaultValue;
|
||||||
|
|
||||||
|
public ConfigNode(String path, Supplier<T> defaultValue, String... comment) {
|
||||||
|
Objects.requireNonNull(path, "Config node path must not be null");
|
||||||
|
Objects.requireNonNull(defaultValue, "Default value supplier must not be null");
|
||||||
|
Objects.requireNonNull(comment, "Config node comments must not be null");
|
||||||
|
this.path = path;
|
||||||
|
this.defaultValue = defaultValue;
|
||||||
|
this.comment = NEWLINE.join(comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String path() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String comment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Supplier<T> defaultValue() {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
ConfigNode<?> that = (ConfigNode<?>) o;
|
||||||
|
return path.equals(that.path) &&
|
||||||
|
comment.equals(that.comment) &&
|
||||||
|
defaultValue.equals(that.defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(path, comment, defaultValue);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package sciwhiz12.janitor.api.config;
|
||||||
|
|
||||||
|
public final class CoreConfigs {
|
||||||
|
public static final ConfigNode<Boolean> ENABLE = new ConfigNode<>(
|
||||||
|
"enable", () -> true,
|
||||||
|
"Whether the bot is enabled for this guild.",
|
||||||
|
"Can be used to temporarily disable the bot in emergency situations.");
|
||||||
|
|
||||||
|
public static final ConfigNode<String> COMMAND_PREFIX = new ConfigNode<>(
|
||||||
|
"commands.prefix", () -> "!",
|
||||||
|
"The prefix for all commands.");
|
||||||
|
|
||||||
|
private CoreConfigs() {}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package sciwhiz12.janitor.api.config;
|
||||||
|
|
||||||
|
import com.electronwill.nightconfig.core.CommentedConfig;
|
||||||
|
import net.dv8tion.jda.api.entities.GuildChannel;
|
||||||
|
|
||||||
|
public interface GuildConfig {
|
||||||
|
CommentedConfig getChannelOverrides();
|
||||||
|
|
||||||
|
CommentedConfig getChannelConfig(GuildChannel channel);
|
||||||
|
|
||||||
|
<T> T forGuild(ConfigNode<T> node);
|
||||||
|
|
||||||
|
<T> void forGuild(ConfigNode<T> node, T newValue);
|
||||||
|
|
||||||
|
<T> T forChannel(GuildChannel channel, ConfigNode<T> node);
|
||||||
|
|
||||||
|
<T> void forChannel(GuildChannel channel, ConfigNode<T> node, T newValue);
|
||||||
|
|
||||||
|
long getGuildID();
|
||||||
|
|
||||||
|
CommentedConfig getRawConfig();
|
||||||
|
|
||||||
|
void save();
|
||||||
|
|
||||||
|
void close();
|
||||||
|
}
|
|
@ -1,23 +1,19 @@
|
||||||
package sciwhiz12.janitor.msg.json;
|
package sciwhiz12.janitor.api.messages;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
import com.google.common.primitives.Ints;
|
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||||
import joptsimple.internal.Strings;
|
|
||||||
import net.dv8tion.jda.api.EmbedBuilder;
|
|
||||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
import sciwhiz12.janitor.msg.TranslationMap;
|
import sciwhiz12.janitor.api.messages.substitution.ModifiableSubstitutions;
|
||||||
import sciwhiz12.janitor.msg.substitution.CustomSubstitutions;
|
import sciwhiz12.janitor.api.messages.substitution.ModifiableSubstitutor;
|
||||||
import sciwhiz12.janitor.msg.substitution.ISubstitutor;
|
import sciwhiz12.janitor.api.messages.substitution.SubstitutionsMap;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
|
||||||
import java.time.ZoneOffset;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@JsonDeserialize(using = ListingMessageDeserializer.class)
|
|
||||||
public class ListingMessage {
|
public class ListingMessage {
|
||||||
@Nullable protected final String title;
|
@Nullable protected final String title;
|
||||||
@Nullable protected final String url;
|
@Nullable protected final String url;
|
||||||
|
@ -141,72 +137,6 @@ public class ListingMessage {
|
||||||
return afterFields;
|
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 interface Entry {}
|
||||||
|
|
||||||
public static class DescriptionEntry implements Entry {
|
public static class DescriptionEntry implements Entry {
|
||||||
|
@ -251,4 +181,23 @@ public class ListingMessage {
|
||||||
return inline;
|
return inline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface Builder<T> extends ModifiableSubstitutions<Builder<T>> {
|
||||||
|
Builder<T> amountPerPage(int amountPerPage);
|
||||||
|
|
||||||
|
Builder<T> setEntryApplier(BiConsumer<T, ModifiableSubstitutor<?>> entryApplier);
|
||||||
|
|
||||||
|
Builder<T> apply(Consumer<Builder<T>> consumer);
|
||||||
|
|
||||||
|
Builder<T> with(final String argument, final Supplier<String> value);
|
||||||
|
|
||||||
|
void build(MessageChannel channel,
|
||||||
|
SubstitutionsMap globalSubstitutions,
|
||||||
|
Message triggerMessage,
|
||||||
|
List<T> entries);
|
||||||
|
|
||||||
|
default void build(MessageChannel channel, JanitorBot bot, Message triggerMessage, List<T> entries) {
|
||||||
|
build(channel, bot.getSubstitutions(), triggerMessage, entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package sciwhiz12.janitor.api.messages;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
public interface Messages {
|
||||||
|
JanitorBot getBot();
|
||||||
|
|
||||||
|
void loadMessages();
|
||||||
|
|
||||||
|
RegularMessage.Builder<?> getRegularMessage(String messageKey);
|
||||||
|
|
||||||
|
<T> ListingMessage.Builder<T> getListingMessage(String messageKey);
|
||||||
|
|
||||||
|
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))
|
||||||
|
);
|
||||||
|
|
||||||
|
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,48 +1,31 @@
|
||||||
package sciwhiz12.janitor.msg.json;
|
package sciwhiz12.janitor.api.messages;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||||
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.MessageEmbed;
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
import net.dv8tion.jda.api.requests.restaction.MessageAction;
|
||||||
import sciwhiz12.janitor.msg.TranslationMap;
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
import sciwhiz12.janitor.msg.substitution.ISubstitutor;
|
import sciwhiz12.janitor.api.messages.substitution.ModifiableSubstitutions;
|
||||||
|
import sciwhiz12.janitor.api.messages.substitution.SubstitutionsMap;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
|
||||||
import java.time.ZoneOffset;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.StringJoiner;
|
import java.util.StringJoiner;
|
||||||
import java.util.function.Function;
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@JsonDeserialize(using = RegularMessageDeserializer.class)
|
|
||||||
public class RegularMessage {
|
public class RegularMessage {
|
||||||
@Nullable
|
@Nullable protected final String title;
|
||||||
protected final String title;
|
@Nullable protected final String url;
|
||||||
@Nullable
|
@Nullable protected final String description;
|
||||||
protected final String url;
|
@Nullable protected final String color;
|
||||||
@Nullable
|
@Nullable protected final String authorName;
|
||||||
protected final String description;
|
@Nullable protected final String authorUrl;
|
||||||
@Nullable
|
@Nullable protected final String authorIconUrl;
|
||||||
protected final String color;
|
@Nullable protected final String footerText;
|
||||||
@Nullable
|
@Nullable protected final String footerIconUrl;
|
||||||
protected final String authorName;
|
@Nullable protected final String imageUrl;
|
||||||
@Nullable
|
@Nullable protected final String thumbnailUrl;
|
||||||
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;
|
protected final List<MessageEmbed.Field> fields;
|
||||||
|
|
||||||
public RegularMessage(
|
public RegularMessage(
|
||||||
|
@ -176,37 +159,14 @@ public class RegularMessage {
|
||||||
thumbnailUrl, fields);
|
thumbnailUrl, fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmbedBuilder create(TranslationMap translations, ISubstitutor substitutions) {
|
public interface Builder<T extends Builder<?>> extends ModifiableSubstitutions<T> {
|
||||||
final Function<String, String> func = str -> str != null ? substitutions.substitute(translations.translate(str)) : null;
|
MessageEmbed build(SubstitutionsMap substitutions);
|
||||||
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) {
|
MessageEmbed build(JanitorBot bot);
|
||||||
if (Strings.isNullOrEmpty(str)) return Role.DEFAULT_COLOR_RAW;
|
|
||||||
if (str.startsWith("0x")) {
|
default MessageAction send(JanitorBot bot, MessageChannel channel) {
|
||||||
// noinspection UnstableApiUsage
|
return channel.sendMessage(build(bot));
|
||||||
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,16 @@
|
||||||
|
package sciwhiz12.janitor.api.messages.emote;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface ReactionManager {
|
||||||
|
ReactionMessage newMessage(Message message);
|
||||||
|
|
||||||
|
void removeMessage(long messageID);
|
||||||
|
|
||||||
|
Map<Long, ReactionMessage> getRegisteredMessages();
|
||||||
|
|
||||||
|
JanitorBot getBot();
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package sciwhiz12.janitor.api.messages.emote;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Emote;
|
||||||
|
import net.dv8tion.jda.api.entities.MessageReaction.ReactionEmote;
|
||||||
|
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
|
public interface ReactionMessage {
|
||||||
|
ReactionMessage add(ReactionEmote emote, ReactionListener listener);
|
||||||
|
|
||||||
|
ReactionMessage add(String emote, ReactionListener listener);
|
||||||
|
|
||||||
|
ReactionMessage add(Emote emote, ReactionListener listener);
|
||||||
|
|
||||||
|
ReactionMessage removeEmotes(boolean remove);
|
||||||
|
|
||||||
|
ReactionMessage owner(long ownerID);
|
||||||
|
|
||||||
|
void create();
|
||||||
|
|
||||||
|
long getOwnerID();
|
||||||
|
|
||||||
|
boolean isOwnerOnly();
|
||||||
|
|
||||||
|
Map<ReactionEmote, ReactionListener> getListeners();
|
||||||
|
|
||||||
|
JanitorBot getBot();
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
interface ReactionListener extends BiConsumer<ReactionMessage, MessageReactionAddEvent> {
|
||||||
|
void accept(ReactionMessage message, MessageReactionAddEvent event);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
package sciwhiz12.janitor.msg.substitution;
|
package sciwhiz12.janitor.api.messages.substitution;
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public interface IHasCustomSubstitutions<T extends IHasCustomSubstitutions<?>> {
|
public interface ModifiableSubstitutions<T extends ModifiableSubstitutions<?>> {
|
||||||
T with(String argument, Supplier<String> value);
|
T with(String argument, Supplier<String> value);
|
||||||
|
|
||||||
T apply(Consumer<T> consumer);
|
T apply(Consumer<T> consumer);
|
|
@ -0,0 +1,4 @@
|
||||||
|
package sciwhiz12.janitor.api.messages.substitution;
|
||||||
|
|
||||||
|
public interface ModifiableSubstitutor<T extends ModifiableSubstitutor<?>> extends ModifiableSubstitutions<T>, Substitutor {
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package sciwhiz12.janitor.api.messages.substitution;
|
||||||
|
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||||
|
|
||||||
|
public interface SubstitutionsMap extends Substitutor {
|
||||||
|
Pattern ARGUMENT_REGEX = Pattern.compile("\\$\\{(.+?)}", CASE_INSENSITIVE);
|
||||||
|
Pattern NULL_ARGUMENT_REGEX = Pattern.compile("nullcheck;(.+?);(.+)", CASE_INSENSITIVE);
|
||||||
|
|
||||||
|
static String quote(@Nullable String input) {
|
||||||
|
return input != null ? Matcher.quoteReplacement(input) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
static String substitute(@Nullable String text, Map<String, Supplier<String>> arguments) {
|
||||||
|
if (text == null || text.isBlank()) return null;
|
||||||
|
final Matcher matcher = ARGUMENT_REGEX.matcher(text);
|
||||||
|
return matcher.replaceAll(matchResult -> {
|
||||||
|
final Matcher nullMatcher = NULL_ARGUMENT_REGEX.matcher(matchResult.group(1));
|
||||||
|
if (nullMatcher.matches()) {
|
||||||
|
final String grp1 = nullMatcher.group(1);
|
||||||
|
return quote(arguments.getOrDefault(
|
||||||
|
grp1,
|
||||||
|
() -> arguments.getOrDefault(nullMatcher.group(2), () -> nullMatcher.group(2)).get()
|
||||||
|
).get());
|
||||||
|
}
|
||||||
|
return quote(arguments.getOrDefault(matchResult.group(1), () -> matchResult.group(0)).get());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
String with(String text, Map<String, Supplier<String>> substitutions);
|
||||||
|
|
||||||
|
ModifiableSubstitutor<?> with(Map<String, Supplier<String>> customSubstitutions);
|
||||||
|
|
||||||
|
Map<String, Supplier<String>> createDefaultedMap(Map<String, Supplier<String>> custom);
|
||||||
|
|
||||||
|
JanitorBot getBot();
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package sciwhiz12.janitor.api.messages.substitution;
|
||||||
|
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public interface Substitutor extends UnaryOperator<String> {
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
default String apply(@Nullable String input) {
|
||||||
|
return substitute(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
String substitute(@Nullable String text);
|
||||||
|
}
|
11
core/src/api/java/sciwhiz12/janitor/api/module/Module.java
Normal file
11
core/src/api/java/sciwhiz12/janitor/api/module/Module.java
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package sciwhiz12.janitor.api.module;
|
||||||
|
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
|
||||||
|
public interface Module {
|
||||||
|
void activate();
|
||||||
|
|
||||||
|
void shutdown();
|
||||||
|
|
||||||
|
JanitorBot getBot();
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package sciwhiz12.janitor.api.module;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class ModuleKey<M extends Module> {
|
||||||
|
private final String moduleID;
|
||||||
|
private final Class<M> type;
|
||||||
|
|
||||||
|
public ModuleKey(String storageID, Class<M> type) {
|
||||||
|
Preconditions.checkNotNull(storageID, "Module ID must not be null");
|
||||||
|
Preconditions.checkArgument(!storageID.isBlank(), "Module ID must not be empty or blank");
|
||||||
|
Preconditions.checkNotNull(type, "Class type must not be null");
|
||||||
|
this.moduleID = storageID;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModuleID() {
|
||||||
|
return moduleID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<M> getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
ModuleKey<?> that = (ModuleKey<?>) o;
|
||||||
|
return moduleID.equals(that.moduleID) &&
|
||||||
|
type.equals(that.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(moduleID, type);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package sciwhiz12.janitor.api.module;
|
||||||
|
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public interface ModuleManager {
|
||||||
|
void disableModule(String id);
|
||||||
|
|
||||||
|
void enableModule(String id);
|
||||||
|
|
||||||
|
Set<ModuleKey<?>> getAvailableModules();
|
||||||
|
|
||||||
|
Set<ModuleKey<?>> getActiveModules();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
<M extends Module> M getModule(ModuleKey<M> moduleKey);
|
||||||
|
|
||||||
|
boolean isActivated();
|
||||||
|
|
||||||
|
JanitorBot getBot();
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package sciwhiz12.janitor.api.module;
|
||||||
|
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public interface ModuleProvider {
|
||||||
|
Set<ModuleKey<?>> getAvailableModules();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
<M extends Module> M createModule(ModuleKey<M> moduleID, JanitorBot bot);
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
package sciwhiz12.janitor.storage;
|
package sciwhiz12.janitor.api.storage;
|
||||||
|
|
||||||
public abstract class AbstractStorage implements IStorage {
|
public abstract class AbstractStorage implements Storage {
|
||||||
private boolean dirty;
|
private boolean dirty;
|
||||||
|
|
||||||
public boolean isDirty() {
|
public boolean isDirty() {
|
|
@ -0,0 +1,18 @@
|
||||||
|
package sciwhiz12.janitor.api.storage;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public interface GuildStorageManager {
|
||||||
|
default <S extends Storage> S getOrCreate(Guild guild, StorageKey<S> key, Supplier<S> defaultSupplier) {
|
||||||
|
return getOrCreate(guild.getIdLong(), key, defaultSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
<S extends Storage> S getOrCreate(long guildID, StorageKey<S> key, Supplier<S> defaultSupplier);
|
||||||
|
|
||||||
|
void save();
|
||||||
|
|
||||||
|
JanitorBot getBot();
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor.storage;
|
package sciwhiz12.janitor.api.storage;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
@ -1,11 +1,10 @@
|
||||||
package sciwhiz12.janitor.storage;
|
package sciwhiz12.janitor.api.storage;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
|
|
||||||
public interface IStorage {
|
public interface Storage {
|
||||||
|
|
||||||
boolean dirty();
|
boolean dirty();
|
||||||
|
|
||||||
void write(Writer output) throws IOException;
|
void write(Writer output) throws IOException;
|
|
@ -1,15 +1,15 @@
|
||||||
package sciwhiz12.janitor.storage;
|
package sciwhiz12.janitor.api.storage;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A storage key, used to retrieve an instance of an {@link IStorage} from a {@link GuildStorage}.
|
* A storage key, used to retrieve an instance of an {@link Storage} from a {@link GuildStorageManager}.
|
||||||
*
|
*
|
||||||
* @param <S> the type of the {@link IStorage}
|
* @param <S> the type of the {@link Storage}
|
||||||
*/
|
*/
|
||||||
public class StorageKey<S extends IStorage> {
|
public class StorageKey<S extends Storage> {
|
||||||
private final String storageID;
|
private final String storageID;
|
||||||
private final Class<S> type;
|
private final Class<S> type;
|
||||||
|
|
||||||
|
@ -31,9 +31,9 @@ public class StorageKey<S extends IStorage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the storage ID, used by {@link GuildStorage} to uniquely identify this storage's data.
|
* Returns the storage ID, used by {@link GuildStorageManager} to uniquely identify this storage's data.
|
||||||
*
|
*
|
||||||
* <p>This is currently used by {@code GuildStorage} as the folder name of the storage.
|
* <p>This is currently used by {@code GuildStorageManager} as the folder name of the storage.
|
||||||
*
|
*
|
||||||
* @return the storage ID
|
* @return the storage ID
|
||||||
*/
|
*/
|
||||||
|
@ -42,7 +42,7 @@ public class StorageKey<S extends IStorage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the class of the {@link IStorage} subtype that this storage key represents, which
|
* Returns the class of the {@link Storage} subtype that this storage key represents, which
|
||||||
* is also used in the key's generics.
|
* is also used in the key's generics.
|
||||||
*
|
*
|
||||||
* @return the class of the generic type
|
* @return the class of the generic type
|
|
@ -1,11 +1,13 @@
|
||||||
package sciwhiz12.janitor.commands.util;
|
package sciwhiz12.janitor.api.utils;
|
||||||
|
|
||||||
import com.mojang.brigadier.arguments.ArgumentType;
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
|
|
||||||
public class CommandHelper {
|
public final class CommandHelper {
|
||||||
|
private CommandHelper() {}
|
||||||
|
|
||||||
public static LiteralArgumentBuilder<MessageReceivedEvent> literal(String command) {
|
public static LiteralArgumentBuilder<MessageReceivedEvent> literal(String command) {
|
||||||
return LiteralArgumentBuilder.literal(command);
|
return LiteralArgumentBuilder.literal(command);
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor.msg;
|
package sciwhiz12.janitor.api.utils;
|
||||||
|
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.IMentionable;
|
import net.dv8tion.jda.api.entities.IMentionable;
|
||||||
|
@ -6,32 +6,31 @@ import net.dv8tion.jda.api.entities.ISnowflake;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.Role;
|
import net.dv8tion.jda.api.entities.Role;
|
||||||
import net.dv8tion.jda.api.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
import sciwhiz12.janitor.moderation.notes.NoteEntry;
|
import sciwhiz12.janitor.api.messages.substitution.ModifiableSubstitutions;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
|
||||||
import sciwhiz12.janitor.msg.substitution.IHasCustomSubstitutions;
|
|
||||||
|
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.DateTimeFormatterBuilder;
|
import java.time.format.DateTimeFormatterBuilder;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static java.time.temporal.ChronoField.*;
|
import static java.time.temporal.ChronoField.*;
|
||||||
|
|
||||||
public class MessageHelper {
|
public final class MessageHelper {
|
||||||
private MessageHelper() {}
|
private MessageHelper() {}
|
||||||
|
|
||||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> snowflake(String head, ISnowflake snowflake) {
|
public static <T extends ModifiableSubstitutions<?>> Consumer<T> snowflake(String head, ISnowflake snowflake) {
|
||||||
return builder -> builder
|
return builder -> builder
|
||||||
.with(head + ".id", snowflake::getId)
|
.with(head + ".id", snowflake::getId)
|
||||||
.with(head + ".creation_datetime", () -> snowflake.getTimeCreated().format(DATE_TIME_FORMAT));
|
.with(head + ".creation_datetime", () -> snowflake.getTimeCreated().format(DATE_TIME_FORMAT));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> mentionable(String head, IMentionable mentionable) {
|
public static <T extends ModifiableSubstitutions<?>> Consumer<T> mentionable(String head, IMentionable mentionable) {
|
||||||
return builder -> builder
|
return builder -> builder
|
||||||
.apply(snowflake(head, mentionable))
|
.apply(snowflake(head, mentionable))
|
||||||
.with(head + ".mention", mentionable::getAsMention);
|
.with(head + ".mention", mentionable::getAsMention);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> role(String head, Role role) {
|
public static <T extends ModifiableSubstitutions<?>> Consumer<T> role(String head, Role role) {
|
||||||
return builder -> builder
|
return builder -> builder
|
||||||
.apply(mentionable(head, role))
|
.apply(mentionable(head, role))
|
||||||
.with(head + ".color_hex", () -> Integer.toHexString(role.getColorRaw()))
|
.with(head + ".color_hex", () -> Integer.toHexString(role.getColorRaw()))
|
||||||
|
@ -39,7 +38,7 @@ public class MessageHelper {
|
||||||
.with(head + ".permissions", role.getPermissions()::toString);
|
.with(head + ".permissions", role.getPermissions()::toString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> user(String head, User user) {
|
public static <T extends ModifiableSubstitutions<?>> Consumer<T> user(String head, User user) {
|
||||||
return builder -> builder
|
return builder -> builder
|
||||||
.apply(mentionable(head, user))
|
.apply(mentionable(head, user))
|
||||||
.with(head + ".name", user::getName)
|
.with(head + ".name", user::getName)
|
||||||
|
@ -48,7 +47,7 @@ public class MessageHelper {
|
||||||
.with(head + ".flags", user.getFlags()::toString);
|
.with(head + ".flags", user.getFlags()::toString);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> guild(String head, Guild guild) {
|
public static <T extends ModifiableSubstitutions<?>> Consumer<T> guild(String head, Guild guild) {
|
||||||
return builder -> builder
|
return builder -> builder
|
||||||
.apply(snowflake(head, guild))
|
.apply(snowflake(head, guild))
|
||||||
.with(head + ".name", guild::getName)
|
.with(head + ".name", guild::getName)
|
||||||
|
@ -58,10 +57,10 @@ public class MessageHelper {
|
||||||
.with(head + ".boost.count", () -> String.valueOf(guild.getBoostCount()))
|
.with(head + ".boost.count", () -> String.valueOf(guild.getBoostCount()))
|
||||||
.with(head + ".locale", guild.getLocale()::toString)
|
.with(head + ".locale", guild.getLocale()::toString)
|
||||||
.with(head + ".verification_level", guild.getVerificationLevel()::toString)
|
.with(head + ".verification_level", guild.getVerificationLevel()::toString)
|
||||||
.with(head + ".icon_url", guild::getIconUrl);
|
.with(head + ".icon_url", () -> Objects.toString(guild.getIconUrl(), ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> member(String head, Member member) {
|
public static <T extends ModifiableSubstitutions<?>> Consumer<T> member(String head, Member member) {
|
||||||
return builder -> builder
|
return builder -> builder
|
||||||
.apply(user(head, member.getUser()))
|
.apply(user(head, member.getUser()))
|
||||||
.apply(guild(head + ".guild", member.getGuild()))
|
.apply(guild(head + ".guild", member.getGuild()))
|
||||||
|
@ -71,24 +70,6 @@ public class MessageHelper {
|
||||||
.with(head + ".color", () -> String.valueOf(member.getColorRaw()));
|
.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()
|
public static final DateTimeFormatter DATE_TIME_FORMAT = new DateTimeFormatterBuilder()
|
||||||
.parseCaseInsensitive()
|
.parseCaseInsensitive()
|
||||||
.parseLenient()
|
.parseLenient()
|
|
@ -1,11 +1,13 @@
|
||||||
package sciwhiz12.janitor.utils;
|
package sciwhiz12.janitor.api.utils;
|
||||||
|
|
||||||
import com.mojang.brigadier.StringReader;
|
import com.mojang.brigadier.StringReader;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
|
||||||
import static com.mojang.brigadier.StringReader.isQuotedStringStart;
|
import static com.mojang.brigadier.StringReader.isQuotedStringStart;
|
||||||
|
|
||||||
public class StringReaderUtil {
|
public final class StringReaderUtil {
|
||||||
|
private StringReaderUtil() {}
|
||||||
|
|
||||||
public static boolean isAllowedInUnquotedString(final char c) {
|
public static boolean isAllowedInUnquotedString(final char c) {
|
||||||
return c >= '0' && c <= '9'
|
return c >= '0' && c <= '9'
|
||||||
|| c >= 'A' && c <= 'Z'
|
|| c >= 'A' && c <= 'Z'
|
||||||
|
@ -24,7 +26,7 @@ public class StringReaderUtil {
|
||||||
return reader.getString().substring(start, reader.getCursor());
|
return reader.getString().substring(start, reader.getCursor());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String readQuotedString(StringReader reader) throws CommandSyntaxException {
|
public static String readQuotedString(StringReader reader) throws CommandSyntaxException {
|
||||||
if (!reader.canRead()) {
|
if (!reader.canRead()) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
|
@ -1,18 +1,20 @@
|
||||||
package sciwhiz12.janitor;
|
package sciwhiz12.janitor;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
import static sciwhiz12.janitor.Logging.CONSOLE;
|
|
||||||
|
|
||||||
public class BotConsole {
|
public class BotConsole {
|
||||||
private final JanitorBot bot;
|
public static final Logger CONSOLE = LoggerFactory.getLogger("janitor.console");
|
||||||
|
|
||||||
|
private final JanitorBotImpl bot;
|
||||||
private final Thread thread;
|
private final Thread thread;
|
||||||
private volatile boolean running = true;
|
private volatile boolean running = true;
|
||||||
|
|
||||||
public BotConsole(JanitorBot bot, InputStream input) {
|
public BotConsole(JanitorBotImpl bot, InputStream input) {
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
this.thread = new Thread(this.new ConsoleThread(input));
|
this.thread = new Thread(this.new ConsoleThread(input));
|
||||||
this.thread.setName("janitor_console");
|
this.thread.setName("janitor_console");
|
||||||
|
@ -44,11 +46,6 @@ public class BotConsole {
|
||||||
case "reload": {
|
case "reload": {
|
||||||
if (parts.length >= 2)
|
if (parts.length >= 2)
|
||||||
switch (parts[1]) {
|
switch (parts[1]) {
|
||||||
case "translations": {
|
|
||||||
CONSOLE.info("Reloading translations");
|
|
||||||
bot.getTranslations().loadTranslations();
|
|
||||||
break outer;
|
|
||||||
}
|
|
||||||
case "messages": {
|
case "messages": {
|
||||||
CONSOLE.info("Reloading messages");
|
CONSOLE.info("Reloading messages");
|
||||||
bot.getMessages().loadMessages();
|
bot.getMessages().loadMessages();
|
|
@ -6,46 +6,52 @@ import net.dv8tion.jda.api.entities.Activity;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.PrivateChannel;
|
import net.dv8tion.jda.api.entities.PrivateChannel;
|
||||||
import net.dv8tion.jda.api.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
import sciwhiz12.janitor.config.BotConfig;
|
import sciwhiz12.janitor.commands.CommandRegistryImpl;
|
||||||
import sciwhiz12.janitor.msg.Messages;
|
import sciwhiz12.janitor.config.BotConfigImpl;
|
||||||
import sciwhiz12.janitor.msg.TranslationMap;
|
import sciwhiz12.janitor.config.ConfigManagerImpl;
|
||||||
import sciwhiz12.janitor.msg.emote.ReactionManager;
|
import sciwhiz12.janitor.messages.MessagesImpl;
|
||||||
import sciwhiz12.janitor.msg.substitution.SubstitutionMap;
|
import sciwhiz12.janitor.messages.emote.ReactionManagerImpl;
|
||||||
import sciwhiz12.janitor.storage.GuildStorage;
|
import sciwhiz12.janitor.messages.substitution.SubstitutionsMapImpl;
|
||||||
|
import sciwhiz12.janitor.module.ModuleManagerImpl;
|
||||||
|
import sciwhiz12.janitor.storage.GuildStorageManagerImpl;
|
||||||
import sciwhiz12.janitor.utils.Util;
|
import sciwhiz12.janitor.utils.Util;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||||
import static sciwhiz12.janitor.Logging.STATUS;
|
import static sciwhiz12.janitor.api.Logging.STATUS;
|
||||||
|
|
||||||
public class JanitorBot {
|
public class JanitorBotImpl implements JanitorBot {
|
||||||
private final JDA discord;
|
private final JDA discord;
|
||||||
private final BotConfig config;
|
private final BotConfigImpl config;
|
||||||
private final BotConsole console;
|
private final BotConsole console;
|
||||||
private final GuildStorage storage;
|
private final GuildStorageManagerImpl storage;
|
||||||
private final GuildStorage.SavingThread storageSavingThread;
|
private final GuildStorageManagerImpl.SavingThread storageSavingThread;
|
||||||
private final CommandRegistry cmdRegistry;
|
private final ConfigManagerImpl configManager;
|
||||||
private final TranslationMap translations;
|
private final CommandRegistryImpl cmdRegistry;
|
||||||
private final SubstitutionMap substitutions;
|
private final SubstitutionsMapImpl substitutions;
|
||||||
private final Messages messages;
|
private final MessagesImpl messages;
|
||||||
private final ReactionManager reactions;
|
private final ReactionManagerImpl reactions;
|
||||||
|
private final ModuleManagerImpl modules;
|
||||||
|
|
||||||
public JanitorBot(JDA discord, BotConfig config) {
|
public JanitorBotImpl(JDA discord, BotConfigImpl config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.discord = discord;
|
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 GuildStorageManagerImpl(this, Path.of(config.STORAGE_PATH.get()));
|
||||||
this.cmdRegistry = new CommandRegistry(this, config.getCommandPrefix());
|
this.configManager = new ConfigManagerImpl(this, config.getConfigsFolder());
|
||||||
this.translations = new TranslationMap(this, config.getTranslationsFile());
|
this.cmdRegistry = new CommandRegistryImpl(this);
|
||||||
this.substitutions = new SubstitutionMap(this);
|
this.substitutions = new SubstitutionsMapImpl(this);
|
||||||
this.messages = new Messages(this, config.getTranslationsFile());
|
this.messages = new MessagesImpl(this);
|
||||||
this.reactions = new ReactionManager(this);
|
this.reactions = new ReactionManagerImpl(this);
|
||||||
|
this.modules = new ModuleManagerImpl(this);
|
||||||
|
modules.activateModules();
|
||||||
// TODO: find which of these can be loaded in parallel before the bot JDA is ready
|
// TODO: find which of these can be loaded in parallel before the bot JDA is ready
|
||||||
discord.addEventListener(cmdRegistry, reactions);
|
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!"));
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
discord.getGuilds().forEach(Guild::loadMembers);
|
discord.getGuilds().forEach(Guild::loadMembers);
|
||||||
JANITOR.info("Ready!");
|
JANITOR.info("Ready!");
|
||||||
config.getOwnerID()
|
config.getOwnerID()
|
||||||
|
@ -59,40 +65,60 @@ public class JanitorBot {
|
||||||
error -> JANITOR.error(STATUS, "Error while sending ready message to owner", error)
|
error -> JANITOR.error(STATUS, "Error while sending ready message to owner", error)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
storageSavingThread = new GuildStorage.SavingThread(storage);
|
storageSavingThread = new GuildStorageManagerImpl.SavingThread(storage);
|
||||||
storageSavingThread.start();
|
storageSavingThread.start();
|
||||||
console.start();
|
console.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public JDA getDiscord() {
|
public JDA getDiscord() {
|
||||||
return this.discord;
|
return this.discord;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BotConfig getConfig() {
|
@Override
|
||||||
|
public BotConfigImpl getBotConfig() {
|
||||||
return this.config;
|
return this.config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Messages getMessages() {
|
@Override
|
||||||
|
public MessagesImpl getMessages() {
|
||||||
return messages;
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GuildStorage getStorage() { return this.storage; }
|
@Override
|
||||||
|
public SubstitutionsMapImpl getSubstitutions() {
|
||||||
|
return substitutions;
|
||||||
|
}
|
||||||
|
|
||||||
public CommandRegistry getCommandRegistry() {
|
@Override
|
||||||
|
public GuildStorageManagerImpl getGuildStorage() {
|
||||||
|
return this.storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigManagerImpl getConfigs() {
|
||||||
|
return configManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandRegistryImpl getCommands() {
|
||||||
return this.cmdRegistry;
|
return this.cmdRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TranslationMap getTranslations() {
|
@Override
|
||||||
return this.translations;
|
public ReactionManagerImpl getReactions() {
|
||||||
}
|
|
||||||
|
|
||||||
public ReactionManager getReactionManager() {
|
|
||||||
return this.reactions;
|
return this.reactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ModuleManagerImpl getModuleManager() {
|
||||||
|
return modules;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
JANITOR.info(STATUS, "Shutting down!");
|
JANITOR.info(STATUS, "Shutting down!");
|
||||||
getConfig().getOwnerID()
|
getBotConfig().getOwnerID()
|
||||||
.map(discord::retrieveUserById)
|
.map(discord::retrieveUserById)
|
||||||
.map(owner ->
|
.map(owner ->
|
||||||
owner
|
owner
|
||||||
|
@ -110,13 +136,13 @@ public class JanitorBot {
|
||||||
.error(STATUS, "Error while sending shutdown message to owner", err)
|
.error(STATUS, "Error while sending shutdown message to owner", err)
|
||||||
))
|
))
|
||||||
).ifPresent(CompletableFuture::join);
|
).ifPresent(CompletableFuture::join);
|
||||||
|
modules.shutdown();
|
||||||
discord.shutdown();
|
discord.shutdown();
|
||||||
storageSavingThread.stopThread();
|
storageSavingThread.stopThread();
|
||||||
storage.save();
|
storage.save();
|
||||||
|
configManager.save();
|
||||||
|
configManager.close();
|
||||||
console.stop();
|
console.stop();
|
||||||
}
|
config.close();
|
||||||
|
|
||||||
public SubstitutionMap getSubstitutions() {
|
|
||||||
return substitutions;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,78 +8,80 @@ import net.dv8tion.jda.api.events.GenericEvent;
|
||||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
import net.dv8tion.jda.api.hooks.EventListener;
|
import net.dv8tion.jda.api.hooks.EventListener;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.JanitorBotImpl;
|
||||||
|
import sciwhiz12.janitor.api.command.Command;
|
||||||
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
|
import sciwhiz12.janitor.api.config.CoreConfigs;
|
||||||
import sciwhiz12.janitor.commands.bot.ShutdownCommand;
|
import sciwhiz12.janitor.commands.bot.ShutdownCommand;
|
||||||
import sciwhiz12.janitor.commands.misc.HelloCommand;
|
import sciwhiz12.janitor.commands.misc.HelloCommand;
|
||||||
import sciwhiz12.janitor.commands.misc.OKCommand;
|
import sciwhiz12.janitor.commands.misc.OKCommand;
|
||||||
import sciwhiz12.janitor.commands.misc.PingCommand;
|
import sciwhiz12.janitor.commands.misc.PingCommand;
|
||||||
import sciwhiz12.janitor.commands.moderation.BanCommand;
|
|
||||||
import sciwhiz12.janitor.commands.moderation.KickCommand;
|
|
||||||
import sciwhiz12.janitor.commands.moderation.NoteCommand;
|
|
||||||
import sciwhiz12.janitor.commands.moderation.UnbanCommand;
|
|
||||||
import sciwhiz12.janitor.commands.moderation.UnwarnCommand;
|
|
||||||
import sciwhiz12.janitor.commands.moderation.WarnCommand;
|
|
||||||
import sciwhiz12.janitor.commands.moderation.WarnListCommand;
|
|
||||||
import sciwhiz12.janitor.utils.Util;
|
import sciwhiz12.janitor.utils.Util;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static sciwhiz12.janitor.Logging.COMMANDS;
|
import static sciwhiz12.janitor.api.Logging.COMMANDS;
|
||||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||||
|
|
||||||
public class CommandRegistry implements EventListener {
|
public class CommandRegistryImpl implements CommandRegistry, EventListener {
|
||||||
private final JanitorBot bot;
|
private final JanitorBotImpl bot;
|
||||||
private final String prefix;
|
private final Map<String, Command> registry = new HashMap<>();
|
||||||
private final Map<String, BaseCommand> registry = new HashMap<>();
|
|
||||||
private final CommandDispatcher<MessageReceivedEvent> dispatcher;
|
private final CommandDispatcher<MessageReceivedEvent> dispatcher;
|
||||||
|
|
||||||
public CommandRegistry(JanitorBot bot, String prefix) {
|
public CommandRegistryImpl(JanitorBotImpl bot) {
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
this.prefix = prefix;
|
|
||||||
this.dispatcher = new CommandDispatcher<>();
|
this.dispatcher = new CommandDispatcher<>();
|
||||||
|
|
||||||
addCommand(new PingCommand(this, "ping", "Pong!"));
|
addCommand(reg -> new PingCommand(reg, "ping", "Pong!"));
|
||||||
addCommand(new PingCommand(this, "pong", "Ping!"));
|
addCommand(reg -> new PingCommand(reg, "pong", "Ping!"));
|
||||||
addCommand(new OKCommand(this));
|
addCommand(OKCommand::new);
|
||||||
addCommand(new HelloCommand(this));
|
addCommand(HelloCommand::new);
|
||||||
addCommand(new KickCommand(this));
|
addCommand(ShutdownCommand::new);
|
||||||
addCommand(new BanCommand(this));
|
|
||||||
addCommand(new UnbanCommand(this));
|
|
||||||
addCommand(new WarnCommand(this));
|
|
||||||
addCommand(new WarnListCommand(this));
|
|
||||||
addCommand(new UnwarnCommand(this));
|
|
||||||
addCommand(new ShutdownCommand(this));
|
|
||||||
addCommand(new NoteCommand(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public CommandDispatcher<MessageReceivedEvent> getDispatcher() {
|
public CommandDispatcher<MessageReceivedEvent> getDispatcher() {
|
||||||
return this.dispatcher;
|
return this.dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JanitorBot getBot() {
|
@Override
|
||||||
|
public JanitorBotImpl getBot() {
|
||||||
return this.bot;
|
return this.bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCommand(BaseCommand instance) {
|
@Override
|
||||||
dispatcher.register(instance.getNode());
|
public void addCommand(Function<CommandRegistry, Command> command) {
|
||||||
|
dispatcher.register(command.apply(this).getNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(@NotNull GenericEvent genericEvent) {
|
public void onEvent(@NotNull GenericEvent genericEvent) {
|
||||||
if (!(genericEvent instanceof MessageReceivedEvent)) return;
|
if (!(genericEvent instanceof MessageReceivedEvent)) return;
|
||||||
MessageReceivedEvent event = (MessageReceivedEvent) genericEvent;
|
MessageReceivedEvent event = (MessageReceivedEvent) genericEvent;
|
||||||
|
if (event.getAuthor().isBot()) return;
|
||||||
|
final String prefix;
|
||||||
|
if (event.isFromGuild()) {
|
||||||
|
prefix = getBot().getConfigs().get(event.getGuild().getIdLong())
|
||||||
|
.forGuild(CoreConfigs.COMMAND_PREFIX);
|
||||||
|
} else {
|
||||||
|
prefix = getBot().getBotConfig().getCommandPrefix();
|
||||||
|
}
|
||||||
|
|
||||||
String msg = event.getMessage().getContentRaw();
|
String msg = event.getMessage().getContentRaw();
|
||||||
if (!msg.startsWith(this.prefix)) return;
|
if (!msg.startsWith(prefix)) return;
|
||||||
JANITOR.debug(COMMANDS, "Received message starting with valid command prefix. Author: {}, full message: {}",
|
JANITOR.debug(COMMANDS, "Received message starting with valid command prefix. Author: {}, full message: {}",
|
||||||
Util.toString(event.getAuthor()), msg);
|
Util.toString(event.getAuthor()), msg);
|
||||||
try {
|
try {
|
||||||
StringReader command = new StringReader(msg.substring(this.prefix.length()));
|
StringReader command = new StringReader(msg.substring(prefix.length()));
|
||||||
ParseResults<MessageReceivedEvent> parseResults = this.dispatcher.parse(command, event);
|
ParseResults<MessageReceivedEvent> parseResults = this.dispatcher.parse(command, event);
|
||||||
if (parseResults.getReader().canRead()) {
|
if (parseResults.getReader().canRead()) {
|
||||||
// Parsing did not succeed, i.e. command not found
|
if (parseResults.getExceptions().isEmpty()) {
|
||||||
// TODO: add separate code path when insufficient permissions / requires fails
|
JANITOR.info(COMMANDS, "Command not found.");
|
||||||
JANITOR.error(COMMANDS, "Error while parsing command: {}", parseResults.getExceptions().values());
|
} else {
|
||||||
|
JANITOR.error(COMMANDS, "Error while parsing command: {}", parseResults.getExceptions().values());
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JANITOR.debug(COMMANDS, "Executing command.");
|
JANITOR.debug(COMMANDS, "Executing command.");
|
|
@ -3,12 +3,12 @@ package sciwhiz12.janitor.commands.bot;
|
||||||
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 net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
import sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.api.command.BaseCommand;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
import sciwhiz12.janitor.utils.Util;
|
import sciwhiz12.janitor.utils.Util;
|
||||||
|
|
||||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||||
|
|
||||||
public class ShutdownCommand extends BaseCommand {
|
public class ShutdownCommand extends BaseCommand {
|
||||||
public ShutdownCommand(CommandRegistry registry) {
|
public ShutdownCommand(CommandRegistry registry) {
|
||||||
|
@ -18,7 +18,7 @@ public class ShutdownCommand extends BaseCommand {
|
||||||
@Override
|
@Override
|
||||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||||
return literal("shutdown")
|
return literal("shutdown")
|
||||||
.requires(ctx -> getBot().getConfig().getOwnerID().map(
|
.requires(ctx -> getBot().getBotConfig().getOwnerID().map(
|
||||||
id -> id == ctx.getAuthor().getIdLong()).orElse(false)
|
id -> id == ctx.getAuthor().getIdLong()).orElse(false)
|
||||||
)
|
)
|
||||||
.executes(this::run);
|
.executes(this::run);
|
|
@ -5,17 +5,17 @@ import com.mojang.brigadier.context.CommandContext;
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
import sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.api.command.BaseCommand;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
import sciwhiz12.janitor.commands.arguments.GuildMemberArgument;
|
import sciwhiz12.janitor.api.command.arguments.GuildMemberArgument;
|
||||||
import sciwhiz12.janitor.utils.Util;
|
import sciwhiz12.janitor.utils.Util;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMembers;
|
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.getMembers;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||||
|
|
||||||
public class HelloCommand extends BaseCommand {
|
public class HelloCommand extends BaseCommand {
|
||||||
public HelloCommand(CommandRegistry registry) {
|
public HelloCommand(CommandRegistry registry) {
|
||||||
|
@ -38,7 +38,7 @@ public class HelloCommand extends BaseCommand {
|
||||||
success -> {
|
success -> {
|
||||||
JANITOR.debug("Sent greeting message to {}, on cmd of {}", Util.toString(member.getUser()),
|
JANITOR.debug("Sent greeting message to {}, on cmd of {}", Util.toString(member.getUser()),
|
||||||
Util.toString(ctx.getSource().getAuthor()));
|
Util.toString(ctx.getSource().getAuthor()));
|
||||||
getBot().getReactionManager().newMessage(success)
|
getBot().getReactions().newMessage(success)
|
||||||
.add("\u274C", (msg, event) -> success.delete()
|
.add("\u274C", (msg, event) -> success.delete()
|
||||||
.flatMap(v -> event.getChannel()
|
.flatMap(v -> event.getChannel()
|
||||||
.deleteMessageById(ctx.getSource().getMessageIdLong()))
|
.deleteMessageById(ctx.getSource().getMessageIdLong()))
|
|
@ -3,12 +3,12 @@ package sciwhiz12.janitor.commands.misc;
|
||||||
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 net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
import sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.api.command.BaseCommand;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
import sciwhiz12.janitor.utils.Util;
|
import sciwhiz12.janitor.utils.Util;
|
||||||
|
|
||||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||||
|
|
||||||
public class OKCommand extends BaseCommand {
|
public class OKCommand extends BaseCommand {
|
||||||
public OKCommand(CommandRegistry registry) {
|
public OKCommand(CommandRegistry registry) {
|
|
@ -3,12 +3,12 @@ package sciwhiz12.janitor.commands.misc;
|
||||||
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 net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
import sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.api.command.BaseCommand;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
import sciwhiz12.janitor.utils.Util;
|
import sciwhiz12.janitor.utils.Util;
|
||||||
|
|
||||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||||
|
|
||||||
public class PingCommand extends BaseCommand {
|
public class PingCommand extends BaseCommand {
|
||||||
private final String command;
|
private final String command;
|
|
@ -4,43 +4,38 @@ 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 com.google.common.base.Preconditions;
|
||||||
|
import sciwhiz12.janitor.api.config.BotConfig;
|
||||||
|
|
||||||
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 javax.annotation.Nullable;
|
||||||
|
|
||||||
import static sciwhiz12.janitor.Logging.CONFIG;
|
import static sciwhiz12.janitor.api.Logging.CONFIG;
|
||||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||||
|
|
||||||
public class BotConfig {
|
public class BotConfigImpl implements BotConfig {
|
||||||
public static final Path DEFAULT_CONFIG_PATH = Path.of("config.toml");
|
public static final Path DEFAULT_CONFIG_PATH = Path.of("config.toml");
|
||||||
|
|
||||||
private final CommentedConfigSpec.ConfigValue<String> CLIENT_TOKEN;
|
private final CommentedConfigSpec.ConfigValue<String> CLIENT_TOKEN;
|
||||||
private final CommentedConfigSpec.LongValue OWNER_ID;
|
private final CommentedConfigSpec.LongValue OWNER_ID;
|
||||||
|
|
||||||
|
public final CommentedConfigSpec.ConfigValue<String> CONFIGS_PATH;
|
||||||
|
|
||||||
public final CommentedConfigSpec.ConfigValue<String> STORAGE_PATH;
|
public final CommentedConfigSpec.ConfigValue<String> STORAGE_PATH;
|
||||||
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_MESSAGES_DIRECTORY;
|
public final CommentedConfigSpec.ConfigValue<String> CUSTOM_MESSAGES_DIRECTORY;
|
||||||
|
|
||||||
public final CommentedConfigSpec.ConfigValue<String> COMMAND_PREFIX;
|
public final CommentedConfigSpec.ConfigValue<String> COMMAND_PREFIX;
|
||||||
|
|
||||||
public final CommentedConfigSpec.BooleanValue WARNINGS_ENABLE;
|
|
||||||
public final CommentedConfigSpec.BooleanValue WARNINGS_RESPECT_MOD_ROLES;
|
|
||||||
public final CommentedConfigSpec.BooleanValue WARNINGS_PREVENT_WARNING_MODS;
|
|
||||||
public final CommentedConfigSpec.BooleanValue WARNINGS_REMOVE_SELF_WARNINGS;
|
|
||||||
|
|
||||||
public final CommentedConfigSpec.IntValue NOTES_MAX_AMOUNT_PER_MOD;
|
|
||||||
public final CommentedConfigSpec.BooleanValue NOTES_ENABLE;
|
|
||||||
|
|
||||||
private final BotOptions options;
|
private final BotOptions options;
|
||||||
private final Path configPath;
|
private final Path configPath;
|
||||||
private final CommentedConfigSpec spec;
|
private final CommentedConfigSpec spec;
|
||||||
private final CommentedFileConfig config;
|
private final CommentedFileConfig config;
|
||||||
|
|
||||||
public BotConfig(BotOptions options) {
|
public BotConfigImpl(BotOptions options) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
|
||||||
final CommentedConfigSpec.Builder builder = new CommentedConfigSpec.Builder();
|
final CommentedConfigSpec.Builder builder = new CommentedConfigSpec.Builder();
|
||||||
|
@ -55,6 +50,10 @@ public class BotConfig {
|
||||||
.defineInRange("owner_id", 0L, Long.MIN_VALUE, Long.MAX_VALUE);
|
.defineInRange("owner_id", 0L, Long.MIN_VALUE, Long.MAX_VALUE);
|
||||||
builder.pop();
|
builder.pop();
|
||||||
|
|
||||||
|
CONFIGS_PATH = builder
|
||||||
|
.comment("The folder where guild configs are kept.")
|
||||||
|
.define("configs_path", "configs");
|
||||||
|
|
||||||
builder.push("storage");
|
builder.push("storage");
|
||||||
STORAGE_PATH = builder
|
STORAGE_PATH = builder
|
||||||
.comment("The folder where per-guild storage is kept.")
|
.comment("The folder where per-guild storage is kept.")
|
||||||
|
@ -64,10 +63,6 @@ public class BotConfig {
|
||||||
.defineInRange("autosave_internal", 20, 1, Integer.MAX_VALUE);
|
.defineInRange("autosave_internal", 20, 1, Integer.MAX_VALUE);
|
||||||
builder.pop();
|
builder.pop();
|
||||||
|
|
||||||
CUSTOM_TRANSLATION_FILE = builder
|
|
||||||
.comment("A file which contains custom translation keys to load for messages.",
|
|
||||||
"If blank, no file shall be loaded.")
|
|
||||||
.define("messages.custom_translations", "");
|
|
||||||
CUSTOM_MESSAGES_DIRECTORY = builder
|
CUSTOM_MESSAGES_DIRECTORY = builder
|
||||||
.comment("A folder containing custom messages, with a 'messages.json' key file.",
|
.comment("A folder containing custom messages, with a 'messages.json' key file.",
|
||||||
"If blank, no folder shall be loaded and defaults will be used.")
|
"If blank, no folder shall be loaded and defaults will be used.")
|
||||||
|
@ -77,36 +72,6 @@ public class BotConfig {
|
||||||
.comment("The prefix for commands.")
|
.comment("The prefix for commands.")
|
||||||
.define("commands.prefix", "!");
|
.define("commands.prefix", "!");
|
||||||
|
|
||||||
builder.comment("Moderation settings").push("moderation");
|
|
||||||
{
|
|
||||||
builder.comment("Settings for the warnings system").push("warnings");
|
|
||||||
WARNINGS_ENABLE = builder
|
|
||||||
.comment("Whether to enable the warnings system. If disabled, the related commands are force-disabled.")
|
|
||||||
.define("enable", true);
|
|
||||||
WARNINGS_RESPECT_MOD_ROLES = builder
|
|
||||||
.comment(
|
|
||||||
"Whether to prevent lower-ranked moderators (in the role hierarchy) from removing warnings issued by " +
|
|
||||||
"higher-ranked moderators.")
|
|
||||||
.define("respect_mod_roles", false);
|
|
||||||
WARNINGS_PREVENT_WARNING_MODS = builder
|
|
||||||
.comment("Whether to prevent moderators from issuing warnings against other moderators.")
|
|
||||||
.define("warn_other_moderators", false);
|
|
||||||
WARNINGS_REMOVE_SELF_WARNINGS = builder
|
|
||||||
.comment("Whether to allow moderators to remove warnings from themselves.")
|
|
||||||
.define("remove_self_warnings", false);
|
|
||||||
builder.pop();
|
|
||||||
|
|
||||||
builder.comment("Settings for the notes system").push("notes");
|
|
||||||
NOTES_ENABLE = builder
|
|
||||||
.comment("Whether to enable the notes system. If disabled, the related commands are force-disabled.")
|
|
||||||
.define("enable", true);
|
|
||||||
NOTES_MAX_AMOUNT_PER_MOD = builder
|
|
||||||
.comment("The max amount of notes for a user per moderator.")
|
|
||||||
.defineInRange("max_amount", Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
|
|
||||||
builder.pop();
|
|
||||||
}
|
|
||||||
builder.pop();
|
|
||||||
|
|
||||||
spec = builder.build();
|
spec = builder.build();
|
||||||
|
|
||||||
this.configPath = options.getConfigPath().orElse(DEFAULT_CONFIG_PATH);
|
this.configPath = options.getConfigPath().orElse(DEFAULT_CONFIG_PATH);
|
||||||
|
@ -123,21 +88,16 @@ public class BotConfig {
|
||||||
} 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);
|
||||||
}
|
}
|
||||||
|
Preconditions.checkArgument(!getToken().isEmpty(), "Supply a client token through config or command line");
|
||||||
|
Preconditions.checkArgument(options.getConfigsFolder().
|
||||||
|
or(() -> Optional.ofNullable(Path.of(CONFIGS_PATH.get()))).isPresent(), "No guilds config folder defined");
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommentedFileConfig getRawConfig() {
|
public CommentedFileConfig getRawConfig() {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Override
|
||||||
public Path getTranslationsFile() {
|
|
||||||
return options.getTranslationsFile().
|
|
||||||
or(() -> CUSTOM_TRANSLATION_FILE.get().isBlank() ?
|
|
||||||
Optional.empty() :
|
|
||||||
Optional.of(Path.of(CUSTOM_TRANSLATION_FILE.get())))
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Path getMessagesFolder() {
|
public Path getMessagesFolder() {
|
||||||
return options.getMessagesFolder().
|
return options.getMessagesFolder().
|
||||||
|
@ -147,16 +107,25 @@ public class BotConfig {
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Path getConfigsFolder() {
|
||||||
|
return options.getConfigsFolder().
|
||||||
|
orElseGet(() -> Path.of(CONFIGS_PATH.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getToken() {
|
public String getToken() {
|
||||||
return options.getToken().orElse(CLIENT_TOKEN.get());
|
return options.getToken().orElse(CLIENT_TOKEN.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getCommandPrefix() {
|
public String getCommandPrefix() {
|
||||||
return options.getCommandPrefix().orElseGet(COMMAND_PREFIX::get);
|
return options.getCommandPrefix().orElseGet(COMMAND_PREFIX::get);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Optional<Long> getOwnerID() {
|
public Optional<Long> getOwnerID() {
|
||||||
final Long ret = options.getOwnerID().orElse(OWNER_ID.get());
|
final long ret = options.getOwnerID().orElse(OWNER_ID.get());
|
||||||
if (ret == 0) return Optional.empty();
|
if (ret == 0) return Optional.empty();
|
||||||
return Optional.of(ret);
|
return Optional.of(ret);
|
||||||
}
|
}
|
|
@ -13,8 +13,8 @@ import static joptsimple.util.PathProperties.*;
|
||||||
public class BotOptions {
|
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> messagesFolder;
|
private final ArgumentAcceptingOptionSpec<Path> messagesFolder;
|
||||||
|
private final ArgumentAcceptingOptionSpec<Path> configsFolder;
|
||||||
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;
|
||||||
|
@ -25,12 +25,12 @@ public class BotOptions {
|
||||||
.accepts("config", "The path to the config file; defaults to 'config.toml'")
|
.accepts("config", "The path to the config file; defaults to 'config.toml'")
|
||||||
.withRequiredArg()
|
.withRequiredArg()
|
||||||
.withValuesConvertedBy(new PathConverter(FILE_EXISTING, READABLE, WRITABLE));
|
.withValuesConvertedBy(new PathConverter(FILE_EXISTING, READABLE, WRITABLE));
|
||||||
this.translationsPath = parser
|
|
||||||
.accepts("translations", "The path to the translations file")
|
|
||||||
.withRequiredArg()
|
|
||||||
.withValuesConvertedBy(new PathConverter(FILE_EXISTING, READABLE));
|
|
||||||
this.messagesFolder = parser
|
this.messagesFolder = parser
|
||||||
.accepts("translations", "The path to the custom messages folder")
|
.accepts("messages", "The path to the custom messages folder")
|
||||||
|
.withRequiredArg()
|
||||||
|
.withValuesConvertedBy(new PathConverter(DIRECTORY_EXISTING, READABLE));
|
||||||
|
this.configsFolder = parser
|
||||||
|
.accepts("guildConfigs", "The path to the guild configs folder")
|
||||||
.withRequiredArg()
|
.withRequiredArg()
|
||||||
.withValuesConvertedBy(new PathConverter(DIRECTORY_EXISTING, READABLE));
|
.withValuesConvertedBy(new PathConverter(DIRECTORY_EXISTING, READABLE));
|
||||||
this.token = parser
|
this.token = parser
|
||||||
|
@ -50,14 +50,14 @@ public class BotOptions {
|
||||||
return configPath.valueOptional(options);
|
return configPath.valueOptional(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Path> getTranslationsFile() {
|
|
||||||
return translationsPath.valueOptional(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<Path> getMessagesFolder() {
|
public Optional<Path> getMessagesFolder() {
|
||||||
return messagesFolder.valueOptional(options);
|
return messagesFolder.valueOptional(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<Path> getConfigsFolder() {
|
||||||
|
return configsFolder.valueOptional(options);
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<String> getToken() {
|
public Optional<String> getToken() {
|
||||||
return token.valueOptional(options);
|
return token.valueOptional(options);
|
||||||
}
|
}
|
|
@ -32,7 +32,7 @@ import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.ObjectArrays;
|
import com.google.common.collect.ObjectArrays;
|
||||||
import sciwhiz12.janitor.Logging;
|
import sciwhiz12.janitor.api.Logging;
|
||||||
import sciwhiz12.janitor.utils.Pair;
|
import sciwhiz12.janitor.utils.Pair;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -60,7 +60,7 @@ import static com.google.common.base.Preconditions.checkState;
|
||||||
* Like {@link com.electronwill.nightconfig.core.ConfigSpec} except in builder format, and extended to accept comments.
|
* Like {@link com.electronwill.nightconfig.core.ConfigSpec} except in builder format, and extended to accept comments.
|
||||||
*
|
*
|
||||||
* @author @MinecraftForge
|
* @author @MinecraftForge
|
||||||
* @author SciWhiz12 (modified to remove unneede parts)
|
* @author SciWhiz12 (modified to remove unneeded parts)
|
||||||
*/
|
*/
|
||||||
//TODO: Remove extends and pipe everything through getSpec/getValues?
|
//TODO: Remove extends and pipe everything through getSpec/getValues?
|
||||||
public class CommentedConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfig> {
|
public class CommentedConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfig> {
|
|
@ -0,0 +1,72 @@
|
||||||
|
package sciwhiz12.janitor.config;
|
||||||
|
|
||||||
|
import com.electronwill.nightconfig.core.CommentedConfig;
|
||||||
|
import sciwhiz12.janitor.JanitorBotImpl;
|
||||||
|
import sciwhiz12.janitor.api.config.ConfigManager;
|
||||||
|
import sciwhiz12.janitor.api.config.ConfigNode;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static sciwhiz12.janitor.api.config.CoreConfigs.COMMAND_PREFIX;
|
||||||
|
import static sciwhiz12.janitor.api.config.CoreConfigs.ENABLE;
|
||||||
|
|
||||||
|
public class ConfigManagerImpl implements ConfigManager {
|
||||||
|
private final JanitorBotImpl bot;
|
||||||
|
private final Path configPath;
|
||||||
|
private final Map<Long, GuildConfigImpl> configMap = new HashMap<>();
|
||||||
|
private final List<ConfigNode<?>> configNodes = new ArrayList<>();
|
||||||
|
|
||||||
|
public ConfigManagerImpl(JanitorBotImpl bot, Path configPath) {
|
||||||
|
this.bot = bot;
|
||||||
|
this.configPath = configPath;
|
||||||
|
registerNodes(ENABLE, COMMAND_PREFIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GuildConfigImpl get(long guildID) {
|
||||||
|
final GuildConfigImpl config = configMap.computeIfAbsent(guildID, (id) -> new GuildConfigImpl(id, getFile(guildID)));
|
||||||
|
configNodes.forEach(config::forGuild); // Ensures the config is correct
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JanitorBotImpl getBot() {
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() {
|
||||||
|
configMap.values().forEach(GuildConfigImpl::save);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerNode(ConfigNode<?> node) {
|
||||||
|
configNodes.add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
configMap.values().forEach(GuildConfigImpl::close);
|
||||||
|
for (Iterator<GuildConfigImpl> iterator = configMap.values().iterator(); iterator.hasNext(); ) {
|
||||||
|
iterator.next().close();
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path getFile(long guildID) {
|
||||||
|
final Path file = Path.of(Long.toHexString(guildID) + ".toml");
|
||||||
|
return configPath.resolve(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ensureComment(CommentedConfig config, String path, String expectedComment) {
|
||||||
|
if (!Objects.equals(config.getComment(path), expectedComment)) {
|
||||||
|
config.setComment(path, expectedComment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
140
core/src/main/java/sciwhiz12/janitor/config/GuildConfigImpl.java
Normal file
140
core/src/main/java/sciwhiz12/janitor/config/GuildConfigImpl.java
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
package sciwhiz12.janitor.config;
|
||||||
|
|
||||||
|
import com.electronwill.nightconfig.core.CommentedConfig;
|
||||||
|
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||||
|
import com.electronwill.nightconfig.core.file.FileNotFoundAction;
|
||||||
|
import com.electronwill.nightconfig.core.file.FileWatcher;
|
||||||
|
import com.electronwill.nightconfig.toml.TomlFormat;
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import net.dv8tion.jda.api.entities.GuildChannel;
|
||||||
|
import sciwhiz12.janitor.api.config.ConfigNode;
|
||||||
|
import sciwhiz12.janitor.api.config.GuildConfig;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import static sciwhiz12.janitor.api.Logging.CONFIG;
|
||||||
|
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||||
|
import static sciwhiz12.janitor.config.ConfigManagerImpl.ensureComment;
|
||||||
|
|
||||||
|
public class GuildConfigImpl implements GuildConfig {
|
||||||
|
private static final Joiner NEWLINE = Joiner.on("\n");
|
||||||
|
|
||||||
|
private final long guild;
|
||||||
|
private final CommentedFileConfig config;
|
||||||
|
private boolean closed = false;
|
||||||
|
|
||||||
|
GuildConfigImpl(long guild, Path configPath) {
|
||||||
|
this.guild = guild;
|
||||||
|
this.config = CommentedFileConfig.builder(configPath, TomlFormat.instance())
|
||||||
|
.onFileNotFound(FileNotFoundAction.CREATE_EMPTY)
|
||||||
|
.preserveInsertionOrder()
|
||||||
|
.autosave()
|
||||||
|
.build();
|
||||||
|
try {
|
||||||
|
CONFIG.info("Building guild config for {} from {}", Long.toHexString(this.guild), configPath);
|
||||||
|
config.load();
|
||||||
|
FileWatcher.defaultInstance().addWatch(configPath, this::onFileChange);
|
||||||
|
// ConfigNode.nodes.forEach(this::forGuild);
|
||||||
|
save();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
JANITOR.error("Error while building config from file {}", configPath, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommentedConfig getChannelOverrides() {
|
||||||
|
final String channelOverridesID = "channel_overrides";
|
||||||
|
CommentedConfig channelConfigs = config.get(channelOverridesID);
|
||||||
|
if (channelConfigs == null) {
|
||||||
|
channelConfigs = config.createSubConfig();
|
||||||
|
config.set(channelOverridesID, channelConfigs);
|
||||||
|
config.setComment(channelOverridesID, "Channel overrides for certain configuration options");
|
||||||
|
}
|
||||||
|
return channelConfigs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommentedConfig getChannelConfig(GuildChannel channel) {
|
||||||
|
final String id = channel.getId();
|
||||||
|
CommentedConfig overrides = getChannelOverrides();
|
||||||
|
CommentedConfig channelOverride = overrides.get(id);
|
||||||
|
if (channelOverride == null) {
|
||||||
|
channelOverride = overrides.createSubConfig();
|
||||||
|
overrides.set(id, channelOverride);
|
||||||
|
overrides.setComment(id, "Channel overrides for channel with name " + channel.getName());
|
||||||
|
}
|
||||||
|
return channelOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T forGuild(ConfigNode<T> node) {
|
||||||
|
ensureComment(config, node.path(), node.comment());
|
||||||
|
T value = config.get(node.path());
|
||||||
|
if (value == null) {
|
||||||
|
value = node.defaultValue().get();
|
||||||
|
config.set(node.path(), value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> void forGuild(ConfigNode<T> node, T newValue) {
|
||||||
|
ensureComment(config, node.path(), node.comment());
|
||||||
|
config.set(node.path(), newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T forChannel(GuildChannel channel, ConfigNode<T> node) {
|
||||||
|
CommentedConfig channelConfig = getChannelConfig(channel);
|
||||||
|
ensureComment(channelConfig, node.path(), node.comment());
|
||||||
|
T value = channelConfig.getRaw(node.path());
|
||||||
|
if (value == null) {
|
||||||
|
value = node.defaultValue().get();
|
||||||
|
channelConfig.set(node.path(), node.defaultValue().get());
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> void forChannel(GuildChannel channel, ConfigNode<T> node, T newValue) {
|
||||||
|
CommentedConfig channelConfig = getChannelConfig(channel);
|
||||||
|
ensureComment(channelConfig, node.path(), node.comment());
|
||||||
|
channelConfig.set(node.path(), newValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getGuildID() {
|
||||||
|
return guild;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommentedFileConfig getRawConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save() {
|
||||||
|
if (!closed) {
|
||||||
|
config.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if (!closed) {
|
||||||
|
closed = true;
|
||||||
|
config.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onFileChange() {
|
||||||
|
if (closed) return;
|
||||||
|
try {
|
||||||
|
CONFIG.info("Reloading config due to file change {}", config.getNioPath());
|
||||||
|
config.load();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
CONFIG.error("Error while reloading config from {}", config.getNioPath(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,238 @@
|
||||||
|
package sciwhiz12.janitor.messages;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.primitives.Ints;
|
||||||
|
import joptsimple.internal.Strings;
|
||||||
|
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 net.dv8tion.jda.api.entities.Role;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
import sciwhiz12.janitor.api.messages.ListingMessage;
|
||||||
|
import sciwhiz12.janitor.api.messages.substitution.ModifiableSubstitutor;
|
||||||
|
import sciwhiz12.janitor.api.messages.substitution.SubstitutionsMap;
|
||||||
|
import sciwhiz12.janitor.api.messages.substitution.Substitutor;
|
||||||
|
import sciwhiz12.janitor.messages.substitution.CustomSubstitutions;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
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.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ListingMessageBuilder<T> implements ListingMessage.Builder<T> {
|
||||||
|
private final ListingMessage message;
|
||||||
|
private final Map<String, Supplier<String>> customSubstitutions;
|
||||||
|
private int amountPerPage = 6;
|
||||||
|
private BiConsumer<T, ModifiableSubstitutor<?>> 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, ModifiableSubstitutor<?>> entryApplier) {
|
||||||
|
this.entryApplier = entryApplier;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListingMessageBuilder<T> apply(Consumer<ListingMessage.Builder<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,
|
||||||
|
SubstitutionsMap globalSubstitutions,
|
||||||
|
Message triggerMessage,
|
||||||
|
List<T> entries) {
|
||||||
|
|
||||||
|
final ModifiableSubstitutor<?> customSubs = globalSubstitutions.with(customSubstitutions);
|
||||||
|
final ImmutableList<T> list = ImmutableList.copyOf(entries);
|
||||||
|
final PagedMessage pagedMessage = new PagedMessage(message, list, amountPerPage);
|
||||||
|
|
||||||
|
channel.sendMessage(pagedMessage.createMessage(customSubs, entryApplier))
|
||||||
|
.queue(listMsg -> globalSubstitutions.getBot().getReactions().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(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(customSubs, entryApplier))
|
||||||
|
)
|
||||||
|
.queue();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.create()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void build(MessageChannel channel, JanitorBot bot, Message triggerMessage, List<T> entries) {
|
||||||
|
build(channel, 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(ModifiableSubstitutor<?> substitutions,
|
||||||
|
BiConsumer<T, ModifiableSubstitutor<?>> applier) {
|
||||||
|
if (currentPage != lastPage) {
|
||||||
|
cachedMessage = create(
|
||||||
|
message,
|
||||||
|
substitutions
|
||||||
|
.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
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> EmbedBuilder create(
|
||||||
|
ListingMessage message,
|
||||||
|
Substitutor global,
|
||||||
|
Iterable<T> iterable,
|
||||||
|
BiConsumer<T, ModifiableSubstitutor<?>> entryApplier
|
||||||
|
) {
|
||||||
|
final EmbedBuilder builder = new EmbedBuilder();
|
||||||
|
builder.setTitle(global.substitute(message.getTitle()), global.substitute(message.getUrl()));
|
||||||
|
builder.setColor(parseColor(global.substitute(message.getColor())));
|
||||||
|
builder.setAuthor(global.substitute(message.getAuthorName()), global.substitute(message.getAuthorUrl()),
|
||||||
|
global.substitute(message.getAuthorIconUrl()));
|
||||||
|
builder.setDescription(global.substitute(message.getDescription()));
|
||||||
|
builder.setImage(global.substitute(message.getImageUrl()));
|
||||||
|
builder.setThumbnail(global.substitute(message.getThumbnailUrl()));
|
||||||
|
builder.setTimestamp(OffsetDateTime.now(ZoneOffset.UTC));
|
||||||
|
builder.setFooter(global.substitute(message.getFooterText()), global.substitute(message.getFooterIconUrl()));
|
||||||
|
for (MessageEmbed.Field field : message.getBeforeFields()) {
|
||||||
|
builder.addField(global.substitute(field.getName()), global.substitute(field.getValue()), field.isInline());
|
||||||
|
}
|
||||||
|
|
||||||
|
final ListingMessage.Entry entry = message.getEntry();
|
||||||
|
|
||||||
|
final CustomSubstitutions entrySubs = new CustomSubstitutions();
|
||||||
|
final Function<String, String> entryFunc = str -> str != null ? entrySubs.substitute(global.substitute(str)) : null;
|
||||||
|
int count = 0;
|
||||||
|
for (T listEntry : iterable) {
|
||||||
|
entryApplier.accept(listEntry, entrySubs);
|
||||||
|
if (entry instanceof ListingMessage.FieldEntry) {
|
||||||
|
ListingMessage.FieldEntry fieldEntry = (ListingMessage.FieldEntry) entry;
|
||||||
|
builder.addField(
|
||||||
|
entryFunc.apply(fieldEntry.getFieldName()),
|
||||||
|
entryFunc.apply(fieldEntry.getFieldValue()),
|
||||||
|
fieldEntry.isInline()
|
||||||
|
);
|
||||||
|
} else if (entry instanceof ListingMessage.DescriptionEntry) {
|
||||||
|
ListingMessage.DescriptionEntry descEntry = (ListingMessage.DescriptionEntry) entry;
|
||||||
|
builder.getDescriptionBuilder().append(entryFunc.apply(descEntry.getDescription()));
|
||||||
|
builder.getDescriptionBuilder().append(descEntry.getJoiner());
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (count < 1) {
|
||||||
|
builder.getDescriptionBuilder().append(global.substitute(message.getEmptyText()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MessageEmbed.Field field : message.getAfterFields()) {
|
||||||
|
builder.addField(global.substitute(field.getName()), global.substitute(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;
|
||||||
|
}
|
||||||
|
}
|
159
core/src/main/java/sciwhiz12/janitor/messages/MessagesImpl.java
Normal file
159
core/src/main/java/sciwhiz12/janitor/messages/MessagesImpl.java
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
package sciwhiz12.janitor.messages;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
import sciwhiz12.janitor.JanitorBotImpl;
|
||||||
|
import sciwhiz12.janitor.api.messages.ListingMessage;
|
||||||
|
import sciwhiz12.janitor.api.messages.Messages;
|
||||||
|
import sciwhiz12.janitor.api.messages.RegularMessage;
|
||||||
|
import sciwhiz12.janitor.messages.json.ListingMessageDeserializer;
|
||||||
|
import sciwhiz12.janitor.messages.json.RegularMessageDeserializer;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||||
|
import static sciwhiz12.janitor.api.Logging.MESSAGES;
|
||||||
|
|
||||||
|
public class MessagesImpl implements Messages {
|
||||||
|
public static final String JSON_FILE_SUFFIX = ".json";
|
||||||
|
public static final String MESSAGE_LIST_FILENAME = "messages.json";
|
||||||
|
public static final String MESSAGES_FOLDER = "messages/";
|
||||||
|
public static final TypeReference<List<String>> LIST_TYPE = new TypeReference<>() {};
|
||||||
|
|
||||||
|
private final JanitorBotImpl bot;
|
||||||
|
|
||||||
|
private final Map<String, RegularMessage> defaultRegularMessages = new HashMap<>();
|
||||||
|
private final Map<String, ListingMessage> defaultListingMessages = new HashMap<>();
|
||||||
|
private final Map<String, RegularMessage> customRegularMessages = new HashMap<>();
|
||||||
|
private final Map<String, ListingMessage> customListingMessages = new HashMap<>();
|
||||||
|
private final ObjectMapper jsonMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
public MessagesImpl(JanitorBotImpl bot) {
|
||||||
|
this.bot = bot;
|
||||||
|
SimpleModule messageModule = new SimpleModule();
|
||||||
|
messageModule.addDeserializer(ListingMessage.class, new ListingMessageDeserializer());
|
||||||
|
messageModule.addDeserializer(RegularMessage.class, new RegularMessageDeserializer());
|
||||||
|
jsonMapper.registerModule(messageModule);
|
||||||
|
loadMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JanitorBotImpl getBot() {
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadMessages() {
|
||||||
|
ClassLoader ctxLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
|
||||||
|
JANITOR.info(MESSAGES, "Loading default messages");
|
||||||
|
defaultListingMessages.clear();
|
||||||
|
ctxLoader.resources(MESSAGES_FOLDER + MESSAGE_LIST_FILENAME)
|
||||||
|
.forEach(url -> {
|
||||||
|
JANITOR.info("Loading messages from {}", url.getPath());
|
||||||
|
try (Reader keyReader = new InputStreamReader(url.openStream())) {
|
||||||
|
int loadedCount = 0;
|
||||||
|
for (String messageKey : jsonMapper.readValue(keyReader, LIST_TYPE)) {
|
||||||
|
InputStream resourceStream = ctxLoader
|
||||||
|
.getResourceAsStream(MESSAGES_FOLDER + messageKey + JSON_FILE_SUFFIX);
|
||||||
|
if (resourceStream == null) {
|
||||||
|
JANITOR.warn("Defined message {} cannot be found", messageKey);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
loadedCount += readMessage(messageKey,
|
||||||
|
() -> new InputStreamReader(resourceStream),
|
||||||
|
defaultRegularMessages,
|
||||||
|
defaultListingMessages);
|
||||||
|
}
|
||||||
|
JANITOR.debug(MESSAGES, "Loaded {} messages", loadedCount);
|
||||||
|
} catch (Exception e) {
|
||||||
|
JANITOR.error(MESSAGES, "Error while loading default messages from {}", url.getPath(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Path messagesFolder = bot.getBotConfig().getMessagesFolder();
|
||||||
|
if (messagesFolder != null) {
|
||||||
|
JANITOR.info(MESSAGES, "Loading custom messages from folder {}", messagesFolder);
|
||||||
|
try (Reader keyReader = Files.newBufferedReader(messagesFolder.resolve(MESSAGE_LIST_FILENAME))) {
|
||||||
|
int loadedCount = 0;
|
||||||
|
for (String messageKey : jsonMapper.readValue(keyReader, LIST_TYPE)) {
|
||||||
|
final Path messagePath = messagesFolder.resolve(messageKey + JSON_FILE_SUFFIX);
|
||||||
|
if (Files.notExists(messagePath)) {
|
||||||
|
JANITOR.warn("Defined message {} cannot be found", messageKey);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
readMessage(messageKey, () -> Files.newBufferedReader(messagePath), customRegularMessages,
|
||||||
|
customListingMessages);
|
||||||
|
loadedCount++;
|
||||||
|
}
|
||||||
|
JANITOR.debug(MESSAGES, "Loaded {} messages", loadedCount);
|
||||||
|
} catch (Exception e) {
|
||||||
|
JANITOR.error(MESSAGES, "Error while loading custom messages", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
JANITOR.info(MESSAGES, "No custom messages folder specified");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
interface ThrowableSupplier<T, E extends Throwable> {
|
||||||
|
T get() throws E;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int readMessage(String messageKey, ThrowableSupplier<Reader, Exception> input,
|
||||||
|
Map<String, RegularMessage> regularMessages, Map<String, ListingMessage> listingMessages) {
|
||||||
|
try {
|
||||||
|
final JsonNode tree = jsonMapper.readTree(input.get());
|
||||||
|
final String type = tree.path("type").asText("regular");
|
||||||
|
switch (type) {
|
||||||
|
case "regular": {
|
||||||
|
regularMessages.put(messageKey, jsonMapper.convertValue(tree, RegularMessage.class));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "listing": {
|
||||||
|
listingMessages.put(messageKey, jsonMapper.convertValue(tree, ListingMessage.class));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
JANITOR.warn(MESSAGES, "Unknown message type {} for {}", tree.path("type").asText(), messageKey);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
} catch (Exception e) {
|
||||||
|
JANITOR.error(MESSAGES, "Error while loading message {}", messageKey, e);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegularMessageBuilder getRegularMessage(String messageKey) {
|
||||||
|
RegularMessage msg = customRegularMessages.get(messageKey);
|
||||||
|
if (msg == null) {
|
||||||
|
msg = defaultRegularMessages.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 <T> ListingMessageBuilder<T> getListingMessage(String messageKey) {
|
||||||
|
ListingMessage msg = customListingMessages.get(messageKey);
|
||||||
|
if (msg == null) {
|
||||||
|
msg = defaultListingMessages.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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
package sciwhiz12.janitor.messages;
|
||||||
|
|
||||||
|
import com.google.common.primitives.Ints;
|
||||||
|
import joptsimple.internal.Strings;
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder;
|
||||||
|
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||||
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
|
import net.dv8tion.jda.api.entities.Role;
|
||||||
|
import net.dv8tion.jda.api.requests.restaction.MessageAction;
|
||||||
|
import sciwhiz12.janitor.JanitorBotImpl;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
import sciwhiz12.janitor.api.messages.RegularMessage;
|
||||||
|
import sciwhiz12.janitor.api.messages.substitution.SubstitutionsMap;
|
||||||
|
import sciwhiz12.janitor.api.messages.substitution.Substitutor;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class RegularMessageBuilder implements RegularMessage.Builder<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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageEmbed build(SubstitutionsMap substitutions) {
|
||||||
|
return create(message, substitutions.with(customSubstitutions)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MessageEmbed build(JanitorBot bot) {
|
||||||
|
return build(bot.getSubstitutions());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageAction send(JanitorBotImpl bot, MessageChannel channel) {
|
||||||
|
return channel.sendMessage(build(bot));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EmbedBuilder create(RegularMessage message, Substitutor subs) {
|
||||||
|
final EmbedBuilder builder = new EmbedBuilder();
|
||||||
|
builder.setTitle(subs.substitute(message.getTitle()), subs.substitute(message.getUrl()));
|
||||||
|
builder.setColor(parseColor(subs.substitute(message.getColor())));
|
||||||
|
builder.setAuthor(subs.substitute(message.getAuthorName()), subs.substitute(message.getAuthorUrl()), subs.substitute(
|
||||||
|
message.getAuthorIconUrl()));
|
||||||
|
builder.setDescription(subs.substitute(message.getDescription()));
|
||||||
|
builder.setImage(subs.substitute(message.getImageUrl()));
|
||||||
|
builder.setThumbnail(subs.substitute(message.getThumbnailUrl()));
|
||||||
|
builder.setTimestamp(OffsetDateTime.now(ZoneOffset.UTC));
|
||||||
|
builder.setFooter(subs.substitute(message.getFooterText()), subs.substitute(message.getFooterIconUrl()));
|
||||||
|
for (MessageEmbed.Field field : message.getFields()) {
|
||||||
|
builder.addField(subs.substitute(field.getName()), subs.substitute(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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,27 +1,29 @@
|
||||||
package sciwhiz12.janitor.msg.emote;
|
package sciwhiz12.janitor.messages.emote;
|
||||||
|
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
import net.dv8tion.jda.api.events.message.MessageDeleteEvent;
|
import net.dv8tion.jda.api.events.message.MessageDeleteEvent;
|
||||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.JanitorBotImpl;
|
||||||
|
import sciwhiz12.janitor.api.messages.emote.ReactionManager;
|
||||||
|
import sciwhiz12.janitor.api.messages.emote.ReactionMessage;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
public class ReactionManager extends ListenerAdapter {
|
public class ReactionManagerImpl extends ListenerAdapter implements ReactionManager {
|
||||||
private final JanitorBot bot;
|
private final JanitorBotImpl bot;
|
||||||
private final Map<Long, ReactionMessage> messageMap = new HashMap<>();
|
private final Map<Long, ReactionMessage> messageMap = new HashMap<>();
|
||||||
|
|
||||||
public ReactionManager(JanitorBot bot) {
|
public ReactionManagerImpl(JanitorBotImpl bot) {
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactionMessage newMessage(Message message) {
|
public ReactionMessageImpl newMessage(Message message) {
|
||||||
if (messageMap.containsKey(message.getIdLong())) {
|
if (messageMap.containsKey(message.getIdLong())) {
|
||||||
throw new IllegalArgumentException("Reaction message already exists for message with id " + message.getIdLong());
|
throw new IllegalArgumentException("Reaction message already exists for message with id " + message.getIdLong());
|
||||||
}
|
}
|
||||||
final ReactionMessage msg = new ReactionMessage(bot, message);
|
final ReactionMessageImpl msg = new ReactionMessageImpl(bot, message);
|
||||||
messageMap.put(message.getIdLong(), msg);
|
messageMap.put(message.getIdLong(), msg);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
@ -34,6 +36,11 @@ public class ReactionManager extends ListenerAdapter {
|
||||||
return messageMap;
|
return messageMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JanitorBotImpl getBot() {
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessageDelete(@Nonnull MessageDeleteEvent event) {
|
public void onMessageDelete(@Nonnull MessageDeleteEvent event) {
|
||||||
if (messageMap.containsKey(event.getMessageIdLong())) {
|
if (messageMap.containsKey(event.getMessageIdLong())) {
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor.msg.emote;
|
package sciwhiz12.janitor.messages.emote;
|
||||||
|
|
||||||
import net.dv8tion.jda.api.entities.Emote;
|
import net.dv8tion.jda.api.entities.Emote;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
@ -7,54 +7,54 @@ import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
|
||||||
import net.dv8tion.jda.api.exceptions.ErrorHandler;
|
import net.dv8tion.jda.api.exceptions.ErrorHandler;
|
||||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||||
import net.dv8tion.jda.api.requests.ErrorResponse;
|
import net.dv8tion.jda.api.requests.ErrorResponse;
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.JanitorBotImpl;
|
||||||
|
import sciwhiz12.janitor.api.messages.emote.ReactionMessage;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
import static net.dv8tion.jda.api.Permission.MESSAGE_MANAGE;
|
import static net.dv8tion.jda.api.Permission.MESSAGE_MANAGE;
|
||||||
|
|
||||||
public class ReactionMessage extends ListenerAdapter {
|
public class ReactionMessageImpl extends ListenerAdapter implements ReactionMessage {
|
||||||
private final JanitorBot bot;
|
private final JanitorBotImpl bot;
|
||||||
private final Message message;
|
private final Message message;
|
||||||
private final Map<ReactionEmote, IReactionListener> emotes = new LinkedHashMap<>();
|
private final Map<ReactionEmote, ReactionListener> emotes = new LinkedHashMap<>();
|
||||||
private boolean removeEmotes = true;
|
private boolean removeEmotes = true;
|
||||||
private long ownerID;
|
private long ownerID;
|
||||||
private boolean onlyOwner;
|
private boolean onlyOwner;
|
||||||
|
|
||||||
public ReactionMessage(JanitorBot bot, Message message, boolean onlyOwner, long ownerID) {
|
public ReactionMessageImpl(JanitorBotImpl bot, Message message, boolean onlyOwner, long ownerID) {
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.ownerID = ownerID;
|
this.ownerID = ownerID;
|
||||||
this.onlyOwner = onlyOwner;
|
this.onlyOwner = onlyOwner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactionMessage(JanitorBot bot, Message message) {
|
public ReactionMessageImpl(JanitorBotImpl bot, Message message) {
|
||||||
this(bot, message, false, 0);
|
this(bot, message, false, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactionMessage add(ReactionEmote emote, IReactionListener listener) {
|
public ReactionMessageImpl add(ReactionEmote emote, ReactionListener listener) {
|
||||||
emotes.put(emote, listener);
|
emotes.put(emote, listener);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactionMessage add(String emote, IReactionListener listener) {
|
public ReactionMessageImpl add(String emote, ReactionListener listener) {
|
||||||
return add(ReactionEmote.fromUnicode(emote, bot.getDiscord()), listener);
|
return add(ReactionEmote.fromUnicode(emote, bot.getDiscord()), listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactionMessage add(Emote emote, IReactionListener listener) {
|
public ReactionMessageImpl add(Emote emote, ReactionListener listener) {
|
||||||
return add(ReactionEmote.fromCustom(emote), listener);
|
return add(ReactionEmote.fromCustom(emote), listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactionMessage removeEmotes(boolean remove) {
|
public ReactionMessageImpl removeEmotes(boolean remove) {
|
||||||
this.removeEmotes = remove;
|
this.removeEmotes = remove;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactionMessage owner(long ownerID) {
|
public ReactionMessageImpl owner(long ownerID) {
|
||||||
this.ownerID = ownerID;
|
this.ownerID = ownerID;
|
||||||
this.onlyOwner = true;
|
this.onlyOwner = true;
|
||||||
return this;
|
return this;
|
||||||
|
@ -89,7 +89,7 @@ public class ReactionMessage extends ListenerAdapter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public JanitorBot getBot() {
|
public JanitorBotImpl getBot() {
|
||||||
return bot;
|
return bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,12 +101,7 @@ public class ReactionMessage extends ListenerAdapter {
|
||||||
return onlyOwner;
|
return onlyOwner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<ReactionEmote, IReactionListener> getListeners() {
|
public Map<ReactionEmote, ReactionListener> getListeners() {
|
||||||
return Collections.unmodifiableMap(emotes);
|
return Collections.unmodifiableMap(emotes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface IReactionListener extends BiConsumer<ReactionMessage, MessageReactionAddEvent> {
|
|
||||||
void accept(ReactionMessage message, MessageReactionAddEvent event);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor.msg.json;
|
package sciwhiz12.janitor.messages.json;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||||
import net.dv8tion.jda.api.EmbedBuilder;
|
import net.dv8tion.jda.api.EmbedBuilder;
|
||||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
|
import sciwhiz12.janitor.api.messages.ListingMessage;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
|
@ -1,10 +1,11 @@
|
||||||
package sciwhiz12.janitor.msg.json;
|
package sciwhiz12.janitor.messages.json;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||||
|
import sciwhiz12.janitor.api.messages.RegularMessage;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
|
@ -1,14 +1,17 @@
|
||||||
package sciwhiz12.janitor.msg.substitution;
|
package sciwhiz12.janitor.messages.substitution;
|
||||||
|
|
||||||
import org.apache.commons.collections4.TransformerUtils;
|
import org.apache.commons.collections4.TransformerUtils;
|
||||||
import org.apache.commons.collections4.map.DefaultedMap;
|
import org.apache.commons.collections4.map.DefaultedMap;
|
||||||
|
import sciwhiz12.janitor.api.messages.substitution.ModifiableSubstitutor;
|
||||||
|
import sciwhiz12.janitor.api.messages.substitution.SubstitutionsMap;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class CustomSubstitutions implements ISubstitutor, IHasCustomSubstitutions<CustomSubstitutions> {
|
public class CustomSubstitutions implements ModifiableSubstitutor<CustomSubstitutions> {
|
||||||
private final Map<String, Supplier<String>> map;
|
private final Map<String, Supplier<String>> map;
|
||||||
|
|
||||||
public CustomSubstitutions(Map<String, Supplier<String>> map) {
|
public CustomSubstitutions(Map<String, Supplier<String>> map) {
|
||||||
|
@ -20,8 +23,9 @@ public class CustomSubstitutions implements ISubstitutor, IHasCustomSubstitution
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String substitute(String text) {
|
@Nullable
|
||||||
return SubstitutionMap.substitute(text, map);
|
public String substitute(@Nullable String text) {
|
||||||
|
return SubstitutionsMap.substitute(text, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CustomSubstitutions apply(Consumer<CustomSubstitutions> consumer) {
|
public CustomSubstitutions apply(Consumer<CustomSubstitutions> consumer) {
|
|
@ -1,8 +1,9 @@
|
||||||
package sciwhiz12.janitor.msg.substitution;
|
package sciwhiz12.janitor.messages.substitution;
|
||||||
|
|
||||||
import org.apache.commons.collections4.TransformerUtils;
|
import org.apache.commons.collections4.TransformerUtils;
|
||||||
import org.apache.commons.collections4.map.DefaultedMap;
|
import org.apache.commons.collections4.map.DefaultedMap;
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.JanitorBotImpl;
|
||||||
|
import sciwhiz12.janitor.api.messages.substitution.SubstitutionsMap;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
@ -11,34 +12,40 @@ import java.util.Map;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static java.util.regex.Matcher.quoteReplacement;
|
|
||||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||||
import static sciwhiz12.janitor.msg.MessageHelper.DATE_TIME_FORMAT;
|
import static sciwhiz12.janitor.api.utils.MessageHelper.DATE_TIME_FORMAT;
|
||||||
|
|
||||||
public class SubstitutionMap implements ISubstitutor {
|
public class SubstitutionsMapImpl implements SubstitutionsMap {
|
||||||
public static final Pattern ARGUMENT_REGEX = Pattern.compile("\\$\\{(.+?)}", CASE_INSENSITIVE);
|
public static final Pattern ARGUMENT_REGEX = Pattern.compile("\\$\\{(.+?)}", CASE_INSENSITIVE);
|
||||||
public static final Pattern NULL_ARGUMENT_REGEX = Pattern.compile("nullcheck;(.+?);(.+)", CASE_INSENSITIVE);
|
public static final Pattern NULL_ARGUMENT_REGEX = Pattern.compile("nullcheck;(.+?);(.+)", CASE_INSENSITIVE);
|
||||||
|
|
||||||
public static String substitute(String text, Map<String, Supplier<String>> arguments) {
|
private static String quote(@Nullable String input) {
|
||||||
|
return input != null ? Matcher.quoteReplacement(input) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static String substitute(@Nullable String text, Map<String, Supplier<String>> arguments) {
|
||||||
|
if (text == null || text.isBlank()) return null;
|
||||||
final Matcher matcher = ARGUMENT_REGEX.matcher(text);
|
final Matcher matcher = ARGUMENT_REGEX.matcher(text);
|
||||||
return matcher.replaceAll(matchResult -> {
|
return matcher.replaceAll(matchResult -> {
|
||||||
final Matcher nullMatcher = NULL_ARGUMENT_REGEX.matcher(matchResult.group(1));
|
final Matcher nullMatcher = NULL_ARGUMENT_REGEX.matcher(matchResult.group(1));
|
||||||
if (nullMatcher.matches()) {
|
if (nullMatcher.matches()) {
|
||||||
final String grp1 = nullMatcher.group(1);
|
final String grp1 = nullMatcher.group(1);
|
||||||
final String str = arguments.containsKey(grp1) ? arguments.get(grp1).get() : null;
|
return quote(arguments.getOrDefault(
|
||||||
return str != null ?
|
grp1,
|
||||||
quoteReplacement(str) :
|
() -> arguments.getOrDefault(nullMatcher.group(2), () -> nullMatcher.group(2)).get()
|
||||||
quoteReplacement(arguments.getOrDefault(nullMatcher.group(2), () -> nullMatcher.group(2)).get());
|
).get());
|
||||||
}
|
}
|
||||||
return quoteReplacement(arguments.getOrDefault(matchResult.group(1), () -> matchResult.group(0)).get());
|
return quote(arguments.getOrDefault(matchResult.group(1), () -> matchResult.group(0)).get());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private final JanitorBot bot;
|
private final JanitorBotImpl bot;
|
||||||
private final Map<String, Supplier<String>> defaultSubstitutions = new HashMap<>();
|
private final Map<String, Supplier<String>> defaultSubstitutions = new HashMap<>();
|
||||||
|
|
||||||
public SubstitutionMap(JanitorBot bot) {
|
public SubstitutionsMapImpl(JanitorBotImpl bot) {
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
defaultSubstitutions.put("time.now", () -> OffsetDateTime.now(ZoneOffset.UTC).format(DATE_TIME_FORMAT));
|
defaultSubstitutions.put("time.now", () -> OffsetDateTime.now(ZoneOffset.UTC).format(DATE_TIME_FORMAT));
|
||||||
defaultSubstitutions.put("moderation.color", () -> "0xF1BD25");
|
defaultSubstitutions.put("moderation.color", () -> "0xF1BD25");
|
||||||
|
@ -47,16 +54,17 @@ public class SubstitutionMap implements ISubstitutor {
|
||||||
defaultSubstitutions.put("general.error.color", () -> "0xF73132");
|
defaultSubstitutions.put("general.error.color", () -> "0xF73132");
|
||||||
}
|
}
|
||||||
|
|
||||||
public JanitorBot getBot() {
|
public JanitorBotImpl getBot() {
|
||||||
return bot;
|
return bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String substitute(String text) {
|
@Nullable
|
||||||
return SubstitutionMap.substitute(text, defaultSubstitutions);
|
public String substitute(@Nullable String text) {
|
||||||
|
return SubstitutionsMap.substitute(text, defaultSubstitutions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String with(String text, Map<String, Supplier<String>> substitutions) {
|
public String with(String text, Map<String, Supplier<String>> substitutions) {
|
||||||
return SubstitutionMap.substitute(text, createDefaultedMap(substitutions));
|
return SubstitutionsMap.substitute(text, createDefaultedMap(substitutions));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CustomSubstitutions with(Map<String, Supplier<String>> customSubstitutions) {
|
public CustomSubstitutions with(Map<String, Supplier<String>> customSubstitutions) {
|
||||||
|
@ -66,5 +74,4 @@ public class SubstitutionMap implements ISubstitutor {
|
||||||
public Map<String, Supplier<String>> createDefaultedMap(Map<String, Supplier<String>> custom) {
|
public Map<String, Supplier<String>> createDefaultedMap(Map<String, Supplier<String>> custom) {
|
||||||
return DefaultedMap.defaultedMap(custom, TransformerUtils.mapTransformer(defaultSubstitutions));
|
return DefaultedMap.defaultedMap(custom, TransformerUtils.mapTransformer(defaultSubstitutions));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
package sciwhiz12.janitor.module;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import sciwhiz12.janitor.JanitorBotImpl;
|
||||||
|
import sciwhiz12.janitor.api.module.Module;
|
||||||
|
import sciwhiz12.janitor.api.module.ModuleKey;
|
||||||
|
import sciwhiz12.janitor.api.module.ModuleManager;
|
||||||
|
import sciwhiz12.janitor.api.module.ModuleProvider;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||||
|
import static sciwhiz12.janitor.api.Logging.MODULE;
|
||||||
|
|
||||||
|
public class ModuleManagerImpl implements ModuleManager {
|
||||||
|
private final JanitorBotImpl bot;
|
||||||
|
private final ServiceLoader<ModuleProvider> moduleProviders;
|
||||||
|
private boolean active = false;
|
||||||
|
private final Set<ModuleKey<?>> availableModules = new HashSet<>();
|
||||||
|
private final Set<String> disabledModules = new HashSet<>();
|
||||||
|
private final Map<String, InnerStorage<?>> activeModules = new HashMap<>();
|
||||||
|
|
||||||
|
public ModuleManagerImpl(JanitorBotImpl bot) {
|
||||||
|
this.bot = bot;
|
||||||
|
this.moduleProviders = ServiceLoader.load(ModuleProvider.class);
|
||||||
|
loadProviders();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadProviders() {
|
||||||
|
final Set<String> knownModules = new HashSet<>();
|
||||||
|
moduleProviders.reload();
|
||||||
|
availableModules.clear();
|
||||||
|
for (ModuleProvider provider : moduleProviders) {
|
||||||
|
for (ModuleKey<?> moduleID : provider.getAvailableModules()) {
|
||||||
|
if (knownModules.contains(moduleID.getModuleID()))
|
||||||
|
throw new RuntimeException("Duplicate modules with module id " + moduleID);
|
||||||
|
availableModules.add(moduleID);
|
||||||
|
knownModules.add(moduleID.getModuleID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activateModules() {
|
||||||
|
if (active)
|
||||||
|
throw new IllegalStateException("Modules are already activated");
|
||||||
|
active = true;
|
||||||
|
JANITOR.debug(MODULE, "Activating modules...");
|
||||||
|
for (ModuleProvider provider : moduleProviders) {
|
||||||
|
for (ModuleKey<?> moduleID : provider.getAvailableModules()) {
|
||||||
|
String providerName = provider.getClass().getName();
|
||||||
|
if (disabledModules.contains(moduleID.getModuleID())) {
|
||||||
|
JANITOR.debug(MODULE, "Module with ID {} from provider {} is disabled, skipping", moduleID, providerName);
|
||||||
|
} else if (!availableModules.contains(moduleID)) {
|
||||||
|
JANITOR
|
||||||
|
.debug(MODULE, "Module with ID {} from provider {} was not previously available at loading, skipping",
|
||||||
|
moduleID, providerName);
|
||||||
|
} else {
|
||||||
|
if (activateModule(provider, moduleID)) {
|
||||||
|
JANITOR.debug(MODULE, "Module with ID {} from provider {} is now activated", moduleID, providerName);
|
||||||
|
} else {
|
||||||
|
JANITOR.warn(MODULE,
|
||||||
|
"Module with ID {} was declared to be available by provider {}, but did not create a module; " +
|
||||||
|
"skipping",
|
||||||
|
moduleID, providerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
JANITOR.info(MODULE, "Modules are now activated");
|
||||||
|
}
|
||||||
|
|
||||||
|
private <M extends Module> boolean activateModule(ModuleProvider provider, ModuleKey<M> moduleID) {
|
||||||
|
final M module = provider.createModule(moduleID, bot);
|
||||||
|
if (module == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
module.activate();
|
||||||
|
activeModules.put(moduleID.getModuleID(), new InnerStorage<>(moduleID, module));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
if (!active)
|
||||||
|
throw new IllegalStateException("Modules are not activated");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disableModule(String id) {
|
||||||
|
if (active)
|
||||||
|
throw new IllegalStateException("Cannot disable modules, as modules are already activated");
|
||||||
|
disabledModules.add(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enableModule(String id) {
|
||||||
|
if (active)
|
||||||
|
throw new IllegalStateException("Cannot reenable modules, as modules are already activated");
|
||||||
|
disabledModules.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<ModuleKey<?>> getAvailableModules() {
|
||||||
|
return Collections.unmodifiableSet(availableModules);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<ModuleKey<?>> getActiveModules() {
|
||||||
|
return activeModules.values().stream()
|
||||||
|
.map(InnerStorage::getKey)
|
||||||
|
.collect(ImmutableSet.toImmutableSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <M extends Module> M getModule(ModuleKey<M> moduleKey) {
|
||||||
|
if (activeModules.containsKey(moduleKey.getModuleID())) {
|
||||||
|
return moduleKey.getType().cast(activeModules.get(moduleKey.getModuleID()).module);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActivated() {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JanitorBotImpl getBot() {
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <strong>For internal use only.</strong>
|
||||||
|
*/
|
||||||
|
static class InnerStorage<M extends Module> {
|
||||||
|
private final ModuleKey<M> key;
|
||||||
|
private final M module;
|
||||||
|
|
||||||
|
InnerStorage(ModuleKey<M> key, M storage) {
|
||||||
|
this.key = key;
|
||||||
|
this.module = storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModuleKey<M> getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public M getModule() {
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,11 @@ package sciwhiz12.janitor.storage;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.JanitorBotImpl;
|
||||||
import sciwhiz12.janitor.Logging;
|
import sciwhiz12.janitor.api.Logging;
|
||||||
|
import sciwhiz12.janitor.api.storage.GuildStorageManager;
|
||||||
|
import sciwhiz12.janitor.api.storage.Storage;
|
||||||
|
import sciwhiz12.janitor.api.storage.StorageKey;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
@ -19,26 +22,24 @@ 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 GuildStorageManagerImpl implements GuildStorageManager {
|
||||||
private final JanitorBot bot;
|
private final JanitorBotImpl 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<>();
|
||||||
|
|
||||||
public GuildStorage(JanitorBot bot, Path mainFolder) {
|
public GuildStorageManagerImpl(JanitorBotImpl bot, Path mainFolder) {
|
||||||
Preconditions.checkArgument(Files.isDirectory(mainFolder) || Files.notExists(mainFolder));
|
Preconditions.checkArgument(Files.isDirectory(mainFolder) || Files.notExists(mainFolder));
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
this.mainFolder = mainFolder;
|
this.mainFolder = mainFolder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JanitorBot getBot() {
|
@Override
|
||||||
|
public JanitorBotImpl getBot() {
|
||||||
return bot;
|
return bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <S extends IStorage> S getOrCreate(Guild guild, StorageKey<S> key, Supplier<S> defaultSupplier) {
|
@Override
|
||||||
return getOrCreate(guild.getIdLong(), key, defaultSupplier);
|
public <S extends Storage> 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());
|
||||||
|
@ -50,7 +51,7 @@ public class GuildStorage {
|
||||||
return mainFolder.resolve(guildFolder).resolve(file);
|
return mainFolder.resolve(guildFolder).resolve(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends IStorage> T load(long guildID, String key, T storage) {
|
public <T extends Storage> T load(long guildID, String key, T storage) {
|
||||||
final Path file = getFile(guildID, key);
|
final Path file = getFile(guildID, key);
|
||||||
if (Files.notExists(file)) return storage;
|
if (Files.notExists(file)) return storage;
|
||||||
|
|
||||||
|
@ -63,6 +64,7 @@ public class GuildStorage {
|
||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void save() {
|
public void save() {
|
||||||
save(false);
|
save(false);
|
||||||
}
|
}
|
||||||
|
@ -96,13 +98,13 @@ public class GuildStorage {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A thread that calls {@link GuildStorage#save(boolean)} between specified delays.
|
* A thread that calls {@link GuildStorageManagerImpl#save(boolean)} between specified delays.
|
||||||
*/
|
*/
|
||||||
public static class SavingThread extends Thread {
|
public static class SavingThread extends Thread {
|
||||||
private final GuildStorage storage;
|
private final GuildStorageManagerImpl storage;
|
||||||
private volatile boolean running = true;
|
private volatile boolean running = true;
|
||||||
|
|
||||||
public SavingThread(GuildStorage storage) {
|
public SavingThread(GuildStorageManagerImpl storage) {
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
this.setName("GuildStorage-Saving-Thread");
|
this.setName("GuildStorage-Saving-Thread");
|
||||||
this.setDaemon(true);
|
this.setDaemon(true);
|
||||||
|
@ -118,7 +120,7 @@ public class GuildStorage {
|
||||||
while (running) {
|
while (running) {
|
||||||
storage.save(true);
|
storage.save(true);
|
||||||
try {
|
try {
|
||||||
Thread.sleep(storage.getBot().getConfig().AUTOSAVE_INTERVAL.get() * 1000);
|
Thread.sleep(storage.getBot().getBotConfig().AUTOSAVE_INTERVAL.get() * 1000);
|
||||||
} catch (InterruptedException ignored) {}
|
} catch (InterruptedException ignored) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,7 +129,7 @@ public class GuildStorage {
|
||||||
/**
|
/**
|
||||||
* <strong>For internal use only.</strong>
|
* <strong>For internal use only.</strong>
|
||||||
*/
|
*/
|
||||||
static class InnerStorage<S extends IStorage> {
|
static class InnerStorage<S extends Storage> {
|
||||||
private final StorageKey<S> key;
|
private final StorageKey<S> key;
|
||||||
private final S storage;
|
private final S storage;
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class Util {
|
||||||
|
|
||||||
public static String toString(@Nullable final User user) {
|
public static String toString(@Nullable final User user) {
|
||||||
return user != null ?
|
return user != null ?
|
||||||
String.format("{User,%s#%s}:%s", user.getName(), user.getDiscriminator(), getID(user)) :
|
String.format("{User,%s#%s}:%s", user.getName(), user.getDiscriminator(), user.getAsMention()) :
|
||||||
"unknown";
|
"unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,10 +51,6 @@ public class Util {
|
||||||
return String.format("<%s%s>", prefix, entity.getId());
|
return String.format("<%s%s>", prefix, entity.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String nameFor(User user) {
|
|
||||||
return user.getName().concat("#").concat(user.getDiscriminator());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <Success, Err> BiConsumer<Success, Err> handle(final Consumer<Success> success,
|
public static <Success, Err> BiConsumer<Success, Err> handle(final Consumer<Success> success,
|
||||||
final Consumer<Err> exceptionally) {
|
final Consumer<Err> exceptionally) {
|
||||||
return (suc, ex) -> {
|
return (suc, ex) -> {
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "Ambiguous member argument!",
|
||||||
|
"description": "The name you have specified is too ambiguous (leads to more than 1 member)!\nPlease narrow down the specified name until it can uniquely identify a member of this guild."
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "Performer cannot act against self."
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "Cannot perform this action against myself."
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"description": "Cannot perform action on the given member, likely due to me being lower in the role hierarchy.",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Target",
|
||||||
|
"value": "${target.mention}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "Guild only command!"
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"description": "I do not have sufficient permissions to carry out this action.\nPlease contact your server administrators if you believe this is in error.",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Required permissions",
|
||||||
|
"value": "${required_permissions}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
8
core/src/main/resources/messages/messages.json
Normal file
8
core/src/main/resources/messages/messages.json
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[
|
||||||
|
"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"
|
||||||
|
]
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-all.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
package sciwhiz12.janitor.moderation;
|
||||||
|
|
||||||
|
import sciwhiz12.janitor.api.config.ConfigNode;
|
||||||
|
|
||||||
|
public class ModerationConfigs {
|
||||||
|
public static final ConfigNode<Boolean> ENABLE_WARNS = new ConfigNode<>(
|
||||||
|
"sciwhiz12.janitor.moderation.warns.enable", () -> true,
|
||||||
|
"Whether to enable the warnings system. If disabled, the related commands are force-disabled.");
|
||||||
|
|
||||||
|
public static final ConfigNode<Boolean> WARNS_RESPECT_MOD_ROLES = new ConfigNode<>(
|
||||||
|
"sciwhiz12.janitor.moderation.warns.respect_mod_roles", () -> false,
|
||||||
|
"Whether to prevent lower-ranked moderators (in the role hierarchy) from removing warnings " +
|
||||||
|
"issued by higher-ranked moderators.");
|
||||||
|
public static final ConfigNode<Boolean> ALLOW_WARN_OTHER_MODERATORS = new ConfigNode<>(
|
||||||
|
"sciwhiz12.janitor.moderation.warns.warn_other_moderators", () -> true,
|
||||||
|
"Whether to allow moderators to issue warnings against other moderators.");
|
||||||
|
public static final ConfigNode<Boolean> ALLOW_REMOVE_SELF_WARNINGS = new ConfigNode<>(
|
||||||
|
"sciwhiz12.janitor.moderation.warns.remove_self_warnings", () -> false,
|
||||||
|
"Whether to allow moderators to remove warnings from themselves.");
|
||||||
|
|
||||||
|
public static final ConfigNode<Boolean> ENABLE_NOTES = new ConfigNode<>(
|
||||||
|
"sciwhiz12.janitor.moderation.notes.enable", () -> true,
|
||||||
|
"Whether to enable the notes system. If disabled, the related commands are force-disabled.");
|
||||||
|
public static final ConfigNode<Integer> MAX_NOTES_PER_MOD = new ConfigNode<>(
|
||||||
|
"sciwhiz12.janitor.moderation.notes.max_amount", () -> Integer.MAX_VALUE,
|
||||||
|
"The max amount of notes for a user per moderator.");
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package sciwhiz12.janitor.moderation;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
|
import net.dv8tion.jda.api.entities.User;
|
||||||
|
import net.dv8tion.jda.api.requests.restaction.AuditableRestAction;
|
||||||
|
import sciwhiz12.janitor.api.messages.substitution.ModifiableSubstitutions;
|
||||||
|
import sciwhiz12.janitor.moderation.notes.NoteEntry;
|
||||||
|
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import static sciwhiz12.janitor.api.utils.MessageHelper.DATE_TIME_FORMAT;
|
||||||
|
import static sciwhiz12.janitor.api.utils.MessageHelper.user;
|
||||||
|
|
||||||
|
public class ModerationHelper {
|
||||||
|
public static AuditableRestAction<Void> kickUser(Guild guild, Member performer, Member target, @Nullable String reason) {
|
||||||
|
StringBuilder auditReason = new StringBuilder();
|
||||||
|
auditReason.append("Kicked by ")
|
||||||
|
.append(performer.getUser().getAsTag())
|
||||||
|
.append(" on ")
|
||||||
|
.append(Instant.now().atOffset(ZoneOffset.UTC).format(DATE_TIME_FORMAT));
|
||||||
|
if (reason != null)
|
||||||
|
auditReason.append(" for reason: ").append(reason);
|
||||||
|
return guild.kick(target, auditReason.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AuditableRestAction<Void> banUser(Guild guild, Member performer, Member target, int deleteDuration,
|
||||||
|
@Nullable String reason) {
|
||||||
|
StringBuilder auditReason = new StringBuilder();
|
||||||
|
auditReason.append("Banned by ")
|
||||||
|
.append(performer.getUser().getAsTag())
|
||||||
|
.append(" on ")
|
||||||
|
.append(Instant.now().atOffset(ZoneOffset.UTC).format(DATE_TIME_FORMAT));
|
||||||
|
if (reason != null)
|
||||||
|
auditReason.append(" for reason: ").append(reason);
|
||||||
|
return guild.ban(target, deleteDuration, auditReason.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AuditableRestAction<Void> unbanUser(Guild guild, User target) {
|
||||||
|
return guild.unban(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends ModifiableSubstitutions<?>> 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 ModifiableSubstitutions<?>> 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package sciwhiz12.janitor.moderation;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import sciwhiz12.janitor.api.module.Module;
|
||||||
|
import sciwhiz12.janitor.api.module.ModuleKey;
|
||||||
|
import sciwhiz12.janitor.moderation.notes.NoteStorage;
|
||||||
|
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
||||||
|
|
||||||
|
public interface ModerationModule extends Module {
|
||||||
|
Logger LOGGER = LoggerFactory.getLogger("janitor.moderation");
|
||||||
|
ModuleKey<ModerationModule> ID = new ModuleKey<>("moderation", ModerationModule.class);
|
||||||
|
|
||||||
|
NoteStorage getNotes(Guild guild);
|
||||||
|
|
||||||
|
WarningStorage getWarns(Guild guild);
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package sciwhiz12.janitor.moderation.notes;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.User;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class NoteEntry {
|
||||||
|
private final User performer;
|
||||||
|
private final User target;
|
||||||
|
private final OffsetDateTime dateTime;
|
||||||
|
private final String contents;
|
||||||
|
|
||||||
|
public NoteEntry(User performer, User target, OffsetDateTime dateTime, String contents) {
|
||||||
|
this.performer = performer;
|
||||||
|
this.target = target;
|
||||||
|
this.dateTime = dateTime;
|
||||||
|
this.contents = contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getPerformer() {
|
||||||
|
return performer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getDateTime() {
|
||||||
|
return dateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContents() {
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
NoteEntry noteEntry = (NoteEntry) o;
|
||||||
|
return getPerformer().equals(noteEntry.getPerformer()) &&
|
||||||
|
getTarget().equals(noteEntry.getTarget()) &&
|
||||||
|
getDateTime().equals(noteEntry.getDateTime()) &&
|
||||||
|
getContents().equals(noteEntry.getContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(getPerformer(), getTarget(), getDateTime(), getContents());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package sciwhiz12.janitor.moderation.notes;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.User;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
import sciwhiz12.janitor.api.storage.Storage;
|
||||||
|
import sciwhiz12.janitor.api.storage.StorageKey;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface NoteStorage extends Storage {
|
||||||
|
StorageKey<NoteStorage> KEY = new StorageKey<>("notes", NoteStorage.class);
|
||||||
|
|
||||||
|
int addNote(NoteEntry entry);
|
||||||
|
|
||||||
|
@Nullable NoteEntry getNote(int noteID);
|
||||||
|
|
||||||
|
void removeNote(int noteID);
|
||||||
|
|
||||||
|
int getAmountOfNotes(User target);
|
||||||
|
|
||||||
|
Map<Integer, NoteEntry> getNotes();
|
||||||
|
|
||||||
|
JanitorBot getBot();
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package sciwhiz12.janitor.moderation.warns;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.User;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.Objects;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class WarningEntry {
|
||||||
|
private final User performer;
|
||||||
|
private final User warned;
|
||||||
|
private final OffsetDateTime dateTime;
|
||||||
|
@Nullable
|
||||||
|
private final String reason;
|
||||||
|
|
||||||
|
public WarningEntry(User performer, User warned, OffsetDateTime dateTime, @Nullable String reason) {
|
||||||
|
this.performer = performer;
|
||||||
|
this.warned = warned;
|
||||||
|
this.dateTime = dateTime;
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getPerformer() {
|
||||||
|
return performer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getWarned() {
|
||||||
|
return warned;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getDateTime() {
|
||||||
|
return dateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getReason() {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
WarningEntry that = (WarningEntry) o;
|
||||||
|
return getPerformer().equals(that.getPerformer()) &&
|
||||||
|
getWarned().equals(that.getWarned()) &&
|
||||||
|
getDateTime().equals(that.getDateTime()) &&
|
||||||
|
Objects.equals(getReason(), that.getReason());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(getPerformer(), getWarned(), getDateTime(), getReason());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package sciwhiz12.janitor.moderation.warns;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
import sciwhiz12.janitor.api.storage.Storage;
|
||||||
|
import sciwhiz12.janitor.api.storage.StorageKey;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface WarningStorage extends Storage {
|
||||||
|
StorageKey<WarningStorage> KEY = new StorageKey<>("warnings", WarningStorage.class);
|
||||||
|
|
||||||
|
JanitorBot getBot();
|
||||||
|
|
||||||
|
int addWarning(WarningEntry entry);
|
||||||
|
|
||||||
|
@Nullable WarningEntry getWarning(int caseID);
|
||||||
|
|
||||||
|
void removeWarning(int caseID);
|
||||||
|
|
||||||
|
Map<Integer, WarningEntry> getWarnings();
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor.commands.moderation;
|
package sciwhiz12.janitor.moderation;
|
||||||
|
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
@ -8,10 +8,8 @@ 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 sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.api.utils.MessageHelper;
|
||||||
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;
|
||||||
|
@ -22,22 +20,16 @@ import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
|
||||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||||
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;
|
||||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMembers;
|
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.getMembers;
|
||||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.member;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||||
|
|
||||||
public class BanCommand extends BaseCommand {
|
public class BanCommand extends ModBaseCommand {
|
||||||
public static final EnumSet<Permission> BAN_PERMISSION = EnumSet.of(Permission.BAN_MEMBERS);
|
public static final EnumSet<Permission> BAN_PERMISSION = EnumSet.of(Permission.BAN_MEMBERS);
|
||||||
|
|
||||||
/*
|
public BanCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||||
ban command
|
super(module, registry);
|
||||||
!ban <user> [reason]
|
|
||||||
!ban delete <number of days> <user> [reason]
|
|
||||||
*/
|
|
||||||
|
|
||||||
public BanCommand(CommandRegistry registry) {
|
|
||||||
super(registry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -124,7 +116,7 @@ public class BanCommand extends BaseCommand {
|
||||||
.flatMap(v -> messages().getRegularMessage("moderation/ban/info")
|
.flatMap(v -> messages().getRegularMessage("moderation/ban/info")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
.apply(MessageHelper.member("target", target))
|
.apply(MessageHelper.member("target", target))
|
||||||
.with("private_message", () -> res.isSuccess() ? "✅" : "❌")
|
.with("private_message", () -> res.isSuccess() ? "\u2705" : "\u274C")
|
||||||
.with("delete_duration", () -> String.valueOf(days))
|
.with("delete_duration", () -> String.valueOf(days))
|
||||||
.with("reason", () -> reason)
|
.with("reason", () -> reason)
|
||||||
.send(getBot(), channel)
|
.send(getBot(), channel)
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor.commands.moderation;
|
package sciwhiz12.janitor.moderation;
|
||||||
|
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
@ -8,11 +8,9 @@ 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 sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.api.utils.CommandHelper;
|
||||||
import sciwhiz12.janitor.commands.util.CommandHelper;
|
import sciwhiz12.janitor.api.utils.MessageHelper;
|
||||||
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;
|
||||||
|
@ -21,14 +19,14 @@ 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;
|
||||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMembers;
|
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.getMembers;
|
||||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.member;
|
||||||
|
|
||||||
public class KickCommand extends BaseCommand {
|
public class KickCommand extends ModBaseCommand {
|
||||||
public static final EnumSet<Permission> KICK_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
public static final EnumSet<Permission> KICK_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||||
|
|
||||||
public KickCommand(CommandRegistry registry) {
|
public KickCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||||
super(registry);
|
super(module, registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -110,7 +108,7 @@ public class KickCommand extends BaseCommand {
|
||||||
.flatMap(v -> messages().getRegularMessage("moderation/kick/info")
|
.flatMap(v -> messages().getRegularMessage("moderation/kick/info")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
.apply(MessageHelper.member("target", target))
|
.apply(MessageHelper.member("target", target))
|
||||||
.with("private_message", () -> res.isSuccess() ? "✅" : "❌")
|
.with("private_message", () -> res.isSuccess() ? "\u2705" : "\u274C")
|
||||||
.with("reason", () -> reason)
|
.with("reason", () -> reason)
|
||||||
.send(getBot(), channel)
|
.send(getBot(), channel)
|
||||||
)
|
)
|
|
@ -0,0 +1,24 @@
|
||||||
|
package sciwhiz12.janitor.moderation;
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
import sciwhiz12.janitor.api.command.BaseCommand;
|
||||||
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
|
import sciwhiz12.janitor.moderation.notes.NoteStorage;
|
||||||
|
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
||||||
|
|
||||||
|
public abstract class ModBaseCommand extends BaseCommand {
|
||||||
|
protected ModerationModuleImpl module;
|
||||||
|
|
||||||
|
public ModBaseCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||||
|
super(registry);
|
||||||
|
this.module = module;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NoteStorage getNotes(Guild guild) {
|
||||||
|
return module.getNotes(guild);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected WarningStorage getWarns(Guild guild) {
|
||||||
|
return module.getWarns(guild);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
package sciwhiz12.janitor.moderation;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
import sciwhiz12.janitor.api.module.Module;
|
||||||
|
import sciwhiz12.janitor.api.module.ModuleKey;
|
||||||
|
import sciwhiz12.janitor.api.module.ModuleProvider;
|
||||||
|
import sciwhiz12.janitor.moderation.notes.NoteCommand;
|
||||||
|
import sciwhiz12.janitor.moderation.notes.NoteStorage;
|
||||||
|
import sciwhiz12.janitor.moderation.notes.NoteStorageImpl;
|
||||||
|
import sciwhiz12.janitor.moderation.warns.UnwarnCommand;
|
||||||
|
import sciwhiz12.janitor.moderation.warns.WarnCommand;
|
||||||
|
import sciwhiz12.janitor.moderation.warns.WarnListCommand;
|
||||||
|
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
||||||
|
import sciwhiz12.janitor.moderation.warns.WarningStorageImpl;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import static sciwhiz12.janitor.moderation.ModerationConfigs.*;
|
||||||
|
|
||||||
|
public class ModerationModuleImpl implements ModerationModule {
|
||||||
|
private final JanitorBot bot;
|
||||||
|
|
||||||
|
ModerationModuleImpl(JanitorBot bot) {
|
||||||
|
this.bot = bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void activate() {
|
||||||
|
bot.getCommands().addCommand(reg -> new KickCommand(this, reg));
|
||||||
|
bot.getCommands().addCommand(reg -> new BanCommand(this, reg));
|
||||||
|
bot.getCommands().addCommand(reg -> new UnbanCommand(this, reg));
|
||||||
|
bot.getCommands().addCommand(reg -> new WarnCommand(this, reg));
|
||||||
|
bot.getCommands().addCommand(reg -> new WarnListCommand(this, reg));
|
||||||
|
bot.getCommands().addCommand(reg -> new UnwarnCommand(this, reg));
|
||||||
|
bot.getCommands().addCommand(reg -> new NoteCommand(this, reg));
|
||||||
|
bot.getConfigs().registerNodes(
|
||||||
|
ENABLE_WARNS,
|
||||||
|
WARNS_RESPECT_MOD_ROLES,
|
||||||
|
ALLOW_WARN_OTHER_MODERATORS,
|
||||||
|
ALLOW_REMOVE_SELF_WARNINGS,
|
||||||
|
ENABLE_NOTES,
|
||||||
|
MAX_NOTES_PER_MOD
|
||||||
|
);
|
||||||
|
LOGGER.info("Moderation module is activated");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JanitorBot getBot() {
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NoteStorage getNotes(Guild guild) {
|
||||||
|
return bot.getGuildStorage().getOrCreate(guild, NoteStorage.KEY, () -> new NoteStorageImpl(bot));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WarningStorage getWarns(Guild guild) {
|
||||||
|
return bot.getGuildStorage().getOrCreate(guild, WarningStorage.KEY, () -> new WarningStorageImpl(bot));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Provider implements ModuleProvider {
|
||||||
|
@Override
|
||||||
|
public Set<ModuleKey<?>> getAvailableModules() {
|
||||||
|
return ImmutableSet.of(ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public <M extends Module> M createModule(ModuleKey<M> moduleID, JanitorBot bot) {
|
||||||
|
if (ID.equals(moduleID)) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (M) new ModerationModuleImpl(bot);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor.commands.moderation;
|
package sciwhiz12.janitor.moderation;
|
||||||
|
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
@ -9,10 +9,8 @@ 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.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||||
import sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.api.utils.MessageHelper;
|
||||||
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;
|
||||||
|
@ -22,14 +20,14 @@ import java.util.stream.Collectors;
|
||||||
import static com.mojang.brigadier.arguments.LongArgumentType.getLong;
|
import static com.mojang.brigadier.arguments.LongArgumentType.getLong;
|
||||||
import static com.mojang.brigadier.arguments.LongArgumentType.longArg;
|
import static com.mojang.brigadier.arguments.LongArgumentType.longArg;
|
||||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||||
|
|
||||||
public class UnbanCommand extends BaseCommand {
|
public class UnbanCommand extends ModBaseCommand {
|
||||||
public static final EnumSet<Permission> UNBAN_PERMISSION = EnumSet.of(Permission.BAN_MEMBERS);
|
public static final EnumSet<Permission> UNBAN_PERMISSION = EnumSet.of(Permission.BAN_MEMBERS);
|
||||||
|
|
||||||
public UnbanCommand(CommandRegistry registry) {
|
public UnbanCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||||
super(registry);
|
super(module, registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor.commands.moderation;
|
package sciwhiz12.janitor.moderation.notes;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
@ -9,11 +9,11 @@ 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 sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.api.utils.MessageHelper;
|
||||||
import sciwhiz12.janitor.moderation.notes.NoteEntry;
|
import sciwhiz12.janitor.moderation.ModBaseCommand;
|
||||||
import sciwhiz12.janitor.moderation.notes.NoteStorage;
|
import sciwhiz12.janitor.moderation.ModerationHelper;
|
||||||
import sciwhiz12.janitor.msg.MessageHelper;
|
import sciwhiz12.janitor.moderation.ModerationModuleImpl;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
@ -29,24 +29,26 @@ import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
|
||||||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||||
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;
|
||||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMembers;
|
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.getMembers;
|
||||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.member;
|
||||||
import static sciwhiz12.janitor.commands.moderation.NoteCommand.ModeratorFilter.*;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.api.utils.MessageHelper.user;
|
||||||
import static sciwhiz12.janitor.msg.MessageHelper.*;
|
import static sciwhiz12.janitor.moderation.ModerationConfigs.ENABLE_NOTES;
|
||||||
|
import static sciwhiz12.janitor.moderation.ModerationConfigs.MAX_NOTES_PER_MOD;
|
||||||
|
import static sciwhiz12.janitor.moderation.notes.NoteCommand.ModeratorFilter.*;
|
||||||
|
|
||||||
public class NoteCommand extends BaseCommand {
|
public class NoteCommand extends ModBaseCommand {
|
||||||
public static EnumSet<Permission> NOTE_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
public static EnumSet<Permission> NOTE_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||||
|
|
||||||
public NoteCommand(CommandRegistry registry) {
|
public NoteCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||||
super(registry);
|
super(module, registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||||
return literal("note")
|
return literal("note")
|
||||||
.requires(ctx -> config().NOTES_ENABLE.get())
|
.requires(event -> config(event).forGuild(ENABLE_NOTES))
|
||||||
.then(literal("add")
|
.then(literal("add")
|
||||||
.then(argument("target", member())
|
.then(argument("target", member())
|
||||||
.then(argument("contents", greedyString())
|
.then(argument("contents", greedyString())
|
||||||
|
@ -125,8 +127,9 @@ public class NoteCommand extends BaseCommand {
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
final NoteStorage storage = NoteStorage.get(getBot().getStorage(), guild);
|
final NoteStorage storage = getNotes(guild);
|
||||||
final int maxAmount = config().NOTES_MAX_AMOUNT_PER_MOD.get();
|
|
||||||
|
final int maxAmount = config(ctx.getSource()).forGuild(MAX_NOTES_PER_MOD);
|
||||||
if (storage.getAmountOfNotes(target.getUser()) >= maxAmount) {
|
if (storage.getAmountOfNotes(target.getUser()) >= maxAmount) {
|
||||||
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
|
@ -140,7 +143,7 @@ public class NoteCommand extends BaseCommand {
|
||||||
|
|
||||||
messages().getRegularMessage("moderation/note/add")
|
messages().getRegularMessage("moderation/note/add")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
.apply(noteEntry("note_entry", noteID, entry))
|
.apply(ModerationHelper.noteEntry("note_entry", noteID, entry))
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -201,16 +204,11 @@ public class NoteCommand extends BaseCommand {
|
||||||
} else {
|
} else {
|
||||||
messages().<Map.Entry<Integer, NoteEntry>>getListingMessage("moderation/note/list")
|
messages().<Map.Entry<Integer, NoteEntry>>getListingMessage("moderation/note/list")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
.amountPerPage(8)
|
|
||||||
.setEntryApplier((entry, subs) -> subs
|
.setEntryApplier((entry, subs) -> subs
|
||||||
.with("note_entry.note_id", () -> String.valueOf(entry.getKey()))
|
.apply(ModerationHelper.noteEntry("note_entry", entry.getKey(), entry.getValue()))
|
||||||
.apply(user("note_entry.performer", entry.getValue().getPerformer()))
|
|
||||||
.apply(user("note_entry.target", entry.getValue().getTarget()))
|
|
||||||
.with("note_entry.date_time", () -> entry.getValue().getDateTime().format(DATE_TIME_FORMAT))
|
|
||||||
.with("note_entry.contents", entry.getValue()::getContents)
|
|
||||||
)
|
)
|
||||||
.build(channel, getBot(), ctx.getSource().getMessage(),
|
.build(channel, getBot(), ctx.getSource().getMessage(),
|
||||||
NoteStorage.get(getBot().getStorage(), guild)
|
getNotes(guild)
|
||||||
.getNotes()
|
.getNotes()
|
||||||
.entrySet().stream()
|
.entrySet().stream()
|
||||||
.filter(predicate)
|
.filter(predicate)
|
||||||
|
@ -240,7 +238,7 @@ public class NoteCommand extends BaseCommand {
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
final NoteStorage storage = NoteStorage.get(getBot().getStorage(), guild);
|
final NoteStorage storage = getNotes(guild);
|
||||||
@Nullable
|
@Nullable
|
||||||
final NoteEntry entry = storage.getNote(noteID);
|
final NoteEntry entry = storage.getNote(noteID);
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
|
@ -254,7 +252,7 @@ public class NoteCommand extends BaseCommand {
|
||||||
|
|
||||||
messages().getRegularMessage("moderation/note/remove")
|
messages().getRegularMessage("moderation/note/remove")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
.apply(noteEntry("note_entry", noteID, entry))
|
.apply(ModerationHelper.noteEntry("note_entry", noteID, entry))
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package sciwhiz12.janitor.moderation.notes;
|
||||||
|
|
||||||
|
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.User;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class NoteEntryDeserializer extends StdDeserializer<NoteEntry> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final Supplier<JanitorBot> bot;
|
||||||
|
|
||||||
|
public NoteEntryDeserializer(Supplier<JanitorBot> bot) {
|
||||||
|
super(NoteEntry.class);
|
||||||
|
this.bot = bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NoteEntry deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
|
||||||
|
final JsonNode obj = ctx.readTree(p);
|
||||||
|
User performer = bot.get().getDiscord().retrieveUserById(obj.get("performer").asLong()).complete();
|
||||||
|
User target = bot.get().getDiscord().retrieveUserById(obj.get("target").asLong()).complete();
|
||||||
|
OffsetDateTime dateTime = OffsetDateTime.parse(obj.get("dateTime").asText());
|
||||||
|
String contents = obj.get("contents").asText();
|
||||||
|
return new NoteEntry(performer, target, dateTime, contents);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package sciwhiz12.janitor.moderation.notes;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class NoteEntrySerializer extends StdSerializer<NoteEntry> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public NoteEntrySerializer() {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,31 +6,23 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
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;
|
||||||
import sciwhiz12.janitor.JanitorBot;
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
import sciwhiz12.janitor.storage.GuildStorage;
|
import sciwhiz12.janitor.api.storage.JsonStorage;
|
||||||
import sciwhiz12.janitor.storage.JsonStorage;
|
|
||||||
import sciwhiz12.janitor.storage.StorageKey;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
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 NoteStorageImpl extends JsonStorage implements NoteStorage {
|
||||||
private static final TypeReference<Map<Integer, NoteEntry>> NOTE_MAP_TYPE = new TypeReference<>() {};
|
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 NoteStorage get(GuildStorage storage, Guild guild) {
|
|
||||||
return storage.getOrCreate(guild, KEY, () -> new NoteStorage(storage.getBot()));
|
|
||||||
}
|
|
||||||
|
|
||||||
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 NoteStorageImpl(JanitorBot bot) {
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,8 +60,8 @@ public class NoteStorage extends JsonStorage {
|
||||||
super.initialize(mapper);
|
super.initialize(mapper);
|
||||||
mapper.registerModule(
|
mapper.registerModule(
|
||||||
new SimpleModule()
|
new SimpleModule()
|
||||||
.addSerializer(NoteEntry.class, new NoteEntry.Serializer())
|
.addSerializer(NoteEntry.class, new NoteEntrySerializer())
|
||||||
.addDeserializer(NoteEntry.class, new NoteEntry.Deserializer(this::getBot))
|
.addDeserializer(NoteEntry.class, new NoteEntryDeserializer(this::getBot))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor.commands.moderation;
|
package sciwhiz12.janitor.moderation.warns;
|
||||||
|
|
||||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
@ -8,30 +8,31 @@ 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 sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.api.utils.MessageHelper;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
import sciwhiz12.janitor.moderation.ModBaseCommand;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
import sciwhiz12.janitor.moderation.ModerationHelper;
|
||||||
import sciwhiz12.janitor.msg.MessageHelper;
|
import sciwhiz12.janitor.moderation.ModerationModuleImpl;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||||
|
import static sciwhiz12.janitor.moderation.ModerationConfigs.*;
|
||||||
|
|
||||||
public class UnwarnCommand extends BaseCommand {
|
public class UnwarnCommand extends ModBaseCommand {
|
||||||
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||||
|
|
||||||
public UnwarnCommand(CommandRegistry registry) {
|
public UnwarnCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||||
super(registry);
|
super(module, registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||||
return literal("unwarn")
|
return literal("unwarn")
|
||||||
.requires(ctx -> getBot().getConfig().WARNINGS_ENABLE.get())
|
.requires(ctx -> config(ctx).forGuild(ENABLE_WARNS))
|
||||||
.then(argument("caseId", IntegerArgumentType.integer(1))
|
.then(argument("caseId", IntegerArgumentType.integer(1))
|
||||||
.executes(this::run)
|
.executes(this::run)
|
||||||
);
|
);
|
||||||
|
@ -62,7 +63,7 @@ public class UnwarnCommand extends BaseCommand {
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
final WarningStorage storage = WarningStorage.get(getBot().getStorage(), guild);
|
final WarningStorage storage = getWarns(guild);
|
||||||
@Nullable
|
@Nullable
|
||||||
final WarningEntry entry = storage.getWarning(caseID);
|
final WarningEntry entry = storage.getWarning(caseID);
|
||||||
Member temp;
|
Member temp;
|
||||||
|
@ -73,24 +74,24 @@ public class UnwarnCommand extends BaseCommand {
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
} else if (entry.getWarned().getIdLong() == performer.getIdLong()
|
} else if (entry.getWarned().getIdLong() == performer.getIdLong()
|
||||||
&& !config().WARNINGS_REMOVE_SELF_WARNINGS.get()) {
|
&& !config(guild).forGuild(ALLOW_REMOVE_SELF_WARNINGS)) {
|
||||||
messages().getRegularMessage("moderation/error/unwarn/cannot_unwarn_self")
|
messages().getRegularMessage("moderation/error/unwarn/cannot_unwarn_self")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
.apply(MessageHelper.warningEntry("warning_entry", caseID, entry))
|
.apply(ModerationHelper.warningEntry("warning_entry", caseID, entry))
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
} else if (config().WARNINGS_RESPECT_MOD_ROLES.get()
|
} else if (config(guild).forGuild(WARNS_RESPECT_MOD_ROLES)
|
||||||
&& (temp = guild.getMember(entry.getPerformer())) != null && !performer.canInteract(temp)) {
|
&& (temp = guild.getMember(entry.getPerformer())) != null && !performer.canInteract(temp)) {
|
||||||
messages().getRegularMessage("moderation/error/unwarn/cannot_remove_higher_mod")
|
messages().getRegularMessage("moderation/error/unwarn/cannot_remove_higher_mod")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
.apply(MessageHelper.warningEntry("warning_entry", caseID, entry))
|
.apply(ModerationHelper.warningEntry("warning_entry", caseID, entry))
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
storage.removeWarning(caseID);
|
storage.removeWarning(caseID);
|
||||||
messages().getRegularMessage("moderation/unwarn/info")
|
messages().getRegularMessage("moderation/unwarn/info")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
.apply(MessageHelper.warningEntry("warning_entry", caseID, entry))
|
.apply(ModerationHelper.warningEntry("warning_entry", caseID, entry))
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor.commands.moderation;
|
package sciwhiz12.janitor.moderation.warns;
|
||||||
|
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
@ -8,11 +8,11 @@ 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 sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.api.utils.MessageHelper;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
import sciwhiz12.janitor.moderation.ModBaseCommand;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
import sciwhiz12.janitor.moderation.ModerationHelper;
|
||||||
import sciwhiz12.janitor.msg.MessageHelper;
|
import sciwhiz12.janitor.moderation.ModerationModuleImpl;
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.ZoneOffset;
|
import java.time.ZoneOffset;
|
||||||
|
@ -22,22 +22,24 @@ import java.util.Objects;
|
||||||
|
|
||||||
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;
|
||||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMembers;
|
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.getMembers;
|
||||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.member;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||||
|
import static sciwhiz12.janitor.moderation.ModerationConfigs.ALLOW_WARN_OTHER_MODERATORS;
|
||||||
|
import static sciwhiz12.janitor.moderation.ModerationConfigs.ENABLE_WARNS;
|
||||||
|
|
||||||
public class WarnCommand extends BaseCommand {
|
public class WarnCommand extends ModBaseCommand {
|
||||||
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||||
|
|
||||||
public WarnCommand(CommandRegistry registry) {
|
public WarnCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||||
super(registry);
|
super(module, registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||||
return literal("warn")
|
return literal("warn")
|
||||||
.requires(ctx -> getBot().getConfig().WARNINGS_ENABLE.get())
|
.requires(ctx -> config(ctx).forGuild(ENABLE_WARNS))
|
||||||
.then(argument("member", member())
|
.then(argument("member", member())
|
||||||
.then(argument("reason", greedyString())
|
.then(argument("reason", greedyString())
|
||||||
.executes(ctx -> this.run(ctx, getString(ctx, "reason")))
|
.executes(ctx -> this.run(ctx, getString(ctx, "reason")))
|
||||||
|
@ -84,27 +86,27 @@ public class WarnCommand extends BaseCommand {
|
||||||
.apply(MessageHelper.member("target", target))
|
.apply(MessageHelper.member("target", target))
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
} else if (target.hasPermission(WARN_PERMISSION) && config().WARNINGS_PREVENT_WARNING_MODS.get()) {
|
} else if (target.hasPermission(WARN_PERMISSION) && config(guild).forGuild(ALLOW_WARN_OTHER_MODERATORS)) {
|
||||||
messages().getRegularMessage("moderation/error/warn/cannot_warn_mods")
|
messages().getRegularMessage("moderation/error/warn/cannot_warn_mods")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
.apply(MessageHelper.member("target", target))
|
.apply(MessageHelper.member("target", target))
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
WarningEntry entry = new WarningEntry(target.getUser(), performer.getUser(), dateTime, reason);
|
WarningEntry entry = new WarningEntry(performer.getUser(), target.getUser(), dateTime, reason);
|
||||||
int caseId = WarningStorage.get(getBot().getStorage(), guild).addWarning(entry);
|
int caseId = getWarns(guild).addWarning(entry);
|
||||||
|
|
||||||
target.getUser().openPrivateChannel()
|
target.getUser().openPrivateChannel()
|
||||||
.flatMap(dm -> messages().getRegularMessage("moderation/warn/dm")
|
.flatMap(dm -> messages().getRegularMessage("moderation/warn/dm")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
.apply(MessageHelper.warningEntry("warning_entry", caseId, entry))
|
.apply(ModerationHelper.warningEntry("warning_entry", caseId, entry))
|
||||||
.send(getBot(), dm)
|
.send(getBot(), dm)
|
||||||
)
|
)
|
||||||
.mapToResult()
|
.mapToResult()
|
||||||
.flatMap(res -> messages().getRegularMessage("moderation/warn/info")
|
.flatMap(res -> messages().getRegularMessage("moderation/warn/info")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(MessageHelper.member("performer", performer))
|
||||||
.apply(MessageHelper.warningEntry("warning_entry", caseId, entry))
|
.apply(ModerationHelper.warningEntry("warning_entry", caseId, entry))
|
||||||
.with("private_message", () -> res.isSuccess() ? "✅" : "❌")
|
.with("private_message", () -> res.isSuccess() ? "\u2705" : "\u274C")
|
||||||
.send(getBot(), channel)
|
.send(getBot(), channel)
|
||||||
)
|
)
|
||||||
.queue();
|
.queue();
|
|
@ -1,4 +1,4 @@
|
||||||
package sciwhiz12.janitor.commands.moderation;
|
package sciwhiz12.janitor.moderation.warns;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
@ -9,11 +9,9 @@ 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 sciwhiz12.janitor.commands.BaseCommand;
|
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
import sciwhiz12.janitor.moderation.ModBaseCommand;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
import sciwhiz12.janitor.moderation.ModerationModuleImpl;
|
||||||
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
|
||||||
import sciwhiz12.janitor.msg.MessageHelper;
|
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
@ -22,24 +20,26 @@ import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMembers;
|
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.getMembers;
|
||||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.member;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||||
import static sciwhiz12.janitor.msg.MessageHelper.DATE_TIME_FORMAT;
|
import static sciwhiz12.janitor.api.utils.MessageHelper.member;
|
||||||
import static sciwhiz12.janitor.msg.MessageHelper.user;
|
import static sciwhiz12.janitor.api.utils.MessageHelper.user;
|
||||||
|
import static sciwhiz12.janitor.moderation.ModerationConfigs.ENABLE_WARNS;
|
||||||
|
import static sciwhiz12.janitor.moderation.ModerationHelper.warningEntry;
|
||||||
|
|
||||||
public class WarnListCommand extends BaseCommand {
|
public class WarnListCommand extends ModBaseCommand {
|
||||||
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||||
|
|
||||||
public WarnListCommand(CommandRegistry registry) {
|
public WarnListCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||||
super(registry);
|
super(module, registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||||
return literal("warnlist")
|
return literal("warnlist")
|
||||||
.requires(ctx -> getBot().getConfig().WARNINGS_ENABLE.get())
|
.requires(ctx -> config(ctx).forGuild(ENABLE_WARNS))
|
||||||
.then(literal("target")
|
.then(literal("target")
|
||||||
.then(argument("target", member())
|
.then(argument("target", member())
|
||||||
.then(literal("mod")
|
.then(literal("mod")
|
||||||
|
@ -62,7 +62,7 @@ public class WarnListCommand extends BaseCommand {
|
||||||
MessageChannel channel = ctx.getSource().getChannel();
|
MessageChannel channel = ctx.getSource().getChannel();
|
||||||
if (!ctx.getSource().isFromGuild()) {
|
if (!ctx.getSource().isFromGuild()) {
|
||||||
messages().getRegularMessage("general/error/guild_only_command")
|
messages().getRegularMessage("general/error/guild_only_command")
|
||||||
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
.apply(user("performer", ctx.getSource().getAuthor()))
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -77,7 +77,7 @@ public class WarnListCommand extends BaseCommand {
|
||||||
final Member target = members.get(0);
|
final Member target = members.get(0);
|
||||||
if (guild.getSelfMember().equals(target)) {
|
if (guild.getSelfMember().equals(target)) {
|
||||||
messages().getRegularMessage("general/error/cannot_interact")
|
messages().getRegularMessage("general/error/cannot_interact")
|
||||||
.apply(MessageHelper.member("target", target))
|
.apply(member("target", target))
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -93,23 +93,18 @@ public class WarnListCommand extends BaseCommand {
|
||||||
|
|
||||||
if (!performer.hasPermission(WARN_PERMISSION)) {
|
if (!performer.hasPermission(WARN_PERMISSION)) {
|
||||||
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(member("performer", performer))
|
||||||
.with("required_permissions", WARN_PERMISSION::toString)
|
.with("required_permissions", WARN_PERMISSION::toString)
|
||||||
.send(getBot(), channel).queue();
|
.send(getBot(), channel).queue();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
messages().<Map.Entry<Integer, WarningEntry>>getListingMessage("moderation/warn/list")
|
messages().<Map.Entry<Integer, WarningEntry>>getListingMessage("moderation/warn/list")
|
||||||
.apply(MessageHelper.member("performer", performer))
|
.apply(member("performer", performer))
|
||||||
.amountPerPage(8)
|
.setEntryApplier((entry, subs) ->
|
||||||
.setEntryApplier((entry, subs) -> subs
|
subs.apply(warningEntry("warning_entry", entry.getKey(), entry.getValue()))
|
||||||
.with("warning_entry.case_id", () -> String.valueOf(entry.getKey()))
|
|
||||||
.apply(user("warning_entry.performer", entry.getValue().getPerformer()))
|
|
||||||
.apply(user("warning_entry.warned", entry.getValue().getWarned()))
|
|
||||||
.with("warning_entry.date_time", () -> entry.getValue().getDateTime().format(DATE_TIME_FORMAT))
|
|
||||||
.with("warning_entry.reason", entry.getValue()::getReason)
|
|
||||||
)
|
)
|
||||||
.build(channel, getBot(), ctx.getSource().getMessage(),
|
.build(channel, getBot(), ctx.getSource().getMessage(),
|
||||||
WarningStorage.get(getBot().getStorage(), guild)
|
getWarns(guild)
|
||||||
.getWarnings()
|
.getWarnings()
|
||||||
.entrySet().stream()
|
.entrySet().stream()
|
||||||
.filter(predicate)
|
.filter(predicate)
|
|
@ -0,0 +1,33 @@
|
||||||
|
package sciwhiz12.janitor.moderation.warns;
|
||||||
|
|
||||||
|
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.User;
|
||||||
|
import sciwhiz12.janitor.api.JanitorBot;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class WarningEntryDeserializer extends StdDeserializer<WarningEntry> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final Supplier<JanitorBot> bot;
|
||||||
|
|
||||||
|
public WarningEntryDeserializer(Supplier<JanitorBot> bot) {
|
||||||
|
super(WarningEntry.class);
|
||||||
|
this.bot = bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WarningEntry deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
|
||||||
|
final JsonNode obj = ctx.readTree(p);
|
||||||
|
User performer = bot.get().getDiscord().retrieveUserById(obj.get("performer").asLong()).complete();
|
||||||
|
User warned = bot.get().getDiscord().retrieveUserById(obj.get("warned").asLong()).complete();
|
||||||
|
OffsetDateTime dateTime = OffsetDateTime.parse(obj.get("dateTime").asText());
|
||||||
|
String contents = obj.get("reason").asText();
|
||||||
|
return new WarningEntry(performer, warned, dateTime, contents);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package sciwhiz12.janitor.moderation.warns;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class WarningEntrySerializer extends StdSerializer<WarningEntry> {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public WarningEntrySerializer() {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,29 +6,21 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
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.api.JanitorBot;
|
||||||
import sciwhiz12.janitor.storage.GuildStorage;
|
import sciwhiz12.janitor.api.storage.JsonStorage;
|
||||||
import sciwhiz12.janitor.storage.JsonStorage;
|
|
||||||
import sciwhiz12.janitor.storage.StorageKey;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class WarningStorage extends JsonStorage {
|
public class WarningStorageImpl extends JsonStorage implements WarningStorage {
|
||||||
private static final TypeReference<Map<Integer, WarningEntry>> WARNING_MAP_TYPE = new TypeReference<>() {};
|
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 WarningStorage get(GuildStorage storage, Guild guild) {
|
|
||||||
return storage.getOrCreate(guild, KEY, () -> new WarningStorage(storage.getBot()));
|
|
||||||
}
|
|
||||||
|
|
||||||
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 WarningStorageImpl(JanitorBot bot) {
|
||||||
this.bot = bot;
|
this.bot = bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,8 +52,8 @@ public class WarningStorage extends JsonStorage {
|
||||||
super.initialize(mapper);
|
super.initialize(mapper);
|
||||||
mapper.registerModule(
|
mapper.registerModule(
|
||||||
new SimpleModule()
|
new SimpleModule()
|
||||||
.addSerializer(WarningEntry.class, new WarningEntry.Serializer())
|
.addSerializer(WarningEntry.class, new WarningEntrySerializer())
|
||||||
.addDeserializer(WarningEntry.class, new WarningEntry.Deserializer(this::getBot))
|
.addDeserializer(WarningEntry.class, new WarningEntryDeserializer(this::getBot))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
sciwhiz12.janitor.moderation.ModerationModuleImpl$Provider
|
|
@ -1,10 +1,4 @@
|
||||||
[
|
[
|
||||||
"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/cannot_interact",
|
||||||
"moderation/error/insufficient_permissions",
|
"moderation/error/insufficient_permissions",
|
||||||
"moderation/kick/info",
|
"moderation/kick/info",
|
|
@ -4,16 +4,16 @@
|
||||||
"name": "${performer.guild.name}",
|
"name": "${performer.guild.name}",
|
||||||
"icon_url": "${performer.guild.icon_url}"
|
"icon_url": "${performer.guild.icon_url}"
|
||||||
},
|
},
|
||||||
"title": "<moderation.ban.dm.title>",
|
"title": "You were banned from this server.",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"name": "<moderation.ban.dm.field.performer>",
|
"name": "Moderator",
|
||||||
"value": "${performer.mention}",
|
"value": "${performer.mention}",
|
||||||
"inline": true
|
"inline": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "<moderation.ban.dm.field.reason.name>",
|
"name": "Reason",
|
||||||
"value": "<moderation.ban.dm.field.reason.value>",
|
"value": "${nullcheck;reason;_No reason specified._}",
|
||||||
"inline": true
|
"inline": true
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -1,28 +1,33 @@
|
||||||
{
|
{
|
||||||
"color": "${moderation.color}",
|
"color": "${moderation.color}",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "<moderation.kick.info.author>",
|
"name": "Banned user from server.",
|
||||||
"icon_url": "${moderation.icon_url}"
|
"icon_url": "${moderation.icon_url}"
|
||||||
},
|
},
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"name": "<moderation.kick.info.field.performer>",
|
"name": "Performer",
|
||||||
"value": "${performer.mention}",
|
"value": "${performer.mention}",
|
||||||
"inline": true
|
"inline": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "<moderation.kick.info.field.target>",
|
"name": "Target",
|
||||||
"value": "${target.mention}",
|
"value": "${target.mention}",
|
||||||
"inline": true
|
"inline": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "<moderation.kick.info.field.private_message>",
|
"name": "Sent DM",
|
||||||
"value": "${private_message}",
|
"value": "${private_message}",
|
||||||
"inline": true
|
"inline": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "<moderation.kick.info.field.reason.name>",
|
"name": "Message Deletion",
|
||||||
"value": "<moderation.kick.info.field.reason.value>",
|
"value": "${delete_duration} day(s)",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Reason",
|
||||||
|
"value": "${nullcheck;reason;_No reason specified._}",
|
||||||
"inline": false
|
"inline": false
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"description": "The performer of this command cannot moderate the target user, likely due to being lower in the role hierarchy.",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Target",
|
||||||
|
"value": "${target.mention}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"description": "The performer of this command has insufficient permissions to use this command.",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Required permissions",
|
||||||
|
"value": "${required_permissions}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"description": "The performer has reached the maximum amount of notes for the target user.",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Target",
|
||||||
|
"value": "${target.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "(Max.) Amount",
|
||||||
|
"value": "${notes_amount}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"description": "No note with that note ID was found."
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "Cannot remove warning issued by higher-ranked moderator.",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Performer",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Issuer",
|
||||||
|
"value": "${warning_entry.performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"title": "Cannot remove warning from self.",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Performer/Target",
|
||||||
|
"value": "${performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Issuer",
|
||||||
|
"value": "${warning_entry.performer.mention}",
|
||||||
|
"inline": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"color": "${general.error.color}",
|
||||||
|
"description": "No warning with that case ID was found."
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user