2019-07-23 21:50:55 +02:00
package moe.kageru.kagebot.features
2019-11-13 22:06:30 +01:00
import arrow.Kind
import arrow.core.*
import arrow.core.extensions.either.applicative.applicative
2019-11-13 16:59:44 +01:00
import arrow.core.extensions.either.monad.flatMap
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
2019-11-13 22:06:30 +01:00
import arrow.core.extensions.option.applicative.applicative
2019-11-12 21:13:01 +01:00
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
import moe.kageru.kagebot.config.Config
2019-10-18 19:34:41 +02:00
import moe.kageru.kagebot.config.LocalizationSpec
2019-11-13 16:59:44 +01:00
import moe.kageru.kagebot.extensions.*
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 {
2019-11-13 22:06:30 +01:00
it . mapFirst ( Option . applicative ( ) , :: findUser ) . fix ( )
. toEither { " Error: User ${it.a} not found, consider using the user ID " }
2019-11-13 16:59:44 +01:00
} . flatMap {
2019-11-13 22:06:30 +01:00
it . mapSecond ( Either . applicative ( ) ) { time ->
time . toLongOrNull ( ) . rightIfNotNull { " Error: malformed time “ ${it.b} ” " }
} . fix ( )
2019-11-12 21:13:01 +01:00
} . on { ( user , time , _ ) ->
applyTimeout ( user , time )
} . fold (
2019-11-13 22:06:30 +01:00
{ error -> message . channel . sendMessage ( error ) } ,
2019-11-12 21:13:01 +01:00
{ ( 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
}