feat: add rcon command
This commit is contained in:
7 files changed
+195
-2
No files matched your search
@@ -18,6 +18,7 @@ repositories {
|
||||
maven("https://oss.sonatype.org/content/repositories/snapshots")
|
||||
maven("https://repo.rtast.cn/api/v4/projects/33/packages/maven")
|
||||
maven("https://repo.rtast.cn/api/v4/projects/19/packages/maven")
|
||||
maven("https://repo.rtast.cn/api/v4/projects/3/packages/maven")
|
||||
}
|
||||
|
||||
tasks.compileKotlin {
|
||||
@@ -46,6 +47,7 @@ dependencies {
|
||||
implementation(libs.logback.classic)
|
||||
implementation(libs.slf4j.api)
|
||||
implementation(libs.aws.s3.sdk)
|
||||
implementation(libs.rconlib)
|
||||
}
|
||||
|
||||
tasks.build {
|
||||
|
||||
@@ -14,6 +14,7 @@ zxingVersion = "3.5.3"
|
||||
logbackClassicVersion = "1.5.8"
|
||||
sl4jVersion = "2.0.16"
|
||||
awsS3SDKVersion = "2.28.18"
|
||||
rconLibVersion = "1.1.0"
|
||||
|
||||
[libraries]
|
||||
ronebot = { group = "cn.rtast", name = "ROneBot", version.ref = "ronebotVersion" }
|
||||
@@ -31,6 +32,7 @@ zxing-javase = { group = "com.google.zxing", name = "javase", version.ref = "zxi
|
||||
logback-classic = { group = "ch.qos.logback", name = "logback-classic", version.ref = "logbackClassicVersion" }
|
||||
slf4j-api = { group = "org.slf4j", name = "slf4j-api", version.ref = "sl4jVersion" }
|
||||
aws-s3-sdk = { group = "software.amazon.awssdk", name = "s3", version.ref = "awsS3SDKVersion" }
|
||||
rconlib = { group = "cn.rtast", name = "RCONLib", version.ref = "rconLibVersion" }
|
||||
|
||||
[bundles]
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import cn.rtast.fancybot.util.file.BlackListManager
|
||||
import cn.rtast.fancybot.util.file.ConfigManager
|
||||
import cn.rtast.fancybot.util.file.NiuziBankManager
|
||||
import cn.rtast.fancybot.util.file.NiuziManager
|
||||
import cn.rtast.fancybot.util.file.RCONManager
|
||||
import cn.rtast.fancybot.util.item.ItemManager
|
||||
import cn.rtast.rob.ROneBotFactory
|
||||
import com.google.gson.Gson
|
||||
@@ -89,6 +90,7 @@ val itemManager = ItemManager()
|
||||
val niuziManager = NiuziManager()
|
||||
val niuziBankManager = NiuziBankManager()
|
||||
val blackListManager = BlackListManager()
|
||||
val rconManager = RCONManager()
|
||||
|
||||
val START_UP_TIME = Instant.now().epochSecond
|
||||
|
||||
@@ -124,5 +126,5 @@ val commands = listOf(
|
||||
ZDJDCommand(), ScanQRCodeCommand(), TTSCommand(), SlimeChunkHelperCommand(),
|
||||
SupportMeCommand(), TheCatCommand(), TheHistoryOfTodayCommand(), MCVersionCommand(),
|
||||
MinecraftWikiCommand(), GaoKaoDaysRemainCommand(), IdiomExplainCommand(), NiuziManagerCommand(),
|
||||
TodayEatCommand(), TodayDrinkCommand(), MCLoginCommand()
|
||||
TodayEatCommand(), TodayDrinkCommand(), MCLoginCommand(), RCONCommand()
|
||||
)
|
||||
+91
-1
@@ -6,7 +6,7 @@
|
||||
|
||||
@file:Suppress("KDocUnresolvedReference")
|
||||
|
||||
package cn.rtast.fancybot.commands.lookup
|
||||
package cn.rtast.fancybot.commands.misc
|
||||
|
||||
import cn.rtast.fancybot.annotations.CommandDescription
|
||||
import cn.rtast.fancybot.commands.lookup.WikipediaCommand.Companion.extractPlainTextFromHtml
|
||||
@@ -27,6 +27,7 @@ import cn.rtast.fancybot.entity.mc.oauth.ObtainXSTSPayload
|
||||
import cn.rtast.fancybot.entity.mc.oauth.ObtainXSTSResponse
|
||||
import cn.rtast.fancybot.entity.mc.oauth.RedeemCodeResponse
|
||||
import cn.rtast.fancybot.enums.mc.MCVersionType
|
||||
import cn.rtast.fancybot.rconManager
|
||||
import cn.rtast.fancybot.util.Http
|
||||
import cn.rtast.fancybot.util.Logger
|
||||
import cn.rtast.fancybot.util.misc.isFullyTransparent
|
||||
@@ -41,6 +42,8 @@ import cn.rtast.fancybot.util.str.toJson
|
||||
import cn.rtast.fancybot.util.str.uriEncode
|
||||
import cn.rtast.motdpinger.BedrockPing
|
||||
import cn.rtast.motdpinger.JavaPing
|
||||
import cn.rtast.rcon.RCon
|
||||
import cn.rtast.rcon.exceptions.AuthFailedException
|
||||
import cn.rtast.rob.entity.GroupMessage
|
||||
import cn.rtast.rob.entity.PrivateMessage
|
||||
import cn.rtast.rob.util.BaseCommand
|
||||
@@ -503,4 +506,91 @@ class MCLoginCommand : BaseCommand() {
|
||||
message.reply(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@CommandDescription("通过RCON来控制MC服务器(仅限私聊执行)")
|
||||
class RCONCommand : BaseCommand() {
|
||||
override val commandNames = listOf("/rcon", "/r")
|
||||
|
||||
override suspend fun executeGroup(listener: OneBotListener, message: GroupMessage, args: List<String>) {
|
||||
message.reply("请在私聊中使用此命令")
|
||||
}
|
||||
|
||||
override suspend fun executePrivate(listener: OneBotListener, message: PrivateMessage, args: List<String>) {
|
||||
if (args.isEmpty()) {
|
||||
val msg = MessageChain.Builder()
|
||||
.addText("这条指令用于在群内操作mc服务器")
|
||||
.addNewLine()
|
||||
.addText("使用`/r add <name> <host> <port> <password>` 可以创建一条配置")
|
||||
.addNewLine()
|
||||
.addText("使用`/r <name> <command>`可以执行命令")
|
||||
.addNewLine()
|
||||
.addText("使用`/r remove <name>`可以移除这条RCON配置")
|
||||
.build()
|
||||
message.reply(msg)
|
||||
return
|
||||
}
|
||||
val action = args.first()
|
||||
when (action) {
|
||||
"get" -> {
|
||||
val allRcons = rconManager.getAllRconsById(message.sender.userId)
|
||||
if (allRcons.isEmpty()) {
|
||||
message.reply("你还没有RCON配置呢, 发送`/r add <name> <host> <port> <password>`来创建一个配置吧")
|
||||
return
|
||||
}
|
||||
val messages = mutableListOf<MessageChain>()
|
||||
.also { it.add(listOf("所有配置如下").asMessageChain()) }
|
||||
allRcons.forEach {
|
||||
val msg = MessageChain.Builder()
|
||||
.addText("名称: ${it.name}")
|
||||
.addNewLine()
|
||||
.addText("地址: ${it.host}:${it.port}")
|
||||
.addNewLine()
|
||||
.addText("密码: *********")
|
||||
.build()
|
||||
messages.add(msg)
|
||||
}
|
||||
message.reply(messages.asNode(configManager.selfId))
|
||||
}
|
||||
|
||||
"add" -> {
|
||||
val name = args[1]
|
||||
val host = args[2]
|
||||
val port = args[3].toInt()
|
||||
val password = args[4]
|
||||
rconManager.insertConfig(message.sender.userId, name, host, port, password)
|
||||
message.reply("成功增加一条记录: $name")
|
||||
}
|
||||
|
||||
"remove" -> {
|
||||
val name = args.last()
|
||||
val count = rconManager.removeRRCON(message.sender.userId, name)
|
||||
if (count == 0) {
|
||||
message.reply("RCON($name)不存在")
|
||||
} else {
|
||||
message.reply("成功移除了$name")
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
val name = args.first().trim()
|
||||
val command = args.drop(1).joinToString(" ").trim()
|
||||
val rconData = rconManager.getRcon(message.sender.userId, name)
|
||||
if (rconData == null) {
|
||||
message.reply("RCON($name)配置不存在")
|
||||
} else {
|
||||
try {
|
||||
val result = rconManager.executeCommand(message.sender.userId, name, command)
|
||||
val messages = mutableListOf<MessageChain>()
|
||||
.also { it.add(listOf("执行结果如下").asMessageChain()) }
|
||||
.also { it.add(listOf(result).asMessageChain()) }
|
||||
.asNode(configManager.selfId)
|
||||
message.reply(messages)
|
||||
} catch (_: AuthFailedException) {
|
||||
message.reply("执行失败, 密码不正确")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright © 2024 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2024/10/13
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.fancybot.db
|
||||
|
||||
import org.jetbrains.exposed.sql.Table
|
||||
|
||||
object RCONTable : Table("rcon") {
|
||||
val id = integer("id").autoIncrement()
|
||||
val host = varchar("host", 50)
|
||||
val port = integer("port")
|
||||
val userId = long("user_id")
|
||||
val password = varchar("password", 128)
|
||||
val name = varchar("name", 50)
|
||||
override val primaryKey = PrimaryKey(id)
|
||||
}
|
||||
|
||||
data class RCONEntity(
|
||||
val host: String,
|
||||
val port: Int,
|
||||
val userId: Long,
|
||||
val name: String,
|
||||
val password: String
|
||||
)
|
||||
|
||||
@@ -14,6 +14,7 @@ import cn.rtast.fancybot.db.JrrpTable
|
||||
import cn.rtast.fancybot.db.MinecraftAccessTokenTable
|
||||
import cn.rtast.fancybot.db.NiuziBankTable
|
||||
import cn.rtast.fancybot.db.NiuziTable
|
||||
import cn.rtast.fancybot.db.RCONTable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.SchemaUtils
|
||||
@@ -28,6 +29,7 @@ suspend fun initDatabase() {
|
||||
SchemaUtils.createMissingTablesAndColumns(ActionTable)
|
||||
SchemaUtils.createMissingTablesAndColumns(BlackListTable)
|
||||
SchemaUtils.createMissingTablesAndColumns(MinecraftAccessTokenTable)
|
||||
SchemaUtils.createMissingTablesAndColumns(RCONTable)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright © 2024 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2024/10/13
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.fancybot.util.file
|
||||
|
||||
import cn.rtast.fancybot.db.MinecraftAccessTokenTable
|
||||
import cn.rtast.fancybot.db.RCONEntity
|
||||
import cn.rtast.fancybot.db.RCONTable
|
||||
import cn.rtast.fancybot.db.RCONTable.host
|
||||
import cn.rtast.fancybot.db.RCONTable.password
|
||||
import cn.rtast.fancybot.db.RCONTable.port
|
||||
import cn.rtast.fancybot.util.suspendedTransaction
|
||||
import cn.rtast.rcon.RCon
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.deleteWhere
|
||||
import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.selectAll
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
|
||||
class RCONManager {
|
||||
|
||||
suspend fun getRcon(userId: Long, name: String): RCONEntity? {
|
||||
return suspendedTransaction {
|
||||
RCONTable.selectAll().where { (RCONTable.userId eq userId) and (RCONTable.name eq name) }
|
||||
.map { RCONEntity(it[host], it[port], it[RCONTable.userId], it[RCONTable.name], it[password]) }
|
||||
}.singleOrNull()
|
||||
}
|
||||
|
||||
suspend fun getAllRconsById(userId: Long): List<RCONEntity> {
|
||||
return suspendedTransaction {
|
||||
RCONTable.selectAll().where { (RCONTable.userId eq userId) }
|
||||
.map { RCONEntity(it[host], it[port], it[RCONTable.userId], it[RCONTable.name], it[password]) }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun executeCommand(userId: Long, name: String, command: String): String {
|
||||
val rconData = getRcon(userId, name)!!
|
||||
val rcon = RCon(rconData.host, rconData.port)
|
||||
rcon.authenticate(rconData.password)
|
||||
val result = rcon.executeCommand(command).body
|
||||
rcon.close()
|
||||
return result
|
||||
}
|
||||
|
||||
suspend fun insertConfig(userId: Long, name: String, host: String, port: Int, password: String) {
|
||||
suspendedTransaction {
|
||||
RCONTable.insert {
|
||||
it[RCONTable.userId] = userId
|
||||
it[RCONTable.name] = name
|
||||
it[RCONTable.host] = host
|
||||
it[RCONTable.port] = port
|
||||
it[RCONTable.password] = password
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun removeRRCON(userId: Long, name: String): Int {
|
||||
return suspendedTransaction {
|
||||
MinecraftAccessTokenTable.deleteWhere { (RCONTable.userId eq userId) and (RCONTable.name eq name) }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user