Add neededRoles parameter to command

This commit is contained in:
kageru 2019-06-09 01:04:00 +02:00
parent a91dda33c7
commit 6d7cd5b776
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
6 changed files with 82 additions and 4 deletions

View File

@ -1,5 +1,6 @@
package moe.kageru.kagebot
import moe.kageru.kagebot.Config.Companion.config
import moe.kageru.kagebot.Util.doIf
import org.javacord.api.entity.message.MessageAuthor
import org.javacord.api.event.message.MessageCreateEvent
@ -10,15 +11,29 @@ class Command(
trigger: String?,
private val response: String?,
matchType: MatchType?,
private val deleteMessage: Boolean
private val deleteMessage: Boolean,
neededPermissions: Iterable<Long>?
) {
val trigger: String = trigger!!
val regex: Regex? = if (matchType == MatchType.REGEX) Regex(trigger!!) else null
private val matchType: MatchType = matchType ?: MatchType.PREFIX
private val neededRoles = neededPermissions?.toSet()
constructor(cmd: Command) : this(cmd.trigger, cmd.response, cmd.matchType, cmd.deleteMessage)
constructor(cmd: Command) : this(
cmd.trigger,
cmd.response,
cmd.matchType,
cmd.deleteMessage,
cmd.neededRoles
)
fun execute(message: MessageCreateEvent) {
neededRoles?.let { roles ->
if (!(message.messageAuthor.isBotOwner || hasOneOf(message.messageAuthor, roles))) {
message.channel.sendMessage(config.localization.permissionDenied)
return
}
}
if (this.deleteMessage && message.message.canYouDelete()) {
message.deleteMessage()
}
@ -27,6 +42,14 @@ class Command(
}
}
private fun hasOneOf(messageAuthor: MessageAuthor, roles: Set<Long>): Boolean {
val optional = messageAuthor.asUser()
return when {
optional.isEmpty -> false
else -> optional.get().getRoles(Config.server).map { it.id }.toSet().intersect(roles).isNotEmpty()
}
}
fun matches(msg: String) = this.matchType.matches(msg, this)
private fun respond(author: MessageAuthor) = this.response!!.doIf({ it.contains(AUTHOR_PLACEHOLDER) }) {
it.replace(AUTHOR_PLACEHOLDER, MessageUtil.mention(author))

View File

@ -1,12 +1,15 @@
package moe.kageru.kagebot
import com.moandjiezana.toml.Toml
import org.javacord.api.entity.server.Server
import java.io.File
class Config(val system: System, val commands: List<Command>) {
class Config(val system: System, val localization: Localization, val commands: List<Command>) {
companion object {
val config: Config by lazy { read("config.toml") }
val secret = File("secret").readText().replace("\n", "")
var server: Server? = null
get() = field!!
private fun read(path: String): Config {
val rawConfig: Toml = Toml().read(run {
@ -20,6 +23,7 @@ class Config(val system: System, val commands: List<Command>) {
val parsed = rawConfig.to(Config::class.java)
return Config(
parsed.system,
parsed.localization,
parsed.commands.map { Command(it) }
)
}
@ -28,4 +32,4 @@ class Config(val system: System, val commands: List<Command>) {
}
data class System(val serverId: String)
data class Localization(val permissionDenied: String)

View File

@ -22,6 +22,7 @@ class Kagebot {
init {
val api = DiscordApiBuilder().setToken(Config.secret).login().join()
Config.server = api.getServerById(config.system.serverId).orElseThrow()
Runtime.getRuntime().addShutdownHook(Thread {
log.info("Bot has been interrupted. Shutting down.")
api.disconnect()

View File

@ -1,6 +1,9 @@
[system]
serverId = "356414885292277771"
[localization]
permissionDenied = "You do not have permission to use this command."
[[commands]]
trigger = "!ping"
response = "pong"
@ -25,6 +28,15 @@ response = "@@ there you go"
trigger = "delet this"
deleteMessage = true
[[commands]]
trigger = "!restricted"
response = "access granted"
# a user needs *one of* these roles to trigger the command
neededRoles = [
452034011393425409,
446668543816106004
]
[[commands]]
trigger = "^[^`]*([()|DoOvVcC][-=^']?;|;[-=^']?[()|DoOpPvVcC3]|:wink:|😉)[^`]*$"
response = "@@ Oboe!"

View File

@ -5,8 +5,13 @@ import io.kotlintest.specs.StringSpec
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import moe.kageru.kagebot.Config.Companion.config
import org.javacord.api.entity.permission.Role
import org.javacord.api.entity.user.User
import java.util.*
class CommandTest : StringSpec({
Config.server = mockk()
"should match prefix command" {
testMessageSuccess("!ping", "pong")
}
@ -30,6 +35,38 @@ class CommandTest : StringSpec({
Kagebot.processMessage(mockMessage)
verify(exactly = 1) { mockMessage.deleteMessage() }
}
"should refuse command without permissions" {
val calls = mutableListOf<String>()
val mockOptional = mockk<Optional<User>>()
every { mockOptional.isEmpty } returns false
every { mockOptional.get().getRoles(any()) } returns emptyList()
val mockMessage = TestUtil.mockMessage("!restricted", capturedCalls = calls)
every { mockMessage.messageAuthor.asUser() } returns mockOptional
Kagebot.processMessage(mockMessage)
calls.size shouldBe 1
calls[0] shouldBe config.localization.permissionDenied
}
"should accept restricted command for owner" {
val calls = mutableListOf<String>()
val mockMessage = TestUtil.mockMessage("!restricted", capturedCalls = calls)
every { mockMessage.messageAuthor.isBotOwner } returns true
Kagebot.processMessage(mockMessage)
calls.size shouldBe 1
calls[0] shouldBe "access granted"
}
"should accept restricted command with permissions" {
val calls = mutableListOf<String>()
val mockRole = mockk<Role>()
every { mockRole.id } returns 452034011393425409
val mockOptional = mockk<Optional<User>>()
every { mockOptional.isEmpty } returns false
every { mockOptional.get().getRoles(any()) } returns listOf(mockRole)
val mockMessage = TestUtil.mockMessage("!restricted", capturedCalls = calls)
every { mockMessage.messageAuthor.asUser() } returns mockOptional
Kagebot.processMessage(mockMessage)
calls.size shouldBe 1
calls[0] shouldBe "access granted"
}
}) {
companion object {
fun testMessageSuccess(content: String, result: String) {

View File

@ -17,6 +17,7 @@ object TestUtil {
every { message.channel.sendMessage(capture(capturedCalls)) } returns mockk()
every { message.messageAuthor.isYourself } returns isSelf
every { message.message.canYouDelete() } returns true
every { message.messageAuthor.isBotOwner } returns false
return message
}
}