mirror of
https://github.com/amalthea-mc/spigot-tg-bridge.git
synced 2024-11-23 19:02:21 +00:00
Move to kotlinx coroutines
This commit is contained in:
parent
443dfb9394
commit
41fbe85f7f
@ -36,7 +36,8 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val tgBotVersion = "6.0.4"
|
val tgBotVersion = "6.0.4"
|
||||||
val plugDir = "MinecraftServers/spigot_1.16.5/plugins/"
|
val retrofitVersion = "2.7.1"
|
||||||
|
val plugDir = "MinecraftServers/spigot_1.17/plugins/"
|
||||||
val homeDir = System.getProperty("user.home")
|
val homeDir = System.getProperty("user.home")
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
@ -45,6 +46,9 @@ tasks {
|
|||||||
"spigot-tg-bridge-${spigotApiVersion}-v${pluginVersion}.jar"
|
"spigot-tg-bridge-${spigotApiVersion}-v${pluginVersion}.jar"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
build {
|
||||||
|
dependsOn("shadowJar")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register<Copy>("copyArtifacts") {
|
tasks.register<Copy>("copyArtifacts") {
|
||||||
@ -57,15 +61,14 @@ tasks.register("pack") {
|
|||||||
finalizedBy("copyArtifacts")
|
finalizedBy("copyArtifacts")
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultTasks("pack")
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||||
compileOnly("org.spigotmc:spigot-api:$spigotApiVersion-R0.1-SNAPSHOT")
|
compileOnly("org.spigotmc:spigot-api:$spigotApiVersion-R0.1-SNAPSHOT")
|
||||||
implementation(
|
implementation("com.google.code.gson:gson:2.8.7")
|
||||||
"io.github.kotlin-telegram-bot.kotlin-telegram-bot" +
|
implementation("com.squareup.retrofit2:retrofit:$retrofitVersion")
|
||||||
":telegram:$tgBotVersion"
|
implementation("com.squareup.retrofit2:converter-gson:$retrofitVersion")
|
||||||
)
|
implementation("com.squareup.okhttp3:logging-interceptor:4.2.1")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0")
|
||||||
implementation("com.vdurmont:emoji-java:5.1.1")
|
implementation("com.vdurmont:emoji-java:5.1.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
package org.kraftwerk28.spigot_tg_bridge
|
||||||
|
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import com.google.gson.annotations.SerializedName as Name
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
import retrofit2.http.*
|
||||||
|
import java.time.Duration
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
|
||||||
|
interface TgApiService {
|
||||||
|
data class TgResponse<T>(val ok: Boolean, val result: T?, val description: String?)
|
||||||
|
data class WebhookOptions(val drop_pending_updates: Boolean)
|
||||||
|
|
||||||
|
data class User(
|
||||||
|
@Name("id") val id: Long,
|
||||||
|
@Name("is_bot") val isBot: Boolean,
|
||||||
|
@Name("first_name") val firstName: String,
|
||||||
|
@Name("last_name") val lastName: String? = null,
|
||||||
|
@Name("username") val username: String? = null,
|
||||||
|
@Name("language_code") val languageCode: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Chat(
|
||||||
|
val id: Long,
|
||||||
|
val type: String,
|
||||||
|
val title: String? = null,
|
||||||
|
val username: String? = null,
|
||||||
|
@Name("first_name") val firstName: String? = null,
|
||||||
|
@Name("last_name") val lastName: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Message(
|
||||||
|
@Name("message_id") val messageId: Long,
|
||||||
|
val from: User? = null,
|
||||||
|
@Name("sender_chat") val senderChat: Chat? = null,
|
||||||
|
val date: Long,
|
||||||
|
val chat: Chat,
|
||||||
|
@Name("reply_to_message") val replyToMessage: Message? = null,
|
||||||
|
val text: String? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class Update(
|
||||||
|
@Name("update_id") val updateId: Long,
|
||||||
|
val message: Message? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class BotCommand(val command: String, val description: String)
|
||||||
|
data class SetMyCommands(val commands: List<BotCommand>)
|
||||||
|
|
||||||
|
@GET("deleteWebhook")
|
||||||
|
suspend fun deleteWebhook(
|
||||||
|
@Query("drop_pending_updates") dropPendingUpdates: Boolean
|
||||||
|
): TgResponse<Boolean>
|
||||||
|
|
||||||
|
@GET("sendMessage?parse_mode=HTML")
|
||||||
|
suspend fun sendMessage(
|
||||||
|
@Query("chat_id") chatId: Long,
|
||||||
|
@Query("text") text: String,
|
||||||
|
@Query("reply_to_message_id") replyToMessageId: Long? = null,
|
||||||
|
): TgResponse<Message>
|
||||||
|
|
||||||
|
@GET("getUpdates")
|
||||||
|
suspend fun getUpdates(
|
||||||
|
@Query("offset") offset: Long,
|
||||||
|
@Query("limit") limit: Int = 100,
|
||||||
|
@Query("timeout") timeout: Int = 0,
|
||||||
|
): TgResponse<List<Update>>
|
||||||
|
|
||||||
|
@GET("getMe")
|
||||||
|
suspend fun getMe(): TgResponse<User>
|
||||||
|
|
||||||
|
@POST("setMyCommands")
|
||||||
|
suspend fun setMyCommands(
|
||||||
|
@Body commands: SetMyCommands,
|
||||||
|
): TgResponse<Boolean>
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun create(token: String): TgApiService {
|
||||||
|
val interceptor = HttpLoggingInterceptor().apply {
|
||||||
|
level = HttpLoggingInterceptor.Level.NONE;
|
||||||
|
}
|
||||||
|
val client = OkHttpClient
|
||||||
|
.Builder()
|
||||||
|
.addInterceptor(interceptor)
|
||||||
|
.readTimeout(Duration.ZERO)
|
||||||
|
.build();
|
||||||
|
val r = Retrofit.Builder()
|
||||||
|
.baseUrl("https://api.telegram.org/bot$token/")
|
||||||
|
.client(client)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build()
|
||||||
|
return r.create(TgApiService::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ import org.bukkit.event.player.AsyncPlayerChatEvent
|
|||||||
import org.bukkit.event.player.PlayerBedEnterEvent
|
import org.bukkit.event.player.PlayerBedEnterEvent
|
||||||
import org.bukkit.event.player.PlayerJoinEvent
|
import org.bukkit.event.player.PlayerJoinEvent
|
||||||
import org.bukkit.event.player.PlayerQuitEvent
|
import org.bukkit.event.player.PlayerQuitEvent
|
||||||
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
class EventHandler(
|
class EventHandler(
|
||||||
private val tgBot: TgBot,
|
private val tgBot: TgBot,
|
||||||
@ -17,16 +18,21 @@ class EventHandler(
|
|||||||
fun onPlayerChat(event: AsyncPlayerChatEvent) {
|
fun onPlayerChat(event: AsyncPlayerChatEvent) {
|
||||||
if (!config.logFromMCtoTG) return
|
if (!config.logFromMCtoTG) return
|
||||||
event.run {
|
event.run {
|
||||||
|
measureTimeMillis {
|
||||||
tgBot.sendMessageToTelegram(
|
tgBot.sendMessageToTelegram(
|
||||||
message, player.displayName
|
message, player.displayName
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
.also {
|
||||||
|
println("Time: $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
fun onPlayerJoin(event: PlayerJoinEvent) {
|
fun onPlayerJoin(event: PlayerJoinEvent) {
|
||||||
if (!config.logJoinLeave || config.joinString == null) return
|
if (!config.logJoinLeave || config.joinString == null) return
|
||||||
val username = fullEscape(event.player.displayName)
|
val username = event.player.displayName.fullEscape()
|
||||||
val text = config.joinString!!.replace("%username%", username)
|
val text = config.joinString!!.replace("%username%", username)
|
||||||
tgBot.sendMessageToTelegram(text)
|
tgBot.sendMessageToTelegram(text)
|
||||||
}
|
}
|
||||||
@ -34,7 +40,7 @@ class EventHandler(
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
fun onPlayerLeave(event: PlayerQuitEvent) {
|
fun onPlayerLeave(event: PlayerQuitEvent) {
|
||||||
if (!config.logJoinLeave || config.leaveString == null) return
|
if (!config.logJoinLeave || config.leaveString == null) return
|
||||||
val username = fullEscape(event.player.displayName)
|
val username = event.player.displayName.fullEscape()
|
||||||
val text = config.leaveString!!.replace("%username%", username)
|
val text = config.leaveString!!.replace("%username%", username)
|
||||||
tgBot.sendMessageToTelegram(text)
|
tgBot.sendMessageToTelegram(text)
|
||||||
}
|
}
|
||||||
@ -43,7 +49,7 @@ class EventHandler(
|
|||||||
fun onPlayerDied(event: PlayerDeathEvent) {
|
fun onPlayerDied(event: PlayerDeathEvent) {
|
||||||
if (!config.logDeath) return
|
if (!config.logDeath) return
|
||||||
event.deathMessage?.let {
|
event.deathMessage?.let {
|
||||||
val username = fullEscape(event.entity.displayName)
|
val username = event.entity.displayName.fullEscape()
|
||||||
val text = it.replace(username, "<i>$username</i>")
|
val text = it.replace(username, "<i>$username</i>")
|
||||||
tgBot.sendMessageToTelegram(text)
|
tgBot.sendMessageToTelegram(text)
|
||||||
}
|
}
|
||||||
|
@ -36,27 +36,27 @@ class Plugin : JavaPlugin() {
|
|||||||
|
|
||||||
override fun onDisable() {
|
override fun onDisable() {
|
||||||
if (!config.isEnabled) return
|
if (!config.isEnabled) return
|
||||||
config.serverStopMessage?.let { message ->
|
config.serverStopMessage?.let {
|
||||||
tgBot?.sendMessageToTelegram(message)
|
tgBot?.sendMessageToTelegram(it)
|
||||||
}
|
}
|
||||||
logger.info("Plugin stopped.")
|
logger.info("Plugin stopped.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendMessageToMinecraft(text: String, username: String? = null) {
|
fun sendMessageToMinecraft(text: String, username: String? = null) =
|
||||||
var prepared = config.telegramMessageFormat
|
config.telegramMessageFormat
|
||||||
.replace(C.MESSAGE_TEXT_PLACEHOLDER, escapeEmoji(text))
|
.replace(C.MESSAGE_TEXT_PLACEHOLDER, text.escapeEmoji())
|
||||||
username?.let {
|
.run {
|
||||||
prepared = prepared
|
username?.let { username ->
|
||||||
.replace(C.USERNAME_PLACEHOLDER, escapeEmoji(it))
|
replace(C.USERNAME_PLACEHOLDER, username.escapeEmoji())
|
||||||
}
|
} ?: this
|
||||||
server.broadcastMessage(prepared)
|
|
||||||
}
|
}
|
||||||
|
.also { server.broadcastMessage(it) }
|
||||||
|
|
||||||
fun reload() {
|
fun reload() {
|
||||||
logger.info(C.INFO.reloading)
|
logger.info(C.INFO.reloading)
|
||||||
config.reload(this)
|
config.reload(this)
|
||||||
tgBot?.stop()
|
tgBot?.stop()
|
||||||
tgBot?.start(this, config)
|
tgBot = TgBot(this, config)
|
||||||
logger.info(C.INFO.reloadComplete)
|
logger.info(C.INFO.reloadComplete)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,96 +1,127 @@
|
|||||||
package org.kraftwerk28.spigot_tg_bridge
|
package org.kraftwerk28.spigot_tg_bridge
|
||||||
|
|
||||||
import com.github.kotlintelegrambot.*
|
|
||||||
import com.github.kotlintelegrambot.dispatcher.command
|
|
||||||
import com.github.kotlintelegrambot.dispatcher.text
|
|
||||||
import com.github.kotlintelegrambot.entities.BotCommand
|
|
||||||
import com.github.kotlintelegrambot.entities.ParseMode
|
|
||||||
import com.github.kotlintelegrambot.entities.Update
|
|
||||||
import com.github.kotlintelegrambot.logging.LogLevel
|
|
||||||
import com.github.kotlintelegrambot.entities.ChatId
|
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
|
||||||
import org.kraftwerk28.spigot_tg_bridge.Constants as C
|
import org.kraftwerk28.spigot_tg_bridge.Constants as C
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import kotlinx.coroutines.channels.*
|
||||||
|
|
||||||
class TgBot(private val plugin: Plugin, private val config: Configuration) {
|
class TgBot(
|
||||||
|
private val plugin: Plugin,
|
||||||
private lateinit var bot: Bot
|
private val config: Configuration,
|
||||||
|
private val pollTimeout: Int = 30,
|
||||||
|
) {
|
||||||
|
private val api: TgApiService
|
||||||
|
val updateChan = Channel<TgApiService.Update>()
|
||||||
|
val scope = CoroutineScope(Dispatchers.Default)
|
||||||
|
val pollJob: Job
|
||||||
|
val handlerJob: Job
|
||||||
|
var currentOffset: Long = -1
|
||||||
|
var me: TgApiService.User
|
||||||
|
var commandRegex: Regex
|
||||||
|
val commandMap = config.commands.run {
|
||||||
|
mapOf(
|
||||||
|
online to ::onlineHandler,
|
||||||
|
time to ::timeHandler,
|
||||||
|
chatID to ::chatIdHandler,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
start(plugin, config)
|
api = TgApiService.create(config.botToken)
|
||||||
|
runBlocking {
|
||||||
|
me = api.getMe().result!!
|
||||||
|
// I don't put optional @username in regex since bot is
|
||||||
|
// only used in group chats
|
||||||
|
commandRegex = """^\/(\w+)(?:@${me.username})$""".toRegex()
|
||||||
|
|
||||||
|
|
||||||
|
val commands = config.commands.run { listOf(time, online, chatID) }
|
||||||
|
.zip(C.COMMAND_DESC.run {
|
||||||
|
listOf(timeDesc, onlineDesc, chatIDDesc)
|
||||||
|
})
|
||||||
|
.map { TgApiService.BotCommand(it.first!!, it.second) }
|
||||||
|
.let { TgApiService.SetMyCommands(it) }
|
||||||
|
|
||||||
|
api.setMyCommands(commands)
|
||||||
}
|
}
|
||||||
|
pollJob = scope.launch {
|
||||||
fun start(plugin: Plugin, config: Configuration) {
|
try {
|
||||||
val slashRegex = "^/+".toRegex()
|
while (true) {
|
||||||
val commands = config.commands
|
try {
|
||||||
|
pollUpdates()
|
||||||
skipUpdates()
|
} catch (e: Exception) {
|
||||||
bot = bot {
|
e.printStackTrace()
|
||||||
token = config.botToken
|
|
||||||
logLevel = LogLevel.None
|
|
||||||
|
|
||||||
val commandBindings = commands.let {
|
|
||||||
mapOf(
|
|
||||||
it.time to ::time,
|
|
||||||
it.online to ::online,
|
|
||||||
it.chatID to ::chatID
|
|
||||||
)
|
|
||||||
}.filterKeys { it != null }
|
|
||||||
|
|
||||||
dispatch {
|
|
||||||
commandBindings.forEach { (text, handler) ->
|
|
||||||
command(text!!.replace(slashRegex, "")) {
|
|
||||||
handler(update)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
text { onText(update) }
|
} catch (e: CancellationException) {}
|
||||||
|
}
|
||||||
|
handlerJob = scope.launch {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
handleUpdate()
|
||||||
|
}
|
||||||
|
} catch (e: CancellationException) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bot.setMyCommands(getBotCommands())
|
|
||||||
|
|
||||||
config.webhookConfig?.let { _ ->
|
suspend fun pollUpdates() {
|
||||||
plugin.logger.info("Running in webhook mode.")
|
val updatesResponse = api
|
||||||
} ?: run {
|
.getUpdates(offset = currentOffset, timeout = pollTimeout)
|
||||||
bot.startPolling()
|
updatesResponse.result?.let { updates ->
|
||||||
|
if (!updates.isEmpty()) {
|
||||||
|
updates.forEach { updateChan.send(it) }
|
||||||
|
currentOffset = updates.last().updateId + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun handleUpdate() {
|
||||||
|
val update = updateChan.receive()
|
||||||
|
update.message?.text?.let {
|
||||||
|
println("Text: $it")
|
||||||
|
commandRegex.matchEntire(it)?.groupValues?.let {
|
||||||
|
commandMap[it[1]]?.let { it(update) } ?: onTextHandler(update)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stop() {
|
fun stop() {
|
||||||
bot.stopPolling()
|
runBlocking {
|
||||||
|
pollJob.cancelAndJoin()
|
||||||
|
handlerJob.cancelAndJoin()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun time(update: Update) {
|
private suspend fun timeHandler(update: TgApiService.Update) {
|
||||||
val msg = update.message!!
|
val msg = update.message!!
|
||||||
if (!config.allowedChats.contains(msg.chat.id)) {
|
if (!config.allowedChats.contains(msg.chat.id)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (plugin.server.worlds.isEmpty()) {
|
if (plugin.server.worlds.isEmpty()) {
|
||||||
bot.sendMessage(
|
api.sendMessage(
|
||||||
ChatId.fromId(msg.chat.id),
|
msg.chat.id,
|
||||||
"No worlds available",
|
"No worlds available",
|
||||||
replyToMessageId = msg.messageId
|
replyToMessageId = msg.messageId
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val t = plugin.server.worlds.first().time
|
// TODO: handle multiple worlds
|
||||||
val text = when {
|
val time = plugin.server.worlds.first().time
|
||||||
t <= 12000 -> C.TIMES_OF_DAY.day
|
val text = C.TIMES_OF_DAY.run {
|
||||||
t <= 13800 -> C.TIMES_OF_DAY.sunset
|
when {
|
||||||
t <= 22200 -> C.TIMES_OF_DAY.night
|
time <= 12000 -> day
|
||||||
t <= 24000 -> C.TIMES_OF_DAY.sunrise
|
time <= 13800 -> sunset
|
||||||
|
time <= 22200 -> night
|
||||||
|
time <= 24000 -> sunrise
|
||||||
else -> ""
|
else -> ""
|
||||||
} + " ($t)"
|
}
|
||||||
|
} + " ($time)"
|
||||||
|
|
||||||
bot.sendMessage(
|
api.sendMessage(msg.chat.id, text, replyToMessageId = msg.messageId)
|
||||||
ChatId.fromId(msg.chat.id),
|
|
||||||
text,
|
|
||||||
replyToMessageId = msg.messageId,
|
|
||||||
parseMode = ParseMode.HTML
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun online(update: Update) {
|
private suspend fun onlineHandler(update: TgApiService.Update) {
|
||||||
val msg = update.message!!
|
val msg = update.message!!
|
||||||
if (!config.allowedChats.contains(msg.chat.id)) {
|
if (!config.allowedChats.contains(msg.chat.id)) {
|
||||||
return
|
return
|
||||||
@ -99,62 +130,40 @@ class TgBot(private val plugin: Plugin, private val config: Configuration) {
|
|||||||
val playerList = plugin.server.onlinePlayers
|
val playerList = plugin.server.onlinePlayers
|
||||||
val playerStr = plugin.server
|
val playerStr = plugin.server
|
||||||
.onlinePlayers
|
.onlinePlayers
|
||||||
.mapIndexed { i, s -> "${i + 1}. ${fullEscape(s.displayName)}" }
|
.mapIndexed { i, s -> "${i + 1}. ${s.displayName.fullEscape()}" }
|
||||||
.joinToString("\n")
|
.joinToString("\n")
|
||||||
val text =
|
val text =
|
||||||
if (playerList.isNotEmpty()) "${config.onlineString}:\n$playerStr"
|
if (playerList.isNotEmpty()) "${config.onlineString}:\n$playerStr"
|
||||||
else config.nobodyOnlineString
|
else config.nobodyOnlineString
|
||||||
bot.sendMessage(
|
api.sendMessage(msg.chat.id, text, replyToMessageId = msg.messageId)
|
||||||
ChatId.fromId(msg.chat.id),
|
|
||||||
text,
|
|
||||||
replyToMessageId = msg.messageId,
|
|
||||||
parseMode = ParseMode.HTML
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun chatID(update: Update) {
|
private suspend fun chatIdHandler(update: TgApiService.Update) {
|
||||||
val msg = update.message!!
|
val msg = update.message!!
|
||||||
val chatID = msg.chat.id
|
val chatId = msg.chat.id
|
||||||
val text = """
|
val text = """
|
||||||
Chat ID:
|
Chat ID:
|
||||||
<code>$chatID</code>
|
<code>${chatId}</code>
|
||||||
paste this id to <code>chats:</code> section in you config.yml file so it will look like this:
|
paste this id to <code>chats:</code> section in you config.yml file so it will look like this:
|
||||||
""".trimIndent() +
|
""".trimIndent() +
|
||||||
"\n\n<code>chats:\n # other ids...\n - ${chatID}</code>"
|
"\n\n<code>chats:\n # other ids...\n - ${chatId}</code>"
|
||||||
bot.sendMessage(
|
api.sendMessage(chatId, text, replyToMessageId = msg.messageId)
|
||||||
ChatId.fromId(chatID),
|
|
||||||
text,
|
|
||||||
parseMode = ParseMode.HTML,
|
|
||||||
replyToMessageId = msg.messageId
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendMessageToTelegram(text: String, username: String? = null) {
|
fun sendMessageToTelegram(text: String, username: String? = null) {
|
||||||
config.allowedChats.forEach { chatID ->
|
val messageText = username?.let { formatMsgFromMinecraft(it, text) } ?: text
|
||||||
username?.let {
|
config.allowedChats.forEach { chatId ->
|
||||||
bot.sendMessage(
|
scope.launch {
|
||||||
ChatId.fromId(chatID),
|
delay(1000)
|
||||||
formatMsgFromMinecraft(username, text),
|
api.sendMessage(chatId, messageText)
|
||||||
parseMode = ParseMode.HTML,
|
|
||||||
)
|
|
||||||
} ?: run {
|
|
||||||
bot.sendMessage(
|
|
||||||
ChatId.fromId(chatID),
|
|
||||||
text,
|
|
||||||
parseMode = ParseMode.HTML,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onText(update: Update) {
|
private suspend fun onTextHandler(update: TgApiService.Update) {
|
||||||
if (!config.logFromTGtoMC) return
|
if (!config.logFromTGtoMC) return
|
||||||
val msg = update.message!!
|
val msg = update.message!!
|
||||||
|
plugin.sendMessageToMinecraft(msg.text!!, msg.from!!.rawUserMention())
|
||||||
// Suppress commands to be sent to Minecraft
|
|
||||||
if (msg.text!!.startsWith("/")) return
|
|
||||||
|
|
||||||
plugin.sendMessageToMinecraft(msg.text!!, rawUserMention(msg.from!!))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun formatMsgFromMinecraft(
|
private fun formatMsgFromMinecraft(
|
||||||
@ -162,21 +171,6 @@ class TgBot(private val plugin: Plugin, private val config: Configuration) {
|
|||||||
text: String
|
text: String
|
||||||
): String =
|
): String =
|
||||||
config.minecraftMessageFormat
|
config.minecraftMessageFormat
|
||||||
.replace("%username%", fullEscape(username))
|
.replace("%username%", username.fullEscape())
|
||||||
.replace("%message%", escapeHTML(text))
|
.replace("%message%", text.escapeHtml())
|
||||||
|
|
||||||
private fun getBotCommands(): List<BotCommand> {
|
|
||||||
val cmdList = config.commands.run { listOfNotNull(time, online, chatID) }
|
|
||||||
val descList = C.COMMAND_DESC.run { listOf(timeDesc, onlineDesc, chatIDDesc) }
|
|
||||||
return cmdList.zip(descList).map { BotCommand(it.first, it.second) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun skipUpdates() {
|
|
||||||
// Creates a temporary bot w/ 0 timeout to skip updates
|
|
||||||
bot {
|
|
||||||
token = config.botToken
|
|
||||||
timeout = 0
|
|
||||||
logLevel = LogLevel.None
|
|
||||||
}.skipUpdates()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,35 +1,34 @@
|
|||||||
package org.kraftwerk28.spigot_tg_bridge
|
package org.kraftwerk28.spigot_tg_bridge
|
||||||
|
|
||||||
import com.github.kotlintelegrambot.Bot
|
|
||||||
import com.github.kotlintelegrambot.entities.Update
|
|
||||||
import com.github.kotlintelegrambot.entities.User
|
|
||||||
import com.vdurmont.emoji.EmojiParser
|
import com.vdurmont.emoji.EmojiParser
|
||||||
|
|
||||||
fun Bot.skipUpdates(lastUpdateID: Long = 0) {
|
// fun Bot.skipUpdates(lastUpdateID: Long = 0) {
|
||||||
val newUpdates = getUpdates(lastUpdateID)
|
// val newUpdates = getUpdates(lastUpdateID)
|
||||||
|
|
||||||
if (newUpdates.isNotEmpty()) {
|
// if (newUpdates.isNotEmpty()) {
|
||||||
val lastUpd = newUpdates.last()
|
// val lastUpd = newUpdates.last()
|
||||||
if (lastUpd !is Update) return
|
// if (lastUpd !is Update) return
|
||||||
return skipUpdates(lastUpd.updateId + 1)
|
// return skipUpdates(lastUpd.updateId + 1)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
fun String.escapeHtml() =
|
fun String.escapeHtml() = this
|
||||||
this.replace("&", "&").replace(">", ">").replace("<", "<")
|
|
||||||
|
|
||||||
fun escapeHTML(s: String) = s
|
|
||||||
.replace("&", "&")
|
.replace("&", "&")
|
||||||
.replace(">", ">")
|
.replace(">", ">")
|
||||||
.replace("<", "<")
|
.replace("<", "<")
|
||||||
|
|
||||||
fun escapeColorCodes(s: String) = s.replace("\u00A7.".toRegex(), "")
|
fun String.escapeHTML() = this
|
||||||
|
.replace("&", "&")
|
||||||
|
.replace(">", ">")
|
||||||
|
.replace("<", "<")
|
||||||
|
|
||||||
fun fullEscape(s: String) = escapeColorCodes(escapeHTML(s))
|
fun String.escapeColorCodes() = replace("\u00A7.".toRegex(), "")
|
||||||
|
|
||||||
fun escapeEmoji(text: String) = EmojiParser.parseToAliases(text)
|
fun String.fullEscape() = escapeHTML().escapeColorCodes()
|
||||||
|
|
||||||
fun rawUserMention(user: User): String =
|
fun String.escapeEmoji() = EmojiParser.parseToAliases(this)
|
||||||
(if (user.firstName.length < 2) null else user.firstName)
|
|
||||||
?: user.username
|
fun TgApiService.User.rawUserMention(): String =
|
||||||
?: user.lastName!!
|
(if (firstName.length < 2) null else firstName)
|
||||||
|
?: username
|
||||||
|
?: lastName!!
|
||||||
|
Loading…
Reference in New Issue
Block a user