Skip to content

Commit

Permalink
add mention settings
Browse files Browse the repository at this point in the history
  • Loading branch information
Lars committed Dec 1, 2024
1 parent 427ac30 commit 8900398
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 59 deletions.
96 changes: 57 additions & 39 deletions src/main/kotlin/net/rk4z/fabricord/Fabricord.kt
Original file line number Diff line number Diff line change
@@ -1,48 +1,31 @@
package net.rk4z.fabricord

import net.fabricmc.api.DedicatedServerModInitializer
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents
import net.fabricmc.fabric.api.message.v1.ServerMessageEvents
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents
import net.fabricmc.loader.api.FabricLoader
import net.minecraft.text.Text
import net.rk4z.fabricord.discord.DiscordBotManager
import net.rk4z.fabricord.discord.DiscordEmbed
import net.rk4z.fabricord.discord.DiscordPlayerEventHandler.handleMCMessage
import net.rk4z.fabricord.utils.System
import net.rk4z.s1.swiftbase.core.CB
import net.rk4z.s1.swiftbase.core.LMB
import net.rk4z.s1.swiftbase.core.Logger
import net.rk4z.s1.swiftbase.fabric.DedicatedServerModEntry
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.yaml.snakeyaml.Yaml
import java.nio.file.Path
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService

