feat: add rcon command
This commit is contained in:
7 files changed
+195
-2
No files matched your search
@@ -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