Skip to content

Commit

Permalink
Add !fabric and revamp message sending code
Browse files Browse the repository at this point in the history
Signed-off-by: shedaniel <[email protected]>
  • Loading branch information
shedaniel committed Dec 15, 2020
1 parent bdca46a commit aa4d629
Show file tree
Hide file tree
Showing 47 changed files with 1,112 additions and 411 deletions.
13 changes: 13 additions & 0 deletions HEADER.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Copyright (c) ${year} ${name}

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
44 changes: 25 additions & 19 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,25 @@ plugins {
id("org.jetbrains.kotlin.plugin.serialization") version("1.4.0")
id("java")
id("com.github.johnrengelman.shadow") version("5.2.0")
id("net.minecrell.licenser") version("0.4.1")
}

group "me.shedaniel"
sourceCompatibility = targetCompatibility = 1.8

license {
include "**/*.kt"
header = project.file("HEADER.txt")
ext {
name = "shedaniel"
year = "2019, 2020"
}
}

configurations {
shadow
shadow {
extendsFrom(runtime)
}
}

repositories {
Expand All @@ -24,32 +36,26 @@ repositories {
}

dependencies {
depend "me.shedaniel:linkie-core:1.0.41"
depend "com.discord4j:discord4j-core:3.1.3-SNAPSHOT", true
depend "org.graalvm.js:js-scriptengine:20.2.0"
depend "org.graalvm.js:js:20.2.0"
depend "io.ktor:ktor-server-core:$ktor_version"
depend "io.ktor:ktor-server-netty:$ktor_version"
compile("me.shedaniel:linkie-core:1.0.41") {
exclude module: "tiny-mappings-parser"
}
compile("com.discord4j:discord4j-core:3.1.3-SNAPSHOT") {
force = true
}
compile "org.graalvm.js:js-scriptengine:20.2.0"
compile "org.graalvm.js:js:20.2.0"
compile "io.ktor:ktor-server-core:$ktor_version"
compile "io.ktor:ktor-server-netty:$ktor_version"
compile "com.github.shedaniel:CurseMetaApi:0.2"
// exclude(module: "truffle-api")
// compile("org.graalvm.sdk:graal-sdk:20.2.0")
// compile("org.graalvm.truffle:truffle-api:20.2.0")
}

def depend(str, forced = false) {
dependencies {
compile(str) {
force = forced
}
shadow(str) {
force = forced
}
}
}

jar {
manifest {
attributes(
'Main-Class': 'me.shedaniel.linkie.discord.LinkieBot'
"Main-Class": "me.shedaniel.linkie.discord.LinkieBot"
)
}
}
Expand Down
144 changes: 114 additions & 30 deletions src/main/kotlin/me/shedaniel/linkie/discord/CommandBase.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright (c) 2019, 2020 shedaniel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package me.shedaniel.linkie.discord

import discord4j.common.util.Snowflake
Expand All @@ -6,19 +22,67 @@ 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.Permission
import me.shedaniel.linkie.InvalidUsageException
import me.shedaniel.linkie.MappingsProvider
import me.shedaniel.linkie.Namespace
import me.shedaniel.linkie.discord.config.ConfigManager
import me.shedaniel.linkie.discord.utils.addInlineField
import me.shedaniel.linkie.discord.utils.sendEmbedMessage
import me.shedaniel.linkie.discord.utils.editOrCreate
import me.shedaniel.linkie.discord.utils.*
import reactor.core.publisher.Mono
import java.time.Duration
import java.util.*
import java.util.concurrent.atomic.AtomicReference

typealias EmbedCreator = EmbedCreateSpec.() -> Unit

fun embedCreator(creator: EmbedCreator) = creator

fun MessageCreator.sendPages(
initialPage: Int,
maxPages: Int,
creator: EmbedCreateSpec.(Int) -> Unit,
) = sendPages(initialPage, maxPages, previous.author.get().id, creator)

fun MessageCreator.sendPages(
initialPage: Int,
maxPages: Int,
user: User,
creator: EmbedCreateSpec.(Int) -> Unit,
) = sendPages(initialPage, maxPages, user.id, creator)

fun MessageCreator.sendPages(
initialPage: Int,
maxPages: Int,
userId: Snowflake,
creator: EmbedCreateSpec.(Int) -> Unit,
) {
var page = initialPage
val builder = embedCreator { creator(this, page) }
sendEmbed(builder).subscribe { msg ->
msg.tryRemoveAllReactions().block()
buildReactions(Duration.ofMinutes(2)) {
if (maxPages > 1) register("") {
if (page > 0) {
page--
sendEmbed(builder).subscribe()
}
}
registerB("") {
msg.delete().subscribe()
false
}
if (maxPages > 1) register("") {
if (page < maxPages - 1) {
page++
sendEmbed(builder).subscribe()
}
}
}.build(msg) { it == userId }
}
}

interface CommandBase {
fun execute(event: MessageCreateEvent, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel)
fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel)

fun getName(): String? = null
fun getDescription(): String? = null
Expand All @@ -27,9 +91,42 @@ interface CommandBase {
fun postRegister() {}
}

fun MessageChannel.deferMessage(previous: Message) = MessageCreator(
this,
previous,
null
)

data class MessageCreator(
val channel: MessageChannel,
var previous: Message,
var message: Message?,
) {
fun send(content: String): Mono<Message> {
return if (message == null) {
channel.sendMessage {
it.content = content
it.setMessageReference(previous.id)
}
} else {
message!!.sendEdit {
it.content = content
}
}.doOnSuccess { message = it }
}

fun sendEmbed(content: EmbedCreator): Mono<Message> {
return if (message == null) {
channel.sendEmbedMessage(previous, content)
} else {
message!!.sendEditEmbed(content)
}.doOnSuccess { message = it }
}
}

open class SubCommandHolder : CommandBase {
private val subcommands = mutableMapOf<String, SubCommandBase>()
override fun execute(event: MessageCreateEvent, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel) {
override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel) {
args.validateNotEmpty(prefix, "$cmd help")

when (val subcommand = args[0].toLowerCase(Locale.ROOT)) {
Expand All @@ -42,7 +139,7 @@ open class SubCommandHolder : CommandBase {
}.subscribe()
}
in subcommands -> {
subcommands[subcommand]!!.execute(event, prefix, user, "$cmd $subcommand", args.drop(1).toMutableList(), channel)
subcommands[subcommand]!!.execute(event, message, prefix, user, "$cmd $subcommand", args.drop(1).toMutableList(), channel)
}
else -> {
throw InvalidUsageException("$prefix help")
Expand All @@ -58,23 +155,23 @@ open class SubCommandHolder : CommandBase {
val reactor = field.get(this) as SubCommandReactor
subcommands[name] = object : SubCommandBase {
override val name: String = name
override fun execute(event: MessageCreateEvent, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel) =
reactor.execute(event, prefix, user, cmd, args, channel)
override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel) =
reactor.execute(event, message, prefix, user, cmd, args, channel)

}
}
}
}

fun subCmd(reactor: (event: MessageCreateEvent, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel) -> Unit): SubCommandReactor = object : SubCommandReactor {
override fun execute(event: MessageCreateEvent, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel) {
reactor(event, prefix, user, cmd, args, channel)
fun subCmd(reactor: (event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel) -> Unit): SubCommandReactor = object : SubCommandReactor {
override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel) {
reactor(event, message, prefix, user, cmd, args, channel)
}
}

fun subCmd(reactor: CommandBase): SubCommandReactor = object : SubCommandReactor {
override fun execute(event: MessageCreateEvent, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel) {
reactor.execute(event, prefix, user, cmd, args, channel)
override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel) {
reactor.execute(event, message, prefix, user, cmd, args, channel)
}
}
}
Expand All @@ -84,28 +181,15 @@ interface SubCommandBase : SubCommandReactor {
}

interface SubCommandReactor {
fun execute(event: MessageCreateEvent, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel)
}

inline fun runCatching(message: AtomicReference<Message?>, channel: MessageChannel, user: User, run: () -> Unit) {
try {
run()
} catch (t: Throwable) {
try {
if (t !is SuppressedException) message.editOrCreate(channel) { generateThrowable(t, user) }.subscribe()
} catch (throwable2: Throwable) {
throwable2.addSuppressed(t)
throw throwable2
}
}
fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel)
}

