From 2e4ead9992120038a2bb258d1963a14e47c69dd0 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 29 Dec 2019 12:49:26 +0000 Subject: [PATCH 001/206] Created the base enum for modlog actions https://hasteb.in/ijutejib --- .../cascadebot/moderation/ModlogEvent.java | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java b/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java new file mode 100644 index 000000000..60ddb330d --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java @@ -0,0 +1,166 @@ +package org.cascadebot.cascadebot.moderation; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public enum ModlogEvent { + + EMOTE_CREATED(Category.EMOTE), + EMOTE_DELETED(Category.EMOTE), + EMOTE_UPDATED_NAME(Category.EMOTE), + EMOTE_UPDATED_ROLES(Category.EMOTE), + + GUILD_MEMBER_JOINED(Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_LEFT(Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_KICKED(Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + GUILD_MEMBER_BANNED(Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + GUILD_MEMBER_ROLE_ADDED(Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_NICKNAME_UPDATED(Category.GUILD, Category.GUILD_MEMBER), + GUILD_USER_UNBANNED(Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + +// GUILD_MESSAGE_DELETED(Category.GUILD, Category.GUILD_MESSAGE), +// GUILD_MESSAGE_UPDATED(Category.GUILD, Category.GUILD_MESSAGE), + + GUILD_BOOST_COUNT_UPDATED(Category.GUILD, Category.GUILD_BOOST), + GUILD_BOOST_TIER_UPDATED(Category.GUILD, Category.GUILD_BOOST), + + GUILD_UPDATE_AFK_CHANNEL(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_AFK_TIMEOUT(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_BANNER(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_DESCRIPTION(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_EXPLICIT_FILTER(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_FEATURES(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_ICON(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_MAX_MEMBERS(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_MAX_PRESENCES(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_MFA_LEVEL(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_NAME(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_NOTIFICATION_LEVEL(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_REGION(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_SPLASH(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_SYSTEM_CHANNEL(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_VANITY_CODE(Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_VERIFICATION_LEVEL(Category.GUILD, Category.GUILD_SETTINGS), + + VOICE_DEAFEN(Category.VOICE), + VOICE_MUTE(Category.VOICE), + VOICE_SERVER_DEAFEN(Category.VOICE, Category.MODERATION), + VOICE_SERVER_MUTE(Category.VOICE, Category.MODERATION), + VOICE_JOIN(Category.VOICE), + VOICE_LEAVE(Category.VOICE), + VOICE_MOVE(Category.VOICE), + VOICE_DISCONNECT(Category.VOICE, Category.MODERATION), + + ROLE_CREATED(Category.ROLE), + ROLE_DELETED(Category.ROLE), + ROLE_COLOR_UPDATED(Category.ROLE), + ROLE_HOIST_UPDATED(Category.ROLE), + ROLE_MENTIONABLE_UPDATED(Category.ROLE), + ROLE_NAME_UPDATED(Category.ROLE), + ROLE_PERMISSIONS_UPDATED(Category.ROLE), + ROLE_POSITION_UPDATED(Category.ROLE), + + USER_DISCRIMINATOR_UPDATED(Category.USER), + USER_NAME_UPDATED(Category.USER), + + CHANNEL_CREATED(Category.CHANNEL), + CHANNEL_DELETED(Category.CHANNEL), + CHANNEL_NAME_UPDATED(Category.CHANNEL), + CHANNEL_PERMISSIONS_UPDATED(Category.CHANNEL), + CHANNEL_POSITION_UPDATED(Category.CHANNEL), + CHANNEL_PARENT_UPDATED(Category.CHANNEL), + + VOICE_CHANNEL_BITRATE_UPDATED(Category.CHANNEL), + VOICE_CHANNEL_USER_LIMIT_UPDATED(Category.CHANNEL), + + TEXT_CHANNEL_NSFW_UPDATED(Category.CHANNEL), + TEXT_CHANNEL_SLOWMODE_UPDATED(Category.CHANNEL), + TEXT_CHANNEL_TOPIC_UPDATED(Category.CHANNEL), + + CASCADE_PERMISSIONS_GROUP_CREATED(Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_DELETED(Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD(Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE(Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_LINK(Category.CASCADE, Category.CASCADE_PERMISSIONS), + + CASCADE_PERMISSIONS_USER_PERMISSION_ADD(Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE(Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_USER_GROUP_ADD(Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_USER_GROUP_REMOVE(Category.CASCADE, Category.CASCADE_PERMISSIONS), + + CASCADE_SETTINGS_UPDATED(Category.CASCADE), + + CASCADE_MODULE_UPDATED(Category.CASCADE), + + CASCADE_COMMAND_RUN(Category.CASCADE), + CASCADE_COMMAND_RUN_ERROR(Category.CASCADE), + + CASCADE_PLAYLIST_CREATED(Category.CASCADE), + CASCADE_PLAYLIST_DELETED(Category.CASCADE), + + CASCADE_TEMP_MUTE(Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_TEMP_BAN(Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_SOFT_BAN(Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_PURGE(Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + + CASCADE_WHITELIST(Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_BLACKLIST(Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + + CASCADE_SCRIPT_CREATED(Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_SCRIPT_DELETED(Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_SCRIPT_UPDATED(Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + + CASCADE_TAG_CREATED(Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_TAG_DELETED(Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_TAG_UPDATED(Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS); + + @Getter + private static Map> modlogCategoryMap = new HashMap<>(); + + static { + modlogCategoryMap.put(Category.ALL, Arrays.asList(ModlogEvent.values())); + for (ModlogEvent event : ModlogEvent.values()) { + for (Category category : event.getCategories()) { + if (modlogCategoryMap.containsKey(category)) { + modlogCategoryMap.get(category).add(event); + } else { + modlogCategoryMap.put(category, new ArrayList<>(Set.of(event))); + } + } + } + } + + @Getter + private final List categories; + + ModlogEvent(Category... categories) { + this.categories = Arrays.asList(categories); + } + + public enum Category { + ALL, + MODERATION, + EMOTE, + GUILD, + GUILD_MEMBER, + GUILD_MESSAGE, + GUILD_BOOST, + GUILD_SETTINGS, + VOICE, + ROLE, + USER, + CHANNEL, + CASCADE, + CASCADE_PERMISSIONS, + CASCADE_MODERATION, + CASCADE_CUSTOM_COMMANDS + } + + +} From d79ded488bb67ea2ece5a5e18f266787dfc0ef4c Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 29 Dec 2019 12:56:47 +0000 Subject: [PATCH 002/206] Format ModlogEvent --- .../cascadebot/cascadebot/moderation/ModlogEvent.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java b/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java index 60ddb330d..522e61945 100644 --- a/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java +++ b/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java @@ -24,8 +24,8 @@ public enum ModlogEvent { GUILD_MEMBER_NICKNAME_UPDATED(Category.GUILD, Category.GUILD_MEMBER), GUILD_USER_UNBANNED(Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), -// GUILD_MESSAGE_DELETED(Category.GUILD, Category.GUILD_MESSAGE), -// GUILD_MESSAGE_UPDATED(Category.GUILD, Category.GUILD_MESSAGE), + // GUILD_MESSAGE_DELETED(Category.GUILD, Category.GUILD_MESSAGE), + // GUILD_MESSAGE_UPDATED(Category.GUILD, Category.GUILD_MESSAGE), GUILD_BOOST_COUNT_UPDATED(Category.GUILD, Category.GUILD_BOOST), GUILD_BOOST_TIER_UPDATED(Category.GUILD, Category.GUILD_BOOST), @@ -68,17 +68,17 @@ public enum ModlogEvent { USER_DISCRIMINATOR_UPDATED(Category.USER), USER_NAME_UPDATED(Category.USER), - + CHANNEL_CREATED(Category.CHANNEL), CHANNEL_DELETED(Category.CHANNEL), CHANNEL_NAME_UPDATED(Category.CHANNEL), CHANNEL_PERMISSIONS_UPDATED(Category.CHANNEL), CHANNEL_POSITION_UPDATED(Category.CHANNEL), CHANNEL_PARENT_UPDATED(Category.CHANNEL), - + VOICE_CHANNEL_BITRATE_UPDATED(Category.CHANNEL), VOICE_CHANNEL_USER_LIMIT_UPDATED(Category.CHANNEL), - + TEXT_CHANNEL_NSFW_UPDATED(Category.CHANNEL), TEXT_CHANNEL_SLOWMODE_UPDATED(Category.CHANNEL), TEXT_CHANNEL_TOPIC_UPDATED(Category.CHANNEL), From 692e857a89799c89684e85430b77621e8fbda560 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 14 May 2020 14:03:46 -0500 Subject: [PATCH 003/206] Push to the correct branch this time --- config.example.yml | 14 ++- pom.xml | 12 ++ .../org/cascadebot/cascadebot/CascadeBot.java | 9 ++ .../cascadebot/cascadebot/data/Config.java | 43 ++++++++ .../events/MessageEventListener.java | 13 +++ .../cascadebot/utils/CryptUtils.java | 104 ++++++++++++++++++ .../cascadebot/cascadebot/CryptUtilsTest.java | 45 ++++++++ 7 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java create mode 100644 src/main/java/org/cascadebot/cascadebot/utils/CryptUtils.java create mode 100644 src/test/java/org/cascadebot/cascadebot/CryptUtilsTest.java diff --git a/config.example.yml b/config.example.yml index 7df8e9b9a..c87575c59 100644 --- a/config.example.yml +++ b/config.example.yml @@ -111,4 +111,16 @@ haste: web: # The secret to use when authenticating with the site/wrapper - secret_key: \ No newline at end of file + secret_key: + +# The redis server to connect to. If you don't specify a redis server then the bot will not log messages for modlog +redis: + host: '127.0.0.1' + port: 7379 + password: '' + +# If this is specified all sub fields are required to have encryption +encryption_key: + key: 'AES key, 256 bit recommended' + iv: '64 bit iv key' + mac: '128 bit mac key' \ No newline at end of file diff --git a/pom.xml b/pom.xml index f34c6f774..76e968a9a 100644 --- a/pom.xml +++ b/pom.xml @@ -297,6 +297,11 @@ emoji-java 4.0.0 + + org.bouncycastle + bcprov-jdk15on + 1.65 + @@ -348,6 +353,13 @@ mongodb-driver-sync 3.9.1 + + redis.clients + jedis + 3.2.0 + jar + compile + io.netty netty-all diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 6058e7eb8..032008aae 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -47,6 +47,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; +import redis.clients.jedis.Jedis; import javax.annotation.Nonnull; import javax.security.auth.login.LoginException; @@ -74,6 +75,7 @@ public class CascadeBot { private OkHttpClient httpClient; private MusicHandler musicHandler; private EventWaiter eventWaiter; + private Jedis redisClient; public static void main(String[] args) { try (Scanner scanner = new Scanner(CascadeBot.class.getResourceAsStream("/version.txt"))) { @@ -142,6 +144,13 @@ private void init() { return; } + if (Config.INS.getRedisHost() != null) { + redisClient = new Jedis(Config.INS.getRedisHost(), Config.INS.getRedisPort()); + if (Config.INS.getRedisPassword() != null) { + redisClient.auth(Config.INS.getRedisPassword()); + } + } + // Sends a message to break up the status log flow to see what events apply to each bot run Config.INS.getEventWebhook().send( UnicodeConstants.ZERO_WIDTH_SPACE + "\n" + diff --git a/src/main/java/org/cascadebot/cascadebot/data/Config.java b/src/main/java/org/cascadebot/cascadebot/data/Config.java index 4742462a6..acd579140 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/Config.java +++ b/src/main/java/org/cascadebot/cascadebot/data/Config.java @@ -83,6 +83,14 @@ public class Config { private List musicNodes = new ArrayList<>(); + private String redisHost; + private int redisPort; + private String redisPassword; + + private byte[] encryptKey; + private byte[] ivSpec; + private byte[] mac; + private Config(String file) throws IOException { config = new File(file); initConfig(); @@ -241,6 +249,41 @@ private void initConfig() throws IOException { youtubeKey = config.getString("music_keys.youtube"); + redisHost = config.getString("redis.host"); + redisPort = config.getInt("port", 7379); + redisPassword = config.getString("redis.password"); + + String stringKey = config.getString("encryption_key.key"); + byte[] keyBytes = stringKey.getBytes(); + if (keyBytes.length != 16 && keyBytes.length != 24 && keyBytes.length != 32) { + CascadeBot.LOGGER.warn("Encryption key invalid size! must be 128, 192, or 265 bits!"); + } else { + this.encryptKey = keyBytes; + } + + String stringIv = config.getString("encryption_key.iv"); + byte[] ivBytes = stringIv.getBytes(); + if (ivBytes.length != 8) { + CascadeBot.LOGGER.warn("Encryption iv invalid size! must be 64 bits!"); + } else { + this.ivSpec = ivBytes; + } + + String stringMac = config.getString("encryption_key.mac"); + byte[] macBytes = stringMac.getBytes(); + if (macBytes.length != 16) { + CascadeBot.LOGGER.warn("Encryption mac invalid size! must be 128, 192, or 265 bits!"); + } else { + this.mac = macBytes; + } + + if (encryptKey == null || ivSpec == null || mac == null) { + CascadeBot.LOGGER.warn("One of the required encryption values are null, or wrong size. Encryption will not work!"); + encryptKey = null; + ivSpec = null; + mac = null; + } + LOG.info("Finished loading configuration!"); } diff --git a/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java new file mode 100644 index 000000000..405afa68e --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java @@ -0,0 +1,13 @@ +package org.cascadebot.cascadebot.events; + +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; + +public class MessageEventListener extends ListenerAdapter { + + @Override + public void onGuildMessageReceived(GuildMessageReceivedEvent event) { + + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/utils/CryptUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/CryptUtils.java new file mode 100644 index 000000000..e64f1ba1d --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/utils/CryptUtils.java @@ -0,0 +1,104 @@ +package org.cascadebot.cascadebot.utils; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.Mac; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.ShortBufferException; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Security; + +public class CryptUtils { + + static { + Security.addProvider(new BouncyCastleProvider()); + } + + public static EncryptResults encryptString(byte[] key, byte[] iv, byte[] hashKey, String encrypt) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, ShortBufferException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException { + SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); + Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(iv)); + Mac mac = Mac.getInstance("HmacSHA512"); + + SecretKeySpec hmacKey = new SecretKeySpec(hashKey, "HmacSHA512"); + mac.init(hmacKey); + + byte[] encryptBytes = encrypt.getBytes(StandardCharsets.UTF_8); + byte[] encrypted = new byte[cipher.getOutputSize(encrypt.length() + mac.getMacLength())]; + + int cypherLength = cipher.update(encryptBytes, 0, encryptBytes.length, encrypted, 0); + + mac.update(encryptBytes); + + cypherLength += cipher.doFinal(mac.doFinal(), 0, mac.getMacLength(), encrypted, cypherLength); + + return new EncryptResults(encrypted, cypherLength); + } + + public static String decryptString(byte[] key, byte[] iv, byte[] hashKey, byte[] decrypt, int cypherLength) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, EncryptionTamperedWithException, InvalidAlgorithmParameterException { + SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); + Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); + cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv)); + + Mac hmac = Mac.getInstance("HmacSHA512"); + SecretKeySpec hmacKey = new SecretKeySpec(hashKey, "HmacSHA512"); + hmac.init(hmacKey); + + byte[] decrypted = cipher.doFinal(decrypt, 0, cypherLength); + int decryptLength = decrypted.length - hmac.getMacLength(); + + hmac.update(decrypted, 0, decryptLength); + + byte[] hash = new byte[hmac.getMacLength()]; + System.arraycopy(decrypted, decryptLength, hash, 0, hash.length); + + byte[] text = new byte[decryptLength]; + System.arraycopy(decrypted, 0, text, 0, decryptLength); + String decryptedString = new String(text, StandardCharsets.UTF_8); + + byte[] mac = hmac.doFinal(); + + if (!MessageDigest.isEqual(mac, hash)) { + throw new EncryptionTamperedWithException("Encryption was tampered with! Check security."); + } + + return decryptedString; + + } + + public static class EncryptResults { + + private final byte[] encrypted; + + private final int cryptBytes; + + public EncryptResults(byte[] encrypted, int cryptBytes) { + this.encrypted = encrypted; + this.cryptBytes = cryptBytes; + } + + public byte[] getEncrypted() { + return encrypted; + } + + public int getCryptBytes() { + return cryptBytes; + } + } + + public static class EncryptionTamperedWithException extends Exception { + public EncryptionTamperedWithException(String message) { + super(message); + } + } + +} diff --git a/src/test/java/org/cascadebot/cascadebot/CryptUtilsTest.java b/src/test/java/org/cascadebot/cascadebot/CryptUtilsTest.java new file mode 100644 index 000000000..f8b435224 --- /dev/null +++ b/src/test/java/org/cascadebot/cascadebot/CryptUtilsTest.java @@ -0,0 +1,45 @@ +package org.cascadebot.cascadebot; + +import org.cascadebot.cascadebot.utils.CryptUtils; +import org.junit.jupiter.api.Test; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.ShortBufferException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class CryptUtilsTest { + @Test + public void testEncryptDecryptNoTamper() throws NoSuchPaddingException, BadPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, ShortBufferException, InvalidKeyException, CryptUtils.EncryptionTamperedWithException, InvalidAlgorithmParameterException { + byte[] key = "eThWmZq4t7wbzbCbFbJbNcRfUjXn2r5u".getBytes(); + byte[] hashKey = "bJaNdRfU".getBytes(); + String input = "This is a test!"; + + CryptUtils.EncryptResults encryptResults = CryptUtils.encryptString(key, "u8x/A?D*G-KaPdSg".getBytes(), hashKey, input); + + String decrypt = CryptUtils.decryptString(key, "u8x/A?D*G-KaPdSg".getBytes(), hashKey, encryptResults.getEncrypted(), encryptResults.getCryptBytes()); + assertEquals(input, decrypt); + } + + @Test + public void testEncryptDecryptTamper() { + assertThrows(CryptUtils.EncryptionTamperedWithException.class, () -> { + byte[] key = "WnZr4u7xbAbCbFbJaNdRgUkXp2s5v8yb".getBytes(); + byte[] hashKey = "GbKaPdSg".getBytes(); + String input = "This is a test!"; + + CryptUtils.EncryptResults encryptResults = CryptUtils.encryptString(key, "u8x/A?D*G-KaPdSg".getBytes(), hashKey, input); + + byte[] tampered = encryptResults.getEncrypted(); + tampered[9] ^= '0' ^ 9; + + CryptUtils.decryptString(key, "u8x/A?D*G-KaPdSg".getBytes(), hashKey, tampered, encryptResults.getEncrypted().length); + }); + } +} From efd5c231a8ad77442508196223eabc3883af96b3 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 14 May 2020 15:06:38 -0500 Subject: [PATCH 004/206] Store messages in redis --- config.example.yml | 2 +- .../org/cascadebot/cascadebot/CascadeBot.java | 17 ++++++++++ .../cascadebot/cascadebot/data/Config.java | 2 +- .../events/MessageEventListener.java | 32 ++++++++++++++++++- 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/config.example.yml b/config.example.yml index c87575c59..8ba594748 100644 --- a/config.example.yml +++ b/config.example.yml @@ -116,7 +116,7 @@ web: # The redis server to connect to. If you don't specify a redis server then the bot will not log messages for modlog redis: host: '127.0.0.1' - port: 7379 + port: 6379 password: '' # If this is specified all sub fields are required to have encryption diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 032008aae..795e377fe 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -35,6 +35,7 @@ import org.cascadebot.cascadebot.events.CommandListener; import org.cascadebot.cascadebot.events.GeneralEventListener; import org.cascadebot.cascadebot.events.JDAEventMetricsListener; +import org.cascadebot.cascadebot.events.MessageEventListener; import org.cascadebot.cascadebot.events.VoiceEventListener; import org.cascadebot.cascadebot.metrics.Metrics; import org.cascadebot.cascadebot.moderation.ModerationManager; @@ -48,6 +49,7 @@ import org.slf4j.LoggerFactory; import org.slf4j.MDC; import redis.clients.jedis.Jedis; +import redis.clients.jedis.exceptions.JedisConnectionException; import javax.annotation.Nonnull; import javax.security.auth.login.LoginException; @@ -149,6 +151,13 @@ private void init() { if (Config.INS.getRedisPassword() != null) { redisClient.auth(Config.INS.getRedisPassword()); } + try { + redisClient.ping("Hello!"); + LOGGER.info("Redis connected!"); + } catch (JedisConnectionException e) { + LOGGER.warn("Failed to connect to redis", e); + redisClient = null; + } } // Sends a message to break up the status log flow to see what events apply to each bot run @@ -211,6 +220,10 @@ private void init() { defaultShardManagerBuilder.setAudioSendFactory(new NativeAudioSendFactory()); } + if (redisClient != null) { + defaultShardManagerBuilder.addEventListeners(new MessageEventListener()); + } + shardManager = defaultShardManagerBuilder.build(); } catch (LoginException e) { LOGGER.error("Error building JDA", e); @@ -327,4 +340,8 @@ public long getUptime() { return System.currentTimeMillis() - startupTime; } + public Jedis getRedisClient() { + return redisClient; + } + } diff --git a/src/main/java/org/cascadebot/cascadebot/data/Config.java b/src/main/java/org/cascadebot/cascadebot/data/Config.java index acd579140..872b1d764 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/Config.java +++ b/src/main/java/org/cascadebot/cascadebot/data/Config.java @@ -250,7 +250,7 @@ private void initConfig() throws IOException { youtubeKey = config.getString("music_keys.youtube"); redisHost = config.getString("redis.host"); - redisPort = config.getInt("port", 7379); + redisPort = config.getInt("redis.port", 6379); redisPassword = config.getString("redis.password"); String stringKey = config.getString("encryption_key.key"); diff --git a/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java index 405afa68e..981d1532c 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java @@ -1,13 +1,43 @@ package org.cascadebot.cascadebot.events; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; +import org.cascadebot.cascadebot.CascadeBot; +import org.cascadebot.cascadebot.data.Config; +import org.cascadebot.cascadebot.utils.CryptUtils; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.ShortBufferException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; public class MessageEventListener extends ListenerAdapter { @Override public void onGuildMessageReceived(GuildMessageReceivedEvent event) { - + if (Config.INS.getEncryptKey() != null) { + try { + CryptUtils.EncryptResults results = CryptUtils.encryptString(Config.INS.getEncryptKey(), Config.INS.getIvSpec(), Config.INS.getMac(), event.getMessage().getContentRaw()); + JsonObject jsonObject = new JsonObject(); + jsonObject.add("sender", new JsonPrimitive(event.getMember().getIdLong())); + jsonObject.add("content", CascadeBot.getGSON().toJsonTree(results)); + String json = CascadeBot.getGSON().toJson(jsonObject); + CascadeBot.INS.getRedisClient().set(event.getMessageId(), json); + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | ShortBufferException | BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException ignored) { + CascadeBot.LOGGER.warn("Failed to encrypt", ignored); + } + } else { + JsonObject jsonObject = new JsonObject(); + jsonObject.add("sender", new JsonPrimitive(event.getMember().getIdLong())); + jsonObject.add("content", CascadeBot.getGSON().toJsonTree(event.getMessage().getContentRaw())); + String json = CascadeBot.getGSON().toJson(jsonObject); + CascadeBot.INS.getRedisClient().set(event.getMessageId(), json); + } } } From 4d9b56394162d26bb06ddcb73cf8dd50fa8233ae Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 14 May 2020 18:09:47 -0500 Subject: [PATCH 005/206] Benchmarking Also implement non-hmac encrypt/decrypt --- pom.xml | 12 ++++ .../cascadebot/CascadeBenchmark.java | 17 +++++ .../cascadebot/CryptUtilsBenchmark.java | 65 +++++++++++++++++++ .../cascadebot/utils/CryptUtils.java | 28 +++++++- .../cascadebot/cascadebot/CryptUtilsTest.java | 26 ++++++-- 5 files changed, 141 insertions(+), 7 deletions(-) create mode 100644 src/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java create mode 100644 src/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java diff --git a/pom.xml b/pom.xml index 76e968a9a..27f76c4f6 100644 --- a/pom.xml +++ b/pom.xml @@ -437,6 +437,18 @@ 64.2 + + + org.openjdk.jmh + jmh-core + 1.19 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.19 + + diff --git a/src/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java b/src/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java new file mode 100644 index 000000000..e124f587d --- /dev/null +++ b/src/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java @@ -0,0 +1,17 @@ +package org.cascadebot.cascadebot; + +import org.openjdk.jmh.runner.RunnerException; + +import java.io.IOException; + +public class CascadeBenchmark { + + public static void main(String... args) { + try { + org.openjdk.jmh.Main.main(args); + } catch (RunnerException | IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/src/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java b/src/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java new file mode 100644 index 000000000..a42c40e2d --- /dev/null +++ b/src/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java @@ -0,0 +1,65 @@ +package org.cascadebot.cascadebot; + +import org.cascadebot.cascadebot.utils.CryptUtils; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.ShortBufferException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +@State(Scope.Benchmark) +public class CryptUtilsBenchmark { + + int hmacI = 0; + int normalI = 0; + + List testStrings = new ArrayList<>(); + + @Setup + public void setup() { + Random random = new Random(); + for (int i = 0; i < 400; i++) { + byte[] bytes = new byte[random.nextInt(2000)]; + random.nextBytes(bytes); + testStrings.add(new String(bytes)); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void runHmacBenchmark() throws NoSuchPaddingException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IllegalBlockSizeException, ShortBufferException, InvalidKeyException { + byte[] key = "eThWmZq4t7wbzbCbFbJbNcRfUjXn2r5u".getBytes(); + byte[] hashKey = "bJaNdRfU".getBytes(); + byte[] iv = "u8x/A?D*G-KaPdSg".getBytes(); + String testString = testStrings.get(hmacI % 400); + CryptUtils.encryptString(key, iv, hashKey, testString); + hmacI++; + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MICROSECONDS) + public void runNormalBenchmark() throws NoSuchPaddingException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, ShortBufferException { + byte[] key = "eThWmZq4t7wbzbCbFbJbNcRfUjXn2r5u".getBytes(); + byte[] iv = "u8x/A?D*G-KaPdSg".getBytes(); + String testString = testStrings.get(normalI % 400); + CryptUtils.encryptString(key, iv, testString); + normalI++; + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/utils/CryptUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/CryptUtils.java index e64f1ba1d..2a4bdfb75 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/CryptUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/CryptUtils.java @@ -33,7 +33,7 @@ public static EncryptResults encryptString(byte[] key, byte[] iv, byte[] hashKey mac.init(hmacKey); byte[] encryptBytes = encrypt.getBytes(StandardCharsets.UTF_8); - byte[] encrypted = new byte[cipher.getOutputSize(encrypt.length() + mac.getMacLength())]; + byte[] encrypted = new byte[cipher.getOutputSize(encryptBytes.length + mac.getMacLength())]; int cypherLength = cipher.update(encryptBytes, 0, encryptBytes.length, encrypted, 0); @@ -75,6 +75,32 @@ public static String decryptString(byte[] key, byte[] iv, byte[] hashKey, byte[] } + public static EncryptResults encryptString(byte[] key, byte[] iv, String encrypt) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, ShortBufferException { + SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); + Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(iv)); + + byte[] encryptBytes = encrypt.getBytes(); + byte[] encrypted = new byte[cipher.getOutputSize(encryptBytes.length)]; + + int cypherLength = cipher.update(encryptBytes, 0, encryptBytes.length, encrypted, 0); + cypherLength += cipher.doFinal(encrypted, cypherLength); + + return new EncryptResults(encrypted, cypherLength); + } + + public static String decryptString(byte[] key, byte[] iv, byte[] decrypt, int cypherLength) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, ShortBufferException { + SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); + Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); + cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv)); + + byte[] decrypted = new byte[cypherLength]; + int decryptLength = cipher.update(decrypt, 0, decrypt.length, decrypted, 0); + cipher.doFinal(decrypted, decryptLength); + + return new String(decrypted); + } + public static class EncryptResults { private final byte[] encrypted; diff --git a/src/test/java/org/cascadebot/cascadebot/CryptUtilsTest.java b/src/test/java/org/cascadebot/cascadebot/CryptUtilsTest.java index f8b435224..a2ed8e5fc 100644 --- a/src/test/java/org/cascadebot/cascadebot/CryptUtilsTest.java +++ b/src/test/java/org/cascadebot/cascadebot/CryptUtilsTest.java @@ -19,27 +19,41 @@ public class CryptUtilsTest { public void testEncryptDecryptNoTamper() throws NoSuchPaddingException, BadPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, ShortBufferException, InvalidKeyException, CryptUtils.EncryptionTamperedWithException, InvalidAlgorithmParameterException { byte[] key = "eThWmZq4t7wbzbCbFbJbNcRfUjXn2r5u".getBytes(); byte[] hashKey = "bJaNdRfU".getBytes(); + byte[] iv = "u8x/A?D*G-KaPdSg".getBytes(); String input = "This is a test!"; - CryptUtils.EncryptResults encryptResults = CryptUtils.encryptString(key, "u8x/A?D*G-KaPdSg".getBytes(), hashKey, input); + CryptUtils.EncryptResults encryptResults = CryptUtils.encryptString(key, iv, hashKey, input); - String decrypt = CryptUtils.decryptString(key, "u8x/A?D*G-KaPdSg".getBytes(), hashKey, encryptResults.getEncrypted(), encryptResults.getCryptBytes()); + String decrypt = CryptUtils.decryptString(key, iv, hashKey, encryptResults.getEncrypted(), encryptResults.getCryptBytes()); assertEquals(input, decrypt); } @Test public void testEncryptDecryptTamper() { assertThrows(CryptUtils.EncryptionTamperedWithException.class, () -> { - byte[] key = "WnZr4u7xbAbCbFbJaNdRgUkXp2s5v8yb".getBytes(); - byte[] hashKey = "GbKaPdSg".getBytes(); + byte[] key = "eThWmZq4t7wbzbCbFbJbNcRfUjXn2r5u".getBytes(); + byte[] hashKey = "bJaNdRfU".getBytes(); + byte[] iv = "u8x/A?D*G-KaPdSg".getBytes(); String input = "This is a test!"; - CryptUtils.EncryptResults encryptResults = CryptUtils.encryptString(key, "u8x/A?D*G-KaPdSg".getBytes(), hashKey, input); + CryptUtils.EncryptResults encryptResults = CryptUtils.encryptString(key, iv, hashKey, input); byte[] tampered = encryptResults.getEncrypted(); tampered[9] ^= '0' ^ 9; - CryptUtils.decryptString(key, "u8x/A?D*G-KaPdSg".getBytes(), hashKey, tampered, encryptResults.getEncrypted().length); + CryptUtils.decryptString(key, iv, hashKey, tampered, encryptResults.getEncrypted().length); }); } + + @Test + public void testEncryptDecryptNoHmac() throws NoSuchPaddingException, ShortBufferException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException { + byte[] key = "eThWmZq4t7wbzbCbFbJbNcRfUjXn2r5u".getBytes(); + byte[] iv = "u8x/A?D*G-KaPdSg".getBytes(); + String input = "This is a test!"; + + CryptUtils.EncryptResults encryptResults = CryptUtils.encryptString(key, iv, input); + + String decrypt = CryptUtils.decryptString(key, iv, encryptResults.getEncrypted(), encryptResults.getCryptBytes()); + assertEquals(input, decrypt); + } } From b6bf1cb736699539645cfc69d6c3ae0d6c6cff87 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Fri, 15 May 2020 13:55:58 -0500 Subject: [PATCH 006/206] Put stuff in queue so we don't block the event thread --- .../org/cascadebot/cascadebot/CascadeBot.java | 9 +++ .../events/MessageEventListener.java | 19 +----- .../runnables/MessageReceivedRunnable.java | 62 +++++++++++++++++++ 3 files changed, 72 insertions(+), 18 deletions(-) create mode 100644 src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 795e377fe..4008f270e 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -41,6 +41,7 @@ import org.cascadebot.cascadebot.moderation.ModerationManager; import org.cascadebot.cascadebot.music.MusicHandler; import org.cascadebot.cascadebot.permissions.PermissionsManager; +import org.cascadebot.cascadebot.runnables.MessageReceivedRunnable; import org.cascadebot.cascadebot.tasks.Task; import org.cascadebot.cascadebot.utils.EventWaiter; import org.cascadebot.cascadebot.utils.LogbackUtils; @@ -79,6 +80,8 @@ public class CascadeBot { private EventWaiter eventWaiter; private Jedis redisClient; + private MessageReceivedRunnable messageReceivedRunnable; + public static void main(String[] args) { try (Scanner scanner = new Scanner(CascadeBot.class.getResourceAsStream("/version.txt"))) { version = Version.parseVer(scanner.next()); @@ -176,6 +179,9 @@ private void init() { builder.setPrettyPrinting(); } + messageReceivedRunnable = new MessageReceivedRunnable(); + new Thread(messageReceivedRunnable, "messageHandleThread").start(); + if (Config.INS.getConnectionString() != null) { databaseManager = new DatabaseManager(Config.INS.getConnectionString()); } else { @@ -344,4 +350,7 @@ public Jedis getRedisClient() { return redisClient; } + public MessageReceivedRunnable getMessageReceivedRunnable() { + return messageReceivedRunnable; + } } diff --git a/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java index 981d1532c..f6b09222e 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java @@ -20,24 +20,7 @@ public class MessageEventListener extends ListenerAdapter { @Override public void onGuildMessageReceived(GuildMessageReceivedEvent event) { - if (Config.INS.getEncryptKey() != null) { - try { - CryptUtils.EncryptResults results = CryptUtils.encryptString(Config.INS.getEncryptKey(), Config.INS.getIvSpec(), Config.INS.getMac(), event.getMessage().getContentRaw()); - JsonObject jsonObject = new JsonObject(); - jsonObject.add("sender", new JsonPrimitive(event.getMember().getIdLong())); - jsonObject.add("content", CascadeBot.getGSON().toJsonTree(results)); - String json = CascadeBot.getGSON().toJson(jsonObject); - CascadeBot.INS.getRedisClient().set(event.getMessageId(), json); - } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | ShortBufferException | BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException ignored) { - CascadeBot.LOGGER.warn("Failed to encrypt", ignored); - } - } else { - JsonObject jsonObject = new JsonObject(); - jsonObject.add("sender", new JsonPrimitive(event.getMember().getIdLong())); - jsonObject.add("content", CascadeBot.getGSON().toJsonTree(event.getMessage().getContentRaw())); - String json = CascadeBot.getGSON().toJson(jsonObject); - CascadeBot.INS.getRedisClient().set(event.getMessageId(), json); - } + CascadeBot.INS.getMessageReceivedRunnable().getQueue().add(event); } } diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java new file mode 100644 index 000000000..e87cf14c5 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java @@ -0,0 +1,62 @@ +package org.cascadebot.cascadebot.runnables; + +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import org.cascadebot.cascadebot.CascadeBot; +import org.cascadebot.cascadebot.ShutdownHandler; +import org.cascadebot.cascadebot.data.Config; +import org.cascadebot.cascadebot.utils.CryptUtils; +import org.cascadebot.cascadebot.utils.PasteUtils; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.ShortBufferException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +public class MessageReceivedRunnable implements Runnable { + + private BlockingQueue queue = new LinkedBlockingQueue<>(); + + @Override + public void run() { + while (!ShutdownHandler.SHUTDOWN_LOCK.get()) { + try { + GuildMessageReceivedEvent event = queue.take(); + String message = ""; + if (Config.INS.getEncryptKey() != null) { + try { + CryptUtils.EncryptResults results = CryptUtils.encryptString(Config.INS.getEncryptKey(), Config.INS.getIvSpec(), Config.INS.getMac(), event.getMessage().getContentRaw()); + JsonObject jsonObject = new JsonObject(); + jsonObject.add("sender", new JsonPrimitive(event.getMember().getIdLong())); + jsonObject.add("content", CascadeBot.getGSON().toJsonTree(results)); + message = CascadeBot.getGSON().toJson(jsonObject); + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | ShortBufferException | BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException ignored) { + CascadeBot.LOGGER.warn("Failed to encrypt", ignored); + return; + } + } else { + JsonObject jsonObject = new JsonObject(); + jsonObject.add("sender", new JsonPrimitive(event.getMember().getIdLong())); + jsonObject.add("content", CascadeBot.getGSON().toJsonTree(event.getMessage().getContentRaw())); + message = CascadeBot.getGSON().toJson(jsonObject); + } + CascadeBot.INS.getRedisClient().set("message:" + event.getMessageId(), message); + CascadeBot.INS.getRedisClient().expire("message:" + event.getMessageId(), (int) TimeUnit.HOURS.toSeconds(24)); + } catch (InterruptedException e) { + CascadeBot.LOGGER.warn("Message thread interrupted: " + PasteUtils.getStackTrace(e)); + } + } + } + + public BlockingQueue getQueue() { + return queue; + } + +} From 617c79fb53315661c0626c1aeda7b73b1c81dcfe Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 16 May 2020 14:41:34 -0500 Subject: [PATCH 007/206] Change all the crypt stuff Change over to CBC Don't use hmac for message --- .../runnables/MessageReceivedRunnable.java | 2 +- .../cascadebot/utils/CryptUtils.java | 52 ++++++------------- .../cascadebot/cascadebot/CryptUtilsTest.java | 30 ++++++++--- 3 files changed, 39 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java index e87cf14c5..4ecacbef8 100644 --- a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java +++ b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java @@ -32,7 +32,7 @@ public void run() { String message = ""; if (Config.INS.getEncryptKey() != null) { try { - CryptUtils.EncryptResults results = CryptUtils.encryptString(Config.INS.getEncryptKey(), Config.INS.getIvSpec(), Config.INS.getMac(), event.getMessage().getContentRaw()); + byte[] results = CryptUtils.encryptString(Config.INS.getEncryptKey(), Config.INS.getIvSpec(), event.getMessage().getContentRaw()); JsonObject jsonObject = new JsonObject(); jsonObject.add("sender", new JsonPrimitive(event.getMember().getIdLong())); jsonObject.add("content", CascadeBot.getGSON().toJsonTree(results)); diff --git a/src/main/java/org/cascadebot/cascadebot/utils/CryptUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/CryptUtils.java index 2a4bdfb75..ebb7b401a 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/CryptUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/CryptUtils.java @@ -23,9 +23,9 @@ public class CryptUtils { Security.addProvider(new BouncyCastleProvider()); } - public static EncryptResults encryptString(byte[] key, byte[] iv, byte[] hashKey, String encrypt) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, ShortBufferException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException { + public static byte[] encryptString(byte[] key, byte[] iv, byte[] hashKey, String encrypt) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, ShortBufferException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException { SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); - Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(iv)); Mac mac = Mac.getInstance("HmacSHA512"); @@ -39,21 +39,21 @@ public static EncryptResults encryptString(byte[] key, byte[] iv, byte[] hashKey mac.update(encryptBytes); - cypherLength += cipher.doFinal(mac.doFinal(), 0, mac.getMacLength(), encrypted, cypherLength); + cipher.doFinal(mac.doFinal(), 0, mac.getMacLength(), encrypted, cypherLength); - return new EncryptResults(encrypted, cypherLength); + return encrypted; } - public static String decryptString(byte[] key, byte[] iv, byte[] hashKey, byte[] decrypt, int cypherLength) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, EncryptionTamperedWithException, InvalidAlgorithmParameterException { + public static String decryptString(byte[] key, byte[] iv, byte[] hashKey, byte[] decrypt) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, EncryptionTamperedWithException, InvalidAlgorithmParameterException { SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); - Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv)); Mac hmac = Mac.getInstance("HmacSHA512"); SecretKeySpec hmacKey = new SecretKeySpec(hashKey, "HmacSHA512"); hmac.init(hmacKey); - byte[] decrypted = cipher.doFinal(decrypt, 0, cypherLength); + byte[] decrypted = cipher.doFinal(decrypt, 0, decrypt.length); int decryptLength = decrypted.length - hmac.getMacLength(); hmac.update(decrypted, 0, decryptLength); @@ -71,54 +71,34 @@ public static String decryptString(byte[] key, byte[] iv, byte[] hashKey, byte[] throw new EncryptionTamperedWithException("Encryption was tampered with! Check security."); } - return decryptedString; + return decryptedString.trim(); } - public static EncryptResults encryptString(byte[] key, byte[] iv, String encrypt) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, ShortBufferException { + public static byte[] encryptString(byte[] key, byte[] iv, String encrypt) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, ShortBufferException { SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); - Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(iv)); byte[] encryptBytes = encrypt.getBytes(); byte[] encrypted = new byte[cipher.getOutputSize(encryptBytes.length)]; int cypherLength = cipher.update(encryptBytes, 0, encryptBytes.length, encrypted, 0); - cypherLength += cipher.doFinal(encrypted, cypherLength); + cipher.doFinal(encrypted, cypherLength); - return new EncryptResults(encrypted, cypherLength); + return encrypted; } - public static String decryptString(byte[] key, byte[] iv, byte[] decrypt, int cypherLength) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, ShortBufferException { + public static String decryptString(byte[] key, byte[] iv, byte[] decrypt) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, ShortBufferException { SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES"); - Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv)); - byte[] decrypted = new byte[cypherLength]; + byte[] decrypted = new byte[decrypt.length]; int decryptLength = cipher.update(decrypt, 0, decrypt.length, decrypted, 0); cipher.doFinal(decrypted, decryptLength); - return new String(decrypted); - } - - public static class EncryptResults { - - private final byte[] encrypted; - - private final int cryptBytes; - - public EncryptResults(byte[] encrypted, int cryptBytes) { - this.encrypted = encrypted; - this.cryptBytes = cryptBytes; - } - - public byte[] getEncrypted() { - return encrypted; - } - - public int getCryptBytes() { - return cryptBytes; - } + return new String(decrypted).trim(); } public static class EncryptionTamperedWithException extends Exception { diff --git a/src/test/java/org/cascadebot/cascadebot/CryptUtilsTest.java b/src/test/java/org/cascadebot/cascadebot/CryptUtilsTest.java index a2ed8e5fc..1b0c2e545 100644 --- a/src/test/java/org/cascadebot/cascadebot/CryptUtilsTest.java +++ b/src/test/java/org/cascadebot/cascadebot/CryptUtilsTest.java @@ -22,9 +22,9 @@ public void testEncryptDecryptNoTamper() throws NoSuchPaddingException, BadPaddi byte[] iv = "u8x/A?D*G-KaPdSg".getBytes(); String input = "This is a test!"; - CryptUtils.EncryptResults encryptResults = CryptUtils.encryptString(key, iv, hashKey, input); + byte[] encryptResults = CryptUtils.encryptString(key, iv, hashKey, input); - String decrypt = CryptUtils.decryptString(key, iv, hashKey, encryptResults.getEncrypted(), encryptResults.getCryptBytes()); + String decrypt = CryptUtils.decryptString(key, iv, hashKey, encryptResults); assertEquals(input, decrypt); } @@ -36,12 +36,11 @@ public void testEncryptDecryptTamper() { byte[] iv = "u8x/A?D*G-KaPdSg".getBytes(); String input = "This is a test!"; - CryptUtils.EncryptResults encryptResults = CryptUtils.encryptString(key, iv, hashKey, input); + byte[] encryptResults = CryptUtils.encryptString(key, iv, hashKey, input); - byte[] tampered = encryptResults.getEncrypted(); - tampered[9] ^= '0' ^ 9; + encryptResults[9] ^= '0' ^ 9; - CryptUtils.decryptString(key, iv, hashKey, tampered, encryptResults.getEncrypted().length); + CryptUtils.decryptString(key, iv, hashKey, encryptResults); }); } @@ -51,9 +50,24 @@ public void testEncryptDecryptNoHmac() throws NoSuchPaddingException, ShortBuffe byte[] iv = "u8x/A?D*G-KaPdSg".getBytes(); String input = "This is a test!"; - CryptUtils.EncryptResults encryptResults = CryptUtils.encryptString(key, iv, input); + byte[] encryptResults = CryptUtils.encryptString(key, iv, input); - String decrypt = CryptUtils.decryptString(key, iv, encryptResults.getEncrypted(), encryptResults.getCryptBytes()); + String decrypt = CryptUtils.decryptString(key, iv, encryptResults); assertEquals(input, decrypt); } + + @Test + public void testEncryptDecryptNoHmacTamper() throws NoSuchPaddingException, ShortBufferException, InvalidKeyException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException { + byte[] key = "eThWmZq4t7wbzbCbFbJbNcRfUjXn2r5u".getBytes(); + byte[] iv = "u8x/A?D*G-KaPdSg".getBytes(); + String input = "This is a test!"; + + byte[] encryptResults = CryptUtils.encryptString(key, iv, input); + + encryptResults[9] ^= '0' ^ 9; + + assertThrows(BadPaddingException.class, () -> { + CryptUtils.decryptString(key, iv, encryptResults); + }); + } } From a1ab9ca9b00da06424666930e4fc9c7da73350bb Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 18 May 2020 10:48:32 -0500 Subject: [PATCH 008/206] Work on implementing modlog events parsing --- .../org/cascadebot/cascadebot/CascadeBot.java | 2 + .../events/ModlogEventListener.java | 299 ++++++++++++++++++ .../cascadebot/moderation/ModlogEvent.java | 9 +- .../data/objects/ModlogEventStore.kt | 14 + 4 files changed, 321 insertions(+), 3 deletions(-) create mode 100644 src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 4008f270e..29e5d5163 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -36,6 +36,7 @@ import org.cascadebot.cascadebot.events.GeneralEventListener; import org.cascadebot.cascadebot.events.JDAEventMetricsListener; import org.cascadebot.cascadebot.events.MessageEventListener; +import org.cascadebot.cascadebot.events.ModlogEventListener; import org.cascadebot.cascadebot.events.VoiceEventListener; import org.cascadebot.cascadebot.metrics.Metrics; import org.cascadebot.cascadebot.moderation.ModerationManager; @@ -206,6 +207,7 @@ private void init() { .addEventListeners(new ButtonEventListener()) .addEventListeners(new VoiceEventListener()) .addEventListeners(new JDAEventMetricsListener()) + .addEventListeners(new ModlogEventListener()) .addEventListeners(eventWaiter) .setToken(Config.INS.getBotToken()) .setShardsTotal(-1) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java new file mode 100644 index 000000000..7f633e359 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -0,0 +1,299 @@ +package org.cascadebot.cascadebot.events; + +import club.minnced.discord.webhook.send.WebhookEmbed; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import net.dv8tion.jda.api.audit.ActionType; +import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.Emote; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.events.channel.category.GenericCategoryEvent; +import net.dv8tion.jda.api.events.channel.store.GenericStoreChannelEvent; +import net.dv8tion.jda.api.events.channel.text.GenericTextChannelEvent; +import net.dv8tion.jda.api.events.channel.voice.GenericVoiceChannelEvent; +import net.dv8tion.jda.api.events.emote.EmoteAddedEvent; +import net.dv8tion.jda.api.events.emote.EmoteRemovedEvent; +import net.dv8tion.jda.api.events.emote.GenericEmoteEvent; +import net.dv8tion.jda.api.events.emote.update.EmoteUpdateNameEvent; +import net.dv8tion.jda.api.events.emote.update.EmoteUpdateRolesEvent; +import net.dv8tion.jda.api.events.guild.GuildBanEvent; +import net.dv8tion.jda.api.events.guild.GuildUnbanEvent; +import net.dv8tion.jda.api.events.guild.member.GenericGuildMemberEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberLeaveEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleAddEvent; +import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent; +import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateNicknameEvent; +import net.dv8tion.jda.api.events.guild.update.GenericGuildUpdateEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent; +import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent; +import net.dv8tion.jda.api.events.role.GenericRoleEvent; +import net.dv8tion.jda.api.events.user.update.UserUpdateDiscriminatorEvent; +import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import org.cascadebot.cascadebot.CascadeBot; +import org.cascadebot.cascadebot.data.Config; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEvent; +import org.cascadebot.cascadebot.utils.CryptUtils; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.ShortBufferException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class ModlogEventListener extends ListenerAdapter { + + //TODO move everything over to using language paths instead of hard coded string + public void onGenericEmote(GenericEmoteEvent event) { + Emote emote = event.getEmote(); + event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + User user = null; + if (entry.getType().equals(ActionType.EMOTE_UPDATE) || entry.getType().equals(ActionType.EMOTE_CREATE) || entry.getType().equals(ActionType.EMOTE_DELETE)) { + user = auditLogEntries.get(0).getUser(); + } + List embedFieldList = new ArrayList<>(); + ModlogEvent modlogEvent; + if (event instanceof EmoteAddedEvent) { + modlogEvent = ModlogEvent.EMOTE_CREATED; + } else if (event instanceof EmoteRemovedEvent) { + modlogEvent = ModlogEvent.EMOTE_DELETED; + } else if (event instanceof EmoteUpdateNameEvent) { + modlogEvent = ModlogEvent.EMOTE_UPDATED_NAME; + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", ((EmoteUpdateNameEvent) event).getOldName())); + } else if (event instanceof EmoteUpdateRolesEvent) { + modlogEvent = ModlogEvent.EMOTE_UPDATED_ROLES; + List oldRoles = ((EmoteUpdateRolesEvent) event).getOldRoles(); + List newRoles = ((EmoteUpdateRolesEvent) event).getNewRoles(); + ListChanges roleListChanges = new ListChanges<>(oldRoles, newRoles); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added Roles", + roleListChanges.added.stream().map(role -> role.getName() + " (" + role.getId() + ")") + .collect(Collectors.joining("\n")))); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed Roles", + roleListChanges.removed.stream().map(role -> role.getName() + " (" + role.getId() + ")") + .collect(Collectors.joining("\n")))); + } else { + return; + } + ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, user, emote, embedFieldList); + }); + } + + public void onGenericGuildMember(GenericGuildMemberEvent event) { + User user = event.getMember().getUser(); + event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + ModlogEvent modlogEvent; + User responsible = null; + if (event instanceof GuildMemberJoinEvent) { + modlogEvent = ModlogEvent.GUILD_MEMBER_JOINED; + } else if (event instanceof GuildMemberLeaveEvent) { + if (entry.getType().equals(ActionType.KICK)) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Responsible", Objects.requireNonNull(entry.getUser()).getAsTag())); + if (entry.getReason() != null) { + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Reason", entry.getReason())); + } + modlogEvent = ModlogEvent.GUILD_MEMBER_KICKED; + } else { //TODO not assume leave if audit log entry for kick was not found. + modlogEvent = ModlogEvent.GUILD_MEMBER_LEFT; + } + } else if (event instanceof GuildMemberRoleAddEvent) { + if (entry.getType().equals(ActionType.MEMBER_ROLE_UPDATE)) { + responsible = entry.getUser(); + } + modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_ADDED; + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added Roles", ((GuildMemberRoleAddEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n")))); + } else if (event instanceof GuildMemberRoleRemoveEvent) { + if (entry.getType().equals(ActionType.MEMBER_ROLE_UPDATE)) { + responsible = entry.getUser(); + } + modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_REMOVED; + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed Roles", ((GuildMemberRoleRemoveEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n")))); + } else if (event instanceof GuildMemberUpdateNicknameEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Nickname", Objects.requireNonNull(((GuildMemberUpdateNicknameEvent) event).getOldValue()))); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Nickname", Objects.requireNonNull(((GuildMemberUpdateNicknameEvent) event).getNewValue()))); + modlogEvent = ModlogEvent.GUILD_MEMBER_NICKNAME_UPDATED; + } else { + return; + } + ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); + }); + } + + //region Ban events + public void onGuildBan(GuildBanEvent event) { + User user = event.getUser(); + event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + ModlogEvent modlogEvent = ModlogEvent.GUILD_USER_BANNED; + User responsible = null; + if (entry.getType().equals(ActionType.BAN)) { + responsible = entry.getUser(); + if (entry.getReason() != null) { + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Reason", entry.getReason())); + } + } + ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); + }); + } + + public void onGuildUnban(GuildUnbanEvent event) { + User user = event.getUser(); + event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + ModlogEvent modlogEvent = ModlogEvent.GUILD_USER_UNBANNED; + User responsible = null; + if (entry.getType().equals(ActionType.UNBAN)) { + responsible = entry.getUser(); + } + ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); + }); + } + //endregion + + //region Message + public void onGuildMessageDelete(GuildMessageDeleteEvent event) { + String messageID = event.getMessageId(); + String messageJson = CascadeBot.INS.getRedisClient().get("message:" + messageID); + CascadeBot.INS.getRedisClient().del("message:" + messageID); + JsonObject jsonObject = new JsonParser().parse(messageJson).getAsJsonObject(); + long messageSender = jsonObject.get("sender").getAsLong(); + User affected = CascadeBot.INS.getClient().getUserById(messageSender); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Message", getMessageFromJson(jsonObject))); + if (affected == null) { + return; + } + event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + ModlogEvent modlogEvent; + User responsible; + if (entry.getType().equals(ActionType.MESSAGE_DELETE)) { + modlogEvent = ModlogEvent.GUILD_MESSAGE_DELETED; + responsible = entry.getUser(); + } else { //TODO not assume self delete if audit log entry for message delete was not found. + modlogEvent = ModlogEvent.GUILD_MESSAGE_DELETED_SELF; + responsible = affected; + } + ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); + }); + } + + public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { + Message message = event.getMessage(); + String messageJson = CascadeBot.INS.getRedisClient().get("message:" + message.getId()); + CascadeBot.INS.getRedisClient().del("message:" + message.getId()); + JsonObject jsonObject = new JsonParser().parse(messageJson).getAsJsonObject(); + long messageSender = jsonObject.get("sender").getAsLong(); + User affected = CascadeBot.INS.getClient().getUserById(messageSender); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Old Message", getMessageFromJson(jsonObject))); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "New Message", message.getContentRaw())); + if (affected == null) { + return; + } + ModlogEvent modlogEvent = ModlogEvent.GUILD_MESSAGE_UPDATED; + ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, null, affected, embedFieldList); + } + + private String getMessageFromJson(JsonObject jsonObject) { + String message; + if (Config.INS.getEncryptKey() != null) { + JsonArray bytesJsonArray = jsonObject.get("content").getAsJsonArray(); + byte[] messageBytes = new byte[bytesJsonArray.size()]; + for (int i = 0; i < bytesJsonArray.size(); i++) { + messageBytes[i] = bytesJsonArray.get(i).getAsByte(); + } + try { + message = CryptUtils.decryptString(Config.INS.getEncryptKey(), Config.INS.getIvSpec(), messageBytes); + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | ShortBufferException e) { + e.printStackTrace(); + // TODO log these + return ""; + } catch (BadPaddingException e) { + e.printStackTrace(); + return ""; + } + } else { + message = jsonObject.get("content").getAsString(); + } + return message; + } + //endregion + + public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { + + } + + public void onGenericStoreChannel(GenericStoreChannelEvent event) { + + } + + public void onGenericTextChannel(GenericTextChannelEvent event) { + + } + + public void onGenericVoiceChannel(GenericVoiceChannelEvent event) { + + } + + public void onGenericCategory(GenericCategoryEvent event) { + + } + + public void onGenericRole(GenericRoleEvent event) { + + } + + //region Username updates + public void onUserUpdateName(UserUpdateNameEvent event) { + + } + + public void onUserUpdateDiscriminator(UserUpdateDiscriminatorEvent event) { + + } + //endregion + + //TODO move this to a util class + public static class ListChanges { + private final List added = new ArrayList<>(); + private final List removed = new ArrayList<>(); + + public ListChanges(List originalList, List newList) { + for (T object : originalList) { + if (!newList.contains(object)) { + removed.add(object); + } + } + for (T object : newList) { + if (!originalList.contains(object)) { + added.add(object); + } + } + } + + public List getAdded() { + return added; + } + + public List getRemoved() { + return removed; + } + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java b/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java index 522e61945..2b1686a30 100644 --- a/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java +++ b/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java @@ -19,13 +19,16 @@ public enum ModlogEvent { GUILD_MEMBER_JOINED(Category.GUILD, Category.GUILD_MEMBER), GUILD_MEMBER_LEFT(Category.GUILD, Category.GUILD_MEMBER), GUILD_MEMBER_KICKED(Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), - GUILD_MEMBER_BANNED(Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), GUILD_MEMBER_ROLE_ADDED(Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_ROLE_REMOVED(Category.GUILD, Category.GUILD_MEMBER), GUILD_MEMBER_NICKNAME_UPDATED(Category.GUILD, Category.GUILD_MEMBER), + + GUILD_USER_BANNED(Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), GUILD_USER_UNBANNED(Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), - // GUILD_MESSAGE_DELETED(Category.GUILD, Category.GUILD_MESSAGE), - // GUILD_MESSAGE_UPDATED(Category.GUILD, Category.GUILD_MESSAGE), + GUILD_MESSAGE_DELETED(Category.GUILD, Category.GUILD_MESSAGE), + GUILD_MESSAGE_DELETED_SELF(Category.GUILD, Category.GUILD_MESSAGE), + GUILD_MESSAGE_UPDATED(Category.GUILD, Category.GUILD_MESSAGE), GUILD_BOOST_COUNT_UPDATED(Category.GUILD, Category.GUILD_BOOST), GUILD_BOOST_TIER_UPDATED(Category.GUILD, Category.GUILD_BOOST), diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt new file mode 100644 index 000000000..7d8a74071 --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -0,0 +1,14 @@ +package org.cascadebot.cascadebot.data.objects + +import club.minnced.discord.webhook.send.WebhookEmbed +import net.dv8tion.jda.api.entities.ISnowflake +import net.dv8tion.jda.api.entities.User +import org.cascadebot.cascadebot.moderation.ModlogEvent + +data class ModlogEventStore( + val trigger: ModlogEvent, + val responsible: User?, + val affected: ISnowflake, + + val extraInfo: List +) \ No newline at end of file From 797ebf83beb9a5c80393c7910ebbd24adf161bf5 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 18 May 2020 14:53:22 -0500 Subject: [PATCH 009/206] Guild Update Events --- .../events/ModlogEventListener.java | 121 +++++++++++++++++- .../cascadebot/utils/FormatUtils.java | 16 ++- 2 files changed, 131 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 7f633e359..75d79c295 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -7,6 +7,7 @@ import net.dv8tion.jda.api.audit.ActionType; import net.dv8tion.jda.api.audit.AuditLogEntry; import net.dv8tion.jda.api.entities.Emote; +import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.User; @@ -28,6 +29,23 @@ import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent; import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateNicknameEvent; import net.dv8tion.jda.api.events.guild.update.GenericGuildUpdateEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateAfkChannelEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateAfkTimeoutEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateBannerEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateDescriptionEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateExplicitContentLevelEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateFeaturesEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateIconEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateMFALevelEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateMaxMembersEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateMaxPresencesEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateNameEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateNotificationLevelEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateRegionEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateSplashEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateSystemChannelEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateVanityCodeEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateVerificationLevelEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent; import net.dv8tion.jda.api.events.role.GenericRoleEvent; @@ -36,9 +54,12 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.data.Config; +import org.cascadebot.cascadebot.data.managers.GuildDataManager; +import org.cascadebot.cascadebot.data.objects.GuildData; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.utils.CryptUtils; +import org.cascadebot.cascadebot.utils.FormatUtils; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; @@ -48,6 +69,7 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; @@ -56,6 +78,7 @@ public class ModlogEventListener extends ListenerAdapter { //TODO move everything over to using language paths instead of hard coded string public void onGenericEmote(GenericEmoteEvent event) { + GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); Emote emote = event.getEmote(); event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); @@ -91,6 +114,7 @@ public void onGenericEmote(GenericEmoteEvent event) { } public void onGenericGuildMember(GenericGuildMemberEvent event) { + GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); User user = event.getMember().getUser(); event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); @@ -122,8 +146,8 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_REMOVED; embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed Roles", ((GuildMemberRoleRemoveEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n")))); } else if (event instanceof GuildMemberUpdateNicknameEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Nickname", Objects.requireNonNull(((GuildMemberUpdateNicknameEvent) event).getOldValue()))); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Nickname", Objects.requireNonNull(((GuildMemberUpdateNicknameEvent) event).getNewValue()))); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Nickname", ((GuildMemberUpdateNicknameEvent) event).getOldValue())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Nickname", ((GuildMemberUpdateNicknameEvent) event).getNewValue())); modlogEvent = ModlogEvent.GUILD_MEMBER_NICKNAME_UPDATED; } else { return; @@ -134,6 +158,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { //region Ban events public void onGuildBan(GuildBanEvent event) { + GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); User user = event.getUser(); event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); @@ -151,6 +176,7 @@ public void onGuildBan(GuildBanEvent event) { } public void onGuildUnban(GuildUnbanEvent event) { + GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); User user = event.getUser(); event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); @@ -167,6 +193,7 @@ public void onGuildUnban(GuildUnbanEvent event) { //region Message public void onGuildMessageDelete(GuildMessageDeleteEvent event) { + GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); String messageID = event.getMessageId(); String messageJson = CascadeBot.INS.getRedisClient().get("message:" + messageID); CascadeBot.INS.getRedisClient().del("message:" + messageID); @@ -194,6 +221,7 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { } public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { + GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); Message message = event.getMessage(); String messageJson = CascadeBot.INS.getRedisClient().get("message:" + message.getId()); CascadeBot.INS.getRedisClient().del("message:" + message.getId()); @@ -236,7 +264,92 @@ private String getMessageFromJson(JsonObject jsonObject) { //endregion public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { - + Guild affected = event.getEntity(); + GuildData guildData = GuildDataManager.getGuildData(affected.getIdLong()); + event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + User responsible = null; + ModlogEvent modlogEvent; + if (entry.getType().equals(ActionType.GUILD_UPDATE)) { + responsible = entry.getUser(); + } + if (event instanceof GuildUpdateAfkChannelEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Channel", ((GuildUpdateAfkChannelEvent) event).getOldAfkChannel().getName())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Channel", ((GuildUpdateAfkChannelEvent) event).getNewAfkChannel().getName())); + modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_CHANNEL; + } else if (event instanceof GuildUpdateAfkTimeoutEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Value", ((GuildUpdateAfkTimeoutEvent) event).getOldAfkTimeout().getSeconds() + " seconds")); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Value", ((GuildUpdateAfkTimeoutEvent) event).getNewAfkTimeout().getSeconds() + " seconds")); + modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_TIMEOUT; + } else if (event instanceof GuildUpdateBannerEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Old Image", ((GuildUpdateBannerEvent) event).getOldBannerUrl())); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "New Image", ((GuildUpdateBannerEvent) event).getNewBannerIdUrl())); + modlogEvent = ModlogEvent.GUILD_UPDATE_BANNER; + } else if (event instanceof GuildUpdateDescriptionEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Old Description", ((GuildUpdateDescriptionEvent) event).getOldDescription())); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "New Description", ((GuildUpdateDescriptionEvent) event).getNewDescription())); + modlogEvent = ModlogEvent.GUILD_UPDATE_DESCRIPTION; + } else if (event instanceof GuildUpdateExplicitContentLevelEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Filter", ((GuildUpdateExplicitContentLevelEvent) event).getOldLevel().name())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Filter", ((GuildUpdateExplicitContentLevelEvent) event).getNewLevel().name())); + modlogEvent = ModlogEvent.GUILD_UPDATE_EXPLICIT_FILTER; + } else if (event instanceof GuildUpdateFeaturesEvent) { + ListChanges featuresChanged = new ListChanges<>(((GuildUpdateFeaturesEvent) event).getOldFeatures(), ((GuildUpdateFeaturesEvent) event).getNewFeatures()); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added Features", String.join("\n", featuresChanged.added))); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed Features", String.join("\n", featuresChanged.removed))); + modlogEvent = ModlogEvent.GUILD_UPDATE_FEATURES; + } else if (event instanceof GuildUpdateIconEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Old Image", ((GuildUpdateIconEvent) event).getOldIconUrl())); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "New Image", ((GuildUpdateIconEvent) event).getNewIconUrl())); + modlogEvent = ModlogEvent.GUILD_UPDATE_ICON; + } else if (event instanceof GuildUpdateMaxMembersEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Max Members", ((GuildUpdateMaxMembersEvent) event).getOldMaxMembers() + " members")); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Max Members", ((GuildUpdateMaxMembersEvent) event).getNewMaxMembers() + " members")); + modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_MEMBERS; + } else if (event instanceof GuildUpdateMaxPresencesEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Max Presences", ((GuildUpdateMaxPresencesEvent) event).getOldMaxPresences() + " presences")); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Max Presences", ((GuildUpdateMaxPresencesEvent) event).getNewMaxPresences() + " presences")); + modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_PRESENCES; + } else if (event instanceof GuildUpdateMFALevelEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old MFA Level", ((GuildUpdateMFALevelEvent) event).getOldMFALevel().name())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New MFA Level", ((GuildUpdateMFALevelEvent) event).getNewMFALevel().name())); + modlogEvent = ModlogEvent.GUILD_UPDATE_MFA_LEVEL; + } else if (event instanceof GuildUpdateNameEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", ((GuildUpdateNameEvent) event).getOldName())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Name", ((GuildUpdateNameEvent) event).getNewName())); + modlogEvent = ModlogEvent.GUILD_UPDATE_NAME; + } else if (event instanceof GuildUpdateNotificationLevelEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Level", ((GuildUpdateNotificationLevelEvent) event).getOldNotificationLevel().name())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Level", ((GuildUpdateNotificationLevelEvent) event).getNewNotificationLevel().name())); + modlogEvent = ModlogEvent.GUILD_UPDATE_NOTIFICATION_LEVEL; + } else if (event instanceof GuildUpdateRegionEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Region", ((GuildUpdateRegionEvent) event).getOldRegion().getName())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Region", ((GuildUpdateRegionEvent) event).getNewRegion().getName())); + modlogEvent = ModlogEvent.GUILD_UPDATE_REGION; + } else if (event instanceof GuildUpdateSplashEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Old Splash", ((GuildUpdateSplashEvent) event).getOldSplashUrl())); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "New Splash", ((GuildUpdateSplashEvent) event).getNewSplashUrl())); + modlogEvent = ModlogEvent.GUILD_UPDATE_SPLASH; + } else if (event instanceof GuildUpdateSystemChannelEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old System Channel", ((GuildUpdateSystemChannelEvent) event).getOldSystemChannel().getName())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New System Channel", ((GuildUpdateSystemChannelEvent) event).getNewSystemChannel().getName())); + modlogEvent = ModlogEvent.GUILD_UPDATE_SYSTEM_CHANNEL; + } else if (event instanceof GuildUpdateVanityCodeEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Vanity Code", ((GuildUpdateVanityCodeEvent) event).getOldVanityCode())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Vanity Url", ((GuildUpdateVanityCodeEvent) event).getOldVanityUrl())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Vanity Code", ((GuildUpdateVanityCodeEvent) event).getNewVanityCode())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Vanity Url", ((GuildUpdateVanityCodeEvent) event).getNewVanityUrl())); + modlogEvent = ModlogEvent.GUILD_UPDATE_VANITY_CODE; + } else if (event instanceof GuildUpdateVerificationLevelEvent) { + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Verification Level", FormatUtils.getVerificationLevelString(((GuildUpdateVerificationLevelEvent) event).getOldVerificationLevel()))); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Verification Level", FormatUtils.getVerificationLevelString(((GuildUpdateVerificationLevelEvent) event).getNewVerificationLevel()))); + modlogEvent = ModlogEvent.GUILD_UPDATE_VERIFICATION_LEVEL; + } else { + return; + } + ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); + }); } public void onGenericStoreChannel(GenericStoreChannelEvent event) { @@ -274,7 +387,7 @@ public static class ListChanges { private final List added = new ArrayList<>(); private final List removed = new ArrayList<>(); - public ListChanges(List originalList, List newList) { + public ListChanges(Collection originalList, Collection newList) { for (T object : originalList) { if (!newList.contains(object)) { removed.add(object); diff --git a/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java index 443c7bf8b..75d1ec9b4 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java @@ -14,6 +14,7 @@ import com.vdurmont.emoji.EmojiManager; import lombok.experimental.UtilityClass; import net.dv8tion.jda.api.entities.Emote; +import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.internal.utils.Checks; import org.apache.commons.lang3.StringUtils; @@ -213,8 +214,8 @@ public static String formatDateTime(OffsetDateTime dateTime, Locale locale) { *

* Both forms follow the relative locale's time formatting rules. * - * @param millis The time to be formatted in milliseconds. - * @param locale The locale for the time to be formatted in. + * @param millis The time to be formatted in milliseconds. + * @param locale The locale for the time to be formatted in. * @param isShort Whether to display in short form or not. * @return The formatted string */ @@ -287,4 +288,15 @@ public static String formatLongTimeMills(long time) { return String.format("%02d:%02d:%02d", hours, mins, seconds); } + public static String getVerificationLevelString(Guild.VerificationLevel verificationLevel) { + switch (verificationLevel.getKey()) { + case 4: + return "(\u256F\u00B0\u25A1\u00B0\uFF09\u256F\uFE35 \u253B\u2501\u253B"; // (╯°□°)╯︵ ┻━┻ + case 5: + return "\u253B\u2501\u253B \uFF90\u30FD(\u0CA0\u76CA\u0CA0)\u30CE\u5F61\u253B\u2501\u253B"; // ┻━┻ ミヽ(ಠ益ಠ)ノ彡┻━┻ + default: + return verificationLevel.name(); + } + } + } From bee58091df9ac53e3ef90345757d739e54357562 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Tue, 19 May 2020 11:57:56 -0500 Subject: [PATCH 010/206] Channel Modlog Events --- .../events/ModlogEventListener.java | 199 +++++++++++++++++- 1 file changed, 191 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 75d79c295..4fb980f55 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -4,17 +4,45 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.audit.ActionType; +import net.dv8tion.jda.api.audit.AuditLogChange; import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.ChannelType; import net.dv8tion.jda.api.entities.Emote; import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.GuildChannel; +import net.dv8tion.jda.api.entities.IPermissionHolder; +import net.dv8tion.jda.api.entities.ISnowflake; +import net.dv8tion.jda.api.entities.Invite; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.events.GenericEvent; +import net.dv8tion.jda.api.events.channel.category.CategoryCreateEvent; +import net.dv8tion.jda.api.events.channel.category.CategoryDeleteEvent; import net.dv8tion.jda.api.events.channel.category.GenericCategoryEvent; +import net.dv8tion.jda.api.events.channel.category.update.CategoryUpdateNameEvent; +import net.dv8tion.jda.api.events.channel.category.update.CategoryUpdatePermissionsEvent; +import net.dv8tion.jda.api.events.channel.category.update.CategoryUpdatePositionEvent; import net.dv8tion.jda.api.events.channel.store.GenericStoreChannelEvent; +import net.dv8tion.jda.api.events.channel.store.StoreChannelCreateEvent; +import net.dv8tion.jda.api.events.channel.store.StoreChannelDeleteEvent; +import net.dv8tion.jda.api.events.channel.store.update.StoreChannelUpdateNameEvent; +import net.dv8tion.jda.api.events.channel.store.update.StoreChannelUpdatePermissionsEvent; +import net.dv8tion.jda.api.events.channel.store.update.StoreChannelUpdatePositionEvent; import net.dv8tion.jda.api.events.channel.text.GenericTextChannelEvent; +import net.dv8tion.jda.api.events.channel.text.TextChannelCreateEvent; +import net.dv8tion.jda.api.events.channel.text.TextChannelDeleteEvent; +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateNameEvent; +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdatePermissionsEvent; +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdatePositionEvent; import net.dv8tion.jda.api.events.channel.voice.GenericVoiceChannelEvent; +import net.dv8tion.jda.api.events.channel.voice.VoiceChannelCreateEvent; +import net.dv8tion.jda.api.events.channel.voice.VoiceChannelDeleteEvent; +import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateNameEvent; +import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdatePermissionsEvent; +import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdatePositionEvent; import net.dv8tion.jda.api.events.emote.EmoteAddedEvent; import net.dv8tion.jda.api.events.emote.EmoteRemovedEvent; import net.dv8tion.jda.api.events.emote.GenericEmoteEvent; @@ -60,6 +88,7 @@ import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.utils.CryptUtils; import org.cascadebot.cascadebot.utils.FormatUtils; +import org.jetbrains.annotations.NotNull; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; @@ -70,7 +99,9 @@ import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; +import java.util.EnumSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @@ -101,10 +132,10 @@ public void onGenericEmote(GenericEmoteEvent event) { List newRoles = ((EmoteUpdateRolesEvent) event).getNewRoles(); ListChanges roleListChanges = new ListChanges<>(oldRoles, newRoles); embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added Roles", - roleListChanges.added.stream().map(role -> role.getName() + " (" + role.getId() + ")") + roleListChanges.getAdded().stream().map(role -> role.getName() + " (" + role.getId() + ")") .collect(Collectors.joining("\n")))); embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed Roles", - roleListChanges.removed.stream().map(role -> role.getName() + " (" + role.getId() + ")") + roleListChanges.getRemoved().stream().map(role -> role.getName() + " (" + role.getId() + ")") .collect(Collectors.joining("\n")))); } else { return; @@ -296,8 +327,8 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { modlogEvent = ModlogEvent.GUILD_UPDATE_EXPLICIT_FILTER; } else if (event instanceof GuildUpdateFeaturesEvent) { ListChanges featuresChanged = new ListChanges<>(((GuildUpdateFeaturesEvent) event).getOldFeatures(), ((GuildUpdateFeaturesEvent) event).getNewFeatures()); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added Features", String.join("\n", featuresChanged.added))); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed Features", String.join("\n", featuresChanged.removed))); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added Features", String.join("\n", featuresChanged.getAdded()))); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed Features", String.join("\n", featuresChanged.getRemoved()))); modlogEvent = ModlogEvent.GUILD_UPDATE_FEATURES; } else if (event instanceof GuildUpdateIconEvent) { embedFieldList.add(new WebhookEmbed.EmbedField(false, "Old Image", ((GuildUpdateIconEvent) event).getOldIconUrl())); @@ -352,21 +383,173 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { }); } - public void onGenericStoreChannel(GenericStoreChannelEvent event) { + //region Channels + public void onGenericStoreChannel(@NotNull GenericStoreChannelEvent event) { + if (event instanceof StoreChannelCreateEvent) { + handleChannelCreateEvents(event.getChannel().getGuild(), ChannelType.STORE, event.getChannel()); + } else if (event instanceof StoreChannelDeleteEvent) { + handleChannelDeleteEvents(event.getChannel().getGuild(), ChannelType.STORE, event.getChannel()); + } else if (event instanceof StoreChannelUpdateNameEvent) { + handleChannelUpdateNameEvents(event.getChannel().getGuild(), ChannelType.STORE, ((StoreChannelUpdateNameEvent) event).getOldName(), event.getChannel()); + } else if (event instanceof StoreChannelUpdatePermissionsEvent) { + handleChannelUpdatePermissionsEvents(event.getChannel().getGuild(), ChannelType.STORE, ((StoreChannelUpdatePermissionsEvent) event).getChangedPermissionHolders(), event.getChannel()); + } else if (event instanceof StoreChannelUpdatePositionEvent) { + handleChannelUpdatePositionEvents(event.getChannel().getGuild(), ChannelType.STORE, ((StoreChannelUpdatePositionEvent) event).getOldPosition(), event.getChannel()); + } + } + public void onGenericTextChannel(@NotNull GenericTextChannelEvent event) { + if (event instanceof TextChannelCreateEvent) { + handleChannelCreateEvents(event.getGuild(), ChannelType.TEXT, event.getChannel()); + } else if (event instanceof TextChannelDeleteEvent) { + handleChannelDeleteEvents(event.getGuild(), ChannelType.TEXT, event.getChannel()); + } else if (event instanceof TextChannelUpdateNameEvent) { + handleChannelUpdateNameEvents(event.getGuild(), ChannelType.TEXT, ((TextChannelUpdateNameEvent) event).getOldName(), event.getChannel()); + } else if (event instanceof TextChannelUpdatePermissionsEvent) { + ((TextChannelUpdatePermissionsEvent) event).getChangedPermissionHolders(); + handleChannelUpdatePermissionsEvents(event.getGuild(), ChannelType.TEXT, ((TextChannelUpdatePermissionsEvent) event).getChangedPermissionHolders(), event.getChannel()); + } else if (event instanceof TextChannelUpdatePositionEvent) { + handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.TEXT, ((TextChannelUpdatePositionEvent) event).getOldPosition(), event.getChannel()); + } } - public void onGenericTextChannel(GenericTextChannelEvent event) { + public void onGenericVoiceChannel(@NotNull GenericVoiceChannelEvent event) { + if (event instanceof VoiceChannelCreateEvent) { + handleChannelCreateEvents(event.getGuild(), ChannelType.VOICE, event.getChannel()); + } else if (event instanceof VoiceChannelDeleteEvent) { + handleChannelDeleteEvents(event.getGuild(), ChannelType.VOICE, event.getChannel()); + } else if (event instanceof VoiceChannelUpdateNameEvent) { + handleChannelUpdateNameEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdateNameEvent) event).getOldName(), event.getChannel()); + } else if (event instanceof VoiceChannelUpdatePermissionsEvent) { + handleChannelUpdatePermissionsEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdatePermissionsEvent) event).getChangedPermissionHolders(), event.getChannel()); + } else if (event instanceof VoiceChannelUpdatePositionEvent) { + handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdatePositionEvent) event).getOldPosition(), event.getChannel()); + } + } + public void onGenericCategory(@NotNull GenericCategoryEvent event) { + if (event instanceof CategoryCreateEvent) { + handleChannelCreateEvents(event.getGuild(), ChannelType.CATEGORY, event.getCategory()); + } else if (event instanceof CategoryDeleteEvent) { + handleChannelDeleteEvents(event.getGuild(), ChannelType.CATEGORY, event.getCategory()); + } else if (event instanceof CategoryUpdateNameEvent) { + handleChannelUpdateNameEvents(event.getGuild(), ChannelType.CATEGORY, ((CategoryUpdateNameEvent) event).getOldName(), event.getCategory()); + } else if (event instanceof CategoryUpdatePermissionsEvent) { + handleChannelUpdatePermissionsEvents(event.getGuild(), ChannelType.CATEGORY, ((CategoryUpdatePermissionsEvent) event).getChangedPermissionHolders(), event.getCategory()); + } else if (event instanceof CategoryUpdatePositionEvent) { + handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.CATEGORY, ((CategoryUpdatePositionEvent) event).getOldPosition(), event.getCategory()); + } } + //endregion - public void onGenericVoiceChannel(GenericVoiceChannelEvent event) { + //region Channel handlers + private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChannel channel) { + ModlogEvent event = ModlogEvent.CHANNEL_CREATED; + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + guild.retrieveAuditLogs().queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + User responsible = null; + if (entry.getType().equals(ActionType.CHANNEL_CREATE)) { + responsible = entry.getUser(); + } + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); + ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + }); + } + private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChannel channel) { + ModlogEvent event = ModlogEvent.CHANNEL_DELETED; + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + guild.retrieveAuditLogs().queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + User responsible = null; + if (entry.getType().equals(ActionType.CHANNEL_DELETE)) { + responsible = entry.getUser(); + } + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); + ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + }); } - public void onGenericCategory(GenericCategoryEvent event) { + private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String oldName, GuildChannel channel) { + ModlogEvent event = ModlogEvent.CHANNEL_NAME_UPDATED; + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + guild.retrieveAuditLogs().queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + User responsible = null; + if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { + responsible = entry.getUser(); + } + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", oldName)); + ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + }); + } + + private void handleChannelUpdatePermissionsEvents(Guild guild, ChannelType type, List changedPermissionHolders, GuildChannel channel) { + ModlogEvent event = ModlogEvent.CHANNEL_PERMISSIONS_UPDATED; + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + guild.retrieveAuditLogs().queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + User responsible = null; + if (entry.getType().equals(ActionType.CHANNEL_UPDATE) || entry.getType().equals(ActionType.CHANNEL_OVERRIDE_UPDATE)) { + responsible = entry.getUser(); + Map auditLogChangeMap = entry.getChanges(); + for (Map.Entry auditLogChangeEntry : auditLogChangeMap.entrySet()) { + AuditLogChange value = auditLogChangeEntry.getValue(); + EnumSet oldPermissions = Permission.getPermissions(((Integer) value.getOldValue()).longValue()); + EnumSet newPermissions = Permission.getPermissions(((Integer) value.getNewValue()).longValue()); + ListChanges permissionListChanges = new ListChanges<>(oldPermissions, newPermissions); + String change = "unknown"; + switch (auditLogChangeEntry.getKey()) { + case "allow": + change = "Allowed"; + break; + case "deny": + change = "Denied"; + break; + } + String affectedType = entry.getOptionByName("type"); + long affectedId = entry.getTargetIdLong(); + String affected = "unknown"; + switch (affectedType) { + case "role": + affected = CascadeBot.INS.getShardManager().getRoleById(affectedId).getName(); + break; + case "user": + affected = CascadeBot.INS.getShardManager().getUserById(affectedId).getAsTag(); + break; + } + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added " + change + " Permissions to " + affected, permissionListChanges.getAdded().stream().map(permission -> permission.getName()).collect(Collectors.joining("\n")))); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed " + change + " Permissions to " + affected, permissionListChanges.getRemoved().stream().map(permission -> permission.getName()).collect(Collectors.joining("\n")))); + } + } + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); + ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + }); + } + private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, int oldPos, GuildChannel channel) { + ModlogEvent event = ModlogEvent.CHANNEL_POSITION_UPDATED; + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + guild.retrieveAuditLogs().queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + User responsible = null; + if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { + responsible = entry.getUser(); + } + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Position", String.valueOf(oldPos))); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Position", String.valueOf(channel.getPosition()))); + ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + }); } + //endregion public void onGenericRole(GenericRoleEvent event) { From 0090498d9e6bbde9bd14b257ddbcb4435cb44929 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Tue, 19 May 2020 12:28:55 -0500 Subject: [PATCH 011/206] Role Events --- .../events/ModlogEventListener.java | 78 +++++++++++++++---- 1 file changed, 63 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 4fb980f55..583294bad 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -13,12 +13,9 @@ import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.GuildChannel; import net.dv8tion.jda.api.entities.IPermissionHolder; -import net.dv8tion.jda.api.entities.ISnowflake; -import net.dv8tion.jda.api.entities.Invite; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.events.GenericEvent; import net.dv8tion.jda.api.events.channel.category.CategoryCreateEvent; import net.dv8tion.jda.api.events.channel.category.CategoryDeleteEvent; import net.dv8tion.jda.api.events.channel.category.GenericCategoryEvent; @@ -77,6 +74,14 @@ import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent; import net.dv8tion.jda.api.events.role.GenericRoleEvent; +import net.dv8tion.jda.api.events.role.RoleCreateEvent; +import net.dv8tion.jda.api.events.role.RoleDeleteEvent; +import net.dv8tion.jda.api.events.role.update.RoleUpdateColorEvent; +import net.dv8tion.jda.api.events.role.update.RoleUpdateHoistedEvent; +import net.dv8tion.jda.api.events.role.update.RoleUpdateMentionableEvent; +import net.dv8tion.jda.api.events.role.update.RoleUpdateNameEvent; +import net.dv8tion.jda.api.events.role.update.RoleUpdatePermissionsEvent; +import net.dv8tion.jda.api.events.role.update.RoleUpdatePositionEvent; import net.dv8tion.jda.api.events.user.update.UserUpdateDiscriminatorEvent; import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; @@ -111,7 +116,7 @@ public class ModlogEventListener extends ListenerAdapter { public void onGenericEmote(GenericEmoteEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); Emote emote = event.getEmote(); - event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { + event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); User user = null; if (entry.getType().equals(ActionType.EMOTE_UPDATE) || entry.getType().equals(ActionType.EMOTE_CREATE) || entry.getType().equals(ActionType.EMOTE_DELETE)) { @@ -147,7 +152,7 @@ public void onGenericEmote(GenericEmoteEvent event) { public void onGenericGuildMember(GenericGuildMemberEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); User user = event.getMember().getUser(); - event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { + event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent; @@ -191,7 +196,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { public void onGuildBan(GuildBanEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); User user = event.getUser(); - event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { + event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent = ModlogEvent.GUILD_USER_BANNED; @@ -209,7 +214,7 @@ public void onGuildBan(GuildBanEvent event) { public void onGuildUnban(GuildUnbanEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); User user = event.getUser(); - event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { + event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent = ModlogEvent.GUILD_USER_UNBANNED; @@ -236,7 +241,7 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { if (affected == null) { return; } - event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { + event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); ModlogEvent modlogEvent; User responsible; @@ -297,7 +302,7 @@ private String getMessageFromJson(JsonObject jsonObject) { public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { Guild affected = event.getEntity(); GuildData guildData = GuildDataManager.getGuildData(affected.getIdLong()); - event.getGuild().retrieveAuditLogs().queue(auditLogEntries -> { + event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); List embedFieldList = new ArrayList<>(); User responsible = null; @@ -446,7 +451,7 @@ public void onGenericCategory(@NotNull GenericCategoryEvent event) { private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChannel channel) { ModlogEvent event = ModlogEvent.CHANNEL_CREATED; GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().queue(auditLogEntries -> { + guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); List embedFieldList = new ArrayList<>(); User responsible = null; @@ -461,7 +466,7 @@ private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChann private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChannel channel) { ModlogEvent event = ModlogEvent.CHANNEL_DELETED; GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().queue(auditLogEntries -> { + guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); List embedFieldList = new ArrayList<>(); User responsible = null; @@ -476,7 +481,7 @@ private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChann private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String oldName, GuildChannel channel) { ModlogEvent event = ModlogEvent.CHANNEL_NAME_UPDATED; GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().queue(auditLogEntries -> { + guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); List embedFieldList = new ArrayList<>(); User responsible = null; @@ -492,7 +497,7 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String private void handleChannelUpdatePermissionsEvents(Guild guild, ChannelType type, List changedPermissionHolders, GuildChannel channel) { ModlogEvent event = ModlogEvent.CHANNEL_PERMISSIONS_UPDATED; GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().queue(auditLogEntries -> { + guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); List embedFieldList = new ArrayList<>(); User responsible = null; @@ -536,7 +541,7 @@ private void handleChannelUpdatePermissionsEvents(Guild guild, ChannelType type, private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, int oldPos, GuildChannel channel) { ModlogEvent event = ModlogEvent.CHANNEL_POSITION_UPDATED; GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().queue(auditLogEntries -> { + guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); List embedFieldList = new ArrayList<>(); User responsible = null; @@ -552,7 +557,50 @@ private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, in //endregion public void onGenericRole(GenericRoleEvent event) { - + GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); + event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + User responsible = null; + ModlogEvent modlogEvent; + if (entry.getType().equals(ActionType.ROLE_CREATE) || entry.getType().equals(ActionType.ROLE_DELETE) || entry.getType().equals(ActionType.ROLE_UPDATE)) { + responsible = entry.getUser(); + } + Role affected = event.getRole(); + if (event instanceof RoleCreateEvent) { + modlogEvent = ModlogEvent.ROLE_CREATED; + } else if (event instanceof RoleDeleteEvent) { + modlogEvent = ModlogEvent.ROLE_DELETED; + } else if (event instanceof RoleUpdateColorEvent) { + modlogEvent = ModlogEvent.ROLE_COLOR_UPDATED; + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Color", ((RoleUpdateColorEvent) event).getOldColor().toString())); // TODO properly show color + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Color", ((RoleUpdateColorEvent) event).getNewColor().toString())); + } else if (event instanceof RoleUpdateHoistedEvent) { + modlogEvent = ModlogEvent.ROLE_HOIST_UPDATED; + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Hoisted", String.valueOf(!((RoleUpdateHoistedEvent) event).wasHoisted()))); + } else if (event instanceof RoleUpdateMentionableEvent) { + modlogEvent = ModlogEvent.ROLE_MENTIONABLE_UPDATED; + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Mentionable", String.valueOf(!((RoleUpdateMentionableEvent) event).wasMentionable()))); + } else if (event instanceof RoleUpdateNameEvent) { + modlogEvent = ModlogEvent.ROLE_NAME_UPDATED; + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", ((RoleUpdateNameEvent) event).getOldName())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Name", ((RoleUpdateNameEvent) event).getNewName())); + } else if (event instanceof RoleUpdatePermissionsEvent) { + modlogEvent = ModlogEvent.ROLE_PERMISSIONS_UPDATED; + EnumSet oldPermissions = ((RoleUpdatePermissionsEvent) event).getOldPermissions(); + EnumSet newPermissions = ((RoleUpdatePermissionsEvent) event).getNewPermissions(); + ListChanges permissionListChanges = new ListChanges<>(oldPermissions, newPermissions); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added Permissions", permissionListChanges.getAdded().stream().map(permission -> permission.getName()).collect(Collectors.joining("\n")))); + embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed Permissions", permissionListChanges.getRemoved().stream().map(permission -> permission.getName()).collect(Collectors.joining("\n")))); + } else if (event instanceof RoleUpdatePositionEvent) { + modlogEvent = ModlogEvent.ROLE_POSITION_UPDATED; + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Position", String.valueOf(((RoleUpdatePositionEvent) event).getOldPosition()))); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Position", String.valueOf(((RoleUpdatePositionEvent) event).getNewPosition()))); + } else { + return; + } + ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); + }); } //region Username updates From 3b93490cb1f2b9aeadf079b16bb00becdf385858 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Tue, 19 May 2020 12:33:53 -0500 Subject: [PATCH 012/206] User events --- .../cascadebot/events/ModlogEventListener.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 583294bad..a9902d978 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -605,11 +605,18 @@ public void onGenericRole(GenericRoleEvent event) { //region Username updates public void onUserUpdateName(UserUpdateNameEvent event) { - + // TODO propagate to guilds + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", event.getOldName())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Name", event.getNewName())); + ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_NAME_UPDATED, event.getUser(), event.getUser(), embedFieldList); } public void onUserUpdateDiscriminator(UserUpdateDiscriminatorEvent event) { - + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Discriminator", event.getOldDiscriminator())); + embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Discriminator", event.getNewDiscriminator())); + ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_NAME_UPDATED, event.getUser(), event.getUser(), embedFieldList); } //endregion From 52b3d43952d91f8228549da80c97c55fc5f4668b Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 21 May 2020 17:58:44 -0500 Subject: [PATCH 013/206] Send webhook message Also creation of webhook --- .../org/cascadebot/cascadebot/CascadeBot.java | 2 + .../data/objects/GuildSettingsModeration.java | 23 -- .../events/ModlogEventListener.java | 15 +- .../cascadebot/moderation/ModlogEvent.java | 238 +++++++++--------- .../runnables/MessageReceivedRunnable.java | 3 + .../cascadebot/utils/PurgeUtils.java | 2 +- .../cascadebot/data/objects/GuildData.kt | 1 + .../data/objects/GuildSettingsModeration.kt | 138 ++++++++++ 8 files changed, 283 insertions(+), 139 deletions(-) delete mode 100644 src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.java create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 29e5d5163..19e8dde57 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -10,6 +10,8 @@ import ch.qos.logback.contrib.json.classic.JsonLayout; import ch.qos.logback.core.ConsoleAppender; import ch.qos.logback.core.encoder.LayoutWrappingEncoder; +import club.minnced.discord.webhook.WebhookClient; +import club.minnced.discord.webhook.WebhookClientBuilder; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory; diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.java deleted file mode 100644 index 9bdd94f6d..000000000 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2019 CascadeBot. All rights reserved. - * Licensed under the MIT license. - */ - -package org.cascadebot.cascadebot.data.objects; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.cascadebot.cascadebot.commandmeta.Module; - -@SettingsContainer(module = Module.MODERATION) -@Getter -@Setter -@NoArgsConstructor(access = AccessLevel.PUBLIC) -public class GuildSettingsModeration { - - @Setting - private boolean purgePinnedMessages = false; - -} diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index a9902d978..e13536ecd 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -146,6 +146,7 @@ public void onGenericEmote(GenericEmoteEvent event) { return; } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, user, emote, embedFieldList); + guildData.getModeration().sendModlogEvent(eventStore); }); } @@ -189,6 +190,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { return; } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); + guildData.getModeration().sendModlogEvent(eventStore); }); } @@ -208,6 +210,7 @@ public void onGuildBan(GuildBanEvent event) { } } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); + guildData.getModeration().sendModlogEvent(eventStore); }); } @@ -223,6 +226,7 @@ public void onGuildUnban(GuildUnbanEvent event) { responsible = entry.getUser(); } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); + guildData.getModeration().sendModlogEvent(eventStore); }); } //endregion @@ -253,6 +257,7 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { responsible = affected; } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); + guildData.getModeration().sendModlogEvent(eventStore); }); } @@ -272,6 +277,7 @@ public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { } ModlogEvent modlogEvent = ModlogEvent.GUILD_MESSAGE_UPDATED; ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, null, affected, embedFieldList); + guildData.getModeration().sendModlogEvent(eventStore); } private String getMessageFromJson(JsonObject jsonObject) { @@ -385,6 +391,7 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { return; } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); + guildData.getModeration().sendModlogEvent(eventStore); }); } @@ -460,6 +467,7 @@ private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChann } embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + guildData.getModeration().sendModlogEvent(modlogEventStore); }); } @@ -475,6 +483,7 @@ private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChann } embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + guildData.getModeration().sendModlogEvent(modlogEventStore); }); } @@ -491,6 +500,7 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", oldName)); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + guildData.getModeration().sendModlogEvent(modlogEventStore); }); } @@ -535,6 +545,7 @@ private void handleChannelUpdatePermissionsEvents(Guild guild, ChannelType type, } embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + guildData.getModeration().sendModlogEvent(modlogEventStore); }); } @@ -552,6 +563,7 @@ private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, in embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Position", String.valueOf(oldPos))); embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Position", String.valueOf(channel.getPosition()))); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + guildData.getModeration().sendModlogEvent(modlogEventStore); }); } //endregion @@ -600,6 +612,7 @@ public void onGenericRole(GenericRoleEvent event) { return; } ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); + guildData.getModeration().sendModlogEvent(modlogEventStore); }); } @@ -616,7 +629,7 @@ public void onUserUpdateDiscriminator(UserUpdateDiscriminatorEvent event) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Discriminator", event.getOldDiscriminator())); embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Discriminator", event.getNewDiscriminator())); - ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_NAME_UPDATED, event.getUser(), event.getUser(), embedFieldList); + ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_DISCRIMINATOR_UPDATED, event.getUser(), event.getUser(), embedFieldList); } //endregion diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java b/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java index 2b1686a30..96beae7df 100644 --- a/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java +++ b/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java @@ -1,6 +1,7 @@ package org.cascadebot.cascadebot.moderation; import lombok.Getter; +import org.cascadebot.cascadebot.messaging.MessageType; import java.util.ArrayList; import java.util.Arrays; @@ -11,117 +12,117 @@ public enum ModlogEvent { - EMOTE_CREATED(Category.EMOTE), - EMOTE_DELETED(Category.EMOTE), - EMOTE_UPDATED_NAME(Category.EMOTE), - EMOTE_UPDATED_ROLES(Category.EMOTE), - - GUILD_MEMBER_JOINED(Category.GUILD, Category.GUILD_MEMBER), - GUILD_MEMBER_LEFT(Category.GUILD, Category.GUILD_MEMBER), - GUILD_MEMBER_KICKED(Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), - GUILD_MEMBER_ROLE_ADDED(Category.GUILD, Category.GUILD_MEMBER), - GUILD_MEMBER_ROLE_REMOVED(Category.GUILD, Category.GUILD_MEMBER), - GUILD_MEMBER_NICKNAME_UPDATED(Category.GUILD, Category.GUILD_MEMBER), - - GUILD_USER_BANNED(Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), - GUILD_USER_UNBANNED(Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), - - GUILD_MESSAGE_DELETED(Category.GUILD, Category.GUILD_MESSAGE), - GUILD_MESSAGE_DELETED_SELF(Category.GUILD, Category.GUILD_MESSAGE), - GUILD_MESSAGE_UPDATED(Category.GUILD, Category.GUILD_MESSAGE), - - GUILD_BOOST_COUNT_UPDATED(Category.GUILD, Category.GUILD_BOOST), - GUILD_BOOST_TIER_UPDATED(Category.GUILD, Category.GUILD_BOOST), - - GUILD_UPDATE_AFK_CHANNEL(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_AFK_TIMEOUT(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_BANNER(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_DESCRIPTION(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_EXPLICIT_FILTER(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_FEATURES(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_ICON(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_MAX_MEMBERS(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_MAX_PRESENCES(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_MFA_LEVEL(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_NAME(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_NOTIFICATION_LEVEL(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_REGION(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_SPLASH(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_SYSTEM_CHANNEL(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_VANITY_CODE(Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_VERIFICATION_LEVEL(Category.GUILD, Category.GUILD_SETTINGS), - - VOICE_DEAFEN(Category.VOICE), - VOICE_MUTE(Category.VOICE), - VOICE_SERVER_DEAFEN(Category.VOICE, Category.MODERATION), - VOICE_SERVER_MUTE(Category.VOICE, Category.MODERATION), - VOICE_JOIN(Category.VOICE), - VOICE_LEAVE(Category.VOICE), - VOICE_MOVE(Category.VOICE), - VOICE_DISCONNECT(Category.VOICE, Category.MODERATION), - - ROLE_CREATED(Category.ROLE), - ROLE_DELETED(Category.ROLE), - ROLE_COLOR_UPDATED(Category.ROLE), - ROLE_HOIST_UPDATED(Category.ROLE), - ROLE_MENTIONABLE_UPDATED(Category.ROLE), - ROLE_NAME_UPDATED(Category.ROLE), - ROLE_PERMISSIONS_UPDATED(Category.ROLE), - ROLE_POSITION_UPDATED(Category.ROLE), - - USER_DISCRIMINATOR_UPDATED(Category.USER), - USER_NAME_UPDATED(Category.USER), - - CHANNEL_CREATED(Category.CHANNEL), - CHANNEL_DELETED(Category.CHANNEL), - CHANNEL_NAME_UPDATED(Category.CHANNEL), - CHANNEL_PERMISSIONS_UPDATED(Category.CHANNEL), - CHANNEL_POSITION_UPDATED(Category.CHANNEL), - CHANNEL_PARENT_UPDATED(Category.CHANNEL), - - VOICE_CHANNEL_BITRATE_UPDATED(Category.CHANNEL), - VOICE_CHANNEL_USER_LIMIT_UPDATED(Category.CHANNEL), - - TEXT_CHANNEL_NSFW_UPDATED(Category.CHANNEL), - TEXT_CHANNEL_SLOWMODE_UPDATED(Category.CHANNEL), - TEXT_CHANNEL_TOPIC_UPDATED(Category.CHANNEL), - - CASCADE_PERMISSIONS_GROUP_CREATED(Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_GROUP_DELETED(Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD(Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE(Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_GROUP_LINK(Category.CASCADE, Category.CASCADE_PERMISSIONS), - - CASCADE_PERMISSIONS_USER_PERMISSION_ADD(Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE(Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_USER_GROUP_ADD(Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_USER_GROUP_REMOVE(Category.CASCADE, Category.CASCADE_PERMISSIONS), - - CASCADE_SETTINGS_UPDATED(Category.CASCADE), - - CASCADE_MODULE_UPDATED(Category.CASCADE), - - CASCADE_COMMAND_RUN(Category.CASCADE), - CASCADE_COMMAND_RUN_ERROR(Category.CASCADE), - - CASCADE_PLAYLIST_CREATED(Category.CASCADE), - CASCADE_PLAYLIST_DELETED(Category.CASCADE), - - CASCADE_TEMP_MUTE(Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_TEMP_BAN(Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_SOFT_BAN(Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_PURGE(Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - - CASCADE_WHITELIST(Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_BLACKLIST(Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - - CASCADE_SCRIPT_CREATED(Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_SCRIPT_DELETED(Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_SCRIPT_UPDATED(Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - - CASCADE_TAG_CREATED(Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_TAG_DELETED(Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_TAG_UPDATED(Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS); + EMOTE_CREATED(MessageType.INFO, Category.EMOTE), + EMOTE_DELETED(MessageType.INFO, Category.EMOTE), + EMOTE_UPDATED_NAME(MessageType.INFO, Category.EMOTE), + EMOTE_UPDATED_ROLES(MessageType.INFO, Category.EMOTE), + + GUILD_MEMBER_JOINED(MessageType.INFO, Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_LEFT(MessageType.INFO, Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_KICKED(MessageType.WARNING, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + GUILD_MEMBER_ROLE_ADDED(MessageType.WARNING, Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_ROLE_REMOVED(MessageType.WARNING, Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_NICKNAME_UPDATED(MessageType.INFO, Category.GUILD, Category.GUILD_MEMBER), + + GUILD_USER_BANNED(MessageType.DANGER, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + GUILD_USER_UNBANNED(MessageType.DANGER, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + + GUILD_MESSAGE_DELETED(MessageType.WARNING, Category.GUILD, Category.GUILD_MESSAGE), + GUILD_MESSAGE_DELETED_SELF(MessageType.INFO, Category.GUILD, Category.GUILD_MESSAGE), + GUILD_MESSAGE_UPDATED(MessageType.INFO, Category.GUILD, Category.GUILD_MESSAGE), + + GUILD_BOOST_COUNT_UPDATED(MessageType.INFO, Category.GUILD, Category.GUILD_BOOST), + GUILD_BOOST_TIER_UPDATED(MessageType.INFO, Category.GUILD, Category.GUILD_BOOST), + + GUILD_UPDATE_AFK_CHANNEL(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_AFK_TIMEOUT(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_BANNER(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_DESCRIPTION(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_EXPLICIT_FILTER(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_FEATURES(MessageType.INFO, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_ICON(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_MAX_MEMBERS(MessageType.INFO, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_MAX_PRESENCES(MessageType.INFO, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_MFA_LEVEL(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_NAME(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_NOTIFICATION_LEVEL(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_REGION(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_SPLASH(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_SYSTEM_CHANNEL(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_VANITY_CODE(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_VERIFICATION_LEVEL(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), + + VOICE_DEAFEN(MessageType.INFO, Category.VOICE), + VOICE_MUTE(MessageType.INFO, Category.VOICE), + VOICE_SERVER_DEAFEN(MessageType.WARNING, Category.VOICE, Category.MODERATION), + VOICE_SERVER_MUTE(MessageType.WARNING, Category.VOICE, Category.MODERATION), + VOICE_JOIN(MessageType.INFO, Category.VOICE), + VOICE_LEAVE(MessageType.INFO, Category.VOICE), + VOICE_MOVE(MessageType.WARNING, Category.VOICE), + VOICE_DISCONNECT(MessageType.WARNING, Category.VOICE, Category.MODERATION), + + ROLE_CREATED(MessageType.WARNING, Category.ROLE), + ROLE_DELETED(MessageType.WARNING, Category.ROLE), + ROLE_COLOR_UPDATED(MessageType.WARNING, Category.ROLE), + ROLE_HOIST_UPDATED(MessageType.WARNING, Category.ROLE), + ROLE_MENTIONABLE_UPDATED(MessageType.WARNING, Category.ROLE), + ROLE_NAME_UPDATED(MessageType.WARNING, Category.ROLE), + ROLE_PERMISSIONS_UPDATED(MessageType.WARNING, Category.ROLE), + ROLE_POSITION_UPDATED(MessageType.WARNING, Category.ROLE), + + USER_DISCRIMINATOR_UPDATED(MessageType.INFO, Category.USER), + USER_NAME_UPDATED(MessageType.INFO, Category.USER), + + CHANNEL_CREATED(MessageType.WARNING, Category.CHANNEL), + CHANNEL_DELETED(MessageType.WARNING, Category.CHANNEL), + CHANNEL_NAME_UPDATED(MessageType.WARNING, Category.CHANNEL), + CHANNEL_PERMISSIONS_UPDATED(MessageType.WARNING, Category.CHANNEL), + CHANNEL_POSITION_UPDATED(MessageType.WARNING, Category.CHANNEL), + CHANNEL_PARENT_UPDATED(MessageType.WARNING, Category.CHANNEL), + + VOICE_CHANNEL_BITRATE_UPDATED(MessageType.WARNING, Category.CHANNEL), + VOICE_CHANNEL_USER_LIMIT_UPDATED(MessageType.WARNING, Category.CHANNEL), + + TEXT_CHANNEL_NSFW_UPDATED(MessageType.WARNING, Category.CHANNEL), + TEXT_CHANNEL_SLOWMODE_UPDATED(MessageType.WARNING, Category.CHANNEL), + TEXT_CHANNEL_TOPIC_UPDATED(MessageType.WARNING, Category.CHANNEL), + + CASCADE_PERMISSIONS_GROUP_CREATED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_DELETED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_LINK(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), + + CASCADE_PERMISSIONS_USER_PERMISSION_ADD(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_USER_GROUP_ADD(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_USER_GROUP_REMOVE(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), + + CASCADE_SETTINGS_UPDATED(MessageType.WARNING, Category.CASCADE), + + CASCADE_MODULE_UPDATED(MessageType.WARNING, Category.CASCADE), + + CASCADE_COMMAND_RUN(MessageType.INFO, Category.CASCADE), + CASCADE_COMMAND_RUN_ERROR(MessageType.WARNING, Category.CASCADE), + + CASCADE_PLAYLIST_CREATED(MessageType.INFO, Category.CASCADE), + CASCADE_PLAYLIST_DELETED(MessageType.INFO, Category.CASCADE), + + CASCADE_TEMP_MUTE(MessageType.DANGER, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_TEMP_BAN(MessageType.DANGER, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_SOFT_BAN(MessageType.DANGER, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_PURGE(MessageType.DANGER, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + + CASCADE_WHITELIST(MessageType.WARNING, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_BLACKLIST(MessageType.WARNING, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + + CASCADE_SCRIPT_CREATED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_SCRIPT_DELETED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_SCRIPT_UPDATED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + + CASCADE_TAG_CREATED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_TAG_DELETED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_TAG_UPDATED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS); @Getter private static Map> modlogCategoryMap = new HashMap<>(); @@ -139,11 +140,21 @@ public enum ModlogEvent { } } - @Getter private final List categories; - ModlogEvent(Category... categories) { + private final MessageType messageType; + + ModlogEvent(MessageType messageType, Category... categories) { this.categories = Arrays.asList(categories); + this.messageType = messageType; + } + + public List getCategories() { + return categories; + } + + public MessageType getMessageType() { + return messageType; } public enum Category { @@ -165,5 +176,4 @@ public enum Category { CASCADE_CUSTOM_COMMANDS } - } diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java index 4ecacbef8..d25427bdf 100644 --- a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java +++ b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java @@ -29,6 +29,9 @@ public void run() { while (!ShutdownHandler.SHUTDOWN_LOCK.get()) { try { GuildMessageReceivedEvent event = queue.take(); + if (event.getMember() == null) { + return; + } String message = ""; if (Config.INS.getEncryptKey() != null) { try { diff --git a/src/main/java/org/cascadebot/cascadebot/utils/PurgeUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/PurgeUtils.java index aa54b20ed..c35af7ccc 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/PurgeUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/PurgeUtils.java @@ -44,7 +44,7 @@ public static void purge(CommandContext context, PurgeCriteria type, int amount, break; } - if (!context.getData().getModeration().isPurgePinnedMessages() && message.isPinned()) { + if (!context.getData().getModeration().getPurgePinnedMessages() && message.isPinned()) { continue; } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index b3fa549ab..b24a27390 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -56,6 +56,7 @@ class GuildData(@field:Id val guildId: Long) { fun onGuildLoaded() { loadMusicSettings() permissionsManager.registerPermissions(this) + moderation.buildWebhookClients() } private fun loadMusicSettings() { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt new file mode 100644 index 000000000..7eba7deca --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -0,0 +1,138 @@ +package org.cascadebot.cascadebot.data.objects + +import club.minnced.discord.webhook.WebhookClient +import club.minnced.discord.webhook.WebhookClientBuilder +import club.minnced.discord.webhook.send.WebhookEmbed +import club.minnced.discord.webhook.send.WebhookEmbed.EmbedField +import club.minnced.discord.webhook.send.WebhookEmbed.EmbedTitle +import club.minnced.discord.webhook.send.WebhookEmbedBuilder +import de.bild.codec.annotations.Transient +import net.dv8tion.jda.api.entities.Emote +import net.dv8tion.jda.api.entities.Guild +import net.dv8tion.jda.api.entities.ISnowflake +import net.dv8tion.jda.api.entities.Role +import net.dv8tion.jda.api.entities.TextChannel +import net.dv8tion.jda.api.entities.User +import org.cascadebot.cascadebot.commandmeta.Module +import org.cascadebot.cascadebot.moderation.ModlogEvent +import java.util.ArrayList +import java.util.Collections +import java.util.function.Consumer + +@SettingsContainer(module = Module.MODERATION) +class GuildSettingsModeration() { + + @Setting + public val purgePinnedMessages: Boolean = false + + private val modlogEvents: MutableList = ArrayList() + + fun sendModlogEvent(modlogEventStore: ModlogEventStore) { + val eventsInfo: List = getEventInfoForEvent(modlogEventStore.trigger) + for (eventInfo in eventsInfo) { + eventInfo.sendEvent(modlogEventStore); + } + // TODO add to list for dashboard + } + + private fun getEventInfoForEvent(event: ModlogEvent): List { + val channelModlogEventsInfos: MutableList = ArrayList() + for (channelModlogEventsInfo in modlogEvents) { + if (channelModlogEventsInfo.getEvents().contains(event)) { + channelModlogEventsInfos.add(channelModlogEventsInfo) + } + } + return channelModlogEventsInfos + } + + fun getModlogEvents(): List { + return modlogEvents + } + + fun buildWebhookClients() { + for (channelModlogEventsInfo in modlogEvents) { + channelModlogEventsInfo.buildWebhookClient() + } + } + + fun createModlogEventsInfo(channel: TextChannel, consumer: Consumer) { + channel.createWebhook("Cascade-modlog").queue { webhook -> + val eventsInfo = ChannelModlogEventsInfo(channel.idLong, webhook.idLong, webhook.token!!) + modlogEvents.add(eventsInfo) + consumer.accept(eventsInfo) + } + } + + class ChannelModlogEventsInfo { + private val events: MutableList = ArrayList() + private var channelId: Long = 0 + private var webhookId: Long = 0 + private var webhookToken: String = "" + + @Transient + @kotlin.jvm.Transient + private var webhookClient: WebhookClient? = null + + private constructor() {} + constructor(channelId: Long, webhookId: Long, webhookToken: String) { + this.channelId = channelId + this.webhookId = webhookId + this.webhookToken = webhookToken + buildWebhookClient() + } + + fun buildWebhookClient() { + webhookClient = WebhookClientBuilder(webhookId, webhookToken).build() + } + + fun getEvents(): List { + return Collections.unmodifiableList(events) + } + + fun addEvent(event: ModlogEvent) { + events.add(event) + } + + fun removeEvent(event: ModlogEvent) { + events.remove(event) + } + + fun sendEvent(modlogEventStore: ModlogEventStore) { + val webhookEmbedBuilder = WebhookEmbedBuilder() + webhookEmbedBuilder.setTitle(EmbedTitle(modlogEventStore.trigger.name, null)) + val affected: ISnowflake = modlogEventStore.affected; + var affectedType = "" + val affectedStr = when (affected) { + + is User -> { + affectedType = "User"; + affected.name + " (" + affected.id + ")" + } + is Role -> { + affectedType = "Role" + affected.name + " (" + affected.id + ")" + } + is Emote -> { + affectedType = "Emote" + affected.name + } + is Guild -> { + affectedType = "Guild" + null + } + else -> null + } + if (affectedStr != null) { + webhookEmbedBuilder.addField(EmbedField(true, "Affected $affectedType", affectedStr)) + } + for (embedField in modlogEventStore.extraInfo) { + webhookEmbedBuilder.addField(embedField) + } + webhookEmbedBuilder.setColor(modlogEventStore.trigger.messageType.color.rgb) + if (modlogEventStore.responsible != null) { + webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventStore.responsible.name + " (" + modlogEventStore.responsible.id + ")", null)) + } + webhookClient?.send(webhookEmbedBuilder.build()); + } + } +} From de08257208715cdcc2b1a8ad140f110d9f4cdd2e Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 21 May 2020 18:07:58 -0500 Subject: [PATCH 014/206] Store ChannelModlogEventsInfo in a map --- .../data/objects/GuildSettingsModeration.kt | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 7eba7deca..c5cc63f6c 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -10,11 +10,14 @@ import de.bild.codec.annotations.Transient import net.dv8tion.jda.api.entities.Emote import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.entities.ISnowflake +import net.dv8tion.jda.api.entities.Icon import net.dv8tion.jda.api.entities.Role import net.dv8tion.jda.api.entities.TextChannel import net.dv8tion.jda.api.entities.User +import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.moderation.ModlogEvent +import java.net.URL import java.util.ArrayList import java.util.Collections import java.util.function.Consumer @@ -25,7 +28,7 @@ class GuildSettingsModeration() { @Setting public val purgePinnedMessages: Boolean = false - private val modlogEvents: MutableList = ArrayList() + private val modlogEvents: MutableMap = HashMap() fun sendModlogEvent(modlogEventStore: ModlogEventStore) { val eventsInfo: List = getEventInfoForEvent(modlogEventStore.trigger) @@ -37,35 +40,34 @@ class GuildSettingsModeration() { private fun getEventInfoForEvent(event: ModlogEvent): List { val channelModlogEventsInfos: MutableList = ArrayList() - for (channelModlogEventsInfo in modlogEvents) { - if (channelModlogEventsInfo.getEvents().contains(event)) { - channelModlogEventsInfos.add(channelModlogEventsInfo) + for (entry in modlogEvents) { + if (entry.value.getEvents().contains(event)) { + channelModlogEventsInfos.add(entry.value) } } return channelModlogEventsInfos } fun getModlogEvents(): List { - return modlogEvents + return modlogEvents.map { entry -> entry.value } } fun buildWebhookClients() { - for (channelModlogEventsInfo in modlogEvents) { - channelModlogEventsInfo.buildWebhookClient() + for (entry in modlogEvents) { + entry.value.buildWebhookClient() } } - fun createModlogEventsInfo(channel: TextChannel, consumer: Consumer) { - channel.createWebhook("Cascade-modlog").queue { webhook -> - val eventsInfo = ChannelModlogEventsInfo(channel.idLong, webhook.idLong, webhook.token!!) - modlogEvents.add(eventsInfo) + private fun createModlogEventsInfo(channel: TextChannel, consumer: Consumer) { + channel.createWebhook("Cascade-modlog").setAvatar(Icon.from(URL(CascadeBot.INS.client.selfUser.avatarUrl).openStream())).queue { webhook -> + val eventsInfo = ChannelModlogEventsInfo(webhook.idLong, webhook.token!!) + modlogEvents.put(channel.idLong, eventsInfo) consumer.accept(eventsInfo) } } class ChannelModlogEventsInfo { private val events: MutableList = ArrayList() - private var channelId: Long = 0 private var webhookId: Long = 0 private var webhookToken: String = "" @@ -74,8 +76,7 @@ class GuildSettingsModeration() { private var webhookClient: WebhookClient? = null private constructor() {} - constructor(channelId: Long, webhookId: Long, webhookToken: String) { - this.channelId = channelId + constructor(webhookId: Long, webhookToken: String) { this.webhookId = webhookId this.webhookToken = webhookToken buildWebhookClient() From 52fc0a4a5d901ef848f79a9a3917635458d7ae70 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 23 May 2020 14:46:24 -0500 Subject: [PATCH 015/206] Start adding language to modlog WARNING: doesn't build --- .../events/ModlogEventListener.java | 108 ++++++++++++------ .../data/objects/GuildSettingsModeration.kt | 16 ++- .../data/objects/ModlogEventStore.kt | 4 +- .../cascadebot/utils/LanguageEmbedField.kt | 42 +++++++ src/main/resources/lang/en-GB.json | 28 +++++ 5 files changed, 156 insertions(+), 42 deletions(-) create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index e13536ecd..335660652 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -16,6 +16,7 @@ import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.User; +import net.dv8tion.jda.api.entities.VoiceChannel; import net.dv8tion.jda.api.events.channel.category.CategoryCreateEvent; import net.dv8tion.jda.api.events.channel.category.CategoryDeleteEvent; import net.dv8tion.jda.api.events.channel.category.GenericCategoryEvent; @@ -93,6 +94,7 @@ import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.utils.CryptUtils; import org.cascadebot.cascadebot.utils.FormatUtils; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.jetbrains.annotations.NotNull; import javax.crypto.BadPaddingException; @@ -122,7 +124,7 @@ public void onGenericEmote(GenericEmoteEvent event) { if (entry.getType().equals(ActionType.EMOTE_UPDATE) || entry.getType().equals(ActionType.EMOTE_CREATE) || entry.getType().equals(ActionType.EMOTE_DELETE)) { user = auditLogEntries.get(0).getUser(); } - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent; if (event instanceof EmoteAddedEvent) { modlogEvent = ModlogEvent.EMOTE_CREATED; @@ -130,18 +132,24 @@ public void onGenericEmote(GenericEmoteEvent event) { modlogEvent = ModlogEvent.EMOTE_DELETED; } else if (event instanceof EmoteUpdateNameEvent) { modlogEvent = ModlogEvent.EMOTE_UPDATED_NAME; - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", ((EmoteUpdateNameEvent) event).getOldName())); + LanguageEmbedField languageEmbedField = new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable"); + languageEmbedField.addValueObjects(((EmoteUpdateNameEvent) event).getOldName()); + embedFieldList.add(languageEmbedField + //new WebhookEmbed.EmbedField(true, "Old Name", ((EmoteUpdateNameEvent) event).getOldName()) + ); } else if (event instanceof EmoteUpdateRolesEvent) { modlogEvent = ModlogEvent.EMOTE_UPDATED_ROLES; List oldRoles = ((EmoteUpdateRolesEvent) event).getOldRoles(); List newRoles = ((EmoteUpdateRolesEvent) event).getNewRoles(); ListChanges roleListChanges = new ListChanges<>(oldRoles, newRoles); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added Roles", - roleListChanges.getAdded().stream().map(role -> role.getName() + " (" + role.getId() + ")") - .collect(Collectors.joining("\n")))); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed Roles", - roleListChanges.getRemoved().stream().map(role -> role.getName() + " (" + role.getId() + ")") - .collect(Collectors.joining("\n")))); + LanguageEmbedField addedRolesEmbed = new LanguageEmbedField(false, "modlog.general.added_roles", "modlog.general.variable"); + addedRolesEmbed.addValueObjects(roleListChanges.getAdded().stream().map(role -> role.getName() + " (" + role.getId() + ")") + .collect(Collectors.joining("\n"))); + LanguageEmbedField removedRolesEmbed = new LanguageEmbedField(false, "modlog.general.removed_roles", "modlog.general.variable"); + removedRolesEmbed.addValueObjects( roleListChanges.getRemoved().stream().map(role -> role.getName() + " (" + role.getId() + ")") + .collect(Collectors.joining("\n"))); + embedFieldList.add(addedRolesEmbed); + embedFieldList.add(removedRolesEmbed); } else { return; } @@ -155,16 +163,20 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { User user = event.getMember().getUser(); event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent; User responsible = null; if (event instanceof GuildMemberJoinEvent) { modlogEvent = ModlogEvent.GUILD_MEMBER_JOINED; } else if (event instanceof GuildMemberLeaveEvent) { if (entry.getType().equals(ActionType.KICK)) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Responsible", Objects.requireNonNull(entry.getUser()).getAsTag())); + LanguageEmbedField respLanguageEmbedField = new LanguageEmbedField(true, "modlog.general.responsible", "modlog.general.variable"); + respLanguageEmbedField.addValueObjects(Objects.requireNonNull(entry.getUser()).getAsTag()); + embedFieldList.add(respLanguageEmbedField); if (entry.getReason() != null) { - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Reason", entry.getReason())); + LanguageEmbedField reasonEmbedField = new LanguageEmbedField(false, "modlog.general.reason", "modlog.general.variable"); + respLanguageEmbedField.addValueObjects(entry.getReason()); + embedFieldList.add(reasonEmbedField); } modlogEvent = ModlogEvent.GUILD_MEMBER_KICKED; } else { //TODO not assume leave if audit log entry for kick was not found. @@ -175,16 +187,28 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { responsible = entry.getUser(); } modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_ADDED; - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added Roles", ((GuildMemberRoleAddEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n")))); + LanguageEmbedField addedRolesEmbedField = new LanguageEmbedField(false, "modlog.general.added_roles", "modlog.general.variable"); + addedRolesEmbedField.addValueObjects(((GuildMemberRoleAddEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n"))); + embedFieldList.add(addedRolesEmbedField); } else if (event instanceof GuildMemberRoleRemoveEvent) { if (entry.getType().equals(ActionType.MEMBER_ROLE_UPDATE)) { responsible = entry.getUser(); } modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_REMOVED; - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed Roles", ((GuildMemberRoleRemoveEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n")))); + LanguageEmbedField removedRolesEmbedField = new LanguageEmbedField(false, "modlog.general.removed_roles", "modlog.general.variable"); + removedRolesEmbedField.addValueObjects(((GuildMemberRoleRemoveEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n"))); + embedFieldList.add(removedRolesEmbedField); } else if (event instanceof GuildMemberUpdateNicknameEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Nickname", ((GuildMemberUpdateNicknameEvent) event).getOldValue())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Nickname", ((GuildMemberUpdateNicknameEvent) event).getNewValue())); + if (((GuildMemberUpdateNicknameEvent) event).getOldValue() != null) { + LanguageEmbedField oldNickEmbedField = new LanguageEmbedField(true, "modlog.member.old_nick", "modlog.general.variable"); + oldNickEmbedField.addValueObjects(((GuildMemberUpdateNicknameEvent) event).getOldValue()); + embedFieldList.add(oldNickEmbedField); + } + if (((GuildMemberUpdateNicknameEvent) event).getNewValue() != null) { + LanguageEmbedField newNickEmbedField = new LanguageEmbedField(true, "modlog.member.new_nick", "modlog.general.variable"); + newNickEmbedField.addValueObjects(((GuildMemberUpdateNicknameEvent) event).getNewValue()); + embedFieldList.add(newNickEmbedField); + } modlogEvent = ModlogEvent.GUILD_MEMBER_NICKNAME_UPDATED; } else { return; @@ -200,13 +224,15 @@ public void onGuildBan(GuildBanEvent event) { User user = event.getUser(); event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent = ModlogEvent.GUILD_USER_BANNED; User responsible = null; if (entry.getType().equals(ActionType.BAN)) { responsible = entry.getUser(); if (entry.getReason() != null) { - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Reason", entry.getReason())); + LanguageEmbedField reasonEmbedField = new LanguageEmbedField(false, "modlog.general.reason", "modlog.general.variable"); + reasonEmbedField.addValueObjects(entry.getReason()); + embedFieldList.add(reasonEmbedField); } } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); @@ -219,7 +245,7 @@ public void onGuildUnban(GuildUnbanEvent event) { User user = event.getUser(); event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent = ModlogEvent.GUILD_USER_UNBANNED; User responsible = null; if (entry.getType().equals(ActionType.UNBAN)) { @@ -240,8 +266,10 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { JsonObject jsonObject = new JsonParser().parse(messageJson).getAsJsonObject(); long messageSender = jsonObject.get("sender").getAsLong(); User affected = CascadeBot.INS.getClient().getUserById(messageSender); - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Message", getMessageFromJson(jsonObject))); + List embedFieldList = new ArrayList<>(); + LanguageEmbedField messageEmbedField = new LanguageEmbedField(false, "modlog.message.message", "modlog.general.variable"); + messageEmbedField.addValueObjects(getMessageFromJson(jsonObject)); + embedFieldList.add(messageEmbedField); if (affected == null) { return; } @@ -269,9 +297,12 @@ public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { JsonObject jsonObject = new JsonParser().parse(messageJson).getAsJsonObject(); long messageSender = jsonObject.get("sender").getAsLong(); User affected = CascadeBot.INS.getClient().getUserById(messageSender); - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Old Message", getMessageFromJson(jsonObject))); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "New Message", message.getContentRaw())); + List embedFieldList = new ArrayList<>(); + LanguageEmbedField oldEmbedField = new LanguageEmbedField(false, "modlog.message.old_message", "modlog.general.variable"); + oldEmbedField.addValueObjects(getMessageFromJson(jsonObject)); + LanguageEmbedField newEmbedField = new LanguageEmbedField(false, "modlog.message.new_message", "modlog.general.variable"); + newEmbedField.addValueObjects(message.getContentRaw()); + embedFieldList.add(newEmbedField); if (affected == null) { return; } @@ -310,19 +341,25 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { GuildData guildData = GuildDataManager.getGuildData(affected.getIdLong()); event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); User responsible = null; ModlogEvent modlogEvent; if (entry.getType().equals(ActionType.GUILD_UPDATE)) { responsible = entry.getUser(); } if (event instanceof GuildUpdateAfkChannelEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Channel", ((GuildUpdateAfkChannelEvent) event).getOldAfkChannel().getName())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Channel", ((GuildUpdateAfkChannelEvent) event).getNewAfkChannel().getName())); + VoiceChannel oldChannel = ((GuildUpdateAfkChannelEvent) event).getOldAfkChannel(); + if (oldChannel != null) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_channel", "modlog.general.variable", oldChannel.getName())); + } + VoiceChannel newChannel = ((GuildUpdateAfkChannelEvent) event).getNewAfkChannel(); + if (newChannel != null) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_channel", "modlog.general.variable", oldChannel.getName())); + } modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_CHANNEL; } else if (event instanceof GuildUpdateAfkTimeoutEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Value", ((GuildUpdateAfkTimeoutEvent) event).getOldAfkTimeout().getSeconds() + " seconds")); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Value", ((GuildUpdateAfkTimeoutEvent) event).getNewAfkTimeout().getSeconds() + " seconds")); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getOldAfkTimeout().getSeconds()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getNewAfkTimeout().getSeconds()))); modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_TIMEOUT; } else if (event instanceof GuildUpdateBannerEvent) { embedFieldList.add(new WebhookEmbed.EmbedField(false, "Old Image", ((GuildUpdateBannerEvent) event).getOldBannerUrl())); @@ -359,7 +396,6 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { modlogEvent = ModlogEvent.GUILD_UPDATE_MFA_LEVEL; } else if (event instanceof GuildUpdateNameEvent) { embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", ((GuildUpdateNameEvent) event).getOldName())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Name", ((GuildUpdateNameEvent) event).getNewName())); modlogEvent = ModlogEvent.GUILD_UPDATE_NAME; } else if (event instanceof GuildUpdateNotificationLevelEvent) { embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Level", ((GuildUpdateNotificationLevelEvent) event).getOldNotificationLevel().name())); @@ -460,7 +496,7 @@ private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChann GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_CREATE)) { responsible = entry.getUser(); @@ -492,7 +528,7 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { responsible = entry.getUser(); @@ -509,7 +545,7 @@ private void handleChannelUpdatePermissionsEvents(Guild guild, ChannelType type, GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_UPDATE) || entry.getType().equals(ActionType.CHANNEL_OVERRIDE_UPDATE)) { responsible = entry.getUser(); @@ -554,7 +590,7 @@ private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, in GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { responsible = entry.getUser(); @@ -572,7 +608,7 @@ public void onGenericRole(GenericRoleEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); User responsible = null; ModlogEvent modlogEvent; if (entry.getType().equals(ActionType.ROLE_CREATE) || entry.getType().equals(ActionType.ROLE_DELETE) || entry.getType().equals(ActionType.ROLE_UPDATE)) { @@ -619,14 +655,14 @@ public void onGenericRole(GenericRoleEvent event) { //region Username updates public void onUserUpdateName(UserUpdateNameEvent event) { // TODO propagate to guilds - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", event.getOldName())); embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Name", event.getNewName())); ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_NAME_UPDATED, event.getUser(), event.getUser(), embedFieldList); } public void onUserUpdateDiscriminator(UserUpdateDiscriminatorEvent event) { - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Discriminator", event.getOldDiscriminator())); embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Discriminator", event.getNewDiscriminator())); ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_DISCRIMINATOR_UPDATED, event.getUser(), event.getUser(), embedFieldList); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index c5cc63f6c..43f13d429 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -23,7 +23,15 @@ import java.util.Collections import java.util.function.Consumer @SettingsContainer(module = Module.MODERATION) -class GuildSettingsModeration() { +class GuildSettingsModeration { + + var guildData: GuildData? = null + + constructor(guildData: GuildData) { + this.guildData = guildData + } + + constructor() @Setting public val purgePinnedMessages: Boolean = false @@ -33,7 +41,7 @@ class GuildSettingsModeration() { fun sendModlogEvent(modlogEventStore: ModlogEventStore) { val eventsInfo: List = getEventInfoForEvent(modlogEventStore.trigger) for (eventInfo in eventsInfo) { - eventInfo.sendEvent(modlogEventStore); + guildData?.let { eventInfo.sendEvent(it, modlogEventStore) }; } // TODO add to list for dashboard } @@ -98,7 +106,7 @@ class GuildSettingsModeration() { events.remove(event) } - fun sendEvent(modlogEventStore: ModlogEventStore) { + fun sendEvent(guildData: GuildData, modlogEventStore: ModlogEventStore) { val webhookEmbedBuilder = WebhookEmbedBuilder() webhookEmbedBuilder.setTitle(EmbedTitle(modlogEventStore.trigger.name, null)) val affected: ISnowflake = modlogEventStore.affected; @@ -127,7 +135,7 @@ class GuildSettingsModeration() { webhookEmbedBuilder.addField(EmbedField(true, "Affected $affectedType", affectedStr)) } for (embedField in modlogEventStore.extraInfo) { - webhookEmbedBuilder.addField(embedField) + webhookEmbedBuilder.addField(embedField.getLocalizedEmbedField(guildData.locale)) } webhookEmbedBuilder.setColor(modlogEventStore.trigger.messageType.color.rgb) if (modlogEventStore.responsible != null) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 7d8a74071..f2ae6a1a0 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -1,14 +1,14 @@ package org.cascadebot.cascadebot.data.objects -import club.minnced.discord.webhook.send.WebhookEmbed import net.dv8tion.jda.api.entities.ISnowflake import net.dv8tion.jda.api.entities.User import org.cascadebot.cascadebot.moderation.ModlogEvent +import org.cascadebot.cascadebot.utils.LanguageEmbedField data class ModlogEventStore( val trigger: ModlogEvent, val responsible: User?, val affected: ISnowflake, - val extraInfo: List + val extraInfo: List ) \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt new file mode 100644 index 000000000..be6f21177 --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt @@ -0,0 +1,42 @@ +package org.cascadebot.cascadebot.utils + +import club.minnced.discord.webhook.send.WebhookEmbed +import org.cascadebot.cascadebot.data.language.Language +import org.cascadebot.cascadebot.data.language.Locale + +class LanguageEmbedField { + + var inline: Boolean = false + + var titleLanguagePath: String = "" + var titleLanguageObjects: MutableList = ArrayList() + + var valueLanguagePath: String = "" + var valueLanguageObjects: MutableList = ArrayList() + + constructor(inline: Boolean = true, + titleLanguagePath: String, + valueLanguagePath: String, vararg valueLanguageObjects: String) { + this.inline = inline; + this.titleLanguagePath = titleLanguagePath + this.valueLanguagePath = valueLanguagePath + this.titleLanguageObjects.addAll(valueLanguageObjects) + // TODO add checks for if language string exists + } + + fun addTitleObjects(vararg titleLanguageObjects: String) { + this.titleLanguageObjects.addAll(titleLanguageObjects) + // TODO add checks for if there is room for objects in language string + } + + fun addValueObjects(vararg valueLanguageObjects: String) { + this.valueLanguageObjects.addAll(valueLanguageObjects) + } + + fun getLocalizedEmbedField(locale: Locale): WebhookEmbed.EmbedField { + return WebhookEmbed.EmbedField(inline, + Language.i18n(locale, titleLanguagePath, titleLanguageObjects), + Language.i18n(locale, valueLanguagePath, valueLanguageObjects)) + } + +} \ No newline at end of file diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 7c98de6e8..9bd6717c6 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1293,5 +1293,33 @@ "yellowgreen": "Yellowgreen" } } + }, + "modlog": { + "general": { + "old_name": "Old Name", + "variable": "{0}", + "responsible": "Responsible", + "reason": "Reason", + "added_roles": "Added Roles", + "removed_roles": "Removed Roles" + }, + "member": { + "old_nick": "Old Nickname", + "new_nick": "New Nickname" + }, + "message": { + "message": "Message", + "old_message": "Old Message", + "new_message": "New Message" + }, + "guild": { + "old_channel": "Old Channel", + "new_channel": "New Channel", + "timeout": "{0} seconds", + "old_timeout": "Old Value", + "new_timeout": "New Value", + "old_image": "Old Image", + "new_image": "New Image" + } } } From 7a1a5660c4aa9b293fde828bd7ca323a577ac738 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 23 May 2020 16:35:36 -0500 Subject: [PATCH 016/206] More events with proper language Still doesn't build --- pom.xml | 2 +- .../events/ModlogEventListener.java | 109 +++++++++++------- .../cascadebot/utils/FormatUtils.java | 11 +- src/main/resources/lang/en-GB.json | 58 +++++++++- 4 files changed, 129 insertions(+), 51 deletions(-) diff --git a/pom.xml b/pom.xml index 27f76c4f6..ab29e6f35 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ DEV - 4.0.0_39 + 4.1.1_154 1.3.47 f9ab37f 1.3.72 diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 335660652..5a0a10058 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -15,6 +15,7 @@ import net.dv8tion.jda.api.entities.IPermissionHolder; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.TextChannel; import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.VoiceChannel; import net.dv8tion.jda.api.events.channel.category.CategoryCreateEvent; @@ -54,6 +55,7 @@ import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleAddEvent; import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent; import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateNicknameEvent; +import net.dv8tion.jda.api.events.guild.override.GenericPermissionOverrideEvent; import net.dv8tion.jda.api.events.guild.update.GenericGuildUpdateEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateAfkChannelEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateAfkTimeoutEvent; @@ -97,6 +99,7 @@ import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.jetbrains.annotations.NotNull; +import javax.annotation.Nonnull; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; @@ -362,66 +365,96 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getNewAfkTimeout().getSeconds()))); modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_TIMEOUT; } else if (event instanceof GuildUpdateBannerEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Old Image", ((GuildUpdateBannerEvent) event).getOldBannerUrl())); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "New Image", ((GuildUpdateBannerEvent) event).getNewBannerIdUrl())); + if (((GuildUpdateBannerEvent) event).getOldBannerUrl() != null) { + embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.old_image", "modlog.general.variable", ((GuildUpdateBannerEvent) event).getOldBannerUrl())); + } + if (((GuildUpdateBannerEvent) event).getNewBannerIdUrl() != null) { + embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.new_image", "modlog.general.variable", ((GuildUpdateBannerEvent) event).getNewBannerIdUrl())); + } modlogEvent = ModlogEvent.GUILD_UPDATE_BANNER; } else if (event instanceof GuildUpdateDescriptionEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Old Description", ((GuildUpdateDescriptionEvent) event).getOldDescription())); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "New Description", ((GuildUpdateDescriptionEvent) event).getNewDescription())); + if (((GuildUpdateDescriptionEvent) event).getOldDescription() != null) { + embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.old_description", "modlog.general.variable", ((GuildUpdateDescriptionEvent) event).getOldDescription())); + } + if (((GuildUpdateDescriptionEvent) event).getNewDescription() != null) { + embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.new_description", "modlog.general.variable", ((GuildUpdateDescriptionEvent) event).getNewDescription())); + } modlogEvent = ModlogEvent.GUILD_UPDATE_DESCRIPTION; } else if (event instanceof GuildUpdateExplicitContentLevelEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Filter", ((GuildUpdateExplicitContentLevelEvent) event).getOldLevel().name())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Filter", ((GuildUpdateExplicitContentLevelEvent) event).getNewLevel().name())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.content_filter.old", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getOldLevel().name().toLowerCase())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.content_filter.new", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getNewLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_EXPLICIT_FILTER; } else if (event instanceof GuildUpdateFeaturesEvent) { ListChanges featuresChanged = new ListChanges<>(((GuildUpdateFeaturesEvent) event).getOldFeatures(), ((GuildUpdateFeaturesEvent) event).getNewFeatures()); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added Features", String.join("\n", featuresChanged.getAdded()))); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed Features", String.join("\n", featuresChanged.getRemoved()))); + embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.add_feature", "modlog.general.variable", String.join("\n", featuresChanged.getAdded()))); + embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.removed_feature", "modlog.general.variable", String.join("\n", featuresChanged.getRemoved()))); modlogEvent = ModlogEvent.GUILD_UPDATE_FEATURES; } else if (event instanceof GuildUpdateIconEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Old Image", ((GuildUpdateIconEvent) event).getOldIconUrl())); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "New Image", ((GuildUpdateIconEvent) event).getNewIconUrl())); + if (((GuildUpdateIconEvent) event).getOldIconUrl() != null) { + embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.old_image", "modlog.general.variable", ((GuildUpdateIconEvent) event).getOldIconUrl())); + } + if (((GuildUpdateIconEvent) event).getNewIconUrl() != null) { + embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.new_image", "modlog.general.variable", ((GuildUpdateIconEvent) event).getNewIconUrl())); + } modlogEvent = ModlogEvent.GUILD_UPDATE_ICON; } else if (event instanceof GuildUpdateMaxMembersEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Max Members", ((GuildUpdateMaxMembersEvent) event).getOldMaxMembers() + " members")); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Max Members", ((GuildUpdateMaxMembersEvent) event).getNewMaxMembers() + " members")); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getOldMaxMembers()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getNewMaxMembers()))); modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_MEMBERS; } else if (event instanceof GuildUpdateMaxPresencesEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Max Presences", ((GuildUpdateMaxPresencesEvent) event).getOldMaxPresences() + " presences")); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Max Presences", ((GuildUpdateMaxPresencesEvent) event).getNewMaxPresences() + " presences")); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getOldMaxPresences()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getNewMaxPresences()))); modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_PRESENCES; } else if (event instanceof GuildUpdateMFALevelEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old MFA Level", ((GuildUpdateMFALevelEvent) event).getOldMFALevel().name())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New MFA Level", ((GuildUpdateMFALevelEvent) event).getNewMFALevel().name())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.mfa.old", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getOldMFALevel().name().toLowerCase())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.mfa.new", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getNewMFALevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_MFA_LEVEL; } else if (event instanceof GuildUpdateNameEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", ((GuildUpdateNameEvent) event).getOldName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable", ((GuildUpdateNameEvent) event).getOldName())); modlogEvent = ModlogEvent.GUILD_UPDATE_NAME; } else if (event instanceof GuildUpdateNotificationLevelEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Level", ((GuildUpdateNotificationLevelEvent) event).getOldNotificationLevel().name())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Level", ((GuildUpdateNotificationLevelEvent) event).getNewNotificationLevel().name())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.notification.old", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getOldNotificationLevel().name().toLowerCase())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.notification.new", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getNewNotificationLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_NOTIFICATION_LEVEL; } else if (event instanceof GuildUpdateRegionEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Region", ((GuildUpdateRegionEvent) event).getOldRegion().getName())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Region", ((GuildUpdateRegionEvent) event).getNewRegion().getName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_region", "modlog.general.variable", ((GuildUpdateRegionEvent) event).getOldRegion().getName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_region", "modlog.general.variable", ((GuildUpdateRegionEvent) event).getNewRegion().getName())); modlogEvent = ModlogEvent.GUILD_UPDATE_REGION; } else if (event instanceof GuildUpdateSplashEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Old Splash", ((GuildUpdateSplashEvent) event).getOldSplashUrl())); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "New Splash", ((GuildUpdateSplashEvent) event).getNewSplashUrl())); + if (((GuildUpdateSplashEvent) event).getOldSplashUrl() != null) { + embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.old_splash", "modlog.general.variable", ((GuildUpdateSplashEvent) event).getOldSplashUrl())); + } + if (((GuildUpdateSplashEvent) event).getNewSplashUrl() != null) { + embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.new_splash", "modlog.general.variable", ((GuildUpdateSplashEvent) event).getNewSplashUrl())); + } modlogEvent = ModlogEvent.GUILD_UPDATE_SPLASH; } else if (event instanceof GuildUpdateSystemChannelEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old System Channel", ((GuildUpdateSystemChannelEvent) event).getOldSystemChannel().getName())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New System Channel", ((GuildUpdateSystemChannelEvent) event).getNewSystemChannel().getName())); + TextChannel oldSystemChannel = ((GuildUpdateSystemChannelEvent) event).getOldSystemChannel(); + if (oldSystemChannel != null) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_sys", "modlog.general.variable", oldSystemChannel.getName())); + } + TextChannel newSystemChannel = ((GuildUpdateSystemChannelEvent) event).getNewSystemChannel(); + if (newSystemChannel != null) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_sys", "modlog.general.variable", newSystemChannel.getName())); + } modlogEvent = ModlogEvent.GUILD_UPDATE_SYSTEM_CHANNEL; } else if (event instanceof GuildUpdateVanityCodeEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Vanity Code", ((GuildUpdateVanityCodeEvent) event).getOldVanityCode())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Vanity Url", ((GuildUpdateVanityCodeEvent) event).getOldVanityUrl())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Vanity Code", ((GuildUpdateVanityCodeEvent) event).getNewVanityCode())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Vanity Url", ((GuildUpdateVanityCodeEvent) event).getNewVanityUrl())); + if (((GuildUpdateVanityCodeEvent) event).getOldVanityCode() != null) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.vanity_code.old", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getOldVanityCode())); + } + if (((GuildUpdateVanityCodeEvent) event).getOldVanityUrl() != null) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.vanity_url.old", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getOldVanityUrl())); + } + if (((GuildUpdateVanityCodeEvent) event).getNewVanityCode() != null) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.vanity_code.new", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getNewVanityCode())); + } + if (((GuildUpdateVanityCodeEvent) event).getNewVanityUrl() != null) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.vanity_url.new", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getNewVanityUrl())); + } modlogEvent = ModlogEvent.GUILD_UPDATE_VANITY_CODE; } else if (event instanceof GuildUpdateVerificationLevelEvent) { - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Verification Level", FormatUtils.getVerificationLevelString(((GuildUpdateVerificationLevelEvent) event).getOldVerificationLevel()))); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Verification Level", FormatUtils.getVerificationLevelString(((GuildUpdateVerificationLevelEvent) event).getNewVerificationLevel()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getOldVerificationLevel().name().toLowerCase())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getNewVerificationLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_VERIFICATION_LEVEL; } else { return; @@ -439,8 +472,6 @@ public void onGenericStoreChannel(@NotNull GenericStoreChannelEvent event) { handleChannelDeleteEvents(event.getChannel().getGuild(), ChannelType.STORE, event.getChannel()); } else if (event instanceof StoreChannelUpdateNameEvent) { handleChannelUpdateNameEvents(event.getChannel().getGuild(), ChannelType.STORE, ((StoreChannelUpdateNameEvent) event).getOldName(), event.getChannel()); - } else if (event instanceof StoreChannelUpdatePermissionsEvent) { - handleChannelUpdatePermissionsEvents(event.getChannel().getGuild(), ChannelType.STORE, ((StoreChannelUpdatePermissionsEvent) event).getChangedPermissionHolders(), event.getChannel()); } else if (event instanceof StoreChannelUpdatePositionEvent) { handleChannelUpdatePositionEvents(event.getChannel().getGuild(), ChannelType.STORE, ((StoreChannelUpdatePositionEvent) event).getOldPosition(), event.getChannel()); } @@ -453,9 +484,6 @@ public void onGenericTextChannel(@NotNull GenericTextChannelEvent event) { handleChannelDeleteEvents(event.getGuild(), ChannelType.TEXT, event.getChannel()); } else if (event instanceof TextChannelUpdateNameEvent) { handleChannelUpdateNameEvents(event.getGuild(), ChannelType.TEXT, ((TextChannelUpdateNameEvent) event).getOldName(), event.getChannel()); - } else if (event instanceof TextChannelUpdatePermissionsEvent) { - ((TextChannelUpdatePermissionsEvent) event).getChangedPermissionHolders(); - handleChannelUpdatePermissionsEvents(event.getGuild(), ChannelType.TEXT, ((TextChannelUpdatePermissionsEvent) event).getChangedPermissionHolders(), event.getChannel()); } else if (event instanceof TextChannelUpdatePositionEvent) { handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.TEXT, ((TextChannelUpdatePositionEvent) event).getOldPosition(), event.getChannel()); } @@ -468,8 +496,6 @@ public void onGenericVoiceChannel(@NotNull GenericVoiceChannelEvent event) { handleChannelDeleteEvents(event.getGuild(), ChannelType.VOICE, event.getChannel()); } else if (event instanceof VoiceChannelUpdateNameEvent) { handleChannelUpdateNameEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdateNameEvent) event).getOldName(), event.getChannel()); - } else if (event instanceof VoiceChannelUpdatePermissionsEvent) { - handleChannelUpdatePermissionsEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdatePermissionsEvent) event).getChangedPermissionHolders(), event.getChannel()); } else if (event instanceof VoiceChannelUpdatePositionEvent) { handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdatePositionEvent) event).getOldPosition(), event.getChannel()); } @@ -482,12 +508,15 @@ public void onGenericCategory(@NotNull GenericCategoryEvent event) { handleChannelDeleteEvents(event.getGuild(), ChannelType.CATEGORY, event.getCategory()); } else if (event instanceof CategoryUpdateNameEvent) { handleChannelUpdateNameEvents(event.getGuild(), ChannelType.CATEGORY, ((CategoryUpdateNameEvent) event).getOldName(), event.getCategory()); - } else if (event instanceof CategoryUpdatePermissionsEvent) { - handleChannelUpdatePermissionsEvents(event.getGuild(), ChannelType.CATEGORY, ((CategoryUpdatePermissionsEvent) event).getChangedPermissionHolders(), event.getCategory()); } else if (event instanceof CategoryUpdatePositionEvent) { handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.CATEGORY, ((CategoryUpdatePositionEvent) event).getOldPosition(), event.getCategory()); } } + + public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { + + } + //endregion //region Channel handlers diff --git a/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java index 75d1ec9b4..7723e9a6c 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java @@ -288,15 +288,8 @@ public static String formatLongTimeMills(long time) { return String.format("%02d:%02d:%02d", hours, mins, seconds); } - public static String getVerificationLevelString(Guild.VerificationLevel verificationLevel) { - switch (verificationLevel.getKey()) { - case 4: - return "(\u256F\u00B0\u25A1\u00B0\uFF09\u256F\uFE35 \u253B\u2501\u253B"; // (╯°□°)╯︵ ┻━┻ - case 5: - return "\u253B\u2501\u253B \uFF90\u30FD(\u0CA0\u76CA\u0CA0)\u30CE\u5F61\u253B\u2501\u253B"; // ┻━┻ ミヽ(ಠ益ಠ)ノ彡┻━┻ - default: - return verificationLevel.name(); - } + public static String getVerificationLevelString(Locale locale, Guild.VerificationLevel verificationLevel) { + return Language.i18n(locale, "utils.verification_level." + verificationLevel.name().toLowerCase()); } } diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 9bd6717c6..e0981e3ee 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1131,6 +1131,14 @@ "no_permissions": "No permissions!", "no_linked_roles": "No linked roles!" }, + "verification_level": { + "none": "None", + "low": "Low", + "medium": "Medium", + "high": "(╯°□°)╯︵ ┻━┻", + "very_high": "┻━┻ ミヽ(ಠ益ಠ)ノ彡┻━┻", + "unknown": "Unknown" + }, "color": { "invalid_rgb": "RGB values should be between 0 and 255!", "invalid_hex_code": "Please provide a valid hex value! #000000-#FFFFFF", @@ -1319,7 +1327,55 @@ "old_timeout": "Old Value", "new_timeout": "New Value", "old_image": "Old Image", - "new_image": "New Image" + "new_image": "New Image", + "old_description": "Old Description", + "new_description": "New Description", + "content_filter": { + "old": "Old Filter", + "new": "New Filter", + "off": "Off", + "no_role": "No Role", + "all": "All", + "unknown": "unknown" + }, + "add_feature": "Added Features", + "removed_feature": "Removed Features", + "old_max_members": "Old Max Members", + "new_max_members": "New Max Members", + "members": "{0} members", + "old_presences": "Old Max Presences", + "new_presences": "New Max Presences", + "presences": "{0} presences", + "mfa": { + "old": "Old MFA Level", + "new": "New MFA Level", + "none": "None", + "two_factor_auth": "2fa Required", + "unknown": "Unknown" + }, + "notification": { + "old": "Old Level", + "new": "New Level", + "all_messages": "All Messages", + "mentions_only": "Mentions Only", + "unknown": "Unknown" + }, + "old_region": "Old Region", + "new_region": "New Region", + "old_splash": "Old Splash", + "new_splash": "New Splash", + "old_sys": "Old System Channel", + "new_sys": "New System Channel", + "vanity_code": { + "old": "Old Vanity Code", + "new": "New Vanity Code" + }, + "vanity_url": { + "old": "Old Vanity Url", + "new": "New Vanity Url" + }, + "old_verification": "Old Verification Level", + "new_verification": "New Verification Level" } } } From c02b64df0ae94d8112d6a4c94c77bb268506985f Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 25 May 2020 11:11:46 -0500 Subject: [PATCH 017/206] Finish adding language to modlog events --- .../events/ModlogEventListener.java | 157 ++++++++++-------- src/main/resources/lang/en-GB.json | 37 ++++- 2 files changed, 125 insertions(+), 69 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 5a0a10058..b7c535336 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -56,6 +56,9 @@ import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent; import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateNicknameEvent; import net.dv8tion.jda.api.events.guild.override.GenericPermissionOverrideEvent; +import net.dv8tion.jda.api.events.guild.override.PermissionOverrideCreateEvent; +import net.dv8tion.jda.api.events.guild.override.PermissionOverrideDeleteEvent; +import net.dv8tion.jda.api.events.guild.override.PermissionOverrideUpdateEvent; import net.dv8tion.jda.api.events.guild.update.GenericGuildUpdateEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateAfkChannelEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateAfkTimeoutEvent; @@ -94,6 +97,7 @@ import org.cascadebot.cascadebot.data.objects.GuildData; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; import org.cascadebot.cascadebot.moderation.ModlogEvent; +import org.cascadebot.cascadebot.utils.ColorUtils; import org.cascadebot.cascadebot.utils.CryptUtils; import org.cascadebot.cascadebot.utils.FormatUtils; import org.cascadebot.cascadebot.utils.LanguageEmbedField; @@ -104,6 +108,7 @@ import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.ShortBufferException; +import java.awt.Color; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -514,7 +519,57 @@ public void onGenericCategory(@NotNull GenericCategoryEvent event) { } public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { - + ModlogEvent modlogEvent = ModlogEvent.CHANNEL_PERMISSIONS_UPDATED; + Guild guild = event.getGuild(); + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + User responsible = null; + if (entry.getType().equals(ActionType.CHANNEL_UPDATE) || entry.getType().equals(ActionType.CHANNEL_OVERRIDE_UPDATE)) { + responsible = entry.getUser(); + } + String permissionsHolderName; + if (event.getPermissionHolder() instanceof User) { + permissionsHolderName = ((User) event.getPermissionHolder()).getName(); + } else if (event.getPermissionHolder() instanceof Role) { + permissionsHolderName = ((Role) event.getPermissionHolder()).getName(); + } else { + permissionsHolderName = ""; + } + + String allowedPath; + String deniedPath; + if (event instanceof PermissionOverrideCreateEvent) { + allowedPath = "modlog.channel.perm.added_allow"; + deniedPath = "modlog.channel.perm.added_deny"; + } else if (event instanceof PermissionOverrideDeleteEvent) { + allowedPath = "modlog.channel.perm.removed_allow"; + deniedPath = "modlog.channel.perm.removed_deny"; + } else if (event instanceof PermissionOverrideUpdateEvent) { + allowedPath = "modlog.channel.perm.update_allow"; + deniedPath = "modlog.channel.perm.update_deny"; + LanguageEmbedField oldAllowed = new LanguageEmbedField(false, "modlog.channel.perm.old_allow", "modlog.general.variable", + ((PermissionOverrideUpdateEvent) event).getOldAllow().stream().map(Permission::getName).collect(Collectors.joining("\n"))); + oldAllowed.addTitleObjects(permissionsHolderName); + LanguageEmbedField oldDenied = new LanguageEmbedField(false, "modlog.channel.perm.old_allow", "modlog.general.variable", + ((PermissionOverrideUpdateEvent) event).getOldDeny().stream().map(Permission::getName).collect(Collectors.joining("\n"))); + oldDenied.addTitleObjects(permissionsHolderName); + embedFieldList.add(oldAllowed); + embedFieldList.add(oldDenied); + } else { + return; + } + LanguageEmbedField allowed = new LanguageEmbedField(false, allowedPath, "modlog.general.variable", event.getPermissionOverride().getAllowed().stream().map(Permission::getName).collect(Collectors.joining("\n"))); + allowed.addTitleObjects(permissionsHolderName); + LanguageEmbedField denied = new LanguageEmbedField(false, deniedPath, "modlog.general.variable", event.getPermissionOverride().getDenied().stream().map(Permission::getName).collect(Collectors.joining("\n"))); + denied.addTitleObjects(permissionsHolderName); + embedFieldList.add(allowed); + embedFieldList.add(denied); + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + event.getChannelType().name().toLowerCase())); + ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, event.getChannel(), embedFieldList); + guildData.getModeration().sendModlogEvent(modlogEventStore); + }); } //endregion @@ -530,7 +585,7 @@ private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChann if (entry.getType().equals(ActionType.CHANNEL_CREATE)) { responsible = entry.getUser(); } - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(modlogEventStore); }); @@ -541,12 +596,12 @@ private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChann GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_DELETE)) { responsible = entry.getUser(); } - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(modlogEventStore); }); @@ -562,53 +617,8 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { responsible = entry.getUser(); } - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", oldName)); - ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); - guildData.getModeration().sendModlogEvent(modlogEventStore); - }); - } - - private void handleChannelUpdatePermissionsEvents(Guild guild, ChannelType type, List changedPermissionHolders, GuildChannel channel) { - ModlogEvent event = ModlogEvent.CHANNEL_PERMISSIONS_UPDATED; - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - List embedFieldList = new ArrayList<>(); - User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_UPDATE) || entry.getType().equals(ActionType.CHANNEL_OVERRIDE_UPDATE)) { - responsible = entry.getUser(); - Map auditLogChangeMap = entry.getChanges(); - for (Map.Entry auditLogChangeEntry : auditLogChangeMap.entrySet()) { - AuditLogChange value = auditLogChangeEntry.getValue(); - EnumSet oldPermissions = Permission.getPermissions(((Integer) value.getOldValue()).longValue()); - EnumSet newPermissions = Permission.getPermissions(((Integer) value.getNewValue()).longValue()); - ListChanges permissionListChanges = new ListChanges<>(oldPermissions, newPermissions); - String change = "unknown"; - switch (auditLogChangeEntry.getKey()) { - case "allow": - change = "Allowed"; - break; - case "deny": - change = "Denied"; - break; - } - String affectedType = entry.getOptionByName("type"); - long affectedId = entry.getTargetIdLong(); - String affected = "unknown"; - switch (affectedType) { - case "role": - affected = CascadeBot.INS.getShardManager().getRoleById(affectedId).getName(); - break; - case "user": - affected = CascadeBot.INS.getShardManager().getUserById(affectedId).getAsTag(); - break; - } - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added " + change + " Permissions to " + affected, permissionListChanges.getAdded().stream().map(permission -> permission.getName()).collect(Collectors.joining("\n")))); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed " + change + " Permissions to " + affected, permissionListChanges.getRemoved().stream().map(permission -> permission.getName()).collect(Collectors.joining("\n")))); - } - } - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable", oldName)); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(modlogEventStore); }); @@ -624,9 +634,9 @@ private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, in if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { responsible = entry.getUser(); } - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Type", type.name())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Position", String.valueOf(oldPos))); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Position", String.valueOf(channel.getPosition()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_pos", "modlog.general.variable", String.valueOf(oldPos))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.new_pos", "modlog.general.variable", String.valueOf(channel.getPosition()))); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(modlogEventStore); }); @@ -650,29 +660,34 @@ public void onGenericRole(GenericRoleEvent event) { modlogEvent = ModlogEvent.ROLE_DELETED; } else if (event instanceof RoleUpdateColorEvent) { modlogEvent = ModlogEvent.ROLE_COLOR_UPDATED; - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Color", ((RoleUpdateColorEvent) event).getOldColor().toString())); // TODO properly show color - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Color", ((RoleUpdateColorEvent) event).getNewColor().toString())); + Color oldColor = ((RoleUpdateColorEvent) event).getOldColor(); + if (oldColor != null) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.role.old_color", "modlog.general.variable", ColorUtils.getHex(oldColor.getRed(), oldColor.getGreen(), oldColor.getBlue()))); + } + Color newColor = ((RoleUpdateColorEvent) event).getNewColor(); + if (newColor != null) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.role.new_color", "modlog.general.variable", ColorUtils.getHex(newColor.getRed(), newColor.getGreen(), newColor.getBlue()))); + } } else if (event instanceof RoleUpdateHoistedEvent) { modlogEvent = ModlogEvent.ROLE_HOIST_UPDATED; - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Hoisted", String.valueOf(!((RoleUpdateHoistedEvent) event).wasHoisted()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.role.hoisted", "modlog.general.variable", String.valueOf(!((RoleUpdateHoistedEvent) event).wasHoisted()))); } else if (event instanceof RoleUpdateMentionableEvent) { modlogEvent = ModlogEvent.ROLE_MENTIONABLE_UPDATED; - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Mentionable", String.valueOf(!((RoleUpdateMentionableEvent) event).wasMentionable()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.role.mention", "modlog.general.variable", String.valueOf(!((RoleUpdateMentionableEvent) event).wasMentionable()))); } else if (event instanceof RoleUpdateNameEvent) { modlogEvent = ModlogEvent.ROLE_NAME_UPDATED; - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", ((RoleUpdateNameEvent) event).getOldName())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Name", ((RoleUpdateNameEvent) event).getNewName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable", ((RoleUpdateNameEvent) event).getOldName())); } else if (event instanceof RoleUpdatePermissionsEvent) { modlogEvent = ModlogEvent.ROLE_PERMISSIONS_UPDATED; EnumSet oldPermissions = ((RoleUpdatePermissionsEvent) event).getOldPermissions(); EnumSet newPermissions = ((RoleUpdatePermissionsEvent) event).getNewPermissions(); ListChanges permissionListChanges = new ListChanges<>(oldPermissions, newPermissions); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Added Permissions", permissionListChanges.getAdded().stream().map(permission -> permission.getName()).collect(Collectors.joining("\n")))); - embedFieldList.add(new WebhookEmbed.EmbedField(false, "Removed Permissions", permissionListChanges.getRemoved().stream().map(permission -> permission.getName()).collect(Collectors.joining("\n")))); + embedFieldList.add(new LanguageEmbedField(false, "modlog.role.added_perm", "modlog.general.variable", permissionListChanges.getAdded().stream().map(Permission::getName).collect(Collectors.joining("\n")))); + embedFieldList.add(new LanguageEmbedField(false, "modlog.role.removed_perm", "modlog.general.variable", permissionListChanges.getRemoved().stream().map(Permission::getName).collect(Collectors.joining("\n")))); } else if (event instanceof RoleUpdatePositionEvent) { modlogEvent = ModlogEvent.ROLE_POSITION_UPDATED; - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Position", String.valueOf(((RoleUpdatePositionEvent) event).getOldPosition()))); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Position", String.valueOf(((RoleUpdatePositionEvent) event).getNewPosition()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_pos", "modlog.general.variable", String.valueOf(((RoleUpdatePositionEvent) event).getOldPosition()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.general.new_pos", "modlog.general.variable", String.valueOf(((RoleUpdatePositionEvent) event).getNewPosition()))); } else { return; } @@ -685,16 +700,22 @@ public void onGenericRole(GenericRoleEvent event) { public void onUserUpdateName(UserUpdateNameEvent event) { // TODO propagate to guilds List embedFieldList = new ArrayList<>(); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Name", event.getOldName())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Name", event.getNewName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable", event.getOldName())); ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_NAME_UPDATED, event.getUser(), event.getUser(), embedFieldList); + for (Guild guild : CascadeBot.INS.getClient().getMutualGuilds(event.getUser())) { + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + guildData.getModeration().sendModlogEvent(modlogEventStore); + } } public void onUserUpdateDiscriminator(UserUpdateDiscriminatorEvent event) { List embedFieldList = new ArrayList<>(); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "Old Discriminator", event.getOldDiscriminator())); - embedFieldList.add(new WebhookEmbed.EmbedField(true, "New Discriminator", event.getNewDiscriminator())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.user.old_discrim", "modlog.general.variable", event.getOldDiscriminator())); ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_DISCRIMINATOR_UPDATED, event.getUser(), event.getUser(), embedFieldList); + for (Guild guild : CascadeBot.INS.getClient().getMutualGuilds(event.getUser())) { + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + guildData.getModeration().sendModlogEvent(modlogEventStore); + } } //endregion diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index e0981e3ee..ce2aa5837 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1309,7 +1309,9 @@ "responsible": "Responsible", "reason": "Reason", "added_roles": "Added Roles", - "removed_roles": "Removed Roles" + "removed_roles": "Removed Roles", + "old_pos": "Old Position", + "new_pos": "New Position" }, "member": { "old_nick": "Old Nickname", @@ -1376,6 +1378,39 @@ }, "old_verification": "Old Verification Level", "new_verification": "New Verification Level" + }, + "channel": { + "type": { + "name": "Type", + "text": "Text", + "private": "Private", + "voice": "Voice", + "group": "Group", + "category": "Category", + "store": "Store", + "unknown": "Unknown" + }, + "perm": { + "added_allow": "Added Allowed permission to {0}", + "removed_allow": "Removed Allowed permission from {0}", + "update_allow": "New Allowed permission for {0}", + "added_deny": "Added Denied permission to {0}", + "removed_deny": "Removed Denied permission from {0}", + "update_deny": "New Denied permission for {0}", + "old_allow": "Old Allowed permission for {0}", + "old_deny": "Old Denied permissions for {0}" + } + }, + "role": { + "old_color": "Old Color", + "new_color": "New Color", + "hoisted": "Hoisted", + "mention": "Mentionable", + "added_perm": "Added Permissions", + "removed_perm": "Removed Permissions" + }, + "user": { + "old_discrim": "Old Discriminator" } } } From 02f2102e35f4458a7f323f446aad69348f1eff91 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 25 May 2020 11:14:35 -0500 Subject: [PATCH 018/206] Minor fixes, and cleanup --- .../cascadebot/events/ModlogEventListener.java | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index b7c535336..ef4ba66e8 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -1,18 +1,15 @@ package org.cascadebot.cascadebot.events; -import club.minnced.discord.webhook.send.WebhookEmbed; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.audit.ActionType; -import net.dv8tion.jda.api.audit.AuditLogChange; import net.dv8tion.jda.api.audit.AuditLogEntry; import net.dv8tion.jda.api.entities.ChannelType; import net.dv8tion.jda.api.entities.Emote; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.GuildChannel; -import net.dv8tion.jda.api.entities.IPermissionHolder; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.TextChannel; @@ -22,25 +19,21 @@ import net.dv8tion.jda.api.events.channel.category.CategoryDeleteEvent; import net.dv8tion.jda.api.events.channel.category.GenericCategoryEvent; import net.dv8tion.jda.api.events.channel.category.update.CategoryUpdateNameEvent; -import net.dv8tion.jda.api.events.channel.category.update.CategoryUpdatePermissionsEvent; import net.dv8tion.jda.api.events.channel.category.update.CategoryUpdatePositionEvent; import net.dv8tion.jda.api.events.channel.store.GenericStoreChannelEvent; import net.dv8tion.jda.api.events.channel.store.StoreChannelCreateEvent; import net.dv8tion.jda.api.events.channel.store.StoreChannelDeleteEvent; import net.dv8tion.jda.api.events.channel.store.update.StoreChannelUpdateNameEvent; -import net.dv8tion.jda.api.events.channel.store.update.StoreChannelUpdatePermissionsEvent; import net.dv8tion.jda.api.events.channel.store.update.StoreChannelUpdatePositionEvent; import net.dv8tion.jda.api.events.channel.text.GenericTextChannelEvent; import net.dv8tion.jda.api.events.channel.text.TextChannelCreateEvent; import net.dv8tion.jda.api.events.channel.text.TextChannelDeleteEvent; import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateNameEvent; -import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdatePermissionsEvent; import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdatePositionEvent; import net.dv8tion.jda.api.events.channel.voice.GenericVoiceChannelEvent; import net.dv8tion.jda.api.events.channel.voice.VoiceChannelCreateEvent; import net.dv8tion.jda.api.events.channel.voice.VoiceChannelDeleteEvent; import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateNameEvent; -import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdatePermissionsEvent; import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdatePositionEvent; import net.dv8tion.jda.api.events.emote.EmoteAddedEvent; import net.dv8tion.jda.api.events.emote.EmoteRemovedEvent; @@ -99,11 +92,9 @@ import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.utils.ColorUtils; import org.cascadebot.cascadebot.utils.CryptUtils; -import org.cascadebot.cascadebot.utils.FormatUtils; import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.jetbrains.annotations.NotNull; -import javax.annotation.Nonnull; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; @@ -116,7 +107,6 @@ import java.util.Collection; import java.util.EnumSet; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @@ -362,7 +352,7 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { } VoiceChannel newChannel = ((GuildUpdateAfkChannelEvent) event).getNewAfkChannel(); if (newChannel != null) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_channel", "modlog.general.variable", oldChannel.getName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_channel", "modlog.general.variable", newChannel.getName())); } modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_CHANNEL; } else if (event instanceof GuildUpdateAfkTimeoutEvent) { @@ -373,8 +363,8 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { if (((GuildUpdateBannerEvent) event).getOldBannerUrl() != null) { embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.old_image", "modlog.general.variable", ((GuildUpdateBannerEvent) event).getOldBannerUrl())); } - if (((GuildUpdateBannerEvent) event).getNewBannerIdUrl() != null) { - embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.new_image", "modlog.general.variable", ((GuildUpdateBannerEvent) event).getNewBannerIdUrl())); + if (((GuildUpdateBannerEvent) event).getNewBannerUrl() != null) { + embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.new_image", "modlog.general.variable", ((GuildUpdateBannerEvent) event).getNewBannerUrl())); } modlogEvent = ModlogEvent.GUILD_UPDATE_BANNER; } else if (event instanceof GuildUpdateDescriptionEvent) { From 532a6bc16b35ec88073b91a46fea5ea40b49d300 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 25 May 2020 11:23:55 -0500 Subject: [PATCH 019/206] Some utility functions --- .../cascadebot/moderation/ModlogEvent.java | 5 +++++ .../data/objects/GuildSettingsModeration.kt | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java b/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java index 96beae7df..c6bc3717f 100644 --- a/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java +++ b/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java @@ -1,5 +1,6 @@ package org.cascadebot.cascadebot.moderation; +import kotlin.jvm.JvmStatic; import lombok.Getter; import org.cascadebot.cascadebot.messaging.MessageType; @@ -149,6 +150,10 @@ public enum ModlogEvent { this.messageType = messageType; } + public static List getEventsFromCategory(Category category) { + return modlogCategoryMap.get(category); + } + public List getCategories() { return categories; } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 43f13d429..a4d66e12d 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -66,6 +66,20 @@ class GuildSettingsModeration { } } + fun enableEvent(channel: TextChannel, event: ModlogEvent) { + if (modlogEvents.containsKey(channel.idLong)) { + modlogEvents[channel.idLong]?.addEvent(event) + } else { + createModlogEventsInfo(channel, Consumer { it.addEvent(event) }) + } + } + + fun enableEventByCategory(channel: TextChannel, category: ModlogEvent.Category) { + for (modlogEvent in ModlogEvent.getEventsFromCategory(category)) { + enableEvent(channel, modlogEvent) + } + } + private fun createModlogEventsInfo(channel: TextChannel, consumer: Consumer) { channel.createWebhook("Cascade-modlog").setAvatar(Icon.from(URL(CascadeBot.INS.client.selfUser.avatarUrl).openStream())).queue { webhook -> val eventsInfo = ChannelModlogEventsInfo(webhook.idLong, webhook.token!!) From 1a6e74d48837b1172397c88f7e5297384b0d187a Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 25 May 2020 14:45:04 -0500 Subject: [PATCH 020/206] Minor fixes and store events --- .../data/database/DatabaseManager.java | 3 +- .../events/ModlogEventListener.java | 36 ++++++++------ .../cascadebot/data/objects/GuildData.kt | 2 +- .../data/objects/GuildSettingsModeration.kt | 41 +++++++++++++--- .../data/objects/ModlogEventStore.kt | 48 ++++++++++++++++--- .../cascadebot/utils/LanguageEmbedField.kt | 4 +- 6 files changed, 104 insertions(+), 30 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java b/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java index 952bc5b70..3bc80bdfe 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java @@ -19,6 +19,7 @@ import org.bson.Document; import org.bson.codecs.configuration.CodecRegistries; import org.bson.codecs.configuration.CodecRegistry; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,7 +41,7 @@ public class DatabaseManager { "org.cascadebot.cascadebot.utils.buttons", "org.cascadebot.cascadebot.scheduler", "org.cascadebot.shared" - ).build()) + ).register(LanguageEmbedField.class).build()) ); @Getter diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index ef4ba66e8..eeb573bb4 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -539,23 +539,31 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { } else if (event instanceof PermissionOverrideUpdateEvent) { allowedPath = "modlog.channel.perm.update_allow"; deniedPath = "modlog.channel.perm.update_deny"; - LanguageEmbedField oldAllowed = new LanguageEmbedField(false, "modlog.channel.perm.old_allow", "modlog.general.variable", - ((PermissionOverrideUpdateEvent) event).getOldAllow().stream().map(Permission::getName).collect(Collectors.joining("\n"))); - oldAllowed.addTitleObjects(permissionsHolderName); - LanguageEmbedField oldDenied = new LanguageEmbedField(false, "modlog.channel.perm.old_allow", "modlog.general.variable", - ((PermissionOverrideUpdateEvent) event).getOldDeny().stream().map(Permission::getName).collect(Collectors.joining("\n"))); - oldDenied.addTitleObjects(permissionsHolderName); - embedFieldList.add(oldAllowed); - embedFieldList.add(oldDenied); + if (((PermissionOverrideUpdateEvent) event).getOldAllow().size() > 0) { + LanguageEmbedField oldAllowed = new LanguageEmbedField(false, "modlog.channel.perm.old_allow", "modlog.general.variable", + ((PermissionOverrideUpdateEvent) event).getOldAllow().stream().map(Permission::getName).collect(Collectors.joining("\n"))); + oldAllowed.addTitleObjects(permissionsHolderName); + embedFieldList.add(oldAllowed); + } + if (((PermissionOverrideUpdateEvent) event).getOldDeny().size() > 0) { + LanguageEmbedField oldDenied = new LanguageEmbedField(false, "modlog.channel.perm.old_allow", "modlog.general.variable", + ((PermissionOverrideUpdateEvent) event).getOldDeny().stream().map(Permission::getName).collect(Collectors.joining("\n"))); + oldDenied.addTitleObjects(permissionsHolderName); + embedFieldList.add(oldDenied); + } } else { return; } - LanguageEmbedField allowed = new LanguageEmbedField(false, allowedPath, "modlog.general.variable", event.getPermissionOverride().getAllowed().stream().map(Permission::getName).collect(Collectors.joining("\n"))); - allowed.addTitleObjects(permissionsHolderName); - LanguageEmbedField denied = new LanguageEmbedField(false, deniedPath, "modlog.general.variable", event.getPermissionOverride().getDenied().stream().map(Permission::getName).collect(Collectors.joining("\n"))); - denied.addTitleObjects(permissionsHolderName); - embedFieldList.add(allowed); - embedFieldList.add(denied); + if (event.getPermissionOverride().getAllowed().size() > 0) { + LanguageEmbedField allowed = new LanguageEmbedField(false, allowedPath, "modlog.general.variable", event.getPermissionOverride().getAllowed().stream().map(Permission::getName).collect(Collectors.joining("\n"))); + allowed.addTitleObjects(permissionsHolderName); + embedFieldList.add(allowed); + } + if (event.getPermissionOverride().getDenied().size() > 0) { + LanguageEmbedField denied = new LanguageEmbedField(false, deniedPath, "modlog.general.variable", event.getPermissionOverride().getDenied().stream().map(Permission::getName).collect(Collectors.joining("\n"))); + denied.addTitleObjects(permissionsHolderName); + embedFieldList.add(denied); + } embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + event.getChannelType().name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, event.getChannel(), embedFieldList); guildData.getModeration().sendModlogEvent(modlogEventStore); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index b24a27390..c6d777842 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -33,7 +33,7 @@ class GuildData(@field:Id val guildId: Long) { //region Guild data containers val core = GuildSettingsCore() val useful = GuildSettingsUseful() - val moderation = GuildSettingsModeration() + val moderation = GuildSettingsModeration(guildId) val management = GuildSettingsManagement() val music = GuildSettingsMusic() //endregion diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index a4d66e12d..fcb3b3fe5 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -9,6 +9,7 @@ import club.minnced.discord.webhook.send.WebhookEmbedBuilder import de.bild.codec.annotations.Transient import net.dv8tion.jda.api.entities.Emote import net.dv8tion.jda.api.entities.Guild +import net.dv8tion.jda.api.entities.GuildChannel import net.dv8tion.jda.api.entities.ISnowflake import net.dv8tion.jda.api.entities.Icon import net.dv8tion.jda.api.entities.Role @@ -16,19 +17,23 @@ import net.dv8tion.jda.api.entities.TextChannel import net.dv8tion.jda.api.entities.User import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.commandmeta.Module +import org.cascadebot.cascadebot.data.database.DebugLogCallback +import org.cascadebot.cascadebot.data.database.IAsyncMongoTask +import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.moderation.ModlogEvent import java.net.URL import java.util.ArrayList import java.util.Collections +import java.util.Date import java.util.function.Consumer @SettingsContainer(module = Module.MODERATION) class GuildSettingsModeration { - var guildData: GuildData? = null + var guildId: Long = 0 - constructor(guildData: GuildData) { - this.guildData = guildData + constructor(guildId: Long) { + this.guildId = guildId; } constructor() @@ -41,9 +46,9 @@ class GuildSettingsModeration { fun sendModlogEvent(modlogEventStore: ModlogEventStore) { val eventsInfo: List = getEventInfoForEvent(modlogEventStore.trigger) for (eventInfo in eventsInfo) { - guildData?.let { eventInfo.sendEvent(it, modlogEventStore) }; + eventInfo.sendEvent(GuildDataManager.getGuildData(guildId), modlogEventStore); } - // TODO add to list for dashboard + CascadeBot.INS.databaseManager.runAsyncTask { database -> database.getCollection("modlog", MongoModlogEventObject::class.java).insertOne(MongoModlogEventObject(guildId, modlogEventStore, "default" /* TODO change to actual time */), DebugLogCallback("Inserted Event")) } } private fun getEventInfoForEvent(event: ModlogEvent): List { @@ -141,7 +146,11 @@ class GuildSettingsModeration { } is Guild -> { affectedType = "Guild" - null + affected.name + } + is GuildChannel -> { + affectedType = "Channel" + affected.name } else -> null } @@ -153,9 +162,27 @@ class GuildSettingsModeration { } webhookEmbedBuilder.setColor(modlogEventStore.trigger.messageType.color.rgb) if (modlogEventStore.responsible != null) { - webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventStore.responsible.name + " (" + modlogEventStore.responsible.id + ")", null)) + webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventStore.responsible!!.name + " (" + modlogEventStore.responsible!!.id + ")", null)) } webhookClient?.send(webhookEmbedBuilder.build()); } } + + class MongoModlogEventObject { + + private var guildId: Long = 0; + private var modlogEventStore: ModlogEventStore? = null + + private var createdDate: Date = Date() + private var tier: String = "" + + private constructor() + + constructor(guildId: Long, modlogEventStore: ModlogEventStore, tier: String) { + this.guildId = guildId + this.modlogEventStore = modlogEventStore + this.tier = tier + } + + } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index f2ae6a1a0..4cabe05f6 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -1,14 +1,50 @@ package org.cascadebot.cascadebot.data.objects +import net.dv8tion.jda.api.entities.Emote +import net.dv8tion.jda.api.entities.Guild +import net.dv8tion.jda.api.entities.GuildChannel import net.dv8tion.jda.api.entities.ISnowflake +import net.dv8tion.jda.api.entities.Role import net.dv8tion.jda.api.entities.User +import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.utils.LanguageEmbedField -data class ModlogEventStore( - val trigger: ModlogEvent, - val responsible: User?, - val affected: ISnowflake, +class ModlogEventStore { + var trigger: ModlogEvent = ModlogEvent.CASCADE_BLACKLIST - val extraInfo: List -) \ No newline at end of file + @Transient + var responsible: User? = null + + @Transient + var affected: ISnowflake = CascadeBot.INS.selfUser + + var extraInfo: List = ArrayList() + + var affectedId: Long = 0 + var affectedType: String = "" + + var responsibleId: Long = 0; + + constructor(trigger: ModlogEvent, responsible: User?, affected: ISnowflake, extraInfo: List) { + this.trigger = trigger + this.responsible = responsible + this.affected = affected + this.extraInfo = extraInfo + + affectedId = affected.idLong + affectedType = when (affected) { + is User -> "User" + is Role -> "Role" + is Emote -> "Emote" + is Guild -> "Guild" + is GuildChannel -> "Channel" + else -> "unknown" + } + + responsibleId = responsible!!.idLong + } + + constructor() + +} \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt index be6f21177..f8c35779a 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt @@ -20,10 +20,12 @@ class LanguageEmbedField { this.inline = inline; this.titleLanguagePath = titleLanguagePath this.valueLanguagePath = valueLanguagePath - this.titleLanguageObjects.addAll(valueLanguageObjects) + this.valueLanguageObjects.addAll(valueLanguageObjects) // TODO add checks for if language string exists } + constructor() + fun addTitleObjects(vararg titleLanguageObjects: String) { this.titleLanguageObjects.addAll(titleLanguageObjects) // TODO add checks for if there is room for objects in language string From 34fb1130711d625d6b330fabd9e81ba9db472f9b Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 28 May 2020 17:08:57 -0500 Subject: [PATCH 021/206] Enable and disable commands Also minor fixes --- .../commands/moderation/ModlogCommand.java | 34 +++++ .../moderation/ModlogDisableSubCommand.java | 142 +++++++++++++++++ .../moderation/ModlogEnableSubCommand.java | 143 ++++++++++++++++++ .../events/ModlogEventListener.java | 3 + .../data/objects/GuildSettingsModeration.kt | 25 ++- .../data/objects/ModlogEventStore.kt | 4 +- 6 files changed, 342 insertions(+), 9 deletions(-) create mode 100644 src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java create mode 100644 src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java create mode 100644 src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java new file mode 100644 index 000000000..513d30574 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java @@ -0,0 +1,34 @@ +package org.cascadebot.cascadebot.commands.moderation; + +import net.dv8tion.jda.api.entities.Member; +import org.cascadebot.cascadebot.commandmeta.CommandContext; +import org.cascadebot.cascadebot.commandmeta.MainCommand; +import org.cascadebot.cascadebot.commandmeta.Module; +import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.permissions.CascadePermission; + +import java.util.Set; + +public class ModlogCommand extends MainCommand { + + public void onCommand(Member sender, CommandContext context) { + context.getUiMessaging().replyUsage(); + + } + + public String command() { + return "modlog"; + } + + public CascadePermission permission() { + return CascadePermission.of("modlog", false, Module.MODERATION); + } + + public Module module() { + return Module.MODERATION; + } + + public Set subCommands() { + return Set.of(new ModlogEnableSubCommand(), new ModlogDisableSubCommand()); + } +} diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java new file mode 100644 index 000000000..367871516 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java @@ -0,0 +1,142 @@ +package org.cascadebot.cascadebot.commands.moderation; + +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.TextChannel; +import org.apache.commons.lang3.EnumUtils; +import org.cascadebot.cascadebot.commandmeta.CommandContext; +import org.cascadebot.cascadebot.commandmeta.Module; +import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.messaging.MessageType; +import org.cascadebot.cascadebot.moderation.ModlogEvent; +import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.DiscordUtils; +import org.cascadebot.cascadebot.utils.pagination.Page; +import org.cascadebot.cascadebot.utils.pagination.PageObjects; +import org.cascadebot.cascadebot.utils.pagination.PageUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class ModlogDisableSubCommand extends SubCommand { + + @Override + public void onCommand(Member sender, CommandContext context) { + if (context.getArgs().length < 2) { + context.getUiMessaging().replyUsage(); + return; + } + TextChannel textChannel = DiscordUtils.getTextChannel(context.getGuild(), context.getArg(0)); + if (textChannel == null) { + context.reply("Invalid channel"); + // Invalid channel + return; + } + List events = new ArrayList<>(Arrays.asList(context.getArgs())); + events.remove(0); + List modlogEvents = new ArrayList<>(); + List failed = new ArrayList<>(); + for (String event : events) { + if (EnumUtils.isValidEnum(ModlogEvent.class, event.toUpperCase())) { + modlogEvents.add(ModlogEvent.valueOf(event.toUpperCase())); + } else if (EnumUtils.isValidEnum(ModlogEvent.Category.class, event.toUpperCase())){ + ModlogEvent.Category category = ModlogEvent.Category.valueOf(event.toUpperCase()); + List additionalEvents = ModlogEvent.getEventsFromCategory(category); + modlogEvents.addAll(additionalEvents); + } else { + failed.add(event); + } + } + if (failed.size() == events.size()) { + context.getTypedMessaging().replyDanger("Failed to find all specified events"); + return; + } + List failedEvents = new ArrayList<>(); + List succeed = new ArrayList<>(); + for (ModlogEvent event : modlogEvents) { + if (context.getData().getModeration().disableEvent(textChannel, event)) { + succeed.add(event); + } else { + failedEvents.add(event); + } + } + List pageList = new ArrayList<>(); + if (failedEvents.size() == modlogEvents.size()) { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageType.DANGER.getColor()); + embedBuilder.setTitle("Failed to disable all specified events"); + embedBuilder.setDescription("Failed to disable or find all specified events. Refer to the other pages for more info"); + pageList.add(new PageObjects.EmbedPage(embedBuilder)); + } else { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageType.SUCCESS.getColor()); + embedBuilder.setTitle("Successfully disabled events!"); + embedBuilder.setDescription("Some events may have still failed to disable, check other pages for more info"); + pageList.add(new PageObjects.EmbedPage(embedBuilder)); + } + if (succeed.size() > 0) { + List pageValues = PageUtils.splitString(succeed.stream().map(event -> event.name().toLowerCase()).collect(Collectors.joining("\n")), 1000, '\n'); + int subPage = 1; + for (String pageValue: pageValues) { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageType.SUCCESS.getColor()); + embedBuilder.setTitle("Disabled Events"); + embedBuilder.setDescription("These events where successfully disabled in the specified channel"); + embedBuilder.addField("Events", pageValue, false); + if (pageValues.size() > 1) { + embedBuilder.addField("Sub Page", subPage + "/" + pageValues.size(), true); + subPage++; + } + pageList.add(new PageObjects.EmbedPage(embedBuilder)); + } + } + if (failedEvents.size() > 0) { + List pageValues = PageUtils.splitString(failedEvents.stream().map(event -> event.name().toLowerCase()).collect(Collectors.joining("\n")), 1000, '\n'); + int subPage = 1; + for (String pageValue: pageValues) { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageType.WARNING.getColor()); + embedBuilder.setTitle("Failed to disable events"); + embedBuilder.setDescription("These events failed to disable. This means they are probably not enabled in that channel"); + embedBuilder.addField("Events", pageValue, false); + if (pageValues.size() > 1) { + embedBuilder.addField("Sub Page", subPage + "/" + pageValues.size(), true); + subPage++; + } + pageList.add(new PageObjects.EmbedPage(embedBuilder)); + } + } + if (failed.size() > 0) { + List pageValues = PageUtils.splitString(String.join("\n", failed), 1000, '\n'); + int subPage = 1; + for (String pageValue: pageValues) { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageType.DANGER.getColor()); + embedBuilder.setTitle("Failed to find events"); + embedBuilder.setDescription("The events specified where not found, so could not be disabled. Refer to `;modlog events` for list of available events"); + embedBuilder.addField("Events", pageValue, false); + if (pageValues.size() > 1) { + embedBuilder.addField("Sub Page", subPage + "/" + pageValues.size(), true); + subPage++; + } + pageList.add(new PageObjects.EmbedPage(embedBuilder)); + } + } + context.getUiMessaging().sendPagedMessage(pageList); + } + + public String command() { + return "disable"; + } + + public CascadePermission permission() { + return CascadePermission.of("modlog.disable", false, Module.MODERATION); + } + + public String parent() { + return "modlog"; + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java new file mode 100644 index 000000000..21816da9d --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java @@ -0,0 +1,143 @@ +package org.cascadebot.cascadebot.commands.moderation; + +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.TextChannel; +import org.apache.commons.lang3.EnumUtils; +import org.cascadebot.cascadebot.commandmeta.CommandContext; +import org.cascadebot.cascadebot.commandmeta.Module; +import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.LoopMode; +import org.cascadebot.cascadebot.messaging.MessageType; +import org.cascadebot.cascadebot.moderation.ModlogEvent; +import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.DiscordUtils; +import org.cascadebot.cascadebot.utils.pagination.Page; +import org.cascadebot.cascadebot.utils.pagination.PageObjects; +import org.cascadebot.cascadebot.utils.pagination.PageUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class ModlogEnableSubCommand extends SubCommand { + + @Override + public void onCommand(Member sender, CommandContext context) { + if (context.getArgs().length < 2) { + context.getUiMessaging().replyUsage(); + return; + } + TextChannel textChannel = DiscordUtils.getTextChannel(context.getGuild(), context.getArg(0)); + if (textChannel == null) { + context.reply("Invalid channel"); + // Invalid channel + return; + } + List events = new ArrayList<>(Arrays.asList(context.getArgs())); + events.remove(0); + List modlogEvents = new ArrayList<>(); + List failed = new ArrayList<>(); + for (String event : events) { + if (EnumUtils.isValidEnum(ModlogEvent.class, event.toUpperCase())) { + modlogEvents.add(ModlogEvent.valueOf(event.toUpperCase())); + } else if (EnumUtils.isValidEnum(ModlogEvent.Category.class, event.toUpperCase())){ + ModlogEvent.Category category = ModlogEvent.Category.valueOf(event.toUpperCase()); + List additionalEvents = ModlogEvent.getEventsFromCategory(category); + modlogEvents.addAll(additionalEvents); + } else { + failed.add(event); + } + } + if (failed.size() == events.size()) { + context.getTypedMessaging().replyDanger("Failed to find all specified events"); + return; + } + List failedEvents = new ArrayList<>(); + List succeed = new ArrayList<>(); + for (ModlogEvent event : modlogEvents) { + if (context.getData().getModeration().enableEvent(textChannel, event)) { + succeed.add(event); + } else { + failedEvents.add(event); + } + } + List pageList = new ArrayList<>(); + if (failedEvents.size() == modlogEvents.size()) { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageType.DANGER.getColor()); + embedBuilder.setTitle("Failed to enable all specified events"); + embedBuilder.setDescription("Failed to enable or find all specified events. Refer to the other pages for more info"); + pageList.add(new PageObjects.EmbedPage(embedBuilder)); + } else { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageType.SUCCESS.getColor()); + embedBuilder.setTitle("Successfully enabled events!"); + embedBuilder.setDescription("Some events may have still failed to enable, check other pages for more info"); + pageList.add(new PageObjects.EmbedPage(embedBuilder)); + } + if (succeed.size() > 0) { + List pageValues = PageUtils.splitString(succeed.stream().map(event -> event.name().toLowerCase()).collect(Collectors.joining("\n")), 1000, '\n'); + int subPage = 1; + for (String pageValue: pageValues) { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageType.SUCCESS.getColor()); + embedBuilder.setTitle("Enabled Events"); + embedBuilder.setDescription("These events where successfully enabled in the specified channel"); + embedBuilder.addField("Events", pageValue, false); + if (pageValues.size() > 1) { + embedBuilder.addField("Sub Page", subPage + "/" + pageValues.size(), true); + subPage++; + } + pageList.add(new PageObjects.EmbedPage(embedBuilder)); + } + } + if (failedEvents.size() > 0) { + List pageValues = PageUtils.splitString(failedEvents.stream().map(event -> event.name().toLowerCase()).collect(Collectors.joining("\n")), 1000, '\n'); + int subPage = 1; + for (String pageValue: pageValues) { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageType.WARNING.getColor()); + embedBuilder.setTitle("Failed to enable events"); + embedBuilder.setDescription("These events failed to enable. This means they are probably already enabled in that channel"); + embedBuilder.addField("Events", pageValue, false); + if (pageValues.size() > 1) { + embedBuilder.addField("Sub Page", subPage + "/" + pageValues.size(), true); + subPage++; + } + pageList.add(new PageObjects.EmbedPage(embedBuilder)); + } + } + if (failed.size() > 0) { + List pageValues = PageUtils.splitString(String.join("\n", failed), 1000, '\n'); + int subPage = 1; + for (String pageValue: pageValues) { + EmbedBuilder embedBuilder = new EmbedBuilder(); + embedBuilder.setColor(MessageType.DANGER.getColor()); + embedBuilder.setTitle("Failed to find events"); + embedBuilder.setDescription("The events specified where not found, so could not be enabled. Refer to `;modlog events` for list of available events"); + embedBuilder.addField("Events", pageValue, false); + if (pageValues.size() > 1) { + embedBuilder.addField("Sub Page", subPage + "/" + pageValues.size(), true); + subPage++; + } + pageList.add(new PageObjects.EmbedPage(embedBuilder)); + } + } + context.getUiMessaging().sendPagedMessage(pageList); + } + + public String command() { + return "enable"; + } + + public CascadePermission permission() { + return CascadePermission.of("modlog.enable", false, Module.MODERATION); + } + + public String parent() { + return "modlog"; + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index eeb573bb4..1ba7b9a42 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -288,6 +288,9 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { } public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { + if (event.getAuthor().isBot()) { + return; + } GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); Message message = event.getMessage(); String messageJson = CascadeBot.INS.getRedisClient().get("message:" + message.getId()); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index fcb3b3fe5..a1dc4069c 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -71,11 +71,20 @@ class GuildSettingsModeration { } } - fun enableEvent(channel: TextChannel, event: ModlogEvent) { + fun enableEvent(channel: TextChannel, event: ModlogEvent): Boolean { if (modlogEvents.containsKey(channel.idLong)) { - modlogEvents[channel.idLong]?.addEvent(event) + return modlogEvents[channel.idLong]!!.addEvent(event) } else { createModlogEventsInfo(channel, Consumer { it.addEvent(event) }) + return true + } + } + + fun disableEvent(channel: TextChannel, event: ModlogEvent): Boolean { + if (modlogEvents.containsKey(channel.idLong)) { + return modlogEvents[channel.idLong]!!.removeEvent(event) + } else { + return false } } @@ -94,7 +103,7 @@ class GuildSettingsModeration { } class ChannelModlogEventsInfo { - private val events: MutableList = ArrayList() + private val events: MutableSet = LinkedHashSet() private var webhookId: Long = 0 private var webhookToken: String = "" @@ -114,15 +123,15 @@ class GuildSettingsModeration { } fun getEvents(): List { - return Collections.unmodifiableList(events) + return ArrayList(events) } - fun addEvent(event: ModlogEvent) { - events.add(event) + fun addEvent(event: ModlogEvent): Boolean { + return events.add(event) } - fun removeEvent(event: ModlogEvent) { - events.remove(event) + fun removeEvent(event: ModlogEvent): Boolean { + return events.remove(event) } fun sendEvent(guildData: GuildData, modlogEventStore: ModlogEventStore) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 4cabe05f6..34d2c99ce 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -42,7 +42,9 @@ class ModlogEventStore { else -> "unknown" } - responsibleId = responsible!!.idLong + if (responsible != null) { + responsibleId = responsible.idLong + } } constructor() From 5a189c2816e375237be23e2348c1f80f443f92fc Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 1 Jun 2020 16:19:33 -0500 Subject: [PATCH 022/206] Store most message metadata --- .../cascadebot/cascadebot/data/Config.java | 4 +- .../events/ModlogEventListener.java | 40 ++++---- .../runnables/MessageReceivedRunnable.java | 26 +++--- .../data/objects/GuildSettingsModeration.kt | 28 ++++-- .../cascadebot/utils/SerializableMessage.kt | 93 +++++++++++++++++++ 5 files changed, 151 insertions(+), 40 deletions(-) create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/utils/SerializableMessage.kt diff --git a/src/main/java/org/cascadebot/cascadebot/data/Config.java b/src/main/java/org/cascadebot/cascadebot/data/Config.java index 872b1d764..3b5816e4e 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/Config.java +++ b/src/main/java/org/cascadebot/cascadebot/data/Config.java @@ -263,8 +263,8 @@ private void initConfig() throws IOException { String stringIv = config.getString("encryption_key.iv"); byte[] ivBytes = stringIv.getBytes(); - if (ivBytes.length != 8) { - CascadeBot.LOGGER.warn("Encryption iv invalid size! must be 64 bits!"); + if (ivBytes.length != 16) { + CascadeBot.LOGGER.warn("Encryption iv invalid size! must be 128 bits!"); } else { this.ivSpec = ivBytes; } diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 1ba7b9a42..e09f6543c 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -93,6 +93,7 @@ import org.cascadebot.cascadebot.utils.ColorUtils; import org.cascadebot.cascadebot.utils.CryptUtils; import org.cascadebot.cascadebot.utils.LanguageEmbedField; +import org.cascadebot.cascadebot.utils.SerializableMessage; import org.jetbrains.annotations.NotNull; import javax.crypto.BadPaddingException; @@ -259,14 +260,16 @@ public void onGuildUnban(GuildUnbanEvent event) { public void onGuildMessageDelete(GuildMessageDeleteEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); String messageID = event.getMessageId(); - String messageJson = CascadeBot.INS.getRedisClient().get("message:" + messageID); + String messageString = CascadeBot.INS.getRedisClient().get("message:" + messageID); CascadeBot.INS.getRedisClient().del("message:" + messageID); - JsonObject jsonObject = new JsonParser().parse(messageJson).getAsJsonObject(); - long messageSender = jsonObject.get("sender").getAsLong(); - User affected = CascadeBot.INS.getClient().getUserById(messageSender); + SerializableMessage message = getMessageFromString(messageString); + if (message == null) { + return; + } + User affected = CascadeBot.INS.getClient().getUserById(message.getAuthorId()); List embedFieldList = new ArrayList<>(); LanguageEmbedField messageEmbedField = new LanguageEmbedField(false, "modlog.message.message", "modlog.general.variable"); - messageEmbedField.addValueObjects(getMessageFromJson(jsonObject)); + messageEmbedField.addValueObjects(message.getContent()); embedFieldList.add(messageEmbedField); if (affected == null) { return; @@ -293,29 +296,28 @@ public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { } GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); Message message = event.getMessage(); - String messageJson = CascadeBot.INS.getRedisClient().get("message:" + message.getId()); + String messageString = CascadeBot.INS.getRedisClient().get("message:" + message.getId()); CascadeBot.INS.getRedisClient().del("message:" + message.getId()); - JsonObject jsonObject = new JsonParser().parse(messageJson).getAsJsonObject(); - long messageSender = jsonObject.get("sender").getAsLong(); - User affected = CascadeBot.INS.getClient().getUserById(messageSender); + SerializableMessage oldMessage = getMessageFromString(messageString); + if (oldMessage == null) { + return; + } + User affected = message.getAuthor(); List embedFieldList = new ArrayList<>(); LanguageEmbedField oldEmbedField = new LanguageEmbedField(false, "modlog.message.old_message", "modlog.general.variable"); - oldEmbedField.addValueObjects(getMessageFromJson(jsonObject)); + oldEmbedField.addValueObjects(oldMessage.getContent()); LanguageEmbedField newEmbedField = new LanguageEmbedField(false, "modlog.message.new_message", "modlog.general.variable"); newEmbedField.addValueObjects(message.getContentRaw()); embedFieldList.add(newEmbedField); - if (affected == null) { - return; - } ModlogEvent modlogEvent = ModlogEvent.GUILD_MESSAGE_UPDATED; ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, null, affected, embedFieldList); guildData.getModeration().sendModlogEvent(eventStore); } - private String getMessageFromJson(JsonObject jsonObject) { + private SerializableMessage getMessageFromString(String messageString) { String message; if (Config.INS.getEncryptKey() != null) { - JsonArray bytesJsonArray = jsonObject.get("content").getAsJsonArray(); + JsonArray bytesJsonArray = new JsonParser().parse(messageString).getAsJsonArray(); byte[] messageBytes = new byte[bytesJsonArray.size()]; for (int i = 0; i < bytesJsonArray.size(); i++) { messageBytes[i] = bytesJsonArray.get(i).getAsByte(); @@ -325,15 +327,15 @@ private String getMessageFromJson(JsonObject jsonObject) { } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | ShortBufferException e) { e.printStackTrace(); // TODO log these - return ""; + return null; } catch (BadPaddingException e) { e.printStackTrace(); - return ""; + return null; } } else { - message = jsonObject.get("content").getAsString(); + message = messageString; } - return message; + return CascadeBot.getGSON().fromJson(message, SerializableMessage.class); } //endregion diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java index d25427bdf..2ef00c3db 100644 --- a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java +++ b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java @@ -1,5 +1,8 @@ package org.cascadebot.cascadebot.runnables; +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.JsonObject; import com.google.gson.JsonPrimitive; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; @@ -8,17 +11,22 @@ import org.cascadebot.cascadebot.data.Config; import org.cascadebot.cascadebot.utils.CryptUtils; import org.cascadebot.cascadebot.utils.PasteUtils; +import org.cascadebot.cascadebot.utils.SerializableMessage; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.ShortBufferException; +import java.io.IOException; +import java.io.StringWriter; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; public class MessageReceivedRunnable implements Runnable { @@ -32,23 +40,19 @@ public void run() { if (event.getMember() == null) { return; } + SerializableMessage serializableMessage = SerializableMessage.createSerializeMessageFromJda(event.getMessage()); + String messageJson = CascadeBot.getGSON().toJson(serializableMessage); String message = ""; if (Config.INS.getEncryptKey() != null) { try { - byte[] results = CryptUtils.encryptString(Config.INS.getEncryptKey(), Config.INS.getIvSpec(), event.getMessage().getContentRaw()); - JsonObject jsonObject = new JsonObject(); - jsonObject.add("sender", new JsonPrimitive(event.getMember().getIdLong())); - jsonObject.add("content", CascadeBot.getGSON().toJsonTree(results)); - message = CascadeBot.getGSON().toJson(jsonObject); - } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | ShortBufferException | BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException ignored) { - CascadeBot.LOGGER.warn("Failed to encrypt", ignored); + byte[] results = CryptUtils.encryptString(Config.INS.getEncryptKey(), Config.INS.getIvSpec(), messageJson); + message = CascadeBot.getGSON().toJson(CascadeBot.getGSON().toJsonTree(results)); + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | ShortBufferException | BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException exception) { + CascadeBot.LOGGER.warn("Failed to encrypt", exception); return; } } else { - JsonObject jsonObject = new JsonObject(); - jsonObject.add("sender", new JsonPrimitive(event.getMember().getIdLong())); - jsonObject.add("content", CascadeBot.getGSON().toJsonTree(event.getMessage().getContentRaw())); - message = CascadeBot.getGSON().toJson(jsonObject); + message = messageJson; } CascadeBot.INS.getRedisClient().set("message:" + event.getMessageId(), message); CascadeBot.INS.getRedisClient().expire("message:" + event.getMessageId(), (int) TimeUnit.HOURS.toSeconds(24)); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index a1dc4069c..6ae4034eb 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -2,6 +2,7 @@ package org.cascadebot.cascadebot.data.objects import club.minnced.discord.webhook.WebhookClient import club.minnced.discord.webhook.WebhookClientBuilder +import club.minnced.discord.webhook.exception.HttpException import club.minnced.discord.webhook.send.WebhookEmbed import club.minnced.discord.webhook.send.WebhookEmbed.EmbedField import club.minnced.discord.webhook.send.WebhookEmbed.EmbedTitle @@ -61,8 +62,8 @@ class GuildSettingsModeration { return channelModlogEventsInfos } - fun getModlogEvents(): List { - return modlogEvents.map { entry -> entry.value } + fun getModlogEvents(): Map { + return modlogEvents } fun buildWebhookClients() { @@ -95,23 +96,26 @@ class GuildSettingsModeration { } private fun createModlogEventsInfo(channel: TextChannel, consumer: Consumer) { + val eventsInfo = ChannelModlogEventsInfo() + modlogEvents.put(channel.idLong, eventsInfo) channel.createWebhook("Cascade-modlog").setAvatar(Icon.from(URL(CascadeBot.INS.client.selfUser.avatarUrl).openStream())).queue { webhook -> - val eventsInfo = ChannelModlogEventsInfo(webhook.idLong, webhook.token!!) - modlogEvents.put(channel.idLong, eventsInfo) + eventsInfo.webhookId = webhook.idLong + eventsInfo.webhookToken = webhook.token!! + eventsInfo.buildWebhookClient() consumer.accept(eventsInfo) } } class ChannelModlogEventsInfo { private val events: MutableSet = LinkedHashSet() - private var webhookId: Long = 0 - private var webhookToken: String = "" + internal var webhookId: Long = 0 + internal var webhookToken: String = "" @Transient @kotlin.jvm.Transient private var webhookClient: WebhookClient? = null - private constructor() {} + internal constructor() {} constructor(webhookId: Long, webhookToken: String) { this.webhookId = webhookId this.webhookToken = webhookToken @@ -134,6 +138,10 @@ class GuildSettingsModeration { return events.remove(event) } + fun getWebhookId() : Long { + return webhookId + } + fun sendEvent(guildData: GuildData, modlogEventStore: ModlogEventStore) { val webhookEmbedBuilder = WebhookEmbedBuilder() webhookEmbedBuilder.setTitle(EmbedTitle(modlogEventStore.trigger.name, null)) @@ -173,7 +181,11 @@ class GuildSettingsModeration { if (modlogEventStore.responsible != null) { webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventStore.responsible!!.name + " (" + modlogEventStore.responsible!!.id + ")", null)) } - webhookClient?.send(webhookEmbedBuilder.build()); + try { + webhookClient?.send(webhookEmbedBuilder.build()) + } catch (ignored: HttpException) { + // TODO not ignore + } } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/SerializableMessage.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/SerializableMessage.kt new file mode 100644 index 000000000..343598f6a --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/SerializableMessage.kt @@ -0,0 +1,93 @@ +package org.cascadebot.cascadebot.utils + +import club.minnced.discord.webhook.send.WebhookEmbed +import club.minnced.discord.webhook.send.WebhookEmbedBuilder +import net.dv8tion.jda.api.entities.Message +import net.dv8tion.jda.api.entities.Message.MessageFlag +import net.dv8tion.jda.api.entities.MessageEmbed +import net.dv8tion.jda.api.entities.MessageType +import java.time.OffsetDateTime +import java.util.stream.Collectors + +class SerializableMessage( + var id: Long, + var channelId: Long, + var guildId: Long, + var authorId: Long, + var content: String, + var sent: OffsetDateTime, + var edited: OffsetDateTime?, + var tts: Boolean, + var mentionsEveryone: Boolean, + var userMentions: List, + var channelMentions: List, + var roleMentions: List, + var attachments: List, + var embeds: List, + var reactions: List, + var pinned: Boolean, + var messageType: MessageType, + var messageFlags: List? +) { + companion object { + @JvmStatic + fun createSerializeMessageFromJda(message: Message): SerializableMessage? { + val userMentions: List = message.mentionedUsers.stream().map { it.idLong }.collect(Collectors.toList()) + val channelMentions: List = message.mentionedChannels.stream().map { ChannelMention(it.idLong, it.guild.idLong) }.collect(Collectors.toList()) + val roleMentions: List = message.mentionedRoles.stream().map { it.idLong }.collect(Collectors.toList()) + val attachments: List = message.attachments.stream().map { Attachment(it.idLong, it.fileName, it.size, it.url) }.collect(Collectors.toList()) + val embeds: List = message.embeds.stream().map { + var webhookEmbedBuilder = WebhookEmbedBuilder() + if (it.title != null) { + webhookEmbedBuilder.setTitle(WebhookEmbed.EmbedTitle(it.title!!, it.url)) + } + if (it.description != null) { + webhookEmbedBuilder.setDescription(it.description) + } + if (it.timestamp != null) { + webhookEmbedBuilder.setTimestamp(it.timestamp) + } + webhookEmbedBuilder.setColor(it.colorRaw) + if (it.footer != null) { + webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(it.footer!!.text!!, it.footer!!.iconUrl)) + } + if (it.image != null) { + webhookEmbedBuilder.setImageUrl(it.image!!.url) + } + if (it.thumbnail != null) { + webhookEmbedBuilder.setThumbnailUrl(it.thumbnail!!.url) + } + if (it.author != null) { + webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(it.author!!.name!!, it.author!!.iconUrl, it.author!!.url)) + } + for (field: MessageEmbed.Field in it.fields) { + webhookEmbedBuilder.addField(WebhookEmbed.EmbedField(field.isInline, field.name!!, field.value!!)) + } + webhookEmbedBuilder.build() + }.collect(Collectors.toList()) + val reactions: List = message.reactions.stream().map { Reaction(it.count, it.reactionEmote.idLong, it.reactionEmote.name) }.collect(Collectors.toList()) + return SerializableMessage(message.idLong, message.channel.idLong, message.guild.idLong, message.author.idLong, + message.contentRaw, message.timeCreated, message.timeEdited, message.isTTS, message.mentionsEveryone(), + userMentions, channelMentions, roleMentions, attachments, embeds, reactions, message.isPinned, message.type, + message.flags.stream().collect(Collectors.toList())); + } + } +} + +data class Attachment( + var id: Long, + var fileName: String, + var size: Int, + var url: String +) + +data class ChannelMention( + var id: Long, + var guildId: Long +) + +data class Reaction( + var count: Int, + var id: Long?, + var name: String +) \ No newline at end of file From 925cd022cbd3dcbe31f0f63f5969b29b0e98322c Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 4 Jun 2020 11:17:45 -0500 Subject: [PATCH 023/206] Modlog channel sub command --- .../moderation/ModlogChannelSubCommand.java | 198 ++++++++++++++++++ .../commands/moderation/ModlogCommand.java | 2 +- .../moderation/ModlogEventsSubCommand.java | 66 ++++++ .../data/managers/GuildDataManager.java | 3 + .../events/ModlogEventListener.java | 13 +- .../data/objects/GuildSettingsModeration.kt | 22 +- 6 files changed, 297 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java create mode 100644 src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java new file mode 100644 index 000000000..e8a9c8e3d --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java @@ -0,0 +1,198 @@ +package org.cascadebot.cascadebot.commands.moderation; + +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.TextChannel; +import net.dv8tion.jda.api.entities.Webhook; +import org.cascadebot.cascadebot.CascadeBot; +import org.cascadebot.cascadebot.commandmeta.CommandContext; +import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.GuildSettingsModeration; +import org.cascadebot.cascadebot.messaging.MessagingObjects; +import org.cascadebot.cascadebot.moderation.ModlogEvent; +import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.DiscordUtils; +import org.cascadebot.cascadebot.utils.pagination.Page; +import org.cascadebot.cascadebot.utils.pagination.PageObjects; +import org.cascadebot.cascadebot.utils.pagination.PageUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +public class ModlogChannelSubCommand extends SubCommand { + + public void onCommand(Member sender, CommandContext context) { + if (context.getArgs().length < 1) { + context.getUiMessaging().replyUsage(); + return; + } + if (context.getArg(0).equalsIgnoreCase("list")) { + StringBuilder enabled = new StringBuilder(); + StringBuilder disabled = new StringBuilder(); + StringBuilder deleted = new StringBuilder(); + Set> channelModlogEventsSet = context.getData().getModeration().getModlogEvents().entrySet(); + if (channelModlogEventsSet.size() == 0) { + context.reply("No channels have been set up with modlog events!"); + return; + } + for (Map.Entry channelModlogEventsInfo : channelModlogEventsSet) { + TextChannel modlogChannel = CascadeBot.INS.getShardManager().getTextChannelById(channelModlogEventsInfo.getKey()); + boolean channelExists = modlogChannel != null; + boolean someEvents = false; + int numEvents = channelModlogEventsInfo.getValue().getEvents().size(); + if (numEvents > 5) { + numEvents = 3; + someEvents = true; + } + boolean webhookExists = false; + if (modlogChannel != null) { + List webhooks = modlogChannel.retrieveWebhooks().complete(); + for (Webhook webhook : webhooks) { + if (webhook.getIdLong() == channelModlogEventsInfo.getValue().getWebhookId()) { + webhookExists = true; + break; + } + } + } + String eventsListString = channelModlogEventsInfo.getValue().getEvents().stream().limit(numEvents).map(Enum::name).collect(Collectors.joining(", ")); + if (someEvents) { + eventsListString += ", and " + (channelModlogEventsInfo.getValue().getEvents().size() - 3) + " more"; + } + if (channelExists && webhookExists) { // Channel exists and is enabled + enabled.append(modlogChannel.getAsMention()).append(" - ").append(eventsListString).append('\n'); + } else if (channelExists) { // Channel exists, but is disabled + disabled.append(modlogChannel.getAsMention()).append(" - ").append(eventsListString).append('\n'); + } else { // Channel doesn't exist + deleted.append("#deleted-channel (" + channelModlogEventsInfo.getValue().getId() + ") - ").append(eventsListString).append('\n'); + } + } + List pages = new ArrayList<>(); + if (enabled.length() > 0) { + EmbedBuilder enabledBuilder = new EmbedBuilder(); + enabledBuilder.setTitle("Channel list - Enabled"); + enabledBuilder.setDescription(enabled.toString()); + pages.add(new PageObjects.EmbedPage(enabledBuilder)); + } + if (disabled.length() > 0) { + EmbedBuilder disabledBuilder = new EmbedBuilder(); + disabledBuilder.setTitle("Channel list - disabled"); + disabledBuilder.setDescription(disabled.toString()); + pages.add(new PageObjects.EmbedPage(disabledBuilder)); + } + if (deleted.length() > 0) { + EmbedBuilder deletedBuilder = new EmbedBuilder(); + deletedBuilder.setTitle("Channel list - deleted channels"); + deletedBuilder.setDescription(deleted.toString()); + pages.add(new PageObjects.EmbedPage(deletedBuilder)); + } + context.getUiMessaging().sendPagedMessage(pages); + return; + } + if (context.getArgs().length == 3 && context.getArg(0).equalsIgnoreCase("move")) { + TextChannel targetChannel = DiscordUtils.getTextChannel(context.getGuild(), context.getArg(2)); + if (targetChannel == null) { + context.getTypedMessaging().replyDanger("Couldn't find channel `" + context.getArg(2) + "`"); + return; + } + GuildSettingsModeration.ChannelModlogEventsInfo channelModlogEventsInfo = null; + if (context.isArgInteger(1)) { + int id = context.getArgAsInteger(1); + for (Map.Entry eventsInfoEntry : context.getData().getModeration().getModlogEvents().entrySet()) { + if (eventsInfoEntry.getValue().getId() == id) { + channelModlogEventsInfo = eventsInfoEntry.getValue(); + } + } + } else { + TextChannel originalChannel = DiscordUtils.getTextChannel(context.getGuild(), context.getArg(1)); + if (originalChannel != null) { + channelModlogEventsInfo = context.getData().getModeration().getModlogEvents().get(originalChannel.getIdLong()); + } + } + if (channelModlogEventsInfo == null) { + context.reply("Couldn't find events for channel `" + context.getArg(1) + "`"); + return; + } + for (ModlogEvent event : channelModlogEventsInfo.getEvents()) { + context.getData().getModeration().enableEvent(targetChannel, event); + } + context.getTypedMessaging().replySuccess("Successfully moved all events!"); + return; + } + if (context.getArgs().length < 2) { + context.getUiMessaging().replyUsage(); + return; + } + TextChannel channel = DiscordUtils.getTextChannel(context.getGuild(), context.getArg(1)); + if (channel == null) { + context.getTypedMessaging().replyDanger("Couldn't find channel `" + context.getArg(1) + "`"); + return; + } + if (!context.getData().getModeration().getModlogEvents().containsKey(channel.getIdLong())) { + context.getTypedMessaging().replyDanger("The specified channel is not a modlog channel!"); + return; + } + if (context.getArg(0).equalsIgnoreCase("enable")) { + if (isEnabled(channel, context)) { + context.getTypedMessaging().replyDanger("Channel is already enabled!"); + return; + } + channel.createWebhook("cascade-modlog").queue(webhook -> { + context.getData().getModeration().getModlogEvents().get(channel.getIdLong()).setNewWebhook(webhook.getIdLong(), webhook.getToken()); + context.getTypedMessaging().replySuccess("Successfully disabled channel!"); + }, throwable -> { + context.getTypedMessaging().replyDanger("Failed to enable events! The bot probably doesn't have permissions to create webhooks."); + }); + } else if (context.getArg(0).equalsIgnoreCase("disable")) { + if (!isEnabled(channel, context)) { + context.getTypedMessaging().replyDanger("Channel is already disabled!"); + return; + } + channel.deleteWebhookById(String.valueOf(context.getData().getModeration().getModlogEvents().get(channel.getIdLong()).getWebhookId())).queue(aVoid -> { + context.getTypedMessaging().replySuccess("Successfully enabled channel!"); + }, throwable -> { + context.getTypedMessaging().replyDanger("Failed to disable events! The bot probably doesn't have permissions to delete webhooks."); + }); + } else if (context.getArg(0).equalsIgnoreCase("delete")) { + context.getData().getModeration().getModlogEvents().remove(channel.getIdLong()); + context.getTypedMessaging().replySuccess("Successfully deleted channel!"); + } else if (context.getArg(0).equalsIgnoreCase("info")) { + GuildSettingsModeration.ChannelModlogEventsInfo channelModlogEventsInfo = context.getData().getModeration().getModlogEvents().get(channel.getIdLong()); + String events = channelModlogEventsInfo.getEvents().stream().map(ModlogEvent::name).collect(Collectors.joining("\n")); + context.getUiMessaging().sendPagedMessage(PageUtils.splitStringToEmbedPages(events, "Events for channel " + channel.getName(), 1000, '\n')); + } else { + context.getUiMessaging().replyUsage(); + } + } + + private boolean isEnabled(TextChannel channel, CommandContext context) { + boolean webhookExists = false; + if (channel != null) { + List webhooks = channel.retrieveWebhooks().complete(); + for (Webhook webhook : webhooks) { + if (webhook.getIdLong() == context.getData().getModeration().getModlogEvents().get(channel.getIdLong()).getWebhookId()) { + webhookExists = true; + break; + } + } + } + return webhookExists; + } + + public String command() { + return "channel"; + } + + public CascadePermission permission() { + return CascadePermission.of("modlog.channel", false); + } + + public String parent() { + return "modlog"; + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java index 513d30574..1e0a1cd7a 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java @@ -29,6 +29,6 @@ public Module module() { } public Set subCommands() { - return Set.of(new ModlogEnableSubCommand(), new ModlogDisableSubCommand()); + return Set.of(new ModlogEnableSubCommand(), new ModlogDisableSubCommand(), new ModlogEventsSubCommand(), new ModlogChannelSubCommand()); } } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java new file mode 100644 index 000000000..b1ecae3a1 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java @@ -0,0 +1,66 @@ +package org.cascadebot.cascadebot.commands.moderation; + +import net.dv8tion.jda.api.EmbedBuilder; +import net.dv8tion.jda.api.entities.Member; +import org.cascadebot.cascadebot.commandmeta.CommandContext; +import org.cascadebot.cascadebot.commandmeta.Module; +import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.messaging.MessageType; +import org.cascadebot.cascadebot.moderation.ModlogEvent; +import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.pagination.Page; +import org.cascadebot.cascadebot.utils.pagination.PageObjects; +import org.cascadebot.cascadebot.utils.pagination.PageUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class ModlogEventsSubCommand extends SubCommand { + + public void onCommand(Member sender, CommandContext context) { + Map> modlogCategoryMap = ModlogEvent.getModlogCategoryMap(); + List embedPages = new ArrayList<>(); + for (Map.Entry> categoryListEntry : modlogCategoryMap.entrySet()) { + ModlogEvent.Category category = categoryListEntry.getKey(); + if (category.equals(ModlogEvent.Category.ALL)) { + continue; + } + List pageValues = PageUtils.splitString(categoryListEntry.getValue().stream().map(event -> event.name().toLowerCase()).collect(Collectors.joining("\n")), 1000, '\n'); + int subPage = 1; + for (String pageValue: pageValues) { + EmbedBuilder embedBuilder = new EmbedBuilder() + .setColor(MessageType.INFO.getColor()) + .setTitle("Modlog Events"); + if (subPage == 1) { + embedBuilder.addField(category.name().toLowerCase(), pageValue, false); + } else { + embedBuilder.addField(category.name().toLowerCase() + " cont.", pageValue, false); + } + if (pageValues.size() > 1) { + embedBuilder.addField("Sub Page", subPage + "/" + pageValues.size(), true); + subPage++; + } + embedPages.add(new PageObjects.EmbedPage(embedBuilder)); + } + } + context.getUiMessaging().sendPagedMessage(embedPages); + } + + public String command() { + return "events"; + } + + public CascadePermission permission() { + return CascadePermission.of("modlog.events", false, Module.MODERATION); + } + + public String parent() { + return "modlog"; + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java index 3283ec775..357515b03 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java @@ -64,6 +64,9 @@ public static void replaceSync(long id, GuildData data) { } public static GuildData getGuildData(long id) { + if (id == 0) { + throw new UnsupportedOperationException("Cannot load guild with id 0"); + } return guilds.get(id); } diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index e09f6543c..806656edf 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -113,7 +113,6 @@ public class ModlogEventListener extends ListenerAdapter { - //TODO move everything over to using language paths instead of hard coded string public void onGenericEmote(GenericEmoteEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); Emote emote = event.getEmote(); @@ -133,9 +132,7 @@ public void onGenericEmote(GenericEmoteEvent event) { modlogEvent = ModlogEvent.EMOTE_UPDATED_NAME; LanguageEmbedField languageEmbedField = new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable"); languageEmbedField.addValueObjects(((EmoteUpdateNameEvent) event).getOldName()); - embedFieldList.add(languageEmbedField - //new WebhookEmbed.EmbedField(true, "Old Name", ((EmoteUpdateNameEvent) event).getOldName()) - ); + embedFieldList.add(languageEmbedField); } else if (event instanceof EmoteUpdateRolesEvent) { modlogEvent = ModlogEvent.EMOTE_UPDATED_ROLES; List oldRoles = ((EmoteUpdateRolesEvent) event).getOldRoles(); @@ -261,6 +258,9 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); String messageID = event.getMessageId(); String messageString = CascadeBot.INS.getRedisClient().get("message:" + messageID); + if (messageString == null) { + return; + } CascadeBot.INS.getRedisClient().del("message:" + messageID); SerializableMessage message = getMessageFromString(messageString); if (message == null) { @@ -274,6 +274,7 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { if (affected == null) { return; } + //TODO handle embeds/ect... event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); ModlogEvent modlogEvent; @@ -297,6 +298,9 @@ public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); Message message = event.getMessage(); String messageString = CascadeBot.INS.getRedisClient().get("message:" + message.getId()); + if (messageString == null) { + return; + } CascadeBot.INS.getRedisClient().del("message:" + message.getId()); SerializableMessage oldMessage = getMessageFromString(messageString); if (oldMessage == null) { @@ -308,6 +312,7 @@ public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { oldEmbedField.addValueObjects(oldMessage.getContent()); LanguageEmbedField newEmbedField = new LanguageEmbedField(false, "modlog.message.new_message", "modlog.general.variable"); newEmbedField.addValueObjects(message.getContentRaw()); + // TODO handle embeds/ect... embedFieldList.add(newEmbedField); ModlogEvent modlogEvent = ModlogEvent.GUILD_MESSAGE_UPDATED; ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, null, affected, embedFieldList); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 6ae4034eb..bafd4820c 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -33,6 +33,8 @@ class GuildSettingsModeration { var guildId: Long = 0 + var modlogChannelNum: Int = 1; + constructor(guildId: Long) { this.guildId = guildId; } @@ -97,6 +99,7 @@ class GuildSettingsModeration { private fun createModlogEventsInfo(channel: TextChannel, consumer: Consumer) { val eventsInfo = ChannelModlogEventsInfo() + eventsInfo.id = modlogChannelNum++ modlogEvents.put(channel.idLong, eventsInfo) channel.createWebhook("Cascade-modlog").setAvatar(Icon.from(URL(CascadeBot.INS.client.selfUser.avatarUrl).openStream())).queue { webhook -> eventsInfo.webhookId = webhook.idLong @@ -110,15 +113,20 @@ class GuildSettingsModeration { private val events: MutableSet = LinkedHashSet() internal var webhookId: Long = 0 internal var webhookToken: String = "" + internal var id: Int @Transient @kotlin.jvm.Transient private var webhookClient: WebhookClient? = null - internal constructor() {} - constructor(webhookId: Long, webhookToken: String) { + internal constructor() { + id = 0 + } + + constructor(webhookId: Long, webhookToken: String, id: Int) { this.webhookId = webhookId this.webhookToken = webhookToken + this.id = id buildWebhookClient() } @@ -126,6 +134,10 @@ class GuildSettingsModeration { webhookClient = WebhookClientBuilder(webhookId, webhookToken).build() } + fun getId(): Int { + return id + } + fun getEvents(): List { return ArrayList(events) } @@ -142,6 +154,12 @@ class GuildSettingsModeration { return webhookId } + fun setNewWebhook(webhookId: Long, webhookToken: String) { + this.webhookId = webhookId + this.webhookToken = webhookToken + buildWebhookClient() + } + fun sendEvent(guildData: GuildData, modlogEventStore: ModlogEventStore) { val webhookEmbedBuilder = WebhookEmbedBuilder() webhookEmbedBuilder.setTitle(EmbedTitle(modlogEventStore.trigger.name, null)) From cb536df45c69c9107afc08b8164783a783b0ff91 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 4 Jun 2020 13:10:14 -0500 Subject: [PATCH 024/206] Events language --- .../moderation/ModlogChannelSubCommand.java | 5 +- .../moderation/ModlogDisableSubCommand.java | 5 +- .../moderation/ModlogEnableSubCommand.java | 5 +- .../moderation/ModlogEventsSubCommand.java | 4 +- .../data/objects/GuildSettingsModeration.kt | 6 +- src/main/resources/lang/en-GB.json | 362 ++++++++++++++++++ 6 files changed, 377 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java index e8a9c8e3d..12a8f7caa 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java @@ -7,6 +7,7 @@ import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.language.Language; import org.cascadebot.cascadebot.data.objects.GuildSettingsModeration; import org.cascadebot.cascadebot.messaging.MessagingObjects; import org.cascadebot.cascadebot.moderation.ModlogEvent; @@ -59,7 +60,7 @@ public void onCommand(Member sender, CommandContext context) { } } } - String eventsListString = channelModlogEventsInfo.getValue().getEvents().stream().limit(numEvents).map(Enum::name).collect(Collectors.joining(", ")); + String eventsListString = channelModlogEventsInfo.getValue().getEvents().stream().limit(numEvents).map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining(", ")); if (someEvents) { eventsListString += ", and " + (channelModlogEventsInfo.getValue().getEvents().size() - 3) + " more"; } @@ -162,7 +163,7 @@ public void onCommand(Member sender, CommandContext context) { context.getTypedMessaging().replySuccess("Successfully deleted channel!"); } else if (context.getArg(0).equalsIgnoreCase("info")) { GuildSettingsModeration.ChannelModlogEventsInfo channelModlogEventsInfo = context.getData().getModeration().getModlogEvents().get(channel.getIdLong()); - String events = channelModlogEventsInfo.getEvents().stream().map(ModlogEvent::name).collect(Collectors.joining("\n")); + String events = channelModlogEventsInfo.getEvents().stream().map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")); context.getUiMessaging().sendPagedMessage(PageUtils.splitStringToEmbedPages(events, "Events for channel " + channel.getName(), 1000, '\n')); } else { context.getUiMessaging().replyUsage(); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java index 367871516..53c1e654d 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java @@ -7,6 +7,7 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.language.Language; import org.cascadebot.cascadebot.messaging.MessageType; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; @@ -77,7 +78,7 @@ public void onCommand(Member sender, CommandContext context) { pageList.add(new PageObjects.EmbedPage(embedBuilder)); } if (succeed.size() > 0) { - List pageValues = PageUtils.splitString(succeed.stream().map(event -> event.name().toLowerCase()).collect(Collectors.joining("\n")), 1000, '\n'); + List pageValues = PageUtils.splitString(succeed.stream().map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; for (String pageValue: pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); @@ -93,7 +94,7 @@ public void onCommand(Member sender, CommandContext context) { } } if (failedEvents.size() > 0) { - List pageValues = PageUtils.splitString(failedEvents.stream().map(event -> event.name().toLowerCase()).collect(Collectors.joining("\n")), 1000, '\n'); + List pageValues = PageUtils.splitString(failedEvents.stream().map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; for (String pageValue: pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java index 21816da9d..d464ceec4 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java @@ -7,6 +7,7 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.language.Language; import org.cascadebot.cascadebot.data.objects.LoopMode; import org.cascadebot.cascadebot.messaging.MessageType; import org.cascadebot.cascadebot.moderation.ModlogEvent; @@ -78,7 +79,7 @@ public void onCommand(Member sender, CommandContext context) { pageList.add(new PageObjects.EmbedPage(embedBuilder)); } if (succeed.size() > 0) { - List pageValues = PageUtils.splitString(succeed.stream().map(event -> event.name().toLowerCase()).collect(Collectors.joining("\n")), 1000, '\n'); + List pageValues = PageUtils.splitString(succeed.stream().map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; for (String pageValue: pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); @@ -94,7 +95,7 @@ public void onCommand(Member sender, CommandContext context) { } } if (failedEvents.size() > 0) { - List pageValues = PageUtils.splitString(failedEvents.stream().map(event -> event.name().toLowerCase()).collect(Collectors.joining("\n")), 1000, '\n'); + List pageValues = PageUtils.splitString(failedEvents.stream().map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; for (String pageValue: pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java index b1ecae3a1..f7e6bd427 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java @@ -5,9 +5,11 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.language.Language; import org.cascadebot.cascadebot.messaging.MessageType; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.FormatUtils; import org.cascadebot.cascadebot.utils.pagination.Page; import org.cascadebot.cascadebot.utils.pagination.PageObjects; import org.cascadebot.cascadebot.utils.pagination.PageUtils; @@ -30,7 +32,7 @@ public void onCommand(Member sender, CommandContext context) { if (category.equals(ModlogEvent.Category.ALL)) { continue; } - List pageValues = PageUtils.splitString(categoryListEntry.getValue().stream().map(event -> event.name().toLowerCase()).collect(Collectors.joining("\n")), 1000, '\n'); + List pageValues = PageUtils.splitString(categoryListEntry.getValue().stream().map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".select")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; for (String pageValue: pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder() diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index bafd4820c..0e8d874d8 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -19,12 +19,12 @@ import net.dv8tion.jda.api.entities.User import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.database.DebugLogCallback -import org.cascadebot.cascadebot.data.database.IAsyncMongoTask +import org.cascadebot.cascadebot.data.language.Language +import org.cascadebot.cascadebot.data.language.Language.i18n import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.moderation.ModlogEvent import java.net.URL import java.util.ArrayList -import java.util.Collections import java.util.Date import java.util.function.Consumer @@ -162,7 +162,7 @@ class GuildSettingsModeration { fun sendEvent(guildData: GuildData, modlogEventStore: ModlogEventStore) { val webhookEmbedBuilder = WebhookEmbedBuilder() - webhookEmbedBuilder.setTitle(EmbedTitle(modlogEventStore.trigger.name, null)) + webhookEmbedBuilder.setTitle(EmbedTitle(i18n(guildData.locale, "enums.moldogevent." + modlogEventStore.trigger.name.toLowerCase() + ".display"), null)) val affected: ISnowflake = modlogEventStore.affected; var affectedType = "" val affectedStr = when (affected) { diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index ce2aa5837..9f93aec8d 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -926,6 +926,368 @@ "permissionmode":{ "most_restrictive": "most restrictive", "hierarchical": "hierarchical" + }, + "moldogevent": { + "emote_created": { + "select": "emote_created", + "display": "Emote created" + }, + "emote_deleted": { + "select": "emote_deleted", + "display": "Emote deleted" + }, + "emote_updated_name": { + "select": "emote_updated_name", + "display": "Emote updated name" + }, + "emote_updated_roles": { + "select": "emote_updated_roles", + "display": "Emote updated roles" + }, + "guild_member_joined": { + "select": "guild_member_joined", + "display": "Guild member joined" + }, + "guild_member_left": { + "select": "guild_member_left", + "display": "Guild member left" + }, + "guild_member_kicked": { + "select": "guild_member_kicked", + "display": "Guild member kicked" + }, + "guild_member_role_added": { + "select": "guild_member_role_added", + "display": "Guild member role added" + }, + "guild_member_role_removed": { + "select": "guild_member_role_removed", + "display": "Guild member role removed" + }, + "guild_member_nickname_updated": { + "select": "guild_member_nickname_updated", + "display": "Guild member nickname updated" + }, + "guild_user_banned": { + "select": "guild_user_banned", + "display": "Guild user banned" + }, + "guild_user_unbanned": { + "select": "guild_user_unbanned", + "display": "Guild user unbanned" + }, + "guild_message_deleted": { + "select": "guild_message_deleted", + "display": "Guild message deleted" + }, + "guild_message_deleted_self": { + "select": "guild_message_deleted_self", + "display": "Guild message deleted self" + }, + "guild_message_updated": { + "select": "guild_message_updated", + "display": "Guild message updated" + }, + "guild_boost_count_updated": { + "select": "guild_boost_count_updated", + "display": "Guild boost count updated" + }, + "guild_boost_tier_updated": { + "select": "guild_boost_tier_updated", + "display": "Guild boost tier updated" + }, + "guild_update_afk_channel": { + "select": "guild_update_afk_channel", + "display": "Guild update afk channel" + }, + "guild_update_afk_timeout": { + "select": "guild_update_afk_timeout", + "display": "Guild update afk timeout" + }, + "guild_update_banner": { + "select": "guild_update_banner", + "display": "Guild update banner" + }, + "guild_update_description": { + "select": "guild_update_description", + "display": "Guild update description" + }, + "guild_update_explicit_filter": { + "select": "guild_update_explicit_filter", + "display": "Guild update explicit filter" + }, + "guild_update_features": { + "select": "guild_update_features", + "display": "Guild update features" + }, + "guild_update_icon": { + "select": "guild_update_icon", + "display": "Guild update icon" + }, + "guild_update_max_members": { + "select": "guild_update_max_members", + "display": "Guild update max members" + }, + "guild_update_max_presences": { + "select": "guild_update_max_presences", + "display": "Guild update max presences" + }, + "guild_update_mfa_level": { + "select": "guild_update_mfa_level", + "display": "Guild update mfa level" + }, + "guild_update_name": { + "select": "guild_update_name", + "display": "Guild update name" + }, + "guild_update_notification_level": { + "select": "guild_update_notification_level", + "display": "Guild update notification level" + }, + "guild_update_region": { + "select": "guild_update_region", + "display": "Guild update region" + }, + "guild_update_splash": { + "select": "guild_update_splash", + "display": "Guild update splash" + }, + "guild_update_system_channel": { + "select": "guild_update_system_channel", + "display": "Guild update system channel" + }, + "guild_update_vanity_code": { + "select": "guild_update_vanity_code", + "display": "Guild update vanity code" + }, + "guild_update_verification_level": { + "select": "guild_update_verification_level", + "display": "Guild update verification level" + }, + "voice_deafen": { + "select": "voice_deafen", + "display": "Voice deafen" + }, + "voice_mute": { + "select": "voice_mute", + "display": "Voice mute" + }, + "voice_server_deafen": { + "select": "voice_server_deafen", + "display": "Voice server deafen" + }, + "voice_server_mute": { + "select": "voice_server_mute", + "display": "Voice server mute" + }, + "voice_join": { + "select": "voice_join", + "display": "Voice join" + }, + "voice_leave": { + "select": "voice_leave", + "display": "Voice leave" + }, + "voice_move": { + "select": "voice_move", + "display": "Voice move" + }, + "voice_disconnect": { + "select": "voice_disconnect", + "display": "Voice disconnect" + }, + "role_created": { + "select": "role_created", + "display": "Role created" + }, + "role_deleted": { + "select": "role_deleted", + "display": "Role deleted" + }, + "role_color_updated": { + "select": "role_color_updated", + "display": "Role color updated" + }, + "role_hoist_updated": { + "select": "role_hoist_updated", + "display": "Role hoist updated" + }, + "role_mentionable_updated": { + "select": "role_mentionable_updated", + "display": "Role mentionable updated" + }, + "role_name_updated": { + "select": "role_name_updated", + "display": "Role name updated" + }, + "role_permissions_updated": { + "select": "role_permissions_updated", + "display": "Role permissions updated" + }, + "role_position_updated": { + "select": "role_position_updated", + "display": "Role position updated" + }, + "user_discriminator_updated": { + "select": "user_discriminator_updated", + "display": "User discriminator updated" + }, + "user_name_updated": { + "select": "user_name_updated", + "display": "User name updated" + }, + "channel_created": { + "select": "channel_created", + "display": "Channel created" + }, + "channel_deleted": { + "select": "channel_deleted", + "display": "Channel deleted" + }, + "channel_name_updated": { + "select": "channel_name_updated", + "display": "Channel name updated" + }, + "channel_permissions_updated": { + "select": "channel_permissions_updated", + "display": "Channel permissions updated" + }, + "channel_position_updated": { + "select": "channel_position_updated", + "display": "Channel position updated" + }, + "channel_parent_updated": { + "select": "channel_parent_updated", + "display": "Channel parent updated" + }, + "voice_channel_bitrate_updated": { + "select": "voice_channel_bitrate_updated", + "display": "Voice channel bitrate updated" + }, + "voice_channel_user_limit_updated": { + "select": "voice_channel_user_limit_updated", + "display": "Voice channel user limit updated" + }, + "text_channel_nsfw_updated": { + "select": "text_channel_nsfw_updated", + "display": "Text channel nsfw updated" + }, + "text_channel_slowmode_updated": { + "select": "text_channel_slowmode_updated", + "display": "Text channel slowmode updated" + }, + "text_channel_topic_updated": { + "select": "text_channel_topic_updated", + "display": "Text channel topic updated" + }, + "cascade_permissions_group_created": { + "select": "cascade_permissions_group_created", + "display": "Cascade permissions group created" + }, + "cascade_permissions_group_deleted": { + "select": "cascade_permissions_group_deleted", + "display": "Cascade permissions group deleted" + }, + "cascade_permissions_group_permission_add": { + "select": "cascade_permissions_group_permission_add", + "display": "Cascade permissions group permission add" + }, + "cascade_permissions_group_permission_remove": { + "select": "cascade_permissions_group_permission_remove", + "display": "Cascade permissions group permission remove" + }, + "cascade_permissions_group_link": { + "select": "cascade_permissions_group_link", + "display": "Cascade permissions group link" + }, + "cascade_permissions_user_permission_add": { + "select": "cascade_permissions_user_permission_add", + "display": "Cascade permissions user permission add" + }, + "cascade_permissions_user_permission_remove": { + "select": "cascade_permissions_user_permission_remove", + "display": "Cascade permissions user permission remove" + }, + "cascade_permissions_user_group_add": { + "select": "cascade_permissions_user_group_add", + "display": "Cascade permissions user group add" + }, + "cascade_permissions_user_group_remove": { + "select": "cascade_permissions_user_group_remove", + "display": "Cascade permissions user group remove" + }, + "cascade_settings_updated": { + "select": "cascade_settings_updated", + "display": "Cascade settings updated" + }, + "cascade_module_updated": { + "select": "cascade_module_updated", + "display": "Cascade module updated" + }, + "cascade_command_run": { + "select": "cascade_command_run", + "display": "Cascade command run" + }, + "cascade_command_run_error": { + "select": "cascade_command_run_error", + "display": "Cascade command run error" + }, + "cascade_playlist_created": { + "select": "cascade_playlist_created", + "display": "Cascade playlist created" + }, + "cascade_playlist_deleted": { + "select": "cascade_playlist_deleted", + "display": "Cascade playlist deleted" + }, + "cascade_temp_mute": { + "select": "cascade_temp_mute", + "display": "Cascade temp mute" + }, + "cascade_temp_ban": { + "select": "cascade_temp_ban", + "display": "Cascade temp ban" + }, + "cascade_soft_ban": { + "select": "cascade_soft_ban", + "display": "Cascade soft ban" + }, + "cascade_purge": { + "select": "cascade_purge", + "display": "Cascade purge" + }, + "cascade_whitelist": { + "select": "cascade_whitelist", + "display": "Cascade whitelist" + }, + "cascade_blacklist": { + "select": "cascade_blacklist", + "display": "Cascade blacklist" + }, + "cascade_script_created": { + "select": "cascade_script_created", + "display": "Cascade script created" + }, + "cascade_script_deleted": { + "select": "cascade_script_deleted", + "display": "Cascade script deleted" + }, + "cascade_script_updated": { + "select": "cascade_script_updated", + "display": "Cascade script updated" + }, + "cascade_tag_created": { + "select": "cascade_tag_created", + "display": "Cascade tag created" + }, + "cascade_tag_deleted": { + "select": "cascade_tag_deleted", + "display": "Cascade tag deleted" + }, + "cascade_tag_updated": { + "select": "cascade_tag_updated", + "display": "Cascade tag updated" + } } }, "game_types": { From 3d847172c7f0238b1424a4b93c4781445e78cee6 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 4 Jun 2020 13:15:04 -0500 Subject: [PATCH 025/206] Fix some small issues --- .../moderation/ModlogDisableSubCommand.java | 2 +- .../moderation/ModlogEnableSubCommand.java | 2 +- .../cascadebot/cascadebot/data/Config.java | 36 +++++++++++-------- .../events/ModlogEventListener.java | 6 ++++ .../runnables/MessageReceivedRunnable.java | 3 ++ 5 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java index 53c1e654d..1dad3cb0b 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java @@ -41,7 +41,7 @@ public void onCommand(Member sender, CommandContext context) { List failed = new ArrayList<>(); for (String event : events) { if (EnumUtils.isValidEnum(ModlogEvent.class, event.toUpperCase())) { - modlogEvents.add(ModlogEvent.valueOf(event.toUpperCase())); + modlogEvents.add(ModlogEvent.valueOf(event.toUpperCase())); // TODO reverse language to get event } else if (EnumUtils.isValidEnum(ModlogEvent.Category.class, event.toUpperCase())){ ModlogEvent.Category category = ModlogEvent.Category.valueOf(event.toUpperCase()); List additionalEvents = ModlogEvent.getEventsFromCategory(category); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java index d464ceec4..e01314d01 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java @@ -42,7 +42,7 @@ public void onCommand(Member sender, CommandContext context) { List failed = new ArrayList<>(); for (String event : events) { if (EnumUtils.isValidEnum(ModlogEvent.class, event.toUpperCase())) { - modlogEvents.add(ModlogEvent.valueOf(event.toUpperCase())); + modlogEvents.add(ModlogEvent.valueOf(event.toUpperCase())); // TODO reverse language to get event } else if (EnumUtils.isValidEnum(ModlogEvent.Category.class, event.toUpperCase())){ ModlogEvent.Category category = ModlogEvent.Category.valueOf(event.toUpperCase()); List additionalEvents = ModlogEvent.getEventsFromCategory(category); diff --git a/src/main/java/org/cascadebot/cascadebot/data/Config.java b/src/main/java/org/cascadebot/cascadebot/data/Config.java index 3b5816e4e..a9cac396f 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/Config.java +++ b/src/main/java/org/cascadebot/cascadebot/data/Config.java @@ -254,27 +254,33 @@ private void initConfig() throws IOException { redisPassword = config.getString("redis.password"); String stringKey = config.getString("encryption_key.key"); - byte[] keyBytes = stringKey.getBytes(); - if (keyBytes.length != 16 && keyBytes.length != 24 && keyBytes.length != 32) { - CascadeBot.LOGGER.warn("Encryption key invalid size! must be 128, 192, or 265 bits!"); - } else { - this.encryptKey = keyBytes; + if (stringKey != null) { + byte[] keyBytes = stringKey.getBytes(); + if (keyBytes.length != 16 && keyBytes.length != 24 && keyBytes.length != 32) { + CascadeBot.LOGGER.warn("Encryption key invalid size! must be 128, 192, or 265 bits!"); + } else { + this.encryptKey = keyBytes; + } } String stringIv = config.getString("encryption_key.iv"); - byte[] ivBytes = stringIv.getBytes(); - if (ivBytes.length != 16) { - CascadeBot.LOGGER.warn("Encryption iv invalid size! must be 128 bits!"); - } else { - this.ivSpec = ivBytes; + if (stringIv != null) { + byte[] ivBytes = stringIv.getBytes(); + if (ivBytes.length != 16) { + CascadeBot.LOGGER.warn("Encryption iv invalid size! must be 128 bits!"); + } else { + this.ivSpec = ivBytes; + } } String stringMac = config.getString("encryption_key.mac"); - byte[] macBytes = stringMac.getBytes(); - if (macBytes.length != 16) { - CascadeBot.LOGGER.warn("Encryption mac invalid size! must be 128, 192, or 265 bits!"); - } else { - this.mac = macBytes; + if (stringMac != null) { + byte[] macBytes = stringMac.getBytes(); + if (macBytes.length != 16) { + CascadeBot.LOGGER.warn("Encryption mac invalid size! must be 128, 192, or 265 bits!"); + } else { + this.mac = macBytes; + } } if (encryptKey == null || ivSpec == null || mac == null) { diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 806656edf..3bcb1e1a1 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -255,6 +255,9 @@ public void onGuildUnban(GuildUnbanEvent event) { //region Message public void onGuildMessageDelete(GuildMessageDeleteEvent event) { + if (CascadeBot.INS.getRedisClient() == null) { + return; + } GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); String messageID = event.getMessageId(); String messageString = CascadeBot.INS.getRedisClient().get("message:" + messageID); @@ -292,6 +295,9 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { } public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { + if (CascadeBot.INS.getRedisClient() == null) { + return; + } if (event.getAuthor().isBot()) { return; } diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java index 2ef00c3db..2a4f924a5 100644 --- a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java +++ b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java @@ -40,6 +40,9 @@ public void run() { if (event.getMember() == null) { return; } + if (CascadeBot.INS.getRedisClient() == null) { + return; + } SerializableMessage serializableMessage = SerializableMessage.createSerializeMessageFromJda(event.getMessage()); String messageJson = CascadeBot.getGSON().toJson(serializableMessage); String message = ""; From 2dc98afae111a3dd59af2717b5cbc8ffa959fd04 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 6 Jun 2020 17:42:13 -0500 Subject: [PATCH 026/206] Clear and prune commands as well as fixes Fixes: - Made encryption not require mac - Removed unneeded class --- .../moderation/ModlogClearSubCommand.java | 88 +++++++++++++++++++ .../commands/moderation/ModlogCommand.java | 3 +- .../moderation/ModlogPruneSubCommand.java | 35 ++++++++ .../cascadebot/cascadebot/data/Config.java | 2 +- .../data/objects/GuildModeration.java | 11 --- 5 files changed, 126 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java create mode 100644 src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java delete mode 100644 src/main/java/org/cascadebot/cascadebot/data/objects/GuildModeration.java diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java new file mode 100644 index 000000000..06550d2fd --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java @@ -0,0 +1,88 @@ +package org.cascadebot.cascadebot.commands.moderation; + +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.TextChannel; +import net.dv8tion.jda.api.entities.Webhook; +import org.cascadebot.cascadebot.CascadeBot; +import org.cascadebot.cascadebot.commandmeta.CommandContext; +import org.cascadebot.cascadebot.commandmeta.Module; +import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.GuildSettingsModeration; +import org.cascadebot.cascadebot.messaging.MessageType; +import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.ConfirmUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +public class ModlogClearSubCommand extends SubCommand { + + String clearAction = "modlog_clear"; + String clearDisabledAction = "modlog_disabled"; + + public void onCommand(Member sender, CommandContext context) { + if (context.getArgs().length == 0) { + if (ConfirmUtils.hasConfirmedAction(clearAction, sender.getIdLong())) { + ConfirmUtils.completeAction(clearAction, sender.getIdLong()); + } else { + ConfirmUtils.confirmAction(sender.getIdLong(), clearAction, context.getChannel(), MessageType.WARNING, + "Confirm that you want to remove ALL events", 0, TimeUnit.SECONDS.toMillis(5), + true, new ConfirmUtils.ConfirmRunnable() { + @Override + public void execute() { + context.getData().getModeration().getModlogEvents().clear(); + context.getTypedMessaging().replySuccess("Removed all modlog events!"); + } + }); + } + return; + } + if (context.getArg(0).equalsIgnoreCase("disabled")) { + if (ConfirmUtils.hasConfirmedAction(clearDisabledAction, sender.getIdLong())) { + ConfirmUtils.completeAction(clearDisabledAction, sender.getIdLong()); + } else { + ConfirmUtils.confirmAction(sender.getIdLong(), clearDisabledAction, context.getChannel(), MessageType.WARNING, + "Confirm that you want to remove all events in disabled channels", 0, TimeUnit.SECONDS.toMillis(5), + true, new ConfirmUtils.ConfirmRunnable() { + @Override + public void execute() { + List delete = new ArrayList<>(); + for (Map.Entry entry : context.getData().getModeration().getModlogEvents().entrySet()) { + TextChannel textChannel = CascadeBot.INS.getClient().getTextChannelById(entry.getKey()); + if (textChannel == null) { + continue; + } + List webhooks = textChannel.retrieveWebhooks().complete(); + for (Webhook webhook : webhooks) { + if (webhook.getIdLong() == entry.getValue().getWebhookId()) { + delete.add(entry.getKey()); + } + } + } + for (Long id : delete) { + context.getData().getModeration().getModlogEvents().remove(id); + } + context.getTypedMessaging().replySuccess("Deleted events from " + delete.size() + " disabled channel"); + } + }); + } + return; + } + context.getUiMessaging().replyUsage(); + } + + public String command() { + return "clear"; + } + + public CascadePermission permission() { + return CascadePermission.of("modlog.clear", false, Module.MODERATION); + } + + public String parent() { + return "modlog"; + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java index 1e0a1cd7a..479c7bbc0 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java @@ -29,6 +29,7 @@ public Module module() { } public Set subCommands() { - return Set.of(new ModlogEnableSubCommand(), new ModlogDisableSubCommand(), new ModlogEventsSubCommand(), new ModlogChannelSubCommand()); + return Set.of(new ModlogEnableSubCommand(), new ModlogDisableSubCommand(), new ModlogEventsSubCommand(), + new ModlogChannelSubCommand(), new ModlogPruneSubCommand(), new ModlogClearSubCommand()); } } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java new file mode 100644 index 000000000..a235b8ac8 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java @@ -0,0 +1,35 @@ +package org.cascadebot.cascadebot.commands.moderation; + +import net.dv8tion.jda.api.entities.Member; +import org.cascadebot.cascadebot.CascadeBot; +import org.cascadebot.cascadebot.commandmeta.CommandContext; +import org.cascadebot.cascadebot.commandmeta.Module; +import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.permissions.CascadePermission; + +public class ModlogPruneSubCommand extends SubCommand { + + public void onCommand(Member sender, CommandContext context) { + int amount = 0; + for (Long id : context.getData().getModeration().getModlogEvents().keySet()) { + if (CascadeBot.INS.getShardManager().getTextChannelById(id) == null) { + context.getData().getModeration().getModlogEvents().remove(id); + amount++; + } + } + context.getTypedMessaging().replySuccess("Removed all events from " + amount + " deleted channels"); + } + + public String command() { + return "prune"; + } + + public CascadePermission permission() { + return CascadePermission.of("modlog.prune", false, Module.MODERATION); + } + + public String parent() { + return "modlog"; + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/data/Config.java b/src/main/java/org/cascadebot/cascadebot/data/Config.java index a9cac396f..ec76704c2 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/Config.java +++ b/src/main/java/org/cascadebot/cascadebot/data/Config.java @@ -283,7 +283,7 @@ private void initConfig() throws IOException { } } - if (encryptKey == null || ivSpec == null || mac == null) { + if (encryptKey == null || ivSpec == null) { CascadeBot.LOGGER.warn("One of the required encryption values are null, or wrong size. Encryption will not work!"); encryptKey = null; ivSpec = null; diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildModeration.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildModeration.java deleted file mode 100644 index 84cedc1fe..000000000 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildModeration.java +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2019 CascadeBot. All rights reserved. - * Licensed under the MIT license. - */ - -package org.cascadebot.cascadebot.data.objects; - -public class GuildModeration { - - -} From 701b27dfddfa4426676bdd474b0f890326549b5c Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 6 Jun 2020 18:31:09 -0500 Subject: [PATCH 027/206] Remove iv from config Generally the iv should eater be random, or based of the data. In this case it uses the user id twice. --- .../commands/moderation/ModlogCommand.java | 1 - .../org/cascadebot/cascadebot/data/Config.java | 16 ++-------------- .../cascadebot/events/ModlogEventListener.java | 18 +++++++++++++++--- .../runnables/MessageReceivedRunnable.java | 14 +++++++++++--- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java index 479c7bbc0..213b73d1d 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogCommand.java @@ -13,7 +13,6 @@ public class ModlogCommand extends MainCommand { public void onCommand(Member sender, CommandContext context) { context.getUiMessaging().replyUsage(); - } public String command() { diff --git a/src/main/java/org/cascadebot/cascadebot/data/Config.java b/src/main/java/org/cascadebot/cascadebot/data/Config.java index ec76704c2..1f6a84ffd 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/Config.java +++ b/src/main/java/org/cascadebot/cascadebot/data/Config.java @@ -88,7 +88,6 @@ public class Config { private String redisPassword; private byte[] encryptKey; - private byte[] ivSpec; private byte[] mac; private Config(String file) throws IOException { @@ -263,16 +262,6 @@ private void initConfig() throws IOException { } } - String stringIv = config.getString("encryption_key.iv"); - if (stringIv != null) { - byte[] ivBytes = stringIv.getBytes(); - if (ivBytes.length != 16) { - CascadeBot.LOGGER.warn("Encryption iv invalid size! must be 128 bits!"); - } else { - this.ivSpec = ivBytes; - } - } - String stringMac = config.getString("encryption_key.mac"); if (stringMac != null) { byte[] macBytes = stringMac.getBytes(); @@ -283,10 +272,9 @@ private void initConfig() throws IOException { } } - if (encryptKey == null || ivSpec == null) { - CascadeBot.LOGGER.warn("One of the required encryption values are null, or wrong size. Encryption will not work!"); + if (encryptKey == null) { + CascadeBot.LOGGER.warn("Encryption key is not set. Encryption will not work!"); encryptKey = null; - ivSpec = null; mac = null; } diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 3bcb1e1a1..7afbd36bd 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -1,6 +1,7 @@ package org.cascadebot.cascadebot.events; import com.google.gson.JsonArray; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import net.dv8tion.jda.api.Permission; @@ -326,15 +327,26 @@ public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { } private SerializableMessage getMessageFromString(String messageString) { + JsonObject object = new JsonParser().parse(messageString).getAsJsonObject(); String message; if (Config.INS.getEncryptKey() != null) { - JsonArray bytesJsonArray = new JsonParser().parse(messageString).getAsJsonArray(); + JsonArray messageIdJson = object.getAsJsonArray("id"); + byte[] messageId = new byte[messageIdJson.size()]; + int mi = 0; + for (JsonElement element : messageIdJson) { + messageId[mi] = element.getAsByte(); + mi++; + } + JsonArray bytesJsonArray = object.getAsJsonArray("content"); + byte[] iv = new byte[messageId.length * 2]; + System.arraycopy(messageId, 0, iv, 0, messageId.length); + System.arraycopy(messageId, 0, iv, messageId.length, messageId.length); byte[] messageBytes = new byte[bytesJsonArray.size()]; for (int i = 0; i < bytesJsonArray.size(); i++) { messageBytes[i] = bytesJsonArray.get(i).getAsByte(); } try { - message = CryptUtils.decryptString(Config.INS.getEncryptKey(), Config.INS.getIvSpec(), messageBytes); + message = CryptUtils.decryptString(Config.INS.getEncryptKey(), iv, messageBytes); } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | ShortBufferException e) { e.printStackTrace(); // TODO log these @@ -344,7 +356,7 @@ private SerializableMessage getMessageFromString(String messageString) { return null; } } else { - message = messageString; + message = object.get("content").getAsString(); } return CascadeBot.getGSON().fromJson(message, SerializableMessage.class); } diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java index 2a4f924a5..cccdee56a 100644 --- a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java +++ b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java @@ -19,6 +19,7 @@ import javax.crypto.ShortBufferException; import java.io.IOException; import java.io.StringWriter; +import java.nio.ByteBuffer; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -45,18 +46,25 @@ public void run() { } SerializableMessage serializableMessage = SerializableMessage.createSerializeMessageFromJda(event.getMessage()); String messageJson = CascadeBot.getGSON().toJson(serializableMessage); + byte[] messageId = ByteBuffer.allocate(Long.BYTES).putLong(event.getMessage().getIdLong()).array(); + JsonObject jsonObject = new JsonObject(); + jsonObject.add("id", CascadeBot.getGSON().toJsonTree(messageId)); String message = ""; if (Config.INS.getEncryptKey() != null) { try { - byte[] results = CryptUtils.encryptString(Config.INS.getEncryptKey(), Config.INS.getIvSpec(), messageJson); - message = CascadeBot.getGSON().toJson(CascadeBot.getGSON().toJsonTree(results)); + byte[] iv = new byte[messageId.length * 2]; + System.arraycopy(messageId, 0, iv, 0, messageId.length); + System.arraycopy(messageId, 0, iv, messageId.length, messageId.length); + byte[] results = CryptUtils.encryptString(Config.INS.getEncryptKey(), iv, messageJson); + jsonObject.add("content", CascadeBot.getGSON().toJsonTree(results)); } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | ShortBufferException | BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException exception) { CascadeBot.LOGGER.warn("Failed to encrypt", exception); return; } } else { - message = messageJson; + jsonObject.add("content", new JsonPrimitive(messageJson)); } + message = CascadeBot.getGSON().toJson(jsonObject); CascadeBot.INS.getRedisClient().set("message:" + event.getMessageId(), message); CascadeBot.INS.getRedisClient().expire("message:" + event.getMessageId(), (int) TimeUnit.HOURS.toSeconds(24)); } catch (InterruptedException e) { From 0e71f12b78254f2f3d094a66300dc317e58c6f25 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 6 Jun 2020 19:10:43 -0500 Subject: [PATCH 028/206] Don't store message id Everything that needs the id has access to it alllready --- .../events/ModlogEventListener.java | 21 +++++++------------ .../runnables/MessageReceivedRunnable.java | 9 +++----- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 7afbd36bd..1eee4f96d 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -1,7 +1,6 @@ package org.cascadebot.cascadebot.events; import com.google.gson.JsonArray; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import net.dv8tion.jda.api.Permission; @@ -102,6 +101,7 @@ import javax.crypto.NoSuchPaddingException; import javax.crypto.ShortBufferException; import java.awt.Color; +import java.nio.ByteBuffer; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -266,7 +266,7 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { return; } CascadeBot.INS.getRedisClient().del("message:" + messageID); - SerializableMessage message = getMessageFromString(messageString); + SerializableMessage message = getMessageFromString(event.getMessageIdLong(), messageString); if (message == null) { return; } @@ -309,7 +309,7 @@ public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { return; } CascadeBot.INS.getRedisClient().del("message:" + message.getId()); - SerializableMessage oldMessage = getMessageFromString(messageString); + SerializableMessage oldMessage = getMessageFromString(message.getIdLong(), messageString); if (oldMessage == null) { return; } @@ -326,21 +326,14 @@ public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { guildData.getModeration().sendModlogEvent(eventStore); } - private SerializableMessage getMessageFromString(String messageString) { - JsonObject object = new JsonParser().parse(messageString).getAsJsonObject(); + private SerializableMessage getMessageFromString(long id, String messageString) { String message; if (Config.INS.getEncryptKey() != null) { - JsonArray messageIdJson = object.getAsJsonArray("id"); - byte[] messageId = new byte[messageIdJson.size()]; - int mi = 0; - for (JsonElement element : messageIdJson) { - messageId[mi] = element.getAsByte(); - mi++; - } - JsonArray bytesJsonArray = object.getAsJsonArray("content"); + byte[] messageId = ByteBuffer.allocate(Long.BYTES).putLong(id).array(); byte[] iv = new byte[messageId.length * 2]; System.arraycopy(messageId, 0, iv, 0, messageId.length); System.arraycopy(messageId, 0, iv, messageId.length, messageId.length); + JsonArray bytesJsonArray = new JsonParser().parse(messageString).getAsJsonArray(); byte[] messageBytes = new byte[bytesJsonArray.size()]; for (int i = 0; i < bytesJsonArray.size(); i++) { messageBytes[i] = bytesJsonArray.get(i).getAsByte(); @@ -356,7 +349,7 @@ private SerializableMessage getMessageFromString(String messageString) { return null; } } else { - message = object.get("content").getAsString(); + message = messageString; } return CascadeBot.getGSON().fromJson(message, SerializableMessage.class); } diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java index cccdee56a..3a173d1d8 100644 --- a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java +++ b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java @@ -46,25 +46,22 @@ public void run() { } SerializableMessage serializableMessage = SerializableMessage.createSerializeMessageFromJda(event.getMessage()); String messageJson = CascadeBot.getGSON().toJson(serializableMessage); - byte[] messageId = ByteBuffer.allocate(Long.BYTES).putLong(event.getMessage().getIdLong()).array(); - JsonObject jsonObject = new JsonObject(); - jsonObject.add("id", CascadeBot.getGSON().toJsonTree(messageId)); String message = ""; if (Config.INS.getEncryptKey() != null) { try { + byte[] messageId = ByteBuffer.allocate(Long.BYTES).putLong(event.getMessage().getIdLong()).array(); byte[] iv = new byte[messageId.length * 2]; System.arraycopy(messageId, 0, iv, 0, messageId.length); System.arraycopy(messageId, 0, iv, messageId.length, messageId.length); byte[] results = CryptUtils.encryptString(Config.INS.getEncryptKey(), iv, messageJson); - jsonObject.add("content", CascadeBot.getGSON().toJsonTree(results)); + message = CascadeBot.getGSON().toJson(CascadeBot.getGSON().toJsonTree(results)); } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | ShortBufferException | BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException exception) { CascadeBot.LOGGER.warn("Failed to encrypt", exception); return; } } else { - jsonObject.add("content", new JsonPrimitive(messageJson)); + message = messageJson; } - message = CascadeBot.getGSON().toJson(jsonObject); CascadeBot.INS.getRedisClient().set("message:" + event.getMessageId(), message); CascadeBot.INS.getRedisClient().expire("message:" + event.getMessageId(), (int) TimeUnit.HOURS.toSeconds(24)); } catch (InterruptedException e) { From e60c7c4833b83a6fb00d4bc58f6a49e2f2906132 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 7 Jun 2020 09:31:19 -0500 Subject: [PATCH 029/206] singleton --- .../java/org/cascadebot/cascadebot/CascadeBot.java | 8 +------- .../cascadebot/events/MessageEventListener.java | 3 ++- .../cascadebot/runnables/MessageReceivedRunnable.java | 10 ++++++++++ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 19e8dde57..e4c6d8ee6 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -83,8 +83,6 @@ public class CascadeBot { private EventWaiter eventWaiter; private Jedis redisClient; - private MessageReceivedRunnable messageReceivedRunnable; - public static void main(String[] args) { try (Scanner scanner = new Scanner(CascadeBot.class.getResourceAsStream("/version.txt"))) { version = Version.parseVer(scanner.next()); @@ -182,8 +180,7 @@ private void init() { builder.setPrettyPrinting(); } - messageReceivedRunnable = new MessageReceivedRunnable(); - new Thread(messageReceivedRunnable, "messageHandleThread").start(); + new Thread(MessageReceivedRunnable.getInstance(), "messageHandleThread").start(); if (Config.INS.getConnectionString() != null) { databaseManager = new DatabaseManager(Config.INS.getConnectionString()); @@ -354,7 +351,4 @@ public Jedis getRedisClient() { return redisClient; } - public MessageReceivedRunnable getMessageReceivedRunnable() { - return messageReceivedRunnable; - } } diff --git a/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java index f6b09222e..77b0fa0e0 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/MessageEventListener.java @@ -6,6 +6,7 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.data.Config; +import org.cascadebot.cascadebot.runnables.MessageReceivedRunnable; import org.cascadebot.cascadebot.utils.CryptUtils; import javax.crypto.BadPaddingException; @@ -20,7 +21,7 @@ public class MessageEventListener extends ListenerAdapter { @Override public void onGuildMessageReceived(GuildMessageReceivedEvent event) { - CascadeBot.INS.getMessageReceivedRunnable().getQueue().add(event); + MessageReceivedRunnable.getInstance().getQueue().add(event); } } diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java index 3a173d1d8..86eb5024b 100644 --- a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java +++ b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java @@ -33,6 +33,12 @@ public class MessageReceivedRunnable implements Runnable { private BlockingQueue queue = new LinkedBlockingQueue<>(); + private static MessageReceivedRunnable instance; + + static { + instance = new MessageReceivedRunnable(); + } + @Override public void run() { while (!ShutdownHandler.SHUTDOWN_LOCK.get()) { @@ -74,4 +80,8 @@ public BlockingQueue getQueue() { return queue; } + public static MessageReceivedRunnable getInstance() { + return instance; + } + } From 6ece5570f8065385eb2d7adc89f5dc49c9836dbf Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 7 Jun 2020 09:41:32 -0500 Subject: [PATCH 030/206] Misc fixes Mostly from pr review --- config.example.yml | 4 ++-- .../moderation/ModlogChannelSubCommand.java | 21 ++++++------------- .../moderation/ModlogDisableSubCommand.java | 7 +++---- .../moderation/ModlogEnableSubCommand.java | 7 +++---- .../moderation/ModlogEventsSubCommand.java | 4 ++-- .../moderation/ModlogPruneSubCommand.java | 2 +- .../runnables/MessageReceivedRunnable.java | 3 +-- .../data/objects/ModlogEventStore.kt | 1 + .../cascadebot/utils/SerializableMessage.kt | 2 +- 9 files changed, 20 insertions(+), 31 deletions(-) diff --git a/config.example.yml b/config.example.yml index 8ba594748..5d26bfd29 100644 --- a/config.example.yml +++ b/config.example.yml @@ -119,8 +119,8 @@ redis: port: 6379 password: '' -# If this is specified all sub fields are required to have encryption +# If this is specified the key is required for encryption. encryption_key: key: 'AES key, 256 bit recommended' - iv: '64 bit iv key' + # This isn't required, but might be used in the future for some encryption mac: '128 bit mac key' \ No newline at end of file diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java index 12a8f7caa..cb71de222 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java @@ -36,12 +36,12 @@ public void onCommand(Member sender, CommandContext context) { StringBuilder enabled = new StringBuilder(); StringBuilder disabled = new StringBuilder(); StringBuilder deleted = new StringBuilder(); - Set> channelModlogEventsSet = context.getData().getModeration().getModlogEvents().entrySet(); + var channelModlogEventsSet = context.getData().getModeration().getModlogEvents().entrySet(); if (channelModlogEventsSet.size() == 0) { - context.reply("No channels have been set up with modlog events!"); + context.getTypedMessaging().replyDanger("No channels have been set up with modlog events!"); return; } - for (Map.Entry channelModlogEventsInfo : channelModlogEventsSet) { + for (var channelModlogEventsInfo : channelModlogEventsSet) { TextChannel modlogChannel = CascadeBot.INS.getShardManager().getTextChannelById(channelModlogEventsInfo.getKey()); boolean channelExists = modlogChannel != null; boolean someEvents = false; @@ -50,16 +50,7 @@ public void onCommand(Member sender, CommandContext context) { numEvents = 3; someEvents = true; } - boolean webhookExists = false; - if (modlogChannel != null) { - List webhooks = modlogChannel.retrieveWebhooks().complete(); - for (Webhook webhook : webhooks) { - if (webhook.getIdLong() == channelModlogEventsInfo.getValue().getWebhookId()) { - webhookExists = true; - break; - } - } - } + boolean webhookExists = isEnabled(modlogChannel, context); String eventsListString = channelModlogEventsInfo.getValue().getEvents().stream().limit(numEvents).map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining(", ")); if (someEvents) { eventsListString += ", and " + (channelModlogEventsInfo.getValue().getEvents().size() - 3) + " more"; @@ -69,7 +60,7 @@ public void onCommand(Member sender, CommandContext context) { } else if (channelExists) { // Channel exists, but is disabled disabled.append(modlogChannel.getAsMention()).append(" - ").append(eventsListString).append('\n'); } else { // Channel doesn't exist - deleted.append("#deleted-channel (" + channelModlogEventsInfo.getValue().getId() + ") - ").append(eventsListString).append('\n'); + deleted.append("#deleted-channel (").append(channelModlogEventsInfo.getValue().getId()).append(") - ").append(eventsListString).append('\n'); } } List pages = new ArrayList<>(); @@ -103,7 +94,7 @@ public void onCommand(Member sender, CommandContext context) { GuildSettingsModeration.ChannelModlogEventsInfo channelModlogEventsInfo = null; if (context.isArgInteger(1)) { int id = context.getArgAsInteger(1); - for (Map.Entry eventsInfoEntry : context.getData().getModeration().getModlogEvents().entrySet()) { + for (var eventsInfoEntry : context.getData().getModeration().getModlogEvents().entrySet()) { if (eventsInfoEntry.getValue().getId() == id) { channelModlogEventsInfo = eventsInfoEntry.getValue(); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java index 1dad3cb0b..72e04af0b 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java @@ -31,8 +31,7 @@ public void onCommand(Member sender, CommandContext context) { } TextChannel textChannel = DiscordUtils.getTextChannel(context.getGuild(), context.getArg(0)); if (textChannel == null) { - context.reply("Invalid channel"); - // Invalid channel + context.getTypedMessaging().replyDanger("Invalid channel"); return; } List events = new ArrayList<>(Arrays.asList(context.getArgs())); @@ -40,9 +39,9 @@ public void onCommand(Member sender, CommandContext context) { List modlogEvents = new ArrayList<>(); List failed = new ArrayList<>(); for (String event : events) { - if (EnumUtils.isValidEnum(ModlogEvent.class, event.toUpperCase())) { + if (EnumUtils.isValidEnumIgnoreCase(ModlogEvent.class, event.toUpperCase())) { modlogEvents.add(ModlogEvent.valueOf(event.toUpperCase())); // TODO reverse language to get event - } else if (EnumUtils.isValidEnum(ModlogEvent.Category.class, event.toUpperCase())){ + } else if (EnumUtils.isValidEnumIgnoreCase(ModlogEvent.Category.class, event.toUpperCase())){ ModlogEvent.Category category = ModlogEvent.Category.valueOf(event.toUpperCase()); List additionalEvents = ModlogEvent.getEventsFromCategory(category); modlogEvents.addAll(additionalEvents); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java index e01314d01..10adfcab6 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java @@ -32,8 +32,7 @@ public void onCommand(Member sender, CommandContext context) { } TextChannel textChannel = DiscordUtils.getTextChannel(context.getGuild(), context.getArg(0)); if (textChannel == null) { - context.reply("Invalid channel"); - // Invalid channel + context.getTypedMessaging().replyDanger("Invalid channel"); return; } List events = new ArrayList<>(Arrays.asList(context.getArgs())); @@ -41,9 +40,9 @@ public void onCommand(Member sender, CommandContext context) { List modlogEvents = new ArrayList<>(); List failed = new ArrayList<>(); for (String event : events) { - if (EnumUtils.isValidEnum(ModlogEvent.class, event.toUpperCase())) { + if (EnumUtils.isValidEnumIgnoreCase(ModlogEvent.class, event.toUpperCase())) { modlogEvents.add(ModlogEvent.valueOf(event.toUpperCase())); // TODO reverse language to get event - } else if (EnumUtils.isValidEnum(ModlogEvent.Category.class, event.toUpperCase())){ + } else if (EnumUtils.isValidEnumIgnoreCase(ModlogEvent.Category.class, event.toUpperCase())){ ModlogEvent.Category category = ModlogEvent.Category.valueOf(event.toUpperCase()); List additionalEvents = ModlogEvent.getEventsFromCategory(category); modlogEvents.addAll(additionalEvents); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java index f7e6bd427..a782b335a 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java @@ -25,9 +25,9 @@ public class ModlogEventsSubCommand extends SubCommand { public void onCommand(Member sender, CommandContext context) { - Map> modlogCategoryMap = ModlogEvent.getModlogCategoryMap(); + var modlogCategoryMap = ModlogEvent.getModlogCategoryMap(); List embedPages = new ArrayList<>(); - for (Map.Entry> categoryListEntry : modlogCategoryMap.entrySet()) { + for (var categoryListEntry : modlogCategoryMap.entrySet()) { ModlogEvent.Category category = categoryListEntry.getKey(); if (category.equals(ModlogEvent.Category.ALL)) { continue; diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java index a235b8ac8..697d24a8c 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java @@ -11,7 +11,7 @@ public class ModlogPruneSubCommand extends SubCommand { public void onCommand(Member sender, CommandContext context) { int amount = 0; - for (Long id : context.getData().getModeration().getModlogEvents().keySet()) { + for (long id : context.getData().getModeration().getModlogEvents().keySet()) { if (CascadeBot.INS.getShardManager().getTextChannelById(id) == null) { context.getData().getModeration().getModlogEvents().remove(id); amount++; diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java index 86eb5024b..62e0e27bb 100644 --- a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java +++ b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java @@ -68,8 +68,7 @@ public void run() { } else { message = messageJson; } - CascadeBot.INS.getRedisClient().set("message:" + event.getMessageId(), message); - CascadeBot.INS.getRedisClient().expire("message:" + event.getMessageId(), (int) TimeUnit.HOURS.toSeconds(24)); + CascadeBot.INS.getRedisClient().setex("message:" + event.getMessageId(), (int) TimeUnit.HOURS.toSeconds(24), message); } catch (InterruptedException e) { CascadeBot.LOGGER.warn("Message thread interrupted: " + PasteUtils.getStackTrace(e)); } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 34d2c99ce..25ab18f02 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -11,6 +11,7 @@ import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.utils.LanguageEmbedField class ModlogEventStore { + var trigger: ModlogEvent = ModlogEvent.CASCADE_BLACKLIST @Transient diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/SerializableMessage.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/SerializableMessage.kt index 343598f6a..2b8536b40 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/SerializableMessage.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/SerializableMessage.kt @@ -31,7 +31,7 @@ class SerializableMessage( ) { companion object { @JvmStatic - fun createSerializeMessageFromJda(message: Message): SerializableMessage? { + fun createSerializeMessageFromJda(message: Message): SerializableMessage { val userMentions: List = message.mentionedUsers.stream().map { it.idLong }.collect(Collectors.toList()) val channelMentions: List = message.mentionedChannels.stream().map { ChannelMention(it.idLong, it.guild.idLong) }.collect(Collectors.toList()) val roleMentions: List = message.mentionedRoles.stream().map { it.idLong }.collect(Collectors.toList()) From f0a1f12dae35237fa86bd8be5bf4c96c443789a5 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 7 Jun 2020 09:42:49 -0500 Subject: [PATCH 031/206] log error if redis doesn't connect --- src/main/java/org/cascadebot/cascadebot/CascadeBot.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index e4c6d8ee6..cab3f86c4 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -159,7 +159,7 @@ private void init() { redisClient.ping("Hello!"); LOGGER.info("Redis connected!"); } catch (JedisConnectionException e) { - LOGGER.warn("Failed to connect to redis", e); + LOGGER.error("Failed to connect to redis", e); redisClient = null; } } From a49d8fce7d69930104fa6dfca3b1ca6ae9178513 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 7 Jun 2020 09:49:55 -0500 Subject: [PATCH 032/206] benchmark in submodule --- CascadeBenchmark/pom.xml | 34 +++++++++++++++++++ .../cascadebot/CascadeBenchmark.java | 0 .../cascadebot/CryptUtilsBenchmark.java | 0 pom.xml | 17 +++------- 4 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 CascadeBenchmark/pom.xml rename {src => CascadeBenchmark/src}/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java (100%) rename {src => CascadeBenchmark/src}/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java (100%) diff --git a/CascadeBenchmark/pom.xml b/CascadeBenchmark/pom.xml new file mode 100644 index 000000000..c2f274b4d --- /dev/null +++ b/CascadeBenchmark/pom.xml @@ -0,0 +1,34 @@ + + + + cascadebot + org.cascadebot + 0.1.8 + + 4.0.0 + + CascadeBenchmark + + + + + org.openjdk.jmh + jmh-core + 1.19 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.19 + + + org.cascadebot + cascadebot + 0.1.8 + + + + + \ No newline at end of file diff --git a/src/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java b/CascadeBenchmark/src/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java similarity index 100% rename from src/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java rename to CascadeBenchmark/src/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java diff --git a/src/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java b/CascadeBenchmark/src/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java similarity index 100% rename from src/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java rename to CascadeBenchmark/src/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java diff --git a/pom.xml b/pom.xml index ab29e6f35..32ec0e540 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,11 @@ org.cascadebot cascadebot + pom 0.1.8 + + CascadeBenchmark + DEV @@ -436,19 +440,6 @@ icu4j 64.2 - - - - org.openjdk.jmh - jmh-core - 1.19 - - - org.openjdk.jmh - jmh-generator-annprocess - 1.19 - - From 19b59837704e486dc811821f587925c9d1cd93d4 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 7 Jun 2020 10:31:52 -0500 Subject: [PATCH 033/206] Convert events to kotlin --- .../cascadebot/moderation/ModlogEvent.kt} | 77 ++++++++----------- 1 file changed, 31 insertions(+), 46 deletions(-) rename src/main/{java/org/cascadebot/cascadebot/moderation/ModlogEvent.java => kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt} (84%) diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt similarity index 84% rename from src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java rename to src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index c6bc3717f..ff1086deb 100644 --- a/src/main/java/org/cascadebot/cascadebot/moderation/ModlogEvent.java +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -1,17 +1,12 @@ -package org.cascadebot.cascadebot.moderation; +package org.cascadebot.cascadebot.moderation -import kotlin.jvm.JvmStatic; -import lombok.Getter; -import org.cascadebot.cascadebot.messaging.MessageType; +import lombok.Getter +import org.cascadebot.cascadebot.messaging.MessageType +import java.util.ArrayList +import java.util.Arrays +import java.util.HashMap -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public enum ModlogEvent { +enum class ModlogEvent(messageType: MessageType, vararg categories: Category) { EMOTE_CREATED(MessageType.INFO, Category.EMOTE), EMOTE_DELETED(MessageType.INFO, Category.EMOTE), @@ -125,50 +120,36 @@ public enum ModlogEvent { CASCADE_TAG_DELETED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), CASCADE_TAG_UPDATED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS); - @Getter - private static Map> modlogCategoryMap = new HashMap<>(); - - static { - modlogCategoryMap.put(Category.ALL, Arrays.asList(ModlogEvent.values())); - for (ModlogEvent event : ModlogEvent.values()) { - for (Category category : event.getCategories()) { - if (modlogCategoryMap.containsKey(category)) { - modlogCategoryMap.get(category).add(event); - } else { - modlogCategoryMap.put(category, new ArrayList<>(Set.of(event))); + companion object { + @Getter + private val modlogCategoryMap: MutableMap> = HashMap() + fun getEventsFromCategory(category: Category): List { + return modlogCategoryMap[category]!! + } + + init { + modlogCategoryMap[Category.ALL] = Arrays.asList(*values()) + for (cat in Category.values()) { + modlogCategoryMap[cat] = ArrayList() + } + for (event in values()) { + for (category in event.categories) { + modlogCategoryMap[category]?.add(event) } } } } - private final List categories; - - private final MessageType messageType; - - ModlogEvent(MessageType messageType, Category... categories) { - this.categories = Arrays.asList(categories); - this.messageType = messageType; - } - - public static List getEventsFromCategory(Category category) { - return modlogCategoryMap.get(category); - } - - public List getCategories() { - return categories; - } + val categories: List + val messageType: MessageType - public MessageType getMessageType() { - return messageType; - } - - public enum Category { + enum class Category { ALL, MODERATION, EMOTE, GUILD, GUILD_MEMBER, - GUILD_MESSAGE, + GUILD_MESSAGE, GUILD_BOOST, GUILD_SETTINGS, VOICE, @@ -181,4 +162,8 @@ public enum Category { CASCADE_CUSTOM_COMMANDS } -} + init { + this.categories = Arrays.asList(*categories) + this.messageType = messageType + } +} \ No newline at end of file From 9e0a35702c9558bedc20252b170154e93c9c3546 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 7 Jun 2020 11:40:31 -0500 Subject: [PATCH 034/206] Rest of discord events --- .../events/ModlogEventListener.java | 160 +++++++++++++++++- src/main/resources/lang/en-GB.json | 34 +++- 2 files changed, 183 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 1eee4f96d..4d0b407bb 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -1,11 +1,11 @@ package org.cascadebot.cascadebot.events; import com.google.gson.JsonArray; -import com.google.gson.JsonObject; import com.google.gson.JsonParser; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.audit.ActionType; import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.Category; import net.dv8tion.jda.api.entities.ChannelType; import net.dv8tion.jda.api.entities.Emote; import net.dv8tion.jda.api.entities.Guild; @@ -28,13 +28,20 @@ import net.dv8tion.jda.api.events.channel.text.GenericTextChannelEvent; import net.dv8tion.jda.api.events.channel.text.TextChannelCreateEvent; import net.dv8tion.jda.api.events.channel.text.TextChannelDeleteEvent; +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateNSFWEvent; import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateNameEvent; +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateParentEvent; import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdatePositionEvent; +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateSlowmodeEvent; +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateTopicEvent; import net.dv8tion.jda.api.events.channel.voice.GenericVoiceChannelEvent; import net.dv8tion.jda.api.events.channel.voice.VoiceChannelCreateEvent; import net.dv8tion.jda.api.events.channel.voice.VoiceChannelDeleteEvent; +import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateBitrateEvent; import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateNameEvent; +import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateParentEvent; import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdatePositionEvent; +import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateUserLimitEvent; import net.dv8tion.jda.api.events.emote.EmoteAddedEvent; import net.dv8tion.jda.api.events.emote.EmoteRemovedEvent; import net.dv8tion.jda.api.events.emote.GenericEmoteEvent; @@ -56,6 +63,8 @@ import net.dv8tion.jda.api.events.guild.update.GuildUpdateAfkChannelEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateAfkTimeoutEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateBannerEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostCountEvent; +import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostTierEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateDescriptionEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateExplicitContentLevelEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateFeaturesEvent; @@ -70,6 +79,14 @@ import net.dv8tion.jda.api.events.guild.update.GuildUpdateSystemChannelEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateVanityCodeEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateVerificationLevelEvent; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceDeafenEvent; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceGuildDeafenEvent; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceGuildMuteEvent; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceMoveEvent; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceMuteEvent; +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent; import net.dv8tion.jda.api.events.role.GenericRoleEvent; @@ -94,7 +111,6 @@ import org.cascadebot.cascadebot.utils.CryptUtils; import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.cascadebot.utils.SerializableMessage; -import org.jetbrains.annotations.NotNull; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; @@ -143,7 +159,7 @@ public void onGenericEmote(GenericEmoteEvent event) { addedRolesEmbed.addValueObjects(roleListChanges.getAdded().stream().map(role -> role.getName() + " (" + role.getId() + ")") .collect(Collectors.joining("\n"))); LanguageEmbedField removedRolesEmbed = new LanguageEmbedField(false, "modlog.general.removed_roles", "modlog.general.variable"); - removedRolesEmbed.addValueObjects( roleListChanges.getRemoved().stream().map(role -> role.getName() + " (" + role.getId() + ")") + removedRolesEmbed.addValueObjects(roleListChanges.getRemoved().stream().map(role -> role.getName() + " (" + role.getId() + ")") .collect(Collectors.joining("\n"))); embedFieldList.add(addedRolesEmbed); embedFieldList.add(removedRolesEmbed); @@ -472,6 +488,14 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getOldVerificationLevel().name().toLowerCase())); embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getNewVerificationLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_VERIFICATION_LEVEL; + } else if (event instanceof GuildUpdateBoostCountEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_boost_count", "modlog.general.variable", String.valueOf(event.getOldValue()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_boost_count", "modlog.general.variable", String.valueOf(event.getNewValue()))); + modlogEvent = ModlogEvent.GUILD_BOOST_COUNT_UPDATED; + } else if (event instanceof GuildUpdateBoostTierEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getOldBoostTier().name().toLowerCase())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getNewBoostTier().name().toLowerCase())); + modlogEvent = ModlogEvent.GUILD_BOOST_TIER_UPDATED; } else { return; } @@ -480,8 +504,50 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { }); } + public void onGuildVoiceUpdate(GuildVoiceUpdateEvent event) { + User affected = event.getEntity().getUser(); + List embedFieldList = new ArrayList<>(); + ModlogEvent action; + Guild guild; + if (event.getChannelLeft() != null) { + guild = event.getChannelLeft().getGuild(); + } else if (event.getChannelJoined() != null) { + guild = event.getChannelJoined().getGuild(); + } else { + return; + } + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + if (event instanceof GuildVoiceDeafenEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceDeafenEvent) event).isDeafened()))); + action = ModlogEvent.VOICE_DEAFEN; + } else if (event instanceof GuildVoiceMuteEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceMuteEvent) event).isMuted()))); + action = ModlogEvent.VOICE_MUTE; + } else if (event instanceof GuildVoiceGuildDeafenEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()))); + action = ModlogEvent.VOICE_SERVER_DEAFEN; + } else if (event instanceof GuildVoiceGuildMuteEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceGuildMuteEvent) event).isGuildMuted()))); + action = ModlogEvent.VOICE_SERVER_MUTE; + } else if (event instanceof GuildVoiceJoinEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.join", "modlog.general.variable", event.getChannelJoined().getName())); + action = ModlogEvent.VOICE_JOIN; + } else if (event instanceof GuildVoiceLeaveEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.left", "modlog.general.variable", event.getChannelLeft().getName())); + action = ModlogEvent.VOICE_LEAVE; + } else if (event instanceof GuildVoiceMoveEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.left", "modlog.general.variable", event.getChannelLeft().getName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.join", "modlog.general.variable", event.getChannelJoined().getName())); + action = ModlogEvent.VOICE_MOVE; + } else { + return; + } + ModlogEventStore eventStore = new ModlogEventStore(action, null, affected, embedFieldList); + guildData.getModeration().sendModlogEvent(eventStore); + } + //region Channels - public void onGenericStoreChannel(@NotNull GenericStoreChannelEvent event) { + public void onGenericStoreChannel(GenericStoreChannelEvent event) { if (event instanceof StoreChannelCreateEvent) { handleChannelCreateEvents(event.getChannel().getGuild(), ChannelType.STORE, event.getChannel()); } else if (event instanceof StoreChannelDeleteEvent) { @@ -493,19 +559,52 @@ public void onGenericStoreChannel(@NotNull GenericStoreChannelEvent event) { } } - public void onGenericTextChannel(@NotNull GenericTextChannelEvent event) { + public void onGenericTextChannel(GenericTextChannelEvent event) { if (event instanceof TextChannelCreateEvent) { handleChannelCreateEvents(event.getGuild(), ChannelType.TEXT, event.getChannel()); + return; } else if (event instanceof TextChannelDeleteEvent) { handleChannelDeleteEvents(event.getGuild(), ChannelType.TEXT, event.getChannel()); + return; } else if (event instanceof TextChannelUpdateNameEvent) { handleChannelUpdateNameEvents(event.getGuild(), ChannelType.TEXT, ((TextChannelUpdateNameEvent) event).getOldName(), event.getChannel()); + return; } else if (event instanceof TextChannelUpdatePositionEvent) { handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.TEXT, ((TextChannelUpdatePositionEvent) event).getOldPosition(), event.getChannel()); + return; + } else if (event instanceof TextChannelUpdateParentEvent) { + handleChannelUpdateParentEvents(event.getGuild(), ChannelType.TEXT, ((TextChannelUpdateParentEvent) event).getOldParent(), ((TextChannelUpdateParentEvent) event).getNewParent(), event.getChannel()); + return; } + GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); + event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { + ModlogEvent trigger; + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + User responsible = null; + if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { + responsible = entry.getUser(); + } + if (event instanceof TextChannelUpdateNSFWEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.nsfw", "modlog.general.variable", String.valueOf(!((TextChannelUpdateNSFWEvent) event).getOldNSFW()))); + trigger = ModlogEvent.TEXT_CHANNEL_NSFW_UPDATED; + } else if (event instanceof TextChannelUpdateSlowmodeEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_slowmode", "modlog.general.variable", String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getOldSlowmode()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.new_slowmode", "modlog.general.variable", String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getNewSlowmode()))); + trigger = ModlogEvent.TEXT_CHANNEL_SLOWMODE_UPDATED; + } else if (event instanceof TextChannelUpdateTopicEvent) { + embedFieldList.add(new LanguageEmbedField(false, "modlog.channel.old_topic", "modlog.general.variable", ((TextChannelUpdateTopicEvent) event).getOldTopic())); + embedFieldList.add(new LanguageEmbedField(false, "modlog.channel.new_topic", "modlog.general.variable", ((TextChannelUpdateTopicEvent) event).getNewTopic())); + trigger = ModlogEvent.TEXT_CHANNEL_TOPIC_UPDATED; + } else { + return; + } + ModlogEventStore eventStore = new ModlogEventStore(trigger, responsible, event.getChannel(), embedFieldList); + guildData.getModeration().sendModlogEvent(eventStore); + }); } - public void onGenericVoiceChannel(@NotNull GenericVoiceChannelEvent event) { + public void onGenericVoiceChannel(GenericVoiceChannelEvent event) { if (event instanceof VoiceChannelCreateEvent) { handleChannelCreateEvents(event.getGuild(), ChannelType.VOICE, event.getChannel()); } else if (event instanceof VoiceChannelDeleteEvent) { @@ -514,10 +613,35 @@ public void onGenericVoiceChannel(@NotNull GenericVoiceChannelEvent event) { handleChannelUpdateNameEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdateNameEvent) event).getOldName(), event.getChannel()); } else if (event instanceof VoiceChannelUpdatePositionEvent) { handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdatePositionEvent) event).getOldPosition(), event.getChannel()); + } else if (event instanceof VoiceChannelUpdateParentEvent) { + handleChannelUpdateParentEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdateParentEvent) event).getOldParent(), ((VoiceChannelUpdateParentEvent) event).getNewParent(), event.getChannel()); } + GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); + event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { + ModlogEvent trigger; + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + User responsible = null; + if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { + responsible = entry.getUser(); + } + if (event instanceof VoiceChannelUpdateBitrateEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getOldBitrate()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.new_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getNewBitrate()))); + trigger = ModlogEvent.VOICE_CHANNEL_BITRATE_UPDATED; + } else if (event instanceof VoiceChannelUpdateUserLimitEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_users", "modlog.channel.user", String.valueOf(((VoiceChannelUpdateUserLimitEvent) event).getOldUserLimit()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.new_users", "modlog.channel.user", String.valueOf(((VoiceChannelUpdateUserLimitEvent) event).getNewUserLimit()))); + trigger = ModlogEvent.VOICE_CHANNEL_USER_LIMIT_UPDATED; + } else { + return; + } + ModlogEventStore eventStore = new ModlogEventStore(trigger, responsible, event.getChannel(), embedFieldList); + guildData.getModeration().sendModlogEvent(eventStore); + }); } - public void onGenericCategory(@NotNull GenericCategoryEvent event) { + public void onGenericCategory(GenericCategoryEvent event) { if (event instanceof CategoryCreateEvent) { handleChannelCreateEvents(event.getGuild(), ChannelType.CATEGORY, event.getCategory()); } else if (event instanceof CategoryDeleteEvent) { @@ -654,8 +778,26 @@ private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, in responsible = entry.getUser(); } embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_pos", "modlog.general.variable", String.valueOf(oldPos))); - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.new_pos", "modlog.general.variable", String.valueOf(channel.getPosition()))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_pos", "modlog.general.variable", String.valueOf(oldPos))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.general.new_pos", "modlog.general.variable", String.valueOf(channel.getPosition()))); + ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + guildData.getModeration().sendModlogEvent(modlogEventStore); + }); + } + + public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Category oldParent, Category newParent, GuildChannel channel) { + ModlogEvent event = ModlogEvent.CHANNEL_PARENT_UPDATED; + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + List embedFieldList = new ArrayList<>(); + User responsible = null; + if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { + responsible = entry.getUser(); + } + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_parent", "modlog.general.variable", oldParent.getName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.new_parent", "modlog.general.variable", newParent.getName())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(modlogEventStore); }); diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 9f93aec8d..24d47ce3b 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1739,7 +1739,18 @@ "new": "New Vanity Url" }, "old_verification": "Old Verification Level", - "new_verification": "New Verification Level" + "new_verification": "New Verification Level", + "old_boost_count": "Old boost count", + "new_boost_count": "New boost count", + "boost_tier": { + "none": "None", + "tier_1": "Level 1", + "tier_2": "Level 2", + "tier_3": "Level 3", + "unknown": "Unknown" + }, + "old_boost_tier": "Old boost tier", + "new_boost_tier": "New boost tier" }, "channel": { "type": { @@ -1761,7 +1772,20 @@ "update_deny": "New Denied permission for {0}", "old_allow": "Old Allowed permission for {0}", "old_deny": "Old Denied permissions for {0}" - } + }, + "old_parent": "Old Parent", + "new_parent": "New Parent", + "nsfw": "NSFW", + "old_slowmode": "Old Slowmode", + "new_slowmode": "New Slowmode", + "old_topic": "Old topic", + "new_topic": "New topic", + "kpbs": "{0}kbps", + "old_bitrate": "Old bitrate", + "new_bitrate": "New bitrate", + "user": "{0} users", + "old_users": "Old user limit", + "new_users": "New user limit" }, "role": { "old_color": "Old Color", @@ -1773,6 +1797,12 @@ }, "user": { "old_discrim": "Old Discriminator" + }, + "voice": { + "deafen": "Deafened", + "mute": "Muted", + "join": "Joined Channel", + "left": "Left Channel" } } } From a49ae7ce29586e2d36dadd59449658dc59e2fa36 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 7 Jun 2020 12:23:23 -0500 Subject: [PATCH 035/206] Start work on cascade events Also make it compile --- .../GroupPermissionAddSubCommand.java | 12 +++++- .../GroupPermissionCreateSubCommand.java | 10 +++++ .../GroupPermissionDeleteSubCommand.java | 7 ++++ .../GroupPermissionLinkRoleSubCommand.java | 11 +++++ .../GroupPermissionRemoveSubCommand.java | 11 +++++ .../moderation/ModlogDisableSubCommand.java | 2 +- .../moderation/ModlogEnableSubCommand.java | 2 +- .../moderation/ModlogEventsSubCommand.java | 2 +- .../cascadebot/permissions/objects/Group.java | 4 +- .../data/objects/GuildSettingsModeration.kt | 4 +- .../data/objects/ModlogEventStore.kt | 42 ++++++++++++++----- .../cascadebot/moderation/ModlogEvent.kt | 8 +++- src/main/resources/lang/en-GB.json | 5 +++ 13 files changed, 101 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java index 8aafe77aa..ce2a78233 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java @@ -9,9 +9,15 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; +import java.util.ArrayList; +import java.util.List; + public class GroupPermissionAddSubCommand extends SubCommand { @Override @@ -20,7 +26,6 @@ public void onCommand(Member sender, CommandContext context) { context.getUiMessaging().replyUsage(); return; } - if (!context.getData().getPermissionsManager().isValidPermission(context.getArg(1))) { context.getTypedMessaging().replyDanger(context.i18n("responses.permission_not_exist", context.getArg(1))); return; @@ -29,6 +34,11 @@ public void onCommand(Member sender, CommandContext context) { PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { if (group.addPermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.add.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_added", "moldog.general.variable", context.getArg(1))); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD; + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); + context.getData().getModeration().sendModlogEvent(eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.add.fail", context.getArg(1), group.getName() + "(" + group.getId() + ")")); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java index 6bd4f7d3f..b47800a80 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java @@ -9,8 +9,14 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.objects.Group; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; + +import java.util.ArrayList; +import java.util.List; public class GroupPermissionCreateSubCommand extends SubCommand { @@ -23,6 +29,10 @@ public void onCommand(Member sender, CommandContext context) { Group group = context.getData().getManagement().getPermissions().createGroup(context.getArg(0)); context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.create.success", context.getArg(0), group.getId())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_CREATED; + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, new ArrayList<>()); + context.getData().getModeration().sendModlogEvent(eventStore); + } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java index 6e28212c9..df6dd6de8 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java @@ -4,9 +4,13 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; +import java.util.ArrayList; + public class GroupPermissionDeleteSubCommand extends SubCommand { @Override @@ -20,6 +24,9 @@ public void onCommand(Member sender, CommandContext context) { if (context.getData().getManagement().getPermissions().deleteGroup(group.getId())) { // If the group existed to delete and has been successfully deleted. context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.delete.success", group.getName(), group.getId())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_DELETED; + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, new ArrayList<>()); + context.getData().getModeration().sendModlogEvent(eventStore); } else { // Throwing an exception here because this *should* never happen throw new IllegalStateException("Couldn't delete group!"); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java index 1560bd105..c34e2854c 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java @@ -10,10 +10,16 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.DiscordUtils; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; +import java.util.ArrayList; +import java.util.List; + public class GroupPermissionLinkRoleSubCommand extends SubCommand { @Override @@ -32,6 +38,11 @@ public void onCommand(Member sender, CommandContext context) { PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { if (group.linkRole(role.getIdLong())) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.link.success", group.getName(), role.getName())); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new LanguageEmbedField(false, "modlog.cascade_permissions.linked_role", "modlog.general.variable", role.getAsMention())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_LINK; + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); + context.getData().getModeration().sendModlogEvent(eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.link.fail", group.getName(), role.getName())); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java index 019243d93..440d9eb27 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java @@ -9,9 +9,15 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; +import java.util.ArrayList; +import java.util.List; + public class GroupPermissionRemoveSubCommand extends SubCommand { @Override @@ -29,6 +35,11 @@ public void onCommand(Member sender, CommandContext context) { PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { if (group.removePermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.remove.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_removed", "moldog.general.variable", context.getArg(1))); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE; + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); + context.getData().getModeration().sendModlogEvent(eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.remove.fail", context.getArg(1), group.getName() + "(" + group.getId() + ")")); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java index 72e04af0b..a9b20d754 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java @@ -43,7 +43,7 @@ public void onCommand(Member sender, CommandContext context) { modlogEvents.add(ModlogEvent.valueOf(event.toUpperCase())); // TODO reverse language to get event } else if (EnumUtils.isValidEnumIgnoreCase(ModlogEvent.Category.class, event.toUpperCase())){ ModlogEvent.Category category = ModlogEvent.Category.valueOf(event.toUpperCase()); - List additionalEvents = ModlogEvent.getEventsFromCategory(category); + List additionalEvents = ModlogEvent.Companion.getEventsFromCategory(category); modlogEvents.addAll(additionalEvents); } else { failed.add(event); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java index 10adfcab6..9ac2bf526 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java @@ -44,7 +44,7 @@ public void onCommand(Member sender, CommandContext context) { modlogEvents.add(ModlogEvent.valueOf(event.toUpperCase())); // TODO reverse language to get event } else if (EnumUtils.isValidEnumIgnoreCase(ModlogEvent.Category.class, event.toUpperCase())){ ModlogEvent.Category category = ModlogEvent.Category.valueOf(event.toUpperCase()); - List additionalEvents = ModlogEvent.getEventsFromCategory(category); + List additionalEvents = ModlogEvent.Companion.getEventsFromCategory(category); modlogEvents.addAll(additionalEvents); } else { failed.add(event); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java index a782b335a..fb0e65be4 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java @@ -25,7 +25,7 @@ public class ModlogEventsSubCommand extends SubCommand { public void onCommand(Member sender, CommandContext context) { - var modlogCategoryMap = ModlogEvent.getModlogCategoryMap(); + var modlogCategoryMap = ModlogEvent.Companion.getModlogCategoryMap(); List embedPages = new ArrayList<>(); for (var categoryListEntry : modlogCategoryMap.entrySet()) { ModlogEvent.Category category = categoryListEntry.getKey(); diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java index 714597c0e..e81435539 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java @@ -23,7 +23,6 @@ public class Group extends PermissionHolder { // Base 55 with 5 chars gives 503284375 combinations, we should be ok for uniqueness // This is normal alphanumeric with similar characters removed for less errors when inputting - @Getter private String id = RandomStringUtils.random(5, "abcdefghijkmnopqrstuvwxyzACDEFHJKLMNPRSTUVWXYZ123467890"); @Getter @@ -53,4 +52,7 @@ HolderType getType() { return HolderType.GROUP; } + public String getId() { + return id; + } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 0e8d874d8..6added10f 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -163,7 +163,7 @@ class GuildSettingsModeration { fun sendEvent(guildData: GuildData, modlogEventStore: ModlogEventStore) { val webhookEmbedBuilder = WebhookEmbedBuilder() webhookEmbedBuilder.setTitle(EmbedTitle(i18n(guildData.locale, "enums.moldogevent." + modlogEventStore.trigger.name.toLowerCase() + ".display"), null)) - val affected: ISnowflake = modlogEventStore.affected; + val affected: Any = modlogEventStore.affected; var affectedType = "" val affectedStr = when (affected) { @@ -186,7 +186,7 @@ class GuildSettingsModeration { is GuildChannel -> { affectedType = "Channel" affected.name - } + } // TODO rest of events else -> null } if (affectedStr != null) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 25ab18f02..8f1bdda1b 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -8,6 +8,7 @@ import net.dv8tion.jda.api.entities.Role import net.dv8tion.jda.api.entities.User import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.moderation.ModlogEvent +import org.cascadebot.cascadebot.permissions.objects.Group import org.cascadebot.cascadebot.utils.LanguageEmbedField class ModlogEventStore { @@ -18,29 +19,50 @@ class ModlogEventStore { var responsible: User? = null @Transient - var affected: ISnowflake = CascadeBot.INS.selfUser + var affected: Any = CascadeBot.INS.selfUser var extraInfo: List = ArrayList() - var affectedId: Long = 0 + var affectedId: String = "" var affectedType: String = "" var responsibleId: Long = 0; - constructor(trigger: ModlogEvent, responsible: User?, affected: ISnowflake, extraInfo: List) { + constructor(trigger: ModlogEvent, responsible: User?, affected: Any, extraInfo: List) { this.trigger = trigger this.responsible = responsible this.affected = affected this.extraInfo = extraInfo - affectedId = affected.idLong affectedType = when (affected) { - is User -> "User" - is Role -> "Role" - is Emote -> "Emote" - is Guild -> "Guild" - is GuildChannel -> "Channel" - else -> "unknown" + is User -> { + affectedId = affected.id + "User" + } + is Role -> { + affectedId = affected.id + "Role" + } + is Emote -> { + affectedId = affected.id + "Emote" + } + is Guild -> { + affectedId = affected.id + "Guild" + } + is GuildChannel -> { + affectedId = affected.id + "Channel" + } + is Group -> { + affectedId = affected.id + "Group" + } + else -> { + affectedId = "unknown" + "unknown" + } } if (responsible != null) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index ff1086deb..a5bfe5715 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -121,8 +121,12 @@ enum class ModlogEvent(messageType: MessageType, vararg categories: Category) { CASCADE_TAG_UPDATED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS); companion object { - @Getter private val modlogCategoryMap: MutableMap> = HashMap() + + fun getModlogCategoryMap(): Map> { + return modlogCategoryMap + } + fun getEventsFromCategory(category: Category): List { return modlogCategoryMap[category]!! } @@ -149,7 +153,7 @@ enum class ModlogEvent(messageType: MessageType, vararg categories: Category) { EMOTE, GUILD, GUILD_MEMBER, - GUILD_MESSAGE, + GUILD_MESSAGE, GUILD_BOOST, GUILD_SETTINGS, VOICE, diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 24d47ce3b..78b25db05 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1803,6 +1803,11 @@ "mute": "Muted", "join": "Joined Channel", "left": "Left Channel" + }, + "cascade_permissions": { + "permission_added": "Added permission", + "permission_removed": "Removed permission", + "linked_role": "Linked Role" } } } From bf57d8965132ca92160e8795b5eea3faae72116c Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 7 Jun 2020 12:33:35 -0500 Subject: [PATCH 036/206] Revert "benchmark in submodule" It broke everything --- CascadeBenchmark/pom.xml | 34 ------------------- pom.xml | 17 +++++++--- .../cascadebot/CascadeBenchmark.java | 0 .../cascadebot/CryptUtilsBenchmark.java | 0 4 files changed, 13 insertions(+), 38 deletions(-) delete mode 100644 CascadeBenchmark/pom.xml rename {CascadeBenchmark/src => src}/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java (100%) rename {CascadeBenchmark/src => src}/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java (100%) diff --git a/CascadeBenchmark/pom.xml b/CascadeBenchmark/pom.xml deleted file mode 100644 index c2f274b4d..000000000 --- a/CascadeBenchmark/pom.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - cascadebot - org.cascadebot - 0.1.8 - - 4.0.0 - - CascadeBenchmark - - - - - org.openjdk.jmh - jmh-core - 1.19 - - - org.openjdk.jmh - jmh-generator-annprocess - 1.19 - - - org.cascadebot - cascadebot - 0.1.8 - - - - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index 32ec0e540..ab29e6f35 100644 --- a/pom.xml +++ b/pom.xml @@ -6,11 +6,7 @@ org.cascadebot cascadebot - pom 0.1.8 - - CascadeBenchmark - DEV @@ -440,6 +436,19 @@ icu4j 64.2 + + + + org.openjdk.jmh + jmh-core + 1.19 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.19 + + diff --git a/CascadeBenchmark/src/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java b/src/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java similarity index 100% rename from CascadeBenchmark/src/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java rename to src/benchmark/java/org/cascadebot/cascadebot/CascadeBenchmark.java diff --git a/CascadeBenchmark/src/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java b/src/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java similarity index 100% rename from CascadeBenchmark/src/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java rename to src/benchmark/java/org/cascadebot/cascadebot/CryptUtilsBenchmark.java From a71c997d32211bdc5a92a755cfc48384c7ea87dc Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 7 Jun 2020 13:24:49 -0500 Subject: [PATCH 037/206] More Cascade modlog events --- .../management/ModuleDisableSubCommand.java | 11 ++++++++ .../management/ModuleEnableSubCommand.java | 11 ++++++++ .../commands/management/SettingsCommand.java | 10 ++++++++ .../GroupPermissionAddSubCommand.java | 2 +- .../GroupPermissionRemoveSubCommand.java | 2 +- .../UserPermissionAddSubCommand.java | 11 ++++++++ .../UserPermissionGroupSubCommand.java | 18 +++++++++++-- .../UserPermissionRemoveSubCommand.java | 11 ++++++++ .../moderation/ModlogChannelSubCommand.java | 4 +-- .../moderation/ModlogDisableSubCommand.java | 4 +-- .../moderation/ModlogEnableSubCommand.java | 4 +-- .../moderation/ModlogEventsSubCommand.java | 2 +- .../cascadebot/events/CommandListener.java | 20 ++++++++++++++- .../data/objects/GuildSettingsModeration.kt | 25 ++++++++++++++++--- .../data/objects/ModlogEventStore.kt | 15 +++++++++++ src/main/resources/lang/en-GB.json | 17 +++++++++++-- 16 files changed, 150 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleDisableSubCommand.java index 9e69084a4..15ab7b428 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleDisableSubCommand.java @@ -11,7 +11,13 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; + +import java.util.ArrayList; +import java.util.List; public class ModuleDisableSubCommand extends SubCommand { @@ -29,6 +35,11 @@ public void onCommand(Member sender, CommandContext context) { if (context.getData().getCore().disableModule(module)) { // If module wasn't already disabled context.getTypedMessaging().replySuccess(context.i18n("commands.module.disable.disabled", module.toString())); + ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new LanguageEmbedField(true, "modlog.module.enabled", "modlog.general.variable", "false")); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), module, embedFieldList); + context.getData().getModeration().sendModlogEvent(eventStore); } else { // If module was already disabled context.getTypedMessaging().replyInfo(context.i18n("commands.module.disable.already_disabled", module.toString())); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleEnableSubCommand.java index c4bcf6641..28f2f4aec 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleEnableSubCommand.java @@ -11,7 +11,13 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; + +import java.util.ArrayList; +import java.util.List; public class ModuleEnableSubCommand extends SubCommand { @@ -29,6 +35,11 @@ public void onCommand(Member sender, CommandContext context) { if (context.getCoreSettings().enableModule(module)) { // If the module wasn't enabled context.getTypedMessaging().replySuccess(context.i18n("commands.module.enable.enabled", module.toString())); + ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new LanguageEmbedField(true, "modlog.module.enabled", "modlog.general.variable", "true")); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), module, embedFieldList); + context.getData().getModeration().sendModlogEvent(eventStore); } else { // If the module was enabled context.getTypedMessaging().replyInfo(context.i18n("commands.module.enable.already_enabled", module.toString())); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/SettingsCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/SettingsCommand.java index 70679e55c..8d88581e6 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/SettingsCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/SettingsCommand.java @@ -13,9 +13,12 @@ import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.language.Language; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; import org.cascadebot.cascadebot.data.objects.Setting; import org.cascadebot.cascadebot.data.objects.SettingsContainer; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.cascadebot.utils.ReflectionUtils; import java.io.IOException; @@ -59,6 +62,7 @@ public void onCommand(Member sender, CommandContext context) { context.getUiMessaging().replyUsage(); return; } + String oldValue = field.get(context.getCoreSettings()).toString(); String value = context.getArg(1); if (field.getType() == boolean.class) { boolean booleanValue = Boolean.parseBoolean(value); @@ -70,6 +74,12 @@ public void onCommand(Member sender, CommandContext context) { return; } context.getTypedMessaging().replySuccess(context.i18n("commands.settings.setting_set", field.getName(), value)); + ModlogEvent event = ModlogEvent.CASCADE_SETTINGS_UPDATED; + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new LanguageEmbedField(true, "modlog.setting.old", "modlog.general.variable", oldValue)); + embedFieldList.add(new LanguageEmbedField(true, "modlog.setting.new", "modlog.general.variable", value)); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), field, embedFieldList); + context.getData().getModeration().sendModlogEvent(eventStore); } catch (IllegalAccessException e) { context.getTypedMessaging().replyException(context.i18n("commands.settings.cannot_access"), e); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java index ce2a78233..4cbb0838d 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java @@ -35,7 +35,7 @@ public void onCommand(Member sender, CommandContext context) { if (group.addPermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.add.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_added", "moldog.general.variable", context.getArg(1))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_added", "modlog.general.variable", context.getArg(1))); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD; ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); context.getData().getModeration().sendModlogEvent(eventStore); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java index 440d9eb27..b36d3c415 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java @@ -36,7 +36,7 @@ public void onCommand(Member sender, CommandContext context) { if (group.removePermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.remove.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_removed", "moldog.general.variable", context.getArg(1))); + embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_removed", "modlog.general.variable", context.getArg(1))); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE; ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); context.getData().getModeration().sendModlogEvent(eventStore); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java index ac381432c..c5e380e99 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java @@ -9,9 +9,15 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.objects.User; import org.cascadebot.cascadebot.utils.DiscordUtils; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; + +import java.util.ArrayList; +import java.util.List; public class UserPermissionAddSubCommand extends SubCommand { @@ -37,6 +43,11 @@ public void onCommand(Member sender, CommandContext context) { if (user.addPermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.add.success", context.getArg(1), member.getUser().getAsTag())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_PERMISSION_ADD; + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_added", "modlog.general.variable", context.getArg(1))); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); + context.getData().getModeration().sendModlogEvent(eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.add.fail", context.getArg(1), member.getUser().getAsTag())); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java index e9a0e29ba..11f3e105e 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java @@ -9,11 +9,17 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.objects.User; import org.cascadebot.cascadebot.utils.DiscordUtils; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; +import java.util.ArrayList; +import java.util.List; + public class UserPermissionGroupSubCommand extends SubCommand { @Override @@ -39,19 +45,27 @@ public void onCommand(Member sender, CommandContext context) { if (context.testForArg("put")) { if (user.addGroup(group)) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.group.put.success", member.getUser().getAsTag(), group.getName())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_GROUP_ADD; + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.group_added", "modlog.general.variable", group.getName() + "(" + group.getId() + ")")); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); + context.getData().getModeration().sendModlogEvent(eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.group.put.fail", member.getUser().getAsTag(), group.getName())); } } else if (context.testForArg("remove")) { if (user.removeGroup(group)) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.group.remove.success", member.getUser().getAsTag(), group.getName())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_GROUP_REMOVE; + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.group_removed", "modlog.general.variable", group.getName() + "(" + group.getId() + ")")); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); + context.getData().getModeration().sendModlogEvent(eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.group.remove.fail", member.getUser().getAsTag(), group.getName())); } } }, sender.getIdLong()); - - } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java index 5ce99de07..1eb10780a 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java @@ -9,9 +9,15 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.objects.User; import org.cascadebot.cascadebot.utils.DiscordUtils; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; + +import java.util.ArrayList; +import java.util.List; public class UserPermissionRemoveSubCommand extends SubCommand { @@ -32,6 +38,11 @@ public void onCommand(Member sender, CommandContext context) { if (user.removePermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.remove.success", context.getArg(1), member.getUser().getAsTag())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE; + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_removed", "modlog.general.variable", context.getArg(1))); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); + context.getData().getModeration().sendModlogEvent(eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.remove.fail", context.getArg(1), member.getUser().getAsTag())); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java index cb71de222..1f8c4cee7 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java @@ -51,7 +51,7 @@ public void onCommand(Member sender, CommandContext context) { someEvents = true; } boolean webhookExists = isEnabled(modlogChannel, context); - String eventsListString = channelModlogEventsInfo.getValue().getEvents().stream().limit(numEvents).map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining(", ")); + String eventsListString = channelModlogEventsInfo.getValue().getEvents().stream().limit(numEvents).map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining(", ")); if (someEvents) { eventsListString += ", and " + (channelModlogEventsInfo.getValue().getEvents().size() - 3) + " more"; } @@ -154,7 +154,7 @@ public void onCommand(Member sender, CommandContext context) { context.getTypedMessaging().replySuccess("Successfully deleted channel!"); } else if (context.getArg(0).equalsIgnoreCase("info")) { GuildSettingsModeration.ChannelModlogEventsInfo channelModlogEventsInfo = context.getData().getModeration().getModlogEvents().get(channel.getIdLong()); - String events = channelModlogEventsInfo.getEvents().stream().map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")); + String events = channelModlogEventsInfo.getEvents().stream().map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")); context.getUiMessaging().sendPagedMessage(PageUtils.splitStringToEmbedPages(events, "Events for channel " + channel.getName(), 1000, '\n')); } else { context.getUiMessaging().replyUsage(); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java index a9b20d754..49c1d9aa1 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java @@ -77,7 +77,7 @@ public void onCommand(Member sender, CommandContext context) { pageList.add(new PageObjects.EmbedPage(embedBuilder)); } if (succeed.size() > 0) { - List pageValues = PageUtils.splitString(succeed.stream().map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); + List pageValues = PageUtils.splitString(succeed.stream().map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; for (String pageValue: pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); @@ -93,7 +93,7 @@ public void onCommand(Member sender, CommandContext context) { } } if (failedEvents.size() > 0) { - List pageValues = PageUtils.splitString(failedEvents.stream().map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); + List pageValues = PageUtils.splitString(failedEvents.stream().map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; for (String pageValue: pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java index 9ac2bf526..8070baf4e 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java @@ -78,7 +78,7 @@ public void onCommand(Member sender, CommandContext context) { pageList.add(new PageObjects.EmbedPage(embedBuilder)); } if (succeed.size() > 0) { - List pageValues = PageUtils.splitString(succeed.stream().map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); + List pageValues = PageUtils.splitString(succeed.stream().map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; for (String pageValue: pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); @@ -94,7 +94,7 @@ public void onCommand(Member sender, CommandContext context) { } } if (failedEvents.size() > 0) { - List pageValues = PageUtils.splitString(failedEvents.stream().map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); + List pageValues = PageUtils.splitString(failedEvents.stream().map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; for (String pageValue: pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java index fb0e65be4..ea4650c0f 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEventsSubCommand.java @@ -32,7 +32,7 @@ public void onCommand(Member sender, CommandContext context) { if (category.equals(ModlogEvent.Category.ALL)) { continue; } - List pageValues = PageUtils.splitString(categoryListEntry.getValue().stream().map(event -> Language.i18n(context.getLocale(), "enums.moldogevent." + event.name().toLowerCase() + ".select")).collect(Collectors.joining("\n")), 1000, '\n'); + List pageValues = PageUtils.splitString(categoryListEntry.getValue().stream().map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".select")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; for (String pageValue: pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder() diff --git a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java index 48ff9ecee..78fbd9834 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java @@ -23,18 +23,23 @@ import org.cascadebot.cascadebot.data.language.Language; import org.cascadebot.cascadebot.data.managers.GuildDataManager; import org.cascadebot.cascadebot.data.objects.GuildData; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; import org.cascadebot.cascadebot.data.objects.Tag; import org.cascadebot.cascadebot.messaging.MessageType; import org.cascadebot.cascadebot.messaging.Messaging; import org.cascadebot.cascadebot.messaging.MessagingObjects; import org.cascadebot.cascadebot.metrics.Metrics; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.utils.DiscordUtils; import org.cascadebot.cascadebot.utils.FormatUtils; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.shared.Regex; import org.cascadebot.shared.utils.ThreadPoolExecutorLogged; import org.slf4j.MDC; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Pattern; @@ -100,13 +105,26 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { MDC.put("cascade.trigger", trigger); MDC.put("cascade.args", Arrays.toString(args)); + ModlogEvent modlogEvent = null; try { processCommands(event, guildData, trigger, args, isMention); + modlogEvent = ModlogEvent.CASCADE_COMMAND_RUN; } catch (Exception e) { Messaging.sendExceptionMessage(event.getChannel(), Language.i18n(guildData.getLocale(), "responses.failed_to_process_command"), e); - return; + modlogEvent = ModlogEvent.CASCADE_COMMAND_RUN_ERROR; } finally { CascadeBot.clearCascadeMDC(); + MainCommand cmd = CascadeBot.INS.getCommandManager().getCommand(trigger, guildData); + if (modlogEvent != null && cmd != null) { + List embedFieldList = new ArrayList<>(); + StringBuilder stringBuilder = new StringBuilder(); + for (String arg : args) { + stringBuilder.append(arg).append(' '); + } + embedFieldList.add(new LanguageEmbedField(true, "modlog.command.args", "modlog.general.variable", stringBuilder.toString())); + ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, event.getAuthor(),cmd, embedFieldList); + guildData.getModeration().sendModlogEvent(eventStore); + } } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 6added10f..91bc699f3 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -17,12 +17,16 @@ import net.dv8tion.jda.api.entities.Role import net.dv8tion.jda.api.entities.TextChannel import net.dv8tion.jda.api.entities.User import org.cascadebot.cascadebot.CascadeBot +import org.cascadebot.cascadebot.commandmeta.MainCommand import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.database.DebugLogCallback import org.cascadebot.cascadebot.data.language.Language import org.cascadebot.cascadebot.data.language.Language.i18n import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.moderation.ModlogEvent +import org.cascadebot.cascadebot.permissions.objects.Group +import org.cascadebot.cascadebot.utils.FormatUtils +import java.lang.reflect.Field import java.net.URL import java.util.ArrayList import java.util.Date @@ -162,11 +166,10 @@ class GuildSettingsModeration { fun sendEvent(guildData: GuildData, modlogEventStore: ModlogEventStore) { val webhookEmbedBuilder = WebhookEmbedBuilder() - webhookEmbedBuilder.setTitle(EmbedTitle(i18n(guildData.locale, "enums.moldogevent." + modlogEventStore.trigger.name.toLowerCase() + ".display"), null)) + webhookEmbedBuilder.setTitle(EmbedTitle(i18n(guildData.locale, "enums.modlogevent." + modlogEventStore.trigger.name.toLowerCase() + ".display"), null)) val affected: Any = modlogEventStore.affected; var affectedType = "" val affectedStr = when (affected) { - is User -> { affectedType = "User"; affected.name + " (" + affected.id + ")" @@ -186,7 +189,23 @@ class GuildSettingsModeration { is GuildChannel -> { affectedType = "Channel" affected.name - } // TODO rest of events + } + is Group -> { + affectedType = "Group" + affected.name + "(" + affected.id + ")" + } + is Field -> { + affectedType = "Setting" + affected.name + } + is Module -> { + affectedType = "Module" + FormatUtils.formatEnum(affected, guildData.locale) + } + is MainCommand -> { + affectedType = "Command" + affected.command() + } else -> null } if (affectedStr != null) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 8f1bdda1b..1978ae31e 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -7,9 +7,12 @@ import net.dv8tion.jda.api.entities.ISnowflake import net.dv8tion.jda.api.entities.Role import net.dv8tion.jda.api.entities.User import org.cascadebot.cascadebot.CascadeBot +import org.cascadebot.cascadebot.commandmeta.MainCommand +import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.permissions.objects.Group import org.cascadebot.cascadebot.utils.LanguageEmbedField +import java.lang.reflect.Field class ModlogEventStore { @@ -59,6 +62,18 @@ class ModlogEventStore { affectedId = affected.id "Group" } + is Field -> { + affectedId = affected.name + "Setting" + } + is Module -> { + affectedId = affected.name.toLowerCase() + "Module" + } + is MainCommand -> { + affectedId = affected.command() + "Command" + } else -> { affectedId = "unknown" "unknown" diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 78b25db05..d8561d670 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -927,7 +927,7 @@ "most_restrictive": "most restrictive", "hierarchical": "hierarchical" }, - "moldogevent": { + "modlogevent": { "emote_created": { "select": "emote_created", "display": "Emote created" @@ -1807,7 +1807,20 @@ "cascade_permissions": { "permission_added": "Added permission", "permission_removed": "Removed permission", - "linked_role": "Linked Role" + "linked_role": "Linked Role", + "group_added": "Added group", + "group_removed": "Removed group" + }, + "setting": { + "old": "Old Value", + "new": "New Value" + }, + "module": { + "enabled": "Enabled" + }, + "command": { + "command": "Command", + "args": "Arguments" } } } From 1c3216238cf2512f0ea79c0aa616fcff713558ad Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 7 Jun 2020 13:45:38 -0500 Subject: [PATCH 038/206] The rest of the currently doable cascade events --- .../management/TagCreateSubCommand.java | 11 +++++++ .../management/TagDeleteSubCommand.java | 13 +++++++- .../management/TagEditSubCommand.java | 14 ++++++++- .../commands/music/QueueSaveSubCommand.java | 14 ++++++--- .../cascadebot/music/CascadePlayer.java | 31 ++++++++++++++++--- .../cascadebot/data/objects/Enums.kt | 2 +- .../data/objects/GuildSettingsModeration.kt | 8 +++++ .../data/objects/ModlogEventStore.kt | 8 +++++ .../cascadebot/moderation/ModlogEvent.kt | 1 - src/main/resources/lang/en-GB.json | 5 +++ 10 files changed, 94 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/TagCreateSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/TagCreateSubCommand.java index c51b31a33..d59ad802a 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/TagCreateSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/TagCreateSubCommand.java @@ -8,8 +8,14 @@ import net.dv8tion.jda.api.entities.Member; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; import org.cascadebot.cascadebot.data.objects.Tag; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; + +import java.util.ArrayList; +import java.util.List; public class TagCreateSubCommand extends SubCommand { @@ -39,6 +45,11 @@ public void onCommand(Member sender, CommandContext context) { context.getData().getManagement().addTag(context.getArg(0), tag); context.getData().getPermissionsManager().registerGuildPermission(tag.getInternalPermission()); context.getTypedMessaging().replySuccess(message); + ModlogEvent event = ModlogEvent.CASCADE_TAG_CREATED; + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new LanguageEmbedField(false, "modlog.tag.content", "modlog.general.variable", tag.getContent())); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, embedFieldList); + context.getData().getModeration().sendModlogEvent(eventStore); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/TagDeleteSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/TagDeleteSubCommand.java index f379d1df9..7e6f651ea 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/TagDeleteSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/TagDeleteSubCommand.java @@ -8,7 +8,14 @@ import net.dv8tion.jda.api.entities.Member; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.data.objects.Tag; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; + +import java.util.ArrayList; +import java.util.List; public class TagDeleteSubCommand extends SubCommand { @@ -21,8 +28,12 @@ public void onCommand(Member sender, CommandContext context) { String tagName = context.getArg(0).toLowerCase(); - if (context.getData().getManagement().removeTag(tagName)) { + Tag tag = context.getData().getManagement().getTag(tagName); + if (context.getData().getManagement().removeTag(tagName) && tag != null) { context.getTypedMessaging().replySuccess(context.i18n("commands.tag.delete.successfully_deleted_tag")); + ModlogEvent event = ModlogEvent.CASCADE_TAG_DELETED; + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, new ArrayList<>()); + context.getData().getModeration().sendModlogEvent(eventStore); } else { context.getTypedMessaging().replyDanger(context.i18n("commands.tag.delete.tag_doesnt_exist", tagName)); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/TagEditSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/TagEditSubCommand.java index 7e23d094e..98f3351ee 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/TagEditSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/TagEditSubCommand.java @@ -8,8 +8,14 @@ import net.dv8tion.jda.api.entities.Member; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; import org.cascadebot.cascadebot.data.objects.Tag; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; +import org.cascadebot.cascadebot.utils.LanguageEmbedField; + +import java.util.ArrayList; +import java.util.List; public class TagEditSubCommand extends SubCommand { @@ -27,9 +33,15 @@ public void onCommand(Member sender, CommandContext context) { context.getTypedMessaging().replyDanger(context.i18n("commands.tag.cannot_find_tag", tagName)); return; } - + String oldContent = tag.getContent(); tag.setContent(context.getMessage(1)); context.getTypedMessaging().replySuccess(context.i18n("commands.tag.edit.successfully_edited_tag", tagName)); + ModlogEvent event = ModlogEvent.CASCADE_TAG_UPDATED; + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new LanguageEmbedField(false, "modlog.tag.old_content", "modlog.general.variable", oldContent)); + embedFieldList.add(new LanguageEmbedField(false, "modlog.tag.new_content", "modlog.general.variable", tag.getContent())); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, embedFieldList); + context.getData().getModeration().sendModlogEvent(eventStore); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/music/QueueSaveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/music/QueueSaveSubCommand.java index 31ea750b9..39a70c96e 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/music/QueueSaveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/music/QueueSaveSubCommand.java @@ -9,12 +9,15 @@ import org.apache.commons.lang3.EnumUtils; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; import org.cascadebot.cascadebot.data.objects.PlaylistType; -import org.cascadebot.cascadebot.data.objects.SavePlaylistResult; import org.cascadebot.cascadebot.messaging.MessageType; +import org.cascadebot.cascadebot.moderation.ModlogEvent; +import org.cascadebot.cascadebot.music.CascadePlayer; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.ConfirmUtils; +import java.util.ArrayList; import java.util.concurrent.TimeUnit; public class QueueSaveSubCommand extends SubCommand { @@ -52,8 +55,8 @@ public void onCommand(Member sender, CommandContext context) { long lambdaOwner = owner; PlaylistType lambdaScope = scope; - SavePlaylistResult result = context.getMusicPlayer().saveCurrentPlaylist(lambdaOwner, lambdaScope, context.getArg(0), false); - switch (result) { + CascadePlayer.SavePlaylistResult result = context.getMusicPlayer().saveCurrentPlaylist(lambdaOwner, lambdaScope, context.getArg(0), false); + switch (result.getType()) { case ALREADY_EXISTS: if (lambdaScope.equals(PlaylistType.GUILD)) { if (!context.hasPermission("queue.save.overwrite")) { @@ -65,13 +68,16 @@ public void onCommand(Member sender, CommandContext context) { context.i18n("commands.save.already_exists"), TimeUnit.SECONDS.toMillis(1), TimeUnit.SECONDS.toMillis(10), true, new ConfirmUtils.ConfirmRunnable() { @Override public void execute() { - context.getMusicPlayer().saveCurrentPlaylist(lambdaOwner, lambdaScope, context.getArg(0), false); + context.getMusicPlayer().saveCurrentPlaylist(lambdaOwner, lambdaScope, context.getArg(0), true); context.getTypedMessaging().replySuccess(context.i18n("commands.queue.save.saved_playlist", context.getArg(0), lambdaScope.name().toLowerCase())); } }); break; case NEW: context.getTypedMessaging().replySuccess(context.i18n("commands.queue.save.saved_playlist", context.getArg(0), lambdaScope.name().toLowerCase())); + ModlogEvent event = ModlogEvent.CASCADE_PLAYLIST_CREATED; + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), result.getPlaylist(), new ArrayList<>()); + context.getData().getModeration().sendModlogEvent(eventStore); break; } } diff --git a/src/main/java/org/cascadebot/cascadebot/music/CascadePlayer.java b/src/main/java/org/cascadebot/cascadebot/music/CascadePlayer.java index 9cbd77c4c..58ec3ec1e 100644 --- a/src/main/java/org/cascadebot/cascadebot/music/CascadePlayer.java +++ b/src/main/java/org/cascadebot/cascadebot/music/CascadePlayer.java @@ -18,7 +18,7 @@ import org.cascadebot.cascadebot.data.objects.LoopMode; import org.cascadebot.cascadebot.data.objects.Playlist; import org.cascadebot.cascadebot.data.objects.PlaylistType; -import org.cascadebot.cascadebot.data.objects.SavePlaylistResult; +import org.cascadebot.cascadebot.data.objects.SavePlaylistResultType; import org.cascadebot.cascadebot.utils.StringsUtil; import java.util.ArrayList; @@ -240,13 +240,14 @@ default SavePlaylistResult saveCurrentPlaylist(long owner, PlaylistType scope, S if (overwrite) { search.setTracks(ids); PlaylistManager.replacePlaylist(search); - return SavePlaylistResult.OVERWRITE; + return new SavePlaylistResult(SavePlaylistResultType.OVERWRITE, search); } else { - return SavePlaylistResult.ALREADY_EXISTS; + return new SavePlaylistResult(SavePlaylistResultType.ALREADY_EXISTS, null); } } else { - PlaylistManager.savePlaylist(new Playlist(owner, name, scope, ids)); - return SavePlaylistResult.NEW; + Playlist playlist = new Playlist(owner, name, scope, ids); + PlaylistManager.savePlaylist(playlist); + return new SavePlaylistResult(SavePlaylistResultType.NEW, playlist); } } @@ -284,5 +285,25 @@ default void setQueue(Queue newQueue) { @Override void setVolume(int i); + class SavePlaylistResult { + + private SavePlaylistResultType type; + private Playlist playlist; + + public SavePlaylistResult(SavePlaylistResultType type, Playlist playlist) { + this.type = type; + this.playlist = playlist; + } + + public Playlist getPlaylist() { + return playlist; + } + + public SavePlaylistResultType getType() { + return type; + } + + } + } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt index 292bf1811..739f52b1b 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt @@ -83,7 +83,7 @@ enum class LoopMode { DISABLED, PLAYLIST, SONG } -enum class SavePlaylistResult { +enum class SavePlaylistResultType { ALREADY_EXISTS, OVERWRITE, NEW } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 91bc699f3..44197a5e7 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -206,6 +206,14 @@ class GuildSettingsModeration { affectedType = "Command" affected.command() } + is Playlist -> { + affectedType = "Playlist" + affected.name + } + is Tag -> { + affectedType = "Tag" + affected.name + } else -> null } if (affectedStr != null) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 1978ae31e..6bf63d3ec 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -74,6 +74,14 @@ class ModlogEventStore { affectedId = affected.command() "Command" } + is Playlist -> { + affectedId = affected.name + "Playlist" + } + is Tag -> { + affectedId = affected.name + "Tag" + } else -> { affectedId = "unknown" "unknown" diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index a5bfe5715..cfcbaaaf3 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -102,7 +102,6 @@ enum class ModlogEvent(messageType: MessageType, vararg categories: Category) { CASCADE_COMMAND_RUN_ERROR(MessageType.WARNING, Category.CASCADE), CASCADE_PLAYLIST_CREATED(MessageType.INFO, Category.CASCADE), - CASCADE_PLAYLIST_DELETED(MessageType.INFO, Category.CASCADE), CASCADE_TEMP_MUTE(MessageType.DANGER, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), CASCADE_TEMP_BAN(MessageType.DANGER, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index d8561d670..105c2f4de 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1821,6 +1821,11 @@ "command": { "command": "Command", "args": "Arguments" + }, + "tag": { + "content": "Content", + "old_content": "Old content", + "new_content": "New content" } } } From fb561d7579f9d1c6e9e0a767d9c3f5a7f46528b7 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 7 Jun 2020 13:51:20 -0500 Subject: [PATCH 039/206] =?UTF-8?q?lombok=20(=E2=95=AF=C2=B0=E2=96=A1?= =?UTF-8?q?=C2=B0=EF=BC=89=E2=95=AF=EF=B8=B5=20=E2=94=BB=E2=94=81=E2=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cascadebot/data/objects/Playlist.java | 21 ++++++++++++++++++- .../cascadebot/data/objects/Tag.java | 14 ++++++++++++- .../cascadebot/permissions/objects/Group.java | 6 +++++- 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/Playlist.java b/src/main/java/org/cascadebot/cascadebot/data/objects/Playlist.java index 11d289360..1c50c4503 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/Playlist.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/Playlist.java @@ -14,7 +14,6 @@ import java.util.List; -@Getter @NoArgsConstructor(access = AccessLevel.PRIVATE) public class Playlist { @@ -43,4 +42,24 @@ public void removeTrack(String url) { tracks.remove(url); } + public String getName() { + return name; + } + + public long getOwnerId() { + return ownerId; + } + + public PlaylistType getType() { + return scope; + } + + public List getTracks() { + return tracks; + } + + public ObjectId getPlaylistId() { + return playlistId; + } + } diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java index 845a532c9..25152ccfc 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java @@ -18,7 +18,6 @@ import java.util.regex.Pattern; @Setter -@Getter @NoArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor public class Tag extends PermissionObject { @@ -64,4 +63,17 @@ public String getParent() { public Module cascadeModule() { return Module.MANAGEMENT; } + + public String getName() { + return name; + } + + public String getContent() { + return content; + } + + public String getCategory() { + return category; + } + } \ No newline at end of file diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java index e81435539..cbf58685b 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java @@ -25,7 +25,6 @@ public class Group extends PermissionHolder { // This is normal alphanumeric with similar characters removed for less errors when inputting private String id = RandomStringUtils.random(5, "abcdefghijkmnopqrstuvwxyzACDEFHJKLMNPRSTUVWXYZ123467890"); - @Getter @Setter private String name; @@ -55,4 +54,9 @@ HolderType getType() { public String getId() { return id; } + + public String getName() { + return name; + } + } From a5e831c575c188bc38af8293e5fbe41656d4dbbd Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Tue, 9 Jun 2020 09:25:18 -0500 Subject: [PATCH 040/206] Final misc message stuff Besides stuff that requires dashboard --- .../events/ModlogEventListener.java | 21 +++++++++++++------ .../cascadebot/moderation/ModlogEvent.kt | 2 +- src/main/resources/lang/en-GB.json | 3 ++- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 4d0b407bb..8b7b801c3 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -107,6 +107,7 @@ import org.cascadebot.cascadebot.data.objects.GuildData; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; import org.cascadebot.cascadebot.moderation.ModlogEvent; +import org.cascadebot.cascadebot.utils.Attachment; import org.cascadebot.cascadebot.utils.ColorUtils; import org.cascadebot.cascadebot.utils.CryptUtils; import org.cascadebot.cascadebot.utils.LanguageEmbedField; @@ -291,22 +292,30 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { LanguageEmbedField messageEmbedField = new LanguageEmbedField(false, "modlog.message.message", "modlog.general.variable"); messageEmbedField.addValueObjects(message.getContent()); embedFieldList.add(messageEmbedField); + if (message.getAttachments().size() > 0) { + StringBuilder attachmentsBuilder = new StringBuilder(); + for (Attachment attachment : message.getAttachments()) { + attachmentsBuilder.append(attachment.getUrl()).append('\n'); + } + embedFieldList.add(new LanguageEmbedField(false, "modlog.message.attachments", "modlog.general.variable", attachmentsBuilder.toString())); + } if (affected == null) { return; } //TODO handle embeds/ect... event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); - ModlogEvent modlogEvent; User responsible; if (entry.getType().equals(ActionType.MESSAGE_DELETE)) { - modlogEvent = ModlogEvent.GUILD_MESSAGE_DELETED; responsible = entry.getUser(); - } else { //TODO not assume self delete if audit log entry for message delete was not found. - modlogEvent = ModlogEvent.GUILD_MESSAGE_DELETED_SELF; - responsible = affected; + } else { + responsible = null; } - ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); + if (message.getUserMentions().size() > 0 || message.getRoleMentions().size() > 0) { + ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.GUILD_MESSAGE_DELETED_MENTION, responsible, affected, embedFieldList); + guildData.getModeration().sendModlogEvent(eventStore); + } + ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.GUILD_MESSAGE_DELETED, responsible, affected, embedFieldList); guildData.getModeration().sendModlogEvent(eventStore); }); } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index cfcbaaaf3..b381bf0e9 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -24,7 +24,7 @@ enum class ModlogEvent(messageType: MessageType, vararg categories: Category) { GUILD_USER_UNBANNED(MessageType.DANGER, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), GUILD_MESSAGE_DELETED(MessageType.WARNING, Category.GUILD, Category.GUILD_MESSAGE), - GUILD_MESSAGE_DELETED_SELF(MessageType.INFO, Category.GUILD, Category.GUILD_MESSAGE), + GUILD_MESSAGE_DELETED_MENTION(MessageType.INFO, Category.GUILD, Category.GUILD_MESSAGE), GUILD_MESSAGE_UPDATED(MessageType.INFO, Category.GUILD, Category.GUILD_MESSAGE), GUILD_BOOST_COUNT_UPDATED(MessageType.INFO, Category.GUILD, Category.GUILD_BOOST), diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 105c2f4de..dc7de94a5 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1682,7 +1682,8 @@ "message": { "message": "Message", "old_message": "Old Message", - "new_message": "New Message" + "new_message": "New Message", + "attachments": "Attachments" }, "guild": { "old_channel": "Old Channel", From 8c8a2826a7f0a0c733d6febc119e885a7fa9f065 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Tue, 9 Jun 2020 10:56:03 -0500 Subject: [PATCH 041/206] Minor fixes --- .../events/ModlogEventListener.java | 32 +++++++++++++++++-- .../cascadebot/moderation/ModlogEvent.kt | 2 +- src/main/resources/lang/en-GB.json | 4 +++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 8b7b801c3..13f344f37 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -139,6 +139,8 @@ public void onGenericEmote(GenericEmoteEvent event) { User user = null; if (entry.getType().equals(ActionType.EMOTE_UPDATE) || entry.getType().equals(ActionType.EMOTE_CREATE) || entry.getType().equals(ActionType.EMOTE_DELETE)) { user = auditLogEntries.get(0).getUser(); + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find emote entry"); } List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent; @@ -181,7 +183,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { ModlogEvent modlogEvent; User responsible = null; if (event instanceof GuildMemberJoinEvent) { - modlogEvent = ModlogEvent.GUILD_MEMBER_JOINED; + modlogEvent = ModlogEvent.GUILD_MEMBER_LEFT; } else if (event instanceof GuildMemberLeaveEvent) { if (entry.getType().equals(ActionType.KICK)) { LanguageEmbedField respLanguageEmbedField = new LanguageEmbedField(true, "modlog.general.responsible", "modlog.general.variable"); @@ -193,7 +195,8 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { embedFieldList.add(reasonEmbedField); } modlogEvent = ModlogEvent.GUILD_MEMBER_KICKED; - } else { //TODO not assume leave if audit log entry for kick was not found. + } else { //TODO not assume leave if audit log entry for kick was not found. else { + CascadeBot.LOGGER.warn("Modlog: Failed to find kick entry"); modlogEvent = ModlogEvent.GUILD_MEMBER_LEFT; } } else if (event instanceof GuildMemberRoleAddEvent) { @@ -248,6 +251,8 @@ public void onGuildBan(GuildBanEvent event) { reasonEmbedField.addValueObjects(entry.getReason()); embedFieldList.add(reasonEmbedField); } + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find ban entry"); } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); guildData.getModeration().sendModlogEvent(eventStore); @@ -264,6 +269,8 @@ public void onGuildUnban(GuildUnbanEvent event) { User responsible = null; if (entry.getType().equals(ActionType.UNBAN)) { responsible = entry.getUser(); + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find unban entry"); } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); guildData.getModeration().sendModlogEvent(eventStore); @@ -309,6 +316,7 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { if (entry.getType().equals(ActionType.MESSAGE_DELETE)) { responsible = entry.getUser(); } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find message delete entry"); responsible = null; } if (message.getUserMentions().size() > 0 || message.getRoleMentions().size() > 0) { @@ -390,6 +398,8 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { ModlogEvent modlogEvent; if (entry.getType().equals(ActionType.GUILD_UPDATE)) { responsible = entry.getUser(); + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find guild update entry"); } if (event instanceof GuildUpdateAfkChannelEvent) { VoiceChannel oldChannel = ((GuildUpdateAfkChannelEvent) event).getOldAfkChannel(); @@ -593,6 +603,8 @@ public void onGenericTextChannel(GenericTextChannelEvent event) { User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { responsible = entry.getUser(); + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } if (event instanceof TextChannelUpdateNSFWEvent) { embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.nsfw", "modlog.general.variable", String.valueOf(!((TextChannelUpdateNSFWEvent) event).getOldNSFW()))); @@ -633,6 +645,8 @@ public void onGenericVoiceChannel(GenericVoiceChannelEvent event) { User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { responsible = entry.getUser(); + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } if (event instanceof VoiceChannelUpdateBitrateEvent) { embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getOldBitrate()))); @@ -672,6 +686,8 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_UPDATE) || entry.getType().equals(ActionType.CHANNEL_OVERRIDE_UPDATE)) { responsible = entry.getUser(); + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } String permissionsHolderName; if (event.getPermissionHolder() instanceof User) { @@ -736,6 +752,8 @@ private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChann User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_CREATE)) { responsible = entry.getUser(); + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel create entry"); } embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); @@ -752,6 +770,8 @@ private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChann User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_DELETE)) { responsible = entry.getUser(); + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel delete entry"); } embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); @@ -768,6 +788,8 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { responsible = entry.getUser(); + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable", oldName)); @@ -785,6 +807,8 @@ private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, in User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { responsible = entry.getUser(); + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_pos", "modlog.general.variable", String.valueOf(oldPos))); @@ -803,6 +827,8 @@ public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Categ User responsible = null; if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { responsible = entry.getUser(); + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_parent", "modlog.general.variable", oldParent.getName())); @@ -822,6 +848,8 @@ public void onGenericRole(GenericRoleEvent event) { ModlogEvent modlogEvent; if (entry.getType().equals(ActionType.ROLE_CREATE) || entry.getType().equals(ActionType.ROLE_DELETE) || entry.getType().equals(ActionType.ROLE_UPDATE)) { responsible = entry.getUser(); + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find role entry"); } Role affected = event.getRole(); if (event instanceof RoleCreateEvent) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index b381bf0e9..176bde42e 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -131,10 +131,10 @@ enum class ModlogEvent(messageType: MessageType, vararg categories: Category) { } init { - modlogCategoryMap[Category.ALL] = Arrays.asList(*values()) for (cat in Category.values()) { modlogCategoryMap[cat] = ArrayList() } + modlogCategoryMap[Category.ALL] = Arrays.asList(*values()) for (event in values()) { for (category in event.categories) { modlogCategoryMap[category]?.add(event) diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index dc7de94a5..df3f296d5 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1287,6 +1287,10 @@ "cascade_tag_updated": { "select": "cascade_tag_updated", "display": "Cascade tag updated" + }, + "guild_message_deleted_mention": { + "select": "guild_message_deleted_mention", + "display": "Guild message deleted with mention" } } }, From a2cace8b88929fdae5aa674e32bdca12970ce388 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Tue, 9 Jun 2020 11:19:20 -0500 Subject: [PATCH 042/206] page fixes. time for merge conflicts --- .../cascadebot/utils/pagination/PageObjects.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/utils/pagination/PageObjects.java b/src/main/java/org/cascadebot/cascadebot/utils/pagination/PageObjects.java index 0ada06f8b..e7ce62847 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/pagination/PageObjects.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/pagination/PageObjects.java @@ -39,12 +39,17 @@ public EmbedPage(EmbedBuilder embed, boolean numbersInEmbed) { public void pageShow(Message message, int page, int total) { GuildData data = GuildDataManager.getGuildData(message.getTextChannel().getGuild().getIdLong()); if (data.getCore().getUseEmbedForMessages()) { - if (numbersInEmbed && total > 1) { - embed.setFooter(Language.i18n(data.getLocale(), "page_objects.page_footer", page, total), message.getAuthor().getAvatarUrl()); + if (numbersInEmbed) { + if (total > 1) { + embed.setFooter(Language.i18n(data.getLocale(), "page_objects.page_footer", page, total), message.getAuthor().getAvatarUrl()); + } message.editMessage(embed.build()).override(true).queue(); } else { - message.editMessage(new MessageBuilder().setEmbed(embed.build()).append(Language.i18n(data.getLocale(), "page_objects.page_footer", page, total)).build()).override(true).queue(); - + var messageBuilder = new MessageBuilder().setEmbed(embed.build()); + if (total > 1) { + messageBuilder.append(Language.i18n(data.getLocale(), "page_objects.page_footer", page, total)); + } + message.editMessage(messageBuilder.build()).override(true).queue(); } } else { if (total > 1) { From e8053935e4a22766edc5493bf3b8aaceb936b935 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Tue, 9 Jun 2020 11:47:49 -0500 Subject: [PATCH 043/206] More fixes! --- .../org/cascadebot/cascadebot/events/ModlogEventListener.java | 2 ++ .../cascadebot/runnables/MessageReceivedRunnable.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 13f344f37..9914a2ad3 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -227,6 +227,8 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { embedFieldList.add(newNickEmbedField); } modlogEvent = ModlogEvent.GUILD_MEMBER_NICKNAME_UPDATED; + } else if (event instanceof GuildMemberJoinEvent) { + modlogEvent = ModlogEvent.GUILD_MEMBER_JOINED; } else { return; } diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java index 62e0e27bb..872858f27 100644 --- a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java +++ b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java @@ -41,7 +41,7 @@ public class MessageReceivedRunnable implements Runnable { @Override public void run() { - while (!ShutdownHandler.SHUTDOWN_LOCK.get()) { + while (true) { try { GuildMessageReceivedEvent event = queue.take(); if (event.getMember() == null) { From 853b12d111b554767ba1cca64132831a62da3c2e Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Tue, 9 Jun 2020 12:24:05 -0500 Subject: [PATCH 044/206] More fixes, also more entry checks --- .../events/ModlogEventListener.java | 57 ++++++++++++------- .../runnables/MessageReceivedRunnable.java | 9 +-- 2 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 9914a2ad3..b5741b3e3 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -122,6 +122,8 @@ import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.time.Duration; +import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collection; import java.util.EnumSet; @@ -131,13 +133,16 @@ public class ModlogEventListener extends ListenerAdapter { + private final long auditTimeAllowed = 1000l; + public void onGenericEmote(GenericEmoteEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); Emote emote = event.getEmote(); event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); User user = null; - if (entry.getType().equals(ActionType.EMOTE_UPDATE) || entry.getType().equals(ActionType.EMOTE_CREATE) || entry.getType().equals(ActionType.EMOTE_DELETE)) { + if ((entry.getType().equals(ActionType.EMOTE_UPDATE) || entry.getType().equals(ActionType.EMOTE_CREATE) || entry.getType().equals(ActionType.EMOTE_DELETE)) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getEmote().getIdLong()) { user = auditLogEntries.get(0).getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find emote entry"); @@ -179,13 +184,14 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { User user = event.getMember().getUser(); event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent; User responsible = null; if (event instanceof GuildMemberJoinEvent) { - modlogEvent = ModlogEvent.GUILD_MEMBER_LEFT; + modlogEvent = ModlogEvent.GUILD_MEMBER_JOINED; } else if (event instanceof GuildMemberLeaveEvent) { - if (entry.getType().equals(ActionType.KICK)) { + if (entry.getType().equals(ActionType.KICK) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getMember().getIdLong()) { LanguageEmbedField respLanguageEmbedField = new LanguageEmbedField(true, "modlog.general.responsible", "modlog.general.variable"); respLanguageEmbedField.addValueObjects(Objects.requireNonNull(entry.getUser()).getAsTag()); embedFieldList.add(respLanguageEmbedField); @@ -200,7 +206,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { modlogEvent = ModlogEvent.GUILD_MEMBER_LEFT; } } else if (event instanceof GuildMemberRoleAddEvent) { - if (entry.getType().equals(ActionType.MEMBER_ROLE_UPDATE)) { + if (entry.getType().equals(ActionType.MEMBER_ROLE_UPDATE) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getMember().getIdLong()) { responsible = entry.getUser(); } modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_ADDED; @@ -208,7 +214,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { addedRolesEmbedField.addValueObjects(((GuildMemberRoleAddEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n"))); embedFieldList.add(addedRolesEmbedField); } else if (event instanceof GuildMemberRoleRemoveEvent) { - if (entry.getType().equals(ActionType.MEMBER_ROLE_UPDATE)) { + if (entry.getType().equals(ActionType.MEMBER_ROLE_UPDATE) && millis < 1000 && entry.getTargetIdLong() == event.getMember().getIdLong()) { responsible = entry.getUser(); } modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_REMOVED; @@ -227,8 +233,6 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { embedFieldList.add(newNickEmbedField); } modlogEvent = ModlogEvent.GUILD_MEMBER_NICKNAME_UPDATED; - } else if (event instanceof GuildMemberJoinEvent) { - modlogEvent = ModlogEvent.GUILD_MEMBER_JOINED; } else { return; } @@ -244,9 +248,10 @@ public void onGuildBan(GuildBanEvent event) { event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); List embedFieldList = new ArrayList<>(); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); ModlogEvent modlogEvent = ModlogEvent.GUILD_USER_BANNED; User responsible = null; - if (entry.getType().equals(ActionType.BAN)) { + if (entry.getType().equals(ActionType.BAN) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getUser().getIdLong()) { responsible = entry.getUser(); if (entry.getReason() != null) { LanguageEmbedField reasonEmbedField = new LanguageEmbedField(false, "modlog.general.reason", "modlog.general.variable"); @@ -266,10 +271,11 @@ public void onGuildUnban(GuildUnbanEvent event) { User user = event.getUser(); event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent = ModlogEvent.GUILD_USER_UNBANNED; User responsible = null; - if (entry.getType().equals(ActionType.UNBAN)) { + if (entry.getType().equals(ActionType.UNBAN) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getUser().getIdLong()) { responsible = entry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find unban entry"); @@ -314,8 +320,9 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { //TODO handle embeds/ect... event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); User responsible; - if (entry.getType().equals(ActionType.MESSAGE_DELETE)) { + if (entry.getType().equals(ActionType.MESSAGE_DELETE) && millis < auditTimeAllowed && entry.getTargetIdLong() == message.getAuthorId()) { responsible = entry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find message delete entry"); @@ -395,10 +402,11 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { GuildData guildData = GuildDataManager.getGuildData(affected.getIdLong()); event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); List embedFieldList = new ArrayList<>(); User responsible = null; ModlogEvent modlogEvent; - if (entry.getType().equals(ActionType.GUILD_UPDATE)) { + if (entry.getType().equals(ActionType.GUILD_UPDATE) && millis < auditTimeAllowed) { responsible = entry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find guild update entry"); @@ -601,9 +609,10 @@ public void onGenericTextChannel(GenericTextChannelEvent event) { event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { ModlogEvent trigger; AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { + if (entry.getType().equals(ActionType.CHANNEL_UPDATE) && millis < auditTimeAllowed && event.getChannel().getIdLong() == entry.getTargetIdLong()) { responsible = entry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); @@ -643,9 +652,10 @@ public void onGenericVoiceChannel(GenericVoiceChannelEvent event) { event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { ModlogEvent trigger; AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { + if (entry.getType().equals(ActionType.CHANNEL_UPDATE) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getChannel().getIdLong()) { responsible = entry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); @@ -684,9 +694,10 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_UPDATE) || entry.getType().equals(ActionType.CHANNEL_OVERRIDE_UPDATE)) { + if ((entry.getType().equals(ActionType.CHANNEL_UPDATE) || entry.getType().equals(ActionType.CHANNEL_OVERRIDE_UPDATE)) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getChannel().getIdLong()) { responsible = entry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); @@ -750,9 +761,10 @@ private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChann GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_CREATE)) { + if (entry.getType().equals(ActionType.CHANNEL_CREATE) && millis < auditTimeAllowed && entry.getTargetIdLong() == channel.getIdLong()) { responsible = entry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel create entry"); @@ -768,9 +780,10 @@ private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChann GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_DELETE)) { + if (entry.getType().equals(ActionType.CHANNEL_DELETE) && millis < auditTimeAllowed && entry.getTargetIdLong() == channel.getIdLong()) { responsible = entry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel delete entry"); @@ -786,9 +799,10 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { + if (entry.getType().equals(ActionType.CHANNEL_UPDATE) && millis < 1000 && entry.getTargetIdLong() == channel.getIdLong()) { responsible = entry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); @@ -805,9 +819,10 @@ private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, in GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { + if (entry.getType().equals(ActionType.CHANNEL_UPDATE) && millis < 1000 && entry.getTargetIdLong() == channel.getIdLong()) { responsible = entry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); @@ -825,9 +840,10 @@ public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Categ GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_UPDATE)) { + if (entry.getType().equals(ActionType.CHANNEL_UPDATE) && millis < 1000 && entry.getTargetIdLong() == channel.getIdLong()) { responsible = entry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); @@ -845,10 +861,11 @@ public void onGenericRole(GenericRoleEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); List embedFieldList = new ArrayList<>(); User responsible = null; ModlogEvent modlogEvent; - if (entry.getType().equals(ActionType.ROLE_CREATE) || entry.getType().equals(ActionType.ROLE_DELETE) || entry.getType().equals(ActionType.ROLE_UPDATE)) { + if ((entry.getType().equals(ActionType.ROLE_CREATE) || entry.getType().equals(ActionType.ROLE_DELETE) || entry.getType().equals(ActionType.ROLE_UPDATE)) && millis < 1000 && entry.getTargetIdLong() == event.getRole().getIdLong()) { responsible = entry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find role entry"); diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java index 872858f27..4a7384cb3 100644 --- a/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java +++ b/src/main/java/org/cascadebot/cascadebot/runnables/MessageReceivedRunnable.java @@ -41,14 +41,14 @@ public class MessageReceivedRunnable implements Runnable { @Override public void run() { - while (true) { + while (!ShutdownHandler.SHUTDOWN_LOCK.get()) { try { GuildMessageReceivedEvent event = queue.take(); if (event.getMember() == null) { - return; + continue; } if (CascadeBot.INS.getRedisClient() == null) { - return; + continue; } SerializableMessage serializableMessage = SerializableMessage.createSerializeMessageFromJda(event.getMessage()); String messageJson = CascadeBot.getGSON().toJson(serializableMessage); @@ -63,7 +63,7 @@ public void run() { message = CascadeBot.getGSON().toJson(CascadeBot.getGSON().toJsonTree(results)); } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | ShortBufferException | BadPaddingException | IllegalBlockSizeException | InvalidAlgorithmParameterException exception) { CascadeBot.LOGGER.warn("Failed to encrypt", exception); - return; + continue; } } else { message = messageJson; @@ -71,6 +71,7 @@ public void run() { CascadeBot.INS.getRedisClient().setex("message:" + event.getMessageId(), (int) TimeUnit.HOURS.toSeconds(24), message); } catch (InterruptedException e) { CascadeBot.LOGGER.warn("Message thread interrupted: " + PasteUtils.getStackTrace(e)); + return; } } } From 0da709063c73cc909f7f1769dbe5faebbc1c60d0 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Tue, 9 Jun 2020 12:25:45 -0500 Subject: [PATCH 045/206] uggggggg --- .../org/cascadebot/cascadebot/events/ModlogEventListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index b5741b3e3..655fd6bb5 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -362,6 +362,7 @@ public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { LanguageEmbedField newEmbedField = new LanguageEmbedField(false, "modlog.message.new_message", "modlog.general.variable"); newEmbedField.addValueObjects(message.getContentRaw()); // TODO handle embeds/ect... + embedFieldList.add(oldEmbedField); embedFieldList.add(newEmbedField); ModlogEvent modlogEvent = ModlogEvent.GUILD_MESSAGE_UPDATED; ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, null, affected, embedFieldList); From df8350562d7ffe1da4b8e688ba70d995273594d3 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 9 Jun 2020 19:49:08 +0100 Subject: [PATCH 046/206] WHY DOES THIS EXIST --- .../commands/management/SettingsCommand.java | 130 ------------------ 1 file changed, 130 deletions(-) delete mode 100644 src/main/java/org/cascadebot/cascadebot/commands/management/SettingsCommand.java diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/SettingsCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/SettingsCommand.java deleted file mode 100644 index 70679e55c..000000000 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/SettingsCommand.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2019 CascadeBot. All rights reserved. - * Licensed under the MIT license. - */ - -package org.cascadebot.cascadebot.commands.management; - -import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.entities.Member; -import org.cascadebot.cascadebot.CascadeBot; -import org.cascadebot.cascadebot.commandmeta.CommandContext; -import org.cascadebot.cascadebot.commandmeta.MainCommand; -import org.cascadebot.cascadebot.commandmeta.Module; -import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.language.Language; -import org.cascadebot.cascadebot.data.objects.Setting; -import org.cascadebot.cascadebot.data.objects.SettingsContainer; -import org.cascadebot.cascadebot.permissions.CascadePermission; -import org.cascadebot.cascadebot.utils.ReflectionUtils; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -public class SettingsCommand extends MainCommand { - - private static List> settingsClasses = new ArrayList<>(); - - static { - try { - ReflectionUtils.getClasses("org.cascadebot.cascadebot.data.objects").stream().filter(classToFilter -> classToFilter.getAnnotation(SettingsContainer.class) != null).forEach(settingsClasses::add); - } catch (ClassNotFoundException | IOException e) { - CascadeBot.LOGGER.error("Could not load settings!", e); - } - } - - @Override - public void onCommand(Member sender, CommandContext context) { - if (context.getArgs().length == 2) { - Field field = (getAllSettings(settingsClasses).get(context.getArg(0).toLowerCase())); - if (field != null) { - try { - Setting settingAnnotation = field.getAnnotation(Setting.class); - if (settingAnnotation != null) { - if (!context.getData().getEnabledFlags().containsAll(Arrays.asList(settingAnnotation.flagRequired()))) { - String niceName = Language.i18n(context.getGuild().getIdLong(), "settings." + field.getDeclaringClass().getAnnotation(SettingsContainer.class).module().name().toLowerCase() + "." + field.getName() + ".nice_name"); - context.getTypedMessaging().replyDanger(context.i18n("commands.settings.cannot_edit", niceName)); - return; - } - } - - if (context.getArgs().length != 2) { - context.getUiMessaging().replyUsage(); - return; - } - String value = context.getArg(1); - if (field.getType() == boolean.class) { - boolean booleanValue = Boolean.parseBoolean(value); - value = String.valueOf(booleanValue); - field.setBoolean(context.getCoreSettings(), booleanValue); - } else if (field.getType() == String.class) { - field.set(context.getCoreSettings(), value); - } else { - return; - } - context.getTypedMessaging().replySuccess(context.i18n("commands.settings.setting_set", field.getName(), value)); - } catch (IllegalAccessException e) { - context.getTypedMessaging().replyException(context.i18n("commands.settings.cannot_access"), e); - } - } else { - context.getTypedMessaging().replyDanger(context.i18n("commands.settings.cannot_find_field")); - } - } else { - context.getUiMessaging().replyUsage(); - } - } - - @Override - public String command() { - return "settings"; - } - - @Override - public CascadePermission permission() { - return CascadePermission.of("settings", false, Permission.MANAGE_SERVER); - } - - @Override - public Set subCommands() { - return Set.of(new SettingsListSubCommand(settingsClasses)); - } - - @Override - public Module module() { - return Module.MANAGEMENT; - } - - // This is theoretically safe because we will always create the values field to match this - @SuppressWarnings("unchecked") - static Map getSettingsFromClass(Class classForScanning) { - try { - Field values = classForScanning.getField("VALUES"); - values.setAccessible(true); - if (values.getType().isAssignableFrom(Map.class)) { - return (Map) values.get(null); - } - } catch (NoSuchFieldException | IllegalAccessException ignored) { - // If we can't get the values field, we'll loop through manually - } - Map settings = new HashMap<>(); - Arrays.stream(classForScanning.getFields()) - .filter(field -> field.getAnnotation(Setting.class) != null) - .forEach(setting -> settings.put(setting.getName(), setting)); - return settings; - } - - private static Map getAllSettings(List> settingClasses) { - return settingClasses.stream() - .map(SettingsCommand::getSettingsFromClass) - .flatMap(map -> map.entrySet().stream()) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - } - -} From bf2246408d686bc45150d37ea0b029267a6e77b8 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 9 Jun 2020 20:24:44 +0100 Subject: [PATCH 047/206] Make sendModlogEvent functional, don't fuck it up --- .../management/ModuleDisableSubCommand.java | 2 +- .../management/ModuleEnableSubCommand.java | 2 +- .../management/TagCreateSubCommand.java | 2 +- .../management/TagDeleteSubCommand.java | 2 +- .../management/TagEditSubCommand.java | 2 +- .../GroupPermissionAddSubCommand.java | 2 +- .../GroupPermissionCreateSubCommand.java | 4 +- .../GroupPermissionDeleteSubCommand.java | 2 +- .../GroupPermissionLinkRoleSubCommand.java | 2 +- .../GroupPermissionRemoveSubCommand.java | 2 +- .../UserPermissionAddSubCommand.java | 2 +- .../UserPermissionGroupSubCommand.java | 4 +- .../UserPermissionRemoveSubCommand.java | 2 +- .../commands/music/QueueSaveSubCommand.java | 2 +- .../cascadebot/events/CommandListener.java | 2 +- .../events/ModlogEventListener.java | 41 ++++++++++--------- .../cascadebot/data/objects/GuildData.kt | 2 +- .../data/objects/GuildSettingsModeration.kt | 12 +----- 18 files changed, 40 insertions(+), 49 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleDisableSubCommand.java index 15ab7b428..61cddf544 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleDisableSubCommand.java @@ -39,7 +39,7 @@ public void onCommand(Member sender, CommandContext context) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new LanguageEmbedField(true, "modlog.module.enabled", "modlog.general.variable", "false")); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), module, embedFieldList); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { // If module was already disabled context.getTypedMessaging().replyInfo(context.i18n("commands.module.disable.already_disabled", module.toString())); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleEnableSubCommand.java index 28f2f4aec..52a9a8f80 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/ModuleEnableSubCommand.java @@ -39,7 +39,7 @@ public void onCommand(Member sender, CommandContext context) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new LanguageEmbedField(true, "modlog.module.enabled", "modlog.general.variable", "true")); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), module, embedFieldList); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { // If the module was enabled context.getTypedMessaging().replyInfo(context.i18n("commands.module.enable.already_enabled", module.toString())); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/TagCreateSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/TagCreateSubCommand.java index d59ad802a..a44ea5150 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/TagCreateSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/TagCreateSubCommand.java @@ -49,7 +49,7 @@ public void onCommand(Member sender, CommandContext context) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new LanguageEmbedField(false, "modlog.tag.content", "modlog.general.variable", tag.getContent())); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, embedFieldList); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/TagDeleteSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/TagDeleteSubCommand.java index 7e6f651ea..b6e38d114 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/TagDeleteSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/TagDeleteSubCommand.java @@ -33,7 +33,7 @@ public void onCommand(Member sender, CommandContext context) { context.getTypedMessaging().replySuccess(context.i18n("commands.tag.delete.successfully_deleted_tag")); ModlogEvent event = ModlogEvent.CASCADE_TAG_DELETED; ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, new ArrayList<>()); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyDanger(context.i18n("commands.tag.delete.tag_doesnt_exist", tagName)); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/TagEditSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/TagEditSubCommand.java index 98f3351ee..fce267779 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/TagEditSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/TagEditSubCommand.java @@ -41,7 +41,7 @@ public void onCommand(Member sender, CommandContext context) { embedFieldList.add(new LanguageEmbedField(false, "modlog.tag.old_content", "modlog.general.variable", oldContent)); embedFieldList.add(new LanguageEmbedField(false, "modlog.tag.new_content", "modlog.general.variable", tag.getContent())); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, embedFieldList); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java index 4cbb0838d..685c24801 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java @@ -38,7 +38,7 @@ public void onCommand(Member sender, CommandContext context) { embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_added", "modlog.general.variable", context.getArg(1))); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD; ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.add.fail", context.getArg(1), group.getName() + "(" + group.getId() + ")")); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java index b47800a80..b1db46b74 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java @@ -13,10 +13,8 @@ import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.objects.Group; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import java.util.ArrayList; -import java.util.List; public class GroupPermissionCreateSubCommand extends SubCommand { @@ -31,7 +29,7 @@ public void onCommand(Member sender, CommandContext context) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.create.success", context.getArg(0), group.getId())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_CREATED; ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, new ArrayList<>()); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java index df6dd6de8..d45c34981 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java @@ -26,7 +26,7 @@ public void onCommand(Member sender, CommandContext context) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.delete.success", group.getName(), group.getId())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_DELETED; ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, new ArrayList<>()); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { // Throwing an exception here because this *should* never happen throw new IllegalStateException("Couldn't delete group!"); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java index c34e2854c..3965583cc 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java @@ -42,7 +42,7 @@ public void onCommand(Member sender, CommandContext context) { embedFieldList.add(new LanguageEmbedField(false, "modlog.cascade_permissions.linked_role", "modlog.general.variable", role.getAsMention())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_LINK; ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.link.fail", group.getName(), role.getName())); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java index b36d3c415..084106190 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java @@ -39,7 +39,7 @@ public void onCommand(Member sender, CommandContext context) { embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_removed", "modlog.general.variable", context.getArg(1))); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE; ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.remove.fail", context.getArg(1), group.getName() + "(" + group.getId() + ")")); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java index c5e380e99..e68975ad1 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java @@ -47,7 +47,7 @@ public void onCommand(Member sender, CommandContext context) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_added", "modlog.general.variable", context.getArg(1))); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.add.fail", context.getArg(1), member.getUser().getAsTag())); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java index 11f3e105e..82dc85a0d 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java @@ -49,7 +49,7 @@ public void onCommand(Member sender, CommandContext context) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.group_added", "modlog.general.variable", group.getName() + "(" + group.getId() + ")")); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.group.put.fail", member.getUser().getAsTag(), group.getName())); } @@ -60,7 +60,7 @@ public void onCommand(Member sender, CommandContext context) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.group_removed", "modlog.general.variable", group.getName() + "(" + group.getId() + ")")); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.group.remove.fail", member.getUser().getAsTag(), group.getName())); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java index 1eb10780a..4cde63f87 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java @@ -42,7 +42,7 @@ public void onCommand(Member sender, CommandContext context) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_removed", "modlog.general.variable", context.getArg(1))); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.remove.fail", context.getArg(1), member.getUser().getAsTag())); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/music/QueueSaveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/music/QueueSaveSubCommand.java index 39a70c96e..f930d3045 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/music/QueueSaveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/music/QueueSaveSubCommand.java @@ -77,7 +77,7 @@ public void execute() { context.getTypedMessaging().replySuccess(context.i18n("commands.queue.save.saved_playlist", context.getArg(0), lambdaScope.name().toLowerCase())); ModlogEvent event = ModlogEvent.CASCADE_PLAYLIST_CREATED; ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), result.getPlaylist(), new ArrayList<>()); - context.getData().getModeration().sendModlogEvent(eventStore); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); break; } } diff --git a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java index 78fbd9834..b7a492e75 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java @@ -123,7 +123,7 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { } embedFieldList.add(new LanguageEmbedField(true, "modlog.command.args", "modlog.general.variable", stringBuilder.toString())); ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, event.getAuthor(),cmd, embedFieldList); - guildData.getModeration().sendModlogEvent(eventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); } } } diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 655fd6bb5..cc78f3d7e 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -79,6 +79,7 @@ import net.dv8tion.jda.api.events.guild.update.GuildUpdateSystemChannelEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateVanityCodeEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateVerificationLevelEvent; +import net.dv8tion.jda.api.events.guild.voice.GenericGuildVoiceEvent; import net.dv8tion.jda.api.events.guild.voice.GuildVoiceDeafenEvent; import net.dv8tion.jda.api.events.guild.voice.GuildVoiceGuildDeafenEvent; import net.dv8tion.jda.api.events.guild.voice.GuildVoiceGuildMuteEvent; @@ -175,7 +176,7 @@ public void onGenericEmote(GenericEmoteEvent event) { return; } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, user, emote, embedFieldList); - guildData.getModeration().sendModlogEvent(eventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }); } @@ -237,7 +238,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { return; } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); - guildData.getModeration().sendModlogEvent(eventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }); } @@ -262,7 +263,7 @@ public void onGuildBan(GuildBanEvent event) { CascadeBot.LOGGER.warn("Modlog: Failed to find ban entry"); } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); - guildData.getModeration().sendModlogEvent(eventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }); } @@ -281,7 +282,7 @@ public void onGuildUnban(GuildUnbanEvent event) { CascadeBot.LOGGER.warn("Modlog: Failed to find unban entry"); } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); - guildData.getModeration().sendModlogEvent(eventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }); } //endregion @@ -330,10 +331,10 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { } if (message.getUserMentions().size() > 0 || message.getRoleMentions().size() > 0) { ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.GUILD_MESSAGE_DELETED_MENTION, responsible, affected, embedFieldList); - guildData.getModeration().sendModlogEvent(eventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); } ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.GUILD_MESSAGE_DELETED, responsible, affected, embedFieldList); - guildData.getModeration().sendModlogEvent(eventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }); } @@ -366,7 +367,7 @@ public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { embedFieldList.add(newEmbedField); ModlogEvent modlogEvent = ModlogEvent.GUILD_MESSAGE_UPDATED; ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, null, affected, embedFieldList); - guildData.getModeration().sendModlogEvent(eventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); } private SerializableMessage getMessageFromString(long id, String messageString) { @@ -530,7 +531,7 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { return; } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); - guildData.getModeration().sendModlogEvent(eventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }); } @@ -573,7 +574,7 @@ public void onGuildVoiceUpdate(GuildVoiceUpdateEvent event) { return; } ModlogEventStore eventStore = new ModlogEventStore(action, null, affected, embedFieldList); - guildData.getModeration().sendModlogEvent(eventStore); + guildData.getModeration().sendModlogEvent(((GenericGuildVoiceEvent) event).getGuild().getIdLong(), eventStore); } //region Channels @@ -633,7 +634,7 @@ public void onGenericTextChannel(GenericTextChannelEvent event) { return; } ModlogEventStore eventStore = new ModlogEventStore(trigger, responsible, event.getChannel(), embedFieldList); - guildData.getModeration().sendModlogEvent(eventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }); } @@ -673,7 +674,7 @@ public void onGenericVoiceChannel(GenericVoiceChannelEvent event) { return; } ModlogEventStore eventStore = new ModlogEventStore(trigger, responsible, event.getChannel(), embedFieldList); - guildData.getModeration().sendModlogEvent(eventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }); } @@ -750,7 +751,7 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { } embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + event.getChannelType().name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, event.getChannel(), embedFieldList); - guildData.getModeration().sendModlogEvent(modlogEventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventStore); }); } @@ -772,7 +773,7 @@ private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChann } embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); - guildData.getModeration().sendModlogEvent(modlogEventStore); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }); } @@ -791,7 +792,7 @@ private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChann } embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); - guildData.getModeration().sendModlogEvent(modlogEventStore); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }); } @@ -811,7 +812,7 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable", oldName)); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); - guildData.getModeration().sendModlogEvent(modlogEventStore); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }); } @@ -832,7 +833,7 @@ private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, in embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_pos", "modlog.general.variable", String.valueOf(oldPos))); embedFieldList.add(new LanguageEmbedField(true, "modlog.general.new_pos", "modlog.general.variable", String.valueOf(channel.getPosition()))); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); - guildData.getModeration().sendModlogEvent(modlogEventStore); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }); } @@ -853,7 +854,7 @@ public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Categ embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_parent", "modlog.general.variable", oldParent.getName())); embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.new_parent", "modlog.general.variable", newParent.getName())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); - guildData.getModeration().sendModlogEvent(modlogEventStore); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }); } //endregion @@ -910,7 +911,7 @@ public void onGenericRole(GenericRoleEvent event) { return; } ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); - guildData.getModeration().sendModlogEvent(modlogEventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventStore); }); } @@ -922,7 +923,7 @@ public void onUserUpdateName(UserUpdateNameEvent event) { ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_NAME_UPDATED, event.getUser(), event.getUser(), embedFieldList); for (Guild guild : CascadeBot.INS.getClient().getMutualGuilds(event.getUser())) { GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guildData.getModeration().sendModlogEvent(modlogEventStore); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); } } @@ -932,7 +933,7 @@ public void onUserUpdateDiscriminator(UserUpdateDiscriminatorEvent event) { ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_DISCRIMINATOR_UPDATED, event.getUser(), event.getUser(), embedFieldList); for (Guild guild : CascadeBot.INS.getClient().getMutualGuilds(event.getUser())) { GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guildData.getModeration().sendModlogEvent(modlogEventStore); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); } } //endregion diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index c6d777842..b24a27390 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -33,7 +33,7 @@ class GuildData(@field:Id val guildId: Long) { //region Guild data containers val core = GuildSettingsCore() val useful = GuildSettingsUseful() - val moderation = GuildSettingsModeration(guildId) + val moderation = GuildSettingsModeration() val management = GuildSettingsManagement() val music = GuildSettingsMusic() //endregion diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 44197a5e7..f07d2eb35 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -35,22 +35,14 @@ import java.util.function.Consumer @SettingsContainer(module = Module.MODERATION) class GuildSettingsModeration { - var guildId: Long = 0 - var modlogChannelNum: Int = 1; - constructor(guildId: Long) { - this.guildId = guildId; - } - - constructor() - @Setting - public val purgePinnedMessages: Boolean = false + val purgePinnedMessages: Boolean = false private val modlogEvents: MutableMap = HashMap() - fun sendModlogEvent(modlogEventStore: ModlogEventStore) { + fun sendModlogEvent(guildId: Long, modlogEventStore: ModlogEventStore) { val eventsInfo: List = getEventInfoForEvent(modlogEventStore.trigger) for (eventInfo in eventsInfo) { eventInfo.sendEvent(GuildDataManager.getGuildData(guildId), modlogEventStore); From e76384796fbfcf6fcdebce1074c88d094fcc6cf7 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 9 Jun 2020 20:24:53 +0100 Subject: [PATCH 048/206] RYAN --- .../org/cascadebot/cascadebot/utils/LanguageEmbedField.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt index f8c35779a..958295203 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt @@ -37,8 +37,8 @@ class LanguageEmbedField { fun getLocalizedEmbedField(locale: Locale): WebhookEmbed.EmbedField { return WebhookEmbed.EmbedField(inline, - Language.i18n(locale, titleLanguagePath, titleLanguageObjects), - Language.i18n(locale, valueLanguagePath, valueLanguageObjects)) + Language.i18n(locale, titleLanguagePath, titleLanguageObjects.joinToString(" ")), + Language.i18n(locale, valueLanguagePath, valueLanguageObjects.joinToString(" "))) } } \ No newline at end of file From fb6b939792c7ba6f93c74cf11b9dfb622c78e94a Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 9 Jun 2020 20:27:40 +0100 Subject: [PATCH 049/206] Don't question it --- .../org/cascadebot/cascadebot/utils/LanguageEmbedField.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt index 958295203..46b1a1ec8 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt @@ -1,6 +1,7 @@ package org.cascadebot.cascadebot.utils import club.minnced.discord.webhook.send.WebhookEmbed +import org.cascadebot.cascadebot.UnicodeConstants import org.cascadebot.cascadebot.data.language.Language import org.cascadebot.cascadebot.data.language.Locale @@ -37,8 +38,8 @@ class LanguageEmbedField { fun getLocalizedEmbedField(locale: Locale): WebhookEmbed.EmbedField { return WebhookEmbed.EmbedField(inline, - Language.i18n(locale, titleLanguagePath, titleLanguageObjects.joinToString(" ")), - Language.i18n(locale, valueLanguagePath, valueLanguageObjects.joinToString(" "))) + Language.i18n(locale, titleLanguagePath, titleLanguageObjects.joinToString(" ") + UnicodeConstants.ZERO_WIDTH_SPACE), + Language.i18n(locale, valueLanguagePath, valueLanguageObjects.joinToString(" ") + UnicodeConstants.ZERO_WIDTH_SPACE)) } } \ No newline at end of file From 32dc9be950acd758028a087d8fbee57a7877bfd4 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 9 Jun 2020 21:22:17 +0100 Subject: [PATCH 050/206] Fix varargs --- .../org/cascadebot/cascadebot/utils/LanguageEmbedField.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt index 46b1a1ec8..b139be1b6 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt @@ -38,8 +38,8 @@ class LanguageEmbedField { fun getLocalizedEmbedField(locale: Locale): WebhookEmbed.EmbedField { return WebhookEmbed.EmbedField(inline, - Language.i18n(locale, titleLanguagePath, titleLanguageObjects.joinToString(" ") + UnicodeConstants.ZERO_WIDTH_SPACE), - Language.i18n(locale, valueLanguagePath, valueLanguageObjects.joinToString(" ") + UnicodeConstants.ZERO_WIDTH_SPACE)) + Language.i18n(locale, titleLanguagePath, *titleLanguageObjects.toTypedArray()), + Language.i18n(locale, valueLanguagePath, *valueLanguageObjects.toTypedArray())) } } \ No newline at end of file From 97c78bc7275d05466e90dee6cbbc5f9730fa9b7d Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Tue, 9 Jun 2020 15:28:32 -0500 Subject: [PATCH 051/206] Minor fixes Also re-add modlog to settings --- .../cascadebot/cascadebot/events/CommandListener.java | 10 ++++++---- .../cascadebot/commands/management/SettingsCommand.kt | 8 ++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java index b7a492e75..8da72b6fd 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java @@ -117,11 +117,13 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { MainCommand cmd = CascadeBot.INS.getCommandManager().getCommand(trigger, guildData); if (modlogEvent != null && cmd != null) { List embedFieldList = new ArrayList<>(); - StringBuilder stringBuilder = new StringBuilder(); - for (String arg : args) { - stringBuilder.append(arg).append(' '); + if (args.length > 0) { + StringBuilder stringBuilder = new StringBuilder(); + for (String arg : args) { + stringBuilder.append(arg).append(' '); + } + embedFieldList.add(new LanguageEmbedField(true, "modlog.command.args", "modlog.general.variable", stringBuilder.toString())); } - embedFieldList.add(new LanguageEmbedField(true, "modlog.command.args", "modlog.general.variable", stringBuilder.toString())); ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, event.getAuthor(),cmd, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt index efa283644..b635ba356 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt @@ -18,9 +18,12 @@ import org.cascadebot.cascadebot.data.objects.GuildSettingsManagement import org.cascadebot.cascadebot.data.objects.GuildSettingsModeration import org.cascadebot.cascadebot.data.objects.GuildSettingsMusic import org.cascadebot.cascadebot.data.objects.GuildSettingsUseful +import org.cascadebot.cascadebot.data.objects.ModlogEventStore import org.cascadebot.cascadebot.data.objects.Setting import org.cascadebot.cascadebot.data.objects.SettingsContainer +import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.permissions.CascadePermission +import org.cascadebot.cascadebot.utils.LanguageEmbedField import org.cascadebot.cascadebot.utils.ReflectionUtils import java.io.IOException import java.lang.reflect.Field @@ -104,6 +107,7 @@ class SettingsCommand : MainCommand() { context.uiMessaging.replyUsage() return } + val oldValue: String = field.get(settingsContainer).toString() var value = context.getArg(1) when (field.type) { Boolean::class.javaPrimitiveType -> { @@ -119,6 +123,10 @@ class SettingsCommand : MainCommand() { } } context.typedMessaging.replySuccess(context.i18n("commands.settings.setting_set", field.name, value)) + val embedFields: MutableList = ArrayList(); + embedFields.add(LanguageEmbedField(true, "modlog.setting.old", "modlog.general.variable", oldValue)) + embedFields.add(LanguageEmbedField(true, "modlog.setting.new", "modlog.general.variable", value)) + context.data.moderation.sendModlogEvent(context.guild.idLong, ModlogEventStore(ModlogEvent.CASCADE_SETTINGS_UPDATED, sender.user, field, ArrayList())) } catch (e: IllegalAccessException) { context.typedMessaging.replyException(context.i18n("commands.settings.cannot_access"), e) } From 1a0fb24650e93f6074d7ea8d332eda9c6f7bda7c Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Wed, 10 Jun 2020 11:12:16 -0500 Subject: [PATCH 052/206] listen to the correct event --- .../events/ModlogEventListener.java | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index cc78f3d7e..61f2187f3 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -114,6 +114,7 @@ import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.cascadebot.utils.SerializableMessage; +import javax.annotation.Nonnull; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; @@ -535,18 +536,11 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { }); } - public void onGuildVoiceUpdate(GuildVoiceUpdateEvent event) { - User affected = event.getEntity().getUser(); + public void onGenericGuildVoice(GenericGuildVoiceEvent event) { + User affected = event.getMember().getUser(); List embedFieldList = new ArrayList<>(); ModlogEvent action; - Guild guild; - if (event.getChannelLeft() != null) { - guild = event.getChannelLeft().getGuild(); - } else if (event.getChannelJoined() != null) { - guild = event.getChannelJoined().getGuild(); - } else { - return; - } + Guild guild = event.getGuild(); GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); if (event instanceof GuildVoiceDeafenEvent) { embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceDeafenEvent) event).isDeafened()))); @@ -561,20 +555,20 @@ public void onGuildVoiceUpdate(GuildVoiceUpdateEvent event) { embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceGuildMuteEvent) event).isGuildMuted()))); action = ModlogEvent.VOICE_SERVER_MUTE; } else if (event instanceof GuildVoiceJoinEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.join", "modlog.general.variable", event.getChannelJoined().getName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.join", "modlog.general.variable", ((GuildVoiceJoinEvent) event).getChannelJoined().getName())); action = ModlogEvent.VOICE_JOIN; } else if (event instanceof GuildVoiceLeaveEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.left", "modlog.general.variable", event.getChannelLeft().getName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.left", "modlog.general.variable", ((GuildVoiceLeaveEvent) event).getChannelLeft().getName())); action = ModlogEvent.VOICE_LEAVE; } else if (event instanceof GuildVoiceMoveEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.left", "modlog.general.variable", event.getChannelLeft().getName())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.join", "modlog.general.variable", event.getChannelJoined().getName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.left", "modlog.general.variable", ((GuildVoiceMoveEvent) event).getChannelLeft().getName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.join", "modlog.general.variable", ((GuildVoiceMoveEvent) event).getChannelJoined().getName())); action = ModlogEvent.VOICE_MOVE; } else { return; } ModlogEventStore eventStore = new ModlogEventStore(action, null, affected, embedFieldList); - guildData.getModeration().sendModlogEvent(((GenericGuildVoiceEvent) event).getGuild().getIdLong(), eventStore); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); } //region Channels From 4a8e55513bcbc675250afb36ff3ea91be54b9100 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Wed, 10 Jun 2020 17:57:48 +0100 Subject: [PATCH 053/206] Fixed splitter? --- .../utils/pagination/PageUtils.java | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/utils/pagination/PageUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/pagination/PageUtils.java index a8ae28651..7cfa5b3a1 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/pagination/PageUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/pagination/PageUtils.java @@ -82,26 +82,18 @@ public static List splitString(String string, int length, char c) { Checks.check(length <= 1800, "length"); Checks.notEmpty(string, "string"); - int amount = (int) ((double) string.length() / (double) length); + var strings = new ArrayList(); - List strings = new ArrayList<>(); - String toAdd = ""; + int start = 0; - for (int i = 0; i <= amount; i++) { - int start = length * i; - int end = Math.min(start + (length - 1), string.length()); - - String temp = toAdd + string.substring(start, end == string.length() ? end : end - toAdd.length()); - int last; - if (end != string.length()) { - last = temp.lastIndexOf(c); - - toAdd = temp.substring(last + 1); - } else { - last = temp.length(); + while (start < string.length()) { + int end = Math.min(start + length, string.length()); + String substring = string.substring(start, end); + if (substring.lastIndexOf(c) != -1 && end != string.length()) { + substring = substring.substring(0, substring.lastIndexOf(c) + 1); } - - strings.add(temp.substring(0, last)); + strings.add(substring); + start += substring.length(); } return strings; From ed3a48fb2d1b437046dc4ec2e30afe820a4742d2 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Wed, 10 Jun 2020 11:58:05 -0500 Subject: [PATCH 054/206] Audit log checking for voice --- .../events/ModlogEventListener.java | 70 +++++++++++-------- .../cascadebot/moderation/ModlogEvent.kt | 3 +- src/main/resources/lang/en-GB.json | 4 ++ 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 61f2187f3..d2c94f576 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -538,37 +538,49 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { public void onGenericGuildVoice(GenericGuildVoiceEvent event) { User affected = event.getMember().getUser(); - List embedFieldList = new ArrayList<>(); - ModlogEvent action; Guild guild = event.getGuild(); GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - if (event instanceof GuildVoiceDeafenEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceDeafenEvent) event).isDeafened()))); - action = ModlogEvent.VOICE_DEAFEN; - } else if (event instanceof GuildVoiceMuteEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceMuteEvent) event).isMuted()))); - action = ModlogEvent.VOICE_MUTE; - } else if (event instanceof GuildVoiceGuildDeafenEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()))); - action = ModlogEvent.VOICE_SERVER_DEAFEN; - } else if (event instanceof GuildVoiceGuildMuteEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceGuildMuteEvent) event).isGuildMuted()))); - action = ModlogEvent.VOICE_SERVER_MUTE; - } else if (event instanceof GuildVoiceJoinEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.join", "modlog.general.variable", ((GuildVoiceJoinEvent) event).getChannelJoined().getName())); - action = ModlogEvent.VOICE_JOIN; - } else if (event instanceof GuildVoiceLeaveEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.left", "modlog.general.variable", ((GuildVoiceLeaveEvent) event).getChannelLeft().getName())); - action = ModlogEvent.VOICE_LEAVE; - } else if (event instanceof GuildVoiceMoveEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.left", "modlog.general.variable", ((GuildVoiceMoveEvent) event).getChannelLeft().getName())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.join", "modlog.general.variable", ((GuildVoiceMoveEvent) event).getChannelJoined().getName())); - action = ModlogEvent.VOICE_MOVE; - } else { - return; - } - ModlogEventStore eventStore = new ModlogEventStore(action, null, affected, embedFieldList); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); + guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { + AuditLogEntry entry = auditLogEntries.get(0); + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); + List embedFieldList = new ArrayList<>(); + ModlogEvent action; + if (event instanceof GuildVoiceDeafenEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceDeafenEvent) event).isDeafened()))); + action = ModlogEvent.VOICE_DEAFEN; + } else if (event instanceof GuildVoiceMuteEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceMuteEvent) event).isMuted()))); + action = ModlogEvent.VOICE_MUTE; + } else if (event instanceof GuildVoiceGuildDeafenEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()))); + action = ModlogEvent.VOICE_SERVER_DEAFEN; + } else if (event instanceof GuildVoiceGuildMuteEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceGuildMuteEvent) event).isGuildMuted()))); + action = ModlogEvent.VOICE_SERVER_MUTE; + } else if (event instanceof GuildVoiceJoinEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.join", "modlog.general.variable", ((GuildVoiceJoinEvent) event).getChannelJoined().getName())); + action = ModlogEvent.VOICE_JOIN; + } else if (event instanceof GuildVoiceLeaveEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.left", "modlog.general.variable", ((GuildVoiceLeaveEvent) event).getChannelLeft().getName())); + if (entry.getType().equals(ActionType.MEMBER_VOICE_MOVE) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getMember().getIdLong()) { + action = ModlogEvent.VOICE_DISCONNECT; + } else { + action = ModlogEvent.VOICE_LEAVE; + } + } else if (event instanceof GuildVoiceMoveEvent) { + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.left", "modlog.general.variable", ((GuildVoiceMoveEvent) event).getChannelLeft().getName())); + embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.join", "modlog.general.variable", ((GuildVoiceMoveEvent) event).getChannelJoined().getName())); + if (entry.getType().equals(ActionType.MEMBER_VOICE_KICK) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getMember().getIdLong()) { + action = ModlogEvent.VOICE_FORCE_MOVE; + } else { + action = ModlogEvent.VOICE_MOVE; + } + } else { + return; + } + ModlogEventStore eventStore = new ModlogEventStore(action, null, affected, embedFieldList); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); + }); } //region Channels diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 176bde42e..5bb0ad51c 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -54,7 +54,8 @@ enum class ModlogEvent(messageType: MessageType, vararg categories: Category) { VOICE_SERVER_MUTE(MessageType.WARNING, Category.VOICE, Category.MODERATION), VOICE_JOIN(MessageType.INFO, Category.VOICE), VOICE_LEAVE(MessageType.INFO, Category.VOICE), - VOICE_MOVE(MessageType.WARNING, Category.VOICE), + VOICE_MOVE(MessageType.INFO, Category.VOICE), + VOICE_FORCE_MOVE(MessageType.WARNING, Category.VOICE, Category.MODERATION), VOICE_DISCONNECT(MessageType.WARNING, Category.VOICE, Category.MODERATION), ROLE_CREATED(MessageType.WARNING, Category.ROLE), diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 443d6717c..c5949e577 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1291,6 +1291,10 @@ "guild_message_deleted_mention": { "select": "guild_message_deleted_mention", "display": "Guild message deleted with mention" + }, + "voice_force_move": { + "select": "voice_force_move", + "display": "Voice Force Move" } } }, From 18338f31743413013cb46db8e90058f9da148d96 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Wed, 10 Jun 2020 12:01:58 -0500 Subject: [PATCH 055/206] register weight pair --- .../cascadebot/cascadebot/data/database/DatabaseManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java b/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java index d244e3964..a3ae73b0d 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java @@ -43,7 +43,7 @@ public class DatabaseManager { "org.cascadebot.cascadebot.utils.lists", "org.cascadebot.cascadebot.scheduler", "org.cascadebot.shared" - ).register(LanguageEmbedField.class).build()) + ).register(LanguageEmbedField.class).register(WeightPair.class).build()) ); @Getter From 44692a81e887c1d42bb5b862b7eafdae88d6f4e2 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 13 Jun 2020 08:44:38 -0500 Subject: [PATCH 056/206] Fix merge --- .../cascadebot/moderation/ModerationManager.java | 2 +- .../cascadebot/data/objects/GuildSettingsModeration.kt | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java index 470831cd8..4674d260e 100644 --- a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java +++ b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java @@ -77,7 +77,7 @@ private boolean runChecks(ModAction action, User target, Member submitter, Comma } else if (target.equals(context.getSelfUser())) { context.getTypedMessaging().replyWarning(context.i18n("moderation_manager.cannot_action_bot", action.getName(context.getLocale()))); return false; - } else if (context.getData().getModeration().isRespectBanOrKickHierarchy() && !submitter.canInteract(context.getGuild().getMember(target))) { + } else if (context.getData().getModeration().getRespectBanOrKickHierarchy() && !submitter.canInteract(context.getGuild().getMember(target))) { context.getTypedMessaging().replyWarning(context.i18n("moderation_manager.user_cannot_action_superior", action.getName(context.getLocale()), target.getName())); return false; } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index f07d2eb35..bd5ecf235 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -11,7 +11,6 @@ import de.bild.codec.annotations.Transient import net.dv8tion.jda.api.entities.Emote import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.entities.GuildChannel -import net.dv8tion.jda.api.entities.ISnowflake import net.dv8tion.jda.api.entities.Icon import net.dv8tion.jda.api.entities.Role import net.dv8tion.jda.api.entities.TextChannel @@ -20,7 +19,6 @@ import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.commandmeta.MainCommand import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.database.DebugLogCallback -import org.cascadebot.cascadebot.data.language.Language import org.cascadebot.cascadebot.data.language.Language.i18n import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.moderation.ModlogEvent @@ -40,6 +38,13 @@ class GuildSettingsModeration { @Setting val purgePinnedMessages: Boolean = false + @Setting + private val respectBanOrKickHierarchy = true + + fun getRespectBanOrKickHierarchy(): Boolean { + return respectBanOrKickHierarchy + } + private val modlogEvents: MutableMap = HashMap() fun sendModlogEvent(guildId: Long, modlogEventStore: ModlogEventStore) { From 798dc79f97517fac3d52cfd1c93d4c1d25275398 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 15 Jun 2020 12:06:06 -0500 Subject: [PATCH 057/206] Start moving modlog to new system --- .../module/ModuleDisableSubCommand.java | 7 +- .../module/ModuleEnableSubCommand.java | 7 +- .../GroupPermissionAddSubCommand.java | 7 +- .../GroupPermissionLinkRoleSubCommand.java | 7 +- .../GroupPermissionRemoveSubCommand.java | 7 +- .../UserPermissionAddSubCommand.java | 7 +- .../UserPermissionGroupSubCommand.java | 11 +- .../UserPermissionRemoveSubCommand.java | 7 +- .../management/tag/TagCreateSubCommand.java | 7 +- .../management/tag/TagDeleteSubCommand.java | 1 - .../management/tag/TagEditSubCommand.java | 9 +- .../data/database/DatabaseManager.java | 8 +- .../cascadebot/events/CommandListener.java | 7 +- .../events/ModlogEventListener.java | 427 ++++++++---------- .../ModlogChannelMoveCollectorRunnable.java | 84 ++++ .../ModlogMemberRoleCollectorRunnable.java | 10 + .../cascadebot/utils/ModlogUtils.java | 46 ++ .../commands/management/SettingsCommand.kt | 9 +- .../data/objects/GuildSettingsModeration.kt | 4 +- .../data/objects/ModlogEventStore.kt | 6 +- .../cascadebot/moderation/ModlogEmbedPart.kt | 81 ++++ .../cascadebot/moderation/ModlogEvent.kt | 234 +++++----- 22 files changed, 605 insertions(+), 388 deletions(-) create mode 100644 src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java create mode 100644 src/main/java/org/cascadebot/cascadebot/runnables/ModlogMemberRoleCollectorRunnable.java create mode 100644 src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java index 3e44d271c..9a16427b3 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java @@ -12,9 +12,10 @@ import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import java.util.ArrayList; import java.util.List; @@ -36,8 +37,8 @@ public void onCommand(Member sender, CommandContext context) { // If module wasn't already disabled context.getTypedMessaging().replySuccess(context.i18n("commands.module.disable.disabled", module.toString())); ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(true, "modlog.module.enabled", "modlog.general.variable", "false")); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(true, "modlog.module.enabled", "modlog.general.variable", "false")); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), module, embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java index 40bde7f1b..5f19a20df 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java @@ -12,9 +12,10 @@ import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import java.util.ArrayList; import java.util.List; @@ -36,8 +37,8 @@ public void onCommand(Member sender, CommandContext context) { // If the module wasn't enabled context.getTypedMessaging().replySuccess(context.i18n("commands.module.enable.enabled", module.toString())); ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(true, "modlog.module.enabled", "modlog.general.variable", "true")); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(true, "modlog.module.enabled", "modlog.general.variable", "true")); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), module, embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java index 685c24801..c627cbb96 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java @@ -10,9 +10,10 @@ import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; import java.util.ArrayList; @@ -34,8 +35,8 @@ public void onCommand(Member sender, CommandContext context) { PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { if (group.addPermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.add.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_added", "modlog.general.variable", context.getArg(1))); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(true, "modlog.cascade_permissions.permission_added", "modlog.general.variable", context.getArg(1))); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD; ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java index 3965583cc..62eb46693 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java @@ -11,10 +11,11 @@ import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.DiscordUtils; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; import java.util.ArrayList; @@ -38,8 +39,8 @@ public void onCommand(Member sender, CommandContext context) { PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { if (group.linkRole(role.getIdLong())) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.link.success", group.getName(), role.getName())); - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(false, "modlog.cascade_permissions.linked_role", "modlog.general.variable", role.getAsMention())); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(false, "modlog.cascade_permissions.linked_role", "modlog.general.variable", role.getAsMention())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_LINK; ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java index 084106190..68c3c7e62 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java @@ -10,9 +10,10 @@ import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; import java.util.ArrayList; @@ -35,8 +36,8 @@ public void onCommand(Member sender, CommandContext context) { PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { if (group.removePermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.remove.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_removed", "modlog.general.variable", context.getArg(1))); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(true, "modlog.cascade_permissions.permission_removed", "modlog.general.variable", context.getArg(1))); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE; ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java index e68975ad1..343f7b3e3 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java @@ -10,11 +10,12 @@ import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.objects.User; import org.cascadebot.cascadebot.utils.DiscordUtils; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import java.util.ArrayList; import java.util.List; @@ -44,8 +45,8 @@ public void onCommand(Member sender, CommandContext context) { if (user.addPermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.add.success", context.getArg(1), member.getUser().getAsTag())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_PERMISSION_ADD; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_added", "modlog.general.variable", context.getArg(1))); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(true, "modlog.cascade_permissions.permission_added", "modlog.general.variable", context.getArg(1))); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java index 82dc85a0d..932ab969b 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java @@ -10,11 +10,12 @@ import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.objects.User; import org.cascadebot.cascadebot.utils.DiscordUtils; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; import java.util.ArrayList; @@ -46,8 +47,8 @@ public void onCommand(Member sender, CommandContext context) { if (user.addGroup(group)) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.group.put.success", member.getUser().getAsTag(), group.getName())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_GROUP_ADD; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.group_added", "modlog.general.variable", group.getName() + "(" + group.getId() + ")")); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(true, "modlog.cascade_permissions.group_added", "modlog.general.variable", group.getName() + "(" + group.getId() + ")")); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { @@ -57,8 +58,8 @@ public void onCommand(Member sender, CommandContext context) { if (user.removeGroup(group)) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.group.remove.success", member.getUser().getAsTag(), group.getName())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_GROUP_REMOVE; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.group_removed", "modlog.general.variable", group.getName() + "(" + group.getId() + ")")); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(true, "modlog.cascade_permissions.group_removed", "modlog.general.variable", group.getName() + "(" + group.getId() + ")")); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java index 4cde63f87..d165969c6 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java @@ -10,11 +10,12 @@ import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.objects.User; import org.cascadebot.cascadebot.utils.DiscordUtils; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import java.util.ArrayList; import java.util.List; @@ -39,8 +40,8 @@ public void onCommand(Member sender, CommandContext context) { if (user.removePermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.remove.success", context.getArg(1), member.getUser().getAsTag())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(true, "modlog.cascade_permissions.permission_removed", "modlog.general.variable", context.getArg(1))); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(true, "modlog.cascade_permissions.permission_removed", "modlog.general.variable", context.getArg(1))); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java index 5045a093b..41cde8501 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java @@ -10,9 +10,10 @@ import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; import org.cascadebot.cascadebot.data.objects.Tag; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import java.util.ArrayList; import java.util.List; @@ -46,8 +47,8 @@ public void onCommand(Member sender, CommandContext context) { context.getData().getPermissionsManager().registerGuildPermission(tag.getInternalPermission()); context.getTypedMessaging().replySuccess(message); ModlogEvent event = ModlogEvent.CASCADE_TAG_CREATED; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(false, "modlog.tag.content", "modlog.general.variable", tag.getContent())); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.content", "modlog.general.variable", tag.getContent())); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java index 07057a0a5..031adcdb0 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java @@ -12,7 +12,6 @@ import org.cascadebot.cascadebot.data.objects.Tag; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java index ae65b5ce3..53d4a96d5 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java @@ -10,9 +10,10 @@ import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; import org.cascadebot.cascadebot.data.objects.Tag; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import java.util.ArrayList; import java.util.List; @@ -37,9 +38,9 @@ public void onCommand(Member sender, CommandContext context) { tag.setContent(context.getMessage(1)); context.getTypedMessaging().replySuccess(context.i18n("commands.tag.edit.successfully_edited_tag", tagName)); ModlogEvent event = ModlogEvent.CASCADE_TAG_UPDATED; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(false, "modlog.tag.old_content", "modlog.general.variable", oldContent)); - embedFieldList.add(new LanguageEmbedField(false, "modlog.tag.new_content", "modlog.general.variable", tag.getContent())); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.old_content", "modlog.general.variable", oldContent)); + embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.new_content", "modlog.general.variable", tag.getContent())); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java b/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java index a3ae73b0d..aeb6aadec 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java @@ -19,8 +19,11 @@ import org.bson.Document; import org.bson.codecs.configuration.CodecRegistries; import org.bson.codecs.configuration.CodecRegistry; +import org.cascadebot.cascadebot.moderation.ModlogEmbedDescription; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedFooter; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.utils.WeightPair; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,7 +46,8 @@ public class DatabaseManager { "org.cascadebot.cascadebot.utils.lists", "org.cascadebot.cascadebot.scheduler", "org.cascadebot.shared" - ).register(LanguageEmbedField.class).register(WeightPair.class).build()) + ).register(ModlogEmbedPart.class).register(ModlogEmbedField.class).register(ModlogEmbedDescription.class).register(ModlogEmbedFooter.class) + .register(WeightPair.class).build()) ); @Getter diff --git a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java index 8da72b6fd..cdb14947f 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java @@ -29,10 +29,11 @@ import org.cascadebot.cascadebot.messaging.Messaging; import org.cascadebot.cascadebot.messaging.MessagingObjects; import org.cascadebot.cascadebot.metrics.Metrics; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.utils.DiscordUtils; import org.cascadebot.cascadebot.utils.FormatUtils; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; import org.cascadebot.shared.Regex; import org.cascadebot.shared.utils.ThreadPoolExecutorLogged; import org.slf4j.MDC; @@ -116,13 +117,13 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { CascadeBot.clearCascadeMDC(); MainCommand cmd = CascadeBot.INS.getCommandManager().getCommand(trigger, guildData); if (modlogEvent != null && cmd != null) { - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); if (args.length > 0) { StringBuilder stringBuilder = new StringBuilder(); for (String arg : args) { stringBuilder.append(arg).append(' '); } - embedFieldList.add(new LanguageEmbedField(true, "modlog.command.args", "modlog.general.variable", stringBuilder.toString())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.command.args", "modlog.general.variable", stringBuilder.toString())); } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, event.getAuthor(),cmd, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index d2c94f576..f6ea11b42 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -87,7 +87,6 @@ import net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent; import net.dv8tion.jda.api.events.guild.voice.GuildVoiceMoveEvent; import net.dv8tion.jda.api.events.guild.voice.GuildVoiceMuteEvent; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceUpdateEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent; import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent; import net.dv8tion.jda.api.events.role.GenericRoleEvent; @@ -107,14 +106,17 @@ import org.cascadebot.cascadebot.data.managers.GuildDataManager; import org.cascadebot.cascadebot.data.objects.GuildData; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; +import org.cascadebot.cascadebot.runnables.ModlogChannelMoveCollectorRunnable; +import org.cascadebot.cascadebot.runnables.ModlogMemberRoleCollectorRunnable; import org.cascadebot.cascadebot.utils.Attachment; import org.cascadebot.cascadebot.utils.ColorUtils; import org.cascadebot.cascadebot.utils.CryptUtils; -import org.cascadebot.cascadebot.utils.LanguageEmbedField; +import org.cascadebot.cascadebot.utils.ModlogUtils; import org.cascadebot.cascadebot.utils.SerializableMessage; -import javax.annotation.Nonnull; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; @@ -129,27 +131,28 @@ import java.util.ArrayList; import java.util.Collection; import java.util.EnumSet; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; public class ModlogEventListener extends ListenerAdapter { - private final long auditTimeAllowed = 1000l; + private Map moveRunnableMap = new HashMap<>(); + private Map roleRunnableMap = new HashMap<>(); public void onGenericEmote(GenericEmoteEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); Emote emote = event.getEmote(); - event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); + ModlogUtils.getAuditLogFromType(event.getGuild(), event.getEmote().getIdLong(), auditLogEntry -> { User user = null; - if ((entry.getType().equals(ActionType.EMOTE_UPDATE) || entry.getType().equals(ActionType.EMOTE_CREATE) || entry.getType().equals(ActionType.EMOTE_DELETE)) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getEmote().getIdLong()) { - user = auditLogEntries.get(0).getUser(); + if (auditLogEntry != null) { + user = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find emote entry"); } - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent; if (event instanceof EmoteAddedEvent) { modlogEvent = ModlogEvent.EMOTE_CREATED; @@ -157,18 +160,18 @@ public void onGenericEmote(GenericEmoteEvent event) { modlogEvent = ModlogEvent.EMOTE_DELETED; } else if (event instanceof EmoteUpdateNameEvent) { modlogEvent = ModlogEvent.EMOTE_UPDATED_NAME; - LanguageEmbedField languageEmbedField = new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable"); - languageEmbedField.addValueObjects(((EmoteUpdateNameEvent) event).getOldName()); - embedFieldList.add(languageEmbedField); + ModlogEmbedField languageModlogEmbedField = new ModlogEmbedField(true, "modlog.general.old_name", "modlog.general.variable"); + languageModlogEmbedField.addValueObjects(((EmoteUpdateNameEvent) event).getOldName()); + embedFieldList.add(languageModlogEmbedField); } else if (event instanceof EmoteUpdateRolesEvent) { modlogEvent = ModlogEvent.EMOTE_UPDATED_ROLES; List oldRoles = ((EmoteUpdateRolesEvent) event).getOldRoles(); List newRoles = ((EmoteUpdateRolesEvent) event).getNewRoles(); ListChanges roleListChanges = new ListChanges<>(oldRoles, newRoles); - LanguageEmbedField addedRolesEmbed = new LanguageEmbedField(false, "modlog.general.added_roles", "modlog.general.variable"); + ModlogEmbedField addedRolesEmbed = new ModlogEmbedField(false, "modlog.general.added_roles", "modlog.general.variable"); addedRolesEmbed.addValueObjects(roleListChanges.getAdded().stream().map(role -> role.getName() + " (" + role.getId() + ")") .collect(Collectors.joining("\n"))); - LanguageEmbedField removedRolesEmbed = new LanguageEmbedField(false, "modlog.general.removed_roles", "modlog.general.variable"); + ModlogEmbedField removedRolesEmbed = new ModlogEmbedField(false, "modlog.general.removed_roles", "modlog.general.variable"); removedRolesEmbed.addValueObjects(roleListChanges.getRemoved().stream().map(role -> role.getName() + " (" + role.getId() + ")") .collect(Collectors.joining("\n"))); embedFieldList.add(addedRolesEmbed); @@ -178,59 +181,57 @@ public void onGenericEmote(GenericEmoteEvent event) { } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, user, emote, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }); + }, ActionType.EMOTE_CREATE, ActionType.EMOTE_DELETE, ActionType.EMOTE_UPDATE); } public void onGenericGuildMember(GenericGuildMemberEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); User user = event.getMember().getUser(); - event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + ModlogUtils.getAuditLogFromType(event.getGuild(), event.getUser().getIdLong(), auditLogEntry -> { + List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent; User responsible = null; if (event instanceof GuildMemberJoinEvent) { modlogEvent = ModlogEvent.GUILD_MEMBER_JOINED; } else if (event instanceof GuildMemberLeaveEvent) { - if (entry.getType().equals(ActionType.KICK) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getMember().getIdLong()) { - LanguageEmbedField respLanguageEmbedField = new LanguageEmbedField(true, "modlog.general.responsible", "modlog.general.variable"); - respLanguageEmbedField.addValueObjects(Objects.requireNonNull(entry.getUser()).getAsTag()); - embedFieldList.add(respLanguageEmbedField); - if (entry.getReason() != null) { - LanguageEmbedField reasonEmbedField = new LanguageEmbedField(false, "modlog.general.reason", "modlog.general.variable"); - respLanguageEmbedField.addValueObjects(entry.getReason()); + if (auditLogEntry != null) { + ModlogEmbedField respModlogEmbedField = new ModlogEmbedField(true, "modlog.general.responsible", "modlog.general.variable"); + respModlogEmbedField.addValueObjects(Objects.requireNonNull(auditLogEntry.getUser()).getAsTag()); + embedFieldList.add(respModlogEmbedField); + if (auditLogEntry.getReason() != null) { + ModlogEmbedField reasonEmbedField = new ModlogEmbedField(false, "modlog.general.reason", "modlog.general.variable"); + respModlogEmbedField.addValueObjects(auditLogEntry.getReason()); embedFieldList.add(reasonEmbedField); } modlogEvent = ModlogEvent.GUILD_MEMBER_KICKED; - } else { //TODO not assume leave if audit log entry for kick was not found. else { + } else { CascadeBot.LOGGER.warn("Modlog: Failed to find kick entry"); modlogEvent = ModlogEvent.GUILD_MEMBER_LEFT; } } else if (event instanceof GuildMemberRoleAddEvent) { - if (entry.getType().equals(ActionType.MEMBER_ROLE_UPDATE) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getMember().getIdLong()) { - responsible = entry.getUser(); + if (auditLogEntry != null && auditLogEntry.getTargetIdLong() == event.getMember().getIdLong()) { + responsible = auditLogEntry.getUser(); } modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_ADDED; - LanguageEmbedField addedRolesEmbedField = new LanguageEmbedField(false, "modlog.general.added_roles", "modlog.general.variable"); + ModlogEmbedField addedRolesEmbedField = new ModlogEmbedField(false, "modlog.general.added_roles", "modlog.general.variable"); addedRolesEmbedField.addValueObjects(((GuildMemberRoleAddEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n"))); embedFieldList.add(addedRolesEmbedField); } else if (event instanceof GuildMemberRoleRemoveEvent) { - if (entry.getType().equals(ActionType.MEMBER_ROLE_UPDATE) && millis < 1000 && entry.getTargetIdLong() == event.getMember().getIdLong()) { - responsible = entry.getUser(); + if (auditLogEntry != null && auditLogEntry.getTargetIdLong() == event.getMember().getIdLong()) { + responsible = auditLogEntry.getUser(); } modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_REMOVED; - LanguageEmbedField removedRolesEmbedField = new LanguageEmbedField(false, "modlog.general.removed_roles", "modlog.general.variable"); + ModlogEmbedField removedRolesEmbedField = new ModlogEmbedField(false, "modlog.general.removed_roles", "modlog.general.variable"); removedRolesEmbedField.addValueObjects(((GuildMemberRoleRemoveEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n"))); embedFieldList.add(removedRolesEmbedField); } else if (event instanceof GuildMemberUpdateNicknameEvent) { if (((GuildMemberUpdateNicknameEvent) event).getOldValue() != null) { - LanguageEmbedField oldNickEmbedField = new LanguageEmbedField(true, "modlog.member.old_nick", "modlog.general.variable"); + ModlogEmbedField oldNickEmbedField = new ModlogEmbedField(true, "modlog.member.old_nick", "modlog.general.variable"); oldNickEmbedField.addValueObjects(((GuildMemberUpdateNicknameEvent) event).getOldValue()); embedFieldList.add(oldNickEmbedField); } if (((GuildMemberUpdateNicknameEvent) event).getNewValue() != null) { - LanguageEmbedField newNickEmbedField = new LanguageEmbedField(true, "modlog.member.new_nick", "modlog.general.variable"); + ModlogEmbedField newNickEmbedField = new ModlogEmbedField(true, "modlog.member.new_nick", "modlog.general.variable"); newNickEmbedField.addValueObjects(((GuildMemberUpdateNicknameEvent) event).getNewValue()); embedFieldList.add(newNickEmbedField); } @@ -240,24 +241,22 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }); + }, ActionType.KICK, ActionType.MEMBER_ROLE_UPDATE); } //region Ban events public void onGuildBan(GuildBanEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); User user = event.getUser(); - event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - List embedFieldList = new ArrayList<>(); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); + ModlogUtils.getAuditLogFromType(event.getGuild(), event.getUser().getIdLong(), auditLogEntry -> { + List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent = ModlogEvent.GUILD_USER_BANNED; User responsible = null; - if (entry.getType().equals(ActionType.BAN) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getUser().getIdLong()) { - responsible = entry.getUser(); - if (entry.getReason() != null) { - LanguageEmbedField reasonEmbedField = new LanguageEmbedField(false, "modlog.general.reason", "modlog.general.variable"); - reasonEmbedField.addValueObjects(entry.getReason()); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); + if (auditLogEntry.getReason() != null) { + ModlogEmbedField reasonEmbedField = new ModlogEmbedField(false, "modlog.general.reason", "modlog.general.variable"); + reasonEmbedField.addValueObjects(auditLogEntry.getReason()); embedFieldList.add(reasonEmbedField); } } else { @@ -265,26 +264,24 @@ public void onGuildBan(GuildBanEvent event) { } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }); + }, ActionType.BAN); } public void onGuildUnban(GuildUnbanEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); User user = event.getUser(); - event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + ModlogUtils.getAuditLogFromType(event.getGuild(), event.getUser().getIdLong(), auditLogEntry -> { + List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent = ModlogEvent.GUILD_USER_UNBANNED; User responsible = null; - if (entry.getType().equals(ActionType.UNBAN) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getUser().getIdLong()) { - responsible = entry.getUser(); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find unban entry"); } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }); + }, ActionType.UNBAN); } //endregion @@ -305,8 +302,8 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { return; } User affected = CascadeBot.INS.getClient().getUserById(message.getAuthorId()); - List embedFieldList = new ArrayList<>(); - LanguageEmbedField messageEmbedField = new LanguageEmbedField(false, "modlog.message.message", "modlog.general.variable"); + List embedFieldList = new ArrayList<>(); + ModlogEmbedField messageEmbedField = new ModlogEmbedField(false, "modlog.message.message", "modlog.general.variable"); messageEmbedField.addValueObjects(message.getContent()); embedFieldList.add(messageEmbedField); if (message.getAttachments().size() > 0) { @@ -314,18 +311,16 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { for (Attachment attachment : message.getAttachments()) { attachmentsBuilder.append(attachment.getUrl()).append('\n'); } - embedFieldList.add(new LanguageEmbedField(false, "modlog.message.attachments", "modlog.general.variable", attachmentsBuilder.toString())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.message.attachments", "modlog.general.variable", attachmentsBuilder.toString())); } if (affected == null) { return; } //TODO handle embeds/ect... - event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); + ModlogUtils.getAuditLogFromType(event.getGuild(), message.getAuthorId(), auditLogEntry -> { User responsible; - if (entry.getType().equals(ActionType.MESSAGE_DELETE) && millis < auditTimeAllowed && entry.getTargetIdLong() == message.getAuthorId()) { - responsible = entry.getUser(); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find message delete entry"); responsible = null; @@ -336,7 +331,7 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { } ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.GUILD_MESSAGE_DELETED, responsible, affected, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }); + }, ActionType.MESSAGE_DELETE); } public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { @@ -358,10 +353,10 @@ public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { return; } User affected = message.getAuthor(); - List embedFieldList = new ArrayList<>(); - LanguageEmbedField oldEmbedField = new LanguageEmbedField(false, "modlog.message.old_message", "modlog.general.variable"); + List embedFieldList = new ArrayList<>(); + ModlogEmbedField oldEmbedField = new ModlogEmbedField(false, "modlog.message.old_message", "modlog.general.variable"); oldEmbedField.addValueObjects(oldMessage.getContent()); - LanguageEmbedField newEmbedField = new LanguageEmbedField(false, "modlog.message.new_message", "modlog.general.variable"); + ModlogEmbedField newEmbedField = new ModlogEmbedField(false, "modlog.message.new_message", "modlog.general.variable"); newEmbedField.addValueObjects(message.getContentRaw()); // TODO handle embeds/ect... embedFieldList.add(oldEmbedField); @@ -403,174 +398,170 @@ private SerializableMessage getMessageFromString(long id, String messageString) public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { Guild affected = event.getEntity(); GuildData guildData = GuildDataManager.getGuildData(affected.getIdLong()); - event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + ModlogUtils.getAuditLogFromType(event.getGuild(), auditLogEntry -> { + List embedFieldList = new ArrayList<>(); User responsible = null; ModlogEvent modlogEvent; - if (entry.getType().equals(ActionType.GUILD_UPDATE) && millis < auditTimeAllowed) { - responsible = entry.getUser(); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find guild update entry"); } if (event instanceof GuildUpdateAfkChannelEvent) { VoiceChannel oldChannel = ((GuildUpdateAfkChannelEvent) event).getOldAfkChannel(); if (oldChannel != null) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_channel", "modlog.general.variable", oldChannel.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_channel", "modlog.general.variable", oldChannel.getName())); } VoiceChannel newChannel = ((GuildUpdateAfkChannelEvent) event).getNewAfkChannel(); if (newChannel != null) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_channel", "modlog.general.variable", newChannel.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_channel", "modlog.general.variable", newChannel.getName())); } modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_CHANNEL; } else if (event instanceof GuildUpdateAfkTimeoutEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getOldAfkTimeout().getSeconds()))); - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getNewAfkTimeout().getSeconds()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getOldAfkTimeout().getSeconds()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getNewAfkTimeout().getSeconds()))); modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_TIMEOUT; } else if (event instanceof GuildUpdateBannerEvent) { if (((GuildUpdateBannerEvent) event).getOldBannerUrl() != null) { - embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.old_image", "modlog.general.variable", ((GuildUpdateBannerEvent) event).getOldBannerUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", "modlog.general.variable", ((GuildUpdateBannerEvent) event).getOldBannerUrl())); } if (((GuildUpdateBannerEvent) event).getNewBannerUrl() != null) { - embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.new_image", "modlog.general.variable", ((GuildUpdateBannerEvent) event).getNewBannerUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_image", "modlog.general.variable", ((GuildUpdateBannerEvent) event).getNewBannerUrl())); } modlogEvent = ModlogEvent.GUILD_UPDATE_BANNER; } else if (event instanceof GuildUpdateDescriptionEvent) { if (((GuildUpdateDescriptionEvent) event).getOldDescription() != null) { - embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.old_description", "modlog.general.variable", ((GuildUpdateDescriptionEvent) event).getOldDescription())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_description", "modlog.general.variable", ((GuildUpdateDescriptionEvent) event).getOldDescription())); } if (((GuildUpdateDescriptionEvent) event).getNewDescription() != null) { - embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.new_description", "modlog.general.variable", ((GuildUpdateDescriptionEvent) event).getNewDescription())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_description", "modlog.general.variable", ((GuildUpdateDescriptionEvent) event).getNewDescription())); } modlogEvent = ModlogEvent.GUILD_UPDATE_DESCRIPTION; } else if (event instanceof GuildUpdateExplicitContentLevelEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.content_filter.old", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getOldLevel().name().toLowerCase())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.content_filter.new", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getNewLevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.content_filter.old", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getOldLevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.content_filter.new", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getNewLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_EXPLICIT_FILTER; } else if (event instanceof GuildUpdateFeaturesEvent) { ListChanges featuresChanged = new ListChanges<>(((GuildUpdateFeaturesEvent) event).getOldFeatures(), ((GuildUpdateFeaturesEvent) event).getNewFeatures()); - embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.add_feature", "modlog.general.variable", String.join("\n", featuresChanged.getAdded()))); - embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.removed_feature", "modlog.general.variable", String.join("\n", featuresChanged.getRemoved()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.add_feature", "modlog.general.variable", String.join("\n", featuresChanged.getAdded()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.removed_feature", "modlog.general.variable", String.join("\n", featuresChanged.getRemoved()))); modlogEvent = ModlogEvent.GUILD_UPDATE_FEATURES; } else if (event instanceof GuildUpdateIconEvent) { if (((GuildUpdateIconEvent) event).getOldIconUrl() != null) { - embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.old_image", "modlog.general.variable", ((GuildUpdateIconEvent) event).getOldIconUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", "modlog.general.variable", ((GuildUpdateIconEvent) event).getOldIconUrl())); } if (((GuildUpdateIconEvent) event).getNewIconUrl() != null) { - embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.new_image", "modlog.general.variable", ((GuildUpdateIconEvent) event).getNewIconUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_image", "modlog.general.variable", ((GuildUpdateIconEvent) event).getNewIconUrl())); } modlogEvent = ModlogEvent.GUILD_UPDATE_ICON; } else if (event instanceof GuildUpdateMaxMembersEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getOldMaxMembers()))); - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getNewMaxMembers()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getOldMaxMembers()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getNewMaxMembers()))); modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_MEMBERS; } else if (event instanceof GuildUpdateMaxPresencesEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getOldMaxPresences()))); - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getNewMaxPresences()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getOldMaxPresences()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getNewMaxPresences()))); modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_PRESENCES; } else if (event instanceof GuildUpdateMFALevelEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.mfa.old", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getOldMFALevel().name().toLowerCase())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.mfa.new", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getNewMFALevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.mfa.old", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getOldMFALevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.mfa.new", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getNewMFALevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_MFA_LEVEL; } else if (event instanceof GuildUpdateNameEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable", ((GuildUpdateNameEvent) event).getOldName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", "modlog.general.variable", ((GuildUpdateNameEvent) event).getOldName())); modlogEvent = ModlogEvent.GUILD_UPDATE_NAME; } else if (event instanceof GuildUpdateNotificationLevelEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.notification.old", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getOldNotificationLevel().name().toLowerCase())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.notification.new", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getNewNotificationLevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.notification.old", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getOldNotificationLevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.notification.new", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getNewNotificationLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_NOTIFICATION_LEVEL; } else if (event instanceof GuildUpdateRegionEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_region", "modlog.general.variable", ((GuildUpdateRegionEvent) event).getOldRegion().getName())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_region", "modlog.general.variable", ((GuildUpdateRegionEvent) event).getNewRegion().getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_region", "modlog.general.variable", ((GuildUpdateRegionEvent) event).getOldRegion().getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_region", "modlog.general.variable", ((GuildUpdateRegionEvent) event).getNewRegion().getName())); modlogEvent = ModlogEvent.GUILD_UPDATE_REGION; } else if (event instanceof GuildUpdateSplashEvent) { if (((GuildUpdateSplashEvent) event).getOldSplashUrl() != null) { - embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.old_splash", "modlog.general.variable", ((GuildUpdateSplashEvent) event).getOldSplashUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_splash", "modlog.general.variable", ((GuildUpdateSplashEvent) event).getOldSplashUrl())); } if (((GuildUpdateSplashEvent) event).getNewSplashUrl() != null) { - embedFieldList.add(new LanguageEmbedField(false, "modlog.guild.new_splash", "modlog.general.variable", ((GuildUpdateSplashEvent) event).getNewSplashUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_splash", "modlog.general.variable", ((GuildUpdateSplashEvent) event).getNewSplashUrl())); } modlogEvent = ModlogEvent.GUILD_UPDATE_SPLASH; } else if (event instanceof GuildUpdateSystemChannelEvent) { TextChannel oldSystemChannel = ((GuildUpdateSystemChannelEvent) event).getOldSystemChannel(); if (oldSystemChannel != null) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_sys", "modlog.general.variable", oldSystemChannel.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_sys", "modlog.general.variable", oldSystemChannel.getName())); } TextChannel newSystemChannel = ((GuildUpdateSystemChannelEvent) event).getNewSystemChannel(); if (newSystemChannel != null) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_sys", "modlog.general.variable", newSystemChannel.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_sys", "modlog.general.variable", newSystemChannel.getName())); } modlogEvent = ModlogEvent.GUILD_UPDATE_SYSTEM_CHANNEL; } else if (event instanceof GuildUpdateVanityCodeEvent) { if (((GuildUpdateVanityCodeEvent) event).getOldVanityCode() != null) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.vanity_code.old", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getOldVanityCode())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_code.old", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getOldVanityCode())); } if (((GuildUpdateVanityCodeEvent) event).getOldVanityUrl() != null) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.vanity_url.old", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getOldVanityUrl())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_url.old", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getOldVanityUrl())); } if (((GuildUpdateVanityCodeEvent) event).getNewVanityCode() != null) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.vanity_code.new", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getNewVanityCode())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_code.new", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getNewVanityCode())); } if (((GuildUpdateVanityCodeEvent) event).getNewVanityUrl() != null) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.vanity_url.new", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getNewVanityUrl())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_url.new", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getNewVanityUrl())); } modlogEvent = ModlogEvent.GUILD_UPDATE_VANITY_CODE; } else if (event instanceof GuildUpdateVerificationLevelEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getOldVerificationLevel().name().toLowerCase())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getNewVerificationLevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getOldVerificationLevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getNewVerificationLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_VERIFICATION_LEVEL; } else if (event instanceof GuildUpdateBoostCountEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_boost_count", "modlog.general.variable", String.valueOf(event.getOldValue()))); - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_boost_count", "modlog.general.variable", String.valueOf(event.getNewValue()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_boost_count", "modlog.general.variable", String.valueOf(event.getOldValue()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_boost_count", "modlog.general.variable", String.valueOf(event.getNewValue()))); modlogEvent = ModlogEvent.GUILD_BOOST_COUNT_UPDATED; } else if (event instanceof GuildUpdateBoostTierEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.old_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getOldBoostTier().name().toLowerCase())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.guild.new_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getNewBoostTier().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getOldBoostTier().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getNewBoostTier().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_BOOST_TIER_UPDATED; } else { return; } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }); + }, ActionType.GUILD_UPDATE); } public void onGenericGuildVoice(GenericGuildVoiceEvent event) { User affected = event.getMember().getUser(); Guild guild = event.getGuild(); GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + ModlogUtils.getAuditLogFromType(event.getGuild(), event.getMember().getIdLong(), auditLogEntry -> { + List embedFieldList = new ArrayList<>(); ModlogEvent action; if (event instanceof GuildVoiceDeafenEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceDeafenEvent) event).isDeafened()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceDeafenEvent) event).isDeafened()))); action = ModlogEvent.VOICE_DEAFEN; } else if (event instanceof GuildVoiceMuteEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceMuteEvent) event).isMuted()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceMuteEvent) event).isMuted()))); action = ModlogEvent.VOICE_MUTE; } else if (event instanceof GuildVoiceGuildDeafenEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()))); action = ModlogEvent.VOICE_SERVER_DEAFEN; } else if (event instanceof GuildVoiceGuildMuteEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceGuildMuteEvent) event).isGuildMuted()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceGuildMuteEvent) event).isGuildMuted()))); action = ModlogEvent.VOICE_SERVER_MUTE; } else if (event instanceof GuildVoiceJoinEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.join", "modlog.general.variable", ((GuildVoiceJoinEvent) event).getChannelJoined().getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.join", "modlog.general.variable", ((GuildVoiceJoinEvent) event).getChannelJoined().getName())); action = ModlogEvent.VOICE_JOIN; } else if (event instanceof GuildVoiceLeaveEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.left", "modlog.general.variable", ((GuildVoiceLeaveEvent) event).getChannelLeft().getName())); - if (entry.getType().equals(ActionType.MEMBER_VOICE_MOVE) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getMember().getIdLong()) { + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.left", "modlog.general.variable", ((GuildVoiceLeaveEvent) event).getChannelLeft().getName())); + if (auditLogEntry != null) { action = ModlogEvent.VOICE_DISCONNECT; } else { action = ModlogEvent.VOICE_LEAVE; } } else if (event instanceof GuildVoiceMoveEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.left", "modlog.general.variable", ((GuildVoiceMoveEvent) event).getChannelLeft().getName())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.voice.join", "modlog.general.variable", ((GuildVoiceMoveEvent) event).getChannelJoined().getName())); - if (entry.getType().equals(ActionType.MEMBER_VOICE_KICK) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getMember().getIdLong()) { + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.left", "modlog.general.variable", ((GuildVoiceMoveEvent) event).getChannelLeft().getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.join", "modlog.general.variable", ((GuildVoiceMoveEvent) event).getChannelJoined().getName())); + if (auditLogEntry != null) { action = ModlogEvent.VOICE_FORCE_MOVE; } else { action = ModlogEvent.VOICE_MOVE; @@ -580,7 +571,7 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { } ModlogEventStore eventStore = new ModlogEventStore(action, null, affected, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }); + }, ActionType.MEMBER_VOICE_MOVE, ActionType.MEMBER_VOICE_KICK); } //region Channels @@ -614,34 +605,32 @@ public void onGenericTextChannel(GenericTextChannelEvent event) { return; } GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); - event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { + ModlogUtils.getAuditLogFromType(event.getGuild(), event.getChannel().getIdLong(), auditLogEntry -> { ModlogEvent trigger; - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_UPDATE) && millis < auditTimeAllowed && event.getChannel().getIdLong() == entry.getTargetIdLong()) { - responsible = entry.getUser(); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } if (event instanceof TextChannelUpdateNSFWEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.nsfw", "modlog.general.variable", String.valueOf(!((TextChannelUpdateNSFWEvent) event).getOldNSFW()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.nsfw", "modlog.general.variable", String.valueOf(!((TextChannelUpdateNSFWEvent) event).getOldNSFW()))); trigger = ModlogEvent.TEXT_CHANNEL_NSFW_UPDATED; } else if (event instanceof TextChannelUpdateSlowmodeEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_slowmode", "modlog.general.variable", String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getOldSlowmode()))); - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.new_slowmode", "modlog.general.variable", String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getNewSlowmode()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_slowmode", "modlog.general.variable", String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getOldSlowmode()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_slowmode", "modlog.general.variable", String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getNewSlowmode()))); trigger = ModlogEvent.TEXT_CHANNEL_SLOWMODE_UPDATED; } else if (event instanceof TextChannelUpdateTopicEvent) { - embedFieldList.add(new LanguageEmbedField(false, "modlog.channel.old_topic", "modlog.general.variable", ((TextChannelUpdateTopicEvent) event).getOldTopic())); - embedFieldList.add(new LanguageEmbedField(false, "modlog.channel.new_topic", "modlog.general.variable", ((TextChannelUpdateTopicEvent) event).getNewTopic())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_topic", "modlog.general.variable", ((TextChannelUpdateTopicEvent) event).getOldTopic())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_topic", "modlog.general.variable", ((TextChannelUpdateTopicEvent) event).getNewTopic())); trigger = ModlogEvent.TEXT_CHANNEL_TOPIC_UPDATED; } else { return; } ModlogEventStore eventStore = new ModlogEventStore(trigger, responsible, event.getChannel(), embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }); + }, ActionType.CHANNEL_UPDATE); } public void onGenericVoiceChannel(GenericVoiceChannelEvent event) { @@ -657,31 +646,29 @@ public void onGenericVoiceChannel(GenericVoiceChannelEvent event) { handleChannelUpdateParentEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdateParentEvent) event).getOldParent(), ((VoiceChannelUpdateParentEvent) event).getNewParent(), event.getChannel()); } GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); - event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { + ModlogUtils.getAuditLogFromType(event.getGuild(), event.getChannel().getIdLong(), auditLogEntry -> { ModlogEvent trigger; - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_UPDATE) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getChannel().getIdLong()) { - responsible = entry.getUser(); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } if (event instanceof VoiceChannelUpdateBitrateEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getOldBitrate()))); - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.new_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getNewBitrate()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getOldBitrate()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getNewBitrate()))); trigger = ModlogEvent.VOICE_CHANNEL_BITRATE_UPDATED; } else if (event instanceof VoiceChannelUpdateUserLimitEvent) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_users", "modlog.channel.user", String.valueOf(((VoiceChannelUpdateUserLimitEvent) event).getOldUserLimit()))); - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.new_users", "modlog.channel.user", String.valueOf(((VoiceChannelUpdateUserLimitEvent) event).getNewUserLimit()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_users", "modlog.channel.user", String.valueOf(((VoiceChannelUpdateUserLimitEvent) event).getOldUserLimit()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_users", "modlog.channel.user", String.valueOf(((VoiceChannelUpdateUserLimitEvent) event).getNewUserLimit()))); trigger = ModlogEvent.VOICE_CHANNEL_USER_LIMIT_UPDATED; } else { return; } ModlogEventStore eventStore = new ModlogEventStore(trigger, responsible, event.getChannel(), embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }); + }, ActionType.CHANNEL_UPDATE); } public void onGenericCategory(GenericCategoryEvent event) { @@ -700,13 +687,11 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { ModlogEvent modlogEvent = ModlogEvent.CHANNEL_PERMISSIONS_UPDATED; Guild guild = event.getGuild(); GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + ModlogUtils.getAuditLogFromType(event.getGuild(), event.getChannel().getIdLong(), auditLogEntry -> { + List embedFieldList = new ArrayList<>(); User responsible = null; - if ((entry.getType().equals(ActionType.CHANNEL_UPDATE) || entry.getType().equals(ActionType.CHANNEL_OVERRIDE_UPDATE)) && millis < auditTimeAllowed && entry.getTargetIdLong() == event.getChannel().getIdLong()) { - responsible = entry.getUser(); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } @@ -731,13 +716,13 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { allowedPath = "modlog.channel.perm.update_allow"; deniedPath = "modlog.channel.perm.update_deny"; if (((PermissionOverrideUpdateEvent) event).getOldAllow().size() > 0) { - LanguageEmbedField oldAllowed = new LanguageEmbedField(false, "modlog.channel.perm.old_allow", "modlog.general.variable", + ModlogEmbedField oldAllowed = new ModlogEmbedField(false, "modlog.channel.perm.old_allow", "modlog.general.variable", ((PermissionOverrideUpdateEvent) event).getOldAllow().stream().map(Permission::getName).collect(Collectors.joining("\n"))); oldAllowed.addTitleObjects(permissionsHolderName); embedFieldList.add(oldAllowed); } if (((PermissionOverrideUpdateEvent) event).getOldDeny().size() > 0) { - LanguageEmbedField oldDenied = new LanguageEmbedField(false, "modlog.channel.perm.old_allow", "modlog.general.variable", + ModlogEmbedField oldDenied = new ModlogEmbedField(false, "modlog.channel.perm.old_allow", "modlog.general.variable", ((PermissionOverrideUpdateEvent) event).getOldDeny().stream().map(Permission::getName).collect(Collectors.joining("\n"))); oldDenied.addTitleObjects(permissionsHolderName); embedFieldList.add(oldDenied); @@ -746,19 +731,19 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { return; } if (event.getPermissionOverride().getAllowed().size() > 0) { - LanguageEmbedField allowed = new LanguageEmbedField(false, allowedPath, "modlog.general.variable", event.getPermissionOverride().getAllowed().stream().map(Permission::getName).collect(Collectors.joining("\n"))); + ModlogEmbedField allowed = new ModlogEmbedField(false, allowedPath, "modlog.general.variable", event.getPermissionOverride().getAllowed().stream().map(Permission::getName).collect(Collectors.joining("\n"))); allowed.addTitleObjects(permissionsHolderName); embedFieldList.add(allowed); } if (event.getPermissionOverride().getDenied().size() > 0) { - LanguageEmbedField denied = new LanguageEmbedField(false, deniedPath, "modlog.general.variable", event.getPermissionOverride().getDenied().stream().map(Permission::getName).collect(Collectors.joining("\n"))); + ModlogEmbedField denied = new ModlogEmbedField(false, deniedPath, "modlog.general.variable", event.getPermissionOverride().getDenied().stream().map(Permission::getName).collect(Collectors.joining("\n"))); denied.addTitleObjects(permissionsHolderName); embedFieldList.add(denied); } - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + event.getChannelType().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + event.getChannelType().name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, event.getChannel(), embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventStore); - }); + }, ActionType.CHANNEL_OVERRIDE_UPDATE, ActionType.CHANNEL_UPDATE); } //endregion @@ -767,114 +752,102 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChannel channel) { ModlogEvent event = ModlogEvent.CHANNEL_CREATED; GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + ModlogUtils.getAuditLogFromType(guild, channel.getIdLong(), auditLogEntry -> { + List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_CREATE) && millis < auditTimeAllowed && entry.getTargetIdLong() == channel.getIdLong()) { - responsible = entry.getUser(); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel create entry"); } - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); - }); + }, ActionType.CHANNEL_CREATE); } private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChannel channel) { ModlogEvent event = ModlogEvent.CHANNEL_DELETED; GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + ModlogUtils.getAuditLogFromType(guild, channel.getIdLong(), auditLogEntry -> { + List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_DELETE) && millis < auditTimeAllowed && entry.getTargetIdLong() == channel.getIdLong()) { - responsible = entry.getUser(); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel delete entry"); } - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); - }); + }, ActionType.CHANNEL_DELETE); } private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String oldName, GuildChannel channel) { ModlogEvent event = ModlogEvent.CHANNEL_NAME_UPDATED; GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + ModlogUtils.getAuditLogFromType(guild, channel.getIdLong(), auditLogEntry -> { + List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_UPDATE) && millis < 1000 && entry.getTargetIdLong() == channel.getIdLong()) { - responsible = entry.getUser(); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable", oldName)); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", "modlog.general.variable", oldName)); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); - }); + }, ActionType.CHANNEL_UPDATE); } private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, int oldPos, GuildChannel channel) { ModlogEvent event = ModlogEvent.CHANNEL_POSITION_UPDATED; GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + ModlogUtils.getAuditLogFromType(guild, channel.getIdLong(), auditLogEntry -> { + List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_UPDATE) && millis < 1000 && entry.getTargetIdLong() == channel.getIdLong()) { - responsible = entry.getUser(); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_pos", "modlog.general.variable", String.valueOf(oldPos))); - embedFieldList.add(new LanguageEmbedField(true, "modlog.general.new_pos", "modlog.general.variable", String.valueOf(channel.getPosition()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_pos", "modlog.general.variable", String.valueOf(oldPos))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.new_pos", "modlog.general.variable", String.valueOf(channel.getPosition()))); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); - }); + }, ActionType.CHANNEL_UPDATE); } public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Category oldParent, Category newParent, GuildChannel channel) { ModlogEvent event = ModlogEvent.CHANNEL_PARENT_UPDATED; GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guild.retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + ModlogUtils.getAuditLogFromType(guild, channel.getIdLong(), auditLogEntry -> { + List embedFieldList = new ArrayList<>(); User responsible = null; - if (entry.getType().equals(ActionType.CHANNEL_UPDATE) && millis < 1000 && entry.getTargetIdLong() == channel.getIdLong()) { - responsible = entry.getUser(); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.old_parent", "modlog.general.variable", oldParent.getName())); - embedFieldList.add(new LanguageEmbedField(true, "modlog.channel.new_parent", "modlog.general.variable", newParent.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_parent", "modlog.general.variable", oldParent.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_parent", "modlog.general.variable", newParent.getName())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); - }); + }, ActionType.CHANNEL_UPDATE); } //endregion public void onGenericRole(GenericRoleEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); - event.getGuild().retrieveAuditLogs().limit(1).queue(auditLogEntries -> { - AuditLogEntry entry = auditLogEntries.get(0); - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); - List embedFieldList = new ArrayList<>(); + ModlogUtils.getAuditLogFromType(event.getGuild(), event.getRole().getIdLong(), auditLogEntry -> { + List embedFieldList = new ArrayList<>(); User responsible = null; ModlogEvent modlogEvent; - if ((entry.getType().equals(ActionType.ROLE_CREATE) || entry.getType().equals(ActionType.ROLE_DELETE) || entry.getType().equals(ActionType.ROLE_UPDATE)) && millis < 1000 && entry.getTargetIdLong() == event.getRole().getIdLong()) { - responsible = entry.getUser(); + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find role entry"); } @@ -887,45 +860,45 @@ public void onGenericRole(GenericRoleEvent event) { modlogEvent = ModlogEvent.ROLE_COLOR_UPDATED; Color oldColor = ((RoleUpdateColorEvent) event).getOldColor(); if (oldColor != null) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.role.old_color", "modlog.general.variable", ColorUtils.getHex(oldColor.getRed(), oldColor.getGreen(), oldColor.getBlue()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.role.old_color", "modlog.general.variable", ColorUtils.getHex(oldColor.getRed(), oldColor.getGreen(), oldColor.getBlue()))); } Color newColor = ((RoleUpdateColorEvent) event).getNewColor(); if (newColor != null) { - embedFieldList.add(new LanguageEmbedField(true, "modlog.role.new_color", "modlog.general.variable", ColorUtils.getHex(newColor.getRed(), newColor.getGreen(), newColor.getBlue()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.role.new_color", "modlog.general.variable", ColorUtils.getHex(newColor.getRed(), newColor.getGreen(), newColor.getBlue()))); } } else if (event instanceof RoleUpdateHoistedEvent) { modlogEvent = ModlogEvent.ROLE_HOIST_UPDATED; - embedFieldList.add(new LanguageEmbedField(true, "modlog.role.hoisted", "modlog.general.variable", String.valueOf(!((RoleUpdateHoistedEvent) event).wasHoisted()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.role.hoisted", "modlog.general.variable", String.valueOf(!((RoleUpdateHoistedEvent) event).wasHoisted()))); } else if (event instanceof RoleUpdateMentionableEvent) { modlogEvent = ModlogEvent.ROLE_MENTIONABLE_UPDATED; - embedFieldList.add(new LanguageEmbedField(true, "modlog.role.mention", "modlog.general.variable", String.valueOf(!((RoleUpdateMentionableEvent) event).wasMentionable()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.role.mention", "modlog.general.variable", String.valueOf(!((RoleUpdateMentionableEvent) event).wasMentionable()))); } else if (event instanceof RoleUpdateNameEvent) { modlogEvent = ModlogEvent.ROLE_NAME_UPDATED; - embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable", ((RoleUpdateNameEvent) event).getOldName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", "modlog.general.variable", ((RoleUpdateNameEvent) event).getOldName())); } else if (event instanceof RoleUpdatePermissionsEvent) { modlogEvent = ModlogEvent.ROLE_PERMISSIONS_UPDATED; EnumSet oldPermissions = ((RoleUpdatePermissionsEvent) event).getOldPermissions(); EnumSet newPermissions = ((RoleUpdatePermissionsEvent) event).getNewPermissions(); ListChanges permissionListChanges = new ListChanges<>(oldPermissions, newPermissions); - embedFieldList.add(new LanguageEmbedField(false, "modlog.role.added_perm", "modlog.general.variable", permissionListChanges.getAdded().stream().map(Permission::getName).collect(Collectors.joining("\n")))); - embedFieldList.add(new LanguageEmbedField(false, "modlog.role.removed_perm", "modlog.general.variable", permissionListChanges.getRemoved().stream().map(Permission::getName).collect(Collectors.joining("\n")))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.role.added_perm", "modlog.general.variable", permissionListChanges.getAdded().stream().map(Permission::getName).collect(Collectors.joining("\n")))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.role.removed_perm", "modlog.general.variable", permissionListChanges.getRemoved().stream().map(Permission::getName).collect(Collectors.joining("\n")))); } else if (event instanceof RoleUpdatePositionEvent) { modlogEvent = ModlogEvent.ROLE_POSITION_UPDATED; - embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_pos", "modlog.general.variable", String.valueOf(((RoleUpdatePositionEvent) event).getOldPosition()))); - embedFieldList.add(new LanguageEmbedField(true, "modlog.general.new_pos", "modlog.general.variable", String.valueOf(((RoleUpdatePositionEvent) event).getNewPosition()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_pos", "modlog.general.variable", String.valueOf(((RoleUpdatePositionEvent) event).getOldPosition()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.new_pos", "modlog.general.variable", String.valueOf(((RoleUpdatePositionEvent) event).getNewPosition()))); } else { return; } ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventStore); - }); + }, ActionType.ROLE_CREATE, ActionType.ROLE_DELETE, ActionType.ROLE_UPDATE); } //region Username updates public void onUserUpdateName(UserUpdateNameEvent event) { // TODO propagate to guilds - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(true, "modlog.general.old_name", "modlog.general.variable", event.getOldName())); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", "modlog.general.variable", event.getOldName())); ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_NAME_UPDATED, event.getUser(), event.getUser(), embedFieldList); for (Guild guild : CascadeBot.INS.getClient().getMutualGuilds(event.getUser())) { GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); @@ -934,8 +907,8 @@ public void onUserUpdateName(UserUpdateNameEvent event) { } public void onUserUpdateDiscriminator(UserUpdateDiscriminatorEvent event) { - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new LanguageEmbedField(true, "modlog.user.old_discrim", "modlog.general.variable", event.getOldDiscriminator())); + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(true, "modlog.user.old_discrim", "modlog.general.variable", event.getOldDiscriminator())); ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_DISCRIMINATOR_UPDATED, event.getUser(), event.getUser(), embedFieldList); for (Guild guild : CascadeBot.INS.getClient().getMutualGuilds(event.getUser())) { GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java new file mode 100644 index 000000000..223704e12 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java @@ -0,0 +1,84 @@ +package org.cascadebot.cascadebot.runnables; + +import net.dv8tion.jda.api.audit.ActionType; +import net.dv8tion.jda.api.entities.ChannelType; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.GuildChannel; +import net.dv8tion.jda.api.entities.User; +import org.cascadebot.cascadebot.utils.ModlogUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +public class ModlogChannelMoveCollectorRunnable implements Runnable { + + private Guild guild; + private Consumer finishedConsumer; + + public ModlogChannelMoveCollectorRunnable(Guild guild, Consumer finishedConsumer) { + this.guild = guild; + this.finishedConsumer = finishedConsumer; + } + + private BlockingQueue queue = new LinkedBlockingQueue<>(); + private List channelMoveDataList = new ArrayList<>(); + + @Override + public void run() { + boolean collecting = true; + while (collecting) { + try { + ChannelMoveData moveData = queue.poll(500, TimeUnit.MILLISECONDS); + channelMoveDataList.add(moveData); + if (moveData == null) { + collecting = false; + afterCollected(); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private void afterCollected() { + finishedConsumer.accept(null); + ModlogUtils.getAuditLogFromType(guild, auditLogEntry -> { + User responsible = null; + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); + } + + }, ActionType.CHANNEL_UPDATE); + } + + static class ChannelMoveData { + + private ChannelType type; + private int oldPos; + private GuildChannel channel; + + public ChannelMoveData(ChannelType type, int oldPos, GuildChannel channel) { + this.type = type; + this.oldPos = oldPos; + this.channel = channel; + } + + public ChannelType getType() { + return type; + } + + public int getOldPos() { + return oldPos; + } + + public GuildChannel getChannel() { + return channel; + } + + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/ModlogMemberRoleCollectorRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/ModlogMemberRoleCollectorRunnable.java new file mode 100644 index 000000000..cbea1e847 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/runnables/ModlogMemberRoleCollectorRunnable.java @@ -0,0 +1,10 @@ +package org.cascadebot.cascadebot.runnables; + +public class ModlogMemberRoleCollectorRunnable implements Runnable { + + @Override + public void run() { + + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java new file mode 100644 index 000000000..d74f16faf --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java @@ -0,0 +1,46 @@ +package org.cascadebot.cascadebot.utils; + +import net.dv8tion.jda.api.audit.ActionType; +import net.dv8tion.jda.api.audit.AuditLogEntry; +import net.dv8tion.jda.api.entities.Guild; + +import java.time.Duration; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; + +public class ModlogUtils { + + public static void getAuditLogFromType(Guild guild, Consumer entryConsumer, ActionType... actionTypes) { + getAuditLogFromType(guild, -1, entryConsumer, actionTypes); + } + + public static void getAuditLogFromType(Guild guild, long targetId, Consumer entryConsumer, ActionType... actionTypes) { + List actionTypeList = Arrays.asList(actionTypes); + guild.retrieveAuditLogs().limit(5 /* Get last 5 entries in case something else happens in the 500 ms */) + .queueAfter(500, TimeUnit.MILLISECONDS, // Wait 500ms so we have a better chance of it being in the modlog + auditLogEntries -> { + for (AuditLogEntry entry : auditLogEntries) { + long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); + if (!actionTypeList.contains(entry.getType())) { + continue; + } + if (millis > 1000l) { + continue; + } + if (targetId != -1) { + if (entry.getTargetIdLong() != targetId) { + continue; + } + } + entryConsumer.accept(entry); + return; + } + entryConsumer.accept(null); + }); + } + +} diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt index b635ba356..fb9b0b4a2 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt @@ -21,9 +21,10 @@ import org.cascadebot.cascadebot.data.objects.GuildSettingsUseful import org.cascadebot.cascadebot.data.objects.ModlogEventStore import org.cascadebot.cascadebot.data.objects.Setting import org.cascadebot.cascadebot.data.objects.SettingsContainer +import org.cascadebot.cascadebot.moderation.ModlogEmbedField +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.permissions.CascadePermission -import org.cascadebot.cascadebot.utils.LanguageEmbedField import org.cascadebot.cascadebot.utils.ReflectionUtils import java.io.IOException import java.lang.reflect.Field @@ -123,9 +124,9 @@ class SettingsCommand : MainCommand() { } } context.typedMessaging.replySuccess(context.i18n("commands.settings.setting_set", field.name, value)) - val embedFields: MutableList = ArrayList(); - embedFields.add(LanguageEmbedField(true, "modlog.setting.old", "modlog.general.variable", oldValue)) - embedFields.add(LanguageEmbedField(true, "modlog.setting.new", "modlog.general.variable", value)) + val embedFields: MutableList = ArrayList(); + embedFields.add(ModlogEmbedField(true, "modlog.setting.old", "modlog.general.variable", oldValue)) + embedFields.add(ModlogEmbedField(true, "modlog.setting.new", "modlog.general.variable", value)) context.data.moderation.sendModlogEvent(context.guild.idLong, ModlogEventStore(ModlogEvent.CASCADE_SETTINGS_UPDATED, sender.user, field, ArrayList())) } catch (e: IllegalAccessException) { context.typedMessaging.replyException(context.i18n("commands.settings.cannot_access"), e) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index bd5ecf235..3f9755f38 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -216,8 +216,8 @@ class GuildSettingsModeration { if (affectedStr != null) { webhookEmbedBuilder.addField(EmbedField(true, "Affected $affectedType", affectedStr)) } - for (embedField in modlogEventStore.extraInfo) { - webhookEmbedBuilder.addField(embedField.getLocalizedEmbedField(guildData.locale)) + for (embedPart in modlogEventStore.extraInfo) { + embedPart.build(guildData.locale, webhookEmbedBuilder) } webhookEmbedBuilder.setColor(modlogEventStore.trigger.messageType.color.rgb) if (modlogEventStore.responsible != null) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 6bf63d3ec..b698d2466 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -9,9 +9,9 @@ import net.dv8tion.jda.api.entities.User import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.commandmeta.MainCommand import org.cascadebot.cascadebot.commandmeta.Module +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.permissions.objects.Group -import org.cascadebot.cascadebot.utils.LanguageEmbedField import java.lang.reflect.Field class ModlogEventStore { @@ -24,14 +24,14 @@ class ModlogEventStore { @Transient var affected: Any = CascadeBot.INS.selfUser - var extraInfo: List = ArrayList() + var extraInfo: List = ArrayList() var affectedId: String = "" var affectedType: String = "" var responsibleId: Long = 0; - constructor(trigger: ModlogEvent, responsible: User?, affected: Any, extraInfo: List) { + constructor(trigger: ModlogEvent, responsible: User?, affected: Any, extraInfo: List) { this.trigger = trigger this.responsible = responsible this.affected = affected diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt new file mode 100644 index 000000000..73e093b5f --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt @@ -0,0 +1,81 @@ +package org.cascadebot.cascadebot.moderation + +import club.minnced.discord.webhook.send.WebhookEmbed +import club.minnced.discord.webhook.send.WebhookEmbedBuilder +import org.cascadebot.cascadebot.data.language.Language +import org.cascadebot.cascadebot.data.language.Locale + +sealed class ModlogEmbedPart { + + abstract fun build(locale: Locale, embedBuilder: WebhookEmbedBuilder) + +} + +class ModlogEmbedField() : ModlogEmbedPart() { + + var inline: Boolean = false + + var titleLanguagePath: String = "" + var titleLanguageObjects: MutableList = ArrayList() + + var valueLanguagePath: String = "" + var valueLanguageObjects: MutableList = ArrayList() + + constructor(inline: Boolean = true, + titleLanguagePath: String, + valueLanguagePath: String, vararg valueLanguageObjects: String): this() { + this.inline = inline; + this.titleLanguagePath = titleLanguagePath + this.valueLanguagePath = valueLanguagePath + this.valueLanguageObjects.addAll(valueLanguageObjects) + } + + fun addTitleObjects(vararg titleLanguageObjects: String) { + this.titleLanguageObjects.addAll(titleLanguageObjects) + } + + fun addValueObjects(vararg valueLanguageObjects: String) { + this.valueLanguageObjects.addAll(valueLanguageObjects) + } + + override fun build(locale: Locale, embedBuilder: WebhookEmbedBuilder) { + embedBuilder.addField(WebhookEmbed.EmbedField(inline, + Language.i18n(locale, titleLanguagePath, *titleLanguageObjects.toTypedArray()), + Language.i18n(locale, valueLanguagePath, *valueLanguageObjects.toTypedArray()))) + } + +} + +class ModlogEmbedDescription() : ModlogEmbedPart() { + + var languagePath: String = "" + var languageObjects: MutableList = ArrayList() + + constructor(languagePath: String, vararg languageObjects: String): this() { + this.languagePath = languagePath + this.languageObjects.addAll(languageObjects) + } + + override fun build(locale: Locale, embedBuilder: WebhookEmbedBuilder) { + embedBuilder.setDescription(Language.i18n(locale, languagePath, *languageObjects.toTypedArray())) + } + +} + +class ModlogEmbedFooter() : ModlogEmbedPart() { + + var languagePath: String = "" + var languageObjects: MutableList = ArrayList() + + var icon: String? = null + + constructor(languagePath: String, icon: String? = null, vararg languageObjects: String): this() { + this.languagePath = languagePath + this.languageObjects.addAll(languageObjects) + } + + override fun build(locale: Locale, embedBuilder: WebhookEmbedBuilder) { + embedBuilder.setFooter(WebhookEmbed.EmbedFooter(Language.i18n(locale, languagePath, *languageObjects.toTypedArray()), icon)); + } + +} \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 5bb0ad51c..36f512c30 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -6,119 +6,119 @@ import java.util.ArrayList import java.util.Arrays import java.util.HashMap -enum class ModlogEvent(messageType: MessageType, vararg categories: Category) { - - EMOTE_CREATED(MessageType.INFO, Category.EMOTE), - EMOTE_DELETED(MessageType.INFO, Category.EMOTE), - EMOTE_UPDATED_NAME(MessageType.INFO, Category.EMOTE), - EMOTE_UPDATED_ROLES(MessageType.INFO, Category.EMOTE), - - GUILD_MEMBER_JOINED(MessageType.INFO, Category.GUILD, Category.GUILD_MEMBER), - GUILD_MEMBER_LEFT(MessageType.INFO, Category.GUILD, Category.GUILD_MEMBER), - GUILD_MEMBER_KICKED(MessageType.WARNING, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), - GUILD_MEMBER_ROLE_ADDED(MessageType.WARNING, Category.GUILD, Category.GUILD_MEMBER), - GUILD_MEMBER_ROLE_REMOVED(MessageType.WARNING, Category.GUILD, Category.GUILD_MEMBER), - GUILD_MEMBER_NICKNAME_UPDATED(MessageType.INFO, Category.GUILD, Category.GUILD_MEMBER), - - GUILD_USER_BANNED(MessageType.DANGER, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), - GUILD_USER_UNBANNED(MessageType.DANGER, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), - - GUILD_MESSAGE_DELETED(MessageType.WARNING, Category.GUILD, Category.GUILD_MESSAGE), - GUILD_MESSAGE_DELETED_MENTION(MessageType.INFO, Category.GUILD, Category.GUILD_MESSAGE), - GUILD_MESSAGE_UPDATED(MessageType.INFO, Category.GUILD, Category.GUILD_MESSAGE), - - GUILD_BOOST_COUNT_UPDATED(MessageType.INFO, Category.GUILD, Category.GUILD_BOOST), - GUILD_BOOST_TIER_UPDATED(MessageType.INFO, Category.GUILD, Category.GUILD_BOOST), - - GUILD_UPDATE_AFK_CHANNEL(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_AFK_TIMEOUT(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_BANNER(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_DESCRIPTION(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_EXPLICIT_FILTER(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_FEATURES(MessageType.INFO, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_ICON(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_MAX_MEMBERS(MessageType.INFO, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_MAX_PRESENCES(MessageType.INFO, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_MFA_LEVEL(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_NAME(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_NOTIFICATION_LEVEL(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_REGION(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_SPLASH(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_SYSTEM_CHANNEL(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_VANITY_CODE(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_VERIFICATION_LEVEL(MessageType.WARNING, Category.GUILD, Category.GUILD_SETTINGS), - - VOICE_DEAFEN(MessageType.INFO, Category.VOICE), - VOICE_MUTE(MessageType.INFO, Category.VOICE), - VOICE_SERVER_DEAFEN(MessageType.WARNING, Category.VOICE, Category.MODERATION), - VOICE_SERVER_MUTE(MessageType.WARNING, Category.VOICE, Category.MODERATION), - VOICE_JOIN(MessageType.INFO, Category.VOICE), - VOICE_LEAVE(MessageType.INFO, Category.VOICE), - VOICE_MOVE(MessageType.INFO, Category.VOICE), - VOICE_FORCE_MOVE(MessageType.WARNING, Category.VOICE, Category.MODERATION), - VOICE_DISCONNECT(MessageType.WARNING, Category.VOICE, Category.MODERATION), - - ROLE_CREATED(MessageType.WARNING, Category.ROLE), - ROLE_DELETED(MessageType.WARNING, Category.ROLE), - ROLE_COLOR_UPDATED(MessageType.WARNING, Category.ROLE), - ROLE_HOIST_UPDATED(MessageType.WARNING, Category.ROLE), - ROLE_MENTIONABLE_UPDATED(MessageType.WARNING, Category.ROLE), - ROLE_NAME_UPDATED(MessageType.WARNING, Category.ROLE), - ROLE_PERMISSIONS_UPDATED(MessageType.WARNING, Category.ROLE), - ROLE_POSITION_UPDATED(MessageType.WARNING, Category.ROLE), - - USER_DISCRIMINATOR_UPDATED(MessageType.INFO, Category.USER), - USER_NAME_UPDATED(MessageType.INFO, Category.USER), - - CHANNEL_CREATED(MessageType.WARNING, Category.CHANNEL), - CHANNEL_DELETED(MessageType.WARNING, Category.CHANNEL), - CHANNEL_NAME_UPDATED(MessageType.WARNING, Category.CHANNEL), - CHANNEL_PERMISSIONS_UPDATED(MessageType.WARNING, Category.CHANNEL), - CHANNEL_POSITION_UPDATED(MessageType.WARNING, Category.CHANNEL), - CHANNEL_PARENT_UPDATED(MessageType.WARNING, Category.CHANNEL), - - VOICE_CHANNEL_BITRATE_UPDATED(MessageType.WARNING, Category.CHANNEL), - VOICE_CHANNEL_USER_LIMIT_UPDATED(MessageType.WARNING, Category.CHANNEL), - - TEXT_CHANNEL_NSFW_UPDATED(MessageType.WARNING, Category.CHANNEL), - TEXT_CHANNEL_SLOWMODE_UPDATED(MessageType.WARNING, Category.CHANNEL), - TEXT_CHANNEL_TOPIC_UPDATED(MessageType.WARNING, Category.CHANNEL), - - CASCADE_PERMISSIONS_GROUP_CREATED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_GROUP_DELETED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_GROUP_LINK(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), - - CASCADE_PERMISSIONS_USER_PERMISSION_ADD(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_USER_GROUP_ADD(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_USER_GROUP_REMOVE(MessageType.WARNING, Category.CASCADE, Category.CASCADE_PERMISSIONS), - - CASCADE_SETTINGS_UPDATED(MessageType.WARNING, Category.CASCADE), - - CASCADE_MODULE_UPDATED(MessageType.WARNING, Category.CASCADE), - - CASCADE_COMMAND_RUN(MessageType.INFO, Category.CASCADE), - CASCADE_COMMAND_RUN_ERROR(MessageType.WARNING, Category.CASCADE), - - CASCADE_PLAYLIST_CREATED(MessageType.INFO, Category.CASCADE), - - CASCADE_TEMP_MUTE(MessageType.DANGER, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_TEMP_BAN(MessageType.DANGER, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_SOFT_BAN(MessageType.DANGER, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_PURGE(MessageType.DANGER, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - - CASCADE_WHITELIST(MessageType.WARNING, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_BLACKLIST(MessageType.WARNING, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - - CASCADE_SCRIPT_CREATED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_SCRIPT_DELETED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_SCRIPT_UPDATED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - - CASCADE_TAG_CREATED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_TAG_DELETED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_TAG_UPDATED(MessageType.WARNING, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS); +enum class ModlogEvent(messageType: MessageType, displayType: ModlogDisplayType, vararg categories: Category) { + + EMOTE_CREATED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.EMOTE), + EMOTE_DELETED(MessageType.INFO, ModlogDisplayType.PLAIN, Category.EMOTE), + EMOTE_UPDATED_NAME(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.EMOTE), + EMOTE_UPDATED_ROLES(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.EMOTE), + + GUILD_MEMBER_JOINED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_LEFT(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_KICKED(MessageType.WARNING, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + GUILD_MEMBER_ROLE_ADDED(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_ROLE_REMOVED(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_NICKNAME_UPDATED(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MEMBER), + + GUILD_USER_BANNED(MessageType.DANGER, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + GUILD_USER_UNBANNED(MessageType.DANGER, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + + GUILD_MESSAGE_DELETED(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MESSAGE), + GUILD_MESSAGE_DELETED_MENTION(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MESSAGE), + GUILD_MESSAGE_UPDATED(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MESSAGE), + + GUILD_BOOST_COUNT_UPDATED(MessageType.INFO, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_BOOST), + GUILD_BOOST_TIER_UPDATED(MessageType.INFO, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_BOOST), + + GUILD_UPDATE_AFK_CHANNEL(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_AFK_TIMEOUT(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_BANNER(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_DESCRIPTION(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_EXPLICIT_FILTER(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_FEATURES(MessageType.INFO, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_ICON(MessageType.WARNING, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_MAX_MEMBERS(MessageType.INFO, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_MAX_PRESENCES(MessageType.INFO, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_MFA_LEVEL(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_NAME(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_NOTIFICATION_LEVEL(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_REGION(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_SPLASH(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_SYSTEM_CHANNEL(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_VANITY_CODE(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_VERIFICATION_LEVEL(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), + + VOICE_DEAFEN(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE), + VOICE_MUTE(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE), + VOICE_SERVER_DEAFEN(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE, Category.MODERATION), + VOICE_SERVER_MUTE(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE, Category.MODERATION), + VOICE_JOIN(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE), + VOICE_LEAVE(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE), + VOICE_MOVE(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE), + VOICE_FORCE_MOVE(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE, Category.MODERATION), + VOICE_DISCONNECT(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE, Category.MODERATION), + + ROLE_CREATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_DELETED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_COLOR_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_HOIST_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_MENTIONABLE_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_NAME_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_PERMISSIONS_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_POSITION_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + + USER_DISCRIMINATOR_UPDATED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.USER), + USER_NAME_UPDATED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.USER), + + CHANNEL_CREATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), + CHANNEL_DELETED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), + CHANNEL_NAME_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), + CHANNEL_PERMISSIONS_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), + CHANNEL_POSITION_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), + CHANNEL_PARENT_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), + + VOICE_CHANNEL_BITRATE_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), + VOICE_CHANNEL_USER_LIMIT_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), + + TEXT_CHANNEL_NSFW_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), + TEXT_CHANNEL_SLOWMODE_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), + TEXT_CHANNEL_TOPIC_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), + + CASCADE_PERMISSIONS_GROUP_CREATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_DELETED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_LINK(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), + + CASCADE_PERMISSIONS_USER_PERMISSION_ADD(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_USER_GROUP_ADD(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_USER_GROUP_REMOVE(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), + + CASCADE_SETTINGS_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE), + + CASCADE_MODULE_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE), + + CASCADE_COMMAND_RUN(MessageType.INFO, ModlogDisplayType.PLAIN, Category.CASCADE), + CASCADE_COMMAND_RUN_ERROR(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE), + + CASCADE_PLAYLIST_CREATED(MessageType.INFO, ModlogDisplayType.PLAIN, Category.CASCADE), + + CASCADE_TEMP_MUTE(MessageType.DANGER, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_TEMP_BAN(MessageType.DANGER, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_SOFT_BAN(MessageType.DANGER, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_PURGE(MessageType.DANGER, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + + CASCADE_WHITELIST(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_BLACKLIST(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + + CASCADE_SCRIPT_CREATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_SCRIPT_DELETED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_SCRIPT_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + + CASCADE_TAG_CREATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_TAG_DELETED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_TAG_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS); companion object { private val modlogCategoryMap: MutableMap> = HashMap() @@ -146,6 +146,7 @@ enum class ModlogEvent(messageType: MessageType, vararg categories: Category) { val categories: List val messageType: MessageType + val displayType: ModlogDisplayType enum class Category { ALL, @@ -166,8 +167,15 @@ enum class ModlogEvent(messageType: MessageType, vararg categories: Category) { CASCADE_CUSTOM_COMMANDS } + enum class ModlogDisplayType { + AFFECTED_THUMBNAIL, + AFFECTED_AUTHOR, + PLAIN + } + init { this.categories = Arrays.asList(*categories) this.messageType = messageType + this.displayType = displayType } } \ No newline at end of file From 3f65719d3c621ceafdc1e7e225787a4ad95f4ed5 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 2 Aug 2020 11:14:38 -0500 Subject: [PATCH 058/206] New Display System Also grouping of events --- .../org/cascadebot/cascadebot/CascadeBot.java | 2 - .../events/ModlogEventListener.java | 30 +++---- .../ModlogChannelMoveCollectorRunnable.java | 48 +++++++++-- .../cascadebot/data/objects/Enums.kt | 19 +++- .../data/objects/GuildSettingsModeration.kt | 86 +++++++++---------- .../cascadebot/data/objects/ModlogAffected.kt | 9 ++ .../data/objects/ModlogEventStore.kt | 65 +++++++------- .../cascadebot/moderation/ModlogEvent.kt | 3 + src/main/resources/lang/en-GB.json | 4 + 9 files changed, 161 insertions(+), 105 deletions(-) create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 6e9e5a126..05bc4406a 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -10,8 +10,6 @@ import ch.qos.logback.contrib.json.classic.JsonLayout; import ch.qos.logback.core.ConsoleAppender; import ch.qos.logback.core.encoder.LayoutWrappingEncoder; -import club.minnced.discord.webhook.WebhookClient; -import club.minnced.discord.webhook.WebhookClientBuilder; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory; diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index f6ea11b42..58514c8d7 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -802,22 +802,20 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String } private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, int oldPos, GuildChannel channel) { - ModlogEvent event = ModlogEvent.CHANNEL_POSITION_UPDATED; - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - ModlogUtils.getAuditLogFromType(guild, channel.getIdLong(), auditLogEntry -> { - List embedFieldList = new ArrayList<>(); - User responsible = null; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); - } - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_pos", "modlog.general.variable", String.valueOf(oldPos))); - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.new_pos", "modlog.general.variable", String.valueOf(channel.getPosition()))); - ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); - }, ActionType.CHANNEL_UPDATE); + ModlogChannelMoveCollectorRunnable.ChannelMoveData moveData = + new ModlogChannelMoveCollectorRunnable.ChannelMoveData(type, oldPos, channel); + if (moveRunnableMap.containsKey(guild.getIdLong())) { + moveRunnableMap.get(guild.getIdLong()).getQueue().add(moveData); + } else { + ModlogChannelMoveCollectorRunnable runnable = new ModlogChannelMoveCollectorRunnable(guild, new Runnable() { + @Override + public void run() { + moveRunnableMap.remove(guild.getIdLong()); + } + }); + moveRunnableMap.put(guild.getIdLong(), runnable); + new Thread(runnable, "modlog-channel-move-" + guild.getId()).start(); + } } public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Category oldParent, Category newParent, GuildChannel channel) { diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java index 223704e12..d0ecbb56b 100644 --- a/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java +++ b/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java @@ -5,6 +5,12 @@ import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.GuildChannel; import net.dv8tion.jda.api.entities.User; +import org.cascadebot.cascadebot.data.managers.GuildDataManager; +import org.cascadebot.cascadebot.data.objects.GuildData; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEmbedField; +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.utils.ModlogUtils; import java.util.ArrayList; @@ -17,11 +23,11 @@ public class ModlogChannelMoveCollectorRunnable implements Runnable { private Guild guild; - private Consumer finishedConsumer; + private Runnable finishRunnable; - public ModlogChannelMoveCollectorRunnable(Guild guild, Consumer finishedConsumer) { + public ModlogChannelMoveCollectorRunnable(Guild guild, Runnable finishRunnable) { this.guild = guild; - this.finishedConsumer = finishedConsumer; + this.finishRunnable = finishRunnable; } private BlockingQueue queue = new LinkedBlockingQueue<>(); @@ -45,17 +51,49 @@ public void run() { } private void afterCollected() { - finishedConsumer.accept(null); + finishRunnable.run(); ModlogUtils.getAuditLogFromType(guild, auditLogEntry -> { User responsible = null; if (auditLogEntry != null) { responsible = auditLogEntry.getUser(); } + List embedParts = new ArrayList<>(); + int maxDistance = 0; + List maxMoveDatas = new ArrayList<>(); + for (ChannelMoveData moveData : channelMoveDataList) { + if (moveData == null) { + continue; + } + int distance = moveData.channel.getPosition() - moveData.oldPos; + if (distance == maxDistance) { + maxMoveDatas.add(moveData); + } else if (distance > maxDistance) { + maxMoveDatas = new ArrayList<>(); + maxDistance = distance; + maxMoveDatas.add(moveData); + } + } + + for (ChannelMoveData data : maxMoveDatas) { + ModlogEmbedField field = new ModlogEmbedField(false, "modlog.channel.position.title", + "modlog.channel.position.positions", + String.valueOf(data.oldPos), String.valueOf(data.channel.getPosition())); + field.addTitleObjects(data.channel.getName()); + embedParts.add(field); + } + + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.CHANNEL_POSITION_UPDATED, responsible, maxMoveDatas.get(0).channel, embedParts); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), eventStore); }, ActionType.CHANNEL_UPDATE); } - static class ChannelMoveData { + public BlockingQueue getQueue() { + return queue; + } + + public static class ChannelMoveData { private ChannelType type; private int oldPos; diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt index 739f52b1b..c05b71bf4 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt @@ -1,6 +1,7 @@ package org.cascadebot.cascadebot.data.objects import net.dv8tion.jda.api.entities.User +import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.utils.PurgeUtils enum class PlaylistType { @@ -129,4 +130,20 @@ enum class ArgumentType { * Represents that this is just part of the command and isn't a parameter. */ COMMAND -} \ No newline at end of file +} + +enum class AffectedType(vararg val allowedDisplayTypes: ModlogEvent.ModlogDisplayType) { + UNKNOWN(ModlogEvent.ModlogDisplayType.PLAIN), + USER(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogEvent.ModlogDisplayType.PLAIN), + ROLE(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_FOOTER, ModlogEvent.ModlogDisplayType.PLAIN), + EMOTE(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogEvent.ModlogDisplayType.PLAIN), + GUILD(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_FOOTER, ModlogEvent.ModlogDisplayType.PLAIN), + CHANNEL(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.PLAIN), + GROUP(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.PLAIN), + SETTING(ModlogEvent.ModlogDisplayType.PLAIN), + MODULE(ModlogEvent.ModlogDisplayType.PLAIN), + COMMAND(ModlogEvent.ModlogDisplayType.PLAIN), + PLAYLIST(ModlogEvent.ModlogDisplayType.PLAIN), + TAG(ModlogEvent.ModlogDisplayType.PLAIN); + +} diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 3f9755f38..df5466f0a 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -164,58 +164,50 @@ class GuildSettingsModeration { fun sendEvent(guildData: GuildData, modlogEventStore: ModlogEventStore) { val webhookEmbedBuilder = WebhookEmbedBuilder() webhookEmbedBuilder.setTitle(EmbedTitle(i18n(guildData.locale, "enums.modlogevent." + modlogEventStore.trigger.name.toLowerCase() + ".display"), null)) - val affected: Any = modlogEventStore.affected; - var affectedType = "" - val affectedStr = when (affected) { - is User -> { - affectedType = "User"; - affected.name + " (" + affected.id + ")" + val affected: ModlogAffected = modlogEventStore.affected; + + when (modlogEventStore.trigger.displayType) { + ModlogEvent.ModlogDisplayType.PLAIN -> { + var name = affected.name; + if (affected.id != null) { + name += " (" + affected.id + ")" + } + webhookEmbedBuilder.addField(EmbedField(true, "Affected", name)) } - is Role -> { - affectedType = "Role" - affected.name + " (" + affected.id + ")" + ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL -> { + when (affected.affectedType) { + AffectedType.USER -> { + val user: User = CascadeBot.INS.shardManager.getUserById(affected.id!!)!! + webhookEmbedBuilder.setThumbnailUrl(user.avatarUrl) + webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, null, null)) + } + AffectedType.EMOTE -> { + val emote: Emote = CascadeBot.INS.shardManager.getEmoteById(affected.id!!)!! + webhookEmbedBuilder.setThumbnailUrl(emote.imageUrl) + webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, null, null)) + } + } } - is Emote -> { - affectedType = "Emote" - affected.name + ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR -> { + when (affected.affectedType) { + AffectedType.USER -> { + val user: User = CascadeBot.INS.shardManager.getUserById(affected.id!!)!! + webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, user.avatarUrl, "https://discord.com/users/" + affected.id)) + } + AffectedType.EMOTE -> { + val emote: Emote = CascadeBot.INS.shardManager.getEmoteById(affected.id!!)!! + webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, emote.imageUrl, null)) + } + else -> { + webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, null, null)) + } + } } - is Guild -> { - affectedType = "Guild" - affected.name + ModlogEvent.ModlogDisplayType.AFFECTED_FOOTER -> { + webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter("name: " + affected.name + " id: " + affected.id, null)) } - is GuildChannel -> { - affectedType = "Channel" - affected.name - } - is Group -> { - affectedType = "Group" - affected.name + "(" + affected.id + ")" - } - is Field -> { - affectedType = "Setting" - affected.name - } - is Module -> { - affectedType = "Module" - FormatUtils.formatEnum(affected, guildData.locale) - } - is MainCommand -> { - affectedType = "Command" - affected.command() - } - is Playlist -> { - affectedType = "Playlist" - affected.name - } - is Tag -> { - affectedType = "Tag" - affected.name - } - else -> null - } - if (affectedStr != null) { - webhookEmbedBuilder.addField(EmbedField(true, "Affected $affectedType", affectedStr)) } + for (embedPart in modlogEventStore.extraInfo) { embedPart.build(guildData.locale, webhookEmbedBuilder) } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt new file mode 100644 index 000000000..577feabee --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt @@ -0,0 +1,9 @@ +package org.cascadebot.cascadebot.data.objects + +class ModlogAffected(var affectedType: AffectedType, var name: String, var id : String?) { + + constructor(affectedType: AffectedType, name: String) : this(affectedType, name, null) + + constructor() : this(AffectedType.UNKNOWN, "unknown") + +} diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index b698d2466..eecad98f4 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -3,15 +3,14 @@ package org.cascadebot.cascadebot.data.objects import net.dv8tion.jda.api.entities.Emote import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.entities.GuildChannel -import net.dv8tion.jda.api.entities.ISnowflake import net.dv8tion.jda.api.entities.Role import net.dv8tion.jda.api.entities.User -import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.commandmeta.MainCommand import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.moderation.ModlogEmbedPart import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.permissions.objects.Group +import java.lang.UnsupportedOperationException import java.lang.reflect.Field class ModlogEventStore { @@ -21,72 +20,70 @@ class ModlogEventStore { @Transient var responsible: User? = null - @Transient - var affected: Any = CascadeBot.INS.selfUser + var affected: ModlogAffected = ModlogAffected() var extraInfo: List = ArrayList() - var affectedId: String = "" - var affectedType: String = "" - - var responsibleId: Long = 0; + var responsibleId: Long = 0 constructor(trigger: ModlogEvent, responsible: User?, affected: Any, extraInfo: List) { this.trigger = trigger this.responsible = responsible - this.affected = affected this.extraInfo = extraInfo - affectedType = when (affected) { + var affectedType: AffectedType = AffectedType.UNKNOWN + this.affected = when (affected) { is User -> { - affectedId = affected.id - "User" + affectedType = AffectedType.USER + ModlogAffected(AffectedType.USER, affected.asTag, affected.id) } is Role -> { - affectedId = affected.id - "Role" + affectedType = AffectedType.ROLE + ModlogAffected(AffectedType.ROLE, affected.name, affected.id) } is Emote -> { - affectedId = affected.id - "Emote" + affectedType = AffectedType.EMOTE + ModlogAffected(AffectedType.EMOTE, affected.name, affected.id) } is Guild -> { - affectedId = affected.id - "Guild" + affectedType = AffectedType.GUILD + ModlogAffected(AffectedType.GUILD, affected.name) } is GuildChannel -> { - affectedId = affected.id - "Channel" + affectedType = AffectedType.CHANNEL + ModlogAffected(AffectedType.CHANNEL, affected.name, affected.id) } is Group -> { - affectedId = affected.id - "Group" + affectedType = AffectedType.GROUP + ModlogAffected(AffectedType.GROUP, affected.name, affected.id) } is Field -> { - affectedId = affected.name - "Setting" + affectedType = AffectedType.SETTING + ModlogAffected(AffectedType.SETTING, affected.name) } is Module -> { - affectedId = affected.name.toLowerCase() - "Module" + affectedType = AffectedType.MODULE + ModlogAffected(AffectedType.MODULE, affected.name) } is MainCommand -> { - affectedId = affected.command() - "Command" + affectedType = AffectedType.COMMAND + ModlogAffected(AffectedType.COMMAND, affected.command()) } is Playlist -> { - affectedId = affected.name - "Playlist" + affectedType = AffectedType.PLAYLIST + ModlogAffected(AffectedType.PLAYLIST, affected.name, affected.playlistId.toHexString()) } is Tag -> { - affectedId = affected.name - "Tag" + affectedType = AffectedType.TAG + ModlogAffected(AffectedType.TAG, affected.name) } else -> { - affectedId = "unknown" - "unknown" + ModlogAffected() } } + if (!affectedType.allowedDisplayTypes.contains(trigger.displayType)) { + throw UnsupportedOperationException("This events display type does not support this affected") + } if (responsible != null) { responsibleId = responsible.idLong diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 36f512c30..6ad085693 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -1,5 +1,6 @@ package org.cascadebot.cascadebot.moderation +import de.bild.codec.annotations.Transient import lombok.Getter import org.cascadebot.cascadebot.messaging.MessageType import java.util.ArrayList @@ -145,6 +146,7 @@ enum class ModlogEvent(messageType: MessageType, displayType: ModlogDisplayType, } val categories: List + @Transient val messageType: MessageType val displayType: ModlogDisplayType @@ -170,6 +172,7 @@ enum class ModlogEvent(messageType: MessageType, displayType: ModlogDisplayType, enum class ModlogDisplayType { AFFECTED_THUMBNAIL, AFFECTED_AUTHOR, + AFFECTED_FOOTER, PLAIN } diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 1ee3c4909..4e664fef8 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -2026,6 +2026,10 @@ "old_allow": "Old Allowed permission for {0}", "old_deny": "Old Denied permissions for {0}" }, + "position": { + "title": "Channel {0} moved", + "positions": "{0} -> {1}" + }, "old_parent": "Old Parent", "new_parent": "New Parent", "nsfw": "NSFW", From 9ae52add84cba8ecf44aa94c994b60c20278cf87 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 2 Aug 2020 11:39:16 -0500 Subject: [PATCH 059/206] We can actually save now. Wooo! --- .../cascadebot/cascadebot/data/objects/ModlogEventStore.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index eecad98f4..4d586da5b 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -22,11 +22,11 @@ class ModlogEventStore { var affected: ModlogAffected = ModlogAffected() - var extraInfo: List = ArrayList() + var extraInfo: MutableList = ArrayList() var responsibleId: Long = 0 - constructor(trigger: ModlogEvent, responsible: User?, affected: Any, extraInfo: List) { + constructor(trigger: ModlogEvent, responsible: User?, affected: Any, extraInfo: MutableList) { this.trigger = trigger this.responsible = responsible this.extraInfo = extraInfo From 165d44714f26c8de4b6325ec8754c1d480267123 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 2 Aug 2020 17:44:53 +0100 Subject: [PATCH 060/206] =?UTF-8?q?=F0=9F=91=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 4d586da5b..5e586917f 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -22,7 +22,7 @@ class ModlogEventStore { var affected: ModlogAffected = ModlogAffected() - var extraInfo: MutableList = ArrayList() + var extraInfo: MutableList = mutableListOf() var responsibleId: Long = 0 From 6db14309b81f0aed9e725b800ee122d8d480eb26 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 23 Aug 2020 11:22:09 -0500 Subject: [PATCH 061/206] BEGONE THOT --- .../cascadebot/utils/WeightedListTest.kt | 97 ------------------- 1 file changed, 97 deletions(-) delete mode 100644 src/test/kotlin/org/cascadebot/cascadebot/utils/WeightedListTest.kt diff --git a/src/test/kotlin/org/cascadebot/cascadebot/utils/WeightedListTest.kt b/src/test/kotlin/org/cascadebot/cascadebot/utils/WeightedListTest.kt deleted file mode 100644 index e3960566f..000000000 --- a/src/test/kotlin/org/cascadebot/cascadebot/utils/WeightedListTest.kt +++ /dev/null @@ -1,97 +0,0 @@ -package org.cascadebot.cascadebot.utils - -import org.cascadebot.cascadebot.utils.lists.WeightedList -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.CsvSource -import kotlin.math.abs - -class WeightedListTest { - - @Test - fun `Test adding same items`() { - val list = WeightedList() - list.add("hi", 2) - list.add("hi", 3) - assertEquals(1, list.items.size) - assertEquals(5, list.getItemWeight(0)) - } - - @Test - fun `Test item proportion - 2 items`() { - - val proportions = mapOf( - Pair(Pair(2, 2), Pair(0.5, 0.5)), - Pair(Pair(2, 3), Pair(2.0 / 5.0, 3.0 / 5.0)), - Pair(Pair(2, 6), Pair(0.25, 0.75)), - Pair(Pair(2, 8), Pair(0.2, 0.8)), - Pair(Pair(4, 6), Pair(0.4, 0.6)) - ) - - for ((items, outputs) in proportions) { - val list = WeightedList() - list.add("item1", items.first) - list.add("item2", items.second) - assertEquals(2, list.items.size) - assertEquals(outputs.first, list.getItemProportion(0)) - assertEquals(outputs.second, list.getItemProportion(1)) - } - - } - - @Test - fun `Test item proportion - 3 items`() { - - val proportions = mapOf( - Pair(Triple(2, 2, 2), Triple(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)), - Pair(Triple(2, 3, 3), Triple(0.25, 3.0 / 8.0, 3.0 / 8.0)), - Pair(Triple(3, 4, 3), Triple(0.3, 0.4, 0.3)), - Pair(Triple(1, 1, 1), Triple(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)), - Pair(Triple(4, 4, 8), Triple(0.25, 0.25, 0.5)) - ) - - for ((items, outputs) in proportions) { - val list = WeightedList() - list.add("item1", items.first) - list.add("item2", items.second) - list.add("item3", items.third) - assertEquals(3, list.items.size) - assertEquals(outputs.first, list.getItemProportion(0)) - assertEquals(outputs.second, list.getItemProportion(1)) - assertEquals(outputs.third, list.getItemProportion(2)) - } - - } - - @DisplayName("Test random selection") - @ParameterizedTest(name = "Repeat count of {0} with threshold of {1}") - @CsvSource( - "100,0.05", - "1000,0.025", - "10000,0.01" - ) - fun `Test random selection`(repeatCount: Int, threshold: Double) { - val list = WeightedList() - list.add("10%", 1) - list.add("90%", 9) - - val outputItems = mutableListOf() - - repeat(repeatCount) { - list.randomItem?.let { randomItem -> outputItems.add(randomItem) } - } - - val ten = outputItems.count { it == "10%" } - val ninety = outputItems.count { it == "90%" } - - val tenPercentage = ten.toDouble() / repeatCount.toDouble() - val ninetyPercentage = ninety.toDouble() / repeatCount.toDouble() - - assert(abs(0.1 - tenPercentage) <= threshold) - assert(abs(0.9 - ninetyPercentage) <= threshold) - } - - -} \ No newline at end of file From 58ac8f8c0aae9d77504a85fb62359810a7bc6db3 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 23 Aug 2020 11:22:09 -0500 Subject: [PATCH 062/206] Revert "BEGONE THOT" This reverts commit 6db14309b81f0aed9e725b800ee122d8d480eb26. --- .../cascadebot/utils/WeightedListTest.kt | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/test/kotlin/org/cascadebot/cascadebot/utils/WeightedListTest.kt diff --git a/src/test/kotlin/org/cascadebot/cascadebot/utils/WeightedListTest.kt b/src/test/kotlin/org/cascadebot/cascadebot/utils/WeightedListTest.kt new file mode 100644 index 000000000..e3960566f --- /dev/null +++ b/src/test/kotlin/org/cascadebot/cascadebot/utils/WeightedListTest.kt @@ -0,0 +1,97 @@ +package org.cascadebot.cascadebot.utils + +import org.cascadebot.cascadebot.utils.lists.WeightedList +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.CsvSource +import kotlin.math.abs + +class WeightedListTest { + + @Test + fun `Test adding same items`() { + val list = WeightedList() + list.add("hi", 2) + list.add("hi", 3) + assertEquals(1, list.items.size) + assertEquals(5, list.getItemWeight(0)) + } + + @Test + fun `Test item proportion - 2 items`() { + + val proportions = mapOf( + Pair(Pair(2, 2), Pair(0.5, 0.5)), + Pair(Pair(2, 3), Pair(2.0 / 5.0, 3.0 / 5.0)), + Pair(Pair(2, 6), Pair(0.25, 0.75)), + Pair(Pair(2, 8), Pair(0.2, 0.8)), + Pair(Pair(4, 6), Pair(0.4, 0.6)) + ) + + for ((items, outputs) in proportions) { + val list = WeightedList() + list.add("item1", items.first) + list.add("item2", items.second) + assertEquals(2, list.items.size) + assertEquals(outputs.first, list.getItemProportion(0)) + assertEquals(outputs.second, list.getItemProportion(1)) + } + + } + + @Test + fun `Test item proportion - 3 items`() { + + val proportions = mapOf( + Pair(Triple(2, 2, 2), Triple(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)), + Pair(Triple(2, 3, 3), Triple(0.25, 3.0 / 8.0, 3.0 / 8.0)), + Pair(Triple(3, 4, 3), Triple(0.3, 0.4, 0.3)), + Pair(Triple(1, 1, 1), Triple(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)), + Pair(Triple(4, 4, 8), Triple(0.25, 0.25, 0.5)) + ) + + for ((items, outputs) in proportions) { + val list = WeightedList() + list.add("item1", items.first) + list.add("item2", items.second) + list.add("item3", items.third) + assertEquals(3, list.items.size) + assertEquals(outputs.first, list.getItemProportion(0)) + assertEquals(outputs.second, list.getItemProportion(1)) + assertEquals(outputs.third, list.getItemProportion(2)) + } + + } + + @DisplayName("Test random selection") + @ParameterizedTest(name = "Repeat count of {0} with threshold of {1}") + @CsvSource( + "100,0.05", + "1000,0.025", + "10000,0.01" + ) + fun `Test random selection`(repeatCount: Int, threshold: Double) { + val list = WeightedList() + list.add("10%", 1) + list.add("90%", 9) + + val outputItems = mutableListOf() + + repeat(repeatCount) { + list.randomItem?.let { randomItem -> outputItems.add(randomItem) } + } + + val ten = outputItems.count { it == "10%" } + val ninety = outputItems.count { it == "90%" } + + val tenPercentage = ten.toDouble() / repeatCount.toDouble() + val ninetyPercentage = ninety.toDouble() / repeatCount.toDouble() + + assert(abs(0.1 - tenPercentage) <= threshold) + assert(abs(0.9 - ninetyPercentage) <= threshold) + } + + +} \ No newline at end of file From 1928a11ae1da0227201b9fee1df724130fbd90f4 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 23 Aug 2020 11:24:15 -0500 Subject: [PATCH 063/206] BEGONE THOT (better) --- .../cascadebot/utils/WeightedListTest.kt | 31 +------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/src/test/kotlin/org/cascadebot/cascadebot/utils/WeightedListTest.kt b/src/test/kotlin/org/cascadebot/cascadebot/utils/WeightedListTest.kt index e3960566f..208682a52 100644 --- a/src/test/kotlin/org/cascadebot/cascadebot/utils/WeightedListTest.kt +++ b/src/test/kotlin/org/cascadebot/cascadebot/utils/WeightedListTest.kt @@ -64,34 +64,5 @@ class WeightedListTest { } } - - @DisplayName("Test random selection") - @ParameterizedTest(name = "Repeat count of {0} with threshold of {1}") - @CsvSource( - "100,0.05", - "1000,0.025", - "10000,0.01" - ) - fun `Test random selection`(repeatCount: Int, threshold: Double) { - val list = WeightedList() - list.add("10%", 1) - list.add("90%", 9) - - val outputItems = mutableListOf() - - repeat(repeatCount) { - list.randomItem?.let { randomItem -> outputItems.add(randomItem) } - } - - val ten = outputItems.count { it == "10%" } - val ninety = outputItems.count { it == "90%" } - - val tenPercentage = ten.toDouble() / repeatCount.toDouble() - val ninetyPercentage = ninety.toDouble() / repeatCount.toDouble() - - assert(abs(0.1 - tenPercentage) <= threshold) - assert(abs(0.9 - ninetyPercentage) <= threshold) - } - - + } \ No newline at end of file From 4e2768ebe164f81394dac7d5e3810c18a51f7c49 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 20 Sep 2020 13:51:23 -0500 Subject: [PATCH 064/206] Fix merge --- .../cascadebot/data/objects/GuildSettingsModeration.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index df5466f0a..ad6fdb560 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -41,6 +41,9 @@ class GuildSettingsModeration { @Setting private val respectBanOrKickHierarchy = true + @Setting + var muteRoleName = "Muted" + fun getRespectBanOrKickHierarchy(): Boolean { return respectBanOrKickHierarchy } From 043ba65bf6ac26292f8fc24355d48227e544f5eb Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 11 Oct 2020 10:24:50 -0500 Subject: [PATCH 065/206] General event work to make them look nicer --- .../events/ModlogEventListener.java | 17 +- .../cascadebot/data/objects/Enums.kt | 4 +- .../data/objects/GuildSettingsModeration.kt | 27 ++- .../cascadebot/moderation/ModlogEvent.kt | 1 - src/main/resources/lang/en-GB.json | 185 ++++++++++++------ 5 files changed, 153 insertions(+), 81 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 58514c8d7..69f3dc97d 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -106,6 +106,7 @@ import org.cascadebot.cascadebot.data.managers.GuildDataManager; import org.cascadebot.cascadebot.data.objects.GuildData; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEmbedDescription; import org.cascadebot.cascadebot.moderation.ModlogEmbedField; import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; @@ -193,14 +194,14 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { User responsible = null; if (event instanceof GuildMemberJoinEvent) { modlogEvent = ModlogEvent.GUILD_MEMBER_JOINED; + embedFieldList.add(new ModlogEmbedDescription("modlog.member.joined", user.getAsMention())); } else if (event instanceof GuildMemberLeaveEvent) { - if (auditLogEntry != null) { - ModlogEmbedField respModlogEmbedField = new ModlogEmbedField(true, "modlog.general.responsible", "modlog.general.variable"); - respModlogEmbedField.addValueObjects(Objects.requireNonNull(auditLogEntry.getUser()).getAsTag()); - embedFieldList.add(respModlogEmbedField); + if (auditLogEntry != null && auditLogEntry.getType().equals(ActionType.KICK)) { + responsible = auditLogEntry.getUser(); + embedFieldList.add(new ModlogEmbedDescription("modlog.member.kicked", user.getAsMention())); if (auditLogEntry.getReason() != null) { ModlogEmbedField reasonEmbedField = new ModlogEmbedField(false, "modlog.general.reason", "modlog.general.variable"); - respModlogEmbedField.addValueObjects(auditLogEntry.getReason()); + reasonEmbedField.addValueObjects(auditLogEntry.getReason()); embedFieldList.add(reasonEmbedField); } modlogEvent = ModlogEvent.GUILD_MEMBER_KICKED; @@ -254,6 +255,7 @@ public void onGuildBan(GuildBanEvent event) { User responsible = null; if (auditLogEntry != null) { responsible = auditLogEntry.getUser(); + embedFieldList.add(new ModlogEmbedDescription("modlog.member.banned", user.getAsMention())); if (auditLogEntry.getReason() != null) { ModlogEmbedField reasonEmbedField = new ModlogEmbedField(false, "modlog.general.reason", "modlog.general.variable"); reasonEmbedField.addValueObjects(auditLogEntry.getReason()); @@ -894,9 +896,8 @@ public void onGenericRole(GenericRoleEvent event) { //region Username updates public void onUserUpdateName(UserUpdateNameEvent event) { - // TODO propagate to guilds List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", "modlog.general.variable", event.getOldName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.general.name", "modlog.general.small_change", event.getOldName(), event.getNewName())); ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_NAME_UPDATED, event.getUser(), event.getUser(), embedFieldList); for (Guild guild : CascadeBot.INS.getClient().getMutualGuilds(event.getUser())) { GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); @@ -906,7 +907,7 @@ public void onUserUpdateName(UserUpdateNameEvent event) { public void onUserUpdateDiscriminator(UserUpdateDiscriminatorEvent event) { List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(true, "modlog.user.old_discrim", "modlog.general.variable", event.getOldDiscriminator())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.member.discrim", "modlog.general.small_change", event.getOldDiscriminator(), event.getNewDiscriminator())); ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_DISCRIMINATOR_UPDATED, event.getUser(), event.getUser(), embedFieldList); for (Guild guild : CascadeBot.INS.getClient().getMutualGuilds(event.getUser())) { GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt index c05b71bf4..c61a5f257 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt @@ -135,9 +135,9 @@ enum class ArgumentType { enum class AffectedType(vararg val allowedDisplayTypes: ModlogEvent.ModlogDisplayType) { UNKNOWN(ModlogEvent.ModlogDisplayType.PLAIN), USER(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogEvent.ModlogDisplayType.PLAIN), - ROLE(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_FOOTER, ModlogEvent.ModlogDisplayType.PLAIN), + ROLE(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogEvent.ModlogDisplayType.PLAIN), EMOTE(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogEvent.ModlogDisplayType.PLAIN), - GUILD(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_FOOTER, ModlogEvent.ModlogDisplayType.PLAIN), + GUILD(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogEvent.ModlogDisplayType.PLAIN), CHANNEL(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.PLAIN), GROUP(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.PLAIN), SETTING(ModlogEvent.ModlogDisplayType.PLAIN), diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index ad6fdb560..16955e3ad 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -26,6 +26,8 @@ import org.cascadebot.cascadebot.permissions.objects.Group import org.cascadebot.cascadebot.utils.FormatUtils import java.lang.reflect.Field import java.net.URL +import java.time.Instant +import java.time.temporal.TemporalAccessor import java.util.ArrayList import java.util.Date import java.util.function.Consumer @@ -181,8 +183,11 @@ class GuildSettingsModeration { when (affected.affectedType) { AffectedType.USER -> { val user: User = CascadeBot.INS.shardManager.getUserById(affected.id!!)!! - webhookEmbedBuilder.setThumbnailUrl(user.avatarUrl) - webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, null, null)) + if (user.avatarUrl != null) { + webhookEmbedBuilder.setThumbnailUrl(user.avatarUrl) + } else { + webhookEmbedBuilder.setThumbnailUrl(user.defaultAvatarUrl) + } } AffectedType.EMOTE -> { val emote: Emote = CascadeBot.INS.shardManager.getEmoteById(affected.id!!)!! @@ -195,7 +200,12 @@ class GuildSettingsModeration { when (affected.affectedType) { AffectedType.USER -> { val user: User = CascadeBot.INS.shardManager.getUserById(affected.id!!)!! - webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, user.avatarUrl, "https://discord.com/users/" + affected.id)) + var iconUrl = if (user.avatarUrl != null) { + user.avatarUrl + } else { + user.defaultAvatarUrl + } + webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, iconUrl, "https://discord.com/users/" + affected.id)) } AffectedType.EMOTE -> { val emote: Emote = CascadeBot.INS.shardManager.getEmoteById(affected.id!!)!! @@ -206,17 +216,20 @@ class GuildSettingsModeration { } } } - ModlogEvent.ModlogDisplayType.AFFECTED_FOOTER -> { - webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter("name: " + affected.name + " id: " + affected.id, null)) - } } for (embedPart in modlogEventStore.extraInfo) { embedPart.build(guildData.locale, webhookEmbedBuilder) } webhookEmbedBuilder.setColor(modlogEventStore.trigger.messageType.color.rgb) + webhookEmbedBuilder.setTimestamp(Instant.now()) if (modlogEventStore.responsible != null) { - webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventStore.responsible!!.name + " (" + modlogEventStore.responsible!!.id + ")", null)) + var iconUrl = if (modlogEventStore.responsible!!.avatarUrl != null) { + modlogEventStore.responsible!!.avatarUrl + } else { + modlogEventStore.responsible!!.defaultAvatarUrl + } + webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventStore.responsible!!.name + " (" + modlogEventStore.responsible!!.id + ")", iconUrl)) } try { webhookClient?.send(webhookEmbedBuilder.build()) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 6ad085693..52bf19d1a 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -172,7 +172,6 @@ enum class ModlogEvent(messageType: MessageType, displayType: ModlogDisplayType, enum class ModlogDisplayType { AFFECTED_THUMBNAIL, AFFECTED_AUTHOR, - AFFECTED_FOOTER, PLAIN } diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 407487262..e8c9f3d95 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1362,139 +1362,173 @@ "modlogevent": { "emote_created": { "select": "emote_created", - "display": "Emote created" + "display": "Emote created", + "description": "Emote `{0}` was created" }, "emote_deleted": { "select": "emote_deleted", - "display": "Emote deleted" + "display": "Emote deleted", + "description": "Emote `{0}` was deleted" }, "emote_updated_name": { "select": "emote_updated_name", - "display": "Emote updated name" + "display": "Emote updated name", + "description": "Emote name changed" }, "emote_updated_roles": { "select": "emote_updated_roles", - "display": "Emote updated roles" + "display": "Emote updated roles", + "description": "Emote `{0}` roles where changed" }, "guild_member_joined": { "select": "guild_member_joined", - "display": "Guild member joined" + "display": "Guild member joined", + "description": "{0} joined the server" }, "guild_member_left": { "select": "guild_member_left", - "display": "Guild member left" + "display": "Guild member left", + "description": "{0} left the server" }, "guild_member_kicked": { "select": "guild_member_kicked", - "display": "Guild member kicked" + "display": "Guild member kicked", + "description": "{0} was kicked" }, "guild_member_role_added": { "select": "guild_member_role_added", - "display": "Guild member role added" + "display": "Guild member role added", + "description": "Role(s) where added to {0}" }, "guild_member_role_removed": { "select": "guild_member_role_removed", - "display": "Guild member role removed" + "display": "Guild member role removed", + "description": "Role(s) where removed from {0}" }, "guild_member_nickname_updated": { "select": "guild_member_nickname_updated", - "display": "Guild member nickname updated" + "display": "Guild member nickname updated", + "description": "{0} updated there nickanme" }, "guild_user_banned": { "select": "guild_user_banned", - "display": "Guild user banned" + "display": "Guild user banned", + "description": "{0} was banned" }, "guild_user_unbanned": { "select": "guild_user_unbanned", - "display": "Guild user unbanned" + "display": "Guild user unbanned", + "description": "{0} was unbanned" }, "guild_message_deleted": { "select": "guild_message_deleted", - "display": "Guild message deleted" + "display": "Guild message deleted", + "description": "{1} deleted a message sent by {0}" }, "guild_message_deleted_self": { "select": "guild_message_deleted_self", - "display": "Guild message deleted self" + "display": "Guild message deleted self", + "description": "{0} deleted one of their own messages" }, "guild_message_updated": { "select": "guild_message_updated", - "display": "Guild message updated" + "display": "Guild message updated", + "description": "{0} changed there message" }, "guild_boost_count_updated": { "select": "guild_boost_count_updated", - "display": "Guild boost count updated" + "display": "Guild boost count updated", + "description": "Server boost count changed" }, "guild_boost_tier_updated": { "select": "guild_boost_tier_updated", - "display": "Guild boost tier updated" + "display": "Guild boost tier updated", + "description": "Server bost teir changed" }, "guild_update_afk_channel": { "select": "guild_update_afk_channel", - "display": "Guild update afk channel" + "display": "Guild update afk channel", + "description": "Afk channel changed" }, "guild_update_afk_timeout": { "select": "guild_update_afk_timeout", - "display": "Guild update afk timeout" + "display": "Guild update afk timeout", + "description": "Aft timeout changed" }, "guild_update_banner": { "select": "guild_update_banner", - "display": "Guild update banner" + "display": "Guild update banner", + "description": "Server banner changed" }, "guild_update_description": { "select": "guild_update_description", - "display": "Guild update description" + "display": "Guild update description", + "description": "Server description changed" }, "guild_update_explicit_filter": { "select": "guild_update_explicit_filter", - "display": "Guild update explicit filter" + "display": "Guild update explicit filter", + "description": "Explicit content filter changed" }, "guild_update_features": { "select": "guild_update_features", - "display": "Guild update features" + "display": "Guild update features", + "description": "Server featured changed" }, "guild_update_icon": { "select": "guild_update_icon", - "display": "Guild update icon" + "display": "Guild update icon", + "description": "Server icon changed" }, "guild_update_max_members": { "select": "guild_update_max_members", - "display": "Guild update max members" + "display": "Guild update max members", + "description": "Server max members changed" }, "guild_update_max_presences": { "select": "guild_update_max_presences", - "display": "Guild update max presences" + "display": "Guild update max presences", + "description": "Server max presences changed" }, "guild_update_mfa_level": { "select": "guild_update_mfa_level", - "display": "Guild update mfa level" + "display": "Guild update mfa level", + "description": "Server multi factor authentication level changed" }, "guild_update_name": { "select": "guild_update_name", - "display": "Guild update name" + "display": "Guild update name", + "description": "Server name changed" }, "guild_update_notification_level": { "select": "guild_update_notification_level", - "display": "Guild update notification level" + "display": "Guild update notification level", + "description": "Server notification level changed" }, "guild_update_region": { "select": "guild_update_region", - "display": "Guild update region" + "display": "Guild update region", + "description": "Server voce region changed" }, "guild_update_splash": { "select": "guild_update_splash", - "display": "Guild update splash" + "display": "Guild update splash", + "description": "Server splash changed" }, "guild_update_system_channel": { "select": "guild_update_system_channel", - "display": "Guild update system channel" + "display": "Guild update system channel", + "description": "Server update system channel changed" }, "guild_update_vanity_code": { "select": "guild_update_vanity_code", - "display": "Guild update vanity code" + "display": "Guild update vanity code", + "description": "Server vanity code changed" }, "guild_update_verification_level": { "select": "guild_update_verification_level", - "display": "Guild update verification level" + "display": "Guild update verification level", + "description": "Server verification level changed" }, "voice_deafen": { "select": "voice_deafen", @@ -1506,7 +1540,7 @@ }, "voice_server_deafen": { "select": "voice_server_deafen", - "display": "Voice server deafen" + "display": "Voice server deafen", }, "voice_server_mute": { "select": "voice_server_mute", @@ -1514,35 +1548,42 @@ }, "voice_join": { "select": "voice_join", - "display": "Voice join" + "display": "Voice join", + "description": "{0} joined {2}" }, "voice_leave": { "select": "voice_leave", - "display": "Voice leave" + "display": "Voice leave", + "description": "{0} left {2}" }, "voice_move": { "select": "voice_move", - "display": "Voice move" + "display": "Voice move", + "description": "{0} moved from {2} to {3}" }, "voice_disconnect": { "select": "voice_disconnect", - "display": "Voice disconnect" + "display": "Voice disconnect", + "description": "{0} disconnected from voice" }, "role_created": { "select": "role_created", - "display": "Role created" + "display": "Role created", + "description": "{1} created a new role called {0}" }, "role_deleted": { "select": "role_deleted", - "display": "Role deleted" + "display": "Role deleted", + "description": "{1} deleted the role called {0}" }, "role_color_updated": { "select": "role_color_updated", - "display": "Role color updated" + "display": "Role color updated", + "description": "Role {0} color was updated" }, "role_hoist_updated": { "select": "role_hoist_updated", - "display": "Role hoist updated" + "display": "Role hoisted updated" }, "role_mentionable_updated": { "select": "role_mentionable_updated", @@ -1550,55 +1591,68 @@ }, "role_name_updated": { "select": "role_name_updated", - "display": "Role name updated" + "display": "Role name updated", + "description": "Role {0} had its name changed" }, "role_permissions_updated": { "select": "role_permissions_updated", - "display": "Role permissions updated" + "display": "Role permissions updated", + "description": "Role {0} had permissions updated" }, "role_position_updated": { "select": "role_position_updated", - "display": "Role position updated" + "display": "Role position updated", + "description": "Role {0} possition was updated" }, "user_discriminator_updated": { "select": "user_discriminator_updated", - "display": "User discriminator updated" + "display": "User discriminator updated", + "description": "User {0} changed there discriminator" }, "user_name_updated": { "select": "user_name_updated", - "display": "User name updated" + "display": "User name updated", + "description": "{0} changed there name" }, "channel_created": { "select": "channel_created", - "display": "Channel created" + "display": "Channel created", + "description": "Channel {0} was created" }, "channel_deleted": { "select": "channel_deleted", - "display": "Channel deleted" + "display": "Channel deleted", + "description": "Channel {0} was deleted" }, "channel_name_updated": { "select": "channel_name_updated", - "display": "Channel name updated" + "display": "Channel name updated", + "description": "Channel {0} had its name changed" }, "channel_permissions_updated": { "select": "channel_permissions_updated", - "display": "Channel permissions updated" + "display": "Channel permissions updated", + "description": "Channel {0} permissions where changed" }, "channel_position_updated": { "select": "channel_position_updated", - "display": "Channel position updated" + "display": "Channel position updated", + "description": "Channel {0} was moved" }, "channel_parent_updated": { "select": "channel_parent_updated", - "display": "Channel parent updated" + "display": "Channel parent updated", + "description": "Channel {0} changed category" }, "voice_channel_bitrate_updated": { "select": "voice_channel_bitrate_updated", - "display": "Voice channel bitrate updated" + "display": "Voice channel bitrate updated", + "description": "Channel {0} had its bitrate changed" }, "voice_channel_user_limit_updated": { "select": "voice_channel_user_limit_updated", - "display": "Voice channel user limit updated" + "display": "Voice channel user limit updated", + "description": "Channel {0} user limit was changed" }, "text_channel_nsfw_updated": { "select": "text_channel_nsfw_updated", @@ -1606,11 +1660,13 @@ }, "text_channel_slowmode_updated": { "select": "text_channel_slowmode_updated", - "display": "Text channel slowmode updated" + "display": "Text channel slowmode updated", + "description": "Channel {0} slowmode time was changed" }, "text_channel_topic_updated": { "select": "text_channel_topic_updated", - "display": "Text channel topic updated" + "display": "Text channel topic updated", + "description": "Channel {0} topic was updated" }, "cascade_permissions_group_created": { "select": "cascade_permissions_group_created", @@ -2213,11 +2269,17 @@ "added_roles": "Added Roles", "removed_roles": "Removed Roles", "old_pos": "Old Position", - "new_pos": "New Position" + "new_pos": "New Position", + "name": "Name", + "small_change": "{0} --> {1}" }, "member": { "old_nick": "Old Nickname", - "new_nick": "New Nickname" + "new_nick": "New Nickname", + "kicked": "{0} was kicked", + "banned": "{0} was banned", + "joined": "{0} joined the server", + "discrim": "Discriminator" }, "message": { "message": "Message", @@ -2340,9 +2402,6 @@ "added_perm": "Added Permissions", "removed_perm": "Removed Permissions" }, - "user": { - "old_discrim": "Old Discriminator" - }, "voice": { "deafen": "Deafened", "mute": "Muted", From da50127f47dcb0c4fc33afc57fd637cd247c0ac5 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 25 Oct 2020 22:26:51 +0000 Subject: [PATCH 066/206] Descriptions! --- .../data/objects/GuildSettingsModeration.kt | 32 ++++++++++++------- .../data/objects/ModlogEventStore.kt | 1 + 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 16955e3ad..0fa4627f7 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -9,25 +9,18 @@ import club.minnced.discord.webhook.send.WebhookEmbed.EmbedTitle import club.minnced.discord.webhook.send.WebhookEmbedBuilder import de.bild.codec.annotations.Transient import net.dv8tion.jda.api.entities.Emote -import net.dv8tion.jda.api.entities.Guild -import net.dv8tion.jda.api.entities.GuildChannel import net.dv8tion.jda.api.entities.Icon -import net.dv8tion.jda.api.entities.Role import net.dv8tion.jda.api.entities.TextChannel import net.dv8tion.jda.api.entities.User import org.cascadebot.cascadebot.CascadeBot -import org.cascadebot.cascadebot.commandmeta.MainCommand import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.database.DebugLogCallback -import org.cascadebot.cascadebot.data.language.Language.i18n +import org.cascadebot.cascadebot.data.language.Language import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.moderation.ModlogEvent -import org.cascadebot.cascadebot.permissions.objects.Group -import org.cascadebot.cascadebot.utils.FormatUtils -import java.lang.reflect.Field +import org.cascadebot.cascadebot.utils.toCapitalized import java.net.URL import java.time.Instant -import java.time.temporal.TemporalAccessor import java.util.ArrayList import java.util.Date import java.util.function.Consumer @@ -168,11 +161,27 @@ class GuildSettingsModeration { fun sendEvent(guildData: GuildData, modlogEventStore: ModlogEventStore) { val webhookEmbedBuilder = WebhookEmbedBuilder() - webhookEmbedBuilder.setTitle(EmbedTitle(i18n(guildData.locale, "enums.modlogevent." + modlogEventStore.trigger.name.toLowerCase() + ".display"), null)) + + val path = "enums.modlogevent.${modlogEventStore.trigger.name.toLowerCase()}.description" + val element = Language.getLanguageOrDefault(guildData.locale).getElement(path) + + if (element.isPresent) { + webhookEmbedBuilder.setDescription( + Language.i18n( + guildData.locale, + path, + modlogEventStore.affected.name, + modlogEventStore.responsible?.asTag ?: Language.i18n(guildData.locale, "words.unknown").toCapitalized(), + *modlogEventStore.extraDescriptionInfo.toTypedArray() + ) + ) + } + + webhookEmbedBuilder.setTitle(EmbedTitle(Language.i18n(guildData.locale, "enums.modlogevent." + modlogEventStore.trigger.name.toLowerCase() + ".display"), null)) val affected: ModlogAffected = modlogEventStore.affected; when (modlogEventStore.trigger.displayType) { - ModlogEvent.ModlogDisplayType.PLAIN -> { + ModlogEvent.ModlogDisplayType.AFFECTED -> { var name = affected.name; if (affected.id != null) { name += " (" + affected.id + ")" @@ -192,7 +201,6 @@ class GuildSettingsModeration { AffectedType.EMOTE -> { val emote: Emote = CascadeBot.INS.shardManager.getEmoteById(affected.id!!)!! webhookEmbedBuilder.setThumbnailUrl(emote.imageUrl) - webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, null, null)) } } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 5e586917f..92b62dfbb 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -23,6 +23,7 @@ class ModlogEventStore { var affected: ModlogAffected = ModlogAffected() var extraInfo: MutableList = mutableListOf() + var extraDescriptionInfo: MutableList = mutableListOf() var responsibleId: Long = 0 From 789d465640b2083e9515787d676ca5259b6f6537 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 25 Oct 2020 22:27:30 +0000 Subject: [PATCH 067/206] Lengthen time offset for audit log entry checking --- .../java/org/cascadebot/cascadebot/utils/ModlogUtils.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java index d74f16faf..af5213c0b 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java @@ -23,12 +23,13 @@ public static void getAuditLogFromType(Guild guild, long targetId, Consumer { + var startTime = OffsetDateTime.now(); for (AuditLogEntry entry : auditLogEntries) { - long millis = Duration.between(entry.getTimeCreated(), OffsetDateTime.now()).toMillis(); + long millis = Duration.between(entry.getTimeCreated(), startTime).toMillis(); if (!actionTypeList.contains(entry.getType())) { continue; } - if (millis > 1000l) { + if (millis > 5000l) { continue; } if (targetId != -1) { From 47d4c6a78af0c921983ec24e1417de5aaaff0a1a Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 25 Oct 2020 22:27:38 +0000 Subject: [PATCH 068/206] Add a default util --- .../org/cascadebot/cascadebot/data/language/Language.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/language/Language.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/language/Language.kt index fe16ec5dd..84ca7d68f 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/language/Language.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/language/Language.kt @@ -50,6 +50,11 @@ object Language { return languages[locale] } + @JvmStatic + fun getLanguageOrDefault(locale: Locale): JSONConfig { + return languages[locale] ?: languages[Locale.getDefaultLocale()]!! + } + @JvmStatic fun hasLanguageEntry(locale: Locale, path: String?): Boolean { return languages.containsKey(locale) && languages[locale]!!.getString(path).isPresent From bee2bc164f9e93ba39a75a086b4ac8ddd15fc724 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 25 Oct 2020 22:28:18 +0000 Subject: [PATCH 069/206] Kotlinize --- .../cascadebot/moderation/ModlogEmbedPart.kt | 46 ++++++------------- .../cascadebot/moderation/ModlogEvent.kt | 20 +++----- 2 files changed, 20 insertions(+), 46 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt index 73e093b5f..6961e708b 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt @@ -11,24 +11,14 @@ sealed class ModlogEmbedPart { } -class ModlogEmbedField() : ModlogEmbedPart() { +class ModlogEmbedField(val inline: Boolean = true, + val titleLanguagePath: String, + var valueLanguagePath: String? = null, vararg valueLanguageObjects: String) : ModlogEmbedPart() { - var inline: Boolean = false + constructor() : this(true, "", "") - var titleLanguagePath: String = "" - var titleLanguageObjects: MutableList = ArrayList() - - var valueLanguagePath: String = "" - var valueLanguageObjects: MutableList = ArrayList() - - constructor(inline: Boolean = true, - titleLanguagePath: String, - valueLanguagePath: String, vararg valueLanguageObjects: String): this() { - this.inline = inline; - this.titleLanguagePath = titleLanguagePath - this.valueLanguagePath = valueLanguagePath - this.valueLanguageObjects.addAll(valueLanguageObjects) - } + val titleLanguageObjects: MutableList = mutableListOf() + val valueLanguageObjects: MutableList = mutableListOf(*valueLanguageObjects) fun addTitleObjects(vararg titleLanguageObjects: String) { this.titleLanguageObjects.addAll(titleLanguageObjects) @@ -41,20 +31,16 @@ class ModlogEmbedField() : ModlogEmbedPart() { override fun build(locale: Locale, embedBuilder: WebhookEmbedBuilder) { embedBuilder.addField(WebhookEmbed.EmbedField(inline, Language.i18n(locale, titleLanguagePath, *titleLanguageObjects.toTypedArray()), - Language.i18n(locale, valueLanguagePath, *valueLanguageObjects.toTypedArray()))) + Language.i18n(locale, valueLanguagePath ?: "modlog.general.variable", *valueLanguageObjects.toTypedArray()))) } } -class ModlogEmbedDescription() : ModlogEmbedPart() { +class ModlogEmbedDescription(val languagePath: String, vararg languageObjects: String) : ModlogEmbedPart() { - var languagePath: String = "" - var languageObjects: MutableList = ArrayList() + constructor() : this("") - constructor(languagePath: String, vararg languageObjects: String): this() { - this.languagePath = languagePath - this.languageObjects.addAll(languageObjects) - } + var languageObjects: MutableList = mutableListOf(*languageObjects) override fun build(locale: Locale, embedBuilder: WebhookEmbedBuilder) { embedBuilder.setDescription(Language.i18n(locale, languagePath, *languageObjects.toTypedArray())) @@ -62,17 +48,11 @@ class ModlogEmbedDescription() : ModlogEmbedPart() { } -class ModlogEmbedFooter() : ModlogEmbedPart() { - - var languagePath: String = "" - var languageObjects: MutableList = ArrayList() +class ModlogEmbedFooter(val languagePath: String, val icon: String? = null, vararg languageObjects: String) : ModlogEmbedPart() { - var icon: String? = null + constructor() : this("", "") - constructor(languagePath: String, icon: String? = null, vararg languageObjects: String): this() { - this.languagePath = languagePath - this.languageObjects.addAll(languageObjects) - } + var languageObjects: MutableList = mutableListOf(*languageObjects) override fun build(locale: Locale, embedBuilder: WebhookEmbedBuilder) { embedBuilder.setFooter(WebhookEmbed.EmbedFooter(Language.i18n(locale, languagePath, *languageObjects.toTypedArray()), icon)); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 52bf19d1a..4a9d44a4a 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -5,9 +5,10 @@ import lombok.Getter import org.cascadebot.cascadebot.messaging.MessageType import java.util.ArrayList import java.util.Arrays +import java.util.EnumMap import java.util.HashMap -enum class ModlogEvent(messageType: MessageType, displayType: ModlogDisplayType, vararg categories: Category) { +enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: ModlogDisplayType, vararg categories: Category) { EMOTE_CREATED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.EMOTE), EMOTE_DELETED(MessageType.INFO, ModlogDisplayType.PLAIN, Category.EMOTE), @@ -122,7 +123,7 @@ enum class ModlogEvent(messageType: MessageType, displayType: ModlogDisplayType, CASCADE_TAG_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS); companion object { - private val modlogCategoryMap: MutableMap> = HashMap() + private val modlogCategoryMap: MutableMap> = EnumMap(Category::class.java) fun getModlogCategoryMap(): Map> { return modlogCategoryMap @@ -134,9 +135,9 @@ enum class ModlogEvent(messageType: MessageType, displayType: ModlogDisplayType, init { for (cat in Category.values()) { - modlogCategoryMap[cat] = ArrayList() + modlogCategoryMap[cat] = mutableListOf() } - modlogCategoryMap[Category.ALL] = Arrays.asList(*values()) + modlogCategoryMap[Category.ALL] = mutableListOf(*values()) for (event in values()) { for (category in event.categories) { modlogCategoryMap[category]?.add(event) @@ -145,10 +146,7 @@ enum class ModlogEvent(messageType: MessageType, displayType: ModlogDisplayType, } } - val categories: List - @Transient - val messageType: MessageType - val displayType: ModlogDisplayType + val categories: List = listOf(*categories) enum class Category { ALL, @@ -175,9 +173,5 @@ enum class ModlogEvent(messageType: MessageType, displayType: ModlogDisplayType, PLAIN } - init { - this.categories = Arrays.asList(*categories) - this.messageType = messageType - this.displayType = displayType - } +} } \ No newline at end of file From 1280912cecf327d3917f11515d680e7d9caf5849 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 25 Oct 2020 22:28:33 +0000 Subject: [PATCH 070/206] Add a display type :P --- .../cascadebot/moderation/ModlogEvent.kt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 4a9d44a4a..78f53091e 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -60,14 +60,14 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: VOICE_FORCE_MOVE(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE, Category.MODERATION), VOICE_DISCONNECT(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE, Category.MODERATION), - ROLE_CREATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_DELETED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_COLOR_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_HOIST_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_MENTIONABLE_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_NAME_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_PERMISSIONS_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_POSITION_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_CREATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), + ROLE_DELETED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), + ROLE_COLOR_UPDATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), + ROLE_HOIST_UPDATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), + ROLE_MENTIONABLE_UPDATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), + ROLE_NAME_UPDATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), + ROLE_PERMISSIONS_UPDATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), + ROLE_POSITION_UPDATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), USER_DISCRIMINATOR_UPDATED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.USER), USER_NAME_UPDATED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.USER), @@ -170,8 +170,8 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: enum class ModlogDisplayType { AFFECTED_THUMBNAIL, AFFECTED_AUTHOR, + AFFECTED, PLAIN } -} } \ No newline at end of file From cdbbd7df51b4aadc197c2e0e8130bf61c7a9ecb5 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 25 Oct 2020 22:29:19 +0000 Subject: [PATCH 071/206] Shorten code --- .../events/ModlogEventListener.java | 126 +++++++++--------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 69f3dc97d..959e6a7c9 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -151,7 +151,7 @@ public void onGenericEmote(GenericEmoteEvent event) { if (auditLogEntry != null) { user = auditLogEntry.getUser(); } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find emote entry"); + CascadeBot.LOGGER.warn("Modlog: Failed to find emote audit log entry"); } List embedFieldList = new ArrayList<>(); ModlogEvent modlogEvent; @@ -200,7 +200,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { responsible = auditLogEntry.getUser(); embedFieldList.add(new ModlogEmbedDescription("modlog.member.kicked", user.getAsMention())); if (auditLogEntry.getReason() != null) { - ModlogEmbedField reasonEmbedField = new ModlogEmbedField(false, "modlog.general.reason", "modlog.general.variable"); + ModlogEmbedField reasonEmbedField = new ModlogEmbedField(false, "modlog.general.reason", null); reasonEmbedField.addValueObjects(auditLogEntry.getReason()); embedFieldList.add(reasonEmbedField); } @@ -214,7 +214,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { responsible = auditLogEntry.getUser(); } modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_ADDED; - ModlogEmbedField addedRolesEmbedField = new ModlogEmbedField(false, "modlog.general.added_roles", "modlog.general.variable"); + ModlogEmbedField addedRolesEmbedField = new ModlogEmbedField(false, "modlog.general.added_roles", null); addedRolesEmbedField.addValueObjects(((GuildMemberRoleAddEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n"))); embedFieldList.add(addedRolesEmbedField); } else if (event instanceof GuildMemberRoleRemoveEvent) { @@ -222,17 +222,17 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { responsible = auditLogEntry.getUser(); } modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_REMOVED; - ModlogEmbedField removedRolesEmbedField = new ModlogEmbedField(false, "modlog.general.removed_roles", "modlog.general.variable"); + ModlogEmbedField removedRolesEmbedField = new ModlogEmbedField(false, "modlog.general.removed_roles", null); removedRolesEmbedField.addValueObjects(((GuildMemberRoleRemoveEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n"))); embedFieldList.add(removedRolesEmbedField); } else if (event instanceof GuildMemberUpdateNicknameEvent) { if (((GuildMemberUpdateNicknameEvent) event).getOldValue() != null) { - ModlogEmbedField oldNickEmbedField = new ModlogEmbedField(true, "modlog.member.old_nick", "modlog.general.variable"); + ModlogEmbedField oldNickEmbedField = new ModlogEmbedField(true, "modlog.member.old_nick", null); oldNickEmbedField.addValueObjects(((GuildMemberUpdateNicknameEvent) event).getOldValue()); embedFieldList.add(oldNickEmbedField); } if (((GuildMemberUpdateNicknameEvent) event).getNewValue() != null) { - ModlogEmbedField newNickEmbedField = new ModlogEmbedField(true, "modlog.member.new_nick", "modlog.general.variable"); + ModlogEmbedField newNickEmbedField = new ModlogEmbedField(true, "modlog.member.new_nick", null); newNickEmbedField.addValueObjects(((GuildMemberUpdateNicknameEvent) event).getNewValue()); embedFieldList.add(newNickEmbedField); } @@ -257,7 +257,7 @@ public void onGuildBan(GuildBanEvent event) { responsible = auditLogEntry.getUser(); embedFieldList.add(new ModlogEmbedDescription("modlog.member.banned", user.getAsMention())); if (auditLogEntry.getReason() != null) { - ModlogEmbedField reasonEmbedField = new ModlogEmbedField(false, "modlog.general.reason", "modlog.general.variable"); + ModlogEmbedField reasonEmbedField = new ModlogEmbedField(false, "modlog.general.reason", null); reasonEmbedField.addValueObjects(auditLogEntry.getReason()); embedFieldList.add(reasonEmbedField); } @@ -305,7 +305,7 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { } User affected = CascadeBot.INS.getClient().getUserById(message.getAuthorId()); List embedFieldList = new ArrayList<>(); - ModlogEmbedField messageEmbedField = new ModlogEmbedField(false, "modlog.message.message", "modlog.general.variable"); + ModlogEmbedField messageEmbedField = new ModlogEmbedField(false, "modlog.message.message", null); messageEmbedField.addValueObjects(message.getContent()); embedFieldList.add(messageEmbedField); if (message.getAttachments().size() > 0) { @@ -313,7 +313,7 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { for (Attachment attachment : message.getAttachments()) { attachmentsBuilder.append(attachment.getUrl()).append('\n'); } - embedFieldList.add(new ModlogEmbedField(false, "modlog.message.attachments", "modlog.general.variable", attachmentsBuilder.toString())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.message.attachments", null, attachmentsBuilder.toString())); } if (affected == null) { return; @@ -356,9 +356,9 @@ public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { } User affected = message.getAuthor(); List embedFieldList = new ArrayList<>(); - ModlogEmbedField oldEmbedField = new ModlogEmbedField(false, "modlog.message.old_message", "modlog.general.variable"); + ModlogEmbedField oldEmbedField = new ModlogEmbedField(false, "modlog.message.old_message", null); oldEmbedField.addValueObjects(oldMessage.getContent()); - ModlogEmbedField newEmbedField = new ModlogEmbedField(false, "modlog.message.new_message", "modlog.general.variable"); + ModlogEmbedField newEmbedField = new ModlogEmbedField(false, "modlog.message.new_message", null); newEmbedField.addValueObjects(message.getContentRaw()); // TODO handle embeds/ect... embedFieldList.add(oldEmbedField); @@ -412,11 +412,11 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { if (event instanceof GuildUpdateAfkChannelEvent) { VoiceChannel oldChannel = ((GuildUpdateAfkChannelEvent) event).getOldAfkChannel(); if (oldChannel != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_channel", "modlog.general.variable", oldChannel.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_channel", null, oldChannel.getName())); } VoiceChannel newChannel = ((GuildUpdateAfkChannelEvent) event).getNewAfkChannel(); if (newChannel != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_channel", "modlog.general.variable", newChannel.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_channel", null, newChannel.getName())); } modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_CHANNEL; } else if (event instanceof GuildUpdateAfkTimeoutEvent) { @@ -425,18 +425,18 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_TIMEOUT; } else if (event instanceof GuildUpdateBannerEvent) { if (((GuildUpdateBannerEvent) event).getOldBannerUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", "modlog.general.variable", ((GuildUpdateBannerEvent) event).getOldBannerUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", null, ((GuildUpdateBannerEvent) event).getOldBannerUrl())); } if (((GuildUpdateBannerEvent) event).getNewBannerUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_image", "modlog.general.variable", ((GuildUpdateBannerEvent) event).getNewBannerUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_image", null, ((GuildUpdateBannerEvent) event).getNewBannerUrl())); } modlogEvent = ModlogEvent.GUILD_UPDATE_BANNER; } else if (event instanceof GuildUpdateDescriptionEvent) { if (((GuildUpdateDescriptionEvent) event).getOldDescription() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_description", "modlog.general.variable", ((GuildUpdateDescriptionEvent) event).getOldDescription())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_description", null, ((GuildUpdateDescriptionEvent) event).getOldDescription())); } if (((GuildUpdateDescriptionEvent) event).getNewDescription() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_description", "modlog.general.variable", ((GuildUpdateDescriptionEvent) event).getNewDescription())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_description", null, ((GuildUpdateDescriptionEvent) event).getNewDescription())); } modlogEvent = ModlogEvent.GUILD_UPDATE_DESCRIPTION; } else if (event instanceof GuildUpdateExplicitContentLevelEvent) { @@ -445,15 +445,15 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { modlogEvent = ModlogEvent.GUILD_UPDATE_EXPLICIT_FILTER; } else if (event instanceof GuildUpdateFeaturesEvent) { ListChanges featuresChanged = new ListChanges<>(((GuildUpdateFeaturesEvent) event).getOldFeatures(), ((GuildUpdateFeaturesEvent) event).getNewFeatures()); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.add_feature", "modlog.general.variable", String.join("\n", featuresChanged.getAdded()))); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.removed_feature", "modlog.general.variable", String.join("\n", featuresChanged.getRemoved()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.add_feature", null, String.join("\n", featuresChanged.getAdded()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.removed_feature", null, String.join("\n", featuresChanged.getRemoved()))); modlogEvent = ModlogEvent.GUILD_UPDATE_FEATURES; } else if (event instanceof GuildUpdateIconEvent) { if (((GuildUpdateIconEvent) event).getOldIconUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", "modlog.general.variable", ((GuildUpdateIconEvent) event).getOldIconUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", null, ((GuildUpdateIconEvent) event).getOldIconUrl())); } if (((GuildUpdateIconEvent) event).getNewIconUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_image", "modlog.general.variable", ((GuildUpdateIconEvent) event).getNewIconUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_image", null, ((GuildUpdateIconEvent) event).getNewIconUrl())); } modlogEvent = ModlogEvent.GUILD_UPDATE_ICON; } else if (event instanceof GuildUpdateMaxMembersEvent) { @@ -469,46 +469,46 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.mfa.new", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getNewMFALevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_MFA_LEVEL; } else if (event instanceof GuildUpdateNameEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", "modlog.general.variable", ((GuildUpdateNameEvent) event).getOldName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", null, ((GuildUpdateNameEvent) event).getOldName())); modlogEvent = ModlogEvent.GUILD_UPDATE_NAME; } else if (event instanceof GuildUpdateNotificationLevelEvent) { embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.notification.old", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getOldNotificationLevel().name().toLowerCase())); embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.notification.new", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getNewNotificationLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_NOTIFICATION_LEVEL; } else if (event instanceof GuildUpdateRegionEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_region", "modlog.general.variable", ((GuildUpdateRegionEvent) event).getOldRegion().getName())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_region", "modlog.general.variable", ((GuildUpdateRegionEvent) event).getNewRegion().getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_region", null, ((GuildUpdateRegionEvent) event).getOldRegion().getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_region", null, ((GuildUpdateRegionEvent) event).getNewRegion().getName())); modlogEvent = ModlogEvent.GUILD_UPDATE_REGION; } else if (event instanceof GuildUpdateSplashEvent) { if (((GuildUpdateSplashEvent) event).getOldSplashUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_splash", "modlog.general.variable", ((GuildUpdateSplashEvent) event).getOldSplashUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_splash", null, ((GuildUpdateSplashEvent) event).getOldSplashUrl())); } if (((GuildUpdateSplashEvent) event).getNewSplashUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_splash", "modlog.general.variable", ((GuildUpdateSplashEvent) event).getNewSplashUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_splash", null, ((GuildUpdateSplashEvent) event).getNewSplashUrl())); } modlogEvent = ModlogEvent.GUILD_UPDATE_SPLASH; } else if (event instanceof GuildUpdateSystemChannelEvent) { TextChannel oldSystemChannel = ((GuildUpdateSystemChannelEvent) event).getOldSystemChannel(); if (oldSystemChannel != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_sys", "modlog.general.variable", oldSystemChannel.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_sys", null, oldSystemChannel.getName())); } TextChannel newSystemChannel = ((GuildUpdateSystemChannelEvent) event).getNewSystemChannel(); if (newSystemChannel != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_sys", "modlog.general.variable", newSystemChannel.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_sys", null, newSystemChannel.getName())); } modlogEvent = ModlogEvent.GUILD_UPDATE_SYSTEM_CHANNEL; } else if (event instanceof GuildUpdateVanityCodeEvent) { if (((GuildUpdateVanityCodeEvent) event).getOldVanityCode() != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_code.old", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getOldVanityCode())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_code.old", null, ((GuildUpdateVanityCodeEvent) event).getOldVanityCode())); } if (((GuildUpdateVanityCodeEvent) event).getOldVanityUrl() != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_url.old", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getOldVanityUrl())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_url.old", null, ((GuildUpdateVanityCodeEvent) event).getOldVanityUrl())); } if (((GuildUpdateVanityCodeEvent) event).getNewVanityCode() != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_code.new", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getNewVanityCode())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_code.new", null, ((GuildUpdateVanityCodeEvent) event).getNewVanityCode())); } if (((GuildUpdateVanityCodeEvent) event).getNewVanityUrl() != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_url.new", "modlog.general.variable", ((GuildUpdateVanityCodeEvent) event).getNewVanityUrl())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_url.new", null, ((GuildUpdateVanityCodeEvent) event).getNewVanityUrl())); } modlogEvent = ModlogEvent.GUILD_UPDATE_VANITY_CODE; } else if (event instanceof GuildUpdateVerificationLevelEvent) { @@ -516,8 +516,8 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getNewVerificationLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_VERIFICATION_LEVEL; } else if (event instanceof GuildUpdateBoostCountEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_boost_count", "modlog.general.variable", String.valueOf(event.getOldValue()))); - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_boost_count", "modlog.general.variable", String.valueOf(event.getNewValue()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_boost_count", null, String.valueOf(event.getOldValue()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_boost_count", null, String.valueOf(event.getNewValue()))); modlogEvent = ModlogEvent.GUILD_BOOST_COUNT_UPDATED; } else if (event instanceof GuildUpdateBoostTierEvent) { embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getOldBoostTier().name().toLowerCase())); @@ -539,30 +539,30 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { List embedFieldList = new ArrayList<>(); ModlogEvent action; if (event instanceof GuildVoiceDeafenEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceDeafenEvent) event).isDeafened()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.deafen", null, String.valueOf(((GuildVoiceDeafenEvent) event).isDeafened()))); action = ModlogEvent.VOICE_DEAFEN; } else if (event instanceof GuildVoiceMuteEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceMuteEvent) event).isMuted()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.mute", null, String.valueOf(((GuildVoiceMuteEvent) event).isMuted()))); action = ModlogEvent.VOICE_MUTE; } else if (event instanceof GuildVoiceGuildDeafenEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.deafen", "modlog.general.variable", String.valueOf(((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.deafen", null, String.valueOf(((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()))); action = ModlogEvent.VOICE_SERVER_DEAFEN; } else if (event instanceof GuildVoiceGuildMuteEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.mute", "modlog.general.variable", String.valueOf(((GuildVoiceGuildMuteEvent) event).isGuildMuted()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.mute", null, String.valueOf(((GuildVoiceGuildMuteEvent) event).isGuildMuted()))); action = ModlogEvent.VOICE_SERVER_MUTE; } else if (event instanceof GuildVoiceJoinEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.join", "modlog.general.variable", ((GuildVoiceJoinEvent) event).getChannelJoined().getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.join", null, ((GuildVoiceJoinEvent) event).getChannelJoined().getName())); action = ModlogEvent.VOICE_JOIN; } else if (event instanceof GuildVoiceLeaveEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.left", "modlog.general.variable", ((GuildVoiceLeaveEvent) event).getChannelLeft().getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.left", null, ((GuildVoiceLeaveEvent) event).getChannelLeft().getName())); if (auditLogEntry != null) { action = ModlogEvent.VOICE_DISCONNECT; } else { action = ModlogEvent.VOICE_LEAVE; } } else if (event instanceof GuildVoiceMoveEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.left", "modlog.general.variable", ((GuildVoiceMoveEvent) event).getChannelLeft().getName())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.join", "modlog.general.variable", ((GuildVoiceMoveEvent) event).getChannelJoined().getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.left", null, ((GuildVoiceMoveEvent) event).getChannelLeft().getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.join", null, ((GuildVoiceMoveEvent) event).getChannelJoined().getName())); if (auditLogEntry != null) { action = ModlogEvent.VOICE_FORCE_MOVE; } else { @@ -617,15 +617,15 @@ public void onGenericTextChannel(GenericTextChannelEvent event) { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } if (event instanceof TextChannelUpdateNSFWEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.nsfw", "modlog.general.variable", String.valueOf(!((TextChannelUpdateNSFWEvent) event).getOldNSFW()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.nsfw", null, String.valueOf(!((TextChannelUpdateNSFWEvent) event).getOldNSFW()))); trigger = ModlogEvent.TEXT_CHANNEL_NSFW_UPDATED; } else if (event instanceof TextChannelUpdateSlowmodeEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_slowmode", "modlog.general.variable", String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getOldSlowmode()))); - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_slowmode", "modlog.general.variable", String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getNewSlowmode()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_slowmode", null, String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getOldSlowmode()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_slowmode", null, String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getNewSlowmode()))); trigger = ModlogEvent.TEXT_CHANNEL_SLOWMODE_UPDATED; } else if (event instanceof TextChannelUpdateTopicEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_topic", "modlog.general.variable", ((TextChannelUpdateTopicEvent) event).getOldTopic())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_topic", "modlog.general.variable", ((TextChannelUpdateTopicEvent) event).getNewTopic())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_topic", null, ((TextChannelUpdateTopicEvent) event).getOldTopic())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_topic", null, ((TextChannelUpdateTopicEvent) event).getNewTopic())); trigger = ModlogEvent.TEXT_CHANNEL_TOPIC_UPDATED; } else { return; @@ -718,13 +718,13 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { allowedPath = "modlog.channel.perm.update_allow"; deniedPath = "modlog.channel.perm.update_deny"; if (((PermissionOverrideUpdateEvent) event).getOldAllow().size() > 0) { - ModlogEmbedField oldAllowed = new ModlogEmbedField(false, "modlog.channel.perm.old_allow", "modlog.general.variable", + ModlogEmbedField oldAllowed = new ModlogEmbedField(false, "modlog.channel.perm.old_allow", null, ((PermissionOverrideUpdateEvent) event).getOldAllow().stream().map(Permission::getName).collect(Collectors.joining("\n"))); oldAllowed.addTitleObjects(permissionsHolderName); embedFieldList.add(oldAllowed); } if (((PermissionOverrideUpdateEvent) event).getOldDeny().size() > 0) { - ModlogEmbedField oldDenied = new ModlogEmbedField(false, "modlog.channel.perm.old_allow", "modlog.general.variable", + ModlogEmbedField oldDenied = new ModlogEmbedField(false, "modlog.channel.perm.old_allow", null, ((PermissionOverrideUpdateEvent) event).getOldDeny().stream().map(Permission::getName).collect(Collectors.joining("\n"))); oldDenied.addTitleObjects(permissionsHolderName); embedFieldList.add(oldDenied); @@ -733,12 +733,12 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { return; } if (event.getPermissionOverride().getAllowed().size() > 0) { - ModlogEmbedField allowed = new ModlogEmbedField(false, allowedPath, "modlog.general.variable", event.getPermissionOverride().getAllowed().stream().map(Permission::getName).collect(Collectors.joining("\n"))); + ModlogEmbedField allowed = new ModlogEmbedField(false, allowedPath, null, event.getPermissionOverride().getAllowed().stream().map(Permission::getName).collect(Collectors.joining("\n"))); allowed.addTitleObjects(permissionsHolderName); embedFieldList.add(allowed); } if (event.getPermissionOverride().getDenied().size() > 0) { - ModlogEmbedField denied = new ModlogEmbedField(false, deniedPath, "modlog.general.variable", event.getPermissionOverride().getDenied().stream().map(Permission::getName).collect(Collectors.joining("\n"))); + ModlogEmbedField denied = new ModlogEmbedField(false, deniedPath, null, event.getPermissionOverride().getDenied().stream().map(Permission::getName).collect(Collectors.joining("\n"))); denied.addTitleObjects(permissionsHolderName); embedFieldList.add(denied); } @@ -797,7 +797,7 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", "modlog.general.variable", oldName)); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", null, oldName)); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_UPDATE); @@ -832,8 +832,8 @@ public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Categ CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_parent", "modlog.general.variable", oldParent.getName())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_parent", "modlog.general.variable", newParent.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_parent", null, oldParent.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_parent", null, newParent.getName())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_UPDATE); @@ -860,32 +860,32 @@ public void onGenericRole(GenericRoleEvent event) { modlogEvent = ModlogEvent.ROLE_COLOR_UPDATED; Color oldColor = ((RoleUpdateColorEvent) event).getOldColor(); if (oldColor != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.role.old_color", "modlog.general.variable", ColorUtils.getHex(oldColor.getRed(), oldColor.getGreen(), oldColor.getBlue()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.role.old_color", null, ColorUtils.getHex(oldColor.getRed(), oldColor.getGreen(), oldColor.getBlue()))); } Color newColor = ((RoleUpdateColorEvent) event).getNewColor(); if (newColor != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.role.new_color", "modlog.general.variable", ColorUtils.getHex(newColor.getRed(), newColor.getGreen(), newColor.getBlue()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.role.new_color", null, ColorUtils.getHex(newColor.getRed(), newColor.getGreen(), newColor.getBlue()))); } } else if (event instanceof RoleUpdateHoistedEvent) { modlogEvent = ModlogEvent.ROLE_HOIST_UPDATED; - embedFieldList.add(new ModlogEmbedField(true, "modlog.role.hoisted", "modlog.general.variable", String.valueOf(!((RoleUpdateHoistedEvent) event).wasHoisted()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.role.hoisted", null, String.valueOf(!((RoleUpdateHoistedEvent) event).wasHoisted()))); } else if (event instanceof RoleUpdateMentionableEvent) { modlogEvent = ModlogEvent.ROLE_MENTIONABLE_UPDATED; - embedFieldList.add(new ModlogEmbedField(true, "modlog.role.mention", "modlog.general.variable", String.valueOf(!((RoleUpdateMentionableEvent) event).wasMentionable()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.role.mention", null, String.valueOf(!((RoleUpdateMentionableEvent) event).wasMentionable()))); } else if (event instanceof RoleUpdateNameEvent) { modlogEvent = ModlogEvent.ROLE_NAME_UPDATED; - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", "modlog.general.variable", ((RoleUpdateNameEvent) event).getOldName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", null, ((RoleUpdateNameEvent) event).getOldName())); } else if (event instanceof RoleUpdatePermissionsEvent) { modlogEvent = ModlogEvent.ROLE_PERMISSIONS_UPDATED; EnumSet oldPermissions = ((RoleUpdatePermissionsEvent) event).getOldPermissions(); EnumSet newPermissions = ((RoleUpdatePermissionsEvent) event).getNewPermissions(); ListChanges permissionListChanges = new ListChanges<>(oldPermissions, newPermissions); - embedFieldList.add(new ModlogEmbedField(false, "modlog.role.added_perm", "modlog.general.variable", permissionListChanges.getAdded().stream().map(Permission::getName).collect(Collectors.joining("\n")))); - embedFieldList.add(new ModlogEmbedField(false, "modlog.role.removed_perm", "modlog.general.variable", permissionListChanges.getRemoved().stream().map(Permission::getName).collect(Collectors.joining("\n")))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.role.added_perm", null, permissionListChanges.getAdded().stream().map(Permission::getName).collect(Collectors.joining("\n")))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.role.removed_perm", null, permissionListChanges.getRemoved().stream().map(Permission::getName).collect(Collectors.joining("\n")))); } else if (event instanceof RoleUpdatePositionEvent) { modlogEvent = ModlogEvent.ROLE_POSITION_UPDATED; - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_pos", "modlog.general.variable", String.valueOf(((RoleUpdatePositionEvent) event).getOldPosition()))); - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.new_pos", "modlog.general.variable", String.valueOf(((RoleUpdatePositionEvent) event).getNewPosition()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_pos", null, String.valueOf(((RoleUpdatePositionEvent) event).getOldPosition()))); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.new_pos", null, String.valueOf(((RoleUpdatePositionEvent) event).getNewPosition()))); } else { return; } From 83856ac3f727b6068666be3b9198b8318e844593 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 25 Oct 2020 22:29:38 +0000 Subject: [PATCH 072/206] Modlog Events! --- .../events/ModlogEventListener.java | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 959e6a7c9..81f67ce79 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -161,22 +161,34 @@ public void onGenericEmote(GenericEmoteEvent event) { modlogEvent = ModlogEvent.EMOTE_DELETED; } else if (event instanceof EmoteUpdateNameEvent) { modlogEvent = ModlogEvent.EMOTE_UPDATED_NAME; - ModlogEmbedField languageModlogEmbedField = new ModlogEmbedField(true, "modlog.general.old_name", "modlog.general.variable"); - languageModlogEmbedField.addValueObjects(((EmoteUpdateNameEvent) event).getOldName()); - embedFieldList.add(languageModlogEmbedField); + + var oldName = new ModlogEmbedField(false, "modlog.general.old_name", null); + var newName = new ModlogEmbedField(false, "modlog.general.new_name", null); + + oldName.addValueObjects(((EmoteUpdateNameEvent) event).getOldName()); + newName.addValueObjects(((EmoteUpdateNameEvent) event).getNewName()); + + embedFieldList.add(oldName); + embedFieldList.add(newName); } else if (event instanceof EmoteUpdateRolesEvent) { modlogEvent = ModlogEvent.EMOTE_UPDATED_ROLES; + List oldRoles = ((EmoteUpdateRolesEvent) event).getOldRoles(); List newRoles = ((EmoteUpdateRolesEvent) event).getNewRoles(); ListChanges roleListChanges = new ListChanges<>(oldRoles, newRoles); - ModlogEmbedField addedRolesEmbed = new ModlogEmbedField(false, "modlog.general.added_roles", "modlog.general.variable"); - addedRolesEmbed.addValueObjects(roleListChanges.getAdded().stream().map(role -> role.getName() + " (" + role.getId() + ")") - .collect(Collectors.joining("\n"))); - ModlogEmbedField removedRolesEmbed = new ModlogEmbedField(false, "modlog.general.removed_roles", "modlog.general.variable"); - removedRolesEmbed.addValueObjects(roleListChanges.getRemoved().stream().map(role -> role.getName() + " (" + role.getId() + ")") - .collect(Collectors.joining("\n"))); - embedFieldList.add(addedRolesEmbed); - embedFieldList.add(removedRolesEmbed); + + if (!roleListChanges.getAdded().isEmpty()) { + ModlogEmbedField addedRolesEmbed = new ModlogEmbedField(false, "modlog.general.added_roles", null); + addedRolesEmbed.addValueObjects(roleListChanges.getAdded().stream().map(role -> role.getName() + " (" + role.getId() + ")") + .collect(Collectors.joining("\n"))); + embedFieldList.add(addedRolesEmbed); + } + if (!roleListChanges.getRemoved().isEmpty()) { + ModlogEmbedField removedRolesEmbed = new ModlogEmbedField(false, "modlog.general.removed_roles", null); + removedRolesEmbed.addValueObjects(roleListChanges.getRemoved().stream().map(role -> role.getName() + " (" + role.getId() + ")") + .collect(Collectors.joining("\n"))); + embedFieldList.add(removedRolesEmbed); + } } else { return; } From 65e4d5eb0aadaa18d1446b229de993fa859e4935 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 25 Oct 2020 22:30:36 +0000 Subject: [PATCH 073/206] Update some event descriptions --- src/main/resources/lang/en-GB.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index e8c9f3d95..5998f4813 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1378,7 +1378,7 @@ "emote_updated_roles": { "select": "emote_updated_roles", "display": "Emote updated roles", - "description": "Emote `{0}` roles where changed" + "description": "The role whitelist for the emote `{0}` were changed:" }, "guild_member_joined": { "select": "guild_member_joined", @@ -1540,7 +1540,7 @@ }, "voice_server_deafen": { "select": "voice_server_deafen", - "display": "Voice server deafen", + "display": "Voice server deafen" }, "voice_server_mute": { "select": "voice_server_mute", @@ -2048,6 +2048,7 @@ "item": "item", "list": "list", "words": "words", + "unknown": "unknown", "pos": "position", "source": "source", "destination": "destination", @@ -2263,6 +2264,7 @@ "modlog": { "general": { "old_name": "Old Name", + "new_name": "New Name", "variable": "{0}", "responsible": "Responsible", "reason": "Reason", From eee0eed0a61cd9d1ff974013cf3783c2f90536d7 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 26 Oct 2020 08:54:56 +0000 Subject: [PATCH 074/206] Fix merge and warnings --- .../moderation/ModlogClearSubCommand.java | 56 +++++++++---------- .../data/database/DatabaseManager.java | 1 - .../cascadebot/music/CascadePlayer.java | 2 +- .../cascadebot/commands/core/PageCommand.kt | 2 +- .../management/SettingsListSubCommand.kt | 5 +- .../goodbye/GoodbyeRemoveSubCommand.kt | 2 +- .../goodbye/GoodbyeWeightSubCommand.kt | 4 +- .../welcome/WelcomeDMRemoveSubCommand.kt | 2 +- .../welcome/WelcomeDMWeightSubCommand.kt | 4 +- .../welcome/WelcomeRemoveSubCommand.kt | 2 +- .../welcome/WelcomeWeightSubCommand.kt | 4 +- .../cascadebot/data/objects/Greetings.kt | 1 - .../cascadebot/events/GuildEvents.kt | 2 - .../cascadebot/cascadebot/utils/ColorUtils.kt | 1 + .../utils/placeholders/Placeholders.kt | 2 - 15 files changed, 39 insertions(+), 51 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java index 06550d2fd..665027158 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java @@ -24,48 +24,42 @@ public class ModlogClearSubCommand extends SubCommand { public void onCommand(Member sender, CommandContext context) { if (context.getArgs().length == 0) { - if (ConfirmUtils.hasConfirmedAction(clearAction, sender.getIdLong())) { - ConfirmUtils.completeAction(clearAction, sender.getIdLong()); + if (ConfirmUtils.hasRegisteredAction(clearAction, sender.getIdLong())) { + ConfirmUtils.confirmAction(clearAction, sender.getIdLong()); } else { - ConfirmUtils.confirmAction(sender.getIdLong(), clearAction, context.getChannel(), MessageType.WARNING, + ConfirmUtils.registerForConfirmation(sender.getIdLong(), clearAction, context.getChannel(), MessageType.WARNING, "Confirm that you want to remove ALL events", 0, TimeUnit.SECONDS.toMillis(5), - true, new ConfirmUtils.ConfirmRunnable() { - @Override - public void execute() { - context.getData().getModeration().getModlogEvents().clear(); - context.getTypedMessaging().replySuccess("Removed all modlog events!"); - } - }); + true, () -> { + context.getData().getModeration().getModlogEvents().clear(); + context.getTypedMessaging().replySuccess("Removed all modlog events!"); + }); } return; } if (context.getArg(0).equalsIgnoreCase("disabled")) { - if (ConfirmUtils.hasConfirmedAction(clearDisabledAction, sender.getIdLong())) { - ConfirmUtils.completeAction(clearDisabledAction, sender.getIdLong()); + if (ConfirmUtils.hasRegisteredAction(clearDisabledAction, sender.getIdLong())) { + ConfirmUtils.confirmAction(clearDisabledAction, sender.getIdLong()); } else { - ConfirmUtils.confirmAction(sender.getIdLong(), clearDisabledAction, context.getChannel(), MessageType.WARNING, + ConfirmUtils.registerForConfirmation(sender.getIdLong(), clearDisabledAction, context.getChannel(), MessageType.WARNING, "Confirm that you want to remove all events in disabled channels", 0, TimeUnit.SECONDS.toMillis(5), - true, new ConfirmUtils.ConfirmRunnable() { - @Override - public void execute() { - List delete = new ArrayList<>(); - for (Map.Entry entry : context.getData().getModeration().getModlogEvents().entrySet()) { - TextChannel textChannel = CascadeBot.INS.getClient().getTextChannelById(entry.getKey()); - if (textChannel == null) { - continue; - } - List webhooks = textChannel.retrieveWebhooks().complete(); - for (Webhook webhook : webhooks) { - if (webhook.getIdLong() == entry.getValue().getWebhookId()) { - delete.add(entry.getKey()); - } - } + true, () -> { + List delete = new ArrayList<>(); + for (Map.Entry entry : context.getData().getModeration().getModlogEvents().entrySet()) { + TextChannel textChannel = CascadeBot.INS.getClient().getTextChannelById(entry.getKey()); + if (textChannel == null) { + continue; } - for (Long id : delete) { - context.getData().getModeration().getModlogEvents().remove(id); + List webhooks = textChannel.retrieveWebhooks().complete(); + for (Webhook webhook : webhooks) { + if (webhook.getIdLong() == entry.getValue().getWebhookId()) { + delete.add(entry.getKey()); + } } - context.getTypedMessaging().replySuccess("Deleted events from " + delete.size() + " disabled channel"); } + for (Long id : delete) { + context.getData().getModeration().getModlogEvents().remove(id); + } + context.getTypedMessaging().replySuccess("Deleted events from " + delete.size() + " disabled channel"); }); } return; diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java b/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java index 223e7f79f..0d719b55d 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java @@ -23,7 +23,6 @@ import org.cascadebot.cascadebot.moderation.ModlogEmbedField; import org.cascadebot.cascadebot.moderation.ModlogEmbedFooter; import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; -import org.cascadebot.cascadebot.utils.WeightPair; import org.cascadebot.cascadebot.utils.lists.WeightedList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/cascadebot/cascadebot/music/CascadePlayer.java b/src/main/java/org/cascadebot/cascadebot/music/CascadePlayer.java index 1fb5a343d..82520d7b6 100644 --- a/src/main/java/org/cascadebot/cascadebot/music/CascadePlayer.java +++ b/src/main/java/org/cascadebot/cascadebot/music/CascadePlayer.java @@ -290,7 +290,7 @@ public void setQueue(Queue newQueue) { @Override public abstract void setVolume(int i); - class SavePlaylistResult { + public class SavePlaylistResult { private SavePlaylistResultType type; private Playlist playlist; diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/core/PageCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/core/PageCommand.kt index e0dcc0916..36b7b15f5 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/core/PageCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/core/PageCommand.kt @@ -22,7 +22,7 @@ class PageCommand : CoreCommand() { context.typedMessaging.replyDanger(context.i18n("commands.page.page_must_number")) return } - val pageIndex = context.getArgAsInteger(0)!! + val pageIndex = context.getArgAsInteger(0) val buttonCaches = context.data.buttonsCache.mapValues { it.value.values }[context.channel.idLong]?.filter { it.ownerId == context.user.idLong } if (buttonCaches != null && buttonCaches.isNotEmpty()) { val pagesEntry = context.data.pageCache diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsListSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsListSubCommand.kt index d05c1dd64..db391b30f 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsListSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsListSubCommand.kt @@ -18,7 +18,6 @@ import org.cascadebot.cascadebot.utils.FormatUtils import org.cascadebot.cascadebot.utils.pagination.Page import org.cascadebot.cascadebot.utils.pagination.PageObjects import java.lang.reflect.Field -import java.util.Map class SettingsListSubCommand(private val settingsClasses: List>) : SubCommand() { @@ -30,8 +29,8 @@ class SettingsListSubCommand(private val settingsClasses: List>) : SubC if (entries.isEmpty()) continue - entries.stream() - .sorted(Map.Entry.comparingByKey()) + entries + .sortedBy { it.key } .map { it.value } .forEach { f: Field -> val settingsContainer = SettingsCommand.getSettingsContainer(f, context) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/goodbye/GoodbyeRemoveSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/goodbye/GoodbyeRemoveSubCommand.kt index 3c9adbd4c..270754694 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/goodbye/GoodbyeRemoveSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/goodbye/GoodbyeRemoveSubCommand.kt @@ -25,7 +25,7 @@ class GoodbyeRemoveSubCommand : SubCommand() { return } - val index = context.getArgAsInteger(0)!! - 1 + val index = context.getArgAsInteger(0) - 1 val goodbyeMessages = context.data.management.greetings.goodbyeMessages if (index < 0 || index >= goodbyeMessages.size) { context.typedMessaging.replyDanger(context.i18n("commands.goodbye.invalid_message_index", goodbyeMessages.size)) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/goodbye/GoodbyeWeightSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/goodbye/GoodbyeWeightSubCommand.kt index 9a050a6c9..3f012a026 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/goodbye/GoodbyeWeightSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/goodbye/GoodbyeWeightSubCommand.kt @@ -59,8 +59,8 @@ class GoodbyeWeightSubCommand : SubCommand() { return } - val index = context.getArgAsInteger(0)!! - 1 - val weight = context.getArgAsInteger(1)!! + val index = context.getArgAsInteger(0) - 1 + val weight = context.getArgAsInteger(1) if (index < 0 || index >= goodbyeMessages.size) { context.typedMessaging.replyDanger(context.i18n("commands.goodbye.invalid_message_index", goodbyeMessages.size)) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeDMRemoveSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeDMRemoveSubCommand.kt index 9389df92d..3d26a77b0 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeDMRemoveSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeDMRemoveSubCommand.kt @@ -25,7 +25,7 @@ class WelcomeDMRemoveSubCommand : SubCommand() { return } - val index = context.getArgAsInteger(0)!! - 1 + val index = context.getArgAsInteger(0) - 1 val welcomeMessages = context.data.management.greetings.welcomeDMMessages if (index < 0 || index >= welcomeMessages.size) { context.typedMessaging.replyDanger(context.i18n("commands.welcome.invalid_message_index", welcomeMessages.size)) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeDMWeightSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeDMWeightSubCommand.kt index d93887c19..c568ba548 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeDMWeightSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeDMWeightSubCommand.kt @@ -59,8 +59,8 @@ class WelcomeDMWeightSubCommand : SubCommand() { return } - val index = context.getArgAsInteger(0)!! - 1 - val weight = context.getArgAsInteger(1)!! + val index = context.getArgAsInteger(0) - 1 + val weight = context.getArgAsInteger(1) if (index < 0 || index >= welcomeMessages.size) { context.typedMessaging.replyDanger(context.i18n("commands.welcome.invalid_message_index", welcomeMessages.size)) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeRemoveSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeRemoveSubCommand.kt index a9bd60d78..50e5fd2bd 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeRemoveSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeRemoveSubCommand.kt @@ -25,7 +25,7 @@ class WelcomeRemoveSubCommand : SubCommand() { return } - val index = context.getArgAsInteger(0)!! - 1 + val index = context.getArgAsInteger(0) - 1 val welcomeMessages = context.data.management.greetings.welcomeMessages if (index < 0 || index >= welcomeMessages.size) { context.typedMessaging.replyDanger(context.i18n("commands.welcome.invalid_message_index", welcomeMessages.size)) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeWeightSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeWeightSubCommand.kt index c71a69a50..3ecb3cd04 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeWeightSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/welcome/WelcomeWeightSubCommand.kt @@ -59,8 +59,8 @@ class WelcomeWeightSubCommand : SubCommand() { return } - val index = context.getArgAsInteger(0)!! - 1 - val weight = context.getArgAsInteger(1)!! + val index = context.getArgAsInteger(0) - 1 + val weight = context.getArgAsInteger(1) if (index < 0 || index >= welcomeMessages.size) { context.typedMessaging.replyDanger(context.i18n("commands.welcome.invalid_message_index", welcomeMessages.size)) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt index c27dd3ad2..b35cfcf40 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt @@ -2,7 +2,6 @@ package org.cascadebot.cascadebot.data.objects import net.dv8tion.jda.api.entities.TextChannel import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent -import net.dv8tion.jda.api.events.guild.member.GuildMemberLeaveEvent import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.data.language.Language diff --git a/src/main/kotlin/org/cascadebot/cascadebot/events/GuildEvents.kt b/src/main/kotlin/org/cascadebot/cascadebot/events/GuildEvents.kt index 9b087fd01..9edcc15a9 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/events/GuildEvents.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/events/GuildEvents.kt @@ -8,9 +8,7 @@ package org.cascadebot.cascadebot.events import net.dv8tion.jda.api.events.guild.GuildJoinEvent import net.dv8tion.jda.api.events.guild.GuildLeaveEvent import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent -import net.dv8tion.jda.api.events.guild.member.GuildMemberLeaveEvent import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent -import net.dv8tion.jda.api.events.message.MessageDeleteEvent import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent import net.dv8tion.jda.api.events.role.RoleDeleteEvent import net.dv8tion.jda.api.hooks.ListenerAdapter diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/ColorUtils.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/ColorUtils.kt index 99317c5ba..1c47de0f5 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/ColorUtils.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/ColorUtils.kt @@ -21,6 +21,7 @@ object ColorUtils { private val RGB_COLOR = Pattern.compile("(\\d{1,3})[, ](\\d{1,3})[, ](\\d{1,3})") private val BINARY_COLOR = Pattern.compile("([0-1]+)") + @JvmStatic fun getHex(r: Int, g: Int, b: Int): String { return String.format("%02x%02x%02x", r, g, b) } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/placeholders/Placeholders.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/placeholders/Placeholders.kt index 9b00ee9cd..3a23c0653 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/placeholders/Placeholders.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/placeholders/Placeholders.kt @@ -2,7 +2,6 @@ package org.cascadebot.cascadebot.utils.placeholders import net.dv8tion.jda.api.events.guild.member.GenericGuildMemberEvent import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent -import net.dv8tion.jda.api.events.guild.member.GuildMemberLeaveEvent import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent import org.cascadebot.cascadebot.commandmeta.CommandContext import org.cascadebot.cascadebot.data.language.Language @@ -11,7 +10,6 @@ import org.cascadebot.cascadebot.messaging.MessageType import org.cascadebot.cascadebot.messaging.MessagingObjects import org.cascadebot.cascadebot.utils.FormatUtils import org.cascadebot.cascadebot.utils.pagination.PageObjects -import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects.tags import java.time.Duration import java.time.OffsetDateTime From 4a796d4d0a86ecf53676bcb9febf7fc2d431ab6b Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 26 Oct 2020 14:34:32 +0000 Subject: [PATCH 075/206] Remove AFFECTED display type and do roles --- .../events/ModlogEventListener.java | 31 ++++++++++++++----- .../cascadebot/data/objects/Enums.kt | 31 +++++++++---------- .../data/objects/GuildSettingsModeration.kt | 9 +----- .../data/objects/ModlogEventStore.kt | 2 +- .../cascadebot/moderation/ModlogEmbedPart.kt | 10 +++--- .../cascadebot/moderation/ModlogEvent.kt | 17 +++++----- src/main/resources/lang/en-GB.json | 21 +++++++------ 7 files changed, 64 insertions(+), 57 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 81f67ce79..89d19464e 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -856,12 +856,13 @@ public void onGenericRole(GenericRoleEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); ModlogUtils.getAuditLogFromType(event.getGuild(), event.getRole().getIdLong(), auditLogEntry -> { List embedFieldList = new ArrayList<>(); + List descriptionStuff = new ArrayList<>(); User responsible = null; ModlogEvent modlogEvent; if (auditLogEntry != null) { responsible = auditLogEntry.getUser(); } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find role entry"); + CascadeBot.LOGGER.warn("Modlog: Failed to find role audit log entry"); } Role affected = event.getRole(); if (event instanceof RoleCreateEvent) { @@ -880,28 +881,42 @@ public void onGenericRole(GenericRoleEvent event) { } } else if (event instanceof RoleUpdateHoistedEvent) { modlogEvent = ModlogEvent.ROLE_HOIST_UPDATED; - embedFieldList.add(new ModlogEmbedField(true, "modlog.role.hoisted", null, String.valueOf(!((RoleUpdateHoistedEvent) event).wasHoisted()))); + var wasHoisted = ((RoleUpdateHoistedEvent) event).wasHoisted(); + Emote emote = !wasHoisted ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("tick")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("cross")); + // TODO: Display role as new role (17367245237) instead of just new role in the description + descriptionStuff = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(!wasHoisted)); } else if (event instanceof RoleUpdateMentionableEvent) { modlogEvent = ModlogEvent.ROLE_MENTIONABLE_UPDATED; - embedFieldList.add(new ModlogEmbedField(true, "modlog.role.mention", null, String.valueOf(!((RoleUpdateMentionableEvent) event).wasMentionable()))); + Emote emote = ((RoleUpdateMentionableEvent) event).getNewValue() ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("tick")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("cross")); + descriptionStuff = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(((RoleUpdateMentionableEvent) event).getNewValue())); } else if (event instanceof RoleUpdateNameEvent) { modlogEvent = ModlogEvent.ROLE_NAME_UPDATED; - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", null, ((RoleUpdateNameEvent) event).getOldName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.general.old_name", null, ((RoleUpdateNameEvent) event).getOldName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.general.new_name", null, ((RoleUpdateNameEvent) event).getNewValue())); } else if (event instanceof RoleUpdatePermissionsEvent) { modlogEvent = ModlogEvent.ROLE_PERMISSIONS_UPDATED; EnumSet oldPermissions = ((RoleUpdatePermissionsEvent) event).getOldPermissions(); EnumSet newPermissions = ((RoleUpdatePermissionsEvent) event).getNewPermissions(); + ListChanges permissionListChanges = new ListChanges<>(oldPermissions, newPermissions); - embedFieldList.add(new ModlogEmbedField(false, "modlog.role.added_perm", null, permissionListChanges.getAdded().stream().map(Permission::getName).collect(Collectors.joining("\n")))); - embedFieldList.add(new ModlogEmbedField(false, "modlog.role.removed_perm", null, permissionListChanges.getRemoved().stream().map(Permission::getName).collect(Collectors.joining("\n")))); + if (!permissionListChanges.getAdded().isEmpty()) { + embedFieldList.add(new ModlogEmbedField(false, "modlog.role.added_perm", null, permissionListChanges.getAdded().stream().map(Permission::getName).collect(Collectors.joining("\n")))); + } + if (!permissionListChanges.getRemoved().isEmpty()) { + embedFieldList.add(new ModlogEmbedField(false, "modlog.role.removed_perm", null, permissionListChanges.getRemoved().stream().map(Permission::getName).collect(Collectors.joining("\n")))); + } } else if (event instanceof RoleUpdatePositionEvent) { modlogEvent = ModlogEvent.ROLE_POSITION_UPDATED; - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_pos", null, String.valueOf(((RoleUpdatePositionEvent) event).getOldPosition()))); - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.new_pos", null, String.valueOf(((RoleUpdatePositionEvent) event).getNewPosition()))); + if (((RoleUpdatePositionEvent) event).getNewPosition() == ((RoleUpdatePositionEvent) event).getOldPosition()) { + // If the position stays the same, we have no reason to log the event + return; + } + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.position", "modlog.general.small_change", ((RoleUpdatePositionEvent) event).getOldPosition() + 1, ((RoleUpdatePositionEvent) event).getNewPosition() + 1)); } else { return; } ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); + modlogEventStore.setExtraDescriptionInfo(descriptionStuff); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventStore); }, ActionType.ROLE_CREATE, ActionType.ROLE_DELETE, ActionType.ROLE_UPDATE); } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt index d108217b5..ce30c10a8 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt @@ -1,11 +1,8 @@ package org.cascadebot.cascadebot.data.objects -import net.dv8tion.jda.api.entities.Message import net.dv8tion.jda.api.entities.User -import org.cascadebot.cascadebot.moderation.ModlogEvent +import org.cascadebot.cascadebot.moderation.ModlogEvent.ModlogDisplayType import org.cascadebot.cascadebot.utils.PurgeUtils -import java.util.Arrays -import java.util.regex.Pattern enum class PlaylistType { GUILD, USER @@ -135,18 +132,18 @@ enum class ArgumentType { COMMAND } -enum class AffectedType(vararg val allowedDisplayTypes: ModlogEvent.ModlogDisplayType) { - UNKNOWN(ModlogEvent.ModlogDisplayType.PLAIN), - USER(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogEvent.ModlogDisplayType.PLAIN), - ROLE(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogEvent.ModlogDisplayType.PLAIN), - EMOTE(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogEvent.ModlogDisplayType.PLAIN), - GUILD(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogEvent.ModlogDisplayType.PLAIN), - CHANNEL(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.PLAIN), - GROUP(ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR, ModlogEvent.ModlogDisplayType.PLAIN), - SETTING(ModlogEvent.ModlogDisplayType.PLAIN), - MODULE(ModlogEvent.ModlogDisplayType.PLAIN), - COMMAND(ModlogEvent.ModlogDisplayType.PLAIN), - PLAYLIST(ModlogEvent.ModlogDisplayType.PLAIN), - TAG(ModlogEvent.ModlogDisplayType.PLAIN); +enum class AffectedType(vararg val allowedDisplayTypes: ModlogDisplayType) { + UNKNOWN(ModlogDisplayType.PLAIN), + USER(ModlogDisplayType.AFFECTED_AUTHOR, ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogDisplayType.PLAIN), + ROLE(ModlogDisplayType.AFFECTED_AUTHOR, ModlogDisplayType.AFFECTED_THUMBNAIL,ModlogDisplayType.PLAIN), + EMOTE(ModlogDisplayType.AFFECTED_AUTHOR, ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogDisplayType.PLAIN), + GUILD(ModlogDisplayType.AFFECTED_AUTHOR, ModlogDisplayType.AFFECTED_THUMBNAIL, ModlogDisplayType.PLAIN), + CHANNEL(ModlogDisplayType.AFFECTED_AUTHOR, ModlogDisplayType.PLAIN), + GROUP(ModlogDisplayType.AFFECTED_AUTHOR, ModlogDisplayType.PLAIN), + SETTING(ModlogDisplayType.PLAIN), + MODULE(ModlogDisplayType.PLAIN), + COMMAND(ModlogDisplayType.PLAIN), + PLAYLIST(ModlogDisplayType.PLAIN), + TAG(ModlogDisplayType.PLAIN); } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 0fa4627f7..9c650835f 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -171,7 +171,7 @@ class GuildSettingsModeration { guildData.locale, path, modlogEventStore.affected.name, - modlogEventStore.responsible?.asTag ?: Language.i18n(guildData.locale, "words.unknown").toCapitalized(), + modlogEventStore.responsible?.asMention ?: Language.i18n(guildData.locale, "words.unknown").toCapitalized(), *modlogEventStore.extraDescriptionInfo.toTypedArray() ) ) @@ -181,13 +181,6 @@ class GuildSettingsModeration { val affected: ModlogAffected = modlogEventStore.affected; when (modlogEventStore.trigger.displayType) { - ModlogEvent.ModlogDisplayType.AFFECTED -> { - var name = affected.name; - if (affected.id != null) { - name += " (" + affected.id + ")" - } - webhookEmbedBuilder.addField(EmbedField(true, "Affected", name)) - } ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL -> { when (affected.affectedType) { AffectedType.USER -> { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 92b62dfbb..822ff54f8 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -40,7 +40,7 @@ class ModlogEventStore { } is Role -> { affectedType = AffectedType.ROLE - ModlogAffected(AffectedType.ROLE, affected.name, affected.id) + ModlogAffected(AffectedType.ROLE, "${affected.name} (${affected.id})", affected.id) } is Emote -> { affectedType = AffectedType.EMOTE diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt index 6961e708b..9e000cf86 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt @@ -13,18 +13,18 @@ sealed class ModlogEmbedPart { class ModlogEmbedField(val inline: Boolean = true, val titleLanguagePath: String, - var valueLanguagePath: String? = null, vararg valueLanguageObjects: String) : ModlogEmbedPart() { + var valueLanguagePath: String? = null, vararg valueLanguageObjects: Any) : ModlogEmbedPart() { constructor() : this(true, "", "") - val titleLanguageObjects: MutableList = mutableListOf() - val valueLanguageObjects: MutableList = mutableListOf(*valueLanguageObjects) + val titleLanguageObjects: MutableList = mutableListOf() + val valueLanguageObjects: MutableList = mutableListOf(*valueLanguageObjects) - fun addTitleObjects(vararg titleLanguageObjects: String) { + fun addTitleObjects(vararg titleLanguageObjects: Any) { this.titleLanguageObjects.addAll(titleLanguageObjects) } - fun addValueObjects(vararg valueLanguageObjects: String) { + fun addValueObjects(vararg valueLanguageObjects: Any) { this.valueLanguageObjects.addAll(valueLanguageObjects) } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 78f53091e..ce652958d 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -60,14 +60,14 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: VOICE_FORCE_MOVE(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE, Category.MODERATION), VOICE_DISCONNECT(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE, Category.MODERATION), - ROLE_CREATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), - ROLE_DELETED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), - ROLE_COLOR_UPDATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), - ROLE_HOIST_UPDATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), - ROLE_MENTIONABLE_UPDATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), - ROLE_NAME_UPDATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), - ROLE_PERMISSIONS_UPDATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), - ROLE_POSITION_UPDATED(MessageType.WARNING, ModlogDisplayType.AFFECTED, Category.ROLE), + ROLE_CREATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_DELETED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_COLOR_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_HOIST_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_MENTIONABLE_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_NAME_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_PERMISSIONS_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), + ROLE_POSITION_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), USER_DISCRIMINATOR_UPDATED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.USER), USER_NAME_UPDATED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.USER), @@ -170,7 +170,6 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: enum class ModlogDisplayType { AFFECTED_THUMBNAIL, AFFECTED_AUTHOR, - AFFECTED, PLAIN } diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index af78017c3..9aa02e520 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1599,40 +1599,42 @@ "role_created": { "select": "role_created", "display": "Role created", - "description": "{1} created a new role called {0}" + "description": "{1} created a new role called `{0}`" }, "role_deleted": { "select": "role_deleted", "display": "Role deleted", - "description": "{1} deleted the role called {0}" + "description": "{1} deleted the role called `{0}`" }, "role_color_updated": { "select": "role_color_updated", "display": "Role color updated", - "description": "Role {0} color was updated" + "description": "Role `{0}` color was updated" }, "role_hoist_updated": { "select": "role_hoist_updated", - "display": "Role hoisted updated" + "display": "Role hoisted updated", + "description": "{2} {3, select, true {The role `{0}` is now displayed separately in the members list} other {The role `{0}` is no longer displayed separately in the members list}}" }, "role_mentionable_updated": { "select": "role_mentionable_updated", - "display": "Role mentionable updated" + "display": "Role mentionable updated", + "description": "{2} {3, select, true {The role `{0}` is now mentionable} other {The role `{0}` is no longer mentionable}}" }, "role_name_updated": { "select": "role_name_updated", "display": "Role name updated", - "description": "Role {0} had its name changed" + "description": "The role `{0}` had its name changed" }, "role_permissions_updated": { "select": "role_permissions_updated", "display": "Role permissions updated", - "description": "Role {0} had permissions updated" + "description": "The role `{0}` had its permissions updated" }, "role_position_updated": { "select": "role_position_updated", "display": "Role position updated", - "description": "Role {0} possition was updated" + "description": "The role `{0}`'s position was updated" }, "user_discriminator_updated": { "select": "user_discriminator_updated", @@ -2320,8 +2322,9 @@ "removed_roles": "Removed Roles", "old_pos": "Old Position", "new_pos": "New Position", + "position": "Position", "name": "Name", - "small_change": "{0} --> {1}" + "small_change": "{0} \uD83E\uDC16 {1}" }, "member": { "old_nick": "Old Nickname", From ceb9c927e9b155680d2ba35c752ddbd31b6d8fe2 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 26 Oct 2020 14:42:03 +0000 Subject: [PATCH 076/206] Typos! --- src/main/resources/lang/en-GB.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 9aa02e520..604be7f10 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -868,7 +868,7 @@ "cannot_edit": "You cannot edit this todo list. If you want to edit this contact {0}", "cannot_edit_no_owner": "You cannot edit this todo list and the owner has left the guild so the todo list has been deleted", "list_does_not_exist": "Todo list {0} doesn't exist", - "list_already_sent": "This todo list has already been sent, and therefor is no longer editable", + "list_already_sent": "This todo list has already been sent, and therefore is no longer editable", "no_items": "The todo list doesn't have any items!", "user_not_found": "Couldn't find user `{0}`", "embed_list_field": "List", @@ -1438,7 +1438,7 @@ "guild_member_nickname_updated": { "select": "guild_member_nickname_updated", "display": "Guild member nickname updated", - "description": "{0} updated there nickanme" + "description": "{0} updated their nickanme" }, "guild_user_banned": { "select": "guild_user_banned", @@ -1463,7 +1463,7 @@ "guild_message_updated": { "select": "guild_message_updated", "display": "Guild message updated", - "description": "{0} changed there message" + "description": "{0} changed their message" }, "guild_boost_count_updated": { "select": "guild_boost_count_updated", @@ -1639,12 +1639,12 @@ "user_discriminator_updated": { "select": "user_discriminator_updated", "display": "User discriminator updated", - "description": "User {0} changed there discriminator" + "description": "User {0} changed their discriminator" }, "user_name_updated": { "select": "user_name_updated", "display": "User name updated", - "description": "{0} changed there name" + "description": "{0} changed their name" }, "channel_created": { "select": "channel_created", From 6f622f1385aeafeed08577ab2e7ea4a918991a65 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 26 Oct 2020 14:48:18 +0000 Subject: [PATCH 077/206] Goodbye embed inline fields --- .../events/ModlogEventListener.java | 114 +++++++++--------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 89d19464e..dcf11395e 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -239,12 +239,12 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { embedFieldList.add(removedRolesEmbedField); } else if (event instanceof GuildMemberUpdateNicknameEvent) { if (((GuildMemberUpdateNicknameEvent) event).getOldValue() != null) { - ModlogEmbedField oldNickEmbedField = new ModlogEmbedField(true, "modlog.member.old_nick", null); + ModlogEmbedField oldNickEmbedField = new ModlogEmbedField(false, "modlog.member.old_nick", null); oldNickEmbedField.addValueObjects(((GuildMemberUpdateNicknameEvent) event).getOldValue()); embedFieldList.add(oldNickEmbedField); } if (((GuildMemberUpdateNicknameEvent) event).getNewValue() != null) { - ModlogEmbedField newNickEmbedField = new ModlogEmbedField(true, "modlog.member.new_nick", null); + ModlogEmbedField newNickEmbedField = new ModlogEmbedField(false, "modlog.member.new_nick", null); newNickEmbedField.addValueObjects(((GuildMemberUpdateNicknameEvent) event).getNewValue()); embedFieldList.add(newNickEmbedField); } @@ -424,16 +424,16 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { if (event instanceof GuildUpdateAfkChannelEvent) { VoiceChannel oldChannel = ((GuildUpdateAfkChannelEvent) event).getOldAfkChannel(); if (oldChannel != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_channel", null, oldChannel.getName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_channel", null, oldChannel.getName())); } VoiceChannel newChannel = ((GuildUpdateAfkChannelEvent) event).getNewAfkChannel(); if (newChannel != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_channel", null, newChannel.getName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_channel", null, newChannel.getName())); } modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_CHANNEL; } else if (event instanceof GuildUpdateAfkTimeoutEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getOldAfkTimeout().getSeconds()))); - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getNewAfkTimeout().getSeconds()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getOldAfkTimeout().getSeconds()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getNewAfkTimeout().getSeconds()))); modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_TIMEOUT; } else if (event instanceof GuildUpdateBannerEvent) { if (((GuildUpdateBannerEvent) event).getOldBannerUrl() != null) { @@ -452,8 +452,8 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { } modlogEvent = ModlogEvent.GUILD_UPDATE_DESCRIPTION; } else if (event instanceof GuildUpdateExplicitContentLevelEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.content_filter.old", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getOldLevel().name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.content_filter.new", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getNewLevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.content_filter.old", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getOldLevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.content_filter.new", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getNewLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_EXPLICIT_FILTER; } else if (event instanceof GuildUpdateFeaturesEvent) { ListChanges featuresChanged = new ListChanges<>(((GuildUpdateFeaturesEvent) event).getOldFeatures(), ((GuildUpdateFeaturesEvent) event).getNewFeatures()); @@ -469,27 +469,27 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { } modlogEvent = ModlogEvent.GUILD_UPDATE_ICON; } else if (event instanceof GuildUpdateMaxMembersEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getOldMaxMembers()))); - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getNewMaxMembers()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getOldMaxMembers()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getNewMaxMembers()))); modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_MEMBERS; } else if (event instanceof GuildUpdateMaxPresencesEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getOldMaxPresences()))); - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getNewMaxPresences()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getOldMaxPresences()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getNewMaxPresences()))); modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_PRESENCES; } else if (event instanceof GuildUpdateMFALevelEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.mfa.old", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getOldMFALevel().name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.mfa.new", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getNewMFALevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.mfa.old", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getOldMFALevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.mfa.new", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getNewMFALevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_MFA_LEVEL; } else if (event instanceof GuildUpdateNameEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", null, ((GuildUpdateNameEvent) event).getOldName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.general.old_name", null, ((GuildUpdateNameEvent) event).getOldName())); modlogEvent = ModlogEvent.GUILD_UPDATE_NAME; } else if (event instanceof GuildUpdateNotificationLevelEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.notification.old", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getOldNotificationLevel().name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.notification.new", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getNewNotificationLevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.notification.old", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getOldNotificationLevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.notification.new", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getNewNotificationLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_NOTIFICATION_LEVEL; } else if (event instanceof GuildUpdateRegionEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_region", null, ((GuildUpdateRegionEvent) event).getOldRegion().getName())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_region", null, ((GuildUpdateRegionEvent) event).getNewRegion().getName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_region", null, ((GuildUpdateRegionEvent) event).getOldRegion().getName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_region", null, ((GuildUpdateRegionEvent) event).getNewRegion().getName())); modlogEvent = ModlogEvent.GUILD_UPDATE_REGION; } else if (event instanceof GuildUpdateSplashEvent) { if (((GuildUpdateSplashEvent) event).getOldSplashUrl() != null) { @@ -502,38 +502,38 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { } else if (event instanceof GuildUpdateSystemChannelEvent) { TextChannel oldSystemChannel = ((GuildUpdateSystemChannelEvent) event).getOldSystemChannel(); if (oldSystemChannel != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_sys", null, oldSystemChannel.getName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_sys", null, oldSystemChannel.getName())); } TextChannel newSystemChannel = ((GuildUpdateSystemChannelEvent) event).getNewSystemChannel(); if (newSystemChannel != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_sys", null, newSystemChannel.getName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_sys", null, newSystemChannel.getName())); } modlogEvent = ModlogEvent.GUILD_UPDATE_SYSTEM_CHANNEL; } else if (event instanceof GuildUpdateVanityCodeEvent) { if (((GuildUpdateVanityCodeEvent) event).getOldVanityCode() != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_code.old", null, ((GuildUpdateVanityCodeEvent) event).getOldVanityCode())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.vanity_code.old", null, ((GuildUpdateVanityCodeEvent) event).getOldVanityCode())); } if (((GuildUpdateVanityCodeEvent) event).getOldVanityUrl() != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_url.old", null, ((GuildUpdateVanityCodeEvent) event).getOldVanityUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.vanity_url.old", null, ((GuildUpdateVanityCodeEvent) event).getOldVanityUrl())); } if (((GuildUpdateVanityCodeEvent) event).getNewVanityCode() != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_code.new", null, ((GuildUpdateVanityCodeEvent) event).getNewVanityCode())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.vanity_code.new", null, ((GuildUpdateVanityCodeEvent) event).getNewVanityCode())); } if (((GuildUpdateVanityCodeEvent) event).getNewVanityUrl() != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.vanity_url.new", null, ((GuildUpdateVanityCodeEvent) event).getNewVanityUrl())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.vanity_url.new", null, ((GuildUpdateVanityCodeEvent) event).getNewVanityUrl())); } modlogEvent = ModlogEvent.GUILD_UPDATE_VANITY_CODE; } else if (event instanceof GuildUpdateVerificationLevelEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getOldVerificationLevel().name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getNewVerificationLevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getOldVerificationLevel().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getNewVerificationLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_VERIFICATION_LEVEL; } else if (event instanceof GuildUpdateBoostCountEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_boost_count", null, String.valueOf(event.getOldValue()))); - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_boost_count", null, String.valueOf(event.getNewValue()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_boost_count", null, String.valueOf(event.getOldValue()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_boost_count", null, String.valueOf(event.getNewValue()))); modlogEvent = ModlogEvent.GUILD_BOOST_COUNT_UPDATED; } else if (event instanceof GuildUpdateBoostTierEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.old_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getOldBoostTier().name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.guild.new_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getNewBoostTier().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getOldBoostTier().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getNewBoostTier().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_BOOST_TIER_UPDATED; } else { return; @@ -551,30 +551,30 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { List embedFieldList = new ArrayList<>(); ModlogEvent action; if (event instanceof GuildVoiceDeafenEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.deafen", null, String.valueOf(((GuildVoiceDeafenEvent) event).isDeafened()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.deafen", null, String.valueOf(((GuildVoiceDeafenEvent) event).isDeafened()))); action = ModlogEvent.VOICE_DEAFEN; } else if (event instanceof GuildVoiceMuteEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.mute", null, String.valueOf(((GuildVoiceMuteEvent) event).isMuted()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.mute", null, String.valueOf(((GuildVoiceMuteEvent) event).isMuted()))); action = ModlogEvent.VOICE_MUTE; } else if (event instanceof GuildVoiceGuildDeafenEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.deafen", null, String.valueOf(((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.deafen", null, String.valueOf(((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()))); action = ModlogEvent.VOICE_SERVER_DEAFEN; } else if (event instanceof GuildVoiceGuildMuteEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.mute", null, String.valueOf(((GuildVoiceGuildMuteEvent) event).isGuildMuted()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.mute", null, String.valueOf(((GuildVoiceGuildMuteEvent) event).isGuildMuted()))); action = ModlogEvent.VOICE_SERVER_MUTE; } else if (event instanceof GuildVoiceJoinEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.join", null, ((GuildVoiceJoinEvent) event).getChannelJoined().getName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.join", null, ((GuildVoiceJoinEvent) event).getChannelJoined().getName())); action = ModlogEvent.VOICE_JOIN; } else if (event instanceof GuildVoiceLeaveEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.left", null, ((GuildVoiceLeaveEvent) event).getChannelLeft().getName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.left", null, ((GuildVoiceLeaveEvent) event).getChannelLeft().getName())); if (auditLogEntry != null) { action = ModlogEvent.VOICE_DISCONNECT; } else { action = ModlogEvent.VOICE_LEAVE; } } else if (event instanceof GuildVoiceMoveEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.left", null, ((GuildVoiceMoveEvent) event).getChannelLeft().getName())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.voice.join", null, ((GuildVoiceMoveEvent) event).getChannelJoined().getName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.left", null, ((GuildVoiceMoveEvent) event).getChannelLeft().getName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.join", null, ((GuildVoiceMoveEvent) event).getChannelJoined().getName())); if (auditLogEntry != null) { action = ModlogEvent.VOICE_FORCE_MOVE; } else { @@ -629,11 +629,11 @@ public void onGenericTextChannel(GenericTextChannelEvent event) { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } if (event instanceof TextChannelUpdateNSFWEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.nsfw", null, String.valueOf(!((TextChannelUpdateNSFWEvent) event).getOldNSFW()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.nsfw", null, String.valueOf(!((TextChannelUpdateNSFWEvent) event).getOldNSFW()))); trigger = ModlogEvent.TEXT_CHANNEL_NSFW_UPDATED; } else if (event instanceof TextChannelUpdateSlowmodeEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_slowmode", null, String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getOldSlowmode()))); - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_slowmode", null, String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getNewSlowmode()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_slowmode", null, String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getOldSlowmode()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_slowmode", null, String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getNewSlowmode()))); trigger = ModlogEvent.TEXT_CHANNEL_SLOWMODE_UPDATED; } else if (event instanceof TextChannelUpdateTopicEvent) { embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_topic", null, ((TextChannelUpdateTopicEvent) event).getOldTopic())); @@ -670,12 +670,12 @@ public void onGenericVoiceChannel(GenericVoiceChannelEvent event) { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } if (event instanceof VoiceChannelUpdateBitrateEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getOldBitrate()))); - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getNewBitrate()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getOldBitrate()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getNewBitrate()))); trigger = ModlogEvent.VOICE_CHANNEL_BITRATE_UPDATED; } else if (event instanceof VoiceChannelUpdateUserLimitEvent) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_users", "modlog.channel.user", String.valueOf(((VoiceChannelUpdateUserLimitEvent) event).getOldUserLimit()))); - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_users", "modlog.channel.user", String.valueOf(((VoiceChannelUpdateUserLimitEvent) event).getNewUserLimit()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_users", "modlog.channel.user", String.valueOf(((VoiceChannelUpdateUserLimitEvent) event).getOldUserLimit()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_users", "modlog.channel.user", String.valueOf(((VoiceChannelUpdateUserLimitEvent) event).getNewUserLimit()))); trigger = ModlogEvent.VOICE_CHANNEL_USER_LIMIT_UPDATED; } else { return; @@ -754,7 +754,7 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { denied.addTitleObjects(permissionsHolderName); embedFieldList.add(denied); } - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + event.getChannelType().name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + event.getChannelType().name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, event.getChannel(), embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventStore); }, ActionType.CHANNEL_OVERRIDE_UPDATE, ActionType.CHANNEL_UPDATE); @@ -774,7 +774,7 @@ private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChann } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel create entry"); } - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_CREATE); @@ -791,7 +791,7 @@ private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChann } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel delete entry"); } - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_DELETE); @@ -808,8 +808,8 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", null, oldName)); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.general.old_name", null, oldName)); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_UPDATE); @@ -843,9 +843,9 @@ public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Categ } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_parent", null, oldParent.getName())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_parent", null, newParent.getName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_parent", null, oldParent.getName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_parent", null, newParent.getName())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_UPDATE); @@ -873,11 +873,11 @@ public void onGenericRole(GenericRoleEvent event) { modlogEvent = ModlogEvent.ROLE_COLOR_UPDATED; Color oldColor = ((RoleUpdateColorEvent) event).getOldColor(); if (oldColor != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.role.old_color", null, ColorUtils.getHex(oldColor.getRed(), oldColor.getGreen(), oldColor.getBlue()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.role.old_color", null, ColorUtils.getHex(oldColor.getRed(), oldColor.getGreen(), oldColor.getBlue()))); } Color newColor = ((RoleUpdateColorEvent) event).getNewColor(); if (newColor != null) { - embedFieldList.add(new ModlogEmbedField(true, "modlog.role.new_color", null, ColorUtils.getHex(newColor.getRed(), newColor.getGreen(), newColor.getBlue()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.role.new_color", null, ColorUtils.getHex(newColor.getRed(), newColor.getGreen(), newColor.getBlue()))); } } else if (event instanceof RoleUpdateHoistedEvent) { modlogEvent = ModlogEvent.ROLE_HOIST_UPDATED; @@ -911,7 +911,7 @@ public void onGenericRole(GenericRoleEvent event) { // If the position stays the same, we have no reason to log the event return; } - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.position", "modlog.general.small_change", ((RoleUpdatePositionEvent) event).getOldPosition() + 1, ((RoleUpdatePositionEvent) event).getNewPosition() + 1)); + embedFieldList.add(new ModlogEmbedField(false, "modlog.general.position", "modlog.general.small_change", ((RoleUpdatePositionEvent) event).getOldPosition() + 1, ((RoleUpdatePositionEvent) event).getNewPosition() + 1)); } else { return; } From 3b70e8993a5c171f9522e8e1e32ee77a08667428 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 26 Oct 2020 14:55:47 +0000 Subject: [PATCH 078/206] Nickname audit log? --- .../org/cascadebot/cascadebot/events/ModlogEventListener.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index dcf11395e..0932119c3 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -238,6 +238,9 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { removedRolesEmbedField.addValueObjects(((GuildMemberRoleRemoveEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n"))); embedFieldList.add(removedRolesEmbedField); } else if (event instanceof GuildMemberUpdateNicknameEvent) { + if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_UPDATE) { + responsible = auditLogEntry.getUser(); + } if (((GuildMemberUpdateNicknameEvent) event).getOldValue() != null) { ModlogEmbedField oldNickEmbedField = new ModlogEmbedField(false, "modlog.member.old_nick", null); oldNickEmbedField.addValueObjects(((GuildMemberUpdateNicknameEvent) event).getOldValue()); From 8d4a3ae2c38242b6143567cd3c231b37f5f1207f Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 26 Oct 2020 18:14:46 +0000 Subject: [PATCH 079/206] Lots of channel stuff, voice channel, text channel, text channel moves --- .../events/ModlogEventListener.java | 42 ++++++++++++------- .../ModlogChannelMoveCollectorRunnable.java | 35 +++++++++++----- .../cascadebot/moderation/ModlogEvent.kt | 1 + src/main/resources/lang/en-GB.json | 41 +++++++++--------- 4 files changed, 74 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 0932119c3..d99d1f152 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -101,8 +101,11 @@ import net.dv8tion.jda.api.events.user.update.UserUpdateDiscriminatorEvent; import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; +import org.apache.commons.codec.language.bm.Lang; import org.cascadebot.cascadebot.CascadeBot; +import org.cascadebot.cascadebot.UnicodeConstants; import org.cascadebot.cascadebot.data.Config; +import org.cascadebot.cascadebot.data.language.Language; import org.cascadebot.cascadebot.data.managers.GuildDataManager; import org.cascadebot.cascadebot.data.objects.GuildData; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; @@ -117,6 +120,7 @@ import org.cascadebot.cascadebot.utils.CryptUtils; import org.cascadebot.cascadebot.utils.ModlogUtils; import org.cascadebot.cascadebot.utils.SerializableMessage; +import org.cascadebot.shared.utils.ThreadPoolExecutorLogged; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; @@ -136,6 +140,11 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; public class ModlogEventListener extends ListenerAdapter { @@ -238,6 +247,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { removedRolesEmbedField.addValueObjects(((GuildMemberRoleRemoveEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n"))); embedFieldList.add(removedRolesEmbedField); } else if (event instanceof GuildMemberUpdateNicknameEvent) { + // TODO: This still doesn't work, auditLogEntry is null? if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_UPDATE) { responsible = auditLogEntry.getUser(); } @@ -632,13 +642,14 @@ public void onGenericTextChannel(GenericTextChannelEvent event) { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } if (event instanceof TextChannelUpdateNSFWEvent) { + // TODO embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.nsfw", null, String.valueOf(!((TextChannelUpdateNSFWEvent) event).getOldNSFW()))); trigger = ModlogEvent.TEXT_CHANNEL_NSFW_UPDATED; } else if (event instanceof TextChannelUpdateSlowmodeEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_slowmode", null, String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getOldSlowmode()))); - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_slowmode", null, String.valueOf(((TextChannelUpdateSlowmodeEvent) event).getNewSlowmode()))); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.slowmode", "modlog.general.small_change", ((TextChannelUpdateSlowmodeEvent) event).getOldSlowmode(), ((TextChannelUpdateSlowmodeEvent) event).getNewSlowmode())); trigger = ModlogEvent.TEXT_CHANNEL_SLOWMODE_UPDATED; } else if (event instanceof TextChannelUpdateTopicEvent) { + // TODO: If empty new topic, fails embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_topic", null, ((TextChannelUpdateTopicEvent) event).getOldTopic())); embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_topic", null, ((TextChannelUpdateTopicEvent) event).getNewTopic())); trigger = ModlogEvent.TEXT_CHANNEL_TOPIC_UPDATED; @@ -673,12 +684,16 @@ public void onGenericVoiceChannel(GenericVoiceChannelEvent event) { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } if (event instanceof VoiceChannelUpdateBitrateEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getOldBitrate()))); - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_bitrate", "modlog.channel.kpbs", String.valueOf(((VoiceChannelUpdateBitrateEvent) event).getNewBitrate()))); + String oldBitrate = Language.i18n(event.getGuild().getIdLong(), "modlog.channel.kbps", ((VoiceChannelUpdateBitrateEvent) event).getOldBitrate() / 1000); + String newBitrate = Language.i18n(event.getGuild().getIdLong(), "modlog.channel.kbps", ((VoiceChannelUpdateBitrateEvent) event).getNewBitrate() / 1000); + + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.bitrate", "modlog.general.small_change", oldBitrate, newBitrate)); trigger = ModlogEvent.VOICE_CHANNEL_BITRATE_UPDATED; } else if (event instanceof VoiceChannelUpdateUserLimitEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_users", "modlog.channel.user", String.valueOf(((VoiceChannelUpdateUserLimitEvent) event).getOldUserLimit()))); - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_users", "modlog.channel.user", String.valueOf(((VoiceChannelUpdateUserLimitEvent) event).getNewUserLimit()))); + var limitEvent = (VoiceChannelUpdateUserLimitEvent) event; + String oldLimit = limitEvent.getOldUserLimit() == 0 ? UnicodeConstants.INFINITY_SYMBOL : String.valueOf(limitEvent.getOldUserLimit()); + String newLimit = limitEvent.getNewUserLimit() == 0 ? UnicodeConstants.INFINITY_SYMBOL : String.valueOf(limitEvent.getNewUserLimit()); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.users", "modlog.general.small_change", oldLimit, newLimit)); trigger = ModlogEvent.VOICE_CHANNEL_USER_LIMIT_UPDATED; } else { return; @@ -812,7 +827,8 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.general.old_name", null, oldName)); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", null, oldName)); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.new_name", null, channel.getName())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_UPDATE); @@ -824,12 +840,10 @@ private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, in if (moveRunnableMap.containsKey(guild.getIdLong())) { moveRunnableMap.get(guild.getIdLong()).getQueue().add(moveData); } else { - ModlogChannelMoveCollectorRunnable runnable = new ModlogChannelMoveCollectorRunnable(guild, new Runnable() { - @Override - public void run() { - moveRunnableMap.remove(guild.getIdLong()); - } + ModlogChannelMoveCollectorRunnable runnable = new ModlogChannelMoveCollectorRunnable(guild, () -> { + moveRunnableMap.remove(guild.getIdLong()); }); + runnable.getQueue().add(moveData); moveRunnableMap.put(guild.getIdLong(), runnable); new Thread(runnable, "modlog-channel-move-" + guild.getId()).start(); } @@ -847,8 +861,8 @@ public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Categ CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_parent", null, oldParent.getName())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_parent", null, newParent.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_parent", null, oldParent.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_parent", null, newParent.getName())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_UPDATE); diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java index d0ecbb56b..d8755db69 100644 --- a/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java +++ b/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java @@ -5,6 +5,7 @@ import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.GuildChannel; import net.dv8tion.jda.api.entities.User; +import org.bouncycastle.math.raw.Mod; import org.cascadebot.cascadebot.data.managers.GuildDataManager; import org.cascadebot.cascadebot.data.objects.GuildData; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; @@ -57,14 +58,13 @@ private void afterCollected() { if (auditLogEntry != null) { responsible = auditLogEntry.getUser(); } - List embedParts = new ArrayList<>(); int maxDistance = 0; List maxMoveDatas = new ArrayList<>(); for (ChannelMoveData moveData : channelMoveDataList) { if (moveData == null) { continue; } - int distance = moveData.channel.getPosition() - moveData.oldPos; + int distance = Math.abs(moveData.channel.getPosition() - moveData.oldPos); if (distance == maxDistance) { maxMoveDatas.add(moveData); } else if (distance > maxDistance) { @@ -74,17 +74,30 @@ private void afterCollected() { } } - for (ChannelMoveData data : maxMoveDatas) { - ModlogEmbedField field = new ModlogEmbedField(false, "modlog.channel.position.title", - "modlog.channel.position.positions", - String.valueOf(data.oldPos), String.valueOf(data.channel.getPosition())); - field.addTitleObjects(data.channel.getName()); - embedParts.add(field); + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + if (maxMoveDatas.size() == 1) { + ChannelMoveData data = maxMoveDatas.get(0); + ModlogEmbedField field = new ModlogEmbedField(false, + "modlog.general.position", + "modlog.general.small_change", + String.valueOf(data.oldPos), + String.valueOf(data.channel.getPosition())); + ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.CHANNEL_POSITION_UPDATED, responsible, maxMoveDatas.get(0).channel, List.of(field)); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), eventStore); + } else { + List embedParts = new ArrayList<>(); + for (ChannelMoveData data : maxMoveDatas) { + ModlogEmbedField field = new ModlogEmbedField(false, "modlog.channel.position.title", + "modlog.general.small_change", + String.valueOf(data.oldPos), String.valueOf(data.channel.getPosition())); + field.addTitleObjects(data.channel.getName()); + embedParts.add(field); + } + ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.MULTIPLE_CHANNEL_POSITION_UPDATED, responsible, maxMoveDatas.get(0).channel, embedParts); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), eventStore); } - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.CHANNEL_POSITION_UPDATED, responsible, maxMoveDatas.get(0).channel, embedParts); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), eventStore); + }, ActionType.CHANNEL_UPDATE); } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index ce652958d..135a7938a 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -77,6 +77,7 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: CHANNEL_NAME_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), CHANNEL_PERMISSIONS_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), CHANNEL_POSITION_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), + MULTIPLE_CHANNEL_POSITION_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), CHANNEL_PARENT_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), VOICE_CHANNEL_BITRATE_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 604be7f10..b9fa39f66 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1649,56 +1649,60 @@ "channel_created": { "select": "channel_created", "display": "Channel created", - "description": "Channel {0} was created" + "description": "Channel `#{0}` was created" }, "channel_deleted": { "select": "channel_deleted", "display": "Channel deleted", - "description": "Channel {0} was deleted" + "description": "Channel `#{0}` was deleted" }, "channel_name_updated": { "select": "channel_name_updated", "display": "Channel name updated", - "description": "Channel {0} had its name changed" + "description": "Channel `#{0}` had its name changed" }, "channel_permissions_updated": { "select": "channel_permissions_updated", "display": "Channel permissions updated", - "description": "Channel {0} permissions where changed" + "description": "The channel `#{0}` permissions where changed" }, "channel_position_updated": { "select": "channel_position_updated", "display": "Channel position updated", - "description": "Channel {0} was moved" + "description": "The channel `#{0}` was moved" + }, + "multiple_channel_position_updated": { + "select": "multiple_channel_position_updated", + "display": "Multiple channel's position updated" }, "channel_parent_updated": { "select": "channel_parent_updated", "display": "Channel parent updated", - "description": "Channel {0} changed category" + "description": "The channel `#{0}` changed category" }, "voice_channel_bitrate_updated": { "select": "voice_channel_bitrate_updated", "display": "Voice channel bitrate updated", - "description": "Channel {0} had its bitrate changed" + "description": "The channel `#{0}` had its bitrate changed" }, "voice_channel_user_limit_updated": { "select": "voice_channel_user_limit_updated", "display": "Voice channel user limit updated", - "description": "Channel {0} user limit was changed" + "description": "The channel `#{0}` user limit was changed" }, "text_channel_nsfw_updated": { "select": "text_channel_nsfw_updated", - "display": "Text channel nsfw updated" + "display": "Text channel NSFW updated" }, "text_channel_slowmode_updated": { "select": "text_channel_slowmode_updated", "display": "Text channel slowmode updated", - "description": "Channel {0} slowmode time was changed" + "description": "The channel `#{0}` slowmode time was changed" }, "text_channel_topic_updated": { "select": "text_channel_topic_updated", "display": "Text channel topic updated", - "description": "Channel {0} topic was updated" + "description": "Channel `#{0}` topic was updated" }, "cascade_permissions_group_created": { "select": "cascade_permissions_group_created", @@ -1923,6 +1927,7 @@ "conditions": "conditions", "true": "true", "false": "false", + "unknown": "unknown", "command_filters": "command filters" }, "messaging": { @@ -2430,22 +2435,18 @@ "old_deny": "Old Denied permissions for {0}" }, "position": { - "title": "Channel {0} moved", - "positions": "{0} -> {1}" + "title": "Channel {0} moved" }, "old_parent": "Old Parent", "new_parent": "New Parent", "nsfw": "NSFW", - "old_slowmode": "Old Slowmode", - "new_slowmode": "New Slowmode", + "slowmode": "Slowmode", "old_topic": "Old topic", "new_topic": "New topic", - "kpbs": "{0}kbps", - "old_bitrate": "Old bitrate", - "new_bitrate": "New bitrate", + "kbps": "{0}kbps", + "bitrate": "Bitrate", "user": "{0} users", - "old_users": "Old user limit", - "new_users": "New user limit" + "users": "User limit" }, "role": { "old_color": "Old Color", From 92566be2a0ddfda129d423bfc96772331bb0e5bc Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 26 Oct 2020 20:00:47 +0000 Subject: [PATCH 080/206] TextChannel: Topic and NSFW --- .../events/ModlogEventListener.java | 22 +++++++++++++------ src/main/resources/lang/en-GB.json | 3 ++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index d99d1f152..94434f340 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -102,6 +102,7 @@ import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.apache.commons.codec.language.bm.Lang; +import org.apache.commons.lang3.StringUtils; import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.UnicodeConstants; import org.cascadebot.cascadebot.data.Config; @@ -635,6 +636,7 @@ public void onGenericTextChannel(GenericTextChannelEvent event) { ModlogUtils.getAuditLogFromType(event.getGuild(), event.getChannel().getIdLong(), auditLogEntry -> { ModlogEvent trigger; List embedFieldList = new ArrayList<>(); + List descriptionParts = new ArrayList<>(); User responsible = null; if (auditLogEntry != null) { responsible = auditLogEntry.getUser(); @@ -642,21 +644,28 @@ public void onGenericTextChannel(GenericTextChannelEvent event) { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } if (event instanceof TextChannelUpdateNSFWEvent) { - // TODO - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.nsfw", null, String.valueOf(!((TextChannelUpdateNSFWEvent) event).getOldNSFW()))); trigger = ModlogEvent.TEXT_CHANNEL_NSFW_UPDATED; + + Boolean newValue = ((TextChannelUpdateNSFWEvent) event).getNewValue(); + Emote emote = newValue != null && newValue ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("tick")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("cross")); + descriptionParts = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(newValue)); } else if (event instanceof TextChannelUpdateSlowmodeEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.slowmode", "modlog.general.small_change", ((TextChannelUpdateSlowmodeEvent) event).getOldSlowmode(), ((TextChannelUpdateSlowmodeEvent) event).getNewSlowmode())); trigger = ModlogEvent.TEXT_CHANNEL_SLOWMODE_UPDATED; + + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.slowmode", "modlog.general.small_change", ((TextChannelUpdateSlowmodeEvent) event).getOldSlowmode(), ((TextChannelUpdateSlowmodeEvent) event).getNewSlowmode())); } else if (event instanceof TextChannelUpdateTopicEvent) { - // TODO: If empty new topic, fails - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_topic", null, ((TextChannelUpdateTopicEvent) event).getOldTopic())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_topic", null, ((TextChannelUpdateTopicEvent) event).getNewTopic())); trigger = ModlogEvent.TEXT_CHANNEL_TOPIC_UPDATED; + + String oldTopic = ((TextChannelUpdateTopicEvent) event).getOldTopic(); + String newTopic = ((TextChannelUpdateTopicEvent) event).getNewTopic(); + + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_topic", null, StringUtils.isBlank(oldTopic) ? "-" : oldTopic)); + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_topic", null, StringUtils.isBlank(newTopic) ? "-" : newTopic)); } else { return; } ModlogEventStore eventStore = new ModlogEventStore(trigger, responsible, event.getChannel(), embedFieldList); + eventStore.setExtraDescriptionInfo(descriptionParts); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }, ActionType.CHANNEL_UPDATE); } @@ -900,7 +909,6 @@ public void onGenericRole(GenericRoleEvent event) { modlogEvent = ModlogEvent.ROLE_HOIST_UPDATED; var wasHoisted = ((RoleUpdateHoistedEvent) event).wasHoisted(); Emote emote = !wasHoisted ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("tick")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("cross")); - // TODO: Display role as new role (17367245237) instead of just new role in the description descriptionStuff = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(!wasHoisted)); } else if (event instanceof RoleUpdateMentionableEvent) { modlogEvent = ModlogEvent.ROLE_MENTIONABLE_UPDATED; diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index b9fa39f66..83b566efe 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1692,7 +1692,8 @@ }, "text_channel_nsfw_updated": { "select": "text_channel_nsfw_updated", - "display": "Text channel NSFW updated" + "display": "Text channel NSFW updated", + "description": "{2} {3, select, true {The text channel `#{0}` is now an NSFW channel} other {The text channel `#{0}` is no longer a NSFW channel}}" }, "text_channel_slowmode_updated": { "select": "text_channel_slowmode_updated", From f96e1dfbe1c006ed1c30da4acfc87e5bdee51d8c Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 26 Oct 2020 20:03:26 +0000 Subject: [PATCH 081/206] Reduce warnings in Modlog event listener --- .../events/ModlogEventListener.java | 32 ++++++------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 94434f340..fb6ea4416 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -4,7 +4,6 @@ import com.google.gson.JsonParser; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.audit.ActionType; -import net.dv8tion.jda.api.audit.AuditLogEntry; import net.dv8tion.jda.api.entities.Category; import net.dv8tion.jda.api.entities.ChannelType; import net.dv8tion.jda.api.entities.Emote; @@ -101,7 +100,6 @@ import net.dv8tion.jda.api.events.user.update.UserUpdateDiscriminatorEvent; import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import org.apache.commons.codec.language.bm.Lang; import org.apache.commons.lang3.StringUtils; import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.UnicodeConstants; @@ -121,7 +119,7 @@ import org.cascadebot.cascadebot.utils.CryptUtils; import org.cascadebot.cascadebot.utils.ModlogUtils; import org.cascadebot.cascadebot.utils.SerializableMessage; -import org.cascadebot.shared.utils.ThreadPoolExecutorLogged; +import org.jetbrains.annotations.NotNull; import javax.crypto.BadPaddingException; import javax.crypto.IllegalBlockSizeException; @@ -132,26 +130,18 @@ import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; -import java.time.Duration; -import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collection; import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; public class ModlogEventListener extends ListenerAdapter { - private Map moveRunnableMap = new HashMap<>(); - private Map roleRunnableMap = new HashMap<>(); + private final Map moveRunnableMap = new HashMap<>(); + private final Map roleRunnableMap = new HashMap<>(); public void onGenericEmote(GenericEmoteEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); @@ -314,7 +304,7 @@ public void onGuildUnban(GuildUnbanEvent event) { //endregion //region Message - public void onGuildMessageDelete(GuildMessageDeleteEvent event) { + public void onGuildMessageDelete(@NotNull GuildMessageDeleteEvent event) { if (CascadeBot.INS.getRedisClient() == null) { return; } @@ -362,7 +352,7 @@ public void onGuildMessageDelete(GuildMessageDeleteEvent event) { }, ActionType.MESSAGE_DELETE); } - public void onGuildMessageUpdate(GuildMessageUpdateEvent event) { + public void onGuildMessageUpdate(@NotNull GuildMessageUpdateEvent event) { if (CascadeBot.INS.getRedisClient() == null) { return; } @@ -603,7 +593,7 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { } //region Channels - public void onGenericStoreChannel(GenericStoreChannelEvent event) { + public void onGenericStoreChannel(@NotNull GenericStoreChannelEvent event) { if (event instanceof StoreChannelCreateEvent) { handleChannelCreateEvents(event.getChannel().getGuild(), ChannelType.STORE, event.getChannel()); } else if (event instanceof StoreChannelDeleteEvent) { @@ -615,7 +605,7 @@ public void onGenericStoreChannel(GenericStoreChannelEvent event) { } } - public void onGenericTextChannel(GenericTextChannelEvent event) { + public void onGenericTextChannel(@NotNull GenericTextChannelEvent event) { if (event instanceof TextChannelCreateEvent) { handleChannelCreateEvents(event.getGuild(), ChannelType.TEXT, event.getChannel()); return; @@ -670,7 +660,7 @@ public void onGenericTextChannel(GenericTextChannelEvent event) { }, ActionType.CHANNEL_UPDATE); } - public void onGenericVoiceChannel(GenericVoiceChannelEvent event) { + public void onGenericVoiceChannel(@NotNull GenericVoiceChannelEvent event) { if (event instanceof VoiceChannelCreateEvent) { handleChannelCreateEvents(event.getGuild(), ChannelType.VOICE, event.getChannel()); } else if (event instanceof VoiceChannelDeleteEvent) { @@ -712,7 +702,7 @@ public void onGenericVoiceChannel(GenericVoiceChannelEvent event) { }, ActionType.CHANNEL_UPDATE); } - public void onGenericCategory(GenericCategoryEvent event) { + public void onGenericCategory(@NotNull GenericCategoryEvent event) { if (event instanceof CategoryCreateEvent) { handleChannelCreateEvents(event.getGuild(), ChannelType.CATEGORY, event.getCategory()); } else if (event instanceof CategoryDeleteEvent) { @@ -849,9 +839,7 @@ private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, in if (moveRunnableMap.containsKey(guild.getIdLong())) { moveRunnableMap.get(guild.getIdLong()).getQueue().add(moveData); } else { - ModlogChannelMoveCollectorRunnable runnable = new ModlogChannelMoveCollectorRunnable(guild, () -> { - moveRunnableMap.remove(guild.getIdLong()); - }); + ModlogChannelMoveCollectorRunnable runnable = new ModlogChannelMoveCollectorRunnable(guild, () -> moveRunnableMap.remove(guild.getIdLong())); runnable.getQueue().add(moveData); moveRunnableMap.put(guild.getIdLong(), runnable); new Thread(runnable, "modlog-channel-move-" + guild.getId()).start(); From 95faf399db4d88885ef4fd310cb2644ebcbb39a4 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 26 Oct 2020 20:20:56 +0000 Subject: [PATCH 082/206] Kotlinfy the event store and even listener --- .../data/objects/GuildSettingsModeration.kt | 21 ++-- .../data/objects/ModlogEventStore.kt | 112 +++++++----------- 2 files changed, 55 insertions(+), 78 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 9c650835f..f777a4605 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -184,11 +184,13 @@ class GuildSettingsModeration { ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL -> { when (affected.affectedType) { AffectedType.USER -> { - val user: User = CascadeBot.INS.shardManager.getUserById(affected.id!!)!! - if (user.avatarUrl != null) { - webhookEmbedBuilder.setThumbnailUrl(user.avatarUrl) - } else { - webhookEmbedBuilder.setThumbnailUrl(user.defaultAvatarUrl) + val user: User? = CascadeBot.INS.shardManager.getUserById(affected.id!!) + user?.let { + if (it.avatarUrl != null) { + webhookEmbedBuilder.setThumbnailUrl(it.avatarUrl) + } else { + webhookEmbedBuilder.setThumbnailUrl(it.defaultAvatarUrl) + } } } AffectedType.EMOTE -> { @@ -225,12 +227,13 @@ class GuildSettingsModeration { webhookEmbedBuilder.setColor(modlogEventStore.trigger.messageType.color.rgb) webhookEmbedBuilder.setTimestamp(Instant.now()) if (modlogEventStore.responsible != null) { - var iconUrl = if (modlogEventStore.responsible!!.avatarUrl != null) { - modlogEventStore.responsible!!.avatarUrl + var iconUrl = if (modlogEventStore.responsible.avatarUrl != null) { + modlogEventStore.responsible.avatarUrl } else { - modlogEventStore.responsible!!.defaultAvatarUrl + modlogEventStore.responsible.defaultAvatarUrl } - webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventStore.responsible!!.name + " (" + modlogEventStore.responsible!!.id + ")", iconUrl)) + // TODO: by user + webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventStore.responsible.name + " (" + modlogEventStore.responsible.id + ")", iconUrl)) } try { webhookClient?.send(webhookEmbedBuilder.build()) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 822ff54f8..f7698d1bd 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -13,84 +13,58 @@ import org.cascadebot.cascadebot.permissions.objects.Group import java.lang.UnsupportedOperationException import java.lang.reflect.Field -class ModlogEventStore { +class ModlogEventStore(val trigger: ModlogEvent, val responsible: User?, affected: Any, extraInfo: MutableList) { - var trigger: ModlogEvent = ModlogEvent.CASCADE_BLACKLIST - - @Transient - var responsible: User? = null - - var affected: ModlogAffected = ModlogAffected() + val affected: ModlogAffected = when (affected) { + is User -> { + ModlogAffected(AffectedType.USER, affected.asTag, affected.id) + } + is Role -> { + ModlogAffected(AffectedType.ROLE, "${affected.name} (${affected.id})", affected.id) + } + is Emote -> { + ModlogAffected(AffectedType.EMOTE, affected.name, affected.id) + } + is Guild -> { + ModlogAffected(AffectedType.GUILD, affected.name) + } + is GuildChannel -> { + ModlogAffected(AffectedType.CHANNEL, affected.name, affected.id) + } + is Group -> { + ModlogAffected(AffectedType.GROUP, affected.name, affected.id) + } + is Field -> { + ModlogAffected(AffectedType.SETTING, affected.name) + } + is Module -> { + ModlogAffected(AffectedType.MODULE, affected.name) + } + is MainCommand -> { + ModlogAffected(AffectedType.COMMAND, affected.command()) + } + is Playlist -> { + ModlogAffected(AffectedType.PLAYLIST, affected.name, affected.playlistId.toHexString()) + } + is Tag -> { + ModlogAffected(AffectedType.TAG, affected.name) + } + else -> { + ModlogAffected() + } + } var extraInfo: MutableList = mutableListOf() var extraDescriptionInfo: MutableList = mutableListOf() - var responsibleId: Long = 0 + val responsibleId: Long = responsible?.idLong ?: 0 - constructor(trigger: ModlogEvent, responsible: User?, affected: Any, extraInfo: MutableList) { - this.trigger = trigger - this.responsible = responsible - this.extraInfo = extraInfo + constructor() : this(ModlogEvent.CASCADE_BLACKLIST, null, "", mutableListOf()) - var affectedType: AffectedType = AffectedType.UNKNOWN - this.affected = when (affected) { - is User -> { - affectedType = AffectedType.USER - ModlogAffected(AffectedType.USER, affected.asTag, affected.id) - } - is Role -> { - affectedType = AffectedType.ROLE - ModlogAffected(AffectedType.ROLE, "${affected.name} (${affected.id})", affected.id) - } - is Emote -> { - affectedType = AffectedType.EMOTE - ModlogAffected(AffectedType.EMOTE, affected.name, affected.id) - } - is Guild -> { - affectedType = AffectedType.GUILD - ModlogAffected(AffectedType.GUILD, affected.name) - } - is GuildChannel -> { - affectedType = AffectedType.CHANNEL - ModlogAffected(AffectedType.CHANNEL, affected.name, affected.id) - } - is Group -> { - affectedType = AffectedType.GROUP - ModlogAffected(AffectedType.GROUP, affected.name, affected.id) - } - is Field -> { - affectedType = AffectedType.SETTING - ModlogAffected(AffectedType.SETTING, affected.name) - } - is Module -> { - affectedType = AffectedType.MODULE - ModlogAffected(AffectedType.MODULE, affected.name) - } - is MainCommand -> { - affectedType = AffectedType.COMMAND - ModlogAffected(AffectedType.COMMAND, affected.command()) - } - is Playlist -> { - affectedType = AffectedType.PLAYLIST - ModlogAffected(AffectedType.PLAYLIST, affected.name, affected.playlistId.toHexString()) - } - is Tag -> { - affectedType = AffectedType.TAG - ModlogAffected(AffectedType.TAG, affected.name) - } - else -> { - ModlogAffected() - } - } - if (!affectedType.allowedDisplayTypes.contains(trigger.displayType)) { + init { + if (!this.affected.affectedType.allowedDisplayTypes.contains(trigger.displayType)) { throw UnsupportedOperationException("This events display type does not support this affected") } - - if (responsible != null) { - responsibleId = responsible.idLong - } } - constructor() - } \ No newline at end of file From 213a798249a1798b0dc095553db38770ff7c5318 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 26 Oct 2020 17:26:58 -0500 Subject: [PATCH 083/206] Add member updated to audit filter Also disabled saving events to db as it's broken --- .../org/cascadebot/cascadebot/events/ModlogEventListener.java | 3 +-- .../cascadebot/data/objects/GuildSettingsModeration.kt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index fb6ea4416..3ab6855ca 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -238,7 +238,6 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { removedRolesEmbedField.addValueObjects(((GuildMemberRoleRemoveEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n"))); embedFieldList.add(removedRolesEmbedField); } else if (event instanceof GuildMemberUpdateNicknameEvent) { - // TODO: This still doesn't work, auditLogEntry is null? if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_UPDATE) { responsible = auditLogEntry.getUser(); } @@ -258,7 +257,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }, ActionType.KICK, ActionType.MEMBER_ROLE_UPDATE); + }, ActionType.KICK, ActionType.MEMBER_ROLE_UPDATE, ActionType.MEMBER_UPDATE); } //region Ban events diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index f777a4605..22bc59063 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -50,7 +50,7 @@ class GuildSettingsModeration { for (eventInfo in eventsInfo) { eventInfo.sendEvent(GuildDataManager.getGuildData(guildId), modlogEventStore); } - CascadeBot.INS.databaseManager.runAsyncTask { database -> database.getCollection("modlog", MongoModlogEventObject::class.java).insertOne(MongoModlogEventObject(guildId, modlogEventStore, "default" /* TODO change to actual time */), DebugLogCallback("Inserted Event")) } + //CascadeBot.INS.databaseManager.runAsyncTask { database -> database.getCollection("modlog", MongoModlogEventObject::class.java).insertOne(MongoModlogEventObject(guildId, modlogEventStore, "default" /* TODO change to actual time */), DebugLogCallback("Inserted Event")) } } private fun getEventInfoForEvent(event: ModlogEvent): List { From 91d76cfa021717ac9d235a3a5acbdb339f85f88b Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 27 Oct 2020 16:30:50 +0000 Subject: [PATCH 084/206] Tidy up the JSON --- src/main/resources/lang/en-GB.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 83b566efe..15e49abae 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -745,7 +745,7 @@ "description": "Skips the current song.", "force": { "command": "force", - "description": "Forcibily skips the current song." + "description": "Forcibly skips the current song." }, "yes": { "command": "yes", @@ -1438,7 +1438,7 @@ "guild_member_nickname_updated": { "select": "guild_member_nickname_updated", "display": "Guild member nickname updated", - "description": "{0} updated their nickanme" + "description": "{0} updated their nickname" }, "guild_user_banned": { "select": "guild_user_banned", @@ -1473,7 +1473,7 @@ "guild_boost_tier_updated": { "select": "guild_boost_tier_updated", "display": "Guild boost tier updated", - "description": "Server bost teir changed" + "description": "Server boost tier changed" }, "guild_update_afk_channel": { "select": "guild_update_afk_channel", @@ -2074,7 +2074,6 @@ "interval": "interval", "item": "item", "list": "list", - "words": "words", "unknown": "unknown", "max": "max", "member": "member", From 07ba4faf810e1adb5ea67a359d190491c5578bb1 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 27 Oct 2020 16:31:07 +0000 Subject: [PATCH 085/206] Pass base object into Affected so we can use it later on --- .../cascadebot/utils/ModlogUtils.java | 2 +- .../cascadebot/data/objects/ModlogAffected.kt | 6 ++--- .../data/objects/ModlogEventStore.kt | 25 +++++++++---------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java index af5213c0b..cba3c58fa 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java @@ -29,7 +29,7 @@ public static void getAuditLogFromType(Guild guild, long targetId, Consumer 5000l) { + if (millis > 5000L) { continue; } if (targetId != -1) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt index 577feabee..8cc3bfdb0 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt @@ -1,9 +1,9 @@ package org.cascadebot.cascadebot.data.objects -class ModlogAffected(var affectedType: AffectedType, var name: String, var id : String?) { +class ModlogAffected(val affectedType: AffectedType, val name: String, val id : String, @Transient val baseObject: Any) { - constructor(affectedType: AffectedType, name: String) : this(affectedType, name, null) + constructor(affectedType: AffectedType, name: String, baseObject: Any) : this(affectedType, name, "null", baseObject) - constructor() : this(AffectedType.UNKNOWN, "unknown") + constructor() : this(AffectedType.UNKNOWN, "unknown", "null") } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index f7698d1bd..027177101 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -13,48 +13,47 @@ import org.cascadebot.cascadebot.permissions.objects.Group import java.lang.UnsupportedOperationException import java.lang.reflect.Field -class ModlogEventStore(val trigger: ModlogEvent, val responsible: User?, affected: Any, extraInfo: MutableList) { +class ModlogEventStore(val trigger: ModlogEvent, val responsible: User?, affected: Any, var extraInfo: MutableList) { val affected: ModlogAffected = when (affected) { is User -> { - ModlogAffected(AffectedType.USER, affected.asTag, affected.id) + ModlogAffected(AffectedType.USER, affected.asTag, affected.id, affected) } is Role -> { - ModlogAffected(AffectedType.ROLE, "${affected.name} (${affected.id})", affected.id) + ModlogAffected(AffectedType.ROLE, "${affected.name} (${affected.id})", affected.id, affected) } is Emote -> { - ModlogAffected(AffectedType.EMOTE, affected.name, affected.id) + ModlogAffected(AffectedType.EMOTE, affected.name, affected.id, affected) } is Guild -> { - ModlogAffected(AffectedType.GUILD, affected.name) + ModlogAffected(AffectedType.GUILD, affected.name, affected) } is GuildChannel -> { - ModlogAffected(AffectedType.CHANNEL, affected.name, affected.id) + ModlogAffected(AffectedType.CHANNEL, affected.name, affected.id, affected) } is Group -> { - ModlogAffected(AffectedType.GROUP, affected.name, affected.id) + ModlogAffected(AffectedType.GROUP, affected.name, affected.id, affected) } is Field -> { - ModlogAffected(AffectedType.SETTING, affected.name) + ModlogAffected(AffectedType.SETTING, affected.name, affected) } is Module -> { - ModlogAffected(AffectedType.MODULE, affected.name) + ModlogAffected(AffectedType.MODULE, affected.name, affected) } is MainCommand -> { - ModlogAffected(AffectedType.COMMAND, affected.command()) + ModlogAffected(AffectedType.COMMAND, affected.command(), affected) } is Playlist -> { - ModlogAffected(AffectedType.PLAYLIST, affected.name, affected.playlistId.toHexString()) + ModlogAffected(AffectedType.PLAYLIST, affected.name, affected.playlistId.toHexString(), affected) } is Tag -> { - ModlogAffected(AffectedType.TAG, affected.name) + ModlogAffected(AffectedType.TAG, affected.name, affected) } else -> { ModlogAffected() } } - var extraInfo: MutableList = mutableListOf() var extraDescriptionInfo: MutableList = mutableListOf() val responsibleId: Long = responsible?.idLong ?: 0 From cf9879bcc6eb1253788ac6d9f3a6bad93eddda5d Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 27 Oct 2020 16:31:44 +0000 Subject: [PATCH 086/206] Use the base object --- .../data/objects/GuildSettingsModeration.kt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 22bc59063..953d2c0f5 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -202,16 +202,17 @@ class GuildSettingsModeration { ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR -> { when (affected.affectedType) { AffectedType.USER -> { - val user: User = CascadeBot.INS.shardManager.getUserById(affected.id!!)!! - var iconUrl = if (user.avatarUrl != null) { - user.avatarUrl - } else { - user.defaultAvatarUrl + if (affected.baseObject is User) { + val iconUrl = if (affected.baseObject.avatarUrl != null) { + affected.baseObject.avatarUrl + } else { + affected.baseObject.defaultAvatarUrl + } + webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, iconUrl, "https://discord.com/users/" + affected.id)) } - webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, iconUrl, "https://discord.com/users/" + affected.id)) } AffectedType.EMOTE -> { - val emote: Emote = CascadeBot.INS.shardManager.getEmoteById(affected.id!!)!! + val emote: Emote = CascadeBot.INS.shardManager.getEmoteById(affected.id)!! webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, emote.imageUrl, null)) } else -> { From 34614e9721907259c49d47a174e27dc03a196c70 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 27 Oct 2020 16:32:10 +0000 Subject: [PATCH 087/206] Ban hierarchy shouldn't be checked for unban --- .../org/cascadebot/cascadebot/moderation/ModerationManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java index c82dcfadf..eac9f88b9 100644 --- a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java +++ b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java @@ -147,7 +147,7 @@ private boolean runChecks(ModAction action, User target, Member submitter, Comma } else if (target.equals(context.getSelfUser())) { context.getTypedMessaging().replyWarning(context.i18n("moderation_manager.cannot_action_bot", action.getName(context.getLocale()))); return false; - } else if (context.getData().getModeration().getRespectBanOrKickHierarchy() && !submitter.canInteract(context.getGuild().getMember(target))) { + } else if (action != ModAction.UNBAN && context.getData().getModeration().getRespectBanOrKickHierarchy() && !submitter.canInteract(context.getGuild().getMember(target))) { context.getTypedMessaging().replyWarning(context.i18n("moderation_manager.user_cannot_action_superior", action.getName(context.getLocale()), target.getName())); return false; } From 841d55f45bfc9ef2f30d2612960fa8fbeb4a974f Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 27 Oct 2020 21:28:25 +0000 Subject: [PATCH 088/206] Guild updates? Not sure --- .../events/ModlogEventListener.java | 21 ++++++++++-------- .../data/objects/GuildSettingsModeration.kt | 12 ++-------- .../cascadebot/data/objects/ModlogAffected.kt | 4 +--- .../data/objects/ModlogEventStore.kt | 22 +++++++++---------- src/main/resources/lang/en-GB.json | 13 +++++------ 5 files changed, 32 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 3ab6855ca..f1ae13d53 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -303,6 +303,7 @@ public void onGuildUnban(GuildUnbanEvent event) { //endregion //region Message + // TODO public void onGuildMessageDelete(@NotNull GuildMessageDeleteEvent event) { if (CascadeBot.INS.getRedisClient() == null) { return; @@ -351,6 +352,7 @@ public void onGuildMessageDelete(@NotNull GuildMessageDeleteEvent event) { }, ActionType.MESSAGE_DELETE); } + // TODO public void onGuildMessageUpdate(@NotNull GuildMessageUpdateEvent event) { if (CascadeBot.INS.getRedisClient() == null) { return; @@ -425,19 +427,19 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { CascadeBot.LOGGER.warn("Modlog: Failed to find guild update entry"); } if (event instanceof GuildUpdateAfkChannelEvent) { + modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_CHANNEL; + VoiceChannel oldChannel = ((GuildUpdateAfkChannelEvent) event).getOldAfkChannel(); - if (oldChannel != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_channel", null, oldChannel.getName())); - } VoiceChannel newChannel = ((GuildUpdateAfkChannelEvent) event).getNewAfkChannel(); - if (newChannel != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_channel", null, newChannel.getName())); - } - modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_CHANNEL; + + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_channel", null, oldChannel != null ? oldChannel.getName() + " (" + oldChannel.getId() + ")" : "-")); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_channel", null, newChannel != null ? newChannel.getName() + " (" + newChannel.getId() + ")" : "-")); } else if (event instanceof GuildUpdateAfkTimeoutEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getOldAfkTimeout().getSeconds()))); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_timeout", "modlog.guild.timeout", String.valueOf(((GuildUpdateAfkTimeoutEvent) event).getNewAfkTimeout().getSeconds()))); modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_TIMEOUT; + + String oldTimeout = Language.i18n(event.getGuild().getIdLong(), "modlog.guild.timeout_seconds", ((GuildUpdateAfkTimeoutEvent) event).getOldAfkTimeout().getSeconds()); + String newTimeout = Language.i18n(event.getGuild().getIdLong(), "modlog.guild.timeout_seconds", ((GuildUpdateAfkTimeoutEvent) event).getNewAfkTimeout().getSeconds()); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.timeout", "modlog.general.small_change", oldTimeout, newTimeout)); } else if (event instanceof GuildUpdateBannerEvent) { if (((GuildUpdateBannerEvent) event).getOldBannerUrl() != null) { embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", null, ((GuildUpdateBannerEvent) event).getOldBannerUrl())); @@ -476,6 +478,7 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getNewMaxMembers()))); modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_MEMBERS; } else if (event instanceof GuildUpdateMaxPresencesEvent) { + responsible = null; embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getOldMaxPresences()))); embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getNewMaxPresences()))); modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_PRESENCES; diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 953d2c0f5..9a86e5459 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -202,18 +202,10 @@ class GuildSettingsModeration { ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR -> { when (affected.affectedType) { AffectedType.USER -> { - if (affected.baseObject is User) { - val iconUrl = if (affected.baseObject.avatarUrl != null) { - affected.baseObject.avatarUrl - } else { - affected.baseObject.defaultAvatarUrl - } - webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, iconUrl, "https://discord.com/users/" + affected.id)) - } + webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, affected.imageUrl, "https://discord.com/users/" + affected.id)) } AffectedType.EMOTE -> { - val emote: Emote = CascadeBot.INS.shardManager.getEmoteById(affected.id)!! - webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, emote.imageUrl, null)) + webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, affected.imageUrl, null)) } else -> { webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, null, null)) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt index 8cc3bfdb0..b6e2a53c3 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt @@ -1,8 +1,6 @@ package org.cascadebot.cascadebot.data.objects -class ModlogAffected(val affectedType: AffectedType, val name: String, val id : String, @Transient val baseObject: Any) { - - constructor(affectedType: AffectedType, name: String, baseObject: Any) : this(affectedType, name, "null", baseObject) +class ModlogAffected(val affectedType: AffectedType, val name: String, val id : String = "null", val imageUrl: String? = null) { constructor() : this(AffectedType.UNKNOWN, "unknown", "null") diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 027177101..5a0d0c542 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -17,37 +17,37 @@ class ModlogEventStore(val trigger: ModlogEvent, val responsible: User?, affecte val affected: ModlogAffected = when (affected) { is User -> { - ModlogAffected(AffectedType.USER, affected.asTag, affected.id, affected) + ModlogAffected(AffectedType.USER, affected.asTag, affected.id, affected.effectiveAvatarUrl) } is Role -> { - ModlogAffected(AffectedType.ROLE, "${affected.name} (${affected.id})", affected.id, affected) + ModlogAffected(AffectedType.ROLE, "${affected.name} (${affected.id})", affected.id) } is Emote -> { - ModlogAffected(AffectedType.EMOTE, affected.name, affected.id, affected) + ModlogAffected(AffectedType.EMOTE, affected.name, affected.id, affected.imageUrl) } is Guild -> { - ModlogAffected(AffectedType.GUILD, affected.name, affected) + ModlogAffected(AffectedType.GUILD, affected.name, imageUrl = affected.iconUrl) } is GuildChannel -> { - ModlogAffected(AffectedType.CHANNEL, affected.name, affected.id, affected) + ModlogAffected(AffectedType.CHANNEL, affected.name, affected.id) } is Group -> { - ModlogAffected(AffectedType.GROUP, affected.name, affected.id, affected) + ModlogAffected(AffectedType.GROUP, affected.name, affected.id) } is Field -> { - ModlogAffected(AffectedType.SETTING, affected.name, affected) + ModlogAffected(AffectedType.SETTING, affected.name) } is Module -> { - ModlogAffected(AffectedType.MODULE, affected.name, affected) + ModlogAffected(AffectedType.MODULE, affected.name) } is MainCommand -> { - ModlogAffected(AffectedType.COMMAND, affected.command(), affected) + ModlogAffected(AffectedType.COMMAND, affected.command()) } is Playlist -> { - ModlogAffected(AffectedType.PLAYLIST, affected.name, affected.playlistId.toHexString(), affected) + ModlogAffected(AffectedType.PLAYLIST, affected.name, affected.playlistId.toHexString()) } is Tag -> { - ModlogAffected(AffectedType.TAG, affected.name, affected) + ModlogAffected(AffectedType.TAG, affected.name) } else -> { ModlogAffected() diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 15e49abae..917fbc2f9 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1477,13 +1477,13 @@ }, "guild_update_afk_channel": { "select": "guild_update_afk_channel", - "display": "Guild update afk channel", - "description": "Afk channel changed" + "display": "Guild update AFK channel", + "description": "AFK channel changed" }, "guild_update_afk_timeout": { "select": "guild_update_afk_timeout", - "display": "Guild update afk timeout", - "description": "Aft timeout changed" + "display": "Guild update AFK timeout", + "description": "AFK timeout changed" }, "guild_update_banner": { "select": "guild_update_banner", @@ -2348,9 +2348,8 @@ "guild": { "old_channel": "Old Channel", "new_channel": "New Channel", - "timeout": "{0} seconds", - "old_timeout": "Old Value", - "new_timeout": "New Value", + "timeout_seconds": "{0} seconds", + "timeout": "Timeout", "old_image": "Old Image", "new_image": "New Image", "old_description": "Old Description", From e95ecb7fd6117adca51bb0884f3252006b2616d8 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 27 Oct 2020 22:40:46 +0000 Subject: [PATCH 089/206] Databasey stuff --- .../cascadebot/data/objects/GuildSettingsModeration.kt | 2 +- .../org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 9a86e5459..de20c7a40 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -50,7 +50,7 @@ class GuildSettingsModeration { for (eventInfo in eventsInfo) { eventInfo.sendEvent(GuildDataManager.getGuildData(guildId), modlogEventStore); } - //CascadeBot.INS.databaseManager.runAsyncTask { database -> database.getCollection("modlog", MongoModlogEventObject::class.java).insertOne(MongoModlogEventObject(guildId, modlogEventStore, "default" /* TODO change to actual time */), DebugLogCallback("Inserted Event")) } + CascadeBot.INS.databaseManager.runAsyncTask { database -> database.getCollection("modlog", MongoModlogEventObject::class.java).insertOne(MongoModlogEventObject(guildId, modlogEventStore, "default" /* TODO change to actual time */), DebugLogCallback("Inserted Event")) } } private fun getEventInfoForEvent(event: ModlogEvent): List { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 5a0d0c542..0793aeff4 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -13,7 +13,7 @@ import org.cascadebot.cascadebot.permissions.objects.Group import java.lang.UnsupportedOperationException import java.lang.reflect.Field -class ModlogEventStore(val trigger: ModlogEvent, val responsible: User?, affected: Any, var extraInfo: MutableList) { +class ModlogEventStore(val trigger: ModlogEvent, @Transient val responsible: User?, affected: Any, var extraInfo: MutableList) { val affected: ModlogAffected = when (affected) { is User -> { From f9bba3165903a70e8d85080f6aa70e5d36cd3e27 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 22 Nov 2020 17:02:29 +0000 Subject: [PATCH 090/206] Add voice-channels's description items --- .../cascadebot/events/ModlogEventListener.java | 9 +++++---- src/main/resources/lang/en-GB.json | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index f1ae13d53..3ea975178 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -555,6 +555,7 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); ModlogUtils.getAuditLogFromType(event.getGuild(), event.getMember().getIdLong(), auditLogEntry -> { List embedFieldList = new ArrayList<>(); + List extraDescriptionInfo = List.of(); ModlogEvent action; if (event instanceof GuildVoiceDeafenEvent) { embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.deafen", null, String.valueOf(((GuildVoiceDeafenEvent) event).isDeafened()))); @@ -569,18 +570,17 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.mute", null, String.valueOf(((GuildVoiceGuildMuteEvent) event).isGuildMuted()))); action = ModlogEvent.VOICE_SERVER_MUTE; } else if (event instanceof GuildVoiceJoinEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.join", null, ((GuildVoiceJoinEvent) event).getChannelJoined().getName())); + extraDescriptionInfo = List.of(((GuildVoiceJoinEvent) event).getChannelJoined().getName()); action = ModlogEvent.VOICE_JOIN; } else if (event instanceof GuildVoiceLeaveEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.left", null, ((GuildVoiceLeaveEvent) event).getChannelLeft().getName())); + extraDescriptionInfo = List.of(((GuildVoiceLeaveEvent) event).getChannelLeft().getName()); if (auditLogEntry != null) { action = ModlogEvent.VOICE_DISCONNECT; } else { action = ModlogEvent.VOICE_LEAVE; } } else if (event instanceof GuildVoiceMoveEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.left", null, ((GuildVoiceMoveEvent) event).getChannelLeft().getName())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.join", null, ((GuildVoiceMoveEvent) event).getChannelJoined().getName())); + extraDescriptionInfo = List.of(((GuildVoiceMoveEvent) event).getChannelLeft().getName(), ((GuildVoiceMoveEvent) event).getChannelJoined().getName()); if (auditLogEntry != null) { action = ModlogEvent.VOICE_FORCE_MOVE; } else { @@ -590,6 +590,7 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { return; } ModlogEventStore eventStore = new ModlogEventStore(action, null, affected, embedFieldList); + eventStore.setExtraDescriptionInfo(extraDescriptionInfo); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }, ActionType.MEMBER_VOICE_MOVE, ActionType.MEMBER_VOICE_KICK); } diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index adf5aa94c..309ea2201 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1578,17 +1578,17 @@ "voice_join": { "select": "voice_join", "display": "Voice join", - "description": "{0} joined {2}" + "description": "{0} joined `{2}`" }, "voice_leave": { "select": "voice_leave", "display": "Voice leave", - "description": "{0} left {2}" + "description": "{0} left `{2}`" }, "voice_move": { "select": "voice_move", "display": "Voice move", - "description": "{0} moved from {2} to {3}" + "description": "{0} moved from `{2}` to `{3}`" }, "voice_disconnect": { "select": "voice_disconnect", From 79da4c5eadc5d91199d5861b5771cc9827af2823 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 22 Nov 2020 18:00:57 +0000 Subject: [PATCH 091/206] Add indentation to Modlog event to make it easier to read --- .../cascadebot/moderation/ModlogEvent.kt | 235 +++++++++--------- 1 file changed, 116 insertions(+), 119 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 135a7938a..a8b761556 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -1,127 +1,124 @@ package org.cascadebot.cascadebot.moderation import de.bild.codec.annotations.Transient -import lombok.Getter +import org.cascadebot.cascadebot.data.objects.AffectedDisplayType import org.cascadebot.cascadebot.messaging.MessageType -import java.util.ArrayList -import java.util.Arrays import java.util.EnumMap -import java.util.HashMap - -enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: ModlogDisplayType, vararg categories: Category) { - - EMOTE_CREATED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.EMOTE), - EMOTE_DELETED(MessageType.INFO, ModlogDisplayType.PLAIN, Category.EMOTE), - EMOTE_UPDATED_NAME(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.EMOTE), - EMOTE_UPDATED_ROLES(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.EMOTE), - - GUILD_MEMBER_JOINED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.GUILD, Category.GUILD_MEMBER), - GUILD_MEMBER_LEFT(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.GUILD, Category.GUILD_MEMBER), - GUILD_MEMBER_KICKED(MessageType.WARNING, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), - GUILD_MEMBER_ROLE_ADDED(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MEMBER), - GUILD_MEMBER_ROLE_REMOVED(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MEMBER), - GUILD_MEMBER_NICKNAME_UPDATED(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MEMBER), - - GUILD_USER_BANNED(MessageType.DANGER, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), - GUILD_USER_UNBANNED(MessageType.DANGER, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), - - GUILD_MESSAGE_DELETED(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MESSAGE), - GUILD_MESSAGE_DELETED_MENTION(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MESSAGE), - GUILD_MESSAGE_UPDATED(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.GUILD, Category.GUILD_MESSAGE), - - GUILD_BOOST_COUNT_UPDATED(MessageType.INFO, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_BOOST), - GUILD_BOOST_TIER_UPDATED(MessageType.INFO, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_BOOST), - - GUILD_UPDATE_AFK_CHANNEL(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_AFK_TIMEOUT(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_BANNER(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_DESCRIPTION(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_EXPLICIT_FILTER(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_FEATURES(MessageType.INFO, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_ICON(MessageType.WARNING, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_MAX_MEMBERS(MessageType.INFO, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_MAX_PRESENCES(MessageType.INFO, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_MFA_LEVEL(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_NAME(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_NOTIFICATION_LEVEL(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_REGION(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_SPLASH(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_SYSTEM_CHANNEL(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_VANITY_CODE(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - GUILD_UPDATE_VERIFICATION_LEVEL(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.GUILD, Category.GUILD_SETTINGS), - - VOICE_DEAFEN(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE), - VOICE_MUTE(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE), - VOICE_SERVER_DEAFEN(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE, Category.MODERATION), - VOICE_SERVER_MUTE(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE, Category.MODERATION), - VOICE_JOIN(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE), - VOICE_LEAVE(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE), - VOICE_MOVE(MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE), - VOICE_FORCE_MOVE(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE, Category.MODERATION), - VOICE_DISCONNECT(MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, Category.VOICE, Category.MODERATION), - - ROLE_CREATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_DELETED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_COLOR_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_HOIST_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_MENTIONABLE_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_NAME_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_PERMISSIONS_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - ROLE_POSITION_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.ROLE), - - USER_DISCRIMINATOR_UPDATED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.USER), - USER_NAME_UPDATED(MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, Category.USER), - - CHANNEL_CREATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), - CHANNEL_DELETED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), - CHANNEL_NAME_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), - CHANNEL_PERMISSIONS_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), - CHANNEL_POSITION_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), - MULTIPLE_CHANNEL_POSITION_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), - CHANNEL_PARENT_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), - - VOICE_CHANNEL_BITRATE_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), - VOICE_CHANNEL_USER_LIMIT_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), - - TEXT_CHANNEL_NSFW_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), - TEXT_CHANNEL_SLOWMODE_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), - TEXT_CHANNEL_TOPIC_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CHANNEL), - - CASCADE_PERMISSIONS_GROUP_CREATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_GROUP_DELETED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_GROUP_LINK(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), - - CASCADE_PERMISSIONS_USER_PERMISSION_ADD(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_USER_GROUP_ADD(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), - CASCADE_PERMISSIONS_USER_GROUP_REMOVE(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_PERMISSIONS), - - CASCADE_SETTINGS_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE), - - CASCADE_MODULE_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE), - - CASCADE_COMMAND_RUN(MessageType.INFO, ModlogDisplayType.PLAIN, Category.CASCADE), - CASCADE_COMMAND_RUN_ERROR(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE), - - CASCADE_PLAYLIST_CREATED(MessageType.INFO, ModlogDisplayType.PLAIN, Category.CASCADE), - - CASCADE_TEMP_MUTE(MessageType.DANGER, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_TEMP_BAN(MessageType.DANGER, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_SOFT_BAN(MessageType.DANGER, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_PURGE(MessageType.DANGER, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - - CASCADE_WHITELIST(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_BLACKLIST(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - - CASCADE_SCRIPT_CREATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_SCRIPT_DELETED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_SCRIPT_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - - CASCADE_TAG_CREATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_TAG_DELETED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_TAG_UPDATED(MessageType.WARNING, ModlogDisplayType.PLAIN, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS); + +enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: ModlogDisplayType, val affectedDisplayType: AffectedDisplayType, vararg categories: Category) { + + EMOTE_CREATED (MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.EMOTE), + EMOTE_DELETED (MessageType.INFO, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.EMOTE), + EMOTE_UPDATED_NAME (MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.EMOTE), + EMOTE_UPDATED_ROLES (MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.EMOTE), + + GUILD_MEMBER_JOINED (MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_LEFT (MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.NAME, Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_KICKED (MessageType.WARNING, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.NAME, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + GUILD_MEMBER_ROLE_ADDED (MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_ROLE_REMOVED (MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_MEMBER), + GUILD_MEMBER_NICKNAME_UPDATED (MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_MEMBER), + + GUILD_USER_BANNED (MessageType.DANGER, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.NAME, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + GUILD_USER_UNBANNED (MessageType.DANGER, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.NAME, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + + GUILD_MESSAGE_DELETED (MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_MESSAGE), + GUILD_MESSAGE_DELETED_MENTION (MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_MESSAGE), + GUILD_MESSAGE_UPDATED (MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_MESSAGE), + + GUILD_BOOST_COUNT_UPDATED (MessageType.INFO, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_BOOST), + GUILD_BOOST_TIER_UPDATED (MessageType.INFO, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_BOOST), + + GUILD_UPDATE_AFK_CHANNEL (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_AFK_TIMEOUT (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_BANNER (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_DESCRIPTION (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_EXPLICIT_FILTER (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_FEATURES (MessageType.INFO, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_ICON (MessageType.WARNING, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_MAX_MEMBERS (MessageType.INFO, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_MAX_PRESENCES (MessageType.INFO, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_MFA_LEVEL (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_NAME (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_NOTIFICATION_LEVEL (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_REGION (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_SPLASH (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_SYSTEM_CHANNEL (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_VANITY_CODE (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + GUILD_UPDATE_VERIFICATION_LEVEL (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_SETTINGS), + + VOICE_DEAFEN (MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.VOICE), + VOICE_MUTE (MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.VOICE), + VOICE_SERVER_DEAFEN (MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.VOICE, Category.MODERATION), + VOICE_SERVER_MUTE (MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.VOICE, Category.MODERATION), + VOICE_JOIN (MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.VOICE), + VOICE_LEAVE (MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.VOICE), + VOICE_MOVE (MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.VOICE), + VOICE_FORCE_MOVE (MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.VOICE, Category.MODERATION), + VOICE_DISCONNECT (MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.VOICE, Category.MODERATION), + + ROLE_CREATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), + ROLE_DELETED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), + ROLE_COLOR_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), + ROLE_HOIST_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), + ROLE_MENTIONABLE_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), + ROLE_NAME_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), + ROLE_PERMISSIONS_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), + ROLE_POSITION_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), + + USER_DISCRIMINATOR_UPDATED (MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.USER), + USER_NAME_UPDATED (MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.USER), + + CHANNEL_CREATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + CHANNEL_DELETED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + CHANNEL_NAME_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + CHANNEL_PERMISSIONS_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + CHANNEL_POSITION_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + MULTIPLE_CHANNEL_POSITION_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + CHANNEL_PARENT_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + + VOICE_CHANNEL_BITRATE_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + VOICE_CHANNEL_USER_LIMIT_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + + TEXT_CHANNEL_NSFW_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + TEXT_CHANNEL_SLOWMODE_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + TEXT_CHANNEL_TOPIC_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + + CASCADE_PERMISSIONS_GROUP_CREATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_DELETED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_LINK (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), + + CASCADE_PERMISSIONS_USER_PERMISSION_ADD (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_USER_GROUP_ADD (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_USER_GROUP_REMOVE (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), + + CASCADE_SETTINGS_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE), + + CASCADE_MODULE_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE), + + CASCADE_COMMAND_RUN (MessageType.INFO, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE), + CASCADE_COMMAND_RUN_ERROR (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE), + + CASCADE_PLAYLIST_CREATED (MessageType.INFO, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE), + + CASCADE_TEMP_MUTE (MessageType.DANGER, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_TEMP_BAN (MessageType.DANGER, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_SOFT_BAN (MessageType.DANGER, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_PURGE (MessageType.DANGER, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + + CASCADE_WHITELIST (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_BLACKLIST (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + + CASCADE_SCRIPT_CREATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_SCRIPT_DELETED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_SCRIPT_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + + CASCADE_TAG_CREATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_TAG_DELETED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + CASCADE_TAG_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS); companion object { private val modlogCategoryMap: MutableMap> = EnumMap(Category::class.java) From 15006d7100984bf03d179de92d67ac08047e2ef2 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 22 Nov 2020 18:01:09 +0000 Subject: [PATCH 092/206] Add support for different affected display types --- .../data/objects/GuildSettingsModeration.kt | 55 +++++++++++-------- .../cascadebot/data/objects/ModlogAffected.kt | 9 ++- .../data/objects/ModlogEventStore.kt | 26 +++++---- 3 files changed, 55 insertions(+), 35 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index de20c7a40..934970b84 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -4,7 +4,6 @@ import club.minnced.discord.webhook.WebhookClient import club.minnced.discord.webhook.WebhookClientBuilder import club.minnced.discord.webhook.exception.HttpException import club.minnced.discord.webhook.send.WebhookEmbed -import club.minnced.discord.webhook.send.WebhookEmbed.EmbedField import club.minnced.discord.webhook.send.WebhookEmbed.EmbedTitle import club.minnced.discord.webhook.send.WebhookEmbedBuilder import de.bild.codec.annotations.Transient @@ -50,7 +49,7 @@ class GuildSettingsModeration { for (eventInfo in eventsInfo) { eventInfo.sendEvent(GuildDataManager.getGuildData(guildId), modlogEventStore); } - CascadeBot.INS.databaseManager.runAsyncTask { database -> database.getCollection("modlog", MongoModlogEventObject::class.java).insertOne(MongoModlogEventObject(guildId, modlogEventStore, "default" /* TODO change to actual time */), DebugLogCallback("Inserted Event")) } + CascadeBot.INS.databaseManager.runAsyncTask { database -> database.getCollection("modlog", ChannelModlogEventsInfo.MongoModlogEventObject::class.java).insertOne(ChannelModlogEventsInfo.MongoModlogEventObject(guildId, modlogEventStore, "default" /* TODO change to actual time */), DebugLogCallback("Inserted Event")) } } private fun getEventInfoForEvent(event: ModlogEvent): List { @@ -109,6 +108,7 @@ class GuildSettingsModeration { } class ChannelModlogEventsInfo { + private val events: MutableSet = LinkedHashSet() internal var webhookId: Long = 0 internal var webhookToken: String = "" @@ -149,7 +149,7 @@ class GuildSettingsModeration { return events.remove(event) } - fun getWebhookId() : Long { + fun getWebhookId(): Long { return webhookId } @@ -166,12 +166,18 @@ class GuildSettingsModeration { val element = Language.getLanguageOrDefault(guildData.locale).getElement(path) if (element.isPresent) { + val affected = when (modlogEventStore.trigger.affectedDisplayType) { + AffectedDisplayType.NAME -> modlogEventStore.affected.name + AffectedDisplayType.MENTION -> modlogEventStore.affected.mention + ?: Language.i18n(guildData.locale, "words.unknown").toCapitalized() + } webhookEmbedBuilder.setDescription( Language.i18n( guildData.locale, path, - modlogEventStore.affected.name, - modlogEventStore.responsible?.asMention ?: Language.i18n(guildData.locale, "words.unknown").toCapitalized(), + affected, + modlogEventStore.responsible?.asMention + ?: Language.i18n(guildData.locale, "words.unknown").toCapitalized(), *modlogEventStore.extraDescriptionInfo.toTypedArray() ) ) @@ -193,20 +199,24 @@ class GuildSettingsModeration { } } } + AffectedType.EMOTE -> { val emote: Emote = CascadeBot.INS.shardManager.getEmoteById(affected.id!!)!! webhookEmbedBuilder.setThumbnailUrl(emote.imageUrl) } } } + ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR -> { when (affected.affectedType) { AffectedType.USER -> { webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, affected.imageUrl, "https://discord.com/users/" + affected.id)) } + AffectedType.EMOTE -> { webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, affected.imageUrl, null)) } + else -> { webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, null, null)) } @@ -234,23 +244,24 @@ class GuildSettingsModeration { // TODO not ignore } } - } - - class MongoModlogEventObject { - - private var guildId: Long = 0; - private var modlogEventStore: ModlogEventStore? = null - - private var createdDate: Date = Date() - private var tier: String = "" - - private constructor() - - constructor(guildId: Long, modlogEventStore: ModlogEventStore, tier: String) { - this.guildId = guildId - this.modlogEventStore = modlogEventStore - this.tier = tier + + class MongoModlogEventObject { + + private var guildId: Long = 0; + private var modlogEventStore: ModlogEventStore? = null + + private var createdDate: Date = Date() + private var tier: String = "" + + private constructor() + + constructor(guildId: Long, modlogEventStore: ModlogEventStore, tier: String) { + this.guildId = guildId + this.modlogEventStore = modlogEventStore + this.tier = tier + } + } - } + } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt index b6e2a53c3..6f7e48b42 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt @@ -1,7 +1,12 @@ package org.cascadebot.cascadebot.data.objects -class ModlogAffected(val affectedType: AffectedType, val name: String, val id : String = "null", val imageUrl: String? = null) { +class ModlogAffected(val affectedType: AffectedType, val name: String, val mention: String?, val id : String?, val imageUrl: String? = null) { - constructor() : this(AffectedType.UNKNOWN, "unknown", "null") + constructor() : this(AffectedType.UNKNOWN, "unknown", null, null) } + +enum class AffectedDisplayType { + MENTION, + NAME +} \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 0793aeff4..0d035ba56 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -4,6 +4,7 @@ import net.dv8tion.jda.api.entities.Emote import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.entities.GuildChannel import net.dv8tion.jda.api.entities.Role +import net.dv8tion.jda.api.entities.TextChannel import net.dv8tion.jda.api.entities.User import org.cascadebot.cascadebot.commandmeta.MainCommand import org.cascadebot.cascadebot.commandmeta.Module @@ -17,37 +18,40 @@ class ModlogEventStore(val trigger: ModlogEvent, @Transient val responsible: Use val affected: ModlogAffected = when (affected) { is User -> { - ModlogAffected(AffectedType.USER, affected.asTag, affected.id, affected.effectiveAvatarUrl) + ModlogAffected(AffectedType.USER, affected.asTag, affected.asMention, affected.id, affected.effectiveAvatarUrl) } is Role -> { - ModlogAffected(AffectedType.ROLE, "${affected.name} (${affected.id})", affected.id) + ModlogAffected(AffectedType.ROLE, "${affected.name} (${affected.id})", affected.asMention, affected.id) } is Emote -> { - ModlogAffected(AffectedType.EMOTE, affected.name, affected.id, affected.imageUrl) + ModlogAffected(AffectedType.EMOTE, affected.name, affected.asMention, affected.id, affected.imageUrl) } is Guild -> { - ModlogAffected(AffectedType.GUILD, affected.name, imageUrl = affected.iconUrl) + ModlogAffected(AffectedType.GUILD, affected.name, null, affected.id, imageUrl = affected.iconUrl) + } + is TextChannel -> { + ModlogAffected(AffectedType.GUILD, affected.name, affected.asMention, affected.id) } is GuildChannel -> { - ModlogAffected(AffectedType.CHANNEL, affected.name, affected.id) + ModlogAffected(AffectedType.CHANNEL, affected.name, null, affected.id) } is Group -> { - ModlogAffected(AffectedType.GROUP, affected.name, affected.id) + ModlogAffected(AffectedType.GROUP, affected.name, null, affected.id) } is Field -> { - ModlogAffected(AffectedType.SETTING, affected.name) + ModlogAffected(AffectedType.SETTING, affected.name, null, null) } is Module -> { - ModlogAffected(AffectedType.MODULE, affected.name) + ModlogAffected(AffectedType.MODULE, affected.name, null, null) } is MainCommand -> { - ModlogAffected(AffectedType.COMMAND, affected.command()) + ModlogAffected(AffectedType.COMMAND, affected.command(), null, null) } is Playlist -> { - ModlogAffected(AffectedType.PLAYLIST, affected.name, affected.playlistId.toHexString()) + ModlogAffected(AffectedType.PLAYLIST, affected.name, affected.playlistId.toHexString(), null, null) } is Tag -> { - ModlogAffected(AffectedType.TAG, affected.name) + ModlogAffected(AffectedType.TAG, affected.name, null, null) } else -> { ModlogAffected() From 7152705b3a8384bcc7f701497b92ab3d97d49f89 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 22 Nov 2020 18:02:06 +0000 Subject: [PATCH 093/206] Voice chat events: Muting and deadening --- .../cascadebot/events/ModlogEventListener.java | 17 +++++++++++++---- src/main/resources/lang/en-GB.json | 12 ++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 3ea975178..3e18f62a5 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -100,6 +100,7 @@ import net.dv8tion.jda.api.events.user.update.UserUpdateDiscriminatorEvent; import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; +import org.apache.commons.codec.language.bm.Lang; import org.apache.commons.lang3.StringUtils; import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.UnicodeConstants; @@ -558,16 +559,24 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { List extraDescriptionInfo = List.of(); ModlogEvent action; if (event instanceof GuildVoiceDeafenEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.deafen", null, String.valueOf(((GuildVoiceDeafenEvent) event).isDeafened()))); + boolean deafened = (((GuildVoiceDeafenEvent) event).isDeafened()); + Emote emote = deafened ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("self-deafened")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("undeafened")); + extraDescriptionInfo = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(deafened)); action = ModlogEvent.VOICE_DEAFEN; } else if (event instanceof GuildVoiceMuteEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.mute", null, String.valueOf(((GuildVoiceMuteEvent) event).isMuted()))); + boolean muted = (((GuildVoiceMuteEvent) event).isMuted()); + Emote emote = muted ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("self-muted")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("unmuted")); + extraDescriptionInfo = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(muted)); action = ModlogEvent.VOICE_MUTE; } else if (event instanceof GuildVoiceGuildDeafenEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.deafen", null, String.valueOf(((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()))); + boolean guildDeafened = (((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()); + Emote emote = guildDeafened ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("server-deafened")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("undeafened")); + extraDescriptionInfo = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(guildDeafened)); action = ModlogEvent.VOICE_SERVER_DEAFEN; } else if (event instanceof GuildVoiceGuildMuteEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.voice.mute", null, String.valueOf(((GuildVoiceGuildMuteEvent) event).isGuildMuted()))); + boolean guildMuted = (((GuildVoiceGuildMuteEvent) event).isGuildMuted()); + Emote emote = guildMuted ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("server-muted")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("unmuted")); + extraDescriptionInfo = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(guildMuted)); action = ModlogEvent.VOICE_SERVER_MUTE; } else if (event instanceof GuildVoiceJoinEvent) { extraDescriptionInfo = List.of(((GuildVoiceJoinEvent) event).getChannelJoined().getName()); diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 309ea2201..ee663a78e 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1561,19 +1561,23 @@ }, "voice_deafen": { "select": "voice_deafen", - "display": "Voice deafen" + "display": "Voice deafen", + "description": "{2} {3, select, true {The user `{0}` has deafened themselves} other {The user `{0}` has un-deafened themselves}}" }, "voice_mute": { "select": "voice_mute", - "display": "Voice mute" + "display": "Voice mute", + "description": "{2} {3, select, true {The user `{0}` has muted themselves} other {The user `{0}` has un-muted themselves}}" }, "voice_server_deafen": { "select": "voice_server_deafen", - "display": "Voice server deafen" + "display": "Voice server deafen", + "description": "{2} {3, select, true {The user `{0}` has been server deafened} other {The user `{0}` has been un-server deafened}}" }, "voice_server_mute": { "select": "voice_server_mute", - "display": "Voice server mute" + "display": "Voice server mute", + "description": "{2} {3, select, true {The user `{0}` has been server muted} other {The user `{0}` has been un-server muted}}" }, "voice_join": { "select": "voice_join", From 98a3b82a9b850306c585e7bee963ea6fb5452c75 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 22 Nov 2020 21:29:08 +0000 Subject: [PATCH 094/206] Guild modlog --- .../events/ModlogEventListener.java | 63 ++++++++++--------- src/main/resources/lang/en-GB.json | 32 +++++----- 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 3e18f62a5..6fe6b1985 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -100,7 +100,6 @@ import net.dv8tion.jda.api.events.user.update.UserUpdateDiscriminatorEvent; import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import org.apache.commons.codec.language.bm.Lang; import org.apache.commons.lang3.StringUtils; import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.UnicodeConstants; @@ -294,7 +293,7 @@ public void onGuildUnban(GuildUnbanEvent event) { User responsible = null; if (auditLogEntry != null) { responsible = auditLogEntry.getUser(); - } else { + } else { CascadeBot.LOGGER.warn("Modlog: Failed to find unban entry"); } ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); @@ -434,7 +433,7 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { VoiceChannel newChannel = ((GuildUpdateAfkChannelEvent) event).getNewAfkChannel(); embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_channel", null, oldChannel != null ? oldChannel.getName() + " (" + oldChannel.getId() + ")" : "-")); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_channel", null, newChannel != null ? newChannel.getName() + " (" + newChannel.getId() + ")" : "-")); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_channel", null, newChannel != null ? newChannel.getName() + " (" + newChannel.getId() + ")" : "-")); } else if (event instanceof GuildUpdateAfkTimeoutEvent) { modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_TIMEOUT; @@ -467,54 +466,58 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.removed_feature", null, String.join("\n", featuresChanged.getRemoved()))); modlogEvent = ModlogEvent.GUILD_UPDATE_FEATURES; } else if (event instanceof GuildUpdateIconEvent) { - if (((GuildUpdateIconEvent) event).getOldIconUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", null, ((GuildUpdateIconEvent) event).getOldIconUrl())); - } - if (((GuildUpdateIconEvent) event).getNewIconUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_image", null, ((GuildUpdateIconEvent) event).getNewIconUrl())); - } + String oldIconUrl = ((GuildUpdateIconEvent) event).getOldIconUrl(); + String newIconUrl = ((GuildUpdateIconEvent) event).getNewIconUrl(); + + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", null, oldIconUrl != null ? oldIconUrl : "-" )); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_image", null, newIconUrl != null ? newIconUrl : "-")); modlogEvent = ModlogEvent.GUILD_UPDATE_ICON; } else if (event instanceof GuildUpdateMaxMembersEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getOldMaxMembers()))); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_max_members", "modlog.guild.members", String.valueOf(((GuildUpdateMaxMembersEvent) event).getNewMaxMembers()))); + String oldMembers = String.valueOf(((GuildUpdateMaxMembersEvent) event).getOldMaxMembers()); + String newMembers = String.valueOf(((GuildUpdateMaxMembersEvent) event).getNewMaxMembers()); + + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.max_members", "modlog.general.small_change", oldMembers, newMembers)); modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_MEMBERS; } else if (event instanceof GuildUpdateMaxPresencesEvent) { + String oldPresences = String.valueOf(((GuildUpdateMaxPresencesEvent) event).getOldMaxPresences()); + String newPresences = String.valueOf(((GuildUpdateMaxPresencesEvent) event).getNewMaxPresences()); + + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.max_presences", "modlog.general.small_change", oldPresences, newPresences)); responsible = null; - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getOldMaxPresences()))); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_presences", "modlog.guild.presences", String.valueOf(((GuildUpdateMaxPresencesEvent) event).getNewMaxPresences()))); modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_PRESENCES; } else if (event instanceof GuildUpdateMFALevelEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.mfa.old", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getOldMFALevel().name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.mfa.new", "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getNewMFALevel().name().toLowerCase())); + String oldLevel = Language.i18n(event.getGuild().getIdLong(), "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getOldMFALevel().name().toLowerCase()); + String newLevel = Language.i18n(event.getGuild().getIdLong(), "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getNewMFALevel().name().toLowerCase()); + + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.mfa.mfa_level", "modlog.general.small_change", oldLevel, newLevel)); modlogEvent = ModlogEvent.GUILD_UPDATE_MFA_LEVEL; } else if (event instanceof GuildUpdateNameEvent) { embedFieldList.add(new ModlogEmbedField(false, "modlog.general.old_name", null, ((GuildUpdateNameEvent) event).getOldName())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.general.new_name", null, ((GuildUpdateNameEvent) event).getNewValue())); modlogEvent = ModlogEvent.GUILD_UPDATE_NAME; } else if (event instanceof GuildUpdateNotificationLevelEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.notification.old", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getOldNotificationLevel().name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.notification.new", "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getNewNotificationLevel().name().toLowerCase())); + String oldLevel = Language.i18n(event.getGuild().getIdLong(), "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getOldNotificationLevel().name().toLowerCase()); + String newLevel = Language.i18n(event.getGuild().getIdLong(), "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getNewNotificationLevel().name().toLowerCase()); + + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.notification.title", "modlog.general.small_change", oldLevel, newLevel)); modlogEvent = ModlogEvent.GUILD_UPDATE_NOTIFICATION_LEVEL; } else if (event instanceof GuildUpdateRegionEvent) { embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_region", null, ((GuildUpdateRegionEvent) event).getOldRegion().getName())); embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_region", null, ((GuildUpdateRegionEvent) event).getNewRegion().getName())); modlogEvent = ModlogEvent.GUILD_UPDATE_REGION; } else if (event instanceof GuildUpdateSplashEvent) { - if (((GuildUpdateSplashEvent) event).getOldSplashUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_splash", null, ((GuildUpdateSplashEvent) event).getOldSplashUrl())); - } - if (((GuildUpdateSplashEvent) event).getNewSplashUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_splash", null, ((GuildUpdateSplashEvent) event).getNewSplashUrl())); - } + String oldSplashUrl = ((GuildUpdateSplashEvent) event).getOldSplashUrl(); + String newSplashUrl = ((GuildUpdateSplashEvent) event).getNewSplashUrl(); + + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_splash", null, oldSplashUrl != null ? oldSplashUrl : "-")); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_splash", null, newSplashUrl != null ? newSplashUrl : "-")); modlogEvent = ModlogEvent.GUILD_UPDATE_SPLASH; } else if (event instanceof GuildUpdateSystemChannelEvent) { TextChannel oldSystemChannel = ((GuildUpdateSystemChannelEvent) event).getOldSystemChannel(); - if (oldSystemChannel != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_sys", null, oldSystemChannel.getName())); - } TextChannel newSystemChannel = ((GuildUpdateSystemChannelEvent) event).getNewSystemChannel(); - if (newSystemChannel != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_sys", null, newSystemChannel.getName())); - } + + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_sys", null, oldSystemChannel != null ? oldSystemChannel.getName() : "-")); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_sys", null, newSystemChannel != null ? newSystemChannel.getName() : "-")); modlogEvent = ModlogEvent.GUILD_UPDATE_SYSTEM_CHANNEL; } else if (event instanceof GuildUpdateVanityCodeEvent) { if (((GuildUpdateVanityCodeEvent) event).getOldVanityCode() != null) { @@ -970,6 +973,7 @@ public void onUserUpdateDiscriminator(UserUpdateDiscriminatorEvent event) { //TODO move this to a util class public static class ListChanges { + private final List added = new ArrayList<>(); private final List removed = new ArrayList<>(); @@ -993,6 +997,7 @@ public List getAdded() { public List getRemoved() { return removed; } + } } diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index ee663a78e..4cf6c56e8 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1537,7 +1537,7 @@ "guild_update_region": { "select": "guild_update_region", "display": "Guild update region", - "description": "Server voce region changed" + "description": "Server voice region changed" }, "guild_update_splash": { "select": "guild_update_splash", @@ -1562,22 +1562,22 @@ "voice_deafen": { "select": "voice_deafen", "display": "Voice deafen", - "description": "{2} {3, select, true {The user `{0}` has deafened themselves} other {The user `{0}` has un-deafened themselves}}" + "description": "{2} {3, select, true {{0} has deafened themselves} other {{0} has un-deafened themselves}}" }, "voice_mute": { "select": "voice_mute", "display": "Voice mute", - "description": "{2} {3, select, true {The user `{0}` has muted themselves} other {The user `{0}` has un-muted themselves}}" + "description": "{2} {3, select, true {{0} has muted themselves} other {{0} has un-muted themselves}}" }, "voice_server_deafen": { "select": "voice_server_deafen", "display": "Voice server deafen", - "description": "{2} {3, select, true {The user `{0}` has been server deafened} other {The user `{0}` has been un-server deafened}}" + "description": "{2} {3, select, true {{0} has been server deafened} other {{0} has been un-server deafened}}" }, "voice_server_mute": { "select": "voice_server_mute", "display": "Voice server mute", - "description": "{2} {3, select, true {The user `{0}` has been server muted} other {The user `{0}` has been un-server muted}}" + "description": "{2} {3, select, true {{0} has been server muted} other {{0} has been un-server muted}}" }, "voice_join": { "select": "voice_join", @@ -1627,7 +1627,7 @@ "role_name_updated": { "select": "role_name_updated", "display": "Role name updated", - "description": "The role `{0}` had its name changed" + "description": "{0} has had its name changed" }, "role_permissions_updated": { "select": "role_permissions_updated", @@ -2152,8 +2152,8 @@ "none": "None", "low": "Low", "medium": "Medium", - "high": "(╯°□°)╯︵ ┻━┻", - "very_high": "┻━┻ ミヽ(ಠ益ಠ)ノ彡┻━┻", + "high": "High", + "very_high": "Very High", "unknown": "Unknown" }, "color": { @@ -2332,7 +2332,7 @@ "new_pos": "New Position", "position": "Position", "name": "Name", - "small_change": "{0} \uD83E\uDC16 {1}" + "small_change": "{0} \u279C {1}" }, "member": { "old_nick": "Old Nickname", @@ -2367,22 +2367,18 @@ }, "add_feature": "Added Features", "removed_feature": "Removed Features", - "old_max_members": "Old Max Members", - "new_max_members": "New Max Members", + "max_members": "Max Members", "members": "{0} members", - "old_presences": "Old Max Presences", - "new_presences": "New Max Presences", + "max_presences": "Max Presences", "presences": "{0} presences", "mfa": { - "old": "Old MFA Level", - "new": "New MFA Level", + "mfa_level": "MFA Level", "none": "None", - "two_factor_auth": "2fa Required", + "two_factor_auth": "2FA Required", "unknown": "Unknown" }, "notification": { - "old": "Old Level", - "new": "New Level", + "title": "Level", "all_messages": "All Messages", "mentions_only": "Mentions Only", "unknown": "Unknown" From 8a008012dc029155b6efd74512854559e23a3bd4 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 23 Nov 2020 20:51:51 +0000 Subject: [PATCH 095/206] Use effective URL and the affected image url --- .../data/objects/GuildSettingsModeration.kt | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 934970b84..79f5146f0 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -188,23 +188,7 @@ class GuildSettingsModeration { when (modlogEventStore.trigger.displayType) { ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL -> { - when (affected.affectedType) { - AffectedType.USER -> { - val user: User? = CascadeBot.INS.shardManager.getUserById(affected.id!!) - user?.let { - if (it.avatarUrl != null) { - webhookEmbedBuilder.setThumbnailUrl(it.avatarUrl) - } else { - webhookEmbedBuilder.setThumbnailUrl(it.defaultAvatarUrl) - } - } - } - - AffectedType.EMOTE -> { - val emote: Emote = CascadeBot.INS.shardManager.getEmoteById(affected.id!!)!! - webhookEmbedBuilder.setThumbnailUrl(emote.imageUrl) - } - } + webhookEmbedBuilder.setThumbnailUrl(affected.imageUrl) } ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR -> { @@ -230,11 +214,7 @@ class GuildSettingsModeration { webhookEmbedBuilder.setColor(modlogEventStore.trigger.messageType.color.rgb) webhookEmbedBuilder.setTimestamp(Instant.now()) if (modlogEventStore.responsible != null) { - var iconUrl = if (modlogEventStore.responsible.avatarUrl != null) { - modlogEventStore.responsible.avatarUrl - } else { - modlogEventStore.responsible.defaultAvatarUrl - } + val iconUrl = modlogEventStore.responsible.effectiveAvatarUrl // TODO: by user webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventStore.responsible.name + " (" + modlogEventStore.responsible.id + ")", iconUrl)) } From 76c178fd25c6c1ab4250ca14bcee70a16db30507 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 23 Nov 2020 20:52:06 +0000 Subject: [PATCH 096/206] Make everything non-optional --- .../cascadebot/data/objects/ModlogAffected.kt | 4 ++-- .../data/objects/ModlogEventStore.kt | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt index 6f7e48b42..ab94c11fc 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogAffected.kt @@ -1,8 +1,8 @@ package org.cascadebot.cascadebot.data.objects -class ModlogAffected(val affectedType: AffectedType, val name: String, val mention: String?, val id : String?, val imageUrl: String? = null) { +class ModlogAffected(val affectedType: AffectedType, val name: String, val mention: String?, val id : String?, val imageUrl: String?) { - constructor() : this(AffectedType.UNKNOWN, "unknown", null, null) + constructor() : this(AffectedType.UNKNOWN, "unknown", null, null, null) } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 0d035ba56..805f7d65f 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -21,37 +21,37 @@ class ModlogEventStore(val trigger: ModlogEvent, @Transient val responsible: Use ModlogAffected(AffectedType.USER, affected.asTag, affected.asMention, affected.id, affected.effectiveAvatarUrl) } is Role -> { - ModlogAffected(AffectedType.ROLE, "${affected.name} (${affected.id})", affected.asMention, affected.id) + ModlogAffected(AffectedType.ROLE, "${affected.name} (${affected.id})", affected.asMention, affected.id, null) } is Emote -> { ModlogAffected(AffectedType.EMOTE, affected.name, affected.asMention, affected.id, affected.imageUrl) } is Guild -> { - ModlogAffected(AffectedType.GUILD, affected.name, null, affected.id, imageUrl = affected.iconUrl) + ModlogAffected(AffectedType.GUILD, affected.name, null, affected.id, affected.iconUrl) } is TextChannel -> { - ModlogAffected(AffectedType.GUILD, affected.name, affected.asMention, affected.id) + ModlogAffected(AffectedType.GUILD, affected.name, affected.asMention, affected.id, null) } is GuildChannel -> { - ModlogAffected(AffectedType.CHANNEL, affected.name, null, affected.id) + ModlogAffected(AffectedType.CHANNEL, affected.name, null, affected.id, null) } is Group -> { - ModlogAffected(AffectedType.GROUP, affected.name, null, affected.id) + ModlogAffected(AffectedType.GROUP, affected.name, null, affected.id, null) } is Field -> { - ModlogAffected(AffectedType.SETTING, affected.name, null, null) + ModlogAffected(AffectedType.SETTING, affected.name, null, null, null) } is Module -> { - ModlogAffected(AffectedType.MODULE, affected.name, null, null) + ModlogAffected(AffectedType.MODULE, affected.name, null, null, null) } is MainCommand -> { - ModlogAffected(AffectedType.COMMAND, affected.command(), null, null) + ModlogAffected(AffectedType.COMMAND, affected.command(), null, null, null) } is Playlist -> { ModlogAffected(AffectedType.PLAYLIST, affected.name, affected.playlistId.toHexString(), null, null) } is Tag -> { - ModlogAffected(AffectedType.TAG, affected.name, null, null) + ModlogAffected(AffectedType.TAG, affected.name, null, null, null) } else -> { ModlogAffected() From b2f34a657cd5c62cbce48a61469204996e92a261 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 23 Nov 2020 21:40:08 +0000 Subject: [PATCH 097/206] Set correct name and avatar URL when using webhooks --- .../cascadebot/data/objects/GuildSettingsModeration.kt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 79f5146f0..88aeb40e6 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -6,6 +6,7 @@ import club.minnced.discord.webhook.exception.HttpException import club.minnced.discord.webhook.send.WebhookEmbed import club.minnced.discord.webhook.send.WebhookEmbed.EmbedTitle import club.minnced.discord.webhook.send.WebhookEmbedBuilder +import club.minnced.discord.webhook.send.WebhookMessageBuilder import de.bild.codec.annotations.Transient import net.dv8tion.jda.api.entities.Emote import net.dv8tion.jda.api.entities.Icon @@ -99,7 +100,7 @@ class GuildSettingsModeration { val eventsInfo = ChannelModlogEventsInfo() eventsInfo.id = modlogChannelNum++ modlogEvents.put(channel.idLong, eventsInfo) - channel.createWebhook("Cascade-modlog").setAvatar(Icon.from(URL(CascadeBot.INS.client.selfUser.avatarUrl).openStream())).queue { webhook -> + channel.createWebhook(CascadeBot.INS.client.selfUser.name).setAvatar(Icon.from(URL(CascadeBot.INS.client.selfUser.avatarUrl).openStream())).queue { webhook -> eventsInfo.webhookId = webhook.idLong eventsInfo.webhookToken = webhook.token!! eventsInfo.buildWebhookClient() @@ -219,7 +220,12 @@ class GuildSettingsModeration { webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventStore.responsible.name + " (" + modlogEventStore.responsible.id + ")", iconUrl)) } try { - webhookClient?.send(webhookEmbedBuilder.build()) + webhookClient?.send(WebhookMessageBuilder() + .setUsername(CascadeBot.INS.client.selfUser.name) + .setAvatarUrl(CascadeBot.INS.client.selfUser.effectiveAvatarUrl) + .addEmbeds(webhookEmbedBuilder.build()) + .build() + ) } catch (ignored: HttpException) { // TODO not ignore } From 838ccce16849d891ecdb623a1ab83511a626b81c Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 23 Nov 2020 22:00:24 +0000 Subject: [PATCH 098/206] Extract all modlog channel commands into methods --- .../moderation/ModlogChannelSubCommand.java | 253 ++++++++++-------- 1 file changed, 141 insertions(+), 112 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java index 1f8c4cee7..2f7e23d1f 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java @@ -9,7 +9,6 @@ import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.language.Language; import org.cascadebot.cascadebot.data.objects.GuildSettingsModeration; -import org.cascadebot.cascadebot.messaging.MessagingObjects; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.DiscordUtils; @@ -18,11 +17,7 @@ import org.cascadebot.cascadebot.utils.pagination.PageUtils; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Predicate; import java.util.stream.Collectors; public class ModlogChannelSubCommand extends SubCommand { @@ -33,132 +28,166 @@ public void onCommand(Member sender, CommandContext context) { return; } if (context.getArg(0).equalsIgnoreCase("list")) { - StringBuilder enabled = new StringBuilder(); - StringBuilder disabled = new StringBuilder(); - StringBuilder deleted = new StringBuilder(); - var channelModlogEventsSet = context.getData().getModeration().getModlogEvents().entrySet(); - if (channelModlogEventsSet.size() == 0) { - context.getTypedMessaging().replyDanger("No channels have been set up with modlog events!"); - return; - } - for (var channelModlogEventsInfo : channelModlogEventsSet) { - TextChannel modlogChannel = CascadeBot.INS.getShardManager().getTextChannelById(channelModlogEventsInfo.getKey()); - boolean channelExists = modlogChannel != null; - boolean someEvents = false; - int numEvents = channelModlogEventsInfo.getValue().getEvents().size(); - if (numEvents > 5) { - numEvents = 3; - someEvents = true; - } - boolean webhookExists = isEnabled(modlogChannel, context); - String eventsListString = channelModlogEventsInfo.getValue().getEvents().stream().limit(numEvents).map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining(", ")); - if (someEvents) { - eventsListString += ", and " + (channelModlogEventsInfo.getValue().getEvents().size() - 3) + " more"; - } - if (channelExists && webhookExists) { // Channel exists and is enabled - enabled.append(modlogChannel.getAsMention()).append(" - ").append(eventsListString).append('\n'); - } else if (channelExists) { // Channel exists, but is disabled - disabled.append(modlogChannel.getAsMention()).append(" - ").append(eventsListString).append('\n'); - } else { // Channel doesn't exist - deleted.append("#deleted-channel (").append(channelModlogEventsInfo.getValue().getId()).append(") - ").append(eventsListString).append('\n'); - } - } - List pages = new ArrayList<>(); - if (enabled.length() > 0) { - EmbedBuilder enabledBuilder = new EmbedBuilder(); - enabledBuilder.setTitle("Channel list - Enabled"); - enabledBuilder.setDescription(enabled.toString()); - pages.add(new PageObjects.EmbedPage(enabledBuilder)); - } - if (disabled.length() > 0) { - EmbedBuilder disabledBuilder = new EmbedBuilder(); - disabledBuilder.setTitle("Channel list - disabled"); - disabledBuilder.setDescription(disabled.toString()); - pages.add(new PageObjects.EmbedPage(disabledBuilder)); - } - if (deleted.length() > 0) { - EmbedBuilder deletedBuilder = new EmbedBuilder(); - deletedBuilder.setTitle("Channel list - deleted channels"); - deletedBuilder.setDescription(deleted.toString()); - pages.add(new PageObjects.EmbedPage(deletedBuilder)); - } - context.getUiMessaging().sendPagedMessage(pages); + channelList(context); return; } if (context.getArgs().length == 3 && context.getArg(0).equalsIgnoreCase("move")) { - TextChannel targetChannel = DiscordUtils.getTextChannel(context.getGuild(), context.getArg(2)); - if (targetChannel == null) { - context.getTypedMessaging().replyDanger("Couldn't find channel `" + context.getArg(2) + "`"); - return; - } - GuildSettingsModeration.ChannelModlogEventsInfo channelModlogEventsInfo = null; - if (context.isArgInteger(1)) { - int id = context.getArgAsInteger(1); - for (var eventsInfoEntry : context.getData().getModeration().getModlogEvents().entrySet()) { - if (eventsInfoEntry.getValue().getId() == id) { - channelModlogEventsInfo = eventsInfoEntry.getValue(); - } - } - } else { - TextChannel originalChannel = DiscordUtils.getTextChannel(context.getGuild(), context.getArg(1)); - if (originalChannel != null) { - channelModlogEventsInfo = context.getData().getModeration().getModlogEvents().get(originalChannel.getIdLong()); - } - } - if (channelModlogEventsInfo == null) { - context.reply("Couldn't find events for channel `" + context.getArg(1) + "`"); - return; - } - for (ModlogEvent event : channelModlogEventsInfo.getEvents()) { - context.getData().getModeration().enableEvent(targetChannel, event); - } - context.getTypedMessaging().replySuccess("Successfully moved all events!"); + channelMove(context); return; } + if (context.getArgs().length < 2) { context.getUiMessaging().replyUsage(); return; } - TextChannel channel = DiscordUtils.getTextChannel(context.getGuild(), context.getArg(1)); + + String channelInput = context.getArg(0); + String operation = context.getArg(1); + TextChannel channel = DiscordUtils.getTextChannel(context.getGuild(), channelInput); if (channel == null) { - context.getTypedMessaging().replyDanger("Couldn't find channel `" + context.getArg(1) + "`"); + context.getTypedMessaging().replyDanger("Couldn't find channel `" + channelInput + "`"); return; } if (!context.getData().getModeration().getModlogEvents().containsKey(channel.getIdLong())) { context.getTypedMessaging().replyDanger("The specified channel is not a modlog channel!"); return; } - if (context.getArg(0).equalsIgnoreCase("enable")) { - if (isEnabled(channel, context)) { - context.getTypedMessaging().replyDanger("Channel is already enabled!"); - return; - } - channel.createWebhook("cascade-modlog").queue(webhook -> { - context.getData().getModeration().getModlogEvents().get(channel.getIdLong()).setNewWebhook(webhook.getIdLong(), webhook.getToken()); - context.getTypedMessaging().replySuccess("Successfully disabled channel!"); - }, throwable -> { - context.getTypedMessaging().replyDanger("Failed to enable events! The bot probably doesn't have permissions to create webhooks."); - }); - } else if (context.getArg(0).equalsIgnoreCase("disable")) { - if (!isEnabled(channel, context)) { - context.getTypedMessaging().replyDanger("Channel is already disabled!"); - return; + + if (operation.equalsIgnoreCase("enable")) { + channelEnable(context, channel); + return; + } else if (operation.equalsIgnoreCase("disable")) { + channelDisable(context, channel); + return; + } else if (operation.equalsIgnoreCase("delete")) { + channelDelete(context, channel); + return; + } else if (operation.equalsIgnoreCase("info")) { + channelInfo(context, channel); + return; + } + + context.getUiMessaging().replyUsage(); + } + + private void channelMove(CommandContext context) { + TextChannel targetChannel = DiscordUtils.getTextChannel(context.getGuild(), context.getArg(2)); + if (targetChannel == null) { + context.getTypedMessaging().replyDanger("Couldn't find channel `" + context.getArg(2) + "`"); + return; + } + GuildSettingsModeration.ChannelModlogEventsInfo channelModlogEventsInfo = null; + if (context.isArgInteger(1)) { + int id = context.getArgAsInteger(1); + for (var eventsInfoEntry : context.getData().getModeration().getModlogEvents().entrySet()) { + if (eventsInfoEntry.getValue().getId() == id) { + channelModlogEventsInfo = eventsInfoEntry.getValue(); + } } - channel.deleteWebhookById(String.valueOf(context.getData().getModeration().getModlogEvents().get(channel.getIdLong()).getWebhookId())).queue(aVoid -> { - context.getTypedMessaging().replySuccess("Successfully enabled channel!"); - }, throwable -> { - context.getTypedMessaging().replyDanger("Failed to disable events! The bot probably doesn't have permissions to delete webhooks."); - }); - } else if (context.getArg(0).equalsIgnoreCase("delete")) { - context.getData().getModeration().getModlogEvents().remove(channel.getIdLong()); - context.getTypedMessaging().replySuccess("Successfully deleted channel!"); - } else if (context.getArg(0).equalsIgnoreCase("info")) { - GuildSettingsModeration.ChannelModlogEventsInfo channelModlogEventsInfo = context.getData().getModeration().getModlogEvents().get(channel.getIdLong()); - String events = channelModlogEventsInfo.getEvents().stream().map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")); - context.getUiMessaging().sendPagedMessage(PageUtils.splitStringToEmbedPages(events, "Events for channel " + channel.getName(), 1000, '\n')); } else { - context.getUiMessaging().replyUsage(); + TextChannel originalChannel = DiscordUtils.getTextChannel(context.getGuild(), context.getArg(1)); + if (originalChannel != null) { + channelModlogEventsInfo = context.getData().getModeration().getModlogEvents().get(originalChannel.getIdLong()); + } + } + if (channelModlogEventsInfo == null) { + context.reply("Couldn't find events for channel `" + context.getArg(1) + "`"); + return; + } + for (ModlogEvent event : channelModlogEventsInfo.getEvents()) { + context.getData().getModeration().enableEvent(targetChannel, event); + } + context.getTypedMessaging().replySuccess("Successfully moved all events!"); + } + + private void channelList(CommandContext context) { + StringBuilder enabled = new StringBuilder(); + StringBuilder disabled = new StringBuilder(); + StringBuilder deleted = new StringBuilder(); + var channelModlogEventsSet = context.getData().getModeration().getModlogEvents().entrySet(); + if (channelModlogEventsSet.size() == 0) { + context.getTypedMessaging().replyDanger("No channels have been set up with modlog events!"); + return; + } + for (var channelModlogEventsInfo : channelModlogEventsSet) { + TextChannel modlogChannel = CascadeBot.INS.getShardManager().getTextChannelById(channelModlogEventsInfo.getKey()); + boolean channelExists = modlogChannel != null; + boolean someEvents = false; + int numEvents = channelModlogEventsInfo.getValue().getEvents().size(); + if (numEvents > 5) { + numEvents = 3; + someEvents = true; + } + boolean webhookExists = isEnabled(modlogChannel, context); + String eventsListString = channelModlogEventsInfo.getValue().getEvents().stream().limit(numEvents).map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining(", ")); + if (someEvents) { + eventsListString += ", and " + (channelModlogEventsInfo.getValue().getEvents().size() - 3) + " more"; + } + if (channelExists && webhookExists) { // Channel exists and is enabled + enabled.append(modlogChannel.getAsMention()).append(" - ").append(eventsListString).append('\n'); + } else if (channelExists) { // Channel exists, but is disabled + disabled.append(modlogChannel.getAsMention()).append(" - ").append(eventsListString).append('\n'); + } else { // Channel doesn't exist + deleted.append("#deleted-channel (").append(channelModlogEventsInfo.getValue().getId()).append(") - ").append(eventsListString).append('\n'); + } + } + List pages = new ArrayList<>(); + if (enabled.length() > 0) { + EmbedBuilder enabledBuilder = new EmbedBuilder(); + enabledBuilder.setTitle("Channel list - Enabled"); + enabledBuilder.setDescription(enabled.toString()); + pages.add(new PageObjects.EmbedPage(enabledBuilder)); + } + if (disabled.length() > 0) { + EmbedBuilder disabledBuilder = new EmbedBuilder(); + disabledBuilder.setTitle("Channel list - disabled"); + disabledBuilder.setDescription(disabled.toString()); + pages.add(new PageObjects.EmbedPage(disabledBuilder)); + } + if (deleted.length() > 0) { + EmbedBuilder deletedBuilder = new EmbedBuilder(); + deletedBuilder.setTitle("Channel list - deleted channels"); + deletedBuilder.setDescription(deleted.toString()); + pages.add(new PageObjects.EmbedPage(deletedBuilder)); + } + context.getUiMessaging().sendPagedMessage(pages); + return; + } + + private void channelInfo(CommandContext context, TextChannel channel) { + GuildSettingsModeration.ChannelModlogEventsInfo channelModlogEventsInfo = context.getData().getModeration().getModlogEvents().get(channel.getIdLong()); + String events = channelModlogEventsInfo.getEvents().stream().map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")); + context.getUiMessaging().sendPagedMessage(PageUtils.splitStringToEmbedPages(events, "Events for channel " + channel.getName(), 1000, '\n')); + } + + private void channelDelete(CommandContext context, TextChannel channel) { + context.getData().getModeration().getModlogEvents().remove(channel.getIdLong()); + context.getTypedMessaging().replySuccess("Successfully deleted channel!"); + } + + private void channelDisable(CommandContext context, TextChannel channel) { + if (!isEnabled(channel, context)) { + context.getTypedMessaging().replyDanger("Channel is already disabled!"); + return; + } + channel.deleteWebhookById(String.valueOf(context.getData().getModeration().getModlogEvents().get(channel.getIdLong()).getWebhookId())).queue(aVoid -> { + context.getTypedMessaging().replySuccess("Successfully enabled channel!"); + }, throwable -> { + context.getTypedMessaging().replyDanger("Failed to disable events! The bot probably doesn't have permissions to delete webhooks."); + }); + } + + private void channelEnable(CommandContext context, TextChannel channel) { + if (isEnabled(channel, context)) { + context.getTypedMessaging().replyDanger("Channel is already enabled!"); + return; } + channel.createWebhook("cascade-modlog").queue(webhook -> { + context.getData().getModeration().getModlogEvents().get(channel.getIdLong()).setNewWebhook(webhook.getIdLong(), webhook.getToken()); + context.getTypedMessaging().replySuccess("Successfully disabled channel!"); + }, throwable -> { + context.getTypedMessaging().replyDanger("Failed to enable events! The bot probably doesn't have permissions to create webhooks."); + }); } private boolean isEnabled(TextChannel channel, CommandContext context) { From 23e49d3d8528a6814028975beb07abe2a6c87916 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 23 Nov 2020 22:00:27 +0000 Subject: [PATCH 099/206] Modlog Usage --- src/main/resources/arguments.json | 43 ++++++++++++++++++++++ src/main/resources/lang/en-GB.json | 57 ++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/src/main/resources/arguments.json b/src/main/resources/arguments.json index 229e243f8..fbd820308 100644 --- a/src/main/resources/arguments.json +++ b/src/main/resources/arguments.json @@ -102,6 +102,49 @@ } } }, + "modlog*": { + "enable*": { + "channel*": { + "_type": "required", + "events": { + "_type": "required", + "_varargs": true + } + } + }, + "disable*": { + "channel*": { + "_type": "required", + "events": { + "_type": "required", + "_varargs": true + } + } + }, + "events": {}, + "prune": {}, + "clear": { + "disabled": {} + }, + "channel*": { + "list": {}, + "move*": { + "source*": { + "_type": "required", + "destination": { + "_type": "required" + } + } + }, + "channel*": { + "_type": "required", + "enable": {}, + "disable": {}, + "delete": {}, + "info": {} + } + } + }, "tempslowmode*": { "interval*": { "_type": "required", diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 4cf6c56e8..9b192f0be 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -305,6 +305,62 @@ "section_title": "{0} module", "cannot_find_field": "Cannot find that field!" }, + "modlog": { + "command": "modlog", + "enable": { + "command": "enable", + "description": "Enables the specified modlog events for a channel." + }, + "disable": { + "command": "disable", + "description": "Disables the specified modlog events for a channel." + }, + "channel": { + "command": "channel", + "list": { + "command": "list", + "description": "Lists all the modlog channels." + }, + "move": { + "command": "move", + "description": "Moves all events from one channel to another." + }, + "channel": { + "enable": { + "command": "enable", + "description": "Enables a channel to receive modlog events." + }, + "disable": { + "command": "disable", + "description": "Disables a channel from receiving modlog events." + }, + "delete": { + "command": "delete", + "description": "Deletes all modlog events attached to a channel." + }, + "info": { + "command": "info", + "description": "Displays information about a modlog channel." + } + } + }, + "clear": { + "command": "clear", + "description": "Clear all modlog events.", + "disabled": { + "command": "disabled", + "description": "Clears all modlog events for disabled channels." + } + }, + "events": { + "command": "event", + "description": "Displays a list of all modlog events." + }, + "prune": { + "command": "prune", + "description": "Removes all modlog entries for deleted channels." + } + }, "tag": { "command": "tag", "description": "Tag command.", @@ -2109,6 +2165,7 @@ "volume": "volume", "weight": "weight", "words": "words", + "events": "events", "filters#type#whitelist": { "name": "whitelist" }, From 8fb21b0b33dacd8d34f6e04e44b68d7db492da96 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Mon, 23 Nov 2020 22:21:32 +0000 Subject: [PATCH 100/206] 7 Speedrun --- .../cascadebot/events/CommandListener.java | 8 +------- .../cascadebot/events/ModlogEventListener.java | 9 +++------ .../commands/management/SettingsCommand.kt | 7 ++++--- .../cascadebot/moderation/ModlogEvent.kt | 2 +- src/main/resources/lang/en-GB.json | 18 +++++++++--------- 5 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java index 57a4d268a..05d9fd427 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java @@ -119,13 +119,7 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { MainCommand cmd = CascadeBot.INS.getCommandManager().getCommand(trigger, guildData); if (modlogEvent != null && cmd != null) { List embedFieldList = new ArrayList<>(); - if (args.length > 0) { - StringBuilder stringBuilder = new StringBuilder(); - for (String arg : args) { - stringBuilder.append(arg).append(' '); - } - embedFieldList.add(new ModlogEmbedField(true, "modlog.command.args", "modlog.general.variable", stringBuilder.toString())); - } + embedFieldList.add(new ModlogEmbedField(true, "modlog.command.command", "modlog.general.variable", "```" + message + "```")); ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, event.getAuthor(),cmd, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); } diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 6fe6b1985..3532314dc 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -901,13 +901,10 @@ public void onGenericRole(GenericRoleEvent event) { } else if (event instanceof RoleUpdateColorEvent) { modlogEvent = ModlogEvent.ROLE_COLOR_UPDATED; Color oldColor = ((RoleUpdateColorEvent) event).getOldColor(); - if (oldColor != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.role.old_color", null, ColorUtils.getHex(oldColor.getRed(), oldColor.getGreen(), oldColor.getBlue()))); - } Color newColor = ((RoleUpdateColorEvent) event).getNewColor(); - if (newColor != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.role.new_color", null, ColorUtils.getHex(newColor.getRed(), newColor.getGreen(), newColor.getBlue()))); - } + + embedFieldList.add(new ModlogEmbedField(false, "modlog.role.old_color", oldColor != null ? null : "words.default", oldColor != null ? ColorUtils.getHex(oldColor.getRed(), oldColor.getGreen(), oldColor.getBlue()) : null)); + embedFieldList.add(new ModlogEmbedField(false, "modlog.role.new_color", newColor != null ? null : "words.default", newColor != null ? ColorUtils.getHex(newColor.getRed(), newColor.getGreen(), newColor.getBlue()) : null)); } else if (event instanceof RoleUpdateHoistedEvent) { modlogEvent = ModlogEvent.ROLE_HOIST_UPDATED; var wasHoisted = ((RoleUpdateHoistedEvent) event).wasHoisted(); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt index 5644ea863..4f931bdba 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt @@ -127,9 +127,10 @@ class SettingsCommand : MainCommand() { } context.typedMessaging.replySuccess(context.i18n("commands.settings.setting_set", field.name, value)) val embedFields: MutableList = ArrayList(); - embedFields.add(ModlogEmbedField(true, "modlog.setting.old", "modlog.general.variable", oldValue)) - embedFields.add(ModlogEmbedField(true, "modlog.setting.new", "modlog.general.variable", value)) - context.data.moderation.sendModlogEvent(context.guild.idLong, ModlogEventStore(ModlogEvent.CASCADE_SETTINGS_UPDATED, sender.user, field, ArrayList())) + embedFields.add(ModlogEmbedField(true, "modlog.setting.value", "modlog.general.small_change", oldValue, value)) + val modlogEventStore = ModlogEventStore(ModlogEvent.CASCADE_SETTINGS_UPDATED, sender.user, field, embedFields) + modlogEventStore.extraDescriptionInfo = mutableListOf(field.name) + context.data.moderation.sendModlogEvent(context.guild.idLong, modlogEventStore) } catch (e: IllegalAccessException) { context.typedMessaging.replyException(context.i18n("commands.settings.cannot_access"), e) } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index a8b761556..b2c25412e 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -58,7 +58,7 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: VOICE_DISCONNECT (MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.VOICE, Category.MODERATION), ROLE_CREATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), - ROLE_DELETED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), + ROLE_DELETED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.NAME, Category.ROLE), ROLE_COLOR_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), ROLE_HOIST_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), ROLE_MENTIONABLE_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.ROLE), diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 9b192f0be..361a244a1 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1658,17 +1658,17 @@ "role_created": { "select": "role_created", "display": "Role created", - "description": "{1} created a new role called `{0}`" + "description": "A new role was created called {0}" }, "role_deleted": { "select": "role_deleted", "display": "Role deleted", - "description": "{1} deleted the role called `{0}`" + "description": "A role called `{0}` was deleted" }, "role_color_updated": { "select": "role_color_updated", "display": "Role color updated", - "description": "Role `{0}` color was updated" + "description": "Role {0} colour was updated" }, "role_hoist_updated": { "select": "role_hoist_updated", @@ -1802,7 +1802,8 @@ }, "cascade_settings_updated": { "select": "cascade_settings_updated", - "display": "Cascade settings updated" + "display": "Cascade settings updated", + "description": "The setting `{2}` was updated" }, "cascade_module_updated": { "select": "cascade_module_updated", @@ -1810,7 +1811,8 @@ }, "cascade_command_run": { "select": "cascade_command_run", - "display": "Cascade command run" + "display": "Cascade command run", + "description": "{1} ran a command" }, "cascade_command_run_error": { "select": "cascade_command_run_error", @@ -2525,15 +2527,13 @@ "group_removed": "Removed group" }, "setting": { - "old": "Old Value", - "new": "New Value" + "value": "Value" }, "module": { "enabled": "Enabled" }, "command": { - "command": "Command", - "args": "Arguments" + "command": "Command" }, "tag": { "content": "Content", From fed1a5d30e7e36d6e9697ffb586b4a683cc12da2 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 24 Nov 2020 21:13:17 +0000 Subject: [PATCH 101/206] Speedrun v2 (See Desc) - Cascade Setting - Guild Member Left - Guild Member Kick - Guild Member Ban - Server Mute/Deafen --- .../events/ModlogEventListener.java | 22 ++++++++++++++----- .../commands/management/SettingsCommand.kt | 13 ++++++++++- .../cascadebot/moderation/ModlogEvent.kt | 4 ++-- src/main/resources/lang/en-GB.json | 3 ++- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 3532314dc..88a2ab6d2 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -4,6 +4,7 @@ import com.google.gson.JsonParser; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.audit.ActionType; +import net.dv8tion.jda.api.audit.AuditLogEntry; import net.dv8tion.jda.api.entities.Category; import net.dv8tion.jda.api.entities.ChannelType; import net.dv8tion.jda.api.entities.Emote; @@ -209,6 +210,9 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { embedFieldList.add(new ModlogEmbedDescription("modlog.member.joined", user.getAsMention())); } else if (event instanceof GuildMemberLeaveEvent) { if (auditLogEntry != null && auditLogEntry.getType().equals(ActionType.KICK)) { + ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.GUILD_MEMBER_LEFT, null, user, embedFieldList); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); + responsible = auditLogEntry.getUser(); embedFieldList.add(new ModlogEmbedDescription("modlog.member.kicked", user.getAsMention())); if (auditLogEntry.getReason() != null) { @@ -218,7 +222,6 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { } modlogEvent = ModlogEvent.GUILD_MEMBER_KICKED; } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find kick entry"); modlogEvent = ModlogEvent.GUILD_MEMBER_LEFT; } } else if (event instanceof GuildMemberRoleAddEvent) { @@ -561,6 +564,7 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { List embedFieldList = new ArrayList<>(); List extraDescriptionInfo = List.of(); ModlogEvent action; + User responsible = null; if (event instanceof GuildVoiceDeafenEvent) { boolean deafened = (((GuildVoiceDeafenEvent) event).isDeafened()); Emote emote = deafened ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("self-deafened")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("undeafened")); @@ -572,11 +576,17 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { extraDescriptionInfo = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(muted)); action = ModlogEvent.VOICE_MUTE; } else if (event instanceof GuildVoiceGuildDeafenEvent) { + if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_UPDATE) { + responsible = auditLogEntry.getUser(); + } boolean guildDeafened = (((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()); Emote emote = guildDeafened ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("server-deafened")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("undeafened")); extraDescriptionInfo = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(guildDeafened)); action = ModlogEvent.VOICE_SERVER_DEAFEN; } else if (event instanceof GuildVoiceGuildMuteEvent) { + if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_UPDATE) { + responsible = auditLogEntry.getUser(); + } boolean guildMuted = (((GuildVoiceGuildMuteEvent) event).isGuildMuted()); Emote emote = guildMuted ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("server-muted")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("unmuted")); extraDescriptionInfo = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(guildMuted)); @@ -586,25 +596,27 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { action = ModlogEvent.VOICE_JOIN; } else if (event instanceof GuildVoiceLeaveEvent) { extraDescriptionInfo = List.of(((GuildVoiceLeaveEvent) event).getChannelLeft().getName()); - if (auditLogEntry != null) { + if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_VOICE_KICK) { action = ModlogEvent.VOICE_DISCONNECT; + responsible = auditLogEntry.getUser(); } else { action = ModlogEvent.VOICE_LEAVE; } } else if (event instanceof GuildVoiceMoveEvent) { extraDescriptionInfo = List.of(((GuildVoiceMoveEvent) event).getChannelLeft().getName(), ((GuildVoiceMoveEvent) event).getChannelJoined().getName()); - if (auditLogEntry != null) { + if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_VOICE_MOVE) { action = ModlogEvent.VOICE_FORCE_MOVE; + responsible = auditLogEntry.getUser(); } else { action = ModlogEvent.VOICE_MOVE; } } else { return; } - ModlogEventStore eventStore = new ModlogEventStore(action, null, affected, embedFieldList); + ModlogEventStore eventStore = new ModlogEventStore(action, responsible, affected, embedFieldList); eventStore.setExtraDescriptionInfo(extraDescriptionInfo); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }, ActionType.MEMBER_VOICE_MOVE, ActionType.MEMBER_VOICE_KICK); + }, ActionType.MEMBER_VOICE_MOVE, ActionType.MEMBER_VOICE_KICK, ActionType.MEMBER_UPDATE); } //region Channels diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt index 4f931bdba..28967efed 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt @@ -12,6 +12,7 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext import org.cascadebot.cascadebot.commandmeta.MainCommand import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.commandmeta.SubCommand +import org.cascadebot.cascadebot.data.Config import org.cascadebot.cascadebot.data.language.Language.i18n import org.cascadebot.cascadebot.data.objects.GuildSettingsCore import org.cascadebot.cascadebot.data.objects.GuildSettingsManagement @@ -118,6 +119,7 @@ class SettingsCommand : MainCommand() { value = booleanValue.toString() field.setBoolean(settingsContainer, booleanValue) } + String::class.java -> { field[settingsContainer] = value } @@ -127,7 +129,16 @@ class SettingsCommand : MainCommand() { } context.typedMessaging.replySuccess(context.i18n("commands.settings.setting_set", field.name, value)) val embedFields: MutableList = ArrayList(); - embedFields.add(ModlogEmbedField(true, "modlog.setting.value", "modlog.general.small_change", oldValue, value)) + if (field.type == Boolean::class.javaPrimitiveType) { + val emote = if (value.toBoolean()) { + Config.INS.globalEmotes["tick"]?.let { CascadeBot.INS.shardManager.getEmoteById(it)?.asMention } ?: "" + } else { + Config.INS.globalEmotes["cross"]?.let { CascadeBot.INS.shardManager.getEmoteById(it)?.asMention } ?: "" + } + embedFields.add(ModlogEmbedField(true, "modlog.setting.value", "modlog.setting.boolean_change", emote, value)) + } else { + embedFields.add(ModlogEmbedField(true, "modlog.setting.value", "modlog.general.small_change", oldValue, value)) + } val modlogEventStore = ModlogEventStore(ModlogEvent.CASCADE_SETTINGS_UPDATED, sender.user, field, embedFields) modlogEventStore.extraDescriptionInfo = mutableListOf(field.name) context.data.moderation.sendModlogEvent(context.guild.idLong, modlogEventStore) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index b2c25412e..0884276dc 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -19,8 +19,8 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: GUILD_MEMBER_ROLE_REMOVED (MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_MEMBER), GUILD_MEMBER_NICKNAME_UPDATED (MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_MEMBER), - GUILD_USER_BANNED (MessageType.DANGER, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.NAME, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), - GUILD_USER_UNBANNED (MessageType.DANGER, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.NAME, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + GUILD_USER_BANNED (MessageType.DANGER, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.NAME, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), + GUILD_USER_UNBANNED (MessageType.DANGER, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.NAME, Category.GUILD, Category.GUILD_MEMBER, Category.MODERATION), GUILD_MESSAGE_DELETED (MessageType.WARNING, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_MESSAGE), GUILD_MESSAGE_DELETED_MENTION (MessageType.INFO, ModlogDisplayType.AFFECTED_AUTHOR, AffectedDisplayType.MENTION, Category.GUILD, Category.GUILD_MESSAGE), diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 361a244a1..219de19d6 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -2527,7 +2527,8 @@ "group_removed": "Removed group" }, "setting": { - "value": "Value" + "value": "Value", + "boolean_change": "{0} value has been set to `{1}`" }, "module": { "enabled": "Enabled" From ae9755d007822b1b723b886790944469ed95d94d Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 28 Nov 2020 11:03:22 +0000 Subject: [PATCH 102/206] Work on event collector --- .../cascadebot/events/EventCollector.java | 54 +++++++ .../events/ModlogEventListener.java | 112 +++++++++++++-- .../ModlogChannelMoveCollectorRunnable.java | 135 ------------------ .../ModlogMemberRoleCollectorRunnable.java | 10 -- 4 files changed, 155 insertions(+), 156 deletions(-) create mode 100644 src/main/java/org/cascadebot/cascadebot/events/EventCollector.java delete mode 100644 src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java delete mode 100644 src/main/java/org/cascadebot/cascadebot/runnables/ModlogMemberRoleCollectorRunnable.java diff --git a/src/main/java/org/cascadebot/cascadebot/events/EventCollector.java b/src/main/java/org/cascadebot/cascadebot/events/EventCollector.java new file mode 100644 index 000000000..37add8785 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/events/EventCollector.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020 CascadeBot. All rights reserved. + * Licensed under the MIT license. + */ + +package org.cascadebot.cascadebot.events; + +import net.dv8tion.jda.api.entities.Guild; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; + +public class EventCollector implements Runnable { + + private final Guild guild; + private final BiConsumer> finishConsumer; + private final long msTimeout; + + private BlockingQueue queue = new LinkedBlockingQueue<>(); + private List dataList = new ArrayList<>(); + + public EventCollector(Guild guild, BiConsumer> finishConsumer, long msTimeout) { + this.guild = guild; + this.finishConsumer = finishConsumer; + this.msTimeout = msTimeout; + } + + @Override + public void run() { + boolean collecting = true; + while (collecting) { + try { + T data = queue.poll(msTimeout, TimeUnit.MILLISECONDS); + if (data == null) { + collecting = false; + finishConsumer.accept(guild, dataList); + } else { + dataList.add(data); + } + } catch (InterruptedException e) { + break; + } + } + } + + public BlockingQueue getQueue() { + return queue; + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 88a2ab6d2..ec421211d 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -4,12 +4,12 @@ import com.google.gson.JsonParser; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.audit.ActionType; -import net.dv8tion.jda.api.audit.AuditLogEntry; import net.dv8tion.jda.api.entities.Category; import net.dv8tion.jda.api.entities.ChannelType; import net.dv8tion.jda.api.entities.Emote; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.GuildChannel; +import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.TextChannel; @@ -113,13 +113,14 @@ import org.cascadebot.cascadebot.moderation.ModlogEmbedField; import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; -import org.cascadebot.cascadebot.runnables.ModlogChannelMoveCollectorRunnable; import org.cascadebot.cascadebot.runnables.ModlogMemberRoleCollectorRunnable; import org.cascadebot.cascadebot.utils.Attachment; import org.cascadebot.cascadebot.utils.ColorUtils; import org.cascadebot.cascadebot.utils.CryptUtils; import org.cascadebot.cascadebot.utils.ModlogUtils; import org.cascadebot.cascadebot.utils.SerializableMessage; +import org.cascadebot.cascadebot.utils.lists.ChangeList; +import org.cascadebot.shared.utils.ThreadPoolExecutorLogged; import org.jetbrains.annotations.NotNull; import javax.crypto.BadPaddingException; @@ -137,12 +138,17 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; public class ModlogEventListener extends ListenerAdapter { - private final Map moveRunnableMap = new HashMap<>(); - private final Map roleRunnableMap = new HashMap<>(); + private final Map> moveRunnableMap = new HashMap<>(); + private final Map> roleRunnableMap = new HashMap<>(); + + private static final AtomicInteger threadCounter = new AtomicInteger(0); + private final ExecutorService EVENT_COLLECTOR_POOL = ThreadPoolExecutorLogged.newCachedThreadPool((runnable) -> new Thread(runnable, "event-collector-" + threadCounter.getAndIncrement()), CascadeBot.LOGGER); public void onGenericEmote(GenericEmoteEvent event) { GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); @@ -472,7 +478,7 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { String oldIconUrl = ((GuildUpdateIconEvent) event).getOldIconUrl(); String newIconUrl = ((GuildUpdateIconEvent) event).getNewIconUrl(); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", null, oldIconUrl != null ? oldIconUrl : "-" )); + embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", null, oldIconUrl != null ? oldIconUrl : "-")); embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_image", null, newIconUrl != null ? newIconUrl : "-")); modlogEvent = ModlogEvent.GUILD_UPDATE_ICON; } else if (event instanceof GuildUpdateMaxMembersEvent) { @@ -861,18 +867,102 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String } private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, int oldPos, GuildChannel channel) { - ModlogChannelMoveCollectorRunnable.ChannelMoveData moveData = - new ModlogChannelMoveCollectorRunnable.ChannelMoveData(type, oldPos, channel); + ChannelMoveData moveData = new ChannelMoveData(type, oldPos, channel); if (moveRunnableMap.containsKey(guild.getIdLong())) { moveRunnableMap.get(guild.getIdLong()).getQueue().add(moveData); } else { - ModlogChannelMoveCollectorRunnable runnable = new ModlogChannelMoveCollectorRunnable(guild, () -> moveRunnableMap.remove(guild.getIdLong())); - runnable.getQueue().add(moveData); - moveRunnableMap.put(guild.getIdLong(), runnable); - new Thread(runnable, "modlog-channel-move-" + guild.getId()).start(); + EventCollector moveCollector = new EventCollector<>(guild, this::channelMove, 500); + moveCollector.getQueue().add(moveData); + moveRunnableMap.put(guild.getIdLong(), moveCollector); + EVENT_COLLECTOR_POOL.submit(moveCollector); } } + private void channelMove(Guild guild, List channelMoveDataList) { + moveRunnableMap.remove(guild.getIdLong()); + ModlogUtils.getAuditLogFromType(guild, auditLogEntry -> { + User responsible = null; + if (auditLogEntry != null) { + responsible = auditLogEntry.getUser(); + } + int maxDistance = 0; + List maxMoveData = new ArrayList<>(); + for (ChannelMoveData moveData : channelMoveDataList) { + if (moveData == null) { + continue; + } + int distance = Math.abs(moveData.channel.getPosition() - moveData.oldPos); + if (distance == maxDistance) { + maxMoveData.add(moveData); + } else if (distance > maxDistance) { + maxMoveData = new ArrayList<>(); + maxDistance = distance; + maxMoveData.add(moveData); + } + } + + GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); + List embedParts = new ArrayList<>(); + for (ChannelMoveData data : maxMoveData) { + ModlogEmbedField field = new ModlogEmbedField(false, "modlog.channel.position.title", + "modlog.general.small_change", + String.valueOf(data.oldPos), String.valueOf(data.channel.getPosition())); + field.addTitleObjects(data.channel.getName()); + embedParts.add(field); + } + ModlogEvent event = maxMoveData.size() <= 1 ? ModlogEvent.CHANNEL_POSITION_UPDATED : ModlogEvent.MULTIPLE_CHANNEL_POSITION_UPDATED; + ModlogEventStore eventStore = new ModlogEventStore(event, responsible, maxMoveData.get(0).channel, embedParts); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), eventStore); + + }, ActionType.CHANNEL_UPDATE); + } + + public class ChannelMoveData { + + private final ChannelType type; + private final int oldPos; + private final GuildChannel channel; + + public ChannelMoveData(ChannelType type, int oldPos, GuildChannel channel) { + this.type = type; + this.oldPos = oldPos; + this.channel = channel; + } + + public ChannelType getType() { + return type; + } + + public int getOldPos() { + return oldPos; + } + + public GuildChannel getChannel() { + return channel; + } + + } + + public class RoleModifyData { + + private final Member member; + private final ChangeList changeList; + + public RoleModifyData(Member member, ChangeList changeList) { + this.member = member; + this.changeList = changeList; + } + + public Member getMember() { + return member; + } + + public ChangeList getChangeList() { + return changeList; + } + + } + public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Category oldParent, Category newParent, GuildChannel channel) { ModlogEvent event = ModlogEvent.CHANNEL_PARENT_UPDATED; GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java deleted file mode 100644 index d8755db69..000000000 --- a/src/main/java/org/cascadebot/cascadebot/runnables/ModlogChannelMoveCollectorRunnable.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.cascadebot.cascadebot.runnables; - -import net.dv8tion.jda.api.audit.ActionType; -import net.dv8tion.jda.api.entities.ChannelType; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.GuildChannel; -import net.dv8tion.jda.api.entities.User; -import org.bouncycastle.math.raw.Mod; -import org.cascadebot.cascadebot.data.managers.GuildDataManager; -import org.cascadebot.cascadebot.data.objects.GuildData; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; -import org.cascadebot.cascadebot.moderation.ModlogEmbedField; -import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; -import org.cascadebot.cascadebot.moderation.ModlogEvent; -import org.cascadebot.cascadebot.utils.ModlogUtils; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -public class ModlogChannelMoveCollectorRunnable implements Runnable { - - private Guild guild; - private Runnable finishRunnable; - - public ModlogChannelMoveCollectorRunnable(Guild guild, Runnable finishRunnable) { - this.guild = guild; - this.finishRunnable = finishRunnable; - } - - private BlockingQueue queue = new LinkedBlockingQueue<>(); - private List channelMoveDataList = new ArrayList<>(); - - @Override - public void run() { - boolean collecting = true; - while (collecting) { - try { - ChannelMoveData moveData = queue.poll(500, TimeUnit.MILLISECONDS); - channelMoveDataList.add(moveData); - if (moveData == null) { - collecting = false; - afterCollected(); - } - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - private void afterCollected() { - finishRunnable.run(); - ModlogUtils.getAuditLogFromType(guild, auditLogEntry -> { - User responsible = null; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } - int maxDistance = 0; - List maxMoveDatas = new ArrayList<>(); - for (ChannelMoveData moveData : channelMoveDataList) { - if (moveData == null) { - continue; - } - int distance = Math.abs(moveData.channel.getPosition() - moveData.oldPos); - if (distance == maxDistance) { - maxMoveDatas.add(moveData); - } else if (distance > maxDistance) { - maxMoveDatas = new ArrayList<>(); - maxDistance = distance; - maxMoveDatas.add(moveData); - } - } - - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - if (maxMoveDatas.size() == 1) { - ChannelMoveData data = maxMoveDatas.get(0); - ModlogEmbedField field = new ModlogEmbedField(false, - "modlog.general.position", - "modlog.general.small_change", - String.valueOf(data.oldPos), - String.valueOf(data.channel.getPosition())); - ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.CHANNEL_POSITION_UPDATED, responsible, maxMoveDatas.get(0).channel, List.of(field)); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), eventStore); - } else { - List embedParts = new ArrayList<>(); - for (ChannelMoveData data : maxMoveDatas) { - ModlogEmbedField field = new ModlogEmbedField(false, "modlog.channel.position.title", - "modlog.general.small_change", - String.valueOf(data.oldPos), String.valueOf(data.channel.getPosition())); - field.addTitleObjects(data.channel.getName()); - embedParts.add(field); - } - ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.MULTIPLE_CHANNEL_POSITION_UPDATED, responsible, maxMoveDatas.get(0).channel, embedParts); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), eventStore); - } - - - - }, ActionType.CHANNEL_UPDATE); - } - - public BlockingQueue getQueue() { - return queue; - } - - public static class ChannelMoveData { - - private ChannelType type; - private int oldPos; - private GuildChannel channel; - - public ChannelMoveData(ChannelType type, int oldPos, GuildChannel channel) { - this.type = type; - this.oldPos = oldPos; - this.channel = channel; - } - - public ChannelType getType() { - return type; - } - - public int getOldPos() { - return oldPos; - } - - public GuildChannel getChannel() { - return channel; - } - - } - -} diff --git a/src/main/java/org/cascadebot/cascadebot/runnables/ModlogMemberRoleCollectorRunnable.java b/src/main/java/org/cascadebot/cascadebot/runnables/ModlogMemberRoleCollectorRunnable.java deleted file mode 100644 index cbea1e847..000000000 --- a/src/main/java/org/cascadebot/cascadebot/runnables/ModlogMemberRoleCollectorRunnable.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.cascadebot.cascadebot.runnables; - -public class ModlogMemberRoleCollectorRunnable implements Runnable { - - @Override - public void run() { - - } - -} From e0c5c4f688a9be4129d5be9752dd78a7c8752fbb Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 20:01:00 +0000 Subject: [PATCH 103/206] Missed a dodgy import --- .../org/cascadebot/cascadebot/events/ModlogEventListener.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index ec421211d..76b3270d3 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -113,7 +113,6 @@ import org.cascadebot.cascadebot.moderation.ModlogEmbedField; import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; -import org.cascadebot.cascadebot.runnables.ModlogMemberRoleCollectorRunnable; import org.cascadebot.cascadebot.utils.Attachment; import org.cascadebot.cascadebot.utils.ColorUtils; import org.cascadebot.cascadebot.utils.CryptUtils; From 25845d7fd12c35af3ff398b0290e37d3c46bc72d Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 21:19:30 +0000 Subject: [PATCH 104/206] Remove max members for now --- .../cascadebot/events/ModlogEventListener.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 76b3270d3..97560a267 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -480,12 +480,13 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", null, oldIconUrl != null ? oldIconUrl : "-")); embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_image", null, newIconUrl != null ? newIconUrl : "-")); modlogEvent = ModlogEvent.GUILD_UPDATE_ICON; - } else if (event instanceof GuildUpdateMaxMembersEvent) { - String oldMembers = String.valueOf(((GuildUpdateMaxMembersEvent) event).getOldMaxMembers()); - String newMembers = String.valueOf(((GuildUpdateMaxMembersEvent) event).getNewMaxMembers()); - - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.max_members", "modlog.general.small_change", oldMembers, newMembers)); - modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_MEMBERS; +// The max members +// } else if (event instanceof GuildUpdateMaxMembersEvent) { +// String oldMembers = String.valueOf(((GuildUpdateMaxMembersEvent) event).getOldMaxMembers()); +// String newMembers = String.valueOf(((GuildUpdateMaxMembersEvent) event).getNewMaxMembers()); +// +// embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.max_members", "modlog.general.small_change", oldMembers, newMembers)); +// modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_MEMBERS; } else if (event instanceof GuildUpdateMaxPresencesEvent) { String oldPresences = String.valueOf(((GuildUpdateMaxPresencesEvent) event).getOldMaxPresences()); String newPresences = String.valueOf(((GuildUpdateMaxPresencesEvent) event).getNewMaxPresences()); From 36dff20cc6c43ece06956da65aee9f9d9f211107 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 21:21:29 +0000 Subject: [PATCH 105/206] Channel stuff --- .../events/ModlogEventListener.java | 6 ++-- .../data/objects/GuildSettingsModeration.kt | 2 +- .../cascadebot/moderation/ModlogEvent.kt | 2 +- src/main/resources/lang/en-GB.json | 32 +++++++++++-------- 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 97560a267..53ed3d3f6 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -826,6 +826,7 @@ private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChann } embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + modlogEventStore.setExtraDescriptionInfo(List.of(type.name().toLowerCase())); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_CREATE); } @@ -843,6 +844,7 @@ private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChann } embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); + modlogEventStore.setExtraDescriptionInfo(List.of(type.name().toLowerCase())); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_DELETE); } @@ -858,9 +860,7 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.old_name", null, oldName)); - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.new_name", null, channel.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.general.name", "modlog.general.small_change", oldName, channel.getName())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_UPDATE); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 88aeb40e6..6a213f0e6 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -170,7 +170,7 @@ class GuildSettingsModeration { val affected = when (modlogEventStore.trigger.affectedDisplayType) { AffectedDisplayType.NAME -> modlogEventStore.affected.name AffectedDisplayType.MENTION -> modlogEventStore.affected.mention - ?: Language.i18n(guildData.locale, "words.unknown").toCapitalized() + ?: modlogEventStore.affected.name } webhookEmbedBuilder.setDescription( Language.i18n( diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 0884276dc..d455b78ec 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -70,7 +70,7 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: USER_NAME_UPDATED (MessageType.INFO, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.USER), CHANNEL_CREATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), - CHANNEL_DELETED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), + CHANNEL_DELETED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.NAME, Category.CHANNEL), CHANNEL_NAME_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), CHANNEL_PERMISSIONS_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), CHANNEL_POSITION_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CHANNEL), diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 219de19d6..e70ad8364 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1708,7 +1708,7 @@ "channel_created": { "select": "channel_created", "display": "Channel created", - "description": "Channel `#{0}` was created" + "description": "Channel {2, select, text {{0}} other {`#{0}`}} was created" }, "channel_deleted": { "select": "channel_deleted", @@ -1718,17 +1718,17 @@ "channel_name_updated": { "select": "channel_name_updated", "display": "Channel name updated", - "description": "Channel `#{0}` had its name changed" + "description": "Channel {0} had its name changed" }, "channel_permissions_updated": { "select": "channel_permissions_updated", "display": "Channel permissions updated", - "description": "The channel `#{0}` permissions where changed" + "description": "The channel {0} permissions where changed" }, "channel_position_updated": { "select": "channel_position_updated", "display": "Channel position updated", - "description": "The channel `#{0}` was moved" + "description": "The channel {0} was moved" }, "multiple_channel_position_updated": { "select": "multiple_channel_position_updated", @@ -1752,33 +1752,37 @@ "text_channel_nsfw_updated": { "select": "text_channel_nsfw_updated", "display": "Text channel NSFW updated", - "description": "{2} {3, select, true {The text channel `#{0}` is now an NSFW channel} other {The text channel `#{0}` is no longer a NSFW channel}}" + "description": "{2} {3, select, true {The text channel {0} is now an NSFW channel} other {The text channel {0} is no longer a NSFW channel}}" }, "text_channel_slowmode_updated": { "select": "text_channel_slowmode_updated", "display": "Text channel slowmode updated", - "description": "The channel `#{0}` slowmode time was changed" + "description": "The channel {0} slowmode time was changed" }, "text_channel_topic_updated": { "select": "text_channel_topic_updated", "display": "Text channel topic updated", - "description": "Channel `#{0}` topic was updated" + "description": "Channel {0} topic was updated" }, "cascade_permissions_group_created": { "select": "cascade_permissions_group_created", - "display": "Cascade permissions group created" + "display": "Cascade permissions group created", + "description": "Group `{0}` created" }, "cascade_permissions_group_deleted": { "select": "cascade_permissions_group_deleted", - "display": "Cascade permissions group deleted" + "display": "Cascade permissions group deleted", + "description": "Group `{0}` deleted" }, "cascade_permissions_group_permission_add": { "select": "cascade_permissions_group_permission_add", - "display": "Cascade permissions group permission add" + "display": "Cascade permissions group permission add", + "description": "Permission `{1}` added to group `{0}`" }, "cascade_permissions_group_permission_remove": { "select": "cascade_permissions_group_permission_remove", - "display": "Cascade permissions group permission remove" + "display": "Cascade permissions group permission remove", + "description": "Permission `{1}` removed from group `{0}`" }, "cascade_permissions_group_link": { "select": "cascade_permissions_group_link", @@ -2473,12 +2477,12 @@ "channel": { "type": { "name": "Type", - "text": "Text", + "text": "|g:channeltext| Text", "private": "Private", - "voice": "Voice", + "voice": "|g:channelvoice| Voice", "group": "Group", "category": "Category", - "store": "Store", + "store": "|g:channelstore| Store", "unknown": "Unknown" }, "perm": { From a1d0d71b1ee904266831cf6370a7a5816a93c978 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 21:29:40 +0000 Subject: [PATCH 106/206] Remove command run error from events --- .../java/org/cascadebot/cascadebot/events/CommandListener.java | 1 - .../kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java index 05d9fd427..9c7ce6cb7 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java @@ -113,7 +113,6 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { modlogEvent = ModlogEvent.CASCADE_COMMAND_RUN; } catch (Exception e) { Messaging.sendExceptionMessage(event.getChannel(), Language.i18n(guildData.getLocale(), "responses.failed_to_process_command"), e); - modlogEvent = ModlogEvent.CASCADE_COMMAND_RUN_ERROR; } finally { CascadeBot.clearCascadeMDC(); MainCommand cmd = CascadeBot.INS.getCommandManager().getCommand(trigger, guildData); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index d455b78ec..8538c6eab 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -100,7 +100,6 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: CASCADE_MODULE_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE), CASCADE_COMMAND_RUN (MessageType.INFO, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE), - CASCADE_COMMAND_RUN_ERROR (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE), CASCADE_PLAYLIST_CREATED (MessageType.INFO, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE), From 04d7d0d27f8909e735e1af34ba07e984ae3f091d Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 21:29:57 +0000 Subject: [PATCH 107/206] Parent and category changes --- .../cascadebot/cascadebot/events/ModlogEventListener.java | 4 +--- src/main/resources/lang/en-GB.json | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 53ed3d3f6..055f8a7dc 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -974,9 +974,7 @@ public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Categ } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.old_parent", null, oldParent.getName())); - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.new_parent", null, newParent.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.parent", "modlog.general.small_change", oldParent.getName(), newParent.getName())); ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_UPDATE); diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index e70ad8364..614e0738b 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1737,7 +1737,7 @@ "channel_parent_updated": { "select": "channel_parent_updated", "display": "Channel parent updated", - "description": "The channel `#{0}` changed category" + "description": "The channel {0} changed category" }, "voice_channel_bitrate_updated": { "select": "voice_channel_bitrate_updated", @@ -2498,8 +2498,7 @@ "position": { "title": "Channel {0} moved" }, - "old_parent": "Old Parent", - "new_parent": "New Parent", + "parent": "Parent", "nsfw": "NSFW", "slowmode": "Slowmode", "old_topic": "Old topic", From f31a7f19e2d2b1141a84c97c75cd00c87b7db654 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 21:44:52 +0000 Subject: [PATCH 108/206] ui ux --- .../cascadebot/cascadebot/utils/pagination/PageObjects.java | 4 ++-- src/main/resources/arguments.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/utils/pagination/PageObjects.java b/src/main/java/org/cascadebot/cascadebot/utils/pagination/PageObjects.java index 8b3236f58..090f27575 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/pagination/PageObjects.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/pagination/PageObjects.java @@ -26,12 +26,12 @@ public static class EmbedPage implements Page { private final boolean numbersInEmbed; public EmbedPage(EmbedBuilder embed) { - this.embed = embed; + this.embed = new EmbedBuilder(embed); this.numbersInEmbed = true; } public EmbedPage(EmbedBuilder embed, boolean numbersInEmbed) { - this.embed = embed; + this.embed = new EmbedBuilder(embed); this.numbersInEmbed = numbersInEmbed; } diff --git a/src/main/resources/arguments.json b/src/main/resources/arguments.json index fbd820308..5f947f019 100644 --- a/src/main/resources/arguments.json +++ b/src/main/resources/arguments.json @@ -156,7 +156,7 @@ } } }, - "tag": { + "tag*": { "tag": { "_type": "required" }, From 7694b61fa49bcbc8a777dd20f7256e4075809f03 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 22:25:19 +0000 Subject: [PATCH 109/206] Add group id Co-Authored-By: weeryan17 --- .../org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt index 805f7d65f..6f43196aa 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt @@ -36,7 +36,7 @@ class ModlogEventStore(val trigger: ModlogEvent, @Transient val responsible: Use ModlogAffected(AffectedType.CHANNEL, affected.name, null, affected.id, null) } is Group -> { - ModlogAffected(AffectedType.GROUP, affected.name, null, affected.id, null) + ModlogAffected(AffectedType.GROUP, affected.name + " (" + affected.id + ")", null, affected.id, null) } is Field -> { ModlogAffected(AffectedType.SETTING, affected.name, null, null, null) From 9b98d1fb70a7f55d9fa1cb059fc991abd062e81d Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 22:26:04 +0000 Subject: [PATCH 110/206] Modlog module descriptions Co-Authored-By: weeryan17 --- .../commands/management/module/ModuleDisableSubCommand.java | 5 ++--- .../commands/management/module/ModuleEnableSubCommand.java | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java index 9b2f2ecbe..4f83aa1cb 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java @@ -40,9 +40,8 @@ public void onCommand(Member sender, CommandContext context) { // If module wasn't already disabled context.getTypedMessaging().replySuccess(context.i18n("commands.module.disable.disabled", moduleName)); ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(true, "modlog.module.enabled", "modlog.general.variable", "false")); - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), module, embedFieldList); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), module, List.of()); + eventStore.setExtraDescriptionInfo(List.of("false")); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { // If module was already disabled diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java index f3cb7b66d..c0b241754 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java @@ -40,9 +40,8 @@ public void onCommand(Member sender, CommandContext context) { // If the module wasn't enabled context.getTypedMessaging().replySuccess(context.i18n("commands.module.enable.enabled", moduleName)); ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(true, "modlog.module.enabled", "modlog.general.variable", "true")); - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), module, embedFieldList); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), module, List.of()); + eventStore.setExtraDescriptionInfo(List.of("true")); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { // If the module was enabled From de174e1cd9fd2ca0edee14051a3f2e2fbc5b19c5 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 22:26:55 +0000 Subject: [PATCH 111/206] Add an group unlink Co-Authored-By: weeryan17 --- .../kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 8538c6eab..945059bfc 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -89,6 +89,7 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), CASCADE_PERMISSIONS_GROUP_LINK (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), + CASCADE_PERMISSIONS_GROUP_UNLINK (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), CASCADE_PERMISSIONS_USER_PERMISSION_ADD (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_PERMISSIONS), From 771630b567b3b688b97db3b924362e14292e2795 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 22:27:35 +0000 Subject: [PATCH 112/206] Descriptions for permissions Co-Authored-By: weeryan17 --- .../permission/GroupPermissionAddSubCommand.java | 5 ++--- .../permission/GroupPermissionLinkRoleSubCommand.java | 5 ++--- .../permission/GroupPermissionRemoveSubCommand.java | 5 ++--- .../GroupPermissionUnlinkRoleSubCommand.java | 8 ++++++++ .../permission/UserPermissionAddSubCommand.java | 5 ++--- .../permission/UserPermissionGroupSubCommand.java | 10 ++++------ .../permission/UserPermissionRemoveSubCommand.java | 5 ++--- 7 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java index c627cbb96..c2cf9937e 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java @@ -35,10 +35,9 @@ public void onCommand(Member sender, CommandContext context) { PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { if (group.addPermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.add.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(true, "modlog.cascade_permissions.permission_added", "modlog.general.variable", context.getArg(1))); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, List.of()); + eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.add.fail", context.getArg(1), group.getName() + "(" + group.getId() + ")")); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java index 62eb46693..0c43681e7 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java @@ -39,10 +39,9 @@ public void onCommand(Member sender, CommandContext context) { PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { if (group.linkRole(role.getIdLong())) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.link.success", group.getName(), role.getName())); - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(false, "modlog.cascade_permissions.linked_role", "modlog.general.variable", role.getAsMention())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_LINK; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, List.of()); + eventStore.setExtraDescriptionInfo(List.of(role.getAsMention())); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.link.fail", group.getName(), role.getName())); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java index 68c3c7e62..7da9ba903 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java @@ -36,10 +36,9 @@ public void onCommand(Member sender, CommandContext context) { PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { if (group.removePermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.remove.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(true, "modlog.cascade_permissions.permission_removed", "modlog.general.variable", context.getArg(1))); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, embedFieldList); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, List.of()); + eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.remove.fail", context.getArg(1), group.getName() + "(" + group.getId() + ")")); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java index 9bc1aa306..39d10d1b1 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java @@ -10,10 +10,14 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; +import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.DiscordUtils; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; +import java.util.List; + public class GroupPermissionUnlinkRoleSubCommand extends SubCommand { @Override @@ -32,6 +36,10 @@ public void onCommand(Member sender, CommandContext context) { PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { if (group.unlinkRole(role.getIdLong())) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.unlink.success", group.getName(), role.getName())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_UNLINK; + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, List.of()); + eventStore.setExtraDescriptionInfo(List.of(role.getAsMention())); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.unlink.fail", group.getName(), role.getName())); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java index 343f7b3e3..7e0866f1e 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java @@ -45,9 +45,8 @@ public void onCommand(Member sender, CommandContext context) { if (user.addPermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.add.success", context.getArg(1), member.getUser().getAsTag())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_PERMISSION_ADD; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(true, "modlog.cascade_permissions.permission_added", "modlog.general.variable", context.getArg(1))); - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), List.of()); + eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.add.fail", context.getArg(1), member.getUser().getAsTag())); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java index 932ab969b..1bdf9d151 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java @@ -47,9 +47,8 @@ public void onCommand(Member sender, CommandContext context) { if (user.addGroup(group)) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.group.put.success", member.getUser().getAsTag(), group.getName())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_GROUP_ADD; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(true, "modlog.cascade_permissions.group_added", "modlog.general.variable", group.getName() + "(" + group.getId() + ")")); - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), List.of()); + eventStore.setExtraDescriptionInfo(List.of(group.getName() + " (" + group.getId() + ")")); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.group.put.fail", member.getUser().getAsTag(), group.getName())); @@ -58,9 +57,8 @@ public void onCommand(Member sender, CommandContext context) { if (user.removeGroup(group)) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.group.remove.success", member.getUser().getAsTag(), group.getName())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_GROUP_REMOVE; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(true, "modlog.cascade_permissions.group_removed", "modlog.general.variable", group.getName() + "(" + group.getId() + ")")); - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), List.of()); + eventStore.setExtraDescriptionInfo(List.of(group.getName() + " (" + group.getId() + ")")); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.group.remove.fail", member.getUser().getAsTag(), group.getName())); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java index d165969c6..340635610 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java @@ -40,9 +40,8 @@ public void onCommand(Member sender, CommandContext context) { if (user.removePermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.remove.success", context.getArg(1), member.getUser().getAsTag())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(true, "modlog.cascade_permissions.permission_removed", "modlog.general.variable", context.getArg(1))); - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), embedFieldList); + ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), List.of()); + eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.remove.fail", context.getArg(1), member.getUser().getAsTag())); From 8afa52b90f887dcfa71b25fe1e499e04825849c7 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 22:27:50 +0000 Subject: [PATCH 113/206] Tag content markdown santisation Co-Authored-By: weeryan17 --- .../commands/management/tag/TagCreateSubCommand.java | 3 ++- .../commands/management/tag/TagEditSubCommand.java | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java index 41cde8501..971dffeaa 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java @@ -6,6 +6,7 @@ package org.cascadebot.cascadebot.commands.management.tag; import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.utils.MarkdownSanitizer; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; @@ -48,7 +49,7 @@ public void onCommand(Member sender, CommandContext context) { context.getTypedMessaging().replySuccess(message); ModlogEvent event = ModlogEvent.CASCADE_TAG_CREATED; List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.content", "modlog.general.variable", tag.getContent())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.content", "modlog.general.variable", "```" + MarkdownSanitizer.sanitize(tag.getContent()) + "```")); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java index 53d4a96d5..654f5e348 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java @@ -6,6 +6,7 @@ package org.cascadebot.cascadebot.commands.management.tag; import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.utils.MarkdownSanitizer; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.objects.ModlogEventStore; @@ -39,8 +40,8 @@ public void onCommand(Member sender, CommandContext context) { context.getTypedMessaging().replySuccess(context.i18n("commands.tag.edit.successfully_edited_tag", tagName)); ModlogEvent event = ModlogEvent.CASCADE_TAG_UPDATED; List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.old_content", "modlog.general.variable", oldContent)); - embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.new_content", "modlog.general.variable", tag.getContent())); + embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.old_content", "modlog.general.variable", "```" + MarkdownSanitizer.sanitize(oldContent) + "```")); + embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.new_content", "modlog.general.variable", "```" + MarkdownSanitizer.sanitize(tag.getContent()) + "```")); ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } From adf9da1a44d94e569c2085c30ec4c8b0d8cd8c57 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 22:28:14 +0000 Subject: [PATCH 114/206] System channel --- .../cascadebot/cascadebot/events/ModlogEventListener.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 055f8a7dc..f92b749ba 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -101,6 +101,7 @@ import net.dv8tion.jda.api.events.user.update.UserUpdateDiscriminatorEvent; import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; +import net.dv8tion.jda.api.utils.MarkdownSanitizer; import org.apache.commons.lang3.StringUtils; import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.UnicodeConstants; @@ -525,8 +526,11 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { TextChannel oldSystemChannel = ((GuildUpdateSystemChannelEvent) event).getOldSystemChannel(); TextChannel newSystemChannel = ((GuildUpdateSystemChannelEvent) event).getNewSystemChannel(); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_sys", null, oldSystemChannel != null ? oldSystemChannel.getName() : "-")); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_sys", null, newSystemChannel != null ? newSystemChannel.getName() : "-")); + embedFieldList.add(new ModlogEmbedField(false, + "modlog.guild.sys_channel", + "modlog.general.small_change", + oldSystemChannel != null ? oldSystemChannel.getAsMention() : "-", + newSystemChannel != null ? newSystemChannel.getAsMention() : "-")); modlogEvent = ModlogEvent.GUILD_UPDATE_SYSTEM_CHANNEL; } else if (event instanceof GuildUpdateVanityCodeEvent) { if (((GuildUpdateVanityCodeEvent) event).getOldVanityCode() != null) { From 5a8d5fc41acf59ee7cca75873e2e6231feea128a Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 22:28:34 +0000 Subject: [PATCH 115/206] =?UTF-8?q?=E2=9C=A8=20Language=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: weeryan17 --- src/main/resources/lang/en-GB.json | 49 +++++++++++++++++++----------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 614e0738b..dc4b474b1 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1688,12 +1688,12 @@ "role_permissions_updated": { "select": "role_permissions_updated", "display": "Role permissions updated", - "description": "The role `{0}` had its permissions updated" + "description": "The role {0} had its permissions updated" }, "role_position_updated": { "select": "role_position_updated", "display": "Role position updated", - "description": "The role `{0}`'s position was updated" + "description": "The role {0}'s position was updated" }, "user_discriminator_updated": { "select": "user_discriminator_updated", @@ -1777,32 +1777,42 @@ "cascade_permissions_group_permission_add": { "select": "cascade_permissions_group_permission_add", "display": "Cascade permissions group permission add", - "description": "Permission `{1}` added to group `{0}`" + "description": "Permission `{2}` added to group `{0}`" }, "cascade_permissions_group_permission_remove": { "select": "cascade_permissions_group_permission_remove", "display": "Cascade permissions group permission remove", - "description": "Permission `{1}` removed from group `{0}`" + "description": "Permission `{2}` removed from group `{0}`" }, "cascade_permissions_group_link": { "select": "cascade_permissions_group_link", - "display": "Cascade permissions group link" + "display": "Cascade permissions group link", + "description": "Linked group `{0}` to {2}" + }, + "cascade_permissions_group_unlink": { + "select": "cascade_permissions_group_unlink", + "display": "Cascade permissions group unlink", + "description": "Unlinked group `{0}` from {2}" }, "cascade_permissions_user_permission_add": { "select": "cascade_permissions_user_permission_add", - "display": "Cascade permissions user permission add" + "display": "Cascade permissions user permission add", + "description": "Permission `{2}` added to user `{0}`" }, "cascade_permissions_user_permission_remove": { "select": "cascade_permissions_user_permission_remove", - "display": "Cascade permissions user permission remove" + "display": "Cascade permissions user permission remove", + "description": "Permission `{2}` removed from user `{0}`" }, "cascade_permissions_user_group_add": { "select": "cascade_permissions_user_group_add", - "display": "Cascade permissions user group add" + "display": "Cascade permissions user group add", + "description": "Group `{2}` added to user `{0}`" }, "cascade_permissions_user_group_remove": { "select": "cascade_permissions_user_group_remove", - "display": "Cascade permissions user group remove" + "display": "Cascade permissions user group remove", + "description": "Group `{2}` removed from user `{0}`" }, "cascade_settings_updated": { "select": "cascade_settings_updated", @@ -1811,7 +1821,8 @@ }, "cascade_module_updated": { "select": "cascade_module_updated", - "display": "Cascade module updated" + "display": "Cascade module updated", + "description": "Module {0} was {2, select, true {enabled} other {disabled}}" }, "cascade_command_run": { "select": "cascade_command_run", @@ -1824,11 +1835,13 @@ }, "cascade_playlist_created": { "select": "cascade_playlist_created", - "display": "Cascade playlist created" + "display": "Cascade playlist created", + "description": "Playlist {0} was created" }, "cascade_playlist_deleted": { "select": "cascade_playlist_deleted", - "display": "Cascade playlist deleted" + "display": "Cascade playlist deleted", + "description": "Playlist {0} was deleted" }, "cascade_temp_mute": { "select": "cascade_temp_mute", @@ -1868,15 +1881,18 @@ }, "cascade_tag_created": { "select": "cascade_tag_created", - "display": "Cascade tag created" + "display": "Cascade tag created", + "description": "Created tag `{0}`" }, "cascade_tag_deleted": { "select": "cascade_tag_deleted", - "display": "Cascade tag deleted" + "display": "Cascade tag deleted", + "description": "Deleted tag `{0}`" }, "cascade_tag_updated": { "select": "cascade_tag_updated", - "display": "Cascade tag updated" + "display": "Cascade tag updated", + "description": "Tag `{0}` was changed" }, "guild_message_deleted_mention": { "select": "guild_message_deleted_mention", @@ -2450,8 +2466,7 @@ "new_region": "New Region", "old_splash": "Old Splash", "new_splash": "New Splash", - "old_sys": "Old System Channel", - "new_sys": "New System Channel", + "sys_channel": "System Channel", "vanity_code": { "old": "Old Vanity Code", "new": "New Vanity Code" From b20d2a55f60f44fde9a4a37b98a66ed9dd3083ee Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 13 Mar 2021 22:42:21 +0000 Subject: [PATCH 116/206] Make it so null channel parents are handled Co-Authored-By: weeryan17 --- .../org/cascadebot/cascadebot/events/ModlogEventListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index f92b749ba..210425e82 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -978,7 +978,7 @@ public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Categ } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.parent", "modlog.general.small_change", oldParent.getName(), newParent.getName())); + embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.parent", "modlog.general.small_change", oldParent == null ? "None" : oldParent.getName(), newParent == null ? "None" : newParent.getName())); // TODO language string for none ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); }, ActionType.CHANNEL_UPDATE); From fd2ea391148e5d4ee0f648dbfa4765ba81b075f9 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 22 Mar 2021 20:07:12 -0500 Subject: [PATCH 117/206] Clean up role events a little bit --- .../org/cascadebot/cascadebot/events/ModlogEventListener.java | 4 ++-- src/main/resources/lang/en-GB.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 210425e82..4e6e3451e 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -236,7 +236,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { } modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_ADDED; ModlogEmbedField addedRolesEmbedField = new ModlogEmbedField(false, "modlog.general.added_roles", null); - addedRolesEmbedField.addValueObjects(((GuildMemberRoleAddEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n"))); + addedRolesEmbedField.addValueObjects(((GuildMemberRoleAddEvent) event).getRoles().stream().map(Role::getAsMention).collect(Collectors.joining("\n"))); embedFieldList.add(addedRolesEmbedField); } else if (event instanceof GuildMemberRoleRemoveEvent) { if (auditLogEntry != null && auditLogEntry.getTargetIdLong() == event.getMember().getIdLong()) { @@ -244,7 +244,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { } modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_REMOVED; ModlogEmbedField removedRolesEmbedField = new ModlogEmbedField(false, "modlog.general.removed_roles", null); - removedRolesEmbedField.addValueObjects(((GuildMemberRoleRemoveEvent) event).getRoles().stream().map(role -> role.getName() + " (" + role.getId() + ")").collect(Collectors.joining("\n"))); + removedRolesEmbedField.addValueObjects(((GuildMemberRoleRemoveEvent) event).getRoles().stream().map(Role::getAsMention).collect(Collectors.joining("\n"))); embedFieldList.add(removedRolesEmbedField); } else if (event instanceof GuildMemberUpdateNicknameEvent) { if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_UPDATE) { diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index dc4b474b1..0a5334237 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1483,12 +1483,12 @@ "guild_member_role_added": { "select": "guild_member_role_added", "display": "Guild member role added", - "description": "Role(s) where added to {0}" + "description": "Role(s) were added to {0}" }, "guild_member_role_removed": { "select": "guild_member_role_removed", "display": "Guild member role removed", - "description": "Role(s) where removed from {0}" + "description": "Role(s) were removed from {0}" }, "guild_member_nickname_updated": { "select": "guild_member_nickname_updated", From 41f47ad768e6326296e859d286ef6fd7fadbe63b Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 22 Mar 2021 20:19:22 -0500 Subject: [PATCH 118/206] Channel possition calculations --- .../cascadebot/utils/DiscordUtils.java | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/utils/DiscordUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/DiscordUtils.java index d243c792a..bdc1d1c54 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/DiscordUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/DiscordUtils.java @@ -7,7 +7,9 @@ import com.jagrosh.jdautilities.commons.utils.FinderUtil; import lombok.experimental.UtilityClass; +import net.dv8tion.jda.api.entities.Category; import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.GuildChannel; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.TextChannel; @@ -114,7 +116,7 @@ public static TextChannel getTextChannelById(Long channelId) { public static TextChannel getTextChannel(Guild guild, String search) { List channels = FinderUtil.findTextChannels(search, guild); if (channels.size() > 1) { - return null; + return null; } TextChannel channel = channels.size() != 1 ? null : channels.get(0); @@ -205,4 +207,41 @@ public static Consumer handleExpectedErrors(ErrorResponse... }; } + /** + * Calculates a channels position. + * This method is needed as the ne provided by jda seams to only get the position based on the other channels of the same type. + * So for example getting the position of a text channel that is in a category bellow some text channels, but is the only text channel will return 1 + * despite the voice channels above it. This method solves this problem by doing the calculation manually. + * + * @param channel The channel to get an absolute position for. + * @return The position of the channel. + */ + public static int calcChannelPosition(GuildChannel channel) { + if (channel.getParent() != null) { + int parentPos = channel.getParent().getPosition(); + int pos = (int) channel.getGuild().getChannels().stream().filter(channel1 -> channel1.getParent() == null && !(channel instanceof Category)).count(); + List categories = channel.getGuild().getCategories(); + for (int i = 0; i < parentPos - 1; i++) { + pos += categories.get(i).getChannels().size(); + } + for (GuildChannel catChannel : channel.getParent().getChannels()) { + if (catChannel.getIdLong() == channel.getIdLong()) { + break; + } + pos++; + } + return pos; + } else { + int pos = 1; + List rootChannels = channel.getGuild().getChannels().stream().filter(channel1 -> channel1.getParent() == null).collect(Collectors.toList()); + for (GuildChannel rootChannel : rootChannels) { + if (rootChannel.getIdLong() == channel.getIdLong()) { + break; + } + pos++; + } + return pos; + } + } + } From d6e740c1ed035b2bd9b69325050b2cd29242be4a Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 3 Apr 2021 17:46:51 +0100 Subject: [PATCH 119/206] Organise imports Co-Authored-By: weeryan17 --- .../org/cascadebot/cascadebot/events/ModlogEventListener.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 4e6e3451e..71ff1ab6e 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -70,7 +70,6 @@ import net.dv8tion.jda.api.events.guild.update.GuildUpdateFeaturesEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateIconEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateMFALevelEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateMaxMembersEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateMaxPresencesEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateNameEvent; import net.dv8tion.jda.api.events.guild.update.GuildUpdateNotificationLevelEvent; @@ -101,7 +100,6 @@ import net.dv8tion.jda.api.events.user.update.UserUpdateDiscriminatorEvent; import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; -import net.dv8tion.jda.api.utils.MarkdownSanitizer; import org.apache.commons.lang3.StringUtils; import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.UnicodeConstants; @@ -117,6 +115,7 @@ import org.cascadebot.cascadebot.utils.Attachment; import org.cascadebot.cascadebot.utils.ColorUtils; import org.cascadebot.cascadebot.utils.CryptUtils; +import org.cascadebot.cascadebot.utils.DiscordUtils; import org.cascadebot.cascadebot.utils.ModlogUtils; import org.cascadebot.cascadebot.utils.SerializableMessage; import org.cascadebot.cascadebot.utils.lists.ChangeList; From aea60ccff0bbdd953c6593c6784277a6cc39a40f Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 3 Apr 2021 17:47:30 +0100 Subject: [PATCH 120/206] Use the new position calculations Co-Authored-By: weeryan17 --- .../org/cascadebot/cascadebot/events/ModlogEventListener.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 71ff1ab6e..ff4801123 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -909,7 +909,8 @@ private void channelMove(Guild guild, List channelMoveDataList) for (ChannelMoveData data : maxMoveData) { ModlogEmbedField field = new ModlogEmbedField(false, "modlog.channel.position.title", "modlog.general.small_change", - String.valueOf(data.oldPos), String.valueOf(data.channel.getPosition())); + DiscordUtils.calcChannelPosition(data.oldPos, data.channel.getType(), data.channel.getGuild()), + DiscordUtils.calcChannelPosition(data.channel)); field.addTitleObjects(data.channel.getName()); embedParts.add(field); } From 130b8fab1b8662a3286237ec34e970f2362c5c49 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 3 Apr 2021 17:47:51 +0100 Subject: [PATCH 121/206] Simpler channel position type calculation Co-Authored-By: weeryan17 --- .../cascadebot/utils/DiscordUtils.java | 62 ++++++++++--------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/utils/DiscordUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/DiscordUtils.java index bdc1d1c54..1f82efea5 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/DiscordUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/DiscordUtils.java @@ -7,7 +7,7 @@ import com.jagrosh.jdautilities.commons.utils.FinderUtil; import lombok.experimental.UtilityClass; -import net.dv8tion.jda.api.entities.Category; +import net.dv8tion.jda.api.entities.ChannelType; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.GuildChannel; import net.dv8tion.jda.api.entities.Member; @@ -203,45 +203,51 @@ public static Consumer handleExpectedErrors(ErrorResponse... throw (ErrorResponseException) error; } // This shouldn't happen but ¯\_(ツ)_/¯ - if (error instanceof RuntimeException) throw (RuntimeException) error; + if (error instanceof RuntimeException) { + throw (RuntimeException) error; + } }; } /** * Calculates a channels position. - * This method is needed as the ne provided by jda seams to only get the position based on the other channels of the same type. - * So for example getting the position of a text channel that is in a category bellow some text channels, but is the only text channel will return 1 - * despite the voice channels above it. This method solves this problem by doing the calculation manually. + * This method is needed as the information from the Discord API seams to only get the position based on the other channels of the same type. + * So for example getting the position of a voice channel that is in a category below some text channels, but is the only voice channel will return 1 + * despite the text channels above it. This method solves this problem by counting the number of channels preceding a specific position and type combination. * - * @param channel The channel to get an absolute position for. - * @return The position of the channel. + * @param channel The channel to get the position for. + * @return The position of the channel taking into account all other channels. */ public static int calcChannelPosition(GuildChannel channel) { - if (channel.getParent() != null) { - int parentPos = channel.getParent().getPosition(); - int pos = (int) channel.getGuild().getChannels().stream().filter(channel1 -> channel1.getParent() == null && !(channel instanceof Category)).count(); - List categories = channel.getGuild().getCategories(); - for (int i = 0; i < parentPos - 1; i++) { - pos += categories.get(i).getChannels().size(); - } - for (GuildChannel catChannel : channel.getParent().getChannels()) { - if (catChannel.getIdLong() == channel.getIdLong()) { - break; - } - pos++; - } - return pos; - } else { - int pos = 1; - List rootChannels = channel.getGuild().getChannels().stream().filter(channel1 -> channel1.getParent() == null).collect(Collectors.toList()); - for (GuildChannel rootChannel : rootChannels) { - if (rootChannel.getIdLong() == channel.getIdLong()) { + return calcChannelPosition(channel.getPosition(), channel.getType(), channel.getGuild()); + } + + /** + * Calculates a channels position. + * This method is needed as the information from the Discord API seams to only get the position based on the other channels of the same type. + * So for example getting the position of a voice channel that is in a category below some text channels, but is the only voice channel will return 1 + * despite the text channels above it. This method solves this problem by counting the number of channels preceding a specific position and type combination. + * + * @param position The channel position to get an absolute position for. + * @param type The type of channel to get the position of. + * @param guild The guild the calculation is being run for. + * @return The position of the channel taking into account all other channels. + */ + public static int calcChannelPosition(int position, ChannelType type, Guild guild) { + if (type.equals(ChannelType.CATEGORY)) { + return position + 1; + } + int i = 1; + for (GuildChannel channel : guild.getChannels()) { + if (channel.getType() != ChannelType.CATEGORY) { + if (channel.getPosition() != position || channel.getType() != type) { + i++; + } else { break; } - pos++; } - return pos; } + return i; } } From fd89d9b783d121bd01f6e52adbe97ec4eafc1c1a Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 17 Apr 2021 14:42:01 -0500 Subject: [PATCH 122/206] Channel override improvements --- pom.xml | 7 +- .../events/ModlogEventListener.java | 81 ++++++++++--------- .../cascadebot/utils/DiscordUtils.java | 2 +- .../cascadebot/moderation/ModlogEvent.kt | 7 +- src/main/resources/lang/en-GB.json | 11 +-- 5 files changed, 57 insertions(+), 51 deletions(-) diff --git a/pom.xml b/pom.xml index a55487427..1023447d2 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ DEV - 4.2.0_204 + 4.2.1_258 1.3.53 92a858d 1.3.72 @@ -152,6 +152,11 @@ jcenter-bintray https://jcenter.bintray.com + + dv8tion + m2-dv8tion + https://m2.dv8tion.net/releases + jitpack.io https://jitpack.io diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index ff4801123..97eb4a30b 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -9,6 +9,7 @@ import net.dv8tion.jda.api.entities.Emote; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.GuildChannel; +import net.dv8tion.jda.api.entities.IPermissionHolder; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Role; @@ -112,6 +113,7 @@ import org.cascadebot.cascadebot.moderation.ModlogEmbedField; import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; +import org.cascadebot.cascadebot.permissions.objects.PermissionHolder; import org.cascadebot.cascadebot.utils.Attachment; import org.cascadebot.cascadebot.utils.ColorUtils; import org.cascadebot.cascadebot.utils.CryptUtils; @@ -751,68 +753,71 @@ public void onGenericCategory(@NotNull GenericCategoryEvent event) { } public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { - ModlogEvent modlogEvent = ModlogEvent.CHANNEL_PERMISSIONS_UPDATED; Guild guild = event.getGuild(); GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); ModlogUtils.getAuditLogFromType(event.getGuild(), event.getChannel().getIdLong(), auditLogEntry -> { List embedFieldList = new ArrayList<>(); + ModlogEvent modlogEvent; User responsible = null; if (auditLogEntry != null) { responsible = auditLogEntry.getUser(); } else { CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } - String permissionsHolderName; - if (event.getPermissionHolder() instanceof User) { - permissionsHolderName = ((User) event.getPermissionHolder()).getName(); - } else if (event.getPermissionHolder() instanceof Role) { - permissionsHolderName = ((Role) event.getPermissionHolder()).getName(); - } else { - permissionsHolderName = ""; - } - String allowedPath; - String deniedPath; if (event instanceof PermissionOverrideCreateEvent) { - allowedPath = "modlog.channel.perm.added_allow"; - deniedPath = "modlog.channel.perm.added_deny"; + modlogEvent = ModlogEvent.DEBUG; } else if (event instanceof PermissionOverrideDeleteEvent) { - allowedPath = "modlog.channel.perm.removed_allow"; - deniedPath = "modlog.channel.perm.removed_deny"; + modlogEvent = ModlogEvent.DEBUG; } else if (event instanceof PermissionOverrideUpdateEvent) { - allowedPath = "modlog.channel.perm.update_allow"; - deniedPath = "modlog.channel.perm.update_deny"; - if (((PermissionOverrideUpdateEvent) event).getOldAllow().size() > 0) { - ModlogEmbedField oldAllowed = new ModlogEmbedField(false, "modlog.channel.perm.old_allow", null, - ((PermissionOverrideUpdateEvent) event).getOldAllow().stream().map(Permission::getName).collect(Collectors.joining("\n"))); - oldAllowed.addTitleObjects(permissionsHolderName); - embedFieldList.add(oldAllowed); + modlogEvent = ModlogEvent.CHANNEL_PERMISSIONS_UPDATED; + StringBuilder stringBuilder = new StringBuilder(); + for (Permission permission : ((PermissionOverrideUpdateEvent) event).getOldDeny()) { + String current = getCurrentPermissionStateForHolder(permission, event.getChannel(), event.getPermissionHolder()); + if (!current.equals("x")) { + stringBuilder.append("x > ").append(current).append(": ").append(permission.getName()).append('\n'); + } + } + for (Permission permission : ((PermissionOverrideUpdateEvent) event).getOldInherited()) { + String current = getCurrentPermissionStateForHolder(permission, event.getChannel(), event.getPermissionHolder()); + if (!current.equals("\\\\")) { + stringBuilder.append("\\ > ").append(current).append(": ").append(permission.getName()).append('\n'); + } } - if (((PermissionOverrideUpdateEvent) event).getOldDeny().size() > 0) { - ModlogEmbedField oldDenied = new ModlogEmbedField(false, "modlog.channel.perm.old_allow", null, - ((PermissionOverrideUpdateEvent) event).getOldDeny().stream().map(Permission::getName).collect(Collectors.joining("\n"))); - oldDenied.addTitleObjects(permissionsHolderName); - embedFieldList.add(oldDenied); + for (Permission permission : ((PermissionOverrideUpdateEvent) event).getOldAllow()) { + String current = getCurrentPermissionStateForHolder(permission, event.getChannel(), event.getPermissionHolder()); + if (!current.equals("+")) { + stringBuilder.append("+ > ").append(current).append(": ").append(permission.getName()).append('\n'); + } } + embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.perm.changed", "modlog.general.variable", stringBuilder.toString())); } else { return; } - if (event.getPermissionOverride().getAllowed().size() > 0) { - ModlogEmbedField allowed = new ModlogEmbedField(false, allowedPath, null, event.getPermissionOverride().getAllowed().stream().map(Permission::getName).collect(Collectors.joining("\n"))); - allowed.addTitleObjects(permissionsHolderName); - embedFieldList.add(allowed); - } - if (event.getPermissionOverride().getDenied().size() > 0) { - ModlogEmbedField denied = new ModlogEmbedField(false, deniedPath, null, event.getPermissionOverride().getDenied().stream().map(Permission::getName).collect(Collectors.joining("\n"))); - denied.addTitleObjects(permissionsHolderName); - embedFieldList.add(denied); - } - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + event.getChannelType().name().toLowerCase())); ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, event.getChannel(), embedFieldList); + String holderMention = ""; + if (event.getPermissionHolder() instanceof User) { + holderMention = ((User) event.getPermissionHolder()).getAsMention(); + } else if (event.getPermissionHolder() instanceof Role) { + holderMention = ((Role) event.getPermissionHolder()).getAsMention(); + } + modlogEventStore.setExtraDescriptionInfo(List.of(holderMention)); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventStore); }, ActionType.CHANNEL_OVERRIDE_UPDATE, ActionType.CHANNEL_UPDATE); } + private String getCurrentPermissionStateForHolder(Permission permission, GuildChannel channel, IPermissionHolder holder) { + if (channel.getPermissionOverride(holder).getAllowed().contains(permission)) { + return "+"; + } else if (channel.getPermissionOverride(holder).getInherit().contains(permission)) { + return "\\\\"; + } else if (channel.getPermissionOverride(holder).getDenied().contains(permission)) { + return "x"; + } else { + return "unknown"; + } + } + //endregion //region Channel handlers diff --git a/src/main/java/org/cascadebot/cascadebot/utils/DiscordUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/DiscordUtils.java index 1f82efea5..c3968283a 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/DiscordUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/DiscordUtils.java @@ -240,7 +240,7 @@ public static int calcChannelPosition(int position, ChannelType type, Guild guil int i = 1; for (GuildChannel channel : guild.getChannels()) { if (channel.getType() != ChannelType.CATEGORY) { - if (channel.getPosition() != position || channel.getType() != type) { + if (channel.getPosition() != position || channel.getType().getSortBucket() != type.getSortBucket()) { i++; } else { break; diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 945059bfc..3c566b762 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -118,7 +118,9 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: CASCADE_TAG_CREATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), CASCADE_TAG_DELETED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - CASCADE_TAG_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS); + CASCADE_TAG_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), + // Here temporarily for testing purposes + DEBUG (MessageType.DANGER, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.DEBUG); companion object { private val modlogCategoryMap: MutableMap> = EnumMap(Category::class.java) @@ -162,7 +164,8 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: CASCADE, CASCADE_PERMISSIONS, CASCADE_MODERATION, - CASCADE_CUSTOM_COMMANDS + CASCADE_CUSTOM_COMMANDS, + DEBUG } enum class ModlogDisplayType { diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 0a5334237..ee4a5cffc 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1723,7 +1723,7 @@ "channel_permissions_updated": { "select": "channel_permissions_updated", "display": "Channel permissions updated", - "description": "The channel {0} permissions where changed" + "description": "The permissions for {2} on channel {0} were changed" }, "channel_position_updated": { "select": "channel_position_updated", @@ -2501,14 +2501,7 @@ "unknown": "Unknown" }, "perm": { - "added_allow": "Added Allowed permission to {0}", - "removed_allow": "Removed Allowed permission from {0}", - "update_allow": "New Allowed permission for {0}", - "added_deny": "Added Denied permission to {0}", - "removed_deny": "Removed Denied permission from {0}", - "update_deny": "New Denied permission for {0}", - "old_allow": "Old Allowed permission for {0}", - "old_deny": "Old Denied permissions for {0}" + "changed": "Changed Permission Overrides" }, "position": { "title": "Channel {0} moved" From 34a48fa2d8a83f6a8f8ae2387ab37e285a3de7e2 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 22 May 2021 21:26:08 +0100 Subject: [PATCH 123/206] Move CollectionDiff into utility class --- .../events/ModlogEventListener.java | 36 +++---------------- .../cascadebot/utils/lists/CollectionDiff.kt | 26 ++++++++++++++ 2 files changed, 30 insertions(+), 32 deletions(-) create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 97eb4a30b..e3caea10f 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -121,6 +121,7 @@ import org.cascadebot.cascadebot.utils.ModlogUtils; import org.cascadebot.cascadebot.utils.SerializableMessage; import org.cascadebot.cascadebot.utils.lists.ChangeList; +import org.cascadebot.cascadebot.utils.lists.CollectionDiff; import org.cascadebot.shared.utils.ThreadPoolExecutorLogged; import org.jetbrains.annotations.NotNull; @@ -183,7 +184,7 @@ public void onGenericEmote(GenericEmoteEvent event) { List oldRoles = ((EmoteUpdateRolesEvent) event).getOldRoles(); List newRoles = ((EmoteUpdateRolesEvent) event).getNewRoles(); - ListChanges roleListChanges = new ListChanges<>(oldRoles, newRoles); + CollectionDiff roleListChanges = new CollectionDiff<>(oldRoles, newRoles); if (!roleListChanges.getAdded().isEmpty()) { ModlogEmbedField addedRolesEmbed = new ModlogEmbedField(false, "modlog.general.added_roles", null); @@ -471,7 +472,7 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.content_filter.new", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getNewLevel().name().toLowerCase())); modlogEvent = ModlogEvent.GUILD_UPDATE_EXPLICIT_FILTER; } else if (event instanceof GuildUpdateFeaturesEvent) { - ListChanges featuresChanged = new ListChanges<>(((GuildUpdateFeaturesEvent) event).getOldFeatures(), ((GuildUpdateFeaturesEvent) event).getNewFeatures()); + CollectionDiff featuresChanged = new CollectionDiff<>(((GuildUpdateFeaturesEvent) event).getOldFeatures(), ((GuildUpdateFeaturesEvent) event).getNewFeatures()); embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.add_feature", null, String.join("\n", featuresChanged.getAdded()))); embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.removed_feature", null, String.join("\n", featuresChanged.getRemoved()))); modlogEvent = ModlogEvent.GUILD_UPDATE_FEATURES; @@ -1032,7 +1033,7 @@ public void onGenericRole(GenericRoleEvent event) { EnumSet oldPermissions = ((RoleUpdatePermissionsEvent) event).getOldPermissions(); EnumSet newPermissions = ((RoleUpdatePermissionsEvent) event).getNewPermissions(); - ListChanges permissionListChanges = new ListChanges<>(oldPermissions, newPermissions); + CollectionDiff permissionListChanges = new CollectionDiff<>(oldPermissions, newPermissions); if (!permissionListChanges.getAdded().isEmpty()) { embedFieldList.add(new ModlogEmbedField(false, "modlog.role.added_perm", null, permissionListChanges.getAdded().stream().map(Permission::getName).collect(Collectors.joining("\n")))); } @@ -1077,33 +1078,4 @@ public void onUserUpdateDiscriminator(UserUpdateDiscriminatorEvent event) { } //endregion - //TODO move this to a util class - public static class ListChanges { - - private final List added = new ArrayList<>(); - private final List removed = new ArrayList<>(); - - public ListChanges(Collection originalList, Collection newList) { - for (T object : originalList) { - if (!newList.contains(object)) { - removed.add(object); - } - } - for (T object : newList) { - if (!originalList.contains(object)) { - added.add(object); - } - } - } - - public List getAdded() { - return added; - } - - public List getRemoved() { - return removed; - } - - } - } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt new file mode 100644 index 000000000..ff64f610d --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021 CascadeBot. All rights reserved. + * Licensed under the MIT license. + */ + +package org.cascadebot.cascadebot.utils.lists + +class CollectionDiff(originalList: Collection, newList: Collection) { + + val added: MutableList = ArrayList() + val removed: MutableList = ArrayList() + + init { + for (obj in originalList) { + if (!newList.contains(obj)) { + removed.add(obj) + } + } + for (obj in newList) { + if (!originalList.contains(obj)) { + added.add(obj) + } + } + } + +} \ No newline at end of file From 4518ae90ebed622af1fc6bc09a3bdea0e12e6256 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 22 May 2021 21:26:15 +0100 Subject: [PATCH 124/206] General cleanup --- .../events/ModlogEventListener.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index e3caea10f..be25b029f 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -12,6 +12,7 @@ import net.dv8tion.jda.api.entities.IPermissionHolder; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.PermissionOverride; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.TextChannel; import net.dv8tion.jda.api.entities.User; @@ -113,7 +114,6 @@ import org.cascadebot.cascadebot.moderation.ModlogEmbedField; import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; import org.cascadebot.cascadebot.moderation.ModlogEvent; -import org.cascadebot.cascadebot.permissions.objects.PermissionHolder; import org.cascadebot.cascadebot.utils.Attachment; import org.cascadebot.cascadebot.utils.ColorUtils; import org.cascadebot.cascadebot.utils.CryptUtils; @@ -135,7 +135,6 @@ import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.Collection; import java.util.EnumSet; import java.util.HashMap; import java.util.List; @@ -410,12 +409,8 @@ private SerializableMessage getMessageFromString(long id, String messageString) } try { message = CryptUtils.decryptString(Config.INS.getEncryptKey(), iv, messageBytes); - } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | ShortBufferException e) { - e.printStackTrace(); - // TODO log these - return null; - } catch (BadPaddingException e) { - e.printStackTrace(); + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | ShortBufferException | BadPaddingException e) { + CascadeBot.LOGGER.error("Unable to decrypt message!", e); return null; } } else { @@ -574,7 +569,7 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); ModlogUtils.getAuditLogFromType(event.getGuild(), event.getMember().getIdLong(), auditLogEntry -> { List embedFieldList = new ArrayList<>(); - List extraDescriptionInfo = List.of(); + List extraDescriptionInfo; ModlogEvent action; User responsible = null; if (event instanceof GuildVoiceDeafenEvent) { @@ -808,11 +803,16 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { } private String getCurrentPermissionStateForHolder(Permission permission, GuildChannel channel, IPermissionHolder holder) { - if (channel.getPermissionOverride(holder).getAllowed().contains(permission)) { + PermissionOverride permissionOverride = channel.getPermissionOverride(holder); + if (permissionOverride == null) { + return "unknown"; + } + + if (permissionOverride.getAllowed().contains(permission)) { return "+"; - } else if (channel.getPermissionOverride(holder).getInherit().contains(permission)) { + } else if (permissionOverride.getInherit().contains(permission)) { return "\\\\"; - } else if (channel.getPermissionOverride(holder).getDenied().contains(permission)) { + } else if (permissionOverride.getDenied().contains(permission)) { return "x"; } else { return "unknown"; @@ -927,7 +927,7 @@ private void channelMove(Guild guild, List channelMoveDataList) }, ActionType.CHANNEL_UPDATE); } - public class ChannelMoveData { + public static class ChannelMoveData { private final ChannelType type; private final int oldPos; @@ -953,7 +953,7 @@ public GuildChannel getChannel() { } - public class RoleModifyData { + public static class RoleModifyData { private final Member member; private final ChangeList changeList; From 57e85f3a48bf1c2ae76da2874450cdce51fbe6a7 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 22 May 2021 22:14:05 +0100 Subject: [PATCH 125/206] =?UTF-8?q?Improve=20collection=20diff=20algorithm?= =?UTF-8?q?=20to=20cope=20with=20dupes=20and=20add=20=E2=9C=A8unit=20tests?= =?UTF-8?q?=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cascadebot/utils/lists/CollectionDiff.kt | 40 ++++++-- .../cascadebot/utils/CollectionDiffTest.kt | 97 +++++++++++++++++++ 2 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 src/test/kotlin/org/cascadebot/cascadebot/utils/CollectionDiffTest.kt diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt index ff64f610d..ed9664811 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt @@ -7,20 +7,44 @@ package org.cascadebot.cascadebot.utils.lists class CollectionDiff(originalList: Collection, newList: Collection) { - val added: MutableList = ArrayList() - val removed: MutableList = ArrayList() + private val _added: MutableList = ArrayList() + + private val _removed: MutableList = ArrayList() + + val added + get() = _added.toList() + + val removed + get() = _removed.toList() init { - for (obj in originalList) { - if (!newList.contains(obj)) { - removed.add(obj) + val addedDiff = newList.toMutableList() + + for (item in originalList) { + val iter = addedDiff.iterator() + while (iter.hasNext()) { + if (iter.next()?.equals(item) == true) { + iter.remove() + break + } } } - for (obj in newList) { - if (!originalList.contains(obj)) { - added.add(obj) + + _added.addAll(addedDiff) + + val removedDiff = originalList.toMutableList() + + for (item in newList) { + val iter = removedDiff.iterator() + while (iter.hasNext()) { + if (iter.next()?.equals(item) == true) { + iter.remove() + break + } } } + + _removed.addAll(removedDiff) } } \ No newline at end of file diff --git a/src/test/kotlin/org/cascadebot/cascadebot/utils/CollectionDiffTest.kt b/src/test/kotlin/org/cascadebot/cascadebot/utils/CollectionDiffTest.kt new file mode 100644 index 000000000..f038ea1bb --- /dev/null +++ b/src/test/kotlin/org/cascadebot/cascadebot/utils/CollectionDiffTest.kt @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021 CascadeBot. All rights reserved. + * Licensed under the MIT license. + */ + +package org.cascadebot.cascadebot.utils + +import groovy.util.GroovyTestCase.assertEquals +import org.cascadebot.cascadebot.utils.lists.CollectionDiff +import org.junit.Assert.assertTrue +import org.junit.Test + +class CollectionDiffTest { + + @Test + fun `Test added item`() { + val original = listOf(1, 2, 3, 4) + val new = listOf(1, 2, 3, 4, 5) + + val collectionDiff = CollectionDiff(original, new) + + assertEquals(1, collectionDiff.added.size) + assertTrue(collectionDiff.added[0] == 5) + + assertEquals(0, collectionDiff.removed.size) + } + + @Test + fun `Test removed item`() { + val original = listOf(1, 2, 3, 4, 5) + val new = listOf(1, 2, 3, 4) + + val collectionDiff = CollectionDiff(original, new) + + assertEquals(1, collectionDiff.removed.size) + assertTrue(collectionDiff.removed[0] == 5) + + assertEquals(0, collectionDiff.added.size) + } + + @Test + fun `Test add item duplicate`() { + val original = listOf(1, 2, 3, 4) + val new = listOf(1, 2, 3, 4, 1) + + val collectionDiff = CollectionDiff(original, new) + + assertEquals(1, collectionDiff.added.size) + assertTrue(collectionDiff.added[0] == 1) + + assertEquals(0, collectionDiff.removed.size) + } + + @Test + fun `Test remove item duplicate`() { + val original = listOf(1, 2, 1, 3, 4) + val new = listOf(1, 2, 3, 4) + + val collectionDiff = CollectionDiff(original, new) + + assertEquals(1, collectionDiff.removed.size) + assertTrue(collectionDiff.removed[0] == 1) + + assertEquals(0, collectionDiff.added.size) + } + + @Test + fun `Test add and remove`() { + val original = listOf(1, 2, 3, 4) + val new = listOf(1, 2, 5, 3) + + + val collectionDiff = CollectionDiff(original, new) + + assertEquals(1, collectionDiff.removed.size) + assertTrue(collectionDiff.removed[0] == 4) + + assertEquals(1, collectionDiff.added.size) + assertTrue(collectionDiff.added[0] == 5) + } + + @Test + fun `Test add and remove duplicated`() { + val original = listOf(1, 2, 4, 5, 3, 4) + val new = listOf(1, 2, 5, 4, 3, 5) + + + val collectionDiff = CollectionDiff(original, new) + + assertEquals(1, collectionDiff.removed.size) + assertTrue(collectionDiff.removed[0] == 4) + + assertEquals(1, collectionDiff.added.size) + assertTrue(collectionDiff.added[0] == 5) + } + +} \ No newline at end of file From 89d902d8bf5f07b88785709371b2f3e6e0961a81 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 22 May 2021 22:32:03 +0100 Subject: [PATCH 126/206] Add separate message as per review --- .../cascadebot/cascadebot/events/ModlogEventListener.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index be25b029f..e3ff2c595 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -409,9 +409,13 @@ private SerializableMessage getMessageFromString(long id, String messageString) } try { message = CryptUtils.decryptString(Config.INS.getEncryptKey(), iv, messageBytes); - } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | ShortBufferException | BadPaddingException e) { + } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | ShortBufferException e) { CascadeBot.LOGGER.error("Unable to decrypt message!", e); return null; + } catch (BadPaddingException e) { + // TODO emails? notifications? + CascadeBot.LOGGER.error("Unabled to decrypt message due to padding error! **This most likely means the data has been messed with**", e); + return null; } } else { message = messageString; From 699082d7ef93cc7e00a4a59fd17bf0beb401db66 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 25 May 2021 17:51:51 +0100 Subject: [PATCH 127/206] Rename ModlogEventStore to ModlogEventData --- .../module/ModuleDisableSubCommand.java | 7 +- .../module/ModuleEnableSubCommand.java | 7 +- .../GroupPermissionAddSubCommand.java | 7 +- .../GroupPermissionCreateSubCommand.java | 4 +- .../GroupPermissionDeleteSubCommand.java | 4 +- .../GroupPermissionLinkRoleSubCommand.java | 7 +- .../GroupPermissionRemoveSubCommand.java | 7 +- .../GroupPermissionUnlinkRoleSubCommand.java | 4 +- .../UserPermissionAddSubCommand.java | 7 +- .../UserPermissionGroupSubCommand.java | 9 +-- .../UserPermissionRemoveSubCommand.java | 7 +- .../management/tag/TagCreateSubCommand.java | 4 +- .../management/tag/TagDeleteSubCommand.java | 5 +- .../management/tag/TagEditSubCommand.java | 4 +- .../commands/music/QueueSaveSubCommand.java | 4 +- .../cascadebot/events/CommandListener.java | 4 +- .../events/ModlogEventListener.java | 68 +++++++++---------- .../commands/management/SettingsCommand.kt | 8 +-- .../data/objects/GuildSettingsModeration.kt | 48 +++++++------ ...ModlogEventStore.kt => ModlogEventData.kt} | 2 +- .../cascadebot/utils/lists/CollectionDiff.kt | 4 +- 21 files changed, 97 insertions(+), 124 deletions(-) rename src/main/kotlin/org/cascadebot/cascadebot/data/objects/{ModlogEventStore.kt => ModlogEventData.kt} (95%) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java index 4f83aa1cb..b71ad1439 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java @@ -11,15 +11,12 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; -import org.cascadebot.cascadebot.moderation.ModlogEmbedField; -import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.ExtensionsKt; import org.cascadebot.cascadebot.utils.FormatUtils; -import java.util.ArrayList; import java.util.List; public class ModuleDisableSubCommand extends SubCommand { @@ -40,7 +37,7 @@ public void onCommand(Member sender, CommandContext context) { // If module wasn't already disabled context.getTypedMessaging().replySuccess(context.i18n("commands.module.disable.disabled", moduleName)); ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), module, List.of()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), module, List.of()); eventStore.setExtraDescriptionInfo(List.of("false")); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java index c0b241754..2ab30d2a8 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java @@ -11,15 +11,12 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; -import org.cascadebot.cascadebot.moderation.ModlogEmbedField; -import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.ExtensionsKt; import org.cascadebot.cascadebot.utils.FormatUtils; -import java.util.ArrayList; import java.util.List; public class ModuleEnableSubCommand extends SubCommand { @@ -40,7 +37,7 @@ public void onCommand(Member sender, CommandContext context) { // If the module wasn't enabled context.getTypedMessaging().replySuccess(context.i18n("commands.module.enable.enabled", moduleName)); ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), module, List.of()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), module, List.of()); eventStore.setExtraDescriptionInfo(List.of("true")); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java index c2cf9937e..45c52c115 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java @@ -9,14 +9,11 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; -import org.cascadebot.cascadebot.moderation.ModlogEmbedField; -import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; -import java.util.ArrayList; import java.util.List; public class GroupPermissionAddSubCommand extends SubCommand { @@ -36,7 +33,7 @@ public void onCommand(Member sender, CommandContext context) { if (group.addPermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.add.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, List.of()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, List.of()); eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java index b1db46b74..b94523b7f 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java @@ -9,7 +9,7 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.objects.Group; @@ -28,7 +28,7 @@ public void onCommand(Member sender, CommandContext context) { Group group = context.getData().getManagement().getPermissions().createGroup(context.getArg(0)); context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.create.success", context.getArg(0), group.getId())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_CREATED; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, new ArrayList<>()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, new ArrayList<>()); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java index d45c34981..a6fa68c99 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java @@ -4,7 +4,7 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; @@ -25,7 +25,7 @@ public void onCommand(Member sender, CommandContext context) { // If the group existed to delete and has been successfully deleted. context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.delete.success", group.getName(), group.getId())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_DELETED; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, new ArrayList<>()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, new ArrayList<>()); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { // Throwing an exception here because this *should* never happen diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java index 0c43681e7..054ea3a7f 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java @@ -10,15 +10,12 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; -import org.cascadebot.cascadebot.moderation.ModlogEmbedField; -import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.DiscordUtils; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; -import java.util.ArrayList; import java.util.List; public class GroupPermissionLinkRoleSubCommand extends SubCommand { @@ -40,7 +37,7 @@ public void onCommand(Member sender, CommandContext context) { if (group.linkRole(role.getIdLong())) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.link.success", group.getName(), role.getName())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_LINK; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, List.of()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, List.of()); eventStore.setExtraDescriptionInfo(List.of(role.getAsMention())); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java index 7da9ba903..1bd5868a3 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java @@ -9,14 +9,11 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; -import org.cascadebot.cascadebot.moderation.ModlogEmbedField; -import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; -import java.util.ArrayList; import java.util.List; public class GroupPermissionRemoveSubCommand extends SubCommand { @@ -37,7 +34,7 @@ public void onCommand(Member sender, CommandContext context) { if (group.removePermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.remove.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, List.of()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, List.of()); eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java index 39d10d1b1..a90a8d25f 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java @@ -10,7 +10,7 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.DiscordUtils; @@ -37,7 +37,7 @@ public void onCommand(Member sender, CommandContext context) { if (group.unlinkRole(role.getIdLong())) { context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.unlink.success", group.getName(), role.getName())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_UNLINK; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), group, List.of()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, List.of()); eventStore.setExtraDescriptionInfo(List.of(role.getAsMention())); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java index 7e0866f1e..06867afb9 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java @@ -9,15 +9,12 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; -import org.cascadebot.cascadebot.moderation.ModlogEmbedField; -import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.objects.User; import org.cascadebot.cascadebot.utils.DiscordUtils; -import java.util.ArrayList; import java.util.List; public class UserPermissionAddSubCommand extends SubCommand { @@ -45,7 +42,7 @@ public void onCommand(Member sender, CommandContext context) { if (user.addPermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.add.success", context.getArg(1), member.getUser().getAsTag())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_PERMISSION_ADD; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), List.of()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), member.getUser(), List.of()); eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java index 1bdf9d151..aff6a47d5 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java @@ -9,16 +9,13 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; -import org.cascadebot.cascadebot.moderation.ModlogEmbedField; -import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.objects.User; import org.cascadebot.cascadebot.utils.DiscordUtils; import org.cascadebot.cascadebot.utils.PermissionCommandUtils; -import java.util.ArrayList; import java.util.List; public class UserPermissionGroupSubCommand extends SubCommand { @@ -47,7 +44,7 @@ public void onCommand(Member sender, CommandContext context) { if (user.addGroup(group)) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.group.put.success", member.getUser().getAsTag(), group.getName())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_GROUP_ADD; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), List.of()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), member.getUser(), List.of()); eventStore.setExtraDescriptionInfo(List.of(group.getName() + " (" + group.getId() + ")")); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { @@ -57,7 +54,7 @@ public void onCommand(Member sender, CommandContext context) { if (user.removeGroup(group)) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.group.remove.success", member.getUser().getAsTag(), group.getName())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_GROUP_REMOVE; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), List.of()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), member.getUser(), List.of()); eventStore.setExtraDescriptionInfo(List.of(group.getName() + " (" + group.getId() + ")")); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java index 340635610..95fe25310 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java @@ -9,15 +9,12 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; -import org.cascadebot.cascadebot.moderation.ModlogEmbedField; -import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.objects.User; import org.cascadebot.cascadebot.utils.DiscordUtils; -import java.util.ArrayList; import java.util.List; public class UserPermissionRemoveSubCommand extends SubCommand { @@ -40,7 +37,7 @@ public void onCommand(Member sender, CommandContext context) { if (user.removePermission(context.getArg(1))) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.remove.success", context.getArg(1), member.getUser().getAsTag())); ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), member.getUser(), List.of()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), member.getUser(), List.of()); eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java index 971dffeaa..57d4fd82e 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java @@ -9,7 +9,7 @@ import net.dv8tion.jda.api.utils.MarkdownSanitizer; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.data.objects.Tag; import org.cascadebot.cascadebot.moderation.ModlogEmbedField; import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; @@ -50,7 +50,7 @@ public void onCommand(Member sender, CommandContext context) { ModlogEvent event = ModlogEvent.CASCADE_TAG_CREATED; List embedFieldList = new ArrayList<>(); embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.content", "modlog.general.variable", "```" + MarkdownSanitizer.sanitize(tag.getContent()) + "```")); - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), tag, embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java index 031adcdb0..19a367f40 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java @@ -8,13 +8,12 @@ import net.dv8tion.jda.api.entities.Member; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.data.objects.Tag; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; import java.util.ArrayList; -import java.util.List; public class TagDeleteSubCommand extends SubCommand { @@ -31,7 +30,7 @@ public void onCommand(Member sender, CommandContext context) { if (context.getData().getManagement().removeTag(tagName) && tag != null) { context.getTypedMessaging().replySuccess(context.i18n("commands.tag.delete.successfully_deleted_tag")); ModlogEvent event = ModlogEvent.CASCADE_TAG_DELETED; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, new ArrayList<>()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), tag, new ArrayList<>()); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } else { context.getTypedMessaging().replyDanger(context.i18n("commands.tag.delete.tag_doesnt_exist", tagName)); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java index 654f5e348..d9eaed894 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java @@ -9,7 +9,7 @@ import net.dv8tion.jda.api.utils.MarkdownSanitizer; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.data.objects.Tag; import org.cascadebot.cascadebot.moderation.ModlogEmbedField; import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; @@ -42,7 +42,7 @@ public void onCommand(Member sender, CommandContext context) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.old_content", "modlog.general.variable", "```" + MarkdownSanitizer.sanitize(oldContent) + "```")); embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.new_content", "modlog.general.variable", "```" + MarkdownSanitizer.sanitize(tag.getContent()) + "```")); - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), tag, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), tag, embedFieldList); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/music/QueueSaveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/music/QueueSaveSubCommand.java index 8c43b5c1a..f04110f62 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/music/QueueSaveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/music/QueueSaveSubCommand.java @@ -9,7 +9,7 @@ import org.apache.commons.lang3.EnumUtils; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.SubCommand; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.data.objects.PlaylistType; import org.cascadebot.cascadebot.messaging.MessageType; import org.cascadebot.cascadebot.moderation.ModlogEvent; @@ -74,7 +74,7 @@ public void onCommand(Member sender, CommandContext context) { case NEW: context.getTypedMessaging().replySuccess(context.i18n("commands.queue.save.saved_playlist", context.getArg(0), lambdaScope.name().toLowerCase())); ModlogEvent event = ModlogEvent.CASCADE_PLAYLIST_CREATED; - ModlogEventStore eventStore = new ModlogEventStore(event, sender.getUser(), result.getPlaylist(), new ArrayList<>()); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), result.getPlaylist(), new ArrayList<>()); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); break; } diff --git a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java index 9c7ce6cb7..bc9ff3e1e 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java @@ -24,7 +24,7 @@ import org.cascadebot.cascadebot.data.managers.GuildDataManager; import org.cascadebot.cascadebot.data.objects.CommandFilter; import org.cascadebot.cascadebot.data.objects.GuildData; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.data.objects.Tag; import org.cascadebot.cascadebot.messaging.MessageType; import org.cascadebot.cascadebot.messaging.Messaging; @@ -119,7 +119,7 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { if (modlogEvent != null && cmd != null) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new ModlogEmbedField(true, "modlog.command.command", "modlog.general.variable", "```" + message + "```")); - ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, event.getAuthor(),cmd, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(modlogEvent, event.getAuthor(),cmd, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); } } diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index e3ff2c595..3e7887e49 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -109,7 +109,7 @@ import org.cascadebot.cascadebot.data.language.Language; import org.cascadebot.cascadebot.data.managers.GuildDataManager; import org.cascadebot.cascadebot.data.objects.GuildData; -import org.cascadebot.cascadebot.data.objects.ModlogEventStore; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.moderation.ModlogEmbedDescription; import org.cascadebot.cascadebot.moderation.ModlogEmbedField; import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; @@ -200,7 +200,7 @@ public void onGenericEmote(GenericEmoteEvent event) { } else { return; } - ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, user, emote, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(modlogEvent, user, emote, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }, ActionType.EMOTE_CREATE, ActionType.EMOTE_DELETE, ActionType.EMOTE_UPDATE); } @@ -217,7 +217,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { embedFieldList.add(new ModlogEmbedDescription("modlog.member.joined", user.getAsMention())); } else if (event instanceof GuildMemberLeaveEvent) { if (auditLogEntry != null && auditLogEntry.getType().equals(ActionType.KICK)) { - ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.GUILD_MEMBER_LEFT, null, user, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(ModlogEvent.GUILD_MEMBER_LEFT, null, user, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); responsible = auditLogEntry.getUser(); @@ -265,7 +265,7 @@ public void onGenericGuildMember(GenericGuildMemberEvent event) { } else { return; } - ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(modlogEvent, responsible, user, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }, ActionType.KICK, ActionType.MEMBER_ROLE_UPDATE, ActionType.MEMBER_UPDATE); } @@ -289,7 +289,7 @@ public void onGuildBan(GuildBanEvent event) { } else { CascadeBot.LOGGER.warn("Modlog: Failed to find ban entry"); } - ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(modlogEvent, responsible, user, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }, ActionType.BAN); } @@ -306,7 +306,7 @@ public void onGuildUnban(GuildUnbanEvent event) { } else { CascadeBot.LOGGER.warn("Modlog: Failed to find unban entry"); } - ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, user, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(modlogEvent, responsible, user, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }, ActionType.UNBAN); } @@ -354,10 +354,10 @@ public void onGuildMessageDelete(@NotNull GuildMessageDeleteEvent event) { responsible = null; } if (message.getUserMentions().size() > 0 || message.getRoleMentions().size() > 0) { - ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.GUILD_MESSAGE_DELETED_MENTION, responsible, affected, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(ModlogEvent.GUILD_MESSAGE_DELETED_MENTION, responsible, affected, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); } - ModlogEventStore eventStore = new ModlogEventStore(ModlogEvent.GUILD_MESSAGE_DELETED, responsible, affected, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(ModlogEvent.GUILD_MESSAGE_DELETED, responsible, affected, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }, ActionType.MESSAGE_DELETE); } @@ -391,7 +391,7 @@ public void onGuildMessageUpdate(@NotNull GuildMessageUpdateEvent event) { embedFieldList.add(oldEmbedField); embedFieldList.add(newEmbedField); ModlogEvent modlogEvent = ModlogEvent.GUILD_MESSAGE_UPDATED; - ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, null, affected, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(modlogEvent, null, affected, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); } @@ -562,7 +562,7 @@ public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { } else { return; } - ModlogEventStore eventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(modlogEvent, responsible, affected, embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }, ActionType.GUILD_UPDATE); } @@ -624,7 +624,7 @@ public void onGenericGuildVoice(GenericGuildVoiceEvent event) { } else { return; } - ModlogEventStore eventStore = new ModlogEventStore(action, responsible, affected, embedFieldList); + ModlogEventData eventStore = new ModlogEventData(action, responsible, affected, embedFieldList); eventStore.setExtraDescriptionInfo(extraDescriptionInfo); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }, ActionType.MEMBER_VOICE_MOVE, ActionType.MEMBER_VOICE_KICK, ActionType.MEMBER_UPDATE); @@ -692,7 +692,7 @@ public void onGenericTextChannel(@NotNull GenericTextChannelEvent event) { } else { return; } - ModlogEventStore eventStore = new ModlogEventStore(trigger, responsible, event.getChannel(), embedFieldList); + ModlogEventData eventStore = new ModlogEventData(trigger, responsible, event.getChannel(), embedFieldList); eventStore.setExtraDescriptionInfo(descriptionParts); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }, ActionType.CHANNEL_UPDATE); @@ -735,7 +735,7 @@ public void onGenericVoiceChannel(@NotNull GenericVoiceChannelEvent event) { } else { return; } - ModlogEventStore eventStore = new ModlogEventStore(trigger, responsible, event.getChannel(), embedFieldList); + ModlogEventData eventStore = new ModlogEventData(trigger, responsible, event.getChannel(), embedFieldList); guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); }, ActionType.CHANNEL_UPDATE); } @@ -794,15 +794,15 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { } else { return; } - ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, event.getChannel(), embedFieldList); + ModlogEventData modlogEventData = new ModlogEventData(modlogEvent, responsible, event.getChannel(), embedFieldList); String holderMention = ""; if (event.getPermissionHolder() instanceof User) { holderMention = ((User) event.getPermissionHolder()).getAsMention(); } else if (event.getPermissionHolder() instanceof Role) { holderMention = ((Role) event.getPermissionHolder()).getAsMention(); } - modlogEventStore.setExtraDescriptionInfo(List.of(holderMention)); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventStore); + modlogEventData.setExtraDescriptionInfo(List.of(holderMention)); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventData); }, ActionType.CHANNEL_OVERRIDE_UPDATE, ActionType.CHANNEL_UPDATE); } @@ -838,9 +838,9 @@ private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChann CascadeBot.LOGGER.warn("Modlog: Failed to find channel create entry"); } embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); - modlogEventStore.setExtraDescriptionInfo(List.of(type.name().toLowerCase())); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); + ModlogEventData modlogEventData = new ModlogEventData(event, responsible, channel, embedFieldList); + modlogEventData.setExtraDescriptionInfo(List.of(type.name().toLowerCase())); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventData); }, ActionType.CHANNEL_CREATE); } @@ -856,9 +856,9 @@ private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChann CascadeBot.LOGGER.warn("Modlog: Failed to find channel delete entry"); } embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); - modlogEventStore.setExtraDescriptionInfo(List.of(type.name().toLowerCase())); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); + ModlogEventData modlogEventData = new ModlogEventData(event, responsible, channel, embedFieldList); + modlogEventData.setExtraDescriptionInfo(List.of(type.name().toLowerCase())); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventData); }, ActionType.CHANNEL_DELETE); } @@ -874,8 +874,8 @@ private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } embedFieldList.add(new ModlogEmbedField(true, "modlog.general.name", "modlog.general.small_change", oldName, channel.getName())); - ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); + ModlogEventData modlogEventData = new ModlogEventData(event, responsible, channel, embedFieldList); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventData); }, ActionType.CHANNEL_UPDATE); } @@ -925,7 +925,7 @@ private void channelMove(Guild guild, List channelMoveDataList) embedParts.add(field); } ModlogEvent event = maxMoveData.size() <= 1 ? ModlogEvent.CHANNEL_POSITION_UPDATED : ModlogEvent.MULTIPLE_CHANNEL_POSITION_UPDATED; - ModlogEventStore eventStore = new ModlogEventStore(event, responsible, maxMoveData.get(0).channel, embedParts); + ModlogEventData eventStore = new ModlogEventData(event, responsible, maxMoveData.get(0).channel, embedParts); guildData.getModeration().sendModlogEvent(guild.getIdLong(), eventStore); }, ActionType.CHANNEL_UPDATE); @@ -989,8 +989,8 @@ public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Categ CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); } embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.parent", "modlog.general.small_change", oldParent == null ? "None" : oldParent.getName(), newParent == null ? "None" : newParent.getName())); // TODO language string for none - ModlogEventStore modlogEventStore = new ModlogEventStore(event, responsible, channel, embedFieldList); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); + ModlogEventData modlogEventData = new ModlogEventData(event, responsible, channel, embedFieldList); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventData); }, ActionType.CHANNEL_UPDATE); } //endregion @@ -1054,9 +1054,9 @@ public void onGenericRole(GenericRoleEvent event) { } else { return; } - ModlogEventStore modlogEventStore = new ModlogEventStore(modlogEvent, responsible, affected, embedFieldList); - modlogEventStore.setExtraDescriptionInfo(descriptionStuff); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventStore); + ModlogEventData modlogEventData = new ModlogEventData(modlogEvent, responsible, affected, embedFieldList); + modlogEventData.setExtraDescriptionInfo(descriptionStuff); + guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventData); }, ActionType.ROLE_CREATE, ActionType.ROLE_DELETE, ActionType.ROLE_UPDATE); } @@ -1064,20 +1064,20 @@ public void onGenericRole(GenericRoleEvent event) { public void onUserUpdateName(UserUpdateNameEvent event) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new ModlogEmbedField(false, "modlog.general.name", "modlog.general.small_change", event.getOldName(), event.getNewName())); - ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_NAME_UPDATED, event.getUser(), event.getUser(), embedFieldList); + ModlogEventData modlogEventData = new ModlogEventData(ModlogEvent.USER_NAME_UPDATED, event.getUser(), event.getUser(), embedFieldList); for (Guild guild : CascadeBot.INS.getClient().getMutualGuilds(event.getUser())) { GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventData); } } public void onUserUpdateDiscriminator(UserUpdateDiscriminatorEvent event) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new ModlogEmbedField(false, "modlog.member.discrim", "modlog.general.small_change", event.getOldDiscriminator(), event.getNewDiscriminator())); - ModlogEventStore modlogEventStore = new ModlogEventStore(ModlogEvent.USER_DISCRIMINATOR_UPDATED, event.getUser(), event.getUser(), embedFieldList); + ModlogEventData modlogEventData = new ModlogEventData(ModlogEvent.USER_DISCRIMINATOR_UPDATED, event.getUser(), event.getUser(), embedFieldList); for (Guild guild : CascadeBot.INS.getClient().getMutualGuilds(event.getUser())) { GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventStore); + guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventData); } } //endregion diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt index f931e4944..4a347cc40 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/SettingsCommand.kt @@ -21,7 +21,7 @@ import org.cascadebot.cascadebot.data.objects.GuildSettingsManagement import org.cascadebot.cascadebot.data.objects.GuildSettingsModeration import org.cascadebot.cascadebot.data.objects.GuildSettingsMusic import org.cascadebot.cascadebot.data.objects.GuildSettingsUseful -import org.cascadebot.cascadebot.data.objects.ModlogEventStore +import org.cascadebot.cascadebot.data.objects.ModlogEventData import org.cascadebot.cascadebot.data.objects.Setting import org.cascadebot.cascadebot.data.objects.SettingsContainer import org.cascadebot.cascadebot.moderation.ModlogEmbedField @@ -158,9 +158,9 @@ class SettingsCommand : MainCommand() { } else { embedFields.add(ModlogEmbedField(true, "modlog.setting.value", "modlog.general.small_change", oldValue, value)) } - val modlogEventStore = ModlogEventStore(ModlogEvent.CASCADE_SETTINGS_UPDATED, sender.user, field, embedFields) - modlogEventStore.extraDescriptionInfo = mutableListOf(field.name) - context.data.moderation.sendModlogEvent(context.guild.idLong, modlogEventStore) + val modlogEventData = ModlogEventData(ModlogEvent.CASCADE_SETTINGS_UPDATED, sender.user, field, embedFields) + modlogEventData.extraDescriptionInfo = mutableListOf(field.name) + context.data.moderation.sendModlogEvent(context.guild.idLong, modlogEventData) } catch (e: IllegalAccessException) { context.typedMessaging.replyException(context.i18n("commands.settings.cannot_access"), e) } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 6a213f0e6..205180796 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -8,10 +8,8 @@ import club.minnced.discord.webhook.send.WebhookEmbed.EmbedTitle import club.minnced.discord.webhook.send.WebhookEmbedBuilder import club.minnced.discord.webhook.send.WebhookMessageBuilder import de.bild.codec.annotations.Transient -import net.dv8tion.jda.api.entities.Emote import net.dv8tion.jda.api.entities.Icon import net.dv8tion.jda.api.entities.TextChannel -import net.dv8tion.jda.api.entities.User import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.database.DebugLogCallback @@ -45,12 +43,12 @@ class GuildSettingsModeration { private val modlogEvents: MutableMap = HashMap() - fun sendModlogEvent(guildId: Long, modlogEventStore: ModlogEventStore) { - val eventsInfo: List = getEventInfoForEvent(modlogEventStore.trigger) + fun sendModlogEvent(guildId: Long, modlogEventData: ModlogEventData) { + val eventsInfo: List = getEventInfoForEvent(modlogEventData.trigger) for (eventInfo in eventsInfo) { - eventInfo.sendEvent(GuildDataManager.getGuildData(guildId), modlogEventStore); + eventInfo.sendEvent(GuildDataManager.getGuildData(guildId), modlogEventData); } - CascadeBot.INS.databaseManager.runAsyncTask { database -> database.getCollection("modlog", ChannelModlogEventsInfo.MongoModlogEventObject::class.java).insertOne(ChannelModlogEventsInfo.MongoModlogEventObject(guildId, modlogEventStore, "default" /* TODO change to actual time */), DebugLogCallback("Inserted Event")) } + CascadeBot.INS.databaseManager.runAsyncTask { database -> database.getCollection("modlog", ChannelModlogEventsInfo.MongoModlogEventObject::class.java).insertOne(ChannelModlogEventsInfo.MongoModlogEventObject(guildId, modlogEventData, "default" /* TODO change to actual time */), DebugLogCallback("Inserted Event")) } } private fun getEventInfoForEvent(event: ModlogEvent): List { @@ -160,34 +158,34 @@ class GuildSettingsModeration { buildWebhookClient() } - fun sendEvent(guildData: GuildData, modlogEventStore: ModlogEventStore) { + fun sendEvent(guildData: GuildData, modlogEventData: ModlogEventData) { val webhookEmbedBuilder = WebhookEmbedBuilder() - val path = "enums.modlogevent.${modlogEventStore.trigger.name.toLowerCase()}.description" + val path = "enums.modlogevent.${modlogEventData.trigger.name.toLowerCase()}.description" val element = Language.getLanguageOrDefault(guildData.locale).getElement(path) if (element.isPresent) { - val affected = when (modlogEventStore.trigger.affectedDisplayType) { - AffectedDisplayType.NAME -> modlogEventStore.affected.name - AffectedDisplayType.MENTION -> modlogEventStore.affected.mention - ?: modlogEventStore.affected.name + val affected = when (modlogEventData.trigger.affectedDisplayType) { + AffectedDisplayType.NAME -> modlogEventData.affected.name + AffectedDisplayType.MENTION -> modlogEventData.affected.mention + ?: modlogEventData.affected.name } webhookEmbedBuilder.setDescription( Language.i18n( guildData.locale, path, affected, - modlogEventStore.responsible?.asMention + modlogEventData.responsible?.asMention ?: Language.i18n(guildData.locale, "words.unknown").toCapitalized(), - *modlogEventStore.extraDescriptionInfo.toTypedArray() + *modlogEventData.extraDescriptionInfo.toTypedArray() ) ) } - webhookEmbedBuilder.setTitle(EmbedTitle(Language.i18n(guildData.locale, "enums.modlogevent." + modlogEventStore.trigger.name.toLowerCase() + ".display"), null)) - val affected: ModlogAffected = modlogEventStore.affected; + webhookEmbedBuilder.setTitle(EmbedTitle(Language.i18n(guildData.locale, "enums.modlogevent." + modlogEventData.trigger.name.toLowerCase() + ".display"), null)) + val affected: ModlogAffected = modlogEventData.affected; - when (modlogEventStore.trigger.displayType) { + when (modlogEventData.trigger.displayType) { ModlogEvent.ModlogDisplayType.AFFECTED_THUMBNAIL -> { webhookEmbedBuilder.setThumbnailUrl(affected.imageUrl) } @@ -209,15 +207,15 @@ class GuildSettingsModeration { } } - for (embedPart in modlogEventStore.extraInfo) { + for (embedPart in modlogEventData.extraInfo) { embedPart.build(guildData.locale, webhookEmbedBuilder) } - webhookEmbedBuilder.setColor(modlogEventStore.trigger.messageType.color.rgb) + webhookEmbedBuilder.setColor(modlogEventData.trigger.messageType.color.rgb) webhookEmbedBuilder.setTimestamp(Instant.now()) - if (modlogEventStore.responsible != null) { - val iconUrl = modlogEventStore.responsible.effectiveAvatarUrl + if (modlogEventData.responsible != null) { + val iconUrl = modlogEventData.responsible.effectiveAvatarUrl // TODO: by user - webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventStore.responsible.name + " (" + modlogEventStore.responsible.id + ")", iconUrl)) + webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventData.responsible.name + " (" + modlogEventData.responsible.id + ")", iconUrl)) } try { webhookClient?.send(WebhookMessageBuilder() @@ -234,16 +232,16 @@ class GuildSettingsModeration { class MongoModlogEventObject { private var guildId: Long = 0; - private var modlogEventStore: ModlogEventStore? = null + private var modlogEventData: ModlogEventData? = null private var createdDate: Date = Date() private var tier: String = "" private constructor() - constructor(guildId: Long, modlogEventStore: ModlogEventStore, tier: String) { + constructor(guildId: Long, modlogEventData: ModlogEventData, tier: String) { this.guildId = guildId - this.modlogEventStore = modlogEventStore + this.modlogEventData = modlogEventData this.tier = tier } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventData.kt similarity index 95% rename from src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt rename to src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventData.kt index 6f43196aa..9dbea300b 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventStore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventData.kt @@ -14,7 +14,7 @@ import org.cascadebot.cascadebot.permissions.objects.Group import java.lang.UnsupportedOperationException import java.lang.reflect.Field -class ModlogEventStore(val trigger: ModlogEvent, @Transient val responsible: User?, affected: Any, var extraInfo: MutableList) { +class ModlogEventData(val trigger: ModlogEvent, @Transient val responsible: User?, affected: Any, var extraInfo: MutableList) { val affected: ModlogAffected = when (affected) { is User -> { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt index ed9664811..7eab69b69 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt @@ -23,7 +23,7 @@ class CollectionDiff(originalList: Collection, newList: Collection) { for (item in originalList) { val iter = addedDiff.iterator() while (iter.hasNext()) { - if (iter.next()?.equals(item) == true) { + if (iter.next() == item) { iter.remove() break } @@ -37,7 +37,7 @@ class CollectionDiff(originalList: Collection, newList: Collection) { for (item in newList) { val iter = removedDiff.iterator() while (iter.hasNext()) { - if (iter.next()?.equals(item) == true) { + if (iter.next() == item) { iter.remove() break } From a284ba9d780a532612a8b67770a9e92058c1fd7b Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 25 May 2021 20:54:21 +0100 Subject: [PATCH 128/206] Format duration util - Name properly - Add days as a measure --- .../commands/music/SeekCommand.java | 2 +- .../moderation/ModerationManager.java | 2 +- .../cascadebot/utils/FormatUtils.java | 49 +++++++++++++++++-- .../commands/moderation/SlowmodeCommand.kt | 2 +- .../moderation/TempSlowmodeCommand.kt | 4 +- 5 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/music/SeekCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/music/SeekCommand.java index 56c5e20e6..c0c15af56 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/music/SeekCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/music/SeekCommand.java @@ -49,7 +49,7 @@ public void onCommand(Member sender, CommandContext context) { context.getMusicPlayer().seekTo(millis); // TODO: Binary make a method to format time using ICU - String formattedTime = FormatUtils.formatTime(millis, Locale.getDefaultLocale(), true); + String formattedTime = FormatUtils.formatDuration(millis, Locale.getDefaultLocale(), true); context.getTypedMessaging().replySuccess(context.i18n("commands.seek.success", formattedTime)); } diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java index 545c41394..d945923da 100644 --- a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java +++ b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java @@ -190,7 +190,7 @@ private void sendTempSuccess(CommandContext context, User target, Member submitt // TODO, Use kotlin string extensions when PR #232 is merged. builder.addField( context.i18n("words.duration"), - FormatUtils.formatTime(delay, context.getLocale(), true) + FormatUtils.formatDuration(delay, context.getLocale(), true, true) + " (" + context.i18n("words.until") + " " + FormatUtils.formatDateTime(OffsetDateTime.now().plus(delay, ChronoUnit.MILLIS), context.getLocale()) + ")", true ); diff --git a/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java index e1346892b..0e2f31bdf 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java @@ -261,14 +261,53 @@ private static Pair relativeUnitFromDuration(Duratio * @param isShort Whether to display in short form or not. * @return The formatted string */ - public static String formatTime(long millis, Locale locale, boolean isShort) { + public static String formatDuration(long millis, Locale locale, boolean isShort) { + return formatDuration(millis, locale, isShort, false); + } + + /** + * Formats a time string using the ICU library in the order hours, minutes and seconds. + * This only supports up to hours and down to seconds. If there are more than 24 hours, it will just be displayed as such and will not overflow. + *

+ * The short form is like so: 1h 12m 23s.
+ * The long form is like so: 1 hour, 12 minutes, 23 seconds. + *

+ * Both forms follow the relative locale's time formatting rules. + * + * @param millis The time to be formatted in milliseconds. + * @param locale The locale for the time to be formatted in. + * @param isShort Whether to display in short form or not. + * @param showDays + * @return The formatted string + */ + public static String formatDuration(long millis, Locale locale, boolean isShort, boolean showDays) { Checks.notNegative(millis, "time"); - long hours = TimeUnit.MILLISECONDS.toHours(millis); - long minutes = TimeUnit.MILLISECONDS.toMinutes(millis) - (hours * 60); - long seconds = TimeUnit.MILLISECONDS.toSeconds(millis) - (hours * 60 * 60) - (minutes * 60); + long days = TimeUnit.MILLISECONDS.toDays(millis); + long hours = TimeUnit.MILLISECONDS.toHours(millis) - (days * 24); + long minutes = TimeUnit.MILLISECONDS.toMinutes(millis) - (days * 24 * 60) - (hours * 60); + long seconds = TimeUnit.MILLISECONDS.toSeconds(millis) - (days * 24 * 60 * 60) - (hours * 60 * 60) - (minutes * 60); MeasureFormat format = MeasureFormat.getInstance(locale.getULocale(), (isShort ? MeasureFormat.FormatWidth.NARROW : MeasureFormat.FormatWidth.WIDE)); - return format.formatMeasures(new Measure(hours, MeasureUnit.HOUR), new Measure(minutes, MeasureUnit.MINUTE), new Measure(seconds, MeasureUnit.SECOND)); + + // If we don't want to show days, set hours to 0 + if (!showDays) { + hours += (days * 24); + return format.formatMeasures( + new Measure(hours, MeasureUnit.HOUR), + new Measure(minutes, MeasureUnit.MINUTE), + new Measure(seconds, MeasureUnit.SECOND) + ); + } else { + return format.formatMeasures( + new Measure(days, MeasureUnit.DAY), + new Measure(hours, MeasureUnit.HOUR), + new Measure(minutes, MeasureUnit.MINUTE), + new Measure(seconds, MeasureUnit.SECOND) + ); + } + + + } @Deprecated diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/SlowmodeCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/SlowmodeCommand.kt index e24dfb4bb..13044ac13 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/SlowmodeCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/SlowmodeCommand.kt @@ -52,7 +52,7 @@ class SlowmodeCommand : MainCommand() { } try { channel.manager.setSlowmode(duration.toInt() / 1000).queue { - val interval: String = FormatUtils.formatTime(duration, context.locale, true).replace("(0[hms])".toRegex(), "") + val interval: String = FormatUtils.formatDuration(duration, context.locale, true).replace("(0[hms])".toRegex(), "") context.typedMessaging.replySuccess(context.i18n("commands.slowmode.success", interval, channel.name)) } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/TempSlowmodeCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/TempSlowmodeCommand.kt index 4b592f2aa..6370a4035 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/TempSlowmodeCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/TempSlowmodeCommand.kt @@ -61,7 +61,7 @@ class TempSlowmodeCommand : MainCommand() { val oldSlowmode = channel.slowmode try { channel.manager.setSlowmode(longInterval.toInt() / 1000).queue { - val textInterval = FormatUtils.formatTime(longInterval, context.locale, true).replace("(0[hm])".toRegex(), "") + val textInterval = FormatUtils.formatDuration(longInterval, context.locale, true).replace("(0[hm])".toRegex(), "") ScheduledActionManager.registerScheduledAction(ScheduledAction( ActionType.UNSLOWMODE, ScheduledAction.SlowmodeActionData(channel.idLong, oldSlowmode), @@ -71,7 +71,7 @@ class TempSlowmodeCommand : MainCommand() { Instant.now(), longDuration )) - val textDuration = FormatUtils.formatTime(longDuration, context.locale, true).replace("(0[hm])".toRegex(), "") + + val textDuration = FormatUtils.formatDuration(longDuration, context.locale, true).replace("(0[hm])".toRegex(), "") + " (" + context.i18n("words.until") + " " + FormatUtils.formatDateTime(OffsetDateTime.now().plus(longDuration, ChronoUnit.SECONDS), context.locale) + ")" context.typedMessaging.replySuccess(context.i18n("commands.tempslowmode.success", textInterval, channel.name, textDuration)) } From c8e0d9bf2f6a4551e8c1686598424d4c079edb0d Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 25 May 2021 20:54:37 +0100 Subject: [PATCH 129/206] Moderation modlog stuff --- .../moderation/ModerationManager.java | 48 +++++++++++++++++++ .../cascadebot/moderation/ModlogEvent.kt | 10 ++-- src/main/resources/lang/en-GB.json | 14 ++++-- 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java index d945923da..fc91062f7 100644 --- a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java +++ b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java @@ -13,15 +13,19 @@ import org.apache.commons.lang3.StringUtils; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.data.managers.ScheduledActionManager; +import org.cascadebot.cascadebot.data.objects.ModlogEventData; import org.cascadebot.cascadebot.messaging.MessagingObjects; import org.cascadebot.cascadebot.scheduler.ActionType; import org.cascadebot.cascadebot.scheduler.ScheduledAction; import org.cascadebot.cascadebot.utils.ExtensionsKt; import org.cascadebot.cascadebot.utils.FormatUtils; +import java.time.Duration; import java.time.Instant; import java.time.OffsetDateTime; import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; public class ModerationManager { @@ -37,6 +41,13 @@ public void ban(CommandContext context, ModAction action, User target, Member su .ban(target, messagesToDelete, reason) .queue(success -> { sendSuccess(context, target, submitter, action, reason); + if (action == ModAction.SOFT_BAN) { + ModlogEventData eventData = new ModlogEventData(ModlogEvent.CASCADE_SOFT_BAN, + submitter.getUser(), + target, + List.of()); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventData); + } }, throwable -> FAILURE_CONSUMER.accept(context, throwable, target, action)); }, context, action, target); } @@ -66,6 +77,19 @@ public void tempBan(CommandContext context, User target, Member submitter, Strin delay )); sendTempSuccess(context, target, submitter, ModAction.TEMP_BAN, reason, delay); + + List embedParts = new ArrayList<>(); + + if (reason != null) { + embedParts.add(new ModlogEmbedField(false, "words.reason", "modlog.general.variable", reason)); + } + + ModlogEventData eventData = new ModlogEventData(ModlogEvent.CASCADE_TEMP_BAN, + submitter.getUser(), + target, + embedParts); + eventData.setExtraDescriptionInfo(List.of(FormatUtils.formatDuration(delay, context.getLocale(), true, true))); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventData); }); }, context, ModAction.TEMP_BAN, target); } @@ -73,6 +97,7 @@ public void tempBan(CommandContext context, User target, Member submitter, Strin public void softBan(CommandContext context, User target, Member submitter, String reason, int messagesToDelete) { if (runChecks(ModAction.SOFT_BAN, target, submitter, context)) { + // Modlog event is triggered from the ban method to ensure it's only triggered on success ban(context, ModAction.SOFT_BAN, target, submitter, reason, messagesToDelete); runWithCheckedExceptions(() -> { context.getGuild() @@ -106,6 +131,17 @@ public void mute(CommandContext context, Member target, Member submitter, String reason)) .queue(aVoid -> { sendSuccess(context, target.getUser(), submitter, ModAction.MUTE, reason); + List embedParts = new ArrayList<>(); + + if (reason != null) { + embedParts.add(new ModlogEmbedField(false, "words.reason", "modlog.general.variable", reason)); + } + + ModlogEventData eventData = new ModlogEventData(ModlogEvent.CASCADE_MUTE, + submitter.getUser(), + target.getUser(), + embedParts); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventData); }); }, context, ModAction.MUTE, target.getUser()); } @@ -132,6 +168,18 @@ public void tempMute(CommandContext context, Member target, Member submitter, St delay )); sendTempSuccess(context, target.getUser(), submitter, ModAction.TEMP_MUTE, reason, delay); + + List embedParts = new ArrayList<>(); + + if (reason != null) { + embedParts.add(new ModlogEmbedField(false, "words.reason", "modlog.general.variable", reason)); + } + + ModlogEventData eventData = new ModlogEventData(ModlogEvent.CASCADE_TEMP_MUTE, + submitter.getUser(), + target.getUser(), + embedParts); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventData); }); }, context, ModAction.TEMP_MUTE, target.getUser()); } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 3c566b762..cfb372e23 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -104,10 +104,12 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: CASCADE_PLAYLIST_CREATED (MessageType.INFO, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE), - CASCADE_TEMP_MUTE (MessageType.DANGER, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_TEMP_BAN (MessageType.DANGER, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_SOFT_BAN (MessageType.DANGER, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_PURGE (MessageType.DANGER, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_MUTE (MessageType.DANGER, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_UNMUTE (MessageType.DANGER, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_TEMP_MUTE (MessageType.DANGER, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_TEMP_BAN (MessageType.DANGER, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_SOFT_BAN (MessageType.DANGER, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_PURGE (MessageType.DANGER, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), CASCADE_WHITELIST (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), CASCADE_BLACKLIST (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index b2b5b9a74..11241a586 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1844,17 +1844,25 @@ "display": "Cascade playlist deleted", "description": "Playlist {0} was deleted" }, + "cascade_mute": { + "select": "cascade_mute", + "display": "Cascade mute", + "description": "{0} has been muted" + }, "cascade_temp_mute": { "select": "cascade_temp_mute", - "display": "Cascade temp mute" + "display": "Cascade temporary mute", + "description": "{0} has been temporarily muted for {2}" }, "cascade_temp_ban": { "select": "cascade_temp_ban", - "display": "Cascade temp ban" + "display": "Cascade temporary ban", + "description": "{0} has been temporarily banned for {2}" }, "cascade_soft_ban": { "select": "cascade_soft_ban", - "display": "Cascade soft ban" + "display": "Cascade soft ban", + "description": "{0} has been soft-banned" }, "cascade_purge": { "select": "cascade_purge", From 8cbbbe98162784db37312d28920a293fef3f787b Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 25 May 2021 21:14:33 +0100 Subject: [PATCH 130/206] More modlog mod stuff --- .../cascadebot/moderation/ModerationManager.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java index fc91062f7..c52eab642 100644 --- a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java +++ b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java @@ -42,10 +42,16 @@ public void ban(CommandContext context, ModAction action, User target, Member su .queue(success -> { sendSuccess(context, target, submitter, action, reason); if (action == ModAction.SOFT_BAN) { + List embedParts = new ArrayList<>(); + + if (reason != null) { + embedParts.add(new ModlogEmbedField(false, "words.reason", "modlog.general.variable", reason)); + } + ModlogEventData eventData = new ModlogEventData(ModlogEvent.CASCADE_SOFT_BAN, submitter.getUser(), target, - List.of()); + embedParts); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventData); } }, throwable -> FAILURE_CONSUMER.accept(context, throwable, target, action)); @@ -179,6 +185,7 @@ public void tempMute(CommandContext context, Member target, Member submitter, St submitter.getUser(), target.getUser(), embedParts); + eventData.setExtraDescriptionInfo(List.of(FormatUtils.formatDuration(delay, context.getLocale(), true, true))); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventData); }); }, context, ModAction.TEMP_MUTE, target.getUser()); From 54bf625dd132ff86dcf6ef66cb902c58424843aa Mon Sep 17 00:00:00 2001 From: William Oldham Date: Thu, 27 May 2021 12:17:01 +0100 Subject: [PATCH 131/206] Fix softban! --- .../commands/moderation/SoftBanCommand.java | 4 +++- .../moderation/ModerationManager.java | 20 +++++++------------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/SoftBanCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/SoftBanCommand.java index 0924c820b..8cf25fea1 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/SoftBanCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/SoftBanCommand.java @@ -12,6 +12,7 @@ import org.cascadebot.cascadebot.commandmeta.MainCommand; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.messaging.MessagingObjects; +import org.cascadebot.cascadebot.moderation.ModAction; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.DiscordUtils; @@ -36,8 +37,9 @@ public void onCommand(Member sender, CommandContext context) { reason = context.getMessage(1); } - CascadeBot.INS.getModerationManager().softBan( + CascadeBot.INS.getModerationManager().ban( context, + ModAction.SOFT_BAN, targetMember.getUser(), sender, reason, diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java index c52eab642..1eb125975 100644 --- a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java +++ b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java @@ -53,6 +53,13 @@ public void ban(CommandContext context, ModAction action, User target, Member su target, embedParts); context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventData); + + runWithCheckedExceptions(() -> { + context.getGuild() + .unban(target) + .reason("Softban: Unbanned user") + .queue(null, throwable -> FAILURE_CONSUMER.accept(context, throwable, target, ModAction.SOFT_BAN)); + }, context, ModAction.SOFT_BAN, target); } }, throwable -> FAILURE_CONSUMER.accept(context, throwable, target, action)); }, context, action, target); @@ -101,19 +108,6 @@ public void tempBan(CommandContext context, User target, Member submitter, Strin } } - public void softBan(CommandContext context, User target, Member submitter, String reason, int messagesToDelete) { - if (runChecks(ModAction.SOFT_BAN, target, submitter, context)) { - // Modlog event is triggered from the ban method to ensure it's only triggered on success - ban(context, ModAction.SOFT_BAN, target, submitter, reason, messagesToDelete); - runWithCheckedExceptions(() -> { - context.getGuild() - .unban(target) - .reason("Softban: Unbanned user") - .queue(null, throwable -> FAILURE_CONSUMER.accept(context, throwable, target, ModAction.SOFT_BAN)); - }, context, ModAction.SOFT_BAN, target); - } - } - public void kick(CommandContext context, Member target, Member submitter, String reason) { if (runChecks(ModAction.KICK, target.getUser(), submitter, context)) { runWithCheckedExceptions(() -> { From 943d1ccec4584a9bc109f214e0343679b825de1e Mon Sep 17 00:00:00 2001 From: William Oldham Date: Thu, 27 May 2021 12:41:23 +0100 Subject: [PATCH 132/206] Unmute modlog! --- .../moderation/ModerationManager.java | 3 ++- .../commands/moderation/UnMuteCommand.kt | 17 +++++++++++++---- src/main/resources/lang/en-GB.json | 6 ++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java index 1eb125975..d31404cd3 100644 --- a/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java +++ b/src/main/java/org/cascadebot/cascadebot/moderation/ModerationManager.java @@ -219,7 +219,8 @@ private void runWithCheckedExceptions(Runnable actionToRun, CommandContext conte } private void sendSuccess(CommandContext context, User target, Member submitter, ModAction action, String reason) { - EmbedBuilder builder = MessagingObjects.getStandardMessageEmbed(context.i18n("moderation_manager.success", target.getAsTag(), action.getVerb(context.getLocale())), submitter.getUser(), context.getLocale()); + String user = action.doesRequireMember() ? target.getAsMention() : target.getAsTag(); + EmbedBuilder builder = MessagingObjects.getStandardMessageEmbed(context.i18n("moderation_manager.success", user, action.getVerb(context.getLocale())), submitter.getUser(), context.getLocale()); if (!StringUtils.isBlank(reason)) { builder.addField(context.i18n("words.reason"), reason, false); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/UnMuteCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/UnMuteCommand.kt index a1a74fdbf..606b67084 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/UnMuteCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/moderation/UnMuteCommand.kt @@ -8,13 +8,13 @@ package org.cascadebot.cascadebot.commands.moderation import net.dv8tion.jda.api.Permission import net.dv8tion.jda.api.entities.Member import net.dv8tion.jda.api.exceptions.PermissionException -import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.commandmeta.CommandContext import org.cascadebot.cascadebot.commandmeta.MainCommand import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.managers.ScheduledActionManager +import org.cascadebot.cascadebot.data.objects.ModlogEventData import org.cascadebot.cascadebot.messaging.MessagingObjects -import org.cascadebot.cascadebot.moderation.ModerationManager +import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.permissions.CascadePermission import org.cascadebot.cascadebot.scheduler.ActionType import org.cascadebot.cascadebot.scheduler.ScheduledAction @@ -46,13 +46,22 @@ class UnMuteCommand : MainCommand() { } context.guild.removeRoleFromMember(targetMember, mutedRole) .reason(context.i18n("mod_actions.unmute.reason", targetMember.user.asTag, context.user.asTag)) - .queue(null) { + .queue({ + val eventData = ModlogEventData( + ModlogEvent.CASCADE_UNMUTE, + context.user, + targetMember.user, + mutableListOf() + ) + context.data.moderation.sendModlogEvent(context.guild.idLong, eventData) + context.typedMessaging.replySuccess(context.i18n("commands.unmute.success", targetMember.asMention)) + }, { if (it is PermissionException) { context.uiMessaging.sendBotDiscordPermError(it.permission) } else { context.typedMessaging.replyException("Couldn't unmute the user!", it) } - } + }) } else { context.typedMessaging.replyWarning(context.i18n("commands.unmute.not_muted", targetMember.asMention)) } diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 11241a586..07e54fc59 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -646,6 +646,7 @@ "unmute": { "command": "unmute", "description": "Unmutes a member of a guild.", + "success": "The user {0} has been unmuted!", "not_muted": "The user {0} is not muted!" }, "tempmute": { @@ -1849,6 +1850,11 @@ "display": "Cascade mute", "description": "{0} has been muted" }, + "cascade_unmute": { + "select": "cascade_unmute", + "display": "Cascade Unmute", + "description": "{0} has been unmuted" + }, "cascade_temp_mute": { "select": "cascade_temp_mute", "display": "Cascade temporary mute", From 89cda9c2fcada148ca2ca44d02ed1d3b481ab43b Mon Sep 17 00:00:00 2001 From: William Oldham Date: Thu, 27 May 2021 13:53:38 +0100 Subject: [PATCH 133/206] Purge modlog --- .../cascadebot/cascadebot/utils/PurgeUtils.kt | 49 ++++++++++++++++--- src/main/resources/lang/en-GB.json | 3 +- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/PurgeUtils.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/PurgeUtils.kt index 96c0f9629..1700f8af3 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/PurgeUtils.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/PurgeUtils.kt @@ -7,7 +7,11 @@ package org.cascadebot.cascadebot.utils import net.dv8tion.jda.api.entities.Message import org.cascadebot.cascadebot.commandmeta.CommandContext +import org.cascadebot.cascadebot.data.objects.ModlogEventData import org.cascadebot.cascadebot.data.objects.PurgeCriteria +import org.cascadebot.cascadebot.moderation.ModlogEmbedField +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart +import org.cascadebot.cascadebot.moderation.ModlogEvent import java.time.OffsetDateTime import java.util.regex.Pattern @@ -58,20 +62,51 @@ object PurgeUtils { return } + if (messageList.size == 1) { messageList - .first() - .delete() - .queue({ context.typedMessaging.replySuccess(context.i18n("commands.purge.successfully_done", messageList.size)) }) - { context.typedMessaging.replyException(context.i18n("responses.failed_to_run_command"), it) } + .first() + .delete() + .queue({ + context.typedMessaging.replySuccess( + context.i18n( + "commands.purge.successfully_done", + messageList.size + ) + ) + sendPurgeModlogEvent(context, messageList.size) + }) + { context.typedMessaging.replyException(context.i18n("responses.failed_to_run_command"), it) } } else { context.channel.deleteMessages(messageList) - .queue({ context.typedMessaging.replySuccess(context.i18n("commands.purge.successfully_done", messageList.size)) }) - { context.typedMessaging.replyException(context.i18n("responses.failed_to_run_command"), it) } + .queue({ + context.typedMessaging.replySuccess( + context.i18n( + "commands.purge.successfully_done", + messageList.size + ) + ) + sendPurgeModlogEvent(context, messageList.size) + }) + { context.typedMessaging.replyException(context.i18n("responses.failed_to_run_command"), it) } } } - private fun messageMatchesCriteria(criteria: PurgeCriteria, message: Message, argument: String?) : Boolean { + private fun sendPurgeModlogEvent( + context: CommandContext, + messageCount: Int + ) { + val eventData = ModlogEventData( + ModlogEvent.CASCADE_PURGE, + context.user, + context.channel, + mutableListOf() + ) + eventData.extraDescriptionInfo = mutableListOf(messageCount.toString()) + context.data.moderation.sendModlogEvent(context.guild.idLong, eventData) + } + + private fun messageMatchesCriteria(criteria: PurgeCriteria, message: Message, argument: String?): Boolean { return when (criteria) { PurgeCriteria.ATTACHMENT -> message.attachments.isNotEmpty() PurgeCriteria.BOT -> message.author.isBot diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 07e54fc59..32ddaa585 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1872,7 +1872,8 @@ }, "cascade_purge": { "select": "cascade_purge", - "display": "Cascade purge" + "display": "Cascade purge", + "description": "Purged {2} messages from {0}" }, "cascade_whitelist": { "select": "cascade_whitelist", From 3a541de142e7c0494208f130ac0891313aae5716 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Thu, 27 May 2021 21:55:12 +0100 Subject: [PATCH 134/206] Convert modlog utils to Kotlin --- .../cascadebot/utils/ModlogUtils.java | 47 ---------------- .../cascadebot/utils/ModlogUtils.kt | 53 +++++++++++++++++++ 2 files changed, 53 insertions(+), 47 deletions(-) delete mode 100644 src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/utils/ModlogUtils.kt diff --git a/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java deleted file mode 100644 index cba3c58fa..000000000 --- a/src/main/java/org/cascadebot/cascadebot/utils/ModlogUtils.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.cascadebot.cascadebot.utils; - -import net.dv8tion.jda.api.audit.ActionType; -import net.dv8tion.jda.api.audit.AuditLogEntry; -import net.dv8tion.jda.api.entities.Guild; - -import java.time.Duration; -import java.time.OffsetDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; - -public class ModlogUtils { - - public static void getAuditLogFromType(Guild guild, Consumer entryConsumer, ActionType... actionTypes) { - getAuditLogFromType(guild, -1, entryConsumer, actionTypes); - } - - public static void getAuditLogFromType(Guild guild, long targetId, Consumer entryConsumer, ActionType... actionTypes) { - List actionTypeList = Arrays.asList(actionTypes); - guild.retrieveAuditLogs().limit(5 /* Get last 5 entries in case something else happens in the 500 ms */) - .queueAfter(500, TimeUnit.MILLISECONDS, // Wait 500ms so we have a better chance of it being in the modlog - auditLogEntries -> { - var startTime = OffsetDateTime.now(); - for (AuditLogEntry entry : auditLogEntries) { - long millis = Duration.between(entry.getTimeCreated(), startTime).toMillis(); - if (!actionTypeList.contains(entry.getType())) { - continue; - } - if (millis > 5000L) { - continue; - } - if (targetId != -1) { - if (entry.getTargetIdLong() != targetId) { - continue; - } - } - entryConsumer.accept(entry); - return; - } - entryConsumer.accept(null); - }); - } - -} diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/ModlogUtils.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/ModlogUtils.kt new file mode 100644 index 000000000..e7013384a --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/ModlogUtils.kt @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021 CascadeBot. All rights reserved. + * Licensed under the MIT license. + */ + +package org.cascadebot.cascadebot.utils + +import net.dv8tion.jda.api.audit.ActionType +import net.dv8tion.jda.api.audit.AuditLogEntry +import net.dv8tion.jda.api.entities.Guild +import java.time.Duration +import java.time.OffsetDateTime +import java.util.concurrent.TimeUnit +import java.util.function.Consumer + +object ModlogUtils { + + @JvmStatic + fun getAuditLogFromType(guild: Guild, entryConsumer: Consumer, vararg actionTypes: ActionType) { + getAuditLogFromType(guild, -1, entryConsumer, *actionTypes) + } + + @JvmStatic + fun getAuditLogFromType( + guild: Guild, + targetId: Long, + entryConsumer: Consumer, + vararg actionTypes: ActionType + ) { + guild.retrieveAuditLogs().limit(5 /* Get last 5 entries in case something else happens in the 500 ms */) + .queueAfter(500, TimeUnit.MILLISECONDS) // Wait 500ms so we have a better chance of it being in the modlog + { auditLogEntries -> + val startTime = OffsetDateTime.now() + for (entry in auditLogEntries) { + val millis = Duration.between(entry.timeCreated, startTime).toMillis() + if (!actionTypes.contains(entry.type)) { + continue + } + if (millis > 5000L) { + continue + } + if (targetId != -1L) { + if (entry.targetIdLong != targetId) { + continue + } + } + entryConsumer.accept(entry) + return@queueAfter + } + entryConsumer.accept(null) + } + } +} From ed8a4eeb38ac25bb7d5192056a9dcbcc6b8b3883 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Thu, 27 May 2021 22:06:23 +0100 Subject: [PATCH 135/206] Remove redundant data class --- .../cascadebot/utils/LanguageEmbedField.kt | 45 ------------------- 1 file changed, 45 deletions(-) delete mode 100644 src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt deleted file mode 100644 index b139be1b6..000000000 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/LanguageEmbedField.kt +++ /dev/null @@ -1,45 +0,0 @@ -package org.cascadebot.cascadebot.utils - -import club.minnced.discord.webhook.send.WebhookEmbed -import org.cascadebot.cascadebot.UnicodeConstants -import org.cascadebot.cascadebot.data.language.Language -import org.cascadebot.cascadebot.data.language.Locale - -class LanguageEmbedField { - - var inline: Boolean = false - - var titleLanguagePath: String = "" - var titleLanguageObjects: MutableList = ArrayList() - - var valueLanguagePath: String = "" - var valueLanguageObjects: MutableList = ArrayList() - - constructor(inline: Boolean = true, - titleLanguagePath: String, - valueLanguagePath: String, vararg valueLanguageObjects: String) { - this.inline = inline; - this.titleLanguagePath = titleLanguagePath - this.valueLanguagePath = valueLanguagePath - this.valueLanguageObjects.addAll(valueLanguageObjects) - // TODO add checks for if language string exists - } - - constructor() - - fun addTitleObjects(vararg titleLanguageObjects: String) { - this.titleLanguageObjects.addAll(titleLanguageObjects) - // TODO add checks for if there is room for objects in language string - } - - fun addValueObjects(vararg valueLanguageObjects: String) { - this.valueLanguageObjects.addAll(valueLanguageObjects) - } - - fun getLocalizedEmbedField(locale: Locale): WebhookEmbed.EmbedField { - return WebhookEmbed.EmbedField(inline, - Language.i18n(locale, titleLanguagePath, *titleLanguageObjects.toTypedArray()), - Language.i18n(locale, valueLanguagePath, *valueLanguageObjects.toTypedArray())) - } - -} \ No newline at end of file From 4a7dd7b38f3cca2f6dc7ff2ba1e824252144f1ba Mon Sep 17 00:00:00 2001 From: William Oldham Date: Thu, 27 May 2021 22:11:30 +0100 Subject: [PATCH 136/206] ModlogEmbedPart: Add language path validity checks --- .../cascadebot/moderation/ModlogEmbedPart.kt | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt index 9e000cf86..9afd7f8c8 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt @@ -13,9 +13,16 @@ sealed class ModlogEmbedPart { class ModlogEmbedField(val inline: Boolean = true, val titleLanguagePath: String, - var valueLanguagePath: String? = null, vararg valueLanguageObjects: Any) : ModlogEmbedPart() { - - constructor() : this(true, "", "") + val valueLanguagePath: String? = null, vararg valueLanguageObjects: Any) : ModlogEmbedPart() { + + constructor() : this(true, "", "") { + if (titleLanguagePath.isNotBlank()) { + require(Language.defaultLanguage.getString(titleLanguagePath).isPresent) + } + if (valueLanguagePath != null && valueLanguagePath.isNotBlank()) { + require(Language.defaultLanguage.getString(valueLanguagePath).isPresent) + } + } val titleLanguageObjects: MutableList = mutableListOf() val valueLanguageObjects: MutableList = mutableListOf(*valueLanguageObjects) @@ -38,7 +45,11 @@ class ModlogEmbedField(val inline: Boolean = true, class ModlogEmbedDescription(val languagePath: String, vararg languageObjects: String) : ModlogEmbedPart() { - constructor() : this("") + constructor() : this("") { + if (languagePath.isNotBlank()) { + require(Language.defaultLanguage.getString(languagePath).isPresent) + } + } var languageObjects: MutableList = mutableListOf(*languageObjects) @@ -50,7 +61,11 @@ class ModlogEmbedDescription(val languagePath: String, vararg languageObjects: S class ModlogEmbedFooter(val languagePath: String, val icon: String? = null, vararg languageObjects: String) : ModlogEmbedPart() { - constructor() : this("", "") + constructor() : this("", "") { + if (languagePath.isNotBlank()) { + require(Language.defaultLanguage.getString(languagePath).isPresent) + } + } var languageObjects: MutableList = mutableListOf(*languageObjects) From d7089a3361940425326a7fb841f1c9c9f8693600 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Thu, 27 May 2021 22:11:42 +0100 Subject: [PATCH 137/206] Language: Add a quick way to get the default language file --- .../org/cascadebot/cascadebot/data/language/Language.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/language/Language.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/language/Language.kt index 84ca7d68f..26f8ee995 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/language/Language.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/language/Language.kt @@ -14,9 +14,11 @@ object Language { private val languages: MutableMap = EnumMap(Locale::class.java) + val defaultLanguage: JSONConfig by lazy { getLanguage(Locale.getDefaultLocale())!! } + init { try { - loadLanguage(Locale.ENGLISH_UK) + loadLanguage(Locale.getDefaultLocale()) } catch (e: Exception) { CascadeBot.LOGGER.error("Could not load language!", e) ShutdownHandler.exitWithError() From 0e743207cc87decd6f84b1f0c778870ca8f21003 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Fri, 28 May 2021 21:09:19 +0100 Subject: [PATCH 138/206] ModlogEvent: Rename debug to dummy and update comment --- .../org/cascadebot/cascadebot/moderation/ModlogEvent.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index cfb372e23..80ba08d4d 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -121,8 +121,8 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: CASCADE_TAG_CREATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), CASCADE_TAG_DELETED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), CASCADE_TAG_UPDATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), - // Here temporarily for testing purposes - DEBUG (MessageType.DANGER, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.DEBUG); + // Here in case a dummy value is required + DUMMY (MessageType.DANGER, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.DUMMY); companion object { private val modlogCategoryMap: MutableMap> = EnumMap(Category::class.java) @@ -167,7 +167,7 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: CASCADE_PERMISSIONS, CASCADE_MODERATION, CASCADE_CUSTOM_COMMANDS, - DEBUG + DUMMY } enum class ModlogDisplayType { From ebf9b9555837badc060b735b5d8af8b6c51b0dd0 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Fri, 28 May 2021 21:09:31 +0100 Subject: [PATCH 139/206] Don't find modlog event for restricted commands --- .../java/org/cascadebot/cascadebot/events/CommandListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java index bc9ff3e1e..6891a6ec6 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java @@ -116,7 +116,7 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { } finally { CascadeBot.clearCascadeMDC(); MainCommand cmd = CascadeBot.INS.getCommandManager().getCommand(trigger, guildData); - if (modlogEvent != null && cmd != null) { + if (modlogEvent != null && cmd != null && !(cmd instanceof RestrictedCommand)) { List embedFieldList = new ArrayList<>(); embedFieldList.add(new ModlogEmbedField(true, "modlog.command.command", "modlog.general.variable", "```" + message + "```")); ModlogEventData eventStore = new ModlogEventData(modlogEvent, event.getAuthor(),cmd, embedFieldList); From 713a856da8fbe7ea3064b84c41967ac0014f56e3 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Fri, 28 May 2021 21:09:40 +0100 Subject: [PATCH 140/206] Dummy modlog value --- .../org/cascadebot/cascadebot/events/ModlogEventListener.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java index 3e7887e49..d588d4139 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java @@ -766,9 +766,9 @@ public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { } if (event instanceof PermissionOverrideCreateEvent) { - modlogEvent = ModlogEvent.DEBUG; + modlogEvent = ModlogEvent.DUMMY; } else if (event instanceof PermissionOverrideDeleteEvent) { - modlogEvent = ModlogEvent.DEBUG; + modlogEvent = ModlogEvent.DUMMY; } else if (event instanceof PermissionOverrideUpdateEvent) { modlogEvent = ModlogEvent.CHANNEL_PERMISSIONS_UPDATED; StringBuilder stringBuilder = new StringBuilder(); From e268bfa448e422bcc223e36f56705bc43239e703 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Fri, 28 May 2021 21:51:18 +0100 Subject: [PATCH 141/206] Split modlog event listener and convert to Kotlin --- .../org/cascadebot/cascadebot/CascadeBot.java | 7 +- .../events/ModlogEventListener.java | 1085 ----------------- .../modlog/ChannelModlogEventListener.kt | 620 ++++++++++ .../events/modlog/GuildModlogEventListener.kt | 898 ++++++++++++++ .../events/modlog/RoleModlogEventListener.kt | 240 ++++ .../events/modlog/UserModlogEventListener.kt | 57 + 6 files changed, 1820 insertions(+), 1087 deletions(-) delete mode 100644 src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/events/modlog/ChannelModlogEventListener.kt create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/events/modlog/GuildModlogEventListener.kt create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/events/modlog/RoleModlogEventListener.kt create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/events/modlog/UserModlogEventListener.kt diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 54153969c..03b8bac2f 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -38,8 +38,11 @@ import org.cascadebot.cascadebot.events.GuildEvents; import org.cascadebot.cascadebot.events.JDAEventMetricsListener; import org.cascadebot.cascadebot.events.MessageEventListener; -import org.cascadebot.cascadebot.events.ModlogEventListener; import org.cascadebot.cascadebot.events.VoiceEventListener; +import org.cascadebot.cascadebot.events.modlog.ChannelModlogEventListener; +import org.cascadebot.cascadebot.events.modlog.GuildModlogEventListener; +import org.cascadebot.cascadebot.events.modlog.RoleModlogEventListener; +import org.cascadebot.cascadebot.events.modlog.UserModlogEventListener; import org.cascadebot.cascadebot.metrics.Metrics; import org.cascadebot.cascadebot.moderation.ModerationManager; import org.cascadebot.cascadebot.music.MusicHandler; @@ -206,7 +209,7 @@ private void init() { .addEventListeners(new ButtonEventListener()) .addEventListeners(new VoiceEventListener()) .addEventListeners(new JDAEventMetricsListener()) - .addEventListeners(new ModlogEventListener()) + .addEventListeners(new ChannelModlogEventListener(), new GuildModlogEventListener(), new RoleModlogEventListener(), new UserModlogEventListener()) .addEventListeners(eventWaiter) .setToken(Config.INS.getBotToken()) .setShardsTotal(-1) diff --git a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java b/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java deleted file mode 100644 index d588d4139..000000000 --- a/src/main/java/org/cascadebot/cascadebot/events/ModlogEventListener.java +++ /dev/null @@ -1,1085 +0,0 @@ -package org.cascadebot.cascadebot.events; - -import com.google.gson.JsonArray; -import com.google.gson.JsonParser; -import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.audit.ActionType; -import net.dv8tion.jda.api.entities.Category; -import net.dv8tion.jda.api.entities.ChannelType; -import net.dv8tion.jda.api.entities.Emote; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.GuildChannel; -import net.dv8tion.jda.api.entities.IPermissionHolder; -import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.PermissionOverride; -import net.dv8tion.jda.api.entities.Role; -import net.dv8tion.jda.api.entities.TextChannel; -import net.dv8tion.jda.api.entities.User; -import net.dv8tion.jda.api.entities.VoiceChannel; -import net.dv8tion.jda.api.events.channel.category.CategoryCreateEvent; -import net.dv8tion.jda.api.events.channel.category.CategoryDeleteEvent; -import net.dv8tion.jda.api.events.channel.category.GenericCategoryEvent; -import net.dv8tion.jda.api.events.channel.category.update.CategoryUpdateNameEvent; -import net.dv8tion.jda.api.events.channel.category.update.CategoryUpdatePositionEvent; -import net.dv8tion.jda.api.events.channel.store.GenericStoreChannelEvent; -import net.dv8tion.jda.api.events.channel.store.StoreChannelCreateEvent; -import net.dv8tion.jda.api.events.channel.store.StoreChannelDeleteEvent; -import net.dv8tion.jda.api.events.channel.store.update.StoreChannelUpdateNameEvent; -import net.dv8tion.jda.api.events.channel.store.update.StoreChannelUpdatePositionEvent; -import net.dv8tion.jda.api.events.channel.text.GenericTextChannelEvent; -import net.dv8tion.jda.api.events.channel.text.TextChannelCreateEvent; -import net.dv8tion.jda.api.events.channel.text.TextChannelDeleteEvent; -import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateNSFWEvent; -import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateNameEvent; -import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateParentEvent; -import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdatePositionEvent; -import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateSlowmodeEvent; -import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateTopicEvent; -import net.dv8tion.jda.api.events.channel.voice.GenericVoiceChannelEvent; -import net.dv8tion.jda.api.events.channel.voice.VoiceChannelCreateEvent; -import net.dv8tion.jda.api.events.channel.voice.VoiceChannelDeleteEvent; -import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateBitrateEvent; -import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateNameEvent; -import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateParentEvent; -import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdatePositionEvent; -import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateUserLimitEvent; -import net.dv8tion.jda.api.events.emote.EmoteAddedEvent; -import net.dv8tion.jda.api.events.emote.EmoteRemovedEvent; -import net.dv8tion.jda.api.events.emote.GenericEmoteEvent; -import net.dv8tion.jda.api.events.emote.update.EmoteUpdateNameEvent; -import net.dv8tion.jda.api.events.emote.update.EmoteUpdateRolesEvent; -import net.dv8tion.jda.api.events.guild.GuildBanEvent; -import net.dv8tion.jda.api.events.guild.GuildUnbanEvent; -import net.dv8tion.jda.api.events.guild.member.GenericGuildMemberEvent; -import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent; -import net.dv8tion.jda.api.events.guild.member.GuildMemberLeaveEvent; -import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleAddEvent; -import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent; -import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateNicknameEvent; -import net.dv8tion.jda.api.events.guild.override.GenericPermissionOverrideEvent; -import net.dv8tion.jda.api.events.guild.override.PermissionOverrideCreateEvent; -import net.dv8tion.jda.api.events.guild.override.PermissionOverrideDeleteEvent; -import net.dv8tion.jda.api.events.guild.override.PermissionOverrideUpdateEvent; -import net.dv8tion.jda.api.events.guild.update.GenericGuildUpdateEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateAfkChannelEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateAfkTimeoutEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateBannerEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostCountEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostTierEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateDescriptionEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateExplicitContentLevelEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateFeaturesEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateIconEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateMFALevelEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateMaxPresencesEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateNameEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateNotificationLevelEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateRegionEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateSplashEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateSystemChannelEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateVanityCodeEvent; -import net.dv8tion.jda.api.events.guild.update.GuildUpdateVerificationLevelEvent; -import net.dv8tion.jda.api.events.guild.voice.GenericGuildVoiceEvent; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceDeafenEvent; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceGuildDeafenEvent; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceGuildMuteEvent; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceMoveEvent; -import net.dv8tion.jda.api.events.guild.voice.GuildVoiceMuteEvent; -import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent; -import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent; -import net.dv8tion.jda.api.events.role.GenericRoleEvent; -import net.dv8tion.jda.api.events.role.RoleCreateEvent; -import net.dv8tion.jda.api.events.role.RoleDeleteEvent; -import net.dv8tion.jda.api.events.role.update.RoleUpdateColorEvent; -import net.dv8tion.jda.api.events.role.update.RoleUpdateHoistedEvent; -import net.dv8tion.jda.api.events.role.update.RoleUpdateMentionableEvent; -import net.dv8tion.jda.api.events.role.update.RoleUpdateNameEvent; -import net.dv8tion.jda.api.events.role.update.RoleUpdatePermissionsEvent; -import net.dv8tion.jda.api.events.role.update.RoleUpdatePositionEvent; -import net.dv8tion.jda.api.events.user.update.UserUpdateDiscriminatorEvent; -import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent; -import net.dv8tion.jda.api.hooks.ListenerAdapter; -import org.apache.commons.lang3.StringUtils; -import org.cascadebot.cascadebot.CascadeBot; -import org.cascadebot.cascadebot.UnicodeConstants; -import org.cascadebot.cascadebot.data.Config; -import org.cascadebot.cascadebot.data.language.Language; -import org.cascadebot.cascadebot.data.managers.GuildDataManager; -import org.cascadebot.cascadebot.data.objects.GuildData; -import org.cascadebot.cascadebot.data.objects.ModlogEventData; -import org.cascadebot.cascadebot.moderation.ModlogEmbedDescription; -import org.cascadebot.cascadebot.moderation.ModlogEmbedField; -import org.cascadebot.cascadebot.moderation.ModlogEmbedPart; -import org.cascadebot.cascadebot.moderation.ModlogEvent; -import org.cascadebot.cascadebot.utils.Attachment; -import org.cascadebot.cascadebot.utils.ColorUtils; -import org.cascadebot.cascadebot.utils.CryptUtils; -import org.cascadebot.cascadebot.utils.DiscordUtils; -import org.cascadebot.cascadebot.utils.ModlogUtils; -import org.cascadebot.cascadebot.utils.SerializableMessage; -import org.cascadebot.cascadebot.utils.lists.ChangeList; -import org.cascadebot.cascadebot.utils.lists.CollectionDiff; -import org.cascadebot.shared.utils.ThreadPoolExecutorLogged; -import org.jetbrains.annotations.NotNull; - -import javax.crypto.BadPaddingException; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; -import javax.crypto.ShortBufferException; -import java.awt.Color; -import java.nio.ByteBuffer; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; - -public class ModlogEventListener extends ListenerAdapter { - - private final Map> moveRunnableMap = new HashMap<>(); - private final Map> roleRunnableMap = new HashMap<>(); - - private static final AtomicInteger threadCounter = new AtomicInteger(0); - private final ExecutorService EVENT_COLLECTOR_POOL = ThreadPoolExecutorLogged.newCachedThreadPool((runnable) -> new Thread(runnable, "event-collector-" + threadCounter.getAndIncrement()), CascadeBot.LOGGER); - - public void onGenericEmote(GenericEmoteEvent event) { - GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); - Emote emote = event.getEmote(); - ModlogUtils.getAuditLogFromType(event.getGuild(), event.getEmote().getIdLong(), auditLogEntry -> { - User user = null; - if (auditLogEntry != null) { - user = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find emote audit log entry"); - } - List embedFieldList = new ArrayList<>(); - ModlogEvent modlogEvent; - if (event instanceof EmoteAddedEvent) { - modlogEvent = ModlogEvent.EMOTE_CREATED; - } else if (event instanceof EmoteRemovedEvent) { - modlogEvent = ModlogEvent.EMOTE_DELETED; - } else if (event instanceof EmoteUpdateNameEvent) { - modlogEvent = ModlogEvent.EMOTE_UPDATED_NAME; - - var oldName = new ModlogEmbedField(false, "modlog.general.old_name", null); - var newName = new ModlogEmbedField(false, "modlog.general.new_name", null); - - oldName.addValueObjects(((EmoteUpdateNameEvent) event).getOldName()); - newName.addValueObjects(((EmoteUpdateNameEvent) event).getNewName()); - - embedFieldList.add(oldName); - embedFieldList.add(newName); - } else if (event instanceof EmoteUpdateRolesEvent) { - modlogEvent = ModlogEvent.EMOTE_UPDATED_ROLES; - - List oldRoles = ((EmoteUpdateRolesEvent) event).getOldRoles(); - List newRoles = ((EmoteUpdateRolesEvent) event).getNewRoles(); - CollectionDiff roleListChanges = new CollectionDiff<>(oldRoles, newRoles); - - if (!roleListChanges.getAdded().isEmpty()) { - ModlogEmbedField addedRolesEmbed = new ModlogEmbedField(false, "modlog.general.added_roles", null); - addedRolesEmbed.addValueObjects(roleListChanges.getAdded().stream().map(role -> role.getName() + " (" + role.getId() + ")") - .collect(Collectors.joining("\n"))); - embedFieldList.add(addedRolesEmbed); - } - if (!roleListChanges.getRemoved().isEmpty()) { - ModlogEmbedField removedRolesEmbed = new ModlogEmbedField(false, "modlog.general.removed_roles", null); - removedRolesEmbed.addValueObjects(roleListChanges.getRemoved().stream().map(role -> role.getName() + " (" + role.getId() + ")") - .collect(Collectors.joining("\n"))); - embedFieldList.add(removedRolesEmbed); - } - } else { - return; - } - ModlogEventData eventStore = new ModlogEventData(modlogEvent, user, emote, embedFieldList); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }, ActionType.EMOTE_CREATE, ActionType.EMOTE_DELETE, ActionType.EMOTE_UPDATE); - } - - public void onGenericGuildMember(GenericGuildMemberEvent event) { - GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); - User user = event.getMember().getUser(); - ModlogUtils.getAuditLogFromType(event.getGuild(), event.getUser().getIdLong(), auditLogEntry -> { - List embedFieldList = new ArrayList<>(); - ModlogEvent modlogEvent; - User responsible = null; - if (event instanceof GuildMemberJoinEvent) { - modlogEvent = ModlogEvent.GUILD_MEMBER_JOINED; - embedFieldList.add(new ModlogEmbedDescription("modlog.member.joined", user.getAsMention())); - } else if (event instanceof GuildMemberLeaveEvent) { - if (auditLogEntry != null && auditLogEntry.getType().equals(ActionType.KICK)) { - ModlogEventData eventStore = new ModlogEventData(ModlogEvent.GUILD_MEMBER_LEFT, null, user, embedFieldList); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - - responsible = auditLogEntry.getUser(); - embedFieldList.add(new ModlogEmbedDescription("modlog.member.kicked", user.getAsMention())); - if (auditLogEntry.getReason() != null) { - ModlogEmbedField reasonEmbedField = new ModlogEmbedField(false, "modlog.general.reason", null); - reasonEmbedField.addValueObjects(auditLogEntry.getReason()); - embedFieldList.add(reasonEmbedField); - } - modlogEvent = ModlogEvent.GUILD_MEMBER_KICKED; - } else { - modlogEvent = ModlogEvent.GUILD_MEMBER_LEFT; - } - } else if (event instanceof GuildMemberRoleAddEvent) { - if (auditLogEntry != null && auditLogEntry.getTargetIdLong() == event.getMember().getIdLong()) { - responsible = auditLogEntry.getUser(); - } - modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_ADDED; - ModlogEmbedField addedRolesEmbedField = new ModlogEmbedField(false, "modlog.general.added_roles", null); - addedRolesEmbedField.addValueObjects(((GuildMemberRoleAddEvent) event).getRoles().stream().map(Role::getAsMention).collect(Collectors.joining("\n"))); - embedFieldList.add(addedRolesEmbedField); - } else if (event instanceof GuildMemberRoleRemoveEvent) { - if (auditLogEntry != null && auditLogEntry.getTargetIdLong() == event.getMember().getIdLong()) { - responsible = auditLogEntry.getUser(); - } - modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_REMOVED; - ModlogEmbedField removedRolesEmbedField = new ModlogEmbedField(false, "modlog.general.removed_roles", null); - removedRolesEmbedField.addValueObjects(((GuildMemberRoleRemoveEvent) event).getRoles().stream().map(Role::getAsMention).collect(Collectors.joining("\n"))); - embedFieldList.add(removedRolesEmbedField); - } else if (event instanceof GuildMemberUpdateNicknameEvent) { - if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_UPDATE) { - responsible = auditLogEntry.getUser(); - } - if (((GuildMemberUpdateNicknameEvent) event).getOldValue() != null) { - ModlogEmbedField oldNickEmbedField = new ModlogEmbedField(false, "modlog.member.old_nick", null); - oldNickEmbedField.addValueObjects(((GuildMemberUpdateNicknameEvent) event).getOldValue()); - embedFieldList.add(oldNickEmbedField); - } - if (((GuildMemberUpdateNicknameEvent) event).getNewValue() != null) { - ModlogEmbedField newNickEmbedField = new ModlogEmbedField(false, "modlog.member.new_nick", null); - newNickEmbedField.addValueObjects(((GuildMemberUpdateNicknameEvent) event).getNewValue()); - embedFieldList.add(newNickEmbedField); - } - modlogEvent = ModlogEvent.GUILD_MEMBER_NICKNAME_UPDATED; - } else { - return; - } - ModlogEventData eventStore = new ModlogEventData(modlogEvent, responsible, user, embedFieldList); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }, ActionType.KICK, ActionType.MEMBER_ROLE_UPDATE, ActionType.MEMBER_UPDATE); - } - - //region Ban events - public void onGuildBan(GuildBanEvent event) { - GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); - User user = event.getUser(); - ModlogUtils.getAuditLogFromType(event.getGuild(), event.getUser().getIdLong(), auditLogEntry -> { - List embedFieldList = new ArrayList<>(); - ModlogEvent modlogEvent = ModlogEvent.GUILD_USER_BANNED; - User responsible = null; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - embedFieldList.add(new ModlogEmbedDescription("modlog.member.banned", user.getAsMention())); - if (auditLogEntry.getReason() != null) { - ModlogEmbedField reasonEmbedField = new ModlogEmbedField(false, "modlog.general.reason", null); - reasonEmbedField.addValueObjects(auditLogEntry.getReason()); - embedFieldList.add(reasonEmbedField); - } - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find ban entry"); - } - ModlogEventData eventStore = new ModlogEventData(modlogEvent, responsible, user, embedFieldList); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }, ActionType.BAN); - } - - public void onGuildUnban(GuildUnbanEvent event) { - GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); - User user = event.getUser(); - ModlogUtils.getAuditLogFromType(event.getGuild(), event.getUser().getIdLong(), auditLogEntry -> { - List embedFieldList = new ArrayList<>(); - ModlogEvent modlogEvent = ModlogEvent.GUILD_USER_UNBANNED; - User responsible = null; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find unban entry"); - } - ModlogEventData eventStore = new ModlogEventData(modlogEvent, responsible, user, embedFieldList); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }, ActionType.UNBAN); - } - //endregion - - //region Message - // TODO - public void onGuildMessageDelete(@NotNull GuildMessageDeleteEvent event) { - if (CascadeBot.INS.getRedisClient() == null) { - return; - } - GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); - String messageID = event.getMessageId(); - String messageString = CascadeBot.INS.getRedisClient().get("message:" + messageID); - if (messageString == null) { - return; - } - CascadeBot.INS.getRedisClient().del("message:" + messageID); - SerializableMessage message = getMessageFromString(event.getMessageIdLong(), messageString); - if (message == null) { - return; - } - User affected = CascadeBot.INS.getClient().getUserById(message.getAuthorId()); - List embedFieldList = new ArrayList<>(); - ModlogEmbedField messageEmbedField = new ModlogEmbedField(false, "modlog.message.message", null); - messageEmbedField.addValueObjects(message.getContent()); - embedFieldList.add(messageEmbedField); - if (message.getAttachments().size() > 0) { - StringBuilder attachmentsBuilder = new StringBuilder(); - for (Attachment attachment : message.getAttachments()) { - attachmentsBuilder.append(attachment.getUrl()).append('\n'); - } - embedFieldList.add(new ModlogEmbedField(false, "modlog.message.attachments", null, attachmentsBuilder.toString())); - } - if (affected == null) { - return; - } - //TODO handle embeds/ect... - ModlogUtils.getAuditLogFromType(event.getGuild(), message.getAuthorId(), auditLogEntry -> { - User responsible; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find message delete entry"); - responsible = null; - } - if (message.getUserMentions().size() > 0 || message.getRoleMentions().size() > 0) { - ModlogEventData eventStore = new ModlogEventData(ModlogEvent.GUILD_MESSAGE_DELETED_MENTION, responsible, affected, embedFieldList); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - } - ModlogEventData eventStore = new ModlogEventData(ModlogEvent.GUILD_MESSAGE_DELETED, responsible, affected, embedFieldList); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }, ActionType.MESSAGE_DELETE); - } - - // TODO - public void onGuildMessageUpdate(@NotNull GuildMessageUpdateEvent event) { - if (CascadeBot.INS.getRedisClient() == null) { - return; - } - if (event.getAuthor().isBot()) { - return; - } - GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); - Message message = event.getMessage(); - String messageString = CascadeBot.INS.getRedisClient().get("message:" + message.getId()); - if (messageString == null) { - return; - } - CascadeBot.INS.getRedisClient().del("message:" + message.getId()); - SerializableMessage oldMessage = getMessageFromString(message.getIdLong(), messageString); - if (oldMessage == null) { - return; - } - User affected = message.getAuthor(); - List embedFieldList = new ArrayList<>(); - ModlogEmbedField oldEmbedField = new ModlogEmbedField(false, "modlog.message.old_message", null); - oldEmbedField.addValueObjects(oldMessage.getContent()); - ModlogEmbedField newEmbedField = new ModlogEmbedField(false, "modlog.message.new_message", null); - newEmbedField.addValueObjects(message.getContentRaw()); - // TODO handle embeds/ect... - embedFieldList.add(oldEmbedField); - embedFieldList.add(newEmbedField); - ModlogEvent modlogEvent = ModlogEvent.GUILD_MESSAGE_UPDATED; - ModlogEventData eventStore = new ModlogEventData(modlogEvent, null, affected, embedFieldList); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - } - - private SerializableMessage getMessageFromString(long id, String messageString) { - String message; - if (Config.INS.getEncryptKey() != null) { - byte[] messageId = ByteBuffer.allocate(Long.BYTES).putLong(id).array(); - byte[] iv = new byte[messageId.length * 2]; - System.arraycopy(messageId, 0, iv, 0, messageId.length); - System.arraycopy(messageId, 0, iv, messageId.length, messageId.length); - JsonArray bytesJsonArray = new JsonParser().parse(messageString).getAsJsonArray(); - byte[] messageBytes = new byte[bytesJsonArray.size()]; - for (int i = 0; i < bytesJsonArray.size(); i++) { - messageBytes[i] = bytesJsonArray.get(i).getAsByte(); - } - try { - message = CryptUtils.decryptString(Config.INS.getEncryptKey(), iv, messageBytes); - } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidAlgorithmParameterException | InvalidKeyException | IllegalBlockSizeException | ShortBufferException e) { - CascadeBot.LOGGER.error("Unable to decrypt message!", e); - return null; - } catch (BadPaddingException e) { - // TODO emails? notifications? - CascadeBot.LOGGER.error("Unabled to decrypt message due to padding error! **This most likely means the data has been messed with**", e); - return null; - } - } else { - message = messageString; - } - return CascadeBot.getGSON().fromJson(message, SerializableMessage.class); - } - //endregion - - public void onGenericGuildUpdate(GenericGuildUpdateEvent event) { - Guild affected = event.getEntity(); - GuildData guildData = GuildDataManager.getGuildData(affected.getIdLong()); - ModlogUtils.getAuditLogFromType(event.getGuild(), auditLogEntry -> { - List embedFieldList = new ArrayList<>(); - User responsible = null; - ModlogEvent modlogEvent; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find guild update entry"); - } - if (event instanceof GuildUpdateAfkChannelEvent) { - modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_CHANNEL; - - VoiceChannel oldChannel = ((GuildUpdateAfkChannelEvent) event).getOldAfkChannel(); - VoiceChannel newChannel = ((GuildUpdateAfkChannelEvent) event).getNewAfkChannel(); - - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_channel", null, oldChannel != null ? oldChannel.getName() + " (" + oldChannel.getId() + ")" : "-")); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_channel", null, newChannel != null ? newChannel.getName() + " (" + newChannel.getId() + ")" : "-")); - } else if (event instanceof GuildUpdateAfkTimeoutEvent) { - modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_TIMEOUT; - - String oldTimeout = Language.i18n(event.getGuild().getIdLong(), "modlog.guild.timeout_seconds", ((GuildUpdateAfkTimeoutEvent) event).getOldAfkTimeout().getSeconds()); - String newTimeout = Language.i18n(event.getGuild().getIdLong(), "modlog.guild.timeout_seconds", ((GuildUpdateAfkTimeoutEvent) event).getNewAfkTimeout().getSeconds()); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.timeout", "modlog.general.small_change", oldTimeout, newTimeout)); - } else if (event instanceof GuildUpdateBannerEvent) { - if (((GuildUpdateBannerEvent) event).getOldBannerUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", null, ((GuildUpdateBannerEvent) event).getOldBannerUrl())); - } - if (((GuildUpdateBannerEvent) event).getNewBannerUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_image", null, ((GuildUpdateBannerEvent) event).getNewBannerUrl())); - } - modlogEvent = ModlogEvent.GUILD_UPDATE_BANNER; - } else if (event instanceof GuildUpdateDescriptionEvent) { - if (((GuildUpdateDescriptionEvent) event).getOldDescription() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_description", null, ((GuildUpdateDescriptionEvent) event).getOldDescription())); - } - if (((GuildUpdateDescriptionEvent) event).getNewDescription() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_description", null, ((GuildUpdateDescriptionEvent) event).getNewDescription())); - } - modlogEvent = ModlogEvent.GUILD_UPDATE_DESCRIPTION; - } else if (event instanceof GuildUpdateExplicitContentLevelEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.content_filter.old", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getOldLevel().name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.content_filter.new", "modlog.guild.content_filter." + ((GuildUpdateExplicitContentLevelEvent) event).getNewLevel().name().toLowerCase())); - modlogEvent = ModlogEvent.GUILD_UPDATE_EXPLICIT_FILTER; - } else if (event instanceof GuildUpdateFeaturesEvent) { - CollectionDiff featuresChanged = new CollectionDiff<>(((GuildUpdateFeaturesEvent) event).getOldFeatures(), ((GuildUpdateFeaturesEvent) event).getNewFeatures()); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.add_feature", null, String.join("\n", featuresChanged.getAdded()))); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.removed_feature", null, String.join("\n", featuresChanged.getRemoved()))); - modlogEvent = ModlogEvent.GUILD_UPDATE_FEATURES; - } else if (event instanceof GuildUpdateIconEvent) { - String oldIconUrl = ((GuildUpdateIconEvent) event).getOldIconUrl(); - String newIconUrl = ((GuildUpdateIconEvent) event).getNewIconUrl(); - - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_image", null, oldIconUrl != null ? oldIconUrl : "-")); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_image", null, newIconUrl != null ? newIconUrl : "-")); - modlogEvent = ModlogEvent.GUILD_UPDATE_ICON; -// The max members -// } else if (event instanceof GuildUpdateMaxMembersEvent) { -// String oldMembers = String.valueOf(((GuildUpdateMaxMembersEvent) event).getOldMaxMembers()); -// String newMembers = String.valueOf(((GuildUpdateMaxMembersEvent) event).getNewMaxMembers()); -// -// embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.max_members", "modlog.general.small_change", oldMembers, newMembers)); -// modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_MEMBERS; - } else if (event instanceof GuildUpdateMaxPresencesEvent) { - String oldPresences = String.valueOf(((GuildUpdateMaxPresencesEvent) event).getOldMaxPresences()); - String newPresences = String.valueOf(((GuildUpdateMaxPresencesEvent) event).getNewMaxPresences()); - - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.max_presences", "modlog.general.small_change", oldPresences, newPresences)); - responsible = null; - modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_PRESENCES; - } else if (event instanceof GuildUpdateMFALevelEvent) { - String oldLevel = Language.i18n(event.getGuild().getIdLong(), "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getOldMFALevel().name().toLowerCase()); - String newLevel = Language.i18n(event.getGuild().getIdLong(), "modlog.guild.mfa." + ((GuildUpdateMFALevelEvent) event).getNewMFALevel().name().toLowerCase()); - - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.mfa.mfa_level", "modlog.general.small_change", oldLevel, newLevel)); - modlogEvent = ModlogEvent.GUILD_UPDATE_MFA_LEVEL; - } else if (event instanceof GuildUpdateNameEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.general.old_name", null, ((GuildUpdateNameEvent) event).getOldName())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.general.new_name", null, ((GuildUpdateNameEvent) event).getNewValue())); - modlogEvent = ModlogEvent.GUILD_UPDATE_NAME; - } else if (event instanceof GuildUpdateNotificationLevelEvent) { - String oldLevel = Language.i18n(event.getGuild().getIdLong(), "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getOldNotificationLevel().name().toLowerCase()); - String newLevel = Language.i18n(event.getGuild().getIdLong(), "modlog.guild.notification." + ((GuildUpdateNotificationLevelEvent) event).getNewNotificationLevel().name().toLowerCase()); - - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.notification.title", "modlog.general.small_change", oldLevel, newLevel)); - modlogEvent = ModlogEvent.GUILD_UPDATE_NOTIFICATION_LEVEL; - } else if (event instanceof GuildUpdateRegionEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_region", null, ((GuildUpdateRegionEvent) event).getOldRegion().getName())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_region", null, ((GuildUpdateRegionEvent) event).getNewRegion().getName())); - modlogEvent = ModlogEvent.GUILD_UPDATE_REGION; - } else if (event instanceof GuildUpdateSplashEvent) { - String oldSplashUrl = ((GuildUpdateSplashEvent) event).getOldSplashUrl(); - String newSplashUrl = ((GuildUpdateSplashEvent) event).getNewSplashUrl(); - - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_splash", null, oldSplashUrl != null ? oldSplashUrl : "-")); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_splash", null, newSplashUrl != null ? newSplashUrl : "-")); - modlogEvent = ModlogEvent.GUILD_UPDATE_SPLASH; - } else if (event instanceof GuildUpdateSystemChannelEvent) { - TextChannel oldSystemChannel = ((GuildUpdateSystemChannelEvent) event).getOldSystemChannel(); - TextChannel newSystemChannel = ((GuildUpdateSystemChannelEvent) event).getNewSystemChannel(); - - embedFieldList.add(new ModlogEmbedField(false, - "modlog.guild.sys_channel", - "modlog.general.small_change", - oldSystemChannel != null ? oldSystemChannel.getAsMention() : "-", - newSystemChannel != null ? newSystemChannel.getAsMention() : "-")); - modlogEvent = ModlogEvent.GUILD_UPDATE_SYSTEM_CHANNEL; - } else if (event instanceof GuildUpdateVanityCodeEvent) { - if (((GuildUpdateVanityCodeEvent) event).getOldVanityCode() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.vanity_code.old", null, ((GuildUpdateVanityCodeEvent) event).getOldVanityCode())); - } - if (((GuildUpdateVanityCodeEvent) event).getOldVanityUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.vanity_url.old", null, ((GuildUpdateVanityCodeEvent) event).getOldVanityUrl())); - } - if (((GuildUpdateVanityCodeEvent) event).getNewVanityCode() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.vanity_code.new", null, ((GuildUpdateVanityCodeEvent) event).getNewVanityCode())); - } - if (((GuildUpdateVanityCodeEvent) event).getNewVanityUrl() != null) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.vanity_url.new", null, ((GuildUpdateVanityCodeEvent) event).getNewVanityUrl())); - } - modlogEvent = ModlogEvent.GUILD_UPDATE_VANITY_CODE; - } else if (event instanceof GuildUpdateVerificationLevelEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getOldVerificationLevel().name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_verification", "utils.verification_level." + ((GuildUpdateVerificationLevelEvent) event).getNewVerificationLevel().name().toLowerCase())); - modlogEvent = ModlogEvent.GUILD_UPDATE_VERIFICATION_LEVEL; - } else if (event instanceof GuildUpdateBoostCountEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_boost_count", null, String.valueOf(event.getOldValue()))); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_boost_count", null, String.valueOf(event.getNewValue()))); - modlogEvent = ModlogEvent.GUILD_BOOST_COUNT_UPDATED; - } else if (event instanceof GuildUpdateBoostTierEvent) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.old_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getOldBoostTier().name().toLowerCase())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.new_boost_tier", "modlog.guild.boost_tier." + ((GuildUpdateBoostTierEvent) event).getNewBoostTier().name().toLowerCase())); - modlogEvent = ModlogEvent.GUILD_BOOST_TIER_UPDATED; - } else { - return; - } - ModlogEventData eventStore = new ModlogEventData(modlogEvent, responsible, affected, embedFieldList); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }, ActionType.GUILD_UPDATE); - } - - public void onGenericGuildVoice(GenericGuildVoiceEvent event) { - User affected = event.getMember().getUser(); - Guild guild = event.getGuild(); - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - ModlogUtils.getAuditLogFromType(event.getGuild(), event.getMember().getIdLong(), auditLogEntry -> { - List embedFieldList = new ArrayList<>(); - List extraDescriptionInfo; - ModlogEvent action; - User responsible = null; - if (event instanceof GuildVoiceDeafenEvent) { - boolean deafened = (((GuildVoiceDeafenEvent) event).isDeafened()); - Emote emote = deafened ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("self-deafened")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("undeafened")); - extraDescriptionInfo = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(deafened)); - action = ModlogEvent.VOICE_DEAFEN; - } else if (event instanceof GuildVoiceMuteEvent) { - boolean muted = (((GuildVoiceMuteEvent) event).isMuted()); - Emote emote = muted ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("self-muted")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("unmuted")); - extraDescriptionInfo = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(muted)); - action = ModlogEvent.VOICE_MUTE; - } else if (event instanceof GuildVoiceGuildDeafenEvent) { - if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_UPDATE) { - responsible = auditLogEntry.getUser(); - } - boolean guildDeafened = (((GuildVoiceGuildDeafenEvent) event).isGuildDeafened()); - Emote emote = guildDeafened ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("server-deafened")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("undeafened")); - extraDescriptionInfo = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(guildDeafened)); - action = ModlogEvent.VOICE_SERVER_DEAFEN; - } else if (event instanceof GuildVoiceGuildMuteEvent) { - if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_UPDATE) { - responsible = auditLogEntry.getUser(); - } - boolean guildMuted = (((GuildVoiceGuildMuteEvent) event).isGuildMuted()); - Emote emote = guildMuted ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("server-muted")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("unmuted")); - extraDescriptionInfo = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(guildMuted)); - action = ModlogEvent.VOICE_SERVER_MUTE; - } else if (event instanceof GuildVoiceJoinEvent) { - extraDescriptionInfo = List.of(((GuildVoiceJoinEvent) event).getChannelJoined().getName()); - action = ModlogEvent.VOICE_JOIN; - } else if (event instanceof GuildVoiceLeaveEvent) { - extraDescriptionInfo = List.of(((GuildVoiceLeaveEvent) event).getChannelLeft().getName()); - if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_VOICE_KICK) { - action = ModlogEvent.VOICE_DISCONNECT; - responsible = auditLogEntry.getUser(); - } else { - action = ModlogEvent.VOICE_LEAVE; - } - } else if (event instanceof GuildVoiceMoveEvent) { - extraDescriptionInfo = List.of(((GuildVoiceMoveEvent) event).getChannelLeft().getName(), ((GuildVoiceMoveEvent) event).getChannelJoined().getName()); - if (auditLogEntry != null && auditLogEntry.getType() == ActionType.MEMBER_VOICE_MOVE) { - action = ModlogEvent.VOICE_FORCE_MOVE; - responsible = auditLogEntry.getUser(); - } else { - action = ModlogEvent.VOICE_MOVE; - } - } else { - return; - } - ModlogEventData eventStore = new ModlogEventData(action, responsible, affected, embedFieldList); - eventStore.setExtraDescriptionInfo(extraDescriptionInfo); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }, ActionType.MEMBER_VOICE_MOVE, ActionType.MEMBER_VOICE_KICK, ActionType.MEMBER_UPDATE); - } - - //region Channels - public void onGenericStoreChannel(@NotNull GenericStoreChannelEvent event) { - if (event instanceof StoreChannelCreateEvent) { - handleChannelCreateEvents(event.getChannel().getGuild(), ChannelType.STORE, event.getChannel()); - } else if (event instanceof StoreChannelDeleteEvent) { - handleChannelDeleteEvents(event.getChannel().getGuild(), ChannelType.STORE, event.getChannel()); - } else if (event instanceof StoreChannelUpdateNameEvent) { - handleChannelUpdateNameEvents(event.getChannel().getGuild(), ChannelType.STORE, ((StoreChannelUpdateNameEvent) event).getOldName(), event.getChannel()); - } else if (event instanceof StoreChannelUpdatePositionEvent) { - handleChannelUpdatePositionEvents(event.getChannel().getGuild(), ChannelType.STORE, ((StoreChannelUpdatePositionEvent) event).getOldPosition(), event.getChannel()); - } - } - - public void onGenericTextChannel(@NotNull GenericTextChannelEvent event) { - if (event instanceof TextChannelCreateEvent) { - handleChannelCreateEvents(event.getGuild(), ChannelType.TEXT, event.getChannel()); - return; - } else if (event instanceof TextChannelDeleteEvent) { - handleChannelDeleteEvents(event.getGuild(), ChannelType.TEXT, event.getChannel()); - return; - } else if (event instanceof TextChannelUpdateNameEvent) { - handleChannelUpdateNameEvents(event.getGuild(), ChannelType.TEXT, ((TextChannelUpdateNameEvent) event).getOldName(), event.getChannel()); - return; - } else if (event instanceof TextChannelUpdatePositionEvent) { - handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.TEXT, ((TextChannelUpdatePositionEvent) event).getOldPosition(), event.getChannel()); - return; - } else if (event instanceof TextChannelUpdateParentEvent) { - handleChannelUpdateParentEvents(event.getGuild(), ChannelType.TEXT, ((TextChannelUpdateParentEvent) event).getOldParent(), ((TextChannelUpdateParentEvent) event).getNewParent(), event.getChannel()); - return; - } - GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); - ModlogUtils.getAuditLogFromType(event.getGuild(), event.getChannel().getIdLong(), auditLogEntry -> { - ModlogEvent trigger; - List embedFieldList = new ArrayList<>(); - List descriptionParts = new ArrayList<>(); - User responsible = null; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); - } - if (event instanceof TextChannelUpdateNSFWEvent) { - trigger = ModlogEvent.TEXT_CHANNEL_NSFW_UPDATED; - - Boolean newValue = ((TextChannelUpdateNSFWEvent) event).getNewValue(); - Emote emote = newValue != null && newValue ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("tick")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("cross")); - descriptionParts = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(newValue)); - } else if (event instanceof TextChannelUpdateSlowmodeEvent) { - trigger = ModlogEvent.TEXT_CHANNEL_SLOWMODE_UPDATED; - - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.slowmode", "modlog.general.small_change", ((TextChannelUpdateSlowmodeEvent) event).getOldSlowmode(), ((TextChannelUpdateSlowmodeEvent) event).getNewSlowmode())); - } else if (event instanceof TextChannelUpdateTopicEvent) { - trigger = ModlogEvent.TEXT_CHANNEL_TOPIC_UPDATED; - - String oldTopic = ((TextChannelUpdateTopicEvent) event).getOldTopic(); - String newTopic = ((TextChannelUpdateTopicEvent) event).getNewTopic(); - - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.old_topic", null, StringUtils.isBlank(oldTopic) ? "-" : oldTopic)); - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.new_topic", null, StringUtils.isBlank(newTopic) ? "-" : newTopic)); - } else { - return; - } - ModlogEventData eventStore = new ModlogEventData(trigger, responsible, event.getChannel(), embedFieldList); - eventStore.setExtraDescriptionInfo(descriptionParts); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }, ActionType.CHANNEL_UPDATE); - } - - public void onGenericVoiceChannel(@NotNull GenericVoiceChannelEvent event) { - if (event instanceof VoiceChannelCreateEvent) { - handleChannelCreateEvents(event.getGuild(), ChannelType.VOICE, event.getChannel()); - } else if (event instanceof VoiceChannelDeleteEvent) { - handleChannelDeleteEvents(event.getGuild(), ChannelType.VOICE, event.getChannel()); - } else if (event instanceof VoiceChannelUpdateNameEvent) { - handleChannelUpdateNameEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdateNameEvent) event).getOldName(), event.getChannel()); - } else if (event instanceof VoiceChannelUpdatePositionEvent) { - handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdatePositionEvent) event).getOldPosition(), event.getChannel()); - } else if (event instanceof VoiceChannelUpdateParentEvent) { - handleChannelUpdateParentEvents(event.getGuild(), ChannelType.VOICE, ((VoiceChannelUpdateParentEvent) event).getOldParent(), ((VoiceChannelUpdateParentEvent) event).getNewParent(), event.getChannel()); - } - GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); - ModlogUtils.getAuditLogFromType(event.getGuild(), event.getChannel().getIdLong(), auditLogEntry -> { - ModlogEvent trigger; - List embedFieldList = new ArrayList<>(); - User responsible = null; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); - } - if (event instanceof VoiceChannelUpdateBitrateEvent) { - String oldBitrate = Language.i18n(event.getGuild().getIdLong(), "modlog.channel.kbps", ((VoiceChannelUpdateBitrateEvent) event).getOldBitrate() / 1000); - String newBitrate = Language.i18n(event.getGuild().getIdLong(), "modlog.channel.kbps", ((VoiceChannelUpdateBitrateEvent) event).getNewBitrate() / 1000); - - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.bitrate", "modlog.general.small_change", oldBitrate, newBitrate)); - trigger = ModlogEvent.VOICE_CHANNEL_BITRATE_UPDATED; - } else if (event instanceof VoiceChannelUpdateUserLimitEvent) { - var limitEvent = (VoiceChannelUpdateUserLimitEvent) event; - String oldLimit = limitEvent.getOldUserLimit() == 0 ? UnicodeConstants.INFINITY_SYMBOL : String.valueOf(limitEvent.getOldUserLimit()); - String newLimit = limitEvent.getNewUserLimit() == 0 ? UnicodeConstants.INFINITY_SYMBOL : String.valueOf(limitEvent.getNewUserLimit()); - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.users", "modlog.general.small_change", oldLimit, newLimit)); - trigger = ModlogEvent.VOICE_CHANNEL_USER_LIMIT_UPDATED; - } else { - return; - } - ModlogEventData eventStore = new ModlogEventData(trigger, responsible, event.getChannel(), embedFieldList); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), eventStore); - }, ActionType.CHANNEL_UPDATE); - } - - public void onGenericCategory(@NotNull GenericCategoryEvent event) { - if (event instanceof CategoryCreateEvent) { - handleChannelCreateEvents(event.getGuild(), ChannelType.CATEGORY, event.getCategory()); - } else if (event instanceof CategoryDeleteEvent) { - handleChannelDeleteEvents(event.getGuild(), ChannelType.CATEGORY, event.getCategory()); - } else if (event instanceof CategoryUpdateNameEvent) { - handleChannelUpdateNameEvents(event.getGuild(), ChannelType.CATEGORY, ((CategoryUpdateNameEvent) event).getOldName(), event.getCategory()); - } else if (event instanceof CategoryUpdatePositionEvent) { - handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.CATEGORY, ((CategoryUpdatePositionEvent) event).getOldPosition(), event.getCategory()); - } - } - - public void onGenericPermissionOverride(GenericPermissionOverrideEvent event) { - Guild guild = event.getGuild(); - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - ModlogUtils.getAuditLogFromType(event.getGuild(), event.getChannel().getIdLong(), auditLogEntry -> { - List embedFieldList = new ArrayList<>(); - ModlogEvent modlogEvent; - User responsible = null; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); - } - - if (event instanceof PermissionOverrideCreateEvent) { - modlogEvent = ModlogEvent.DUMMY; - } else if (event instanceof PermissionOverrideDeleteEvent) { - modlogEvent = ModlogEvent.DUMMY; - } else if (event instanceof PermissionOverrideUpdateEvent) { - modlogEvent = ModlogEvent.CHANNEL_PERMISSIONS_UPDATED; - StringBuilder stringBuilder = new StringBuilder(); - for (Permission permission : ((PermissionOverrideUpdateEvent) event).getOldDeny()) { - String current = getCurrentPermissionStateForHolder(permission, event.getChannel(), event.getPermissionHolder()); - if (!current.equals("x")) { - stringBuilder.append("x > ").append(current).append(": ").append(permission.getName()).append('\n'); - } - } - for (Permission permission : ((PermissionOverrideUpdateEvent) event).getOldInherited()) { - String current = getCurrentPermissionStateForHolder(permission, event.getChannel(), event.getPermissionHolder()); - if (!current.equals("\\\\")) { - stringBuilder.append("\\ > ").append(current).append(": ").append(permission.getName()).append('\n'); - } - } - for (Permission permission : ((PermissionOverrideUpdateEvent) event).getOldAllow()) { - String current = getCurrentPermissionStateForHolder(permission, event.getChannel(), event.getPermissionHolder()); - if (!current.equals("+")) { - stringBuilder.append("+ > ").append(current).append(": ").append(permission.getName()).append('\n'); - } - } - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.perm.changed", "modlog.general.variable", stringBuilder.toString())); - } else { - return; - } - ModlogEventData modlogEventData = new ModlogEventData(modlogEvent, responsible, event.getChannel(), embedFieldList); - String holderMention = ""; - if (event.getPermissionHolder() instanceof User) { - holderMention = ((User) event.getPermissionHolder()).getAsMention(); - } else if (event.getPermissionHolder() instanceof Role) { - holderMention = ((Role) event.getPermissionHolder()).getAsMention(); - } - modlogEventData.setExtraDescriptionInfo(List.of(holderMention)); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventData); - }, ActionType.CHANNEL_OVERRIDE_UPDATE, ActionType.CHANNEL_UPDATE); - } - - private String getCurrentPermissionStateForHolder(Permission permission, GuildChannel channel, IPermissionHolder holder) { - PermissionOverride permissionOverride = channel.getPermissionOverride(holder); - if (permissionOverride == null) { - return "unknown"; - } - - if (permissionOverride.getAllowed().contains(permission)) { - return "+"; - } else if (permissionOverride.getInherit().contains(permission)) { - return "\\\\"; - } else if (permissionOverride.getDenied().contains(permission)) { - return "x"; - } else { - return "unknown"; - } - } - - //endregion - - //region Channel handlers - private void handleChannelCreateEvents(Guild guild, ChannelType type, GuildChannel channel) { - ModlogEvent event = ModlogEvent.CHANNEL_CREATED; - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - ModlogUtils.getAuditLogFromType(guild, channel.getIdLong(), auditLogEntry -> { - List embedFieldList = new ArrayList<>(); - User responsible = null; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find channel create entry"); - } - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - ModlogEventData modlogEventData = new ModlogEventData(event, responsible, channel, embedFieldList); - modlogEventData.setExtraDescriptionInfo(List.of(type.name().toLowerCase())); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventData); - }, ActionType.CHANNEL_CREATE); - } - - private void handleChannelDeleteEvents(Guild guild, ChannelType type, GuildChannel channel) { - ModlogEvent event = ModlogEvent.CHANNEL_DELETED; - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - ModlogUtils.getAuditLogFromType(guild, channel.getIdLong(), auditLogEntry -> { - List embedFieldList = new ArrayList<>(); - User responsible = null; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find channel delete entry"); - } - embedFieldList.add(new ModlogEmbedField(false, "modlog.channel.type.name", "modlog.channel.type." + type.name().toLowerCase())); - ModlogEventData modlogEventData = new ModlogEventData(event, responsible, channel, embedFieldList); - modlogEventData.setExtraDescriptionInfo(List.of(type.name().toLowerCase())); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventData); - }, ActionType.CHANNEL_DELETE); - } - - private void handleChannelUpdateNameEvents(Guild guild, ChannelType type, String oldName, GuildChannel channel) { - ModlogEvent event = ModlogEvent.CHANNEL_NAME_UPDATED; - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - ModlogUtils.getAuditLogFromType(guild, channel.getIdLong(), auditLogEntry -> { - List embedFieldList = new ArrayList<>(); - User responsible = null; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); - } - embedFieldList.add(new ModlogEmbedField(true, "modlog.general.name", "modlog.general.small_change", oldName, channel.getName())); - ModlogEventData modlogEventData = new ModlogEventData(event, responsible, channel, embedFieldList); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventData); - }, ActionType.CHANNEL_UPDATE); - } - - private void handleChannelUpdatePositionEvents(Guild guild, ChannelType type, int oldPos, GuildChannel channel) { - ChannelMoveData moveData = new ChannelMoveData(type, oldPos, channel); - if (moveRunnableMap.containsKey(guild.getIdLong())) { - moveRunnableMap.get(guild.getIdLong()).getQueue().add(moveData); - } else { - EventCollector moveCollector = new EventCollector<>(guild, this::channelMove, 500); - moveCollector.getQueue().add(moveData); - moveRunnableMap.put(guild.getIdLong(), moveCollector); - EVENT_COLLECTOR_POOL.submit(moveCollector); - } - } - - private void channelMove(Guild guild, List channelMoveDataList) { - moveRunnableMap.remove(guild.getIdLong()); - ModlogUtils.getAuditLogFromType(guild, auditLogEntry -> { - User responsible = null; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } - int maxDistance = 0; - List maxMoveData = new ArrayList<>(); - for (ChannelMoveData moveData : channelMoveDataList) { - if (moveData == null) { - continue; - } - int distance = Math.abs(moveData.channel.getPosition() - moveData.oldPos); - if (distance == maxDistance) { - maxMoveData.add(moveData); - } else if (distance > maxDistance) { - maxMoveData = new ArrayList<>(); - maxDistance = distance; - maxMoveData.add(moveData); - } - } - - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - List embedParts = new ArrayList<>(); - for (ChannelMoveData data : maxMoveData) { - ModlogEmbedField field = new ModlogEmbedField(false, "modlog.channel.position.title", - "modlog.general.small_change", - DiscordUtils.calcChannelPosition(data.oldPos, data.channel.getType(), data.channel.getGuild()), - DiscordUtils.calcChannelPosition(data.channel)); - field.addTitleObjects(data.channel.getName()); - embedParts.add(field); - } - ModlogEvent event = maxMoveData.size() <= 1 ? ModlogEvent.CHANNEL_POSITION_UPDATED : ModlogEvent.MULTIPLE_CHANNEL_POSITION_UPDATED; - ModlogEventData eventStore = new ModlogEventData(event, responsible, maxMoveData.get(0).channel, embedParts); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), eventStore); - - }, ActionType.CHANNEL_UPDATE); - } - - public static class ChannelMoveData { - - private final ChannelType type; - private final int oldPos; - private final GuildChannel channel; - - public ChannelMoveData(ChannelType type, int oldPos, GuildChannel channel) { - this.type = type; - this.oldPos = oldPos; - this.channel = channel; - } - - public ChannelType getType() { - return type; - } - - public int getOldPos() { - return oldPos; - } - - public GuildChannel getChannel() { - return channel; - } - - } - - public static class RoleModifyData { - - private final Member member; - private final ChangeList changeList; - - public RoleModifyData(Member member, ChangeList changeList) { - this.member = member; - this.changeList = changeList; - } - - public Member getMember() { - return member; - } - - public ChangeList getChangeList() { - return changeList; - } - - } - - public void handleChannelUpdateParentEvents(Guild guild, ChannelType type, Category oldParent, Category newParent, GuildChannel channel) { - ModlogEvent event = ModlogEvent.CHANNEL_PARENT_UPDATED; - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - ModlogUtils.getAuditLogFromType(guild, channel.getIdLong(), auditLogEntry -> { - List embedFieldList = new ArrayList<>(); - User responsible = null; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry"); - } - embedFieldList.add(new ModlogEmbedField(true, "modlog.channel.parent", "modlog.general.small_change", oldParent == null ? "None" : oldParent.getName(), newParent == null ? "None" : newParent.getName())); // TODO language string for none - ModlogEventData modlogEventData = new ModlogEventData(event, responsible, channel, embedFieldList); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventData); - }, ActionType.CHANNEL_UPDATE); - } - //endregion - - public void onGenericRole(GenericRoleEvent event) { - GuildData guildData = GuildDataManager.getGuildData(event.getGuild().getIdLong()); - ModlogUtils.getAuditLogFromType(event.getGuild(), event.getRole().getIdLong(), auditLogEntry -> { - List embedFieldList = new ArrayList<>(); - List descriptionStuff = new ArrayList<>(); - User responsible = null; - ModlogEvent modlogEvent; - if (auditLogEntry != null) { - responsible = auditLogEntry.getUser(); - } else { - CascadeBot.LOGGER.warn("Modlog: Failed to find role audit log entry"); - } - Role affected = event.getRole(); - if (event instanceof RoleCreateEvent) { - modlogEvent = ModlogEvent.ROLE_CREATED; - } else if (event instanceof RoleDeleteEvent) { - modlogEvent = ModlogEvent.ROLE_DELETED; - } else if (event instanceof RoleUpdateColorEvent) { - modlogEvent = ModlogEvent.ROLE_COLOR_UPDATED; - Color oldColor = ((RoleUpdateColorEvent) event).getOldColor(); - Color newColor = ((RoleUpdateColorEvent) event).getNewColor(); - - embedFieldList.add(new ModlogEmbedField(false, "modlog.role.old_color", oldColor != null ? null : "words.default", oldColor != null ? ColorUtils.getHex(oldColor.getRed(), oldColor.getGreen(), oldColor.getBlue()) : null)); - embedFieldList.add(new ModlogEmbedField(false, "modlog.role.new_color", newColor != null ? null : "words.default", newColor != null ? ColorUtils.getHex(newColor.getRed(), newColor.getGreen(), newColor.getBlue()) : null)); - } else if (event instanceof RoleUpdateHoistedEvent) { - modlogEvent = ModlogEvent.ROLE_HOIST_UPDATED; - var wasHoisted = ((RoleUpdateHoistedEvent) event).wasHoisted(); - Emote emote = !wasHoisted ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("tick")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("cross")); - descriptionStuff = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(!wasHoisted)); - } else if (event instanceof RoleUpdateMentionableEvent) { - modlogEvent = ModlogEvent.ROLE_MENTIONABLE_UPDATED; - Emote emote = ((RoleUpdateMentionableEvent) event).getNewValue() ? CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("tick")) : CascadeBot.INS.getShardManager().getEmoteById(Config.INS.getGlobalEmotes().get("cross")); - descriptionStuff = List.of(emote != null ? emote.getAsMention() : "", String.valueOf(((RoleUpdateMentionableEvent) event).getNewValue())); - } else if (event instanceof RoleUpdateNameEvent) { - modlogEvent = ModlogEvent.ROLE_NAME_UPDATED; - embedFieldList.add(new ModlogEmbedField(false, "modlog.general.old_name", null, ((RoleUpdateNameEvent) event).getOldName())); - embedFieldList.add(new ModlogEmbedField(false, "modlog.general.new_name", null, ((RoleUpdateNameEvent) event).getNewValue())); - } else if (event instanceof RoleUpdatePermissionsEvent) { - modlogEvent = ModlogEvent.ROLE_PERMISSIONS_UPDATED; - EnumSet oldPermissions = ((RoleUpdatePermissionsEvent) event).getOldPermissions(); - EnumSet newPermissions = ((RoleUpdatePermissionsEvent) event).getNewPermissions(); - - CollectionDiff permissionListChanges = new CollectionDiff<>(oldPermissions, newPermissions); - if (!permissionListChanges.getAdded().isEmpty()) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.role.added_perm", null, permissionListChanges.getAdded().stream().map(Permission::getName).collect(Collectors.joining("\n")))); - } - if (!permissionListChanges.getRemoved().isEmpty()) { - embedFieldList.add(new ModlogEmbedField(false, "modlog.role.removed_perm", null, permissionListChanges.getRemoved().stream().map(Permission::getName).collect(Collectors.joining("\n")))); - } - } else if (event instanceof RoleUpdatePositionEvent) { - modlogEvent = ModlogEvent.ROLE_POSITION_UPDATED; - if (((RoleUpdatePositionEvent) event).getNewPosition() == ((RoleUpdatePositionEvent) event).getOldPosition()) { - // If the position stays the same, we have no reason to log the event - return; - } - embedFieldList.add(new ModlogEmbedField(false, "modlog.general.position", "modlog.general.small_change", ((RoleUpdatePositionEvent) event).getOldPosition() + 1, ((RoleUpdatePositionEvent) event).getNewPosition() + 1)); - } else { - return; - } - ModlogEventData modlogEventData = new ModlogEventData(modlogEvent, responsible, affected, embedFieldList); - modlogEventData.setExtraDescriptionInfo(descriptionStuff); - guildData.getModeration().sendModlogEvent(event.getGuild().getIdLong(), modlogEventData); - }, ActionType.ROLE_CREATE, ActionType.ROLE_DELETE, ActionType.ROLE_UPDATE); - } - - //region Username updates - public void onUserUpdateName(UserUpdateNameEvent event) { - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(false, "modlog.general.name", "modlog.general.small_change", event.getOldName(), event.getNewName())); - ModlogEventData modlogEventData = new ModlogEventData(ModlogEvent.USER_NAME_UPDATED, event.getUser(), event.getUser(), embedFieldList); - for (Guild guild : CascadeBot.INS.getClient().getMutualGuilds(event.getUser())) { - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventData); - } - } - - public void onUserUpdateDiscriminator(UserUpdateDiscriminatorEvent event) { - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(false, "modlog.member.discrim", "modlog.general.small_change", event.getOldDiscriminator(), event.getNewDiscriminator())); - ModlogEventData modlogEventData = new ModlogEventData(ModlogEvent.USER_DISCRIMINATOR_UPDATED, event.getUser(), event.getUser(), embedFieldList); - for (Guild guild : CascadeBot.INS.getClient().getMutualGuilds(event.getUser())) { - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - guildData.getModeration().sendModlogEvent(guild.getIdLong(), modlogEventData); - } - } - //endregion - -} diff --git a/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/ChannelModlogEventListener.kt b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/ChannelModlogEventListener.kt new file mode 100644 index 000000000..36ace5fce --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/ChannelModlogEventListener.kt @@ -0,0 +1,620 @@ +/* + * Copyright (c) 2021 CascadeBot. All rights reserved. + * Licensed under the MIT license. + */ + +package org.cascadebot.cascadebot.events.modlog + +import net.dv8tion.jda.api.Permission +import net.dv8tion.jda.api.audit.ActionType +import net.dv8tion.jda.api.audit.AuditLogEntry +import net.dv8tion.jda.api.entities.Category +import net.dv8tion.jda.api.entities.ChannelType +import net.dv8tion.jda.api.entities.Guild +import net.dv8tion.jda.api.entities.GuildChannel +import net.dv8tion.jda.api.entities.IPermissionHolder +import net.dv8tion.jda.api.entities.Role +import net.dv8tion.jda.api.entities.User +import net.dv8tion.jda.api.events.channel.category.CategoryCreateEvent +import net.dv8tion.jda.api.events.channel.category.CategoryDeleteEvent +import net.dv8tion.jda.api.events.channel.category.GenericCategoryEvent +import net.dv8tion.jda.api.events.channel.category.update.CategoryUpdateNameEvent +import net.dv8tion.jda.api.events.channel.category.update.CategoryUpdatePositionEvent +import net.dv8tion.jda.api.events.channel.store.GenericStoreChannelEvent +import net.dv8tion.jda.api.events.channel.store.StoreChannelCreateEvent +import net.dv8tion.jda.api.events.channel.store.StoreChannelDeleteEvent +import net.dv8tion.jda.api.events.channel.store.update.StoreChannelUpdateNameEvent +import net.dv8tion.jda.api.events.channel.store.update.StoreChannelUpdatePositionEvent +import net.dv8tion.jda.api.events.channel.text.GenericTextChannelEvent +import net.dv8tion.jda.api.events.channel.text.TextChannelCreateEvent +import net.dv8tion.jda.api.events.channel.text.TextChannelDeleteEvent +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateNSFWEvent +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateNameEvent +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateParentEvent +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdatePositionEvent +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateSlowmodeEvent +import net.dv8tion.jda.api.events.channel.text.update.TextChannelUpdateTopicEvent +import net.dv8tion.jda.api.events.channel.voice.GenericVoiceChannelEvent +import net.dv8tion.jda.api.events.channel.voice.VoiceChannelCreateEvent +import net.dv8tion.jda.api.events.channel.voice.VoiceChannelDeleteEvent +import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateBitrateEvent +import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateNameEvent +import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateParentEvent +import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdatePositionEvent +import net.dv8tion.jda.api.events.channel.voice.update.VoiceChannelUpdateUserLimitEvent +import net.dv8tion.jda.api.events.guild.override.GenericPermissionOverrideEvent +import net.dv8tion.jda.api.events.guild.override.PermissionOverrideCreateEvent +import net.dv8tion.jda.api.events.guild.override.PermissionOverrideDeleteEvent +import net.dv8tion.jda.api.events.guild.override.PermissionOverrideUpdateEvent +import net.dv8tion.jda.api.hooks.ListenerAdapter +import org.apache.commons.lang3.StringUtils +import org.cascadebot.cascadebot.CascadeBot +import org.cascadebot.cascadebot.UnicodeConstants +import org.cascadebot.cascadebot.data.Config +import org.cascadebot.cascadebot.data.language.Language.i18n +import org.cascadebot.cascadebot.data.managers.GuildDataManager +import org.cascadebot.cascadebot.data.objects.ModlogEventData +import org.cascadebot.cascadebot.events.EventCollector +import org.cascadebot.cascadebot.moderation.ModlogEmbedField +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart +import org.cascadebot.cascadebot.moderation.ModlogEvent +import org.cascadebot.cascadebot.utils.DiscordUtils +import org.cascadebot.cascadebot.utils.ModlogUtils.getAuditLogFromType +import org.cascadebot.shared.utils.ThreadPoolExecutorLogged +import java.util.concurrent.atomic.AtomicInteger +import java.util.function.Consumer +import kotlin.math.abs + +class ChannelModlogEventListener : ListenerAdapter() { + + private val moveRunnableMap: MutableMap> = HashMap() + + private val threadCounter = AtomicInteger(0) + private val channelEventCollectorPool = ThreadPoolExecutorLogged.newCachedThreadPool({ runnable: Runnable? -> + Thread( + runnable, + "channel-event-collector-" + threadCounter.getAndIncrement() + ) + }, CascadeBot.LOGGER) + + //region Channels + override fun onGenericStoreChannel(event: GenericStoreChannelEvent) { + when (event) { + is StoreChannelCreateEvent -> { + handleChannelCreateEvents(event.getChannel().guild, ChannelType.STORE, event.getChannel()) + } + + is StoreChannelDeleteEvent -> { + handleChannelDeleteEvents(event.getChannel().guild, ChannelType.STORE, event.getChannel()) + } + + is StoreChannelUpdateNameEvent -> { + handleChannelUpdateNameEvents( + event.getChannel().guild, + ChannelType.STORE, + event.oldName, + event.getChannel() + ) + } + + is StoreChannelUpdatePositionEvent -> { + handleChannelUpdatePositionEvents( + event.getChannel().guild, + ChannelType.STORE, + event.oldPosition, + event.getChannel() + ) + } + } + } + + override fun onGenericTextChannel(event: GenericTextChannelEvent) { + when (event) { + is TextChannelCreateEvent -> { + handleChannelCreateEvents(event.getGuild(), ChannelType.TEXT, event.getChannel()) + return + } + + is TextChannelDeleteEvent -> { + handleChannelDeleteEvents(event.getGuild(), ChannelType.TEXT, event.getChannel()) + return + } + + is TextChannelUpdateNameEvent -> { + handleChannelUpdateNameEvents(event.getGuild(), ChannelType.TEXT, event.oldName, event.getChannel()) + return + } + + is TextChannelUpdatePositionEvent -> { + handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.TEXT, event.oldPosition, event.getChannel()) + return + } + + is TextChannelUpdateParentEvent -> { + handleChannelUpdateParentEvents( + event.getGuild(), + ChannelType.TEXT, + event.oldParent, + event.newParent, + event.getChannel() + ) + return + } + + else -> { + val guildData = GuildDataManager.getGuildData(event.guild.idLong) + getAuditLogFromType( + event.guild, event.channel.idLong, + Consumer { auditLogEntry: AuditLogEntry? -> + val trigger: ModlogEvent + val embedFieldList: MutableList = mutableListOf() + var descriptionParts: MutableList = mutableListOf() + var responsible: User? = null + if (auditLogEntry != null) { + responsible = auditLogEntry.user + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry") + } + when (event) { + is TextChannelUpdateNSFWEvent -> { + trigger = ModlogEvent.TEXT_CHANNEL_NSFW_UPDATED + val newValue = event.newValue + val emote = if (newValue != null && newValue) CascadeBot.INS.shardManager.getEmoteById( + Config.INS.globalEmotes["tick"]!! + ) else CascadeBot.INS.shardManager.getEmoteById( + Config.INS.globalEmotes["cross"]!! + ) + descriptionParts = mutableListOf( + emote?.asMention ?: "", + newValue.toString() + ) + } + + is TextChannelUpdateSlowmodeEvent -> { + trigger = ModlogEvent.TEXT_CHANNEL_SLOWMODE_UPDATED + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.channel.slowmode", + "modlog.general.small_change", + event.oldSlowmode, + event.newSlowmode + ) + ) + } + + is TextChannelUpdateTopicEvent -> { + trigger = ModlogEvent.TEXT_CHANNEL_TOPIC_UPDATED + val oldTopic = event.oldTopic + val newTopic = event.newTopic + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.channel.old_topic", + null, + if (StringUtils.isBlank(oldTopic)) "-" else oldTopic!! + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.channel.new_topic", + null, + if (StringUtils.isBlank(newTopic)) "-" else newTopic!! + ) + ) + } + + else -> { + return@Consumer + } + } + val eventStore = ModlogEventData(trigger, responsible, event.channel, embedFieldList) + eventStore.extraDescriptionInfo = descriptionParts + guildData.moderation.sendModlogEvent(event.guild.idLong, eventStore) + }, ActionType.CHANNEL_UPDATE + ) + } + } + } + + override fun onGenericVoiceChannel(event: GenericVoiceChannelEvent) { + when (event) { + is VoiceChannelCreateEvent -> { + handleChannelCreateEvents(event.getGuild(), ChannelType.VOICE, event.getChannel()) + } + + is VoiceChannelDeleteEvent -> { + handleChannelDeleteEvents(event.getGuild(), ChannelType.VOICE, event.getChannel()) + } + + is VoiceChannelUpdateNameEvent -> { + handleChannelUpdateNameEvents(event.getGuild(), ChannelType.VOICE, event.oldName, event.getChannel()) + } + + is VoiceChannelUpdatePositionEvent -> { + handleChannelUpdatePositionEvents( + event.getGuild(), + ChannelType.VOICE, + event.oldPosition, + event.getChannel() + ) + } + + is VoiceChannelUpdateParentEvent -> { + handleChannelUpdateParentEvents( + event.getGuild(), + ChannelType.VOICE, + event.oldParent, + event.newParent, + event.getChannel() + ) + } + } + + val guildData = GuildDataManager.getGuildData(event.guild.idLong) + getAuditLogFromType( + event.guild, event.channel.idLong, + Consumer { auditLogEntry: AuditLogEntry? -> + val trigger: ModlogEvent + val embedFieldList: MutableList = ArrayList() + var responsible: User? = null + if (auditLogEntry != null) { + responsible = auditLogEntry.user + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry") + } + trigger = when (event) { + is VoiceChannelUpdateBitrateEvent -> { + val oldBitrate = i18n( + event.getGuild().idLong, + "modlog.channel.kbps", + event.oldBitrate / 1000 + ) + val newBitrate = i18n( + event.getGuild().idLong, + "modlog.channel.kbps", + event.newBitrate / 1000 + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.channel.bitrate", + "modlog.general.small_change", + oldBitrate, + newBitrate + ) + ) + ModlogEvent.VOICE_CHANNEL_BITRATE_UPDATED + } + + is VoiceChannelUpdateUserLimitEvent -> { + val oldLimit = + if (event.oldUserLimit == 0) UnicodeConstants.INFINITY_SYMBOL else event.oldUserLimit + .toString() + val newLimit = + if (event.newUserLimit == 0) UnicodeConstants.INFINITY_SYMBOL else event.newUserLimit + .toString() + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.channel.users", + "modlog.general.small_change", + oldLimit, + newLimit + ) + ) + ModlogEvent.VOICE_CHANNEL_USER_LIMIT_UPDATED + } + + else -> { + return@Consumer + } + } + val eventStore = ModlogEventData(trigger, responsible, event.channel, embedFieldList) + guildData.moderation.sendModlogEvent(event.guild.idLong, eventStore) + }, ActionType.CHANNEL_UPDATE + ) + } + + override fun onGenericCategory(event: GenericCategoryEvent) { + if (event is CategoryCreateEvent) { + handleChannelCreateEvents(event.getGuild(), ChannelType.CATEGORY, event.getCategory()) + } else if (event is CategoryDeleteEvent) { + handleChannelDeleteEvents(event.getGuild(), ChannelType.CATEGORY, event.getCategory()) + } else if (event is CategoryUpdateNameEvent) { + handleChannelUpdateNameEvents(event.getGuild(), ChannelType.CATEGORY, event.oldName, event.getCategory()) + } else if (event is CategoryUpdatePositionEvent) { + handleChannelUpdatePositionEvents( + event.getGuild(), + ChannelType.CATEGORY, + event.oldPosition, + event.getCategory() + ) + } + } + + override fun onGenericPermissionOverride(event: GenericPermissionOverrideEvent) { + val guild = event.guild + val guildData = GuildDataManager.getGuildData(guild.idLong) + getAuditLogFromType( + event.guild, event.channel.idLong, + Consumer { auditLogEntry: AuditLogEntry? -> + val embedFieldList: MutableList = ArrayList() + val modlogEvent: ModlogEvent + var responsible: User? = null + if (auditLogEntry != null) { + responsible = auditLogEntry.user + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry") + } + when (event) { + is PermissionOverrideCreateEvent -> { + modlogEvent = ModlogEvent.DUMMY + } + + is PermissionOverrideDeleteEvent -> { + modlogEvent = ModlogEvent.DUMMY + } + + is PermissionOverrideUpdateEvent -> { + modlogEvent = ModlogEvent.CHANNEL_PERMISSIONS_UPDATED + val stringBuilder = StringBuilder() + for (permission in event.oldDeny) { + val current = + getCurrentPermissionStateForHolder( + permission, + event.getChannel(), + event.getPermissionHolder() + ) + if (current != "x") { + stringBuilder.append("x > ").append(current).append(": ").append(permission.getName()) + .append('\n') + } + } + for (permission in event.oldInherited) { + val current = + getCurrentPermissionStateForHolder( + permission, + event.getChannel(), + event.getPermissionHolder() + ) + if (current != "\\\\") { + stringBuilder.append("\\ > ").append(current).append(": ").append(permission.getName()) + .append('\n') + } + } + for (permission in event.oldAllow) { + val current = + getCurrentPermissionStateForHolder( + permission, + event.getChannel(), + event.getPermissionHolder() + ) + if (current != "+") { + stringBuilder.append("+ > ").append(current).append(": ").append(permission.getName()) + .append('\n') + } + } + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.channel.perm.changed", + "modlog.general.variable", + stringBuilder.toString() + ) + ) + } + + else -> { + return@Consumer + } + } + val modlogEventData = ModlogEventData(modlogEvent, responsible, event.channel, embedFieldList) + var holderMention = "" + if (event.permissionHolder is User) { + holderMention = (event.permissionHolder as User?)!!.asMention + } else if (event.permissionHolder is Role) { + holderMention = (event.permissionHolder as Role?)!!.asMention + } + modlogEventData.extraDescriptionInfo = mutableListOf(holderMention) + guildData.moderation.sendModlogEvent(event.guild.idLong, modlogEventData) + }, ActionType.CHANNEL_OVERRIDE_UPDATE, ActionType.CHANNEL_UPDATE + ) + } + + private fun getCurrentPermissionStateForHolder( + permission: Permission, + channel: GuildChannel, + holder: IPermissionHolder? + ): String { + val permissionOverride = channel.getPermissionOverride(holder!!) ?: return "unknown" + return when { + permissionOverride.allowed.contains(permission) -> { + "+" + } + + permissionOverride.inherit.contains(permission) -> { + "\\\\" + } + + permissionOverride.denied.contains(permission) -> { + "x" + } + + else -> { + "unknown" + } + } + } + + //endregion + + //endregion + //region Channel handlers + private fun handleChannelCreateEvents(guild: Guild, type: ChannelType, channel: GuildChannel) { + val event = ModlogEvent.CHANNEL_CREATED + val guildData = GuildDataManager.getGuildData(guild.idLong) + getAuditLogFromType(guild, channel.idLong, Consumer { auditLogEntry: AuditLogEntry? -> + val embedFieldList: MutableList = ArrayList() + var responsible: User? = null + if (auditLogEntry != null) { + responsible = auditLogEntry.user + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel create entry") + } + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.channel.type.name", + "modlog.channel.type." + type.name.toLowerCase() + ) + ) + val modlogEventData = ModlogEventData(event, responsible, channel, embedFieldList) + modlogEventData.extraDescriptionInfo = mutableListOf(type.name.toLowerCase()) + guildData.moderation.sendModlogEvent(guild.idLong, modlogEventData) + }, ActionType.CHANNEL_CREATE) + } + + private fun handleChannelDeleteEvents(guild: Guild, type: ChannelType, channel: GuildChannel) { + val event = ModlogEvent.CHANNEL_DELETED + val guildData = GuildDataManager.getGuildData(guild.idLong) + getAuditLogFromType(guild, channel.idLong, Consumer { auditLogEntry: AuditLogEntry? -> + val embedFieldList: MutableList = ArrayList() + var responsible: User? = null + if (auditLogEntry != null) { + responsible = auditLogEntry.user + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel delete entry") + } + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.channel.type.name", + "modlog.channel.type." + type.name.toLowerCase() + ) + ) + val modlogEventData = ModlogEventData(event, responsible, channel, embedFieldList) + modlogEventData.extraDescriptionInfo = mutableListOf(type.name.toLowerCase()) + guildData.moderation.sendModlogEvent(guild.idLong, modlogEventData) + }, ActionType.CHANNEL_DELETE) + } + + private fun handleChannelUpdateNameEvents(guild: Guild, type: ChannelType, oldName: String, channel: GuildChannel) { + val event = ModlogEvent.CHANNEL_NAME_UPDATED + val guildData = GuildDataManager.getGuildData(guild.idLong) + getAuditLogFromType(guild, channel.idLong, Consumer { auditLogEntry: AuditLogEntry? -> + val embedFieldList: MutableList = ArrayList() + var responsible: User? = null + if (auditLogEntry != null) { + responsible = auditLogEntry.user + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry") + } + embedFieldList.add( + ModlogEmbedField( + true, + "modlog.general.name", + "modlog.general.small_change", + oldName, + channel.name + ) + ) + val modlogEventData = ModlogEventData(event, responsible, channel, embedFieldList) + guildData.moderation.sendModlogEvent(guild.idLong, modlogEventData) + }, ActionType.CHANNEL_UPDATE) + } + + private fun handleChannelUpdatePositionEvents(guild: Guild, type: ChannelType, oldPos: Int, channel: GuildChannel) { + val moveData = ChannelMoveData(type, oldPos, channel) + val channelCollector = moveRunnableMap[guild.idLong] + if (channelCollector != null) { + channelCollector.queue.add(moveData) + } else { + val moveCollector = EventCollector( + guild, + { callbackGuild: Guild, channelMoveDataList: List -> + channelMove( + callbackGuild, + channelMoveDataList + ) + }, 500 + ) + moveCollector.queue.add(moveData) + moveRunnableMap[guild.idLong] = moveCollector + channelEventCollectorPool.submit(moveCollector) + } + } + + private fun channelMove(guild: Guild, channelMoveDataList: List) { + moveRunnableMap.remove(guild.idLong) + getAuditLogFromType(guild, Consumer { auditLogEntry: AuditLogEntry? -> + var responsible: User? = null + if (auditLogEntry != null) { + responsible = auditLogEntry.user + } + var maxDistance = 0 + var maxMoveData: MutableList = ArrayList() + for (moveData in channelMoveDataList) { + val distance = abs(moveData.channel.position - moveData.oldPos) + if (distance == maxDistance) { + maxMoveData.add(moveData) + } else if (distance > maxDistance) { + maxMoveData = ArrayList() + maxDistance = distance + maxMoveData.add(moveData) + } + } + val guildData = GuildDataManager.getGuildData(guild.idLong) + val embedParts: MutableList = ArrayList() + for (data in maxMoveData) { + val field = ModlogEmbedField( + false, "modlog.channel.position.title", + "modlog.general.small_change", + DiscordUtils.calcChannelPosition(data.oldPos, data.channel.type, data.channel.guild), + DiscordUtils.calcChannelPosition(data.channel) + ) + field.addTitleObjects(data.channel.name) + embedParts.add(field) + } + val event = + if (maxMoveData.size <= 1) ModlogEvent.CHANNEL_POSITION_UPDATED else ModlogEvent.MULTIPLE_CHANNEL_POSITION_UPDATED + val eventStore = ModlogEventData(event, responsible, maxMoveData[0].channel, embedParts) + guildData.moderation.sendModlogEvent(guild.idLong, eventStore) + }, ActionType.CHANNEL_UPDATE) + } + + class ChannelMoveData(val type: ChannelType, val oldPos: Int, val channel: GuildChannel) + + private fun handleChannelUpdateParentEvents( + guild: Guild, + type: ChannelType, + oldParent: Category?, + newParent: Category?, + channel: GuildChannel + ) { + val event = ModlogEvent.CHANNEL_PARENT_UPDATED + val guildData = GuildDataManager.getGuildData(guild.idLong) + getAuditLogFromType(guild, channel.idLong, Consumer { auditLogEntry: AuditLogEntry? -> + val embedFieldList: MutableList = java.util.ArrayList() + var responsible: User? = null + if (auditLogEntry != null) { + responsible = auditLogEntry.user + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find channel update entry") + } + embedFieldList.add( + ModlogEmbedField( + true, + "modlog.channel.parent", + "modlog.general.small_change", + oldParent?.name ?: "None", + newParent?.name ?: "None" + ) + ) // TODO language string for none + val modlogEventData = ModlogEventData(event, responsible, channel, embedFieldList) + guildData.moderation.sendModlogEvent(guild.idLong, modlogEventData) + }, ActionType.CHANNEL_UPDATE) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/GuildModlogEventListener.kt b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/GuildModlogEventListener.kt new file mode 100644 index 000000000..7904aab42 --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/GuildModlogEventListener.kt @@ -0,0 +1,898 @@ +/* + * Copyright (c) 2021 CascadeBot. All rights reserved. + * Licensed under the MIT license. + */ + +package org.cascadebot.cascadebot.events.modlog + +import com.google.gson.JsonParser +import net.dv8tion.jda.api.audit.ActionType +import net.dv8tion.jda.api.audit.AuditLogEntry +import net.dv8tion.jda.api.entities.Role +import net.dv8tion.jda.api.entities.User +import net.dv8tion.jda.api.events.emote.EmoteAddedEvent +import net.dv8tion.jda.api.events.emote.EmoteRemovedEvent +import net.dv8tion.jda.api.events.emote.GenericEmoteEvent +import net.dv8tion.jda.api.events.emote.update.EmoteUpdateNameEvent +import net.dv8tion.jda.api.events.emote.update.EmoteUpdateRolesEvent +import net.dv8tion.jda.api.events.guild.GuildBanEvent +import net.dv8tion.jda.api.events.guild.GuildUnbanEvent +import net.dv8tion.jda.api.events.guild.member.GenericGuildMemberEvent +import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent +import net.dv8tion.jda.api.events.guild.member.GuildMemberLeaveEvent +import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleAddEvent +import net.dv8tion.jda.api.events.guild.member.GuildMemberRoleRemoveEvent +import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateNicknameEvent +import net.dv8tion.jda.api.events.guild.update.GenericGuildUpdateEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateAfkChannelEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateAfkTimeoutEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateBannerEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostCountEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateBoostTierEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateDescriptionEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateExplicitContentLevelEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateFeaturesEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateIconEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateMFALevelEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateMaxPresencesEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateNameEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateNotificationLevelEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateRegionEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateSplashEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateSystemChannelEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateVanityCodeEvent +import net.dv8tion.jda.api.events.guild.update.GuildUpdateVerificationLevelEvent +import net.dv8tion.jda.api.events.guild.voice.GenericGuildVoiceEvent +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceDeafenEvent +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceGuildDeafenEvent +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceGuildMuteEvent +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceJoinEvent +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceLeaveEvent +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceMoveEvent +import net.dv8tion.jda.api.events.guild.voice.GuildVoiceMuteEvent +import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent +import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent +import net.dv8tion.jda.api.hooks.ListenerAdapter +import org.cascadebot.cascadebot.CascadeBot +import org.cascadebot.cascadebot.data.Config +import org.cascadebot.cascadebot.data.language.Language.i18n +import org.cascadebot.cascadebot.data.managers.GuildDataManager +import org.cascadebot.cascadebot.data.objects.ModlogEventData +import org.cascadebot.cascadebot.moderation.ModlogEmbedDescription +import org.cascadebot.cascadebot.moderation.ModlogEmbedField +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart +import org.cascadebot.cascadebot.moderation.ModlogEvent +import org.cascadebot.cascadebot.utils.CryptUtils +import org.cascadebot.cascadebot.utils.ModlogUtils.getAuditLogFromType +import org.cascadebot.cascadebot.utils.SerializableMessage +import org.cascadebot.cascadebot.utils.lists.CollectionDiff +import java.nio.ByteBuffer +import java.security.InvalidAlgorithmParameterException +import java.security.InvalidKeyException +import java.security.NoSuchAlgorithmException +import java.util.function.Consumer +import java.util.stream.Collectors +import javax.crypto.BadPaddingException +import javax.crypto.IllegalBlockSizeException +import javax.crypto.NoSuchPaddingException +import javax.crypto.ShortBufferException + +class GuildModlogEventListener : ListenerAdapter() { + + override fun onGenericEmote(event: GenericEmoteEvent) { + val guildData = GuildDataManager.getGuildData(event.guild.idLong) + val emote = event.emote + getAuditLogFromType( + event.guild, event.emote.idLong, + Consumer { auditLogEntry: AuditLogEntry? -> + var user: User? = null + if (auditLogEntry != null) { + user = auditLogEntry.user + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find emote audit log entry") + } + val embedFieldList: MutableList = ArrayList() + val modlogEvent: ModlogEvent + if (event is EmoteAddedEvent) { + modlogEvent = ModlogEvent.EMOTE_CREATED + } else if (event is EmoteRemovedEvent) { + modlogEvent = ModlogEvent.EMOTE_DELETED + } else if (event is EmoteUpdateNameEvent) { + modlogEvent = ModlogEvent.EMOTE_UPDATED_NAME + val oldName = ModlogEmbedField(false, "modlog.general.old_name", null) + val newName = ModlogEmbedField(false, "modlog.general.new_name", null) + oldName.addValueObjects(event.oldName) + newName.addValueObjects(event.newName) + embedFieldList.add(oldName) + embedFieldList.add(newName) + } else if (event is EmoteUpdateRolesEvent) { + modlogEvent = ModlogEvent.EMOTE_UPDATED_ROLES + val oldRoles = + event.oldRoles + val newRoles = + event.newRoles + val roleListChanges = + CollectionDiff(oldRoles, newRoles) + if (roleListChanges.added.isNotEmpty()) { + val addedRolesEmbed = ModlogEmbedField(false, "modlog.general.added_roles", null) + addedRolesEmbed.addValueObjects( + roleListChanges.added.stream() + .map { role: Role -> role.name + " (" + role.id + ")" } + .collect(Collectors.joining("\n")) + ) + embedFieldList.add(addedRolesEmbed) + } + if (roleListChanges.removed.isNotEmpty()) { + val removedRolesEmbed = + ModlogEmbedField(false, "modlog.general.removed_roles", null) + removedRolesEmbed.addValueObjects( + roleListChanges.removed.stream() + .map { role: Role -> role.name + " (" + role.id + ")" } + .collect(Collectors.joining("\n")) + ) + embedFieldList.add(removedRolesEmbed) + } + } else { + return@Consumer + } + val eventStore = ModlogEventData(modlogEvent, user, emote, embedFieldList) + guildData.moderation.sendModlogEvent(event.guild.idLong, eventStore) + }, ActionType.EMOTE_CREATE, ActionType.EMOTE_DELETE, ActionType.EMOTE_UPDATE + ) + } + + override fun onGenericGuildMember(event: GenericGuildMemberEvent) { + val guildData = GuildDataManager.getGuildData(event.guild.idLong) + val user = event.member.user + getAuditLogFromType( + event.guild, event.user.idLong, + Consumer { auditLogEntry: AuditLogEntry? -> + val embedFieldList: MutableList = ArrayList() + val modlogEvent: ModlogEvent + var responsible: User? = null + if (event is GuildMemberJoinEvent) { + modlogEvent = ModlogEvent.GUILD_MEMBER_JOINED + embedFieldList.add(ModlogEmbedDescription("modlog.member.joined", user.asMention)) + } else if (event is GuildMemberLeaveEvent) { + if (auditLogEntry != null && auditLogEntry.type == ActionType.KICK) { + val eventStore = + ModlogEventData(ModlogEvent.GUILD_MEMBER_LEFT, null, user, embedFieldList) + guildData.moderation.sendModlogEvent(event.getGuild().idLong, eventStore) + responsible = auditLogEntry.user + embedFieldList.add(ModlogEmbedDescription("modlog.member.kicked", user.asMention)) + if (auditLogEntry.reason != null) { + val reasonEmbedField = ModlogEmbedField(false, "modlog.general.reason", null) + reasonEmbedField.addValueObjects(auditLogEntry.reason!!) + embedFieldList.add(reasonEmbedField) + } + modlogEvent = ModlogEvent.GUILD_MEMBER_KICKED + } else { + modlogEvent = ModlogEvent.GUILD_MEMBER_LEFT + } + } else if (event is GuildMemberRoleAddEvent) { + if (auditLogEntry != null && auditLogEntry.targetIdLong == event.getMember().idLong) { + responsible = auditLogEntry.user + } + modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_ADDED + val addedRolesEmbedField = ModlogEmbedField(false, "modlog.general.added_roles", null) + addedRolesEmbedField.addValueObjects( + event.roles.stream() + .map { obj: Role -> obj.asMention } + .collect(Collectors.joining("\n")) + ) + embedFieldList.add(addedRolesEmbedField) + } else if (event is GuildMemberRoleRemoveEvent) { + if (auditLogEntry != null && auditLogEntry.targetIdLong == event.getMember().idLong) { + responsible = auditLogEntry.user + } + modlogEvent = ModlogEvent.GUILD_MEMBER_ROLE_REMOVED + val removedRolesEmbedField = + ModlogEmbedField(false, "modlog.general.removed_roles", null) + removedRolesEmbedField.addValueObjects( + event.roles.stream() + .map { obj: Role -> obj.asMention } + .collect(Collectors.joining("\n")) + ) + embedFieldList.add(removedRolesEmbedField) + } else if (event is GuildMemberUpdateNicknameEvent) { + if (auditLogEntry != null && auditLogEntry.type == ActionType.MEMBER_UPDATE) { + responsible = auditLogEntry.user + } + if (event.oldValue != null) { + val oldNickEmbedField = ModlogEmbedField(false, "modlog.member.old_nick", null) + oldNickEmbedField.addValueObjects(event.oldValue!!) + embedFieldList.add(oldNickEmbedField) + } + if (event.newValue != null) { + val newNickEmbedField = ModlogEmbedField(false, "modlog.member.new_nick", null) + newNickEmbedField.addValueObjects(event.newValue!!) + embedFieldList.add(newNickEmbedField) + } + modlogEvent = ModlogEvent.GUILD_MEMBER_NICKNAME_UPDATED + } else { + return@Consumer + } + val eventStore = ModlogEventData(modlogEvent, responsible, user, embedFieldList) + guildData.moderation.sendModlogEvent(event.guild.idLong, eventStore) + }, ActionType.KICK, ActionType.MEMBER_ROLE_UPDATE, ActionType.MEMBER_UPDATE + ) + } + + //region Ban events + override fun onGuildBan(event: GuildBanEvent) { + val guildData = GuildDataManager.getGuildData(event.guild.idLong) + val user = event.user + getAuditLogFromType( + event.guild, event.user.idLong, + Consumer { auditLogEntry: AuditLogEntry? -> + val embedFieldList: MutableList = ArrayList() + val modlogEvent = ModlogEvent.GUILD_USER_BANNED + var responsible: User? = null + if (auditLogEntry != null) { + responsible = auditLogEntry.user + embedFieldList.add(ModlogEmbedDescription("modlog.member.banned", user.asMention)) + if (auditLogEntry.reason != null) { + val reasonEmbedField = ModlogEmbedField(false, "modlog.general.reason", null) + reasonEmbedField.addValueObjects(auditLogEntry.reason!!) + embedFieldList.add(reasonEmbedField) + } + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find ban entry") + } + val eventStore = ModlogEventData(modlogEvent, responsible, user, embedFieldList) + guildData.moderation.sendModlogEvent(event.guild.idLong, eventStore) + }, ActionType.BAN + ) + } + + override fun onGuildUnban(event: GuildUnbanEvent) { + val guildData = GuildDataManager.getGuildData(event.guild.idLong) + val user = event.user + getAuditLogFromType( + event.guild, event.user.idLong, + Consumer { auditLogEntry: AuditLogEntry? -> + val embedFieldList: MutableList = ArrayList() + val modlogEvent = ModlogEvent.GUILD_USER_UNBANNED + var responsible: User? = null + if (auditLogEntry != null) { + responsible = auditLogEntry.user + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find unban entry") + } + val eventStore = ModlogEventData(modlogEvent, responsible, user, embedFieldList) + guildData.moderation.sendModlogEvent(event.guild.idLong, eventStore) + }, ActionType.UNBAN + ) + } + //endregion + + //endregion + //region Message + // TODO + override fun onGuildMessageDelete(event: GuildMessageDeleteEvent) { + if (CascadeBot.INS.redisClient == null) { + return + } + val guildData = GuildDataManager.getGuildData(event.guild.idLong) + val messageID = event.messageId + val messageString = CascadeBot.INS.redisClient["message:$messageID"] ?: return + CascadeBot.INS.redisClient.del("message:$messageID") + val message = getMessageFromString(event.messageIdLong, messageString) ?: return + val affected = CascadeBot.INS.client.getUserById(message.authorId) + val embedFieldList: MutableList = ArrayList() + val messageEmbedField = ModlogEmbedField(false, "modlog.message.message", null) + messageEmbedField.addValueObjects(message.content) + embedFieldList.add(messageEmbedField) + if (message.attachments.isNotEmpty()) { + val attachmentsBuilder = StringBuilder() + for ((_, _, _, url) in message.attachments) { + attachmentsBuilder.append(url).append('\n') + } + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.message.attachments", + null, + attachmentsBuilder.toString() + ) + ) + } + if (affected == null) { + return + } + //TODO handle embeds/ect... + getAuditLogFromType(event.guild, message.authorId, Consumer { auditLogEntry: AuditLogEntry? -> + val responsible: User? = if (auditLogEntry != null) { + auditLogEntry.user + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find message delete entry") + null + } + if (message.userMentions.isNotEmpty() || message.roleMentions.isNotEmpty()) { + val eventStore = + ModlogEventData(ModlogEvent.GUILD_MESSAGE_DELETED_MENTION, responsible, affected, embedFieldList) + guildData.moderation.sendModlogEvent(event.guild.idLong, eventStore) + } + val eventStore = + ModlogEventData(ModlogEvent.GUILD_MESSAGE_DELETED, responsible, affected, embedFieldList) + guildData.moderation.sendModlogEvent(event.guild.idLong, eventStore) + }, ActionType.MESSAGE_DELETE) + } + + // TODO + override fun onGuildMessageUpdate(event: GuildMessageUpdateEvent) { + if (CascadeBot.INS.redisClient == null) { + return + } + if (event.author.isBot) { + return + } + val guildData = GuildDataManager.getGuildData(event.guild.idLong) + val message = event.message + val messageString = CascadeBot.INS.redisClient["message:" + message.id] ?: return + CascadeBot.INS.redisClient.del("message:" + message.id) + val oldMessage = getMessageFromString(message.idLong, messageString) ?: return + val affected = message.author + val embedFieldList: MutableList = ArrayList() + val oldEmbedField = ModlogEmbedField(false, "modlog.message.old_message", null) + oldEmbedField.addValueObjects(oldMessage.content) + val newEmbedField = ModlogEmbedField(false, "modlog.message.new_message", null) + newEmbedField.addValueObjects(message.contentRaw) + // TODO handle embeds/ect... + embedFieldList.add(oldEmbedField) + embedFieldList.add(newEmbedField) + val modlogEvent = ModlogEvent.GUILD_MESSAGE_UPDATED + val eventStore = ModlogEventData(modlogEvent, null, affected, embedFieldList) + guildData.moderation.sendModlogEvent(event.guild.idLong, eventStore) + } + + private fun getMessageFromString(id: Long, messageString: String): SerializableMessage? { + val message: String + if (Config.INS.encryptKey != null) { + val messageId = ByteBuffer.allocate(java.lang.Long.BYTES).putLong(id).array() + val iv = ByteArray(messageId.size * 2) + System.arraycopy(messageId, 0, iv, 0, messageId.size) + System.arraycopy(messageId, 0, iv, messageId.size, messageId.size) + val bytesJsonArray = JsonParser().parse(messageString).asJsonArray + val messageBytes = ByteArray(bytesJsonArray.size()) + for (i in 0 until bytesJsonArray.size()) { + messageBytes[i] = bytesJsonArray[i].asByte + } + message = try { + CryptUtils.decryptString(Config.INS.encryptKey, iv, messageBytes) + } catch (e: NoSuchPaddingException) { + CascadeBot.LOGGER.error("Unable to decrypt message!", e) + return null + } catch (e: NoSuchAlgorithmException) { + CascadeBot.LOGGER.error("Unable to decrypt message!", e) + return null + } catch (e: InvalidAlgorithmParameterException) { + CascadeBot.LOGGER.error("Unable to decrypt message!", e) + return null + } catch (e: InvalidKeyException) { + CascadeBot.LOGGER.error("Unable to decrypt message!", e) + return null + } catch (e: IllegalBlockSizeException) { + CascadeBot.LOGGER.error("Unable to decrypt message!", e) + return null + } catch (e: ShortBufferException) { + CascadeBot.LOGGER.error("Unable to decrypt message!", e) + return null + } catch (e: BadPaddingException) { + // TODO emails? notifications? + CascadeBot.LOGGER.error( + "Unabled to decrypt message due to padding error! **This most likely means the data has been messed with**", + e + ) + return null + } + } else { + message = messageString + } + return CascadeBot.getGSON().fromJson(message, SerializableMessage::class.java) + } + //endregion + + //endregion + override fun onGenericGuildUpdate(event: GenericGuildUpdateEvent<*>) { + val affected = event.entity + val guildData = GuildDataManager.getGuildData(affected.idLong) + getAuditLogFromType(event.guild, Consumer { auditLogEntry: AuditLogEntry? -> + val embedFieldList: MutableList = ArrayList() + var responsible: User? = null + val modlogEvent: ModlogEvent + if (auditLogEntry != null) { + responsible = auditLogEntry.user + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find guild update entry") + } + when (event) { + is GuildUpdateAfkChannelEvent -> { + modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_CHANNEL + val oldChannel = + event.oldAfkChannel + val newChannel = + event.newAfkChannel + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.old_channel", + null, + if (oldChannel != null) oldChannel.name + " (" + oldChannel.id + ")" else "-" + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.new_channel", + null, + if (newChannel != null) newChannel.name + " (" + newChannel.id + ")" else "-" + ) + ) + } + + is GuildUpdateAfkTimeoutEvent -> { + modlogEvent = ModlogEvent.GUILD_UPDATE_AFK_TIMEOUT + val oldTimeout = i18n( + event.getGuild().idLong, + "modlog.guild.timeout_seconds", + event.oldAfkTimeout.seconds + ) + val newTimeout = i18n( + event.getGuild().idLong, + "modlog.guild.timeout_seconds", + event.newAfkTimeout.seconds + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.timeout", + "modlog.general.small_change", + oldTimeout, + newTimeout + ) + ) + } + + is GuildUpdateBannerEvent -> { + if (event.oldBannerUrl != null) { + embedFieldList.add( + ModlogEmbedField( + false, "modlog.guild.old_image", null, + event.oldBannerUrl!! + ) + ) + } + if (event.newBannerUrl != null) { + embedFieldList.add( + ModlogEmbedField( + false, "modlog.guild.new_image", null, + event.newBannerUrl!! + ) + ) + } + modlogEvent = ModlogEvent.GUILD_UPDATE_BANNER + } + + is GuildUpdateDescriptionEvent -> { + if (event.oldDescription != null) { + embedFieldList.add( + ModlogEmbedField( + false, "modlog.guild.old_description", null, + event.oldDescription!! + ) + ) + } + if (event.newDescription != null) { + embedFieldList.add( + ModlogEmbedField( + false, "modlog.guild.new_description", null, + event.newDescription!! + ) + ) + } + modlogEvent = ModlogEvent.GUILD_UPDATE_DESCRIPTION + } + + is GuildUpdateExplicitContentLevelEvent -> { + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.content_filter.old", + "modlog.guild.content_filter." + event.oldLevel.name.toLowerCase() + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.content_filter.new", + "modlog.guild.content_filter." + event.newLevel.name.toLowerCase() + ) + ) + modlogEvent = ModlogEvent.GUILD_UPDATE_EXPLICIT_FILTER + } + + is GuildUpdateFeaturesEvent -> { + val featuresChanged = CollectionDiff( + event.oldFeatures, + event.newFeatures + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.add_feature", + null, + java.lang.String.join("\n", featuresChanged.added) + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.removed_feature", + null, + java.lang.String.join("\n", featuresChanged.removed) + ) + ) + modlogEvent = ModlogEvent.GUILD_UPDATE_FEATURES + } + + is GuildUpdateIconEvent -> { + val oldIconUrl = event.oldIconUrl + val newIconUrl = event.newIconUrl + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.old_image", + null, + oldIconUrl ?: "-" + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.new_image", + null, + newIconUrl ?: "-" + ) + ) + modlogEvent = ModlogEvent.GUILD_UPDATE_ICON + // The max members + // } else if (event instanceof GuildUpdateMaxMembersEvent) { + // String oldMembers = String.valueOf(((GuildUpdateMaxMembersEvent) event).getOldMaxMembers()); + // String newMembers = String.valueOf(((GuildUpdateMaxMembersEvent) event).getNewMaxMembers()); + // + // embedFieldList.add(new ModlogEmbedField(false, "modlog.guild.max_members", "modlog.general.small_change", oldMembers, newMembers)); + // modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_MEMBERS; + } + + is GuildUpdateMaxPresencesEvent -> { + val oldPresences = event.oldMaxPresences.toString() + val newPresences = event.newMaxPresences.toString() + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.max_presences", + "modlog.general.small_change", + oldPresences, + newPresences + ) + ) + responsible = null + modlogEvent = ModlogEvent.GUILD_UPDATE_MAX_PRESENCES + } + + is GuildUpdateMFALevelEvent -> { + val oldLevel = i18n( + event.getGuild().idLong, + "modlog.guild.mfa." + event.oldMFALevel.name.toLowerCase() + ) + val newLevel = i18n( + event.getGuild().idLong, + "modlog.guild.mfa." + event.newMFALevel.name.toLowerCase() + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.mfa.mfa_level", + "modlog.general.small_change", + oldLevel, + newLevel + ) + ) + modlogEvent = ModlogEvent.GUILD_UPDATE_MFA_LEVEL + } + + is GuildUpdateNameEvent -> { + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.general.old_name", + null, + event.oldName + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.general.new_name", + null, + event.newValue + ) + ) + modlogEvent = ModlogEvent.GUILD_UPDATE_NAME + } + + is GuildUpdateNotificationLevelEvent -> { + val oldLevel = i18n( + event.getGuild().idLong, + "modlog.guild.notification." + event.oldNotificationLevel.name.toLowerCase() + ) + val newLevel = i18n( + event.getGuild().idLong, + "modlog.guild.notification." + event.newNotificationLevel.name.toLowerCase() + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.notification.title", + "modlog.general.small_change", + oldLevel, + newLevel + ) + ) + modlogEvent = ModlogEvent.GUILD_UPDATE_NOTIFICATION_LEVEL + } + + is GuildUpdateRegionEvent -> { + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.old_region", + null, + event.oldRegion.getName() + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.new_region", + null, + event.newRegion.getName() + ) + ) + modlogEvent = ModlogEvent.GUILD_UPDATE_REGION + } + + is GuildUpdateSplashEvent -> { + val oldSplashUrl = event.oldSplashUrl + val newSplashUrl = event.newSplashUrl + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.old_splash", + null, + oldSplashUrl ?: "-" + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.new_splash", + null, + newSplashUrl ?: "-" + ) + ) + modlogEvent = ModlogEvent.GUILD_UPDATE_SPLASH + } + + is GuildUpdateSystemChannelEvent -> { + val oldSystemChannel = event.oldSystemChannel + val newSystemChannel = event.newSystemChannel + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.sys_channel", + "modlog.general.small_change", + oldSystemChannel?.asMention ?: "-", + newSystemChannel?.asMention ?: "-" + ) + ) + modlogEvent = ModlogEvent.GUILD_UPDATE_SYSTEM_CHANNEL + } + + is GuildUpdateVanityCodeEvent -> { + if (event.oldVanityCode != null) { + embedFieldList.add( + ModlogEmbedField( + false, "modlog.guild.vanity_code.old", null, + event.oldVanityCode!! + ) + ) + } + if (event.oldVanityUrl != null) { + embedFieldList.add( + ModlogEmbedField( + false, "modlog.guild.vanity_url.old", null, + event.oldVanityUrl!! + ) + ) + } + if (event.newVanityCode != null) { + embedFieldList.add( + ModlogEmbedField( + false, "modlog.guild.vanity_code.new", null, + event.newVanityCode!! + ) + ) + } + if (event.newVanityUrl != null) { + embedFieldList.add( + ModlogEmbedField( + false, "modlog.guild.vanity_url.new", null, + event.newVanityUrl!! + ) + ) + } + modlogEvent = ModlogEvent.GUILD_UPDATE_VANITY_CODE + } + + is GuildUpdateVerificationLevelEvent -> { + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.old_verification", + "utils.verification_level." + event.oldVerificationLevel.name.toLowerCase() + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.new_verification", + "utils.verification_level." + event.newVerificationLevel.name.toLowerCase() + ) + ) + modlogEvent = ModlogEvent.GUILD_UPDATE_VERIFICATION_LEVEL + } + + is GuildUpdateBoostCountEvent -> { + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.old_boost_count", + null, + event.oldValue.toString() + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.new_boost_count", + null, + event.newValue.toString() + ) + ) + modlogEvent = ModlogEvent.GUILD_BOOST_COUNT_UPDATED + } + + is GuildUpdateBoostTierEvent -> { + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.old_boost_tier", + "modlog.guild.boost_tier." + event.oldBoostTier.name.toLowerCase() + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.guild.new_boost_tier", + "modlog.guild.boost_tier." + event.newBoostTier.name.toLowerCase() + ) + ) + modlogEvent = ModlogEvent.GUILD_BOOST_TIER_UPDATED + } + + else -> { + return@Consumer + } + } + val eventStore = ModlogEventData(modlogEvent, responsible, affected, embedFieldList) + guildData.moderation.sendModlogEvent(event.guild.idLong, eventStore) + }, ActionType.GUILD_UPDATE) + } + + override fun onGenericGuildVoice(event: GenericGuildVoiceEvent) { + val affected = event.member.user + val guild = event.guild + val guildData = GuildDataManager.getGuildData(guild.idLong) + getAuditLogFromType( + event.guild, event.member.idLong, + Consumer { auditLogEntry: AuditLogEntry? -> + val embedFieldList: MutableList = ArrayList() + val extraDescriptionInfo: MutableList + val action: ModlogEvent + var responsible: User? = null + if (event is GuildVoiceDeafenEvent) { + val deafened = event.isDeafened + val emote = if (deafened) CascadeBot.INS.shardManager.getEmoteById( + Config.INS.globalEmotes["self-deafened"]!! + ) else CascadeBot.INS.shardManager.getEmoteById( + Config.INS.globalEmotes["undeafened"]!! + ) + extraDescriptionInfo = mutableListOf( + emote?.asMention ?: "", + deafened.toString() + ) + action = ModlogEvent.VOICE_DEAFEN + } else if (event is GuildVoiceMuteEvent) { + val muted = event.isMuted + val emote = if (muted) CascadeBot.INS.shardManager.getEmoteById( + Config.INS.globalEmotes["self-muted"]!! + ) else CascadeBot.INS.shardManager.getEmoteById( + Config.INS.globalEmotes["unmuted"]!! + ) + extraDescriptionInfo = mutableListOf(emote?.asMention ?: "", muted.toString()) + action = ModlogEvent.VOICE_MUTE + } else if (event is GuildVoiceGuildDeafenEvent) { + if (auditLogEntry != null && auditLogEntry.type == ActionType.MEMBER_UPDATE) { + responsible = auditLogEntry.user + } + val guildDeafened = event.isGuildDeafened + val emote = if (guildDeafened) CascadeBot.INS.shardManager.getEmoteById( + Config.INS.globalEmotes["server-deafened"]!! + ) else CascadeBot.INS.shardManager.getEmoteById( + Config.INS.globalEmotes["undeafened"]!! + ) + extraDescriptionInfo = mutableListOf( + emote?.asMention ?: "", + guildDeafened.toString() + ) + action = ModlogEvent.VOICE_SERVER_DEAFEN + } else if (event is GuildVoiceGuildMuteEvent) { + if (auditLogEntry != null && auditLogEntry.type == ActionType.MEMBER_UPDATE) { + responsible = auditLogEntry.user + } + val guildMuted = event.isGuildMuted + val emote = if (guildMuted) CascadeBot.INS.shardManager.getEmoteById( + Config.INS.globalEmotes["server-muted"]!! + ) else CascadeBot.INS.shardManager.getEmoteById( + Config.INS.globalEmotes["unmuted"]!! + ) + extraDescriptionInfo = mutableListOf( + emote?.asMention ?: "", + guildMuted.toString() + ) + action = ModlogEvent.VOICE_SERVER_MUTE + } else if (event is GuildVoiceJoinEvent) { + extraDescriptionInfo = mutableListOf(event.channelJoined.name) + action = ModlogEvent.VOICE_JOIN + } else if (event is GuildVoiceLeaveEvent) { + extraDescriptionInfo = mutableListOf(event.channelLeft.name) + if (auditLogEntry != null && auditLogEntry.type == ActionType.MEMBER_VOICE_KICK) { + action = ModlogEvent.VOICE_DISCONNECT + responsible = auditLogEntry.user + } else { + action = ModlogEvent.VOICE_LEAVE + } + } else if (event is GuildVoiceMoveEvent) { + extraDescriptionInfo = mutableListOf( + event.channelLeft.name, + event.channelJoined.name + ) + if (auditLogEntry != null && auditLogEntry.type == ActionType.MEMBER_VOICE_MOVE) { + action = ModlogEvent.VOICE_FORCE_MOVE + responsible = auditLogEntry.user + } else { + action = ModlogEvent.VOICE_MOVE + } + } else { + return@Consumer + } + val eventStore = ModlogEventData(action, responsible, affected, embedFieldList) + eventStore.extraDescriptionInfo = extraDescriptionInfo + guildData.moderation.sendModlogEvent(event.guild.idLong, eventStore) + }, ActionType.MEMBER_VOICE_MOVE, ActionType.MEMBER_VOICE_KICK, ActionType.MEMBER_UPDATE + ) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/RoleModlogEventListener.kt b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/RoleModlogEventListener.kt new file mode 100644 index 000000000..5663efab2 --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/RoleModlogEventListener.kt @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2021 CascadeBot. All rights reserved. + * Licensed under the MIT license. + */ + +package org.cascadebot.cascadebot.events.modlog + +import net.dv8tion.jda.api.Permission +import net.dv8tion.jda.api.audit.ActionType +import net.dv8tion.jda.api.audit.AuditLogEntry +import net.dv8tion.jda.api.entities.User +import net.dv8tion.jda.api.events.role.GenericRoleEvent +import net.dv8tion.jda.api.events.role.RoleCreateEvent +import net.dv8tion.jda.api.events.role.RoleDeleteEvent +import net.dv8tion.jda.api.events.role.update.RoleUpdateColorEvent +import net.dv8tion.jda.api.events.role.update.RoleUpdateHoistedEvent +import net.dv8tion.jda.api.events.role.update.RoleUpdateMentionableEvent +import net.dv8tion.jda.api.events.role.update.RoleUpdateNameEvent +import net.dv8tion.jda.api.events.role.update.RoleUpdatePermissionsEvent +import net.dv8tion.jda.api.events.role.update.RoleUpdatePositionEvent +import net.dv8tion.jda.api.hooks.ListenerAdapter +import org.cascadebot.cascadebot.CascadeBot +import org.cascadebot.cascadebot.data.Config +import org.cascadebot.cascadebot.data.managers.GuildDataManager +import org.cascadebot.cascadebot.data.objects.ModlogEventData +import org.cascadebot.cascadebot.moderation.ModlogEmbedField +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart +import org.cascadebot.cascadebot.moderation.ModlogEvent +import org.cascadebot.cascadebot.utils.ColorUtils.getHex +import org.cascadebot.cascadebot.utils.ModlogUtils.getAuditLogFromType +import org.cascadebot.cascadebot.utils.lists.CollectionDiff +import java.util.function.Consumer +import java.util.stream.Collectors + +class RoleModlogEventListener : ListenerAdapter() { + + override fun onGenericRole(event: GenericRoleEvent) { + val guildData = GuildDataManager.getGuildData(event.guild.idLong) + getAuditLogFromType(event.guild, event.role.idLong, + Consumer { auditLogEntry: AuditLogEntry? -> + val embedFieldList: MutableList = ArrayList() + val descriptionStuff: MutableList = ArrayList() + var responsible: User? = null + val modlogEvent: ModlogEvent + if (auditLogEntry != null) { + responsible = auditLogEntry.user + } else { + CascadeBot.LOGGER.warn("Modlog: Failed to find role audit log entry") + } + val affected = event.role + when (event) { + is RoleCreateEvent -> { + modlogEvent = ModlogEvent.ROLE_CREATED + } + + is RoleDeleteEvent -> { + modlogEvent = ModlogEvent.ROLE_DELETED + } + + is RoleUpdateColorEvent -> { + modlogEvent = ModlogEvent.ROLE_COLOR_UPDATED + roleColorUpdateEvent(event, embedFieldList) + } + + is RoleUpdateHoistedEvent -> { + modlogEvent = ModlogEvent.ROLE_HOIST_UPDATED + roleHoistedUpdateEvent(event, descriptionStuff) + } + + is RoleUpdateMentionableEvent -> { + modlogEvent = ModlogEvent.ROLE_MENTIONABLE_UPDATED + roleMentionableUpdateEvent(event, descriptionStuff) + } + + is RoleUpdateNameEvent -> { + modlogEvent = ModlogEvent.ROLE_NAME_UPDATED + roleNameUpdateEvent(event, embedFieldList) + } + + is RoleUpdatePermissionsEvent -> { + modlogEvent = ModlogEvent.ROLE_PERMISSIONS_UPDATED + rolePermissionUpdateEvent(event, embedFieldList) + } + + is RoleUpdatePositionEvent -> { + modlogEvent = ModlogEvent.ROLE_POSITION_UPDATED + roleUpdatePositionEvent(event, embedFieldList) + } + + else -> { + return@Consumer + } + } + val modlogEventData = ModlogEventData(modlogEvent, responsible, affected, embedFieldList) + modlogEventData.extraDescriptionInfo = descriptionStuff + guildData.moderation.sendModlogEvent(event.guild.idLong, modlogEventData) + }, ActionType.ROLE_CREATE, ActionType.ROLE_DELETE, ActionType.ROLE_UPDATE + ) + } + + private fun roleMentionableUpdateEvent( + event: RoleUpdateMentionableEvent, + descriptionStuff: MutableList + ) { + val emote = + if (event.newValue) CascadeBot.INS.shardManager + .getEmoteById( + Config.INS.globalEmotes["tick"]!! + ) else CascadeBot.INS.shardManager + .getEmoteById(Config.INS.globalEmotes["cross"]!!) + descriptionStuff.addAll( + mutableListOf( + emote?.asMention ?: "", + event.newValue.toString() + ) + ) + } + + private fun roleHoistedUpdateEvent( + event: RoleUpdateHoistedEvent, + descriptionStuff: MutableList + ) { + val wasHoisted = event.wasHoisted() + val emote = if (!wasHoisted) CascadeBot.INS.shardManager.getEmoteById( + Config.INS.globalEmotes["tick"]!! + ) else CascadeBot.INS.shardManager.getEmoteById( + Config.INS.globalEmotes["cross"]!! + ) + descriptionStuff.addAll( + listOf( + emote?.asMention ?: "", + (!wasHoisted).toString() + ) + ) + } + + private fun roleNameUpdateEvent( + event: RoleUpdateNameEvent, + embedFieldList: MutableList + ) { + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.general.old_name", + null, + event.oldName + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.general.new_name", + null, + event.newValue + ) + ) + } + + private fun roleColorUpdateEvent( + event: RoleUpdateColorEvent, + embedFieldList: MutableList + ) { + val oldColor = event.oldColor + val newColor = event.newColor + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.role.old_color", + if (oldColor != null) null else "words.default", + if (oldColor != null) getHex( + oldColor.red, + oldColor.green, + oldColor.blue + ) else "-" + ) + ) + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.role.new_color", + if (newColor != null) null else "words.default", + if (newColor != null) getHex( + newColor.red, + newColor.green, + newColor.blue + ) else "-" + ) + ) + } + + private fun rolePermissionUpdateEvent( + event: RoleUpdatePermissionsEvent, + embedFieldList: MutableList + ) { + val oldPermissions = + event.oldPermissions + val newPermissions = + event.newPermissions + val permissionListChanges = + CollectionDiff(oldPermissions, newPermissions) + if (permissionListChanges.added.isNotEmpty()) { + embedFieldList.add(ModlogEmbedField(false, + "modlog.role.added_perm", + null, + permissionListChanges.added.stream().map { obj: Permission -> obj.getName() } + .collect(Collectors.joining("\n")) + ) + ) + } + if (permissionListChanges.removed.isNotEmpty()) { + embedFieldList.add(ModlogEmbedField(false, + "modlog.role.removed_perm", + null, + permissionListChanges.removed.stream().map { obj: Permission -> obj.getName() } + .collect(Collectors.joining("\n")) + ) + ) + } + } + + private fun roleUpdatePositionEvent( + event: RoleUpdatePositionEvent, + embedFieldList: MutableList + ) { + if (event.newPosition == event.oldPosition) { + // If the position stays the same, we have no reason to log the event + return + } + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.general.position", + "modlog.general.small_change", + event.oldPosition + 1, + event.newPosition + 1 + ) + ) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/UserModlogEventListener.kt b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/UserModlogEventListener.kt new file mode 100644 index 000000000..9dd04ab3f --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/UserModlogEventListener.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 CascadeBot. All rights reserved. + * Licensed under the MIT license. + */ + +package org.cascadebot.cascadebot.events.modlog + +import net.dv8tion.jda.api.events.user.update.UserUpdateDiscriminatorEvent +import net.dv8tion.jda.api.events.user.update.UserUpdateNameEvent +import net.dv8tion.jda.api.hooks.ListenerAdapter +import org.cascadebot.cascadebot.CascadeBot +import org.cascadebot.cascadebot.data.managers.GuildDataManager +import org.cascadebot.cascadebot.data.objects.ModlogEventData +import org.cascadebot.cascadebot.moderation.ModlogEmbedField +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart +import org.cascadebot.cascadebot.moderation.ModlogEvent + +class UserModlogEventListener : ListenerAdapter() { + + override fun onUserUpdateName(event: UserUpdateNameEvent) { + val embedFieldList: MutableList = ArrayList() + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.general.name", + "modlog.general.small_change", + event.oldName, + event.newName + ) + ) + val modlogEventData = ModlogEventData(ModlogEvent.USER_NAME_UPDATED, event.user, event.user, embedFieldList) + for (guild in CascadeBot.INS.client.getMutualGuilds(event.user)) { + val guildData = GuildDataManager.getGuildData(guild.idLong) + guildData.moderation.sendModlogEvent(guild.idLong, modlogEventData) + } + } + + override fun onUserUpdateDiscriminator(event: UserUpdateDiscriminatorEvent) { + val embedFieldList: MutableList = ArrayList() + embedFieldList.add( + ModlogEmbedField( + false, + "modlog.member.discrim", + "modlog.general.small_change", + event.oldDiscriminator, + event.newDiscriminator + ) + ) + val modlogEventData = + ModlogEventData(ModlogEvent.USER_DISCRIMINATOR_UPDATED, event.user, event.user, embedFieldList) + for (guild in CascadeBot.INS.client.getMutualGuilds(event.user)) { + val guildData = GuildDataManager.getGuildData(guild.idLong) + guildData.moderation.sendModlogEvent(guild.idLong, modlogEventData) + } + } + +} \ No newline at end of file From 8b78435575bcca49314b5b5f0ab6067c914f5f0d Mon Sep 17 00:00:00 2001 From: William Oldham Date: Fri, 28 May 2021 22:03:25 +0100 Subject: [PATCH 142/206] Add proper gettings to Config to work with Kotlin --- .../org/cascadebot/cascadebot/data/Config.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/Config.java b/src/main/java/org/cascadebot/cascadebot/data/Config.java index 1f6a84ffd..eb03e8848 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/Config.java +++ b/src/main/java/org/cascadebot/cascadebot/data/Config.java @@ -37,7 +37,6 @@ import java.util.List; import java.util.Map; -@Getter public class Config { private static final Logger LOG = LoggerFactory.getLogger(Config.class); @@ -392,4 +391,20 @@ public int getPrometheusPort() { return prometheusPort; } + public byte[] getEncryptKey() { + return encryptKey; + } + + public String getRedisHost() { + return redisHost; + } + + public int getRedisPort() { + return redisPort; + } + + public String getRedisPassword() { + return redisPassword; + } + } From dbe6fed4957f05cddf04fd2aef16d05c8b873b4f Mon Sep 17 00:00:00 2001 From: William Oldham Date: Fri, 28 May 2021 22:53:27 +0100 Subject: [PATCH 143/206] Add emotes to channel perm overrides --- .../modlog/ChannelModlogEventListener.kt | 52 ++++++++++++++----- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/ChannelModlogEventListener.kt b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/ChannelModlogEventListener.kt index 36ace5fce..c0972aa13 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/ChannelModlogEventListener.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/ChannelModlogEventListener.kt @@ -126,7 +126,12 @@ class ChannelModlogEventListener : ListenerAdapter() { } is TextChannelUpdatePositionEvent -> { - handleChannelUpdatePositionEvents(event.getGuild(), ChannelType.TEXT, event.oldPosition, event.getChannel()) + handleChannelUpdatePositionEvents( + event.getGuild(), + ChannelType.TEXT, + event.oldPosition, + event.getChannel() + ) return } @@ -367,8 +372,12 @@ class ChannelModlogEventListener : ListenerAdapter() { event.getChannel(), event.getPermissionHolder() ) - if (current != "x") { - stringBuilder.append("x > ").append(current).append(": ").append(permission.getName()) + if (current != null && current != OverrideStatus.DENY) { + stringBuilder.append(OverrideStatus.DENY.emote) + .append(" ➜ ") + .append(current.emote) + .append(": ") + .append(permission.getName()) .append('\n') } } @@ -379,8 +388,12 @@ class ChannelModlogEventListener : ListenerAdapter() { event.getChannel(), event.getPermissionHolder() ) - if (current != "\\\\") { - stringBuilder.append("\\ > ").append(current).append(": ").append(permission.getName()) + if (current != null && current != OverrideStatus.INHERIT) { + stringBuilder.append(OverrideStatus.INHERIT.emote) + .append(" ➜ ") + .append(current.emote) + .append(": ") + .append(permission.getName()) .append('\n') } } @@ -391,8 +404,9 @@ class ChannelModlogEventListener : ListenerAdapter() { event.getChannel(), event.getPermissionHolder() ) - if (current != "+") { - stringBuilder.append("+ > ").append(current).append(": ").append(permission.getName()) + if (current != null && current != OverrideStatus.ALLOW) { + stringBuilder.append(OverrideStatus.ALLOW.emote).append(" ➜ ").append(current.emote) + .append(": ").append(permission.getName()) .append('\n') } } @@ -427,27 +441,39 @@ class ChannelModlogEventListener : ListenerAdapter() { permission: Permission, channel: GuildChannel, holder: IPermissionHolder? - ): String { - val permissionOverride = channel.getPermissionOverride(holder!!) ?: return "unknown" + ): OverrideStatus? { + val permissionOverride = channel.getPermissionOverride(holder!!) ?: return null return when { permissionOverride.allowed.contains(permission) -> { - "+" + OverrideStatus.ALLOW } permissionOverride.inherit.contains(permission) -> { - "\\\\" + OverrideStatus.INHERIT } permissionOverride.denied.contains(permission) -> { - "x" + OverrideStatus.DENY } else -> { - "unknown" + null } } } + enum class OverrideStatus(val emoteName: String, val text: String) { + ALLOW("perm_tick", "+"), + DENY("perm_cross", "-"), + INHERIT("perm_neutral", "\\\\"); + + val emote: String by lazy { + val emoteId = Config.INS.globalEmotes[emoteName] ?: return@lazy text + val emote = CascadeBot.INS.shardManager.getEmoteById(emoteId) ?: return@lazy text + return@lazy emote.asMention + } + } + //endregion //endregion From f06f7ce810f7fb9f5aabfcf725c35e639e1cb53e Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 29 May 2021 19:43:03 +0100 Subject: [PATCH 144/206] Formatting and tidying up --- .../modlog/ChannelModlogEventListener.kt | 7 ++- .../events/modlog/GuildModlogEventListener.kt | 48 +++++++++---------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/ChannelModlogEventListener.kt b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/ChannelModlogEventListener.kt index c0972aa13..5d3775e88 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/ChannelModlogEventListener.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/ChannelModlogEventListener.kt @@ -405,8 +405,11 @@ class ChannelModlogEventListener : ListenerAdapter() { event.getPermissionHolder() ) if (current != null && current != OverrideStatus.ALLOW) { - stringBuilder.append(OverrideStatus.ALLOW.emote).append(" ➜ ").append(current.emote) - .append(": ").append(permission.getName()) + stringBuilder.append(OverrideStatus.ALLOW.emote) + .append(" ➜ ") + .append(current.emote) + .append(": ") + .append(permission.getName()) .append('\n') } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/GuildModlogEventListener.kt b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/GuildModlogEventListener.kt index 7904aab42..e35bcb5dd 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/GuildModlogEventListener.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/events/modlog/GuildModlogEventListener.kt @@ -360,31 +360,29 @@ class GuildModlogEventListener : ListenerAdapter() { } message = try { CryptUtils.decryptString(Config.INS.encryptKey, iv, messageBytes) - } catch (e: NoSuchPaddingException) { - CascadeBot.LOGGER.error("Unable to decrypt message!", e) - return null - } catch (e: NoSuchAlgorithmException) { - CascadeBot.LOGGER.error("Unable to decrypt message!", e) - return null - } catch (e: InvalidAlgorithmParameterException) { - CascadeBot.LOGGER.error("Unable to decrypt message!", e) - return null - } catch (e: InvalidKeyException) { - CascadeBot.LOGGER.error("Unable to decrypt message!", e) - return null - } catch (e: IllegalBlockSizeException) { - CascadeBot.LOGGER.error("Unable to decrypt message!", e) - return null - } catch (e: ShortBufferException) { - CascadeBot.LOGGER.error("Unable to decrypt message!", e) - return null - } catch (e: BadPaddingException) { - // TODO emails? notifications? - CascadeBot.LOGGER.error( - "Unabled to decrypt message due to padding error! **This most likely means the data has been messed with**", - e - ) - return null + } catch (e: Exception) { + when (e) { + is NoSuchPaddingException, + is NoSuchAlgorithmException, + is InvalidAlgorithmParameterException, + is InvalidKeyException, + is IllegalBlockSizeException, + is ShortBufferException -> { + CascadeBot.LOGGER.error("Unable to decrypt message!", e) + return null + } + + is BadPaddingException -> { + // TODO emails? notifications? + CascadeBot.LOGGER.error( + "Unable to decrypt message due to padding error! **This most likely means the data has been messed with**", + e + ) + return null + } + + else -> return null + } } } else { message = messageString From 392f89d78c10ab6040c4fad6cf6335df709a6267 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 29 May 2021 20:20:37 +0100 Subject: [PATCH 145/206] Refactor filter create command to fit with modlog --- .../filters/FiltersCreateSubCommand.kt | 62 ++++++++++--------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersCreateSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersCreateSubCommand.kt index 5bee400d5..713a3d88d 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersCreateSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersCreateSubCommand.kt @@ -13,6 +13,7 @@ import org.cascadebot.cascadebot.data.objects.CommandFilter import org.cascadebot.cascadebot.data.objects.CommandFilter.FilterType import org.cascadebot.cascadebot.permissions.CascadePermission import org.cascadebot.cascadebot.utils.FormatUtils +import org.checkerframework.checker.units.qual.s class FiltersCreateSubCommand : SubCommand() { @@ -32,40 +33,45 @@ class FiltersCreateSubCommand : SubCommand() { return } + // A null filter type means that it will not be set on the filter and the default will be used + var type: FilterType? = null + // Args in the format " [type]" - if (context.args.size == 1) { - val filter = CommandFilter(name) - context.data.management.filters.add(filter) - if (context.data.management.filters.size >= 10 && context.data.management.warnOver10Filters) { - context.typedMessaging.replyWarning(context.i18n("commands.filters.create.over10warning")) - } - context.typedMessaging.replySuccess(context.i18n( - "commands.filters.create.created_filter", - FormatUtils.formatEnum(filter.type, context.locale), - filter.name - )) - } else { - val type = context.getArg(1) - if (EnumUtils.isValidEnumIgnoreCase(FilterType::class.java, type)) { - val filter = CommandFilter(name) - filter.type = EnumUtils.getEnumIgnoreCase(FilterType::class.java, type) - context.data.management.filters.add(filter) - if (context.data.management.filters.size >= 10 && context.data.management.warnOver10Filters) { - context.typedMessaging.replyWarning(context.i18n("commands.filters.create.over10warning")) - } - context.typedMessaging.replySuccess(context.i18n( - "commands.filters.create.created_filter", - FormatUtils.formatEnum(filter.type, context.locale), - filter.name - )) + if (context.args.size == 2) { + val typeInput = context.getArg(1) + if (EnumUtils.isValidEnumIgnoreCase(FilterType::class.java, typeInput)) { + type = EnumUtils.getEnumIgnoreCase(FilterType::class.java, typeInput) } else { context.typedMessaging.replyDanger(context.i18n( - "commands.filters.create.type_invalid", - type, - FilterType.values().joinToString(", ") { filterType -> "`" + FormatUtils.formatEnum(filterType, context.locale) + "`" } + "commands.filters.create.type_invalid", + typeInput, + FilterType.values().joinToString(", ") { filterType -> "`" + FormatUtils.formatEnum(filterType, context.locale) + "`" } )) + return } } + + val commandFilter: CommandFilter = createFilter(name, type) + + context.data.management.filters.add(commandFilter) + if (context.data.management.filters.size >= 10 && context.data.management.warnOver10Filters) { + context.typedMessaging.replyWarning(context.i18n("commands.filters.create.over10warning")) + } + + context.typedMessaging.replySuccess(context.i18n( + "commands.filters.create.created_filter", + FormatUtils.formatEnum(commandFilter.type, context.locale), + commandFilter.name + )) + + } + + private fun createFilter(name: String, type: FilterType?): CommandFilter { + val filter = CommandFilter(name) + if (type != null) { + filter.type = type + } + return filter } override fun command(): String = "create" From c024027ccf63c9bd91ef4fcf14bcb1a5d59f43df Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 29 May 2021 20:20:56 +0100 Subject: [PATCH 146/206] ModlogEvent: Add appropriate values for command filters --- .../kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt | 3 ++- .../cascadebot/cascadebot/data/objects/ModlogEventData.kt | 5 ++++- .../org/cascadebot/cascadebot/moderation/ModlogEvent.kt | 7 +++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt index ce30c10a8..26d1c75e6 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Enums.kt @@ -144,6 +144,7 @@ enum class AffectedType(vararg val allowedDisplayTypes: ModlogDisplayType) { MODULE(ModlogDisplayType.PLAIN), COMMAND(ModlogDisplayType.PLAIN), PLAYLIST(ModlogDisplayType.PLAIN), - TAG(ModlogDisplayType.PLAIN); + TAG(ModlogDisplayType.PLAIN), + COMMAND_FILTER(ModlogDisplayType.PLAIN); } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventData.kt index 9dbea300b..0e9c739e0 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/ModlogEventData.kt @@ -53,6 +53,9 @@ class ModlogEventData(val trigger: ModlogEvent, @Transient val responsible: User is Tag -> { ModlogAffected(AffectedType.TAG, affected.name, null, null, null) } + is CommandFilter -> { + ModlogAffected(AffectedType.COMMAND_FILTER, affected.name, null, null, null) + } else -> { ModlogAffected() } @@ -62,7 +65,7 @@ class ModlogEventData(val trigger: ModlogEvent, @Transient val responsible: User val responsibleId: Long = responsible?.idLong ?: 0 - constructor() : this(ModlogEvent.CASCADE_BLACKLIST, null, "", mutableListOf()) + constructor() : this(ModlogEvent.DUMMY, null, "", mutableListOf()) init { if (!this.affected.affectedType.allowedDisplayTypes.contains(trigger.displayType)) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt index 80ba08d4d..a09f857f7 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEvent.kt @@ -111,8 +111,11 @@ enum class ModlogEvent(@Transient val messageType: MessageType, val displayType: CASCADE_SOFT_BAN (MessageType.DANGER, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), CASCADE_PURGE (MessageType.DANGER, ModlogDisplayType.AFFECTED_THUMBNAIL, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_WHITELIST (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), - CASCADE_BLACKLIST (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_FILTER_CREATE (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.NAME, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_FILTER_DELETE (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.NAME, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_FILTER_UPDATE (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.NAME, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_FILTER_ENABLE (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.NAME, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), + CASCADE_FILTER_DISABLE (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.NAME, Category.CASCADE, Category.CASCADE_MODERATION, Category.MODERATION), CASCADE_SCRIPT_CREATED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), CASCADE_SCRIPT_DELETED (MessageType.WARNING, ModlogDisplayType.PLAIN, AffectedDisplayType.MENTION, Category.CASCADE, Category.CASCADE_CUSTOM_COMMANDS), From d1010cbd95eb9eda640f5ed027ace80dccfd3d93 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 29 May 2021 15:24:50 -0500 Subject: [PATCH 147/206] Find the difference between any arbitrary object --- .../cascadebot/utils/diff/Diff.java | 4 + .../cascadebot/utils/diff/DiffUtils.java | 76 +++++++++++++++++++ .../cascadebot/utils/diff/Difference.java | 25 ++++++ .../utils/diff/DifferenceChanged.java | 21 +++++ .../cascadebot/utils/lists/CollectionDiff.kt | 16 +++- 5 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/cascadebot/cascadebot/utils/diff/Diff.java create mode 100644 src/main/java/org/cascadebot/cascadebot/utils/diff/DiffUtils.java create mode 100644 src/main/java/org/cascadebot/cascadebot/utils/diff/Difference.java create mode 100644 src/main/java/org/cascadebot/cascadebot/utils/diff/DifferenceChanged.java diff --git a/src/main/java/org/cascadebot/cascadebot/utils/diff/Diff.java b/src/main/java/org/cascadebot/cascadebot/utils/diff/Diff.java new file mode 100644 index 000000000..9834a6826 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/utils/diff/Diff.java @@ -0,0 +1,4 @@ +package org.cascadebot.cascadebot.utils.diff; + +public interface Diff { +} diff --git a/src/main/java/org/cascadebot/cascadebot/utils/diff/DiffUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/diff/DiffUtils.java new file mode 100644 index 000000000..2bdc10f8e --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/utils/diff/DiffUtils.java @@ -0,0 +1,76 @@ +package org.cascadebot.cascadebot.utils.diff; + +import com.google.gson.reflect.TypeToken; +import lombok.SneakyThrows; +import org.cascadebot.cascadebot.CascadeBot; +import org.cascadebot.cascadebot.utils.lists.CollectionDiff; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class DiffUtils { + + public static Difference diff(Object oldObj, Object newObj) { + return diff(new Difference(), "", oldObj, newObj); + } + + @SneakyThrows + private static Difference diff(Difference currentDiff, String path, Object oldObj, Object newObj) { + Type mapType = new TypeToken>() { + }.getType(); + Map oldMap = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(oldObj), mapType); + Map newMap = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(newObj), mapType); + + List oldKeys = new ArrayList<>(oldMap.keySet()); + List newKeys = new ArrayList<>(oldMap.keySet()); + + CollectionDiff collectionDiff = new CollectionDiff<>(oldKeys, newKeys); + + for (String added : collectionDiff.getAdded()) { + currentDiff.added.put(path + added, newMap.get(added)); + } + + for (String removed : collectionDiff.getRemoved()) { + currentDiff.removed.put(path + removed, oldMap.get(removed)); + } + + for (String key : collectionDiff.getInBoth()) { + Object oldValue = oldMap.get(key); + Object newValue = newMap.get(key); + + if (!oldValue.equals(newValue)) { + System.out.println(Arrays.stream(newValue.getClass().getDeclaredFields()).map(Field::getName).collect(Collectors.joining(", "))); + + if (!oldValue.getClass().getTypeName().equals(newValue.getClass().getTypeName())) { + DifferenceChanged changed = new DifferenceChanged<>(oldValue, newValue); + currentDiff.changed.put(path + key, changed); + } else if (oldValue instanceof String) { + DifferenceChanged changed = new DifferenceChanged<>((String) oldValue, (String) newValue); + currentDiff.changed.put(path + key, changed); + } else if (oldValue instanceof Number) { + DifferenceChanged changed = new DifferenceChanged<>((Number) oldValue, (Number) newValue); + currentDiff.changed.put(path + key, changed); + } else if (oldValue instanceof Boolean) { + DifferenceChanged changed = new DifferenceChanged<>((Boolean) oldValue, (Boolean) newValue); + currentDiff.changed.put(path + key, changed); + } else if (oldValue instanceof Collection) { + CollectionDiff changed = new CollectionDiff<>((Collection) oldValue, (Collection) newValue); + currentDiff.changed.put(path + key, changed); + } else { + diff(currentDiff, path + key + ".", oldValue, newValue); + } + } + } + + return currentDiff; + } + + + +} diff --git a/src/main/java/org/cascadebot/cascadebot/utils/diff/Difference.java b/src/main/java/org/cascadebot/cascadebot/utils/diff/Difference.java new file mode 100644 index 000000000..810f82e2a --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/utils/diff/Difference.java @@ -0,0 +1,25 @@ +package org.cascadebot.cascadebot.utils.diff; + +import java.util.HashMap; +import java.util.Map; + +public class Difference { + + Map added = new HashMap<>(); + Map removed = new HashMap<>(); + + Map changed = new HashMap<>(); + + public Map getAdded() { + return added; + } + + public Map getRemoved() { + return removed; + } + + public Map getChanged() { + return changed; + } + +} diff --git a/src/main/java/org/cascadebot/cascadebot/utils/diff/DifferenceChanged.java b/src/main/java/org/cascadebot/cascadebot/utils/diff/DifferenceChanged.java new file mode 100644 index 000000000..0a5313ea0 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/utils/diff/DifferenceChanged.java @@ -0,0 +1,21 @@ +package org.cascadebot.cascadebot.utils.diff; + +public class DifferenceChanged implements Diff { + + private final T oldObj; + private final T newObj; + + public DifferenceChanged(T oldObj, T newObj) { + this.oldObj = oldObj; + this.newObj = newObj; + } + + public T getOldObj() { + return oldObj; + } + + public T getNewObj() { + return newObj; + } + +} diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt index 7eab69b69..b1e0fefeb 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt @@ -5,18 +5,25 @@ package org.cascadebot.cascadebot.utils.lists -class CollectionDiff(originalList: Collection, newList: Collection) { +import org.cascadebot.cascadebot.utils.diff.Diff + +class CollectionDiff(originalList: Collection, newList: Collection): Diff { private val _added: MutableList = ArrayList() private val _removed: MutableList = ArrayList() + private val _inBoth: MutableList = ArrayList() + val added get() = _added.toList() val removed get() = _removed.toList() + val inBoth + get() = _inBoth.toList() + init { val addedDiff = newList.toMutableList() @@ -45,6 +52,13 @@ class CollectionDiff(originalList: Collection, newList: Collection) { } _removed.addAll(removedDiff) + + // TODO account for duplicated + val both = originalList.toMutableList() + both.retainAll(newList) + + _inBoth.addAll(both) + } } \ No newline at end of file From 4c24807080b8329cd184f4049c2eeeb286aace72 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 29 May 2021 21:48:21 +0100 Subject: [PATCH 148/206] More util stuff --- .../cascadebot/cascadebot/utils/FormatUtils.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java index 0e2f31bdf..90acfb0f2 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/FormatUtils.java @@ -21,6 +21,7 @@ import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.internal.utils.Checks; import org.apache.commons.lang3.StringUtils; +import org.apache.tools.ant.taskdefs.Local; import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.UnicodeConstants; import org.cascadebot.cascadebot.data.Config; @@ -311,16 +312,25 @@ public static String formatDuration(long millis, Locale locale, boolean isShort, } @Deprecated - public static String formatEnum(T theEnum) { + public static > String formatEnum(T theEnum) { return StringUtils.capitalize(theEnum.name().toLowerCase().replace("_", " ")); } - public static String formatEnum(T theEnum, Locale locale) { + public static > String formatEnum(T theEnum, Locale locale) { + return formatEnum(theEnum, locale, false); + } + + public static > String formatEnum(T theEnum, Locale locale, boolean capitalize) { String path = "enums." + theEnum.getClass().getSimpleName().toLowerCase() + "." + theEnum.name().toLowerCase(); if (!Language.hasLanguageEntry(locale, path)) { return formatEnum(theEnum); } - return Language.i18n(locale, path); + + String i18nEnum = Language.i18n(locale, path); + if (capitalize) { + i18nEnum = ExtensionsKt.toCapitalized(i18nEnum); + } + return i18nEnum; } public static String formatUnicode(String stringToFormat) { From d129e25482ae3fead00baa03b9ac0c1b7098fd5b Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 29 May 2021 21:48:28 +0100 Subject: [PATCH 149/206] Modlog event for filter creation --- .../filters/FiltersCreateSubCommand.kt | 11 +++++++ .../cascadebot/moderation/ModlogEmbedPart.kt | 3 +- src/main/resources/lang/en-GB.json | 29 ++++++++++++++----- 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersCreateSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersCreateSubCommand.kt index 713a3d88d..43f109b87 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersCreateSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersCreateSubCommand.kt @@ -11,6 +11,10 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext import org.cascadebot.cascadebot.commandmeta.SubCommand import org.cascadebot.cascadebot.data.objects.CommandFilter import org.cascadebot.cascadebot.data.objects.CommandFilter.FilterType +import org.cascadebot.cascadebot.data.objects.ModlogEventData +import org.cascadebot.cascadebot.moderation.ModlogEmbedField +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart +import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.permissions.CascadePermission import org.cascadebot.cascadebot.utils.FormatUtils import org.checkerframework.checker.units.qual.s @@ -64,6 +68,13 @@ class FiltersCreateSubCommand : SubCommand() { commandFilter.name )) + val embedFieldList = mutableListOf() + + embedFieldList.add(ModlogEmbedField(true, "words.type", null, FormatUtils.formatEnum(commandFilter.type, context.locale, true))) + + val eventStore = ModlogEventData(ModlogEvent.CASCADE_FILTER_CREATE, context.user, commandFilter, embedFieldList) + context.data.moderation.sendModlogEvent(context.guild.idLong, eventStore) + } private fun createFilter(name: String, type: FilterType?): CommandFilter { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt index 9afd7f8c8..57a551b50 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/moderation/ModlogEmbedPart.kt @@ -4,6 +4,7 @@ import club.minnced.discord.webhook.send.WebhookEmbed import club.minnced.discord.webhook.send.WebhookEmbedBuilder import org.cascadebot.cascadebot.data.language.Language import org.cascadebot.cascadebot.data.language.Locale +import org.cascadebot.cascadebot.utils.toCapitalized sealed class ModlogEmbedPart { @@ -37,7 +38,7 @@ class ModlogEmbedField(val inline: Boolean = true, override fun build(locale: Locale, embedBuilder: WebhookEmbedBuilder) { embedBuilder.addField(WebhookEmbed.EmbedField(inline, - Language.i18n(locale, titleLanguagePath, *titleLanguageObjects.toTypedArray()), + Language.i18n(locale, titleLanguagePath, *titleLanguageObjects.toTypedArray()).toCapitalized(), Language.i18n(locale, valueLanguagePath ?: "modlog.general.variable", *valueLanguageObjects.toTypedArray()))) } diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 32ddaa585..0563e4e02 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1875,13 +1875,26 @@ "display": "Cascade purge", "description": "Purged {2} messages from {0}" }, - "cascade_whitelist": { - "select": "cascade_whitelist", - "display": "Cascade whitelist" + "cascade_filter_create": { + "select": "cascade_filter_create", + "display": "Command filter created", + "description": "The command filter with the name `{0}` has been created!" }, - "cascade_blacklist": { - "select": "cascade_blacklist", - "display": "Cascade blacklist" + "cascade_filter_delete": { + "select": "cascade_filter_delete", + "display": "Command filter deleted" + }, + "cascade_filter_update": { + "select": "cascade_filter_update", + "display": "Command filter updated" + }, + "cascade_filter_enable": { + "select": "cascade_filter_enable", + "display": "Command filter enabled" + }, + "cascade_filter_disable": { + "select": "cascade_filter_disable", + "display": "Command filter disabled" }, "cascade_script_created": { "select": "cascade_script_created", @@ -2028,7 +2041,9 @@ "command_filters": "command filters", "unknown": "unknown", "yes_words": ["yes", "true", "on"], - "no_words": ["no", "false", "off"] + "no_words": ["no", "false", "off"], + "name": "name", + "type": "type" }, "messaging": { "loading_page": "Paged message loading...", From 8f2b3ac897e43148b19366845c4f77fdfaa4824b Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 29 May 2021 16:02:41 -0500 Subject: [PATCH 150/206] Saving parts of guild data --- .../module/ModuleEnableSubCommand.java | 25 +++++++------ .../data/managers/GuildDataManager.java | 35 +++++++++++++++++- .../cascadebot/data/objects/GuildData.kt | 36 ++++++++++++++++++- 3 files changed, 83 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java index 2ab30d2a8..3ab0ed45a 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java @@ -33,17 +33,20 @@ public void onCommand(Member sender, CommandContext context) { if (module != null) { String moduleName = ExtensionsKt.toCapitalized(FormatUtils.formatEnum(module, context.getLocale())); try { - if (context.getCoreSettings().enableModule(module)) { - // If the module wasn't enabled - context.getTypedMessaging().replySuccess(context.i18n("commands.module.enable.enabled", moduleName)); - ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), module, List.of()); - eventStore.setExtraDescriptionInfo(List.of("true")); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - } else { - // If the module was enabled - context.getTypedMessaging().replyInfo(context.i18n("commands.module.enable.already_enabled", moduleName)); - } + context.getData().write(data -> { + if (data.getCore().enableModule(module)) { + // If the module wasn't enabled + context.getTypedMessaging().replySuccess(context.i18n("commands.module.enable.enabled", moduleName)); + ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), module, List.of()); + eventStore.setExtraDescriptionInfo(List.of("true")); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + } else { + // If the module was enabled + context.getTypedMessaging().replyInfo(context.i18n("commands.module.enable.already_enabled", moduleName)); + } + }); + } catch (IllegalArgumentException ex) { context.getTypedMessaging().replyDanger(ex.getMessage()); } diff --git a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java index 357515b03..f1d493044 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java @@ -7,12 +7,20 @@ import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; +import com.mongodb.client.model.Updates; import org.bson.conversions.Bson; import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.data.database.DebugLogCallback; import org.cascadebot.cascadebot.data.objects.GuildData; import org.cascadebot.cascadebot.events.GuildSaveListener; +import org.cascadebot.cascadebot.utils.diff.Diff; +import org.cascadebot.cascadebot.utils.diff.Difference; +import org.cascadebot.cascadebot.utils.diff.DifferenceChanged; +import org.cascadebot.cascadebot.utils.lists.CollectionDiff; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import static com.mongodb.client.model.Filters.eq; @@ -42,7 +50,32 @@ public final class GuildDataManager { public static void update(long id, Bson update) { CascadeBot.INS.getDatabaseManager().runAsyncTask(database -> { database.getCollection(COLLECTION, GuildData.class).updateOne(eq("_id", id), update, new DebugLogCallback<>("Updated Guild ID " + id + ":", update)); - }); + });; + } + + public static void updateDiff(long id, Difference difference) { + List bsonList = new ArrayList<>(); + for (Map.Entry added : difference.getAdded().entrySet()) { + bsonList.add(Updates.set(added.getKey(), added.getValue())); + } + for (Map.Entry changed : difference.getChanged().entrySet()) { + if (changed.getValue() instanceof CollectionDiff) { + for (Object obj : ((CollectionDiff) changed.getValue()).getAdded()) { + bsonList.add(Updates.addToSet(changed.getKey(), obj)); + } + for (Object obj : ((CollectionDiff) changed.getValue()).getRemoved()) { + bsonList.add(Updates.pull(changed.getKey(), obj)); + } + } else if (changed.getValue() instanceof DifferenceChanged) { + bsonList.add(Updates.set(changed.getKey(), ((DifferenceChanged) changed.getValue()).getNewObj())); + } + } + for (String removed : difference.getRemoved().keySet()) { + bsonList.add(Updates.unset(removed)); + } + CascadeBot.INS.getDatabaseManager().runAsyncTask(database -> { + database.getCollection(COLLECTION, GuildData.class).updateMany(eq("_id", id), Updates.combine(bsonList), new DebugLogCallback<>("Updated Guild ID " + id)); + });; } public static void insert(long id, GuildData data) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 69b3f45a0..6e0bc85ba 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -1,20 +1,39 @@ package org.cascadebot.cascadebot.data.objects +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.util.ClassUtil.classOf import com.google.common.collect.Sets +import com.google.gson.GsonBuilder +import com.google.gson.JsonParser +import com.google.gson.reflect.TypeToken import de.bild.codec.annotations.Id import de.bild.codec.annotations.Transient import net.dv8tion.jda.api.entities.Message import net.dv8tion.jda.api.entities.MessageChannel import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.data.language.Locale +import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.music.CascadeLavalinkPlayer import org.cascadebot.cascadebot.utils.buttons.ButtonGroup import org.cascadebot.cascadebot.utils.buttons.ButtonsCache import org.cascadebot.cascadebot.utils.buttons.PersistentButtonGroup +import org.cascadebot.cascadebot.utils.diff.DiffUtils +import org.cascadebot.cascadebot.utils.diff.Difference import org.cascadebot.cascadebot.utils.pagination.PageCache +import java.lang.reflect.Type import java.util.Date +import java.util.concurrent.locks.ReadWriteLock +import java.util.concurrent.locks.ReentrantReadWriteLock +import java.util.function.Consumer +import kotlin.concurrent.withLock +import kotlin.reflect.jvm.javaType +import kotlin.reflect.typeOf -class GuildData(@field:Id val guildId: Long) { +class GuildData(@field:Id val guildId: Long): Cloneable { + + @Transient + @kotlin.jvm.Transient + var lock: ReadWriteLock = ReentrantReadWriteLock() private constructor() : this(0L) { // Private constructor for MongoDB @@ -44,12 +63,15 @@ class GuildData(@field:Id val guildId: Long) { //region Transient fields @Transient + @kotlin.jvm.Transient val buttonsCache = ButtonsCache(5) @Transient + @kotlin.jvm.Transient val pageCache = PageCache() @Transient + @kotlin.jvm.Transient val permissionsManager = PerGuildPermissionsManager() //endregion @@ -109,5 +131,17 @@ class GuildData(@field:Id val guildId: Long) { //endregion + public fun write(writer: Consumer) { + this.lock.writeLock().withLock { + val copy: GuildData = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(this), this.javaClass) + writer.accept(copy); + val diff: Difference = DiffUtils.diff(this, copy) + GuildDataManager.updateDiff(guildId, diff) + //println(GsonBuilder().setPrettyPrinting().create().toJson(diff)) + } + } } + + + From d6847c4be0f0db817313ec36ad53c4d3847f870b Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 29 May 2021 16:34:49 -0500 Subject: [PATCH 151/206] Update guild in cache --- .../module/ModuleDisableSubCommand.java | 24 ++++++++++--------- .../data/managers/GuildDataManager.java | 4 +++- .../cascadebot/data/objects/GuildData.kt | 2 +- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java index b71ad1439..b1e73172b 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java @@ -33,17 +33,19 @@ public void onCommand(Member sender, CommandContext context) { if (module != null) { String moduleName = ExtensionsKt.toCapitalized(FormatUtils.formatEnum(module, context.getLocale())); try { - if (context.getData().getCore().disableModule(module)) { - // If module wasn't already disabled - context.getTypedMessaging().replySuccess(context.i18n("commands.module.disable.disabled", moduleName)); - ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), module, List.of()); - eventStore.setExtraDescriptionInfo(List.of("false")); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - } else { - // If module was already disabled - context.getTypedMessaging().replyInfo(context.i18n("commands.module.disable.already_disabled", moduleName)); - } + context.getData().write(guildData -> { + if (guildData.getCore().disableModule(module)) { + // If module wasn't already disabled + context.getTypedMessaging().replySuccess(context.i18n("commands.module.disable.disabled", moduleName)); + ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), module, List.of()); + eventStore.setExtraDescriptionInfo(List.of("false")); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + } else { + // If module was already disabled + context.getTypedMessaging().replyInfo(context.i18n("commands.module.disable.already_disabled", moduleName)); + } + }); } catch (IllegalArgumentException ex) { context.getTypedMessaging().replyDanger(ex.getMessage()); } diff --git a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java index f1d493044..d699cef4b 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java @@ -8,6 +8,7 @@ import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; import com.mongodb.client.model.Updates; +import org.bson.BsonDocument; import org.bson.conversions.Bson; import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.data.database.DebugLogCallback; @@ -53,7 +54,7 @@ public static void update(long id, Bson update) { });; } - public static void updateDiff(long id, Difference difference) { + public static void updateDiff(long id, Difference difference, GuildData newData) { List bsonList = new ArrayList<>(); for (Map.Entry added : difference.getAdded().entrySet()) { bsonList.add(Updates.set(added.getKey(), added.getValue())); @@ -76,6 +77,7 @@ public static void updateDiff(long id, Difference difference) { CascadeBot.INS.getDatabaseManager().runAsyncTask(database -> { database.getCollection(COLLECTION, GuildData.class).updateMany(eq("_id", id), Updates.combine(bsonList), new DebugLogCallback<>("Updated Guild ID " + id)); });; + guilds.put(newData.getGuildId(), newData); } public static void insert(long id, GuildData data) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 6e0bc85ba..87bfda7b9 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -136,7 +136,7 @@ class GuildData(@field:Id val guildId: Long): Cloneable { val copy: GuildData = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(this), this.javaClass) writer.accept(copy); val diff: Difference = DiffUtils.diff(this, copy) - GuildDataManager.updateDiff(guildId, diff) + GuildDataManager.updateDiff(guildId, diff, copy) //println(GsonBuilder().setPrettyPrinting().create().toJson(diff)) } } From 2bc020002f2f140ed3c8d6371b2f3d9a86167d6d Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 29 May 2021 22:51:34 +0100 Subject: [PATCH 152/206] If the item is replaced, don't save it! --- .../java/org/cascadebot/cascadebot/events/GuildSaveListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/cascadebot/cascadebot/events/GuildSaveListener.java b/src/main/java/org/cascadebot/cascadebot/events/GuildSaveListener.java index 8d97f5e5a..72756f4fc 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/GuildSaveListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/GuildSaveListener.java @@ -19,6 +19,7 @@ public class GuildSaveListener implements RemovalListener { @Override public void onRemoval(@Nullable Long aLong, @Nullable GuildData data, @Nonnull RemovalCause removalCause) { if (aLong == null) return; + if (removalCause == RemovalCause.REPLACED) return; GuildDataManager.replace(aLong, data); CascadeBot.LOGGER.debug("Guild with ID: {} was saved to the database as it was removed from the map due to: {}", aLong, removalCause.toString()); // TODO: FUTURE: Use this for statistics? From 1a427721df158ae3221654d1cbdbfd7632ab56a6 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 29 May 2021 17:35:42 -0500 Subject: [PATCH 153/206] Change streams --- .../java/org/cascadebot/cascadebot/CascadeBot.java | 13 +++++++++++++ .../cascadebot/data/managers/GuildDataManager.java | 9 ++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 03b8bac2f..0949edcd3 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -12,6 +12,7 @@ import ch.qos.logback.core.encoder.LayoutWrappingEncoder; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.mongodb.async.client.ChangeStreamIterable; import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory; import io.sentry.Sentry; import io.sentry.SentryClient; @@ -32,6 +33,7 @@ import org.cascadebot.cascadebot.data.database.DatabaseManager; import org.cascadebot.cascadebot.data.managers.GuildDataManager; import org.cascadebot.cascadebot.data.managers.ScheduledActionManager; +import org.cascadebot.cascadebot.data.objects.GuildData; import org.cascadebot.cascadebot.events.BotEvents; import org.cascadebot.cascadebot.events.ButtonEventListener; import org.cascadebot.cascadebot.events.CommandListener; @@ -196,6 +198,17 @@ private void init() { ); } + databaseManager.runAsyncTask(database -> { + ChangeStreamIterable changeStreamIterable = database.getCollection(GuildDataManager.COLLECTION, GuildData.class).watch(); + new Thread(() -> changeStreamIterable.forEach(guildDataChangeStreamDocument -> + GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()), (result, throwable) -> { + if (throwable != null) { + throwable.printStackTrace(); + } + System.out.println(result); + }), "mongoChangeWatch").start(); + }); + musicHandler = new MusicHandler(); eventWaiter = new EventWaiter(); diff --git a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java index d699cef4b..ac8ffafa1 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java @@ -7,7 +7,10 @@ import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; +import com.mongodb.Block; +import com.mongodb.async.client.ChangeStreamIterable; import com.mongodb.client.model.Updates; +import com.mongodb.client.model.changestream.ChangeStreamDocument; import org.bson.BsonDocument; import org.bson.conversions.Bson; import org.cascadebot.cascadebot.CascadeBot; @@ -28,7 +31,7 @@ public final class GuildDataManager { - private static final String COLLECTION = "guilds"; + public static final String COLLECTION = "guilds"; private static LoadingCache guilds = Caffeine.newBuilder() .expireAfterAccess(5, TimeUnit.MINUTES) @@ -92,6 +95,10 @@ public static void replace(long id, GuildData data) { }); } + public static void replaceInternal(GuildData guildData) { + guilds.put(guildData.getGuildId(), guildData); + } + public static void replaceSync(long id, GuildData data) { CascadeBot.INS.getDatabaseManager().runTask(database -> { database.getCollection(COLLECTION, GuildData.class).replaceOne(eq("_id", id), data); From 58528c625d8e4eaf7b9c2941837f5ce2f1def40d Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 29 May 2021 17:47:11 -0500 Subject: [PATCH 154/206] Remove save listener --- .../cascadebot/cascadebot/data/managers/GuildDataManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java index ac8ffafa1..f072869f9 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java @@ -35,7 +35,7 @@ public final class GuildDataManager { private static LoadingCache guilds = Caffeine.newBuilder() .expireAfterAccess(5, TimeUnit.MINUTES) - .removalListener(new GuildSaveListener()) + //.removalListener(new GuildSaveListener()) .recordStats() .build(id -> { GuildData dbData = CascadeBot.INS.getDatabaseManager().getDatabase().getCollection(COLLECTION, GuildData.class).find(eq("_id", id)).first(); From 00ca47dbfbe41e5977a07694c67c3bd5b6a24c16 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sat, 29 May 2021 18:05:14 -0500 Subject: [PATCH 155/206] Write mode, and start of implementing writing everywhere --- .../developer/GuildFlagSubCommand.java | 20 +++++++++---------- .../data/managers/GuildDataManager.java | 2 +- .../data/objects/GuildSettingsUseful.java | 5 +++++ .../cascadebot/data/objects/GuildData.kt | 19 +++++++++++++++++- .../data/objects/GuildSettingsCore.kt | 11 ++++++++++ .../data/objects/GuildSettingsManagement.kt | 4 ++++ .../data/objects/GuildSettingsModeration.kt | 5 +++++ .../cascadebot/data/objects/TodoList.kt | 1 - 8 files changed, 54 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/developer/GuildFlagSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/developer/GuildFlagSubCommand.java index 38d4e46e1..803a53f40 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/developer/GuildFlagSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/developer/GuildFlagSubCommand.java @@ -14,7 +14,6 @@ import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.managers.GuildDataManager; import org.cascadebot.cascadebot.data.objects.Flag; -import org.cascadebot.cascadebot.data.objects.GuildData; import org.cascadebot.cascadebot.messaging.MessagingObjects; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.utils.FormatUtils; @@ -59,15 +58,16 @@ public void onCommand(Member sender, CommandContext context) { } } - GuildData guildData = GuildDataManager.getGuildData(guild.getIdLong()); - - if (guildData.isFlagEnabled(flag)) { - guildData.disableFlag(flag); - context.getTypedMessaging().replySuccess("Disabled flag `%s` for guild `%s (%s)`", FormatUtils.formatEnum(flag, guildData.getLocale()), guild.getName(), guild.getId()); - } else { - guildData.enableFlag(flag); - context.getTypedMessaging().replySuccess("Enabled flag `%s` for guild `%s (%s)`", FormatUtils.formatEnum(flag, guildData.getLocale()), guild.getName(), guild.getId()); - } + Guild finalGuild = guild; + GuildDataManager.getGuildData(guild.getIdLong()).write(guildData -> { + if (guildData.isFlagEnabled(flag)) { + guildData.disableFlag(flag); + context.getTypedMessaging().replySuccess("Disabled flag `%s` for guild `%s (%s)`", FormatUtils.formatEnum(flag, guildData.getLocale()), finalGuild.getName(), finalGuild.getId()); + } else { + guildData.enableFlag(flag); + context.getTypedMessaging().replySuccess("Enabled flag `%s` for guild `%s (%s)`", FormatUtils.formatEnum(flag, guildData.getLocale()), finalGuild.getName(), finalGuild.getId()); + } + }); } } diff --git a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java index f072869f9..e0b17e5fe 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java @@ -35,7 +35,7 @@ public final class GuildDataManager { private static LoadingCache guilds = Caffeine.newBuilder() .expireAfterAccess(5, TimeUnit.MINUTES) - //.removalListener(new GuildSaveListener()) + //.removalListener(new GuildSaveListener()) TODO do we want to use still use this? .recordStats() .build(id -> { GuildData dbData = CascadeBot.INS.getDatabaseManager().getDatabase().getCollection(COLLECTION, GuildData.class).find(eq("_id", id)).first(); diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java index 71e36a387..87e2b8774 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java @@ -10,12 +10,15 @@ public class GuildSettingsUseful { private Map todoLists = new ConcurrentHashMap<>(); + boolean writeMode = false; + //region todo list stuff public TodoList getTodoList(String name) { return todoLists.get(name); } public TodoList createTodoList(String name, long owner) { + if (!writeMode) throw new UnsupportedOperationException("Cannot modify Guild data if not in write mode!"); if (todoLists.containsKey(name)) { return null; } @@ -25,10 +28,12 @@ public TodoList createTodoList(String name, long owner) { } public void deleteTodoList(String name) { + if (!writeMode) throw new UnsupportedOperationException("Cannot modify Guild data if not in write mode!"); todoLists.remove(name); } public TodoList getTodoListByMessage(long messageId) { + if (!writeMode) throw new UnsupportedOperationException("Cannot modify Guild data if not in write mode!"); TodoList list = null; for (Map.Entry listEntry : todoLists.entrySet()) { if (listEntry.getValue().getMessageId() == messageId) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 87bfda7b9..180de644d 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -20,6 +20,7 @@ import org.cascadebot.cascadebot.utils.buttons.PersistentButtonGroup import org.cascadebot.cascadebot.utils.diff.DiffUtils import org.cascadebot.cascadebot.utils.diff.Difference import org.cascadebot.cascadebot.utils.pagination.PageCache +import java.lang.UnsupportedOperationException import java.lang.reflect.Type import java.util.Date import java.util.concurrent.locks.ReadWriteLock @@ -35,6 +36,10 @@ class GuildData(@field:Id val guildId: Long): Cloneable { @kotlin.jvm.Transient var lock: ReadWriteLock = ReentrantReadWriteLock() + @Transient + @kotlin.jvm.Transient + var writeMode = false; + private constructor() : this(0L) { // Private constructor for MongoDB } @@ -121,6 +126,8 @@ class GuildData(@field:Id val guildId: Long): Cloneable { } private fun putPersistentButtonGroup(channelId: Long, messageId: Long, buttonGroup: PersistentButtonGroup) { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + if (persistentButtons.containsKey(channelId) && persistentButtons[channelId] != null) { persistentButtons[channelId]!![messageId] = buttonGroup } else { @@ -131,16 +138,26 @@ class GuildData(@field:Id val guildId: Long): Cloneable { //endregion - public fun write(writer: Consumer) { + fun write(writer: Consumer) { this.lock.writeLock().withLock { val copy: GuildData = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(this), this.javaClass) + copy.setAllWriteMode(true) writer.accept(copy); + copy.setAllWriteMode(false) val diff: Difference = DiffUtils.diff(this, copy) GuildDataManager.updateDiff(guildId, diff, copy) //println(GsonBuilder().setPrettyPrinting().create().toJson(diff)) } } + fun setAllWriteMode(mode: Boolean) { + writeMode = mode + core.writeMode = mode + useful.writeMode = mode + management.writeMode = mode + moderation.writeMode = mode + } + } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt index 507693cb1..871b79bc2 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt @@ -6,6 +6,7 @@ import org.cascadebot.cascadebot.commandmeta.MainCommand import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.Config import org.cascadebot.cascadebot.data.language.Locale +import java.lang.UnsupportedOperationException import java.util.concurrent.ConcurrentHashMap @@ -36,6 +37,8 @@ class GuildSettingsCore { @Setting var helpShowAllModules = false + var writeMode = false + var locale: Locale = Locale.getDefaultLocale() var prefix: String = Config.INS.defaultPrefix @@ -44,11 +47,13 @@ class GuildSettingsCore { //region Modules fun enableModule(module: Module): Boolean { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") require(!module.isPrivate) { "This module is not available to be enabled!" } return enabledModules.add(module) } fun disableModule(module: Module): Boolean { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") require(!module.isPrivate) { "This module is not available to be disabled!" } require(!module.isRequired) { "Cannot disable the ${module.toString().toLowerCase()} module!" } return enabledModules.remove(module) @@ -67,6 +72,7 @@ class GuildSettingsCore { //region Commands fun enableCommand(command: MainCommand) { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") if (command.module().isPrivate) return if (commandInfo.contains(command.javaClass)) { getGuildCommandInfo(command).enabled = true @@ -74,6 +80,7 @@ class GuildSettingsCore { } fun enableCommandByModule(module: Module) { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") if (module.isPrivate) return for (command in CascadeBot.INS.commandManager.getCommandsByModule(module)) { enableCommand(command) @@ -81,11 +88,13 @@ class GuildSettingsCore { } fun disableCommand(command: MainCommand) { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") if (command.module().isPrivate) return getGuildCommandInfo(command).enabled = false } fun disableCommandByModule(module: Module) { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") if (module.isPrivate) return for (command in CascadeBot.INS.commandManager.getCommandsByModule(module)) { disableCommand(command) @@ -105,10 +114,12 @@ class GuildSettingsCore { } fun addAlias(command: MainCommand, alias: String): Boolean { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") return getGuildCommandInfo(command).aliases.add(alias) } fun removeAlias(command: MainCommand, alias: String): Boolean { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") return getGuildCommandInfo(command).aliases.remove(alias) } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt index b766cf937..9559fc5ea 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt @@ -21,6 +21,8 @@ class GuildSettingsManagement { val greetings = Greetings() val autoRoles: MutableSet = mutableSetOf() + var writeMode = false + fun getTag(key: String): Tag? { return tags[key] } @@ -30,10 +32,12 @@ class GuildSettingsManagement { } fun addTag(key: String, tag: Tag) { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") tags[key] = tag } fun removeTag(key: String): Boolean { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") return tags.remove(key) != null } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 205180796..73c5fede7 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -26,6 +26,8 @@ import java.util.function.Consumer @SettingsContainer(module = Module.MODERATION) class GuildSettingsModeration { + var writeMode = false + var modlogChannelNum: Int = 1; @Setting @@ -72,6 +74,7 @@ class GuildSettingsModeration { } fun enableEvent(channel: TextChannel, event: ModlogEvent): Boolean { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") if (modlogEvents.containsKey(channel.idLong)) { return modlogEvents[channel.idLong]!!.addEvent(event) } else { @@ -81,6 +84,7 @@ class GuildSettingsModeration { } fun disableEvent(channel: TextChannel, event: ModlogEvent): Boolean { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") if (modlogEvents.containsKey(channel.idLong)) { return modlogEvents[channel.idLong]!!.removeEvent(event) } else { @@ -89,6 +93,7 @@ class GuildSettingsModeration { } fun enableEventByCategory(channel: TextChannel, category: ModlogEvent.Category) { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") for (modlogEvent in ModlogEvent.getEventsFromCategory(category)) { enableEvent(channel, modlogEvent) } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt index 72220db99..025f70317 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt @@ -12,7 +12,6 @@ import org.cascadebot.cascadebot.messaging.Messaging.sendButtonedMessage import org.cascadebot.cascadebot.messaging.MessagingObjects import org.cascadebot.cascadebot.utils.buttons.PersistentButton import org.cascadebot.cascadebot.utils.buttons.PersistentButtonGroup -import java.util.ArrayList class TodoList(val ownerId: Long) { From 44cf30975e1d28367d52d7e5d041d0ace090fea1 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 30 May 2021 09:22:17 -0500 Subject: [PATCH 156/206] Handle update data without full document --- pom.xml | 6 ++ .../org/cascadebot/cascadebot/CascadeBot.java | 59 ++++++++++++++++++- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b6b03952b..d9ca1ede9 100644 --- a/pom.xml +++ b/pom.xml @@ -460,6 +460,12 @@ 1.19 + + org.springframework.data + spring-data-mongodb + 3.2.1 + + diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 0949edcd3..4fcb13dc1 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -12,7 +12,9 @@ import ch.qos.logback.core.encoder.LayoutWrappingEncoder; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.mongodb.DBRef; import com.mongodb.async.client.ChangeStreamIterable; +import com.mongodb.client.model.changestream.UpdateDescription; import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory; import io.sentry.Sentry; import io.sentry.SentryClient; @@ -27,6 +29,10 @@ import net.dv8tion.jda.api.sharding.ShardManager; import okhttp3.OkHttpClient; import org.apache.commons.lang3.StringUtils; +import org.bson.BsonValue; +import org.bson.Document; +import org.bson.codecs.DecoderContext; +import org.bson.conversions.Bson; import org.cascadebot.cascadebot.commandmeta.ArgumentManager; import org.cascadebot.cascadebot.commandmeta.CommandManager; import org.cascadebot.cascadebot.data.Config; @@ -57,13 +63,18 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; +import org.springframework.data.mongodb.util.BsonUtils; import redis.clients.jedis.Jedis; import redis.clients.jedis.exceptions.JedisConnectionException; import javax.annotation.Nonnull; import javax.security.auth.login.LoginException; import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.Arrays; +import java.util.Date; +import java.util.Map; import java.util.Scanner; import java.util.concurrent.TimeUnit; @@ -200,8 +211,24 @@ private void init() { databaseManager.runAsyncTask(database -> { ChangeStreamIterable changeStreamIterable = database.getCollection(GuildDataManager.COLLECTION, GuildData.class).watch(); - new Thread(() -> changeStreamIterable.forEach(guildDataChangeStreamDocument -> - GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()), (result, throwable) -> { + new Thread(() -> changeStreamIterable.forEach(guildDataChangeStreamDocument -> { + if (guildDataChangeStreamDocument.getFullDocument() != null) { + GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()); + } else { + GuildData currentData = GuildDataManager.getGuildData(guildDataChangeStreamDocument.getDocumentKey().get("_id").asNumber().longValue()); + UpdateDescription updateDescription = guildDataChangeStreamDocument.getUpdateDescription(); + if (updateDescription.getUpdatedFields() != null) { + for (Map.Entry change : updateDescription.getUpdatedFields().entrySet()) { + if (!updateGuildData(change.getKey(), currentData, BsonUtils.toJavaType(change.getValue()))) break; + } + } + if (updateDescription.getRemovedFields() != null) { + for (String removed : updateDescription.getRemovedFields()) { + if (!updateGuildData(removed, currentData, null)) break; + } + } + } + }, (result, throwable) -> { if (throwable != null) { throwable.printStackTrace(); } @@ -280,6 +307,34 @@ private void init() { } + public boolean updateGuildData(String path, GuildData guildData, Object newValue) { + String[] split = path.split("\\."); + String last = split[split.length - 1]; + Object current = guildData; + for (String part : Arrays.copyOfRange(split, 0, split.length - 1)) { + try { + Field field = current.getClass().getDeclaredField(part); + field.setAccessible(true); + current = field.get(current); + } catch (NoSuchFieldException | IllegalAccessException e) { + CascadeBot.LOGGER.error("Failed to update guild data", e); + return false; + } + } + try { + Field field = current.getClass().getDeclaredField(last); + field.setAccessible(true); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(current, newValue); + } catch (NoSuchFieldException | IllegalAccessException e) { + CascadeBot.LOGGER.error("Failed to update guild data", e); + return false; + } + return true; + } + private void setupTasks() { new Task("prune-players") { @Override From 8fafe1de0c603e96d563617291d2a38c9091dfa9 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 30 May 2021 16:03:40 +0100 Subject: [PATCH 157/206] Add command filters to modlog --- .../filters/FiltersDeleteSubCommand.kt | 5 +++++ .../filters/FiltersDisableSubCommand.kt | 5 +++++ .../filters/FiltersEnableSubCommand.kt | 5 +++++ src/main/resources/lang/en-GB.json | 19 +++++++++++-------- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersDeleteSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersDeleteSubCommand.kt index 81fef14ed..46b603a69 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersDeleteSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersDeleteSubCommand.kt @@ -8,6 +8,8 @@ package org.cascadebot.cascadebot.commands.management.filters import net.dv8tion.jda.api.entities.Member import org.cascadebot.cascadebot.commandmeta.CommandContext import org.cascadebot.cascadebot.commandmeta.SubCommand +import org.cascadebot.cascadebot.data.objects.ModlogEventData +import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.permissions.CascadePermission class FiltersDeleteSubCommand : SubCommand() { @@ -30,6 +32,9 @@ class FiltersDeleteSubCommand : SubCommand() { context.data.management.filters.removeIf { it.name == name } context.typedMessaging.replySuccess(context.i18n("commands.filters.delete.success", name)) + + val eventStore = ModlogEventData(ModlogEvent.CASCADE_FILTER_DELETE, context.user, filter, mutableListOf()) + context.data.moderation.sendModlogEvent(context.guild.idLong, eventStore) } override fun command(): String = "delete" diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersDisableSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersDisableSubCommand.kt index a64729724..2567da0fe 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersDisableSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersDisableSubCommand.kt @@ -8,6 +8,8 @@ package org.cascadebot.cascadebot.commands.management.filters import net.dv8tion.jda.api.entities.Member import org.cascadebot.cascadebot.commandmeta.CommandContext import org.cascadebot.cascadebot.commandmeta.SubCommand +import org.cascadebot.cascadebot.data.objects.ModlogEventData +import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.permissions.CascadePermission class FiltersDisableSubCommand : SubCommand() { @@ -29,6 +31,9 @@ class FiltersDisableSubCommand : SubCommand() { if (filter.enabled) { filter.enabled = false context.typedMessaging.replySuccess(context.i18n("commands.filters.disable.success", name)) + + val eventStore = ModlogEventData(ModlogEvent.CASCADE_FILTER_DISABLE, context.user, filter, mutableListOf()) + context.data.moderation.sendModlogEvent(context.guild.idLong, eventStore) } else { context.typedMessaging.replyInfo(context.i18n("commands.filters.disable.already_disabled", name)) } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersEnableSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersEnableSubCommand.kt index 988e9faa8..e82e01986 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersEnableSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersEnableSubCommand.kt @@ -8,6 +8,8 @@ package org.cascadebot.cascadebot.commands.management.filters import net.dv8tion.jda.api.entities.Member import org.cascadebot.cascadebot.commandmeta.CommandContext import org.cascadebot.cascadebot.commandmeta.SubCommand +import org.cascadebot.cascadebot.data.objects.ModlogEventData +import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.permissions.CascadePermission class FiltersEnableSubCommand : SubCommand() { @@ -29,6 +31,9 @@ class FiltersEnableSubCommand : SubCommand() { if (!filter.enabled) { filter.enabled = true context.typedMessaging.replySuccess(context.i18n("commands.filters.enable.success", name)) + + val eventStore = ModlogEventData(ModlogEvent.CASCADE_FILTER_ENABLE, context.user, filter, mutableListOf()) + context.data.moderation.sendModlogEvent(context.guild.idLong, eventStore) } else { context.typedMessaging.replyInfo(context.i18n("commands.filters.enable.already_disabled", name)) } diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index 0563e4e02..e1508aca0 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1876,25 +1876,28 @@ "description": "Purged {2} messages from {0}" }, "cascade_filter_create": { - "select": "cascade_filter_create", + "select": "command_filter_create", "display": "Command filter created", "description": "The command filter with the name `{0}` has been created!" }, "cascade_filter_delete": { - "select": "cascade_filter_delete", - "display": "Command filter deleted" + "select": "command_filter_delete", + "display": "Command filter deleted", + "description": "The command filter with the name `{0}` has been deleted!" }, "cascade_filter_update": { - "select": "cascade_filter_update", + "select": "command_filter_update", "display": "Command filter updated" }, "cascade_filter_enable": { - "select": "cascade_filter_enable", - "display": "Command filter enabled" + "select": "command_filter_enable", + "display": "Command filter enabled", + "description": "|g:perm_tick| The command filter with the name `{0}` has been enabled!" }, "cascade_filter_disable": { - "select": "cascade_filter_disable", - "display": "Command filter disabled" + "select": "command_filter_disable", + "display": "Command filter disabled", + "description": "|g:perm_cross| The command filter with the name `{0}` has been disabled!" }, "cascade_script_created": { "select": "cascade_script_created", From ba081bad6aa13f498edbc83eb7bfb45e1cecbb5c Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 30 May 2021 10:20:46 -0500 Subject: [PATCH 158/206] assertWriteMode --- .../cascadebot/data/objects/GuildData.kt | 10 ++++++++-- .../data/objects/GuildSettingsCore.kt | 20 +++++++++++-------- .../data/objects/GuildSettingsManagement.kt | 8 ++++++-- .../data/objects/GuildSettingsModeration.kt | 10 +++++++--- 4 files changed, 33 insertions(+), 15 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 180de644d..7ecc29e1a 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -34,7 +34,7 @@ class GuildData(@field:Id val guildId: Long): Cloneable { @Transient @kotlin.jvm.Transient - var lock: ReadWriteLock = ReentrantReadWriteLock() + val lock: ReadWriteLock = ReentrantReadWriteLock() @Transient @kotlin.jvm.Transient @@ -105,10 +105,12 @@ class GuildData(@field:Id val guildId: Long): Cloneable { } fun enableFlag(flag: Flag): Boolean { + assertWriteMode() return enabledFlags.add(flag) } fun disableFlag(flag: Flag): Boolean { + assertWriteMode() return enabledFlags.remove(flag) } @@ -126,7 +128,7 @@ class GuildData(@field:Id val guildId: Long): Cloneable { } private fun putPersistentButtonGroup(channelId: Long, messageId: Long, buttonGroup: PersistentButtonGroup) { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() if (persistentButtons.containsKey(channelId) && persistentButtons[channelId] != null) { persistentButtons[channelId]!![messageId] = buttonGroup @@ -158,6 +160,10 @@ class GuildData(@field:Id val guildId: Long): Cloneable { moderation.writeMode = mode } + fun assertWriteMode() { + if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + } + } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt index 871b79bc2..ceaaa8823 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt @@ -47,13 +47,13 @@ class GuildSettingsCore { //region Modules fun enableModule(module: Module): Boolean { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() require(!module.isPrivate) { "This module is not available to be enabled!" } return enabledModules.add(module) } fun disableModule(module: Module): Boolean { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() require(!module.isPrivate) { "This module is not available to be disabled!" } require(!module.isRequired) { "Cannot disable the ${module.toString().toLowerCase()} module!" } return enabledModules.remove(module) @@ -72,7 +72,7 @@ class GuildSettingsCore { //region Commands fun enableCommand(command: MainCommand) { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() if (command.module().isPrivate) return if (commandInfo.contains(command.javaClass)) { getGuildCommandInfo(command).enabled = true @@ -80,7 +80,7 @@ class GuildSettingsCore { } fun enableCommandByModule(module: Module) { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() if (module.isPrivate) return for (command in CascadeBot.INS.commandManager.getCommandsByModule(module)) { enableCommand(command) @@ -88,13 +88,13 @@ class GuildSettingsCore { } fun disableCommand(command: MainCommand) { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() if (command.module().isPrivate) return getGuildCommandInfo(command).enabled = false } fun disableCommandByModule(module: Module) { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() if (module.isPrivate) return for (command in CascadeBot.INS.commandManager.getCommandsByModule(module)) { disableCommand(command) @@ -114,12 +114,12 @@ class GuildSettingsCore { } fun addAlias(command: MainCommand, alias: String): Boolean { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() return getGuildCommandInfo(command).aliases.add(alias) } fun removeAlias(command: MainCommand, alias: String): Boolean { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() return getGuildCommandInfo(command).aliases.remove(alias) } @@ -139,4 +139,8 @@ class GuildSettingsCore { //endregion + fun assertWriteMode() { + if (!writeMode) throw java.lang.UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + } + } \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt index 9559fc5ea..ffff3a07e 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt @@ -32,13 +32,17 @@ class GuildSettingsManagement { } fun addTag(key: String, tag: Tag) { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() tags[key] = tag } fun removeTag(key: String): Boolean { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() return tags.remove(key) != null } + fun assertWriteMode() { + if (!writeMode) throw java.lang.UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + } + } \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 73c5fede7..b034e31b2 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -74,7 +74,7 @@ class GuildSettingsModeration { } fun enableEvent(channel: TextChannel, event: ModlogEvent): Boolean { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() if (modlogEvents.containsKey(channel.idLong)) { return modlogEvents[channel.idLong]!!.addEvent(event) } else { @@ -84,7 +84,7 @@ class GuildSettingsModeration { } fun disableEvent(channel: TextChannel, event: ModlogEvent): Boolean { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() if (modlogEvents.containsKey(channel.idLong)) { return modlogEvents[channel.idLong]!!.removeEvent(event) } else { @@ -93,7 +93,7 @@ class GuildSettingsModeration { } fun enableEventByCategory(channel: TextChannel, category: ModlogEvent.Category) { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + assertWriteMode() for (modlogEvent in ModlogEvent.getEventsFromCategory(category)) { enableEvent(channel, modlogEvent) } @@ -111,6 +111,10 @@ class GuildSettingsModeration { } } + fun assertWriteMode() { + if (!writeMode) throw java.lang.UnsupportedOperationException("Cannot modify Guild data if not in write mode!") + } + class ChannelModlogEventsInfo { private val events: MutableSet = LinkedHashSet() From 3c6cfb56c2caa1db92c3953e9aef6e21cc0943a4 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 30 May 2021 10:25:26 -0500 Subject: [PATCH 159/206] No thread for watching --- .../org/cascadebot/cascadebot/CascadeBot.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 4fcb13dc1..b410a51db 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -12,7 +12,6 @@ import ch.qos.logback.core.encoder.LayoutWrappingEncoder; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.mongodb.DBRef; import com.mongodb.async.client.ChangeStreamIterable; import com.mongodb.client.model.changestream.UpdateDescription; import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory; @@ -30,9 +29,6 @@ import okhttp3.OkHttpClient; import org.apache.commons.lang3.StringUtils; import org.bson.BsonValue; -import org.bson.Document; -import org.bson.codecs.DecoderContext; -import org.bson.conversions.Bson; import org.cascadebot.cascadebot.commandmeta.ArgumentManager; import org.cascadebot.cascadebot.commandmeta.CommandManager; import org.cascadebot.cascadebot.data.Config; @@ -73,7 +69,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Arrays; -import java.util.Date; import java.util.Map; import java.util.Scanner; import java.util.concurrent.TimeUnit; @@ -211,7 +206,7 @@ private void init() { databaseManager.runAsyncTask(database -> { ChangeStreamIterable changeStreamIterable = database.getCollection(GuildDataManager.COLLECTION, GuildData.class).watch(); - new Thread(() -> changeStreamIterable.forEach(guildDataChangeStreamDocument -> { + changeStreamIterable.forEach(guildDataChangeStreamDocument -> { if (guildDataChangeStreamDocument.getFullDocument() != null) { GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()); } else { @@ -219,7 +214,8 @@ private void init() { UpdateDescription updateDescription = guildDataChangeStreamDocument.getUpdateDescription(); if (updateDescription.getUpdatedFields() != null) { for (Map.Entry change : updateDescription.getUpdatedFields().entrySet()) { - if (!updateGuildData(change.getKey(), currentData, BsonUtils.toJavaType(change.getValue()))) break; + if (!updateGuildData(change.getKey(), currentData, BsonUtils.toJavaType(change.getValue()))) + break; } } if (updateDescription.getRemovedFields() != null) { @@ -230,12 +226,13 @@ private void init() { } }, (result, throwable) -> { if (throwable != null) { - throwable.printStackTrace(); + CascadeBot.LOGGER.error("Error on change stream", throwable); } - System.out.println(result); - }), "mongoChangeWatch").start(); + }); }); + CascadeBot.LOGGER.info("Watcher setup"); + musicHandler = new MusicHandler(); eventWaiter = new EventWaiter(); From 4f9876a785dd4caa4f10f8f4f968f7089350ba73 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 30 May 2021 16:30:54 +0100 Subject: [PATCH 160/206] Command filter modlog, operator and type updates --- .../filters/FiltersOperatorSubCommand.kt | 55 +++++++++++++++++-- .../filters/FiltersTypeSubCommand.kt | 19 +++++++ src/main/resources/lang/en-GB.json | 6 +- 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersOperatorSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersOperatorSubCommand.kt index 9804fe21b..3bf05b9e0 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersOperatorSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersOperatorSubCommand.kt @@ -9,9 +9,14 @@ import net.dv8tion.jda.api.entities.Member import org.cascadebot.cascadebot.commandmeta.CommandContext import org.cascadebot.cascadebot.commandmeta.SubCommand import org.cascadebot.cascadebot.data.objects.CommandFilter +import org.cascadebot.cascadebot.data.objects.ModlogEventData +import org.cascadebot.cascadebot.moderation.ModlogEmbedField +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart +import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.permissions.CascadePermission import org.cascadebot.cascadebot.utils.FormatUtils import org.cascadebot.cascadebot.utils.language.LanguageUtils +import org.cascadebot.cascadebot.utils.toCapitalized import org.cascadebot.cascadebot.utils.toTitleCase class FiltersOperatorSubCommand : SubCommand() { @@ -30,26 +35,64 @@ class FiltersOperatorSubCommand : SubCommand() { return } - val operator: CommandFilter.FilterOperator? = LanguageUtils.findEnumByI18n(CommandFilter.FilterOperator::class.java, context.locale, context.getArg(1), true) + val operator: CommandFilter.FilterOperator? = LanguageUtils.findEnumByI18n( + CommandFilter.FilterOperator::class.java, + context.locale, + context.getArg(1), + true + ) if (operator == null) { val validTypes = CommandFilter.FilterOperator.values().joinToString(", ") { "`${it.name.toTitleCase()}`" } - context.typedMessaging.replyDanger(context.i18n("commands.filters.operator.invalid_operator", validTypes, filterName)) + context.typedMessaging.replyDanger( + context.i18n( + "commands.filters.operator.invalid_operator", + validTypes, + filterName + ) + ) return } if (operator == filter.operator) { - context.typedMessaging.replyInfo(context.i18n("commands.filters.operator.already_set", FormatUtils.formatEnum(operator, context.locale), filterName)) + context.typedMessaging.replyInfo( + context.i18n( + "commands.filters.operator.already_set", + FormatUtils.formatEnum(operator, context.locale), + filterName + ) + ) return } + val oldOperator = filter.operator filter.operator = operator - context.typedMessaging.replySuccess(context.i18n("commands.filters.operator.success", FormatUtils.formatEnum(operator, context.locale), filterName)) - + context.typedMessaging.replySuccess( + context.i18n( + "commands.filters.operator.success", + FormatUtils.formatEnum(operator, context.locale), + filterName + ) + ) + + val embedFields = mutableListOf() + + embedFields.add( + ModlogEmbedField( + false, + "words.operator", + "modlog.general.small_change", + FormatUtils.formatEnum(oldOperator, context.locale).toCapitalized(), + FormatUtils.formatEnum(operator, context.locale).toCapitalized() + ) + ) + + val eventStore = ModlogEventData(ModlogEvent.CASCADE_FILTER_UPDATE, context.user, filter, embedFields) + context.data.moderation.sendModlogEvent(context.guild.idLong, eventStore) } - override fun command(): String = "operator" + override fun command(): String = "operator" override fun parent(): String = "filters" diff --git a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersTypeSubCommand.kt b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersTypeSubCommand.kt index 86f6f5e5d..8d615a53b 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersTypeSubCommand.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/commands/management/filters/FiltersTypeSubCommand.kt @@ -9,9 +9,14 @@ import net.dv8tion.jda.api.entities.Member import org.cascadebot.cascadebot.commandmeta.CommandContext import org.cascadebot.cascadebot.commandmeta.SubCommand import org.cascadebot.cascadebot.data.objects.CommandFilter +import org.cascadebot.cascadebot.data.objects.ModlogEventData +import org.cascadebot.cascadebot.moderation.ModlogEmbedField +import org.cascadebot.cascadebot.moderation.ModlogEmbedPart +import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.permissions.CascadePermission import org.cascadebot.cascadebot.utils.FormatUtils import org.cascadebot.cascadebot.utils.language.LanguageUtils +import org.cascadebot.cascadebot.utils.toCapitalized import org.cascadebot.cascadebot.utils.toTitleCase class FiltersTypeSubCommand : SubCommand() { @@ -43,10 +48,24 @@ class FiltersTypeSubCommand : SubCommand() { return } + val oldType = filter.type filter.type = type context.typedMessaging.replySuccess(context.i18n("commands.filters.type.success", FormatUtils.formatEnum(type, context.locale), filterName)) + val embedFields = mutableListOf() + embedFields.add( + ModlogEmbedField( + false, + "words.type", + "modlog.general.small_change", + FormatUtils.formatEnum(oldType, context.locale).toCapitalized(), + FormatUtils.formatEnum(type, context.locale).toCapitalized() + ) + ) + + val eventStore = ModlogEventData(ModlogEvent.CASCADE_FILTER_UPDATE, context.user, filter, embedFields) + context.data.moderation.sendModlogEvent(context.guild.idLong, eventStore) } override fun command(): String = "type" diff --git a/src/main/resources/lang/en-GB.json b/src/main/resources/lang/en-GB.json index e1508aca0..0cb948a9c 100644 --- a/src/main/resources/lang/en-GB.json +++ b/src/main/resources/lang/en-GB.json @@ -1887,7 +1887,8 @@ }, "cascade_filter_update": { "select": "command_filter_update", - "display": "Command filter updated" + "display": "Command filter updated", + "description": "The command filter with the name `{0}` has been updated!\n\nSee what updates have been made below:" }, "cascade_filter_enable": { "select": "command_filter_enable", @@ -2046,7 +2047,8 @@ "yes_words": ["yes", "true", "on"], "no_words": ["no", "false", "off"], "name": "name", - "type": "type" + "type": "type", + "operator": "operator" }, "messaging": { "loading_page": "Paged message loading...", From d5009519bedac698bdf8b4ce9d1882c6472c1d04 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 30 May 2021 10:32:54 -0500 Subject: [PATCH 161/206] Copy old buttons and pages --- .../data/managers/GuildDataManager.java | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java index e0b17e5fe..71baef269 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java @@ -22,6 +22,8 @@ import org.cascadebot.cascadebot.utils.diff.DifferenceChanged; import org.cascadebot.cascadebot.utils.lists.CollectionDiff; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -35,7 +37,6 @@ public final class GuildDataManager { private static LoadingCache guilds = Caffeine.newBuilder() .expireAfterAccess(5, TimeUnit.MINUTES) - //.removalListener(new GuildSaveListener()) TODO do we want to use still use this? .recordStats() .build(id -> { GuildData dbData = CascadeBot.INS.getDatabaseManager().getDatabase().getCollection(COLLECTION, GuildData.class).find(eq("_id", id)).first(); @@ -80,7 +81,7 @@ public static void updateDiff(long id, Difference difference, GuildData newData) CascadeBot.INS.getDatabaseManager().runAsyncTask(database -> { database.getCollection(COLLECTION, GuildData.class).updateMany(eq("_id", id), Updates.combine(bsonList), new DebugLogCallback<>("Updated Guild ID " + id)); });; - guilds.put(newData.getGuildId(), newData); + replaceInternal(newData); } public static void insert(long id, GuildData data) { @@ -96,6 +97,26 @@ public static void replace(long id, GuildData data) { } public static void replaceInternal(GuildData guildData) { + GuildData old = guilds.get(guildData.getGuildId()); + try { + Field buttons = guildData.getClass().getDeclaredField("buttonsCache"); + buttons.setAccessible(true); + Field modifiersFieldButtons = Field.class.getDeclaredField("modifiers"); + modifiersFieldButtons.setAccessible(true); + modifiersFieldButtons.setInt(buttons, buttons.getModifiers() & ~Modifier.FINAL); + + buttons.set(guildData, buttons.get(old)); + + Field pages = guildData.getClass().getDeclaredField("pageCache"); + pages.setAccessible(true); + Field modifiersFieldPages = Field.class.getDeclaredField("modifiers"); + modifiersFieldPages.setAccessible(true); + modifiersFieldPages.setInt(pages, pages.getModifiers() & ~Modifier.FINAL); + + pages.set(guildData, pages.get(old)); + } catch (NoSuchFieldException | IllegalAccessException ignored) { + } + guilds.put(guildData.getGuildId(), guildData); } From 892d38ff934713771f8b108dd6325e717a99cb3a Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 30 May 2021 13:08:03 -0500 Subject: [PATCH 162/206] Wrap permission commands in write --- .../GroupPermissionAddSubCommand.java | 24 ++++---- .../GroupPermissionCreateSubCommand.java | 13 +++-- .../GroupPermissionDeleteSubCommand.java | 26 +++++---- .../GroupPermissionInfoSubCommand.java | 2 +- .../GroupPermissionLinkRoleSubCommand.java | 24 ++++---- .../GroupPermissionMoveSubCommand.java | 56 ++++++++++--------- .../GroupPermissionRemoveSubCommand.java | 24 ++++---- .../GroupPermissionSwitchSubCommand.java | 5 +- .../GroupPermissionUnlinkRoleSubCommand.java | 24 ++++---- .../UserPermissionAddSubCommand.java | 30 +++++----- .../UserPermissionGroupSubCommand.java | 6 +- .../UserPermissionRemoveSubCommand.java | 22 ++++---- .../data/managers/GuildDataManager.java | 3 + .../utils/PermissionCommandUtils.java | 7 ++- .../data/objects/GuildSettingsManagement.kt | 8 ++- 15 files changed, 154 insertions(+), 120 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java index 45c52c115..2980e6493 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionAddSubCommand.java @@ -29,17 +29,19 @@ public void onCommand(Member sender, CommandContext context) { return; } - PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { - if (group.addPermission(context.getArg(1))) { - context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.add.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); - ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, List.of()); - eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - } else { - context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.add.fail", context.getArg(1), group.getName() + "(" + group.getId() + ")")); - } - }, sender.getIdLong()); + context.getData().write(guildData -> { + PermissionCommandUtils.tryGetGroupFromString(context, guildData, context.getArg(0), group -> { + if (group.addPermission(context.getArg(1))) { + context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.add.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_ADD; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, List.of()); + eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + } else { + context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.add.fail", context.getArg(1), group.getName() + "(" + group.getId() + ")")); + } + }, sender.getIdLong()); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java index b94523b7f..a99b3b8bf 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionCreateSubCommand.java @@ -25,12 +25,13 @@ public void onCommand(Member sender, CommandContext context) { return; } - Group group = context.getData().getManagement().getPermissions().createGroup(context.getArg(0)); - context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.create.success", context.getArg(0), group.getId())); - ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_CREATED; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, new ArrayList<>()); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - + context.getData().write(guildData -> { + Group group = guildData.getManagement().getPermissions().createGroup(context.getArg(0)); + context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.create.success", context.getArg(0), group.getId())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_CREATED; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, new ArrayList<>()); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java index a6fa68c99..5243765bd 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionDeleteSubCommand.java @@ -20,18 +20,20 @@ public void onCommand(Member sender, CommandContext context) { return; } - PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { - if (context.getData().getManagement().getPermissions().deleteGroup(group.getId())) { - // If the group existed to delete and has been successfully deleted. - context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.delete.success", group.getName(), group.getId())); - ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_DELETED; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, new ArrayList<>()); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - } else { - // Throwing an exception here because this *should* never happen - throw new IllegalStateException("Couldn't delete group!"); - } - }, sender.getIdLong()); + context.getData().write(guildData -> { + PermissionCommandUtils.tryGetGroupFromString(context, guildData, context.getArg(0), group -> { + if (guildData.getManagement().getPermissions().deleteGroup(group.getId())) { + // If the group existed to delete and has been successfully deleted. + context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.delete.success", group.getName(), group.getId())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_DELETED; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, new ArrayList<>()); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + } else { + // Throwing an exception here because this *should* never happen + throw new IllegalStateException("Couldn't delete group!"); + } + }, sender.getIdLong()); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionInfoSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionInfoSubCommand.java index ef3f2e760..8957359ef 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionInfoSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionInfoSubCommand.java @@ -29,7 +29,7 @@ public void onCommand(Member sender, CommandContext context) { return; } - PermissionCommandUtils.tryGetGroupFromString(context, context.getMessage(0), group -> { + PermissionCommandUtils.tryGetGroupFromString(context, context.getData(), context.getMessage(0), group -> { if (group.getPermissions().isEmpty() && group.getRoleIds().isEmpty()) { context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.info.empty_group")); return; diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java index 054ea3a7f..7a933b930 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionLinkRoleSubCommand.java @@ -33,17 +33,19 @@ public void onCommand(Member sender, CommandContext context) { return; } - PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { - if (group.linkRole(role.getIdLong())) { - context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.link.success", group.getName(), role.getName())); - ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_LINK; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, List.of()); - eventStore.setExtraDescriptionInfo(List.of(role.getAsMention())); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - } else { - context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.link.fail", group.getName(), role.getName())); - } - }, sender.getIdLong()); + context.getData().write(guildData -> { + PermissionCommandUtils.tryGetGroupFromString(context, guildData, context.getArg(0), group -> { + if (group.linkRole(role.getIdLong())) { + context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.link.success", group.getName(), role.getName())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_LINK; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, List.of()); + eventStore.setExtraDescriptionInfo(List.of(role.getAsMention())); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + } else { + context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.link.fail", group.getName(), role.getName())); + } + }, sender.getIdLong()); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionMoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionMoveSubCommand.java index 7d0d947fc..4a6654d2e 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionMoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionMoveSubCommand.java @@ -34,34 +34,40 @@ public void onCommand(Member sender, CommandContext context) { return; } - PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { - if (context.getArgs().length > 1 && context.isArgInteger(1)) { - context.getData().getManagement().getPermissions().moveGroup(group, context.getArgAsInteger(1)); - context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.move.moved", group.getName(), context.getArg(1))); - return; - } - - AtomicInteger currIndex = new AtomicInteger(context.getData().getManagement().getPermissions().getGroups().indexOf(group)); - ButtonGroup buttonGroup = new ButtonGroup(sender.getIdLong(), context.getChannel().getIdLong(), context.getGuild().getIdLong()); - buttonGroup.addButton(new Button.UnicodeButton(UnicodeConstants.ARROW_UP, (runner, channel, message) -> { - if (buttonGroup.getOwner().getIdLong() != runner.getIdLong()) { - return; - } - context.getData().getManagement().getPermissions().moveGroup(context.getData().getManagement().getPermissions().getGroups().get(currIndex.get()), currIndex.get() - 1); - currIndex.addAndGet(-1); - message.editMessage(getGroupsList(group, context.getData().getManagement().getPermissions().getGroups())).queue(); - })); - buttonGroup.addButton(new Button.UnicodeButton(UnicodeConstants.ARROW_DOWN, (runner, channel, message) -> { - if (buttonGroup.getOwner().getIdLong() != runner.getIdLong()) { + context.getData().write(guildData -> { + PermissionCommandUtils.tryGetGroupFromString(context, guildData, context.getArg(0), group -> { + if (context.getArgs().length > 1 && context.isArgInteger(1)) { + guildData.getManagement().getPermissions().moveGroup(group, context.getArgAsInteger(1)); + context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.move.moved", group.getName(), context.getArg(1))); return; } - context.getData().getManagement().getPermissions().moveGroup(context.getData().getManagement().getPermissions().getGroups().get(currIndex.get()), currIndex.get() + 1); - currIndex.addAndGet(1); - message.editMessage(getGroupsList(group, context.getData().getManagement().getPermissions().getGroups())).queue(); - })); - context.getUiMessaging().sendButtonedMessage(getGroupsList(group, context.getData().getManagement().getPermissions().getGroups()), buttonGroup); - }, sender.getIdLong()); + AtomicInteger currIndex = new AtomicInteger(context.getData().getManagement().getPermissions().getGroups().indexOf(group)); + ButtonGroup buttonGroup = new ButtonGroup(sender.getIdLong(), context.getChannel().getIdLong(), context.getGuild().getIdLong()); + buttonGroup.addButton(new Button.UnicodeButton(UnicodeConstants.ARROW_UP, (runner, channel, message) -> { + if (buttonGroup.getOwner().getIdLong() != runner.getIdLong()) { + return; + } + context.getData().write(guildData1 -> { + guildData1.getManagement().getPermissions().moveGroup(context.getData().getManagement().getPermissions().getGroups().get(currIndex.get()), currIndex.get() - 1); + }); + currIndex.addAndGet(-1); + message.editMessage(getGroupsList(group, context.getData().getManagement().getPermissions().getGroups())).queue(); + })); + buttonGroup.addButton(new Button.UnicodeButton(UnicodeConstants.ARROW_DOWN, (runner, channel, message) -> { + if (buttonGroup.getOwner().getIdLong() != runner.getIdLong()) { + return; + } + context.getData().write(guildData1 -> { + guildData1.getManagement().getPermissions().moveGroup(context.getData().getManagement().getPermissions().getGroups().get(currIndex.get()), currIndex.get() + 1); + }); + currIndex.addAndGet(1); + message.editMessage(getGroupsList(group, context.getData().getManagement().getPermissions().getGroups())).queue(); + })); + + context.getUiMessaging().sendButtonedMessage(getGroupsList(group, context.getData().getManagement().getPermissions().getGroups()), buttonGroup); + }, sender.getIdLong()); + }); } public String getGroupsList(Group targetGroup, List groups) { diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java index 1bd5868a3..ff3796d3b 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionRemoveSubCommand.java @@ -30,17 +30,19 @@ public void onCommand(Member sender, CommandContext context) { return; } - PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { - if (group.removePermission(context.getArg(1))) { - context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.remove.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); - ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, List.of()); - eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - } else { - context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.remove.fail", context.getArg(1), group.getName() + "(" + group.getId() + ")")); - } - }, sender.getIdLong()); + context.getData().write(guildData -> { + PermissionCommandUtils.tryGetGroupFromString(context, guildData, context.getArg(0), group -> { + if (group.removePermission(context.getArg(1))) { + context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.remove.success", context.getArg(1), group.getName() + "(" + group.getId() + ")")); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_PERMISSION_REMOVE; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, List.of()); + eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + } else { + context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.remove.fail", context.getArg(1), group.getName() + "(" + group.getId() + ")")); + } + }, sender.getIdLong()); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionSwitchSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionSwitchSubCommand.java index ccb9aebcb..84aeb989b 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionSwitchSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionSwitchSubCommand.java @@ -36,7 +36,10 @@ public void onCommand(Member sender, CommandContext context) { } } - context.getData().getManagement().getPermissions().setMode(mode); + PermissionMode finalMode = mode; + context.getData().write(guildData -> { + guildData.getManagement().getPermissions().setMode(finalMode); + }); context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.switch.success", FormatUtils.formatEnum(mode, context.getLocale()))); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java index a90a8d25f..18761684d 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionUnlinkRoleSubCommand.java @@ -33,17 +33,19 @@ public void onCommand(Member sender, CommandContext context) { return; } - PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { - if (group.unlinkRole(role.getIdLong())) { - context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.unlink.success", group.getName(), role.getName())); - ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_UNLINK; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, List.of()); - eventStore.setExtraDescriptionInfo(List.of(role.getAsMention())); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - } else { - context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.unlink.fail", group.getName(), role.getName())); - } - }, sender.getIdLong()); + context.getData().write(guildData -> { + PermissionCommandUtils.tryGetGroupFromString(context, guildData, context.getArg(0), group -> { + if (group.unlinkRole(role.getIdLong())) { + context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.unlink.success", group.getName(), role.getName())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_GROUP_UNLINK; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), group, List.of()); + eventStore.setExtraDescriptionInfo(List.of(role.getAsMention())); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + } else { + context.getTypedMessaging().replyWarning(context.i18n("commands.groupperms.unlink.fail", group.getName(), role.getName())); + } + }, sender.getIdLong()); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java index 06867afb9..3409727a2 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionAddSubCommand.java @@ -32,22 +32,24 @@ public void onCommand(Member sender, CommandContext context) { return; } - User user = context.getData().getManagement().getPermissions().getPermissionUser(member); + context.getData().write(guildData -> { + User user = guildData.getManagement().getPermissions().getPermissionUser(member); - if (!context.getData().getPermissionsManager().isValidPermission(context.getArg(1))) { - context.getTypedMessaging().replyDanger(context.i18n("responses.permission_not_exist", context.getArg(1))); - return; - } + if (!context.getData().getPermissionsManager().isValidPermission(context.getArg(1))) { + context.getTypedMessaging().replyDanger(context.i18n("responses.permission_not_exist", context.getArg(1))); + return; + } - if (user.addPermission(context.getArg(1))) { - context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.add.success", context.getArg(1), member.getUser().getAsTag())); - ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_PERMISSION_ADD; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), member.getUser(), List.of()); - eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - } else { - context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.add.fail", context.getArg(1), member.getUser().getAsTag())); - } + if (user.addPermission(context.getArg(1))) { + context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.add.success", context.getArg(1), member.getUser().getAsTag())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_PERMISSION_ADD; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), member.getUser(), List.of()); + eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + } else { + context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.add.fail", context.getArg(1), member.getUser().getAsTag())); + } + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java index aff6a47d5..dddba7c9a 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionGroupSubCommand.java @@ -38,8 +38,9 @@ public void onCommand(Member sender, CommandContext context) { return; } - PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(2), group -> { - User user = context.getData().getManagement().getPermissions().getPermissionUser(member); + context.getData().write(guildData -> { + PermissionCommandUtils.tryGetGroupFromString(context, guildData, context.getArg(2), group -> { + User user = guildData.getManagement().getPermissions().getPermissionUser(member); if (context.testForArg("put")) { if (user.addGroup(group)) { context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.group.put.success", member.getUser().getAsTag(), group.getName())); @@ -62,6 +63,7 @@ public void onCommand(Member sender, CommandContext context) { } } }, sender.getIdLong()); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java index 95fe25310..68988a412 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/UserPermissionRemoveSubCommand.java @@ -32,17 +32,19 @@ public void onCommand(Member sender, CommandContext context) { return; } - User user = context.getData().getManagement().getPermissions().getPermissionUser(member); + context.getData().write(guildData -> { + User user = guildData.getManagement().getPermissions().getPermissionUser(member); - if (user.removePermission(context.getArg(1))) { - context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.remove.success", context.getArg(1), member.getUser().getAsTag())); - ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), member.getUser(), List.of()); - eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - } else { - context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.remove.fail", context.getArg(1), member.getUser().getAsTag())); - } + if (user.removePermission(context.getArg(1))) { + context.getTypedMessaging().replySuccess(context.i18n("commands.userperms.remove.success", context.getArg(1), member.getUser().getAsTag())); + ModlogEvent event = ModlogEvent.CASCADE_PERMISSIONS_USER_PERMISSION_REMOVE; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), member.getUser(), List.of()); + eventStore.setExtraDescriptionInfo(List.of(context.getArg(1))); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + } else { + context.getTypedMessaging().replyWarning(context.i18n("commands.userperms.remove.fail", context.getArg(1), member.getUser().getAsTag())); + } + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java index 71baef269..ff0fdc9f2 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java @@ -78,6 +78,9 @@ public static void updateDiff(long id, Difference difference, GuildData newData) for (String removed : difference.getRemoved().keySet()) { bsonList.add(Updates.unset(removed)); } + if (bsonList.size() == 0) { + return; + } CascadeBot.INS.getDatabaseManager().runAsyncTask(database -> { database.getCollection(COLLECTION, GuildData.class).updateMany(eq("_id", id), Updates.combine(bsonList), new DebugLogCallback<>("Updated Guild ID " + id)); });; diff --git a/src/main/java/org/cascadebot/cascadebot/utils/PermissionCommandUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/PermissionCommandUtils.java index 9d787a031..46e3127da 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/PermissionCommandUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/PermissionCommandUtils.java @@ -14,6 +14,7 @@ import net.dv8tion.jda.api.requests.ErrorResponse; import org.cascadebot.cascadebot.UnicodeConstants; import org.cascadebot.cascadebot.commandmeta.CommandContext; +import org.cascadebot.cascadebot.data.objects.GuildData; import org.cascadebot.cascadebot.permissions.objects.Group; import org.cascadebot.cascadebot.utils.buttons.Button; import org.cascadebot.cascadebot.utils.buttons.ButtonGroup; @@ -24,14 +25,14 @@ @UtilityClass public class PermissionCommandUtils { - public static void tryGetGroupFromString(CommandContext context, String s, Consumer groupConsumer, long sender) { - Group groupById = context.getData().getManagement().getPermissions().getGroupById(s); + public static void tryGetGroupFromString(CommandContext context, GuildData data, String s, Consumer groupConsumer, long sender) { + Group groupById = data.getManagement().getPermissions().getGroupById(s); if (groupById != null) { groupConsumer.accept(groupById); return; } - List groupList = context.getData().getManagement().getPermissions().getGroupsByName(s); + List groupList = data.getManagement().getPermissions().getGroupsByName(s); if (groupList.size() == 1) { groupConsumer.accept(groupList.get(0)); return; diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt index ffff3a07e..35fdc925d 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt @@ -18,6 +18,11 @@ class GuildSettingsManagement { val tags: ConcurrentHashMap = ConcurrentHashMap() val filters: MutableList = mutableListOf() val permissions = GuildPermissions() + /* get() { + assertWriteMode() + return field + }*/ + val greetings = Greetings() val autoRoles: MutableSet = mutableSetOf() @@ -44,5 +49,4 @@ class GuildSettingsManagement { fun assertWriteMode() { if (!writeMode) throw java.lang.UnsupportedOperationException("Cannot modify Guild data if not in write mode!") } - -} \ No newline at end of file +} From 1009abb78b1fcfc0ca7701092bc2629a9a673920 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 30 May 2021 13:18:11 -0500 Subject: [PATCH 163/206] Wrap tag commands in write --- .../management/tag/TagCategorySubCommand.java | 20 +++++++------ .../management/tag/TagCreateSubCommand.java | 21 +++++++------ .../management/tag/TagDeleteSubCommand.java | 18 ++++++----- .../management/tag/TagEditSubCommand.java | 30 ++++++++++--------- 4 files changed, 49 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCategorySubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCategorySubCommand.java index 898578848..867f4a90c 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCategorySubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCategorySubCommand.java @@ -20,18 +20,20 @@ public void onCommand(Member sender, CommandContext context) { return; } - Tag tag = context.getData().getManagement().getTag(context.getArg(0)); + context.getData().write(guildData -> { + Tag tag = context.getData().getManagement().getTag(context.getArg(0)); - String tagName = context.getArg(0).toLowerCase(); - String category = context.getArg(1).toLowerCase(); + String tagName = context.getArg(0).toLowerCase(); + String category = context.getArg(1).toLowerCase(); - if (tag == null) { - context.getTypedMessaging().replyDanger(context.i18n("commands.tag.cannot_find_tag", tagName)); - return; - } + if (tag == null) { + context.getTypedMessaging().replyDanger(context.i18n("commands.tag.cannot_find_tag", tagName)); + return; + } - tag.setCategory(category); - context.getTypedMessaging().replySuccess(context.i18n("commands.tag.category.successfully_set_tag", tagName, category)); + tag.setCategory(category); + context.getTypedMessaging().replySuccess(context.i18n("commands.tag.category.successfully_set_tag", tagName, category)); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java index 57d4fd82e..eec7d4686 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagCreateSubCommand.java @@ -43,15 +43,18 @@ public void onCommand(Member sender, CommandContext context) { message += "\n\n" + context.i18n("commands.tag.create.warn_uppercase"); } - Tag tag = new Tag(context.getArg(0), context.getMessage(1), "tag"); - context.getData().getManagement().addTag(context.getArg(0), tag); - context.getData().getPermissionsManager().registerGuildPermission(tag.getInternalPermission()); - context.getTypedMessaging().replySuccess(message); - ModlogEvent event = ModlogEvent.CASCADE_TAG_CREATED; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.content", "modlog.general.variable", "```" + MarkdownSanitizer.sanitize(tag.getContent()) + "```")); - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), tag, embedFieldList); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + String finalMessage = message; + context.getData().write(guildData -> { + Tag tag = new Tag(context.getArg(0), context.getMessage(1), "tag"); + guildData.getManagement().addTag(context.getArg(0), tag); + guildData.getPermissionsManager().registerGuildPermission(tag.getInternalPermission()); + context.getTypedMessaging().replySuccess(finalMessage); + ModlogEvent event = ModlogEvent.CASCADE_TAG_CREATED; + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.content", "modlog.general.variable", "```" + MarkdownSanitizer.sanitize(tag.getContent()) + "```")); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), tag, embedFieldList); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java index 19a367f40..8678625bd 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagDeleteSubCommand.java @@ -27,14 +27,16 @@ public void onCommand(Member sender, CommandContext context) { String tagName = context.getArg(0).toLowerCase(); Tag tag = context.getData().getManagement().getTag(tagName); - if (context.getData().getManagement().removeTag(tagName) && tag != null) { - context.getTypedMessaging().replySuccess(context.i18n("commands.tag.delete.successfully_deleted_tag")); - ModlogEvent event = ModlogEvent.CASCADE_TAG_DELETED; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), tag, new ArrayList<>()); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - } else { - context.getTypedMessaging().replyDanger(context.i18n("commands.tag.delete.tag_doesnt_exist", tagName)); - } + context.getData().write(guildData -> { + if (guildData.getManagement().removeTag(tagName) && tag != null) { + context.getTypedMessaging().replySuccess(context.i18n("commands.tag.delete.successfully_deleted_tag")); + ModlogEvent event = ModlogEvent.CASCADE_TAG_DELETED; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), tag, new ArrayList<>()); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + } else { + context.getTypedMessaging().replyDanger(context.i18n("commands.tag.delete.tag_doesnt_exist", tagName)); + } + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java index d9eaed894..b1b36a43b 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/tag/TagEditSubCommand.java @@ -30,20 +30,22 @@ public void onCommand(Member sender, CommandContext context) { String tagName = context.getArg(0).toLowerCase(); - Tag tag = context.getData().getManagement().getTag(tagName); - if (tag == null) { - context.getTypedMessaging().replyDanger(context.i18n("commands.tag.cannot_find_tag", tagName)); - return; - } - String oldContent = tag.getContent(); - tag.setContent(context.getMessage(1)); - context.getTypedMessaging().replySuccess(context.i18n("commands.tag.edit.successfully_edited_tag", tagName)); - ModlogEvent event = ModlogEvent.CASCADE_TAG_UPDATED; - List embedFieldList = new ArrayList<>(); - embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.old_content", "modlog.general.variable", "```" + MarkdownSanitizer.sanitize(oldContent) + "```")); - embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.new_content", "modlog.general.variable", "```" + MarkdownSanitizer.sanitize(tag.getContent()) + "```")); - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), tag, embedFieldList); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + context.getData().write(guildData -> { + Tag tag = guildData.getManagement().getTag(tagName); + if (tag == null) { + context.getTypedMessaging().replyDanger(context.i18n("commands.tag.cannot_find_tag", tagName)); + return; + } + String oldContent = tag.getContent(); + tag.setContent(context.getMessage(1)); + context.getTypedMessaging().replySuccess(context.i18n("commands.tag.edit.successfully_edited_tag", tagName)); + ModlogEvent event = ModlogEvent.CASCADE_TAG_UPDATED; + List embedFieldList = new ArrayList<>(); + embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.old_content", "modlog.general.variable", "```" + MarkdownSanitizer.sanitize(oldContent) + "```")); + embedFieldList.add(new ModlogEmbedField(false, "modlog.tag.new_content", "modlog.general.variable", "```" + MarkdownSanitizer.sanitize(tag.getContent()) + "```")); + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), tag, embedFieldList); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + }); } @Override From d194597deb2de3f5dd935d6dafedf16a7c8a53a9 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 31 May 2021 06:43:30 -0500 Subject: [PATCH 164/206] Wrap todo commands in write --- .../commands/useful/TodoAddSubCommand.java | 45 +++++++------ .../useful/TodoAddUserSubCommand.java | 37 +++++------ .../commands/useful/TodoCreateSubCommand.java | 22 ++++--- .../commands/useful/TodoRemoveSubCommand.java | 64 ++++++++++--------- .../useful/TodoRemoveUserSubCommand.java | 37 +++++------ .../commands/useful/TodoSendSubCommand.java | 4 +- 6 files changed, 110 insertions(+), 99 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoAddSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoAddSubCommand.java index 33c488871..58e69c947 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoAddSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoAddSubCommand.java @@ -18,31 +18,34 @@ public void onCommand(Member sender, CommandContext context) { } String todoName = context.getArg(0).toLowerCase(); - TodoList todoList = context.getData().getUseful().getTodoList(todoName); + context.getData().write(guildData -> { + TodoList todoList = guildData.getUseful().getTodoList(todoName); - if (todoList == null) { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.list_does_not_exist", todoName)); - return; - } + if (todoList == null) { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.list_does_not_exist", todoName)); + return; + } - if (!todoList.canUserEdit(context.getMember().getIdLong())) { - Member owner = context.getGuild().getMemberById(todoList.getOwnerId()); - if (owner != null) { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.cannot_edit", owner.getAsMention())); - } else { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.cannot_edit_no_owner")); - context.getData().getUseful().deleteTodoList(todoName); + if (!todoList.canUserEdit(context.getMember().getIdLong())) { + Member owner = context.getGuild().getMemberById(todoList.getOwnerId()); + if (owner != null) { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.cannot_edit", owner.getAsMention())); + } else { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.cannot_edit_no_owner")); + context.getData().getUseful().deleteTodoList(todoName); + } + return; } - return; - } - int index = todoList.addTodoItem(context.getMessage(1)) + 1; - EmbedBuilder builder = MessagingObjects.getClearThreadLocalEmbedBuilder(); - builder.setTitle(context.i18n("commands.todo.add.embed_title")); - builder.addField(context.i18n("commands.todo.embed_position_field"), String.valueOf(index), true); - builder.addField(context.i18n("commands.todo.embed_item_field"), context.getMessage(1), true); - context.getTypedMessaging().replySuccess(builder); - todoList.edit(context); + int index = todoList.addTodoItem(context.getMessage(1)) + 1; + EmbedBuilder builder = MessagingObjects.getClearThreadLocalEmbedBuilder(); + builder.setTitle(context.i18n("commands.todo.add.embed_title")); + builder.addField(context.i18n("commands.todo.embed_position_field"), String.valueOf(index), true); + builder.addField(context.i18n("commands.todo.embed_item_field"), context.getMessage(1), true); + context.getTypedMessaging().replySuccess(builder); + todoList.edit(context); + + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoAddUserSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoAddUserSubCommand.java index d771e79e9..e88d54d17 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoAddUserSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoAddUserSubCommand.java @@ -17,30 +17,31 @@ public void onCommand(Member sender, CommandContext context) { } String todoName = context.getArg(0).toLowerCase(); - TodoList todoList = context.getData().getUseful().getTodoList(todoName); + context.getData().write(guildData -> { + TodoList todoList = guildData.getUseful().getTodoList(todoName); - if (todoList == null) { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.list_does_not_exist", todoName)); - return; - } + if (todoList == null) { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.list_does_not_exist", todoName)); + return; + } - if (todoList.getOwnerId() != context.getMember().getIdLong()) { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.owner_only")); - return; - } + if (todoList.getOwnerId() != context.getMember().getIdLong()) { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.owner_only")); + return; + } - //TODO allow multiple users to be added/removed at once - Member target = DiscordUtils.getMember(context.getGuild(), context.getArg(1)); - - if (target == null) { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.user_not_found", context.getArg(1))); - return; - } + //TODO allow multiple users to be added/removed at once + Member target = DiscordUtils.getMember(context.getGuild(), context.getArg(1)); - todoList.addEditUser(target); + if (target == null) { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.user_not_found", context.getArg(1))); + return; + } - context.getTypedMessaging().replySuccess(context.i18n("commands.todo.adduser.added", target.getUser().getAsTag(), todoName)); + todoList.addEditUser(target); + context.getTypedMessaging().replySuccess(context.i18n("commands.todo.adduser.added", target.getUser().getAsTag(), todoName)); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoCreateSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoCreateSubCommand.java index 0619d6d55..02f163ad9 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoCreateSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoCreateSubCommand.java @@ -18,20 +18,22 @@ public void onCommand(Member sender, CommandContext context) { // Warn if the original argument contains uppercase letters boolean warnUppercase = !context.getArg(0).equals(context.getArg(0).toLowerCase()); String todoName = context.getArg(0).toLowerCase(); - TodoList todoList = context.getData().getUseful().createTodoList(todoName, context.getMember().getIdLong()); + context.getData().write(guildData -> { + TodoList todoList = guildData.getUseful().createTodoList(todoName, context.getMember().getIdLong()); - if (todoList == null) { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.create.list_exists")); - return; - } + if (todoList == null) { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.create.list_exists")); + return; + } - String message = context.i18n("commands.todo.create.created", todoName); + String message = context.i18n("commands.todo.create.created", todoName); - if (warnUppercase) { - message += "\n\n" + context.i18n("commands.todo.create.warn_uppercase", todoName); - } + if (warnUppercase) { + message += "\n\n" + context.i18n("commands.todo.create.warn_uppercase", todoName); + } - context.getTypedMessaging().replySuccess(message); + context.getTypedMessaging().replySuccess(message); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoRemoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoRemoveSubCommand.java index 0b332c421..a2386d8e0 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoRemoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoRemoveSubCommand.java @@ -23,46 +23,48 @@ public void onCommand(Member sender, CommandContext context) { } String todoName = context.getArg(0).toLowerCase(); - TodoList todoList = context.getData().getUseful().getTodoList(todoName); + context.getData().write(guildData -> { + TodoList todoList = guildData.getUseful().getTodoList(todoName); - if (todoList == null) { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.list_does_not_exist", todoName)); - return; - } + if (todoList == null) { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.list_does_not_exist", todoName)); + return; + } - if (!todoList.canUserEdit(context.getMember().getIdLong())) { - Member owner = context.getGuild().getMemberById(todoList.getOwnerId()); - if (owner != null) { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.cannot_edit", owner.getAsMention())); - } else { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.cannot_edit_no_owner")); - context.getData().getUseful().deleteTodoList(todoName); + if (!todoList.canUserEdit(context.getMember().getIdLong())) { + Member owner = context.getGuild().getMemberById(todoList.getOwnerId()); + if (owner != null) { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.cannot_edit", owner.getAsMention())); + } else { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.cannot_edit_no_owner")); + context.getData().getUseful().deleteTodoList(todoName); + } + return; } - return; - } - int index = context.getArgAsInteger(1) - 1; + int index = context.getArgAsInteger(1) - 1; - if (index < 0 || index > todoList.getItems().size()) { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.remove.item_does_not_exist")); - return; - } + if (index < 0 || index > todoList.getItems().size()) { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.remove.item_does_not_exist")); + return; + } - TodoList.TodoListItem item = todoList.removeTodoItem(index); - EmbedBuilder builder = MessagingObjects.getClearThreadLocalEmbedBuilder(); - builder.setTitle(context.i18n("commands.todo.remove.embed_title")); - builder.addField(context.i18n("commands.todo.embed_list_field"), todoName, false); - builder.addField(context.i18n("commands.todo.embed_item_field"), item.getText(), false); - context.getTypedMessaging().replySuccess(builder); + TodoList.TodoListItem item = todoList.removeTodoItem(index); + EmbedBuilder builder = MessagingObjects.getClearThreadLocalEmbedBuilder(); + builder.setTitle(context.i18n("commands.todo.remove.embed_title")); + builder.addField(context.i18n("commands.todo.embed_list_field"), todoName, false); + builder.addField(context.i18n("commands.todo.embed_item_field"), item.getText(), false); + context.getTypedMessaging().replySuccess(builder); - if (todoList.getItems().size() == 0) { - context.getData().getUseful().deleteTodoList(todoName); - context.reply(context.i18n("commands.todo.remove.deleted")); - } + if (todoList.getItems().size() == 0) { + guildData.getUseful().deleteTodoList(todoName); + context.reply(context.i18n("commands.todo.remove.deleted")); + } - todoList.setCurrentItem(Math.max(todoList.getCurrentItem() - 1, 0)); + todoList.setCurrentItem(Math.max(todoList.getCurrentItem() - 1, 0)); - todoList.edit(context); + todoList.edit(context); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoRemoveUserSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoRemoveUserSubCommand.java index 6f7f6842b..1d6840c70 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoRemoveUserSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoRemoveUserSubCommand.java @@ -17,30 +17,31 @@ public void onCommand(Member sender, CommandContext context) { } String todoName = context.getArg(0).toLowerCase(); - TodoList todoList = context.getData().getUseful().getTodoList(todoName); + context.getData().write(guildData -> { + TodoList todoList = guildData.getUseful().getTodoList(todoName); - if (todoList == null) { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.list_does_not_exist", todoName)); - return; - } + if (todoList == null) { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.list_does_not_exist", todoName)); + return; + } - if (todoList.getOwnerId() != context.getMember().getIdLong()) { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.owner_only")); - return; - } + if (todoList.getOwnerId() != context.getMember().getIdLong()) { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.owner_only")); + return; + } - //TODO allow multiple users to be added/removed at once - Member target = DiscordUtils.getMember(context.getGuild(), context.getArg(1)); - - if (target == null) { - context.getTypedMessaging().replyDanger(context.i18n("commands.todo.user_not_found", context.getArg(1))); - return; - } + //TODO allow multiple users to be added/removed at once + Member target = DiscordUtils.getMember(context.getGuild(), context.getArg(1)); - todoList.removeEditUser(target); + if (target == null) { + context.getTypedMessaging().replyDanger(context.i18n("commands.todo.user_not_found", context.getArg(1))); + return; + } - context.getTypedMessaging().replySuccess(context.i18n("commands.todo.removeuser.removed", target.getUser().getAsTag(), todoName)); + todoList.removeEditUser(target); + context.getTypedMessaging().replySuccess(context.i18n("commands.todo.removeuser.removed", target.getUser().getAsTag(), todoName)); + }); } @Override diff --git a/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoSendSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoSendSubCommand.java index ef029504c..e42df5554 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoSendSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/useful/TodoSendSubCommand.java @@ -42,7 +42,9 @@ public void onCommand(Member sender, CommandContext context) { context.getTypedMessaging().replyDanger(context.i18n("commands.todo.cannot_edit", owner.getAsMention())); } else { context.getTypedMessaging().replyDanger(context.i18n("commands.todo.cannot_edit_no_owner")); - context.getData().getUseful().deleteTodoList(todoName); + context.getData().write(guildData -> { + context.getData().getUseful().deleteTodoList(todoName); + }); } return; } From 3ae0597a43cb928b6ecbbe06424e2fd1c0118e52 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 31 May 2021 07:02:40 -0500 Subject: [PATCH 165/206] Wrap music commands in write --- .../cascadebot/commands/music/EqualizerCommand.java | 10 ++++++++-- .../commands/music/EqualizerResetSubCommand.java | 5 +++++ .../cascadebot/commands/music/VolumeCommand.java | 8 ++++++-- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerCommand.java index cc63d10c4..1669844c1 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerCommand.java @@ -83,7 +83,10 @@ public void onCommand(Member sender, CommandContext context) { player.setBand(currentBand.get(), ((float) gain) / 20f); if (context.getData().getMusic().getPreserveEqualizer()) { - context.getData().getMusic().getEqualizerBands().replace(currentBand.get(), ((float) gain) / 20f); + int finalGain = gain; + context.getData().write(guildData -> { + guildData.getMusic().getEqualizerBands().replace(currentBand.get(), ((float) finalGain) / 20f); + }); } message.editMessage(getEqualizerEmbed(player.getCurrentBands(), currentBand.get(), runner.getUser(), context).build()).override(true).queue(); @@ -101,7 +104,10 @@ public void onCommand(Member sender, CommandContext context) { player.setBand(currentBand.get(), ((float) gain) / 20f); if (context.getData().getMusic().getPreserveEqualizer()) { - context.getData().getMusic().getEqualizerBands().replace(currentBand.get(), ((float) gain) / 20f); + int finalGain = gain; + context.getData().write(guildData -> { + guildData.getMusic().getEqualizerBands().replace(currentBand.get(), ((float) finalGain) / 20f); + }); } message.editMessage(getEqualizerEmbed(player.getCurrentBands(), currentBand.get(), runner.getUser(), context).build()).override(true).queue(); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerResetSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerResetSubCommand.java index ea0b0a71c..256fdb122 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerResetSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerResetSubCommand.java @@ -35,6 +35,11 @@ public void onCommand(Member sender, CommandContext context) { bands.put(i, 0.0f); } + if (context.getData().getMusic().getPreserveEqualizer()) { + context.getData().write(guildData -> { + guildData.getMusic().setEqualizerBands(bands); + }); + } ((CascadeLavalinkPlayer) context.getMusicPlayer()).setBands(bands); context.getTypedMessaging().replySuccess(context.i18n("commands.equalizer.reset.success")); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/music/VolumeCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/music/VolumeCommand.java index 49fba3244..42cc3afa6 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/music/VolumeCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/music/VolumeCommand.java @@ -45,7 +45,9 @@ public void onCommand(Member sender, CommandContext context) { () -> { player.setVolume(volume); if (context.getData().getMusic().getPreserveVolume()) { - context.getData().getMusic().setVolume(volume); + context.getData().write(guildData -> { + guildData.getMusic().setVolume(volume); + }); } context.getTypedMessaging().replyInfo(context.i18n("commands.volume.volume_set", player.getVolume())); }); @@ -64,7 +66,9 @@ public void onCommand(Member sender, CommandContext context) { } else { player.setVolume(volume); if (context.getData().getMusic().getPreserveVolume()) { - context.getData().getMusic().setVolume(volume); + context.getData().write(guildData -> { + guildData.getMusic().setVolume(volume); + }); } context.getTypedMessaging().replyInfo(context.i18n("commands.volume.volume_set", player.getVolume())); } From 17293a92ff07373d9f88ce7a1341da425044d481 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 31 May 2021 07:17:00 -0500 Subject: [PATCH 166/206] Wrap persistent buttons in write --- .../utils/buttons/PersistentButton.kt | 712 +++++++++++------- 1 file changed, 443 insertions(+), 269 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButton.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButton.kt index a047e982a..e55e81a51 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButton.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButton.kt @@ -11,276 +11,450 @@ import org.cascadebot.cascadebot.commands.music.SkipCommand import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.utils.DiscordUtils import org.cascadebot.cascadebot.utils.votes.VoteButtonGroup +import java.util.function.Consumer enum class PersistentButton(@field:Transient val button: Button) { - TODO_BUTTON_CHECK(Button.UnicodeButton(UnicodeConstants.TICK, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val todoList = GuildDataManager.getGuildData(channel.guild.idLong).useful.getTodoListByMessage(message.idLong) - if (!todoList.canUserEdit(runner.idLong)) { - return@IButtonRunnable - } - val item = todoList.items[todoList.currentItem] - item.done = true - todoList.addUncheckButton(message) - message.editMessage(todoList.todoListMessage).queue() - })), - TODO_BUTTON_UNCHECK(Button.UnicodeButton(UnicodeConstants.WHITE_HALLOW_SQUARE, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val todoList = GuildDataManager.getGuildData(channel.guild.idLong).useful.getTodoListByMessage(message.idLong) - if (!todoList.canUserEdit(runner.idLong)) { - return@IButtonRunnable - } - val item = todoList.items[todoList.currentItem] - item.done = false - todoList.addCheckButton(message) - message.editMessage(todoList.todoListMessage).queue() - })), - TODO_BUTTON_NAVIGATE_LEFT(Button.UnicodeButton(UnicodeConstants.BACKWARD_ARROW, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val todoList = GuildDataManager.getGuildData(channel.guild.idLong).useful.getTodoListByMessage(message.idLong) - if (!todoList.canUserEdit(runner.idLong)) { - return@IButtonRunnable - } - val currentPage = todoList.currentItem / 10 + 1 - val start = currentPage * 10 - 10 - if (start == 0) { - return@IButtonRunnable - } - val newPos = Math.max(start - 10, 0) - todoList.currentItem = newPos - message.editMessage(todoList.todoListMessage).queue() - todoList.doCheckToggle(message) - })), - TODO_BUTTON_NAVIGATE_RIGHT(Button.UnicodeButton(UnicodeConstants.FORWARD_ARROW, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val todoList = GuildDataManager.getGuildData(channel.guild.idLong).useful.getTodoListByMessage(message.idLong) - if (!todoList.canUserEdit(runner.idLong)) { - return@IButtonRunnable - } - val currentPage = todoList.currentItem / 10 + 1 - val start = currentPage * 10 - 10 - val end = start + 9 - if (end + 1 >= todoList.items.size) { - return@IButtonRunnable - } - todoList.currentItem = end + 1 - message.editMessage(todoList.todoListMessage).queue() - todoList.doCheckToggle(message) - })), - TODO_BUTTON_NAVIGATE_UP(Button.UnicodeButton(UnicodeConstants.ARROW_UP, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val todoList = GuildDataManager.getGuildData(channel.guild.idLong).useful.getTodoListByMessage(message.idLong) - if (!todoList.canUserEdit(runner.idLong)) { - return@IButtonRunnable - } - val newItem = todoList.currentItem - 1 - if (newItem < 0) { - return@IButtonRunnable - } - todoList.currentItem = newItem - message.editMessage(todoList.todoListMessage).queue() - todoList.doCheckToggle(message) - })), - TODO_BUTTON_NAVIGATE_DOWN(Button.UnicodeButton(UnicodeConstants.ARROW_DOWN, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val todoList = GuildDataManager.getGuildData(channel.guild.idLong).useful.getTodoListByMessage(message.idLong) - if (!todoList.canUserEdit(runner.idLong)) { - return@IButtonRunnable - } - val newItem = todoList.currentItem + 1 - if (newItem >= todoList.items.size) { - return@IButtonRunnable - } - todoList.currentItem = newItem - message.editMessage(todoList.todoListMessage).queue() - todoList.doCheckToggle(message) - })), - VOTE_BUTTON_YES(Button.UnicodeButton(UnicodeConstants.TICK, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, UnicodeConstants.TICK) - })), - VOTE_BUTTON_NO(Button.UnicodeButton(UnicodeConstants.RED_CROSS, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, UnicodeConstants.RED_CROSS) - })), - VOTE_BUTTON_ONE(Button.UnicodeButton(UnicodeConstants.ONE, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 1) - })), - VOTE_BUTTON_TWO(Button.UnicodeButton(UnicodeConstants.TWO, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 2) - })), - VOTE_BUTTON_THREE(Button.UnicodeButton(UnicodeConstants.THREE, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 3) - })), - VOTE_BUTTON_FOUR(Button.UnicodeButton(UnicodeConstants.FOUR, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 4) - })), - VOTE_BUTTON_FIVE(Button.UnicodeButton(UnicodeConstants.FIVE, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 5) - })), - VOTE_BUTTON_SIX(Button.UnicodeButton(UnicodeConstants.SIX, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 6) - })), - VOTE_BUTTON_SEVEN(Button.UnicodeButton(UnicodeConstants.SEVEN, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 7) - })), - VOTE_BUTTON_EIGHT(Button.UnicodeButton(UnicodeConstants.EIGHT, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 8) - })), - VOTE_BUTTON_NINE(Button.UnicodeButton(UnicodeConstants.NINE, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 9) - })), - VOTE_BUTTON_A(Button.UnicodeButton(UnicodeConstants.A, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 0) - })), - VOTE_BUTTON_B(Button.UnicodeButton(UnicodeConstants.B, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 1) - })), - VOTE_BUTTON_C(Button.UnicodeButton(UnicodeConstants.C, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 2) - })), - VOTE_BUTTON_D(Button.UnicodeButton(UnicodeConstants.D, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 3) - })), - VOTE_BUTTON_E(Button.UnicodeButton(UnicodeConstants.E, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 4) - })), - VOTE_BUTTON_F(Button.UnicodeButton(UnicodeConstants.F, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 5) - })), - VOTE_BUTTON_G(Button.UnicodeButton(UnicodeConstants.G, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 6) - })), - VOTE_BUTTON_H(Button.UnicodeButton(UnicodeConstants.H, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 7) - })), - VOTE_BUTTON_I(Button.UnicodeButton(UnicodeConstants.I, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 8) - })), - VOTE_BUTTON_J(Button.UnicodeButton(UnicodeConstants.J, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 9) - })), - VOTE_BUTTON_K(Button.UnicodeButton(UnicodeConstants.K, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 10) - })), - VOTE_BUTTON_L(Button.UnicodeButton(UnicodeConstants.L, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 11) - })), - VOTE_BUTTON_M(Button.UnicodeButton(UnicodeConstants.M, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 12) - })), - VOTE_BUTTON_N(Button.UnicodeButton(UnicodeConstants.N, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 13) - })), - VOTE_BUTTON_O(Button.UnicodeButton(UnicodeConstants.O, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - val voteButtonGroup = GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { - return@IButtonRunnable - } - voteButtonGroup.addVote(runner.user, 14) - })), - SKIP_BUTTON_FORCE(Button.UnicodeButton(UnicodeConstants.FAST_FORWARD, IButtonRunnable { runner: Member?, channel: TextChannel, message: Message -> - val data = GuildDataManager.getGuildData(channel.guild.idLong) - if (!data.management.permissions.hasPermission(runner, channel, CascadeBot.INS.permissionsManager.getPermission("skip.force"), data.core)) { - return@IButtonRunnable - } - message.delete().queue(null, DiscordUtils.handleExpectedErrors(ErrorResponse.UNKNOWN_MESSAGE)) - val voteButtonGroup = data.persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? - voteButtonGroup!!.stopVote() - SkipCommand.voteMap.remove(channel.guild.idLong) - CascadeBot.INS.musicHandler.getPlayer(channel.guild.idLong)!!.skip() - })); + TODO_BUTTON_CHECK( + Button.UnicodeButton( + UnicodeConstants.TICK, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + GuildDataManager.getGuildData(channel.guild.idLong) + .write(Consumer { + val todoList = + it.useful.getTodoListByMessage(message.idLong) + if (todoList.canUserEdit(runner.idLong)) { + val item = todoList.items[todoList.currentItem] + item.done = true + todoList.addUncheckButton(message) + message.editMessage(todoList.todoListMessage).queue() + } + }) + }) + ), + TODO_BUTTON_UNCHECK( + Button.UnicodeButton( + UnicodeConstants.WHITE_HALLOW_SQUARE, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + GuildDataManager.getGuildData(channel.guild.idLong).write(Consumer { + val todoList = + it.useful.getTodoListByMessage(message.idLong) + if (todoList.canUserEdit(runner.idLong)) { + val item = todoList.items[todoList.currentItem] + item.done = false + todoList.addCheckButton(message) + message.editMessage(todoList.todoListMessage).queue() + } + }) + }) + ), + TODO_BUTTON_NAVIGATE_LEFT( + Button.UnicodeButton( + UnicodeConstants.BACKWARD_ARROW, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val todoList = + GuildDataManager.getGuildData(channel.guild.idLong).useful.getTodoListByMessage(message.idLong) + if (!todoList.canUserEdit(runner.idLong)) { + return@IButtonRunnable + } + val currentPage = todoList.currentItem / 10 + 1 + val start = currentPage * 10 - 10 + if (start == 0) { + return@IButtonRunnable + } + val newPos = Math.max(start - 10, 0) + todoList.currentItem = newPos + message.editMessage(todoList.todoListMessage).queue() + todoList.doCheckToggle(message) + }) + ), + TODO_BUTTON_NAVIGATE_RIGHT( + Button.UnicodeButton( + UnicodeConstants.FORWARD_ARROW, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val todoList = + GuildDataManager.getGuildData(channel.guild.idLong).useful.getTodoListByMessage(message.idLong) + if (!todoList.canUserEdit(runner.idLong)) { + return@IButtonRunnable + } + val currentPage = todoList.currentItem / 10 + 1 + val start = currentPage * 10 - 10 + val end = start + 9 + if (end + 1 >= todoList.items.size) { + return@IButtonRunnable + } + todoList.currentItem = end + 1 + message.editMessage(todoList.todoListMessage).queue() + todoList.doCheckToggle(message) + }) + ), + TODO_BUTTON_NAVIGATE_UP( + Button.UnicodeButton( + UnicodeConstants.ARROW_UP, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val todoList = + GuildDataManager.getGuildData(channel.guild.idLong).useful.getTodoListByMessage(message.idLong) + if (!todoList.canUserEdit(runner.idLong)) { + return@IButtonRunnable + } + val newItem = todoList.currentItem - 1 + if (newItem < 0) { + return@IButtonRunnable + } + todoList.currentItem = newItem + message.editMessage(todoList.todoListMessage).queue() + todoList.doCheckToggle(message) + }) + ), + TODO_BUTTON_NAVIGATE_DOWN( + Button.UnicodeButton( + UnicodeConstants.ARROW_DOWN, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val todoList = + GuildDataManager.getGuildData(channel.guild.idLong).useful.getTodoListByMessage(message.idLong) + if (!todoList.canUserEdit(runner.idLong)) { + return@IButtonRunnable + } + val newItem = todoList.currentItem + 1 + if (newItem >= todoList.items.size) { + return@IButtonRunnable + } + todoList.currentItem = newItem + message.editMessage(todoList.todoListMessage).queue() + todoList.doCheckToggle(message) + }) + ), + VOTE_BUTTON_YES( + Button.UnicodeButton( + UnicodeConstants.TICK, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, UnicodeConstants.TICK) + }) + ), + VOTE_BUTTON_NO( + Button.UnicodeButton( + UnicodeConstants.RED_CROSS, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, UnicodeConstants.RED_CROSS) + }) + ), + VOTE_BUTTON_ONE( + Button.UnicodeButton( + UnicodeConstants.ONE, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 1) + }) + ), + VOTE_BUTTON_TWO( + Button.UnicodeButton( + UnicodeConstants.TWO, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 2) + }) + ), + VOTE_BUTTON_THREE( + Button.UnicodeButton( + UnicodeConstants.THREE, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 3) + }) + ), + VOTE_BUTTON_FOUR( + Button.UnicodeButton( + UnicodeConstants.FOUR, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 4) + }) + ), + VOTE_BUTTON_FIVE( + Button.UnicodeButton( + UnicodeConstants.FIVE, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 5) + }) + ), + VOTE_BUTTON_SIX( + Button.UnicodeButton( + UnicodeConstants.SIX, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 6) + }) + ), + VOTE_BUTTON_SEVEN( + Button.UnicodeButton( + UnicodeConstants.SEVEN, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 7) + }) + ), + VOTE_BUTTON_EIGHT( + Button.UnicodeButton( + UnicodeConstants.EIGHT, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 8) + }) + ), + VOTE_BUTTON_NINE( + Button.UnicodeButton( + UnicodeConstants.NINE, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 9) + }) + ), + VOTE_BUTTON_A( + Button.UnicodeButton( + UnicodeConstants.A, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 0) + }) + ), + VOTE_BUTTON_B( + Button.UnicodeButton( + UnicodeConstants.B, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 1) + }) + ), + VOTE_BUTTON_C( + Button.UnicodeButton( + UnicodeConstants.C, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 2) + }) + ), + VOTE_BUTTON_D( + Button.UnicodeButton( + UnicodeConstants.D, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 3) + }) + ), + VOTE_BUTTON_E( + Button.UnicodeButton( + UnicodeConstants.E, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 4) + }) + ), + VOTE_BUTTON_F( + Button.UnicodeButton( + UnicodeConstants.F, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 5) + }) + ), + VOTE_BUTTON_G( + Button.UnicodeButton( + UnicodeConstants.G, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 6) + }) + ), + VOTE_BUTTON_H( + Button.UnicodeButton( + UnicodeConstants.H, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 7) + }) + ), + VOTE_BUTTON_I( + Button.UnicodeButton( + UnicodeConstants.I, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 8) + }) + ), + VOTE_BUTTON_J( + Button.UnicodeButton( + UnicodeConstants.J, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 9) + }) + ), + VOTE_BUTTON_K( + Button.UnicodeButton( + UnicodeConstants.K, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 10) + }) + ), + VOTE_BUTTON_L( + Button.UnicodeButton( + UnicodeConstants.L, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 11) + }) + ), + VOTE_BUTTON_M( + Button.UnicodeButton( + UnicodeConstants.M, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 12) + }) + ), + VOTE_BUTTON_N( + Button.UnicodeButton( + UnicodeConstants.N, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 13) + }) + ), + VOTE_BUTTON_O( + Button.UnicodeButton( + UnicodeConstants.O, + IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> + val voteButtonGroup = + GuildDataManager.getGuildData(channel.guild.idLong).persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + if (!voteButtonGroup!!.isUserAllowed(runner.idLong)) { + return@IButtonRunnable + } + voteButtonGroup.addVote(runner.user, 14) + }) + ), + SKIP_BUTTON_FORCE( + Button.UnicodeButton( + UnicodeConstants.FAST_FORWARD, + IButtonRunnable { runner: Member?, channel: TextChannel, message: Message -> + val data = GuildDataManager.getGuildData(channel.guild.idLong) + if (!data.management.permissions.hasPermission( + runner, + channel, + CascadeBot.INS.permissionsManager.getPermission("skip.force"), + data.core + ) + ) { + return@IButtonRunnable + } + message.delete().queue(null, DiscordUtils.handleExpectedErrors(ErrorResponse.UNKNOWN_MESSAGE)) + val voteButtonGroup = data.persistentButtons[channel.idLong]!![message.idLong] as VoteButtonGroup? + voteButtonGroup!!.stopVote() + SkipCommand.voteMap.remove(channel.guild.idLong) + CascadeBot.INS.musicHandler.getPlayer(channel.guild.idLong)!!.skip() + }) + ); } From 4dcca4bd6019c51885be0c5269eba8559a5e0001 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 31 May 2021 09:58:56 -0500 Subject: [PATCH 167/206] Write mode on MDC (correct branch this time) --- .../data/objects/GuildPermissions.java | 5 +++++ .../data/objects/GuildSettingsUseful.java | 7 +++--- .../cascadebot/data/objects/Tag.java | 17 +++++++++++++- .../cascadebot/events/CommandListener.java | 1 + .../cascadebot/permissions/objects/Group.java | 9 +++++++- .../permissions/objects/PermissionHolder.java | 4 ++++ .../cascadebot/permissions/objects/User.java | 4 ++++ .../cascadebot/utils/GuildDataUtils.java | 18 +++++++++++++++ .../cascadebot/data/objects/GuildData.kt | 22 ++++--------------- .../data/objects/GuildSettingsCore.kt | 7 +----- .../data/objects/GuildSettingsManagement.kt | 7 ++---- .../data/objects/GuildSettingsModeration.kt | 10 +++++---- .../cascadebot/data/objects/TodoList.kt | 9 ++++++++ 13 files changed, 82 insertions(+), 38 deletions(-) create mode 100644 src/main/java/org/cascadebot/cascadebot/utils/GuildDataUtils.java diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java index 58aaee82e..41c1a5310 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java @@ -29,6 +29,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +import static org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode; + public class GuildPermissions { @Getter @@ -158,6 +160,7 @@ private Result getDefaultAction(CascadePermission permission) { } public Group createGroup(String name) { + assertWriteMode(); Set ids = groups.stream().map(Group::getId).collect(Collectors.toSet()); Group group; int iterations = 0; @@ -174,6 +177,7 @@ public Group createGroup(String name) { } public boolean deleteGroup(String id) { + assertWriteMode(); return groups.removeIf(group -> group.getId().equals(id)); } @@ -218,6 +222,7 @@ public List getGroups() { } public void moveGroup(Group group, int position) throws IndexOutOfBoundsException { + assertWriteMode(); groups.remove(group); groups.add(position, group); } diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java index 87e2b8774..1285b1443 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java @@ -5,6 +5,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import static org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode; + @SettingsContainer(module = Module.USEFUL) public class GuildSettingsUseful { @@ -18,7 +20,7 @@ public TodoList getTodoList(String name) { } public TodoList createTodoList(String name, long owner) { - if (!writeMode) throw new UnsupportedOperationException("Cannot modify Guild data if not in write mode!"); + assertWriteMode(); if (todoLists.containsKey(name)) { return null; } @@ -28,12 +30,11 @@ public TodoList createTodoList(String name, long owner) { } public void deleteTodoList(String name) { - if (!writeMode) throw new UnsupportedOperationException("Cannot modify Guild data if not in write mode!"); + assertWriteMode(); todoLists.remove(name); } public TodoList getTodoListByMessage(long messageId) { - if (!writeMode) throw new UnsupportedOperationException("Cannot modify Guild data if not in write mode!"); TodoList list = null; for (Map.Entry listEntry : todoLists.entrySet()) { if (listEntry.getValue().getMessageId() == messageId) { diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java index 2e195322a..a6bdc926b 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java @@ -16,7 +16,8 @@ import java.util.regex.Pattern; -@Setter +import static org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode; + @NoArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor public class Tag extends PermissionObject { @@ -59,4 +60,18 @@ public String getCategory() { return category; } + public void setCategory(String category) { + assertWriteMode(); + this.category = category; + } + + public void setContent(String content) { + assertWriteMode(); + this.content = content; + } + + public void setName(String name) { + assertWriteMode(); + this.name = name; + } } \ No newline at end of file diff --git a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java index 6891a6ec6..73a88205d 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java @@ -64,6 +64,7 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { MDC.put("cascade.sender", event.getAuthor().toString()); MDC.put("cascade.shard_info", event.getJDA().getShardInfo().getShardString()); MDC.put("cascade.channel", event.getChannel().toString()); + MDC.put("writeMode", String.valueOf(false)); String message = Regex.MULTISPACE_REGEX.matcher(event.getMessage().getContentRaw()).replaceAll(" "); message = MULTIQUOTE_REGEX.matcher(message).replaceAll(""); diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java index cbf58685b..b5cd65f68 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java @@ -16,6 +16,8 @@ import java.util.Set; +import static org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode; + @ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) @NoArgsConstructor(access = AccessLevel.PRIVATE) @@ -25,7 +27,6 @@ public class Group extends PermissionHolder { // This is normal alphanumeric with similar characters removed for less errors when inputting private String id = RandomStringUtils.random(5, "abcdefghijkmnopqrstuvwxyzACDEFHJKLMNPRSTUVWXYZ123467890"); - @Setter private String name; private Set roleIds = Sets.newConcurrentHashSet(); @@ -35,10 +36,12 @@ public Group(String name) { } public boolean linkRole(long roleId) { + assertWriteMode(); return roleIds.add(roleId); } public boolean unlinkRole(long roleId) { + assertWriteMode(); return roleIds.remove(roleId); } @@ -59,4 +62,8 @@ public String getName() { return name; } + public void setName(String name) { + assertWriteMode(); + this.name = name; + } } diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/PermissionHolder.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/PermissionHolder.java index 7afbb036c..ccffdd89c 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/PermissionHolder.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/PermissionHolder.java @@ -9,6 +9,8 @@ import java.util.Set; +import static org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode; + @ToString @EqualsAndHashCode public abstract class PermissionHolder { @@ -22,10 +24,12 @@ public Set getPermissions() { } public boolean addPermission(String permission) { + assertWriteMode(); return permissions.add(permission); } public boolean removePermission(String permission) { + assertWriteMode(); return permissions.remove(permission); } diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java index 0d776f3ec..ff8ddc025 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java @@ -11,6 +11,8 @@ import java.util.Set; +import static org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode; + @ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) public class User extends PermissionHolder { @@ -18,10 +20,12 @@ public class User extends PermissionHolder { private final Set groups = Sets.newConcurrentHashSet(); public boolean addGroup(Group group) { + assertWriteMode(); return groups.add(group.getId()); } public boolean removeGroup(Group group) { + assertWriteMode(); return groups.remove(group.getId()); } diff --git a/src/main/java/org/cascadebot/cascadebot/utils/GuildDataUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/GuildDataUtils.java new file mode 100644 index 000000000..5394912ff --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/utils/GuildDataUtils.java @@ -0,0 +1,18 @@ +package org.cascadebot.cascadebot.utils; + +import org.slf4j.MDC; + +public class GuildDataUtils { + + public static void assertWriteMode() { + String mode = MDC.get("writeMode"); + if (mode == null) { + throw new UnsupportedOperationException("Cannot write guild data if not in write mode!"); + } + boolean writeMode = Boolean.parseBoolean(mode); + if (!writeMode) { + throw new UnsupportedOperationException("Cannot write guild data if not in write mode!"); + } + } + +} diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 7ecc29e1a..abcf9af45 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -20,6 +20,7 @@ import org.cascadebot.cascadebot.utils.buttons.PersistentButtonGroup import org.cascadebot.cascadebot.utils.diff.DiffUtils import org.cascadebot.cascadebot.utils.diff.Difference import org.cascadebot.cascadebot.utils.pagination.PageCache +import org.slf4j.MDC import java.lang.UnsupportedOperationException import java.lang.reflect.Type import java.util.Date @@ -29,6 +30,7 @@ import java.util.function.Consumer import kotlin.concurrent.withLock import kotlin.reflect.jvm.javaType import kotlin.reflect.typeOf +import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode class GuildData(@field:Id val guildId: Long): Cloneable { @@ -36,10 +38,6 @@ class GuildData(@field:Id val guildId: Long): Cloneable { @kotlin.jvm.Transient val lock: ReadWriteLock = ReentrantReadWriteLock() - @Transient - @kotlin.jvm.Transient - var writeMode = false; - private constructor() : this(0L) { // Private constructor for MongoDB } @@ -143,27 +141,15 @@ class GuildData(@field:Id val guildId: Long): Cloneable { fun write(writer: Consumer) { this.lock.writeLock().withLock { val copy: GuildData = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(this), this.javaClass) - copy.setAllWriteMode(true) + MDC.put("writeMode", true.toString()) writer.accept(copy); - copy.setAllWriteMode(false) + MDC.put("writeMode", false.toString()) val diff: Difference = DiffUtils.diff(this, copy) GuildDataManager.updateDiff(guildId, diff, copy) //println(GsonBuilder().setPrettyPrinting().create().toJson(diff)) } } - fun setAllWriteMode(mode: Boolean) { - writeMode = mode - core.writeMode = mode - useful.writeMode = mode - management.writeMode = mode - moderation.writeMode = mode - } - - fun assertWriteMode() { - if (!writeMode) throw UnsupportedOperationException("Cannot modify Guild data if not in write mode!") - } - } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt index ceaaa8823..3c661cee1 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt @@ -6,6 +6,7 @@ import org.cascadebot.cascadebot.commandmeta.MainCommand import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.Config import org.cascadebot.cascadebot.data.language.Locale +import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode import java.lang.UnsupportedOperationException import java.util.concurrent.ConcurrentHashMap @@ -37,8 +38,6 @@ class GuildSettingsCore { @Setting var helpShowAllModules = false - var writeMode = false - var locale: Locale = Locale.getDefaultLocale() var prefix: String = Config.INS.defaultPrefix @@ -139,8 +138,4 @@ class GuildSettingsCore { //endregion - fun assertWriteMode() { - if (!writeMode) throw java.lang.UnsupportedOperationException("Cannot modify Guild data if not in write mode!") - } - } \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt index 35fdc925d..a2d4c7198 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt @@ -1,6 +1,8 @@ package org.cascadebot.cascadebot.data.objects import org.cascadebot.cascadebot.commandmeta.Module +import org.cascadebot.cascadebot.utils.GuildDataUtils +import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode import java.util.concurrent.ConcurrentHashMap @SettingsContainer(module = Module.MANAGEMENT) @@ -26,8 +28,6 @@ class GuildSettingsManagement { val greetings = Greetings() val autoRoles: MutableSet = mutableSetOf() - var writeMode = false - fun getTag(key: String): Tag? { return tags[key] } @@ -46,7 +46,4 @@ class GuildSettingsManagement { return tags.remove(key) != null } - fun assertWriteMode() { - if (!writeMode) throw java.lang.UnsupportedOperationException("Cannot modify Guild data if not in write mode!") - } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index b034e31b2..0890ab0cc 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -16,6 +16,7 @@ import org.cascadebot.cascadebot.data.database.DebugLogCallback import org.cascadebot.cascadebot.data.language.Language import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.moderation.ModlogEvent +import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode import org.cascadebot.cascadebot.utils.toCapitalized import java.net.URL import java.time.Instant @@ -100,6 +101,7 @@ class GuildSettingsModeration { } private fun createModlogEventsInfo(channel: TextChannel, consumer: Consumer) { + assertWriteMode() val eventsInfo = ChannelModlogEventsInfo() eventsInfo.id = modlogChannelNum++ modlogEvents.put(channel.idLong, eventsInfo) @@ -111,10 +113,6 @@ class GuildSettingsModeration { } } - fun assertWriteMode() { - if (!writeMode) throw java.lang.UnsupportedOperationException("Cannot modify Guild data if not in write mode!") - } - class ChannelModlogEventsInfo { private val events: MutableSet = LinkedHashSet() @@ -131,6 +129,7 @@ class GuildSettingsModeration { } constructor(webhookId: Long, webhookToken: String, id: Int) { + assertWriteMode() this.webhookId = webhookId this.webhookToken = webhookToken this.id = id @@ -138,6 +137,7 @@ class GuildSettingsModeration { } fun buildWebhookClient() { + assertWriteMode() webhookClient = WebhookClientBuilder(webhookId, webhookToken).build() } @@ -150,10 +150,12 @@ class GuildSettingsModeration { } fun addEvent(event: ModlogEvent): Boolean { + assertWriteMode() return events.add(event) } fun removeEvent(event: ModlogEvent): Boolean { + assertWriteMode() return events.remove(event) } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt index 025f70317..2782f7033 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt @@ -10,6 +10,7 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.messaging.Messaging.sendButtonedMessage import org.cascadebot.cascadebot.messaging.MessagingObjects +import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode import org.cascadebot.cascadebot.utils.buttons.PersistentButton import org.cascadebot.cascadebot.utils.buttons.PersistentButtonGroup @@ -28,20 +29,24 @@ class TodoList(val ownerId: Long) { } fun addTodoItem(text: String?): Int { + assertWriteMode() val item = TodoListItem(text) items.add(item) return items.indexOf(item) } fun removeTodoItem(id: Int): TodoListItem { + assertWriteMode() return items.removeAt(id) } fun addEditUser(member: Member) { + assertWriteMode() users.add(member.idLong) } fun removeEditUser(member: Member) { + assertWriteMode() users.remove(member.idLong) } @@ -65,6 +70,7 @@ class TodoList(val ownerId: Long) { } fun edit(context: CommandContext) { + assertWriteMode() if (messageId == -1L || channelId == -1L) return val originalChannel = context.guild.getTextChannelById(channelId) if (originalChannel != null && originalChannel.idLong == channelId) { @@ -97,6 +103,7 @@ class TodoList(val ownerId: Long) { } fun addUncheckButton(message: Message?) { + assertWriteMode() val channel = CascadeBot.INS.client.getTextChannelById(channelId) if (channel != null) { val data = GuildDataManager.getGuildData(channel.guild.idLong) @@ -107,6 +114,7 @@ class TodoList(val ownerId: Long) { } fun addCheckButton(message: Message?) { + assertWriteMode() val channel = CascadeBot.INS.client.getTextChannelById(channelId) if (channel != null) { val data = GuildDataManager.getGuildData(channel.guild.idLong) @@ -117,6 +125,7 @@ class TodoList(val ownerId: Long) { } fun doCheckToggle(message: Message?) { + assertWriteMode() val item = items[this.currentItem] if (item.done) { addUncheckButton(message) From 3583c65180c4e38e40411a570b6c04aaeeb3a3a0 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 31 May 2021 10:41:01 -0500 Subject: [PATCH 168/206] Start trying to fix some bson to java conversions --- .../org/cascadebot/cascadebot/CascadeBot.java | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index b410a51db..d1c3ae60f 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -13,6 +13,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.mongodb.async.client.ChangeStreamIterable; +import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.model.changestream.UpdateDescription; import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory; import io.sentry.Sentry; @@ -28,7 +29,10 @@ import net.dv8tion.jda.api.sharding.ShardManager; import okhttp3.OkHttpClient; import org.apache.commons.lang3.StringUtils; +import org.bson.BsonReader; +import org.bson.BsonType; import org.bson.BsonValue; +import org.bson.codecs.DecoderContext; import org.cascadebot.cascadebot.commandmeta.ArgumentManager; import org.cascadebot.cascadebot.commandmeta.CommandManager; import org.cascadebot.cascadebot.data.Config; @@ -68,7 +72,10 @@ import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; +import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.concurrent.TimeUnit; @@ -205,7 +212,8 @@ private void init() { } databaseManager.runAsyncTask(database -> { - ChangeStreamIterable changeStreamIterable = database.getCollection(GuildDataManager.COLLECTION, GuildData.class).watch(); + ChangeStreamIterable changeStreamIterable = database.getCollection(GuildDataManager.COLLECTION, GuildData.class).watch() + .fullDocument(FullDocument.UPDATE_LOOKUP); // TODO not this changeStreamIterable.forEach(guildDataChangeStreamDocument -> { if (guildDataChangeStreamDocument.getFullDocument() != null) { GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()); @@ -214,7 +222,7 @@ private void init() { UpdateDescription updateDescription = guildDataChangeStreamDocument.getUpdateDescription(); if (updateDescription.getUpdatedFields() != null) { for (Map.Entry change : updateDescription.getUpdatedFields().entrySet()) { - if (!updateGuildData(change.getKey(), currentData, BsonUtils.toJavaType(change.getValue()))) + if (!updateGuildData(change.getKey(), currentData, bsonValueToJava(change.getValue()))) break; } } @@ -304,6 +312,22 @@ private void init() { } + public Object bsonValueToJava(BsonValue bsonValue) { + Object decode; + if (bsonValue.getBsonType().equals(BsonType.ARRAY)) { + decode = new ArrayList<>(); + for (BsonValue arrayVale : bsonValue.asArray().getValues()) { + ((List)decode).add(bsonValueToJava(arrayVale)); + } + } else if (bsonValue.getBsonType().equals(BsonType.DOCUMENT)) { + decode = databaseManager.getCodecRegistry().get(Object.class).decode(bsonValue.asDocument().asBsonReader(), DecoderContext.builder().build()); // TODO this can work if we can find the java class, maybe store it? + } else { + // This only handles primitives basically + decode = BsonUtils.toJavaType(bsonValue); + } + return decode; + } + public boolean updateGuildData(String path, GuildData guildData, Object newValue) { String[] split = path.split("\\."); String last = split[split.length - 1]; From 7d5e8988b953078f57b4730dee574fe8bcbb058c Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 31 May 2021 10:59:54 -0500 Subject: [PATCH 169/206] Store the object class so we can decode it later Is it stupid? yes. Does it work? also yes. --- .../org/cascadebot/cascadebot/CascadeBot.java | 21 +++++++++++++------ .../data/objects/GuildPermissions.java | 2 ++ .../data/objects/GuildSettingsUseful.java | 2 ++ .../cascadebot/data/objects/Tag.java | 2 ++ .../cascadebot/permissions/objects/Group.java | 2 ++ .../cascadebot/permissions/objects/User.java | 2 ++ .../cascadebot/data/objects/CommandFilter.kt | 2 ++ .../cascadebot/data/objects/Greetings.kt | 2 ++ .../cascadebot/data/objects/GuildData.kt | 2 ++ .../data/objects/GuildSettingsCore.kt | 2 ++ .../data/objects/GuildSettingsManagement.kt | 2 ++ .../data/objects/GuildSettingsModeration.kt | 4 ++++ .../data/objects/GuildSettingsMusic.kt | 2 ++ .../cascadebot/data/objects/TodoList.kt | 4 ++++ 14 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index d1c3ae60f..dc2b7845c 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -212,18 +212,23 @@ private void init() { } databaseManager.runAsyncTask(database -> { - ChangeStreamIterable changeStreamIterable = database.getCollection(GuildDataManager.COLLECTION, GuildData.class).watch() - .fullDocument(FullDocument.UPDATE_LOOKUP); // TODO not this + ChangeStreamIterable changeStreamIterable = database.getCollection(GuildDataManager.COLLECTION, GuildData.class).watch(); + //.fullDocument(FullDocument.UPDATE_LOOKUP); // TODO not this changeStreamIterable.forEach(guildDataChangeStreamDocument -> { if (guildDataChangeStreamDocument.getFullDocument() != null) { GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()); - } else { + } else if (guildDataChangeStreamDocument.getUpdateDescription() != null) { GuildData currentData = GuildDataManager.getGuildData(guildDataChangeStreamDocument.getDocumentKey().get("_id").asNumber().longValue()); UpdateDescription updateDescription = guildDataChangeStreamDocument.getUpdateDescription(); if (updateDescription.getUpdatedFields() != null) { for (Map.Entry change : updateDescription.getUpdatedFields().entrySet()) { - if (!updateGuildData(change.getKey(), currentData, bsonValueToJava(change.getValue()))) + try { + if (!updateGuildData(change.getKey(), currentData, bsonValueToJava(change.getValue()))) + break; + } catch (ClassNotFoundException e) { + CascadeBot.LOGGER.error("Failed to update data", e); break; + } } } if (updateDescription.getRemovedFields() != null) { @@ -312,7 +317,7 @@ private void init() { } - public Object bsonValueToJava(BsonValue bsonValue) { + public Object bsonValueToJava(BsonValue bsonValue) throws ClassNotFoundException { Object decode; if (bsonValue.getBsonType().equals(BsonType.ARRAY)) { decode = new ArrayList<>(); @@ -320,7 +325,11 @@ public Object bsonValueToJava(BsonValue bsonValue) { ((List)decode).add(bsonValueToJava(arrayVale)); } } else if (bsonValue.getBsonType().equals(BsonType.DOCUMENT)) { - decode = databaseManager.getCodecRegistry().get(Object.class).decode(bsonValue.asDocument().asBsonReader(), DecoderContext.builder().build()); // TODO this can work if we can find the java class, maybe store it? + if (bsonValue.asDocument().containsKey("objClass")) { + decode = databaseManager.getCodecRegistry().get(Class.forName(bsonValue.asDocument().getString("objClass").getValue())).decode(bsonValue.asDocument().asBsonReader(), DecoderContext.builder().build()); // TODO this can work if we can find the java class, maybe store it? + } else { + decode = bsonValue; + } } else { // This only handles primitives basically decode = BsonUtils.toJavaType(bsonValue); diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java index 41c1a5310..4c438002e 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java @@ -33,6 +33,8 @@ public class GuildPermissions { + private final String objClass = this.getClass().getName(); + @Getter @Setter private PermissionMode mode = PermissionMode.MOST_RESTRICTIVE; diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java index 1285b1443..66519ce72 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java @@ -10,6 +10,8 @@ @SettingsContainer(module = Module.USEFUL) public class GuildSettingsUseful { + private final String objClass = this.getClass().getName(); + private Map todoLists = new ConcurrentHashMap<>(); boolean writeMode = false; diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java index a6bdc926b..1f2ff0c42 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java @@ -22,6 +22,8 @@ @AllArgsConstructor public class Tag extends PermissionObject { + private final String objClass = this.getClass().getName(); + // https://regex101.com/r/hlsgVW/1 private static final Pattern TAG_PATTERN = Pattern.compile("\\{([A-z]+)(?::((?:,?\\w+)+))?}"); diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java index b5cd65f68..42d40603c 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java @@ -23,6 +23,8 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class Group extends PermissionHolder { + private final String objClass = this.getClass().getName(); + // Base 55 with 5 chars gives 503284375 combinations, we should be ok for uniqueness // This is normal alphanumeric with similar characters removed for less errors when inputting private String id = RandomStringUtils.random(5, "abcdefghijkmnopqrstuvwxyzACDEFHJKLMNPRSTUVWXYZ123467890"); diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java index ff8ddc025..580322e47 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java @@ -17,6 +17,8 @@ @EqualsAndHashCode(callSuper = true) public class User extends PermissionHolder { + private final String objClass = this.getClass().getName(); + private final Set groups = Sets.newConcurrentHashSet(); public boolean addGroup(Group group) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt index 6fcfae9a3..eb84656c9 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt @@ -21,6 +21,8 @@ import java.util.Collections class CommandFilter(val name: String) { + private val objClass = this.javaClass.name + // Constructor for MongoDB private constructor() : this("") diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt index b35cfcf40..fda90c506 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt @@ -10,6 +10,8 @@ import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects class Greetings { + private val objClass = this.javaClass.name + var welcomeMessages: WeightedList = WeightedList() var welcomeDMMessages: WeightedList = WeightedList() var goodbyeMessages: WeightedList = WeightedList() diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index abcf9af45..da8e0b798 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -64,6 +64,8 @@ class GuildData(@field:Id val guildId: Long): Cloneable { val music = GuildSettingsMusic() //endregion + val objClass = this.javaClass.packageName + "." + this.javaClass.name + //region Transient fields @Transient @kotlin.jvm.Transient diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt index 3c661cee1..8f6cf69d8 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt @@ -44,6 +44,8 @@ class GuildSettingsCore { private val commandInfo = ConcurrentHashMap, MutableSet>() private val enabledModules: MutableSet = Sets.newConcurrentHashSet(Module.getModules(ModuleFlag.DEFAULT)) + private val objClass = this.javaClass.name + //region Modules fun enableModule(module: Module): Boolean { assertWriteMode() diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt index a2d4c7198..f15d109db 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt @@ -17,6 +17,8 @@ class GuildSettingsManagement { @Setting var warnOver10Filters = true + private val objClass = this.javaClass.name + val tags: ConcurrentHashMap = ConcurrentHashMap() val filters: MutableList = mutableListOf() val permissions = GuildPermissions() diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 0890ab0cc..d1abf8ed5 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -40,6 +40,8 @@ class GuildSettingsModeration { @Setting var muteRoleName = "Muted" + private val objClass = this.javaClass.name + fun getRespectBanOrKickHierarchy(): Boolean { return respectBanOrKickHierarchy } @@ -115,6 +117,8 @@ class GuildSettingsModeration { class ChannelModlogEventsInfo { + private val objClass = this.javaClass.name + private val events: MutableSet = LinkedHashSet() internal var webhookId: Long = 0 internal var webhookToken: String = "" diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt index 13841467a..bc95fc8eb 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt @@ -6,6 +6,8 @@ import java.util.concurrent.ConcurrentHashMap @SettingsContainer(module = Module.MUSIC) class GuildSettingsMusic { + private val objClass = this.javaClass.name + // TODO: Handle reverting tier for preserve settings @Setting var preserveVolume = true diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt index 2782f7033..3efe2507c 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt @@ -16,6 +16,8 @@ import org.cascadebot.cascadebot.utils.buttons.PersistentButtonGroup class TodoList(val ownerId: Long) { + private val objClass = this.javaClass.name + val items: MutableList = ArrayList() var messageId: Long = -1 var channelId: Long = -1 @@ -56,6 +58,8 @@ class TodoList(val ownerId: Long) { class TodoListItem { + private val objClass = this.javaClass.name + var done = false var text: String? = null From 258a8c7255bb2942f67fd4ad67fdca5549c9449f Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 31 May 2021 11:01:47 -0500 Subject: [PATCH 170/206] Send an error if we can't find class to use to decode --- src/main/java/org/cascadebot/cascadebot/CascadeBot.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index dc2b7845c..147ac57ac 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -329,6 +329,7 @@ public Object bsonValueToJava(BsonValue bsonValue) throws ClassNotFoundException decode = databaseManager.getCodecRegistry().get(Class.forName(bsonValue.asDocument().getString("objClass").getValue())).decode(bsonValue.asDocument().asBsonReader(), DecoderContext.builder().build()); // TODO this can work if we can find the java class, maybe store it? } else { decode = bsonValue; + CascadeBot.LOGGER.error("Data object doesn't contain object class, so we can't properly decode it!"); } } else { // This only handles primitives basically From 69f50f532a1ebdec8731904b5677752e43305c3a Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Mon, 31 May 2021 11:15:17 -0500 Subject: [PATCH 171/206] Cleanup and documentation --- .../cascadebot/utils/diff/Diff.java | 4 ++++ .../cascadebot/utils/diff/DiffUtils.java | 9 +++++-- .../cascadebot/utils/diff/Difference.java | 24 +++++++++++++++---- .../utils/diff/DifferenceChanged.java | 15 ++++++++++++ 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/utils/diff/Diff.java b/src/main/java/org/cascadebot/cascadebot/utils/diff/Diff.java index 9834a6826..b87d9cde9 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/diff/Diff.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/diff/Diff.java @@ -1,4 +1,8 @@ package org.cascadebot.cascadebot.utils.diff; +/** + * Represents an arbitrary difference between objects. This object has nothing on it as it's meant to be an representation of a diff. + * Currently implemented by {@link DifferenceChanged} and {@link org.cascadebot.cascadebot.utils.lists.CollectionDiff} + */ public interface Diff { } diff --git a/src/main/java/org/cascadebot/cascadebot/utils/diff/DiffUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/diff/DiffUtils.java index 2bdc10f8e..ea9d32e84 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/diff/DiffUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/diff/DiffUtils.java @@ -16,6 +16,13 @@ public class DiffUtils { + /** + * Find the difference between two arbitrary objects, and return it using the {@link Difference} object + * + * @param oldObj The old objects to get the difference from + * @param newObj The new object to get the difference from + * @return a {@link Difference} object + */ public static Difference diff(Object oldObj, Object newObj) { return diff(new Difference(), "", oldObj, newObj); } @@ -45,8 +52,6 @@ private static Difference diff(Difference currentDiff, String path, Object oldOb Object newValue = newMap.get(key); if (!oldValue.equals(newValue)) { - System.out.println(Arrays.stream(newValue.getClass().getDeclaredFields()).map(Field::getName).collect(Collectors.joining(", "))); - if (!oldValue.getClass().getTypeName().equals(newValue.getClass().getTypeName())) { DifferenceChanged changed = new DifferenceChanged<>(oldValue, newValue); currentDiff.changed.put(path + key, changed); diff --git a/src/main/java/org/cascadebot/cascadebot/utils/diff/Difference.java b/src/main/java/org/cascadebot/cascadebot/utils/diff/Difference.java index 810f82e2a..a0b46ac9f 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/diff/Difference.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/diff/Difference.java @@ -5,19 +5,33 @@ public class Difference { - Map added = new HashMap<>(); - Map removed = new HashMap<>(); - - Map changed = new HashMap<>(); - + protected Map added = new HashMap<>(); + protected Map removed = new HashMap<>(); + protected Map changed = new HashMap<>(); + + /** + * Get all the objects that have been newly added. + * + * @return A map containing the new added objects with the key being the path to the object separated by dots and the value being the newly added object + */ public Map getAdded() { return added; } + /** + * Get all the objects that have been removed. + * + * @return A map containing the new added objects with the key being the path to the object separated by dots and the value being the removed object + */ public Map getRemoved() { return removed; } + /** + * Get all the objects that have been changed. + * + * @return A map containing the new added objects with the key being the path to the object separated by dots and the value being a {@link Diff} that represents the change + */ public Map getChanged() { return changed; } diff --git a/src/main/java/org/cascadebot/cascadebot/utils/diff/DifferenceChanged.java b/src/main/java/org/cascadebot/cascadebot/utils/diff/DifferenceChanged.java index 0a5313ea0..7b9d1f60c 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/diff/DifferenceChanged.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/diff/DifferenceChanged.java @@ -1,5 +1,10 @@ package org.cascadebot.cascadebot.utils.diff; +/** + * Represents a change from an old object to a new object. + * + * @param The type of object. + */ public class DifferenceChanged implements Diff { private final T oldObj; @@ -10,10 +15,20 @@ public DifferenceChanged(T oldObj, T newObj) { this.newObj = newObj; } + /** + * Get the old object + * + * @return the old object + */ public T getOldObj() { return oldObj; } + /** + * Get the new object + * + * @return the new object + */ public T getNewObj() { return newObj; } From f1dc9d6434f8c95378a8e607ad5a8570a67df9df Mon Sep 17 00:00:00 2001 From: William Oldham Date: Fri, 4 Jun 2021 11:08:12 +0100 Subject: [PATCH 172/206] Test change --- .../module/ModuleDisableSubCommand.java | 24 ++++++++--------- .../cascadebot/utils/GuildDataUtils.java | 7 ++--- .../cascadebot/data/objects/GuildData.kt | 27 +++++++++++++++++-- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java index b1e73172b..7e35e01d5 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleDisableSubCommand.java @@ -33,19 +33,17 @@ public void onCommand(Member sender, CommandContext context) { if (module != null) { String moduleName = ExtensionsKt.toCapitalized(FormatUtils.formatEnum(module, context.getLocale())); try { - context.getData().write(guildData -> { - if (guildData.getCore().disableModule(module)) { - // If module wasn't already disabled - context.getTypedMessaging().replySuccess(context.i18n("commands.module.disable.disabled", moduleName)); - ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), module, List.of()); - eventStore.setExtraDescriptionInfo(List.of("false")); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - } else { - // If module was already disabled - context.getTypedMessaging().replyInfo(context.i18n("commands.module.disable.already_disabled", moduleName)); - } - }); + if (context.getData().writeInline(data -> data.getCore().disableModule(module))) { + // If module wasn't already disabled + context.getTypedMessaging().replySuccess(context.i18n("commands.module.disable.disabled", moduleName)); + ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), module, List.of()); + eventStore.setExtraDescriptionInfo(List.of("false")); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + } else { + // If module was already disabled + context.getTypedMessaging().replyInfo(context.i18n("commands.module.disable.already_disabled", moduleName)); + } } catch (IllegalArgumentException ex) { context.getTypedMessaging().replyDanger(ex.getMessage()); } diff --git a/src/main/java/org/cascadebot/cascadebot/utils/GuildDataUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/GuildDataUtils.java index 5394912ff..678ee7c12 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/GuildDataUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/GuildDataUtils.java @@ -1,15 +1,12 @@ package org.cascadebot.cascadebot.utils; +import org.cascadebot.cascadebot.data.objects.GuildData; import org.slf4j.MDC; public class GuildDataUtils { public static void assertWriteMode() { - String mode = MDC.get("writeMode"); - if (mode == null) { - throw new UnsupportedOperationException("Cannot write guild data if not in write mode!"); - } - boolean writeMode = Boolean.parseBoolean(mode); + boolean writeMode = GuildData.Companion.getWriteMode().get(); if (!writeMode) { throw new UnsupportedOperationException("Cannot write guild data if not in write mode!"); } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index da8e0b798..0920ab722 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -3,6 +3,7 @@ package org.cascadebot.cascadebot.data.objects import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.util.ClassUtil.classOf import com.google.common.collect.Sets +import com.google.common.math.LongMath import com.google.gson.GsonBuilder import com.google.gson.JsonParser import com.google.gson.reflect.TypeToken @@ -31,6 +32,9 @@ import kotlin.concurrent.withLock import kotlin.reflect.jvm.javaType import kotlin.reflect.typeOf import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode +import java.util.concurrent.atomic.AtomicBoolean +import java.util.function.Function +import kotlin.concurrent.getOrSet class GuildData(@field:Id val guildId: Long): Cloneable { @@ -38,6 +42,12 @@ class GuildData(@field:Id val guildId: Long): Cloneable { @kotlin.jvm.Transient val lock: ReadWriteLock = ReentrantReadWriteLock() + companion object { + + val writeMode: ThreadLocal = ThreadLocal() + + } + private constructor() : this(0L) { // Private constructor for MongoDB } @@ -143,12 +153,25 @@ class GuildData(@field:Id val guildId: Long): Cloneable { fun write(writer: Consumer) { this.lock.writeLock().withLock { val copy: GuildData = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(this), this.javaClass) - MDC.put("writeMode", true.toString()) + writeMode.set(true) writer.accept(copy); - MDC.put("writeMode", false.toString()) + writeMode.set(false) + val diff: Difference = DiffUtils.diff(this, copy) + GuildDataManager.updateDiff(guildId, diff, copy) + //println(GsonBuilder().setPrettyPrinting().create().toJson(diff)) + } + } + + fun writeInline(writer: Function) : T { + this.lock.writeLock().withLock { + val copy: GuildData = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(this), this.javaClass) + writeMode.set(true) + val output = writer.apply(copy); + writeMode.set(false) val diff: Difference = DiffUtils.diff(this, copy) GuildDataManager.updateDiff(guildId, diff, copy) //println(GsonBuilder().setPrettyPrinting().create().toJson(diff)) + return output } } From 4cc7febd6f5bfeb2aa6bd610bdeb351a75edf14b Mon Sep 17 00:00:00 2001 From: William Oldham Date: Fri, 4 Jun 2021 11:17:28 +0100 Subject: [PATCH 173/206] Add functions for better Kotlin interop --- .../org/cascadebot/cascadebot/data/objects/GuildData.kt | 8 ++++++++ .../cascadebot/utils/buttons/PersistentButton.kt | 9 ++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 0920ab722..405b9e599 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -162,6 +162,10 @@ class GuildData(@field:Id val guildId: Long): Cloneable { } } + fun write(writer: (GuildData) -> Unit) { + write(Consumer(writer)) + } + fun writeInline(writer: Function) : T { this.lock.writeLock().withLock { val copy: GuildData = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(this), this.javaClass) @@ -175,6 +179,10 @@ class GuildData(@field:Id val guildId: Long): Cloneable { } } + fun writeInline(writer: (GuildData)->T) : T { + return writeInline(Function(writer)) + } + } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButton.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButton.kt index e55e81a51..5cd55c755 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButton.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButton.kt @@ -11,7 +11,6 @@ import org.cascadebot.cascadebot.commands.music.SkipCommand import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.utils.DiscordUtils import org.cascadebot.cascadebot.utils.votes.VoteButtonGroup -import java.util.function.Consumer enum class PersistentButton(@field:Transient val button: Button) { TODO_BUTTON_CHECK( @@ -19,7 +18,7 @@ enum class PersistentButton(@field:Transient val button: Button) { UnicodeConstants.TICK, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> GuildDataManager.getGuildData(channel.guild.idLong) - .write(Consumer { + .write { val todoList = it.useful.getTodoListByMessage(message.idLong) if (todoList.canUserEdit(runner.idLong)) { @@ -28,14 +27,14 @@ enum class PersistentButton(@field:Transient val button: Button) { todoList.addUncheckButton(message) message.editMessage(todoList.todoListMessage).queue() } - }) + } }) ), TODO_BUTTON_UNCHECK( Button.UnicodeButton( UnicodeConstants.WHITE_HALLOW_SQUARE, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - GuildDataManager.getGuildData(channel.guild.idLong).write(Consumer { + GuildDataManager.getGuildData(channel.guild.idLong).write { val todoList = it.useful.getTodoListByMessage(message.idLong) if (todoList.canUserEdit(runner.idLong)) { @@ -44,7 +43,7 @@ enum class PersistentButton(@field:Transient val button: Button) { todoList.addCheckButton(message) message.editMessage(todoList.todoListMessage).queue() } - }) + } }) ), TODO_BUTTON_NAVIGATE_LEFT( From 1533193bd738f474ca4e329158124ecf64053995 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Fri, 4 Jun 2021 11:17:28 +0100 Subject: [PATCH 174/206] Revert "Add functions for better Kotlin interop" This reverts commit 4cc7febd6f5bfeb2aa6bd610bdeb351a75edf14b. --- .../org/cascadebot/cascadebot/data/objects/GuildData.kt | 8 -------- .../cascadebot/utils/buttons/PersistentButton.kt | 9 +++++---- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 405b9e599..0920ab722 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -162,10 +162,6 @@ class GuildData(@field:Id val guildId: Long): Cloneable { } } - fun write(writer: (GuildData) -> Unit) { - write(Consumer(writer)) - } - fun writeInline(writer: Function) : T { this.lock.writeLock().withLock { val copy: GuildData = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(this), this.javaClass) @@ -179,10 +175,6 @@ class GuildData(@field:Id val guildId: Long): Cloneable { } } - fun writeInline(writer: (GuildData)->T) : T { - return writeInline(Function(writer)) - } - } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButton.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButton.kt index 5cd55c755..e55e81a51 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButton.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButton.kt @@ -11,6 +11,7 @@ import org.cascadebot.cascadebot.commands.music.SkipCommand import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.utils.DiscordUtils import org.cascadebot.cascadebot.utils.votes.VoteButtonGroup +import java.util.function.Consumer enum class PersistentButton(@field:Transient val button: Button) { TODO_BUTTON_CHECK( @@ -18,7 +19,7 @@ enum class PersistentButton(@field:Transient val button: Button) { UnicodeConstants.TICK, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> GuildDataManager.getGuildData(channel.guild.idLong) - .write { + .write(Consumer { val todoList = it.useful.getTodoListByMessage(message.idLong) if (todoList.canUserEdit(runner.idLong)) { @@ -27,14 +28,14 @@ enum class PersistentButton(@field:Transient val button: Button) { todoList.addUncheckButton(message) message.editMessage(todoList.todoListMessage).queue() } - } + }) }) ), TODO_BUTTON_UNCHECK( Button.UnicodeButton( UnicodeConstants.WHITE_HALLOW_SQUARE, IButtonRunnable { runner: Member, channel: TextChannel, message: Message -> - GuildDataManager.getGuildData(channel.guild.idLong).write { + GuildDataManager.getGuildData(channel.guild.idLong).write(Consumer { val todoList = it.useful.getTodoListByMessage(message.idLong) if (todoList.canUserEdit(runner.idLong)) { @@ -43,7 +44,7 @@ enum class PersistentButton(@field:Transient val button: Button) { todoList.addCheckButton(message) message.editMessage(todoList.todoListMessage).queue() } - } + }) }) ), TODO_BUTTON_NAVIGATE_LEFT( From b794118a259be0df6682a9d2cb8182ea28640a08 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 5 Jun 2021 21:18:46 +0100 Subject: [PATCH 175/206] Use writeInline --- .../module/ModuleEnableSubCommand.java | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java index 3ab0ed45a..0e628598c 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/module/ModuleEnableSubCommand.java @@ -33,20 +33,17 @@ public void onCommand(Member sender, CommandContext context) { if (module != null) { String moduleName = ExtensionsKt.toCapitalized(FormatUtils.formatEnum(module, context.getLocale())); try { - context.getData().write(data -> { - if (data.getCore().enableModule(module)) { - // If the module wasn't enabled - context.getTypedMessaging().replySuccess(context.i18n("commands.module.enable.enabled", moduleName)); - ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; - ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), module, List.of()); - eventStore.setExtraDescriptionInfo(List.of("true")); - context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); - } else { - // If the module was enabled - context.getTypedMessaging().replyInfo(context.i18n("commands.module.enable.already_enabled", moduleName)); - } - }); - + if (context.getData().writeInline(data -> data.getCore().enableModule(module))) { + // If the module wasn't enabled + context.getTypedMessaging().replySuccess(context.i18n("commands.module.enable.enabled", moduleName)); + ModlogEvent event = ModlogEvent.CASCADE_MODULE_UPDATED; + ModlogEventData eventStore = new ModlogEventData(event, sender.getUser(), module, List.of()); + eventStore.setExtraDescriptionInfo(List.of("true")); + context.getData().getModeration().sendModlogEvent(context.getGuild().getIdLong(), eventStore); + } else { + // If the module was enabled + context.getTypedMessaging().replyInfo(context.i18n("commands.module.enable.already_enabled", moduleName)); + } } catch (IllegalArgumentException ex) { context.getTypedMessaging().replyDanger(ex.getMessage()); } From 1309af611837d7f5f3e5893f52c649f932bab806 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 5 Jun 2021 21:19:05 +0100 Subject: [PATCH 176/206] Move change stream setup into separate file for clarity --- .../org/cascadebot/cascadebot/CascadeBot.java | 91 +------------ .../data/managers/GuildDataChangeStream.kt | 120 ++++++++++++++++++ 2 files changed, 122 insertions(+), 89 deletions(-) create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/data/managers/GuildDataChangeStream.kt diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 147ac57ac..8eabe754b 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -12,9 +12,6 @@ import ch.qos.logback.core.encoder.LayoutWrappingEncoder; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.mongodb.async.client.ChangeStreamIterable; -import com.mongodb.client.model.changestream.FullDocument; -import com.mongodb.client.model.changestream.UpdateDescription; import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory; import io.sentry.Sentry; import io.sentry.SentryClient; @@ -29,7 +26,6 @@ import net.dv8tion.jda.api.sharding.ShardManager; import okhttp3.OkHttpClient; import org.apache.commons.lang3.StringUtils; -import org.bson.BsonReader; import org.bson.BsonType; import org.bson.BsonValue; import org.bson.codecs.DecoderContext; @@ -37,6 +33,7 @@ import org.cascadebot.cascadebot.commandmeta.CommandManager; import org.cascadebot.cascadebot.data.Config; import org.cascadebot.cascadebot.data.database.DatabaseManager; +import org.cascadebot.cascadebot.data.managers.GuildDataChangeStream; import org.cascadebot.cascadebot.data.managers.GuildDataManager; import org.cascadebot.cascadebot.data.managers.ScheduledActionManager; import org.cascadebot.cascadebot.data.objects.GuildData; @@ -74,9 +71,7 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; -import java.util.Date; import java.util.List; -import java.util.Map; import java.util.Scanner; import java.util.concurrent.TimeUnit; @@ -211,40 +206,7 @@ private void init() { ); } - databaseManager.runAsyncTask(database -> { - ChangeStreamIterable changeStreamIterable = database.getCollection(GuildDataManager.COLLECTION, GuildData.class).watch(); - //.fullDocument(FullDocument.UPDATE_LOOKUP); // TODO not this - changeStreamIterable.forEach(guildDataChangeStreamDocument -> { - if (guildDataChangeStreamDocument.getFullDocument() != null) { - GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()); - } else if (guildDataChangeStreamDocument.getUpdateDescription() != null) { - GuildData currentData = GuildDataManager.getGuildData(guildDataChangeStreamDocument.getDocumentKey().get("_id").asNumber().longValue()); - UpdateDescription updateDescription = guildDataChangeStreamDocument.getUpdateDescription(); - if (updateDescription.getUpdatedFields() != null) { - for (Map.Entry change : updateDescription.getUpdatedFields().entrySet()) { - try { - if (!updateGuildData(change.getKey(), currentData, bsonValueToJava(change.getValue()))) - break; - } catch (ClassNotFoundException e) { - CascadeBot.LOGGER.error("Failed to update data", e); - break; - } - } - } - if (updateDescription.getRemovedFields() != null) { - for (String removed : updateDescription.getRemovedFields()) { - if (!updateGuildData(removed, currentData, null)) break; - } - } - } - }, (result, throwable) -> { - if (throwable != null) { - CascadeBot.LOGGER.error("Error on change stream", throwable); - } - }); - }); - - CascadeBot.LOGGER.info("Watcher setup"); + GuildDataChangeStream.setupChangeStreams(databaseManager); musicHandler = new MusicHandler(); @@ -317,55 +279,6 @@ private void init() { } - public Object bsonValueToJava(BsonValue bsonValue) throws ClassNotFoundException { - Object decode; - if (bsonValue.getBsonType().equals(BsonType.ARRAY)) { - decode = new ArrayList<>(); - for (BsonValue arrayVale : bsonValue.asArray().getValues()) { - ((List)decode).add(bsonValueToJava(arrayVale)); - } - } else if (bsonValue.getBsonType().equals(BsonType.DOCUMENT)) { - if (bsonValue.asDocument().containsKey("objClass")) { - decode = databaseManager.getCodecRegistry().get(Class.forName(bsonValue.asDocument().getString("objClass").getValue())).decode(bsonValue.asDocument().asBsonReader(), DecoderContext.builder().build()); // TODO this can work if we can find the java class, maybe store it? - } else { - decode = bsonValue; - CascadeBot.LOGGER.error("Data object doesn't contain object class, so we can't properly decode it!"); - } - } else { - // This only handles primitives basically - decode = BsonUtils.toJavaType(bsonValue); - } - return decode; - } - - public boolean updateGuildData(String path, GuildData guildData, Object newValue) { - String[] split = path.split("\\."); - String last = split[split.length - 1]; - Object current = guildData; - for (String part : Arrays.copyOfRange(split, 0, split.length - 1)) { - try { - Field field = current.getClass().getDeclaredField(part); - field.setAccessible(true); - current = field.get(current); - } catch (NoSuchFieldException | IllegalAccessException e) { - CascadeBot.LOGGER.error("Failed to update guild data", e); - return false; - } - } - try { - Field field = current.getClass().getDeclaredField(last); - field.setAccessible(true); - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - field.set(current, newValue); - } catch (NoSuchFieldException | IllegalAccessException e) { - CascadeBot.LOGGER.error("Failed to update guild data", e); - return false; - } - return true; - } - private void setupTasks() { new Task("prune-players") { @Override diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/managers/GuildDataChangeStream.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/managers/GuildDataChangeStream.kt new file mode 100644 index 000000000..5727c27c6 --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/managers/GuildDataChangeStream.kt @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021 CascadeBot. All rights reserved. + * Licensed under the MIT license. + */ + +package org.cascadebot.cascadebot.data.managers + +import com.mongodb.async.client.MongoDatabase +import com.mongodb.client.model.changestream.ChangeStreamDocument +import org.bson.BsonType +import org.bson.BsonValue +import org.bson.codecs.DecoderContext +import org.cascadebot.cascadebot.CascadeBot +import org.cascadebot.cascadebot.data.database.DatabaseManager +import org.cascadebot.cascadebot.data.objects.GuildData +import org.springframework.data.mongodb.util.BsonUtils +import java.lang.reflect.Field +import java.lang.reflect.Modifier + +object GuildDataChangeStream { + + @JvmStatic + fun setupChangeStreams(databaseManager: DatabaseManager) { + databaseManager.runAsyncTask { database: MongoDatabase -> + val changeStreamIterable = + database.getCollection(GuildDataManager.COLLECTION, GuildData::class.java).watch() + changeStreamIterable.forEach({ guildDataChangeStreamDocument: ChangeStreamDocument -> + if (guildDataChangeStreamDocument.fullDocument != null) { + GuildDataManager.replaceInternal(guildDataChangeStreamDocument.fullDocument) + } else { + val currentData = GuildDataManager.getGuildData( + guildDataChangeStreamDocument.documentKey["_id"]!!.asNumber().longValue() + ) + val updateDescription = guildDataChangeStreamDocument.updateDescription + if (updateDescription.updatedFields != null) { + for ((key, value) in updateDescription.updatedFields) { + try { + if (!updateGuildData(key, currentData, bsonValueToJava(databaseManager, value))) break + } catch (e: ClassNotFoundException) { + CascadeBot.LOGGER.error("Failed to update data", e) + break + } + } + } + if (updateDescription.removedFields != null) { + for (removed in updateDescription.removedFields) { + if (!updateGuildData(removed, currentData, null)) break + } + } + } + }) { _: Void?, throwable: Throwable? -> + if (throwable != null) { + CascadeBot.LOGGER.error("Error on change stream", throwable) + } + } + } + + CascadeBot.LOGGER.info("Watcher setup") + } + + @Throws(ClassNotFoundException::class) + fun bsonValueToJava(databaseManager: DatabaseManager, bsonValue: BsonValue): Any { + return if (bsonValue.bsonType == BsonType.ARRAY) { + val list = ArrayList() + for (arrayValue in bsonValue.asArray().values) { + list.add(bsonValueToJava(databaseManager, arrayValue)) + } + } else if (bsonValue.bsonType == BsonType.DOCUMENT) { + if (bsonValue.asDocument().containsKey("objClass")) { + databaseManager.codecRegistry + .get(Class.forName(bsonValue.asDocument().getString("objClass").value)).decode( + bsonValue.asDocument().asBsonReader(), + DecoderContext.builder().build() + ) // TODO this can work if we can find the java class, maybe store it? + } else { + CascadeBot.LOGGER.error("Data object doesn't contain object class, so we can't properly decode it!") + bsonValue + } + } else { + // This only handles primitives basically + BsonUtils.toJavaType(bsonValue) + } + } + + private fun updateGuildData(path: String, guildData: GuildData, newValue: Any?): Boolean { + val split = path.split("\\.".toRegex()).toTypedArray() + val last = split[split.size - 1] + var current: Any = guildData + for (part in split.copyOfRange(0, split.size - 1)) { + try { + val field = current.javaClass.getDeclaredField(part) + field.isAccessible = true + current = field[current] + } catch (e: NoSuchFieldException) { + CascadeBot.LOGGER.error("Failed to update guild data", e) + return false + } catch (e: IllegalAccessException) { + CascadeBot.LOGGER.error("Failed to update guild data", e) + return false + } + } + try { + val field = current.javaClass.getDeclaredField(last) + field.isAccessible = true + val modifiersField = Field::class.java.getDeclaredField("modifiers") + modifiersField.isAccessible = true + modifiersField.setInt(field, field.modifiers and Modifier.FINAL.inv()) + field[current] = newValue + } catch (e: NoSuchFieldException) { + CascadeBot.LOGGER.error("Failed to update guild data", e) + return false + } catch (e: IllegalAccessException) { + CascadeBot.LOGGER.error("Failed to update guild data", e) + return false + } + return true + } + + +} \ No newline at end of file From ecce74cfb11423ec69b6f13d17bee07fc19f1328 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 5 Jun 2021 21:19:05 +0100 Subject: [PATCH 177/206] Revert "Move change stream setup into separate file for clarity" This reverts commit 1309af611837d7f5f3e5893f52c649f932bab806. --- .../org/cascadebot/cascadebot/CascadeBot.java | 91 ++++++++++++- .../data/managers/GuildDataChangeStream.kt | 120 ------------------ 2 files changed, 89 insertions(+), 122 deletions(-) delete mode 100644 src/main/kotlin/org/cascadebot/cascadebot/data/managers/GuildDataChangeStream.kt diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 8eabe754b..147ac57ac 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -12,6 +12,9 @@ import ch.qos.logback.core.encoder.LayoutWrappingEncoder; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.mongodb.async.client.ChangeStreamIterable; +import com.mongodb.client.model.changestream.FullDocument; +import com.mongodb.client.model.changestream.UpdateDescription; import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory; import io.sentry.Sentry; import io.sentry.SentryClient; @@ -26,6 +29,7 @@ import net.dv8tion.jda.api.sharding.ShardManager; import okhttp3.OkHttpClient; import org.apache.commons.lang3.StringUtils; +import org.bson.BsonReader; import org.bson.BsonType; import org.bson.BsonValue; import org.bson.codecs.DecoderContext; @@ -33,7 +37,6 @@ import org.cascadebot.cascadebot.commandmeta.CommandManager; import org.cascadebot.cascadebot.data.Config; import org.cascadebot.cascadebot.data.database.DatabaseManager; -import org.cascadebot.cascadebot.data.managers.GuildDataChangeStream; import org.cascadebot.cascadebot.data.managers.GuildDataManager; import org.cascadebot.cascadebot.data.managers.ScheduledActionManager; import org.cascadebot.cascadebot.data.objects.GuildData; @@ -71,7 +74,9 @@ import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Scanner; import java.util.concurrent.TimeUnit; @@ -206,7 +211,40 @@ private void init() { ); } - GuildDataChangeStream.setupChangeStreams(databaseManager); + databaseManager.runAsyncTask(database -> { + ChangeStreamIterable changeStreamIterable = database.getCollection(GuildDataManager.COLLECTION, GuildData.class).watch(); + //.fullDocument(FullDocument.UPDATE_LOOKUP); // TODO not this + changeStreamIterable.forEach(guildDataChangeStreamDocument -> { + if (guildDataChangeStreamDocument.getFullDocument() != null) { + GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()); + } else if (guildDataChangeStreamDocument.getUpdateDescription() != null) { + GuildData currentData = GuildDataManager.getGuildData(guildDataChangeStreamDocument.getDocumentKey().get("_id").asNumber().longValue()); + UpdateDescription updateDescription = guildDataChangeStreamDocument.getUpdateDescription(); + if (updateDescription.getUpdatedFields() != null) { + for (Map.Entry change : updateDescription.getUpdatedFields().entrySet()) { + try { + if (!updateGuildData(change.getKey(), currentData, bsonValueToJava(change.getValue()))) + break; + } catch (ClassNotFoundException e) { + CascadeBot.LOGGER.error("Failed to update data", e); + break; + } + } + } + if (updateDescription.getRemovedFields() != null) { + for (String removed : updateDescription.getRemovedFields()) { + if (!updateGuildData(removed, currentData, null)) break; + } + } + } + }, (result, throwable) -> { + if (throwable != null) { + CascadeBot.LOGGER.error("Error on change stream", throwable); + } + }); + }); + + CascadeBot.LOGGER.info("Watcher setup"); musicHandler = new MusicHandler(); @@ -279,6 +317,55 @@ private void init() { } + public Object bsonValueToJava(BsonValue bsonValue) throws ClassNotFoundException { + Object decode; + if (bsonValue.getBsonType().equals(BsonType.ARRAY)) { + decode = new ArrayList<>(); + for (BsonValue arrayVale : bsonValue.asArray().getValues()) { + ((List)decode).add(bsonValueToJava(arrayVale)); + } + } else if (bsonValue.getBsonType().equals(BsonType.DOCUMENT)) { + if (bsonValue.asDocument().containsKey("objClass")) { + decode = databaseManager.getCodecRegistry().get(Class.forName(bsonValue.asDocument().getString("objClass").getValue())).decode(bsonValue.asDocument().asBsonReader(), DecoderContext.builder().build()); // TODO this can work if we can find the java class, maybe store it? + } else { + decode = bsonValue; + CascadeBot.LOGGER.error("Data object doesn't contain object class, so we can't properly decode it!"); + } + } else { + // This only handles primitives basically + decode = BsonUtils.toJavaType(bsonValue); + } + return decode; + } + + public boolean updateGuildData(String path, GuildData guildData, Object newValue) { + String[] split = path.split("\\."); + String last = split[split.length - 1]; + Object current = guildData; + for (String part : Arrays.copyOfRange(split, 0, split.length - 1)) { + try { + Field field = current.getClass().getDeclaredField(part); + field.setAccessible(true); + current = field.get(current); + } catch (NoSuchFieldException | IllegalAccessException e) { + CascadeBot.LOGGER.error("Failed to update guild data", e); + return false; + } + } + try { + Field field = current.getClass().getDeclaredField(last); + field.setAccessible(true); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(current, newValue); + } catch (NoSuchFieldException | IllegalAccessException e) { + CascadeBot.LOGGER.error("Failed to update guild data", e); + return false; + } + return true; + } + private void setupTasks() { new Task("prune-players") { @Override diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/managers/GuildDataChangeStream.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/managers/GuildDataChangeStream.kt deleted file mode 100644 index 5727c27c6..000000000 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/managers/GuildDataChangeStream.kt +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2021 CascadeBot. All rights reserved. - * Licensed under the MIT license. - */ - -package org.cascadebot.cascadebot.data.managers - -import com.mongodb.async.client.MongoDatabase -import com.mongodb.client.model.changestream.ChangeStreamDocument -import org.bson.BsonType -import org.bson.BsonValue -import org.bson.codecs.DecoderContext -import org.cascadebot.cascadebot.CascadeBot -import org.cascadebot.cascadebot.data.database.DatabaseManager -import org.cascadebot.cascadebot.data.objects.GuildData -import org.springframework.data.mongodb.util.BsonUtils -import java.lang.reflect.Field -import java.lang.reflect.Modifier - -object GuildDataChangeStream { - - @JvmStatic - fun setupChangeStreams(databaseManager: DatabaseManager) { - databaseManager.runAsyncTask { database: MongoDatabase -> - val changeStreamIterable = - database.getCollection(GuildDataManager.COLLECTION, GuildData::class.java).watch() - changeStreamIterable.forEach({ guildDataChangeStreamDocument: ChangeStreamDocument -> - if (guildDataChangeStreamDocument.fullDocument != null) { - GuildDataManager.replaceInternal(guildDataChangeStreamDocument.fullDocument) - } else { - val currentData = GuildDataManager.getGuildData( - guildDataChangeStreamDocument.documentKey["_id"]!!.asNumber().longValue() - ) - val updateDescription = guildDataChangeStreamDocument.updateDescription - if (updateDescription.updatedFields != null) { - for ((key, value) in updateDescription.updatedFields) { - try { - if (!updateGuildData(key, currentData, bsonValueToJava(databaseManager, value))) break - } catch (e: ClassNotFoundException) { - CascadeBot.LOGGER.error("Failed to update data", e) - break - } - } - } - if (updateDescription.removedFields != null) { - for (removed in updateDescription.removedFields) { - if (!updateGuildData(removed, currentData, null)) break - } - } - } - }) { _: Void?, throwable: Throwable? -> - if (throwable != null) { - CascadeBot.LOGGER.error("Error on change stream", throwable) - } - } - } - - CascadeBot.LOGGER.info("Watcher setup") - } - - @Throws(ClassNotFoundException::class) - fun bsonValueToJava(databaseManager: DatabaseManager, bsonValue: BsonValue): Any { - return if (bsonValue.bsonType == BsonType.ARRAY) { - val list = ArrayList() - for (arrayValue in bsonValue.asArray().values) { - list.add(bsonValueToJava(databaseManager, arrayValue)) - } - } else if (bsonValue.bsonType == BsonType.DOCUMENT) { - if (bsonValue.asDocument().containsKey("objClass")) { - databaseManager.codecRegistry - .get(Class.forName(bsonValue.asDocument().getString("objClass").value)).decode( - bsonValue.asDocument().asBsonReader(), - DecoderContext.builder().build() - ) // TODO this can work if we can find the java class, maybe store it? - } else { - CascadeBot.LOGGER.error("Data object doesn't contain object class, so we can't properly decode it!") - bsonValue - } - } else { - // This only handles primitives basically - BsonUtils.toJavaType(bsonValue) - } - } - - private fun updateGuildData(path: String, guildData: GuildData, newValue: Any?): Boolean { - val split = path.split("\\.".toRegex()).toTypedArray() - val last = split[split.size - 1] - var current: Any = guildData - for (part in split.copyOfRange(0, split.size - 1)) { - try { - val field = current.javaClass.getDeclaredField(part) - field.isAccessible = true - current = field[current] - } catch (e: NoSuchFieldException) { - CascadeBot.LOGGER.error("Failed to update guild data", e) - return false - } catch (e: IllegalAccessException) { - CascadeBot.LOGGER.error("Failed to update guild data", e) - return false - } - } - try { - val field = current.javaClass.getDeclaredField(last) - field.isAccessible = true - val modifiersField = Field::class.java.getDeclaredField("modifiers") - modifiersField.isAccessible = true - modifiersField.setInt(field, field.modifiers and Modifier.FINAL.inv()) - field[current] = newValue - } catch (e: NoSuchFieldException) { - CascadeBot.LOGGER.error("Failed to update guild data", e) - return false - } catch (e: IllegalAccessException) { - CascadeBot.LOGGER.error("Failed to update guild data", e) - return false - } - return true - } - - -} \ No newline at end of file From 5aa94059d2ae65619c6ed8cf4d1a5aaf8485ffad Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 12 Jun 2021 22:00:38 +0100 Subject: [PATCH 178/206] Make sure ModlogEvents map is immutable and methods protected --- .../moderation/ModlogChannelSubCommand.java | 2 +- .../moderation/ModlogClearSubCommand.java | 4 +- .../moderation/ModlogPruneSubCommand.java | 2 +- .../data/objects/GuildSettingsModeration.kt | 83 +++++++++++++++---- 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java index 2f7e23d1f..cc4f68c47 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java @@ -161,7 +161,7 @@ private void channelInfo(CommandContext context, TextChannel channel) { } private void channelDelete(CommandContext context, TextChannel channel) { - context.getData().getModeration().getModlogEvents().remove(channel.getIdLong()); + context.getData().getModeration().removeModlogEvent(channel.getIdLong()); context.getTypedMessaging().replySuccess("Successfully deleted channel!"); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java index 665027158..9120a16e5 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java @@ -30,7 +30,7 @@ public void onCommand(Member sender, CommandContext context) { ConfirmUtils.registerForConfirmation(sender.getIdLong(), clearAction, context.getChannel(), MessageType.WARNING, "Confirm that you want to remove ALL events", 0, TimeUnit.SECONDS.toMillis(5), true, () -> { - context.getData().getModeration().getModlogEvents().clear(); + context.getData().getModeration().clearModlogEvents(); context.getTypedMessaging().replySuccess("Removed all modlog events!"); }); } @@ -57,7 +57,7 @@ public void onCommand(Member sender, CommandContext context) { } } for (Long id : delete) { - context.getData().getModeration().getModlogEvents().remove(id); + context.getData().getModeration().removeModlogEvent(id); } context.getTypedMessaging().replySuccess("Deleted events from " + delete.size() + " disabled channel"); }); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java index 697d24a8c..54c2b39d8 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java @@ -13,7 +13,7 @@ public void onCommand(Member sender, CommandContext context) { int amount = 0; for (long id : context.getData().getModeration().getModlogEvents().keySet()) { if (CascadeBot.INS.getShardManager().getTextChannelById(id) == null) { - context.getData().getModeration().getModlogEvents().remove(id); + context.getData().getModeration().removeModlogEvent(id); amount++; } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index d1abf8ed5..e8b2d3ccb 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -20,7 +20,6 @@ import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode import org.cascadebot.cascadebot.utils.toCapitalized import java.net.URL import java.time.Instant -import java.util.ArrayList import java.util.Date import java.util.function.Consumer @@ -53,7 +52,18 @@ class GuildSettingsModeration { for (eventInfo in eventsInfo) { eventInfo.sendEvent(GuildDataManager.getGuildData(guildId), modlogEventData); } - CascadeBot.INS.databaseManager.runAsyncTask { database -> database.getCollection("modlog", ChannelModlogEventsInfo.MongoModlogEventObject::class.java).insertOne(ChannelModlogEventsInfo.MongoModlogEventObject(guildId, modlogEventData, "default" /* TODO change to actual time */), DebugLogCallback("Inserted Event")) } + CascadeBot.INS.databaseManager.runAsyncTask { database -> + database.getCollection( + "modlog", + ChannelModlogEventsInfo.MongoModlogEventObject::class.java + ).insertOne( + ChannelModlogEventsInfo.MongoModlogEventObject( + guildId, + modlogEventData, + "default" /* TODO change to actual time */ + ), DebugLogCallback("Inserted Event") + ) + } } private fun getEventInfoForEvent(event: ModlogEvent): List { @@ -67,7 +77,17 @@ class GuildSettingsModeration { } fun getModlogEvents(): Map { - return modlogEvents + return modlogEvents.toMap() + } + + fun removeModlogEvent(id: Long): ChannelModlogEventsInfo? { + assertWriteMode() + return modlogEvents.remove(id) + } + + fun clearModlogEvents() { + assertWriteMode() + return modlogEvents.clear() } fun buildWebhookClients() { @@ -107,7 +127,8 @@ class GuildSettingsModeration { val eventsInfo = ChannelModlogEventsInfo() eventsInfo.id = modlogChannelNum++ modlogEvents.put(channel.idLong, eventsInfo) - channel.createWebhook(CascadeBot.INS.client.selfUser.name).setAvatar(Icon.from(URL(CascadeBot.INS.client.selfUser.avatarUrl).openStream())).queue { webhook -> + channel.createWebhook(CascadeBot.INS.client.selfUser.name) + .setAvatar(Icon.from(URL(CascadeBot.INS.client.selfUser.avatarUrl).openStream())).queue { webhook -> eventsInfo.webhookId = webhook.idLong eventsInfo.webhookToken = webhook.token!! eventsInfo.buildWebhookClient() @@ -168,6 +189,7 @@ class GuildSettingsModeration { } fun setNewWebhook(webhookId: Long, webhookToken: String) { + assertWriteMode() this.webhookId = webhookId this.webhookToken = webhookToken buildWebhookClient() @@ -183,21 +205,28 @@ class GuildSettingsModeration { val affected = when (modlogEventData.trigger.affectedDisplayType) { AffectedDisplayType.NAME -> modlogEventData.affected.name AffectedDisplayType.MENTION -> modlogEventData.affected.mention - ?: modlogEventData.affected.name + ?: modlogEventData.affected.name } webhookEmbedBuilder.setDescription( - Language.i18n( - guildData.locale, - path, - affected, - modlogEventData.responsible?.asMention - ?: Language.i18n(guildData.locale, "words.unknown").toCapitalized(), - *modlogEventData.extraDescriptionInfo.toTypedArray() - ) + Language.i18n( + guildData.locale, + path, + affected, + modlogEventData.responsible?.asMention + ?: Language.i18n(guildData.locale, "words.unknown").toCapitalized(), + *modlogEventData.extraDescriptionInfo.toTypedArray() + ) ) } - webhookEmbedBuilder.setTitle(EmbedTitle(Language.i18n(guildData.locale, "enums.modlogevent." + modlogEventData.trigger.name.toLowerCase() + ".display"), null)) + webhookEmbedBuilder.setTitle( + EmbedTitle( + Language.i18n( + guildData.locale, + "enums.modlogevent." + modlogEventData.trigger.name.toLowerCase() + ".display" + ), null + ) + ) val affected: ModlogAffected = modlogEventData.affected; when (modlogEventData.trigger.displayType) { @@ -208,11 +237,23 @@ class GuildSettingsModeration { ModlogEvent.ModlogDisplayType.AFFECTED_AUTHOR -> { when (affected.affectedType) { AffectedType.USER -> { - webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, affected.imageUrl, "https://discord.com/users/" + affected.id)) + webhookEmbedBuilder.setAuthor( + WebhookEmbed.EmbedAuthor( + affected.name, + affected.imageUrl, + "https://discord.com/users/" + affected.id + ) + ) } AffectedType.EMOTE -> { - webhookEmbedBuilder.setAuthor(WebhookEmbed.EmbedAuthor(affected.name, affected.imageUrl, null)) + webhookEmbedBuilder.setAuthor( + WebhookEmbed.EmbedAuthor( + affected.name, + affected.imageUrl, + null + ) + ) } else -> { @@ -230,10 +271,16 @@ class GuildSettingsModeration { if (modlogEventData.responsible != null) { val iconUrl = modlogEventData.responsible.effectiveAvatarUrl // TODO: by user - webhookEmbedBuilder.setFooter(WebhookEmbed.EmbedFooter(modlogEventData.responsible.name + " (" + modlogEventData.responsible.id + ")", iconUrl)) + webhookEmbedBuilder.setFooter( + WebhookEmbed.EmbedFooter( + modlogEventData.responsible.name + " (" + modlogEventData.responsible.id + ")", + iconUrl + ) + ) } try { - webhookClient?.send(WebhookMessageBuilder() + webhookClient?.send( + WebhookMessageBuilder() .setUsername(CascadeBot.INS.client.selfUser.name) .setAvatarUrl(CascadeBot.INS.client.selfUser.effectiveAvatarUrl) .addEmbeds(webhookEmbedBuilder.build()) From bf39e0f6370a2f278f6cbe7522fa534128283cd7 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 13 Jun 2021 14:59:47 -0500 Subject: [PATCH 179/206] Get class for decoding from from field --- .../org/cascadebot/cascadebot/CascadeBot.java | 59 ++++++++++--------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 147ac57ac..69e471bf8 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -13,7 +13,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.mongodb.async.client.ChangeStreamIterable; -import com.mongodb.client.model.changestream.FullDocument; import com.mongodb.client.model.changestream.UpdateDescription; import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory; import io.sentry.Sentry; @@ -29,7 +28,6 @@ import net.dv8tion.jda.api.sharding.ShardManager; import okhttp3.OkHttpClient; import org.apache.commons.lang3.StringUtils; -import org.bson.BsonReader; import org.bson.BsonType; import org.bson.BsonValue; import org.bson.codecs.DecoderContext; @@ -72,10 +70,7 @@ import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Date; -import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.concurrent.TimeUnit; @@ -213,7 +208,7 @@ private void init() { databaseManager.runAsyncTask(database -> { ChangeStreamIterable changeStreamIterable = database.getCollection(GuildDataManager.COLLECTION, GuildData.class).watch(); - //.fullDocument(FullDocument.UPDATE_LOOKUP); // TODO not this + //.fullDocument(FullDocument.UPDATE_LOOKUP); // TODO not this changeStreamIterable.forEach(guildDataChangeStreamDocument -> { if (guildDataChangeStreamDocument.getFullDocument() != null) { GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()); @@ -223,9 +218,10 @@ private void init() { if (updateDescription.getUpdatedFields() != null) { for (Map.Entry change : updateDescription.getUpdatedFields().entrySet()) { try { - if (!updateGuildData(change.getKey(), currentData, bsonValueToJava(change.getValue()))) + FieldReturnObject returnObject = getField(change.getKey(), currentData); + if (!updateGuildData(returnObject.field, returnObject.currentObj, bsonValueToJava(change.getValue(), returnObject.field.getType()))) break; - } catch (ClassNotFoundException e) { + } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { CascadeBot.LOGGER.error("Failed to update data", e); break; } @@ -233,7 +229,13 @@ private void init() { } if (updateDescription.getRemovedFields() != null) { for (String removed : updateDescription.getRemovedFields()) { - if (!updateGuildData(removed, currentData, null)) break; + try { + FieldReturnObject returnObject = getField(removed, currentData); + if (!updateGuildData(returnObject.field, returnObject.currentObj, null)) break; + } catch (NoSuchFieldException | IllegalAccessException e) { + CascadeBot.LOGGER.error("Failed to update data", e); + break; + } } } } @@ -317,16 +319,11 @@ private void init() { } - public Object bsonValueToJava(BsonValue bsonValue) throws ClassNotFoundException { + public Object bsonValueToJava(BsonValue bsonValue, Class itemClass) throws ClassNotFoundException { Object decode; - if (bsonValue.getBsonType().equals(BsonType.ARRAY)) { - decode = new ArrayList<>(); - for (BsonValue arrayVale : bsonValue.asArray().getValues()) { - ((List)decode).add(bsonValueToJava(arrayVale)); - } - } else if (bsonValue.getBsonType().equals(BsonType.DOCUMENT)) { + if (bsonValue.getBsonType().equals(BsonType.DOCUMENT) || bsonValue.getBsonType().equals(BsonType.ARRAY)) { if (bsonValue.asDocument().containsKey("objClass")) { - decode = databaseManager.getCodecRegistry().get(Class.forName(bsonValue.asDocument().getString("objClass").getValue())).decode(bsonValue.asDocument().asBsonReader(), DecoderContext.builder().build()); // TODO this can work if we can find the java class, maybe store it? + decode = databaseManager.getCodecRegistry().get(itemClass).decode(bsonValue.asDocument().asBsonReader(), DecoderContext.builder().build()); // TODO this can work if we can find the java class, maybe store it? } else { decode = bsonValue; CascadeBot.LOGGER.error("Data object doesn't contain object class, so we can't properly decode it!"); @@ -338,22 +335,30 @@ public Object bsonValueToJava(BsonValue bsonValue) throws ClassNotFoundException return decode; } - public boolean updateGuildData(String path, GuildData guildData, Object newValue) { + public FieldReturnObject getField(String path, GuildData guildData) throws NoSuchFieldException, IllegalAccessException { String[] split = path.split("\\."); String last = split[split.length - 1]; Object current = guildData; for (String part : Arrays.copyOfRange(split, 0, split.length - 1)) { - try { - Field field = current.getClass().getDeclaredField(part); - field.setAccessible(true); - current = field.get(current); - } catch (NoSuchFieldException | IllegalAccessException e) { - CascadeBot.LOGGER.error("Failed to update guild data", e); - return false; - } + Field field = current.getClass().getDeclaredField(part); + field.setAccessible(true); + current = field.get(current); } + return new FieldReturnObject(current, current.getClass().getDeclaredField(last)); + } + + private static class FieldReturnObject { + Object currentObj; + Field field; + + FieldReturnObject(Object currentObj, Field field) { + this.currentObj = currentObj; + this.field = field; + } + } + + public boolean updateGuildData(Field field, Object current, Object newValue) { try { - Field field = current.getClass().getDeclaredField(last); field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); From 9db5ce1b0802ddfe7acf948529629b29e1188a12 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Sun, 13 Jun 2021 15:02:57 -0500 Subject: [PATCH 180/206] Remove object class as it is no longer needed --- .../cascadebot/cascadebot/data/objects/GuildPermissions.java | 2 +- .../cascadebot/data/objects/GuildSettingsUseful.java | 4 ---- src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java | 2 +- .../org/cascadebot/cascadebot/permissions/objects/Group.java | 2 +- .../org/cascadebot/cascadebot/permissions/objects/User.java | 2 +- .../org/cascadebot/cascadebot/data/objects/CommandFilter.kt | 2 +- .../org/cascadebot/cascadebot/data/objects/Greetings.kt | 2 +- .../org/cascadebot/cascadebot/data/objects/GuildData.kt | 2 -- .../cascadebot/cascadebot/data/objects/GuildSettingsCore.kt | 2 +- .../cascadebot/data/objects/GuildSettingsManagement.kt | 2 +- .../cascadebot/data/objects/GuildSettingsModeration.kt | 4 ++-- .../cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt | 2 +- .../kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt | 4 ++-- 13 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java index 4c438002e..7de4b42cc 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java @@ -33,7 +33,7 @@ public class GuildPermissions { - private final String objClass = this.getClass().getName(); + @Getter @Setter diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java index 66519ce72..fd62a3d28 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java @@ -10,12 +10,8 @@ @SettingsContainer(module = Module.USEFUL) public class GuildSettingsUseful { - private final String objClass = this.getClass().getName(); - private Map todoLists = new ConcurrentHashMap<>(); - boolean writeMode = false; - //region todo list stuff public TodoList getTodoList(String name) { return todoLists.get(name); diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java index 1f2ff0c42..c3dd97b92 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java @@ -22,7 +22,7 @@ @AllArgsConstructor public class Tag extends PermissionObject { - private final String objClass = this.getClass().getName(); + // https://regex101.com/r/hlsgVW/1 private static final Pattern TAG_PATTERN = Pattern.compile("\\{([A-z]+)(?::((?:,?\\w+)+))?}"); diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java index 42d40603c..f2f8c4d55 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java @@ -23,7 +23,7 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class Group extends PermissionHolder { - private final String objClass = this.getClass().getName(); + // Base 55 with 5 chars gives 503284375 combinations, we should be ok for uniqueness // This is normal alphanumeric with similar characters removed for less errors when inputting diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java index 580322e47..6126fec82 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java @@ -17,7 +17,7 @@ @EqualsAndHashCode(callSuper = true) public class User extends PermissionHolder { - private final String objClass = this.getClass().getName(); + private final Set groups = Sets.newConcurrentHashSet(); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt index eb84656c9..447e740f3 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt @@ -21,7 +21,7 @@ import java.util.Collections class CommandFilter(val name: String) { - private val objClass = this.javaClass.name + // Constructor for MongoDB private constructor() : this("") diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt index fda90c506..1155cefc0 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt @@ -10,7 +10,7 @@ import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects class Greetings { - private val objClass = this.javaClass.name + var welcomeMessages: WeightedList = WeightedList() var welcomeDMMessages: WeightedList = WeightedList() diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 0920ab722..9262decca 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -74,8 +74,6 @@ class GuildData(@field:Id val guildId: Long): Cloneable { val music = GuildSettingsMusic() //endregion - val objClass = this.javaClass.packageName + "." + this.javaClass.name - //region Transient fields @Transient @kotlin.jvm.Transient diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt index 8f6cf69d8..e91469646 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt @@ -44,7 +44,7 @@ class GuildSettingsCore { private val commandInfo = ConcurrentHashMap, MutableSet>() private val enabledModules: MutableSet = Sets.newConcurrentHashSet(Module.getModules(ModuleFlag.DEFAULT)) - private val objClass = this.javaClass.name + //region Modules fun enableModule(module: Module): Boolean { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt index f15d109db..d22f88cdc 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt @@ -17,7 +17,7 @@ class GuildSettingsManagement { @Setting var warnOver10Filters = true - private val objClass = this.javaClass.name + val tags: ConcurrentHashMap = ConcurrentHashMap() val filters: MutableList = mutableListOf() diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index e8b2d3ccb..e61310a69 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -39,7 +39,7 @@ class GuildSettingsModeration { @Setting var muteRoleName = "Muted" - private val objClass = this.javaClass.name + fun getRespectBanOrKickHierarchy(): Boolean { return respectBanOrKickHierarchy @@ -138,7 +138,7 @@ class GuildSettingsModeration { class ChannelModlogEventsInfo { - private val objClass = this.javaClass.name + private val events: MutableSet = LinkedHashSet() internal var webhookId: Long = 0 diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt index bc95fc8eb..4b3e54059 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt @@ -6,7 +6,7 @@ import java.util.concurrent.ConcurrentHashMap @SettingsContainer(module = Module.MUSIC) class GuildSettingsMusic { - private val objClass = this.javaClass.name + // TODO: Handle reverting tier for preserve settings @Setting diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt index 3efe2507c..43a17eb3f 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt @@ -16,7 +16,7 @@ import org.cascadebot.cascadebot.utils.buttons.PersistentButtonGroup class TodoList(val ownerId: Long) { - private val objClass = this.javaClass.name + val items: MutableList = ArrayList() var messageId: Long = -1 @@ -58,7 +58,7 @@ class TodoList(val ownerId: Long) { class TodoListItem { - private val objClass = this.javaClass.name + var done = false var text: String? = null From 6fdb56c8ad930dee1b384f64c4f73b963befe08b Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Tue, 20 Jul 2021 12:19:29 -0500 Subject: [PATCH 181/206] Minor fixes and clean up --- .../cascadebot/cascadebot/data/managers/GuildDataManager.java | 4 ++-- .../org/cascadebot/cascadebot/events/CommandListener.java | 1 - .../cascadebot/data/objects/GuildSettingsManagement.kt | 4 ---- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java index ff0fdc9f2..bf847384a 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java @@ -55,7 +55,7 @@ public final class GuildDataManager { public static void update(long id, Bson update) { CascadeBot.INS.getDatabaseManager().runAsyncTask(database -> { database.getCollection(COLLECTION, GuildData.class).updateOne(eq("_id", id), update, new DebugLogCallback<>("Updated Guild ID " + id + ":", update)); - });; + }); } public static void updateDiff(long id, Difference difference, GuildData newData) { @@ -83,7 +83,7 @@ public static void updateDiff(long id, Difference difference, GuildData newData) } CascadeBot.INS.getDatabaseManager().runAsyncTask(database -> { database.getCollection(COLLECTION, GuildData.class).updateMany(eq("_id", id), Updates.combine(bsonList), new DebugLogCallback<>("Updated Guild ID " + id)); - });; + }); replaceInternal(newData); } diff --git a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java index 73a88205d..6891a6ec6 100644 --- a/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java +++ b/src/main/java/org/cascadebot/cascadebot/events/CommandListener.java @@ -64,7 +64,6 @@ public void onGuildMessageReceived(GuildMessageReceivedEvent event) { MDC.put("cascade.sender", event.getAuthor().toString()); MDC.put("cascade.shard_info", event.getJDA().getShardInfo().getShardString()); MDC.put("cascade.channel", event.getChannel().toString()); - MDC.put("writeMode", String.valueOf(false)); String message = Regex.MULTISPACE_REGEX.matcher(event.getMessage().getContentRaw()).replaceAll(" "); message = MULTIQUOTE_REGEX.matcher(message).replaceAll(""); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt index d22f88cdc..410f82079 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt @@ -22,10 +22,6 @@ class GuildSettingsManagement { val tags: ConcurrentHashMap = ConcurrentHashMap() val filters: MutableList = mutableListOf() val permissions = GuildPermissions() - /* get() { - assertWriteMode() - return field - }*/ val greetings = Greetings() val autoRoles: MutableSet = mutableSetOf() From a8bf163f10526300b10a71d77f3a6883e581c761 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 22 Jul 2021 17:39:27 -0500 Subject: [PATCH 182/206] Wrap modlog guild data calls in write --- .../moderation/ModlogChannelSubCommand.java | 10 +++++++--- .../moderation/ModlogClearSubCommand.java | 8 +++++--- .../moderation/ModlogDisableSubCommand.java | 2 +- .../moderation/ModlogEnableSubCommand.java | 2 +- .../moderation/ModlogPruneSubCommand.java | 18 +++++++++++------- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java index cc4f68c47..b863eb2e4 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java @@ -161,7 +161,9 @@ private void channelInfo(CommandContext context, TextChannel channel) { } private void channelDelete(CommandContext context, TextChannel channel) { - context.getData().getModeration().removeModlogEvent(channel.getIdLong()); + context.getData().write(guildData -> { + guildData.getModeration().removeModlogEvent(channel.getIdLong()); + }); context.getTypedMessaging().replySuccess("Successfully deleted channel!"); } @@ -171,7 +173,7 @@ private void channelDisable(CommandContext context, TextChannel channel) { return; } channel.deleteWebhookById(String.valueOf(context.getData().getModeration().getModlogEvents().get(channel.getIdLong()).getWebhookId())).queue(aVoid -> { - context.getTypedMessaging().replySuccess("Successfully enabled channel!"); + context.getTypedMessaging().replySuccess("Successfully disabled channel!"); }, throwable -> { context.getTypedMessaging().replyDanger("Failed to disable events! The bot probably doesn't have permissions to delete webhooks."); }); @@ -183,7 +185,9 @@ private void channelEnable(CommandContext context, TextChannel channel) { return; } channel.createWebhook("cascade-modlog").queue(webhook -> { - context.getData().getModeration().getModlogEvents().get(channel.getIdLong()).setNewWebhook(webhook.getIdLong(), webhook.getToken()); + context.getData().write(guildData -> { + guildData.getModeration().getModlogEvents().get(channel.getIdLong()).setNewWebhook(webhook.getIdLong(), webhook.getToken()); + }); context.getTypedMessaging().replySuccess("Successfully disabled channel!"); }, throwable -> { context.getTypedMessaging().replyDanger("Failed to enable events! The bot probably doesn't have permissions to create webhooks."); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java index 9120a16e5..474346e73 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java @@ -56,9 +56,11 @@ public void onCommand(Member sender, CommandContext context) { } } } - for (Long id : delete) { - context.getData().getModeration().removeModlogEvent(id); - } + context.getData().write(guildData -> { + for (Long id : delete) { + guildData.getModeration().removeModlogEvent(id); + } + }); context.getTypedMessaging().replySuccess("Deleted events from " + delete.size() + " disabled channel"); }); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java index 49c1d9aa1..b53c92fe4 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java @@ -56,7 +56,7 @@ public void onCommand(Member sender, CommandContext context) { List failedEvents = new ArrayList<>(); List succeed = new ArrayList<>(); for (ModlogEvent event : modlogEvents) { - if (context.getData().getModeration().disableEvent(textChannel, event)) { + if (context.getData().writeInline(guildData -> guildData.getModeration().disableEvent(textChannel, event))) { succeed.add(event); } else { failedEvents.add(event); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java index 8070baf4e..4b7ca144e 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java @@ -57,7 +57,7 @@ public void onCommand(Member sender, CommandContext context) { List failedEvents = new ArrayList<>(); List succeed = new ArrayList<>(); for (ModlogEvent event : modlogEvents) { - if (context.getData().getModeration().enableEvent(textChannel, event)) { + if (context.getData().writeInline(guildData -> guildData.getModeration().enableEvent(textChannel, event))) { succeed.add(event); } else { failedEvents.add(event); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java index 54c2b39d8..71ac9af24 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java @@ -7,17 +7,21 @@ import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.permissions.CascadePermission; +import java.util.concurrent.atomic.AtomicInteger; + public class ModlogPruneSubCommand extends SubCommand { public void onCommand(Member sender, CommandContext context) { - int amount = 0; - for (long id : context.getData().getModeration().getModlogEvents().keySet()) { - if (CascadeBot.INS.getShardManager().getTextChannelById(id) == null) { - context.getData().getModeration().removeModlogEvent(id); - amount++; + AtomicInteger amount = new AtomicInteger(0); + context.getData().write(guildData -> { + for (long id : context.getData().getModeration().getModlogEvents().keySet()) { + if (CascadeBot.INS.getShardManager().getTextChannelById(id) == null) { + context.getData().getModeration().removeModlogEvent(id); + amount.getAndIncrement(); + } } - } - context.getTypedMessaging().replySuccess("Removed all events from " + amount + " deleted channels"); + }); + context.getTypedMessaging().replySuccess("Removed all events from " + amount.get() + " deleted channels"); } public String command() { From eb446035fda74e61c746e6cd826095f9e02917d5 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 29 Jul 2021 12:57:30 -0500 Subject: [PATCH 183/206] Fix some data stuffs --- .../org/cascadebot/cascadebot/CascadeBot.java | 15 +++++++-------- .../cascadebot/data/objects/GuildData.kt | 4 ++++ .../data/objects/GuildSettingsModeration.kt | 1 - 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 69e471bf8..b56512f83 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -221,7 +221,7 @@ private void init() { FieldReturnObject returnObject = getField(change.getKey(), currentData); if (!updateGuildData(returnObject.field, returnObject.currentObj, bsonValueToJava(change.getValue(), returnObject.field.getType()))) break; - } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { CascadeBot.LOGGER.error("Failed to update data", e); break; } @@ -322,15 +322,14 @@ private void init() { public Object bsonValueToJava(BsonValue bsonValue, Class itemClass) throws ClassNotFoundException { Object decode; if (bsonValue.getBsonType().equals(BsonType.DOCUMENT) || bsonValue.getBsonType().equals(BsonType.ARRAY)) { - if (bsonValue.asDocument().containsKey("objClass")) { - decode = databaseManager.getCodecRegistry().get(itemClass).decode(bsonValue.asDocument().asBsonReader(), DecoderContext.builder().build()); // TODO this can work if we can find the java class, maybe store it? - } else { - decode = bsonValue; - CascadeBot.LOGGER.error("Data object doesn't contain object class, so we can't properly decode it!"); - } + decode = databaseManager.getCodecRegistry().get(itemClass).decode(bsonValue.asDocument().asBsonReader(), DecoderContext.builder().build()); } else { // This only handles primitives basically - decode = BsonUtils.toJavaType(bsonValue); + if (int.class == itemClass && bsonValue.getBsonType().equals(BsonType.DOUBLE)) { // https://stackoverflow.com/questions/60809700/in-mongodb-integer-datatype-is-automatically-type-cast-to-doube + decode = ((Double)BsonUtils.toJavaType(bsonValue)).intValue(); + } else { + decode = itemClass.cast(BsonUtils.toJavaType(bsonValue)); + } } return decode; } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 9262decca..9e2082a5f 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -46,6 +46,10 @@ class GuildData(@field:Id val guildId: Long): Cloneable { val writeMode: ThreadLocal = ThreadLocal() + init { + writeMode.set(false) + } + } private constructor() : this(0L) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index e61310a69..b1bbb1a62 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -162,7 +162,6 @@ class GuildSettingsModeration { } fun buildWebhookClient() { - assertWriteMode() webhookClient = WebhookClientBuilder(webhookId, webhookToken).build() } From 7a88c3bb4aa66c6ba35de99c5818a101af34c1f7 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 29 Jul 2021 15:06:53 -0500 Subject: [PATCH 184/206] Attempts at fixing guild data stuffs --- pom.xml | 2 +- .../org/cascadebot/cascadebot/CascadeBot.java | 11 +++++--- .../moderation/ModlogChannelSubCommand.java | 2 +- .../moderation/ModlogClearSubCommand.java | 6 ++--- .../moderation/ModlogDisableSubCommand.java | 26 +++++++++++------- .../moderation/ModlogEnableSubCommand.java | 27 ++++++++++++------- .../moderation/ModlogPruneSubCommand.java | 2 +- .../data/database/DatabaseManager.java | 14 ++++++++++ .../data/managers/GuildDataManager.java | 3 +++ .../cascadebot/utils/diff/DiffUtils.java | 14 +++++++--- .../data/objects/GuildSettingsModeration.kt | 16 +++++------ 11 files changed, 83 insertions(+), 40 deletions(-) diff --git a/pom.xml b/pom.xml index 8f9d59437..164cb31ff 100644 --- a/pom.xml +++ b/pom.xml @@ -186,7 +186,7 @@ de.bild.backend polymorphia - 2.5.0 + 2.8.0 org.mongodb diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index b56512f83..18cdf91a0 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -28,6 +28,7 @@ import net.dv8tion.jda.api.sharding.ShardManager; import okhttp3.OkHttpClient; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.reflect.TypeUtils; import org.bson.BsonType; import org.bson.BsonValue; import org.bson.codecs.DecoderContext; @@ -339,9 +340,13 @@ public FieldReturnObject getField(String path, GuildData guildData) throws NoSuc String last = split[split.length - 1]; Object current = guildData; for (String part : Arrays.copyOfRange(split, 0, split.length - 1)) { - Field field = current.getClass().getDeclaredField(part); - field.setAccessible(true); - current = field.get(current); + if (TypeUtils.isAssignable(current.getClass(), Map.class)) { + current = ((Map)current).get(part); + } else { + Field field = current.getClass().getDeclaredField(part); + field.setAccessible(true); + current = field.get(current); + } } return new FieldReturnObject(current, current.getClass().getDeclaredField(last)); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java index b863eb2e4..a005824cd 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogChannelSubCommand.java @@ -162,7 +162,7 @@ private void channelInfo(CommandContext context, TextChannel channel) { private void channelDelete(CommandContext context, TextChannel channel) { context.getData().write(guildData -> { - guildData.getModeration().removeModlogEvent(channel.getIdLong()); + guildData.getModeration().removeModlogEvent(String.valueOf(channel.getIdLong())); }); context.getTypedMessaging().replySuccess("Successfully deleted channel!"); } diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java index 474346e73..5053e713a 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogClearSubCommand.java @@ -43,8 +43,8 @@ public void onCommand(Member sender, CommandContext context) { ConfirmUtils.registerForConfirmation(sender.getIdLong(), clearDisabledAction, context.getChannel(), MessageType.WARNING, "Confirm that you want to remove all events in disabled channels", 0, TimeUnit.SECONDS.toMillis(5), true, () -> { - List delete = new ArrayList<>(); - for (Map.Entry entry : context.getData().getModeration().getModlogEvents().entrySet()) { + List delete = new ArrayList<>(); + for (Map.Entry entry : context.getData().getModeration().getModlogEvents().entrySet()) { TextChannel textChannel = CascadeBot.INS.getClient().getTextChannelById(entry.getKey()); if (textChannel == null) { continue; @@ -57,7 +57,7 @@ public void onCommand(Member sender, CommandContext context) { } } context.getData().write(guildData -> { - for (Long id : delete) { + for (String id : delete) { guildData.getModeration().removeModlogEvent(id); } }); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java index b53c92fe4..2fa922fb3 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogDisableSubCommand.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; public class ModlogDisableSubCommand extends SubCommand { @@ -41,7 +42,7 @@ public void onCommand(Member sender, CommandContext context) { for (String event : events) { if (EnumUtils.isValidEnumIgnoreCase(ModlogEvent.class, event.toUpperCase())) { modlogEvents.add(ModlogEvent.valueOf(event.toUpperCase())); // TODO reverse language to get event - } else if (EnumUtils.isValidEnumIgnoreCase(ModlogEvent.Category.class, event.toUpperCase())){ + } else if (EnumUtils.isValidEnumIgnoreCase(ModlogEvent.Category.class, event.toUpperCase())) { ModlogEvent.Category category = ModlogEvent.Category.valueOf(event.toUpperCase()); List additionalEvents = ModlogEvent.Companion.getEventsFromCategory(category); modlogEvents.addAll(additionalEvents); @@ -55,12 +56,19 @@ public void onCommand(Member sender, CommandContext context) { } List failedEvents = new ArrayList<>(); List succeed = new ArrayList<>(); - for (ModlogEvent event : modlogEvents) { - if (context.getData().writeInline(guildData -> guildData.getModeration().disableEvent(textChannel, event))) { - succeed.add(event); - } else { - failedEvents.add(event); + AtomicBoolean finished = new AtomicBoolean(false); + context.getData().write(guildData -> { + for (ModlogEvent event : modlogEvents) { + if (guildData.getModeration().disableEvent(textChannel, event)) { + succeed.add(event); + } else { + failedEvents.add(event); + } + finished.set(true); } + }); + while (!finished.get()) { + } List pageList = new ArrayList<>(); if (failedEvents.size() == modlogEvents.size()) { @@ -79,7 +87,7 @@ public void onCommand(Member sender, CommandContext context) { if (succeed.size() > 0) { List pageValues = PageUtils.splitString(succeed.stream().map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; - for (String pageValue: pageValues) { + for (String pageValue : pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setColor(MessageType.SUCCESS.getColor()); embedBuilder.setTitle("Disabled Events"); @@ -95,7 +103,7 @@ public void onCommand(Member sender, CommandContext context) { if (failedEvents.size() > 0) { List pageValues = PageUtils.splitString(failedEvents.stream().map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; - for (String pageValue: pageValues) { + for (String pageValue : pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setColor(MessageType.WARNING.getColor()); embedBuilder.setTitle("Failed to disable events"); @@ -111,7 +119,7 @@ public void onCommand(Member sender, CommandContext context) { if (failed.size() > 0) { List pageValues = PageUtils.splitString(String.join("\n", failed), 1000, '\n'); int subPage = 1; - for (String pageValue: pageValues) { + for (String pageValue : pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setColor(MessageType.DANGER.getColor()); embedBuilder.setTitle("Failed to find events"); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java index 4b7ca144e..6cc07ae4f 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogEnableSubCommand.java @@ -8,7 +8,6 @@ import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.commandmeta.SubCommand; import org.cascadebot.cascadebot.data.language.Language; -import org.cascadebot.cascadebot.data.objects.LoopMode; import org.cascadebot.cascadebot.messaging.MessageType; import org.cascadebot.cascadebot.moderation.ModlogEvent; import org.cascadebot.cascadebot.permissions.CascadePermission; @@ -20,6 +19,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; public class ModlogEnableSubCommand extends SubCommand { @@ -42,7 +42,7 @@ public void onCommand(Member sender, CommandContext context) { for (String event : events) { if (EnumUtils.isValidEnumIgnoreCase(ModlogEvent.class, event.toUpperCase())) { modlogEvents.add(ModlogEvent.valueOf(event.toUpperCase())); // TODO reverse language to get event - } else if (EnumUtils.isValidEnumIgnoreCase(ModlogEvent.Category.class, event.toUpperCase())){ + } else if (EnumUtils.isValidEnumIgnoreCase(ModlogEvent.Category.class, event.toUpperCase())) { ModlogEvent.Category category = ModlogEvent.Category.valueOf(event.toUpperCase()); List additionalEvents = ModlogEvent.Companion.getEventsFromCategory(category); modlogEvents.addAll(additionalEvents); @@ -56,12 +56,19 @@ public void onCommand(Member sender, CommandContext context) { } List failedEvents = new ArrayList<>(); List succeed = new ArrayList<>(); - for (ModlogEvent event : modlogEvents) { - if (context.getData().writeInline(guildData -> guildData.getModeration().enableEvent(textChannel, event))) { - succeed.add(event); - } else { - failedEvents.add(event); + AtomicBoolean finished = new AtomicBoolean(false); + context.getData().write(guildData -> { + for (ModlogEvent event : modlogEvents) { + if (guildData.getModeration().enableEvent(textChannel, event)) { + succeed.add(event); + } else { + failedEvents.add(event); + } } + finished.set(true); + }); + while (!finished.get()) { + } List pageList = new ArrayList<>(); if (failedEvents.size() == modlogEvents.size()) { @@ -80,7 +87,7 @@ public void onCommand(Member sender, CommandContext context) { if (succeed.size() > 0) { List pageValues = PageUtils.splitString(succeed.stream().map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; - for (String pageValue: pageValues) { + for (String pageValue : pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setColor(MessageType.SUCCESS.getColor()); embedBuilder.setTitle("Enabled Events"); @@ -96,7 +103,7 @@ public void onCommand(Member sender, CommandContext context) { if (failedEvents.size() > 0) { List pageValues = PageUtils.splitString(failedEvents.stream().map(event -> Language.i18n(context.getLocale(), "enums.modlogevent." + event.name().toLowerCase() + ".display")).collect(Collectors.joining("\n")), 1000, '\n'); int subPage = 1; - for (String pageValue: pageValues) { + for (String pageValue : pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setColor(MessageType.WARNING.getColor()); embedBuilder.setTitle("Failed to enable events"); @@ -112,7 +119,7 @@ public void onCommand(Member sender, CommandContext context) { if (failed.size() > 0) { List pageValues = PageUtils.splitString(String.join("\n", failed), 1000, '\n'); int subPage = 1; - for (String pageValue: pageValues) { + for (String pageValue : pageValues) { EmbedBuilder embedBuilder = new EmbedBuilder(); embedBuilder.setColor(MessageType.DANGER.getColor()); embedBuilder.setTitle("Failed to find events"); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java index 71ac9af24..ded56b3e7 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/moderation/ModlogPruneSubCommand.java @@ -14,7 +14,7 @@ public class ModlogPruneSubCommand extends SubCommand { public void onCommand(Member sender, CommandContext context) { AtomicInteger amount = new AtomicInteger(0); context.getData().write(guildData -> { - for (long id : context.getData().getModeration().getModlogEvents().keySet()) { + for (String id : context.getData().getModeration().getModlogEvents().keySet()) { if (CascadeBot.INS.getShardManager().getTextChannelById(id) == null) { context.getData().getModeration().removeModlogEvent(id); amount.getAndIncrement(); diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java b/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java index 0d719b55d..9f355cdff 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java @@ -13,10 +13,20 @@ import com.mongodb.client.MongoClients; import com.mongodb.client.MongoDatabase; import com.mongodb.connection.netty.NettyStreamFactory; +import de.bild.codec.CodecConfiguration; +import de.bild.codec.CodecResolver; import de.bild.codec.PojoCodecProvider; +import de.bild.codec.PolymorphicCodec; +import de.bild.codec.TypeCodecRegistry; import lombok.Getter; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.reflect.TypeUtils; +import org.bson.BsonReader; +import org.bson.BsonWriter; import org.bson.Document; +import org.bson.codecs.DecoderContext; +import org.bson.codecs.DocumentCodec; +import org.bson.codecs.EncoderContext; import org.bson.codecs.configuration.CodecRegistries; import org.bson.codecs.configuration.CodecRegistry; import org.cascadebot.cascadebot.moderation.ModlogEmbedDescription; @@ -27,8 +37,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.lang.reflect.Type; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; public class DatabaseManager { diff --git a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java index bf847384a..1694aa2ad 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java @@ -59,6 +59,7 @@ public static void update(long id, Bson update) { } public static void updateDiff(long id, Difference difference, GuildData newData) { + CascadeBot.LOGGER.info(CascadeBot.getGSON().toJson(difference)); List bsonList = new ArrayList<>(); for (Map.Entry added : difference.getAdded().entrySet()) { bsonList.add(Updates.set(added.getKey(), added.getValue())); @@ -81,6 +82,8 @@ public static void updateDiff(long id, Difference difference, GuildData newData) if (bsonList.size() == 0) { return; } + Bson update = Updates.combine(bsonList); + CascadeBot.LOGGER.info(update.toString()); CascadeBot.INS.getDatabaseManager().runAsyncTask(database -> { database.getCollection(COLLECTION, GuildData.class).updateMany(eq("_id", id), Updates.combine(bsonList), new DebugLogCallback<>("Updated Guild ID " + id)); }); diff --git a/src/main/java/org/cascadebot/cascadebot/utils/diff/DiffUtils.java b/src/main/java/org/cascadebot/cascadebot/utils/diff/DiffUtils.java index ea9d32e84..8ece7e2fd 100644 --- a/src/main/java/org/cascadebot/cascadebot/utils/diff/DiffUtils.java +++ b/src/main/java/org/cascadebot/cascadebot/utils/diff/DiffUtils.java @@ -34,8 +34,14 @@ private static Difference diff(Difference currentDiff, String path, Object oldOb Map oldMap = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(oldObj), mapType); Map newMap = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(newObj), mapType); + diffMap(currentDiff, path, oldMap, newMap); + + return currentDiff; + } + + private static Difference diffMap(Difference currentDiff, String path, Map oldMap, Map newMap) { List oldKeys = new ArrayList<>(oldMap.keySet()); - List newKeys = new ArrayList<>(oldMap.keySet()); + List newKeys = new ArrayList<>(newMap.keySet()); CollectionDiff collectionDiff = new CollectionDiff<>(oldKeys, newKeys); @@ -67,7 +73,9 @@ private static Difference diff(Difference currentDiff, String path, Object oldOb } else if (oldValue instanceof Collection) { CollectionDiff changed = new CollectionDiff<>((Collection) oldValue, (Collection) newValue); currentDiff.changed.put(path + key, changed); - } else { + } else if (oldValue instanceof Map) { + diffMap(currentDiff, path + key + ".", (Map)oldValue, (Map)newValue); + } else { diff(currentDiff, path + key + ".", oldValue, newValue); } } @@ -76,6 +84,4 @@ private static Difference diff(Difference currentDiff, String path, Object oldOb return currentDiff; } - - } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index b1bbb1a62..d9eeb7602 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -45,7 +45,7 @@ class GuildSettingsModeration { return respectBanOrKickHierarchy } - private val modlogEvents: MutableMap = HashMap() + private val modlogEvents: MutableMap = HashMap() fun sendModlogEvent(guildId: Long, modlogEventData: ModlogEventData) { val eventsInfo: List = getEventInfoForEvent(modlogEventData.trigger) @@ -76,11 +76,11 @@ class GuildSettingsModeration { return channelModlogEventsInfos } - fun getModlogEvents(): Map { + fun getModlogEvents(): Map { return modlogEvents.toMap() } - fun removeModlogEvent(id: Long): ChannelModlogEventsInfo? { + fun removeModlogEvent(id: String): ChannelModlogEventsInfo? { assertWriteMode() return modlogEvents.remove(id) } @@ -98,8 +98,8 @@ class GuildSettingsModeration { fun enableEvent(channel: TextChannel, event: ModlogEvent): Boolean { assertWriteMode() - if (modlogEvents.containsKey(channel.idLong)) { - return modlogEvents[channel.idLong]!!.addEvent(event) + if (modlogEvents.containsKey(channel.idLong.toString())) { + return modlogEvents[channel.idLong.toString()]!!.addEvent(event) } else { createModlogEventsInfo(channel, Consumer { it.addEvent(event) }) return true @@ -108,8 +108,8 @@ class GuildSettingsModeration { fun disableEvent(channel: TextChannel, event: ModlogEvent): Boolean { assertWriteMode() - if (modlogEvents.containsKey(channel.idLong)) { - return modlogEvents[channel.idLong]!!.removeEvent(event) + if (modlogEvents.containsKey(channel.idLong.toString())) { + return modlogEvents[channel.idLong.toString()]!!.removeEvent(event) } else { return false } @@ -126,7 +126,7 @@ class GuildSettingsModeration { assertWriteMode() val eventsInfo = ChannelModlogEventsInfo() eventsInfo.id = modlogChannelNum++ - modlogEvents.put(channel.idLong, eventsInfo) + modlogEvents.put(channel.idLong.toString(), eventsInfo) channel.createWebhook(CascadeBot.INS.client.selfUser.name) .setAvatar(Icon.from(URL(CascadeBot.INS.client.selfUser.avatarUrl).openStream())).queue { webhook -> eventsInfo.webhookId = webhook.idLong From 3d7b850fba9a8491d6c055fb1b2a85a410b6143e Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 8 Aug 2021 13:55:56 +0100 Subject: [PATCH 185/206] More stuff --- pom.xml | 16 +- .../org/cascadebot/cascadebot/CascadeBot.java | 150 ++++++++++++++++-- 2 files changed, 148 insertions(+), 18 deletions(-) diff --git a/pom.xml b/pom.xml index 164cb31ff..2437a07ad 100644 --- a/pom.xml +++ b/pom.xml @@ -184,9 +184,9 @@ ${kotlin.version} - de.bild.backend + com.github.binaryoverload polymorphia - 2.8.0 + a89c3a399f org.mongodb @@ -194,6 +194,18 @@ + + + + + + + + + + + + org.reflections reflections diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 18cdf91a0..68b73e17e 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -15,8 +15,10 @@ import com.mongodb.async.client.ChangeStreamIterable; import com.mongodb.client.model.changestream.UpdateDescription; import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory; +import de.bild.codec.ReflectionHelper; import io.sentry.Sentry; import io.sentry.SentryClient; +import lombok.Getter; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.Activity; @@ -29,6 +31,8 @@ import okhttp3.OkHttpClient; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.reflect.TypeUtils; +import org.bson.BsonDocument; +import org.bson.BsonReader; import org.bson.BsonType; import org.bson.BsonValue; import org.bson.codecs.DecoderContext; @@ -69,11 +73,19 @@ import javax.annotation.Nonnull; import javax.security.auth.login.LoginException; import java.io.IOException; +import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Scanner; +import java.util.Set; import java.util.concurrent.TimeUnit; public class CascadeBot { @@ -219,9 +231,17 @@ private void init() { if (updateDescription.getUpdatedFields() != null) { for (Map.Entry change : updateDescription.getUpdatedFields().entrySet()) { try { - FieldReturnObject returnObject = getField(change.getKey(), currentData); - if (!updateGuildData(returnObject.field, returnObject.currentObj, bsonValueToJava(change.getValue(), returnObject.field.getType()))) - break; + ReturnObject returnObject = getField(change.getKey(), currentData); + if (returnObject instanceof FieldReturnObject) { + FieldReturnObject fieldReturnObject = (FieldReturnObject) returnObject; + if (!updateGuildData(fieldReturnObject.getField(), fieldReturnObject.getCurrentObj(), bsonValueToJava(change.getValue(), fieldReturnObject.getField().getType()))) { + break; + } + } else if (returnObject instanceof SimpleMapReturnObject) { + SimpleMapReturnObject mapReturnObject = (SimpleMapReturnObject) returnObject; + mapReturnObject.getMap().put(mapReturnObject.getKey(), bsonValueToJava(change.getValue(), mapReturnObject.valueClass)); + } + } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { CascadeBot.LOGGER.error("Failed to update data", e); break; @@ -231,8 +251,16 @@ private void init() { if (updateDescription.getRemovedFields() != null) { for (String removed : updateDescription.getRemovedFields()) { try { - FieldReturnObject returnObject = getField(removed, currentData); - if (!updateGuildData(returnObject.field, returnObject.currentObj, null)) break; + ReturnObject returnObject = getField(removed, currentData); + if (returnObject instanceof FieldReturnObject) { + FieldReturnObject fieldReturnObject = (FieldReturnObject) returnObject; + if (!updateGuildData(fieldReturnObject.getField(), fieldReturnObject.getCurrentObj(), null)) { + break; + } + } else if (returnObject instanceof SimpleMapReturnObject) { + SimpleMapReturnObject mapReturnObject = (SimpleMapReturnObject) returnObject; + mapReturnObject.getMap().remove(mapReturnObject.getKey()); + } } catch (NoSuchFieldException | IllegalAccessException e) { CascadeBot.LOGGER.error("Failed to update data", e); break; @@ -320,45 +348,134 @@ private void init() { } + private boolean updateSimpleMapData(Map map, String key, Object bsonValueToJava) { + map.put(key, bsonValueToJava); + return true; + } + public Object bsonValueToJava(BsonValue bsonValue, Class itemClass) throws ClassNotFoundException { - Object decode; - if (bsonValue.getBsonType().equals(BsonType.DOCUMENT) || bsonValue.getBsonType().equals(BsonType.ARRAY)) { + Object decode = null; + if (bsonValue.getBsonType().equals(BsonType.DOCUMENT)) { decode = databaseManager.getCodecRegistry().get(itemClass).decode(bsonValue.asDocument().asBsonReader(), DecoderContext.builder().build()); } else { // This only handles primitives basically if (int.class == itemClass && bsonValue.getBsonType().equals(BsonType.DOUBLE)) { // https://stackoverflow.com/questions/60809700/in-mongodb-integer-datatype-is-automatically-type-cast-to-doube - decode = ((Double)BsonUtils.toJavaType(bsonValue)).intValue(); + decode = ((Double) BsonUtils.toJavaType(bsonValue)).intValue(); } else { - decode = itemClass.cast(BsonUtils.toJavaType(bsonValue)); + Object converted = BsonUtils.toJavaType(bsonValue); + + if (converted instanceof Object[]) { + Object[] objects = (Object[]) converted; + + Class type = null; + + Type collectionInterface = ReflectionHelper.findInterface(itemClass, Collection.class); + if (collectionInterface != null) { + if (collectionInterface instanceof ParameterizedType && !TypeUtils.containsTypeVariables(collectionInterface)) { + ParameterizedType parameterizedType = (ParameterizedType) collectionInterface; + type = (Class) parameterizedType.getActualTypeArguments()[0]; + } + } else if (itemClass.isArray()) { + type = itemClass.getComponentType(); + } + + if (type == null) { + throw new IllegalStateException(String.format("Cannot assign array to non-collection / non-array class \"%s\"", itemClass)); + } + + for (int i = 0; i < objects.length; i++) { + objects[i] = bsonValueToJava((BsonValue) objects[i], type); + } + + if (itemClass.isArray()) { + Object[] arrayOfXType = (Object[]) Array.newInstance(itemClass.getComponentType(), objects.length); + System.arraycopy(objects, 0, arrayOfXType, 0, objects.length); + decode = arrayOfXType; + } else if (itemClass.isAssignableFrom(Collection.class)) { + Collection collection = (Collection) converted; + collection.clear(); + collection.addAll(Arrays.asList(objects)); + decode = collection; + } + } } } + + if (decode == null) { + throw new IllegalStateException(String.format("Could not convert value to class \"%s\"", itemClass)); + } + return decode; } - public FieldReturnObject getField(String path, GuildData guildData) throws NoSuchFieldException, IllegalAccessException { + private List getGenericList(Class type, Object... params) { + List l = new ArrayList(); + for (int i = 0; i < params.length; i++) { + l.add((T) params[i]); + } + return l; + } + + public ReturnObject getField(String path, GuildData guildData) throws NoSuchFieldException, IllegalAccessException { String[] split = path.split("\\."); String last = split[split.length - 1]; Object current = guildData; for (String part : Arrays.copyOfRange(split, 0, split.length - 1)) { if (TypeUtils.isAssignable(current.getClass(), Map.class)) { - current = ((Map)current).get(part); + current = ((Map) current).get(part); } else { Field field = current.getClass().getDeclaredField(part); field.setAccessible(true); current = field.get(current); } } - return new FieldReturnObject(current, current.getClass().getDeclaredField(last)); + if (TypeUtils.isAssignable(current.getClass(), Map.class)) { + Type mapInterface = ReflectionHelper.findInterface(current.getClass(), Map.class); + if (mapInterface instanceof ParameterizedType && !TypeUtils.containsTypeVariables(mapInterface)) { + ParameterizedType parameterizedType = (ParameterizedType) mapInterface; + Class keyClass = (Class) parameterizedType.getActualTypeArguments()[0]; + Class valueClass = (Class) parameterizedType.getActualTypeArguments()[1]; + + if (keyClass == String.class) { + return new SimpleMapReturnObject((Map) current, last, valueClass); + } + } + } else { + return new FieldReturnObject(current, current.getClass().getDeclaredField(last)); + } + return null; + } + + interface ReturnObject { + } - private static class FieldReturnObject { - Object currentObj; - Field field; + @Getter + private static class FieldReturnObject implements ReturnObject { + + private final Object currentObj; + private final Field field; FieldReturnObject(Object currentObj, Field field) { this.currentObj = currentObj; this.field = field; } + + } + + @Getter + private static class SimpleMapReturnObject implements ReturnObject { + + private final Map map; + private final String key; + private final Class valueClass; + + public SimpleMapReturnObject(Map map, String key, Class valueClass) { + this.map = map; + this.key = key; + this.valueClass = valueClass; + } + } public boolean updateGuildData(Field field, Object current, Object newValue) { @@ -394,8 +511,9 @@ protected void execute() { @Nonnull public JDA getClient() { for (JDA jda : shardManager.getShardCache()) { - if (jda.getStatus() == JDA.Status.LOADING_SUBSYSTEMS || jda.getStatus() == JDA.Status.CONNECTED) + if (jda.getStatus() == JDA.Status.LOADING_SUBSYSTEMS || jda.getStatus() == JDA.Status.CONNECTED) { return jda; + } } throw new IllegalStateException("getClient was called when no shards were connected!"); } From da19ce5b38f9cc56ed3e8a9b03670d6f6c764549 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 12 Aug 2021 11:42:37 -0500 Subject: [PATCH 186/206] I made a deep copy method that works! --- .../cascadebot/data/database/DataHandler.java | 99 +++++++++++++++++++ .../cascadebot/data/objects/GuildData.kt | 4 +- 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java new file mode 100644 index 000000000..a32572d34 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java @@ -0,0 +1,99 @@ +package org.cascadebot.cascadebot.data.database; + +import org.bson.BsonDocument; +import org.bson.conversions.Bson; +import org.cascadebot.cascadebot.utils.diff.Difference; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class DataHandler { + + public Y deepCopy(Y original) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, ClassNotFoundException { + if (original == null) { + return null; + } + System.out.println(original.getClass().getName()); + if (original.getClass().isPrimitive()) { + return original; // TODO does this work? + } else if (original.getClass().isArray()) { + throw new UnsupportedOperationException(); + } else if (original instanceof Map) { + Map map = (Map) original; + Map newMap = (Map) original.getClass().getDeclaredConstructor().newInstance(); + for (Map.Entry entry : map.entrySet()) { + newMap.put(deepCopy(entry.getKey()), deepCopy(entry.getValue())); + } + return (Y) newMap; + } else if (original instanceof Collection) { + Collection collection = (Collection) original; + Collection newCol = (Collection) original.getClass().getDeclaredConstructor().newInstance(); + for (Object obj : collection) { + newCol.add(deepCopy(obj)); + } + return (Y) newCol; + } else if (original instanceof Serializable) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(out); + objectOutputStream.writeObject(original); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + ObjectInputStream objectInputStream = new ObjectInputStream(in); + Y copy = (Y) objectInputStream.readObject(); + return copy; + } else { + Constructor constructor; + try { + constructor = (Constructor) original.getClass().getDeclaredConstructor(); + } catch (NoSuchMethodException e) { + return null; + } + constructor.setAccessible(true); + Y obj = (Y) constructor.newInstance(); + + for(Field field : original.getClass().getDeclaredFields()) { + if (Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) { + continue; + } + field.setAccessible(true); + Object fieldOrig = field.get(original); + Object copy = deepCopy(fieldOrig); + + Field toEdit = obj.getClass().getDeclaredField(field.getName()); + makeAccessible(toEdit); + + toEdit.set(obj, copy); + } + + return obj; + } + } + + private void makeAccessible(Field field) throws NoSuchFieldException, IllegalAccessException { + field.setAccessible(true); + + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + } + + /*public Difference diff(T original, T changed) { + + } + + public Bson getUpdate(Difference difference) { + + }*/ + +} diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 9e2082a5f..fa6e5bc2f 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -36,7 +36,7 @@ import java.util.concurrent.atomic.AtomicBoolean import java.util.function.Function import kotlin.concurrent.getOrSet -class GuildData(@field:Id val guildId: Long): Cloneable { +class GuildData(@field:Id val guildId: Long) { @Transient @kotlin.jvm.Transient @@ -44,6 +44,8 @@ class GuildData(@field:Id val guildId: Long): Cloneable { companion object { + @Transient + @kotlin.jvm.Transient val writeMode: ThreadLocal = ThreadLocal() init { From cd9b6044a362a5922274da67581a84e1bbacfc3a Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Fri, 13 Aug 2021 15:21:19 -0500 Subject: [PATCH 187/206] Start work on better diff --- .../cascadebot/data/database/DataHandler.java | 56 ++++++++++++++++++- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java index a32572d34..350ed01ee 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java @@ -1,5 +1,6 @@ package org.cascadebot.cascadebot.data.database; +import com.mongodb.client.model.Updates; import org.bson.BsonDocument; import org.bson.conversions.Bson; import org.cascadebot.cascadebot.utils.diff.Difference; @@ -17,11 +18,17 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Set; public class DataHandler { - public Y deepCopy(Y original) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, ClassNotFoundException { + public T deepCopy(T original) throws IOException, NoSuchFieldException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { + return deepCopyRec(original); + } + + private Y deepCopyRec(Y original) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException, IOException, ClassNotFoundException { if (original == null) { return null; } @@ -88,11 +95,54 @@ private void makeAccessible(Field field) throws NoSuchFieldException, IllegalAcc modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); } - /*public Difference diff(T original, T changed) { + public Bson diffUpdate(T original, T changed) { + List updates = new ArrayList<>(); + diffUpdateRec(original, changed, updates); + return Updates.combine(updates); + } + + private List diffUpdateRec(Y original, Y changed, List updates) { + if (original.getClass().isPrimitive()) { + + } else if (original.getClass().isArray()) { + throw new UnsupportedOperationException(); + } else if (original instanceof Map) { + Set> entrySetOrig = ((Map) original).entrySet(); + Set> entrySetChanged = ((Map) changed).entrySet(); + if (entrySetOrig.isEmpty() && entrySetChanged.isEmpty()) { + return updates; + } + + boolean stringKey; + if (!entrySetOrig.isEmpty()) { + Map.Entry entry = entrySetOrig.iterator().next(); + if (entry.getKey() instanceof String) { + stringKey = true; + } else { + stringKey = false; + } + } else { + Map.Entry entry = entrySetChanged.iterator().next(); + if (entry.getKey() instanceof String) { + stringKey = true; + } else { + stringKey = false; + } + } + + if (stringKey) { + // Update it as if it where an object + } else { + // Covert to an array, and then pass it back in to this method + } + } else if (original instanceof Collection) { + + } + return updates; } - public Bson getUpdate(Difference difference) { + /*public Bson getUpdate(Difference difference) { }*/ From 7f13247fd62ab0ce28e55e75e7b96e55a4fed840 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Fri, 13 Aug 2021 16:36:13 -0500 Subject: [PATCH 188/206] Allow custom comparator in CollectionDiff --- .../cascadebot/utils/lists/CollectionDiff.kt | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt index b1e0fefeb..dac6e0cb8 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/lists/CollectionDiff.kt @@ -7,7 +7,9 @@ package org.cascadebot.cascadebot.utils.lists import org.cascadebot.cascadebot.utils.diff.Diff -class CollectionDiff(originalList: Collection, newList: Collection): Diff { +class CollectionDiff(originalList: Collection, newList: Collection, comparator: Comparator?): Diff { + + constructor(originalList: Collection, newList: Collection): this(originalList, newList, null) private val _added: MutableList = ArrayList() @@ -30,9 +32,16 @@ class CollectionDiff(originalList: Collection, newList: Collection): Di for (item in originalList) { val iter = addedDiff.iterator() while (iter.hasNext()) { - if (iter.next() == item) { - iter.remove() - break + if (comparator == null) { + if (iter.next() == item) { + iter.remove() + break + } + } else { + if (comparator.compare(iter.next(), item) == 0) { + iter.remove() + break + } } } } @@ -44,9 +53,16 @@ class CollectionDiff(originalList: Collection, newList: Collection): Di for (item in newList) { val iter = removedDiff.iterator() while (iter.hasNext()) { - if (iter.next() == item) { - iter.remove() - break + if (comparator == null) { + if (iter.next() == item) { + iter.remove() + break + } + } else { + if (comparator.compare(iter.next(), item) == 0) { + iter.remove() + break + } } } } From 45018dac7faa3ae6284b353c9379cb760cc73e87 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Fri, 13 Aug 2021 17:16:38 -0500 Subject: [PATCH 189/206] More diff stuffs --- .../cascadebot/data/database/DataHandler.java | 45 ++++++++++++++----- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java index 350ed01ee..31676a2c4 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java @@ -4,6 +4,8 @@ import org.bson.BsonDocument; import org.bson.conversions.Bson; import org.cascadebot.cascadebot.utils.diff.Difference; +import org.cascadebot.cascadebot.utils.lists.ChangeList; +import org.cascadebot.cascadebot.utils.lists.CollectionDiff; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -41,14 +43,14 @@ private Y deepCopyRec(Y original) throws NoSuchMethodException, InvocationTa Map map = (Map) original; Map newMap = (Map) original.getClass().getDeclaredConstructor().newInstance(); for (Map.Entry entry : map.entrySet()) { - newMap.put(deepCopy(entry.getKey()), deepCopy(entry.getValue())); + newMap.put(deepCopyRec(entry.getKey()), deepCopyRec(entry.getValue())); } return (Y) newMap; } else if (original instanceof Collection) { Collection collection = (Collection) original; Collection newCol = (Collection) original.getClass().getDeclaredConstructor().newInstance(); for (Object obj : collection) { - newCol.add(deepCopy(obj)); + newCol.add(deepCopyRec(obj)); } return (Y) newCol; } else if (original instanceof Serializable) { @@ -75,7 +77,7 @@ private Y deepCopyRec(Y original) throws NoSuchMethodException, InvocationTa } field.setAccessible(true); Object fieldOrig = field.get(original); - Object copy = deepCopy(fieldOrig); + Object copy = deepCopyRec(fieldOrig); Field toEdit = obj.getClass().getDeclaredField(field.getName()); makeAccessible(toEdit); @@ -97,13 +99,17 @@ private void makeAccessible(Field field) throws NoSuchFieldException, IllegalAcc public Bson diffUpdate(T original, T changed) { List updates = new ArrayList<>(); - diffUpdateRec(original, changed, updates); + diffUpdateRec(original, changed, "", updates); return Updates.combine(updates); } - private List diffUpdateRec(Y original, Y changed, List updates) { + private List diffUpdateRec(Y original, Y changed, String path, List updates) { + if (original.equals(changed)) { + return updates; + } + String objPath = path.substring(0, path.lastIndexOf('.')); if (original.getClass().isPrimitive()) { - + // Trim last . off of path and then save } else if (original.getClass().isArray()) { throw new UnsupportedOperationException(); } else if (original instanceof Map) { @@ -131,19 +137,34 @@ private List diffUpdateRec(Y original, Y changed, List updates) } if (stringKey) { - // Update it as if it where an object + CollectionDiff diff = new CollectionDiff(entrySetOrig, entrySetChanged, Map.Entry.comparingByKey()); + for (Map.Entry added : diff.getAdded()) { + updates.add(Updates.set(path + added.getKey(), added.getValue())); + } + for (Map.Entry removed : diff.getRemoved()) { + updates.add(Updates.unset(path + removed.getKey())); + } + for (Map.Entry both : diff.getInBoth()) { + diffUpdateRec(((Map) original).get(both.getKey()), ((Map) changed).get(both.getKey()), path + both.getKey() + ".", updates); + } } else { - // Covert to an array, and then pass it back in to this method + diffUpdateRec(entrySetOrig, entrySetChanged, path, updates); } } else if (original instanceof Collection) { + updates.add(Updates.set(objPath, changed)); // TODO look into updating individual objects in array (UpdateOptions?) + /*CollectionDiff diff = new CollectionDiff((Collection)original, (Collection)changed); + for (Object added : diff.getAdded()) { + updates.add(Updates.set(objPath, added)); + } + for (Object removed : diff.getRemoved()) { + updates.add(Updates.) + }*/ + } else { + // TODO object } return updates; } - /*public Bson getUpdate(Difference difference) { - - }*/ - } From 372d4feaea76bf00885cdea3af63fefed25ecbd9 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Wed, 1 Sep 2021 12:11:45 -0500 Subject: [PATCH 190/206] Get change stream logic (mostly) worked out --- .../cascadebot/data/database/DataHandler.java | 151 ++++++++++++++++-- 1 file changed, 139 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java index 31676a2c4..53ae158e2 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java @@ -1,8 +1,13 @@ package org.cascadebot.cascadebot.data.database; import com.mongodb.client.model.Updates; +import com.mongodb.client.model.changestream.ChangeStreamDocument; +import com.mongodb.client.model.changestream.UpdateDescription; +import org.bson.BsonArray; import org.bson.BsonDocument; +import org.bson.BsonValue; import org.bson.conversions.Bson; +import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.utils.diff.Difference; import org.cascadebot.cascadebot.utils.lists.ChangeList; import org.cascadebot.cascadebot.utils.lists.CollectionDiff; @@ -72,6 +77,11 @@ private Y deepCopyRec(Y original) throws NoSuchMethodException, InvocationTa Y obj = (Y) constructor.newInstance(); for(Field field : original.getClass().getDeclaredFields()) { + /* TODO copy transient stuffs so we don't have to specifically copy those + Ideas: + - Store a map of the hashCodes encountered plus their copy and if we encounter the same one then use the copy from the map instead of diffing in order to avoid a stack overflow + - Look into how gson is able to create any object no matter what constructor it has + */ if (Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) { continue; } @@ -97,19 +107,22 @@ private void makeAccessible(Field field) throws NoSuchFieldException, IllegalAcc modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); } - public Bson diffUpdate(T original, T changed) { + public Bson diffUpdate(T original, T changed) throws NoSuchFieldException, IllegalAccessException { List updates = new ArrayList<>(); diffUpdateRec(original, changed, "", updates); return Updates.combine(updates); } - private List diffUpdateRec(Y original, Y changed, String path, List updates) { + private List diffUpdateRec(Y original, Y changed, String path, List updates) throws IllegalAccessException, NoSuchFieldException { + if (original == null) { + return updates; + } if (original.equals(changed)) { return updates; } String objPath = path.substring(0, path.lastIndexOf('.')); - if (original.getClass().isPrimitive()) { - // Trim last . off of path and then save + if (original.getClass().isPrimitive() || String.class.isAssignableFrom(original.getClass())) { + updates.add(Updates.set(objPath, changed)); } else if (original.getClass().isArray()) { throw new UnsupportedOperationException(); } else if (original instanceof Map) { @@ -152,19 +165,133 @@ private List diffUpdateRec(Y original, Y changed, String path, List changeStreamDocument, T original) throws NoSuchFieldException, IllegalAccessException { + if (changeStreamDocument.getFullDocument() != null) { + return changeStreamDocument.getFullDocument(); // TODO copy over transient + } else { + UpdateDescription updateDescription = changeStreamDocument.getUpdateDescription(); + T current = original; + if (updateDescription.getRemovedFields() != null) { + current = handleRemoved(updateDescription.getRemovedFields(), current); + } + if (updateDescription.getUpdatedFields() != null) { + current = handleUpdates(updateDescription.getUpdatedFields(), current); + } + return current; // TODO copy over transient + } + } + + private T handleRemoved(List removed, T original) throws NoSuchFieldException, IllegalAccessException { + for (String removedPath: removed) { + List path = List.of(removedPath.split("\\.")); + handleRemovedRec(original, path); + } + return original; + } - /*CollectionDiff diff = new CollectionDiff((Collection)original, (Collection)changed); - for (Object added : diff.getAdded()) { - updates.add(Updates.set(objPath, added)); + private void handleRemovedRec(Y currentObj, List path) throws NoSuchFieldException, IllegalAccessException { + if (path.size() == 1) { + removeItem(currentObj, path.get(0)); + } else { + String item = path.remove(0); + if (currentObj instanceof Map) { + handleRemovedRec(((Map) currentObj).get(item), path); + } else { + Field field = currentObj.getClass().getDeclaredField(item); + makeAccessible(field); + handleRemovedRec(field.get(currentObj), path); } - for (Object removed : diff.getRemoved()) { - updates.add(Updates.) - }*/ + } + } + + private void removeItem(Y obj, String item) throws NoSuchFieldException, IllegalAccessException { + // We only need to account for maps and objects as arrays are updated, never removed + if (obj instanceof Map) { + ((Map) obj).remove(item); } else { - // TODO object + Field field = obj.getClass().getDeclaredField(item); + makeAccessible(field); + field.set(obj, null); } + } - return updates; + private T handleUpdates(BsonDocument updates, T original) throws NoSuchFieldException, IllegalAccessException { + handleUpdatesRec(original, null, updates); + return original; + } + + private void handleUpdatesRec(Y currentObj, String currentItem, BsonValue currentValue) throws NoSuchFieldException, IllegalAccessException { + switch (currentValue.getBsonType()) { + case DOCUMENT: + if (currentObj instanceof Map) { + if (currentItem != null && !((Map) currentObj).containsKey(currentItem)) { + updateItem(currentObj, currentItem, currentValue); + } else { + for (Map.Entry entry: currentValue.asDocument().entrySet()) { + Object newObj = ((Map) currentObj).get(entry.getKey()); + handleUpdatesRec(newObj, entry.getKey(), entry.getValue()); + } + } + } else { + Field field = null; + if (currentItem != null) { + field = currentObj.getClass().getDeclaredField(currentItem); + makeAccessible(field); + } + if (field != null && field.get(currentObj) == null) { + updateItem(currentObj, currentItem, currentValue); + } else { + for (Map.Entry entry: currentValue.asDocument().entrySet()) { + Field field2 = currentObj.getClass().getDeclaredField(entry.getKey()); + makeAccessible(field2); + handleUpdatesRec(field2.get(currentObj), entry.getKey(), entry.getValue()); + } + } + } + break; + case ARRAY: + if (currentObj instanceof Map) { + Map map = new HashMap<>(); + for (BsonValue bsonValue: currentValue.asArray()) { + BsonDocument doc = bsonValue.asDocument(); + Object key = doc.get("key"); // TODO somehow get the key and value type from the map so we can convert it to java + Object value = doc.get("value"); + map.put(key, value); + // TODO replace map + } + } else { + updateArray(currentObj, currentItem, currentValue.asArray()); + } + break; + default: + updateItem(currentObj, currentItem, currentValue); + } + } + + private void updateItem(Y obj, String toSet, BsonValue currentValue) { + // Convert the item to java, and then update it depending on what obj is + } + + private void updateArray(Y obj, String toSet, BsonArray array) { + // Replace the array } } From aeb374d0b2fe64b30bdfa9e6690917941bcc7052 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 2 Sep 2021 10:35:27 -0500 Subject: [PATCH 191/206] Goodbye reflection Also copying over transient --- .../cascadebot/data/database/DataHandler.java | 123 +----------------- 1 file changed, 5 insertions(+), 118 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java index 53ae158e2..462116db7 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java @@ -6,10 +6,9 @@ import org.bson.BsonArray; import org.bson.BsonDocument; import org.bson.BsonValue; +import org.bson.codecs.DecoderContext; import org.bson.conversions.Bson; import org.cascadebot.cascadebot.CascadeBot; -import org.cascadebot.cascadebot.utils.diff.Difference; -import org.cascadebot.cascadebot.utils.lists.ChangeList; import org.cascadebot.cascadebot.utils.lists.CollectionDiff; import java.io.ByteArrayInputStream; @@ -22,6 +21,7 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -77,12 +77,10 @@ private Y deepCopyRec(Y original) throws NoSuchMethodException, InvocationTa Y obj = (Y) constructor.newInstance(); for(Field field : original.getClass().getDeclaredFields()) { - /* TODO copy transient stuffs so we don't have to specifically copy those - Ideas: - - Store a map of the hashCodes encountered plus their copy and if we encounter the same one then use the copy from the map instead of diffing in order to avoid a stack overflow - - Look into how gson is able to create any object no matter what constructor it has - */ if (Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) { + if (!Modifier.isStatic(field.getModifiers())) { + field.set(obj, field.get(original)); + } continue; } field.setAccessible(true); @@ -183,115 +181,4 @@ private List diffUpdateRec(Y original, Y changed, String path, List changeStreamDocument, T original) throws NoSuchFieldException, IllegalAccessException { - if (changeStreamDocument.getFullDocument() != null) { - return changeStreamDocument.getFullDocument(); // TODO copy over transient - } else { - UpdateDescription updateDescription = changeStreamDocument.getUpdateDescription(); - T current = original; - if (updateDescription.getRemovedFields() != null) { - current = handleRemoved(updateDescription.getRemovedFields(), current); - } - if (updateDescription.getUpdatedFields() != null) { - current = handleUpdates(updateDescription.getUpdatedFields(), current); - } - return current; // TODO copy over transient - } - } - - private T handleRemoved(List removed, T original) throws NoSuchFieldException, IllegalAccessException { - for (String removedPath: removed) { - List path = List.of(removedPath.split("\\.")); - handleRemovedRec(original, path); - } - return original; - } - - private void handleRemovedRec(Y currentObj, List path) throws NoSuchFieldException, IllegalAccessException { - if (path.size() == 1) { - removeItem(currentObj, path.get(0)); - } else { - String item = path.remove(0); - if (currentObj instanceof Map) { - handleRemovedRec(((Map) currentObj).get(item), path); - } else { - Field field = currentObj.getClass().getDeclaredField(item); - makeAccessible(field); - handleRemovedRec(field.get(currentObj), path); - } - } - } - - private void removeItem(Y obj, String item) throws NoSuchFieldException, IllegalAccessException { - // We only need to account for maps and objects as arrays are updated, never removed - if (obj instanceof Map) { - ((Map) obj).remove(item); - } else { - Field field = obj.getClass().getDeclaredField(item); - makeAccessible(field); - field.set(obj, null); - } - } - - private T handleUpdates(BsonDocument updates, T original) throws NoSuchFieldException, IllegalAccessException { - handleUpdatesRec(original, null, updates); - return original; - } - - private void handleUpdatesRec(Y currentObj, String currentItem, BsonValue currentValue) throws NoSuchFieldException, IllegalAccessException { - switch (currentValue.getBsonType()) { - case DOCUMENT: - if (currentObj instanceof Map) { - if (currentItem != null && !((Map) currentObj).containsKey(currentItem)) { - updateItem(currentObj, currentItem, currentValue); - } else { - for (Map.Entry entry: currentValue.asDocument().entrySet()) { - Object newObj = ((Map) currentObj).get(entry.getKey()); - handleUpdatesRec(newObj, entry.getKey(), entry.getValue()); - } - } - } else { - Field field = null; - if (currentItem != null) { - field = currentObj.getClass().getDeclaredField(currentItem); - makeAccessible(field); - } - if (field != null && field.get(currentObj) == null) { - updateItem(currentObj, currentItem, currentValue); - } else { - for (Map.Entry entry: currentValue.asDocument().entrySet()) { - Field field2 = currentObj.getClass().getDeclaredField(entry.getKey()); - makeAccessible(field2); - handleUpdatesRec(field2.get(currentObj), entry.getKey(), entry.getValue()); - } - } - } - break; - case ARRAY: - if (currentObj instanceof Map) { - Map map = new HashMap<>(); - for (BsonValue bsonValue: currentValue.asArray()) { - BsonDocument doc = bsonValue.asDocument(); - Object key = doc.get("key"); // TODO somehow get the key and value type from the map so we can convert it to java - Object value = doc.get("value"); - map.put(key, value); - // TODO replace map - } - } else { - updateArray(currentObj, currentItem, currentValue.asArray()); - } - break; - default: - updateItem(currentObj, currentItem, currentValue); - } - } - - private void updateItem(Y obj, String toSet, BsonValue currentValue) { - // Convert the item to java, and then update it depending on what obj is - } - - private void updateArray(Y obj, String toSet, BsonArray array) { - // Replace the array - } - } From bf8a2c4875f3539087f25d54344a37e8904c6ffe Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 2 Sep 2021 10:37:45 -0500 Subject: [PATCH 192/206] Remove legacy code --- .../org/cascadebot/cascadebot/CascadeBot.java | 184 +----------------- 1 file changed, 1 insertion(+), 183 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 68b73e17e..6592aa440 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -227,46 +227,7 @@ private void init() { GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()); } else if (guildDataChangeStreamDocument.getUpdateDescription() != null) { GuildData currentData = GuildDataManager.getGuildData(guildDataChangeStreamDocument.getDocumentKey().get("_id").asNumber().longValue()); - UpdateDescription updateDescription = guildDataChangeStreamDocument.getUpdateDescription(); - if (updateDescription.getUpdatedFields() != null) { - for (Map.Entry change : updateDescription.getUpdatedFields().entrySet()) { - try { - ReturnObject returnObject = getField(change.getKey(), currentData); - if (returnObject instanceof FieldReturnObject) { - FieldReturnObject fieldReturnObject = (FieldReturnObject) returnObject; - if (!updateGuildData(fieldReturnObject.getField(), fieldReturnObject.getCurrentObj(), bsonValueToJava(change.getValue(), fieldReturnObject.getField().getType()))) { - break; - } - } else if (returnObject instanceof SimpleMapReturnObject) { - SimpleMapReturnObject mapReturnObject = (SimpleMapReturnObject) returnObject; - mapReturnObject.getMap().put(mapReturnObject.getKey(), bsonValueToJava(change.getValue(), mapReturnObject.valueClass)); - } - - } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { - CascadeBot.LOGGER.error("Failed to update data", e); - break; - } - } - } - if (updateDescription.getRemovedFields() != null) { - for (String removed : updateDescription.getRemovedFields()) { - try { - ReturnObject returnObject = getField(removed, currentData); - if (returnObject instanceof FieldReturnObject) { - FieldReturnObject fieldReturnObject = (FieldReturnObject) returnObject; - if (!updateGuildData(fieldReturnObject.getField(), fieldReturnObject.getCurrentObj(), null)) { - break; - } - } else if (returnObject instanceof SimpleMapReturnObject) { - SimpleMapReturnObject mapReturnObject = (SimpleMapReturnObject) returnObject; - mapReturnObject.getMap().remove(mapReturnObject.getKey()); - } - } catch (NoSuchFieldException | IllegalAccessException e) { - CascadeBot.LOGGER.error("Failed to update data", e); - break; - } - } - } + } }, (result, throwable) -> { if (throwable != null) { @@ -348,149 +309,6 @@ private void init() { } - private boolean updateSimpleMapData(Map map, String key, Object bsonValueToJava) { - map.put(key, bsonValueToJava); - return true; - } - - public Object bsonValueToJava(BsonValue bsonValue, Class itemClass) throws ClassNotFoundException { - Object decode = null; - if (bsonValue.getBsonType().equals(BsonType.DOCUMENT)) { - decode = databaseManager.getCodecRegistry().get(itemClass).decode(bsonValue.asDocument().asBsonReader(), DecoderContext.builder().build()); - } else { - // This only handles primitives basically - if (int.class == itemClass && bsonValue.getBsonType().equals(BsonType.DOUBLE)) { // https://stackoverflow.com/questions/60809700/in-mongodb-integer-datatype-is-automatically-type-cast-to-doube - decode = ((Double) BsonUtils.toJavaType(bsonValue)).intValue(); - } else { - Object converted = BsonUtils.toJavaType(bsonValue); - - if (converted instanceof Object[]) { - Object[] objects = (Object[]) converted; - - Class type = null; - - Type collectionInterface = ReflectionHelper.findInterface(itemClass, Collection.class); - if (collectionInterface != null) { - if (collectionInterface instanceof ParameterizedType && !TypeUtils.containsTypeVariables(collectionInterface)) { - ParameterizedType parameterizedType = (ParameterizedType) collectionInterface; - type = (Class) parameterizedType.getActualTypeArguments()[0]; - } - } else if (itemClass.isArray()) { - type = itemClass.getComponentType(); - } - - if (type == null) { - throw new IllegalStateException(String.format("Cannot assign array to non-collection / non-array class \"%s\"", itemClass)); - } - - for (int i = 0; i < objects.length; i++) { - objects[i] = bsonValueToJava((BsonValue) objects[i], type); - } - - if (itemClass.isArray()) { - Object[] arrayOfXType = (Object[]) Array.newInstance(itemClass.getComponentType(), objects.length); - System.arraycopy(objects, 0, arrayOfXType, 0, objects.length); - decode = arrayOfXType; - } else if (itemClass.isAssignableFrom(Collection.class)) { - Collection collection = (Collection) converted; - collection.clear(); - collection.addAll(Arrays.asList(objects)); - decode = collection; - } - } - } - } - - if (decode == null) { - throw new IllegalStateException(String.format("Could not convert value to class \"%s\"", itemClass)); - } - - return decode; - } - - private List getGenericList(Class type, Object... params) { - List l = new ArrayList(); - for (int i = 0; i < params.length; i++) { - l.add((T) params[i]); - } - return l; - } - - public ReturnObject getField(String path, GuildData guildData) throws NoSuchFieldException, IllegalAccessException { - String[] split = path.split("\\."); - String last = split[split.length - 1]; - Object current = guildData; - for (String part : Arrays.copyOfRange(split, 0, split.length - 1)) { - if (TypeUtils.isAssignable(current.getClass(), Map.class)) { - current = ((Map) current).get(part); - } else { - Field field = current.getClass().getDeclaredField(part); - field.setAccessible(true); - current = field.get(current); - } - } - if (TypeUtils.isAssignable(current.getClass(), Map.class)) { - Type mapInterface = ReflectionHelper.findInterface(current.getClass(), Map.class); - if (mapInterface instanceof ParameterizedType && !TypeUtils.containsTypeVariables(mapInterface)) { - ParameterizedType parameterizedType = (ParameterizedType) mapInterface; - Class keyClass = (Class) parameterizedType.getActualTypeArguments()[0]; - Class valueClass = (Class) parameterizedType.getActualTypeArguments()[1]; - - if (keyClass == String.class) { - return new SimpleMapReturnObject((Map) current, last, valueClass); - } - } - } else { - return new FieldReturnObject(current, current.getClass().getDeclaredField(last)); - } - return null; - } - - interface ReturnObject { - - } - - @Getter - private static class FieldReturnObject implements ReturnObject { - - private final Object currentObj; - private final Field field; - - FieldReturnObject(Object currentObj, Field field) { - this.currentObj = currentObj; - this.field = field; - } - - } - - @Getter - private static class SimpleMapReturnObject implements ReturnObject { - - private final Map map; - private final String key; - private final Class valueClass; - - public SimpleMapReturnObject(Map map, String key, Class valueClass) { - this.map = map; - this.key = key; - this.valueClass = valueClass; - } - - } - - public boolean updateGuildData(Field field, Object current, Object newValue) { - try { - field.setAccessible(true); - Field modifiersField = Field.class.getDeclaredField("modifiers"); - modifiersField.setAccessible(true); - modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); - field.set(current, newValue); - } catch (NoSuchFieldException | IllegalAccessException e) { - CascadeBot.LOGGER.error("Failed to update guild data", e); - return false; - } - return true; - } private void setupTasks() { new Task("prune-players") { From 612df2087408dd38691ec9bc97581df11259712e Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 2 Sep 2021 13:23:50 -0500 Subject: [PATCH 193/206] Bson decoding on guild data --- .../org/cascadebot/cascadebot/CascadeBot.java | 2 +- .../cascadebot/data/database/BsonObject.java | 14 ++++++ .../data/objects/GuildPermissions.java | 2 - .../data/objects/GuildSettingsUseful.java | 10 ++++- .../cascadebot/data/objects/Tag.java | 2 - .../cascadebot/permissions/objects/Group.java | 2 - .../cascadebot/permissions/objects/User.java | 2 - .../cascadebot/data/objects/GuildData.kt | 45 ++++++++++++++++++- .../data/objects/GuildSettingsCore.kt | 8 +++- .../data/objects/GuildSettingsManagement.kt | 10 +++-- .../data/objects/GuildSettingsModeration.kt | 12 ++--- .../data/objects/GuildSettingsMusic.kt | 11 +++-- .../cascadebot/data/objects/TodoList.kt | 2 - .../utils/buttons/PersistentButtonGroup.kt | 12 ++++- 14 files changed, 107 insertions(+), 27 deletions(-) create mode 100644 src/main/java/org/cascadebot/cascadebot/data/database/BsonObject.java diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index 6592aa440..acf2a4c5b 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -227,7 +227,7 @@ private void init() { GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()); } else if (guildDataChangeStreamDocument.getUpdateDescription() != null) { GuildData currentData = GuildDataManager.getGuildData(guildDataChangeStreamDocument.getDocumentKey().get("_id").asNumber().longValue()); - + } }, (result, throwable) -> { if (throwable != null) { diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/BsonObject.java b/src/main/java/org/cascadebot/cascadebot/data/database/BsonObject.java new file mode 100644 index 000000000..25e0f4e64 --- /dev/null +++ b/src/main/java/org/cascadebot/cascadebot/data/database/BsonObject.java @@ -0,0 +1,14 @@ +package org.cascadebot.cascadebot.data.database; + +import org.bson.BsonDocument; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public interface BsonObject { + + void fromBson(@NotNull BsonDocument bsonDocument); + + //void handleRemove(@NotNull List paths); // TODO not list string + +} diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java index 7de4b42cc..41c1a5310 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java @@ -33,8 +33,6 @@ public class GuildPermissions { - - @Getter @Setter private PermissionMode mode = PermissionMode.MOST_RESTRICTIVE; diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java index fd62a3d28..479382714 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java @@ -1,6 +1,9 @@ package org.cascadebot.cascadebot.data.objects; +import org.bson.BsonDocument; import org.cascadebot.cascadebot.commandmeta.Module; +import org.cascadebot.cascadebot.data.database.BsonObject; +import org.jetbrains.annotations.NotNull; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -8,7 +11,7 @@ import static org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode; @SettingsContainer(module = Module.USEFUL) -public class GuildSettingsUseful { +public class GuildSettingsUseful implements BsonObject { private Map todoLists = new ConcurrentHashMap<>(); @@ -44,4 +47,9 @@ public TodoList getTodoListByMessage(long messageId) { } //endregion + @Override + public void fromBson(@NotNull BsonDocument bsonDocument) { + + } + } diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java index c3dd97b92..a6bdc926b 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java @@ -22,8 +22,6 @@ @AllArgsConstructor public class Tag extends PermissionObject { - - // https://regex101.com/r/hlsgVW/1 private static final Pattern TAG_PATTERN = Pattern.compile("\\{([A-z]+)(?::((?:,?\\w+)+))?}"); diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java index f2f8c4d55..b5cd65f68 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java @@ -23,8 +23,6 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class Group extends PermissionHolder { - - // Base 55 with 5 chars gives 503284375 combinations, we should be ok for uniqueness // This is normal alphanumeric with similar characters removed for less errors when inputting private String id = RandomStringUtils.random(5, "abcdefghijkmnopqrstuvwxyzACDEFHJKLMNPRSTUVWXYZ123467890"); diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java index 6126fec82..ff8ddc025 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java @@ -17,8 +17,6 @@ @EqualsAndHashCode(callSuper = true) public class User extends PermissionHolder { - - private final Set groups = Sets.newConcurrentHashSet(); public boolean addGroup(Group group) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index fa6e5bc2f..a29d71990 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -11,7 +11,10 @@ import de.bild.codec.annotations.Id import de.bild.codec.annotations.Transient import net.dv8tion.jda.api.entities.Message import net.dv8tion.jda.api.entities.MessageChannel +import org.bson.BsonArray +import org.bson.BsonDocument import org.cascadebot.cascadebot.CascadeBot +import org.cascadebot.cascadebot.data.database.BsonObject import org.cascadebot.cascadebot.data.language.Locale import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.music.CascadeLavalinkPlayer @@ -36,7 +39,7 @@ import java.util.concurrent.atomic.AtomicBoolean import java.util.function.Function import kotlin.concurrent.getOrSet -class GuildData(@field:Id val guildId: Long) { +class GuildData(@field:Id val guildId: Long): BsonObject { @Transient @kotlin.jvm.Transient @@ -179,6 +182,46 @@ class GuildData(@field:Id val guildId: Long) { } } + override fun fromBson(bsonDocument: BsonDocument) { + if (bsonDocument.contains("enabledFlags")) { + enabledFlags.clear(); + for (bsonFlag in bsonDocument["enabledFlags"]!!.asArray()) { + val flag: String = bsonFlag.asString().value + enabledFlags.add(Flag.valueOf(flag)) + } + } + if (bsonDocument.contains("mutedRoleId")) { + mutedRoleId = bsonDocument["mutedRoleId"]!!.asNumber().longValue(); + } + if (bsonDocument.contains("persistentButtons")) { + val buttons = bsonDocument["persistentButtons"]!!.asArray() + persistentButtons.clear() + for (entry in buttons) { + val channelId = entry.asDocument()["key"]!!.asNumber().longValue() + val messages = entry.asDocument()["value"]!!.asArray(); + val messageMap = HashMap() + for (message in messages) { + val messageId = message.asDocument()["key"]!!.asNumber().longValue() + val buttonObject = message.asDocument()["value"]!!.asDocument(); + val group = PersistentButtonGroup(buttonObject["ownerId"]!!.asNumber().longValue(), buttonObject["channelId"]!!.asNumber().longValue(), buttonObject["guildId"]!!.asNumber().longValue()) + group.fromBson(buttonObject); + messageMap[messageId] = group; + } + persistentButtons[channelId] = messageMap + } + } + val coreDoc = bsonDocument["core"]!!.asDocument(); + core.fromBson(coreDoc) + val usefulDoc = bsonDocument["useful"]!!.asDocument(); + useful.fromBson(usefulDoc) + val moderationDoc = bsonDocument["moderation"]!!.asDocument() + moderation.fromBson(moderationDoc) + val managementDoc = bsonDocument["management"]!!.asDocument() + management.fromBson(managementDoc) + val musicDoc = bsonDocument["music"]!!.asDocument() + music.fromBson(musicDoc) + } + } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt index e91469646..c7a46f649 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt @@ -1,10 +1,12 @@ package org.cascadebot.cascadebot.data.objects import com.google.common.collect.Sets +import org.bson.BsonDocument import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.commandmeta.MainCommand import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.Config +import org.cascadebot.cascadebot.data.database.BsonObject import org.cascadebot.cascadebot.data.language.Locale import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode import java.lang.UnsupportedOperationException @@ -12,7 +14,7 @@ import java.util.concurrent.ConcurrentHashMap @SettingsContainer(module = Module.CORE) -class GuildSettingsCore { +class GuildSettingsCore : BsonObject { @Setting var mentionPrefix = false @@ -140,4 +142,8 @@ class GuildSettingsCore { //endregion + override fun fromBson(bsonDocument: BsonDocument) { + + } + } \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt index 410f82079..96a6fef4e 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt @@ -1,12 +1,14 @@ package org.cascadebot.cascadebot.data.objects +import org.bson.BsonDocument import org.cascadebot.cascadebot.commandmeta.Module +import org.cascadebot.cascadebot.data.database.BsonObject import org.cascadebot.cascadebot.utils.GuildDataUtils import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode import java.util.concurrent.ConcurrentHashMap @SettingsContainer(module = Module.MANAGEMENT) -class GuildSettingsManagement { +class GuildSettingsManagement : BsonObject { @Setting var allowTagCommands = true @@ -17,8 +19,6 @@ class GuildSettingsManagement { @Setting var warnOver10Filters = true - - val tags: ConcurrentHashMap = ConcurrentHashMap() val filters: MutableList = mutableListOf() val permissions = GuildPermissions() @@ -44,4 +44,8 @@ class GuildSettingsManagement { return tags.remove(key) != null } + override fun fromBson(bsonDocument: BsonDocument) { + + } + } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index d9eeb7602..36d8803ae 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -10,8 +10,10 @@ import club.minnced.discord.webhook.send.WebhookMessageBuilder import de.bild.codec.annotations.Transient import net.dv8tion.jda.api.entities.Icon import net.dv8tion.jda.api.entities.TextChannel +import org.bson.BsonDocument import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.commandmeta.Module +import org.cascadebot.cascadebot.data.database.BsonObject import org.cascadebot.cascadebot.data.database.DebugLogCallback import org.cascadebot.cascadebot.data.language.Language import org.cascadebot.cascadebot.data.managers.GuildDataManager @@ -24,7 +26,7 @@ import java.util.Date import java.util.function.Consumer @SettingsContainer(module = Module.MODERATION) -class GuildSettingsModeration { +class GuildSettingsModeration : BsonObject { var writeMode = false @@ -39,8 +41,6 @@ class GuildSettingsModeration { @Setting var muteRoleName = "Muted" - - fun getRespectBanOrKickHierarchy(): Boolean { return respectBanOrKickHierarchy } @@ -138,8 +138,6 @@ class GuildSettingsModeration { class ChannelModlogEventsInfo { - - private val events: MutableSet = LinkedHashSet() internal var webhookId: Long = 0 internal var webhookToken: String = "" @@ -309,4 +307,8 @@ class GuildSettingsModeration { } } + override fun fromBson(bsonDocument: BsonDocument) { + + } + } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt index 4b3e54059..9fcd6ea53 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt @@ -1,13 +1,12 @@ package org.cascadebot.cascadebot.data.objects +import org.bson.BsonDocument import org.cascadebot.cascadebot.commandmeta.Module +import org.cascadebot.cascadebot.data.database.BsonObject import java.util.concurrent.ConcurrentHashMap @SettingsContainer(module = Module.MUSIC) -class GuildSettingsMusic { - - - +class GuildSettingsMusic : BsonObject { // TODO: Handle reverting tier for preserve settings @Setting var preserveVolume = true @@ -22,4 +21,8 @@ class GuildSettingsMusic { @Setting var joinOnPlay = true; + override fun fromBson(bsonDocument: BsonDocument) { + + } + } \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt index 43a17eb3f..1893357e9 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt @@ -16,8 +16,6 @@ import org.cascadebot.cascadebot.utils.buttons.PersistentButtonGroup class TodoList(val ownerId: Long) { - - val items: MutableList = ArrayList() var messageId: Long = -1 var channelId: Long = -1 diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButtonGroup.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButtonGroup.kt index 29a54ba19..eaeb8e526 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButtonGroup.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/buttons/PersistentButtonGroup.kt @@ -1,9 +1,11 @@ package org.cascadebot.cascadebot.utils.buttons +import org.bson.BsonDocument +import org.cascadebot.cascadebot.data.database.BsonObject import java.util.ArrayList import java.util.stream.Collectors -open class PersistentButtonGroup : ButtonGroup { +open class PersistentButtonGroup : ButtonGroup, BsonObject { private val persistentButtons: MutableList = ArrayList() private constructor() : super(-1, -1, -1) {} @@ -29,4 +31,12 @@ open class PersistentButtonGroup : ButtonGroup { persistentButtons.remove(persistentButton) super.removeButton(persistentButton.button) } + + override fun fromBson(bsonDocument: BsonDocument) { + // TODO maybe implement everything else? It's not really needed though as it's handled in guild data + for (button in bsonDocument["persistentButtons"]!!.asArray()) { + persistentButtons.add(PersistentButton.valueOf(button.asString().value)) + } + } + } From f223b4dba8edf5cad12ecc55e79857f2b3530f24 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 2 Sep 2021 13:32:25 -0500 Subject: [PATCH 194/206] Bson decoding of core settings --- .../data/objects/GuildSettingsCore.kt | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt index c7a46f649..707eace91 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt @@ -143,7 +143,42 @@ class GuildSettingsCore : BsonObject { //endregion override fun fromBson(bsonDocument: BsonDocument) { - + if (bsonDocument.contains("mentionPrefix")) { + mentionPrefix = bsonDocument["mentionPrefix"]!!.asBoolean().value + } + if (bsonDocument.contains("deleteCommand")) { + deleteCommand = bsonDocument["deleteCommand"]!!.asBoolean().value + } + if (bsonDocument.contains("useEmbedForMessages")) { + useEmbedForMessages = bsonDocument["useEmbedForMessages"]!!.asBoolean().value + } + if (bsonDocument.contains("showPermErrors")) { + showPermErrors = bsonDocument["showPermErrors"]!!.asBoolean().value + } + if (bsonDocument.contains("showModuleErrors")) { + showModuleErrors = bsonDocument["showModuleErrors"]!!.asBoolean().value + } + if (bsonDocument.contains("adminsHaveAllPerms")) { + adminsHaveAllPerms = bsonDocument["adminsHaveAllPerms"]!!.asBoolean().value + } + if (bsonDocument.contains("helpHideCommandsNoPermission")) { + helpHideCommandsNoPermission = bsonDocument["helpHideCommandsNoPermission"]!!.asBoolean().value + } + if (bsonDocument.contains("helpShowAllModules")) { + helpShowAllModules = bsonDocument["helpShowAllModules"]!!.asBoolean().value + } + if (bsonDocument.contains("locale")) { + locale = Locale.valueOf(bsonDocument["locale"]!!.asString().value) + } + if (bsonDocument.contains("prefix")) { + prefix = bsonDocument["prefix"]!!.asString().value + } + if (bsonDocument.contains("enabledModules")) { + enabledModules.clear(); + for(module in bsonDocument["enabledModules"]!!.asArray()) { + enabledModules.add(Module.valueOf(module.asString().value)) + } + } } } \ No newline at end of file From 094960c2bf7afd4c1fd6123b392d20c9ce740557 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 2 Sep 2021 13:35:07 -0500 Subject: [PATCH 195/206] Fix oversight in guild data --- .../cascadebot/data/objects/GuildData.kt | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index a29d71990..51945d15a 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -210,16 +210,26 @@ class GuildData(@field:Id val guildId: Long): BsonObject { persistentButtons[channelId] = messageMap } } - val coreDoc = bsonDocument["core"]!!.asDocument(); - core.fromBson(coreDoc) - val usefulDoc = bsonDocument["useful"]!!.asDocument(); - useful.fromBson(usefulDoc) - val moderationDoc = bsonDocument["moderation"]!!.asDocument() - moderation.fromBson(moderationDoc) - val managementDoc = bsonDocument["management"]!!.asDocument() - management.fromBson(managementDoc) - val musicDoc = bsonDocument["music"]!!.asDocument() - music.fromBson(musicDoc) + if (bsonDocument.contains("core")) { + val coreDoc = bsonDocument["core"]!!.asDocument(); + core.fromBson(coreDoc) + } + if (bsonDocument.contains("useful")) { + val usefulDoc = bsonDocument["useful"]!!.asDocument(); + useful.fromBson(usefulDoc) + } + if (bsonDocument.contains("moderation")) { + val moderationDoc = bsonDocument["moderation"]!!.asDocument() + moderation.fromBson(moderationDoc) + } + if (bsonDocument.contains("management")) { + val managementDoc = bsonDocument["management"]!!.asDocument() + management.fromBson(managementDoc) + } + if (bsonDocument.contains("music")) { + val musicDoc = bsonDocument["music"]!!.asDocument() + music.fromBson(musicDoc) + } } } From a1907c5c39bf781e25ba1f560ba4af9518466efe Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 2 Sep 2021 13:54:42 -0500 Subject: [PATCH 196/206] Bson decoding of useful settings --- .../data/objects/GuildSettingsUseful.java | 15 ++++++++++- .../cascadebot/data/objects/TodoList.kt | 25 ++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java index 479382714..0c4fed6b1 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java @@ -1,6 +1,7 @@ package org.cascadebot.cascadebot.data.objects; import org.bson.BsonDocument; +import org.bson.BsonValue; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.data.database.BsonObject; import org.jetbrains.annotations.NotNull; @@ -49,7 +50,19 @@ public TodoList getTodoListByMessage(long messageId) { @Override public void fromBson(@NotNull BsonDocument bsonDocument) { - + if (bsonDocument.containsKey("todoLists")) { + BsonDocument todoListBson = bsonDocument.get("todoLists").asDocument(); + for (Map.Entry entry : todoListBson.entrySet()) { + BsonDocument todoDoc = entry.getValue().asDocument(); + if (todoLists.containsKey(entry.getKey())) { + todoLists.get(entry.getKey()).fromBson(todoDoc); + } else { + TodoList todoList = new TodoList(todoDoc.get("ownerId").asNumber().longValue()); + todoList.fromBson(todoDoc); + todoLists.put(entry.getKey(), todoList); + } + } + } } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt index 1893357e9..ee2241dc4 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt @@ -4,9 +4,11 @@ import net.dv8tion.jda.api.entities.Member import net.dv8tion.jda.api.entities.Message import net.dv8tion.jda.api.entities.MessageEmbed import net.dv8tion.jda.api.entities.TextChannel +import org.bson.BsonDocument import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.UnicodeConstants import org.cascadebot.cascadebot.commandmeta.CommandContext +import org.cascadebot.cascadebot.data.database.BsonObject import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.messaging.Messaging.sendButtonedMessage import org.cascadebot.cascadebot.messaging.MessagingObjects @@ -14,7 +16,7 @@ import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode import org.cascadebot.cascadebot.utils.buttons.PersistentButton import org.cascadebot.cascadebot.utils.buttons.PersistentButtonGroup -class TodoList(val ownerId: Long) { +class TodoList(val ownerId: Long) : BsonObject { val items: MutableList = ArrayList() var messageId: Long = -1 @@ -168,4 +170,25 @@ class TodoList(val ownerId: Long) { embedBuilder.appendDescription(pageBuilder.toString()) return embedBuilder.build() } + + override fun fromBson(bsonDocument: BsonDocument) { + if (bsonDocument.contains("channelId")) { + channelId = bsonDocument["channelId"]!!.asNumber().longValue() + } + if (bsonDocument.contains("messageId")) { + messageId = bsonDocument["messageId"]!!.asNumber().longValue() + } + if (bsonDocument.contains("currentItem")) { + currentItem = bsonDocument["currentItem"]!!.asNumber().intValue() + } + if (bsonDocument.contains("items")) { + items.clear(); + for (item in bsonDocument["items"]!!.asArray()) { + val todoItem = TodoListItem(item.asDocument()["text"]!!.asString().value) + todoItem.done = item.asDocument()["done"]!!.asBoolean().value + items.add(todoItem) + } + } + CascadeBot.INS.client.getTextChannelById(channelId)!!.editMessageById(messageId, todoListMessage).queue() + } } From a096143cb92b5804fe12a4c42510bab546f10a7c Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 2 Sep 2021 14:19:16 -0500 Subject: [PATCH 197/206] Bson decoding of moderation settings Co-authored-by: binaryoverload --- .../data/objects/GuildSettingsModeration.kt | 50 ++++++++++++++++--- .../cascadebot/cascadebot/utils/BsonUtils.kt | 10 ++++ 2 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/utils/BsonUtils.kt diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 36d8803ae..76193eced 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -19,6 +19,7 @@ import org.cascadebot.cascadebot.data.language.Language import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode +import org.cascadebot.cascadebot.utils.ifContains import org.cascadebot.cascadebot.utils.toCapitalized import java.net.URL import java.time.Instant @@ -28,15 +29,13 @@ import java.util.function.Consumer @SettingsContainer(module = Module.MODERATION) class GuildSettingsModeration : BsonObject { - var writeMode = false - var modlogChannelNum: Int = 1; @Setting - val purgePinnedMessages: Boolean = false + var purgePinnedMessages: Boolean = false @Setting - private val respectBanOrKickHierarchy = true + private var respectBanOrKickHierarchy = true @Setting var muteRoleName = "Muted" @@ -136,7 +135,7 @@ class GuildSettingsModeration : BsonObject { } } - class ChannelModlogEventsInfo { + class ChannelModlogEventsInfo : BsonObject { private val events: MutableSet = LinkedHashSet() internal var webhookId: Long = 0 @@ -305,10 +304,49 @@ class GuildSettingsModeration : BsonObject { } } + + override fun fromBson(bsonDocument: BsonDocument) { + bsonDocument.ifContains("events") { + events.clear() + for (event in it.asArray()) { + events.add(ModlogEvent.valueOf(event.asString().value)) + } + } + bsonDocument.ifContains("webhookId") { + webhookId = it.asNumber().longValue() + } + bsonDocument.ifContains("webhookToken") { + webhookToken = it.asString().value + } + bsonDocument.ifContains("id") { + id = it.asNumber().intValue() + } + } } override fun fromBson(bsonDocument: BsonDocument) { - + bsonDocument.ifContains("modlogChannelNum") { + modlogChannelNum = it.asNumber().intValue() + } + bsonDocument.ifContains("purgePinnedMessages") { + purgePinnedMessages = it.asBoolean().value + } + bsonDocument.ifContains("respectBanOrKickHierarchy") { + respectBanOrKickHierarchy = it.asBoolean().value + } + bsonDocument.ifContains("muteRoleName") { + muteRoleName = it.asString().value + } + bsonDocument.ifContains("modlogEvents") { + for (entry in it.asDocument()) { + if (modlogEvents.containsKey(entry.key)) { + modlogEvents[entry.key]!!.fromBson(entry.value.asDocument()) + } else { + val eventInfo = ChannelModlogEventsInfo() + eventInfo.fromBson(entry.value.asDocument()) + } + } + } } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/BsonUtils.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/BsonUtils.kt new file mode 100644 index 000000000..7d95007b0 --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/BsonUtils.kt @@ -0,0 +1,10 @@ +package org.cascadebot.cascadebot.utils + +import org.bson.BsonDocument +import org.bson.BsonValue + +fun BsonDocument.ifContains(key: String, consumer: (BsonValue)->Unit) { + if (this.containsKey(key)) { + consumer(this[key]!!) + } +} \ No newline at end of file From 361c55fa6ab0914241b78b38049c08ad4262b5a4 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 2 Sep 2021 15:17:06 -0500 Subject: [PATCH 198/206] Bson decoding of management settings Co-authored-by: binaryoverload --- .../data/objects/GuildPermissions.java | 32 +++++++++++- .../cascadebot/data/objects/Tag.java | 18 ++++++- .../cascadebot/permissions/objects/Group.java | 23 ++++++++- .../permissions/objects/PermissionHolder.java | 15 +++++- .../cascadebot/permissions/objects/User.java | 16 +++++- .../cascadebot/data/objects/CommandFilter.kt | 45 ++++++++++++++-- .../cascadebot/data/objects/Greetings.kt | 35 +++++++++++-- .../cascadebot/data/objects/GuildData.kt | 47 ++++++----------- .../data/objects/GuildSettingsCore.kt | 51 +++++++------------ .../data/objects/GuildSettingsManagement.kt | 45 +++++++++++++++- .../data/objects/GuildSettingsModeration.kt | 29 +++++------ .../cascadebot/cascadebot/utils/BsonUtils.kt | 37 ++++++++++++++ 12 files changed, 300 insertions(+), 93 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java index 41c1a5310..6e745e7ae 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java @@ -11,14 +11,19 @@ import net.dv8tion.jda.api.entities.GuildChannel; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.internal.utils.Checks; +import org.bson.BsonDocument; +import org.bson.BsonValue; import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.Environment; +import org.cascadebot.cascadebot.data.database.BsonObject; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.Security; import org.cascadebot.cascadebot.permissions.objects.Group; import org.cascadebot.cascadebot.permissions.objects.Result; import org.cascadebot.cascadebot.permissions.objects.User; +import org.cascadebot.cascadebot.utils.BsonUtilsKt; import org.cascadebot.shared.SecurityLevel; +import org.jetbrains.annotations.NotNull; import spark.utils.CollectionUtils; import java.util.ArrayList; @@ -31,7 +36,7 @@ import static org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode; -public class GuildPermissions { +public class GuildPermissions implements BsonObject { @Getter @Setter @@ -227,4 +232,29 @@ public void moveGroup(Group group, int position) throws IndexOutOfBoundsExceptio groups.add(position, group); } + @Override + public void fromBson(@NotNull BsonDocument bsonDocument) { + if (bsonDocument.containsKey("mode")) { + mode = PermissionMode.valueOf(bsonDocument.get("mode").asString().getValue()); + } + if (bsonDocument.containsKey("groups")) { + groups.clear(); + for (BsonValue bsonGroup : bsonDocument.get("groups").asArray()) { + BsonDocument doc = bsonGroup.asDocument(); + Group group = new Group(doc.get("name").asString().getValue()); + group.fromBson(doc); + } + } + if (bsonDocument.containsKey("users")) { + users.clear(); + for (BsonValue entry : bsonDocument.get("users").asArray()) { + BsonDocument doc = entry.asDocument(); + long id = doc.get("key").asNumber().longValue(); + BsonDocument userDoc = doc.get("value").asDocument(); + User user = new User(); + user.fromBson(userDoc); + users.put(id, user); + } + } + } } diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java index a6bdc926b..99ad99948 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java @@ -10,9 +10,12 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import org.bson.BsonDocument; import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; +import org.cascadebot.cascadebot.data.database.BsonObject; import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects; +import org.jetbrains.annotations.NotNull; import java.util.regex.Pattern; @@ -20,7 +23,7 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) @AllArgsConstructor -public class Tag extends PermissionObject { +public class Tag extends PermissionObject implements BsonObject { // https://regex101.com/r/hlsgVW/1 private static final Pattern TAG_PATTERN = Pattern.compile("\\{([A-z]+)(?::((?:,?\\w+)+))?}"); @@ -74,4 +77,17 @@ public void setName(String name) { assertWriteMode(); this.name = name; } + + @Override + public void fromBson(@NotNull BsonDocument bsonDocument) { + if (bsonDocument.containsKey("name")) { + name = bsonDocument.get("name").asString().getValue(); + } + if (bsonDocument.containsKey("content")) { + content = bsonDocument.get("content").asString().getValue(); + } + if (bsonDocument.containsKey("category")) { + category = bsonDocument.get("category").asString().getValue(); + } + } } \ No newline at end of file diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java index b5cd65f68..a49d17060 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java @@ -13,6 +13,10 @@ import lombok.Setter; import lombok.ToString; import org.apache.commons.lang3.RandomStringUtils; +import org.bson.BsonDocument; +import org.bson.BsonValue; +import org.cascadebot.cascadebot.data.database.BsonObject; +import org.jetbrains.annotations.NotNull; import java.util.Set; @@ -21,7 +25,7 @@ @ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) @NoArgsConstructor(access = AccessLevel.PRIVATE) -public class Group extends PermissionHolder { +public class Group extends PermissionHolder implements BsonObject { // Base 55 with 5 chars gives 503284375 combinations, we should be ok for uniqueness // This is normal alphanumeric with similar characters removed for less errors when inputting @@ -66,4 +70,21 @@ public void setName(String name) { assertWriteMode(); this.name = name; } + + @Override + public void fromBson(@NotNull BsonDocument bsonDocument) { + if (bsonDocument.containsKey("id")) { + id = bsonDocument.get("id").asString().getValue(); + } + if (bsonDocument.containsKey("name")) { + name = bsonDocument.get("name").asString().getValue(); + } + if (bsonDocument.containsKey("roleIds")) { + roleIds.clear(); + for (BsonValue idBson : bsonDocument.get("roleIds").asArray()) { + roleIds.add(idBson.asNumber().longValue()); + } + } + super.fromBson(bsonDocument); + } } diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/PermissionHolder.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/PermissionHolder.java index ccffdd89c..23a05275c 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/PermissionHolder.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/PermissionHolder.java @@ -3,9 +3,13 @@ import com.google.common.collect.Sets; import lombok.EqualsAndHashCode; import lombok.ToString; +import org.bson.BsonDocument; +import org.bson.BsonValue; +import org.cascadebot.cascadebot.data.database.BsonObject; import org.cascadebot.cascadebot.data.objects.PermissionAction; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.PermissionNode; +import org.jetbrains.annotations.NotNull; import java.util.Set; @@ -13,7 +17,7 @@ @ToString @EqualsAndHashCode -public abstract class PermissionHolder { +public abstract class PermissionHolder implements BsonObject { private Set permissions = Sets.newConcurrentHashSet(); @@ -48,4 +52,13 @@ enum HolderType { GROUP, USER } + @Override + public void fromBson(@NotNull BsonDocument bsonDocument) { + if (bsonDocument.containsKey("permissions")) { + permissions.clear(); + for (BsonValue permBson : bsonDocument.get("permissions").asArray()) { + permissions.add(permBson.asString().getValue()); + } + } + } } diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java index ff8ddc025..5cfc52469 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java @@ -8,6 +8,10 @@ import com.google.common.collect.Sets; import lombok.EqualsAndHashCode; import lombok.ToString; +import org.bson.BsonDocument; +import org.bson.BsonValue; +import org.cascadebot.cascadebot.data.database.BsonObject; +import org.jetbrains.annotations.NotNull; import java.util.Set; @@ -15,7 +19,7 @@ @ToString(callSuper = true) @EqualsAndHashCode(callSuper = true) -public class User extends PermissionHolder { +public class User extends PermissionHolder implements BsonObject { private final Set groups = Sets.newConcurrentHashSet(); @@ -38,4 +42,14 @@ HolderType getType() { return HolderType.USER; } + @Override + public void fromBson(@NotNull BsonDocument bsonDocument) { + if (bsonDocument.containsKey("groups")) { + groups.clear(); + for (BsonValue groupBson : bsonDocument.get("groups").asArray()) { + groups.add(groupBson.asString().getValue()); + } + } + super.fromBson(bsonDocument); + } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt index 447e740f3..1a2f99263 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt @@ -9,19 +9,22 @@ import net.dv8tion.jda.api.EmbedBuilder import net.dv8tion.jda.api.entities.Member import net.dv8tion.jda.api.entities.Role import net.dv8tion.jda.api.entities.TextChannel +import org.bson.BsonDocument import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.data.Config +import org.cascadebot.cascadebot.data.database.BsonObject import org.cascadebot.cascadebot.data.language.Language import org.cascadebot.cascadebot.data.language.Locale import org.cascadebot.cascadebot.messaging.MessageType import org.cascadebot.cascadebot.messaging.embed +import org.cascadebot.cascadebot.utils.ifContainsArray +import org.cascadebot.cascadebot.utils.ifContainsBoolean +import org.cascadebot.cascadebot.utils.ifContainsString import org.cascadebot.cascadebot.utils.language.LanguageUtils import org.cascadebot.cascadebot.utils.toCapitalized import java.util.Collections -class CommandFilter(val name: String) { - - +class CommandFilter(val name: String) : BsonObject { // Constructor for MongoDB private constructor() : this("") @@ -197,4 +200,40 @@ class CommandFilter(val name: String) { MATCH, NOT_MATCH, NEUTRAL } + override fun fromBson(bsonDocument: BsonDocument) { + bsonDocument.ifContainsString("type") { + type = FilterType.valueOf(it) + } + bsonDocument.ifContainsString("operator") { + operator = FilterOperator.valueOf(it) + } + bsonDocument.ifContainsBoolean("enabled") { + enabled = it + } + bsonDocument.ifContainsArray("commands") { + commands.clear() + for (commandBson in it) { + commands.add(commandBson.asString().value) + } + } + bsonDocument.ifContainsArray("channelIds") { + channelIds.clear() + for (idBson in it) { + channelIds.add(idBson.asNumber().longValue()) + } + } + bsonDocument.ifContainsArray("userIds") { + userIds.clear() + for (idBson in it) { + userIds.add(idBson.asNumber().longValue()) + } + } + bsonDocument.ifContainsArray("roleIds") { + roleIds.clear() + for (idBson in it) { + roleIds.add(idBson.asNumber().longValue()) + } + } + } + } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt index 1155cefc0..8630e338d 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt @@ -3,14 +3,16 @@ package org.cascadebot.cascadebot.data.objects import net.dv8tion.jda.api.entities.TextChannel import net.dv8tion.jda.api.events.guild.member.GuildMemberJoinEvent import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent +import org.bson.BsonDocument import org.cascadebot.cascadebot.CascadeBot +import org.cascadebot.cascadebot.data.database.BsonObject import org.cascadebot.cascadebot.data.language.Language +import org.cascadebot.cascadebot.utils.ifContainsDocument +import org.cascadebot.cascadebot.utils.ifContainsLong import org.cascadebot.cascadebot.utils.lists.WeightedList import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects -class Greetings { - - +class Greetings : BsonObject { var welcomeMessages: WeightedList = WeightedList() var welcomeDMMessages: WeightedList = WeightedList() @@ -51,5 +53,32 @@ class Greetings { } } + override fun fromBson(bsonDocument: BsonDocument) { + bsonDocument.ifContainsDocument("welcomeMessages") { + welcomeMessages = WeightedList(it["seed"]?.asNumber()?.longValue()) + for (itemBson in it["internalList"]!!.asArray()) { + val doc = itemBson.asDocument() + welcomeMessages.add(doc["item"]!!.asString().value, doc["weight"]!!.asNumber().intValue()) + } + } + bsonDocument.ifContainsDocument("welcomeDMMessages") { + welcomeMessages = WeightedList(it["seed"]?.asNumber()?.longValue()) + for (itemBson in it["internalList"]!!.asArray()) { + val doc = itemBson.asDocument() + welcomeMessages.add(doc["item"]!!.asString().value, doc["weight"]!!.asNumber().intValue()) + } + } + bsonDocument.ifContainsDocument("goodbyeMessages") { + welcomeMessages = WeightedList(it["seed"]?.asNumber()?.longValue()) + for (itemBson in it["internalList"]!!.asArray()) { + val doc = itemBson.asDocument() + welcomeMessages.add(doc["item"]!!.asString().value, doc["weight"]!!.asNumber().intValue()) + } + } + bsonDocument.ifContainsLong("welcomeChannelId") { + welcomeChannelId = it + } + } + } \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 51945d15a..7244c62ba 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -35,6 +35,10 @@ import kotlin.concurrent.withLock import kotlin.reflect.jvm.javaType import kotlin.reflect.typeOf import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode +import org.cascadebot.cascadebot.utils.ifContains +import org.cascadebot.cascadebot.utils.ifContainsArray +import org.cascadebot.cascadebot.utils.ifContainsDocument +import org.cascadebot.cascadebot.utils.ifContainsLong import java.util.concurrent.atomic.AtomicBoolean import java.util.function.Function import kotlin.concurrent.getOrSet @@ -183,20 +187,16 @@ class GuildData(@field:Id val guildId: Long): BsonObject { } override fun fromBson(bsonDocument: BsonDocument) { - if (bsonDocument.contains("enabledFlags")) { + bsonDocument.ifContainsArray("enabledFlags") { array -> enabledFlags.clear(); - for (bsonFlag in bsonDocument["enabledFlags"]!!.asArray()) { - val flag: String = bsonFlag.asString().value - enabledFlags.add(Flag.valueOf(flag)) - } - } - if (bsonDocument.contains("mutedRoleId")) { - mutedRoleId = bsonDocument["mutedRoleId"]!!.asNumber().longValue(); + array.map { it.asString().value } + .map { Flag.valueOf(it) } + .forEach { enabledFlags.add(it) } } - if (bsonDocument.contains("persistentButtons")) { - val buttons = bsonDocument["persistentButtons"]!!.asArray() + bsonDocument.ifContainsLong("mutedRoleId") { mutedRoleId = it } + bsonDocument.ifContainsArray("persistentButtons") { persistentButtons.clear() - for (entry in buttons) { + for (entry in it) { val channelId = entry.asDocument()["key"]!!.asNumber().longValue() val messages = entry.asDocument()["value"]!!.asArray(); val messageMap = HashMap() @@ -210,26 +210,11 @@ class GuildData(@field:Id val guildId: Long): BsonObject { persistentButtons[channelId] = messageMap } } - if (bsonDocument.contains("core")) { - val coreDoc = bsonDocument["core"]!!.asDocument(); - core.fromBson(coreDoc) - } - if (bsonDocument.contains("useful")) { - val usefulDoc = bsonDocument["useful"]!!.asDocument(); - useful.fromBson(usefulDoc) - } - if (bsonDocument.contains("moderation")) { - val moderationDoc = bsonDocument["moderation"]!!.asDocument() - moderation.fromBson(moderationDoc) - } - if (bsonDocument.contains("management")) { - val managementDoc = bsonDocument["management"]!!.asDocument() - management.fromBson(managementDoc) - } - if (bsonDocument.contains("music")) { - val musicDoc = bsonDocument["music"]!!.asDocument() - music.fromBson(musicDoc) - } + bsonDocument.ifContainsDocument("core") { core.fromBson(it) } + bsonDocument.ifContainsDocument("useful") { useful.fromBson(it) } + bsonDocument.ifContainsDocument("moderation") { moderation.fromBson(it) } + bsonDocument.ifContainsDocument("management") { management.fromBson(it) } + bsonDocument.ifContainsDocument("music") { music.fromBson(it) } } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt index 707eace91..24435f3fb 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt @@ -9,6 +9,9 @@ import org.cascadebot.cascadebot.data.Config import org.cascadebot.cascadebot.data.database.BsonObject import org.cascadebot.cascadebot.data.language.Locale import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode +import org.cascadebot.cascadebot.utils.ifContainsArray +import org.cascadebot.cascadebot.utils.ifContainsBoolean +import org.cascadebot.cascadebot.utils.ifContainsString import java.lang.UnsupportedOperationException import java.util.concurrent.ConcurrentHashMap @@ -143,41 +146,21 @@ class GuildSettingsCore : BsonObject { //endregion override fun fromBson(bsonDocument: BsonDocument) { - if (bsonDocument.contains("mentionPrefix")) { - mentionPrefix = bsonDocument["mentionPrefix"]!!.asBoolean().value - } - if (bsonDocument.contains("deleteCommand")) { - deleteCommand = bsonDocument["deleteCommand"]!!.asBoolean().value - } - if (bsonDocument.contains("useEmbedForMessages")) { - useEmbedForMessages = bsonDocument["useEmbedForMessages"]!!.asBoolean().value - } - if (bsonDocument.contains("showPermErrors")) { - showPermErrors = bsonDocument["showPermErrors"]!!.asBoolean().value - } - if (bsonDocument.contains("showModuleErrors")) { - showModuleErrors = bsonDocument["showModuleErrors"]!!.asBoolean().value - } - if (bsonDocument.contains("adminsHaveAllPerms")) { - adminsHaveAllPerms = bsonDocument["adminsHaveAllPerms"]!!.asBoolean().value - } - if (bsonDocument.contains("helpHideCommandsNoPermission")) { - helpHideCommandsNoPermission = bsonDocument["helpHideCommandsNoPermission"]!!.asBoolean().value - } - if (bsonDocument.contains("helpShowAllModules")) { - helpShowAllModules = bsonDocument["helpShowAllModules"]!!.asBoolean().value - } - if (bsonDocument.contains("locale")) { - locale = Locale.valueOf(bsonDocument["locale"]!!.asString().value) - } - if (bsonDocument.contains("prefix")) { - prefix = bsonDocument["prefix"]!!.asString().value - } - if (bsonDocument.contains("enabledModules")) { + bsonDocument.ifContainsBoolean("mentionPrefix") { mentionPrefix = it } + bsonDocument.ifContainsBoolean("deleteCommand") { deleteCommand = it } + bsonDocument.ifContainsBoolean("useEmbedForMessages") { useEmbedForMessages = it } + bsonDocument.ifContainsBoolean("showPermErrors") { showPermErrors = it } + bsonDocument.ifContainsBoolean("showModuleErrors") { showModuleErrors = it } + bsonDocument.ifContainsBoolean("adminsHaveAllPerms") { adminsHaveAllPerms = it } + bsonDocument.ifContainsBoolean("helpHideCommandsNoPermission") { helpHideCommandsNoPermission = it } + bsonDocument.ifContainsBoolean("helpShowAllModules") { helpShowAllModules = it } + bsonDocument.ifContainsString("locale") { locale = Locale.valueOf(it) } + bsonDocument.ifContainsString("prefix") { prefix = it } + bsonDocument.ifContainsArray("enabledModules") { array -> enabledModules.clear(); - for(module in bsonDocument["enabledModules"]!!.asArray()) { - enabledModules.add(Module.valueOf(module.asString().value)) - } + array.map{ it.asString().value } // Convert each array value to a string + .map { string -> Module.valueOf(string) } // Map each value to a Module enum + .forEach { enabledModules.add(it) } } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt index 96a6fef4e..b32684e54 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt @@ -5,6 +5,9 @@ import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.database.BsonObject import org.cascadebot.cascadebot.utils.GuildDataUtils import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode +import org.cascadebot.cascadebot.utils.ifContains +import org.cascadebot.cascadebot.utils.ifContainsArray +import org.cascadebot.cascadebot.utils.ifContainsDocument import java.util.concurrent.ConcurrentHashMap @SettingsContainer(module = Module.MANAGEMENT) @@ -45,7 +48,47 @@ class GuildSettingsManagement : BsonObject { } override fun fromBson(bsonDocument: BsonDocument) { - + bsonDocument.ifContains("allowTagCommands") { + allowTagCommands = it.asBoolean().value + } + bsonDocument.ifContains("displayFilterError") { + displayFilterError = it.asBoolean().value + } + bsonDocument.ifContains("warnOver10Filters") { + warnOver10Filters = it.asBoolean().value + } + bsonDocument.ifContainsDocument("tags") { + for (entry in it) { + if (tags.contains(entry.key)) { + tags[entry.key]!!.fromBson(entry.value.asDocument()) + } else { + val doc = entry.value.asDocument() + val tag = Tag(doc["name"]!!.asString().value, doc["content"]!!.asString().value, doc["category"]!!.asString().value) + tags[entry.key] = tag + } + } + } + bsonDocument.ifContainsArray("filters") { + filters.clear() + for (bsonFilter in it) { + val doc = it.asDocument() + val filer = CommandFilter(doc["name"]!!.asString().value) + filer.fromBson(doc) + filters.add(filer) + } + } + bsonDocument.ifContainsDocument("permissions") { + permissions.fromBson(it) + } + bsonDocument.ifContainsDocument("greetings") { + greetings.fromBson(it) + } + bsonDocument.ifContainsArray("autoRoles") { + autoRoles.clear() + for (bsonRole in it) { + autoRoles.add(bsonRole.asNumber().longValue()) + } + } } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 76193eced..5168d5ab1 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -20,6 +20,11 @@ import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.moderation.ModlogEvent import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode import org.cascadebot.cascadebot.utils.ifContains +import org.cascadebot.cascadebot.utils.ifContainsArray +import org.cascadebot.cascadebot.utils.ifContainsBoolean +import org.cascadebot.cascadebot.utils.ifContainsDocument +import org.cascadebot.cascadebot.utils.ifContainsInt +import org.cascadebot.cascadebot.utils.ifContainsString import org.cascadebot.cascadebot.utils.toCapitalized import java.net.URL import java.time.Instant @@ -306,9 +311,9 @@ class GuildSettingsModeration : BsonObject { } override fun fromBson(bsonDocument: BsonDocument) { - bsonDocument.ifContains("events") { + bsonDocument.ifContainsArray("events") { events.clear() - for (event in it.asArray()) { + for (event in it) { events.add(ModlogEvent.valueOf(event.asString().value)) } } @@ -325,20 +330,12 @@ class GuildSettingsModeration : BsonObject { } override fun fromBson(bsonDocument: BsonDocument) { - bsonDocument.ifContains("modlogChannelNum") { - modlogChannelNum = it.asNumber().intValue() - } - bsonDocument.ifContains("purgePinnedMessages") { - purgePinnedMessages = it.asBoolean().value - } - bsonDocument.ifContains("respectBanOrKickHierarchy") { - respectBanOrKickHierarchy = it.asBoolean().value - } - bsonDocument.ifContains("muteRoleName") { - muteRoleName = it.asString().value - } - bsonDocument.ifContains("modlogEvents") { - for (entry in it.asDocument()) { + bsonDocument.ifContainsInt("modlogChannelNum") { modlogChannelNum = it } + bsonDocument.ifContainsBoolean("purgePinnedMessages") { purgePinnedMessages = it } + bsonDocument.ifContainsBoolean("respectBanOrKickHierarchy") { respectBanOrKickHierarchy = it } + bsonDocument.ifContainsString("muteRoleName") { muteRoleName = it } + bsonDocument.ifContainsDocument("modlogEvents") { + for (entry in it) { if (modlogEvents.containsKey(entry.key)) { modlogEvents[entry.key]!!.fromBson(entry.value.asDocument()) } else { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/BsonUtils.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/BsonUtils.kt index 7d95007b0..732cf93aa 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/utils/BsonUtils.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/BsonUtils.kt @@ -1,5 +1,6 @@ package org.cascadebot.cascadebot.utils +import org.bson.BsonArray import org.bson.BsonDocument import org.bson.BsonValue @@ -7,4 +8,40 @@ fun BsonDocument.ifContains(key: String, consumer: (BsonValue)->Unit) { if (this.containsKey(key)) { consumer(this[key]!!) } +} + +fun BsonDocument.ifContainsArray(key: String, consumer: (BsonArray)->Unit) { + if (this.containsKey(key) && this[key]!!.isArray) { + consumer(this[key]!!.asArray()!!) + } +} + +fun BsonDocument.ifContainsDocument(key: String, consumer: (BsonDocument)->Unit) { + if (this.containsKey(key) && this[key]!!.isDocument) { + consumer(this[key]!!.asDocument()!!) + } +} + +fun BsonDocument.ifContainsBoolean(key: String, consumer: (Boolean)->Unit) { + if (this.containsKey(key) && this[key]!!.isBoolean) { + consumer(this[key]!!.asBoolean()!!.value) + } +} + +fun BsonDocument.ifContainsString(key: String, consumer: (String)->Unit) { + if (this.containsKey(key) && this[key]!!.isString) { + consumer(this[key]!!.asString()!!.value) + } +} + +fun BsonDocument.ifContainsInt(key: String, consumer: (Int)->Unit) { + if (this.containsKey(key) && this[key]!!.isInt32) { + consumer(this[key]!!.asInt32().value) + } +} + +fun BsonDocument.ifContainsLong(key: String, consumer: (Long)->Unit) { + if (this.containsKey(key) && this[key]!!.isInt64) { + consumer(this[key]!!.asInt64().value) + } } \ No newline at end of file From 23ad1098ad85537e5b66e3339600809932d74d54 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 2 Sep 2021 15:28:29 -0500 Subject: [PATCH 199/206] Bson decoding of music settings --- .../cascadebot/data/objects/Tag.java | 7 +++++- .../data/objects/GuildSettingsMusic.kt | 23 ++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java index 99ad99948..4ee9b647a 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java @@ -22,7 +22,6 @@ import static org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode; @NoArgsConstructor(access = AccessLevel.PRIVATE) -@AllArgsConstructor public class Tag extends PermissionObject implements BsonObject { // https://regex101.com/r/hlsgVW/1 @@ -32,6 +31,12 @@ public class Tag extends PermissionObject implements BsonObject { private String content; private String category; + public Tag(String name, String content, String category) { + this.name = name; + this.content = content; + this.category = category; + } + public String formatTag(CommandContext commandContext) { return PlaceholderObjects.getTags().formatMessage(commandContext.getLocale(), content, commandContext); } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt index 9fcd6ea53..fe32aa967 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt @@ -3,6 +3,9 @@ package org.cascadebot.cascadebot.data.objects import org.bson.BsonDocument import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.database.BsonObject +import org.cascadebot.cascadebot.utils.ifContainsArray +import org.cascadebot.cascadebot.utils.ifContainsBoolean +import org.cascadebot.cascadebot.utils.ifContainsInt import java.util.concurrent.ConcurrentHashMap @SettingsContainer(module = Module.MUSIC) @@ -22,7 +25,25 @@ class GuildSettingsMusic : BsonObject { var joinOnPlay = true; override fun fromBson(bsonDocument: BsonDocument) { - + bsonDocument.ifContainsBoolean("preserveVolume") { + preserveVolume = it; + } + bsonDocument.ifContainsBoolean("preserveEqualizer") { + preserveEqualizer = it; + } + bsonDocument.ifContainsInt("volume") { + volume = it; + } + bsonDocument.ifContainsBoolean("joinOnPlay") { + joinOnPlay = it; + } + bsonDocument.ifContainsArray("equalizerBands") { + equalizerBands.clear() + for (banBson in it) { + val doc = banBson.asDocument() + equalizerBands[doc["key"]!!.asNumber().intValue()] = doc["value"]!!.asDouble().value.toFloat() + } + } } } \ No newline at end of file From 27c49bf84e7ad0e10c87db29b728b763a5fdee26 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Thu, 2 Sep 2021 18:43:45 -0500 Subject: [PATCH 200/206] Fix the merge It can never be simple can it? --- .../GroupPermissionMoveSubCommand.java | 2 +- .../commands/music/EqualizerCommand.java | 9 +------ .../cascadebot/data/objects/GuildData.kt | 24 +++++++++++++------ 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionMoveSubCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionMoveSubCommand.java index 522155dfe..e5693b720 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionMoveSubCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/management/permission/GroupPermissionMoveSubCommand.java @@ -38,7 +38,7 @@ public void onCommand(Member sender, CommandContext context) { // TODO add a con } context.getData().write(guildData -> { - PermissionCommandUtils.tryGetGroupFromString(context, context.getArg(0), group -> { + PermissionCommandUtils.tryGetGroupFromString(context, context.getData(), context.getArg(0), group -> { if (context.getArgs().length > 1 && context.isArgInteger(1)) { context.getData().getManagement().getPermissions().moveGroup(group, context.getArgAsInteger(1)); context.getTypedMessaging().replySuccess(context.i18n("commands.groupperms.move.moved", group.getName(), context.getArg(1))); diff --git a/src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerCommand.java index 5dd7cd780..7779c1a31 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/music/EqualizerCommand.java @@ -106,7 +106,7 @@ public void onCommand(Member sender, CommandContext context) { if (context.getData().getMusic().getPreserveEqualizer()) { int finalGain = gain; context.getData().write(guildData -> { - guildData.getMusic().getEqualizerBands().replace(currentBand.get(), ((float) finalGain) / 20f); + guildData.getMusic().getEqualizerBands().replace(currentBand, ((float) finalGain) / 20f); }); } } @@ -125,13 +125,6 @@ public void onCommand(Member sender, CommandContext context) { currentBands.clear(); currentBands.add(newBand); - player.setBand(currentBand.get(), ((float) gain) / 20f); - if (context.getData().getMusic().getPreserveEqualizer()) { - int finalGain = gain; - context.getData().write(guildData -> { - guildData.getMusic().getEqualizerBands().replace(currentBand.get(), ((float) finalGain) / 20f); - }); - } CascadeSelectBox innerSelectBox = (CascadeSelectBox) context.getData().getComponentCache().get(channel.getIdLong()).get(message.getIdLong()).getRow(1).getComponents().get(0); message.editMessage(getEqualizerEmbed(player.getCurrentBands(), currentBands, runner.getUser(), context, innerSelectBox).build()).queue(); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 7c59e1c49..cd9d8751f 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -32,10 +32,13 @@ import kotlin.concurrent.withLock import kotlin.reflect.jvm.javaType import kotlin.reflect.typeOf import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode +import org.cascadebot.cascadebot.utils.diff.DiffUtils +import org.cascadebot.cascadebot.utils.diff.Difference import org.cascadebot.cascadebot.utils.ifContains import org.cascadebot.cascadebot.utils.ifContainsArray import org.cascadebot.cascadebot.utils.ifContainsDocument import org.cascadebot.cascadebot.utils.ifContainsLong +import java.util.ArrayList import java.util.concurrent.atomic.AtomicBoolean import java.util.function.Function import kotlin.concurrent.getOrSet @@ -227,20 +230,27 @@ class GuildData(@field:Id val guildId: Long): BsonObject { } bsonDocument.ifContainsLong("mutedRoleId") { mutedRoleId = it } bsonDocument.ifContainsArray("persistentButtons") { - persistentButtons.clear() + persistentComponents.clear() for (entry in it) { val channelId = entry.asDocument()["key"]!!.asNumber().longValue() val messages = entry.asDocument()["value"]!!.asArray(); - val messageMap = HashMap() + val messageMap = HashMap>>() for (message in messages) { val messageId = message.asDocument()["key"]!!.asNumber().longValue() - val buttonObject = message.asDocument()["value"]!!.asDocument(); - val group = PersistentButtonGroup(buttonObject["ownerId"]!!.asNumber().longValue(), buttonObject["channelId"]!!.asNumber().longValue(), buttonObject["guildId"]!!.asNumber().longValue()) - group.fromBson(buttonObject); - messageMap[messageId] = group; + val rowObj = message.asDocument()["value"]!!.asArray(); + val messageComp: MutableList> = mutableListOf() + for (rowBson in rowObj) { + val rowComp: MutableList = mutableListOf() + for (compBson in rowBson.asArray()) { + rowComp.add(PersistentComponent.valueOf(compBson.asString().value)) + } + messageComp.add(rowComp) + } + messageMap[messageId] = messageComp } - persistentButtons[channelId] = messageMap + persistentComponents[channelId] = messageMap } + loadComponents() } bsonDocument.ifContainsDocument("core") { core.fromBson(it) } bsonDocument.ifContainsDocument("useful") { useful.fromBson(it) } From afde81084c82f9962307f02ce92530a74b0d2c85 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Fri, 3 Sep 2021 10:55:36 -0500 Subject: [PATCH 201/206] Handle removed data --- .../org/cascadebot/cascadebot/CascadeBot.java | 8 +++- .../cascadebot/data/database/BsonObject.java | 2 +- .../cascadebot/data/database/DataHandler.java | 43 +++++++++++++++++++ .../data/objects/GuildPermissions.java | 6 +++ .../data/objects/GuildSettingsUseful.java | 15 +++++++ .../cascadebot/data/objects/Tag.java | 6 +++ .../cascadebot/data/objects/Greetings.kt | 8 ++++ .../cascadebot/data/objects/GuildData.kt | 13 ++++++ .../data/objects/GuildSettingsCore.kt | 6 +++ .../data/objects/GuildSettingsManagement.kt | 14 ++++++ .../data/objects/GuildSettingsModeration.kt | 25 ++++++++--- .../data/objects/GuildSettingsMusic.kt | 5 +++ .../cascadebot/data/objects/TodoList.kt | 7 ++- .../cascadebot/utils/RemovedTreeUtils.kt | 17 ++++++++ 14 files changed, 166 insertions(+), 9 deletions(-) create mode 100644 src/main/kotlin/org/cascadebot/cascadebot/utils/RemovedTreeUtils.kt diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index acf2a4c5b..cb3b68aee 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -39,6 +39,7 @@ import org.cascadebot.cascadebot.commandmeta.ArgumentManager; import org.cascadebot.cascadebot.commandmeta.CommandManager; import org.cascadebot.cascadebot.data.Config; +import org.cascadebot.cascadebot.data.database.DataHandler; import org.cascadebot.cascadebot.data.database.DatabaseManager; import org.cascadebot.cascadebot.data.managers.GuildDataManager; import org.cascadebot.cascadebot.data.managers.ScheduledActionManager; @@ -227,7 +228,12 @@ private void init() { GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()); } else if (guildDataChangeStreamDocument.getUpdateDescription() != null) { GuildData currentData = GuildDataManager.getGuildData(guildDataChangeStreamDocument.getDocumentKey().get("_id").asNumber().longValue()); - + if (guildDataChangeStreamDocument.getUpdateDescription().getUpdatedFields() != null) { + currentData.fromBson(guildDataChangeStreamDocument.getUpdateDescription().getUpdatedFields()); + } + if (guildDataChangeStreamDocument.getUpdateDescription().getRemovedFields() != null) { + currentData.handleRemove(DataHandler.RemovedTree.buildTree("guild", guildDataChangeStreamDocument.getUpdateDescription().getRemovedFields())); + } } }, (result, throwable) -> { if (throwable != null) { diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/BsonObject.java b/src/main/java/org/cascadebot/cascadebot/data/database/BsonObject.java index 25e0f4e64..cf50edc86 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/BsonObject.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/BsonObject.java @@ -9,6 +9,6 @@ public interface BsonObject { void fromBson(@NotNull BsonDocument bsonDocument); - //void handleRemove(@NotNull List paths); // TODO not list string + void handleRemove(@NotNull DataHandler.RemovedTree tree); } diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java index 462116db7..041055daf 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java @@ -23,11 +23,14 @@ import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; public class DataHandler { @@ -181,4 +184,44 @@ private List diffUpdateRec(Y original, Y changed, String path, List children = new ArrayList<>(); + + public RemovedTree(String name) { + this.name = name; + } + + public RemovedTree getChild(String name) { + return children.stream().filter(removedTree -> removedTree.name.equals(name)).findFirst().orElse(null); + } + + public static RemovedTree buildTree(String name, List paths) { + Map> map = new HashMap<>(); + RemovedTree tree = new RemovedTree(name); + if (paths.size() == 0) { + return tree; + } + for (String path : paths) { + String[] split = path.split("\\."); + String newPath = String.join(".", Arrays.copyOfRange(split, 1, split.length - 1)); + if (newPath.isEmpty()) { + map.put(split[0], new ArrayList<>()); + continue; + } + if (map.containsKey(split[0])) { + map.get(split[0]).add(newPath); + } else { + List strings = new ArrayList<>(); + strings.add(newPath); + map.put(split[0], strings); + } + } + for (Map.Entry> entry : map.entrySet()) { + tree.children.add(RemovedTree.buildTree(entry.getKey(), entry.getValue())); + } + return tree; + } + } + } diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java index 6e745e7ae..eb96b0a82 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildPermissions.java @@ -16,6 +16,7 @@ import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.Environment; import org.cascadebot.cascadebot.data.database.BsonObject; +import org.cascadebot.cascadebot.data.database.DataHandler; import org.cascadebot.cascadebot.permissions.CascadePermission; import org.cascadebot.cascadebot.permissions.Security; import org.cascadebot.cascadebot.permissions.objects.Group; @@ -257,4 +258,9 @@ public void fromBson(@NotNull BsonDocument bsonDocument) { } } } + + @Override + public void handleRemove(@NotNull DataHandler.RemovedTree tree) { + + } } diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java index 0c4fed6b1..c47225351 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/GuildSettingsUseful.java @@ -4,6 +4,8 @@ import org.bson.BsonValue; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.data.database.BsonObject; +import org.cascadebot.cascadebot.data.database.DataHandler; +import org.cascadebot.cascadebot.utils.RemovedTreeUtilsKt; import org.jetbrains.annotations.NotNull; import java.util.Map; @@ -65,4 +67,17 @@ public void fromBson(@NotNull BsonDocument bsonDocument) { } } + @Override + public void handleRemove(@NotNull DataHandler.RemovedTree tree) { + RemovedTreeUtilsKt.ifContains(tree, "todoLists", (child) -> { + for (Map.Entry entry : todoLists.entrySet()) { + RemovedTreeUtilsKt.ifContains(child, entry.getKey(), (nothing) -> { + todoLists.remove(entry.getKey()); + return null; + }); + } + return null; + }); + } + } diff --git a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java index 4ee9b647a..d98b9a59f 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java +++ b/src/main/java/org/cascadebot/cascadebot/data/objects/Tag.java @@ -14,6 +14,7 @@ import org.cascadebot.cascadebot.commandmeta.CommandContext; import org.cascadebot.cascadebot.commandmeta.Module; import org.cascadebot.cascadebot.data.database.BsonObject; +import org.cascadebot.cascadebot.data.database.DataHandler; import org.cascadebot.cascadebot.utils.placeholders.PlaceholderObjects; import org.jetbrains.annotations.NotNull; @@ -95,4 +96,9 @@ public void fromBson(@NotNull BsonDocument bsonDocument) { category = bsonDocument.get("category").asString().getValue(); } } + + @Override + public void handleRemove(@NotNull DataHandler.RemovedTree tree) { + + } } \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt index 8630e338d..9ddf33cee 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/Greetings.kt @@ -6,7 +6,9 @@ import net.dv8tion.jda.api.events.guild.member.GuildMemberRemoveEvent import org.bson.BsonDocument import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.data.database.BsonObject +import org.cascadebot.cascadebot.data.database.DataHandler import org.cascadebot.cascadebot.data.language.Language +import org.cascadebot.cascadebot.utils.ifContains import org.cascadebot.cascadebot.utils.ifContainsDocument import org.cascadebot.cascadebot.utils.ifContainsLong import org.cascadebot.cascadebot.utils.lists.WeightedList @@ -80,5 +82,11 @@ class Greetings : BsonObject { } } + override fun handleRemove(tree: DataHandler.RemovedTree) { + tree.ifContains("welcomeChannelId") { + welcomeChannelId = null + } + } + } \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index cd9d8751f..3ff316411 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -15,6 +15,7 @@ import org.bson.BsonArray import org.bson.BsonDocument import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.data.database.BsonObject +import org.cascadebot.cascadebot.data.database.DataHandler import org.cascadebot.cascadebot.data.language.Locale import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.music.CascadeLavalinkPlayer @@ -259,6 +260,18 @@ class GuildData(@field:Id val guildId: Long): BsonObject { bsonDocument.ifContainsDocument("music") { music.fromBson(it) } } + override fun handleRemove(tree: DataHandler.RemovedTree) { + tree.ifContains("useful") { + useful.handleRemove(it) + } + tree.ifContains("moderation") { + moderation.handleRemove(it) + } + tree.ifContains("management") { + management.handleRemove(it) + } + } + } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt index 24435f3fb..5f1e05103 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsCore.kt @@ -7,8 +7,10 @@ import org.cascadebot.cascadebot.commandmeta.MainCommand import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.Config import org.cascadebot.cascadebot.data.database.BsonObject +import org.cascadebot.cascadebot.data.database.DataHandler import org.cascadebot.cascadebot.data.language.Locale import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode +import org.cascadebot.cascadebot.utils.ifContains import org.cascadebot.cascadebot.utils.ifContainsArray import org.cascadebot.cascadebot.utils.ifContainsBoolean import org.cascadebot.cascadebot.utils.ifContainsString @@ -164,4 +166,8 @@ class GuildSettingsCore : BsonObject { } } + override fun handleRemove(tree: DataHandler.RemovedTree) { + + } + } \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt index b32684e54..d6b6c534e 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsManagement.kt @@ -3,6 +3,7 @@ package org.cascadebot.cascadebot.data.objects import org.bson.BsonDocument import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.database.BsonObject +import org.cascadebot.cascadebot.data.database.DataHandler import org.cascadebot.cascadebot.utils.GuildDataUtils import org.cascadebot.cascadebot.utils.GuildDataUtils.assertWriteMode import org.cascadebot.cascadebot.utils.ifContains @@ -91,4 +92,17 @@ class GuildSettingsManagement : BsonObject { } } + override fun handleRemove(tree: DataHandler.RemovedTree) { + tree.ifContains("tags") { + for (entry in tags.entries) { + it.ifContains(entry.key) { + tags.remove(entry.key) + } + } + } + tree.ifContains("greetings") { + greetings.handleRemove(it) + } + } + } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt index 5168d5ab1..ad4124319 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsModeration.kt @@ -14,6 +14,7 @@ import org.bson.BsonDocument import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.database.BsonObject +import org.cascadebot.cascadebot.data.database.DataHandler import org.cascadebot.cascadebot.data.database.DebugLogCallback import org.cascadebot.cascadebot.data.language.Language import org.cascadebot.cascadebot.data.managers.GuildDataManager @@ -133,11 +134,11 @@ class GuildSettingsModeration : BsonObject { modlogEvents.put(channel.idLong.toString(), eventsInfo) channel.createWebhook(CascadeBot.INS.client.selfUser.name) .setAvatar(Icon.from(URL(CascadeBot.INS.client.selfUser.avatarUrl).openStream())).queue { webhook -> - eventsInfo.webhookId = webhook.idLong - eventsInfo.webhookToken = webhook.token!! - eventsInfo.buildWebhookClient() - consumer.accept(eventsInfo) - } + eventsInfo.webhookId = webhook.idLong + eventsInfo.webhookToken = webhook.token!! + eventsInfo.buildWebhookClient() + consumer.accept(eventsInfo) + } } class ChannelModlogEventsInfo : BsonObject { @@ -327,6 +328,10 @@ class GuildSettingsModeration : BsonObject { id = it.asNumber().intValue() } } + + override fun handleRemove(tree: DataHandler.RemovedTree) { + + } } override fun fromBson(bsonDocument: BsonDocument) { @@ -346,4 +351,14 @@ class GuildSettingsModeration : BsonObject { } } + override fun handleRemove(tree: DataHandler.RemovedTree) { + tree.ifContains("modlogEvents") { + for (entry in modlogEvents.entries) { + it.ifContains(entry.key) { + modlogEvents.remove(entry.key) + } + } + } + } + } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt index fe32aa967..066164e5a 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildSettingsMusic.kt @@ -3,6 +3,7 @@ package org.cascadebot.cascadebot.data.objects import org.bson.BsonDocument import org.cascadebot.cascadebot.commandmeta.Module import org.cascadebot.cascadebot.data.database.BsonObject +import org.cascadebot.cascadebot.data.database.DataHandler import org.cascadebot.cascadebot.utils.ifContainsArray import org.cascadebot.cascadebot.utils.ifContainsBoolean import org.cascadebot.cascadebot.utils.ifContainsInt @@ -46,4 +47,8 @@ class GuildSettingsMusic : BsonObject { } } + override fun handleRemove(tree: DataHandler.RemovedTree) { + + } + } \ No newline at end of file diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt index 06c0a1929..4e1eb5f81 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/TodoList.kt @@ -9,6 +9,7 @@ import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.UnicodeConstants import org.cascadebot.cascadebot.commandmeta.CommandContext import org.cascadebot.cascadebot.data.database.BsonObject +import org.cascadebot.cascadebot.data.database.DataHandler import org.cascadebot.cascadebot.data.managers.GuildDataManager import org.cascadebot.cascadebot.messaging.Messaging import org.cascadebot.cascadebot.messaging.MessagingObjects @@ -59,8 +60,6 @@ class TodoList(val ownerId: Long) : BsonObject { class TodoListItem { - - var done = false var text: String? = null @@ -199,4 +198,8 @@ class TodoList(val ownerId: Long) : BsonObject { } CascadeBot.INS.client.getTextChannelById(channelId)!!.editMessageById(messageId, todoListMessage).queue() } + + override fun handleRemove(tree: DataHandler.RemovedTree) { + + } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/utils/RemovedTreeUtils.kt b/src/main/kotlin/org/cascadebot/cascadebot/utils/RemovedTreeUtils.kt new file mode 100644 index 000000000..2de6b9915 --- /dev/null +++ b/src/main/kotlin/org/cascadebot/cascadebot/utils/RemovedTreeUtils.kt @@ -0,0 +1,17 @@ +package org.cascadebot.cascadebot.utils + +import org.cascadebot.cascadebot.data.database.DataHandler + +fun DataHandler.RemovedTree.ifContainsAndLast(key: String, consumer: (DataHandler.RemovedTree, Boolean) -> Unit) { + val tree = this.getChild(key); + if (tree != null) { + consumer(tree, tree.children.size == 0) + } +} + +fun DataHandler.RemovedTree.ifContains(key: String, consumer: (DataHandler.RemovedTree) -> Unit) { + val tree = this.getChild(key); + if (tree != null) { + consumer(tree) + } +} \ No newline at end of file From 07080061b0ca1f790395306286412c9b57e60162 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Fri, 3 Sep 2021 11:00:14 -0500 Subject: [PATCH 202/206] Use new bson generator that actually supports everything --- .../cascadebot/data/database/DatabaseManager.java | 6 ++++++ .../cascadebot/data/managers/GuildDataManager.java | 6 ++++++ .../cascadebot/cascadebot/data/objects/GuildData.kt | 10 ++++------ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java b/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java index 9f355cdff..d2cc8f41e 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DatabaseManager.java @@ -29,6 +29,7 @@ import org.bson.codecs.EncoderContext; import org.bson.codecs.configuration.CodecRegistries; import org.bson.codecs.configuration.CodecRegistry; +import org.cascadebot.cascadebot.data.objects.GuildData; import org.cascadebot.cascadebot.moderation.ModlogEmbedDescription; import org.cascadebot.cascadebot.moderation.ModlogEmbedField; import org.cascadebot.cascadebot.moderation.ModlogEmbedFooter; @@ -67,6 +68,8 @@ public class DatabaseManager { @Getter private String databaseName; + private final DataHandler guildDataDataHandler = new DataHandler<>(); + public DatabaseManager(String username, char[] password, String databaseName, List hosts, boolean ssl) { MongoClientSettings.Builder settingsBuilder = MongoClientSettings.builder(); @@ -143,4 +146,7 @@ public CodecRegistry getCodecRegistry() { return CODEC_REGISTRY; } + public DataHandler getGuildDataDataHandler() { + return guildDataDataHandler; + } } diff --git a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java index 1694aa2ad..b374fb635 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java @@ -58,6 +58,12 @@ public static void update(long id, Bson update) { }); } + public static void updateBson(long id, Bson update) { + CascadeBot.INS.getDatabaseManager().runAsyncTask(database -> { + database.getCollection(COLLECTION, GuildData.class).updateMany(eq("_id", id), update, new DebugLogCallback<>("Updated Guild ID " + id)); + }); + } + public static void updateDiff(long id, Difference difference, GuildData newData) { CascadeBot.LOGGER.info(CascadeBot.getGSON().toJson(difference)); List bsonList = new ArrayList<>(); diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 3ff316411..38032d7a0 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -199,24 +199,22 @@ class GuildData(@field:Id val guildId: Long): BsonObject { } fun write(writer: Consumer) { this.lock.writeLock().withLock { - val copy: GuildData = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(this), this.javaClass) + val copy: GuildData = CascadeBot.INS.databaseManager.guildDataDataHandler.deepCopy(this) writeMode.set(true) writer.accept(copy); writeMode.set(false) - val diff: Difference = DiffUtils.diff(this, copy) - GuildDataManager.updateDiff(guildId, diff, copy) + GuildDataManager.updateBson(guildId, CascadeBot.INS.databaseManager.guildDataDataHandler.diffUpdate(this, copy)) //println(GsonBuilder().setPrettyPrinting().create().toJson(diff)) } } fun writeInline(writer: Function) : T { this.lock.writeLock().withLock { - val copy: GuildData = CascadeBot.getGSON().fromJson(CascadeBot.getGSON().toJson(this), this.javaClass) + val copy: GuildData = CascadeBot.INS.databaseManager.guildDataDataHandler.deepCopy(this) writeMode.set(true) val output = writer.apply(copy); writeMode.set(false) - val diff: Difference = DiffUtils.diff(this, copy) - GuildDataManager.updateDiff(guildId, diff, copy) + GuildDataManager.updateBson(guildId, CascadeBot.INS.databaseManager.guildDataDataHandler.diffUpdate(this, copy)) //println(GsonBuilder().setPrettyPrinting().create().toJson(diff)) return output } From 4b004f803e16bb2ca0877c3ecd60caf3f089ecb2 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Fri, 3 Sep 2021 11:15:31 -0500 Subject: [PATCH 203/206] I pulled a binary --- .../cascadebot/cascadebot/permissions/objects/Group.java | 6 ++++++ .../org/cascadebot/cascadebot/permissions/objects/User.java | 6 ++++++ .../org/cascadebot/cascadebot/data/objects/CommandFilter.kt | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java index a49d17060..a136b00a5 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/Group.java @@ -16,6 +16,7 @@ import org.bson.BsonDocument; import org.bson.BsonValue; import org.cascadebot.cascadebot.data.database.BsonObject; +import org.cascadebot.cascadebot.data.database.DataHandler; import org.jetbrains.annotations.NotNull; import java.util.Set; @@ -87,4 +88,9 @@ public void fromBson(@NotNull BsonDocument bsonDocument) { } super.fromBson(bsonDocument); } + + @Override + public void handleRemove(@NotNull DataHandler.RemovedTree tree) { + + } } diff --git a/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java b/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java index 5cfc52469..9bc49b807 100644 --- a/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java +++ b/src/main/java/org/cascadebot/cascadebot/permissions/objects/User.java @@ -11,6 +11,7 @@ import org.bson.BsonDocument; import org.bson.BsonValue; import org.cascadebot.cascadebot.data.database.BsonObject; +import org.cascadebot.cascadebot.data.database.DataHandler; import org.jetbrains.annotations.NotNull; import java.util.Set; @@ -52,4 +53,9 @@ public void fromBson(@NotNull BsonDocument bsonDocument) { } super.fromBson(bsonDocument); } + + @Override + public void handleRemove(@NotNull DataHandler.RemovedTree tree) { + + } } diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt index 1a2f99263..8f50e6e8c 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/CommandFilter.kt @@ -13,6 +13,7 @@ import org.bson.BsonDocument import org.cascadebot.cascadebot.CascadeBot import org.cascadebot.cascadebot.data.Config import org.cascadebot.cascadebot.data.database.BsonObject +import org.cascadebot.cascadebot.data.database.DataHandler import org.cascadebot.cascadebot.data.language.Language import org.cascadebot.cascadebot.data.language.Locale import org.cascadebot.cascadebot.messaging.MessageType @@ -236,4 +237,8 @@ class CommandFilter(val name: String) : BsonObject { } } + override fun handleRemove(tree: DataHandler.RemovedTree) { + + } + } From 0232f0f41afe36d93d17891fe7126e1bbddce991 Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Fri, 3 Sep 2021 13:58:57 -0500 Subject: [PATCH 204/206] Fix some bugs in data handler --- .../cascadebot/commands/core/PrefixCommand.java | 8 ++++++-- .../cascadebot/data/database/DataHandler.java | 13 +++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/commands/core/PrefixCommand.java b/src/main/java/org/cascadebot/cascadebot/commands/core/PrefixCommand.java index 2c780616c..486a6b7c3 100644 --- a/src/main/java/org/cascadebot/cascadebot/commands/core/PrefixCommand.java +++ b/src/main/java/org/cascadebot/cascadebot/commands/core/PrefixCommand.java @@ -19,7 +19,9 @@ public void onCommand(Member sender, CommandContext context) { if (context.testForArg("reset")) { if (context.hasPermission("prefix.reset")) { - context.getCoreSettings().setPrefix(Config.INS.getDefaultPrefix()); + context.getData().write(guildData -> { + guildData.getCore().setPrefix(Config.INS.getDefaultPrefix()); + }); context.getTypedMessaging().replyInfo(context.i18n("commands.prefix.prefix_reset", Config.INS.getDefaultPrefix())); } else { context.getUiMessaging().sendPermissionError("prefix.reset"); @@ -36,7 +38,9 @@ public void onCommand(Member sender, CommandContext context) { context.getTypedMessaging().replyDanger(context.i18n("commands.prefix.prefix_too_long")); return; } - context.getCoreSettings().setPrefix(newPrefix); + context.getData().write(guildData -> { + guildData.getCore().setPrefix(newPrefix); + }); context.getTypedMessaging().replyInfo(context.i18n("commands.prefix.new_prefix", newPrefix)); } else { context.getTypedMessaging().replyInfo(context.i18n("commands.prefix.current_prefix", context.getCoreSettings().getPrefix())); diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java index 041055daf..775b2782a 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java @@ -80,6 +80,7 @@ private Y deepCopyRec(Y original) throws NoSuchMethodException, InvocationTa Y obj = (Y) constructor.newInstance(); for(Field field : original.getClass().getDeclaredFields()) { + makeAccessible(field); if (Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) { if (!Modifier.isStatic(field.getModifiers())) { field.set(obj, field.get(original)); @@ -121,7 +122,12 @@ private List diffUpdateRec(Y original, Y changed, String path, List List diffUpdateRec(Y original, Y changed, String path, List Date: Fri, 3 Sep 2021 14:10:10 -0500 Subject: [PATCH 205/206] Fix guild data not being updated correctly --- src/main/java/org/cascadebot/cascadebot/CascadeBot.java | 2 +- .../cascadebot/cascadebot/data/managers/GuildDataManager.java | 3 ++- .../org/cascadebot/cascadebot/data/objects/GuildData.kt | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java index cb3b68aee..bc5e27a98 100644 --- a/src/main/java/org/cascadebot/cascadebot/CascadeBot.java +++ b/src/main/java/org/cascadebot/cascadebot/CascadeBot.java @@ -226,7 +226,7 @@ private void init() { changeStreamIterable.forEach(guildDataChangeStreamDocument -> { if (guildDataChangeStreamDocument.getFullDocument() != null) { GuildDataManager.replaceInternal(guildDataChangeStreamDocument.getFullDocument()); - } else if (guildDataChangeStreamDocument.getUpdateDescription() != null) { + } else { GuildData currentData = GuildDataManager.getGuildData(guildDataChangeStreamDocument.getDocumentKey().get("_id").asNumber().longValue()); if (guildDataChangeStreamDocument.getUpdateDescription().getUpdatedFields() != null) { currentData.fromBson(guildDataChangeStreamDocument.getUpdateDescription().getUpdatedFields()); diff --git a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java index b374fb635..8039b18ad 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java +++ b/src/main/java/org/cascadebot/cascadebot/data/managers/GuildDataManager.java @@ -58,10 +58,11 @@ public static void update(long id, Bson update) { }); } - public static void updateBson(long id, Bson update) { + public static void updateBson(long id, Bson update, GuildData newData) { CascadeBot.INS.getDatabaseManager().runAsyncTask(database -> { database.getCollection(COLLECTION, GuildData.class).updateMany(eq("_id", id), update, new DebugLogCallback<>("Updated Guild ID " + id)); }); + replaceInternal(newData); } public static void updateDiff(long id, Difference difference, GuildData newData) { diff --git a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt index 38032d7a0..b5255140c 100644 --- a/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt +++ b/src/main/kotlin/org/cascadebot/cascadebot/data/objects/GuildData.kt @@ -203,7 +203,7 @@ class GuildData(@field:Id val guildId: Long): BsonObject { writeMode.set(true) writer.accept(copy); writeMode.set(false) - GuildDataManager.updateBson(guildId, CascadeBot.INS.databaseManager.guildDataDataHandler.diffUpdate(this, copy)) + GuildDataManager.updateBson(guildId, CascadeBot.INS.databaseManager.guildDataDataHandler.diffUpdate(this, copy), copy) //println(GsonBuilder().setPrettyPrinting().create().toJson(diff)) } } @@ -214,7 +214,7 @@ class GuildData(@field:Id val guildId: Long): BsonObject { writeMode.set(true) val output = writer.apply(copy); writeMode.set(false) - GuildDataManager.updateBson(guildId, CascadeBot.INS.databaseManager.guildDataDataHandler.diffUpdate(this, copy)) + GuildDataManager.updateBson(guildId, CascadeBot.INS.databaseManager.guildDataDataHandler.diffUpdate(this, copy), copy) //println(GsonBuilder().setPrettyPrinting().create().toJson(diff)) return output } From 47660374b3181e684e66ad77ef626b6d2903bbff Mon Sep 17 00:00:00 2001 From: weeryan17 Date: Fri, 3 Sep 2021 15:25:43 -0500 Subject: [PATCH 206/206] More attempts to get saving to work with the new system. --- .../cascadebot/data/database/DataHandler.java | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java index 775b2782a..563bbf3b0 100644 --- a/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java +++ b/src/main/java/org/cascadebot/cascadebot/data/database/DataHandler.java @@ -1,14 +1,9 @@ package org.cascadebot.cascadebot.data.database; import com.mongodb.client.model.Updates; -import com.mongodb.client.model.changestream.ChangeStreamDocument; -import com.mongodb.client.model.changestream.UpdateDescription; -import org.bson.BsonArray; -import org.bson.BsonDocument; -import org.bson.BsonValue; -import org.bson.codecs.DecoderContext; +import de.bild.codec.annotations.Transient; +import org.apache.commons.lang3.ClassUtils; import org.bson.conversions.Bson; -import org.cascadebot.cascadebot.CascadeBot; import org.cascadebot.cascadebot.utils.lists.CollectionDiff; import java.io.ByteArrayInputStream; @@ -21,16 +16,13 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; public class DataHandler { @@ -42,11 +34,11 @@ private Y deepCopyRec(Y original) throws NoSuchMethodException, InvocationTa if (original == null) { return null; } - System.out.println(original.getClass().getName()); - if (original.getClass().isPrimitive()) { + //System.out.println(original.getClass().getName()); + if (ClassUtils.isPrimitiveOrWrapper(original.getClass())) { return original; // TODO does this work? } else if (original.getClass().isArray()) { - throw new UnsupportedOperationException(); + return original; } else if (original instanceof Map) { Map map = (Map) original; Map newMap = (Map) original.getClass().getDeclaredConstructor().newInstance(); @@ -61,7 +53,7 @@ private Y deepCopyRec(Y original) throws NoSuchMethodException, InvocationTa newCol.add(deepCopyRec(obj)); } return (Y) newCol; - } else if (original instanceof Serializable) { + } /*else if (original instanceof Serializable) { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(out); objectOutputStream.writeObject(original); @@ -69,7 +61,7 @@ private Y deepCopyRec(Y original) throws NoSuchMethodException, InvocationTa ObjectInputStream objectInputStream = new ObjectInputStream(in); Y copy = (Y) objectInputStream.readObject(); return copy; - } else { + }*/ else { Constructor constructor; try { constructor = (Constructor) original.getClass().getDeclaredConstructor(); @@ -79,7 +71,7 @@ private Y deepCopyRec(Y original) throws NoSuchMethodException, InvocationTa constructor.setAccessible(true); Y obj = (Y) constructor.newInstance(); - for(Field field : original.getClass().getDeclaredFields()) { + for (Field field : original.getClass().getDeclaredFields()) { makeAccessible(field); if (Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) { if (!Modifier.isStatic(field.getModifiers())) { @@ -174,17 +166,18 @@ private List diffUpdateRec(Y original, Y changed, String path, List