Refactoring, 'cause I finally got IJ Idea

This commit is contained in:
kraftwerk28 2021-07-11 17:22:04 +03:00
parent a8aa799b96
commit 4bcd274df4
6 changed files with 71 additions and 74 deletions

1
.gitignore vendored
View File

@ -25,3 +25,4 @@ hs_err_pid*
build/
.gradle/
local.properties
.idea/

View File

@ -2,7 +2,6 @@ package org.kraftwerk28.spigot_tg_bridge
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.Job

View File

@ -37,7 +37,7 @@ class Configuration(plugin: Plugin) {
// plugin.saveResource(C.configFilename, false);
throw Exception(C.WARN.noConfigWarning)
}
val pluginConfig = plugin.getConfig()
val pluginConfig = plugin.config
pluginConfig.load(cfgFile)
pluginConfig.getString("minecraftMessageFormat")?.let {

View File

@ -18,8 +18,8 @@ create table if not exists user (
class IgnAuth(
fileName: String,
val plugin: Plugin,
var conn: Connection? = null,
private val plugin: Plugin,
private var conn: Connection? = null,
) {
init {
plugin.launch {
@ -27,7 +27,7 @@ class IgnAuth(
}
}
suspend fun initializeConnection(fileName: String) = try {
private fun initializeConnection(fileName: String) = try {
DriverManager.getConnection("jdbc:sqlite:$fileName").apply {
createStatement().execute(INIT_DB_QUERY)
}.also {
@ -37,11 +37,11 @@ class IgnAuth(
plugin.logger.info(e.message)
}
suspend fun close() = conn?.run {
fun close() = conn?.run {
close()
}
suspend fun linkUser(
fun linkUser(
tgId: Long,
tgUsername: String? = null,
tgFirstName: String,
@ -70,21 +70,21 @@ class IgnAuth(
execute()
} ?: false
suspend fun getLinkedUserByIgn(ign: String) =
fun getLinkedUserByIgn(ign: String) =
conn?.stmt("select * from user where mc_uuid = ?", ign)?.first {
toLinkedUser()
}
suspend fun getLinkedUserByTgId(id: Long) =
fun getLinkedUserByTgId(id: Long) =
conn?.stmt("select * from user where tg_id = ?", id)?.first {
toLinkedUser()
}
suspend fun unlinkUserByTgId(id: Long) =
fun unlinkUserByTgId(id: Long) =
conn?.stmt("delete from user where tg_id = ?", id)?.run {
executeUpdate() > 0
}
suspend fun getAllLinkedUsers() =
fun getAllLinkedUsers() =
conn?.stmt("select * from user")?.map { toLinkedUser() }
}

View File

@ -1,45 +1,55 @@
package org.kraftwerk28.spigot_tg_bridge
import kotlinx.coroutines.delay
import org.bukkit.event.HandlerList
import java.lang.Exception
import kotlin.system.measureTimeMillis
import org.kraftwerk28.spigot_tg_bridge.Constants as C
class Plugin : AsyncJavaPlugin() {
var tgBot: TgBot? = null
private var tgBot: TgBot? = null
private var eventHandler: EventHandler? = null
var config: Configuration? = null
private var config: Configuration? = null
var ignAuth: IgnAuth? = null
override suspend fun onEnableAsync() = try {
config = Configuration(this).also { config ->
if (!config.isEnabled) return
if (config.enableIgnAuth) {
val dbFilePath = dataFolder.resolve("spigot-tg-bridge.sqlite")
ignAuth = IgnAuth(
fileName = dbFilePath.absolutePath,
plugin = this,
)
}
tgBot?.run { stop() }
tgBot = TgBot(this, config).also { bot ->
bot.startPolling()
eventHandler = EventHandler(this, config, bot).also {
server.pluginManager.registerEvents(it, this)
override suspend fun onEnableAsync() {
try {
launch {
config = Configuration(this).also {
initializeWithConfig(it)
}
}
} catch (e: Exception) {
// Configuration file is missing or incomplete
logger.warning(e.message)
}
}
getCommand(C.COMMANDS.PLUGIN_RELOAD)?.run {
setExecutor(CommandHandler(this@Plugin))
}
config.serverStartMessage?.let {
tgBot?.sendMessageToTelegram(it)
private suspend fun initializeWithConfig(config: Configuration) {
if (!config.isEnabled) return
if (config.enableIgnAuth) {
val dbFilePath = dataFolder.resolve("spigot-tg-bridge.sqlite")
ignAuth = IgnAuth(
fileName = dbFilePath.absolutePath,
plugin = this,
)
}
tgBot?.run { stop() }
tgBot = TgBot(this, config).also { bot ->
bot.startPolling()
eventHandler = EventHandler(this, config, bot).also {
server.pluginManager.registerEvents(it, this)
}
}
} catch (e: Exception) {
// Configuration file is missing or incomplete
logger.warning(e.message)
getCommand(C.COMMANDS.PLUGIN_RELOAD)?.run {
setExecutor(CommandHandler(this@Plugin))
}
config.serverStartMessage?.let {
tgBot?.sendMessageToTelegram(it)
}
}
override suspend fun onDisableAsync() {
@ -52,6 +62,7 @@ class Plugin : AsyncJavaPlugin() {
eventHandler?.let { HandlerList.unregisterAll(it) }
tgBot?.run { stop() }
tgBot = null
ignAuth?.close()
}
}

View File

@ -5,30 +5,35 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.consumeEach
import kotlinx.coroutines.launch
import okhttp3.OkHttpClient
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
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>,
val commandArgs: List<String> = listOf(),
)
class TgBot(
private val plugin: Plugin,
private val config: Configuration,
) {
private val api: TgApiService
private val client: OkHttpClient
private val client: OkHttpClient = OkHttpClient
.Builder()
.readTimeout(Duration.ZERO)
.build()
private val api = Retrofit.Builder()
.baseUrl("https://api.telegram.org/bot${config.botToken}/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(TgApiService::class.java)
private val updateChan = Channel<Update>()
private var pollJob: Job? = null
private var handlerJob: Job? = null
@ -46,24 +51,11 @@ class TgBot(
)
}
init {
client = OkHttpClient
.Builder()
.readTimeout(Duration.ZERO)
.build()
api = Retrofit.Builder()
.baseUrl("https://api.telegram.org/bot${config.botToken}/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(TgApiService::class.java)
}
private suspend fun initialize() {
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})(?:\s+(.+))?$""".toRegex()
commandRegex = """^/(\w+)@${me!!.username}(?:\s+(.+))?$""".toRegex()
val commands = config.commands.run { listOf(time, online, chatID) }
.zip(
C.COMMAND_DESC.run {
@ -88,13 +80,13 @@ class TgBot(
}
private fun initPolling() = plugin.launch {
loop@ while (true) {
loop@while (true) {
try {
api.getUpdates(
offset = currentOffset,
timeout = config.pollTimeout,
).result?.let { updates ->
if (!updates.isEmpty()) {
if (updates.isNotEmpty()) {
updates.forEach { updateChan.send(it) }
currentOffset = updates.last().updateId + 1
}
@ -122,20 +114,19 @@ class TgBot(
}
}
suspend fun handleUpdate(update: Update) {
// Ignore PM or channel
private suspend fun handleUpdate(update: Update) {
// Ignore private message or channel post
if (listOf("private", "channel").contains(update.message?.chat?.type))
return
var ctx = HandlerContext(
val ctx = HandlerContext(
update,
update.message,
update.message?.chat,
listOf(),
)
update.message?.text?.let {
commandRegex?.matchEntire(it)?.groupValues?.let {
commandMap.get(it[1])?.run {
val args = it[2].split("\\s+".toRegex())
commandRegex?.matchEntire(it)?.groupValues?.let { matchList ->
commandMap[matchList[1]]?.run {
val args = matchList[2].split("\\s+".toRegex())
this(ctx.copy(commandArgs = args))
}
} ?: run {
@ -204,7 +195,7 @@ class TgBot(
private suspend fun linkIgnHandler(ctx: HandlerContext) {
val tgUser = ctx.message!!.from!!
val mcUuid = getMinecraftUuidByUsername(ctx.message.text!!)
if (mcUuid == null || ctx.commandArgs.size < 1) {
if (mcUuid == null || ctx.commandArgs.isEmpty()) {
// Respond...
return
}
@ -236,7 +227,7 @@ class TgBot(
}
}
private suspend fun onTextHandler(
private fun onTextHandler(
@Suppress("unused_parameter") ctx: HandlerContext
) {
val msg = ctx.message!!
@ -258,10 +249,5 @@ class TgBot(
config.allowedChats.forEach { chatId ->
api.sendMessage(chatId, formatted)
}
// plugin.launch {
// config.allowedChats.forEach { chatId ->
// api.sendMessage(chatId, formatted)
// }
// }
}
}