mirror of
https://github.com/amalthea-mc/spigot-tg-bridge.git
synced 2024-11-08 19:51:04 +00:00
feature: release 0.0.8
This commit is contained in:
parent
7ba216f98c
commit
6cffdf4b33
@ -47,11 +47,10 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
||||
testImplementation group: 'junit', name: 'junit', version: '4.12'
|
||||
compileOnly "org.spigotmc:spigot-api:1.15.2-R0.1-SNAPSHOT"
|
||||
implementation group: 'org.telegram', name: 'telegrambots', version: '4.6'
|
||||
implementation 'com.vdurmont:emoji-java:5.1.1'
|
||||
|
||||
// def tgBotVer = '5.0.0'
|
||||
// implementation "io.github.kotlin-telegram-bot.kotlin-telegram-bot:telegram:$tgBotVer"
|
||||
def tgBotVer = '5.0.0'
|
||||
implementation "io.github.kotlin-telegram-bot.kotlin-telegram-bot:telegram:$tgBotVer"
|
||||
}
|
||||
|
||||
compileKotlin {
|
||||
|
@ -1,125 +0,0 @@
|
||||
package org.kraftwerk28.spigot_tg_bridge
|
||||
|
||||
import org.telegram.telegrambots.bots.TelegramLongPollingBot
|
||||
import org.telegram.telegrambots.meta.api.methods.ParseMode
|
||||
import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatAdministrators
|
||||
import org.telegram.telegrambots.meta.api.methods.send.SendMessage
|
||||
import org.telegram.telegrambots.meta.api.objects.Message
|
||||
import org.telegram.telegrambots.meta.api.objects.Update
|
||||
import org.telegram.telegrambots.meta.api.objects.User
|
||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiException
|
||||
import org.kraftwerk28.spigot_tg_bridge.Constants as C
|
||||
|
||||
class Bot(private var plugin: Plugin) : TelegramLongPollingBot() {
|
||||
private val allowedChats: List<Long>
|
||||
private val chatToMC: Boolean
|
||||
private val botToken: String
|
||||
private val botUsername: String
|
||||
private val cmd = Commands(plugin)
|
||||
|
||||
init {
|
||||
plugin.config.run {
|
||||
allowedChats = getLongList(C.FIELDS.ALLOWED_CHATS)
|
||||
chatToMC = getBoolean(C.FIELDS.LOG_FROM_TG_TO_MC, C.DEFS.logFromTGtoMC)
|
||||
botToken = getString(C.FIELDS.BOT_TOKEN) ?: throw Exception(C.WARN.noToken)
|
||||
botUsername = getString(C.FIELDS.BOT_USERNAME) ?: throw Exception(C.WARN.noUsername)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getBotToken() = botToken
|
||||
override fun getBotUsername() = botUsername
|
||||
|
||||
override fun onUpdateReceived(update: Update?) {
|
||||
val msg = update?.message
|
||||
plugin.logger.info("Chat id: ${msg?.chatId}, Message id: ${msg?.messageId}.")
|
||||
if (msg == null || msg.text == null) return
|
||||
if (!allowedChats.contains(msg.chatId)) return
|
||||
|
||||
// cmd shows online players
|
||||
if (msg.text.startsWith(cmd.online)) {
|
||||
val playerList = plugin.server.onlinePlayers
|
||||
val playerStr = plugin.server
|
||||
.onlinePlayers
|
||||
.mapIndexed { i, s -> "${i + 1}. ${s.displayName}" }
|
||||
.joinToString("\n")
|
||||
val onlineStr = plugin.config.getString(
|
||||
C.FIELDS.STRINGS.ONLINE,
|
||||
C.DEFS.playersOnline
|
||||
)!!
|
||||
val offlineStr = plugin.config.getString(
|
||||
C.FIELDS.STRINGS.OFFLINE,
|
||||
C.DEFS.nobodyOnline
|
||||
)!!
|
||||
val text =
|
||||
if (playerList.isNotEmpty()) "$onlineStr:\n$playerStr"
|
||||
else offlineStr
|
||||
reply(msg, text) { it.replyToMessageId = msg.messageId }
|
||||
}
|
||||
if (msg.text.startsWith(cmd.time)) {
|
||||
val t = plugin.server.worlds[0].time
|
||||
var text = when {
|
||||
t <= 12000 -> "\uD83C\uDFDE Day"
|
||||
t <= 13800 -> "\uD83C\uDF06 Sunset"
|
||||
t <= 22200 -> "\uD83C\uDF03 Night"
|
||||
t <= 24000 -> "\uD83C\uDF05 Sunrise"
|
||||
else -> ""
|
||||
}
|
||||
text += " ($t)"
|
||||
reply(msg, text) { it.replyToMessageId = msg.messageId }
|
||||
}
|
||||
|
||||
// stop, if no command matched:
|
||||
if (msg.text!!.startsWith("/")) return
|
||||
|
||||
if (chatToMC)
|
||||
plugin.sendMessageToMCFrom(rawUserMention(msg.from), msg.text)
|
||||
}
|
||||
|
||||
fun sendMessageToTGFrom(username: String, text: String) {
|
||||
allowedChats.forEach {
|
||||
try {
|
||||
val msg = SendMessage(it, mcMessageStr(username, text))
|
||||
.setParseMode(ParseMode.HTML)
|
||||
execute(msg)
|
||||
} catch (e: TelegramApiException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun broadcastToTG(text: String) {
|
||||
allowedChats.forEach { chatID ->
|
||||
try {
|
||||
val msg = SendMessage(chatID, text).setParseMode(ParseMode.HTML)
|
||||
execute(msg)
|
||||
} catch (e: TelegramApiException) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun reply(
|
||||
msg: Message,
|
||||
text: String,
|
||||
prep: ((sender: SendMessage) -> Unit)? = null
|
||||
): Message {
|
||||
val snd = SendMessage(msg.chatId, text).setParseMode(ParseMode.HTML)
|
||||
if (prep != null) prep(snd)
|
||||
return execute(snd)
|
||||
}
|
||||
|
||||
private fun checkAdmin(msg: Message): Boolean {
|
||||
val admins = execute(GetChatAdministrators().setChatId(msg.chatId))
|
||||
return admins.any { it.user.id == msg.from.id }
|
||||
}
|
||||
|
||||
private fun mcMessageStr(username: String, text: String): String =
|
||||
"<b>$username</b>: $text"
|
||||
|
||||
private fun rawUserMention(user: User): String =
|
||||
(if (user.firstName.length < 2) null else user.firstName)
|
||||
?: user.userName
|
||||
?: user.lastName
|
||||
|
||||
private fun telegramUserMention(user: User): String =
|
||||
if (user.userName != null) "@${user.userName}"
|
||||
else "<a href=\"tg://user?id=${user.id}\">${user.firstName ?: user.lastName}</a>"
|
||||
}
|
@ -1,48 +1,48 @@
|
||||
package org.kraftwerk28.spigot_tg_bridge
|
||||
|
||||
object Constants {
|
||||
val configFilename = "config.yml"
|
||||
const val configFilename = "config.yml"
|
||||
// Config field names
|
||||
object FIELDS {
|
||||
val BOT_TOKEN = "botToken"
|
||||
val BOT_USERNAME = "botUsername"
|
||||
val ALLOWED_CHATS = "chats"
|
||||
val LOG_FROM_MC_TO_TG = "logFromMCtoTG"
|
||||
val LOG_FROM_TG_TO_MC = "logFromTGtoMC"
|
||||
val SERVER_START_MSG = "serverStartMessage"
|
||||
val SERVER_STOP_MSG = "serverStopMessage"
|
||||
val LOG_JOIN_LEAVE = "logJoinLeave"
|
||||
val LOG_PLAYER_DEATH = "logPlayerDeath"
|
||||
val LOG_PLAYER_ASLEEP = "logPlayerAsleep"
|
||||
const val BOT_TOKEN = "botToken"
|
||||
const val BOT_USERNAME = "botUsername"
|
||||
const val ALLOWED_CHATS = "chats"
|
||||
const val LOG_FROM_MC_TO_TG = "logFromMCtoTG"
|
||||
const val LOG_FROM_TG_TO_MC = "logFromTGtoMC"
|
||||
const val SERVER_START_MSG = "serverStartMessage"
|
||||
const val SERVER_STOP_MSG = "serverStopMessage"
|
||||
const val LOG_JOIN_LEAVE = "logJoinLeave"
|
||||
const val LOG_PLAYER_DEATH = "logPlayerDeath"
|
||||
const val LOG_PLAYER_ASLEEP = "logPlayerAsleep"
|
||||
object STRINGS {
|
||||
val ONLINE = "strings.online"
|
||||
val OFFLINE = "strings.offline"
|
||||
val JOINED = "strings.joined"
|
||||
val LEFT = "strings.left"
|
||||
const val ONLINE = "strings.online"
|
||||
const val OFFLINE = "strings.offline"
|
||||
const val JOINED = "strings.joined"
|
||||
const val LEFT = "strings.left"
|
||||
}
|
||||
object COMMANDS {
|
||||
val TIME = "commands.time"
|
||||
val ONLINE = "commands.online"
|
||||
const val TIME = "commands.time"
|
||||
const val ONLINE = "commands.online"
|
||||
}
|
||||
}
|
||||
object DEFS {
|
||||
val logFromMCtoTG = false
|
||||
val logFromTGtoMC = false
|
||||
val logJoinLeave = false
|
||||
val logPlayerDeath = false
|
||||
val logPlayerAsleep = false
|
||||
const val logFromMCtoTG = false
|
||||
const val logFromTGtoMC = false
|
||||
const val logJoinLeave = false
|
||||
const val logPlayerDeath = false
|
||||
const val logPlayerAsleep = false
|
||||
object COMMANDS {
|
||||
val TIME = "/time"
|
||||
val ONLINE = "/online"
|
||||
const val TIME = "time"
|
||||
const val ONLINE = "online"
|
||||
}
|
||||
val playersOnline = "Online"
|
||||
val nobodyOnline = "Nobody online"
|
||||
val playerJoined = "joined"
|
||||
val playerLeft = "left"
|
||||
const val playersOnline = "Online"
|
||||
const val nobodyOnline = "Nobody online"
|
||||
const val playerJoined = "joined"
|
||||
const val playerLeft = "left"
|
||||
}
|
||||
object WARN {
|
||||
val noConfigWarning = "No config file found! Writing default config to config.yml."
|
||||
val noToken = "Bot token must be defined."
|
||||
val noUsername = "Bot username must be defined."
|
||||
const val noConfigWarning = "No config file found! Writing default config to config.yml."
|
||||
const val noToken = "Bot token must be defined."
|
||||
const val noUsername = "Bot username must be defined."
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ class EventHandler(private val plugin: Plugin) : Listener {
|
||||
@EventHandler
|
||||
fun onPlayerChat(event: AsyncPlayerChatEvent) {
|
||||
if (plugin.chatToTG) {
|
||||
plugin.tgBot?.sendMessageToTGFrom(
|
||||
escapeHTML(event.player.displayName), event.message
|
||||
plugin.tgBot.sendMessageToTGFrom(
|
||||
event.player.displayName, event.message
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -40,15 +40,15 @@ class EventHandler(private val plugin: Plugin) : Listener {
|
||||
@EventHandler
|
||||
fun onPlayerJoin(event: PlayerJoinEvent) {
|
||||
if (!logJoinLeave) return
|
||||
val text = "<b>${escapeHTML(event.player.displayName)}</b> $joinStr."
|
||||
plugin.tgBot?.broadcastToTG(text)
|
||||
val text = "<b>${TgBot.escapeHTML(event.player.displayName)}</b> $joinStr."
|
||||
plugin.tgBot.broadcastToTG(text)
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onPlayerLeave(event: PlayerQuitEvent) {
|
||||
if (!logJoinLeave) return
|
||||
val text = "<b>${escapeHTML(event.player.displayName)}</b> $leftStr."
|
||||
plugin.tgBot?.broadcastToTG(text)
|
||||
val text = "<b>${TgBot.escapeHTML(event.player.displayName)}</b> $leftStr."
|
||||
plugin.tgBot.broadcastToTG(text)
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@ -57,7 +57,7 @@ class EventHandler(private val plugin: Plugin) : Listener {
|
||||
event.deathMessage?.let {
|
||||
val plName = event.entity.displayName
|
||||
val text = it.replace(plName, "<b>$plName</b>")
|
||||
plugin.tgBot?.broadcastToTG(text)
|
||||
plugin.tgBot.broadcastToTG(text)
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,6 +66,6 @@ class EventHandler(private val plugin: Plugin) : Listener {
|
||||
if (!logPlayerAsleep) return
|
||||
if (event.bedEnterResult != PlayerBedEnterEvent.BedEnterResult.OK) return
|
||||
val text = "<b>${event.player.displayName}</b> fell asleep."
|
||||
plugin.tgBot?.broadcastToTG(text)
|
||||
plugin.tgBot.broadcastToTG(text)
|
||||
}
|
||||
}
|
@ -2,14 +2,12 @@ package org.kraftwerk28.spigot_tg_bridge
|
||||
|
||||
import com.vdurmont.emoji.EmojiParser
|
||||
import org.bukkit.plugin.java.JavaPlugin
|
||||
import org.telegram.telegrambots.ApiContextInitializer
|
||||
import org.telegram.telegrambots.meta.TelegramBotsApi
|
||||
import java.io.File
|
||||
import org.kraftwerk28.spigot_tg_bridge.Constants as C
|
||||
|
||||
class Plugin : JavaPlugin() {
|
||||
|
||||
var tgBot: Bot? = null
|
||||
lateinit var tgBot: TgBot
|
||||
var chatToTG: Boolean = false
|
||||
|
||||
init {
|
||||
@ -32,26 +30,19 @@ class Plugin : JavaPlugin() {
|
||||
return
|
||||
}
|
||||
|
||||
ApiContextInitializer.init()
|
||||
val botsApi = TelegramBotsApi()
|
||||
tgBot = Bot(this)
|
||||
|
||||
botsApi.registerBot(tgBot)
|
||||
|
||||
tgBot = TgBot(this)
|
||||
server.pluginManager.registerEvents(EventHandler(this), this)
|
||||
|
||||
// Notify everything about server start
|
||||
config.getString(C.FIELDS.SERVER_START_MSG, null)?.let {
|
||||
logger.info("Server start message: $it")
|
||||
tgBot?.broadcastToTG(it)
|
||||
tgBot.broadcastToTG(it)
|
||||
}
|
||||
logger.info("Plugin started.")
|
||||
}
|
||||
|
||||
override fun onDisable() {
|
||||
config.getString(C.FIELDS.SERVER_STOP_MSG, null)?.let {
|
||||
logger.info("Server stop message: $it")
|
||||
tgBot?.broadcastToTG(it)
|
||||
tgBot.broadcastToTG(it)
|
||||
}
|
||||
logger.info("Plugin stopped.")
|
||||
}
|
||||
@ -62,10 +53,10 @@ class Plugin : JavaPlugin() {
|
||||
}
|
||||
|
||||
fun sendMessageToMCFrom(username: String, text: String) {
|
||||
val text = run {
|
||||
val text = "<${escapeHTML(username)}> $text"
|
||||
EmojiParser.parseToAliases(text)
|
||||
}
|
||||
server.broadcastMessage(text)
|
||||
server.broadcastMessage(
|
||||
EmojiParser.parseToAliases(
|
||||
"<${TgBot.escapeHTML(username)}> $text"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
120
src/main/kotlin/org/kraftwerk28/spigot_tg_bridge/TgBot.kt
Normal file
120
src/main/kotlin/org/kraftwerk28/spigot_tg_bridge/TgBot.kt
Normal file
@ -0,0 +1,120 @@
|
||||
package org.kraftwerk28.spigot_tg_bridge
|
||||
|
||||
import com.github.kotlintelegrambot.Bot
|
||||
import com.github.kotlintelegrambot.bot
|
||||
import com.github.kotlintelegrambot.dispatch
|
||||
import com.github.kotlintelegrambot.dispatcher.command
|
||||
import com.github.kotlintelegrambot.dispatcher.text
|
||||
import com.github.kotlintelegrambot.entities.ParseMode
|
||||
import com.github.kotlintelegrambot.entities.Update
|
||||
import com.github.kotlintelegrambot.entities.User
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
|
||||
class TgBot(val plugin: Plugin) {
|
||||
|
||||
private val commands = Commands(plugin)
|
||||
private val bot: Bot
|
||||
private val allowedChats: List<Long>
|
||||
private val chatToMC: Boolean
|
||||
private val botToken: String
|
||||
private val botUsername: String
|
||||
|
||||
init {
|
||||
plugin.config.run {
|
||||
allowedChats = getLongList(Constants.FIELDS.ALLOWED_CHATS)
|
||||
chatToMC = getBoolean(Constants.FIELDS.LOG_FROM_TG_TO_MC, Constants.DEFS.logFromTGtoMC)
|
||||
botToken = getString(Constants.FIELDS.BOT_TOKEN) ?: throw Exception(Constants.WARN.noToken)
|
||||
botUsername = getString(Constants.FIELDS.BOT_USERNAME) ?: throw Exception(Constants.WARN.noUsername)
|
||||
}
|
||||
val slashRegex = "^/+".toRegex()
|
||||
|
||||
bot = bot {
|
||||
token = botToken
|
||||
logLevel = HttpLoggingInterceptor.Level.NONE
|
||||
dispatch {
|
||||
text(null, ::onText)
|
||||
command(commands.time.replace(slashRegex, ""), ::time)
|
||||
command(commands.online.replace(slashRegex, ""), ::online)
|
||||
}
|
||||
}
|
||||
bot.startPolling()
|
||||
}
|
||||
|
||||
private fun time(bot: Bot, update: Update) {
|
||||
val t = plugin.server.worlds[0].time
|
||||
var text = when {
|
||||
t <= 12000 -> "\uD83C\uDFDE Day"
|
||||
t <= 13800 -> "\uD83C\uDF06 Sunset"
|
||||
t <= 22200 -> "\uD83C\uDF03 Night"
|
||||
t <= 24000 -> "\uD83C\uDF05 Sunrise"
|
||||
else -> ""
|
||||
}
|
||||
text += " ($t)"
|
||||
val msg = update.message!!
|
||||
bot.sendMessage(
|
||||
msg.chat.id, text,
|
||||
replyToMessageId = msg.messageId,
|
||||
parseMode = ParseMode.HTML
|
||||
)
|
||||
}
|
||||
|
||||
private fun online(bot: Bot, update: Update) {
|
||||
val playerList = plugin.server.onlinePlayers
|
||||
val playerStr = plugin.server
|
||||
.onlinePlayers
|
||||
.mapIndexed { i, s -> "${i + 1}. ${s.displayName}" }
|
||||
.joinToString("\n")
|
||||
val onlineStr = plugin.config.getString(
|
||||
Constants.FIELDS.STRINGS.ONLINE,
|
||||
Constants.DEFS.playersOnline
|
||||
)!!
|
||||
val offlineStr = plugin.config.getString(
|
||||
Constants.FIELDS.STRINGS.OFFLINE,
|
||||
Constants.DEFS.nobodyOnline
|
||||
)!!
|
||||
val text =
|
||||
if (playerList.isNotEmpty()) "$onlineStr:\n$playerStr"
|
||||
else offlineStr
|
||||
val msg = update.message!!
|
||||
bot.sendMessage(
|
||||
msg.chat.id, text,
|
||||
replyToMessageId = msg.messageId,
|
||||
parseMode = ParseMode.HTML
|
||||
)
|
||||
}
|
||||
|
||||
fun broadcastToTG(text: String) {
|
||||
allowedChats.forEach { chatID ->
|
||||
bot.sendMessage(chatID, text, parseMode = ParseMode.HTML)
|
||||
}
|
||||
}
|
||||
|
||||
fun sendMessageToTGFrom(username: String, text: String) {
|
||||
allowedChats.forEach { chatID ->
|
||||
bot.sendMessage(
|
||||
chatID,
|
||||
mcMessageStr(username, text),
|
||||
parseMode = ParseMode.HTML
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onText(bot: Bot, update: Update) {
|
||||
if (!chatToMC) return
|
||||
val msg = update.message!!
|
||||
plugin.sendMessageToMCFrom(rawUserMention(msg.from!!), msg.text!!)
|
||||
}
|
||||
|
||||
private fun mcMessageStr(username: String, text: String): String =
|
||||
"<b>${escapeHTML(username)}</b>: $text"
|
||||
|
||||
private fun rawUserMention(user: User): String =
|
||||
(if (user.firstName.length < 2) null else user.firstName)
|
||||
?: user.username
|
||||
?: user.lastName!!
|
||||
|
||||
companion object {
|
||||
fun escapeHTML(s: String): String =
|
||||
s.replace("&", "&").replace(">", ">").replace("<", "<")
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package org.kraftwerk28.spigot_tg_bridge
|
||||
|
||||
import org.telegram.telegrambots.meta.api.objects.User
|
||||
|
||||
fun escapeHTML(s: String): String =
|
||||
s.replace("&", "&").replace(">", ">").replace("<", "<")
|
||||
|
@ -15,5 +15,5 @@ strings:
|
||||
joined: 'joined'
|
||||
left: 'left'
|
||||
commands:
|
||||
time: '/time'
|
||||
online: '/online'
|
||||
time: 'time'
|
||||
online: 'online'
|
@ -1,5 +1,5 @@
|
||||
name: SpigotTGBridge
|
||||
version: 0.0.7
|
||||
version: 0.0.8
|
||||
api-version: '1.15'
|
||||
main: org.kraftwerk28.spigot_tg_bridge.Plugin
|
||||
description: Telegram <-> Minecraft communication plugin for Spigot.
|
||||
|
Loading…
Reference in New Issue
Block a user