fix: stability issues

This commit is contained in:
kraftwerk28 2021-07-10 02:00:22 +03:00
parent 8c401887ad
commit 5b4374f0c9
3 changed files with 69 additions and 52 deletions

View File

@ -2,15 +2,13 @@ package org.kraftwerk28.spigot_tg_bridge
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.bukkit.plugin.java.JavaPlugin
open class AsyncJavaPlugin : JavaPlugin() {
private val scope = CoroutineScope(Dispatchers.Default)
private val jobs: MutableList<Job> = mutableListOf()
override fun onEnable() {
runBlocking { onEnableAsync() }
@ -19,7 +17,7 @@ open class AsyncJavaPlugin : JavaPlugin() {
override fun onDisable() {
runBlocking {
onDisableAsync()
jobs.joinAll()
scope.cancel()
}
}
@ -27,9 +25,5 @@ open class AsyncJavaPlugin : JavaPlugin() {
open suspend fun onDisableAsync() = Unit
fun <T> launch(f: suspend () -> T) = scope.launch {
f()
}.also {
jobs.add(it)
}
fun <T> launch(f: suspend () -> T) = scope.launch { f() }
}

View File

@ -82,6 +82,7 @@ class Plugin : AsyncJavaPlugin() {
eventHandler?.let { HandlerList.unregisterAll(it) }
tgBot?.run { stop() }
tgBot = TgBot(this, config).also { bot ->
bot.startPolling()
eventHandler = EventHandler(this, config, bot).also {
server.pluginManager.registerEvents(it, this)
}

View File

@ -14,6 +14,14 @@ import java.time.Duration
import org.kraftwerk28.spigot_tg_bridge.Constants as C
typealias UpdateRequest = Call<TgResponse<List<Update>>>?
typealias CmdHandler = suspend (HandlerContext) -> Unit
data class HandlerContext(
val update: Update,
val message: Message?,
val chat: Chat?,
val commandArgs: List<String>,
)
class TgBot(
private val plugin: Plugin,
@ -27,14 +35,14 @@ class TgBot(
private var currentOffset: Long = -1
private var me: User? = null
private var commandRegex: Regex? = null
private val commandMap: Map<String?, suspend (u: Update) -> Unit> =
config.commands.run {
private val commandMap: Map<String?, CmdHandler> = config.commands.run {
mapOf(
online to ::onlineHandler,
time to ::timeHandler,
chatID to ::chatIdHandler,
linkIgn to ::linkIgnHandler,
getAllLinked to ::getLinkedUsersHandler,
// TODO:
// linkIgn to ::linkIgnHandler,
// getAllLinked to ::getLinkedUsersHandler,
)
}
@ -55,7 +63,7 @@ class TgBot(
me = api.getMe().result!!
// I intentionally don't put optional @username in regex
// since bot is only used in group chats
commandRegex = """^\/(\w+)(?:@${me!!.username})$""".toRegex()
commandRegex = """^\/(\w+)(?:@${me!!.username})(?:\s+(.+))?$""".toRegex()
val commands = config.commands.run { listOf(time, online, chatID) }
.zip(
C.COMMAND_DESC.run {
@ -118,17 +126,26 @@ class TgBot(
// Ignore PM or channel
if (listOf("private", "channel").contains(update.message?.chat?.type))
return
var ctx = HandlerContext(
update,
update.message,
update.message?.chat,
listOf(),
)
update.message?.text?.let {
commandRegex?.matchEntire(it)?.groupValues?.let {
commandMap.get(it[1])?.let { it(update) }
commandMap.get(it[1])?.run {
val args = it[2].split("\\s+".toRegex())
this(ctx.copy(commandArgs = args))
}
} ?: run {
onTextHandler(update)
onTextHandler(ctx)
}
}
}
private suspend fun timeHandler(update: Update) {
val msg = update.message!!
private suspend fun timeHandler(ctx: HandlerContext) {
val msg = ctx.message!!
if (!config.allowedChats.contains(msg.chat.id)) {
return
}
@ -154,8 +171,8 @@ class TgBot(
api.sendMessage(msg.chat.id, text, replyToMessageId = msg.messageId)
}
private suspend fun onlineHandler(update: Update) {
val msg = update.message!!
private suspend fun onlineHandler(ctx: HandlerContext) {
val msg = ctx.message!!
if (!config.allowedChats.contains(msg.chat.id)) {
return
}
@ -170,8 +187,8 @@ class TgBot(
api.sendMessage(msg.chat.id, text, replyToMessageId = msg.messageId)
}
private suspend fun chatIdHandler(update: Update) {
val msg = update.message!!
private suspend fun chatIdHandler(ctx: HandlerContext) {
val msg = ctx.message!!
val chatId = msg.chat.id
val text = """
|Chat ID: <code>$chatId</code>.
@ -184,25 +201,45 @@ class TgBot(
api.sendMessage(chatId, text, replyToMessageId = msg.messageId)
}
private suspend fun linkIgnHandler(update: Update) {
val tgUser = update.message!!.from!!
val mcUuid = getMinecraftUuidByUsername(update.message.text!!)
if (mcUuid == null) {
private suspend fun linkIgnHandler(ctx: HandlerContext) {
val tgUser = ctx.message!!.from!!
val mcUuid = getMinecraftUuidByUsername(ctx.message.text!!)
if (mcUuid == null || ctx.commandArgs.size < 1) {
// Respond...
return
}
val (minecraftIgn) = ctx.commandArgs
val linked = plugin.ignAuth?.linkUser(
tgId = tgUser.id,
tgFirstName = tgUser.firstName,
tgLastName = tgUser.lastName,
minecraftUsername = tgUser.username,
minecraftUsername = minecraftIgn,
minecraftUuid = mcUuid,
)
println(tgUser.toString())
) ?: false
if (linked) {
// TODO
}
}
private suspend fun onTextHandler(update: Update) {
val msg = update.message!!
private suspend fun getLinkedUsersHandler(ctx: HandlerContext) {
val linkedUsers = plugin.ignAuth?.run {
getAllLinkedUsers()
} ?: listOf()
if (linkedUsers.isEmpty()) {
api.sendMessage(ctx.message!!.chat.id, "No linked users.")
} else {
val text = "<b>Linked users:</b>\n" +
linkedUsers.mapIndexed { i, dbUser ->
"${i + 1}. ${dbUser.fullName()}"
}.joinToString("\n")
api.sendMessage(ctx.message!!.chat.id, text)
}
}
private suspend fun onTextHandler(
@Suppress("unused_parameter") ctx: HandlerContext
) {
val msg = ctx.message!!
if (!config.logFromTGtoMC || msg.from == null)
return
plugin.sendMessageToMinecraft(
@ -212,21 +249,6 @@ class TgBot(
)
}
private suspend fun getLinkedUsersHandler(update: Update) {
val linkedUsers = plugin.ignAuth?.run {
getAllLinkedUsers()
} ?: listOf()
if (linkedUsers.isEmpty()) {
api.sendMessage(update.message!!.chat.id, "No linked users.")
} else {
val text = "<b>Linked users:</b>\n" +
linkedUsers.mapIndexed { i, dbUser ->
"${i + 1}. ${dbUser.fullName()}"
}.joinToString("\n")
api.sendMessage(update.message!!.chat.id, text)
}
}
suspend fun sendMessageToTelegram(text: String, username: String? = null) {
val formatted = username?.let {
config.telegramFormat