2019-06-08 21:14:57 +02:00
package moe.kageru.kagebot
2019-11-24 14:03:45 +01:00
import arrow.core.*
2019-11-12 14:02:31 +01:00
import arrow.core.extensions.either.monad.flatMap
2019-11-11 23:52:14 +01:00
import arrow.core.extensions.list.foldable.find
2019-07-13 15:39:50 +02:00
import moe.kageru.kagebot.config.Config.server
2019-11-12 22:02:32 +01:00
import moe.kageru.kagebot.extensions.*
2019-06-12 23:43:36 +02:00
import org.javacord.api.entity.channel.TextChannel
2019-06-10 09:19:03 +02:00
import org.javacord.api.entity.message.MessageAuthor
2019-06-15 12:27:20 +02:00
import org.javacord.api.entity.message.embed.EmbedBuilder
2019-06-12 23:43:36 +02:00
import org.javacord.api.entity.permission.Role
2019-07-11 22:16:02 +02:00
import org.javacord.api.entity.user.User
2019-06-15 12:27:20 +02:00
import java.awt.Color
2019-07-13 15:39:50 +02:00
import java.util.*
2019-06-13 00:19:02 +02:00
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletionException
2019-06-08 23:50:05 +02:00
2019-06-08 21:14:57 +02:00
object Util {
2019-11-14 15:10:30 +01:00
inline fun < T > T . applyIf ( condition : Boolean , op : ( T ) -> T ) : T {
return if ( condition ) op ( this ) else this
}
2019-06-08 23:50:05 +02:00
2019-11-14 15:10:30 +01:00
fun hasOneOf ( messageAuthor : MessageAuthor , roles : Set < Role > ) : Boolean {
return messageAuthor . asUser ( ) . asOption ( ) . flatMap { user ->
user . roles ( ) . find { it in roles }
} . nonEmpty ( )
}
2019-06-12 23:43:36 +02:00
2019-11-14 15:10:30 +01:00
private val channelIdRegex = Regex ( " \\ d{18} " )
private fun String . isEntityId ( ) = channelIdRegex . matches ( this )
2019-06-12 23:43:36 +02:00
2019-11-14 15:10:30 +01:00
fun findRole ( idOrName : String ) : Either < String , Role > {
return when {
idOrName . isEntityId ( ) -> server . getRoleById ( idOrName ) . asOption ( ) . toEither { 0 }
else -> server . rolesByName ( idOrName ) . getOnly ( )
} . mapLeft { " Found $it results, expected 1 " }
}
2019-09-17 22:59:55 +02:00
2019-11-14 15:10:30 +01:00
private fun < T > ListK < T > . getOnly ( ) : Either < Int , T > {
return when ( size ) {
1 -> Either . right ( first ( ) )
else -> Either . left ( size )
2019-06-12 23:43:36 +02:00
}
2019-11-14 15:10:30 +01:00
}
2019-06-12 23:43:36 +02:00
2019-11-14 15:10:30 +01:00
fun findUser ( idOrName : String ) : Option < User > {
return when {
idOrName . isEntityId ( ) -> server . getMemberById ( idOrName ) . asOption ( )
idOrName . contains ( '#' ) -> server . getMemberByDiscriminatedNameIgnoreCase ( idOrName ) . asOption ( )
else -> server . membersByName ( idOrName ) . firstOrNone ( )
2019-07-23 21:50:55 +02:00
}
2019-11-14 15:10:30 +01:00
}
2019-07-23 21:50:55 +02:00
2019-11-14 15:10:30 +01:00
fun < T > CompletableFuture < T > . asOption ( ) : Option < T > {
return try {
2019-11-24 14:03:45 +01:00
val future = join ( )
if ( isCompletedExceptionally ) None else Option . just ( future )
2019-11-14 15:10:30 +01:00
} catch ( e : CompletionException ) {
Option . empty ( )
2019-11-12 14:02:31 +01:00
}
2019-11-14 15:10:30 +01:00
}
2019-11-12 14:02:31 +01:00
2019-11-14 15:10:30 +01:00
fun < T > Optional < T > . asOption ( ) : Option < T > = if ( this . isPresent ) Option . just ( this . get ( ) ) else Option . empty ( )
2019-06-13 00:19:02 +02:00
2019-11-14 15:10:30 +01:00
fun findChannel ( idOrName : String ) : Either < String , TextChannel > {
return when {
idOrName . isEntityId ( ) -> server . channelById ( idOrName ) . toEither { " Channel $idOrName not found " }
idOrName . startsWith ( '@' ) -> Globals . api . getCachedUserByDiscriminatedName ( idOrName . removePrefix ( " @ " ) ) . asOption ( )
. toEither { " User $idOrName not found " }
. flatMap { user ->
user . openPrivateChannel ( ) . asOption ( ) . toEither { " Can’t DM user $idOrName " }
2019-06-12 23:43:36 +02:00
}
2019-11-14 15:10:30 +01:00
else -> server . channelsByName ( idOrName ) . getOnly ( ) . mapLeft { " Found $it channels for $idOrName , expected 1 " }
2019-06-12 23:43:36 +02:00
}
2019-11-14 15:10:30 +01:00
}
2019-06-15 12:27:20 +02:00
2019-11-14 15:10:30 +01:00
inline fun checked ( op : ( ( ) -> Unit ) ) {
try {
op ( )
} catch ( e : Exception ) {
Log . warn ( " An uncaught exception occurred. \n $e " )
Log . warn ( e . stackTrace . joinToString ( " \n " ) )
MessageUtil . sendEmbed (
Globals . api . owner . get ( ) ,
EmbedBuilder ( )
. setColor ( Color . RED )
. addField ( " Error " , " kagebot has encountered an error " )
. addField (
" $e " , """ ```
2019-11-12 22:22:32 +01:00
$ { e . stackTrace . joinToString ( " \n \t " ) }
2019-07-23 21:50:55 +02:00
` ` ` """ .trimIndent().run { applyIf(length > 1800) { substring(1..1800) } }
2019-11-14 15:10:30 +01:00
)
)
2019-06-15 12:27:20 +02:00
}
2019-11-14 15:10:30 +01:00
}
2019-07-13 14:52:05 +02:00
}