Skip to content

Commit

Permalink
Separate bot api out
Browse files Browse the repository at this point in the history
Signed-off-by: shedaniel <daniel@shedaniel.me>
  • Loading branch information
shedaniel committed Aug 22, 2021
1 parent 5beff91 commit 62e58b5
Show file tree
Hide file tree
Showing 34 changed files with 479 additions and 284 deletions.
42 changes: 27 additions & 15 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,26 @@ license {
}
}

configurations {
shadow {
extendsFrom(implementation)
}
}

sourceSets {
tricks {
resources.srcDirs += rootProject.file("tricks")
}
discord_api
main {
compileClasspath += discord_api.compileClasspath + discord_api.output
runtimeClasspath += discord_api.runtimeClasspath + discord_api.output
}
testDiscordApi {
compileClasspath += discord_api.compileClasspath + discord_api.output
runtimeClasspath += discord_api.runtimeClasspath + discord_api.output
}
}

configurations {
shadow {
extendsFrom(implementation)
extendsFrom(discord_apiImplementation)
}
}

repositories {
Expand All @@ -47,29 +57,30 @@ dependencies {
implementation("me.shedaniel:linkie-core:1.0.87") {
exclude module: "korio"
}
implementation("com.discord4j.discord4j:discord4j-core:bab624fb5e") {
discord_apiImplementation("com.discord4j.discord4j:discord4j-core:bab624fb5e") {
force = true
}
// compile("com.github.shadorc.discord4j:discord4j-core:217336e") {
// force = true
// }
implementation('com.soywiz.korlibs.korio:korio-jvm:2.3.1') {
discord_apiImplementation('com.soywiz.korlibs.korio:korio-jvm:2.3.1') {
exclude module: "kds"
exclude module: "klock"
exclude module: "klogger"
exclude module: "krypto"
exclude module: "kmem"
}
implementation('com.soywiz.korlibs.kds:kds-jvm:2.3.1')
implementation('com.soywiz.korlibs.klock:klock-jvm:2.3.1')
implementation('com.soywiz.korlibs.klogger:klogger-jvm:2.3.1')
implementation('com.soywiz.korlibs.krypto:krypto-jvm:2.3.1')
implementation('com.soywiz.korlibs.kmem:kmem-jvm:2.3.1')
discord_apiImplementation('com.soywiz.korlibs.kds:kds-jvm:2.3.1')
discord_apiImplementation('com.soywiz.korlibs.klock:klock-jvm:2.3.1')
discord_apiImplementation('com.soywiz.korlibs.klogger:klogger-jvm:2.3.1')
discord_apiImplementation('com.soywiz.korlibs.krypto:krypto-jvm:2.3.1')
discord_apiImplementation('com.soywiz.korlibs.kmem:kmem-jvm:2.3.1')
implementation 'org.graalvm.js:js-scriptengine:21.2.0'
implementation 'org.graalvm.js:js:21.2.0'
implementation "io.ktor:ktor-server-core:$ktor_version"
implementation "io.ktor:ktor-server-netty:$ktor_version"
discord_apiImplementation "io.ktor:ktor-server-core:$ktor_version"
discord_apiImplementation "io.ktor:ktor-server-netty:$ktor_version"
implementation "com.github.shedaniel:CurseMetaApi:0.2"
testDiscordApiImplementation "org.jetbrains.kotlin:kotlin-test-junit5:1.5.21"
// exclude(module: "truffle-api")
// compile("org.graalvm.sdk:graal-sdk:20.2.0")
// compile("org.graalvm.truffle:truffle-api:20.2.0")
Expand All @@ -92,6 +103,7 @@ shadowJar {

task mainJar(type: Jar, dependsOn: [shadowJar, tasks.tricksZip]) {
from zipTree(shadowJar.archiveFile.get())
from tasks.compileDiscord_apiKotlin.outputs
from tasks.tricksZip.archiveFile
manifest {
attributes(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package me.shedaniel.linkie.discord

import com.soywiz.korio.async.runBlockingNoJs
import discord4j.core.`object`.entity.Message
import discord4j.core.`object`.entity.User
import me.shedaniel.linkie.discord.scommands.ArgReader
import me.shedaniel.linkie.discord.scommands.ExecuteResult
import me.shedaniel.linkie.discord.scommands.NestedSlashCommandOption
import me.shedaniel.linkie.discord.scommands.OptionsGetter
Expand All @@ -30,9 +30,7 @@ import me.shedaniel.linkie.discord.scommands.SlashCommandExecutorAcceptor
import me.shedaniel.linkie.discord.scommands.SubCommandOption
import me.shedaniel.linkie.discord.scommands.SubGroupCommandOption
import me.shedaniel.linkie.discord.scommands.sub
import me.shedaniel.linkie.discord.utils.ArgReaderImpl
import me.shedaniel.linkie.discord.utils.CommandContext
import me.shedaniel.linkie.discord.utils.MessageCreator
import me.shedaniel.linkie.discord.utils.property
import java.util.*

Expand Down Expand Up @@ -76,7 +74,7 @@ interface Command {
val root = if (isGroup) SubGroupCommandOption(ctx.cmd, "", listOf()) else SubCommandOption(ctx.cmd, "", listOf())
command.options.forEach(root::arg)
root.execute(command)
val reader = ArgReaderImpl(if (isGroup) args else (sequenceOf(ctx.cmd) + args.asSequence()).toMutableList())
val reader = ArgReader(if (isGroup) args else (sequenceOf(ctx.cmd) + args.asSequence()).toMutableList())
return root.execute(ctx, command, reader.property, OptionsGetterBuilder(command, ctx)) == ExecuteResult.EXECUTED
}

Expand Down Expand Up @@ -123,7 +121,7 @@ interface OptionlessCommand : Command {
suspend fun execute(ctx: CommandContext)
}

@Deprecated("bruh")
@Deprecated("Legacy Command!")
interface LegacyCommand {
suspend fun execute(ctx: CommandContext, trigger: Message, args: MutableList<String>)
fun postRegister() {}
Expand Down Expand Up @@ -151,17 +149,3 @@ open class SubCommandHolder : Command {
}

data class SubCommandEntry<T : Command>(val command: T)

inline fun <T> MessageCreator.getCatching(user: User, run: () -> T): T {
try {
return run()
} catch (t: Throwable) {
try {
if (t !is SuppressedException) reply { generateThrowable(t, user) }
throw SuppressedException()
} catch (throwable2: Throwable) {
throwable2.addSuppressed(t)
throw throwable2
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,50 +14,62 @@
* limitations under the License.
*/

package me.shedaniel.linkie.discord
package me.shedaniel.linkie.discord.handler

import discord4j.core.GatewayDiscordClient
import discord4j.core.`object`.entity.Message
import discord4j.core.`object`.entity.User
import discord4j.core.`object`.entity.channel.MessageChannel
import discord4j.core.event.domain.message.MessageCreateEvent
import discord4j.core.spec.EmbedCreateSpec
import discord4j.rest.util.Color
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import me.shedaniel.linkie.discord.scommands.splitArgs
import me.shedaniel.linkie.discord.utils.CommandContext
import me.shedaniel.linkie.discord.utils.MessageBasedCommandContext
import me.shedaniel.linkie.discord.utils.basicEmbed
import me.shedaniel.linkie.discord.utils.buildReactions
import me.shedaniel.linkie.discord.utils.dismissButton
import me.shedaniel.linkie.discord.utils.event
import me.shedaniel.linkie.discord.utils.msgCreator
import me.shedaniel.linkie.discord.utils.sendEmbedMessage
import java.time.Duration

class CommandMap(private val commandAcceptor: CommandAcceptor, private val defaultPrefix: String) {
class CommandHandler(
private val client: GatewayDiscordClient,
private val commandAcceptor: CommandAcceptor,
private val throwableHandler: ThrowableHandler,
) {
val scope = CoroutineScope(Dispatchers.Default)

fun register() {
client.event(this::onMessageCreate)
}

fun onMessageCreate(event: MessageCreateEvent) {
val channel = event.message.channel.block() ?: return
val user = event.message.author.orElse(null)?.takeUnless { it.isBot } ?: return
val message: String = event.message.content
val prefix = commandAcceptor.getPrefix(event) ?: defaultPrefix
val prefix = commandAcceptor.getPrefix(event)
scope.launch {
try {
if (message.toLowerCase().startsWith(prefix)) {
if (message.lowercase().startsWith(prefix)) {
val content = message.substring(prefix.length)
val split = content.splitArgs()
if (split.isNotEmpty()) {
val cmd = split[0].toLowerCase()
val cmd = split[0].lowercase()
val ctx = MessageBasedCommandContext(event, channel.msgCreator(event.message), prefix, cmd, channel)
val args = split.drop(1).toMutableList()
try {
commandAcceptor.execute(event, ctx, args)
} catch (throwable: Throwable) {
if (throwable is SuppressedException) return@launch
try {
ctx.message.reply(ctx, {
dismissButton()
}) {
generateThrowable(throwable, user)
throwableHandler.generateThrowable(this, throwable, user)
}
} catch (throwable2: Exception) {
throwable2.addSuppressed(throwable)
Expand All @@ -67,66 +79,46 @@ class CommandMap(private val commandAcceptor: CommandAcceptor, private val defau
}
}
} catch (throwable: Throwable) {
if (throwable is SuppressedException) return@launch
try {
channel.sendEmbedMessage { generateThrowable(throwable, user) }.subscribe { message ->
buildReactions(Duration.ofMinutes(2)) {
registerB("") {
message.delete().subscribe()
event.message.delete().subscribe()
false
}
}.build(message) { it == user.id }
}
} catch (throwable2: Exception) {
throwable2.addSuppressed(throwable)
throwable2.printStackTrace()
}
throwableHandler.generateErrorMessage(event.message, throwable, channel, user)
}
}
}
}

fun String.splitArgs(): MutableList<String> {
val args = mutableListOf<String>()
val stringBuilder = StringBuilder()
forEach {
val whitespace = it.isWhitespace()
if (whitespace) {
args.add(stringBuilder.toString())
stringBuilder.clear()
}
if (it == '\n' || !whitespace) {
stringBuilder.append(it)
}
}
if (stringBuilder.isNotEmpty())
args.add(stringBuilder.toString())
return args.dropLastWhile(String::isEmpty).toMutableList()
interface CommandAcceptor {
suspend fun execute(event: MessageCreateEvent, ctx: CommandContext, args: MutableList<String>): Boolean
fun getPrefix(event: MessageCreateEvent): String
}

interface CommandAcceptor {
suspend fun execute(event: MessageCreateEvent, ctx: CommandContext, args: MutableList<String>)
fun getPrefix(event: MessageCreateEvent): String?
interface ThrowableHandler {
fun generateErrorMessage(original: Message?, throwable: Throwable, channel: MessageChannel, user: User)
fun generateThrowable(builder: EmbedCreateSpec.Builder, throwable: Throwable, user: User)
}

fun EmbedCreateSpec.Builder.generateThrowable(throwable: Throwable, user: User? = null) {
title("Linkie Error")
color(Color.RED)
basicEmbed(user)
when {
throwable is org.graalvm.polyglot.PolyglotException -> {
val details = throwable.localizedMessage ?: ""
addField("Error occurred while processing the command", "```$details```", false)
}
throwable.javaClass.name.startsWith("org.graalvm") -> {
val details = throwable.localizedMessage ?: ""
addField("Error occurred while processing the command", "```" + throwable.javaClass.name + (if (details.isEmpty()) "" else ":\n") + details + "```", false)
open class SimpleThrowableHandler : ThrowableHandler {
override fun generateErrorMessage(original: Message?, throwable: Throwable, channel: MessageChannel, user: User) {
try {
channel.sendEmbedMessage { generateThrowable(this, throwable, user) }.subscribe { message ->
buildReactions(Duration.ofMinutes(2)) {
registerB("") {
message.delete().subscribe()
original?.delete()?.subscribe()
false
}
}.build(message) { it == user.id }
}
} catch (throwable2: Exception) {
throwable2.addSuppressed(throwable)
throwable2.printStackTrace()
}
else -> {
}

override fun generateThrowable(builder: EmbedCreateSpec.Builder, throwable: Throwable, user: User) {
builder.apply {
title("Linkie Error")
color(Color.RED)
basicEmbed(user)
addField("Error occurred while processing the command:", throwable.javaClass.simpleName + ": " + (throwable.localizedMessage ?: "Unknown Message"), false)
}
}
if (isDebug)
throwable.printStackTrace()
}
}
Loading

0 comments on commit 62e58b5

Please sign in to comment.