diff --git a/src/main/kotlin/moe/kageru/kagebot/command/Command.kt b/src/main/kotlin/moe/kageru/kagebot/command/Command.kt index efdef14..6d7f930 100644 --- a/src/main/kotlin/moe/kageru/kagebot/command/Command.kt +++ b/src/main/kotlin/moe/kageru/kagebot/command/Command.kt @@ -5,6 +5,7 @@ import moe.kageru.kagebot.Log import moe.kageru.kagebot.MessageUtil import moe.kageru.kagebot.Util.applyIf import moe.kageru.kagebot.config.Config +import moe.kageru.kagebot.config.LocalizationSpec import moe.kageru.kagebot.config.RawCommand import moe.kageru.kagebot.features.MessageFeature import org.javacord.api.entity.message.MessageAuthor @@ -41,8 +42,8 @@ class Command(cmd: RawCommand) { fun execute(message: MessageCreateEvent): Boolean { if (permissions?.isAllowed(message) == false) { - if (Config.localization.permissionDenied.isNotBlank()) { - message.channel.sendMessage(Config.localization.permissionDenied) + if (Config.localization[LocalizationSpec.permissionDenied].isNotBlank()) { + message.channel.sendMessage(Config.localization[LocalizationSpec.permissionDenied]) } Log.info("Denying command ${this.trigger} to user ${message.messageAuthor.discriminatedName} (ID: ${message.messageAuthor.id})") return false @@ -62,9 +63,10 @@ class Command(cmd: RawCommand) { fun matches(msg: String) = this.matchType.matches(msg, this) - private fun respond(author: MessageAuthor, response: String) = response.applyIf(response.contains(AUTHOR_PLACEHOLDER)) { - it.replace(AUTHOR_PLACEHOLDER, MessageUtil.mention(author)) - } + private fun respond(author: MessageAuthor, response: String) = + response.applyIf(response.contains(AUTHOR_PLACEHOLDER)) { + it.replace(AUTHOR_PLACEHOLDER, MessageUtil.mention(author)) + } } enum class MatchType { diff --git a/src/main/kotlin/moe/kageru/kagebot/command/MessageActions.kt b/src/main/kotlin/moe/kageru/kagebot/command/MessageActions.kt index 0f35c2e..103cce9 100644 --- a/src/main/kotlin/moe/kageru/kagebot/command/MessageActions.kt +++ b/src/main/kotlin/moe/kageru/kagebot/command/MessageActions.kt @@ -3,6 +3,7 @@ package moe.kageru.kagebot.command import moe.kageru.kagebot.Log import moe.kageru.kagebot.MessageUtil.sendEmbed import moe.kageru.kagebot.config.Config +import moe.kageru.kagebot.config.LocalizationSpec import moe.kageru.kagebot.config.RawMessageActions import org.javacord.api.event.message.MessageCreateEvent @@ -24,7 +25,7 @@ class MessageActions(rawActions: RawMessageActions) { message.deleteMessage() message.messageAuthor.asUser().ifPresent { user -> user.sendEmbed { - addField("__Blacklisted__", Config.localization.messageDeleted) + addField("__Blacklisted__", Config.localization[LocalizationSpec.messageDeleted]) addField("Original:", "“${message.readableMessageContent}”") } } diff --git a/src/main/kotlin/moe/kageru/kagebot/command/MessageRedirect.kt b/src/main/kotlin/moe/kageru/kagebot/command/MessageRedirect.kt index 5a471d3..d1e01ad 100644 --- a/src/main/kotlin/moe/kageru/kagebot/command/MessageRedirect.kt +++ b/src/main/kotlin/moe/kageru/kagebot/command/MessageRedirect.kt @@ -6,6 +6,7 @@ import moe.kageru.kagebot.Util import moe.kageru.kagebot.Util.applyIf import moe.kageru.kagebot.Util.failed import moe.kageru.kagebot.config.Config +import moe.kageru.kagebot.config.LocalizationSpec import moe.kageru.kagebot.config.RawRedirect import org.javacord.api.entity.channel.TextChannel import org.javacord.api.event.message.MessageCreateEvent @@ -21,7 +22,7 @@ internal class MessageRedirect(rawRedirect: RawRedirect) { .applyIf(command.matchType == MatchType.PREFIX) { content -> content.removePrefix(command.trigger).trim() } - addField(Config.localization.redirectedMessage, redirectedText) + addField(Config.localization[LocalizationSpec.redirectedMessage], redirectedText) Log.info("Redirected message: $redirectedText") } // No inlined if/else because the types are different. diff --git a/src/main/kotlin/moe/kageru/kagebot/config/Config.kt b/src/main/kotlin/moe/kageru/kagebot/config/Config.kt index 99383c7..766de74 100644 --- a/src/main/kotlin/moe/kageru/kagebot/config/Config.kt +++ b/src/main/kotlin/moe/kageru/kagebot/config/Config.kt @@ -7,10 +7,11 @@ import moe.kageru.kagebot.features.Features import org.javacord.api.entity.server.Server object Config { - val specs = Config { addSpec(SystemSpec) }.from.toml - lateinit var config: Config + val systemSpec = Config { addSpec(SystemSpec) }.from.toml + val localeSpec = Config { addSpec(LocalizationSpec) }.from.toml + lateinit var system: Config + lateinit var localization: Config lateinit var server: Server lateinit var commands: List lateinit var features: Features - lateinit var localization: Localization } diff --git a/src/main/kotlin/moe/kageru/kagebot/config/ConfigParser.kt b/src/main/kotlin/moe/kageru/kagebot/config/ConfigParser.kt index 8a04d60..b469eab 100644 --- a/src/main/kotlin/moe/kageru/kagebot/config/ConfigParser.kt +++ b/src/main/kotlin/moe/kageru/kagebot/config/ConfigParser.kt @@ -11,21 +11,16 @@ object ConfigParser { fun initialLoad(file: String) { val rawConfig = RawConfig.read(file) - val config = Config.specs.file(RawConfig.getFile(file)) - Config.config = config - + val configFile = RawConfig.getFile(file) + val config = Config.systemSpec.file(configFile) + Config.system = config Config.server = Globals.api.getServerById(config[serverId]) .orElseThrow { IllegalArgumentException("Invalid server configured.") } - reloadLocalization(rawConfig) + Config.localization = Config.localeSpec.file(configFile) reloadFeatures(rawConfig) reloadCommands(rawConfig) } - fun reloadLocalization(rawConfig: RawConfig) { - Config.localization = rawConfig.localization?.let(::Localization) - ?: throw IllegalArgumentException("No [localization] block in config.") - } - fun reloadCommands(rawConfig: RawConfig) { Config.commands = rawConfig.commands?.map(::Command)?.toMutableList() ?: throw IllegalArgumentException("No commands found in config.") @@ -36,22 +31,3 @@ object ConfigParser { ?: Features(RawFeatures(null, null)) } } - -class Localization( - val permissionDenied: String, - val redirectedMessage: String, - val messageDeleted: String, - val timeout: String -) { - - constructor(rawLocalization: RawLocalization) : this( - permissionDenied = rawLocalization.permissionDenied - ?: throw IllegalArgumentException("No [localization.permissionDenied] defined"), - redirectedMessage = rawLocalization.redirectedMessage - ?: throw IllegalArgumentException("No [localization.redirectMessage] defined"), - messageDeleted = rawLocalization.messageDeleted - ?: throw IllegalArgumentException("No [localization.messageDeleted] defined"), - timeout = rawLocalization.timeout - ?: throw IllegalArgumentException("No [localization.timeout] defined") - ) -} diff --git a/src/main/kotlin/moe/kageru/kagebot/config/RawConfig.kt b/src/main/kotlin/moe/kageru/kagebot/config/RawConfig.kt index 3fe7798..3ab1795 100644 --- a/src/main/kotlin/moe/kageru/kagebot/config/RawConfig.kt +++ b/src/main/kotlin/moe/kageru/kagebot/config/RawConfig.kt @@ -3,12 +3,11 @@ package moe.kageru.kagebot.config import com.google.gson.annotations.SerializedName import com.moandjiezana.toml.Toml import com.uchuhimo.konf.ConfigSpec -import moe.kageru.kagebot.config.Config.config +import moe.kageru.kagebot.config.Config.system import java.awt.Color import java.io.File class RawConfig( - val localization: RawLocalization?, @SerializedName("command") val commands: List?, @SerializedName("feature") @@ -38,12 +37,12 @@ class RawConfig( object SystemSpec : ConfigSpec() { private val rawColor by optional("#1793d0", name = "color") val serverId by required() - val color by kotlin.lazy { Color.decode(config[rawColor])!! } + val color by kotlin.lazy { Color.decode(system[rawColor])!! } } -class RawLocalization( - val permissionDenied: String?, - val redirectedMessage: String?, - val messageDeleted: String?, - val timeout: String? -) +object LocalizationSpec : ConfigSpec() { + val permissionDenied by optional("You do not have the permission to use this command.") + val redirectedMessage by optional("says") + val messageDeleted by optional("Your message was deleted.") + val timeout by optional("You have been timed out for @@ minutes.") +} diff --git a/src/main/kotlin/moe/kageru/kagebot/features/SetConfigFeature.kt b/src/main/kotlin/moe/kageru/kagebot/features/SetConfigFeature.kt index 4a59d5f..17c8235 100644 --- a/src/main/kotlin/moe/kageru/kagebot/features/SetConfigFeature.kt +++ b/src/main/kotlin/moe/kageru/kagebot/features/SetConfigFeature.kt @@ -2,6 +2,7 @@ package moe.kageru.kagebot.features import moe.kageru.kagebot.Log import moe.kageru.kagebot.MessageUtil.sendEmbed +import moe.kageru.kagebot.config.Config import moe.kageru.kagebot.config.ConfigParser import moe.kageru.kagebot.config.RawConfig import org.javacord.api.entity.channel.TextChannel @@ -22,7 +23,7 @@ class SetConfigFeature : MessageFeature { return } try { - ConfigParser.reloadLocalization(rawConfig) + Config.localization = Config.localeSpec.string(newConfig) ConfigParser.reloadFeatures(rawConfig) ConfigParser.reloadCommands(rawConfig) ConfigParser.configFile.writeText(newConfig) diff --git a/src/main/kotlin/moe/kageru/kagebot/features/TimeoutFeature.kt b/src/main/kotlin/moe/kageru/kagebot/features/TimeoutFeature.kt index ef33ebe..ef01c1d 100644 --- a/src/main/kotlin/moe/kageru/kagebot/features/TimeoutFeature.kt +++ b/src/main/kotlin/moe/kageru/kagebot/features/TimeoutFeature.kt @@ -6,6 +6,7 @@ import moe.kageru.kagebot.Util.findRole import moe.kageru.kagebot.Util.findUser import moe.kageru.kagebot.Util.ifNotEmpty import moe.kageru.kagebot.config.Config +import moe.kageru.kagebot.config.LocalizationSpec import moe.kageru.kagebot.config.RawTimeoutFeature import moe.kageru.kagebot.persistence.Dao import org.javacord.api.entity.permission.Role @@ -41,7 +42,10 @@ class TimeoutFeature(raw: RawTimeoutFeature) : MessageFeature { val releaseTime = Instant.now().plus(Duration.ofMinutes(timeout.duration)).epochSecond Dao.saveTimeout(releaseTime, listOf(user.id) + oldRoles) user.sendEmbed { - addField("Timeout", Config.localization.timeout.replace("@@", timeout.duration.toString())) + addField( + "Timeout", + Config.localization[LocalizationSpec.timeout].replace("@@", timeout.duration.toString()) + ) timeout.reason?.let { addField("Reason", it) } diff --git a/src/test/kotlin/moe/kageru/kagebot/ConfigTest.kt b/src/test/kotlin/moe/kageru/kagebot/ConfigTest.kt index 27bc0fe..527820c 100644 --- a/src/test/kotlin/moe/kageru/kagebot/ConfigTest.kt +++ b/src/test/kotlin/moe/kageru/kagebot/ConfigTest.kt @@ -6,6 +6,7 @@ import io.kotlintest.specs.ShouldSpec import io.mockk.every import io.mockk.mockk import moe.kageru.kagebot.config.Config +import moe.kageru.kagebot.config.LocalizationSpec import moe.kageru.kagebot.config.SystemSpec import moe.kageru.kagebot.features.SetConfigFeature import java.awt.Color @@ -14,9 +15,8 @@ import java.awt.Color class ConfigTest : ShouldSpec({ TestUtil.prepareTestEnvironment() "should properly parse test config" { - Config.config[SystemSpec.serverId] shouldNotBe null + Config.system[SystemSpec.serverId] shouldNotBe null SystemSpec.color shouldBe Color.decode("#1793d0") - Config.localization shouldNotBe null Config.features shouldNotBe null Config.commands.size shouldBe 3 } @@ -38,6 +38,6 @@ class ConfigTest : ShouldSpec({ every { url.openStream().readAllBytes() } returns testConfig.toByteArray() }) SetConfigFeature().handle(message) - Config.localization.permissionDenied shouldBe denied + Config.localization[LocalizationSpec.permissionDenied] shouldBe denied } }) diff --git a/src/test/kotlin/moe/kageru/kagebot/TestUtil.kt b/src/test/kotlin/moe/kageru/kagebot/TestUtil.kt index 5d5d42f..14cf93f 100644 --- a/src/test/kotlin/moe/kageru/kagebot/TestUtil.kt +++ b/src/test/kotlin/moe/kageru/kagebot/TestUtil.kt @@ -116,7 +116,7 @@ object TestUtil { return (embed.delegate as EmbedBuilderDelegateImpl).toJsonNode().toString() } - fun withCommands(config: String, test: (() -> R)) { + fun withCommands(config: String, test: (() -> Unit)) { val oldCmds = Config.commands val rawConfig = RawConfig.readFromString(config) ConfigParser.reloadCommands(rawConfig) @@ -124,10 +124,9 @@ object TestUtil { Config.commands = oldCmds } - fun withLocalization(config: String, test: (() -> R)) { + fun withLocalization(config: String, test: (() -> Unit)) { val oldLoc = Config.localization - val rawConfig = RawConfig.readFromString(config) - ConfigParser.reloadLocalization(rawConfig) + Config.localization = Config.localeSpec.string(config) test() Config.localization = oldLoc } diff --git a/src/test/kotlin/moe/kageru/kagebot/command/CommandTest.kt b/src/test/kotlin/moe/kageru/kagebot/command/CommandTest.kt index 8cf3e14..1456b5c 100644 --- a/src/test/kotlin/moe/kageru/kagebot/command/CommandTest.kt +++ b/src/test/kotlin/moe/kageru/kagebot/command/CommandTest.kt @@ -5,7 +5,6 @@ import io.kotlintest.shouldBe import io.kotlintest.specs.StringSpec import io.mockk.every import io.mockk.mockk -import moe.kageru.kagebot.config.Config import moe.kageru.kagebot.Globals import moe.kageru.kagebot.Kagebot.process import moe.kageru.kagebot.TestUtil @@ -17,6 +16,9 @@ import moe.kageru.kagebot.TestUtil.testMessageSuccess import moe.kageru.kagebot.TestUtil.withCommands import moe.kageru.kagebot.TestUtil.withLocalization import moe.kageru.kagebot.Util +import moe.kageru.kagebot.config.Config +import moe.kageru.kagebot.config.Config.localization +import moe.kageru.kagebot.config.LocalizationSpec import org.javacord.api.entity.message.embed.EmbedBuilder import org.javacord.api.entity.permission.Role import org.javacord.api.entity.user.User @@ -146,7 +148,7 @@ class CommandTest : StringSpec({ val replies = mutableListOf() val mockMessage = mockMessage("!restricted", replies = replies) mockMessage.process() - replies shouldBe mutableListOf(Config.localization.permissionDenied) + replies shouldBe mutableListOf(localization[LocalizationSpec.permissionDenied]) withLocalization( """ [localization] @@ -231,7 +233,7 @@ class CommandTest : StringSpec({ every { get().getRoles(any()) } returns emptyList() } mockMessage.process() - calls shouldBe mutableListOf(Config.localization.permissionDenied, "access granted") + calls shouldBe mutableListOf(localization[LocalizationSpec.permissionDenied], "access granted") } } "should refuse DM only message in server channel" { @@ -246,7 +248,7 @@ class CommandTest : StringSpec({ ) { val calls = mutableListOf() mockMessage("!dm", replies = calls).process() - calls shouldBe listOf(Config.localization.permissionDenied) + calls shouldBe listOf(localization[LocalizationSpec.permissionDenied]) } } /* diff --git a/src/test/kotlin/moe/kageru/kagebot/features/HelpFeatureTest.kt b/src/test/kotlin/moe/kageru/kagebot/features/HelpFeatureTest.kt index bc831c0..0686b85 100644 --- a/src/test/kotlin/moe/kageru/kagebot/features/HelpFeatureTest.kt +++ b/src/test/kotlin/moe/kageru/kagebot/features/HelpFeatureTest.kt @@ -3,12 +3,12 @@ package moe.kageru.kagebot.features import io.kotlintest.specs.StringSpec import io.mockk.every import io.mockk.mockk -import moe.kageru.kagebot.config.Config import moe.kageru.kagebot.Kagebot.process import moe.kageru.kagebot.TestUtil import moe.kageru.kagebot.TestUtil.mockMessage import moe.kageru.kagebot.TestUtil.withCommands import moe.kageru.kagebot.TestUtil.withReplyContents +import moe.kageru.kagebot.config.Config import org.javacord.api.entity.message.embed.EmbedBuilder import java.util.*