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)