diff --git a/src/main/kotlin/nl/skbotnl/chatog/BlocklistManager.kt b/src/main/kotlin/nl/skbotnl/chatog/BlocklistManager.kt index 5d5e192..ba9aa75 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/BlocklistManager.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/BlocklistManager.kt @@ -7,7 +7,7 @@ import kotlinx.coroutines.launch class BlocklistManager { private val lock = Any() - private var blockList = mutableListOf() + private val blockList = mutableListOf() init { ChatOG.plugin.logger.info("Loading the blocklists...") @@ -24,14 +24,13 @@ class BlocklistManager { private fun refresh() { blockList.clear() - URI("https://raw.githubusercontent.com/hagezi/dns-blocklists/main/domains/multi.txt") - .toURL() - .openStream() - .use { input -> + ChatOG.config.blocklists.forEach { blocklist -> + URI(blocklist).toURL().openStream().use { input -> input.bufferedReader().use { bufferedReader -> synchronized(lock) { bufferedReader.lines().forEach { if (!it.startsWith("#")) blockList.add(it) } } } } + } } private val urlRegex = Regex("(?:https?://)?([a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})") diff --git a/src/main/kotlin/nl/skbotnl/chatog/ChatHelper.kt b/src/main/kotlin/nl/skbotnl/chatog/ChatHelper.kt deleted file mode 100644 index 2a9606e..0000000 --- a/src/main/kotlin/nl/skbotnl/chatog/ChatHelper.kt +++ /dev/null @@ -1,32 +0,0 @@ -package nl.skbotnl.chatog - -import me.clip.placeholderapi.PlaceholderAPI -import net.kyori.adventure.text.TextComponent -import net.trueog.utilitiesog.UtilitiesOG -import nl.skbotnl.chatog.Helper.legacyToMm -import org.bukkit.entity.Player - -internal object ChatHelper { - fun getPlayerPart(player: Player, addSuffix: Boolean): TextComponent { - val playerPartString = getPlayerPartString(player) - - val suffix = - if (addSuffix) { - PlayerAffix.getSuffix(player.uniqueId) - } else { - "" - } - - return UtilitiesOG.trueogColorize(legacyToMm("$playerPartString$suffix")) - } - - fun getPlayerPartString(player: Player): String { - var playerPart = "${PlayerAffix.getPrefix(player.uniqueId)}${player.name}" - - if (PlaceholderAPI.setPlaceholders(player, "%simpleclans_clan_color_tag%") != "") { - playerPart = PlaceholderAPI.setPlaceholders(player, "&8[%simpleclans_clan_color_tag%&8] $playerPart") - } - - return playerPart - } -} diff --git a/src/main/kotlin/nl/skbotnl/chatog/ChatOG.kt b/src/main/kotlin/nl/skbotnl/chatog/ChatOG.kt index 68c963f..d3262db 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/ChatOG.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/ChatOG.kt @@ -19,7 +19,7 @@ internal class ChatOG : JavaPlugin() { lateinit var plugin: JavaPlugin lateinit var config: Config - lateinit var blocklistManager: BlocklistManager + var blocklistManager: BlocklistManager? = null lateinit var luckPerms: LuckPerms lateinit var languageDatabase: LanguageDatabase var translator: OpenAI? = null @@ -27,6 +27,8 @@ internal class ChatOG : JavaPlugin() { val discordBridgeLock = ReentrantReadWriteLock() var essentials = Bukkit.getServer().pluginManager.getPlugin("Essentials") as Essentials var lastMessagedMap: MutableMap = HashMap() + + fun isLanguageDatabaseInitialized() = ::languageDatabase.isInitialized } @OptIn(DelicateCoroutinesApi::class) @@ -40,18 +42,20 @@ internal class ChatOG : JavaPlugin() { return } - blocklistManager = BlocklistManager() + if (Companion.config.blocklistEnabled) { + blocklistManager = BlocklistManager() + } translator = if (Companion.config.openAIEnabled) { if (Companion.config.openAIBaseUrl == null) { this.logger.warning( - "You have enabled OpenAI but have not set up the base url, not enabling the translator" + "You have enabled OpenAI translation but have not set up the base url, not enabling the translator" ) null } else if (Companion.config.openAIApiKey == null) { this.logger.warning( - "You have enabled OpenAI but have not set up the api key, not enabling the translator" + "You have enabled OpenAI translation but have not set up the api key, not enabling the translator" ) null } else { @@ -81,10 +85,14 @@ internal class ChatOG : JavaPlugin() { this.getCommand("translatesettings")?.setExecutor(TranslateSettings()) this.getCommand("translatesettings")?.tabCompleter = TranslateSettingsTabCompleter() this.getCommand("chatconfigreload")?.setExecutor(ChatConfigReload()) + this.getCommand("gc")?.setExecutor(GeneralChat()) + this.getCommand("g")?.setExecutor(GeneralChat()) this.getCommand("sc")?.setExecutor(StaffChat()) this.getCommand("s")?.setExecutor(StaffChat()) this.getCommand("pc")?.setExecutor(PremiumChat()) this.getCommand("p")?.setExecutor(PremiumChat()) + this.getCommand("dc")?.setExecutor(DeveloperChat()) + this.getCommand("d")?.setExecutor(DeveloperChat()) this.getCommand("msg")?.setExecutor(PrivateMessage()) this.getCommand("whisper")?.setExecutor(PrivateMessage()) this.getCommand("pm")?.setExecutor(PrivateMessage()) @@ -100,7 +108,7 @@ internal class ChatOG : JavaPlugin() { } override fun onDisable() { - if (Companion.config.discordEnabled) { + if (discordBridge != null) { discordBridgeLock.read { val discordBridge = discordBridge val serverHasStoppedMessage = @@ -117,6 +125,10 @@ internal class ChatOG : JavaPlugin() { } } + if (isLanguageDatabaseInitialized()) { + languageDatabase.shutdown() + } + scope.cancel() runBlocking { scope.coroutineContext[Job]?.join() } diff --git a/src/main/kotlin/nl/skbotnl/chatog/ChatSystem.kt b/src/main/kotlin/nl/skbotnl/chatog/ChatSystem.kt index c580238..9ad9b3e 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/ChatSystem.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/ChatSystem.kt @@ -11,8 +11,7 @@ import net.kyori.adventure.text.event.HoverEvent import net.trueog.utilitiesog.UtilitiesOG import nl.skbotnl.chatog.ChatOG.Companion.config import nl.skbotnl.chatog.ChatOG.Companion.discordBridgeLock -import nl.skbotnl.chatog.Helper.legacyToMm -import nl.skbotnl.chatog.Helper.removeColor +import nl.skbotnl.chatog.ChatUtil.legacyToMm import nl.skbotnl.chatog.commands.TranslateMessage import org.bukkit.Bukkit import org.bukkit.entity.Player @@ -23,29 +22,26 @@ internal object ChatSystem { GENERAL_CHAT, STAFF_CHAT, PREMIUM_CHAT, + DEVELOPER_CHAT, } var inChat: MutableMap = HashMap() fun sendMessageInStaffChat(player: Player, text: String) { - var playerPartString = ChatHelper.getPlayerPartString(player) + var playerPartString = ChatUtil.getPlayerPartString(player) playerPartString = "&cSTAFF | $playerPartString" if (config.staffDiscordEnabled) { - val discordMessageString = Helper.convertEmojis(text) + val discordMessageString = ChatUtil.convertEmojis(text) ChatOG.scope.launch { discordBridgeLock.read { - ChatOG.discordBridge?.sendStaffMessage( - discordMessageString, - removeColor(playerPartString), - player.uniqueId, - ) + ChatOG.discordBridge?.sendStaffMessage(discordMessageString, playerPartString, player.uniqueId) } } } - val messageComponent = Helper.processText(text, player) + val messageComponent = ChatUtil.processText(text, player) if (messageComponent == null) { return } @@ -78,24 +74,20 @@ internal object ChatSystem { } fun sendMessageInPremiumChat(player: Player, text: String) { - var playerPartString = ChatHelper.getPlayerPartString(player) + var playerPartString = ChatUtil.getPlayerPartString(player) playerPartString = "&aPREMIUM | $playerPartString" if (config.premiumDiscordEnabled) { - val discordMessageString = Helper.convertEmojis(text) + val discordMessageString = ChatUtil.convertEmojis(text) ChatOG.scope.launch { discordBridgeLock.read { - ChatOG.discordBridge?.sendPremiumMessage( - discordMessageString, - removeColor(playerPartString), - player.uniqueId, - ) + ChatOG.discordBridge?.sendPremiumMessage(discordMessageString, playerPartString, player.uniqueId) } } } - val messageComponent = Helper.processText(text, player) + val messageComponent = ChatUtil.processText(text, player) if (messageComponent == null) { return } @@ -126,4 +118,50 @@ internal object ChatSystem { } } } + + fun sendMessageInDeveloperChat(player: Player, text: String) { + var playerPartString = ChatUtil.getPlayerPartString(player) + playerPartString = "DEVELOPER | $playerPartString" + + if (config.premiumDiscordEnabled) { + val discordMessageString = ChatUtil.convertEmojis(text) + + ChatOG.scope.launch { + discordBridgeLock.read { + ChatOG.discordBridge?.sendDeveloperMessage(discordMessageString, playerPartString, player.uniqueId) + } + } + } + + val messageComponent = ChatUtil.processText(text, player) + if (messageComponent == null) { + return + } + + val chatComponent = + UtilitiesOG.trueogColorize(legacyToMm("$playerPartString${PlayerAffix.getSuffix(player.uniqueId)}")) + + var textComponent = Component.join(JoinConfiguration.noSeparators(), chatComponent, messageComponent) + textComponent = + textComponent.hoverEvent( + HoverEvent.hoverEvent( + HoverEvent.Action.SHOW_TEXT, + UtilitiesOG.trueogColorize("Click to translate this message"), + ) + ) + + val randomUUID = UUID.randomUUID() + textComponent = + textComponent.clickEvent( + ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/translatemessage $randomUUID 1") + ) + + TranslateMessage.chatMessages[randomUUID] = TranslateMessage.SentChatMessage(text, player) + + for (p in Bukkit.getOnlinePlayers()) { + if (p.hasPermission("chat-og.developer")) { + p.sendMessage(textComponent) + } + } + } } diff --git a/src/main/kotlin/nl/skbotnl/chatog/Helper.kt b/src/main/kotlin/nl/skbotnl/chatog/ChatUtil.kt old mode 100755 new mode 100644 similarity index 73% rename from src/main/kotlin/nl/skbotnl/chatog/Helper.kt rename to src/main/kotlin/nl/skbotnl/chatog/ChatUtil.kt index 4d9339f..6d3538d --- a/src/main/kotlin/nl/skbotnl/chatog/Helper.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/ChatUtil.kt @@ -1,9 +1,13 @@ package nl.skbotnl.chatog import dev.minn.jda.ktx.coroutines.await -import java.util.* +import java.util.HashMap +import java.util.UUID +import kotlin.collections.forEach import kotlin.concurrent.read +import me.clip.placeholderapi.PlaceholderAPI import net.kyori.adventure.text.Component +import net.kyori.adventure.text.TextComponent import net.kyori.adventure.text.event.ClickEvent import net.kyori.adventure.text.event.HoverEvent import net.kyori.adventure.text.format.TextColor @@ -13,14 +17,54 @@ import net.kyori.adventure.text.minimessage.tag.Tag import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver import net.kyori.adventure.text.minimessage.tag.standard.StandardTags +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer import net.trueog.utilitiesog.UtilitiesOG import nl.skbotnl.chatog.ChatOG.Companion.blocklistManager import nl.skbotnl.chatog.ChatOG.Companion.config import nl.skbotnl.chatog.ChatOG.Companion.discordBridgeLock import org.bukkit.Bukkit +import org.bukkit.Sound import org.bukkit.entity.Player -internal object Helper { +internal object ChatUtil { + fun getPlayerPart(player: Player, addSuffix: Boolean): TextComponent { + val playerPartString = getPlayerPartString(player) + + val suffix = + if (addSuffix) { + PlayerAffix.getSuffix(player.uniqueId) + } else { + "" + } + + return UtilitiesOG.trueogColorize(legacyToMm("$playerPartString$suffix")) + } + + fun getPlayerPartString(player: Player): String { + var playerPart = "${PlayerAffix.getPrefix(player.uniqueId)}${player.name}" + + if (PlaceholderAPI.setPlaceholders(player, "%simpleclans_clan_color_tag%") != "") { + playerPart = PlaceholderAPI.setPlaceholders(player, "&8[%simpleclans_clan_color_tag%&8] $playerPart") + } + + return playerPart + } + + val mentionRegex = Regex("@([A-Za-z0-9_]{3,16})") + + fun dingForMentions(dontDingFor: UUID, component: Component) { + val messageContent = PlainTextComponentSerializer.plainText().serialize(component) + + val namesToMention = mutableListOf() + mentionRegex.findAll(messageContent).iterator().forEach { namesToMention += it.groups[1]!!.value.lowercase() } + + for (player in Bukkit.getOnlinePlayers()) { + if (player.uniqueId == dontDingFor) continue + if (player.name.lowercase() !in namesToMention) continue + player.playSound(player, Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1f, 1f) + } + } + private var translateTimeout: MutableMap = HashMap() fun getTranslateTimeout(uuid: UUID): Long { @@ -70,14 +114,6 @@ internal object Helper { return legacyRegex.replace(text) { legacyToMmMap[it.groupValues[1].lowercase()] ?: it.value } } - private val colorRegex = Regex("[§&]?[§&]([0-9a-fk-orA-FK-OR])") - - fun removeColor(text: String): String { - var tempText = text - colorRegex.findAll(text).iterator().forEach { tempText = tempText.replace(it.value, "") } - return tempText - } - private val getHandle = Regex("@([a-z0-9_.]{2,32})") suspend fun convertMentions(text: String): String { @@ -103,7 +139,11 @@ internal object Helper { private val urlRegex = Regex("(.*?)((?:https?://)?[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}(?:/?[a-zA-Z]*)+)(.*)") - val noColorMm = MiniMessage.builder().editTags { b -> b.tag("a", Helper::createA) }.build() + val noColorMm = + MiniMessage.builder() + .tags(TagResolver.builder().build()) + .editTags { b -> b.tag("a", ChatUtil::createA) } + .build() val colorMm = MiniMessage.builder() @@ -117,7 +157,7 @@ internal object Helper { .resolver(StandardTags.gradient()) .build() ) - .editTags { b -> b.tag("a", Helper::createA) } + .editTags { b -> b.tag("a", ChatUtil::createA) } .build() fun createA(args: ArgumentQueue, @Suppress("unused") ctx: Context): Tag { @@ -136,11 +176,11 @@ internal object Helper { ) } - fun processText(text: String, player: Player) = processText(text, player, null) + fun processText(text: String, player: Player) = processText(text, player, null, false) - fun processText(text: String, username: String) = processText(text, null, username) + fun processText(text: String, username: String, color: Boolean) = processText(text, null, username, color) - private fun processText(text: String, player: Player?, username: String?): Component? { + private fun processText(text: String, player: Player?, username: String?, color: Boolean): Component? { val words: MutableList = mutableListOf() legacyToMm(text).split(" ").forEach { word -> @@ -148,7 +188,7 @@ internal object Helper { if (url != null) { val link = url.groups[2]?.value ?: "" - if (blocklistManager.checkUrl(link)) { + if (blocklistManager?.checkUrl(link) == true) { player?.sendMessage( UtilitiesOG.trueogColorize( "${config.prefix}: WARNING: You are not allowed to post links like that here." @@ -181,7 +221,11 @@ internal object Helper { return if (player?.hasPermission("chat-og.color") == true) { colorMm.deserialize(words.joinToString(" ")) } else { - noColorMm.deserialize(words.joinToString(" ")) + if (color) { + colorMm.deserialize(words.joinToString(" ")) + } else { + noColorMm.deserialize(words.joinToString(" ")) + } } } @@ -222,4 +266,15 @@ internal object Helper { return tempText } + + fun recolorComponent(component: Component, color: TextColor): Component { + var newComponent = component + if (component.color() == null) { + newComponent = component.color(color) + } + + val children = newComponent.children().map { recolorComponent(it, color) } + newComponent.children(children) + return newComponent + } } diff --git a/src/main/kotlin/nl/skbotnl/chatog/Config.kt b/src/main/kotlin/nl/skbotnl/chatog/Config.kt index 7c71df2..3449104 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/Config.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/Config.kt @@ -6,6 +6,8 @@ import org.bukkit.configuration.file.YamlConfiguration internal class Config private constructor() { lateinit var prefix: String + var blocklistEnabled = false + var blocklists = listOf() lateinit var redisUrl: String var openAIEnabled = false var openAIBaseUrl: String? = null @@ -14,6 +16,7 @@ internal class Config private constructor() { var discordEnabled = false var staffDiscordEnabled = false var premiumDiscordEnabled = false + var developerDiscordEnabled = false var status: String? = null var serverHasStartedMessage: String? = null var serverHasStoppedMessage: String? = null @@ -21,15 +24,20 @@ internal class Config private constructor() { var channelId: String? = null var staffChannelId: String? = null var premiumChannelId: String? = null + var developerChannelId: String? = null var guildId: String? = null var webhook: String? = null var staffWebhook: String? = null var premiumWebhook: String? = null + var developerWebhook: String? = null var listCommandName: String? = null var listCommandText: String? = null - var colorCodeRoles: List = listOf() - var roles: Set = setOf() + var useColorCodeRoles = false + var colorCodeRoles = listOf() + var roles = setOf() var roleMessageColor: MutableMap = mutableMapOf() + var rolesWithSuffixes = setOf() + var roleSuffix: MutableMap = mutableMapOf() data class RGBColor(val r: Int, val g: Int, val b: Int) @@ -50,6 +58,17 @@ internal class Config private constructor() { return null } + try { + config.blocklistEnabled = yamlConfig.get("blocklistEnabled") as Boolean + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"blocklistEnabled\" as a boolean") + return null + } + + if (config.blocklistEnabled) { + config.blocklists = yamlConfig.getStringList("blocklists") + } + try { config.redisUrl = yamlConfig.get("redisUrl") as String } catch (_: Exception) { @@ -108,6 +127,13 @@ internal class Config private constructor() { return null } + try { + config.developerDiscordEnabled = yamlConfig.get("developerDiscordEnabled") as Boolean + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"developerDiscordEnabled\" as a boolean") + return null + } + if (config.discordEnabled) { try { config.status = yamlConfig.get("status") as String @@ -183,6 +209,22 @@ internal class Config private constructor() { } } + if (config.developerDiscordEnabled) { + try { + config.developerChannelId = (yamlConfig.get("developerChannelId") as Long).toString() + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"developerChannelId\" as a long") + return null + } + + try { + config.developerWebhook = yamlConfig.get("developerWebhook") as String + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"developerWebhook\" as a string") + return null + } + } + try { config.webhook = yamlConfig.get("webhook") as String } catch (_: Exception) { @@ -204,69 +246,102 @@ internal class Config private constructor() { return null } + try { + config.useColorCodeRoles = yamlConfig.get("useColorCodeRoles") as Boolean + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"useColorCodeRoles\" as a boolean") + return null + } + config.colorCodeRoles = yamlConfig.getStringList("colorCodeRoles") config.roles = yamlConfig.getConfigurationSection("roles")?.getKeys(false) ?: setOf() + config.rolesWithSuffixes = yamlConfig.getConfigurationSection("roleSuffixes")?.getKeys(false) ?: setOf() } - if (config.roles.isEmpty()) { - config.roleMessageColor = mutableMapOf() - return config - } + if (config.roles.isNotEmpty()) { + val messageColors = + mapOf( + Pair("BLACK", NamedTextColor.BLACK), + Pair("DARK_BLUE", NamedTextColor.DARK_BLUE), + Pair("DARK_GREEN", NamedTextColor.DARK_GREEN), + Pair("DARK_AQUA", NamedTextColor.DARK_AQUA), + Pair("DARK_RED", NamedTextColor.DARK_RED), + Pair("DARK_PURPLE", NamedTextColor.DARK_PURPLE), + Pair("GOLD", NamedTextColor.GOLD), + Pair("GRAY", NamedTextColor.GRAY), + Pair("DARK_GRAY", NamedTextColor.DARK_GRAY), + Pair("BLUE", NamedTextColor.BLUE), + Pair("GREEN", NamedTextColor.GREEN), + Pair("AQUA", NamedTextColor.AQUA), + Pair("RED", NamedTextColor.RED), + Pair("LIGHT_PURPLE", NamedTextColor.LIGHT_PURPLE), + Pair("YELLOW", NamedTextColor.YELLOW), + Pair("WHITE", NamedTextColor.WHITE), + ) + config.roles.forEach { + val messageColorList = yamlConfig.getStringList("roles.$it.message_color") + config.roleMessageColor[it] = + if (messageColorList.isEmpty()) { + try { + yamlConfig.get("roles.$it.message_color") as String + } catch (_: Exception) { + ChatOG.plugin.logger.warning( + "Failed to parse config option \"role.$it.message_color\" as a string" + ) + return@forEach + } - val messageColors = - mapOf( - Pair("BLACK", NamedTextColor.BLACK), - Pair("DARK_BLUE", NamedTextColor.DARK_BLUE), - Pair("DARK_GREEN", NamedTextColor.DARK_GREEN), - Pair("DARK_AQUA", NamedTextColor.DARK_AQUA), - Pair("DARK_RED", NamedTextColor.DARK_RED), - Pair("DARK_PURPLE", NamedTextColor.DARK_PURPLE), - Pair("GOLD", NamedTextColor.GOLD), - Pair("GRAY", NamedTextColor.GRAY), - Pair("DARK_GRAY", NamedTextColor.DARK_GRAY), - Pair("BLUE", NamedTextColor.BLUE), - Pair("GREEN", NamedTextColor.GREEN), - Pair("AQUA", NamedTextColor.AQUA), - Pair("RED", NamedTextColor.RED), - Pair("LIGHT_PURPLE", NamedTextColor.LIGHT_PURPLE), - Pair("YELLOW", NamedTextColor.YELLOW), - Pair("WHITE", NamedTextColor.WHITE), - ) - config.roles.forEach { - val messageColorList = yamlConfig.getStringList("roles.$it.message_color") - config.roleMessageColor[it] = - if (messageColorList.isEmpty()) { - try { - yamlConfig.get("roles.$it.message_color") as String - } catch (_: Exception) { - return@forEach + if (!messageColors.contains(messageColorList[0].uppercase())) { + ChatOG.plugin.logger.severe( + "The message color for \"$it\" (\"${messageColorList[0]}\") is invalid." + ) + return@forEach + } + + messageColors[messageColorList[0].uppercase()]!! + } else { + if (messageColorList.size != 3) { + ChatOG.plugin.logger.severe( + "The message color for \"$it\" is not a color or an RGB value." + ) + return@forEach + } + + messageColorList.forEach colorForEach@{ colorInList -> + try { + colorInList.toUByte() + } catch (_: Exception) { + ChatOG.plugin.logger.severe("The RGB value for \"$it\" is invalid.") + return@forEach + } + } + RGBColor( + messageColorList[0].toInt(), + messageColorList[1].toInt(), + messageColorList[2].toInt(), + ) } + } + } else { + config.roleMessageColor = mutableMapOf() + } - if (!messageColors.contains(messageColorList[0].uppercase())) { - ChatOG.plugin.logger.severe( - "The message color for \"$it\" (\"${messageColorList[0]}\") is invalid." + if (config.rolesWithSuffixes.isNotEmpty()) { + config.rolesWithSuffixes.forEach { + val suffixList = + try { + yamlConfig.get("roleSuffixes.$it.suffix") as String + } catch (_: Exception) { + ChatOG.plugin.logger.warning( + "Failed to parse config option \"roleSuffixes.$it.suffix\" as a string" ) return@forEach } - - messageColors[messageColorList[0].uppercase()]!! - } else { - if (messageColorList.size != 3) { - ChatOG.plugin.logger.severe("The message color for \"$it\" is not a color or an RGB value.") - return@forEach - } - - messageColorList.forEach colorForEach@{ colorInList -> - try { - colorInList.toUByte() - } catch (_: Exception) { - ChatOG.plugin.logger.severe("The RGB value for \"$it\" is invalid.") - return@forEach - } - } - RGBColor(messageColorList[0].toInt(), messageColorList[1].toInt(), messageColorList[2].toInt()) - } + config.roleSuffix[it] = suffixList + } + } else { + config.roleSuffix = mutableMapOf() } return config diff --git a/src/main/kotlin/nl/skbotnl/chatog/DiscordBridge.kt b/src/main/kotlin/nl/skbotnl/chatog/DiscordBridge.kt index 1a27195..0dc73f9 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/DiscordBridge.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/DiscordBridge.kt @@ -29,8 +29,9 @@ import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextColor import net.trueog.utilitiesog.UtilitiesOG import nl.skbotnl.chatog.ChatOG.Companion.config -import nl.skbotnl.chatog.Helper.convertMentions -import nl.skbotnl.chatog.Helper.stripGroupMentions +import nl.skbotnl.chatog.ChatUtil.convertMentions +import nl.skbotnl.chatog.ChatUtil.recolorComponent +import nl.skbotnl.chatog.ChatUtil.stripGroupMentions import nl.skbotnl.chatog.commands.TranslateMessage import org.bukkit.Bukkit import org.bukkit.entity.Player @@ -40,6 +41,7 @@ internal class DiscordBridge private constructor() { private lateinit var webhook: WebhookClient private var staffWebhook: WebhookClient? = null private var premiumWebhook: WebhookClient? = null + private var developerWebhook: WebhookClient? = null companion object { fun create(): DiscordBridge? { @@ -72,6 +74,17 @@ internal class DiscordBridge private constructor() { } else if (config.premiumDiscordEnabled) { ChatOG.plugin.logger.warning("You have enabled premium Discord but have not set up the premium webhook") } + if (config.developerWebhook != null) { + try { + discordBridge.developerWebhook = WebhookClient.withUrl(config.developerWebhook!!) + } catch (_: IllegalArgumentException) { + ChatOG.plugin.logger.warning("Config option \"developer\" is invalid") + } + } else if (config.premiumDiscordEnabled) { + ChatOG.plugin.logger.warning( + "You have enabled developer Discord but have not set up the developer webhook" + ) + } if (config.botToken == null) { ChatOG.plugin.logger.severe("You have enabled Discord but have not set up the bot token") @@ -162,7 +175,8 @@ internal class DiscordBridge private constructor() { if ( it.channel.id != config.channelId && (if (config.staffDiscordEnabled) it.channel.id != config.staffChannelId else true) && - (if (config.premiumDiscordEnabled) it.channel.id != config.premiumChannelId else true) + (if (config.premiumDiscordEnabled) it.channel.id != config.premiumChannelId else true) && + (if (config.developerDiscordEnabled) it.channel.id != config.developerChannelId else true) ) { return@listener } @@ -185,6 +199,7 @@ internal class DiscordBridge private constructor() { val roles = member.roles val topRole = roles.maxByOrNull { role -> role.positionRaw } + val sortedRoles = member.roles.sortedByDescending { role -> role.positionRaw } val discordComponent = Component.text("Discord: ").color(TextColor.color(88, 101, 242)) val userComponent: TextComponent = @@ -198,13 +213,7 @@ internal class DiscordBridge private constructor() { if (config.roles.isEmpty()) { NamedTextColor.GRAY } else { - val roleId = - message.guild - .getRoleById( - config.roles - .filter { role -> topRole!!.id == message.guild.getRoleById(role)?.id }[0] - ) - ?.id + val roleId = sortedRoles.first { role -> role.id in config.roles }?.id if (roleId != null) { val roleColor = config.roleMessageColor[roleId] @@ -216,7 +225,19 @@ internal class DiscordBridge private constructor() { } else NamedTextColor.GRAY } - val messageComponents = mutableListOf(Component.text(">")) + val suffix = + if (config.rolesWithSuffixes.isEmpty()) { + ">" + } else { + val roleId = sortedRoles.first { role -> role.id in config.rolesWithSuffixes }?.id + if (roleId != null) { + config.roleSuffix[roleId]!! + } else { + ">" + } + } + + val messageComponents = mutableListOf(UtilitiesOG.trueogColorize(suffix)) val attachmentComponents = mutableListOf() @@ -243,19 +264,30 @@ internal class DiscordBridge private constructor() { } } + val useColor = + if (config.useColorCodeRoles) { + roles.any { role -> role.id in config.colorCodeRoles } + } else { + true + } + if (message.contentDisplay != "") { messageComponents += - Helper.processText( + recolorComponent( + ChatUtil.processText( EmojiConverter.replaceEmojisWithNames(message.contentDisplay), "@${user.name}", - ) - ?.color(messageColor) ?: return@listener + useColor, + ) ?: return@listener, + messageColor, + ) } val contentComponent = Component.join( JoinConfiguration.separator(Component.text(" ")), - messageComponents + attachmentComponents, + Component.join(JoinConfiguration.noSeparators(), messageComponents), + Component.join(JoinConfiguration.noSeparators(), attachmentComponents), ) var replyComponent = Component.text("") @@ -297,6 +329,18 @@ internal class DiscordBridge private constructor() { ) } + config.developerChannelId -> { + val developerComponent = Component.text("DEVELOPER | ").color(NamedTextColor.AQUA) + Component.join( + JoinConfiguration.noSeparators(), + discordComponent, + developerComponent, + replyComponent, + userComponent, + contentComponent, + ) + } + else -> { Component.join( JoinConfiguration.noSeparators(), @@ -351,7 +395,7 @@ internal class DiscordBridge private constructor() { message.contentDisplay, member.effectiveName, Component.join(JoinConfiguration.noSeparators(), discordComponent, userComponent), - Component.text("> "), + Component.text("$suffix "), ) } return discordBridge @@ -381,7 +425,7 @@ internal class DiscordBridge private constructor() { suspend fun sendMessage(message: String, player: Player) { val webhookMessage = WebhookMessageBuilder() - .setUsername(UtilitiesOG.stripFormatting(ChatHelper.getPlayerPartString(player))) + .setUsername(UtilitiesOG.stripFormatting(ChatUtil.getPlayerPartString(player))) .setContent(UtilitiesOG.stripFormatting(stripGroupMentions(convertMentions(message)))) .setAvatarUrl("https://minotar.net/helm/${player.uniqueId}.png") @@ -435,6 +479,24 @@ internal class DiscordBridge private constructor() { premiumWebhook!!.send(webhookMessage.build()) } + suspend fun sendDeveloperMessage(message: String, name: String, uuid: UUID?) { + if (!config.developerDiscordEnabled) return + + if (developerWebhook == null) { + ChatOG.plugin.logger.warning("developerWebhook has not been set or is invalid") + return + } + + val webhookMessage = + WebhookMessageBuilder().apply { + setUsername(UtilitiesOG.stripFormatting(name)) + setContent(UtilitiesOG.stripFormatting(stripGroupMentions((convertMentions(message))))) + if (uuid != null) setAvatarUrl("https://minotar.net/helm/$uuid.png") + } + + developerWebhook!!.send(webhookMessage.build()) + } + fun sendEmbed(message: String, uuid: UUID?, color: Int?) { var iconUrl: String? = null if (uuid != null) { diff --git a/src/main/kotlin/nl/skbotnl/chatog/Events.kt b/src/main/kotlin/nl/skbotnl/chatog/Events.kt index dc917b2..863be70 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/Events.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/Events.kt @@ -21,8 +21,7 @@ import net.trueog.utilitiesog.UtilitiesOG import nl.skbotnl.chatog.ChatOG.Companion.config import nl.skbotnl.chatog.ChatOG.Companion.discordBridgeLock import nl.skbotnl.chatog.ChatSystem.ChatType -import nl.skbotnl.chatog.Helper.legacyToMm -import nl.skbotnl.chatog.Helper.removeColor +import nl.skbotnl.chatog.ChatUtil.legacyToMm import nl.skbotnl.chatog.commands.TranslateMessage import org.bukkit.Bukkit import org.bukkit.event.EventHandler @@ -43,7 +42,7 @@ internal class Events : Listener { return } - val playerPartString = ChatHelper.getPlayerPartString(event.player) + val playerPartString = ChatUtil.getPlayerPartString(event.player) ChatOG.scope.launch { discordBridgeLock.read { @@ -67,12 +66,12 @@ internal class Events : Listener { return } - val playerPartString = ChatHelper.getPlayerPartString(event.player) + val playerPartString = ChatUtil.getPlayerPartString(event.player) ChatOG.scope.launch { discordBridgeLock.read { ChatOG.discordBridge?.sendEmbed( - "${removeColor(playerPartString)} has left the game. ${ + "$playerPartString has left the game. ${ Bukkit.getOnlinePlayers().count() - 1 } player(s) online.", event.player.uniqueId, @@ -91,14 +90,14 @@ internal class Events : Listener { return } - val playerPartString = ChatHelper.getPlayerPartString(event.player) + val playerPartString = ChatUtil.getPlayerPartString(event.player) val reason = PlainTextComponentSerializer.plainText().serialize(event.reason()) ChatOG.scope.launch { discordBridgeLock.read { ChatOG.discordBridge?.sendEmbed( - "${removeColor(playerPartString)} was kicked with reason: \"${reason}\". ${ + "$playerPartString was kicked with reason: \"${reason}\". ${ Bukkit.getOnlinePlayers().count() - 1 } player(s) online.", event.player.uniqueId, @@ -117,7 +116,7 @@ internal class Events : Listener { return } - val playerPartString = ChatHelper.getPlayerPartString(event.player) + val playerPartString = ChatUtil.getPlayerPartString(event.player) val advancementTitleKey = event.advancement.display?.title() ?: return val advancementTitle = PlainTextComponentSerializer.plainText().serialize(advancementTitleKey) @@ -135,7 +134,7 @@ internal class Events : Listener { ChatOG.scope.launch { discordBridgeLock.read { ChatOG.discordBridge?.sendEmbed( - "${removeColor(playerPartString)} $advancementMessage.", + "$playerPartString $advancementMessage.", event.player.uniqueId, 0xFFFF00, ) @@ -169,23 +168,30 @@ internal class Events : Listener { val eventMessage = event.message() as TextComponent - if (ChatSystem.inChat[event.player.uniqueId] == ChatType.STAFF_CHAT) { - ChatSystem.sendMessageInStaffChat(event.player, eventMessage.content()) - return - } - if (ChatSystem.inChat[event.player.uniqueId] == ChatType.PREMIUM_CHAT) { - ChatSystem.sendMessageInPremiumChat(event.player, eventMessage.content()) - return + when (ChatSystem.inChat[event.player.uniqueId]) { + ChatType.STAFF_CHAT -> { + ChatSystem.sendMessageInStaffChat(event.player, eventMessage.content()) + return + } + ChatType.PREMIUM_CHAT -> { + ChatSystem.sendMessageInPremiumChat(event.player, eventMessage.content()) + return + } + ChatType.DEVELOPER_CHAT -> { + ChatSystem.sendMessageInDeveloperChat(event.player, eventMessage.content()) + return + } + else -> {} } - val discordMessageString = Helper.convertEmojis(eventMessage.content()) + val discordMessageString = ChatUtil.convertEmojis(eventMessage.content()) ChatOG.scope.launch { discordBridgeLock.read { ChatOG.discordBridge?.sendMessage(discordMessageString, event.player) } } - val playerPart = ChatHelper.getPlayerPart(event.player, true) + val playerPart = ChatUtil.getPlayerPart(event.player, true) - val messageComponent = Helper.processText(eventMessage.content(), event.player) + val messageComponent = ChatUtil.processText(eventMessage.content(), event.player) if (messageComponent == null) { return } @@ -207,6 +213,8 @@ internal class Events : Listener { event.viewers().forEach { it.sendMessage(textComponent) } + ChatUtil.dingForMentions(event.player.uniqueId, messageComponent) + TranslateMessage.chatMessages[randomUUID] = TranslateMessage.SentChatMessage(eventMessage.content(), event.player) } @@ -224,7 +232,7 @@ internal class Events : Listener { ChatOG.scope.launch { discordBridgeLock.read { ChatOG.discordBridge?.sendEmbed( - removeColor((event.deathMessage() as TextComponent).content()), + (event.deathMessage() as TextComponent).content(), event.player.uniqueId, 0xFF0000, ) @@ -254,7 +262,7 @@ internal class Events : Listener { ChatOG.scope.launch { discordBridgeLock.read { - ChatOG.discordBridge?.sendEmbed(removeColor(translatedDeathMessage), event.player.uniqueId, 0xFF0000) + ChatOG.discordBridge?.sendEmbed(translatedDeathMessage, event.player.uniqueId, 0xFF0000) } } } diff --git a/src/main/kotlin/nl/skbotnl/chatog/LanguageDatabase.kt b/src/main/kotlin/nl/skbotnl/chatog/LanguageDatabase.kt index 6d3dafb..edcaa57 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/LanguageDatabase.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/LanguageDatabase.kt @@ -33,4 +33,8 @@ internal class LanguageDatabase { commands.set("chatog:language:$uuid", language) connection.close() } + + fun shutdown() { + redisClient.shutdown() + } } diff --git a/src/main/kotlin/nl/skbotnl/chatog/PlayerAffix.kt b/src/main/kotlin/nl/skbotnl/chatog/PlayerAffix.kt index d42189c..e93c030 100644 --- a/src/main/kotlin/nl/skbotnl/chatog/PlayerAffix.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/PlayerAffix.kt @@ -1,41 +1,9 @@ package nl.skbotnl.chatog import java.util.* +import nl.skbotnl.chatog.ChatUtil.legacyToMm internal object PlayerAffix { - private val legacyToMmMap = - mapOf( - "0" to "", - "1" to "", - "2" to "", - "3" to "", - "4" to "", - "5" to "", - "6" to "", - "7" to "", - "8" to "", - "9" to "", - "a" to "", - "b" to "", - "c" to "", - "d" to "", - "e" to "", - "f" to "", - "k" to "", - "l" to "", - "m" to "", - "n" to "", - "o" to "", - "r" to "", - "*" to "", - ) - - val legacyRegex = Regex("[§&]([0-9a-fk-or*])", RegexOption.IGNORE_CASE) - - fun legacyToMm(text: String): String { - return legacyRegex.replace(text) { legacyToMmMap[it.groupValues[1].lowercase()] ?: it.value } - } - fun getPrefix(uuid: UUID): String { var user = ChatOG.luckPerms.userManager.getUser(uuid) if (user == null) { diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/ChatConfigReload.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/ChatConfigReload.kt index 766ebea..bb936d5 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/commands/ChatConfigReload.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/ChatConfigReload.kt @@ -3,13 +3,17 @@ package nl.skbotnl.chatog.commands import kotlin.concurrent.write import kotlinx.coroutines.launch import net.trueog.utilitiesog.UtilitiesOG +import nl.skbotnl.chatog.BlocklistManager import nl.skbotnl.chatog.ChatOG +import nl.skbotnl.chatog.ChatOG.Companion.blocklistManager import nl.skbotnl.chatog.ChatOG.Companion.config import nl.skbotnl.chatog.ChatOG.Companion.discordBridgeLock import nl.skbotnl.chatog.ChatOG.Companion.scope +import nl.skbotnl.chatog.ChatOG.Companion.translator import nl.skbotnl.chatog.Config import nl.skbotnl.chatog.DiscordBridge import nl.skbotnl.chatog.LanguageDatabase +import nl.skbotnl.chatog.OpenAI import org.bukkit.Bukkit import org.bukkit.command.Command import org.bukkit.command.CommandExecutor @@ -29,6 +33,27 @@ internal class ChatConfigReload : CommandExecutor { return true } + if (config.blocklistEnabled) { + blocklistManager = BlocklistManager() + } + + translator = + if (config.openAIEnabled) { + if (config.openAIBaseUrl == null) { + ChatOG.plugin.logger.warning( + "You have enabled OpenAI translation but have not set up the base url, not enabling the translator" + ) + null + } else if (config.openAIApiKey == null) { + ChatOG.plugin.logger.warning( + "You have enabled OpenAI translation but have not set up the api key, not enabling the translator" + ) + null + } else { + OpenAI() + } + } else null + ChatOG.languageDatabase = LanguageDatabase() if (ChatOG.languageDatabase.testConnection()) { ChatOG.plugin.logger.severe("Could not connect to Redis") diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/DeveloperChat.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/DeveloperChat.kt new file mode 100644 index 0000000..6e3106f --- /dev/null +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/DeveloperChat.kt @@ -0,0 +1,49 @@ +package nl.skbotnl.chatog.commands + +import kotlin.collections.set +import net.trueog.utilitiesog.UtilitiesOG +import nl.skbotnl.chatog.ChatOG.Companion.config +import nl.skbotnl.chatog.ChatSystem +import nl.skbotnl.chatog.ChatSystem.ChatType +import org.bukkit.command.Command +import org.bukkit.command.CommandExecutor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +class DeveloperChat : CommandExecutor { + override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array?): Boolean { + if (sender !is Player) { + sender.sendMessage("You can only execute this command as a player.") + return true + } + + if (!sender.hasPermission("chat-og.developer")) { + sender.sendMessage( + UtilitiesOG.trueogColorize( + "${config.prefix}: You do not have permission to run this command." + ) + ) + return true + } + + if (args == null || args.isEmpty()) { + if (ChatSystem.inChat[sender.uniqueId] == ChatType.DEVELOPER_CHAT) { + ChatSystem.inChat[sender.uniqueId] = ChatType.GENERAL_CHAT + + sender.sendMessage( + UtilitiesOG.trueogColorize("${config.prefix}: You are now talking in the general chat.") + ) + return true + } + ChatSystem.inChat[sender.uniqueId] = ChatType.DEVELOPER_CHAT + sender.sendMessage( + UtilitiesOG.trueogColorize("${config.prefix}: You are now talking in the developer chat.") + ) + return true + } + + ChatSystem.sendMessageInDeveloperChat(sender, args.joinToString(separator = " ")) + + return true + } +} diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/GeneralChat.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/GeneralChat.kt new file mode 100644 index 0000000..cba5b2a --- /dev/null +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/GeneralChat.kt @@ -0,0 +1,41 @@ +package nl.skbotnl.chatog.commands + +import kotlin.collections.set +import net.trueog.utilitiesog.UtilitiesOG +import nl.skbotnl.chatog.ChatOG.Companion.config +import nl.skbotnl.chatog.ChatSystem +import nl.skbotnl.chatog.ChatSystem.ChatType +import org.bukkit.command.Command +import org.bukkit.command.CommandExecutor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +class GeneralChat : CommandExecutor { + override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array?): Boolean { + if (sender !is Player) { + sender.sendMessage("You can only execute this command as a player.") + return true + } + + if (args == null || args.isEmpty()) { + if (ChatSystem.inChat[sender.uniqueId] != ChatType.GENERAL_CHAT) { + ChatSystem.inChat[sender.uniqueId] = ChatType.GENERAL_CHAT + + sender.sendMessage( + UtilitiesOG.trueogColorize("${config.prefix}: You are now talking in the general chat.") + ) + return true + } + sender.sendMessage( + UtilitiesOG.trueogColorize("${config.prefix}: You are already talking in the general chat.") + ) + return true + } + + val originalChat = ChatSystem.inChat[sender.uniqueId] + ChatSystem.inChat[sender.uniqueId] = ChatType.GENERAL_CHAT + sender.chat(args.joinToString(separator = " ")) + if (originalChat != null) ChatSystem.inChat[sender.uniqueId] = originalChat + return true + } +} diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/PremiumChat.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/PremiumChat.kt index d9dec83..8212f15 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/commands/PremiumChat.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/PremiumChat.kt @@ -28,13 +28,13 @@ internal class PremiumChat : CommandExecutor { ChatSystem.inChat[sender.uniqueId] = ChatType.GENERAL_CHAT sender.sendMessage( - UtilitiesOG.trueogColorize("${config.prefix}: You are now talking in normal chat.") + UtilitiesOG.trueogColorize("${config.prefix}: You are now talking in the general chat.") ) return true } ChatSystem.inChat[sender.uniqueId] = ChatType.PREMIUM_CHAT sender.sendMessage( - UtilitiesOG.trueogColorize("${config.prefix}: You are now talking in premium chat.") + UtilitiesOG.trueogColorize("${config.prefix}: You are now talking in the premium chat.") ) return true } diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/PrivateMessage.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/PrivateMessage.kt index 01bdd64..110e0ae 100644 --- a/src/main/kotlin/nl/skbotnl/chatog/commands/PrivateMessage.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/PrivateMessage.kt @@ -9,7 +9,7 @@ import net.kyori.adventure.text.event.HoverEvent import net.trueog.utilitiesog.UtilitiesOG import nl.skbotnl.chatog.ChatOG.Companion.config import nl.skbotnl.chatog.ChatOG.Companion.lastMessagedMap -import nl.skbotnl.chatog.Helper +import nl.skbotnl.chatog.ChatUtil import org.bukkit.Bukkit import org.bukkit.command.Command import org.bukkit.command.CommandExecutor @@ -57,7 +57,7 @@ internal class PrivateMessage : CommandExecutor { TranslateMessage.pmMessages[randomUUID] = TranslateMessage.SentPMMessage(message, sender.uniqueId, toPlayer.uniqueId) - val messageComponent = Helper.processText(message, sender) + val messageComponent = ChatUtil.processText(message, sender) if (messageComponent == null) { return true } diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/Reply.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/Reply.kt index 8dbcf9a..1a3e20a 100644 --- a/src/main/kotlin/nl/skbotnl/chatog/commands/Reply.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/Reply.kt @@ -9,7 +9,7 @@ import net.kyori.adventure.text.event.HoverEvent import net.trueog.utilitiesog.UtilitiesOG import nl.skbotnl.chatog.ChatOG.Companion.config import nl.skbotnl.chatog.ChatOG.Companion.lastMessagedMap -import nl.skbotnl.chatog.Helper +import nl.skbotnl.chatog.ChatUtil import org.bukkit.Bukkit import org.bukkit.command.Command import org.bukkit.command.CommandExecutor @@ -53,7 +53,7 @@ internal class Reply : CommandExecutor { TranslateMessage.pmMessages[randomUUID] = TranslateMessage.SentPMMessage(message, sender.uniqueId, toPlayer.uniqueId) - val messageComponent = Helper.processText(message, sender) + val messageComponent = ChatUtil.processText(message, sender) if (messageComponent == null) { return true } diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/StaffChat.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/StaffChat.kt index 54843d4..d108812 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/commands/StaffChat.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/StaffChat.kt @@ -15,6 +15,7 @@ internal class StaffChat : CommandExecutor { sender.sendMessage("You can only execute this command as a player.") return true } + if (!sender.hasPermission("chat-og.staff")) { sender.sendMessage( UtilitiesOG.trueogColorize( @@ -23,12 +24,13 @@ internal class StaffChat : CommandExecutor { ) return true } + if (args == null || args.isEmpty()) { if (ChatSystem.inChat[sender.uniqueId] == ChatType.STAFF_CHAT) { ChatSystem.inChat[sender.uniqueId] = ChatType.GENERAL_CHAT sender.sendMessage( - UtilitiesOG.trueogColorize("${config.prefix}: You are now talking in normal chat.") + UtilitiesOG.trueogColorize("${config.prefix}: You are now talking in general chat.") ) return true } diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateMessage.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateMessage.kt index ebe4f59..2825fbf 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateMessage.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateMessage.kt @@ -9,8 +9,8 @@ import net.kyori.adventure.text.format.NamedTextColor import net.trueog.utilitiesog.UtilitiesOG import nl.skbotnl.chatog.ChatOG import nl.skbotnl.chatog.ChatOG.Companion.config -import nl.skbotnl.chatog.Helper -import nl.skbotnl.chatog.Helper.legacyToMm +import nl.skbotnl.chatog.ChatUtil +import nl.skbotnl.chatog.ChatUtil.legacyToMm import nl.skbotnl.chatog.PlayerAffix import org.bukkit.Bukkit import org.bukkit.command.Command @@ -56,7 +56,7 @@ internal class TranslateMessage : CommandExecutor { } val player: Player = sender - if (Helper.getTranslateTimeout(player.uniqueId) != 0L) { + if (ChatUtil.getTranslateTimeout(player.uniqueId) != 0L) { player.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}: You're doing that too fast.")) return true } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 0cf900d..58e3343 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,6 +1,11 @@ # ---General--- # MiniMessage-formatted prefix (https://docs.advntr.dev/minimessage/format.html) prefix: [Chat-OG] +blocklistEnabled: true +# Only blocklists with just a list of domains +blocklists: + - https://raw.githubusercontent.com/hagezi/dns-blocklists/main/domains/multi.txt + - https://raw.githubusercontent.com/hagezi/dns-blocklists/main/wildcard/nsfw-onlydomains.txt # ---Redis--- # Redis URL according to https://redis.github.io/lettuce/user-guide/connecting-redis/#uri-syntax @@ -20,6 +25,7 @@ model: "" discordEnabled: false staffDiscordEnabled: false premiumDiscordEnabled: false +developerDiscordEnabled: false status: Minecraft serverHasStartedMessage: The server has started serverHasStoppedMessage: The server has stopped @@ -28,13 +34,16 @@ guildId: channelId: staffChannelId: premiumChannelId: +developerChannelId: webhook: -staffWebhook: -premiumWebhook: +staffWebhook: +premiumWebhook: +developerWebhook: listCommandName: list # Available placeholders: %onlineplayers%, %maxplayers% listCommandText: "%onlineplayers% player(s) online:" +useColorCodeRoles: false # Configure which roles can use color codes with Discord -> Minecraft # For example: # @@ -47,10 +56,17 @@ listCommandText: "%onlineplayers% player(s) online:" # 1234567891234567890: # message_color: RED # -# message_color can be one of these: BLACK, DARK_BLUE, DARK_GREEN, DARK_AQUA, DARK_RED, DARK_PURPLE, GOLD, GRAY, DARK_GRAY, BLUE, GREEN, AQUA, RED, LIGHT_PURPLE, YELLOW, WHITE +# message_color can be one of the following: BLACK, DARK_BLUE, DARK_GREEN, DARK_AQUA, DARK_RED, DARK_PURPLE, GOLD, GRAY, DARK_GRAY, BLUE, GREEN, AQUA, RED, LIGHT_PURPLE, YELLOW, WHITE # # You can also use RGB for the color: # # roles: # 1234567891234567890: # message_color: [255, 255, 255] + +# Configure the suffix for roles (has to include the space). color codes are allowed. +# For example: + +# roleSuffixes: +# 1234567891234567890: +# suffix: ": " \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 75dcbd0..1fbb15b 100755 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -20,6 +20,12 @@ commands: chatconfigreload: description: Reload Chat-OG's config usage: /chatconfigreload + gc: + description: Toggle or talk in general chat + usage: /gc OR /gc + g: + description: Toggle or talk in general chat + usage: /g OR /g sc: description: Toggle or talk in staff chat usage: /sc OR /sc @@ -28,10 +34,16 @@ commands: usage: /s OR /s pc: description: Toggle or talk in premium chat - usage: /p OR /p + usage: /pc OR /pc p: description: Toggle or talk in premium chat usage: /p OR /p + dc: + description: Toggle or talk in developer chat + usage: /dc OR /dc + d: + description: Toggle or talk in developer chat + usage: /d OR /d msg: description: Send a private message to a player usage: /msg