Files
Claw e1fbd31c64 完整 AgentSkill:词库外部化 + 全部脚本/Skill 脱敏上传
- 高危词库从 process.py 抽到 config.toml [security] section
- process.py 改为 _get_high_risk_words() 动态加载(配置优先)
- 新增 15 个 QQ 操作脚本(已脱敏:QQ号/IP/Token → 占位符)
- 新增 8 个 SKILL.md(qq-messenger/management/resolver/napcat-extras 等)
- 新增 SKILL.md 入口(完整部署方案文档)
- 保留 SDK 框架(plugin_modules.py, file_store_api.py, package.py 等)
2026-05-04 16:23:59 +08:00

122 lines
5.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""获取Minecraft世界详细信息JSON输出"""
import sys, os, subprocess, re
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from mc_config import RCON_HOST, RCON_PORT, RCON_PASSWORD, MC_SERVER_DIR
from mc_rcon import RCONClient
def get_entity_stats():
try:
with RCONClient(RCON_HOST, RCON_PORT, RCON_PASSWORD) as client:
resp = client.send_command("forge entity list")
body = resp.get("body", "") if resp else ""
if not body:
return {}
m = re.search(r'Total:\s*(\d+)', body)
total = int(m.group(1)) if m else 0
entity_map = {}
for line in body.strip().split("\n")[1:]:
line = line.strip()
em = re.match(r'(\d+):\s*(.+)', line)
if em:
entity_map[em.group(2).strip()] = int(em.group(1))
hostile_types = {"zombie", "skeleton", "creeper", "spider", "enderman", "witch", "slime", "phantom", "husk", "stray", "drowned", "pillager", "vindicator", "evoker", "ravager", "vex", "hoglin", "zoglin", "piglin", "piglin_brute", "wither_skeleton", "blaze", "ghast", "magma_cube", "guardian", "elder_guardian", "shulker", "endermite", "silverfish"}
passive_types = {"sheep", "cow", "pig", "chicken", "horse", "donkey", "mule", "rabbit", "fox", "bee", "cat", "wolf", "parrot", "turtle", "panda", "polar_bear", "llama", "mooshroom", "bat", "squid", "dolphin", "cod", "salmon", "tropical_fish", "pufferfish", "villager", "wandering_trader", "iron_golem", "snow_golem", "frog", "axolotl", "goat", "sniffer", "camel"}
hostile, passive, other = 0, 0, 0
for name, count in entity_map.items():
nl = name.replace("minecraft:", "").lower()
if nl in hostile_types:
hostile += count
elif nl in passive_types:
passive += count
else:
other += count
top = sorted(entity_map.items(), key=lambda x: -x[1])[:5]
return {"total": total, "hostile": hostile, "passive": passive, "other": other, "top": top}
except Exception:
return {}
def get_game_time():
try:
with RCONClient(RCON_HOST, RCON_PORT, RCON_PASSWORD) as client:
resp_day = client.send_command("time query day")
resp_daytime = client.send_command("time query daytime")
body_day = resp_day.get("body", "") if resp_day else ""
body_daytime = resp_daytime.get("body", "") if resp_daytime else ""
m_day = re.search(r'The time is (\d+)', body_day)
m_daytime = re.search(r'The time is (\d+)', body_daytime)
day = int(m_day.group(1)) + 1 if m_day else 1
daytime = int(m_daytime.group(1)) if m_daytime else 0
years = day // 365
months = (day % 365) // 30
days = (day % 365) % 30
hours = int(daytime / 1000)
minutes = int((daytime % 1000) * 60 / 1000)
if 0 <= daytime < 1000:
phase = "日出"
elif 1000 <= daytime < 12000:
phase = "白天"
elif 12000 <= daytime < 13000:
phase = "日落"
elif 13000 <= daytime < 23000:
phase = "夜晚"
else:
phase = "黎明"
return {"day": day, "years": years, "months": months, "days": days, "time": f"{hours:02d}:{minutes:02d}", "phase": phase}
except Exception:
return {}
def get_network_stats():
try:
with open("/proc/net/dev", "r") as f:
lines = f.readlines()
total_rx, total_tx = 0, 0
for line in lines[2:]:
parts = line.strip().split()
if len(parts) >= 10 and not parts[0].startswith("lo:"):
total_rx += int(parts[1])
total_tx += int(parts[9])
def fmt(b):
if b >= 1024**3:
return f"{b/1024**3:.1f}GB"
elif b >= 1024**2:
return f"{b/1024**2:.0f}MB"
elif b >= 1024:
return f"{b/1024:.0f}KB"
return f"{b}B"
return {"rx": fmt(total_rx), "tx": fmt(total_tx)}
except Exception:
return {}
def get_active_mods(limit=3):
log_path = os.path.join(MC_SERVER_DIR, "logs", "debug.log")
if not os.path.exists(log_path):
return []
skip = ["net.minecraft", "net.minecraftforge", "Server thread", "RCON", "Thread", "Generic", "mojang", "java", "sun.", "com.google", "org.apache", "io.netty", "org.mtr", "Mixin", "dev.architectury", "libIPN", "MinecraftMappings", "Yggdrasil", "DataFixer"]
counts = {}
try:
with open(log_path, "r", errors="ignore") as f:
lines = f.readlines()
for line in lines[-2000:]:
m = re.search(r'\[([^\/\]]+)/\]', line)
if not m:
continue
mod = m.group(1)
if any(mod.startswith(s) for s in skip) or len(mod) < 3:
continue
counts[mod] = counts.get(mod, 0) + 1
return [m[0] for m in sorted(counts.items(), key=lambda x: -x[1])[:limit]]
except Exception:
return []
if __name__ == "__main__":
import json
result = {
"entity_stats": get_entity_stats(),
"game_time": get_game_time(),
"network": get_network_stats(),
"active_mods": get_active_mods(),
}
print(json.dumps(result, ensure_ascii=False, indent=2))