class Fabricord : DedicatedServerModEntry(
"fabricord",
"net.rk4z.fabricord",
false,
id= "fabricord",
packageName = "net.rk4z.fabricord",
isDebug = false,
configFile = "config.yml",
availableLang = listOf("ja", "en"),
langDir = "lang",
logger = LoggerFactory.getLogger(Fabricord::class.simpleName),
enableUpdateChecker = true,
modrinthID = "xU8Bn98V",
) {
//TODO: 言語の実装、起動時の呼び出しの実装
companion object {
private const val MOD_ID = "fabricord"

val logger: Logger = LoggerFactory.getLogger(Fabricord::class.simpleName)

private val loader: FabricLoader = FabricLoader.getInstance()
val executorService: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()

private val serverDir: Path = loader.gameDir.toRealPath()
private val modDir: Path = serverDir.resolve(MOD_ID)

private val yaml = Yaml()
private var initializeIsDone = false

//region Configurations
// Required
var botToken: String? = null
Expand All @@ -62,37 +45,72 @@ class Fabricord : DedicatedServerModEntry(
var botActivityMessage: String? = null

var messageStyle: String? = null

var allowMention: Boolean? = false
var allowEveryone: Boolean? = false
var allowHere: Boolean? = false
var allowRoleMention: Boolean? = false
var allowedRoles: List<String>? = null
var allowUserMention: Boolean? = false
var allowedUsers: List<String>? = null

var webHookId: String? = null
//endregion
}

override fun onInitializeServer() {
logger.info("Initializing Fabricord...")
val name: String = description.name
val version: String = description.version.friendlyString

override fun onInstanceInitialized() {
CB.apply {
onCheckUpdate = {
Logger.info(LMB.getSysMessage(System.Log.CHECKING_UPDATE))
}

onAllVersionsRetrieved = { versionCount ->
Logger.info(LMB.getSysMessage(System.Log.ALL_VERSION_COUNT, versionCount.toString()))
}

onNewVersionFound = { latestVersion, newerVersionCount ->
Logger.info(LMB.getSysMessage(System.Log.NEW_VERSION_COUNT, newerVersionCount.toString()))
Logger.info(LMB.getSysMessage(System.Log.LATEST_VERSION_FOUND, latestVersion, version))
Logger.info(LMB.getSysMessage(System.Log.VIEW_LATEST_VER, MODRINTH_DOWNLOAD_URL))
}

onNoNewVersionFound = {
Logger.info(LMB.getSysMessage(System.Log.YOU_ARE_USING_LATEST))
}

onUpdateCheckFailed = { responseCode ->
Logger.warn(LMB.getSysMessage(System.Log.FAILED_TO_CHECK_UPDATE, responseCode.toString()))
}

onUpdateCheckError = { e ->
Logger.error(LMB.getSysMessage(System.Log.ERROR_WHILE_CHECKING_UPDATE, e.message ?: LMB.getSysMessage(System.Log.Other.UNKNOWN_ERROR)))
}
}
}

override fun onDirectoriesAndFilesInitialized() {
Logger.info(LMB.getSysMessage(System.Log.LOADING, name, version))
loadConfig()

if (requiredNullCheck()) {
logger.error("Bot token or log channel ID is missing in config file.")
logger.error("Maybe you are running the mod for the first time?")
logger.error("Please check the config file at $configFile")
Logger.error(LMB.getSysMessage(System.Log.MissingRequiredParam.ITEM_0))
Logger.error(LMB.getSysMessage(System.Log.MissingRequiredParam.ITEM_1))
Logger.error(LMB.getSysMessage(System.Log.MissingRequiredParam.ITEM_2, "$configFile"))
return
}
nullCheck()

registerEvents()

initializeIsDone = true
logger.info("Fabricord initialized successfully.")
Logger.info(LMB.getSysMessage(System.Log.INITIALIZED, name))
}

private fun registerEvents() {
ServerMessageEvents.CHAT_MESSAGE.register(ServerMessageEvents.ChatMessage { message, sender, _ ->
executorService.submit {
CB.executor.executeAsync {
val content = message.content.string
handleMCMessage(sender, content)
}
Expand All @@ -102,29 +120,29 @@ class Fabricord : DedicatedServerModEntry(
val player = handler.player

if (!DiscordBotManager.botIsInitialized) {
player.networkHandler.disconnect(Text.of("Server is still starting up, please try again later."))
player.networkHandler.disconnect(Text.of(LMB.getSysMessage(System.Log.STILLSTARTINGUP)))
return@Join
}

executorService.submit {
CB.executor.executeAsync {
DiscordEmbed.sendPlayerJoinEmbed(player)
}
})

ServerPlayConnectionEvents.DISCONNECT.register(ServerPlayConnectionEvents.Disconnect { handler, _ ->
executorService.submit {
CB.executor.executeAsync {
val player = handler.player
DiscordEmbed.sendPlayerLeftEmbed(player)
}
})

ServerLifecycleEvents.SERVER_STARTED.register { server ->
executorService.submit {
CB.executor.executeAsync {
try {
DiscordBotManager.init(server)
DiscordBotManager.startBot()
} catch (e: Exception) {
logger.error("Failed to start Discord bot", e)
logger.error(LMB.getSysMessage(System.Log.FAILEDSTART, e))
server.stop(false)
}
}
Expand All @@ -133,9 +151,8 @@ class Fabricord : DedicatedServerModEntry(
ServerLifecycleEvents.SERVER_STOPPING.register { _ ->
try {
DiscordBotManager.stopBot()
executorService.shutdownNow()
} catch (e: Exception) {
logger.error("Failed to stop Discord bot", e)
logger.error(LMB.getSysMessage(System.Log.FAILEDSTOP, e))
}
}
}
Expand Down Expand Up @@ -163,6 +180,7 @@ class Fabricord : DedicatedServerModEntry(

messageStyle = lc("MessageStyle")

allowMention = lc("AllowedMentions.AllowMention")
allowEveryone = lc("AllowedMentions.AllowEveryone")
allowHere = lc("AllowedMentions.AllowHere")
allowRoleMention = lc("AllowedMentions.AllowRole")
Expand Down
69 changes: 51 additions & 18 deletions src/main/kotlin/net/rk4z/fabricord/discord/DiscordBotManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import net.dv8tion.jda.api.JDA
import net.dv8tion.jda.api.JDABuilder
import net.dv8tion.jda.api.OnlineStatus
import net.dv8tion.jda.api.entities.Activity
import net.dv8tion.jda.api.entities.Message
import net.dv8tion.jda.api.entities.Webhook
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
import net.dv8tion.jda.api.events.message.MessageReceivedEvent
Expand All @@ -14,10 +15,10 @@ import net.dv8tion.jda.api.requests.GatewayIntent
import net.minecraft.server.MinecraftServer
import net.minecraft.server.network.ServerPlayerEntity
import net.rk4z.fabricord.Fabricord
import net.rk4z.fabricord.Fabricord.Companion.executorService
import net.rk4z.s1.swiftbase.core.CB
import net.rk4z.s1.swiftbase.core.Logger
import java.awt.Color
import java.util.*
import java.util.concurrent.TimeUnit
import javax.security.auth.login.LoginException

object DiscordBotManager : ListenerAdapter() {
Expand All @@ -33,7 +34,7 @@ object DiscordBotManager : ListenerAdapter() {
}

fun startBot() {
executorService.submit {
CB.executor.execute {
val onlineStatus = getOnlineStatus()
val activity = getBotActivity()

Expand All @@ -54,32 +55,32 @@ object DiscordBotManager : ListenerAdapter() {
jda?.updateCommands()

botIsInitialized = true
Fabricord.logger.info("Discord bot is now online")
Logger.info("Discord bot is now online")
Fabricord.serverStartMessage?.let { sendToDiscord(it) }

if (Fabricord.messageStyle == "modern") {
if (!Fabricord.webHookId.isNullOrBlank()) {
webHook = jda?.retrieveWebhookById(Fabricord.webHookId!!)?.complete()
} else {
Fabricord.logger.error("The message style is set to 'modern' but the webhook URL is not configured.")
Logger.error("The message style is set to 'modern' but the webhook URL is not configured.")
}
}
} catch (e: LoginException) {
Fabricord.logger.error("Failed to login to Discord with the provided token", e)
Logger.error("Failed to login to Discord with the provided token", e)
} catch (e: Exception) {
Fabricord.logger.error("An unexpected error occurred during Discord bot startup", e)
Logger.error("An unexpected error occurred during Discord bot startup", e)
}
}
}

fun stopBot() {
if (botIsInitialized) {
Fabricord.serverStopMessage?.let { sendToDiscord(it) }
Fabricord.logger.info("Discord bot is now offline")
Logger.info("Discord bot is now offline")
jda?.shutdown()
botIsInitialized = false
} else {
Fabricord.logger.error("Discord bot is not initialized. Cannot stop the bot.")
Logger.error("Discord bot is not initialized. Cannot stop the bot.")
}
}

Expand Down Expand Up @@ -113,9 +114,9 @@ object DiscordBotManager : ListenerAdapter() {

private val discordListener = object : ListenerAdapter() {
override fun onMessageReceived(event: MessageReceivedEvent) {
val server = server ?: return Fabricord.logger.error("MinecraftServer is not initialized. Cannot process Discord message.")
val server = server ?: return Logger.error("MinecraftServer is not initialized. Cannot process Discord message.")

executorService.submit {
CB.executor.executeAsync {
val mentionedPlayers = findMentionedPlayers(event.message.contentRaw, server.playerManager.playerList)
if (mentionedPlayers.isNotEmpty()) {
DiscordMessageHandler.handleMentionedDiscordMessage(event, server, mentionedPlayers, false)
Expand All @@ -128,13 +129,13 @@ object DiscordBotManager : ListenerAdapter() {

private fun handlePlayerListCommand(event: SlashCommandInteractionEvent) {
val server = server ?: run {
Fabricord.logger.error("MinecraftServer is not initialized. Cannot process /playerlist command.")
Logger.error("MinecraftServer is not initialized. Cannot process /playerlist command.")
event.reply("Sorry, I can't get the player list right now.")
.setEphemeral(true)
.queue {
executorService.schedule({
CB.executor.executeAsyncLater({
it.deleteOriginal().queue()
}, 5, TimeUnit.SECONDS)
}, 5000)
}
return
}
Expand Down Expand Up @@ -176,10 +177,42 @@ object DiscordBotManager : ListenerAdapter() {
}

fun sendToDiscord(message: String) {
executorService.submit {
Fabricord.logChannelID?.let {
val messageAction = jda?.getTextChannelById(it)?.sendMessage(message)
if (Fabricord.allowMentions == false) {
CB.executor.executeAsync {
Fabricord.logChannelID?.let { logChannelID ->
val messageAction = jda?.getTextChannelById(logChannelID)?.sendMessage(message)
if (Fabricord.allowMention == true) {
val allowedMentions = mutableSetOf<Message.MentionType>()

if (Fabricord.allowEveryone == true) {
allowedMentions.add(Message.MentionType.EVERYONE)
}

if (Fabricord.allowHere == true) {
allowedMentions.add(Message.MentionType.HERE)
}

if (Fabricord.allowRoleMention == true) {
allowedMentions.add(Message.MentionType.ROLE)

if (!Fabricord.allowedRoles.isNullOrEmpty()) {
messageAction?.mentionRoles(Fabricord.allowedRoles!!)
} else {
messageAction?.mentionRoles(emptyList()) // 空リストを指定して全ロール許可
}
}

if (Fabricord.allowUserMention == true) {
allowedMentions.add(Message.MentionType.USER)

if (!Fabricord.allowedUsers.isNullOrEmpty()) {
messageAction?.mentionUsers(Fabricord.allowedUsers!!)
} else {
messageAction?.mentionUsers(emptyList()) // 空リストを指定して全ユーザー許可
}
}

messageAction?.setAllowedMentions(allowedMentions)
} else {
messageAction?.setAllowedMentions(emptySet())
}
messageAction?.queue()
Expand Down
38 changes: 38 additions & 0 deletions src/main/kotlin/net/rk4z/fabricord/utils/Translations.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package net.rk4z.fabricord.utils

import net.rk4z.s1.swiftbase.fabric.FabricMessageKey

@Suppress("MISSING_DEPENDENCY_SUPERCLASS_IN_TYPE_ARGUMENT", "ClassName", "unused")
open class System : FabricMessageKey {
open class Log : System() {
object LOADING : Log()
object ENABLING : Log()
object DISABLING : Log()
object INITIALIZED : Log()

open class MissingRequiredParam : Log() {
object ITEM_0 : MissingRequiredParam()
object ITEM_1 : MissingRequiredParam()
object ITEM_2 : MissingRequiredParam()
}

object STILLSTARTINGUP : Log()
object FAILEDSTART : Log()
object FAILEDSTOP : Log()

object CHECKING_UPDATE : Log()
object ALL_VERSION_COUNT : Log()
object NEW_VERSION_COUNT : Log()
object VIEW_LATEST_VER : Log()
object LATEST_VERSION_FOUND : Log()
object YOU_ARE_USING_LATEST : Log()
object FAILED_TO_CHECK_UPDATE : Log()
object ERROR_WHILE_CHECKING_UPDATE : Log()

open class Other : Log() {
object UNKNOWN : Other()
object UNKNOWN_ERROR : Other()
object ERROR : Other()
}
}
}
Loading

0 comments on commit 8900398

Please sign in to comment.