ForcePilot/backend/package/yuxi/channels/adapters/imessage/setup_wizard.py
Kris 068cf70fe9 feat(imessage): 实现完整的 iMessage 适配器基础模块
新增 iMessage 通道适配器完整实现,包含:
1. 核心适配器与工具工厂导出
2. 运行时存储、反射防护、会话路由等基础组件
3. 消息信封、线程管理、回复上下文格式化
4. Tapback 表情反应处理、自定义异常体系
5. 审批按钮、联系人解析、速率限制功能
6. 文本净化、目标解析、缓存管理模块
7. 配置 schema、多账户支持、安装向导等配置模块
8. 审计日志、媒体AI处理等扩展功能
2026-05-12 00:44:44 +08:00

134 lines
4.2 KiB
Python

from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any
_registered_plugin: bool = False
def register_setup_plugin() -> bool:
global _registered_plugin
if _registered_plugin:
return True
_registered_plugin = True
return True
def is_setup_plugin_registered() -> bool:
return _registered_plugin
def unregister_setup_plugin() -> None:
global _registered_plugin
_registered_plugin = False
@dataclass
class SetupWizardStep:
step_id: str
label: str
description: str
field: str
field_type: str
required: bool = True
default_value: Any = None
options: list[dict[str, str]] = field(default_factory=list)
hint: str = ""
SETUP_STEPS: list[SetupWizardStep] = [
SetupWizardStep(
step_id="server_url",
label="BlueBubbles Server URL",
description="The URL of your BlueBubbles server (e.g. http://192.168.1.100:1234)",
field="server_url",
field_type="text",
default_value="http://localhost:1234",
),
SetupWizardStep(
step_id="password",
label="Server Password",
description="The password configured in your BlueBubbles server settings",
field="password",
field_type="password",
),
SetupWizardStep(
step_id="dm_policy",
label="DM Access Policy",
description="How should the bot handle direct messages?",
field="dm_policy",
field_type="select",
default_value="pairing",
options=[
{"value": "pairing", "label": "Pairing (users must request approval)"},
{"value": "allowlist", "label": "Allowlist (only approved contacts)"},
{"value": "open", "label": "Open (anyone can DM)"},
{"value": "disabled", "label": "Disabled (no DMs)"},
],
hint="Pairing is recommended for controlled access. Users get a code to share with admins.",
),
SetupWizardStep(
step_id="group_policy",
label="Group Chat Policy",
description="How should the bot handle group chats?",
field="group_policy",
field_type="select",
default_value="allowlist",
options=[
{"value": "open", "label": "Open (any group can add the bot)"},
{"value": "allowlist", "label": "Allowlist (only approved groups)"},
{"value": "disabled", "label": "Disabled (no group chats)"},
],
),
SetupWizardStep(
step_id="allow_from",
label="Allowed Contacts",
description="List of contacts allowed to interact with the bot (one per line). Use * for everyone.",
field="allow_from",
field_type="textarea",
required=False,
hint="Phone numbers (E.164), email addresses, or * for all. Prefix with chat_id: or chat_guid: for specific chats.",
),
SetupWizardStep(
step_id="completed",
label="Setup Complete",
description="Your iMessage channel is now configured! The bot will restart with these settings.",
field="completed",
field_type="info",
),
]
def get_setup_steps() -> list[dict[str, Any]]:
return [
{
"step_id": s.step_id,
"label": s.label,
"description": s.description,
"field": s.field,
"field_type": s.field_type,
"required": s.required,
"default_value": s.default_value,
"options": s.options,
"hint": s.hint,
}
for s in SETUP_STEPS
]
def generate_permissions_summary(config: dict[str, Any]) -> str:
"""生成权限提醒摘要文本。"""
dm_policy = config.get("dmPolicy", config.get("dm_policy", "pairing"))
lines = [
"iMessage channel configured successfully!",
"",
f"DM Policy: {dm_policy}",
f"Group Policy: {config.get('groupPolicy', config.get('group_policy', 'allowlist'))}",
"",
"Notes:",
"- Ensure BlueBubbles server has 'Private API' enabled",
"- The bot must be signed into iMessage on the Mac running BlueBubbles",
"- Group chats: add the bot to a group, then approve the group GUID via allowlist",
]
return "\n".join(lines)