ForcePilot/backend/package/yuxi/channel/extensions/minecraft/setup.py

148 lines
5.4 KiB
Python
Raw Normal View History

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