ForcePilot/backend/package/yuxi/channel/extensions/minecraft/setup.py
Kris b3b6c95094 feat(channel): 添加 Minecraft 渠道扩展
新增 Minecraft 渠道扩展,支持在 Yuxi 平台中集成 Minecraft 游戏服务器渠道。

包含以下功能模块:
- client: Minecraft 客户端封装
- config: 渠道配置管理
- gateway: SSE/WebSocket 网关接入
- outbound: 外发消息管理
- streaming: 流式消息处理
- pairing: 用户配对与绑定
- security: 安全校验
- auth: 认证管理
- accounts: 账户管理
- dedupe: 消息去重
- monitor: 渠道状态监控
- status: 会话状态管理
- protocol: Minecraft 协议处理
- rcon: RCON 远程控制
- keepalive: 连接保活
- version_adapter: 版本适配
- setup: 初始化设置
- types: 类型定义
2026-05-21 11:26:52 +08:00

148 lines
5.4 KiB
Python
Raw 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.

from yuxi.channel.protocols import SetupWizardStep
class MinecraftSetupWizard:
steps = [
SetupWizardStep(
key="host",
label="服务器地址",
description="Minecraft 服务器 IP 或域名(如 localhost 或 mc.example.com",
input_type="text",
required=True,
default="localhost",
),
SetupWizardStep(
key="port",
label="服务器端口",
description="Minecraft 服务器端口(默认 25565",
input_type="text",
required=True,
default="25565",
),
SetupWizardStep(
key="username",
label="Bot 用户名",
description="Bot 在游戏中显示的用户名",
input_type="text",
required=True,
default="ForcePilotBot",
),
SetupWizardStep(
key="auth_mode",
label="认证模式",
description="选择认证方式offline离线模式或 microsoft正版验证",
input_type="select",
required=True,
default="offline",
options=[
{"label": "离线模式offline", "value": "offline"},
{"label": "正版验证microsoft", "value": "microsoft"},
],
),
SetupWizardStep(
key="version",
label="游戏版本",
description="选择 Minecraft 版本auto 表示自动探测",
input_type="select",
required=True,
default="auto",
options=[
{"label": "自动探测auto", "value": "auto"},
{"label": "1.20.4", "value": "1.20.4"},
{"label": "1.21-1.21.1", "value": "1.21"},
{"label": "1.21.2-1.21.3", "value": "1.21.2"},
{"label": "1.21.4", "value": "1.21.4"},
{"label": "1.21.5", "value": "1.21.5"},
],
),
SetupWizardStep(
key="rcon_port",
label="RCON 端口",
description="RCON 远程管理端口(默认 25575不需要可留空",
input_type="text",
required=False,
default="25575",
),
SetupWizardStep(
key="rcon_password",
label="RCON 密码",
description="RCON 认证密码(不需要远程管理可留空)",
input_type="password",
required=False,
),
]
def setup_wizard_steps(self) -> list[SetupWizardStep]:
return self.steps
def validate_wizard_input(self, step_key: str, value: str) -> str | None:
if step_key == "host":
if not value or not value.strip():
return "服务器地址不能为空"
stripped = value.strip()
if len(stripped) > 253:
return "服务器地址过长(最大 253 字符)"
elif step_key == "port":
try:
port = int(value)
if not (1 <= port <= 65535):
return "端口必须在 1-65535 之间"
except ValueError:
return "端口必须是有效的整数"
elif step_key == "username":
if not value or not value.strip():
return "用户名不能为空"
stripped = value.strip()
if len(stripped) > 16:
return "Minecraft 用户名不能超过 16 个字符"
if not stripped.replace("_", "").isalnum():
return "用户名只能包含字母、数字和下划线"
elif step_key == "auth_mode":
if value not in ("offline", "microsoft"):
return "认证模式必须是 offline 或 microsoft"
elif step_key == "version":
valid_versions = ("auto", "1.20.4", "1.21", "1.21.2", "1.21.4", "1.21.5")
if value not in valid_versions:
return f"版本必须是以下之一: {', '.join(valid_versions)}"
elif step_key == "rcon_port":
if value:
try:
port = int(value)
if not (1 <= port <= 65535):
return "RCON 端口必须在 1-65535 之间"
except ValueError:
return "RCON 端口必须是有效的整数"
return None
async def finalize(self, config: dict) -> dict:
result = dict(config)
result.setdefault("host", "localhost")
result.setdefault("port", 25565)
result.setdefault("username", "ForcePilotBot")
result.setdefault("auth_mode", "offline")
result.setdefault("version", "auto")
result.setdefault("rcon_port", 25575)
if "port" in result and isinstance(result["port"], str):
result["port"] = int(result["port"])
if "rcon_port" in result and isinstance(result["rcon_port"], str):
result["rcon_port"] = int(result["rcon_port"])
result.setdefault("group_policy", "mention")
result.setdefault("require_mention", True)
result.setdefault("dm_policy", "pairing")
result.setdefault("allow_from", [])
result.setdefault("text_chunk_limit", 256)
result.setdefault("rate_limit_window", 5.0)
result.setdefault("rate_limit_max", 10)
result.setdefault("reconnect_max_retries", 10)
return result