diff --git a/src/main/kotlin/com/dominikkorsa/discordintegration/DiscordIntegration.kt b/src/main/kotlin/com/dominikkorsa/discordintegration/DiscordIntegration.kt index 8f1ce1e..3820309 100644 --- a/src/main/kotlin/com/dominikkorsa/discordintegration/DiscordIntegration.kt +++ b/src/main/kotlin/com/dominikkorsa/discordintegration/DiscordIntegration.kt @@ -34,6 +34,7 @@ class DiscordIntegration: JavaPlugin() { val discordFormatter = DiscordFormatter(this) val minecraftFormatter = MinecraftFormatter(this) val avatarService = AvatarService(this) + val lockFileService = LockFileService(this) lateinit var configManager: ConfigManager lateinit var messageManager: MessageManager private var activityJob: Job? = null @@ -45,11 +46,15 @@ class DiscordIntegration: JavaPlugin() { messageManager = MessageManager(this) initCommands() registerEvents() - this.launchAsync { connect(true) } + this.launchAsync { + connect(true) + lockFileService.start() + } } override fun onDisable() { super.onDisable() + lockFileService.stop() runBlocking { withTimeout(Duration.ofSeconds(5)) { disconnect(true) @@ -86,7 +91,9 @@ class DiscordIntegration: JavaPlugin() { client.disconnect() } - suspend fun reconnect() { + suspend fun reload() { + configManager.reload() + messageManager.reload() connectionLock.withLock { disconnect(false) connect(false) diff --git a/src/main/kotlin/com/dominikkorsa/discordintegration/LockFileService.kt b/src/main/kotlin/com/dominikkorsa/discordintegration/LockFileService.kt new file mode 100644 index 0000000..1fbec59 --- /dev/null +++ b/src/main/kotlin/com/dominikkorsa/discordintegration/LockFileService.kt @@ -0,0 +1,60 @@ +package com.dominikkorsa.discordintegration + +import com.github.shynixn.mccoroutine.launchAsync +import discord4j.core.spec.EmbedCreateSpec +import kotlinx.coroutines.Job +import kotlinx.coroutines.isActive +import kotlinx.coroutines.time.delay +import java.time.Duration +import java.util.* + +class LockFileService(private val plugin: DiscordIntegration) { + private var job: Job? = null + private val file = plugin.dataFolder.resolve("lock.txt") + + suspend fun start() { + readFile()?.let { notifyCrashed(it) } + job = plugin.launchAsync { + while (isActive) { + updateFile() + delay(Duration.ofSeconds(15)) + } + } + } + + fun stop() { + job?.cancel() + job = null + file.delete() + } + + private fun readFile(): Long? { + if (!file.exists()) return null + return file.readText().toLong() + } + + private fun updateFile() { + file.writeText(Date().time.toString()) + } + + private suspend fun notifyCrashed(timestamp: Long) { + if (!plugin.configManager.crashEmbed.enabled) return + val webhookBuilder = plugin.client.getWebhookBuilder() + plugin.client.sendWebhook( + webhookBuilder + .addEmbed( + EmbedCreateSpec.builder() + .title(plugin.messageManager.discordCrashEmbedTitle) + .description(plugin.messageManager.discordCrashEmbedContent) + .addField( + plugin.messageManager.discordCrashEmbedLastOnline, + "", + false + ) + .color(plugin.configManager.crashEmbed.color) + .build() + ) + .build() + ) + } +} diff --git a/src/main/kotlin/com/dominikkorsa/discordintegration/command/DiscordIntegrationCommand.kt b/src/main/kotlin/com/dominikkorsa/discordintegration/command/DiscordIntegrationCommand.kt index 4d95bf3..aafc3ac 100644 --- a/src/main/kotlin/com/dominikkorsa/discordintegration/command/DiscordIntegrationCommand.kt +++ b/src/main/kotlin/com/dominikkorsa/discordintegration/command/DiscordIntegrationCommand.kt @@ -11,11 +11,7 @@ class DiscordIntegrationCommand(val plugin: DiscordIntegration): BaseCommand() { @Subcommand("reload") @CommandPermission("discordintegration.command.reload") fun onReload() { - plugin.launchAsync { - plugin.configManager.reload() - plugin.messageManager.reload() - plugin.reconnect() - } + plugin.launchAsync { plugin.reload() } } @Subcommand("help") diff --git a/src/main/kotlin/com/dominikkorsa/discordintegration/config/ConfigManager.kt b/src/main/kotlin/com/dominikkorsa/discordintegration/config/ConfigManager.kt index 7891b12..a52ae36 100644 --- a/src/main/kotlin/com/dominikkorsa/discordintegration/config/ConfigManager.kt +++ b/src/main/kotlin/com/dominikkorsa/discordintegration/config/ConfigManager.kt @@ -44,4 +44,5 @@ class ConfigManager(private val plugin: DiscordIntegration) { val joinEmbed get() = getEmbedConfig("chat.join-embed") val quitEmbed get() = getEmbedConfig("chat.quit-embed") val deathEmbed get() = getEmbedConfig("chat.death-embed") + val crashEmbed get() = getEmbedConfig("chat.crash-embed") } diff --git a/src/main/kotlin/com/dominikkorsa/discordintegration/config/MessageManager.kt b/src/main/kotlin/com/dominikkorsa/discordintegration/config/MessageManager.kt index e5c668a..83f7ab0 100644 --- a/src/main/kotlin/com/dominikkorsa/discordintegration/config/MessageManager.kt +++ b/src/main/kotlin/com/dominikkorsa/discordintegration/config/MessageManager.kt @@ -34,6 +34,9 @@ class MessageManager(plugin: DiscordIntegration) { val discordDeath get() = getString("discord.death") val discordDeathFallback get() = getString("discord.death-fallback") val discordDeathEmbedTitle get() = getString("discord.death-embed-title") + val discordCrashEmbedTitle get() = getString("discord.crash-embed.title") + val discordCrashEmbedContent get() = getString("discord.crash-embed.content") + val discordCrashEmbedLastOnline get() = getString("discord.crash-embed.last-online") val commandsHelpHeader get() = getString("commands.help.header") val commandsHelpCommand get() = getString("commands.help.command") val commandsUnknown get() = getString("commands.unknown") diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index c93eb6e..416ab1a 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -14,6 +14,9 @@ chat: death-embed: enabled: true color: 0xffd166 + crash-embed: + enabled: true + color: 0xff8d0a player-as-status-author: false avatar: # Set to true on cracked servers, diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index ecfe90c..9da3684 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -8,6 +8,13 @@ discord: death: '**%death-message%**' death-fallback: '**%player% died**' death-embed-title: '**%player% died**' + crash-embed: + title: Server started after crash + content: | + The previous server process did not exit properly. + It might have crashed or have been force stopped. + This might also be an error of Discord Integration. + last-online: Last online minecraft: message: '§2%nickname% §7in #%channel-name%§7 » §r%content%' tooltip: | @@ -21,7 +28,7 @@ commands: §9§lDiscord Integration help§r §9Version: §l%plugin-version%§r command: '§9> §r%command% §9- %description%§r' - unknown: '§cUnknown command. See avaliable commands using §r/di help' + unknown: '§cUnknown command. See available commands using §r/di help' descriptions: help: 'Show list of plugin commands' reload: 'Reload plugin configuration and reconnect'