diff --git a/src/main/kotlin/moe/kageru/kagebot/Command.kt b/src/main/kotlin/moe/kageru/kagebot/Command.kt index d19170a..97c0845 100644 --- a/src/main/kotlin/moe/kageru/kagebot/Command.kt +++ b/src/main/kotlin/moe/kageru/kagebot/Command.kt @@ -2,7 +2,6 @@ package moe.kageru.kagebot import moe.kageru.kagebot.Config.Companion.config import moe.kageru.kagebot.Util.doIf -import moe.kageru.kagebot.Util.ifNotEmpty import org.javacord.api.entity.message.MessageAuthor import org.javacord.api.event.message.MessageCreateEvent @@ -12,28 +11,25 @@ class Command( trigger: String?, private val response: String?, matchType: MatchType?, - neededPermissions: Iterable?, + private val permissions: Permissions?, private val actions: MessageActions? ) { val trigger: String = trigger!! val regex: Regex? = if (matchType == MatchType.REGEX) Regex(trigger!!) else null val matchType: MatchType = matchType ?: MatchType.PREFIX - private val neededRoles = neededPermissions?.toSet() constructor(cmd: Command) : this( cmd.trigger, cmd.response, cmd.matchType, - cmd.neededRoles, + cmd.permissions?.let { Permissions(it) }, cmd.actions ) fun execute(message: MessageCreateEvent) { - neededRoles?.let { roles -> - if (!(message.messageAuthor.isBotOwner || hasOneOf(message.messageAuthor, roles))) { - message.channel.sendMessage(config.localization.permissionDenied) - return - } + if (!(message.messageAuthor.isBotOwner || permissions?.isAllowed(message) != false)) { + message.channel.sendMessage(config.localization.permissionDenied) + return } this.actions?.run(message, this) this.response?.let { @@ -41,12 +37,6 @@ class Command( } } - private fun hasOneOf(messageAuthor: MessageAuthor, roles: Set): Boolean { - return messageAuthor.asUser().ifNotEmpty { user -> - user.getRoles(Config.server).map { it.id }.toSet().intersect(roles).isNotEmpty() - } ?: false - } - 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)) @@ -66,3 +56,23 @@ enum class MatchType { abstract fun matches(message: String, command: Command): Boolean } + +class Permissions(hasOneOf: Iterable?, hasNoneOf: Iterable?, private val onlyDM: Boolean) { + private val hasNoneOf = hasNoneOf?.toSet() + private val hasOneOf = hasOneOf?.toSet() + + constructor(perms: Permissions) : this(perms.hasOneOf, perms.hasNoneOf, perms.onlyDM) + + fun isAllowed(message: MessageCreateEvent): Boolean { + if (onlyDM && !message.isPrivateMessage) { + return false + } + hasOneOf?.let { + if (!Util.hasOneOf(message.messageAuthor, hasOneOf)) return false + } + hasNoneOf?.let { + if (Util.hasOneOf(message.messageAuthor, hasNoneOf)) return false + } + return true + } +} \ No newline at end of file diff --git a/src/main/kotlin/moe/kageru/kagebot/Util.kt b/src/main/kotlin/moe/kageru/kagebot/Util.kt index a27c0ed..8a25ef1 100644 --- a/src/main/kotlin/moe/kageru/kagebot/Util.kt +++ b/src/main/kotlin/moe/kageru/kagebot/Util.kt @@ -1,5 +1,6 @@ package moe.kageru.kagebot +import org.javacord.api.entity.message.MessageAuthor import java.util.* object Util { @@ -13,4 +14,10 @@ object Util { } return null } + + fun hasOneOf(messageAuthor: MessageAuthor, roles: Set): Boolean { + return messageAuthor.asUser().ifNotEmpty { user -> + user.getRoles(Config.server).map { it.id }.toSet().intersect(roles).isNotEmpty() + } ?: false + } } \ No newline at end of file diff --git a/src/main/resources/config.toml b/src/main/resources/config.toml index a851e8e..d3ae0af 100644 --- a/src/main/resources/config.toml +++ b/src/main/resources/config.toml @@ -34,12 +34,22 @@ actions = { delete = true } [[commands]] trigger = "!restricted" response = "access granted" -# a user needs *one of* these roles to trigger the command -neededRoles = [ +[commands.permissions] +hasOneOf = [ 452034011393425409, 446668543816106004 ] +[[commands]] +trigger = "!almostUnrestricted" +response = "access granted" +[commands.permissions] +hasNoneOf = [ + 452034011393425409 +] + + + # redirect every message that starts with !redirect to channel 555097559023222825 [[commands]] trigger = "!redirect" diff --git a/src/test/kotlin/moe/kageru/kagebot/CommandTest.kt b/src/test/kotlin/moe/kageru/kagebot/CommandTest.kt index 4908f1a..8a5159c 100644 --- a/src/test/kotlin/moe/kageru/kagebot/CommandTest.kt +++ b/src/test/kotlin/moe/kageru/kagebot/CommandTest.kt @@ -67,6 +67,28 @@ class CommandTest : StringSpec({ calls.size shouldBe 1 calls[0] shouldBe "access granted" } + "should deny command to excluded roles" { + val calls = mutableListOf() + val mockMessage = TestUtil.mockMessage("!almostUnrestricted", capturedCalls = calls) + // with the banned role + every { mockMessage.messageAuthor.asUser() } returns mockk { + every { isPresent } returns true + every { get().getRoles(any()) } returns listOf( + mockk { every { id } returns 452034011393425409 } + ) + } + Kagebot.processMessage(mockMessage) + + // without the role + every { mockMessage.messageAuthor.asUser() } returns mockk { + every { isPresent } returns true + every { get().getRoles(any()) } returns emptyList() + } + Kagebot.processMessage(mockMessage) + calls.size shouldBe 2 + calls[0] shouldBe config.localization.permissionDenied + calls[1] shouldBe "access granted" + } /* * This implicitly tests that the message author is not included in anonymous complaints * because getting the author’s name from the mock is undefined.