diff --git a/build.gradle.kts b/build.gradle.kts index 2981eff..59eb166 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -37,6 +37,7 @@ dependencies { compileOnly("net.essentialsx:EssentialsX:2.21.0") compileOnly(files("libs/AnnouncerPlus-1.4.1.jar")) compileOnly(project(":libs:Utilities-OG")) + compileOnly("net.luckperms:api:5.5") implementation("net.dv8tion:JDA:5.5.1") implementation("club.minnced:jda-ktx:0.12.0") diff --git a/libs/Utilities-OG b/libs/Utilities-OG index ed7f99d..fc93c2e 160000 --- a/libs/Utilities-OG +++ b/libs/Utilities-OG @@ -1 +1 @@ -Subproject commit ed7f99d354cf6cf2eff115cfbb2772c6be23af14 +Subproject commit fc93c2ed4f748c8f5e871e06cf18a349956f8879 diff --git a/src/main/kotlin/nl/skbotnl/chatog/BlocklistManager.kt b/src/main/kotlin/nl/skbotnl/chatog/BlocklistManager.kt index 174321b..5d5e192 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/BlocklistManager.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/BlocklistManager.kt @@ -5,14 +5,13 @@ import java.util.concurrent.TimeUnit import kotlinx.coroutines.delay import kotlinx.coroutines.launch -object BlocklistManager { +class BlocklistManager { + private val lock = Any() private var blockList = mutableListOf() - fun load() { + init { ChatOG.plugin.logger.info("Loading the blocklists...") - refresh() - ChatOG.plugin.logger.info("Loaded the blocklists!") ChatOG.scope.launch { @@ -24,30 +23,22 @@ object BlocklistManager { } private fun refresh() { + blockList.clear() URI("https://raw.githubusercontent.com/hagezi/dns-blocklists/main/domains/multi.txt") .toURL() .openStream() .use { input -> input.bufferedReader().use { bufferedReader -> - bufferedReader.lines().skip(11).forEach { blockList += it } + synchronized(lock) { bufferedReader.lines().forEach { if (!it.startsWith("#")) blockList.add(it) } } } } } - private val urlRegex = Regex("^(https?|ftp|file)://([-a-zA-Z0-9+&@#/%?=~_|!:,.;]*?[^/]*)") + private val urlRegex = Regex("(?:https?://)?([a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})") fun checkUrl(url: String): Boolean { - var baseUrl: String? = null - urlRegex.findAll(url).iterator().forEach { urlMatch -> baseUrl = urlMatch.groups[2]?.value } - if (baseUrl == null) { - return false - } - - blockList.forEach { - if (it == baseUrl) { - return true - } - } - return false + val match = urlRegex.find(url) ?: return false + val baseUrl = match.groups[1]?.value ?: return false + return synchronized(lock) { blockList.contains(baseUrl) } } } diff --git a/src/main/kotlin/nl/skbotnl/chatog/ChatAPI.kt b/src/main/kotlin/nl/skbotnl/chatog/ChatAPI.kt new file mode 100644 index 0000000..f9fb2c5 --- /dev/null +++ b/src/main/kotlin/nl/skbotnl/chatog/ChatAPI.kt @@ -0,0 +1,87 @@ +package nl.skbotnl.chatog + +import java.util.UUID +import kotlin.concurrent.read +import kotlinx.coroutines.launch +import nl.skbotnl.chatog.ChatOG.Companion.discordBridgeLock +import nl.skbotnl.chatog.ChatOG.Companion.scope +import org.bukkit.entity.Player + +class ChatAPI { + @Suppress("unused") + fun isDiscordEnabled(): Boolean { + return ChatOG.config.discordEnabled + } + + @Suppress("unused") + fun isStaffDiscordEnabled(): Boolean { + return ChatOG.config.staffDiscordEnabled + } + + @Suppress("unused") + fun isPremiumDiscordEnabled(): Boolean { + return ChatOG.config.premiumDiscordEnabled + } + + @Suppress("unused") + fun sendMessageWithBot(message: String) { + if (!ChatOG.config.discordEnabled) return + scope.launch { + discordBridgeLock.read { + val discordBridge = ChatOG.discordBridge + discordBridge!!.sendMessageWithBot(message) + } + } + return + } + + @Suppress("unused") + fun sendMessage(message: String, player: Player) { + if (!ChatOG.config.discordEnabled) return + discordBridgeLock.read { + val discordBridge = ChatOG.discordBridge + scope.launch { discordBridge!!.sendMessage(message, player) } + } + return + } + + @Suppress("unused") + fun sendMessage(message: String, name: String, uuid: UUID?) { + if (!ChatOG.config.discordEnabled) return + discordBridgeLock.read { + val discordBridge = ChatOG.discordBridge + scope.launch { discordBridge!!.sendMessage(message, name, uuid) } + } + return + } + + @Suppress("unused") + fun sendStaffMessage(message: String, name: String, uuid: UUID?) { + if (!ChatOG.config.discordEnabled) return + discordBridgeLock.read { + val discordBridge = ChatOG.discordBridge + scope.launch { discordBridge!!.sendStaffMessage(message, name, uuid) } + } + return + } + + @Suppress("unused") + fun sendPremiumMessage(message: String, name: String, uuid: UUID?) { + if (!ChatOG.config.discordEnabled) return + discordBridgeLock.read { + val discordBridge = ChatOG.discordBridge + scope.launch { discordBridge!!.sendPremiumMessage(message, name, uuid) } + } + return + } + + @Suppress("unused") + fun sendEmbed(message: String, uuid: UUID?, color: Int?) { + if (!ChatOG.config.discordEnabled) return + discordBridgeLock.read { + val discordBridge = ChatOG.discordBridge + scope.launch { discordBridge!!.sendEmbed(message, uuid, color) } + } + return + } +} diff --git a/src/main/kotlin/nl/skbotnl/chatog/ChatHelper.kt b/src/main/kotlin/nl/skbotnl/chatog/ChatHelper.kt new file mode 100644 index 0000000..2a9606e --- /dev/null +++ b/src/main/kotlin/nl/skbotnl/chatog/ChatHelper.kt @@ -0,0 +1,32 @@ +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 e6be7da..68c963f 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/ChatOG.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/ChatOG.kt @@ -2,66 +2,61 @@ package nl.skbotnl.chatog import com.earth2me.essentials.Essentials import java.util.* +import java.util.concurrent.locks.ReentrantReadWriteLock +import kotlin.concurrent.read +import kotlin.concurrent.write import kotlinx.coroutines.* -import net.milkbowl.vault.chat.Chat +import net.luckperms.api.LuckPerms import nl.skbotnl.chatog.commands.* import org.bukkit.Bukkit +import org.bukkit.plugin.ServicePriority import org.bukkit.plugin.java.JavaPlugin -class ChatOG : JavaPlugin() { +internal class ChatOG : JavaPlugin() { @OptIn(DelicateCoroutinesApi::class) companion object { val scope = CoroutineScope(Dispatchers.Default + SupervisorJob()) lateinit var plugin: JavaPlugin - lateinit var chat: Chat + lateinit var config: Config + lateinit var blocklistManager: BlocklistManager + lateinit var luckPerms: LuckPerms lateinit var languageDatabase: LanguageDatabase var translator: OpenAI? = null + var discordBridge: DiscordBridge? = null + val discordBridgeLock = ReentrantReadWriteLock() var essentials = Bukkit.getServer().pluginManager.getPlugin("Essentials") as Essentials - - // API - @JvmStatic - @Suppress("unused") - fun sendMessageWithBot(message: String) { - scope.launch { DiscordBridge.sendMessageWithBot(message) } - } - - @JvmStatic - @Suppress("unused") - fun sendMessage(message: String, player: String, uuid: UUID?) { - scope.launch { DiscordBridge.sendMessage(message, player, uuid) } - } - - @JvmStatic - @Suppress("unused") - fun sendStaffMessage(message: String, player: String, uuid: UUID?) { - scope.launch { DiscordBridge.sendStaffMessage(message, player, uuid) } - } - - @JvmStatic - @Suppress("unused") - fun sendPremiumMessage(message: String, player: String, uuid: UUID?) { - scope.launch { DiscordBridge.sendPremiumMessage(message, player, uuid) } - } - - @JvmStatic - @Suppress("unused") - fun sendEmbed(message: String, uuid: UUID?, color: Int) { - scope.launch { DiscordBridge.sendEmbed(message, uuid, color) } - } + var lastMessagedMap: MutableMap = HashMap() } @OptIn(DelicateCoroutinesApi::class) override fun onEnable() { plugin = this - if (Config.load()) { - Bukkit.getPluginManager().disablePlugin(this) - return - } + Companion.config = + Config.create() + ?: run { + Bukkit.getPluginManager().disablePlugin(this) + return + } + + blocklistManager = BlocklistManager() + translator = - if (Config.openAIEnabled) { - OpenAI() + 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" + ) + 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" + ) + null + } else { + OpenAI() + } } else null languageDatabase = LanguageDatabase() @@ -71,11 +66,15 @@ class ChatOG : JavaPlugin() { return } - BlocklistManager.load() scope.launch { EmojiConverter.load() } - val rsp = server.servicesManager.getRegistration(Chat::class.java) - chat = rsp!!.provider + val luckPermsProvider = Bukkit.getServicesManager().getRegistration(LuckPerms::class.java) + if (luckPermsProvider == null) { + this.logger.severe("LuckPerms API is null, quitting...") + Bukkit.getPluginManager().disablePlugin(this) + return + } + luckPerms = luckPermsProvider.provider this.server.pluginManager.registerEvents(Events(), this) this.getCommand("translatemessage")?.setExecutor(TranslateMessage()) @@ -83,18 +82,38 @@ class ChatOG : JavaPlugin() { this.getCommand("translatesettings")?.tabCompleter = TranslateSettingsTabCompleter() this.getCommand("chatconfigreload")?.setExecutor(ChatConfigReload()) this.getCommand("sc")?.setExecutor(StaffChat()) + this.getCommand("s")?.setExecutor(StaffChat()) + this.getCommand("pc")?.setExecutor(PremiumChat()) this.getCommand("p")?.setExecutor(PremiumChat()) + this.getCommand("msg")?.setExecutor(PrivateMessage()) + this.getCommand("whisper")?.setExecutor(PrivateMessage()) + this.getCommand("pm")?.setExecutor(PrivateMessage()) + this.getCommand("reply")?.setExecutor(Reply()) + this.getCommand("r")?.setExecutor(Reply()) - if (Config.discordEnabled) { - scope.launch { DiscordBridge.main() } + if (Companion.config.discordEnabled) { + scope.launch { discordBridgeLock.write { discordBridge = DiscordBridge.create() } } } + + val chatAPI = ChatAPI() + this.server.servicesManager.register(ChatAPI::class.java, chatAPI, this, ServicePriority.Normal) } override fun onDisable() { - if (Config.discordEnabled) { - if (DiscordBridge.jda != null) { - DiscordBridge.sendMessageWithBot(Config.serverHasStoppedMessage) - DiscordBridge.jda!!.shutdownNow() + if (Companion.config.discordEnabled) { + discordBridgeLock.read { + val discordBridge = discordBridge + val serverHasStoppedMessage = + if (Companion.config.serverHasStoppedMessage == null) { + this.logger.warning( + "You have enabled Discord but have not set up the server has stopped message, using the default one instead" + ) + "The server has stopped" + } else { + Companion.config.serverHasStoppedMessage!! + } + discordBridge!!.sendMessageWithBot(serverHasStoppedMessage) + discordBridge.shutdownNow() } } diff --git a/src/main/kotlin/nl/skbotnl/chatog/ChatSystemHelper.kt b/src/main/kotlin/nl/skbotnl/chatog/ChatSystem.kt similarity index 59% rename from src/main/kotlin/nl/skbotnl/chatog/ChatSystemHelper.kt rename to src/main/kotlin/nl/skbotnl/chatog/ChatSystem.kt index 3eaf9f2..c580238 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/ChatSystemHelper.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/ChatSystem.kt @@ -1,15 +1,16 @@ package nl.skbotnl.chatog import java.util.* +import kotlin.concurrent.read import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.launch -import me.clip.placeholderapi.PlaceholderAPI import net.kyori.adventure.text.Component import net.kyori.adventure.text.JoinConfiguration -import net.kyori.adventure.text.TextComponent import net.kyori.adventure.text.event.ClickEvent 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.commands.TranslateMessage @@ -17,36 +18,40 @@ import org.bukkit.Bukkit import org.bukkit.entity.Player @OptIn(DelicateCoroutinesApi::class) -object ChatSystemHelper { - object ChatType { - const val STAFFCHAT = "staffchat" - const val PREMIUMCHAT = "premiumchat" +internal object ChatSystem { + enum class ChatType { + GENERAL_CHAT, + STAFF_CHAT, + PREMIUM_CHAT, } - var inChat: MutableMap = HashMap() + var inChat: MutableMap = HashMap() fun sendMessageInStaffChat(player: Player, text: String) { - var chatString = "${ChatOG.chat.getPlayerPrefix(player)}${player.name}" + var playerPartString = ChatHelper.getPlayerPartString(player) + playerPartString = "&cSTAFF | $playerPartString" - if (PlaceholderAPI.setPlaceholders(player, "%simpleclans_clan_color_tag%") != "") { - chatString = PlaceholderAPI.setPlaceholders(player, "&8[%simpleclans_clan_color_tag%&8] $chatString") - } - chatString = "&cSTAFF | $chatString" - - if (Config.staffDiscordEnabled) { + if (config.staffDiscordEnabled) { val discordMessageString = Helper.convertEmojis(text) ChatOG.scope.launch { - DiscordBridge.sendStaffMessage(discordMessageString, removeColor(chatString), player.uniqueId) + discordBridgeLock.read { + ChatOG.discordBridge?.sendStaffMessage( + discordMessageString, + removeColor(playerPartString), + player.uniqueId, + ) + } } } - val messageComponents = Helper.convertLinks(text, player) + val messageComponent = Helper.processText(text, player) + if (messageComponent == null) { + return + } - val messageComponent = - Component.join(JoinConfiguration.separator(Component.text(" ")), messageComponents) as TextComponent - - val chatComponent = UtilitiesOG.trueogColorize(legacyToMm("$chatString${ChatOG.chat.getPlayerSuffix(player)}")) + val chatComponent = + UtilitiesOG.trueogColorize(legacyToMm("$playerPartString${PlayerAffix.getSuffix(player.uniqueId)}")) var textComponent = Component.join(JoinConfiguration.noSeparators(), chatComponent, messageComponent) textComponent = @@ -73,27 +78,30 @@ object ChatSystemHelper { } fun sendMessageInPremiumChat(player: Player, text: String) { - var chatString = "${ChatOG.chat.getPlayerPrefix(player)}${player.name}" + var playerPartString = ChatHelper.getPlayerPartString(player) + playerPartString = "&aPREMIUM | $playerPartString" - if (PlaceholderAPI.setPlaceholders(player, "%simpleclans_clan_color_tag%") != "") { - chatString = PlaceholderAPI.setPlaceholders(player, "&8[%simpleclans_clan_color_tag%&8] $chatString") - } - chatString = "&aPREMIUM | $chatString" - - if (Config.premiumDiscordEnabled) { + if (config.premiumDiscordEnabled) { val discordMessageString = Helper.convertEmojis(text) ChatOG.scope.launch { - DiscordBridge.sendPremiumMessage(discordMessageString, removeColor(chatString), player.uniqueId) + discordBridgeLock.read { + ChatOG.discordBridge?.sendPremiumMessage( + discordMessageString, + removeColor(playerPartString), + player.uniqueId, + ) + } } } - val messageComponents = Helper.convertLinks(text, player) + val messageComponent = Helper.processText(text, player) + if (messageComponent == null) { + return + } - val messageComponent = - Component.join(JoinConfiguration.separator(Component.text(" ")), messageComponents) as TextComponent - - val chatComponent = UtilitiesOG.trueogColorize(legacyToMm("$chatString${ChatOG.chat.getPlayerSuffix(player)}")) + val chatComponent = + UtilitiesOG.trueogColorize(legacyToMm("$playerPartString${PlayerAffix.getSuffix(player.uniqueId)}")) var textComponent = Component.join(JoinConfiguration.noSeparators(), chatComponent, messageComponent) textComponent = diff --git a/src/main/kotlin/nl/skbotnl/chatog/Config.kt b/src/main/kotlin/nl/skbotnl/chatog/Config.kt index eb490e7..7c71df2 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/Config.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/Config.kt @@ -4,269 +4,272 @@ import java.io.File import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.configuration.file.YamlConfiguration -object Config { +internal class Config private constructor() { lateinit var prefix: String lateinit var redisUrl: String var openAIEnabled = false - var openAIBaseUrl: String = "" - var openAIApiKey: String = "" - var openAIModel: String = "" + var openAIBaseUrl: String? = null + var openAIApiKey: String? = null + var openAIModel: String? = null var discordEnabled = false var staffDiscordEnabled = false var premiumDiscordEnabled = false - var status: String = "" - var serverHasStartedMessage: String = "" - var serverHasStoppedMessage: String = "" - var botToken: String = "" - var channelId: String = "" - var staffChannelId: String = "" - var premiumChannelId: String = "" - var guildId: String = "" - var webhook: String = "" - var staffWebhook: String = "" - var premiumWebhook: String = "" - var listCommandName: String = "" - var listCommandText: String = "" + var status: String? = null + var serverHasStartedMessage: String? = null + var serverHasStoppedMessage: String? = null + var botToken: String? = null + var channelId: String? = null + var staffChannelId: String? = null + var premiumChannelId: String? = null + var guildId: String? = null + var webhook: String? = null + var staffWebhook: String? = null + var premiumWebhook: String? = null + var listCommandName: String? = null + var listCommandText: String? = null var colorCodeRoles: List = listOf() var roles: Set = setOf() var roleMessageColor: MutableMap = mutableMapOf() data class RGBColor(val r: Int, val g: Int, val b: Int) - /** @return True if failed */ - fun load(): Boolean { - val file = File(ChatOG.plugin.dataFolder, "config.yml") - if (!file.exists()) { - ChatOG.plugin.saveDefaultConfig() - } - val config = YamlConfiguration.loadConfiguration(file) + companion object { + fun create(): Config? { + val config = Config() - try { - prefix = config.get("prefix") as String - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"prefix\" as a string") - return true - } + val file = File(ChatOG.plugin.dataFolder, "config.yml") + if (!file.exists()) { + ChatOG.plugin.saveDefaultConfig() + } + val yamlConfig = YamlConfiguration.loadConfiguration(file) - try { - redisUrl = config.get("redisUrl") as String - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"redisUrl\" as a string") - return true - } - - try { - openAIEnabled = config.get("openAIEnabled") as Boolean - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"openAIEnabled\" as a boolean") - return true - } - - if (openAIEnabled) { try { - openAIBaseUrl = config.get("baseUrl") as String + config.prefix = yamlConfig.get("prefix") as String } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"baseUrl\" as a string") - return true + ChatOG.plugin.logger.severe("Failed to parse config option \"prefix\" as a string") + return null } try { - openAIApiKey = config.get("apiKey") as String + config.redisUrl = yamlConfig.get("redisUrl") as String } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"apiKey\" as a string") - return true + ChatOG.plugin.logger.severe("Failed to parse config option \"redisUrl\" as a string") + return null } - openAIModel = + try { + config.openAIEnabled = yamlConfig.get("openAIEnabled") as Boolean + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"openAIEnabled\" as a boolean") + return null + } + + if (config.openAIEnabled) { try { - config.get("model") as String + config.openAIBaseUrl = yamlConfig.get("baseUrl") as String } catch (_: Exception) { - "" - } - } - - try { - discordEnabled = config.get("discordEnabled") as Boolean - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"discordEnabled\" as a boolean") - return true - } - - try { - staffDiscordEnabled = config.get("staffDiscordEnabled") as Boolean - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"staffDiscordEnabled\" as a boolean") - return true - } - - try { - premiumDiscordEnabled = config.get("premiumDiscordEnabled") as Boolean - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"premiumDiscordEnabled\" as a boolean") - return true - } - - if (discordEnabled) { - try { - status = config.get("status") as String - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"status\" as a string") - return true - } - - try { - serverHasStartedMessage = config.get("serverHasStartedMessage") as String - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"serverHasStartedMessage\" as a string") - return true - } - - try { - serverHasStoppedMessage = config.get("serverHasStoppedMessage") as String - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"serverHasStoppedMessage\" as a string") - return true - } - - try { - botToken = config.get("botToken") as String - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"botToken\" as a string") - return true - } - - try { - guildId = (config.get("guildId") as Long).toString() - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"guildId\" as a long") - return true - } - - try { - channelId = (config.get("channelId") as Long).toString() - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"channelId\" as a long") - return true - } - - if (staffDiscordEnabled) { - try { - staffChannelId = (config.get("staffChannelId") as Long).toString() - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"staffChannelId\" as a long") - return true + ChatOG.plugin.logger.severe("Failed to parse config option \"baseUrl\" as a string") + return null } try { - staffWebhook = config.get("staffWebhook") as String + config.openAIApiKey = yamlConfig.get("apiKey") as String } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"staffWebhook\" as a string") - return true - } - } - - if (premiumDiscordEnabled) { - try { - premiumChannelId = (config.get("premiumChannelId") as Long).toString() - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"premiumChannelId\" as a long") - return true + ChatOG.plugin.logger.severe("Failed to parse config option \"apiKey\" as a string") + return null } - try { - premiumWebhook = config.get("premiumWebhook") as String - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"premiumWebhook\" as a string") - return true - } - } - - try { - webhook = config.get("webhook") as String - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"webhook\" as a string") - return true - } - - try { - listCommandName = config.get("listCommandName") as String - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"listCommandName\" as a string") - return true - } - - try { - listCommandText = config.get("listCommandText") as String - } catch (_: Exception) { - ChatOG.plugin.logger.severe("Failed to parse config option \"listCommandText\" as a string") - return true - } - - colorCodeRoles = config.getStringList("colorCodeRoles") - - roles = config.getConfigurationSection("roles")?.getKeys(false) ?: setOf() - } - - if (roles.isEmpty()) { - roleMessageColor = mutableMapOf() - return false - } - - 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), - ) - roles.forEach { - val messageColorList = config.getStringList("roles.$it.message_color") - roleMessageColor[it] = - if (messageColorList.isEmpty()) { + config.openAIModel = try { - config.get("roles.$it.message_color") as String + yamlConfig.get("model") as String } catch (_: Exception) { - return@forEach + "" + } + } + + try { + config.discordEnabled = yamlConfig.get("discordEnabled") as Boolean + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"discordEnabled\" as a boolean") + return null + } + + try { + config.staffDiscordEnabled = yamlConfig.get("staffDiscordEnabled") as Boolean + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"staffDiscordEnabled\" as a boolean") + return null + } + + try { + config.premiumDiscordEnabled = yamlConfig.get("premiumDiscordEnabled") as Boolean + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"premiumDiscordEnabled\" as a boolean") + return null + } + + if (config.discordEnabled) { + try { + config.status = yamlConfig.get("status") as String + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"status\" as a string") + return null + } + + try { + config.serverHasStartedMessage = yamlConfig.get("serverHasStartedMessage") as String + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"serverHasStartedMessage\" as a string") + return null + } + + try { + config.serverHasStoppedMessage = yamlConfig.get("serverHasStoppedMessage") as String + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"serverHasStoppedMessage\" as a string") + return null + } + + try { + config.botToken = yamlConfig.get("botToken") as String + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"botToken\" as a string") + return null + } + + try { + config.guildId = (yamlConfig.get("guildId") as Long).toString() + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"guildId\" as a long") + return null + } + + try { + config.channelId = (yamlConfig.get("channelId") as Long).toString() + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"channelId\" as a long") + return null + } + + if (config.staffDiscordEnabled) { + try { + config.staffChannelId = (yamlConfig.get("staffChannelId") as Long).toString() + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"staffChannelId\" as a long") + return null } - if (!messageColors.contains(messageColorList[0].uppercase())) { - ChatOG.plugin.logger.severe( - "The message color for \"$it\" (\"${messageColorList[0]}\") is invalid." - ) - return@forEach + try { + config.staffWebhook = yamlConfig.get("staffWebhook") as String + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"staffWebhook\" as a string") + return null + } + } + + if (config.premiumDiscordEnabled) { + try { + config.premiumChannelId = (yamlConfig.get("premiumChannelId") as Long).toString() + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"premiumChannelId\" as a long") + return null } - 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 + try { + config.premiumWebhook = yamlConfig.get("premiumWebhook") as String + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"premiumWebhook\" as a string") + return null } + } - messageColorList.forEach colorForEach@{ colorInList -> + try { + config.webhook = yamlConfig.get("webhook") as String + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"webhook\" as a string") + return null + } + + try { + config.listCommandName = yamlConfig.get("listCommandName") as String + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"listCommandName\" as a string") + return null + } + + try { + config.listCommandText = yamlConfig.get("listCommandText") as String + } catch (_: Exception) { + ChatOG.plugin.logger.severe("Failed to parse config option \"listCommandText\" as a string") + return null + } + + config.colorCodeRoles = yamlConfig.getStringList("colorCodeRoles") + + config.roles = yamlConfig.getConfigurationSection("roles")?.getKeys(false) ?: setOf() + } + + if (config.roles.isEmpty()) { + config.roleMessageColor = mutableMapOf() + return config + } + + 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 { - colorInList.toUByte() + yamlConfig.get("roles.$it.message_color") as String } 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()) - } - } - return false + 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()) + } + } + + return config + } } } diff --git a/src/main/kotlin/nl/skbotnl/chatog/DiscordBridge.kt b/src/main/kotlin/nl/skbotnl/chatog/DiscordBridge.kt index fbef174..1a27195 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/DiscordBridge.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/DiscordBridge.kt @@ -12,6 +12,7 @@ import dev.minn.jda.ktx.jdabuilder.light import java.util.* import net.dv8tion.jda.api.JDA import net.dv8tion.jda.api.entities.Activity +import net.dv8tion.jda.api.entities.Guild import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent import net.dv8tion.jda.api.events.message.MessageReceivedEvent @@ -27,374 +28,379 @@ import net.kyori.adventure.text.event.HoverEvent 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.legacyToMm -import nl.skbotnl.chatog.Helper.removeColor import nl.skbotnl.chatog.Helper.stripGroupMentions import nl.skbotnl.chatog.commands.TranslateMessage import org.bukkit.Bukkit +import org.bukkit.entity.Player -object DiscordBridge { - var jda: JDA? = null - var webhook: WebhookClient? = null - var staffWebhook: WebhookClient? = null - var premiumWebhook: WebhookClient? = null +internal class DiscordBridge private constructor() { + private lateinit var jda: JDA + private lateinit var webhook: WebhookClient + private var staffWebhook: WebhookClient? = null + private var premiumWebhook: WebhookClient? = null - private val urlRegex = - Regex("(.*)((https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;()]*[-a-zA-Z0-9+&@#/%=~_|()])(.*)") - - fun main() { - try { - webhook = WebhookClient.withUrl(Config.webhook) - } catch (e: IllegalArgumentException) { - ChatOG.plugin.logger.warning("Config option \"webhook\" is invalid") - } - try { - staffWebhook = WebhookClient.withUrl(Config.staffWebhook) - } catch (e: IllegalArgumentException) { - ChatOG.plugin.logger.warning("Config option \"staffWebhook\" is invalid") - } - try { - premiumWebhook = WebhookClient.withUrl(Config.premiumWebhook) - } catch (e: IllegalArgumentException) { - ChatOG.plugin.logger.warning("Config option \"premiumWebhook\" is invalid") - } - - jda = - light(Config.botToken, enableCoroutines = true) { - intents += listOf(GatewayIntent.GUILD_MEMBERS, GatewayIntent.MESSAGE_CONTENT) - cache += listOf(CacheFlag.EMOJI) - setMemberCachePolicy(MemberCachePolicy.ALL) - } - - jda?.presence?.setPresence(Activity.playing(Config.status), false) - - jda?.listener { - sendMessageWithBot(Config.serverHasStartedMessage) - jda?.getGuildById(Config.guildId) - ?.upsertCommand(Config.listCommandName, "List all online players.") - ?.queue() - } - - jda?.listener { - if (it.name == Config.listCommandName) { - it.deferReply().queue() + companion object { + fun create(): DiscordBridge? { + val discordBridge = DiscordBridge() + if (config.webhook != null) { try { - if (Bukkit.getOnlinePlayers().isEmpty()) { - it.hook.sendMessage("There are no players online.").queue() - return@listener + discordBridge.webhook = WebhookClient.withUrl(config.webhook!!) + } catch (_: IllegalArgumentException) { + ChatOG.plugin.logger.warning("Config option \"webhook\" is invalid") + } + } else { + ChatOG.plugin.logger.severe("You have enabled Discord but have not set up the webhook") + return null + } + if (config.staffWebhook != null) { + try { + discordBridge.staffWebhook = WebhookClient.withUrl(config.staffWebhook!!) + } catch (_: IllegalArgumentException) { + ChatOG.plugin.logger.warning("Config option \"staffWebhook\" is invalid") + } + } else if (config.staffDiscordEnabled) { + ChatOG.plugin.logger.warning("You have enabled staff Discord but have not set up the staff webhook") + } + if (config.premiumWebhook != null) { + try { + discordBridge.premiumWebhook = WebhookClient.withUrl(config.premiumWebhook!!) + } catch (_: IllegalArgumentException) { + ChatOG.plugin.logger.warning("Config option \"premiumWebhook\" is invalid") + } + } else if (config.premiumDiscordEnabled) { + ChatOG.plugin.logger.warning("You have enabled premium Discord but have not set up the premium webhook") + } + + if (config.botToken == null) { + ChatOG.plugin.logger.severe("You have enabled Discord but have not set up the bot token") + return null + } + discordBridge.jda = + light(config.botToken!!, enableCoroutines = true) { + intents += listOf(GatewayIntent.GUILD_MEMBERS, GatewayIntent.MESSAGE_CONTENT) + cache += listOf(CacheFlag.EMOJI) + setMemberCachePolicy(MemberCachePolicy.ALL) + } + + val status = + if (config.status == null) { + ChatOG.plugin.logger.warning( + "You have enabled Discord but have not set up the status, using the default one instead" + ) + "Minecraft" + } else { + config.status!! + } + + discordBridge.jda.presence.setPresence(Activity.playing(status), false) + + val serverHasStartedMessage = + if (config.serverHasStartedMessage == null) { + ChatOG.plugin.logger.warning( + "You have enabled Discord but have not set up the server has started message, using the default one instead" + ) + "The server has started" + } else { + config.serverHasStartedMessage!! + } + + if (config.guildId == null) { + ChatOG.plugin.logger.severe("You have enabled Discord but have not set up the guild ID") + return null + } + + discordBridge.jda.listener { + discordBridge.sendMessageWithBot(serverHasStartedMessage) + val guild = discordBridge.jda.getGuildById(config.guildId!!) + if (guild == null) { + ChatOG.plugin.logger.severe("Guild was null") + return@listener + } + if (config.listCommandName == null) { + ChatOG.plugin.logger.warning( + "You have enabled Discord but have not set up the list command name, the command will not be created" + ) + return@listener + } + if (config.listCommandText == null) { + ChatOG.plugin.logger.warning( + "You have enabled Discord but have not set up the list command text, the command will not be created" + ) + } + + guild.upsertCommand(config.listCommandName!!, "List all online players.").queue() + } + + discordBridge.jda.listener { + if (it.name == config.listCommandName) { + it.deferReply().queue() + try { + if (Bukkit.getOnlinePlayers().isEmpty()) { + it.hook.sendMessage("There are no players online.").queue() + return@listener + } + it.hook + .sendMessage( + "${ + config.listCommandText!! + .replace("%onlineplayers%", Bukkit.getOnlinePlayers().count().toString()) + .replace("%maxplayers%", Bukkit.getMaxPlayers().toString()) + }\n${ + Bukkit.getOnlinePlayers().joinToString(separator = ", ") { player -> player.name } + }" + ) + .queue() + } catch (_: Exception) { + ChatOG.plugin.logger.warning("Could not respond to /list interaction") } - it.hook - .sendMessage( - "${ - Config.listCommandText - .replace("%onlineplayers%", Bukkit.getOnlinePlayers().count().toString()) - .replace("%maxplayers%", Bukkit.getMaxPlayers().toString()) - }\n${ - Bukkit.getOnlinePlayers().joinToString(separator = ", ") { player -> player.name } - }" - ) - .queue() - } catch (e: Exception) { - ChatOG.plugin.logger.warning("Could not respond to /list interaction") - } - } - } - - jda?.listener { - 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) - ) { - return@listener - } - - if (it.author.isBot) { - return@listener - } - - val message = it.message - - val user = it.author - val member = it.member ?: return@listener - val color = member.color - val textColor: TextColor = - if (color == null) { - TextColor.color(153, 170, 181) - } else { - TextColor.color(color.rgb) - } - - val roles = member.roles - val roleIds = roles.map { role -> role.id } - - val topRole = roles.maxBy { role -> role.positionRaw } - - val discordComponent = Component.text("Discord: ").color(TextColor.color(88, 101, 242)) - val userComponent: TextComponent = - if (color == null) { - Component.text("@${user.name}").color(NamedTextColor.GRAY) - } else { - Component.text("[#${topRole.name}] @${user.name}").color(textColor) - } - - val messageColor = - 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 - if (roleId != null) { - val roleColor = Config.roleMessageColor[roleId] - - if (roleColor is Config.RGBColor) { - TextColor.color(roleColor.r, roleColor.g, roleColor.b) - } else { - roleColor as NamedTextColor - } - } else NamedTextColor.GRAY - } - - val messageComponents = mutableListOf(Component.text(" >").color(messageColor)) - - val attachmentComponents = mutableListOf() - - if (message.stickers.size != 0) - attachmentComponents += Component.text("[Sticker: ${message.stickers[0].name}]").color(messageColor) - - if (message.attachments.isNotEmpty()) { - message.attachments.forEach { attachment -> - var linkComponent = Component.text(attachment.url).color(TextColor.color(34, 100, 255)) - - linkComponent = - linkComponent.hoverEvent( - HoverEvent.hoverEvent( - HoverEvent.Action.SHOW_TEXT, - UtilitiesOG.trueogColorize("Click to open link"), - ) - ) - - linkComponent = - linkComponent.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, attachment.url)) - - attachmentComponents += linkComponent } } - if (message.contentDisplay != "") { - for (word in EmojiConverter.replaceEmojisWithNames(message.contentDisplay).split(" ")) { - val urlIter = urlRegex.findAll(word).iterator() - if (urlIter.hasNext()) { - for (url in urlIter) { - if (BlocklistManager.checkUrl(word)) { - for (player in Bukkit.getOnlinePlayers()) { - if (player.hasPermission("group.moderator")) { - player.sendMessage( - UtilitiesOG.trueogColorize( - "${Config.prefix}: @${user.name} has posted a disallowed link: ${ - word.replace( - ".", - "[dot]", - ) - }." - ) - ) - } - } - return@listener - } + discordBridge.jda.listener { + 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) + ) { + return@listener + } - var linkComponent = - Component.text(url.groups[2]!!.value).color(TextColor.color(34, 100, 255)) - linkComponent = - linkComponent.hoverEvent( - HoverEvent.hoverEvent( - HoverEvent.Action.SHOW_TEXT, - UtilitiesOG.trueogColorize("Click to open link"), - ) - ) + if (it.author.isBot) { + return@listener + } - linkComponent = - linkComponent.clickEvent( - ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, url.groups[2]!!.value) - ) + val message = it.message - val beforeComponent = Component.text(url.groups[1]?.value ?: "").color(messageColor) - val afterComponent = Component.text(url.groups[4]?.value ?: "").color(messageColor) - - val fullComponent = - Component.join( - JoinConfiguration.noSeparators(), - beforeComponent, - linkComponent, - afterComponent, - ) - messageComponents += fullComponent - } - continue + val user = it.author + val member = it.member ?: return@listener + val color = member.color + val userColor: TextColor = + if (color == null) { + TextColor.color(153, 170, 181) + } else { + TextColor.color(color.rgb) } - var messageText: Component = Component.text(word) - if (Config.colorCodeRoles.any { colorCodeRole -> colorCodeRole in roleIds }) { - messageText = - if (messageComponents.isNotEmpty()) { - val lastContent = (messageComponents.last() as TextComponent).content() - if ( - Helper.getColorSection(lastContent) != "" && Helper.getFirstColorSection(word) == "" - ) { - UtilitiesOG.trueogColorize(legacyToMm(Helper.getColorSection(lastContent) + word)) - } else { - UtilitiesOG.trueogColorize(legacyToMm(word)) - } + val roles = member.roles + val topRole = roles.maxByOrNull { role -> role.positionRaw } + + val discordComponent = Component.text("Discord: ").color(TextColor.color(88, 101, 242)) + val userComponent: TextComponent = + if (color == null) { + Component.text("@${user.name}").color(NamedTextColor.GRAY) + } else { + Component.text("[#${topRole!!.name}] @${user.name}").color(userColor) + } + + val messageColor = + 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 + if (roleId != null) { + val roleColor = config.roleMessageColor[roleId] + + if (roleColor is Config.RGBColor) { + TextColor.color(roleColor.r, roleColor.g, roleColor.b) } else { - UtilitiesOG.trueogColorize(legacyToMm(word)) + roleColor as NamedTextColor } + } else NamedTextColor.GRAY } - messageComponents += messageText.color(messageColor) + + val messageComponents = mutableListOf(Component.text(">")) + + val attachmentComponents = mutableListOf() + + if (message.stickers.isNotEmpty()) { + attachmentComponents += Component.text("[Sticker: ${message.stickers[0].name}]").color(messageColor) } - } - val contentComponent = - Component.join( - JoinConfiguration.separator(Component.text(" ")), - messageComponents + attachmentComponents, - ) + if (message.attachments.isNotEmpty()) { + message.attachments.forEach { attachment -> + var linkComponent = Component.text(attachment.url).color(TextColor.color(34, 100, 255)) - var replyComponent = Component.text("") - - if (message.messageReference != null) { - val replyMessage = message.messageReference!!.message - if (replyMessage != null) { - replyComponent = - Component.text( - "[Reply to: ${if (!replyMessage.isWebhookMessage) "@" else ""}${replyMessage.author.name}] " + linkComponent = + linkComponent.hoverEvent( + HoverEvent.hoverEvent( + HoverEvent.Action.SHOW_TEXT, + UtilitiesOG.trueogColorize("Click to open link"), + ) ) - .color(NamedTextColor.GREEN) - } - } - var messageComponent = - when (it.channel.id) { - Config.staffChannelId -> { - val staffComponent = Component.text("STAFF | ").color(NamedTextColor.RED) - Component.join( - JoinConfiguration.noSeparators(), - discordComponent, - staffComponent, - replyComponent, - userComponent, - contentComponent, - ) + linkComponent = + linkComponent.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, attachment.url)) + + attachmentComponents += linkComponent + } + } + + if (message.contentDisplay != "") { + messageComponents += + Helper.processText( + EmojiConverter.replaceEmojisWithNames(message.contentDisplay), + "@${user.name}", + ) + ?.color(messageColor) ?: return@listener + } + + val contentComponent = + Component.join( + JoinConfiguration.separator(Component.text(" ")), + messageComponents + attachmentComponents, + ) + + var replyComponent = Component.text("") + + if (message.messageReference != null) { + val replyMessage = message.messageReference!!.message + if (replyMessage != null) { + replyComponent = + Component.text( + "[Reply to: ${if (!replyMessage.isWebhookMessage) "@" else ""}${replyMessage.author.name}] " + ) + .color(NamedTextColor.GREEN) + } + } + + var messageComponent = + when (it.channel.id) { + config.staffChannelId -> { + val staffComponent = Component.text("STAFF | ").color(NamedTextColor.RED) + Component.join( + JoinConfiguration.noSeparators(), + discordComponent, + staffComponent, + replyComponent, + userComponent, + contentComponent, + ) + } + + config.premiumChannelId -> { + val premiumComponent = Component.text("PREMIUM | ").color(NamedTextColor.GREEN) + Component.join( + JoinConfiguration.noSeparators(), + discordComponent, + premiumComponent, + replyComponent, + userComponent, + contentComponent, + ) + } + + else -> { + Component.join( + JoinConfiguration.noSeparators(), + discordComponent, + replyComponent, + userComponent, + contentComponent, + ) + } } - Config.premiumChannelId -> { - val premiumComponent = Component.text("PREMIUM | ").color(NamedTextColor.GREEN) - Component.join( - JoinConfiguration.noSeparators(), - discordComponent, - premiumComponent, - replyComponent, - userComponent, - contentComponent, + messageComponent = + messageComponent.hoverEvent( + HoverEvent.hoverEvent( + HoverEvent.Action.SHOW_TEXT, + UtilitiesOG.trueogColorize("Click to translate this message"), ) + ) + + val randomUUID = UUID.randomUUID() + messageComponent = + messageComponent.clickEvent( + ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/translatemessage $randomUUID 2") + ) + + when (it.channel.id) { + config.staffChannelId -> { + for (p in Bukkit.getOnlinePlayers()) { + if (p.hasPermission("chat-og.staff")) { + p.sendMessage(messageComponent) + } + } + } + + config.premiumChannelId -> { + for (p in Bukkit.getOnlinePlayers()) { + if (p.hasPermission("chat-og.premium")) { + p.sendMessage(messageComponent) + } + } } else -> { - Component.join( - JoinConfiguration.noSeparators(), - discordComponent, - replyComponent, - userComponent, - contentComponent, - ) + for (p in Bukkit.getOnlinePlayers()) { + p.sendMessage(messageComponent) + } } } - messageComponent = - messageComponent.hoverEvent( - HoverEvent.hoverEvent( - HoverEvent.Action.SHOW_TEXT, - UtilitiesOG.trueogColorize("Click to translate this message"), + TranslateMessage.customMessages[randomUUID] = + TranslateMessage.SentCustomMessage( + message.contentDisplay, + member.effectiveName, + Component.join(JoinConfiguration.noSeparators(), discordComponent, userComponent), + Component.text("> "), ) - ) - - val randomUUID = UUID.randomUUID() - messageComponent = - messageComponent.clickEvent( - ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/translatemessage $randomUUID 2") - ) - - when (it.channel.id) { - Config.staffChannelId -> { - for (p in Bukkit.getOnlinePlayers()) { - if (p.hasPermission("chat-og.staff")) { - p.sendMessage(messageComponent) - } - } - } - - Config.premiumChannelId -> { - for (p in Bukkit.getOnlinePlayers()) { - if (p.hasPermission("chat-og.premium")) { - p.sendMessage(messageComponent) - } - } - } - - else -> { - for (p in Bukkit.getOnlinePlayers()) { - p.sendMessage(messageComponent) - } - } } - - TranslateMessage.customMessages[randomUUID] = - TranslateMessage.SentCustomMessage( - message.contentDisplay, - member.effectiveName, - Component.join(JoinConfiguration.noSeparators(), discordComponent, userComponent), - Component.text(" > ").color(messageColor), - ) + return discordBridge } } + fun shutdownNow() { + jda.shutdownNow() + } + + fun getGuildById(id: String): Guild? { + return jda.getGuildById(id) + } + fun sendMessageWithBot(message: String) { - if (!Config.discordEnabled) return + if (config.channelId == null) return - val channel = jda?.getChannel(Config.channelId) + val channel = jda.getChannel(config.channelId!!) if (channel == null) { ChatOG.plugin.logger.warning("channelId has not been set or is invalid") - } - - channel?.sendMessage(message)?.complete() - } - - suspend fun sendMessage(message: String, player: String, uuid: UUID?) { - if (!Config.discordEnabled) return - - if (webhook == null) { - ChatOG.plugin.logger.warning("webhook has not been set or is invalid") return } - val webhookMessage = - WebhookMessageBuilder() - .setUsername(removeColor(player)) - .setContent(stripGroupMentions(convertMentions(message))) - if (uuid != null) { - webhookMessage.setAvatarUrl("https://minotar.net/helm/$uuid.png") - } - - webhook?.send(webhookMessage.build()) + channel.sendMessage(UtilitiesOG.stripFormatting(message)).complete() } - suspend fun sendStaffMessage(message: String, player: String, uuid: UUID?) { - if (!Config.discordEnabled || !Config.staffDiscordEnabled) return + suspend fun sendMessage(message: String, player: Player) { + val webhookMessage = + WebhookMessageBuilder() + .setUsername(UtilitiesOG.stripFormatting(ChatHelper.getPlayerPartString(player))) + .setContent(UtilitiesOG.stripFormatting(stripGroupMentions(convertMentions(message)))) + .setAvatarUrl("https://minotar.net/helm/${player.uniqueId}.png") + + webhook.send(webhookMessage.build()) + } + + suspend fun sendMessage(message: String, name: String, uuid: UUID?) { + val webhookMessage = + WebhookMessageBuilder().apply { + setUsername(UtilitiesOG.stripFormatting(name)) + setContent(UtilitiesOG.stripFormatting(stripGroupMentions((convertMentions(message))))) + if (uuid != null) setAvatarUrl("https://minotar.net/helm/$uuid.png") + } + + webhook.send(webhookMessage.build()) + } + + suspend fun sendStaffMessage(message: String, name: String, uuid: UUID?) { + if (!config.staffDiscordEnabled) return if (staffWebhook == null) { ChatOG.plugin.logger.warning("staffWebhook has not been set or is invalid") @@ -402,18 +408,17 @@ object DiscordBridge { } val webhookMessage = - WebhookMessageBuilder() - .setUsername(removeColor(player)) - .setContent(stripGroupMentions((convertMentions(message)))) - if (uuid != null) { - webhookMessage.setAvatarUrl("https://minotar.net/helm/$uuid.png") - } + WebhookMessageBuilder().apply { + setUsername(UtilitiesOG.stripFormatting(name)) + setContent(UtilitiesOG.stripFormatting(stripGroupMentions((convertMentions(message))))) + if (uuid != null) setAvatarUrl("https://minotar.net/helm/$uuid.png") + } - staffWebhook?.send(webhookMessage.build()) + staffWebhook!!.send(webhookMessage.build()) } - suspend fun sendPremiumMessage(message: String, player: String, uuid: UUID?) { - if (!Config.discordEnabled || !Config.premiumDiscordEnabled) return + suspend fun sendPremiumMessage(message: String, name: String, uuid: UUID?) { + if (!config.premiumDiscordEnabled) return if (premiumWebhook == null) { ChatOG.plugin.logger.warning("premiumWebhook has not been set or is invalid") @@ -421,32 +426,28 @@ object DiscordBridge { } val webhookMessage = - WebhookMessageBuilder() - .setUsername(removeColor(player)) - .setContent(stripGroupMentions((convertMentions(message)))) - if (uuid != null) { - webhookMessage.setAvatarUrl("https://minotar.net/helm/$uuid.png") - } + WebhookMessageBuilder().apply { + setUsername(UtilitiesOG.stripFormatting(name)) + setContent(UtilitiesOG.stripFormatting(stripGroupMentions((convertMentions(message))))) + if (uuid != null) setAvatarUrl("https://minotar.net/helm/$uuid.png") + } - premiumWebhook?.send(webhookMessage.build()) + premiumWebhook!!.send(webhookMessage.build()) } - fun sendEmbed(message: String, uuid: UUID?, color: Int) { - if (!Config.discordEnabled) return - - if (webhook == null) { - ChatOG.plugin.logger.warning("Webhook has not been set or is invalid") - return - } - + fun sendEmbed(message: String, uuid: UUID?, color: Int?) { var iconUrl: String? = null if (uuid != null) { iconUrl = "https://minotar.net/helm/$uuid.png" } val webhookMessage = - WebhookEmbedBuilder().setColor(color).setAuthor(WebhookEmbed.EmbedAuthor(message, iconUrl, null)) + WebhookEmbedBuilder().apply { + if (color != null) + setColor(color) + .setAuthor(WebhookEmbed.EmbedAuthor(UtilitiesOG.stripFormatting(message), iconUrl, null)) + } - webhook?.send(webhookMessage.build()) + webhook.send(webhookMessage.build()) } } diff --git a/src/main/kotlin/nl/skbotnl/chatog/EmojiConverter.kt b/src/main/kotlin/nl/skbotnl/chatog/EmojiConverter.kt index 4bc8e00..2faae96 100644 --- a/src/main/kotlin/nl/skbotnl/chatog/EmojiConverter.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/EmojiConverter.kt @@ -2,7 +2,7 @@ package nl.skbotnl.chatog import com.google.gson.JsonParser -object EmojiConverter { +internal object EmojiConverter { private val emojiRegex = Regex( "[#*0-9]\\uFE0F?\\u20E3|[\\xA9\\xAE\\u203C\\u2049\\u2122\\u2139\\u2194-\\u2199\\u21A9\\u21AA\\u231A\\u231B\\u2328\\u23CF\\u23ED-\\u23EF\\u23F1\\u23F2\\u23F8-\\u23FA\\u24C2\\u25AA\\u25AB\\u25B6\\u25C0\\u25FB\\u25FC\\u25FE\\u2600-\\u2604\\u260E\\u2611\\u2614\\u2615\\u2618\\u2620\\u2622\\u2623\\u2626\\u262A\\u262E\\u262F\\u2638-\\u263A\\u2640\\u2642\\u2648-\\u2653\\u265F\\u2660\\u2663\\u2665\\u2666\\u2668\\u267B\\u267E\\u267F\\u2692\\u2694-\\u2697\\u2699\\u269B\\u269C\\u26A0\\u26A7\\u26AA\\u26B0\\u26B1\\u26BD\\u26BE\\u26C4\\u26C8\\u26CF\\u26D1\\u26E9\\u26F0-\\u26F5\\u26F7\\u26F8\\u26FA\\u2702\\u2708\\u2709\\u270F\\u2712\\u2714\\u2716\\u271D\\u2721\\u2733\\u2734\\u2744\\u2747\\u2757\\u2763\\u27A1\\u2934\\u2935\\u2B05-\\u2B07\\u2B1B\\u2B1C\\u2B55\\u3030\\u303D\\u3297\\u3299\\x{1F004}\\x{1F170}\\x{1F171}\\x{1F17E}\\x{1F17F}\\x{1F202}\\x{1F237}\\x{1F321}\\x{1F324}-\\x{1F32C}\\x{1F336}\\x{1F37D}\\x{1F396}\\x{1F397}\\x{1F399}-\\x{1F39B}\\x{1F39E}\\x{1F39F}\\x{1F3CD}\\x{1F3CE}\\x{1F3D4}-\\x{1F3DF}\\x{1F3F5}\\x{1F3F7}\\x{1F43F}\\x{1F4FD}\\x{1F549}\\x{1F54A}\\x{1F56F}\\x{1F570}\\x{1F573}\\x{1F576}-\\x{1F579}\\x{1F587}\\x{1F58A}-\\x{1F58D}\\x{1F5A5}\\x{1F5A8}\\x{1F5B1}\\x{1F5B2}\\x{1F5BC}\\x{1F5C2}-\\x{1F5C4}\\x{1F5D1}-\\x{1F5D3}\\x{1F5DC}-\\x{1F5DE}\\x{1F5E1}\\x{1F5E3}\\x{1F5E8}\\x{1F5EF}\\x{1F5F3}\\x{1F5FA}\\x{1F6CB}\\x{1F6CD}-\\x{1F6CF}\\x{1F6E0}-\\x{1F6E5}\\x{1F6E9}\\x{1F6F0}\\x{1F6F3}]\\uFE0F?|[\\u261D\\u270C\\u270D\\x{1F574}\\x{1F590}][\\uFE0F\\x{1F3FB}-\\x{1F3FF}]?|[\\u26F9\\x{1F3CB}\\x{1F3CC}\\x{1F575}][\\uFE0F\\x{1F3FB}-\\x{1F3FF}]?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\u270A\\u270B\\x{1F385}\\x{1F3C2}\\x{1F3C7}\\x{1F442}\\x{1F443}\\x{1F446}-\\x{1F450}\\x{1F466}\\x{1F467}\\x{1F46B}-\\x{1F46D}\\x{1F472}\\x{1F474}-\\x{1F476}\\x{1F478}\\x{1F47C}\\x{1F483}\\x{1F485}\\x{1F48F}\\x{1F491}\\x{1F4AA}\\x{1F57A}\\x{1F595}\\x{1F596}\\x{1F64C}\\x{1F64F}\\x{1F6C0}\\x{1F6CC}\\x{1F90C}\\x{1F90F}\\x{1F918}-\\x{1F91F}\\x{1F930}-\\x{1F934}\\x{1F936}\\x{1F977}\\x{1F9B5}\\x{1F9B6}\\x{1F9BB}\\x{1F9D2}\\x{1F9D3}\\x{1F9D5}\\x{1FAC3}-\\x{1FAC5}\\x{1FAF0}\\x{1FAF2}-\\x{1FAF8}][\\x{1F3FB}-\\x{1F3FF}]?|[\\x{1F3C3}\\x{1F6B6}\\x{1F9CE}][\\x{1F3FB}-\\x{1F3FF}]?(?:\\u200D(?:[\\u2640\\u2642]\\uFE0F?(?:\\u200D\\u27A1\\uFE0F?)?|\\u27A1\\uFE0F?))?|[\\x{1F3C4}\\x{1F3CA}\\x{1F46E}\\x{1F470}\\x{1F471}\\x{1F473}\\x{1F477}\\x{1F481}\\x{1F482}\\x{1F486}\\x{1F487}\\x{1F645}-\\x{1F647}\\x{1F64B}\\x{1F64D}\\x{1F64E}\\x{1F6A3}\\x{1F6B4}\\x{1F6B5}\\x{1F926}\\x{1F935}\\x{1F937}-\\x{1F939}\\x{1F93D}\\x{1F93E}\\x{1F9B8}\\x{1F9B9}\\x{1F9CD}\\x{1F9CF}\\x{1F9D4}\\x{1F9D6}-\\x{1F9DD}][\\x{1F3FB}-\\x{1F3FF}]?(?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\x{1F46F}\\x{1F9DE}\\x{1F9DF}](?:\\u200D[\\u2640\\u2642]\\uFE0F?)?|[\\u23E9-\\u23EC\\u23F0\\u23F3\\u25FD\\u2693\\u26A1\\u26AB\\u26C5\\u26CE\\u26D4\\u26EA\\u26FD\\u2705\\u2728\\u274C\\u274E\\u2753-\\u2755\\u2795-\\u2797\\u27B0\\u27BF\\u2B50\\x{1F0CF}\\x{1F18E}\\x{1F191}-\\x{1F19A}\\x{1F201}\\x{1F21A}\\x{1F22F}\\x{1F232}-\\x{1F236}\\x{1F238}-\\x{1F23A}\\x{1F250}\\x{1F251}\\x{1F300}-\\x{1F320}\\x{1F32D}-\\x{1F335}\\x{1F337}-\\x{1F343}\\x{1F345}-\\x{1F34A}\\x{1F34C}-\\x{1F37C}\\x{1F37E}-\\x{1F384}\\x{1F386}-\\x{1F393}\\x{1F3A0}-\\x{1F3C1}\\x{1F3C5}\\x{1F3C6}\\x{1F3C8}\\x{1F3C9}\\x{1F3CF}-\\x{1F3D3}\\x{1F3E0}-\\x{1F3F0}\\x{1F3F8}-\\x{1F407}\\x{1F409}-\\x{1F414}\\x{1F416}-\\x{1F425}\\x{1F427}-\\x{1F43A}\\x{1F43C}-\\x{1F43E}\\x{1F440}\\x{1F444}\\x{1F445}\\x{1F451}-\\x{1F465}\\x{1F46A}\\x{1F479}-\\x{1F47B}\\x{1F47D}-\\x{1F480}\\x{1F484}\\x{1F488}-\\x{1F48E}\\x{1F490}\\x{1F492}-\\x{1F4A9}\\x{1F4AB}-\\x{1F4FC}\\x{1F4FF}-\\x{1F53D}\\x{1F54B}-\\x{1F54E}\\x{1F550}-\\x{1F567}\\x{1F5A4}\\x{1F5FB}-\\x{1F62D}\\x{1F62F}-\\x{1F634}\\x{1F637}-\\x{1F641}\\x{1F643}\\x{1F644}\\x{1F648}-\\x{1F64A}\\x{1F680}-\\x{1F6A2}\\x{1F6A4}-\\x{1F6B3}\\x{1F6B7}-\\x{1F6BF}\\x{1F6C1}-\\x{1F6C5}\\x{1F6D0}-\\x{1F6D2}\\x{1F6D5}-\\x{1F6D7}\\x{1F6DC}-\\x{1F6DF}\\x{1F6EB}\\x{1F6EC}\\x{1F6F4}-\\x{1F6FC}\\x{1F7E0}-\\x{1F7EB}\\x{1F7F0}\\x{1F90D}\\x{1F90E}\\x{1F910}-\\x{1F917}\\x{1F920}-\\x{1F925}\\x{1F927}-\\x{1F92F}\\x{1F93A}\\x{1F93F}-\\x{1F945}\\x{1F947}-\\x{1F976}\\x{1F978}-\\x{1F9B4}\\x{1F9B7}\\x{1F9BA}\\x{1F9BC}-\\x{1F9CC}\\x{1F9D0}\\x{1F9E0}-\\x{1F9FF}\\x{1FA70}-\\x{1FA7C}\\x{1FA80}-\\x{1FA89}\\x{1FA8F}-\\x{1FAC2}\\x{1FAC6}\\x{1FACE}-\\x{1FADC}\\x{1FADF}-\\x{1FAE9}]|\\u26D3\\uFE0F?(?:\\u200D\\x{1F4A5})?|\\u2764\\uFE0F?(?:\\u200D[\\x{1F525}\\x{1FA79}])?|\\x{1F1E6}[\\x{1F1E8}-\\x{1F1EC}\\x{1F1EE}\\x{1F1F1}\\x{1F1F2}\\x{1F1F4}\\x{1F1F6}-\\x{1F1FA}\\x{1F1FC}\\x{1F1FD}\\x{1F1FF}]|\\x{1F1E7}[\\x{1F1E6}\\x{1F1E7}\\x{1F1E9}-\\x{1F1EF}\\x{1F1F1}-\\x{1F1F4}\\x{1F1F6}-\\x{1F1F9}\\x{1F1FB}\\x{1F1FC}\\x{1F1FE}\\x{1F1FF}]|\\x{1F1E8}[\\x{1F1E6}\\x{1F1E8}\\x{1F1E9}\\x{1F1EB}-\\x{1F1EE}\\x{1F1F0}-\\x{1F1F7}\\x{1F1FA}-\\x{1F1FF}]|\\x{1F1E9}[\\x{1F1EA}\\x{1F1EC}\\x{1F1EF}\\x{1F1F0}\\x{1F1F2}\\x{1F1F4}\\x{1F1FF}]|\\x{1F1EA}[\\x{1F1E6}\\x{1F1E8}\\x{1F1EA}\\x{1F1EC}\\x{1F1ED}\\x{1F1F7}-\\x{1F1FA}]|\\x{1F1EB}[\\x{1F1EE}-\\x{1F1F0}\\x{1F1F2}\\x{1F1F4}\\x{1F1F7}]|\\x{1F1EC}[\\x{1F1E6}\\x{1F1E7}\\x{1F1E9}-\\x{1F1EE}\\x{1F1F1}-\\x{1F1F3}\\x{1F1F5}-\\x{1F1FA}\\x{1F1FC}\\x{1F1FE}]|\\x{1F1ED}[\\x{1F1F0}\\x{1F1F2}\\x{1F1F3}\\x{1F1F7}\\x{1F1F9}\\x{1F1FA}]|\\x{1F1EE}[\\x{1F1E8}-\\x{1F1EA}\\x{1F1F1}-\\x{1F1F4}\\x{1F1F6}-\\x{1F1F9}]|\\x{1F1EF}[\\x{1F1EA}\\x{1F1F2}\\x{1F1F4}\\x{1F1F5}]|\\x{1F1F0}[\\x{1F1EA}\\x{1F1EC}-\\x{1F1EE}\\x{1F1F2}\\x{1F1F3}\\x{1F1F5}\\x{1F1F7}\\x{1F1FC}\\x{1F1FE}\\x{1F1FF}]|\\x{1F1F1}[\\x{1F1E6}-\\x{1F1E8}\\x{1F1EE}\\x{1F1F0}\\x{1F1F7}-\\x{1F1FB}\\x{1F1FE}]|\\x{1F1F2}[\\x{1F1E6}\\x{1F1E8}-\\x{1F1ED}\\x{1F1F0}-\\x{1F1FF}]|\\x{1F1F3}[\\x{1F1E6}\\x{1F1E8}\\x{1F1EA}-\\x{1F1EC}\\x{1F1EE}\\x{1F1F1}\\x{1F1F4}\\x{1F1F5}\\x{1F1F7}\\x{1F1FA}\\x{1F1FF}]|\\x{1F1F4}\\x{1F1F2}|\\x{1F1F5}[\\x{1F1E6}\\x{1F1EA}-\\x{1F1ED}\\x{1F1F0}-\\x{1F1F3}\\x{1F1F7}-\\x{1F1F9}\\x{1F1FC}\\x{1F1FE}]|\\x{1F1F6}\\x{1F1E6}|\\x{1F1F7}[\\x{1F1EA}\\x{1F1F4}\\x{1F1F8}\\x{1F1FA}\\x{1F1FC}]|\\x{1F1F8}[\\x{1F1E6}-\\x{1F1EA}\\x{1F1EC}-\\x{1F1F4}\\x{1F1F7}-\\x{1F1F9}\\x{1F1FB}\\x{1F1FD}-\\x{1F1FF}]|\\x{1F1F9}[\\x{1F1E6}\\x{1F1E8}\\x{1F1E9}\\x{1F1EB}-\\x{1F1ED}\\x{1F1EF}-\\x{1F1F4}\\x{1F1F7}\\x{1F1F9}\\x{1F1FB}\\x{1F1FC}\\x{1F1FF}]|\\x{1F1FA}[\\x{1F1E6}\\x{1F1EC}\\x{1F1F2}\\x{1F1F3}\\x{1F1F8}\\x{1F1FE}\\x{1F1FF}]|\\x{1F1FB}[\\x{1F1E6}\\x{1F1E8}\\x{1F1EA}\\x{1F1EC}\\x{1F1EE}\\x{1F1F3}\\x{1F1FA}]|\\x{1F1FC}[\\x{1F1EB}\\x{1F1F8}]|\\x{1F1FD}\\x{1F1F0}|\\x{1F1FE}[\\x{1F1EA}\\x{1F1F9}]|\\x{1F1FF}[\\x{1F1E6}\\x{1F1F2}\\x{1F1FC}]|\\x{1F344}(?:\\u200D\\x{1F7EB})?|\\x{1F34B}(?:\\u200D\\x{1F7E9})?|\\x{1F3F3}\\uFE0F?(?:\\u200D(?:\\u26A7\\uFE0F?|\\x{1F308}))?|\\x{1F3F4}(?:\\u200D\\u2620\\uFE0F?|\\x{E0067}\\x{E0062}(?:\\x{E0065}\\x{E006E}\\x{E0067}|\\x{E0073}\\x{E0063}\\x{E0074}|\\x{E0077}\\x{E006C}\\x{E0073})\\x{E007F})?|\\x{1F408}(?:\\u200D\\u2B1B)?|\\x{1F415}(?:\\u200D\\x{1F9BA})?|\\x{1F426}(?:\\u200D[\\u2B1B\\x{1F525}])?|\\x{1F43B}(?:\\u200D\\u2744\\uFE0F?)?|\\x{1F441}\\uFE0F?(?:\\u200D\\x{1F5E8}\\uFE0F?)?|\\x{1F468}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F468}\\x{1F469}]\\u200D(?:\\x{1F466}(?:\\u200D\\x{1F466})?|\\x{1F467}(?:\\u200D[\\x{1F466}\\x{1F467}])?)|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:\\x{1F48B}\\u200D)?\\x{1F468}|\\x{1F466}(?:\\u200D\\x{1F466})?|\\x{1F467}(?:\\u200D[\\x{1F466}\\x{1F467}])?)|\\x{1F3FB}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:\\x{1F48B}\\u200D)?\\x{1F468}[\\x{1F3FB}-\\x{1F3FF}]|\\x{1F91D}\\u200D\\x{1F468}[\\x{1F3FC}-\\x{1F3FF}]))?|\\x{1F3FC}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:\\x{1F48B}\\u200D)?\\x{1F468}[\\x{1F3FB}-\\x{1F3FF}]|\\x{1F91D}\\u200D\\x{1F468}[\\x{1F3FB}\\x{1F3FD}-\\x{1F3FF}]))?|\\x{1F3FD}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:\\x{1F48B}\\u200D)?\\x{1F468}[\\x{1F3FB}-\\x{1F3FF}]|\\x{1F91D}\\u200D\\x{1F468}[\\x{1F3FB}\\x{1F3FC}\\x{1F3FE}\\x{1F3FF}]))?|\\x{1F3FE}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:\\x{1F48B}\\u200D)?\\x{1F468}[\\x{1F3FB}-\\x{1F3FF}]|\\x{1F91D}\\u200D\\x{1F468}[\\x{1F3FB}-\\x{1F3FD}\\x{1F3FF}]))?|\\x{1F3FF}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:\\x{1F48B}\\u200D)?\\x{1F468}[\\x{1F3FB}-\\x{1F3FF}]|\\x{1F91D}\\u200D\\x{1F468}[\\x{1F3FB}-\\x{1F3FE}]))?)?|\\x{1F469}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:\\x{1F48B}\\u200D)?[\\x{1F468}\\x{1F469}]|\\x{1F466}(?:\\u200D\\x{1F466})?|\\x{1F467}(?:\\u200D[\\x{1F466}\\x{1F467}])?|\\x{1F469}\\u200D(?:\\x{1F466}(?:\\u200D\\x{1F466})?|\\x{1F467}(?:\\u200D[\\x{1F466}\\x{1F467}])?))|\\x{1F3FB}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:[\\x{1F468}\\x{1F469}]|\\x{1F48B}\\u200D[\\x{1F468}\\x{1F469}])[\\x{1F3FB}-\\x{1F3FF}]|\\x{1F91D}\\u200D[\\x{1F468}\\x{1F469}][\\x{1F3FC}-\\x{1F3FF}]))?|\\x{1F3FC}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:[\\x{1F468}\\x{1F469}]|\\x{1F48B}\\u200D[\\x{1F468}\\x{1F469}])[\\x{1F3FB}-\\x{1F3FF}]|\\x{1F91D}\\u200D[\\x{1F468}\\x{1F469}][\\x{1F3FB}\\x{1F3FD}-\\x{1F3FF}]))?|\\x{1F3FD}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:[\\x{1F468}\\x{1F469}]|\\x{1F48B}\\u200D[\\x{1F468}\\x{1F469}])[\\x{1F3FB}-\\x{1F3FF}]|\\x{1F91D}\\u200D[\\x{1F468}\\x{1F469}][\\x{1F3FB}\\x{1F3FC}\\x{1F3FE}\\x{1F3FF}]))?|\\x{1F3FE}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:[\\x{1F468}\\x{1F469}]|\\x{1F48B}\\u200D[\\x{1F468}\\x{1F469}])[\\x{1F3FB}-\\x{1F3FF}]|\\x{1F91D}\\u200D[\\x{1F468}\\x{1F469}][\\x{1F3FB}-\\x{1F3FD}\\x{1F3FF}]))?|\\x{1F3FF}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:[\\x{1F468}\\x{1F469}]|\\x{1F48B}\\u200D[\\x{1F468}\\x{1F469}])[\\x{1F3FB}-\\x{1F3FF}]|\\x{1F91D}\\u200D[\\x{1F468}\\x{1F469}][\\x{1F3FB}-\\x{1F3FE}]))?)?|\\x{1F62E}(?:\\u200D\\x{1F4A8})?|\\x{1F635}(?:\\u200D\\x{1F4AB})?|\\x{1F636}(?:\\u200D\\x{1F32B}\\uFE0F?)?|\\x{1F642}(?:\\u200D[\\u2194\\u2195]\\uFE0F?)?|\\x{1F93C}(?:[\\x{1F3FB}-\\x{1F3FF}]|\\u200D[\\u2640\\u2642]\\uFE0F?)?|\\x{1F9D1}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F384}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\x{1F91D}\\u200D\\x{1F9D1}|\\x{1F9D1}\\u200D\\x{1F9D2}(?:\\u200D\\x{1F9D2})?|\\x{1F9D2}(?:\\u200D\\x{1F9D2})?)|\\x{1F3FB}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F384}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:\\x{1F48B}\\u200D)?\\x{1F9D1}[\\x{1F3FC}-\\x{1F3FF}]|\\x{1F91D}\\u200D\\x{1F9D1}[\\x{1F3FB}-\\x{1F3FF}]))?|\\x{1F3FC}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F384}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:\\x{1F48B}\\u200D)?\\x{1F9D1}[\\x{1F3FB}\\x{1F3FD}-\\x{1F3FF}]|\\x{1F91D}\\u200D\\x{1F9D1}[\\x{1F3FB}-\\x{1F3FF}]))?|\\x{1F3FD}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F384}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:\\x{1F48B}\\u200D)?\\x{1F9D1}[\\x{1F3FB}\\x{1F3FC}\\x{1F3FE}\\x{1F3FF}]|\\x{1F91D}\\u200D\\x{1F9D1}[\\x{1F3FB}-\\x{1F3FF}]))?|\\x{1F3FE}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F384}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:\\x{1F48B}\\u200D)?\\x{1F9D1}[\\x{1F3FB}-\\x{1F3FD}\\x{1F3FF}]|\\x{1F91D}\\u200D\\x{1F9D1}[\\x{1F3FB}-\\x{1F3FF}]))?|\\x{1F3FF}(?:\\u200D(?:[\\u2695\\u2696\\u2708]\\uFE0F?|[\\x{1F9AF}\\x{1F9BC}\\x{1F9BD}](?:\\u200D\\u27A1\\uFE0F?)?|[\\x{1F33E}\\x{1F373}\\x{1F37C}\\x{1F384}\\x{1F393}\\x{1F3A4}\\x{1F3A8}\\x{1F3EB}\\x{1F3ED}\\x{1F4BB}\\x{1F4BC}\\x{1F527}\\x{1F52C}\\x{1F680}\\x{1F692}\\x{1F9B0}-\\x{1F9B3}]|\\u2764\\uFE0F?\\u200D(?:\\x{1F48B}\\u200D)?\\x{1F9D1}[\\x{1F3FB}-\\x{1F3FE}]|\\x{1F91D}\\u200D\\x{1F9D1}[\\x{1F3FB}-\\x{1F3FF}]))?)?|\\x{1FAF1}(?:\\x{1F3FB}(?:\\u200D\\x{1FAF2}[\\x{1F3FC}-\\x{1F3FF}])?|\\x{1F3FC}(?:\\u200D\\x{1FAF2}[\\x{1F3FB}\\x{1F3FD}-\\x{1F3FF}])?|\\x{1F3FD}(?:\\u200D\\x{1FAF2}[\\x{1F3FB}\\x{1F3FC}\\x{1F3FE}\\x{1F3FF}])?|\\x{1F3FE}(?:\\u200D\\x{1FAF2}[\\x{1F3FB}-\\x{1F3FD}\\x{1F3FF}])?|\\x{1F3FF}(?:\\u200D\\x{1FAF2}[\\x{1F3FB}-\\x{1F3FE}])?)?" diff --git a/src/main/kotlin/nl/skbotnl/chatog/Events.kt b/src/main/kotlin/nl/skbotnl/chatog/Events.kt index ff3dfa1..dc917b2 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/Events.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/Events.kt @@ -3,6 +3,7 @@ package nl.skbotnl.chatog import io.papermc.paper.advancement.AdvancementDisplay.Frame.* import io.papermc.paper.event.player.AsyncChatEvent import java.util.* +import kotlin.concurrent.read import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.launch import me.clip.placeholderapi.PlaceholderAPI @@ -17,12 +18,13 @@ import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextColor import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer import net.trueog.utilitiesog.UtilitiesOG -import nl.skbotnl.chatog.ChatSystemHelper.ChatType +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.commands.TranslateMessage import org.bukkit.Bukkit -import org.bukkit.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.Listener import org.bukkit.event.entity.PlayerDeathEvent @@ -31,103 +33,91 @@ import org.bukkit.event.server.BroadcastMessageEvent import xyz.jpenilla.announcerplus.listener.JoinQuitListener @OptIn(DelicateCoroutinesApi::class) -class Events : Listener { - private var lastMessaged: MutableMap = HashMap() - +internal class Events : Listener { @EventHandler fun onJoin(event: PlayerJoinEvent) { - if (!Config.discordEnabled) { + if (!config.discordEnabled) { return } if (ChatOG.essentials.getUser(event.player).isVanished && event.joinMessage() !is TextComponent) { return } - var chatString = "${ChatOG.chat.getPlayerPrefix(event.player)} ${event.player.name}" - - if (PlaceholderAPI.setPlaceholders(event.player, "%simpleclans_clan_color_tag%") != "") { - chatString = PlaceholderAPI.setPlaceholders(event.player, "&8[%simpleclans_clan_color_tag%&8] $chatString") - } + val playerPartString = ChatHelper.getPlayerPartString(event.player) ChatOG.scope.launch { - DiscordBridge.sendEmbed( - "${removeColor(chatString)} has joined the game. ${ - Bukkit.getOnlinePlayers().count() - } player(s) online.", - event.player.uniqueId, - 0x00FF00, - ) + discordBridgeLock.read { + ChatOG.discordBridge?.sendEmbed( + "$playerPartString has joined the game. ${ + Bukkit.getOnlinePlayers().count() + } player(s) online.", + event.player.uniqueId, + 0x00FF00, + ) + } } } @EventHandler fun onQuit(event: PlayerQuitEvent) { - if (!Config.discordEnabled) { + if (!config.discordEnabled) { return } if (ChatOG.essentials.getUser(event.player).isVanished) { return } - var chatString = "${ChatOG.chat.getPlayerPrefix(event.player)} ${event.player.name}" - - if (PlaceholderAPI.setPlaceholders(event.player, "%simpleclans_clan_color_tag%") != "") { - chatString = PlaceholderAPI.setPlaceholders(event.player, "&8[%simpleclans_clan_color_tag%&8] $chatString") - } + val playerPartString = ChatHelper.getPlayerPartString(event.player) ChatOG.scope.launch { - DiscordBridge.sendEmbed( - "${removeColor(chatString)} has left the game. ${ - Bukkit.getOnlinePlayers().count() - 1 - } player(s) online.", - event.player.uniqueId, - 0xFF0000, - ) + discordBridgeLock.read { + ChatOG.discordBridge?.sendEmbed( + "${removeColor(playerPartString)} has left the game. ${ + Bukkit.getOnlinePlayers().count() - 1 + } player(s) online.", + event.player.uniqueId, + 0xFF0000, + ) + } } } @EventHandler fun onKick(event: PlayerKickEvent) { - if (!Config.discordEnabled) { + if (!config.discordEnabled) { return } if (ChatOG.essentials.getUser(event.player).isVanished) { return } - var chatString = "${ChatOG.chat.getPlayerPrefix(event.player)} ${event.player.name}" - - if (PlaceholderAPI.setPlaceholders(event.player, "%simpleclans_clan_color_tag%") != "") { - chatString = PlaceholderAPI.setPlaceholders(event.player, "&8[%simpleclans_clan_color_tag%&8] $chatString") - } + val playerPartString = ChatHelper.getPlayerPartString(event.player) val reason = PlainTextComponentSerializer.plainText().serialize(event.reason()) ChatOG.scope.launch { - DiscordBridge.sendEmbed( - "${removeColor(chatString)} was kicked with reason: \"${reason}\". ${ - Bukkit.getOnlinePlayers().count() - 1 - } player(s) online.", - event.player.uniqueId, - 0xFF0000, - ) + discordBridgeLock.read { + ChatOG.discordBridge?.sendEmbed( + "${removeColor(playerPartString)} was kicked with reason: \"${reason}\". ${ + Bukkit.getOnlinePlayers().count() - 1 + } player(s) online.", + event.player.uniqueId, + 0xFF0000, + ) + } } } @EventHandler fun onAdvancement(event: PlayerAdvancementDoneEvent) { - if (!Config.discordEnabled) { + if (!config.discordEnabled) { return } if (ChatOG.essentials.getUser(event.player).isVanished) { return } - var chatString = "${ChatOG.chat.getPlayerPrefix(event.player)} ${event.player.name}" - - if (PlaceholderAPI.setPlaceholders(event.player, "%simpleclans_clan_color_tag%") != "") { - chatString = PlaceholderAPI.setPlaceholders(event.player, "&8[%simpleclans_clan_color_tag%&8] $chatString") - } + val playerPartString = ChatHelper.getPlayerPartString(event.player) val advancementTitleKey = event.advancement.display?.title() ?: return val advancementTitle = PlainTextComponentSerializer.plainText().serialize(advancementTitleKey) @@ -143,13 +133,19 @@ class Events : Listener { } ChatOG.scope.launch { - DiscordBridge.sendEmbed("${removeColor(chatString)} $advancementMessage.", event.player.uniqueId, 0xFFFF00) + discordBridgeLock.read { + ChatOG.discordBridge?.sendEmbed( + "${removeColor(playerPartString)} $advancementMessage.", + event.player.uniqueId, + 0xFFFF00, + ) + } } } @EventHandler fun onBroadcast(event: BroadcastMessageEvent) { - if (!Config.discordEnabled) { + if (!config.discordEnabled) { return } if (event.message() !is TextComponent) { @@ -161,7 +157,9 @@ class Events : Listener { return } - ChatOG.scope.launch { DiscordBridge.sendMessage(content, "[Server] Broadcast", null) } + ChatOG.scope.launch { + discordBridgeLock.read { ChatOG.discordBridge?.sendMessage(content, "[Server] Broadcast", null) } + } } @EventHandler @@ -169,36 +167,30 @@ class Events : Listener { if (event.isCancelled) return event.isCancelled = true - val oldTextComponent = event.message() as TextComponent + val eventMessage = event.message() as TextComponent - if (ChatSystemHelper.inChat[event.player.uniqueId] == ChatType.STAFFCHAT) { - ChatSystemHelper.sendMessageInStaffChat(event.player, oldTextComponent.content()) + if (ChatSystem.inChat[event.player.uniqueId] == ChatType.STAFF_CHAT) { + ChatSystem.sendMessageInStaffChat(event.player, eventMessage.content()) return } - if (ChatSystemHelper.inChat[event.player.uniqueId] == ChatType.PREMIUMCHAT) { - ChatSystemHelper.sendMessageInPremiumChat(event.player, oldTextComponent.content()) + if (ChatSystem.inChat[event.player.uniqueId] == ChatType.PREMIUM_CHAT) { + ChatSystem.sendMessageInPremiumChat(event.player, eventMessage.content()) return } - var chatString = "${ChatOG.chat.getPlayerPrefix(event.player)} ${event.player.name}" - - if (PlaceholderAPI.setPlaceholders(event.player, "%simpleclans_clan_color_tag%") != "") { - chatString = PlaceholderAPI.setPlaceholders(event.player, "&8[%simpleclans_clan_color_tag%&8] $chatString") + val discordMessageString = Helper.convertEmojis(eventMessage.content()) + ChatOG.scope.launch { + discordBridgeLock.read { ChatOG.discordBridge?.sendMessage(discordMessageString, event.player) } } - val discordMessageString = Helper.convertEmojis(oldTextComponent.content()) + val playerPart = ChatHelper.getPlayerPart(event.player, true) - ChatOG.scope.launch { DiscordBridge.sendMessage(discordMessageString, chatString, event.player.uniqueId) } + val messageComponent = Helper.processText(eventMessage.content(), event.player) + if (messageComponent == null) { + return + } - val messageComponents = Helper.convertLinks(oldTextComponent.content(), event.player) - - val messageComponent = - Component.join(JoinConfiguration.separator(Component.text(" ")), messageComponents) as TextComponent - - val chatComponent = - UtilitiesOG.trueogColorize(legacyToMm("$chatString${ChatOG.chat.getPlayerSuffix(event.player)}")) - - var textComponent = Component.join(JoinConfiguration.noSeparators(), chatComponent, messageComponent) + var textComponent = Component.join(JoinConfiguration.noSeparators(), playerPart, messageComponent) textComponent = textComponent.hoverEvent( HoverEvent.hoverEvent( @@ -216,160 +208,12 @@ class Events : Listener { event.viewers().forEach { it.sendMessage(textComponent) } TranslateMessage.chatMessages[randomUUID] = - TranslateMessage.SentChatMessage(oldTextComponent.content(), event.player) - } - - @EventHandler - fun onCommandPreprocess(event: PlayerCommandPreprocessEvent) { - val checkSplit = event.message.split(" ", limit = 2)[0] - - if ( - !(checkSplit == "/msg" || - checkSplit == "/whisper" || - checkSplit == "/pm" || - checkSplit == "/reply" || - checkSplit == "/r") - ) { - if (checkSplit == "/s") { - event.isCancelled = true - - if (!event.player.hasPermission("chat-og.staff")) { - event.player.sendMessage( - UtilitiesOG.trueogColorize( - "${Config.prefix}: You do not have permission to run this command." - ) - ) - return - } - - val args = event.message.split(" ").drop(1) - - if (args.isEmpty()) { - if (ChatSystemHelper.inChat[event.player.uniqueId] == ChatType.STAFFCHAT) { - ChatSystemHelper.inChat[event.player.uniqueId] = "" - - event.player.sendMessage( - UtilitiesOG.trueogColorize("${Config.prefix}: You are now talking in normal chat.") - ) - return - } - ChatSystemHelper.inChat[event.player.uniqueId] = ChatType.STAFFCHAT - event.player.sendMessage( - UtilitiesOG.trueogColorize("${Config.prefix}: You are now talking in staff chat.") - ) - return - } - - ChatSystemHelper.sendMessageInStaffChat(event.player, args.joinToString(separator = " ")) - } - return - } - event.isCancelled = true - - val messageSplit: List = - if (checkSplit == "/r" || checkSplit == "/reply") { - event.message.split(" ", ignoreCase = true, limit = 2) - } else { - event.message.split(" ", ignoreCase = true, limit = 3) - } - - if (messageSplit.count() < 3 && !(checkSplit == "/r" || checkSplit == "/reply")) { - event.player.sendMessage(UtilitiesOG.trueogColorize("${messageSplit[0]} ")) - return - } - if (messageSplit.count() < 2) { - event.player.sendMessage(UtilitiesOG.trueogColorize("${messageSplit[0]} ")) - return - } - - val player: Player? - val message: String - - if (checkSplit == "/r" || checkSplit == "/reply") { - message = messageSplit[1] - - if (!lastMessaged.containsKey(event.player.uniqueId)) { - event.player.sendMessage( - UtilitiesOG.trueogColorize("${Config.prefix}: You haven't messaged anyone yet.") - ) - return - } - - val lastMessagedPlayer = lastMessaged[event.player.uniqueId] - player = Bukkit.getPlayer(lastMessagedPlayer!!) - } else { - player = Bukkit.getPlayer(messageSplit[1]) - message = messageSplit[2] - } - - if (player == null) { - event.player.sendMessage( - UtilitiesOG.trueogColorize("${Config.prefix}: That player doesn't exist or isn't online.") - ) - return - } - - val randomUUID = UUID.randomUUID() - - TranslateMessage.pmMessages[randomUUID] = - TranslateMessage.SentPMMessage(message, event.player.uniqueId, player.uniqueId) - - val colourMessage = - if (event.player.hasPermission("chat-og.color")) { - UtilitiesOG.trueogColorize(legacyToMm(message)) - } else { - Component.text(message) - } - - val toSenderPrefix = "[me -> ${player.name}]" - var toSenderTextComponent = - Component.join( - JoinConfiguration.separator(Component.text(" ")), - UtilitiesOG.trueogColorize(toSenderPrefix), - colourMessage, - ) - toSenderTextComponent = - toSenderTextComponent.hoverEvent( - HoverEvent.hoverEvent( - HoverEvent.Action.SHOW_TEXT, - UtilitiesOG.trueogColorize("Click to translate this message"), - ) - ) - toSenderTextComponent = - toSenderTextComponent.clickEvent( - ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/translatemessage $randomUUID 3") - ) - event.player.sendMessage(toSenderTextComponent) - - val toPrefix = "[${event.player.name} -> me]" - var toTextComponent = - Component.join( - JoinConfiguration.separator(Component.text(" ")), - UtilitiesOG.trueogColorize(toPrefix), - colourMessage, - ) - toTextComponent = - toTextComponent.hoverEvent( - HoverEvent.hoverEvent( - HoverEvent.Action.SHOW_TEXT, - UtilitiesOG.trueogColorize("Click to translate this message"), - ) - ) - toTextComponent = - toTextComponent.clickEvent( - ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/translatemessage $randomUUID 3") - ) - player.sendMessage(toTextComponent) - - lastMessaged[event.player.uniqueId] = player.uniqueId - lastMessaged[player.uniqueId] = event.player.uniqueId - - return + TranslateMessage.SentChatMessage(eventMessage.content(), event.player) } @EventHandler fun onDeath(event: PlayerDeathEvent) { - if (!Config.discordEnabled) { + if (!config.discordEnabled) { return } if (ChatOG.essentials.getUser(event.player).isVanished) { @@ -378,16 +222,18 @@ class Events : Listener { if (event.deathMessage() is TextComponent) { ChatOG.scope.launch { - DiscordBridge.sendEmbed( - removeColor((event.deathMessage() as TextComponent).content()), - event.player.uniqueId, - 0xFF0000, - ) + discordBridgeLock.read { + ChatOG.discordBridge?.sendEmbed( + removeColor((event.deathMessage() as TextComponent).content()), + event.player.uniqueId, + 0xFF0000, + ) + } } return } - var nameString = "${ChatOG.chat.getPlayerPrefix(event.player)} ${event.player.name}" + var nameString = "${PlayerAffix.getPrefix(event.player.uniqueId)}${event.player.name}" if (PlaceholderAPI.setPlaceholders(event.player, "%simpleclans_clan_color_tag%") != "") { nameString = PlaceholderAPI.setPlaceholders(event.player, "&8[%simpleclans_clan_color_tag%&8] $nameString") @@ -407,7 +253,9 @@ class Events : Listener { val translatedDeathMessage = PlainTextComponentSerializer.plainText().serialize(deathMessage) ChatOG.scope.launch { - DiscordBridge.sendEmbed(removeColor(translatedDeathMessage), event.player.uniqueId, 0xFF0000) + discordBridgeLock.read { + ChatOG.discordBridge?.sendEmbed(removeColor(translatedDeathMessage), event.player.uniqueId, 0xFF0000) + } } } diff --git a/src/main/kotlin/nl/skbotnl/chatog/Helper.kt b/src/main/kotlin/nl/skbotnl/chatog/Helper.kt index 44ec281..4d9339f 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/Helper.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/Helper.kt @@ -2,18 +2,25 @@ package nl.skbotnl.chatog import dev.minn.jda.ktx.coroutines.await import java.util.* -import net.dv8tion.jda.api.entities.emoji.RichCustomEmoji +import kotlin.concurrent.read import net.kyori.adventure.text.Component -import net.kyori.adventure.text.JoinConfiguration -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 +import net.kyori.adventure.text.minimessage.Context +import net.kyori.adventure.text.minimessage.MiniMessage +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.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.entity.Player -object Helper { +internal object Helper { private var translateTimeout: MutableMap = HashMap() fun getTranslateTimeout(uuid: UUID): Long { @@ -30,25 +37,37 @@ object Helper { return cooldown } + 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 text - .replace("[§&]4".toRegex(), "") - .replace("[§&]c".toRegex(), "") - .replace("[§&]6".toRegex(), "") - .replace("[§&]e".toRegex(), "") - .replace("[§&]2".toRegex(), "") - .replace("[§&]a".toRegex(), "") - .replace("[§&]b".toRegex(), "") - .replace("[§&]3".toRegex(), "") - .replace("[§&]1".toRegex(), "") - .replace("[§&]9".toRegex(), "") - .replace("[§&]d".toRegex(), "") - .replace("[§&]5".toRegex(), "") - .replace("[§&]f".toRegex(), "") - .replace("[§&]7".toRegex(), "") - .replace("[§&]8".toRegex(), "") - .replace("[§&]0".toRegex(), "") - .replace("[§&]r".toRegex(), "") + return legacyRegex.replace(text) { legacyToMmMap[it.groupValues[1].lowercase()] ?: it.value } } private val colorRegex = Regex("[§&]?[§&]([0-9a-fk-orA-FK-OR])") @@ -59,48 +78,12 @@ object Helper { return tempText } - fun getColorSection(text: String): String { - val it = colorRegex.findAll(text).iterator() - - var last = "" - while (it.hasNext()) { - last = it.next().value - } - - return last - } - - fun getFirstColorSection(text: String): String { - val it = colorRegex.findAll(text).iterator() - - var first = "" - while (it.hasNext()) { - first = it.next().value - break - } - - return first - } - - private val getColorRegex = Regex("(&)?&([0-9a-fk-orA-FK-OR])") - - private fun getColor(text: String): String { - val it = getColorRegex.findAll(text).iterator() - - var last = "" - while (it.hasNext()) { - last = it.next().value - } - - return last - } - private val getHandle = Regex("@([a-z0-9_.]{2,32})") suspend fun convertMentions(text: String): String { - val guild = DiscordBridge.jda?.getGuildById(Config.guildId) + val guild = discordBridgeLock.read { ChatOG.discordBridge?.getGuildById(config.guildId!!) } if (guild == null) { - ChatOG.plugin.logger.warning("Can't get the guild, is guildId set?") + ChatOG.plugin.logger.warning("Guild was null") return text } @@ -118,102 +101,98 @@ object Helper { return tempText } - private val urlRegex = - Regex("(.*)((https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;()]*[-a-zA-Z0-9+&@#/%=~_|()])(.*)") + private val urlRegex = Regex("(.*?)((?:https?://)?[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}(?:/?[a-zA-Z]*)+)(.*)") - fun convertLinks(text: String, player: Player): MutableList { - val messageComponents = mutableListOf() + val noColorMm = MiniMessage.builder().editTags { b -> b.tag("a", Helper::createA) }.build() - text.split(" ").forEach { word -> - val urlIter = urlRegex.findAll(word).iterator() - val chatColor = getColor(ChatOG.chat.getPlayerSuffix(player)) + val colorMm = + MiniMessage.builder() + .tags( + TagResolver.builder() + .resolver(StandardTags.color()) + .resolver(StandardTags.decorations()) + .resolver(StandardTags.color()) + .resolver(StandardTags.reset()) + .resolver(StandardTags.rainbow()) + .resolver(StandardTags.gradient()) + .build() + ) + .editTags { b -> b.tag("a", Helper::createA) } + .build() - if (urlIter.hasNext()) { - urlIter.forEach { link -> - if (BlocklistManager.checkUrl(word)) { - player.sendMessage( - UtilitiesOG.trueogColorize( - "${Config.prefix}: WARNING: You are not allowed to post links like that here." - ) - ) - for (onlinePlayer in Bukkit.getOnlinePlayers()) { - if (onlinePlayer.hasPermission("group.moderator")) { - onlinePlayer.sendMessage( - UtilitiesOG.trueogColorize( - "${Config.prefix}: ${player.name} has posted a disallowed link: ${ - word.replace( - ".", - "[dot]", - ) - }." - ) - ) - } - } - return messageComponents - } + fun createA(args: ArgumentQueue, @Suppress("unused") ctx: Context): Tag { + val link = args.popOr("The tag requires exactly one argument, the link to open").value() - var linkComponent = Component.text(link.groups[2]!!.value).color(TextColor.color(34, 100, 255)) - linkComponent = - linkComponent.hoverEvent( - HoverEvent.hoverEvent( - HoverEvent.Action.SHOW_TEXT, - UtilitiesOG.trueogColorize("Click to open link"), - ) - ) - - linkComponent = - linkComponent.clickEvent( - ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, link.groups[2]!!.value) - ) - - val beforeComponent = - UtilitiesOG.trueogColorize(legacyToMm(chatColor) + (link.groups[1]?.value ?: "")) - val afterComponent = - UtilitiesOG.trueogColorize(legacyToMm(chatColor) + (link.groups[4]?.value ?: "")) - - val fullComponent = - Component.join(JoinConfiguration.noSeparators(), beforeComponent, linkComponent, afterComponent) - - messageComponents += fullComponent - } - return@forEach - } - val wordComponent = - if (player.hasPermission("chat-og.color")) { - if (messageComponents.isNotEmpty()) { - val lastContent = (messageComponents.last() as TextComponent).content() - if (getColorSection(lastContent) != "" && getFirstColorSection(word) == "") { - UtilitiesOG.trueogColorize(legacyToMm(getColorSection(lastContent) + word)) - } else { - UtilitiesOG.trueogColorize(legacyToMm(chatColor + word)) - } - } else { - UtilitiesOG.trueogColorize(legacyToMm(chatColor + word)) - } + return Tag.styling( + TextColor.color(34, 100, 255), + ClickEvent.openUrl( + if (!link.startsWith("http")) { + "https://" } else { - Component.join( - JoinConfiguration.noSeparators(), - UtilitiesOG.trueogColorize(legacyToMm(chatColor)), - Component.text(word), - ) - } - messageComponents += wordComponent - } - - return messageComponents + "" + } + link + ), + HoverEvent.showText(UtilitiesOG.trueogColorize("Click to open link")), + ) } - private val emojiRegex = Regex(":(.*?):") + fun processText(text: String, player: Player) = processText(text, player, null) + + fun processText(text: String, username: String) = processText(text, null, username) + + private fun processText(text: String, player: Player?, username: String?): Component? { + val words: MutableList = mutableListOf() + + legacyToMm(text).split(" ").forEach { word -> + val url = urlRegex.find(word) + + if (url != null) { + val link = url.groups[2]?.value ?: "" + if (blocklistManager.checkUrl(link)) { + player?.sendMessage( + UtilitiesOG.trueogColorize( + "${config.prefix}: WARNING: You are not allowed to post links like that here." + ) + ) + for (onlinePlayer in Bukkit.getOnlinePlayers()) { + if (onlinePlayer.hasPermission("group.moderator")) { + onlinePlayer.sendMessage( + UtilitiesOG.trueogColorize( + "${config.prefix}: ${player?.name ?: username} has posted a disallowed link: ${ + word.replace( + ".", + "[dot]", + ) + }." + ) + ) + } + } + return null + } + val before = url.groups[1]?.value ?: "" + val after = url.groups[3]?.value ?: "" + words += "$before$link$after" + } else { + words += word + } + } + + return if (player?.hasPermission("chat-og.color") == true) { + colorMm.deserialize(words.joinToString(" ")) + } else { + noColorMm.deserialize(words.joinToString(" ")) + } + } + + private val emojiRegex = Regex(":([a-zA-Z0-9_]*?):") fun convertEmojis(text: String): String { var discordMessageString = text - var guildEmojis: List? = null - try { - guildEmojis = DiscordBridge.jda?.getGuildById(Config.guildId)?.emojis - } catch (e: Exception) { - ChatOG.plugin.logger.warning("Can't get the guild's emojis, is the guildId set?") + val guildEmojis = discordBridgeLock.read { ChatOG.discordBridge?.getGuildById(config.guildId!!)?.emojis } + if (guildEmojis == null) { + ChatOG.plugin.logger.warning("Guild emojis was null") } if (guildEmojis != null) { diff --git a/src/main/kotlin/nl/skbotnl/chatog/LanguageDatabase.kt b/src/main/kotlin/nl/skbotnl/chatog/LanguageDatabase.kt index 380b453..6d3dafb 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/LanguageDatabase.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/LanguageDatabase.kt @@ -3,9 +3,10 @@ package nl.skbotnl.chatog import io.lettuce.core.RedisClient import io.lettuce.core.RedisConnectionException import java.util.* +import nl.skbotnl.chatog.ChatOG.Companion.config -class LanguageDatabase { - private val redisClient: RedisClient = RedisClient.create(Config.redisUrl) +internal class LanguageDatabase { + private val redisClient: RedisClient = RedisClient.create(config.redisUrl) /** @return True if failed */ fun testConnection(): Boolean { diff --git a/src/main/kotlin/nl/skbotnl/chatog/OpenAI.kt b/src/main/kotlin/nl/skbotnl/chatog/OpenAI.kt index 43e2f71..358b2a0 100644 --- a/src/main/kotlin/nl/skbotnl/chatog/OpenAI.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/OpenAI.kt @@ -5,12 +5,13 @@ import com.google.gson.annotations.SerializedName import java.util.logging.Level import net.kyori.adventure.text.Component import net.trueog.utilitiesog.UtilitiesOG +import nl.skbotnl.chatog.ChatOG.Companion.config import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody -class OpenAI { +internal class OpenAI { data class Translated(val translatedFrom: String?, val translatedText: String?, val error: Component?) private var httpClient: OkHttpClient = OkHttpClient() @@ -30,7 +31,7 @@ class OpenAI { fun translate(text: String, language: String): Translated { val openAICompletion = CompletionReq( - model = Config.openAIModel, + model = config.openAIModel ?: "", messages = listOf( Message( @@ -43,8 +44,8 @@ class OpenAI { val request: Request = Request.Builder() - .url(Config.openAIBaseUrl + "/v1/chat/completions") - .header("Authorization", "Bearer ${Config.openAIApiKey}") + .url(config.openAIBaseUrl + "/v1/chat/completions") + .header("Authorization", "Bearer ${config.openAIApiKey}") .post(gson.toJson(openAICompletion).toRequestBody("application/json".toMediaType())) .build() @@ -60,7 +61,7 @@ class OpenAI { null, null, UtilitiesOG.trueogColorize( - "${Config.prefix}: Something went wrong while translating your message." + "${config.prefix}: Something went wrong while translating that message." ), ) } diff --git a/src/main/kotlin/nl/skbotnl/chatog/PlayerAffix.kt b/src/main/kotlin/nl/skbotnl/chatog/PlayerAffix.kt new file mode 100644 index 0000000..d42189c --- /dev/null +++ b/src/main/kotlin/nl/skbotnl/chatog/PlayerAffix.kt @@ -0,0 +1,58 @@ +package nl.skbotnl.chatog + +import java.util.* + +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) { + user = ChatOG.luckPerms.userManager.loadUser(uuid).get() + } + val prefixNode = user.nodes.singleOrNull { node -> node.key.startsWith("prefix.1.") } + if (prefixNode == null) return "" + return legacyToMm(prefixNode.key.split(".").last()) + " " + } + + fun getSuffix(uuid: UUID): String { + var user = ChatOG.luckPerms.userManager.getUser(uuid) + if (user == null) { + user = ChatOG.luckPerms.userManager.loadUser(uuid).get() + } + val prefixNode = user.nodes.singleOrNull { node -> node.key.startsWith("suffix.1.") } + if (prefixNode == null) return "> " + return legacyToMm(prefixNode.key.split(".").last()) + } +} diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/ChatConfigReload.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/ChatConfigReload.kt index 2ca5ea9..766ebea 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/commands/ChatConfigReload.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/ChatConfigReload.kt @@ -1,9 +1,12 @@ package nl.skbotnl.chatog.commands -import club.minnced.discord.webhook.WebhookClient -import net.dv8tion.jda.api.entities.Activity +import kotlin.concurrent.write +import kotlinx.coroutines.launch import net.trueog.utilitiesog.UtilitiesOG import nl.skbotnl.chatog.ChatOG +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.Config import nl.skbotnl.chatog.DiscordBridge import nl.skbotnl.chatog.LanguageDatabase @@ -12,15 +15,19 @@ import org.bukkit.command.Command import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender -class ChatConfigReload : CommandExecutor { +internal class ChatConfigReload : CommandExecutor { override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array?): Boolean { - if (Config.load()) { - sender.sendMessage( - UtilitiesOG.trueogColorize("Failed to reload the config. Check the console for more information.") - ) - Bukkit.getPluginManager().disablePlugin(ChatOG.plugin) - return true - } + config = + Config.create() + ?: run { + sender.sendMessage( + UtilitiesOG.trueogColorize( + "Failed to reload the config. Check the console for more information." + ) + ) + Bukkit.getPluginManager().disablePlugin(ChatOG.plugin) + return true + } ChatOG.languageDatabase = LanguageDatabase() if (ChatOG.languageDatabase.testConnection()) { @@ -29,20 +36,25 @@ class ChatConfigReload : CommandExecutor { return true } - if (Config.discordEnabled) { - DiscordBridge.webhook = WebhookClient.withUrl(Config.webhook) - if (Config.staffDiscordEnabled) { - DiscordBridge.staffWebhook = WebhookClient.withUrl(Config.staffWebhook) + if (config.discordEnabled) { + scope.launch { + discordBridgeLock.write { + val discordBridge = ChatOG.discordBridge + if (discordBridge != null) { + discordBridge.sendMessageWithBot("Reloading the config...") + discordBridge.shutdownNow() + } + ChatOG.discordBridge = DiscordBridge.create() + sender.sendMessage( + UtilitiesOG.trueogColorize("${config.prefix}: Successfully reloaded the config.") + ) + } } - if (Config.premiumDiscordEnabled) { - DiscordBridge.premiumWebhook = WebhookClient.withUrl(Config.premiumWebhook) - } - DiscordBridge.jda?.presence?.setPresence(Activity.playing(Config.status), false) + } else { + sender.sendMessage( + UtilitiesOG.trueogColorize("${config.prefix}: Successfully reloaded the config.") + ) } - - sender.sendMessage( - UtilitiesOG.trueogColorize("${Config.prefix}: Successfully reloaded the config.") - ) 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 df8f905..d9dec83 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/commands/PremiumChat.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/PremiumChat.kt @@ -1,15 +1,15 @@ package nl.skbotnl.chatog.commands import net.trueog.utilitiesog.UtilitiesOG -import nl.skbotnl.chatog.ChatSystemHelper -import nl.skbotnl.chatog.ChatSystemHelper.ChatType -import nl.skbotnl.chatog.Config +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 PremiumChat : CommandExecutor { +internal class PremiumChat : 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.") @@ -18,28 +18,28 @@ class PremiumChat : CommandExecutor { if (!sender.hasPermission("chat-og.premium")) { sender.sendMessage( UtilitiesOG.trueogColorize( - "${Config.prefix}: You do not have permission to run this command." + "${config.prefix}: You do not have permission to run this command." ) ) return true } if (args == null || args.isEmpty()) { - if (ChatSystemHelper.inChat[sender.uniqueId] == ChatType.PREMIUMCHAT) { - ChatSystemHelper.inChat[sender.uniqueId] = "" + if (ChatSystem.inChat[sender.uniqueId] == ChatType.PREMIUM_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 normal chat.") ) return true } - ChatSystemHelper.inChat[sender.uniqueId] = ChatType.PREMIUMCHAT + 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 premium chat.") ) return true } - ChatSystemHelper.sendMessageInPremiumChat(sender, args.joinToString(separator = " ")) + ChatSystem.sendMessageInPremiumChat(sender, args.joinToString(separator = " ")) return true } diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/PrivateMessage.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/PrivateMessage.kt new file mode 100644 index 0000000..01bdd64 --- /dev/null +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/PrivateMessage.kt @@ -0,0 +1,110 @@ +package nl.skbotnl.chatog.commands + +import java.util.UUID +import kotlin.collections.set +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.JoinConfiguration +import net.kyori.adventure.text.event.ClickEvent +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 org.bukkit.Bukkit +import org.bukkit.command.Command +import org.bukkit.command.CommandExecutor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +internal class PrivateMessage : 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()) { + sender.sendMessage( + UtilitiesOG.trueogColorize( + "${config.prefix}: You did not provide the player that you want to send a message to and your message." + ) + ) + return true + } + if (args.size < 2) { + sender.sendMessage( + UtilitiesOG.trueogColorize( + "${config.prefix}: Please provide the player that you want to send a message to and your message." + ) + ) + return true + } + + val playerName = args[0] + + val toPlayer = Bukkit.getPlayer(playerName) + if (toPlayer == null) { + sender.sendMessage( + UtilitiesOG.trueogColorize("${config.prefix}: That player doesn't exist or isn't online.") + ) + return true + } + + val message = args.drop(1).joinToString(" ") + + val randomUUID = UUID.randomUUID() + + TranslateMessage.pmMessages[randomUUID] = + TranslateMessage.SentPMMessage(message, sender.uniqueId, toPlayer.uniqueId) + + val messageComponent = Helper.processText(message, sender) + if (messageComponent == null) { + return true + } + + val toSenderPrefix = "[me -> ${toPlayer.name}]" + var toSenderTextComponent = + Component.join( + JoinConfiguration.separator(Component.text(" ")), + UtilitiesOG.trueogColorize(toSenderPrefix), + messageComponent, + ) + toSenderTextComponent = + toSenderTextComponent.hoverEvent( + HoverEvent.hoverEvent( + HoverEvent.Action.SHOW_TEXT, + UtilitiesOG.trueogColorize("Click to translate this message"), + ) + ) + toSenderTextComponent = + toSenderTextComponent.clickEvent( + ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/translatemessage $randomUUID 3") + ) + sender.sendMessage(toSenderTextComponent) + + val toPrefix = "[${sender.name} -> me]" + var toTextComponent = + Component.join( + JoinConfiguration.separator(Component.text(" ")), + UtilitiesOG.trueogColorize(toPrefix), + messageComponent, + ) + toTextComponent = + toTextComponent.hoverEvent( + HoverEvent.hoverEvent( + HoverEvent.Action.SHOW_TEXT, + UtilitiesOG.trueogColorize("Click to translate this message"), + ) + ) + toTextComponent = + toTextComponent.clickEvent( + ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/translatemessage $randomUUID 3") + ) + toPlayer.sendMessage(toTextComponent) + + lastMessagedMap[sender.uniqueId] = toPlayer.uniqueId + lastMessagedMap[toPlayer.uniqueId] = sender.uniqueId + + return true + } +} diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/Reply.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/Reply.kt new file mode 100644 index 0000000..8dbcf9a --- /dev/null +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/Reply.kt @@ -0,0 +1,105 @@ +package nl.skbotnl.chatog.commands + +import java.util.UUID +import kotlin.collections.set +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.JoinConfiguration +import net.kyori.adventure.text.event.ClickEvent +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 org.bukkit.Bukkit +import org.bukkit.command.Command +import org.bukkit.command.CommandExecutor +import org.bukkit.command.CommandSender +import org.bukkit.entity.Player + +internal class Reply : 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()) { + sender.sendMessage( + UtilitiesOG.trueogColorize("${config.prefix}: You did not provide your message.") + ) + return true + } + + val lastMessaged = lastMessagedMap[sender.uniqueId] + if (lastMessaged == null) { + sender.sendMessage( + UtilitiesOG.trueogColorize("${config.prefix}: You haven't messaged anyone yet.") + ) + return true + } + + val toPlayer = Bukkit.getPlayer(lastMessaged) + if (toPlayer == null) { + sender.sendMessage( + UtilitiesOG.trueogColorize("${config.prefix}: That player doesn't exist or isn't online.") + ) + return true + } + + val message = args.joinToString(" ") + + val randomUUID = UUID.randomUUID() + + TranslateMessage.pmMessages[randomUUID] = + TranslateMessage.SentPMMessage(message, sender.uniqueId, toPlayer.uniqueId) + + val messageComponent = Helper.processText(message, sender) + if (messageComponent == null) { + return true + } + + val toSenderPrefix = "[me -> ${toPlayer.name}]" + var toSenderTextComponent = + Component.join( + JoinConfiguration.separator(Component.text(" ")), + UtilitiesOG.trueogColorize(toSenderPrefix), + messageComponent, + ) + toSenderTextComponent = + toSenderTextComponent.hoverEvent( + HoverEvent.hoverEvent( + HoverEvent.Action.SHOW_TEXT, + UtilitiesOG.trueogColorize("Click to translate this message"), + ) + ) + toSenderTextComponent = + toSenderTextComponent.clickEvent( + ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/translatemessage $randomUUID 3") + ) + sender.sendMessage(toSenderTextComponent) + + val toPrefix = "[${sender.name} -> me]" + var toTextComponent = + Component.join( + JoinConfiguration.separator(Component.text(" ")), + UtilitiesOG.trueogColorize(toPrefix), + messageComponent, + ) + toTextComponent = + toTextComponent.hoverEvent( + HoverEvent.hoverEvent( + HoverEvent.Action.SHOW_TEXT, + UtilitiesOG.trueogColorize("Click to translate this message"), + ) + ) + toTextComponent = + toTextComponent.clickEvent( + ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/translatemessage $randomUUID 3") + ) + toPlayer.sendMessage(toTextComponent) + + lastMessagedMap[sender.uniqueId] = toPlayer.uniqueId + lastMessagedMap[toPlayer.uniqueId] = sender.uniqueId + 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 e683b3b..54843d4 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/commands/StaffChat.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/StaffChat.kt @@ -1,45 +1,45 @@ package nl.skbotnl.chatog.commands import net.trueog.utilitiesog.UtilitiesOG -import nl.skbotnl.chatog.ChatSystemHelper -import nl.skbotnl.chatog.ChatSystemHelper.ChatType -import nl.skbotnl.chatog.Config +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 StaffChat : CommandExecutor { +internal class StaffChat : 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") + sender.sendMessage("You can only execute this command as a player.") return true } if (!sender.hasPermission("chat-og.staff")) { sender.sendMessage( UtilitiesOG.trueogColorize( - "${Config.prefix}: You do not have permission to run this command." + "${config.prefix}: You do not have permission to run this command." ) ) return true } if (args == null || args.isEmpty()) { - if (ChatSystemHelper.inChat[sender.uniqueId] == ChatType.STAFFCHAT) { - ChatSystemHelper.inChat[sender.uniqueId] = "" + 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 normal chat.") ) return true } - ChatSystemHelper.inChat[sender.uniqueId] = ChatType.STAFFCHAT + ChatSystem.inChat[sender.uniqueId] = ChatType.STAFF_CHAT sender.sendMessage( - UtilitiesOG.trueogColorize("${Config.prefix}: You are now talking in staff chat.") + UtilitiesOG.trueogColorize("${config.prefix}: You are now talking in staff chat.") ) return true } - ChatSystemHelper.sendMessageInStaffChat(sender, args.joinToString(separator = " ")) + ChatSystem.sendMessageInStaffChat(sender, args.joinToString(separator = " ")) 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 d5195fa..ebe4f59 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateMessage.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateMessage.kt @@ -8,16 +8,17 @@ import net.kyori.adventure.text.JoinConfiguration import net.kyori.adventure.text.format.NamedTextColor import net.trueog.utilitiesog.UtilitiesOG import nl.skbotnl.chatog.ChatOG -import nl.skbotnl.chatog.Config +import nl.skbotnl.chatog.ChatOG.Companion.config import nl.skbotnl.chatog.Helper import nl.skbotnl.chatog.Helper.legacyToMm +import nl.skbotnl.chatog.PlayerAffix import org.bukkit.Bukkit import org.bukkit.command.Command import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender import org.bukkit.entity.Player -class TranslateMessage : CommandExecutor { +internal class TranslateMessage : CommandExecutor { interface ISentMessage { val message: String } @@ -56,7 +57,7 @@ class TranslateMessage : CommandExecutor { val player: Player = sender if (Helper.getTranslateTimeout(player.uniqueId) != 0L) { - player.sendMessage(UtilitiesOG.trueogColorize("${Config.prefix}: You're doing that too fast.")) + player.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}: You're doing that too fast.")) return true } @@ -65,7 +66,7 @@ class TranslateMessage : CommandExecutor { try { uuid = UUID.fromString(args[0]) } catch (_: IllegalArgumentException) { - player.sendMessage(UtilitiesOG.trueogColorize("${Config.prefix}: That is not a valid UUID.")) + player.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}: That is not a valid UUID.")) return true } @@ -73,7 +74,7 @@ class TranslateMessage : CommandExecutor { try { messageType = args[1].toInt() } catch (_: NumberFormatException) { - player.sendMessage(UtilitiesOG.trueogColorize("${Config.prefix}: Invalid message type.")) + player.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}: Invalid message type.")) return true } @@ -88,12 +89,12 @@ class TranslateMessage : CommandExecutor { } if (sentMessage == null) { - player.sendMessage(UtilitiesOG.trueogColorize("${Config.prefix}: Could not find that message.")) + player.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}: Could not find that message.")) return true } if (ChatOG.translator == null) { - player.sendMessage(UtilitiesOG.trueogColorize("${Config.prefix}: The translator is disabled.")) + player.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}: The translator is disabled.")) return true } @@ -102,14 +103,14 @@ class TranslateMessage : CommandExecutor { if (language == null) { player.sendMessage( UtilitiesOG.trueogColorize( - "${Config.prefix}: Something went wrong while trying to get your preferred language." + "${config.prefix}: Something went wrong while trying to get your preferred language." ) ) return true } player.sendMessage( - UtilitiesOG.trueogColorize("${Config.prefix}: Translating message (this can take some time)...") + UtilitiesOG.trueogColorize("${config.prefix}: Translating message (this can take some time)...") ) val translated = ChatOG.translator!!.translate(sentMessage.message, language) @@ -121,7 +122,7 @@ class TranslateMessage : CommandExecutor { if (translated.translatedText == null) { player.sendMessage( - UtilitiesOG.trueogColorize("${Config.prefix}: Could not translate that message.") + UtilitiesOG.trueogColorize("${config.prefix}: Could not translate that message.") ) return true } @@ -132,8 +133,8 @@ class TranslateMessage : CommandExecutor { 1 -> { val sentChatMessage = sentMessage as SentChatMessage var playerString = - "${ChatOG.chat.getPlayerPrefix(sentChatMessage.player)}${sentChatMessage.player.name}${ - ChatOG.chat.getPlayerSuffix(sentChatMessage.player) + "${PlayerAffix.getPrefix(sentChatMessage.player.uniqueId)}${sentChatMessage.player.name}${ + PlayerAffix.getSuffix(sentChatMessage.player.uniqueId) }" if (PlaceholderAPI.setPlaceholders(sentMessage.player, "%simpleclans_clan_color_tag%") != "") { playerString = diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateSettings.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateSettings.kt index 523d9b9..b327b46 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateSettings.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateSettings.kt @@ -3,13 +3,13 @@ package nl.skbotnl.chatog.commands import kotlinx.coroutines.DelicateCoroutinesApi import net.trueog.utilitiesog.UtilitiesOG import nl.skbotnl.chatog.ChatOG -import nl.skbotnl.chatog.Config +import nl.skbotnl.chatog.ChatOG.Companion.config import org.bukkit.command.Command import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender import org.bukkit.entity.Player -class TranslateSettings : CommandExecutor { +internal class TranslateSettings : CommandExecutor { companion object { val languagesList = listOf( @@ -74,13 +74,13 @@ class TranslateSettings : CommandExecutor { val language = args[0] if (languagesList.indexOf(language) == -1) { - sender.sendMessage(UtilitiesOG.trueogColorize("${Config.prefix}: Invalid language.")) + sender.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}: Invalid language.")) return true } ChatOG.languageDatabase.setPlayerLanguage(sender.uniqueId, language) sender.sendMessage( - UtilitiesOG.trueogColorize("${Config.prefix}: Set language to: $language.") + UtilitiesOG.trueogColorize("${config.prefix}: Set language to: $language.") ) return true diff --git a/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateSettingsTabCompleter.kt b/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateSettingsTabCompleter.kt index 5f7f2d2..3df71da 100755 --- a/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateSettingsTabCompleter.kt +++ b/src/main/kotlin/nl/skbotnl/chatog/commands/TranslateSettingsTabCompleter.kt @@ -4,7 +4,7 @@ import org.bukkit.command.Command import org.bukkit.command.CommandSender import org.bukkit.command.TabCompleter -class TranslateSettingsTabCompleter : TabCompleter { +internal class TranslateSettingsTabCompleter : TabCompleter { override fun onTabComplete( sender: CommandSender, command: Command, diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7892e01..75dcbd0 100755 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -3,7 +3,13 @@ version: '${version}' main: nl.skbotnl.chatog.ChatOG author: SKBotNL api-version: '${apiVersion}' -depend: [ PlaceholderAPI, Vault, AnnouncerPlus, Utilities-OG, Essentials ] +depend: + - PlaceholderAPI + - LuckPerms + - AnnouncerPlus + - Utilities-OG +softdepend: + - Essentials commands: translatemessage: description: Internal command for translating messages @@ -20,6 +26,24 @@ commands: s: description: Toggle or talk in staff chat usage: /s OR /s + pc: + description: Toggle or talk in premium chat + usage: /p OR /p p: description: Toggle or talk in premium chat usage: /p OR /p + msg: + description: Send a private message to a player + usage: /msg + whisper: + description: Send a private message to a player + usage: /whisper + pm: + description: Send a private message to a player + usage: /pm + r: + description: Sends a message to the player that you messaged last or who last messaged you + usage: /r + reply: + description: Sends a message to the player that you messaged last or who last messaged you + usage: /reply