feature: release 0.0.6

Changelog:
  - Custom commands
This commit is contained in:
kraftwerk28 2020-07-11 16:15:26 +03:00
parent a3207e0b22
commit d6dd9cb4a1
13 changed files with 141 additions and 54 deletions

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="CompilerConfiguration"> <component name="CompilerConfiguration">
<bytecodeTargetLevel target="1.8" /> <bytecodeTargetLevel target="14" />
</component> </component>
</project> </project>

View File

@ -8,8 +8,6 @@
<option name="testRunner" value="GRADLE" /> <option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" /> <option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="/usr/share/java/gradle" />
<option name="gradleJvm" value="13" />
<option name="modules"> <option name="modules">
<set> <set>
<option value="$PROJECT_DIR$" /> <option value="$PROJECT_DIR$" />

View File

@ -26,5 +26,10 @@
<option name="name" value="maven" /> <option name="name" value="maven" />
<option name="url" value="https://oss.sonatype.org/content/repositories/snapshots/" /> <option name="url" value="https://oss.sonatype.org/content/repositories/snapshots/" />
</remote-repository> </remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="https://jitpack.io" />
</remote-repository>
</component> </component>
</project> </project>

View File

@ -12,7 +12,7 @@
<component name="JavaScriptSettings"> <component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" /> <option name="languageLevel" value="ES6" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_13" default="false" project-jdk-name="14" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_14" default="true" project-jdk-name="14" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>

View File

