from __future__ import annotations from typing import Any WizardStep = dict[str, Any] class MatrixSetupWizard: def __init__(self): self._steps: list[WizardStep] = [] self._current_step = 0 self._config: dict[str, Any] = {} def build_steps(self) -> list[WizardStep]: return [ { "id": "homeserver", "title": "Homeserver", "description": "Enter your Matrix homeserver URL", "field": "homeserver", "type": "text", "default": "https://matrix.org", "required": True, }, { "id": "auth", "title": "Authentication", "description": "Choose authentication method: access_token or password", "field": "auth_method", "type": "select", "options": ["access_token", "password"], "default": "password", "required": True, }, { "id": "user_id", "title": "User ID", "description": "Your Matrix user ID (e.g. @bot:matrix.org)", "field": "user_id", "type": "text", "required": True, }, { "id": "credential", "title": "Credentials", "description": "Enter your access token or password", "field": "credential", "type": "password", "required": True, }, { "id": "device_id", "title": "Device ID", "description": "Device identifier (auto-generated if empty)", "field": "device_id", "type": "text", "default": "yuxi-bot", "required": False, }, { "id": "dm_policy", "title": "DM Policy", "description": "Who can DM the bot?", "field": "dm.policy", "type": "select", "options": ["open", "disabled", "allowlist", "pairing"], "default": "pairing", "required": False, }, { "id": "group_policy", "title": "Group Policy", "description": "Group access control policy", "field": "groupPolicy", "type": "select", "options": ["open", "disabled", "allowlist"], "default": "allowlist", "required": False, }, { "id": "encryption", "title": "Encryption", "description": "Enable End-to-End Encryption?", "field": "encryption", "type": "boolean", "default": False, "required": False, }, { "id": "confirm", "title": "Confirm", "description": "Review and save your configuration", "field": "confirm", "type": "confirm", }, ] def get_current_step(self) -> WizardStep | None: steps = self.build_steps() if 0 <= self._current_step < len(steps): return steps[self._current_step] return None def set_answer(self, step_id: str, value: Any) -> None: field = step_id steps = self.build_steps() for step in steps: if step["id"] == step_id: field = step["field"] break self._config[field] = value def advance(self) -> bool: steps = self.build_steps() if self._current_step < len(steps) - 1: self._current_step += 1 return True return False def go_back(self) -> bool: if self._current_step > 0: self._current_step -= 1 return True return False def to_config(self) -> dict[str, Any]: config: dict[str, Any] = {} config["homeserver"] = self._config.get("homeserver", "https://matrix.org") config["user_id"] = self._config.get("user_id", "") credential = self._config.get("credential", "") auth_method = self._config.get("auth_method", "password") if auth_method == "access_token": config["access_token"] = credential else: config["password"] = credential if self._config.get("device_id"): config["device_id"] = self._config["device_id"] if self._config.get("dm.policy"): config.setdefault("dm", {}) config["dm"]["policy"] = self._config["dm.policy"] if self._config.get("groupPolicy"): config["groupPolicy"] = self._config["groupPolicy"] if self._config.get("encryption"): config["encryption"] = True return config @property def is_complete(self) -> bool: steps = self.build_steps() return self._current_step >= len(steps) - 1