Added !help feature

This commit is contained in:
kageru 2019-07-11 20:14:22 +02:00
parent 32eca9e7aa
commit 931a8cdf19
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
11 changed files with 132 additions and 19 deletions

View File

@ -34,6 +34,8 @@ class Command(cmd: RawCommand) {
embed = cmd.embed?.let(MessageUtil::mapToEmbed)
}
fun isAllowed(message: MessageCreateEvent) = permissions?.isAllowed(message) ?: true
fun execute(message: MessageCreateEvent) {
if (permissions?.isAllowed(message) == false) {
if (config.localization.permissionDenied.isNotBlank()) {

View File

@ -43,12 +43,13 @@ class RawCommand(
class RawPermissions(val hasOneOf: List<String>?, val hasNoneOf: List<String>?, val onlyDM: Boolean)
class RawMessageActions(val delete: Boolean, val redirect: RawRedirect?)
class RawRedirect(val target: String?, val anonymous: Boolean)
class RawFeatures(val welcome: RawWelcomeFeature?, val debug: RawDebugFeature?)
class RawFeatures(val welcome: RawWelcomeFeature?, val debug: RawDebugFeature?, val help: RawHelpFeature?)
class RawWelcomeFeature(
val enabled: Boolean,
val enable: Boolean,
val content: Map<String, String>?,
val fallbackChannel: String?,
val fallbackMessage: String?,
@SerializedName("command") val commandEnabled: Boolean
)
class RawDebugFeature(var enabled: Boolean)
class RawDebugFeature(val enable: Boolean)
class RawHelpFeature(val enable: Boolean)

View File

@ -11,7 +11,7 @@ import java.time.Duration
import java.time.temporal.ChronoUnit
class DebugFeature(rawDebugFeatures: RawDebugFeature): MessageFeature() {
override val commandEnabled = rawDebugFeatures.enabled
override val commandEnabled = rawDebugFeatures.enable
override fun handleInternal(message: MessageCreateEvent) {
if (message.messageAuthor.isBotOwner) {

View File

@ -2,17 +2,18 @@ package moe.kageru.kagebot.features
import moe.kageru.kagebot.config.RawFeatures
class Features(val welcome: WelcomeFeature?, val debug: DebugFeature?) {
class Features(val welcome: WelcomeFeature?, val debug: DebugFeature?, val help: HelpFeature?) {
constructor(rawFeatures: RawFeatures) : this(
rawFeatures.welcome?.let(::WelcomeFeature),
rawFeatures.debug?.let(::DebugFeature)
rawFeatures.debug?.let(::DebugFeature),
rawFeatures.help?.let(::HelpFeature)
)
fun all() = listOfNotNull(this.welcome, this.debug)
fun allWithMessage() = listOfNotNull(this.welcome, this.debug).filterIsInstance<MessageFeature>()
fun all() = listOfNotNull(this.welcome, this.debug, this.help)
fun allWithMessage() = all().filterIsInstance<MessageFeature>()
companion object {
val NONE = Features(null, null)
val NONE = Features(null, null, null)
}
}

View File

@ -0,0 +1,26 @@
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
override fun handleInternal(message: MessageCreateEvent) {
if (message.readableMessageContent.startsWith("!help")) {
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")
}

View File

@ -3,13 +3,15 @@ package moe.kageru.kagebot.features
import moe.kageru.kagebot.Globals
import org.javacord.api.event.message.MessageCreateEvent
abstract class MessageFeature: Feature {
abstract class MessageFeature : Feature {
abstract val commandEnabled: Boolean
fun handle(message: MessageCreateEvent) {
Globals.commandCounter.incrementAndGet()
handleInternal(message)
if (commandEnabled) {
Globals.commandCounter.incrementAndGet()
handleInternal(message)
}
}
abstract fun handleInternal(message: MessageCreateEvent)
internal abstract fun handleInternal(message: MessageCreateEvent)
}

View File

@ -16,7 +16,7 @@ class WelcomeFeature(rawWelcome: RawWelcomeFeature) : MessageFeature() {
}
}
val enabled: Boolean = rawWelcome.enabled
val enabled: Boolean = rawWelcome.enable
val embed: EmbedBuilder? by lazy {
rawWelcome.content?.let(MessageUtil::mapToEmbed)
}

View File

@ -9,11 +9,11 @@ permissionDenied = "You do not have permission to use this command."
redirectedMessage = "says"
messageDeleted = "Your message was deleted because it contained a banned word or phrase."
# If this is enabled, every new user will receive a welcome message.
# If this is enable, every new user will receive a welcome message.
# 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]
enabled = true
enable = true
# enable the !welcome command which will print the welcome embed
command = true
fallbackChannel = "555097559023222825"
@ -26,7 +26,10 @@ fallbackMessage = "@@ I would like to greet you, but I can’t. :("
# allow the bot owner to get debug stats
[feature.debug]
enabled = true
enable = true
[feature.help]
enable = true
[[command]]
trigger = "!ping"

View File

@ -1,5 +1,7 @@
package moe.kageru.kagebot
import io.kotlintest.matchers.string.shouldContain
import io.kotlintest.matchers.string.shouldNotContain
import io.kotlintest.shouldBe
import io.mockk.Runs
import io.mockk.every
@ -100,4 +102,17 @@ object TestUtil {
test()
Globals.config.localization = oldLoc
}
fun assertEmbedContents(expected: List<String>, unexpected: List<String>, op: (MutableList<EmbedBuilder>) -> Unit) {
val replies = mutableListOf<EmbedBuilder>()
op(replies)
replies.size shouldBe 1
val replyString = embedToString(replies[0])
for (string in expected) {
replyString shouldContain string
}
for (string in unexpected) {
replyString shouldNotContain string
}
}
}

View File

@ -0,0 +1,60 @@
package moe.kageru.kagebot.features
import io.kotlintest.specs.StringSpec
import io.mockk.every
import io.mockk.mockk
import moe.kageru.kagebot.Globals
import moe.kageru.kagebot.TestUtil
import moe.kageru.kagebot.TestUtil.assertEmbedContents
import moe.kageru.kagebot.TestUtil.mockMessage
import moe.kageru.kagebot.TestUtil.withCommands
import moe.kageru.kagebot.config.RawHelpFeature
import org.javacord.api.entity.message.embed.EmbedBuilder
import java.util.Optional
class HelpFeatureTest : StringSpec({
val sentEmbeds = mutableListOf<EmbedBuilder>()
TestUtil.prepareTestEnvironment(sentEmbeds = sentEmbeds)
val commandConfig = """
[[command]]
trigger = "!ping"
[[command]]
trigger = "!something"
[[command]]
trigger = "not a prefix"
matchType = "CONTAINS"
[[command]]
trigger = "!prison"
[command.permissions]
hasOneOf = ["testrole"]
""".trimIndent()
"should show prefix command" {
withCommands(commandConfig) {
val expected = listOf("!ping", "!something")
val unexpected = listOf("not a prefix", "!prison")
assertEmbedContents(expected = expected, unexpected = unexpected) { replies ->
HelpFeature(RawHelpFeature(true))
.handle(message = mockMessage("!help", replyEmbeds = replies))
//Kagebot.processMessage(TestUtil.mockMessage("!help", replyEmbeds = replies))
}
}
}
"should show moderation commands for mod" {
withCommands(commandConfig) {
val expected = listOf("!ping", "!something", "!prison")
val unexpected = listOf("not a prefix")
assertEmbedContents(expected = expected, unexpected = unexpected) { replies ->
val message = mockMessage("!help", replyEmbeds = replies)
every { message.messageAuthor.asUser() } returns Optional.of(mockk {
every { getRoles(any()) } returns listOf(
Globals.server.getRolesByNameIgnoreCase("testrole")[0]
)
})
HelpFeature(RawHelpFeature(true))
.handle(message = message)
//Kagebot.processMessage(TestUtil.mockMessage("!help", replyEmbeds = replies))
}
}
}
})

View File

@ -8,11 +8,14 @@ redirectedMessage = "says"
messageDeleted = "message dongered"
[feature.welcome]
enabled = true
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.
# Do not use empty strings to get empty headings or paragraphs. The discord API rejects those.
[feature.welcome.content]
"Welcome to the Server" = "This is the content of the first paragraph"
"Second paragraph heading" = "Second paragraph content"
"Second paragraph heading" = "Second paragraph content"
[feature.help]
enable = true