@ -7,16 +7,16 @@ plugins {
group 'org.kraftwerk28' group 'org.kraftwerk28'
version '0.0.4-SNAPSHOT' version '0.0.4-SNAPSHOT'
def defaultOutDir = "$System.env.HOME/MinecraftServers/spigot_1.15.2/plugins/" //def defaultOutDir = "$System.env.HOME/MinecraftServers/spigot_1.15.2/plugins/"
rootProject.libsDirName = System.getenv("OUT_DIR") ?: defaultOutDir //rootProject.libsDirName = System.getenv("OUT_DIR") ?: defaultOutDir
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories { repositories {
maven { maven {
url "https://hub.spigotmc.org/nexus/content/repositories/snapshots" url "https://hub.spigotmc.org/nexus/content/repositories/snapshots"
} }
maven {
url "https://jitpack.io"
}
maven { maven {
url "https://oss.sonatype.org/content/repositories/snapshots/" url "https://oss.sonatype.org/content/repositories/snapshots/"
} }
@ -25,11 +25,13 @@ repositories {
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
testCompile group: 'junit', name: 'junit', version: '4.12' testImplementation group: 'junit', name: 'junit', version: '4.12'
compileOnly "org.spigotmc:spigot-api:1.15.2-R0.1-SNAPSHOT" compileOnly "org.spigotmc:spigot-api:1.15.2-R0.1-SNAPSHOT"
compile group: 'org.telegram', name: 'telegrambots', version: '4.6' implementation group: 'org.telegram', name: 'telegrambots', version: '4.6'
compile group: 'org.yaml', name: 'snakeyaml', version: '1.25' implementation 'com.vdurmont:emoji-java:5.1.1'
compile 'com.vdurmont:emoji-java:5.1.1'
def tgBotVer = '5.0.0'
implementation "io.github.kotlin-telegram-bot.kotlin-telegram-bot:telegram:$tgBotVer"
} }
compileKotlin { compileKotlin {

View File

@ -8,53 +8,54 @@ import org.telegram.telegrambots.meta.api.objects.Message
import org.telegram.telegrambots.meta.api.objects.Update import org.telegram.telegrambots.meta.api.objects.Update
import org.telegram.telegrambots.meta.api.objects.User import org.telegram.telegrambots.meta.api.objects.User
import org.telegram.telegrambots.meta.exceptions.TelegramApiException import org.telegram.telegrambots.meta.exceptions.TelegramApiException
import org.kraftwerk28.spigot_tg_bridge.Constants as C
class Bot(private var plugin: Plugin) : TelegramLongPollingBot() { class Bot(private var plugin: Plugin) : TelegramLongPollingBot() {
private val allowedChats: List<Long> private val allowedChats: List<Long>
private val chatToMC: Boolean private val chatToMC: Boolean
private val botToken: String private val botToken: String
private val botUsername: String private val botUsername: String
private val cmd = Commands(plugin)
init { init {
plugin.config.run { plugin.config.run {
allowedChats = getLongList("chats") allowedChats = getLongList(C.FIELDS.ALLOWED_CHATS)
chatToMC = getBoolean("logFromTGtoMC", false) chatToMC = getBoolean(C.FIELDS.LOG_FROM_TG_TO_MC, C.DEFS.logFromTGtoMC)
botToken = getString("botToken") ?: throw Exception("Bot token must be defined.") botToken = getString(C.FIELDS.BOT_TOKEN) ?: throw Exception(C.WARN.noToken)
botUsername = getString("botUsername") ?: throw Exception("Bot username must be defined.") botUsername = getString(C.FIELDS.BOT_USERNAME) ?: throw Exception(C.WARN.noUsername)
} }
} }
override fun getBotToken() = botToken override fun getBotToken() = botToken
override fun getBotUsername() = botUsername override fun getBotUsername() = botUsername
override fun onUpdateReceived(update: Update?) { override fun onUpdateReceived(update: Update?) {
val msg = update?.message val msg = update?.message
plugin.logger.info("chat id: ${msg?.chatId}, message id: ${msg?.messageId}") plugin.logger.info("Chat id: ${msg?.chatId}, Message id: ${msg?.messageId}.")
if (msg == null || msg.text == null) return if (msg == null || msg.text == null) return
if (!allowedChats.contains(msg.chatId)) return if (!allowedChats.contains(msg.chatId)) return
// cmd shows online players // cmd shows online players
if (msg.text.startsWith("/online")) { if (msg.text.startsWith(cmd.online)) {
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}. ${s.displayName}" } .mapIndexed { i, s -> "${i + 1}. ${s.displayName}" }
.joinToString("\n") .joinToString("\n")
val onlineStr = plugin.config.getString( val onlineStr = plugin.config.getString(
"strings.online", C.FIELDS.STRINGS.ONLINE,
"Online" C.DEFS.playersOnline
)!! )!!
val offlineStr = plugin.config.getString( val offlineStr = plugin.config.getString(
"strings.nobodyOnline", C.FIELDS.STRINGS.OFFLINE,
"Nobody online" C.DEFS.nobodyOnline
)!! )!!
val text = val text =
if (playerList.isNotEmpty()) "$onlineStr:\n$playerStr" if (playerList.isNotEmpty()) "$onlineStr:\n$playerStr"
else offlineStr else offlineStr
reply(msg, text) { it.replyToMessageId = msg.messageId } reply(msg, text) { it.replyToMessageId = msg.messageId }
} }
if (msg.text.startsWith("/time")) { if (msg.text.startsWith(cmd.time)) {
val t = plugin.server.worlds[0].time val t = plugin.server.worlds[0].time
var text = when { var text = when {
t <= 12000 -> "\uD83C\uDFDE Day" t <= 12000 -> "\uD83C\uDFDE Day"
@ -66,6 +67,7 @@ class Bot(private var plugin: Plugin) : TelegramLongPollingBot() {
text += " ($t)" text += " ($t)"
reply(msg, text) { it.replyToMessageId = msg.messageId } reply(msg, text) { it.replyToMessageId = msg.messageId }
} }
// stop, if no command matched: // stop, if no command matched:
if (msg.text!!.startsWith("/")) return if (msg.text!!.startsWith("/")) return
@ -110,14 +112,10 @@ class Bot(private var plugin: Plugin) : TelegramLongPollingBot() {
} }
private fun mcMessageStr(username: String, text: String): String = private fun mcMessageStr(username: String, text: String): String =
"<i>$username</i>: $text" "<b>$username</b>: $text"
private fun rawUserMention(user: User): String = private fun rawUserMention(user: User): String =
(if (user.firstName.length < 2) null else user.firstName) (if (user.firstName.length < 2) null else user.firstName)
?: user.userName ?: user.userName
?: user.lastName ?: 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>"
} }

View File

@ -0,0 +1,20 @@
package org.kraftwerk28.spigot_tg_bridge
import org.kraftwerk28.spigot_tg_bridge.Constants as C
class Commands(plugin: Plugin) {
val time: String
val online: String
init {
plugin.config.run {
time = getString(
C.FIELDS.COMMANDS.TIME,
C.DEFS.COMMANDS.TIME
)!!
online = getString(
C.FIELDS.COMMANDS.ONLINE,
C.DEFS.COMMANDS.ONLINE
)!!
}
}
}

View File

@ -0,0 +1,44 @@
package org.kraftwerk28.spigot_tg_bridge
object Constants {
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"
object STRINGS {
val ONLINE = "strings.online"
val OFFLINE = "strings.offline"
val JOINED = "strings.joined"
val LEFT = "strings.left"
}
object COMMANDS {
val TIME = "commands.time"
val ONLINE = "commands.online"
}
}
object DEFS {
val logFromMCtoTG = false
val logFromTGtoMC = false
val logJoinLeave = false
object COMMANDS {
val TIME = "/time"
val ONLINE = "/online"
}
val playersOnline = "Online"
val nobodyOnline = "Nobody online"
val playerJoined = "joined"
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."
}
}

View File

@ -5,6 +5,7 @@ import org.bukkit.event.Listener
import org.bukkit.event.player.AsyncPlayerChatEvent import org.bukkit.event.player.AsyncPlayerChatEvent
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 org.kraftwerk28.spigot_tg_bridge.Constants as C
class EventHandler(private val plugin: Plugin) : Listener { class EventHandler(private val plugin: Plugin) : Listener {
@ -14,9 +15,9 @@ class EventHandler(private val plugin: Plugin) : Listener {
init { init {
plugin.config.run { plugin.config.run {
joinStr = getString("strings.joined", "joined")!! joinStr = getString(C.FIELDS.STRINGS.JOINED, C.DEFS.playerJoined)!!
leftStr = getString("strings.left", "left")!! leftStr = getString(C.FIELDS.STRINGS.LEFT, C.DEFS.playerLeft)!!
logJoinLeave = getBoolean("logJoinLeave", false) logJoinLeave = getBoolean(C.FIELDS.LOG_JOIN_LEAVE, C.DEFS.logJoinLeave)
} }
} }
@ -24,7 +25,7 @@ class EventHandler(private val plugin: Plugin) : Listener {
fun onPlayerChat(event: AsyncPlayerChatEvent) { fun onPlayerChat(event: AsyncPlayerChatEvent) {
if (plugin.chatToTG) { if (plugin.chatToTG) {
plugin.tgBot?.sendMessageToTGFrom( plugin.tgBot?.sendMessageToTGFrom(
event.player.displayName, event.message escapeHTML(event.player.displayName), event.message
) )
} }
} }
@ -32,16 +33,14 @@ class EventHandler(private val plugin: Plugin) : Listener {
@EventHandler @EventHandler
fun onPlayerJoin(event: PlayerJoinEvent) { fun onPlayerJoin(event: PlayerJoinEvent) {
if (!logJoinLeave) return if (!logJoinLeave) return
plugin.tgBot?.broadcastToTG( val text = "<b>${escapeHTML(event.player.displayName)}</b> $joinStr."
"<b>${event.player.displayName}</b> $joinStr." plugin.tgBot?.broadcastToTG(text)
)
} }
@EventHandler @EventHandler
fun onPlayerLeave(event: PlayerQuitEvent) { fun onPlayerLeave(event: PlayerQuitEvent) {
if (!logJoinLeave) return if (!logJoinLeave) return
plugin.tgBot?.broadcastToTG( val text = "<b>${escapeHTML(event.player.displayName)}</b> $leftStr."
"<b>${event.player.displayName}</b> b $leftStr." plugin.tgBot?.broadcastToTG(text)
)
} }
} }

View File

@ -1,11 +1,11 @@
package org.kraftwerk28.spigot_tg_bridge package org.kraftwerk28.spigot_tg_bridge
import com.vdurmont.emoji.EmojiParser import com.vdurmont.emoji.EmojiParser
import org.bukkit.event.Listener
import org.bukkit.plugin.java.JavaPlugin import org.bukkit.plugin.java.JavaPlugin
import org.telegram.telegrambots.ApiContextInitializer import org.telegram.telegrambots.ApiContextInitializer
import org.telegram.telegrambots.meta.TelegramBotsApi import org.telegram.telegrambots.meta.TelegramBotsApi
import java.io.File import java.io.File
import org.kraftwerk28.spigot_tg_bridge.Constants as C
class Plugin : JavaPlugin() { class Plugin : JavaPlugin() {
@ -14,17 +14,20 @@ class Plugin : JavaPlugin() {
init { init {
config.run { config.run {
chatToTG = getBoolean("logFromMCtoTG", false) chatToTG = getBoolean(
C.FIELDS.LOG_FROM_MC_TO_TG,
C.DEFS.logFromMCtoTG
)
} }
} }
override fun onEnable() { override fun onEnable() {
val configFile = File( val configFile = File(
server.pluginManager.getPlugin(name)!!.dataFolder, server.pluginManager.getPlugin(name)!!.dataFolder,
"config.yml" C.configFilename
) )
if (!configFile.exists()) { if (!configFile.exists()) {
logger.warning("No config file found! Saving default one.") logger.warning(C.WARN.noConfigWarning)
saveDefaultConfig() saveDefaultConfig()
return return
} }
@ -38,15 +41,19 @@ class Plugin : JavaPlugin() {
server.pluginManager.registerEvents(EventHandler(this), this) server.pluginManager.registerEvents(EventHandler(this), this)
// Notify everything about server start // Notify everything about server start
val startMsg = config.getString("serverStartMessage", null) config.getString(C.FIELDS.SERVER_START_MSG, null)?.let {
if (startMsg != null) tgBot?.broadcastToTG(startMsg) logger.info("Server start message: $it")
logger.info("Plugin started") tgBot?.broadcastToTG(it)
}
logger.info("Plugin started.")
} }
override fun onDisable() { override fun onDisable() {
val stopMsg = config.getString("serverStopMessage", null) config.getString(C.FIELDS.SERVER_STOP_MSG, null)?.let {
if (stopMsg != null) tgBot?.broadcastToTG(stopMsg) logger.info("Server stop message: $it")
logger.info("Plugin stopped") tgBot?.broadcastToTG(it)
}
logger.info("Plugin stopped.")
} }
fun sendMessageToMC(text: String) { fun sendMessageToMC(text: String) {
@ -55,7 +62,10 @@ class Plugin : JavaPlugin() {
} }
fun sendMessageToMCFrom(username: String, text: String) { fun sendMessageToMCFrom(username: String, text: String) {
val prep = EmojiParser.parseToAliases("<$username> $text") val text = run {
server.broadcastMessage(prep) val text = "<${escapeHTML(username)}> $text"
EmojiParser.parseToAliases(text)
}
server.broadcastMessage(text)
} }
} }

View File

@ -0,0 +1,10 @@
package org.kraftwerk28.spigot_tg_bridge
import org.telegram.telegrambots.meta.api.objects.User
fun escapeHTML(s: String): String =
s.replace("&", "&amp;").replace(">", "&gt;").replace("<", "&lt;")
fun telegramUserMention(user: User): String =
if (user.userName != null) "@${user.userName}"
else "<a href=\"tg://user?id=${user.id}\">${user.firstName ?: user.lastName}</a>"

View File

@ -12,3 +12,4 @@ strings:
nobodyOnline: '<b>Nobody online...</b>' nobodyOnline: '<b>Nobody online...</b>'
joined: 'joined' joined: 'joined'
left: 'left' left: 'left'

View File

@ -1,5 +1,5 @@
name: SpigotTGBridge name: SpigotTGBridge
version: 0.0.5 version: 0.0.6
api-version: '1.15' api-version: '1.15'
main: org.kraftwerk28.spigot_tg_bridge.Plugin main: org.kraftwerk28.spigot_tg_bridge.Plugin
description: Telegram <-> Minecraft communication plugin for Spigot. description: Telegram <-> Minecraft communication plugin for Spigot.