Internal cleanup #6

Merged
SKBotNL merged 2 commits from main into main 2025-07-22 11:03:27 -04:00
24 changed files with 1396 additions and 1115 deletions

No files matched your search

+1
View File
@@ -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")
@@ -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<String>()
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) }
}
}
@@ -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
}
}
@@ -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<reset>$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
}
}
+68 -49
View File
@@ -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<UUID, UUID> = 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()
}
}
@@ -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<UUID, String> = HashMap()
var inChat: MutableMap<UUID, ChatType> = 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<reset>${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<reset>${PlayerAffix.getSuffix(player.uniqueId)}"))
var textComponent = Component.join(JoinConfiguration.noSeparators(), chatComponent, messageComponent)
textComponent =
+224 -221
View File
@@ -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<String> = listOf()
var roles: Set<String> = setOf()
var roleMessageColor: MutableMap<String, Any> = 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<String, NamedTextColor>(
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<String, NamedTextColor>(
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
}
}
}
+348 -347
View File
@@ -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<ReadyEvent> {
sendMessageWithBot(Config.serverHasStartedMessage)
jda?.getGuildById(Config.guildId)
?.upsertCommand(Config.listCommandName, "List all online players.")
?.queue()
}
jda?.listener<SlashCommandInteractionEvent> {
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<ReadyEvent> {
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<SlashCommandInteractionEvent> {
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<MessageReceivedEvent> {
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>(Component.text(" >").color(messageColor))
val attachmentComponents = mutableListOf<Component>()
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("<green>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}<reset>: @${user.name} has posted a disallowed link: ${
word.replace(
".",
"[dot]",
)
}."
)
)
}
}
return@listener
}
discordBridge.jda.listener<MessageReceivedEvent> {
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("<green>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>(Component.text(">"))
val attachmentComponents = mutableListOf<Component>()
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("<green>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("<green>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("<green>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<MessageChannel>(Config.channelId)
val channel = jda.getChannel<MessageChannel>(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())
}
}
@@ -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}Line truncated
+78 -230
View File
@@ -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<UUID, UUID> = 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}<reset>: <red>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}<reset>: You are now talking in normal chat.")
)
return
}
ChatSystemHelper.inChat[event.player.uniqueId] = ChatType.STAFFCHAT
event.player.sendMessage(
UtilitiesOG.trueogColorize("${Config.prefix}<reset>: You are now talking in staff chat.")
)
return
}
ChatSystemHelper.sendMessageInStaffChat(event.player, args.joinToString(separator = " "))
}
return
}
event.isCancelled = true
val messageSplit: List<String> =
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("<red>${messageSplit[0]} <to> <message>"))
return
}
if (messageSplit.count() < 2) {
event.player.sendMessage(UtilitiesOG.trueogColorize("<red>${messageSplit[0]} <message>"))
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}<reset>: <red>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}<reset>: <red>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 = "<gold>[<red>me <gold>-> <dark_red>${player.name}<gold>]<white>"
var toSenderTextComponent =
Component.join(
JoinConfiguration.separator(Component.text(" ")),
UtilitiesOG.trueogColorize(toSenderPrefix),
colourMessage,
)
toSenderTextComponent =
toSenderTextComponent.hoverEvent(
HoverEvent.hoverEvent(
HoverEvent.Action.SHOW_TEXT,
UtilitiesOG.trueogColorize("<green>Click to translate this message"),
)
)
toSenderTextComponent =
toSenderTextComponent.clickEvent(
ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/translatemessage $randomUUID 3")
)
event.player.sendMessage(toSenderTextComponent)
val toPrefix = "<gold>[<dark_red>${event.player.name} <gold>-> <red>me<gold>]<white>"
var toTextComponent =
Component.join(
JoinConfiguration.separator(Component.text(" ")),
UtilitiesOG.trueogColorize(toPrefix),
colourMessage,
)
toTextComponent =
toTextComponent.hoverEvent(
HoverEvent.hoverEvent(
HoverEvent.Action.SHOW_TEXT,
UtilitiesOG.trueogColorize("<green>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)
}
}
}
+124 -145
View File
@@ -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<UUID, Long> = HashMap()
fun getTranslateTimeout(uuid: UUID): Long {
@@ -30,25 +37,37 @@ object Helper {
return cooldown
}
private val legacyToMmMap =
mapOf(
"0" to "<black>",
"1" to "<dark_blue>",
"2" to "<dark_green>",
"3" to "<dark_aqua>",
"4" to "<dark_red>",
"5" to "<dark_purple>",
"6" to "<gold>",
"7" to "<gray>",
"8" to "<dark_gray>",
"9" to "<blue>",
"a" to "<green>",
"b" to "<aqua>",
"c" to "<red>",
"d" to "<light_purple>",
"e" to "<yellow>",
"f" to "<white>",
"k" to "<obfuscated>",
"l" to "<bold>",
"m" to "<strikethrough>",
"n" to "<underlined>",
"o" to "<italic>",
"r" to "<reset>",
"*" to "<rainbow>",
)
val legacyRegex = Regex("[§&]([0-9a-fk-or*])", RegexOption.IGNORE_CASE)
fun legacyToMm(text: String): String {
return text
.replace("[§&]4".toRegex(), "<dark_red>")
.replace("[§&]c".toRegex(), "<red>")
.replace("[§&]6".toRegex(), "<gold>")
.replace("[§&]e".toRegex(), "<yellow>")
.replace("[§&]2".toRegex(), "<dark_green>")
.replace("[§&]a".toRegex(), "<green>")
.replace("[§&]b".toRegex(), "<aqua>")
.replace("[§&]3".toRegex(), "<dark_aqua>")
.replace("[§&]1".toRegex(), "<dark_blue>")
.replace("[§&]9".toRegex(), "<blue>")
.replace("[§&]d".toRegex(), "<light_purple>")
.replace("[§&]5".toRegex(), "<dark_purple>")
.replace("[§&]f".toRegex(), "<white>")
.replace("[§&]7".toRegex(), "<gray>")
.replace("[§&]8".toRegex(), "<dark_gray>")
.replace("[§&]0".toRegex(), "<black>")
.replace("[§&]r".toRegex(), "<reset>")
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<Component> {
val messageComponents = mutableListOf<Component>()
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}<reset>: <red>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}<reset>: ${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 <a> 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("<green>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("<green>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<String> = 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}<reset>: <red>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}<reset>: ${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<a:$link>$link</a>$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<RichCustomEmoji>? = 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) {
@@ -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 {
+6 -5
View File
@@ -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}<reset>: <red>Something went wrong while translating your message."
"${config.prefix}<reset>: <red>Something went wrong while translating that message."
),
)
}
@@ -0,0 +1,58 @@
package nl.skbotnl.chatog
import java.util.*
internal object PlayerAffix {
private val legacyToMmMap =
mapOf(
"0" to "<black>",
"1" to "<dark_blue>",
"2" to "<dark_green>",
"3" to "<dark_aqua>",
"4" to "<dark_red>",
"5" to "<dark_purple>",
"6" to "<gold>",
"7" to "<gray>",
"8" to "<dark_gray>",
"9" to "<blue>",
"a" to "<green>",
"b" to "<aqua>",
"c" to "<red>",
"d" to "<light_purple>",
"e" to "<yellow>",
"f" to "<white>",
"k" to "<obfuscated>",
"l" to "<bold>",
"m" to "<strikethrough>",
"n" to "<underlined>",
"o" to "<italic>",
"r" to "<reset>",
"*" to "<rainbow>",
)
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())
}
}
@@ -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<out String>?): Boolean {
if (Config.load()) {
sender.sendMessage(
UtilitiesOG.trueogColorize("<red>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(
"<red>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}<reset>: <green>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}<reset>: <green>Successfully reloaded the config.")
)
}
sender.sendMessage(
UtilitiesOG.trueogColorize("${Config.prefix}<reset>: <green>Successfully reloaded the config.")
)
return true
}
}
@@ -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<out String>?): 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}<reset>: <red>You do not have permission to run this command."
"${config.prefix}<reset>: <red>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}<reset>: You are now talking in normal chat.")
UtilitiesOG.trueogColorize("${config.prefix}<reset>: 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}<reset>: You are now talking in premium chat.")
UtilitiesOG.trueogColorize("${config.prefix}<reset>: You are now talking in premium chat.")
)
return true
}
ChatSystemHelper.sendMessageInPremiumChat(sender, args.joinToString(separator = " "))
ChatSystem.sendMessageInPremiumChat(sender, args.joinToString(separator = " "))
return true
}
@@ -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<out String>?): 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}<reset>: <red>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}<reset>: <red>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}<reset>: <red>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 = "<gold>[<red>me <gold>-> <dark_red>${toPlayer.name}<gold>]<white>"
var toSenderTextComponent =
Component.join(
JoinConfiguration.separator(Component.text(" ")),
UtilitiesOG.trueogColorize(toSenderPrefix),
messageComponent,
)
toSenderTextComponent =
toSenderTextComponent.hoverEvent(
HoverEvent.hoverEvent(
HoverEvent.Action.SHOW_TEXT,
UtilitiesOG.trueogColorize("<green>Click to translate this message"),
)
)
toSenderTextComponent =
toSenderTextComponent.clickEvent(
ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/translatemessage $randomUUID 3")
)
sender.sendMessage(toSenderTextComponent)
val toPrefix = "<gold>[<dark_red>${sender.name} <gold>-> <red>me<gold>]<white>"
var toTextComponent =
Component.join(
JoinConfiguration.separator(Component.text(" ")),
UtilitiesOG.trueogColorize(toPrefix),
messageComponent,
)
toTextComponent =
toTextComponent.hoverEvent(
HoverEvent.hoverEvent(
HoverEvent.Action.SHOW_TEXT,
UtilitiesOG.trueogColorize("<green>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
}
}
@@ -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<out String>?): 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}<reset>: <red>You did not provide your message.")
)
return true
}
val lastMessaged = lastMessagedMap[sender.uniqueId]
if (lastMessaged == null) {
sender.sendMessage(
UtilitiesOG.trueogColorize("${config.prefix}<reset>: <red>You haven't messaged anyone yet.")
)
return true
}
val toPlayer = Bukkit.getPlayer(lastMessaged)
if (toPlayer == null) {
sender.sendMessage(
UtilitiesOG.trueogColorize("${config.prefix}<reset>: <red>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 = "<gold>[<red>me <gold>-> <dark_red>${toPlayer.name}<gold>]<white>"
var toSenderTextComponent =
Component.join(
JoinConfiguration.separator(Component.text(" ")),
UtilitiesOG.trueogColorize(toSenderPrefix),
messageComponent,
)
toSenderTextComponent =
toSenderTextComponent.hoverEvent(
HoverEvent.hoverEvent(
HoverEvent.Action.SHOW_TEXT,
UtilitiesOG.trueogColorize("<green>Click to translate this message"),
)
)
toSenderTextComponent =
toSenderTextComponent.clickEvent(
ClickEvent.clickEvent(ClickEvent.Action.RUN_COMMAND, "/translatemessage $randomUUID 3")
)
sender.sendMessage(toSenderTextComponent)
val toPrefix = "<gold>[<dark_red>${sender.name} <gold>-> <red>me<gold>]<white>"
var toTextComponent =
Component.join(
JoinConfiguration.separator(Component.text(" ")),
UtilitiesOG.trueogColorize(toPrefix),
messageComponent,
)
toTextComponent =
toTextComponent.hoverEvent(
HoverEvent.hoverEvent(
HoverEvent.Action.SHOW_TEXT,
UtilitiesOG.trueogColorize("<green>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
}
}
@@ -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<out String>?): 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}<reset>: <red>You do not have permission to run this command."
"${config.prefix}<reset>: <red>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}<reset>: You are now talking in normal chat.")
UtilitiesOG.trueogColorize("${config.prefix}<reset>: 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}<reset>: You are now talking in staff chat.")
UtilitiesOG.trueogColorize("${config.prefix}<reset>: You are now talking in staff chat.")
)
return true
}
ChatSystemHelper.sendMessageInStaffChat(sender, args.joinToString(separator = " "))
ChatSystem.sendMessageInStaffChat(sender, args.joinToString(separator = " "))
return true
}
@@ -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}<reset>: <red>You're doing that too fast."))
player.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}<reset>: <red>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}<reset>: <red>That is not a valid UUID."))
player.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}<reset>: <red>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}<reset>: <red>Invalid message type."))
player.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}<reset>: <red>Invalid message type."))
return true
}
@@ -88,12 +89,12 @@ class TranslateMessage : CommandExecutor {
}
if (sentMessage == null) {
player.sendMessage(UtilitiesOG.trueogColorize("${Config.prefix}<reset>: <red>Could not find that message."))
player.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}<reset>: <red>Could not find that message."))
return true
}
if (ChatOG.translator == null) {
player.sendMessage(UtilitiesOG.trueogColorize("${Config.prefix}<reset>: <red>The translator is disabled."))
player.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}<reset>: <red>The translator is disabled."))
return true
}
@@ -102,14 +103,14 @@ class TranslateMessage : CommandExecutor {
if (language == null) {
player.sendMessage(
UtilitiesOG.trueogColorize(
"${Config.prefix}<reset>: <red>Something went wrong while trying to get your preferred language."
"${config.prefix}<reset>: <red>Something went wrong while trying to get your preferred language."
)
)
return true
}
player.sendMessage(
UtilitiesOG.trueogColorize("${Config.prefix}<reset>: Translating message (this can take some time)...")
UtilitiesOG.trueogColorize("${config.prefix}<reset>: 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}<reset>: <red>Could not translate that message.")
UtilitiesOG.trueogColorize("${config.prefix}<reset>: <red>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 =
@@ -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}<reset>: <red>Invalid language."))
sender.sendMessage(UtilitiesOG.trueogColorize("${config.prefix}<reset>: <red>Invalid language."))
return true
}
ChatOG.languageDatabase.setPlayerLanguage(sender.uniqueId, language)
sender.sendMessage(
UtilitiesOG.trueogColorize("${Config.prefix}<reset>: <green>Set language to: <white>$language.")
UtilitiesOG.trueogColorize("${config.prefix}<reset>: <green>Set language to: <white>$language.")
)
return true
@@ -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,
+25 -1
View File
@@ -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 <message here>
pc:
description: Toggle or talk in premium chat
usage: /p OR /p <message here>
p:
description: Toggle or talk in premium chat
usage: /p OR /p <message here>
msg:
description: Send a private message to a player
usage: /msg <player name> <message>
whisper:
description: Send a private message to a player
usage: /whisper <player name> <message>
pm:
description: Send a private message to a player
usage: /pm <player name> <message>
r:
description: Sends a message to the player that you messaged last or who last messaged you
usage: /r <message>
reply:
description: Sends a message to the player that you messaged last or who last messaged you
usage: /reply <message>