inline fun <T> getCatching(message: AtomicReference<Message?>, channel: MessageChannel, user: User, run: () -> T): T {
inline fun <T> MessageCreator.getCatching(user: User, run: () -> T): T {
try {
return run()
} catch (t: Throwable) {
try {
if (t !is SuppressedException) message.editOrCreate(channel) { generateThrowable(t, user) }.subscribe()
if (t !is SuppressedException) sendEmbed { generateThrowable(t, user) }.subscribe()
throw SuppressedException()
} catch (throwable2: Throwable) {
throwable2.addSuppressed(t)
Expand Down
20 changes: 18 additions & 2 deletions src/main/kotlin/me/shedaniel/linkie/discord/CommandHandler.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright (c) 2019, 2020 shedaniel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package me.shedaniel.linkie.discord

import discord4j.core.`object`.entity.User
Expand All @@ -20,8 +36,8 @@ object CommandHandler : CommandAcceptor {
override fun getPrefix(event: MessageCreateEvent): String? =
event.guildId.orElse(null)?.let { ConfigManager[it.asLong()].prefix }

override fun execute(event: MessageCreateEvent, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel) {
override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel) {
if (cmd in commandMap)
commandMap[cmd]!!.execute(event, prefix, user, cmd, args, channel)
commandMap[cmd]!!.execute(event, message, prefix, user, cmd, args, channel)
}
}
20 changes: 18 additions & 2 deletions src/main/kotlin/me/shedaniel/linkie/discord/CommandMap.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright (c) 2019, 2020 shedaniel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package me.shedaniel.linkie.discord

import discord4j.core.`object`.entity.User
Expand Down Expand Up @@ -25,7 +41,7 @@ class CommandMap(private val commandAcceptor: CommandAcceptor, private val defau
if (split.isNotEmpty()) {
val cmd = split[0].toLowerCase()
val args = split.drop(1).toMutableList()
commandAcceptor.execute(event, prefix, user, cmd, args, channel)
commandAcceptor.execute(event, channel.deferMessage(event.message), prefix, user, cmd, args, channel)
}
}
}.exceptionOrNull()?.also { throwable ->
Expand Down Expand Up @@ -60,7 +76,7 @@ class CommandMap(private val commandAcceptor: CommandAcceptor, private val defau
}

interface CommandAcceptor {
fun execute(event: MessageCreateEvent, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel)
fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList<String>, channel: MessageChannel)
fun getPrefix(event: MessageCreateEvent): String?
}

Expand Down
17 changes: 17 additions & 0 deletions src/main/kotlin/me/shedaniel/linkie/discord/LinkieBot.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/*
* Copyright (c) 2019, 2020 shedaniel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

@file:JvmName("LinkieBot")

package me.shedaniel.linkie.discord
Expand Down Expand Up @@ -140,6 +156,7 @@ fun registerCommands(commands: CommandHandler) {
commands.registerCommand(ValueListCommand, "value-list")
commands.registerCommand(TricksCommand, "trick")
commands.registerCommand(ValueCommand, "value")
commands.registerCommand(FabricCommand, "fabric")
}

private fun registerWelcomeMessages() {
Expand Down
Loading

0 comments on commit aa4d629

Please sign in to comment.