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

View File

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

View File

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