mirror of
https://github.com/sciwhiz12/Janitor.git
synced 2024-11-09 22:51:26 +00:00
Compare commits
No commits in common. "199b40b160330c564e4f0283d7d203ad2ec4d506" and "df831da94d16b31bc0ed82d2e1a36813e1edfec5" have entirely different histories.
199b40b160
...
df831da94d
132
build.gradle
132
build.gradle
|
@ -9,6 +9,15 @@ buildscript {
|
|||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven {
|
||||
name = "Minecraft Libraries"
|
||||
url = "https://libraries.minecraft.net"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
apply plugin: 'org.ajoberstar.grgit'
|
||||
apply plugin: 'idea'
|
||||
|
@ -16,6 +25,8 @@ apply plugin: 'java'
|
|||
apply plugin: 'application'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
group = 'sciwhiz12.janitor'
|
||||
archivesBaseName = 'janitor_bot'
|
||||
version = getVersion()
|
||||
println("Version: ${version}")
|
||||
|
||||
|
@ -29,117 +40,34 @@ tasks.withType(JavaCompile) {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':core')
|
||||
implementation project(path: ':core', configuration: 'api')
|
||||
runtimeOnly project(':moderation')
|
||||
runtimeOnly project(path: ':moderation', configuration: 'api')
|
||||
implementation group: 'net.dv8tion', name: 'JDA', version: jda_version
|
||||
implementation group: 'com.electronwill.night-config', name: 'toml', version: nightconfig_version
|
||||
implementation group: 'net.sf.jopt-simple', name: 'jopt-simple', version: jopt_version
|
||||
implementation group: 'com.google.guava', name: 'guava', version: guava_version
|
||||
implementation group: 'com.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 {
|
||||
mainClassName = 'sciwhiz12.janitor.BotStartup'
|
||||
}
|
||||
jar.finalizedBy 'shadowJar'
|
||||
shadowJar {
|
||||
exclude 'META-INF/NOTICE**'
|
||||
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')
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||
from sourceSets.main.allSource
|
||||
classifier "sources"
|
||||
}
|
||||
jar.finalizedBy('sourcesJar')
|
||||
jar.finalizedBy('shadowJar')
|
||||
|
||||
def getVersion() {
|
||||
try {
|
||||
String raw_version = grgit.describe(longDescr: true, tags: true)
|
||||
def raw_version = grgit.describe(longDescr: true, tags: true)
|
||||
def versionSep = raw_version.split "-"
|
||||
def startVer = versionSep[0].substring(1)
|
||||
return startVer + "." + versionSep[1]
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
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,30 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
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,18 +0,0 @@
|
|||
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();
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
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();
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
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() {}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
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,51 +0,0 @@
|
|||
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,16 +0,0 @@
|
|||
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();
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
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,4 +0,0 @@
|
|||
package sciwhiz12.janitor.api.messages.substitution;
|
||||
|
||||
public interface ModifiableSubstitutor<T extends ModifiableSubstitutor<?>> extends ModifiableSubstitutions<T>, Substitutor {
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
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();
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
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);
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package sciwhiz12.janitor.api.module;
|
||||
|
||||
import sciwhiz12.janitor.api.JanitorBot;
|
||||
|
||||
public interface Module {
|
||||
void activate();
|
||||
|
||||
void shutdown();
|
||||
|
||||
JanitorBot getBot();
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
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();
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
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,18 +0,0 @@
|
|||
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,72 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
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,158 +0,0 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"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."
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "Performer cannot act against self."
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "Cannot perform this action against myself."
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "Guild only command!"
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
[
|
||||
"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
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
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.");
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
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);
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
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());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
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();
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
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());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
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,24 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
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,33 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
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();
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
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();
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
sciwhiz12.janitor.moderation.ModerationModuleImpl$Provider
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"description": "No note with that note ID was found."
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"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
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"description": "No warning with that case ID was found."
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"color": "${general.error.color}",
|
||||
"title": "Cannot warn other moderators.",
|
||||
"fields": [
|
||||
{
|
||||
"name": "Target",
|
||||
"value": "${target.mention}",
|
||||
"inline": true
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "Kicked user from server.",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"fields": [
|
||||
{
|
||||
"name": "Performer",
|
||||
"value": "${performer.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "Target",
|
||||
"value": "${target.mention}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "Sent DM",
|
||||
"value": "${private_message}",
|
||||
"inline": true
|
||||
},
|
||||
{
|
||||
"name": "Reason",
|
||||
"value": "${nullcheck;reason;_No reason specified._}",
|
||||
"inline": false
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"type": "listing",
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "Listing of Notes (Page ${page.current}/${page.max})",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"entry": {
|
||||
"type": "description",
|
||||
"text": "**#${note_entry.note_id}**: ${note_entry.target.mention} by ${note_entry.performer.mention}\n - _${note_entry.date_time}_\n${note_entry.contents}"
|
||||
},
|
||||
"empty": "**_No recorded notes matching your query._**"
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"type": "listing",
|
||||
"color": "${moderation.color}",
|
||||
"author": {
|
||||
"name": "Listing of Warnings (Page ${page.current}/${page.max})",
|
||||
"icon_url": "${moderation.icon_url}"
|
||||
},
|
||||
"entry": {
|
||||
"type": "description",
|
||||
"text": "**Case #${warning_entry.case_id}**: Warned ${warning_entry.target.mention} by ${warning_entry.performer.mention} \n - _Date & Time:_ ${warning_entry.date_time} \n - _Reason:_ ${warning_entry.reason}"
|
||||
},
|
||||
"empty": "**_No warnings logged matching your query._**"
|
||||
}
|
|
@ -1,2 +1,10 @@
|
|||
/*
|
||||
* This file was generated by the Gradle 'init' task.
|
||||
*
|
||||
* The settings file is used to specify which projects to include in your build.
|
||||
*
|
||||
* Detailed information about configuring a multi-project build in Gradle can be found
|
||||
* in the user manual at https://docs.gradle.org/6.6.1/userguide/multi_project_builds.html
|
||||
*/
|
||||
|
||||
rootProject.name = 'Janitor'
|
||||
include 'core', 'moderation'
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
package sciwhiz12.janitor;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class BotConsole {
|
||||
public static final Logger CONSOLE = LoggerFactory.getLogger("janitor.console");
|
||||
import static sciwhiz12.janitor.Logging.CONSOLE;
|
||||
|
||||
private final JanitorBotImpl bot;
|
||||
public class BotConsole {
|
||||
private final JanitorBot bot;
|
||||
private final Thread thread;
|
||||
private volatile boolean running = true;
|
||||
|
||||
public BotConsole(JanitorBotImpl bot, InputStream input) {
|
||||
public BotConsole(JanitorBot bot, InputStream input) {
|
||||
this.bot = bot;
|
||||
this.thread = new Thread(this.new ConsoleThread(input));
|
||||
this.thread.setName("janitor_console");
|
||||
|
@ -46,6 +44,11 @@ public class BotConsole {
|
|||
case "reload": {
|
||||
if (parts.length >= 2)
|
||||
switch (parts[1]) {
|
||||
case "translations": {
|
||||
CONSOLE.info("Reloading translations");
|
||||
bot.getTranslations().loadTranslations();
|
||||
break outer;
|
||||
}
|
||||
case "messages": {
|
||||
CONSOLE.info("Reloading messages");
|
||||
bot.getMessages().loadMessages();
|
|
@ -1,5 +1,6 @@
|
|||
package sciwhiz12.janitor;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import net.dv8tion.jda.api.JDABuilder;
|
||||
import net.dv8tion.jda.api.OnlineStatus;
|
||||
import net.dv8tion.jda.api.entities.Activity;
|
||||
|
@ -7,19 +8,20 @@ import net.dv8tion.jda.api.events.ReadyEvent;
|
|||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import sciwhiz12.janitor.config.BotConfigImpl;
|
||||
import sciwhiz12.janitor.config.BotConfig;
|
||||
import sciwhiz12.janitor.config.BotOptions;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||
|
||||
public class BotStartup {
|
||||
public static void main(String[] args) {
|
||||
JANITOR.info("Starting...");
|
||||
|
||||
BotOptions options = new BotOptions(args);
|
||||
BotConfigImpl config = new BotConfigImpl(options);
|
||||
BotConfig config = new BotConfig(options);
|
||||
Preconditions.checkArgument(!config.getToken().isEmpty(), "Supply a client token through config or command line");
|
||||
|
||||
JANITOR.info("Building bot instance and connecting to Discord...");
|
||||
|
||||
|
@ -31,13 +33,12 @@ public class BotStartup {
|
|||
.addEventListeners(new ListenerAdapter() {
|
||||
@Override
|
||||
public void onReady(@NotNull ReadyEvent event) {
|
||||
new JanitorBotImpl(event.getJDA(), config);
|
||||
new JanitorBot(event.getJDA(), config);
|
||||
}
|
||||
})
|
||||
.build();
|
||||
} catch (Exception ex) {
|
||||
JANITOR.error("Error while building Discord connection", ex);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,52 +6,46 @@ import net.dv8tion.jda.api.entities.Activity;
|
|||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.PrivateChannel;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import sciwhiz12.janitor.api.JanitorBot;
|
||||
import sciwhiz12.janitor.commands.CommandRegistryImpl;
|
||||
import sciwhiz12.janitor.config.BotConfigImpl;
|
||||
import sciwhiz12.janitor.config.ConfigManagerImpl;
|
||||
import sciwhiz12.janitor.messages.MessagesImpl;
|
||||
import sciwhiz12.janitor.messages.emote.ReactionManagerImpl;
|
||||
import sciwhiz12.janitor.messages.substitution.SubstitutionsMapImpl;
|
||||
import sciwhiz12.janitor.module.ModuleManagerImpl;
|
||||
import sciwhiz12.janitor.storage.GuildStorageManagerImpl;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.config.BotConfig;
|
||||
import sciwhiz12.janitor.msg.Messages;
|
||||
import sciwhiz12.janitor.msg.TranslationMap;
|
||||
import sciwhiz12.janitor.msg.emote.ReactionManager;
|
||||
import sciwhiz12.janitor.msg.substitution.SubstitutionMap;
|
||||
import sciwhiz12.janitor.storage.GuildStorage;
|
||||
import sciwhiz12.janitor.utils.Util;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.api.Logging.STATUS;
|
||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.Logging.STATUS;
|
||||
|
||||
public class JanitorBotImpl implements JanitorBot {
|
||||
public class JanitorBot {
|
||||
private final JDA discord;
|
||||
private final BotConfigImpl config;
|
||||
private final BotConfig config;
|
||||
private final BotConsole console;
|
||||
private final GuildStorageManagerImpl storage;
|
||||
private final GuildStorageManagerImpl.SavingThread storageSavingThread;
|
||||
private final ConfigManagerImpl configManager;
|
||||
private final CommandRegistryImpl cmdRegistry;
|
||||
private final SubstitutionsMapImpl substitutions;
|
||||
private final MessagesImpl messages;
|
||||
private final ReactionManagerImpl reactions;
|
||||
private final ModuleManagerImpl modules;
|
||||
private final GuildStorage storage;
|
||||
private final GuildStorage.SavingThread storageSavingThread;
|
||||
private final CommandRegistry cmdRegistry;
|
||||
private final TranslationMap translations;
|
||||
private final SubstitutionMap substitutions;
|
||||
private final Messages messages;
|
||||
private final ReactionManager reactions;
|
||||
|
||||
public JanitorBotImpl(JDA discord, BotConfigImpl config) {
|
||||
public JanitorBot(JDA discord, BotConfig config) {
|
||||
this.config = config;
|
||||
this.discord = discord;
|
||||
this.console = new BotConsole(this, System.in);
|
||||
this.storage = new GuildStorageManagerImpl(this, Path.of(config.STORAGE_PATH.get()));
|
||||
this.configManager = new ConfigManagerImpl(this, config.getConfigsFolder());
|
||||
this.cmdRegistry = new CommandRegistryImpl(this);
|
||||
this.substitutions = new SubstitutionsMapImpl(this);
|
||||
this.messages = new MessagesImpl(this);
|
||||
this.reactions = new ReactionManagerImpl(this);
|
||||
this.modules = new ModuleManagerImpl(this);
|
||||
modules.activateModules();
|
||||
this.storage = new GuildStorage(this, Path.of(config.STORAGE_PATH.get()));
|
||||
this.cmdRegistry = new CommandRegistry(this, config.getCommandPrefix());
|
||||
this.translations = new TranslationMap(this, config.getTranslationsFile());
|
||||
this.substitutions = new SubstitutionMap(this);
|
||||
this.messages = new Messages(this, config.getTranslationsFile());
|
||||
this.reactions = new ReactionManager(this);
|
||||
// TODO: find which of these can be loaded in parallel before the bot JDA is ready
|
||||
discord.addEventListener(cmdRegistry, reactions);
|
||||
discord.getPresence().setPresence(OnlineStatus.ONLINE, Activity.playing(" n' sweeping n' testing!"));
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
discord.getGuilds().forEach(Guild::loadMembers);
|
||||
JANITOR.info("Ready!");
|
||||
config.getOwnerID()
|
||||
|
@ -65,60 +59,40 @@ public class JanitorBotImpl implements JanitorBot {
|
|||
error -> JANITOR.error(STATUS, "Error while sending ready message to owner", error)
|
||||
)
|
||||
);
|
||||
storageSavingThread = new GuildStorageManagerImpl.SavingThread(storage);
|
||||
storageSavingThread = new GuildStorage.SavingThread(storage);
|
||||
storageSavingThread.start();
|
||||
console.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JDA getDiscord() {
|
||||
return this.discord;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BotConfigImpl getBotConfig() {
|
||||
public BotConfig getConfig() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessagesImpl getMessages() {
|
||||
public Messages getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubstitutionsMapImpl getSubstitutions() {
|
||||
return substitutions;
|
||||
}
|
||||
public GuildStorage getStorage() { return this.storage; }
|
||||
|
||||
@Override
|
||||
public GuildStorageManagerImpl getGuildStorage() {
|
||||
return this.storage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigManagerImpl getConfigs() {
|
||||
return configManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandRegistryImpl getCommands() {
|
||||
public CommandRegistry getCommandRegistry() {
|
||||
return this.cmdRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactionManagerImpl getReactions() {
|
||||
public TranslationMap getTranslations() {
|
||||
return this.translations;
|
||||
}
|
||||
|
||||
public ReactionManager getReactionManager() {
|
||||
return this.reactions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleManagerImpl getModuleManager() {
|
||||
return modules;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
JANITOR.info(STATUS, "Shutting down!");
|
||||
getBotConfig().getOwnerID()
|
||||
getConfig().getOwnerID()
|
||||
.map(discord::retrieveUserById)
|
||||
.map(owner ->
|
||||
owner
|
||||
|
@ -136,13 +110,13 @@ public class JanitorBotImpl implements JanitorBot {
|
|||
.error(STATUS, "Error while sending shutdown message to owner", err)
|
||||
))
|
||||
).ifPresent(CompletableFuture::join);
|
||||
modules.shutdown();
|
||||
discord.shutdown();
|
||||
storageSavingThread.stopThread();
|
||||
storage.save();
|
||||
configManager.save();
|
||||
configManager.close();
|
||||
console.stop();
|
||||
config.close();
|
||||
}
|
||||
|
||||
public SubstitutionMap getSubstitutions() {
|
||||
return substitutions;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package sciwhiz12.janitor.api;
|
||||
package sciwhiz12.janitor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -8,10 +8,11 @@ import org.slf4j.MarkerFactory;
|
|||
public class Logging {
|
||||
public static final Marker STATUS = MarkerFactory.getMarker("STATUS");
|
||||
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 STORAGE = MarkerFactory.getMarker("STORAGE");
|
||||
public static final Marker MODULE = MarkerFactory.getMarker("MODULE");
|
||||
|
||||
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");
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
package sciwhiz12.janitor.api.command;
|
||||
package sciwhiz12.janitor.commands;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.api.JanitorBot;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
import sciwhiz12.janitor.config.BotConfig;
|
||||
import sciwhiz12.janitor.msg.Messages;
|
||||
|
||||
public abstract class BaseCommand implements Command {
|
||||
public abstract class BaseCommand {
|
||||
private final CommandRegistry registry;
|
||||
|
||||
public BaseCommand(CommandRegistry registry) {
|
||||
|
@ -19,5 +21,13 @@ public abstract class BaseCommand implements Command {
|
|||
return registry.getBot();
|
||||
}
|
||||
|
||||
protected Messages messages() {
|
||||
return getBot().getMessages();
|
||||
}
|
||||
|
||||
protected BotConfig config() {
|
||||
return getBot().getConfig();
|
||||
}
|
||||
|
||||
public abstract LiteralArgumentBuilder<MessageReceivedEvent> getNode();
|
||||
}
|
|
@ -8,80 +8,78 @@ import net.dv8tion.jda.api.events.GenericEvent;
|
|||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.hooks.EventListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
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.JanitorBot;
|
||||
import sciwhiz12.janitor.commands.bot.ShutdownCommand;
|
||||
import sciwhiz12.janitor.commands.misc.HelloCommand;
|
||||
import sciwhiz12.janitor.commands.misc.OKCommand;
|
||||
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 java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static sciwhiz12.janitor.api.Logging.COMMANDS;
|
||||
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.Logging.COMMANDS;
|
||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||
|
||||
public class CommandRegistryImpl implements CommandRegistry, EventListener {
|
||||
private final JanitorBotImpl bot;
|
||||
private final Map<String, Command> registry = new HashMap<>();
|
||||
public class CommandRegistry implements EventListener {
|
||||
private final JanitorBot bot;
|
||||
private final String prefix;
|
||||
private final Map<String, BaseCommand> registry = new HashMap<>();
|
||||
private final CommandDispatcher<MessageReceivedEvent> dispatcher;
|
||||
|
||||
public CommandRegistryImpl(JanitorBotImpl bot) {
|
||||
public CommandRegistry(JanitorBot bot, String prefix) {
|
||||
this.bot = bot;
|
||||
this.prefix = prefix;
|
||||
this.dispatcher = new CommandDispatcher<>();
|
||||
|
||||
addCommand(reg -> new PingCommand(reg, "ping", "Pong!"));
|
||||
addCommand(reg -> new PingCommand(reg, "pong", "Ping!"));
|
||||
addCommand(OKCommand::new);
|
||||
addCommand(HelloCommand::new);
|
||||
addCommand(ShutdownCommand::new);
|
||||
addCommand(new PingCommand(this, "ping", "Pong!"));
|
||||
addCommand(new PingCommand(this, "pong", "Ping!"));
|
||||
addCommand(new OKCommand(this));
|
||||
addCommand(new HelloCommand(this));
|
||||
addCommand(new KickCommand(this));
|
||||
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() {
|
||||
return this.dispatcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JanitorBotImpl getBot() {
|
||||
public JanitorBot getBot() {
|
||||
return this.bot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCommand(Function<CommandRegistry, Command> command) {
|
||||
dispatcher.register(command.apply(this).getNode());
|
||||
public void addCommand(BaseCommand instance) {
|
||||
dispatcher.register(instance.getNode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(@NotNull GenericEvent genericEvent) {
|
||||
if (!(genericEvent instanceof MessageReceivedEvent)) return;
|
||||
MessageReceivedEvent event = (MessageReceivedEvent) genericEvent;
|
||||
if (event.getAuthor().isBot()) return;
|
||||
final String prefix;
|
||||
if (event.isFromGuild()) {
|
||||
prefix = getBot().getConfigs().get(event.getGuild().getIdLong())
|
||||
.forGuild(CoreConfigs.COMMAND_PREFIX);
|
||||
} else {
|
||||
prefix = getBot().getBotConfig().getCommandPrefix();
|
||||
}
|
||||
|
||||
String msg = event.getMessage().getContentRaw();
|
||||
if (!msg.startsWith(prefix)) return;
|
||||
if (!msg.startsWith(this.prefix)) return;
|
||||
JANITOR.debug(COMMANDS, "Received message starting with valid command prefix. Author: {}, full message: {}",
|
||||
Util.toString(event.getAuthor()), msg);
|
||||
try {
|
||||
StringReader command = new StringReader(msg.substring(prefix.length()));
|
||||
StringReader command = new StringReader(msg.substring(this.prefix.length()));
|
||||
ParseResults<MessageReceivedEvent> parseResults = this.dispatcher.parse(command, event);
|
||||
if (parseResults.getReader().canRead()) {
|
||||
if (parseResults.getExceptions().isEmpty()) {
|
||||
JANITOR.info(COMMANDS, "Command not found.");
|
||||
} else {
|
||||
JANITOR.error(COMMANDS, "Error while parsing command: {}", parseResults.getExceptions().values());
|
||||
}
|
||||
// Parsing did not succeed, i.e. command not found
|
||||
// TODO: add separate code path when insufficient permissions / requires fails
|
||||
JANITOR.error(COMMANDS, "Error while parsing command: {}", parseResults.getExceptions().values());
|
||||
return;
|
||||
}
|
||||
JANITOR.debug(COMMANDS, "Executing command.");
|
|
@ -1,11 +1,11 @@
|
|||
package sciwhiz12.janitor.api.command.arguments;
|
||||
package sciwhiz12.janitor.commands.arguments;
|
||||
|
||||
import com.mojang.brigadier.StringReader;
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import sciwhiz12.janitor.api.utils.StringReaderUtil;
|
||||
import sciwhiz12.janitor.utils.StringReaderUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
|
@ -17,15 +17,18 @@ public class CustomStringArgumentType implements ArgumentType<String> {
|
|||
}
|
||||
|
||||
public static CustomStringArgumentType word() {
|
||||
return new CustomStringArgumentType(StringArgumentType.StringType.SINGLE_WORD);
|
||||
return new CustomStringArgumentType(
|
||||
StringArgumentType.StringType.SINGLE_WORD);
|
||||
}
|
||||
|
||||
public static CustomStringArgumentType string() {
|
||||
return new CustomStringArgumentType(StringArgumentType.StringType.QUOTABLE_PHRASE);
|
||||
return new CustomStringArgumentType(
|
||||
StringArgumentType.StringType.QUOTABLE_PHRASE);
|
||||
}
|
||||
|
||||
public static CustomStringArgumentType greedyString() {
|
||||
return new CustomStringArgumentType(StringArgumentType.StringType.GREEDY_PHRASE);
|
||||
return new CustomStringArgumentType(
|
||||
StringArgumentType.StringType.GREEDY_PHRASE);
|
||||
}
|
||||
|
||||
public static String getString(final CommandContext<?> context, final String name) {
|
|
@ -1,4 +1,4 @@
|
|||
package sciwhiz12.janitor.api.command.arguments;
|
||||
package sciwhiz12.janitor.commands.arguments;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.brigadier.LiteralMessage;
|
||||
|
@ -9,7 +9,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import sciwhiz12.janitor.api.utils.StringReaderUtil;
|
||||
import sciwhiz12.janitor.utils.StringReaderUtil;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -71,11 +71,6 @@ public class GuildMemberArgument implements ArgumentType<GuildMemberArgument.IMe
|
|||
throw UNKNOWN_MEMBER_IDENTIFIER.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "member()";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getExamples() {
|
||||
return ImmutableList.of("<@!607058472709652501>", "<@750291676764962816>");
|
|
@ -3,12 +3,12 @@ package sciwhiz12.janitor.commands.bot;
|
|||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.api.command.BaseCommand;
|
||||
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.utils.Util;
|
||||
|
||||
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
|
||||
public class ShutdownCommand extends BaseCommand {
|
||||
public ShutdownCommand(CommandRegistry registry) {
|
||||
|
@ -18,7 +18,7 @@ public class ShutdownCommand extends BaseCommand {
|
|||
@Override
|
||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||
return literal("shutdown")
|
||||
.requires(ctx -> getBot().getBotConfig().getOwnerID().map(
|
||||
.requires(ctx -> getBot().getConfig().getOwnerID().map(
|
||||
id -> id == ctx.getAuthor().getIdLong()).orElse(false)
|
||||
)
|
||||
.executes(this::run);
|
|
@ -5,17 +5,17 @@ import com.mojang.brigadier.context.CommandContext;
|
|||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.api.command.BaseCommand;
|
||||
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||
import sciwhiz12.janitor.api.command.arguments.GuildMemberArgument;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.commands.arguments.GuildMemberArgument;
|
||||
import sciwhiz12.janitor.utils.Util;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.getMembers;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMembers;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
|
||||
public class HelloCommand extends BaseCommand {
|
||||
public HelloCommand(CommandRegistry registry) {
|
||||
|
@ -38,7 +38,7 @@ public class HelloCommand extends BaseCommand {
|
|||
success -> {
|
||||
JANITOR.debug("Sent greeting message to {}, on cmd of {}", Util.toString(member.getUser()),
|
||||
Util.toString(ctx.getSource().getAuthor()));
|
||||
getBot().getReactions().newMessage(success)
|
||||
getBot().getReactionManager().newMessage(success)
|
||||
.add("\u274C", (msg, event) -> success.delete()
|
||||
.flatMap(v -> event.getChannel()
|
||||
.deleteMessageById(ctx.getSource().getMessageIdLong()))
|
|
@ -3,12 +3,12 @@ package sciwhiz12.janitor.commands.misc;
|
|||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.api.command.BaseCommand;
|
||||
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.utils.Util;
|
||||
|
||||
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
|
||||
public class OKCommand extends BaseCommand {
|
||||
public OKCommand(CommandRegistry registry) {
|
|
@ -3,12 +3,12 @@ package sciwhiz12.janitor.commands.misc;
|
|||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.api.command.BaseCommand;
|
||||
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.utils.Util;
|
||||
|
||||
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
|
||||
public class PingCommand extends BaseCommand {
|
||||
private final String command;
|
|
@ -1,4 +1,4 @@
|
|||
package sciwhiz12.janitor.moderation;
|
||||
package sciwhiz12.janitor.commands.moderation;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
@ -8,8 +8,10 @@ import net.dv8tion.jda.api.entities.Guild;
|
|||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||
import sciwhiz12.janitor.api.utils.MessageHelper;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.commands.util.ModerationHelper;
|
||||
import sciwhiz12.janitor.msg.MessageHelper;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
@ -20,16 +22,22 @@ import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
|
|||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
|
||||
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.getMembers;
|
||||
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.member;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMembers;
|
||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
|
||||
public class BanCommand extends ModBaseCommand {
|
||||
public class BanCommand extends BaseCommand {
|
||||
public static final EnumSet<Permission> BAN_PERMISSION = EnumSet.of(Permission.BAN_MEMBERS);
|
||||
|
||||
public BanCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||
super(module, registry);
|
||||
/*
|
||||
ban command
|
||||
!ban <user> [reason]
|
||||
!ban delete <number of days> <user> [reason]
|
||||
*/
|
||||
|
||||
public BanCommand(CommandRegistry registry) {
|
||||
super(registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -116,7 +124,7 @@ public class BanCommand extends ModBaseCommand {
|
|||
.flatMap(v -> messages().getRegularMessage("moderation/ban/info")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(MessageHelper.member("target", target))
|
||||
.with("private_message", () -> res.isSuccess() ? "\u2705" : "\u274C")
|
||||
.with("private_message", () -> res.isSuccess() ? "✅" : "❌")
|
||||
.with("delete_duration", () -> String.valueOf(days))
|
||||
.with("reason", () -> reason)
|
||||
.send(getBot(), channel)
|
|
@ -1,4 +1,4 @@
|
|||
package sciwhiz12.janitor.moderation;
|
||||
package sciwhiz12.janitor.commands.moderation;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
|
@ -8,9 +8,11 @@ import net.dv8tion.jda.api.entities.Guild;
|
|||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||
import sciwhiz12.janitor.api.utils.CommandHelper;
|
||||
import sciwhiz12.janitor.api.utils.MessageHelper;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.commands.util.CommandHelper;
|
||||
import sciwhiz12.janitor.commands.util.ModerationHelper;
|
||||
import sciwhiz12.janitor.msg.MessageHelper;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
@ -19,14 +21,14 @@ import javax.annotation.Nullable;
|
|||
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
|
||||
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.getMembers;
|
||||
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.member;
|
||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMembers;
|
||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
||||
|
||||
public class KickCommand extends ModBaseCommand {
|
||||
public class KickCommand extends BaseCommand {
|
||||
public static final EnumSet<Permission> KICK_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||
|
||||
public KickCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||
super(module, registry);
|
||||
public KickCommand(CommandRegistry registry) {
|
||||
super(registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -108,7 +110,7 @@ public class KickCommand extends ModBaseCommand {
|
|||
.flatMap(v -> messages().getRegularMessage("moderation/kick/info")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(MessageHelper.member("target", target))
|
||||
.with("private_message", () -> res.isSuccess() ? "\u2705" : "\u274C")
|
||||
.with("private_message", () -> res.isSuccess() ? "✅" : "❌")
|
||||
.with("reason", () -> reason)
|
||||
.send(getBot(), channel)
|
||||
)
|
|
@ -1,4 +1,4 @@
|
|||
package sciwhiz12.janitor.moderation.notes;
|
||||
package sciwhiz12.janitor.commands.moderation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
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.MessageChannel;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||
import sciwhiz12.janitor.api.utils.MessageHelper;
|
||||
import sciwhiz12.janitor.moderation.ModBaseCommand;
|
||||
import sciwhiz12.janitor.moderation.ModerationHelper;
|
||||
import sciwhiz12.janitor.moderation.ModerationModuleImpl;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.moderation.notes.NoteEntry;
|
||||
import sciwhiz12.janitor.moderation.notes.NoteStorage;
|
||||
import sciwhiz12.janitor.msg.MessageHelper;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
|
@ -29,26 +29,24 @@ import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
|
|||
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
|
||||
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.getMembers;
|
||||
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.member;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.api.utils.MessageHelper.user;
|
||||
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.*;
|
||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMembers;
|
||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
||||
import static sciwhiz12.janitor.commands.moderation.NoteCommand.ModeratorFilter.*;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.msg.MessageHelper.*;
|
||||
|
||||
public class NoteCommand extends ModBaseCommand {
|
||||
public class NoteCommand extends BaseCommand {
|
||||
public static EnumSet<Permission> NOTE_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||
|
||||
public NoteCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||
super(module, registry);
|
||||
public NoteCommand(CommandRegistry registry) {
|
||||
super(registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||
return literal("note")
|
||||
.requires(event -> config(event).forGuild(ENABLE_NOTES))
|
||||
.requires(ctx -> config().NOTES_ENABLE.get())
|
||||
.then(literal("add")
|
||||
.then(argument("target", member())
|
||||
.then(argument("contents", greedyString())
|
||||
|
@ -127,9 +125,8 @@ public class NoteCommand extends ModBaseCommand {
|
|||
.send(getBot(), channel).queue();
|
||||
|
||||
} else {
|
||||
final NoteStorage storage = getNotes(guild);
|
||||
|
||||
final int maxAmount = config(ctx.getSource()).forGuild(MAX_NOTES_PER_MOD);
|
||||
final NoteStorage storage = NoteStorage.get(getBot().getStorage(), guild);
|
||||
final int maxAmount = config().NOTES_MAX_AMOUNT_PER_MOD.get();
|
||||
if (storage.getAmountOfNotes(target.getUser()) >= maxAmount) {
|
||||
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
|
@ -143,7 +140,7 @@ public class NoteCommand extends ModBaseCommand {
|
|||
|
||||
messages().getRegularMessage("moderation/note/add")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(ModerationHelper.noteEntry("note_entry", noteID, entry))
|
||||
.apply(noteEntry("note_entry", noteID, entry))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
}
|
||||
|
@ -204,11 +201,16 @@ public class NoteCommand extends ModBaseCommand {
|
|||
} else {
|
||||
messages().<Map.Entry<Integer, NoteEntry>>getListingMessage("moderation/note/list")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.amountPerPage(8)
|
||||
.setEntryApplier((entry, subs) -> subs
|
||||
.apply(ModerationHelper.noteEntry("note_entry", entry.getKey(), entry.getValue()))
|
||||
.with("note_entry.note_id", () -> String.valueOf(entry.getKey()))
|
||||
.apply(user("note_entry.performer", entry.getValue().getPerformer()))
|
||||
.apply(user("note_entry.target", entry.getValue().getTarget()))
|
||||
.with("note_entry.date_time", () -> entry.getValue().getDateTime().format(DATE_TIME_FORMAT))
|
||||
.with("note_entry.contents", entry.getValue()::getContents)
|
||||
)
|
||||
.build(channel, getBot(), ctx.getSource().getMessage(),
|
||||
getNotes(guild)
|
||||
NoteStorage.get(getBot().getStorage(), guild)
|
||||
.getNotes()
|
||||
.entrySet().stream()
|
||||
.filter(predicate)
|
||||
|
@ -238,7 +240,7 @@ public class NoteCommand extends ModBaseCommand {
|
|||
.send(getBot(), channel).queue();
|
||||
|
||||
} else {
|
||||
final NoteStorage storage = getNotes(guild);
|
||||
final NoteStorage storage = NoteStorage.get(getBot().getStorage(), guild);
|
||||
@Nullable
|
||||
final NoteEntry entry = storage.getNote(noteID);
|
||||
if (entry == null) {
|
||||
|
@ -252,7 +254,7 @@ public class NoteCommand extends ModBaseCommand {
|
|||
|
||||
messages().getRegularMessage("moderation/note/remove")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(ModerationHelper.noteEntry("note_entry", noteID, entry))
|
||||
.apply(noteEntry("note_entry", noteID, entry))
|
||||
.send(getBot(), channel).queue();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package sciwhiz12.janitor.moderation;
|
||||
package sciwhiz12.janitor.commands.moderation;
|
||||
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
|
@ -9,8 +9,10 @@ import net.dv8tion.jda.api.entities.Member;
|
|||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||
import sciwhiz12.janitor.api.utils.MessageHelper;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.commands.util.ModerationHelper;
|
||||
import sciwhiz12.janitor.msg.MessageHelper;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Locale;
|
||||
|
@ -20,14 +22,14 @@ import java.util.stream.Collectors;
|
|||
import static com.mojang.brigadier.arguments.LongArgumentType.getLong;
|
||||
import static com.mojang.brigadier.arguments.LongArgumentType.longArg;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
|
||||
public class UnbanCommand extends ModBaseCommand {
|
||||
public class UnbanCommand extends BaseCommand {
|
||||
public static final EnumSet<Permission> UNBAN_PERMISSION = EnumSet.of(Permission.BAN_MEMBERS);
|
||||
|
||||
public UnbanCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||
super(module, registry);
|
||||
public UnbanCommand(CommandRegistry registry) {
|
||||
super(registry);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,4 +1,4 @@
|
|||
package sciwhiz12.janitor.moderation.warns;
|
||||
package sciwhiz12.janitor.commands.moderation;
|
||||
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
|
@ -8,31 +8,30 @@ import net.dv8tion.jda.api.entities.Guild;
|
|||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||
import sciwhiz12.janitor.api.utils.MessageHelper;
|
||||
import sciwhiz12.janitor.moderation.ModBaseCommand;
|
||||
import sciwhiz12.janitor.moderation.ModerationHelper;
|
||||
import sciwhiz12.janitor.moderation.ModerationModuleImpl;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
||||
import sciwhiz12.janitor.msg.MessageHelper;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.moderation.ModerationConfigs.*;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
|
||||
public class UnwarnCommand extends ModBaseCommand {
|
||||
public class UnwarnCommand extends BaseCommand {
|
||||
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||
|
||||
public UnwarnCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||
super(module, registry);
|
||||
public UnwarnCommand(CommandRegistry registry) {
|
||||
super(registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||
return literal("unwarn")
|
||||
.requires(ctx -> config(ctx).forGuild(ENABLE_WARNS))
|
||||
.requires(ctx -> getBot().getConfig().WARNINGS_ENABLE.get())
|
||||
.then(argument("caseId", IntegerArgumentType.integer(1))
|
||||
.executes(this::run)
|
||||
);
|
||||
|
@ -63,7 +62,7 @@ public class UnwarnCommand extends ModBaseCommand {
|
|||
.send(getBot(), channel).queue();
|
||||
|
||||
} else {
|
||||
final WarningStorage storage = getWarns(guild);
|
||||
final WarningStorage storage = WarningStorage.get(getBot().getStorage(), guild);
|
||||
@Nullable
|
||||
final WarningEntry entry = storage.getWarning(caseID);
|
||||
Member temp;
|
||||
|
@ -74,24 +73,24 @@ public class UnwarnCommand extends ModBaseCommand {
|
|||
.send(getBot(), channel).queue();
|
||||
|
||||
} else if (entry.getWarned().getIdLong() == performer.getIdLong()
|
||||
&& !config(guild).forGuild(ALLOW_REMOVE_SELF_WARNINGS)) {
|
||||
&& !config().WARNINGS_REMOVE_SELF_WARNINGS.get()) {
|
||||
messages().getRegularMessage("moderation/error/unwarn/cannot_unwarn_self")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(ModerationHelper.warningEntry("warning_entry", caseID, entry))
|
||||
.apply(MessageHelper.warningEntry("warning_entry", caseID, entry))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
} else if (config(guild).forGuild(WARNS_RESPECT_MOD_ROLES)
|
||||
} else if (config().WARNINGS_RESPECT_MOD_ROLES.get()
|
||||
&& (temp = guild.getMember(entry.getPerformer())) != null && !performer.canInteract(temp)) {
|
||||
messages().getRegularMessage("moderation/error/unwarn/cannot_remove_higher_mod")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(ModerationHelper.warningEntry("warning_entry", caseID, entry))
|
||||
.apply(MessageHelper.warningEntry("warning_entry", caseID, entry))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
} else {
|
||||
storage.removeWarning(caseID);
|
||||
messages().getRegularMessage("moderation/unwarn/info")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(ModerationHelper.warningEntry("warning_entry", caseID, entry))
|
||||
.apply(MessageHelper.warningEntry("warning_entry", caseID, entry))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package sciwhiz12.janitor.moderation.warns;
|
||||
package sciwhiz12.janitor.commands.moderation;
|
||||
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
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.MessageChannel;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||
import sciwhiz12.janitor.api.utils.MessageHelper;
|
||||
import sciwhiz12.janitor.moderation.ModBaseCommand;
|
||||
import sciwhiz12.janitor.moderation.ModerationHelper;
|
||||
import sciwhiz12.janitor.moderation.ModerationModuleImpl;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
||||
import sciwhiz12.janitor.msg.MessageHelper;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
|
@ -22,24 +22,22 @@ import java.util.Objects;
|
|||
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.getString;
|
||||
import static com.mojang.brigadier.arguments.StringArgumentType.greedyString;
|
||||
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.getMembers;
|
||||
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.member;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||
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;
|
||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMembers;
|
||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
|
||||
public class WarnCommand extends ModBaseCommand {
|
||||
public class WarnCommand extends BaseCommand {
|
||||
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||
|
||||
public WarnCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||
super(module, registry);
|
||||
public WarnCommand(CommandRegistry registry) {
|
||||
super(registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||
return literal("warn")
|
||||
.requires(ctx -> config(ctx).forGuild(ENABLE_WARNS))
|
||||
.requires(ctx -> getBot().getConfig().WARNINGS_ENABLE.get())
|
||||
.then(argument("member", member())
|
||||
.then(argument("reason", greedyString())
|
||||
.executes(ctx -> this.run(ctx, getString(ctx, "reason")))
|
||||
|
@ -86,27 +84,27 @@ public class WarnCommand extends ModBaseCommand {
|
|||
.apply(MessageHelper.member("target", target))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
} else if (target.hasPermission(WARN_PERMISSION) && config(guild).forGuild(ALLOW_WARN_OTHER_MODERATORS)) {
|
||||
} else if (target.hasPermission(WARN_PERMISSION) && config().WARNINGS_PREVENT_WARNING_MODS.get()) {
|
||||
messages().getRegularMessage("moderation/error/warn/cannot_warn_mods")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(MessageHelper.member("target", target))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
} else {
|
||||
WarningEntry entry = new WarningEntry(performer.getUser(), target.getUser(), dateTime, reason);
|
||||
int caseId = getWarns(guild).addWarning(entry);
|
||||
WarningEntry entry = new WarningEntry(target.getUser(), performer.getUser(), dateTime, reason);
|
||||
int caseId = WarningStorage.get(getBot().getStorage(), guild).addWarning(entry);
|
||||
|
||||
target.getUser().openPrivateChannel()
|
||||
.flatMap(dm -> messages().getRegularMessage("moderation/warn/dm")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(ModerationHelper.warningEntry("warning_entry", caseId, entry))
|
||||
.apply(MessageHelper.warningEntry("warning_entry", caseId, entry))
|
||||
.send(getBot(), dm)
|
||||
)
|
||||
.mapToResult()
|
||||
.flatMap(res -> messages().getRegularMessage("moderation/warn/info")
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.apply(ModerationHelper.warningEntry("warning_entry", caseId, entry))
|
||||
.with("private_message", () -> res.isSuccess() ? "\u2705" : "\u274C")
|
||||
.apply(MessageHelper.warningEntry("warning_entry", caseId, entry))
|
||||
.with("private_message", () -> res.isSuccess() ? "✅" : "❌")
|
||||
.send(getBot(), channel)
|
||||
)
|
||||
.queue();
|
|
@ -1,4 +1,4 @@
|
|||
package sciwhiz12.janitor.moderation.warns;
|
||||
package sciwhiz12.janitor.commands.moderation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
|
@ -9,9 +9,11 @@ import net.dv8tion.jda.api.entities.Guild;
|
|||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import sciwhiz12.janitor.api.command.CommandRegistry;
|
||||
import sciwhiz12.janitor.moderation.ModBaseCommand;
|
||||
import sciwhiz12.janitor.moderation.ModerationModuleImpl;
|
||||
import sciwhiz12.janitor.commands.BaseCommand;
|
||||
import sciwhiz12.janitor.commands.CommandRegistry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningStorage;
|
||||
import sciwhiz12.janitor.msg.MessageHelper;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
|
@ -20,26 +22,24 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.getMembers;
|
||||
import static sciwhiz12.janitor.api.command.arguments.GuildMemberArgument.member;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.api.utils.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.api.utils.MessageHelper.member;
|
||||
import static sciwhiz12.janitor.api.utils.MessageHelper.user;
|
||||
import static sciwhiz12.janitor.moderation.ModerationConfigs.ENABLE_WARNS;
|
||||
import static sciwhiz12.janitor.moderation.ModerationHelper.warningEntry;
|
||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.getMembers;
|
||||
import static sciwhiz12.janitor.commands.arguments.GuildMemberArgument.member;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.argument;
|
||||
import static sciwhiz12.janitor.commands.util.CommandHelper.literal;
|
||||
import static sciwhiz12.janitor.msg.MessageHelper.DATE_TIME_FORMAT;
|
||||
import static sciwhiz12.janitor.msg.MessageHelper.user;
|
||||
|
||||
public class WarnListCommand extends ModBaseCommand {
|
||||
public class WarnListCommand extends BaseCommand {
|
||||
public static final EnumSet<Permission> WARN_PERMISSION = EnumSet.of(Permission.KICK_MEMBERS);
|
||||
|
||||
public WarnListCommand(ModerationModuleImpl module, CommandRegistry registry) {
|
||||
super(module, registry);
|
||||
public WarnListCommand(CommandRegistry registry) {
|
||||
super(registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiteralArgumentBuilder<MessageReceivedEvent> getNode() {
|
||||
return literal("warnlist")
|
||||
.requires(ctx -> config(ctx).forGuild(ENABLE_WARNS))
|
||||
.requires(ctx -> getBot().getConfig().WARNINGS_ENABLE.get())
|
||||
.then(literal("target")
|
||||
.then(argument("target", member())
|
||||
.then(literal("mod")
|
||||
|
@ -62,7 +62,7 @@ public class WarnListCommand extends ModBaseCommand {
|
|||
MessageChannel channel = ctx.getSource().getChannel();
|
||||
if (!ctx.getSource().isFromGuild()) {
|
||||
messages().getRegularMessage("general/error/guild_only_command")
|
||||
.apply(user("performer", ctx.getSource().getAuthor()))
|
||||
.apply(MessageHelper.user("performer", ctx.getSource().getAuthor()))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
return 1;
|
||||
|
@ -77,7 +77,7 @@ public class WarnListCommand extends ModBaseCommand {
|
|||
final Member target = members.get(0);
|
||||
if (guild.getSelfMember().equals(target)) {
|
||||
messages().getRegularMessage("general/error/cannot_interact")
|
||||
.apply(member("target", target))
|
||||
.apply(MessageHelper.member("target", target))
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
return 1;
|
||||
|
@ -93,18 +93,23 @@ public class WarnListCommand extends ModBaseCommand {
|
|||
|
||||
if (!performer.hasPermission(WARN_PERMISSION)) {
|
||||
messages().getRegularMessage("moderation/error/insufficient_permissions")
|
||||
.apply(member("performer", performer))
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.with("required_permissions", WARN_PERMISSION::toString)
|
||||
.send(getBot(), channel).queue();
|
||||
|
||||
} else {
|
||||
messages().<Map.Entry<Integer, WarningEntry>>getListingMessage("moderation/warn/list")
|
||||
.apply(member("performer", performer))
|
||||
.setEntryApplier((entry, subs) ->
|
||||
subs.apply(warningEntry("warning_entry", entry.getKey(), entry.getValue()))
|
||||
.apply(MessageHelper.member("performer", performer))
|
||||
.amountPerPage(8)
|
||||
.setEntryApplier((entry, subs) -> subs
|
||||
.with("warning_entry.case_id", () -> String.valueOf(entry.getKey()))
|
||||
.apply(user("warning_entry.performer", entry.getValue().getPerformer()))
|
||||
.apply(user("warning_entry.warned", entry.getValue().getWarned()))
|
||||
.with("warning_entry.date_time", () -> entry.getValue().getDateTime().format(DATE_TIME_FORMAT))
|
||||
.with("warning_entry.reason", entry.getValue()::getReason)
|
||||
)
|
||||
.build(channel, getBot(), ctx.getSource().getMessage(),
|
||||
getWarns(guild)
|
||||
WarningStorage.get(getBot().getStorage(), guild)
|
||||
.getWarnings()
|
||||
.entrySet().stream()
|
||||
.filter(predicate)
|
|
@ -1,13 +1,11 @@
|
|||
package sciwhiz12.janitor.api.utils;
|
||||
package sciwhiz12.janitor.commands.util;
|
||||
|
||||
import com.mojang.brigadier.arguments.ArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
|
||||
public final class CommandHelper {
|
||||
private CommandHelper() {}
|
||||
|
||||
public class CommandHelper {
|
||||
public static LiteralArgumentBuilder<MessageReceivedEvent> literal(String command) {
|
||||
return LiteralArgumentBuilder.literal(command);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package sciwhiz12.janitor.commands.util;
|
||||
|
||||
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 java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static sciwhiz12.janitor.msg.MessageHelper.DATE_TIME_FORMAT;
|
||||
import static sciwhiz12.janitor.utils.Util.nameFor;
|
||||
|
||||
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(nameFor(performer.getUser()))
|
||||
.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(nameFor(performer.getUser()))
|
||||
.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);
|
||||
}
|
||||
}
|
|
@ -4,38 +4,43 @@ 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.Preconditions;
|
||||
import sciwhiz12.janitor.api.config.BotConfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static sciwhiz12.janitor.api.Logging.CONFIG;
|
||||
import static sciwhiz12.janitor.api.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.Logging.CONFIG;
|
||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||
|
||||
public class BotConfigImpl implements BotConfig {
|
||||
public class BotConfig {
|
||||
public static final Path DEFAULT_CONFIG_PATH = Path.of("config.toml");
|
||||
|
||||
private final CommentedConfigSpec.ConfigValue<String> CLIENT_TOKEN;
|
||||
private final CommentedConfigSpec.LongValue OWNER_ID;
|
||||
|
||||
public final CommentedConfigSpec.ConfigValue<String> CONFIGS_PATH;
|
||||
|
||||
public final CommentedConfigSpec.ConfigValue<String> STORAGE_PATH;
|
||||
public final CommentedConfigSpec.IntValue AUTOSAVE_INTERVAL;
|
||||
|
||||
public final CommentedConfigSpec.ConfigValue<String> CUSTOM_TRANSLATION_FILE;
|
||||
public final CommentedConfigSpec.ConfigValue<String> CUSTOM_MESSAGES_DIRECTORY;
|
||||
|
||||
public final CommentedConfigSpec.ConfigValue<String> COMMAND_PREFIX;
|
||||
|
||||
public final CommentedConfigSpec.BooleanValue WARNINGS_ENABLE;
|
||||
public final CommentedConfigSpec.BooleanValue WARNINGS_RESPECT_MOD_ROLES;
|
||||
public final CommentedConfigSpec.BooleanValue WARNINGS_PREVENT_WARNING_MODS;
|
||||
public final CommentedConfigSpec.BooleanValue WARNINGS_REMOVE_SELF_WARNINGS;
|
||||
|
||||
public final CommentedConfigSpec.IntValue NOTES_MAX_AMOUNT_PER_MOD;
|
||||
public final CommentedConfigSpec.BooleanValue NOTES_ENABLE;
|
||||
|
||||
private final BotOptions options;
|
||||
private final Path configPath;
|
||||
private final CommentedConfigSpec spec;
|
||||
private final CommentedFileConfig config;
|
||||
|
||||
public BotConfigImpl(BotOptions options) {
|
||||
public BotConfig(BotOptions options) {
|
||||
this.options = options;
|
||||
|
||||
final CommentedConfigSpec.Builder builder = new CommentedConfigSpec.Builder();
|
||||
|
@ -50,10 +55,6 @@ public class BotConfigImpl implements BotConfig {
|
|||
.defineInRange("owner_id", 0L, Long.MIN_VALUE, Long.MAX_VALUE);
|
||||
builder.pop();
|
||||
|
||||
CONFIGS_PATH = builder
|
||||
.comment("The folder where guild configs are kept.")
|
||||
.define("configs_path", "configs");
|
||||
|
||||
builder.push("storage");
|
||||
STORAGE_PATH = builder
|
||||
.comment("The folder where per-guild storage is kept.")
|
||||
|
@ -63,6 +64,10 @@ public class BotConfigImpl implements BotConfig {
|
|||
.defineInRange("autosave_internal", 20, 1, Integer.MAX_VALUE);
|
||||
builder.pop();
|
||||
|
||||
CUSTOM_TRANSLATION_FILE = builder
|
||||
.comment("A file which contains custom translation keys to load for messages.",
|
||||
"If blank, no file shall be loaded.")
|
||||
.define("messages.custom_translations", "");
|
||||
CUSTOM_MESSAGES_DIRECTORY = builder
|
||||
.comment("A folder containing custom messages, with a 'messages.json' key file.",
|
||||
"If blank, no folder shall be loaded and defaults will be used.")
|
||||
|
@ -72,6 +77,36 @@ public class BotConfigImpl implements BotConfig {
|
|||
.comment("The prefix for commands.")
|
||||
.define("commands.prefix", "!");
|
||||
|
||||
builder.comment("Moderation settings").push("moderation");
|
||||
{
|
||||
builder.comment("Settings for the warnings system").push("warnings");
|
||||
WARNINGS_ENABLE = builder
|
||||
.comment("Whether to enable the warnings system. If disabled, the related commands are force-disabled.")
|
||||
.define("enable", true);
|
||||
WARNINGS_RESPECT_MOD_ROLES = builder
|
||||
.comment(
|
||||
"Whether to prevent lower-ranked moderators (in the role hierarchy) from removing warnings issued by " +
|
||||
"higher-ranked moderators.")
|
||||
.define("respect_mod_roles", false);
|
||||
WARNINGS_PREVENT_WARNING_MODS = builder
|
||||
.comment("Whether to prevent moderators from issuing warnings against other moderators.")
|
||||
.define("warn_other_moderators", false);
|
||||
WARNINGS_REMOVE_SELF_WARNINGS = builder
|
||||
.comment("Whether to allow moderators to remove warnings from themselves.")
|
||||
.define("remove_self_warnings", false);
|
||||
builder.pop();
|
||||
|
||||
builder.comment("Settings for the notes system").push("notes");
|
||||
NOTES_ENABLE = builder
|
||||
.comment("Whether to enable the notes system. If disabled, the related commands are force-disabled.")
|
||||
.define("enable", true);
|
||||
NOTES_MAX_AMOUNT_PER_MOD = builder
|
||||
.comment("The max amount of notes for a user per moderator.")
|
||||
.defineInRange("max_amount", Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
|
||||
builder.pop();
|
||||
}
|
||||
builder.pop();
|
||||
|
||||
spec = builder.build();
|
||||
|
||||
this.configPath = options.getConfigPath().orElse(DEFAULT_CONFIG_PATH);
|
||||
|
@ -88,16 +123,21 @@ public class BotConfigImpl implements BotConfig {
|
|||
} catch (IOException 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() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Path getTranslationsFile() {
|
||||
return options.getTranslationsFile().
|
||||
or(() -> CUSTOM_TRANSLATION_FILE.get().isBlank() ?
|
||||
Optional.empty() :
|
||||
Optional.of(Path.of(CUSTOM_TRANSLATION_FILE.get())))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Path getMessagesFolder() {
|
||||
return options.getMessagesFolder().
|
||||
|
@ -107,25 +147,16 @@ public class BotConfigImpl implements BotConfig {
|
|||
.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path getConfigsFolder() {
|
||||
return options.getConfigsFolder().
|
||||
orElseGet(() -> Path.of(CONFIGS_PATH.get()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToken() {
|
||||
return options.getToken().orElse(CLIENT_TOKEN.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandPrefix() {
|
||||
return options.getCommandPrefix().orElseGet(COMMAND_PREFIX::get);
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
return Optional.of(ret);
|
||||
}
|
|
@ -13,8 +13,8 @@ import static joptsimple.util.PathProperties.*;
|
|||
public class BotOptions {
|
||||
private final OptionSet options;
|
||||
private final ArgumentAcceptingOptionSpec<Path> configPath;
|
||||
private final ArgumentAcceptingOptionSpec<Path> translationsPath;
|
||||
private final ArgumentAcceptingOptionSpec<Path> messagesFolder;
|
||||
private final ArgumentAcceptingOptionSpec<Path> configsFolder;
|
||||
private final ArgumentAcceptingOptionSpec<String> token;
|
||||
private final ArgumentAcceptingOptionSpec<String> prefix;
|
||||
private final ArgumentAcceptingOptionSpec<Long> owner;
|
||||
|
@ -25,12 +25,12 @@ public class BotOptions {
|
|||
.accepts("config", "The path to the config file; defaults to 'config.toml'")
|
||||
.withRequiredArg()
|
||||
.withValuesConvertedBy(new PathConverter(FILE_EXISTING, READABLE, WRITABLE));
|
||||
this.messagesFolder = parser
|
||||
.accepts("messages", "The path to the custom messages folder")
|
||||
this.translationsPath = parser
|
||||
.accepts("translations", "The path to the translations file")
|
||||
.withRequiredArg()
|
||||
.withValuesConvertedBy(new PathConverter(DIRECTORY_EXISTING, READABLE));
|
||||
this.configsFolder = parser
|
||||
.accepts("guildConfigs", "The path to the guild configs folder")
|
||||
.withValuesConvertedBy(new PathConverter(FILE_EXISTING, READABLE));
|
||||
this.messagesFolder = parser
|
||||
.accepts("translations", "The path to the custom messages folder")
|
||||
.withRequiredArg()
|
||||
.withValuesConvertedBy(new PathConverter(DIRECTORY_EXISTING, READABLE));
|
||||
this.token = parser
|
||||
|
@ -50,12 +50,12 @@ public class BotOptions {
|
|||
return configPath.valueOptional(options);
|
||||
}
|
||||
|
||||
public Optional<Path> getMessagesFolder() {
|
||||
return messagesFolder.valueOptional(options);
|
||||
public Optional<Path> getTranslationsFile() {
|
||||
return translationsPath.valueOptional(options);
|
||||
}
|
||||
|
||||
public Optional<Path> getConfigsFolder() {
|
||||
return configsFolder.valueOptional(options);
|
||||
public Optional<Path> getMessagesFolder() {
|
||||
return messagesFolder.valueOptional(options);
|
||||
}
|
||||
|
||||
public Optional<String> getToken() {
|
|
@ -32,7 +32,7 @@ import com.google.common.base.Joiner;
|
|||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
import sciwhiz12.janitor.api.Logging;
|
||||
import sciwhiz12.janitor.Logging;
|
||||
import sciwhiz12.janitor.utils.Pair;
|
||||
|
||||
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.
|
||||
*
|
||||
* @author @MinecraftForge
|
||||
* @author SciWhiz12 (modified to remove unneeded parts)
|
||||
* @author SciWhiz12 (modified to remove unneede parts)
|
||||
*/
|
||||
//TODO: Remove extends and pipe everything through getSpec/getValues?
|
||||
public class CommentedConfigSpec extends UnmodifiableConfigWrapper<UnmodifiableConfig> {
|
101
src/main/java/sciwhiz12/janitor/moderation/notes/NoteEntry.java
Normal file
101
src/main/java/sciwhiz12/janitor/moderation/notes/NoteEntry.java
Normal file
|
@ -0,0 +1,101 @@
|
|||
package sciwhiz12.janitor.moderation.notes;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
public static class Serializer extends StdSerializer<NoteEntry> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public Serializer() {
|
||||
super(NoteEntry.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(NoteEntry value, JsonGenerator gen, SerializerProvider provider) throws IOException {
|
||||
gen.writeStartObject();
|
||||
gen.writeNumberField("performer", value.getPerformer().getIdLong());
|
||||
gen.writeNumberField("target", value.getTarget().getIdLong());
|
||||
gen.writeStringField("dateTime", value.getDateTime().toString());
|
||||
gen.writeStringField("contents", value.getContents());
|
||||
gen.writeEndObject();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Deserializer extends StdDeserializer<NoteEntry> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Supplier<JanitorBot> bot;
|
||||
|
||||
public Deserializer(Supplier<JanitorBot> bot) {
|
||||
super(NoteEntry.class);
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,23 +6,31 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import sciwhiz12.janitor.api.JanitorBot;
|
||||
import sciwhiz12.janitor.api.storage.JsonStorage;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
import sciwhiz12.janitor.storage.GuildStorage;
|
||||
import sciwhiz12.janitor.storage.JsonStorage;
|
||||
import sciwhiz12.janitor.storage.StorageKey;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class NoteStorageImpl extends JsonStorage implements NoteStorage {
|
||||
public class NoteStorage extends JsonStorage {
|
||||
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 int lastID = 1;
|
||||
private final Map<Integer, NoteEntry> notes = new ObservedMap<>(new HashMap<>(), this::markDirty);
|
||||
|
||||
public NoteStorageImpl(JanitorBot bot) {
|
||||
public NoteStorage(JanitorBot bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
|
@ -60,8 +68,8 @@ public class NoteStorageImpl extends JsonStorage implements NoteStorage {
|
|||
super.initialize(mapper);
|
||||
mapper.registerModule(
|
||||
new SimpleModule()
|
||||
.addSerializer(NoteEntry.class, new NoteEntrySerializer())
|
||||
.addDeserializer(NoteEntry.class, new NoteEntryDeserializer(this::getBot))
|
||||
.addSerializer(NoteEntry.class, new NoteEntry.Serializer())
|
||||
.addDeserializer(NoteEntry.class, new NoteEntry.Deserializer(this::getBot))
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
package sciwhiz12.janitor.moderation.warns;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
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 warned, User performer, 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());
|
||||
}
|
||||
|
||||
public static class Serializer extends StdSerializer<WarningEntry> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public Serializer() {
|
||||
super(WarningEntry.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(WarningEntry value, JsonGenerator gen, SerializerProvider provider) throws IOException {
|
||||
gen.writeStartObject();
|
||||
gen.writeNumberField("performer", value.getPerformer().getIdLong());
|
||||
gen.writeNumberField("warned", value.getWarned().getIdLong());
|
||||
gen.writeStringField("dateTime", value.getDateTime().toString());
|
||||
gen.writeStringField("reason", value.getReason());
|
||||
gen.writeEndObject();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Deserializer extends StdDeserializer<WarningEntry> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Supplier<JanitorBot> bot;
|
||||
|
||||
public Deserializer(Supplier<JanitorBot> bot) {
|
||||
super(WarningEntry.class);
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,21 +6,29 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import sciwhiz12.janitor.api.JanitorBot;
|
||||
import sciwhiz12.janitor.api.storage.JsonStorage;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
import sciwhiz12.janitor.storage.GuildStorage;
|
||||
import sciwhiz12.janitor.storage.JsonStorage;
|
||||
import sciwhiz12.janitor.storage.StorageKey;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class WarningStorageImpl extends JsonStorage implements WarningStorage {
|
||||
public class WarningStorage extends JsonStorage {
|
||||
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 int lastID = 1;
|
||||
private final Map<Integer, WarningEntry> warnings = new ObservedMap<>(new HashMap<>(), this::markDirty);
|
||||
|
||||
public WarningStorageImpl(JanitorBot bot) {
|
||||
public WarningStorage(JanitorBot bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
|
@ -52,8 +60,8 @@ public class WarningStorageImpl extends JsonStorage implements WarningStorage {
|
|||
super.initialize(mapper);
|
||||
mapper.registerModule(
|
||||
new SimpleModule()
|
||||
.addSerializer(WarningEntry.class, new WarningEntrySerializer())
|
||||
.addDeserializer(WarningEntry.class, new WarningEntryDeserializer(this::getBot))
|
||||
.addSerializer(WarningEntry.class, new WarningEntry.Serializer())
|
||||
.addDeserializer(WarningEntry.class, new WarningEntry.Deserializer(this::getBot))
|
||||
);
|
||||
}
|
||||
|
161
src/main/java/sciwhiz12/janitor/msg/ListingMessageBuilder.java
Normal file
161
src/main/java/sciwhiz12/janitor/msg/ListingMessageBuilder.java
Normal file
|
@ -0,0 +1,161 @@
|
|||
package sciwhiz12.janitor.msg;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
import sciwhiz12.janitor.msg.json.ListingMessage;
|
||||
import sciwhiz12.janitor.msg.substitution.CustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.IHasCustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.SubstitutionMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ListingMessageBuilder<T> implements IHasCustomSubstitutions<ListingMessageBuilder<T>> {
|
||||
private final ListingMessage message;
|
||||
private final Map<String, Supplier<String>> customSubstitutions;
|
||||
private int amountPerPage = 10;
|
||||
private BiConsumer<T, CustomSubstitutions> entryApplier = (entry, sub) -> {};
|
||||
|
||||
public ListingMessageBuilder(ListingMessage message, Map<String, Supplier<String>> customSubstitutions) {
|
||||
this.message = message;
|
||||
this.customSubstitutions = customSubstitutions;
|
||||
}
|
||||
|
||||
public ListingMessageBuilder(ListingMessage message) {
|
||||
this(message, new HashMap<>());
|
||||
}
|
||||
|
||||
public ListingMessageBuilder<T> amountPerPage(int amountPerPage) {
|
||||
this.amountPerPage = amountPerPage;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ListingMessageBuilder<T> setEntryApplier(BiConsumer<T, CustomSubstitutions> entryApplier) {
|
||||
this.entryApplier = entryApplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ListingMessageBuilder<T> apply(Consumer<ListingMessageBuilder<T>> consumer) {
|
||||
consumer.accept(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ListingMessageBuilder<T> with(final String argument, final Supplier<String> value) {
|
||||
this.customSubstitutions.put(argument, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void build(MessageChannel channel, TranslationMap translations, SubstitutionMap globalSubstitutions,
|
||||
Message triggerMessage, List<T> entries) {
|
||||
|
||||
final CustomSubstitutions customSubs = globalSubstitutions.with(customSubstitutions);
|
||||
final ImmutableList<T> list = ImmutableList.copyOf(entries);
|
||||
final PagedMessage pagedMessage = new PagedMessage(message, list, amountPerPage);
|
||||
|
||||
channel.sendMessage(pagedMessage.createMessage(translations, customSubs, entryApplier))
|
||||
.queue(listMsg -> translations.getBot().getReactionManager().newMessage(listMsg)
|
||||
.owner(triggerMessage.getAuthor().getIdLong())
|
||||
.removeEmotes(true)
|
||||
.add("\u2b05", (msg, event) -> { // PREVIOUS
|
||||
if (pagedMessage.advancePage(PageDirection.PREVIOUS)) {
|
||||
event.retrieveMessage()
|
||||
.flatMap(eventMsg -> eventMsg.editMessage(
|
||||
pagedMessage.createMessage(translations, customSubs, entryApplier))
|
||||
)
|
||||
.queue();
|
||||
}
|
||||
})
|
||||
.add("\u274c", (msg, event) -> { // CLOSE
|
||||
event.getChannel().deleteMessageById(event.getMessageIdLong())
|
||||
.flatMap(v -> !triggerMessage.isFromGuild() ||
|
||||
event.getGuild().getSelfMember()
|
||||
.hasPermission(triggerMessage.getTextChannel(),
|
||||
Permission.MESSAGE_MANAGE),
|
||||
v -> triggerMessage.delete())
|
||||
.queue();
|
||||
})
|
||||
.add("\u27a1", (msg, event) -> { // NEXT
|
||||
if (pagedMessage.advancePage(PageDirection.NEXT)) {
|
||||
event.retrieveMessage()
|
||||
.flatMap(eventMsg -> eventMsg.editMessage(
|
||||
pagedMessage.createMessage(translations, customSubs, entryApplier))
|
||||
)
|
||||
.queue();
|
||||
}
|
||||
})
|
||||
.create()
|
||||
);
|
||||
}
|
||||
|
||||
public void build(MessageChannel channel, JanitorBot bot, Message triggerMessage, List<T> entries) {
|
||||
build(channel, bot.getTranslations(), bot.getSubstitutions(), triggerMessage, entries);
|
||||
}
|
||||
|
||||
class PagedMessage {
|
||||
private final ListingMessage message;
|
||||
private final ImmutableList<T> list;
|
||||
private final int maxPages;
|
||||
private final int amountPerPage;
|
||||
private int currentPage = 0;
|
||||
private int lastPage = -1;
|
||||
private EmbedBuilder cachedMessage;
|
||||
|
||||
PagedMessage(ListingMessage message, ImmutableList<T> list, int amountPerPage) {
|
||||
this.message = message;
|
||||
this.list = list;
|
||||
this.amountPerPage = amountPerPage;
|
||||
this.maxPages = Math.floorDiv(list.size(), ListingMessageBuilder.this.amountPerPage);
|
||||
}
|
||||
|
||||
public int getMaxPages() {
|
||||
return maxPages;
|
||||
}
|
||||
|
||||
public int getCurrentPage() {
|
||||
return currentPage;
|
||||
}
|
||||
|
||||
public boolean advancePage(PageDirection direction) {
|
||||
if (direction == PageDirection.PREVIOUS && currentPage > 0) {
|
||||
currentPage -= 1;
|
||||
return true;
|
||||
} else if (direction == PageDirection.NEXT && currentPage < maxPages) {
|
||||
currentPage += 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public MessageEmbed createMessage(TranslationMap translations, CustomSubstitutions substitutions,
|
||||
BiConsumer<T, CustomSubstitutions> applier) {
|
||||
if (currentPage != lastPage) {
|
||||
cachedMessage = message.create(
|
||||
translations,
|
||||
substitutions.with(new HashMap<>())
|
||||
.with("page.max", () -> String.valueOf(maxPages + 1))
|
||||
.with("page.current", () -> String.valueOf(currentPage + 1)),
|
||||
list.stream()
|
||||
.skip(currentPage * amountPerPage)
|
||||
.limit(amountPerPage)
|
||||
.collect(Collectors.toList()),
|
||||
applier);
|
||||
lastPage = currentPage;
|
||||
}
|
||||
return cachedMessage.build();
|
||||
}
|
||||
}
|
||||
|
||||
enum PageDirection {
|
||||
PREVIOUS, NEXT
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package sciwhiz12.janitor.api.utils;
|
||||
package sciwhiz12.janitor.msg;
|
||||
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.IMentionable;
|
||||
|
@ -6,31 +6,32 @@ import net.dv8tion.jda.api.entities.ISnowflake;
|
|||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import sciwhiz12.janitor.api.messages.substitution.ModifiableSubstitutions;
|
||||
import sciwhiz12.janitor.moderation.notes.NoteEntry;
|
||||
import sciwhiz12.janitor.moderation.warns.WarningEntry;
|
||||
import sciwhiz12.janitor.msg.substitution.IHasCustomSubstitutions;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeFormatterBuilder;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static java.time.temporal.ChronoField.*;
|
||||
|
||||
public final class MessageHelper {
|
||||
public class MessageHelper {
|
||||
private MessageHelper() {}
|
||||
|
||||
public static <T extends ModifiableSubstitutions<?>> Consumer<T> snowflake(String head, ISnowflake snowflake) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> snowflake(String head, ISnowflake snowflake) {
|
||||
return builder -> builder
|
||||
.with(head + ".id", snowflake::getId)
|
||||
.with(head + ".creation_datetime", () -> snowflake.getTimeCreated().format(DATE_TIME_FORMAT));
|
||||
}
|
||||
|
||||
public static <T extends ModifiableSubstitutions<?>> Consumer<T> mentionable(String head, IMentionable mentionable) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> mentionable(String head, IMentionable mentionable) {
|
||||
return builder -> builder
|
||||
.apply(snowflake(head, mentionable))
|
||||
.with(head + ".mention", mentionable::getAsMention);
|
||||
}
|
||||
|
||||
public static <T extends ModifiableSubstitutions<?>> Consumer<T> role(String head, Role role) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> role(String head, Role role) {
|
||||
return builder -> builder
|
||||
.apply(mentionable(head, role))
|
||||
.with(head + ".color_hex", () -> Integer.toHexString(role.getColorRaw()))
|
||||
|
@ -38,7 +39,7 @@ public final class MessageHelper {
|
|||
.with(head + ".permissions", role.getPermissions()::toString);
|
||||
}
|
||||
|
||||
public static <T extends ModifiableSubstitutions<?>> Consumer<T> user(String head, User user) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> user(String head, User user) {
|
||||
return builder -> builder
|
||||
.apply(mentionable(head, user))
|
||||
.with(head + ".name", user::getName)
|
||||
|
@ -47,7 +48,7 @@ public final class MessageHelper {
|
|||
.with(head + ".flags", user.getFlags()::toString);
|
||||
}
|
||||
|
||||
public static <T extends ModifiableSubstitutions<?>> Consumer<T> guild(String head, Guild guild) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> guild(String head, Guild guild) {
|
||||
return builder -> builder
|
||||
.apply(snowflake(head, guild))
|
||||
.with(head + ".name", guild::getName)
|
||||
|
@ -57,10 +58,10 @@ public final class MessageHelper {
|
|||
.with(head + ".boost.count", () -> String.valueOf(guild.getBoostCount()))
|
||||
.with(head + ".locale", guild.getLocale()::toString)
|
||||
.with(head + ".verification_level", guild.getVerificationLevel()::toString)
|
||||
.with(head + ".icon_url", () -> Objects.toString(guild.getIconUrl(), ""));
|
||||
.with(head + ".icon_url", guild::getIconUrl);
|
||||
}
|
||||
|
||||
public static <T extends ModifiableSubstitutions<?>> Consumer<T> member(String head, Member member) {
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> member(String head, Member member) {
|
||||
return builder -> builder
|
||||
.apply(user(head, member.getUser()))
|
||||
.apply(guild(head + ".guild", member.getGuild()))
|
||||
|
@ -70,6 +71,24 @@ public final class MessageHelper {
|
|||
.with(head + ".color", () -> String.valueOf(member.getColorRaw()));
|
||||
}
|
||||
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> warningEntry(String head, int caseID, WarningEntry entry) {
|
||||
return builder -> builder
|
||||
.with(head + ".case_id", () -> String.valueOf(caseID))
|
||||
.apply(user(head + ".performer", entry.getPerformer()))
|
||||
.apply(user(head + ".target", entry.getWarned()))
|
||||
.with(head + ".date_time", () -> entry.getDateTime().format(DATE_TIME_FORMAT))
|
||||
.with(head + ".reason", entry::getReason);
|
||||
}
|
||||
|
||||
public static <T extends IHasCustomSubstitutions<?>> Consumer<T> noteEntry(String head, int noteID, NoteEntry entry) {
|
||||
return builder -> builder
|
||||
.with(head + ".note_id", () -> String.valueOf(noteID))
|
||||
.apply(user(head + ".performer", entry.getPerformer()))
|
||||
.apply(user(head + ".target", entry.getTarget()))
|
||||
.with(head + ".date_time", () -> entry.getDateTime().format(DATE_TIME_FORMAT))
|
||||
.with(head + ".contents", entry::getContents);
|
||||
}
|
||||
|
||||
public static final DateTimeFormatter DATE_TIME_FORMAT = new DateTimeFormatterBuilder()
|
||||
.parseCaseInsensitive()
|
||||
.parseLenient()
|
161
src/main/java/sciwhiz12/janitor/msg/Messages.java
Normal file
161
src/main/java/sciwhiz12/janitor/msg/Messages.java
Normal file
|
@ -0,0 +1,161 @@
|
|||
package sciwhiz12.janitor.msg;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
import sciwhiz12.janitor.msg.json.ListingMessage;
|
||||
import sciwhiz12.janitor.msg.json.RegularMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.io.Resources.getResource;
|
||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.Logging.MESSAGES;
|
||||
|
||||
public class Messages {
|
||||
public static final String JSON_FILE_SUFFIX = ".json";
|
||||
public static final String MESSAGES_FILENAME = "messages";
|
||||
public static final String DEFAULT_MESSAGES_FOLDER = "messages/";
|
||||
public static final TypeReference<List<String>> LIST_TYPE = new TypeReference<>() {};
|
||||
|
||||
private final JanitorBot bot;
|
||||
private final Path messagesFolder;
|
||||
private final Map<String, RegularMessage> regularMessages = new HashMap<>();
|
||||
private final Map<String, ListingMessage> listingMessages = new HashMap<>();
|
||||
private final ObjectMapper jsonMapper = new ObjectMapper();
|
||||
|
||||
public Messages(JanitorBot bot, Path messagesFolder) {
|
||||
this.bot = bot;
|
||||
this.messagesFolder = messagesFolder;
|
||||
loadMessages();
|
||||
}
|
||||
|
||||
public JanitorBot getBot() {
|
||||
return bot;
|
||||
}
|
||||
|
||||
public void loadMessages() {
|
||||
boolean success = false;
|
||||
|
||||
if (messagesFolder != null) {
|
||||
JANITOR.debug(MESSAGES, "Loading messages from folder {}", messagesFolder);
|
||||
success = loadMessages(
|
||||
path -> Files.newBufferedReader(messagesFolder.resolve(path + JSON_FILE_SUFFIX))
|
||||
);
|
||||
} else {
|
||||
JANITOR.info(MESSAGES, "No custom messages folder specified");
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
JANITOR.info(MESSAGES, "Loading default messages");
|
||||
//noinspection UnstableApiUsage
|
||||
loadMessages(
|
||||
file -> new InputStreamReader(getResource(DEFAULT_MESSAGES_FOLDER + file + JSON_FILE_SUFFIX).openStream())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
boolean loadMessages(FileOpener files) {
|
||||
try (Reader keyReader = files.open(MESSAGES_FILENAME)) {
|
||||
List<String> keysList = jsonMapper.readValue(keyReader, LIST_TYPE);
|
||||
regularMessages.clear();
|
||||
for (String messageKey : keysList) {
|
||||
final String path = messageKey.replace("/", FileSystems.getDefault().getSeparator());
|
||||
try (Reader reader = files.open(path)) {
|
||||
final JsonNode tree = jsonMapper.readTree(reader);
|
||||
final String type = tree.path("type").asText("regular");
|
||||
if ("regular".equals(type)) {
|
||||
regularMessages.put(messageKey, jsonMapper.convertValue(tree, RegularMessage.class));
|
||||
} else if ("listing".equals(type)) {
|
||||
listingMessages.put(messageKey, jsonMapper.convertValue(tree, ListingMessage.class));
|
||||
} else {
|
||||
JANITOR.warn(MESSAGES, "Unknown message type {} for {}", tree.path("type").asText(), messageKey);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
JANITOR.error(MESSAGES, "Error while loading message {}", path, e);
|
||||
}
|
||||
}
|
||||
JANITOR.info(MESSAGES, "Loaded {} messages", regularMessages.size());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
JANITOR.error(MESSAGES, "Error while loading messages", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, RegularMessage> getRegularMessages() {
|
||||
return Collections.unmodifiableMap(regularMessages);
|
||||
}
|
||||
|
||||
public RegularMessageBuilder getRegularMessage(String messageKey) {
|
||||
final RegularMessage msg = regularMessages.get(messageKey);
|
||||
if (msg == null) {
|
||||
JANITOR.warn(MESSAGES, "Attempted to get unknown regular message with key {}", messageKey);
|
||||
return new RegularMessageBuilder(UNKNOWN_REGULAR_MESSAGE).with("key", () -> messageKey);
|
||||
}
|
||||
return new RegularMessageBuilder(msg);
|
||||
}
|
||||
|
||||
public Map<String, ListingMessage> getListingMessages() {
|
||||
return listingMessages;
|
||||
}
|
||||
|
||||
public <T> ListingMessageBuilder<T> getListingMessage(String messageKey) {
|
||||
final ListingMessage msg = listingMessages.get(messageKey);
|
||||
if (msg == null) {
|
||||
JANITOR.warn(MESSAGES, "Attempted to get unknown listing message with key {}", messageKey);
|
||||
return new ListingMessageBuilder<T>(UNKNOWN_LISTING_MESSAGE).with("key", () -> messageKey);
|
||||
}
|
||||
return new ListingMessageBuilder<>(msg);
|
||||
}
|
||||
|
||||
interface FileOpener {
|
||||
Reader open(String filePath) throws IOException;
|
||||
}
|
||||
|
||||
public static final RegularMessage UNKNOWN_REGULAR_MESSAGE = new RegularMessage(
|
||||
"UNKNOWN MESSAGE!",
|
||||
null,
|
||||
"A regular message was tried to be looked up, but was not found. Please report this to your bot " +
|
||||
"maintainer/administrator.",
|
||||
String.valueOf(0xFF0000),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
Collections.singletonList(new MessageEmbed.Field("Message Key", "${key}", false))
|
||||
);
|
||||
|
||||
public static final ListingMessage UNKNOWN_LISTING_MESSAGE = new ListingMessage(
|
||||
"UNKNOWN MESSAGE!",
|
||||
null,
|
||||
"A listing message was tried to be looked up, but was not found. " +
|
||||
"Please report this to your bot maintainer/administrator.",
|
||||
String.valueOf(0xFF0000),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new ListingMessage.DescriptionEntry(null, ""),
|
||||
Collections.singletonList(new MessageEmbed.Field("Message Key", "${key}", false)),
|
||||
Collections.emptyList()
|
||||
);
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package sciwhiz12.janitor.msg;
|
||||
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.requests.restaction.MessageAction;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
import sciwhiz12.janitor.msg.json.RegularMessage;
|
||||
import sciwhiz12.janitor.msg.substitution.IHasCustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.SubstitutionMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class RegularMessageBuilder implements IHasCustomSubstitutions<RegularMessageBuilder> {
|
||||
private final RegularMessage message;
|
||||
private final Map<String, Supplier<String>> customSubstitutions;
|
||||
|
||||
public RegularMessageBuilder(RegularMessage message, Map<String, Supplier<String>> customSubstitutions) {
|
||||
this.message = message;
|
||||
this.customSubstitutions = customSubstitutions;
|
||||
}
|
||||
|
||||
public RegularMessageBuilder(RegularMessage message) {
|
||||
this(message, new HashMap<>());
|
||||
}
|
||||
|
||||
public RegularMessageBuilder(RegularMessageBuilder copy) {
|
||||
this(copy.message, new HashMap<>(copy.customSubstitutions));
|
||||
}
|
||||
|
||||
public RegularMessageBuilder apply(Consumer<RegularMessageBuilder> consumer) {
|
||||
consumer.accept(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegularMessageBuilder with(final String argument, final Supplier<String> value) {
|
||||
customSubstitutions.put(argument, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MessageEmbed build(TranslationMap translations, SubstitutionMap substitutions) {
|
||||
return message.create(translations, substitutions.with(customSubstitutions)).build();
|
||||
}
|
||||
|
||||
public MessageEmbed build(JanitorBot bot) {
|
||||
return build(bot.getTranslations(), bot.getSubstitutions());
|
||||
}
|
||||
|
||||
public MessageAction send(JanitorBot bot, MessageChannel channel) {
|
||||
return channel.sendMessage(build(bot));
|
||||
}
|
||||
}
|
84
src/main/java/sciwhiz12/janitor/msg/TranslationMap.java
Normal file
84
src/main/java/sciwhiz12/janitor/msg/TranslationMap.java
Normal file
|
@ -0,0 +1,84 @@
|
|||
package sciwhiz12.janitor.msg;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.io.Resources;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static java.util.regex.Matcher.quoteReplacement;
|
||||
import static java.util.regex.Pattern.CASE_INSENSITIVE;
|
||||
import static sciwhiz12.janitor.Logging.JANITOR;
|
||||
import static sciwhiz12.janitor.Logging.TRANSLATIONS;
|
||||
|
||||
public class TranslationMap {
|
||||
public static final Pattern TRANSLATION_REGEX = Pattern.compile("<(.+?)>", CASE_INSENSITIVE);
|
||||
private static final String DEFAULT_TRANSLATIONS_RESOURCE = "english.json";
|
||||
private static final TypeReference<Map<String, String>> MAP_TYPE = new TypeReference<>() {};
|
||||
|
||||
private final JanitorBot bot;
|
||||
private final Path translationsFile;
|
||||
private final Map<String, String> translations = new HashMap<>();
|
||||
private final ObjectMapper jsonMapper = new ObjectMapper();
|
||||
|
||||
public TranslationMap(JanitorBot bot, Path translationsFile) {
|
||||
this.bot = bot;
|
||||
this.translationsFile = translationsFile;
|
||||
loadTranslations();
|
||||
}
|
||||
|
||||
public void loadTranslations() {
|
||||
if (translationsFile == null) {
|
||||
JANITOR.info(TRANSLATIONS, "No translation file given, using default english translations");
|
||||
loadDefaultTranslations();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
JANITOR.debug(TRANSLATIONS, "Loading translations from file {}", translationsFile);
|
||||
Map<String, String> trans = jsonMapper.readValue(Files.newBufferedReader(translationsFile), MAP_TYPE);
|
||||
translations.clear();
|
||||
translations.putAll(trans);
|
||||
JANITOR.info(TRANSLATIONS, "Loaded {} translations from file {}", translations.size(), translationsFile);
|
||||
} catch (Exception e) {
|
||||
JANITOR.error(TRANSLATIONS, "Error while loading translations from file {}", translationsFile, e);
|
||||
loadDefaultTranslations();
|
||||
}
|
||||
}
|
||||
|
||||
void loadDefaultTranslations() {
|
||||
try {
|
||||
JANITOR.debug(TRANSLATIONS, "Loading default english translations");
|
||||
// noinspection UnstableApiUsage
|
||||
Map<String, String> trans = jsonMapper.readValue(
|
||||
new InputStreamReader(Resources.getResource(DEFAULT_TRANSLATIONS_RESOURCE).openStream()),
|
||||
MAP_TYPE);
|
||||
translations.clear();
|
||||
translations.putAll(trans);
|
||||
JANITOR.info(TRANSLATIONS, "Loaded {} default english translations", translations.size());
|
||||
} catch (Exception e) {
|
||||
JANITOR.error(TRANSLATIONS, "Error while loading default english translations", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> getTranslationMap() {
|
||||
return Collections.unmodifiableMap(translations);
|
||||
}
|
||||
|
||||
public String translate(String text) {
|
||||
final Matcher matcher = TRANSLATION_REGEX.matcher(text);
|
||||
return matcher.replaceAll(
|
||||
matchResult -> quoteReplacement(translations.getOrDefault(matchResult.group(1), matchResult.group(0))));
|
||||
}
|
||||
|
||||
public JanitorBot getBot() {
|
||||
return bot;
|
||||
}
|
||||
}
|
|
@ -1,29 +1,27 @@
|
|||
package sciwhiz12.janitor.messages.emote;
|
||||
package sciwhiz12.janitor.msg.emote;
|
||||
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.events.message.MessageDeleteEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
import sciwhiz12.janitor.JanitorBotImpl;
|
||||
import sciwhiz12.janitor.api.messages.emote.ReactionManager;
|
||||
import sciwhiz12.janitor.api.messages.emote.ReactionMessage;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ReactionManagerImpl extends ListenerAdapter implements ReactionManager {
|
||||
private final JanitorBotImpl bot;
|
||||
public class ReactionManager extends ListenerAdapter {
|
||||
private final JanitorBot bot;
|
||||
private final Map<Long, ReactionMessage> messageMap = new HashMap<>();
|
||||
|
||||
public ReactionManagerImpl(JanitorBotImpl bot) {
|
||||
public ReactionManager(JanitorBot bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
public ReactionMessageImpl newMessage(Message message) {
|
||||
public ReactionMessage newMessage(Message message) {
|
||||
if (messageMap.containsKey(message.getIdLong())) {
|
||||
throw new IllegalArgumentException("Reaction message already exists for message with id " + message.getIdLong());
|
||||
}
|
||||
final ReactionMessageImpl msg = new ReactionMessageImpl(bot, message);
|
||||
final ReactionMessage msg = new ReactionMessage(bot, message);
|
||||
messageMap.put(message.getIdLong(), msg);
|
||||
return msg;
|
||||
}
|
||||
|
@ -36,11 +34,6 @@ public class ReactionManagerImpl extends ListenerAdapter implements ReactionMana
|
|||
return messageMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JanitorBotImpl getBot() {
|
||||
return bot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageDelete(@Nonnull MessageDeleteEvent event) {
|
||||
if (messageMap.containsKey(event.getMessageIdLong())) {
|
|
@ -1,4 +1,4 @@
|
|||
package sciwhiz12.janitor.messages.emote;
|
||||
package sciwhiz12.janitor.msg.emote;
|
||||
|
||||
import net.dv8tion.jda.api.entities.Emote;
|
||||
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.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.api.requests.ErrorResponse;
|
||||
import sciwhiz12.janitor.JanitorBotImpl;
|
||||
import sciwhiz12.janitor.api.messages.emote.ReactionMessage;
|
||||
import sciwhiz12.janitor.JanitorBot;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static net.dv8tion.jda.api.Permission.MESSAGE_MANAGE;
|
||||
|
||||
public class ReactionMessageImpl extends ListenerAdapter implements ReactionMessage {
|
||||
private final JanitorBotImpl bot;
|
||||
public class ReactionMessage extends ListenerAdapter {
|
||||
private final JanitorBot bot;
|
||||
private final Message message;
|
||||
private final Map<ReactionEmote, ReactionListener> emotes = new LinkedHashMap<>();
|
||||
private final Map<ReactionEmote, IReactionListener> emotes = new LinkedHashMap<>();
|
||||
private boolean removeEmotes = true;
|
||||
private long ownerID;
|
||||
private boolean onlyOwner;
|
||||
|
||||
public ReactionMessageImpl(JanitorBotImpl bot, Message message, boolean onlyOwner, long ownerID) {
|
||||
public ReactionMessage(JanitorBot bot, Message message, boolean onlyOwner, long ownerID) {
|
||||
this.bot = bot;
|
||||
this.message = message;
|
||||
this.ownerID = ownerID;
|
||||
this.onlyOwner = onlyOwner;
|
||||
}
|
||||
|
||||
public ReactionMessageImpl(JanitorBotImpl bot, Message message) {
|
||||
public ReactionMessage(JanitorBot bot, Message message) {
|
||||
this(bot, message, false, 0);
|
||||
}
|
||||
|
||||
public ReactionMessageImpl add(ReactionEmote emote, ReactionListener listener) {
|
||||
public ReactionMessage add(ReactionEmote emote, IReactionListener listener) {
|
||||
emotes.put(emote, listener);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReactionMessageImpl add(String emote, ReactionListener listener) {
|
||||
public ReactionMessage add(String emote, IReactionListener listener) {
|
||||
return add(ReactionEmote.fromUnicode(emote, bot.getDiscord()), listener);
|
||||
}
|
||||
|
||||
public ReactionMessageImpl add(Emote emote, ReactionListener listener) {
|
||||
public ReactionMessage add(Emote emote, IReactionListener listener) {
|
||||
return add(ReactionEmote.fromCustom(emote), listener);
|
||||
}
|
||||
|
||||
public ReactionMessageImpl removeEmotes(boolean remove) {
|
||||
public ReactionMessage removeEmotes(boolean remove) {
|
||||
this.removeEmotes = remove;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReactionMessageImpl owner(long ownerID) {
|
||||
public ReactionMessage owner(long ownerID) {
|
||||
this.ownerID = ownerID;
|
||||
this.onlyOwner = true;
|
||||
return this;
|
||||
|
@ -89,7 +89,7 @@ public class ReactionMessageImpl extends ListenerAdapter implements ReactionMess
|
|||
}
|
||||
}
|
||||
|
||||
public JanitorBotImpl getBot() {
|
||||
public JanitorBot getBot() {
|
||||
return bot;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,12 @@ public class ReactionMessageImpl extends ListenerAdapter implements ReactionMess
|
|||
return onlyOwner;
|
||||
}
|
||||
|
||||
public Map<ReactionEmote, ReactionListener> getListeners() {
|
||||
public Map<ReactionEmote, IReactionListener> getListeners() {
|
||||
return Collections.unmodifiableMap(emotes);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface IReactionListener extends BiConsumer<ReactionMessage, MessageReactionAddEvent> {
|
||||
void accept(ReactionMessage message, MessageReactionAddEvent event);
|
||||
}
|
||||
}
|
|
@ -1,19 +1,23 @@
|
|||
package sciwhiz12.janitor.api.messages;
|
||||
package sciwhiz12.janitor.msg.json;
|
||||
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.google.common.primitives.Ints;
|
||||
import joptsimple.internal.Strings;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import sciwhiz12.janitor.api.JanitorBot;
|
||||
import sciwhiz12.janitor.api.messages.substitution.ModifiableSubstitutions;
|
||||
import sciwhiz12.janitor.api.messages.substitution.ModifiableSubstitutor;
|
||||
import sciwhiz12.janitor.api.messages.substitution.SubstitutionsMap;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import sciwhiz12.janitor.msg.TranslationMap;
|
||||
import sciwhiz12.janitor.msg.substitution.CustomSubstitutions;
|
||||
import sciwhiz12.janitor.msg.substitution.ISubstitutor;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@JsonDeserialize(using = ListingMessageDeserializer.class)
|
||||
public class ListingMessage {
|
||||
@Nullable protected final String title;
|
||||
@Nullable protected final String url;
|
||||
|
@ -137,6 +141,72 @@ public class ListingMessage {
|
|||
return afterFields;
|
||||
}
|
||||
|
||||
public <T> EmbedBuilder create(
|
||||
TranslationMap translations,
|
||||
ISubstitutor global,
|
||||
Iterable<T> iterable,
|
||||
BiConsumer<T, CustomSubstitutions> entryApplier
|
||||
) {
|
||||
final Function<String, String> func = str -> str != null ? global.substitute(translations.translate(str)) : null;
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.setTitle(func.apply(title), func.apply(url));
|
||||
builder.setColor(parseColor(global.substitute(color)));
|
||||
builder.setAuthor(func.apply(authorName), func.apply(authorUrl), func.apply(authorIconUrl));
|
||||
builder.setDescription(func.apply(description));
|
||||
builder.setImage(func.apply(imageUrl));
|
||||
builder.setThumbnail(func.apply(thumbnailUrl));
|
||||
builder.setTimestamp(OffsetDateTime.now(ZoneOffset.UTC));
|
||||
builder.setFooter(func.apply(footerText), func.apply(footerIconUrl));
|
||||
for (MessageEmbed.Field field : beforeFields) {
|
||||
builder.addField(func.apply(field.getName()), func.apply(field.getValue()), field.isInline());
|
||||
}
|
||||
|
||||
final CustomSubstitutions entrySubs = new CustomSubstitutions();
|
||||
final Function<String, String> entryFunc = str -> str != null ? entrySubs.substitute(func.apply(str)) : null;
|
||||
int count = 0;
|
||||
for (T listEntry : iterable) {
|
||||
entryApplier.accept(listEntry, entrySubs);
|
||||
if (entry instanceof FieldEntry) {
|
||||
FieldEntry fieldEntry = (FieldEntry) entry;
|
||||
builder.addField(
|
||||
entryFunc.apply(fieldEntry.getFieldName()),
|
||||
entryFunc.apply(fieldEntry.getFieldValue()),
|
||||
fieldEntry.isInline()
|
||||
);
|
||||
} else if (entry instanceof DescriptionEntry) {
|
||||
DescriptionEntry descEntry = (DescriptionEntry) entry;
|
||||
builder.getDescriptionBuilder().append(entryFunc.apply(descEntry.getDescription()));
|
||||
builder.getDescriptionBuilder().append(descEntry.getJoiner());
|
||||
}
|
||||
count++;
|
||||
}
|
||||
if (count < 1) {
|
||||
builder.getDescriptionBuilder().append(func.apply(emptyText));
|
||||
}
|
||||
|
||||
for (MessageEmbed.Field field : afterFields) {
|
||||
builder.addField(func.apply(field.getName()), func.apply(field.getValue()), field.isInline());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static int parseColor(String str) {
|
||||
if (Strings.isNullOrEmpty(str)) return Role.DEFAULT_COLOR_RAW;
|
||||
if (str.startsWith("0x")) {
|
||||
// noinspection UnstableApiUsage
|
||||
final Integer res = Ints.tryParse(str.substring(2), 16);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
// noinspection UnstableApiUsage
|
||||
final Integer res = Ints.tryParse(str, 10);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
return Role.DEFAULT_COLOR_RAW;
|
||||
}
|
||||
|
||||
public interface Entry {}
|
||||
|
||||
public static class DescriptionEntry implements Entry {
|
||||
|
@ -181,23 +251,4 @@ public class ListingMessage {
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package sciwhiz12.janitor.messages.json;
|
||||
package sciwhiz12.janitor.msg.json;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
|
@ -6,7 +6,6 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import sciwhiz12.janitor.api.messages.ListingMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
|
@ -1,31 +1,48 @@
|
|||
package sciwhiz12.janitor.api.messages;
|
||||
package sciwhiz12.janitor.msg.json;
|
||||
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.google.common.primitives.Ints;
|
||||
import joptsimple.internal.Strings;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.requests.restaction.MessageAction;
|
||||
import sciwhiz12.janitor.api.JanitorBot;
|
||||
import sciwhiz12.janitor.api.messages.substitution.ModifiableSubstitutions;
|
||||
import sciwhiz12.janitor.api.messages.substitution.SubstitutionsMap;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import sciwhiz12.janitor.msg.TranslationMap;
|
||||
import sciwhiz12.janitor.msg.substitution.ISubstitutor;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.function.Function;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@JsonDeserialize(using = RegularMessageDeserializer.class)
|
||||
public class RegularMessage {
|
||||
@Nullable protected final String title;
|
||||
@Nullable protected final String url;
|
||||
@Nullable protected final String description;
|
||||
@Nullable protected final String color;
|
||||
@Nullable protected final String authorName;
|
||||
@Nullable protected final String authorUrl;
|
||||
@Nullable protected final String authorIconUrl;
|
||||
@Nullable protected final String footerText;
|
||||
@Nullable protected final String footerIconUrl;
|
||||
@Nullable protected final String imageUrl;
|
||||
@Nullable protected final String thumbnailUrl;
|
||||
@Nullable
|
||||
protected final String title;
|
||||
@Nullable
|
||||
protected final String url;
|
||||
@Nullable
|
||||
protected final String description;
|
||||
@Nullable
|
||||
protected final String color;
|
||||
@Nullable
|
||||
protected final String authorName;
|
||||
@Nullable
|
||||
protected final String authorUrl;
|
||||
@Nullable
|
||||
protected final String authorIconUrl;
|
||||
@Nullable
|
||||
protected final String footerText;
|
||||
@Nullable
|
||||
protected final String footerIconUrl;
|
||||
@Nullable
|
||||
protected final String imageUrl;
|
||||
@Nullable
|
||||
protected final String thumbnailUrl;
|
||||
protected final List<MessageEmbed.Field> fields;
|
||||
|
||||
public RegularMessage(
|
||||
|
@ -159,14 +176,37 @@ public class RegularMessage {
|
|||
thumbnailUrl, fields);
|
||||
}
|
||||
|
||||
public interface Builder<T extends Builder<?>> extends ModifiableSubstitutions<T> {
|
||||
MessageEmbed build(SubstitutionsMap substitutions);
|
||||
|
||||
MessageEmbed build(JanitorBot bot);
|
||||
|
||||
default MessageAction send(JanitorBot bot, MessageChannel channel) {
|
||||
return channel.sendMessage(build(bot));
|
||||
public EmbedBuilder create(TranslationMap translations, ISubstitutor substitutions) {
|
||||
final Function<String, String> func = str -> str != null ? substitutions.substitute(translations.translate(str)) : null;
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.setTitle(func.apply(title), func.apply(url));
|
||||
builder.setColor(parseColor(substitutions.substitute(color)));
|
||||
builder.setAuthor(func.apply(authorName), func.apply(authorUrl), func.apply(authorIconUrl));
|
||||
builder.setDescription(func.apply(description));
|
||||
builder.setImage(func.apply(imageUrl));
|
||||
builder.setThumbnail(func.apply(thumbnailUrl));
|
||||
builder.setTimestamp(OffsetDateTime.now(ZoneOffset.UTC));
|
||||
builder.setFooter(func.apply(footerText), func.apply(footerIconUrl));
|
||||
for (MessageEmbed.Field field : fields) {
|
||||
builder.addField(func.apply(field.getName()), func.apply(field.getValue()), field.isInline());
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static int parseColor(String str) {
|
||||
if (Strings.isNullOrEmpty(str)) return Role.DEFAULT_COLOR_RAW;
|
||||
if (str.startsWith("0x")) {
|
||||
// noinspection UnstableApiUsage
|
||||
final Integer res = Ints.tryParse(str.substring(2), 16);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
// noinspection UnstableApiUsage
|
||||
final Integer res = Ints.tryParse(str, 10);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
return Role.DEFAULT_COLOR_RAW;
|
||||
}
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
package sciwhiz12.janitor.messages.json;
|
||||
package sciwhiz12.janitor.msg.json;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import sciwhiz12.janitor.api.messages.RegularMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
|
@ -1,17 +1,14 @@
|
|||
package sciwhiz12.janitor.messages.substitution;
|
||||
package sciwhiz12.janitor.msg.substitution;
|
||||
|
||||
import org.apache.commons.collections4.TransformerUtils;
|
||||
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.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class CustomSubstitutions implements ModifiableSubstitutor<CustomSubstitutions> {
|
||||
public class CustomSubstitutions implements ISubstitutor, IHasCustomSubstitutions<CustomSubstitutions> {
|
||||
private final Map<String, Supplier<String>> map;
|
||||
|
||||
public CustomSubstitutions(Map<String, Supplier<String>> map) {
|
||||
|
@ -23,9 +20,8 @@ public class CustomSubstitutions implements ModifiableSubstitutor<CustomSubstitu
|
|||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String substitute(@Nullable String text) {
|
||||
return SubstitutionsMap.substitute(text, map);
|
||||
public String substitute(String text) {
|
||||
return SubstitutionMap.substitute(text, map);
|
||||
}
|
||||
|
||||
public CustomSubstitutions apply(Consumer<CustomSubstitutions> consumer) {
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user