2019-07-23 21:50:55 +02:00
package moe.kageru.kagebot.features
2019-11-12 21:13:01 +01:00
import arrow.core.*
2019-11-12 14:02:31 +01:00
import arrow.core.extensions.list.monad.map
2019-11-12 21:13:01 +01:00
import arrow.core.extensions.listk.functorFilter.filter
import arrow.syntax.collections.destructured
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
2019-11-12 14:02:31 +01:00
import moe.kageru.kagebot.Util.unwrap
2019-07-23 21:50:55 +02:00
import moe.kageru.kagebot.config.Config
2019-10-18 19:34:41 +02:00
import moe.kageru.kagebot.config.LocalizationSpec
2019-11-12 21:13:01 +01:00
import moe.kageru.kagebot.extensions.memberById
import moe.kageru.kagebot.extensions.on
import moe.kageru.kagebot.extensions.roles
2019-07-23 21:50:55 +02:00
import moe.kageru.kagebot.persistence.Dao
import org.javacord.api.entity.permission.Role
2019-11-12 21:13:01 +01:00
import org.javacord.api.entity.user.User
2019-07-23 21:50:55 +02:00
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 {
2019-11-12 14:02:31 +01:00
private val timeoutRole : Role = findRole ( role ) . unwrap ( )
2019-07-23 21:50:55 +02:00
override fun handle ( message : MessageCreateEvent ) {
2019-11-12 21:13:01 +01:00
message . readableMessageContent . split ( ' ' , limit = 4 ) . let { args ->
Either . cond (
args . size >= 3 ,
{ Tuple3 ( args [ 1 ] , args [ 2 ] , args . getOrNull ( 3 ) ) } ,
{ " Error: expected “<command> <user> <time> [<reason>]”. If the name contains spaces, please use the user ID instead. " }
) . flatMap {
Tuple3 (
findUser ( it . a ) . orNull ( )
?: return @flatMap " Error: User ${it.a} not found, consider using the user ID " . left ( ) ,
it . b . toLongOrNull ( ) ?: return @flatMap " Error: malformed time " . left ( ) ,
it . c
) . right ( )
} . on { ( user , time , _ ) ->
applyTimeout ( user , time )
} . fold (
{ message . channel . sendMessage ( it ) } ,
{ ( user , time , reason ) ->
user . sendEmbed {
addField ( " Timeout " , Config . localization [ LocalizationSpec . timeout ] . replace ( " @@ " , " $time " ) )
reason ?. let { addField ( " Reason " , it ) }
}
2019-07-28 18:49:29 +02:00
}
2019-11-12 21:13:01 +01:00
)
}
2019-07-23 21:50:55 +02:00
}
2019-11-12 21:13:01 +01:00
private fun applyTimeout ( user : User , time : Long ) {
val oldRoles = user . roles ( )
. filter { ! it . isManaged }
. onEach { user . removeRole ( it ) }
. map { it . id }
user . addRole ( timeoutRole )
val releaseTime = Instant . now ( ) . plus ( Duration . ofMinutes ( time ) ) . epochSecond
Dao . saveTimeout ( releaseTime , user . id , oldRoles )
Log . info ( " Removed roles ${oldRoles.joinToString()} from user ${user.discriminatedName} " )
2019-07-23 21:50:55 +02:00
}
2019-11-12 21:13:01 +01:00
fun checkAndRelease ( ) : Unit = Dao . getAllTimeouts ( )
. filter { releaseTime -> Instant . now ( ) . epochSecond > releaseTime }
. map { Dao . deleteTimeout ( it ) }
. map { it . destructured ( ) }
. forEach { ( userId , roleIds ) ->
Config . server . memberById ( userId ) . fold (
{ Log . warn ( " Tried to free user $userId , but couldn’t find them on the server anymore " ) } ,
{ user ->
roleIds . forEach { findRole ( " $it " ) . map ( user :: addRole ) }
user . removeRole ( timeoutRole )
Log . info ( " Lifted timeout from user ${user.discriminatedName} . Stored roles ${roleIds.joinToString()} " )
}
)
2019-07-23 21:50:55 +02:00
}
2019-07-28 18:49:29 +02:00
}