discord-kagebot/src/main/kotlin/moe/kageru/kagebot/Util.kt

97 lines
3.3 KiB
Kotlin
Raw Normal View History

2019-06-08 21:14:57 +02:00
package moe.kageru.kagebot
2019-11-24 14:03:45 +01:00
import arrow.core.*
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.*
import org.javacord.api.entity.channel.TextChannel
2019-06-10 09:19:03 +02:00
import org.javacord.api.entity.message.MessageAuthor
import org.javacord.api.entity.message.embed.EmbedBuilder
import org.javacord.api.entity.permission.Role
import org.javacord.api.entity.user.User
import java.awt.Color
2019-07-13 15:39:50 +02:00
import java.util.*
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-11-14 15:10:30 +01:00
private val channelIdRegex = Regex("\\d{18}")
private fun String.isEntityId() = channelIdRegex.matches(this)
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-11-14 15:10:30 +01: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-11-14 15:10:30 +01: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-14 15:10:30 +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-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-11-14 15:10:30 +01:00
else -> server.channelsByName(idOrName).getOnly().mapLeft { "Found $it channels for $idOrName, expected 1" }
}
2019-11-14 15:10:30 +01: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", """```
${e.stackTrace.joinToString("\n\t")}
```""".trimIndent().run { applyIf(length > 1800) { substring(1..1800) } }
2019-11-14 15:10:30 +01:00
)
)
}
2019-11-14 15:10:30 +01:00
}
2019-07-13 14:52:05 +02:00
}