2019-07-23 21:50:55 +02:00
package moe.kageru.kagebot.features
2019-10-18 21:56:31 +02:00
import com.fasterxml.jackson.annotation.JsonProperty
2019-07-23 21:50:55 +02:00
import moe.kageru.kagebot.Log
2019-07-25 21:24:46 +02:00
import moe.kageru.kagebot.MessageUtil.sendEmbed
2019-07-23 21:50:55 +02:00
import moe.kageru.kagebot.Util.findRole
import moe.kageru.kagebot.Util.findUser
import moe.kageru.kagebot.Util.ifNotEmpty
import moe.kageru.kagebot.config.Config
2019-10-18 19:34:41 +02:00
import moe.kageru.kagebot.config.LocalizationSpec
2019-07-23 21:50:55 +02:00
import moe.kageru.kagebot.persistence.Dao
import org.javacord.api.entity.permission.Role
import org.javacord.api.event.message.MessageCreateEvent
import java.time.Duration
import java.time.Instant
2019-10-18 21:56:31 +02:00
class TimeoutFeature ( @JsonProperty ( " role " ) role : String ) : MessageFeature {
private val timeoutRole : Role = findRole ( role )
2019-07-23 21:50:55 +02:00
override fun handle ( message : MessageCreateEvent ) {
2019-07-28 18:49:29 +02:00
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. " )
2019-07-25 20:18:10 +02:00
return
}
2019-07-28 18:49:29 +02:00
val time = args [ 2 ] . toLongOrNull ( )
2019-07-25 21:04:13 +02:00
if ( time == null ) {
message . channel . sendMessage ( " Error: malformed time " )
return
}
2019-07-28 18:49:29 +02:00
ParsedTimeout ( args [ 1 ] , time , args . getOrNull ( 3 ) )
2019-07-25 20:18:10 +02:00
}
2019-07-28 18:49:29 +02:00
findUser ( timeout . target ) ?. let { user ->
2019-07-23 23:27:04 +02:00
val oldRoles = user . getRoles ( Config . server )
. filter { ! it . isManaged }
. map { role ->
user . removeRole ( role )
role . id
}
2019-07-23 21:50:55 +02:00
user . addRole ( timeoutRole )
2019-07-28 18:49:29 +02:00
val releaseTime = Instant . now ( ) . plus ( Duration . ofMinutes ( timeout . duration ) ) . epochSecond
2019-07-23 21:50:55 +02:00
Dao . saveTimeout ( releaseTime , listOf ( user . id ) + oldRoles )
2019-07-25 21:24:46 +02:00
user . sendEmbed {
2019-10-18 19:34:41 +02:00
addField (
" Timeout " ,
Config . localization [ LocalizationSpec . timeout ] . replace ( " @@ " , timeout . duration . toString ( ) )
)
2019-07-28 18:49:29 +02:00
timeout . reason ?. let {
addField ( " Reason " , it )
}
2019-07-25 21:24:46 +02:00
}
2019-07-25 20:18:10 +02:00
Log . info ( " Removed roles ${oldRoles.joinToString()} from user ${user.discriminatedName} " )
2019-07-28 18:49:29 +02:00
} ?: message . channel . sendMessage ( " Could not find user ${timeout.target} . Consider using the user ID. " )
2019-07-23 21:50:55 +02:00
}
fun checkAndRelease ( ) {
val now = Instant . now ( ) . epochSecond
Dao . getAllTimeouts ( )
. filter { releaseTime -> now > releaseTime }
. map {
Dao . deleteTimeout ( it ) . let { rawIds ->
UserInTimeout . ofLongs ( rawIds ) . toPair ( )
}
} . forEach { ( userId , roleIds ) ->
Config . server . getMemberById ( userId ) . ifNotEmpty { user ->
roleIds . forEach { roleId ->
user . addRole ( findRole ( " $roleId " ) )
}
user . removeRole ( timeoutRole )
2019-07-25 20:18:10 +02:00
Log . info ( " Lifted timeout from user ${user.discriminatedName} . Stored roles ${roleIds.joinToString()} " )
2019-07-23 21:50:55 +02:00
} ?: Log . warn ( " Tried to free user $userId , but couldn’t find them on the server anymore " )
}
}
}
class UserInTimeout ( private val id : Long , private val roles : List < Long > ) {
fun toPair ( ) = Pair ( id , roles )
companion object {
fun ofLongs ( longs : LongArray ) : UserInTimeout = longs . run {
val userId = first ( )
val roles = if ( size > 1 ) slice ( 1 until size ) else emptyList ( )
return UserInTimeout ( userId , roles )
}
}
2019-07-28 18:49:29 +02:00
}
class ParsedTimeout ( val target : String , val duration : Long , val reason : String ? )