Add features as configurable command output
This commit is contained in:
parent
731867f59e
commit
344148cd03
@ -3,6 +3,7 @@ package moe.kageru.kagebot
|
||||
import moe.kageru.kagebot.command.Command
|
||||
import moe.kageru.kagebot.config.Config
|
||||
import moe.kageru.kagebot.config.SystemConfig
|
||||
import moe.kageru.kagebot.features.Features
|
||||
import org.javacord.api.DiscordApi
|
||||
import org.javacord.api.entity.server.Server
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
@ -13,5 +14,6 @@ object Globals {
|
||||
lateinit var config: Config
|
||||
lateinit var commands: List<Command>
|
||||
lateinit var systemConfig: SystemConfig
|
||||
lateinit var features: Features
|
||||
var commandCounter: AtomicInteger = AtomicInteger(0)
|
||||
}
|
@ -4,7 +4,6 @@ import moe.kageru.kagebot.Log.log
|
||||
import moe.kageru.kagebot.Util.checked
|
||||
import moe.kageru.kagebot.config.Config
|
||||
import moe.kageru.kagebot.config.RawConfig
|
||||
import moe.kageru.kagebot.features.MessageFeature
|
||||
import org.javacord.api.DiscordApiBuilder
|
||||
import org.javacord.api.event.message.MessageCreateEvent
|
||||
import org.javacord.api.event.server.member.ServerMemberJoinEvent
|
||||
@ -65,18 +64,9 @@ object Kagebot {
|
||||
})
|
||||
log.info("kagebot Mk II running")
|
||||
Globals.api.addMessageCreateListener { checked { processMessage(it) } }
|
||||
Globals.config.features.welcome?.let { welcome ->
|
||||
if (welcome.enabled) {
|
||||
Globals.api.addServerMemberJoinListener {
|
||||
checked { welcomeUser(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
for (feature in Globals.config.features.allWithMessage()) {
|
||||
if (feature.commandEnabled) {
|
||||
Globals.api.addMessageCreateListener {
|
||||
checked { feature.handle(it) }
|
||||
}
|
||||
Globals.config.features.welcome?.let {
|
||||
Globals.api.addServerMemberJoinListener {
|
||||
checked { welcomeUser(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import moe.kageru.kagebot.Log.log
|
||||
import moe.kageru.kagebot.MessageUtil
|
||||
import moe.kageru.kagebot.Util.doIf
|
||||
import moe.kageru.kagebot.config.RawCommand
|
||||
import moe.kageru.kagebot.features.MessageFeature
|
||||
import org.javacord.api.entity.message.MessageAuthor
|
||||
import org.javacord.api.entity.message.embed.EmbedBuilder
|
||||
import org.javacord.api.event.message.MessageCreateEvent
|
||||
@ -20,6 +21,7 @@ class Command(cmd: RawCommand) {
|
||||
private val actions: MessageActions?
|
||||
val regex: Regex?
|
||||
val embed: EmbedBuilder?
|
||||
val feature: MessageFeature?
|
||||
|
||||
init {
|
||||
trigger = cmd.trigger ?: throw IllegalArgumentException("Every command must have a trigger.")
|
||||
@ -32,6 +34,7 @@ class Command(cmd: RawCommand) {
|
||||
actions = cmd.actions?.let { MessageActions(it) }
|
||||
regex = if (matchType == MatchType.REGEX) Regex(trigger) else null
|
||||
embed = cmd.embed?.let(MessageUtil::mapToEmbed)
|
||||
feature = cmd.feature?.let { Globals.features.findByString(it) }
|
||||
}
|
||||
|
||||
fun isAllowed(message: MessageCreateEvent) = permissions?.isAllowed(message) ?: true
|
||||
@ -53,6 +56,7 @@ class Command(cmd: RawCommand) {
|
||||
this.embed?.let {
|
||||
message.channel.sendMessage(embed)
|
||||
}
|
||||
this.feature?.handle(message)
|
||||
}
|
||||
|
||||
fun matches(msg: String) = this.matchType.matches(msg, this)
|
||||
|
@ -16,9 +16,11 @@ class Config(rawConfig: RawConfig) {
|
||||
init {
|
||||
Globals.systemConfig = system
|
||||
Globals.server = api.getServerById(system.serverId).orElseThrow()
|
||||
Globals.features = rawConfig.features?.let(::Features) ?: Features(RawFeatures(null))
|
||||
// TODO: remove this
|
||||
this.features = Globals.features
|
||||
Globals.commands = rawConfig.commands?.map(::Command) ?: emptyList()
|
||||
Globals.config = this
|
||||
this.features = rawConfig.features?.let(::Features) ?: Features.NONE
|
||||
}
|
||||
|
||||
fun reloadLocalization(rawLocalization: RawLocalization) {
|
||||
|
@ -8,7 +8,8 @@ class RawCommand(
|
||||
val matchType: String?,
|
||||
val permissions: RawPermissions?,
|
||||
@SerializedName("action") val actions: RawMessageActions?,
|
||||
val embed: Map<String, String>?
|
||||
val embed: Map<String, String>?,
|
||||
val feature: String?
|
||||
)
|
||||
|
||||
class RawPermissions(val hasOneOf: List<String>?, val hasNoneOf: List<String>?, val onlyDM: Boolean)
|
||||
|
@ -1,16 +1,4 @@
|
||||
package moe.kageru.kagebot.config
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
|
||||
class RawFeatures(val welcome: RawWelcomeFeature?, val debug: RawDebugFeature?, val help: RawHelpFeature?)
|
||||
class RawWelcomeFeature(
|
||||
val enable: Boolean,
|
||||
val content: Map<String, String>?,
|
||||
val fallbackChannel: String?,
|
||||
val fallbackMessage: String?,
|
||||
@SerializedName("command") val commandEnabled: Boolean
|
||||
)
|
||||
|
||||
class RawDebugFeature(val enable: Boolean)
|
||||
class RawHelpFeature(val enable: Boolean)
|
||||
class RawFeatures(val welcome: RawWelcomeFeature?)
|
||||
class RawWelcomeFeature(val content: Map<String, String>?, val fallbackChannel: String?, val fallbackMessage: String?)
|
||||
|
@ -3,21 +3,17 @@ package moe.kageru.kagebot.features
|
||||
import com.sun.management.OperatingSystemMXBean
|
||||
import moe.kageru.kagebot.Globals
|
||||
import moe.kageru.kagebot.MessageUtil
|
||||
import moe.kageru.kagebot.config.RawDebugFeature
|
||||
import org.javacord.api.entity.message.embed.EmbedBuilder
|
||||
import org.javacord.api.event.message.MessageCreateEvent
|
||||
import java.lang.management.ManagementFactory
|
||||
import java.time.Duration
|
||||
import java.time.temporal.ChronoUnit
|
||||
|
||||
class DebugFeature(rawDebugFeatures: RawDebugFeature): MessageFeature() {
|
||||
override val commandEnabled = rawDebugFeatures.enable
|
||||
class DebugFeature : MessageFeature() {
|
||||
|
||||
override fun handleInternal(message: MessageCreateEvent) {
|
||||
if (message.messageAuthor.isBotOwner) {
|
||||
if (message.readableMessageContent.startsWith("!debugstats")) {
|
||||
message.channel.sendMessage(getPerformanceStats())
|
||||
}
|
||||
message.channel.sendMessage(getPerformanceStats())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,19 +2,14 @@ package moe.kageru.kagebot.features
|
||||
|
||||
import moe.kageru.kagebot.config.RawFeatures
|
||||
|
||||
class Features(val welcome: WelcomeFeature?, val debug: DebugFeature?, val help: HelpFeature?) {
|
||||
class Features(val welcome: WelcomeFeature?, debug: DebugFeature, help: HelpFeature) {
|
||||
constructor(rawFeatures: RawFeatures) : this(
|
||||
rawFeatures.welcome?.let(::WelcomeFeature),
|
||||
rawFeatures.debug?.let(::DebugFeature),
|
||||
rawFeatures.help?.let(::HelpFeature)
|
||||
DebugFeature(),
|
||||
HelpFeature()
|
||||
)
|
||||
|
||||
fun all() = listOfNotNull(this.welcome, this.debug, this.help)
|
||||
fun allWithMessage() = all().filterIsInstance<MessageFeature>()
|
||||
private val featureMap = mapOf("help" to help, "debug" to debug, "welcome" to welcome)
|
||||
|
||||
companion object {
|
||||
val NONE = Features(null, null, null)
|
||||
}
|
||||
fun findByString(feature: String) = featureMap[feature]
|
||||
}
|
||||
|
||||
interface Feature
|
@ -3,24 +3,18 @@ package moe.kageru.kagebot.features
|
||||
import moe.kageru.kagebot.Globals
|
||||
import moe.kageru.kagebot.MessageUtil
|
||||
import moe.kageru.kagebot.command.MatchType
|
||||
import moe.kageru.kagebot.config.RawHelpFeature
|
||||
import org.javacord.api.event.message.MessageCreateEvent
|
||||
|
||||
class HelpFeature(rawFeature: RawHelpFeature) : MessageFeature() {
|
||||
override val commandEnabled = rawFeature.enable
|
||||
|
||||
class HelpFeature : MessageFeature() {
|
||||
override fun handleInternal(message: MessageCreateEvent) {
|
||||
if (message.readableMessageContent.startsWith("!help")) {
|
||||
message.channel.sendMessage(
|
||||
MessageUtil.getEmbedBuilder()
|
||||
.addField("Commands:", listCommands(message))
|
||||
)
|
||||
}
|
||||
message.channel.sendMessage(
|
||||
MessageUtil.getEmbedBuilder()
|
||||
.addField("Commands:", listCommands(message))
|
||||
)
|
||||
}
|
||||
|
||||
private fun listCommands(message: MessageCreateEvent) =
|
||||
Globals.commands
|
||||
.filter { it.matchType == MatchType.PREFIX && it.isAllowed(message) }
|
||||
.map { it.trigger }
|
||||
.joinToString("\n")
|
||||
}
|
||||
|
||||
private fun listCommands(message: MessageCreateEvent) = Globals.commands
|
||||
.filter { it.matchType == MatchType.PREFIX && it.isAllowed(message) }
|
||||
.map { it.trigger }
|
||||
.joinToString("\n")
|
@ -1,16 +1,10 @@
|
||||
package moe.kageru.kagebot.features
|
||||
|
||||
import moe.kageru.kagebot.Globals
|
||||
import org.javacord.api.event.message.MessageCreateEvent
|
||||
|
||||
abstract class MessageFeature : Feature {
|
||||
abstract val commandEnabled: Boolean
|
||||
|
||||
abstract class MessageFeature {
|
||||
fun handle(message: MessageCreateEvent) {
|
||||
if (commandEnabled) {
|
||||
Globals.commandCounter.incrementAndGet()
|
||||
handleInternal(message)
|
||||
}
|
||||
handleInternal(message)
|
||||
}
|
||||
|
||||
internal abstract fun handleInternal(message: MessageCreateEvent)
|
||||
|
@ -8,15 +8,10 @@ import org.javacord.api.entity.message.embed.EmbedBuilder
|
||||
import org.javacord.api.event.message.MessageCreateEvent
|
||||
|
||||
class WelcomeFeature(rawWelcome: RawWelcomeFeature) : MessageFeature() {
|
||||
override val commandEnabled = rawWelcome.commandEnabled
|
||||
|
||||
override fun handleInternal(message: MessageCreateEvent) {
|
||||
if (message.readableMessageContent == "!welcome") {
|
||||
message.channel.sendMessage(embed)
|
||||
}
|
||||
message.channel.sendMessage(embed)
|
||||
}
|
||||
|
||||
val enabled: Boolean = rawWelcome.enable
|
||||
val embed: EmbedBuilder? by lazy {
|
||||
rawWelcome.content?.let(MessageUtil::mapToEmbed)
|
||||
}
|
||||
|
@ -13,9 +13,6 @@ messageDeleted = "Your message was deleted because it contained a banned word or
|
||||
# If the user has disabled their DMs, the fallbackMessage will be sent in the fallbackChannel instead.
|
||||
# If no fallback channel or message is specified, no fallback will be sent.
|
||||
[feature.welcome]
|
||||
enable = true
|
||||
# enable the !welcome command which will print the welcome embed
|
||||
command = true
|
||||
fallbackChannel = "555097559023222825"
|
||||
fallbackMessage = "@@ I would like to greet you, but I can’t. :("
|
||||
# This is a list of pairs where the key is the title and the value the content of the paragraph.
|
||||
@ -24,13 +21,6 @@ fallbackMessage = "@@ I would like to greet you, but I can’t. :("
|
||||
"Welcome to the Server" = "This is the content of the first paragraph"
|
||||
"Second paragraph heading" = "Second paragraph content"
|
||||
|
||||
# allow the bot owner to get debug stats
|
||||
[feature.debug]
|
||||
enable = true
|
||||
|
||||
[feature.help]
|
||||
enable = true
|
||||
|
||||
[[command]]
|
||||
trigger = "!ping"
|
||||
response = "pong"
|
||||
@ -95,3 +85,15 @@ response = "redirected"
|
||||
[command.action.redirect]
|
||||
target = "555097559023222825"
|
||||
anonymous = true
|
||||
|
||||
[[command]]
|
||||
trigger = "!debug"
|
||||
feature = "debug"
|
||||
|
||||
[[command]]
|
||||
trigger = "!welcome"
|
||||
feature = "welcome"
|
||||
|
||||
[[command]]
|
||||
trigger = "!help"
|
||||
feature = "help"
|
||||
|
@ -9,6 +9,6 @@ class ConfigTest : StringSpec({
|
||||
"should properly parse test config" {
|
||||
Globals.config shouldNotBe null
|
||||
Globals.systemConfig shouldNotBe null
|
||||
Globals.commands shouldBe emptyList()
|
||||
Globals.commands.size shouldBe 2
|
||||
}
|
||||
})
|
@ -4,8 +4,8 @@ import io.kotlintest.specs.StringSpec
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import moe.kageru.kagebot.Kagebot
|
||||
import moe.kageru.kagebot.TestUtil
|
||||
import moe.kageru.kagebot.config.RawDebugFeature
|
||||
import org.javacord.api.entity.message.embed.EmbedBuilder
|
||||
import org.javacord.api.event.message.MessageCreateEvent
|
||||
|
||||
@ -14,19 +14,19 @@ class DebugFeatureTest : StringSpec({
|
||||
// this will fail if the bot tries to execute more than it should
|
||||
// because the mock does not provide the necessary methods
|
||||
"should ignore regular users" {
|
||||
val message = mockk<MessageCreateEvent> {
|
||||
every { messageAuthor.isBotOwner } returns false
|
||||
}
|
||||
DebugFeature(RawDebugFeature(true)).handle(message)
|
||||
val message = TestUtil.mockMessage("!debug")
|
||||
every { message.messageAuthor.isBotOwner } returns false
|
||||
Kagebot.processMessage(message)
|
||||
DebugFeature().handle(message)
|
||||
verify(exactly = 0) { message.channel.sendMessage(any<EmbedBuilder>()) }
|
||||
}
|
||||
"should return something" {
|
||||
val message = mockk<MessageCreateEvent> {
|
||||
every { messageAuthor.isBotOwner } returns true
|
||||
every { readableMessageContent } returns "!debugstats something"
|
||||
every { readableMessageContent } returns "!debug"
|
||||
every { channel.sendMessage(any<EmbedBuilder>()) } returns mockk()
|
||||
}
|
||||
DebugFeature(RawDebugFeature(true)).handle(message)
|
||||
DebugFeature().handle(message)
|
||||
verify(exactly = 1) { message.channel.sendMessage(any<EmbedBuilder>()) }
|
||||
}
|
||||
})
|
@ -4,18 +4,21 @@ import io.kotlintest.specs.StringSpec
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import moe.kageru.kagebot.Globals
|
||||
import moe.kageru.kagebot.Kagebot
|
||||
import moe.kageru.kagebot.TestUtil
|
||||
import moe.kageru.kagebot.TestUtil.withReplyContents
|
||||
import moe.kageru.kagebot.TestUtil.mockMessage
|
||||
import moe.kageru.kagebot.TestUtil.withCommands
|
||||
import moe.kageru.kagebot.config.RawHelpFeature
|
||||
import moe.kageru.kagebot.TestUtil.withReplyContents
|
||||
import org.javacord.api.entity.message.embed.EmbedBuilder
|
||||
import java.util.Optional
|
||||
import java.util.*
|
||||
|
||||
class HelpFeatureTest : StringSpec({
|
||||
val sentEmbeds = mutableListOf<EmbedBuilder>()
|
||||
TestUtil.prepareTestEnvironment(sentEmbeds = sentEmbeds)
|
||||
val commandConfig = """
|
||||
[[command]]
|
||||
trigger = "!help"
|
||||
feature = "help"
|
||||
[[command]]
|
||||
trigger = "!ping"
|
||||
[[command]]
|
||||
@ -33,9 +36,7 @@ class HelpFeatureTest : StringSpec({
|
||||
val expected = listOf("!ping", "!something")
|
||||
val unexpected = listOf("not a prefix", "!prison")
|
||||
withReplyContents(expected = expected, unexpected = unexpected) { replies ->
|
||||
HelpFeature(RawHelpFeature(true))
|
||||
.handle(message = mockMessage("!help", replyEmbeds = replies))
|
||||
//Kagebot.processMessage(TestUtil.mockMessage("!help", replyEmbeds = replies))
|
||||
Kagebot.processMessage(mockMessage("!help", replyEmbeds = replies))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -50,11 +51,8 @@ class HelpFeatureTest : StringSpec({
|
||||
Globals.server.getRolesByNameIgnoreCase("testrole")[0]
|
||||
)
|
||||
})
|
||||
HelpFeature(RawHelpFeature(true))
|
||||
.handle(message = message)
|
||||
//Kagebot.processMessage(TestUtil.mockMessage("!help", replyEmbeds = replies))
|
||||
Kagebot.processMessage(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -8,7 +8,6 @@ redirectedMessage = "says"
|
||||
messageDeleted = "message dongered"
|
||||
|
||||
[feature.welcome]
|
||||
enable = true
|
||||
fallbackChannel = "123"
|
||||
fallbackMessage = "@@ welcome"
|
||||
# This is a list of pairs where the key is the title and the value the content of the paragraph.
|
||||
@ -17,5 +16,10 @@ fallbackMessage = "@@ welcome"
|
||||
"Welcome to the Server" = "This is the content of the first paragraph"
|
||||
"Second paragraph heading" = "Second paragraph content"
|
||||
|
||||
[feature.help]
|
||||
enable = true
|
||||
[[command]]
|
||||
trigger = "!debug"
|
||||
feature = "debug"
|
||||
|
||||
[[command]]
|
||||
trigger = "!welcome"
|
||||
feature = "welcome"
|
Loading…
Reference in New Issue
Block a user