This commit is contained in:
sansenhoshi
2026-01-04 17:15:40 +08:00
commit 275f05ee4a
207 changed files with 12305 additions and 0 deletions
@@ -0,0 +1,225 @@
import ast
from asyncio import gather
from base64 import b64decode
from io import BytesIO
from re import findall
from typing import Union
import json
from mcstatus import BedrockServer, JavaServer
from nonebot import on_command, on_regex
from nonebot.adapters.onebot.v11 import (
Bot,
GroupMessageEvent,
Message,
MessageEvent,
)
from nonebot.adapters.onebot.v11 import (
MessageSegment as MS,
)
from nonebot.log import logger
from nonebot.params import RegexGroup
from nonebot.plugin import PluginMetadata
from .config import Config, pc, save_file, var
__plugin_meta__ = PluginMetadata(
name="MC服务器信息查询插件",
description="如名",
type="application",
homepage="https://github.com/nikissXI/nonebot_plugins/tree/main/nonebot_plugin_setu_customization",
supported_adapters={"~onebot.v11"},
config=Config,
usage=f"""插件命令如下:
信息 # 字面意思,需要加命令前缀,默认/
信息数据 # 查看已启用群以及服务器信息,需要加命令前缀,默认/
添加服务器 # 字面意思
删除服务器 # 字面意思
""",
)
async def group_check(event: GroupMessageEvent, bot: Bot) -> bool:
return event.group_id in var.group_list and bot == var.handle_bot
async def admin_check(event: MessageEvent, bot: Bot) -> bool:
return bot == var.handle_bot and event.user_id in pc.mc_status_admin_qqnum
xinxi = on_command("信息", rule=group_check)
list_all = on_command("信息数据", rule=admin_check)
add_server = on_regex(
r"^添加服务器\s*((\d+)\s+(\S+)\s+(\S+)\s+(\S+))?", rule=admin_check
)
del_server = on_regex(r"^删除服务器\s*((\d+)\s+(\S+))?", rule=admin_check)
test_server = on_regex(r"^测试服务器\s*((\S+)\s+(\S+))?", rule=admin_check)
@xinxi.handle()
async def _(event: GroupMessageEvent):
group = event.group_id
task_list = []
for server_name in var.group_list[group]:
server_host = var.group_list[group][server_name][0]
server_type = var.group_list[group][server_name][1]
task_list.append(
check_mc_status(
server_name,
server_host,
server_type,
)
)
result = await gather(*task_list)
count = 0
msg = ""
print(result)
for r in result:
count += 1
if count > 1:
msg += "\n=== 分割线 ===\n"
msg += r
await xinxi.finish(msg)
@add_server.handle()
async def _(mp=RegexGroup()):
if not mp[0]:
await add_server.finish(
f"添加服务器 [群号] [名称] [服务器地址] [类型]\n类型写js或bds,js是Java服务器,bds是基岩服务器\n服务器地址如果知道端口号把端口加上,否则查询速度会慢一点\n添加例子:\nexp1: 添加服务器 114514 哈皮咳嗽 mc.hypixel.net js\nexp2: 添加服务器 114514 某基岩服 mc.bds.net bds\nexp3: 添加服务器 114514 某Java服 mc.java.net:25577 js"
)
else:
group = int(mp[1])
new_server_name = mp[2]
server_host = mp[3]
server_type = mp[4].lower()
if server_type not in ["js", "bds"]:
await add_server.finish("类型请填js或bds")
if group not in var.group_list:
var.group_list[group] = {new_server_name: [server_host, server_type]}
else:
for server_name in var.group_list[group]:
if new_server_name == server_name:
await add_server.finish("有同名服务器啦!")
var.group_list[group][new_server_name] = [server_host, server_type]
save_file()
await add_server.finish("添加成功")
@del_server.handle()
async def _(mp=RegexGroup()):
if not mp[0]:
await del_server.finish(f"删除服务器 [群号] [名称]")
else:
group = int(mp[1])
name = mp[2]
if group not in var.group_list:
await del_server.finish("这个群没有添加服务器")
else:
if name in var.group_list[group]:
var.group_list[group].pop(name)
if not var.group_list[group]:
var.group_list.pop(group)
save_file()
await del_server.finish("删除成功")
else:
await del_server.finish("没找到该名称的服务器")
@list_all.handle()
async def _():
msg = ""
for group_id in var.group_list:
msg += f"{group_id}服务器列表\n"
for server_name in var.group_list[group_id]:
server_host, server_type = var.group_list[group_id][server_name]
msg += f"{server_name} {server_host} {server_type}\n"
msg += "\n"
if not msg:
msg = "无数据"
await list_all.finish(f"mc_status数据\n{msg}")
@test_server.handle()
async def _(mp=RegexGroup()):
if not mp[0]:
await test_server.finish(
f"测试服务器 [服务器地址] [类型]\n类型写js或bds,js是Java服务器,bds是基岩服务器"
)
else:
server_host = mp[1]
server_type = mp[2].lower()
if server_type not in ["js", "bds"]:
await add_server.finish("类型请填js或bds")
msg = await check_mc_status("测试", server_host, server_type)
await list_all.finish(msg)
async def check_mc_status(
name: str, host: str, server_type: str
) -> Union[str, Message]:
try:
if server_type == "js":
js = await JavaServer.async_lookup(host, timeout=2)
status = js.status()
# if status.description.strip():
# print(f"des: {status.description}")
version_list = findall(r"\d+\.\d+(?:\.[\dxX]+)?", status.version.name)
if len(version_list) != 1:
version = f"{version_list[0]}-{version_list[-1]}"
else:
version = version_list[0]
online = f"{status.players.online}/{status.players.max}"
if status.players.online and status.players.sample:
anonymous_player = 0
_player_list = []
for p in status.players.sample:
if p.id == "00000000-0000-0000-0000-000000000000":
anonymous_player += 1
else:
_player_list.append(p.name)
if anonymous_player:
_player_list.append(f"[{anonymous_player}个匿名玩家]")
if _player_list:
player_list = "\n".join(_player_list)
else:
player_list = "没返回玩家列表"
else:
player_list = "没人在线"
latency = round(status.latency)
# base64图标
if status.favicon:
aa, bb = status.favicon.split("base64,")
icon = MS.image(BytesIO(b64decode(bb))) + "\n"
else:
icon = ""
msg = (
icon
+ f"名称:{name}\n版本:{version}\n在线:{online}\n延迟:{latency}ms\n在线列表:\n{player_list}"
)
else:
if host.find(":") != -1:
host, port = host.split(":")
else:
host, port = host, 19132
bds = BedrockServer(host=host, port=int(port))
status = await bds.async_status()
online = f"{status.players_online}/{status.players_max}"
latency = round(status.latency)
version = status.version.version
msg = f"名称:{name}{version}\n在线:{online} 延迟:{latency}ms"
except Exception as e:
msg = f"名称:{name} 查询失败!\n错误:{repr(e)}"
return msg
@@ -0,0 +1,112 @@
from json import dump, load
from os import makedirs, path
from typing import List, Optional
from nonebot import get_bot, get_bots, get_driver, get_plugin_config
from nonebot.adapters import Bot
from pydantic import BaseModel
class Config(BaseModel):
# 管理员的QQ号(别问我为什么)
mc_status_admin_qqnum: List[int] = [] # 必填
# 机器人的QQ号(如果写了就按优先级响应,否则就第一个连上的响应) ['1234','5678','6666']
mc_status_bot_qqnum_list: List[str] = [] # 可选
# 数据文件名
mc_status_data_filename: str = "mc_status_data.json"
class Var:
# 处理消息的bot
handle_bot: Optional[Bot] = None
# {"123456": {"提肛": ["mc.hypixel.net:25565","java"]}}
group_list = {}
driver = get_driver()
pc = get_plugin_config(Config)
var = Var()
@driver.on_startup
async def on_startup():
if not path.exists(f"data"):
makedirs(f"data")
if not path.exists(f"data/{pc.mc_status_data_filename}"):
save_file()
else:
load_file()
def load_file():
with open(f"data/{pc.mc_status_data_filename}", "r", encoding="utf-8") as r:
tmp_data = load(r)
for i in tmp_data:
var.group_list[int(i)] = tmp_data[i]
def save_file():
with open(f"data/{pc.mc_status_data_filename}", "w", encoding="utf-8") as w:
dump(var.group_list, w, indent=4, ensure_ascii=False)
# qq机器人连接时执行
@driver.on_bot_connect
async def on_bot_connect(bot: Bot):
# 是否有写bot qq,如果写了只处理bot qq在列表里的
if pc.mc_status_bot_qqnum_list and bot.self_id in pc.mc_status_bot_qqnum_list:
# 如果已经有bot连了
if var.handle_bot:
# 当前bot qq 下标
handle_bot_id_index = pc.mc_status_bot_qqnum_list.index(
var.handle_bot.self_id
)
# 新连接的bot qq 下标
new_bot_id_index = pc.mc_status_bot_qqnum_list.index(bot.self_id)
# 判断优先级,下标越低优先级越高
if new_bot_id_index < handle_bot_id_index:
var.handle_bot = bot
# 没bot连就直接给
else:
var.handle_bot = bot
# 不写就给第一个连的
elif not pc.mc_status_bot_qqnum_list and not var.handle_bot:
var.handle_bot = bot
# qq机器人断开时执行
@driver.on_bot_disconnect
async def on_bot_disconnect(bot: Bot):
# 判断掉线的是否为handle bot
if bot == var.handle_bot:
# 如果有写bot qq列表
if pc.mc_status_bot_qqnum_list:
# 获取当前连着的bot列表(需要bot是在bot qq列表里)
available_bot_id_list = [
bot_id for bot_id in get_bots() if bot_id in pc.mc_status_bot_qqnum_list
]
if available_bot_id_list:
# 打擂台排序?
new_bot_index = pc.mc_status_bot_qqnum_list.index(
available_bot_id_list[0]
)
for bot_id in available_bot_id_list:
now_bot_index = pc.mc_status_bot_qqnum_list.index(bot_id)
if now_bot_index < new_bot_index:
new_bot_index = now_bot_index
# 取下标在qq列表里最小的bot qq为新的handle bot
var.handle_bot = get_bot(pc.mc_status_bot_qqnum_list[new_bot_index])
else:
var.handle_bot = None
# 不写就随便给一个连着的(如果有)
elif var.handle_bot:
try:
new_bot = get_bot()
var.handle_bot = new_bot
except ValueError:
var.handle_bot = None