Add optional reason to timeout command (closes #14)

This commit is contained in:
kageru 2019-07-28 18:49:29 +02:00
parent b4c2275670
commit 35bd570c93
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
6 changed files with 51 additions and 16 deletions

View File

@ -18,4 +18,4 @@ object CronD {
delay(60_000)
}
}
}
}

View File

@ -9,4 +9,4 @@ interface MessageFeature {
interface EventFeature {
fun register(api: DiscordApi)
}
}

View File

@ -18,19 +18,19 @@ class TimeoutFeature(raw: RawTimeoutFeature) : MessageFeature {
?: throw IllegalArgumentException("No timeout role defined")
override fun handle(message: MessageCreateEvent) {
val (target, time) = message.readableMessageContent.split(' ', limit = 3).let {
if (it.size != 3) {
message.channel.sendMessage("Error: expected “<command> <user> <time>”. If the name contains spaces, please use the user ID instead.")
val timeout = message.readableMessageContent.split(' ', limit = 4).let { args ->
if (args.size < 3) {
message.channel.sendMessage("Error: expected “<command> <user> <time> [<reason>]”. If the name contains spaces, please use the user ID instead.")
return
}
val time = it[2].toLongOrNull()
val time = args[2].toLongOrNull()
if (time == null) {
message.channel.sendMessage("Error: malformed time")
return
}
Pair(it[1], time)
ParsedTimeout(args[1], time, args.getOrNull(3))
}
findUser(target)?.let { user ->
findUser(timeout.target)?.let { user ->
val oldRoles = user.getRoles(Config.server)
.filter { !it.isManaged }
.map { role ->
@ -38,13 +38,16 @@ class TimeoutFeature(raw: RawTimeoutFeature) : MessageFeature {
role.id
}
user.addRole(timeoutRole)
val releaseTime = Instant.now().plus(Duration.ofMinutes(time)).epochSecond
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("@@", time.toString()))
addField("Timeout", Config.localization.timeout.replace("@@", timeout.duration.toString()))
timeout.reason?.let {
addField("Reason", it)
}
}
Log.info("Removed roles ${oldRoles.joinToString()} from user ${user.discriminatedName}")
} ?: message.channel.sendMessage("Could not find user $target. Consider using the user ID.")
} ?: message.channel.sendMessage("Could not find user ${timeout.target}. Consider using the user ID.")
}
fun checkAndRelease() {
@ -77,4 +80,6 @@ class UserInTimeout(private val id: Long, private val roles: List<Long>) {
return UserInTimeout(userId, roles)
}
}
}
}
class ParsedTimeout(val target: String, val duration: Long, val reason: String?)

View File

@ -65,7 +65,8 @@ object TestUtil {
fun prepareTestEnvironment(
sentEmbeds: MutableList<EmbedBuilder> = mutableListOf(),
sentMessages: MutableList<String> = mutableListOf()
sentMessages: MutableList<String> = mutableListOf(),
dmEmbeds: MutableList<EmbedBuilder> = mutableListOf()
) {
val channel = mockk<Optional<ServerTextChannel>>(relaxed = true) {
every { isPresent } returns true
@ -87,6 +88,7 @@ object TestUtil {
every { getMembersByName(any()) } returns listOf(mockk(relaxed = true) {
every { id } returns 123
every { getRoles(any()) } returns listOf(TEST_ROLE)
every { sendMessage(capture(dmEmbeds)) } returns mockk()
})
})
}

View File

@ -7,6 +7,7 @@ import moe.kageru.kagebot.Kagebot.process
import moe.kageru.kagebot.TestUtil
import moe.kageru.kagebot.TestUtil.TEST_ROLE
import moe.kageru.kagebot.persistence.Dao
import org.javacord.api.entity.message.embed.EmbedBuilder
class TimeoutFeatureTest : StringSpec({
TestUtil.prepareTestEnvironment()
@ -17,6 +18,16 @@ class TimeoutFeatureTest : StringSpec({
val user = Dao.deleteTimeout(it.first())
user shouldBe arrayOf(123, TEST_ROLE.id)
}
clearTimeouts()
}
"should announce timeout via DM" {
val dms = mutableListOf<EmbedBuilder>()
TestUtil.prepareTestEnvironment(dmEmbeds = dms)
val time = "1235436"
TestUtil.mockMessage("!timeout kageru $time").process()
dms.size shouldBe 1
TestUtil.embedToString(dms[0]) shouldContain time
clearTimeouts()
}
"should return error for invalid input" {
val replies = mutableListOf<String>()
@ -30,4 +41,21 @@ class TimeoutFeatureTest : StringSpec({
replies.size shouldBe 1
replies[0] shouldContain "Error"
}
})
"should print optional reason" {
val dms = mutableListOf<EmbedBuilder>()
TestUtil.prepareTestEnvironment(dmEmbeds = dms)
val reason = "because I don’t like you"
TestUtil.mockMessage("!timeout kageru 1 $reason").process()
dms.size shouldBe 1
TestUtil.embedToString(dms[0]) shouldContain reason
clearTimeouts()
}
}) {
companion object {
private fun clearTimeouts() {
Dao.getAllTimeouts().forEach { to ->
Dao.deleteTimeout(to)
}
}
}
}

View File

@ -6,7 +6,7 @@ color = "#1793d0"
permissionDenied = "no permissions"
redirectedMessage = "says"
messageDeleted = "message dongered"
timeout = "timeout"
timeout = "timeout @@ minutes"
[feature.welcome]
fallbackChannel = "123"
@ -31,4 +31,4 @@ feature = "welcome"
[[command]]
trigger = "!timeout"
feature = "timeout"
feature = "timeout"