import time from yuxi.channel.extensions.twitch.config import ( TwitchConfig, get_account_config, is_account_configured, list_account_ids, ) from yuxi.channel.extensions.twitch.types import TwitchRole from yuxi.channel.protocols import ChannelStatusIssue def collect_twitch_status_issues( config: TwitchConfig, runtime_snapshots: dict[str, object], ) -> list[ChannelStatusIssue]: issues = [] account_ids = list_account_ids(config) if not account_ids: account_ids = ["default"] for aid in account_ids: account = get_account_config(config, aid) if not is_account_configured(account): issues.append( ChannelStatusIssue( channel="twitch", account_id=aid, kind="unconfigured", message=f"Twitch account '{aid}' is not configured", fix="Provide username, access_token, and channel in config", ) ) continue if not account.enabled: issues.append( ChannelStatusIssue( channel="twitch", account_id=aid, kind="disabled", message=f"Twitch account '{aid}' is disabled", ) ) continue has_client_id = bool(account.client_id) if not has_client_id: issues.append( ChannelStatusIssue( channel="twitch", account_id=aid, kind="missing_client_id", message=f"Twitch account '{aid}' is missing client_id", fix="Add a Twitch Client ID for Helix API access", ) ) if account.allow_from is not None and len(account.allow_from) == 0: issues.append( ChannelStatusIssue( channel="twitch", account_id=aid, kind="empty_allowlist", message=f"Twitch account '{aid}' has empty allow_from, which rejects all users", fix="Add user IDs to allow_from or remove it to use open/role mode", ) ) if TwitchRole.ALL in account.allowed_roles and account.allow_from: issues.append( ChannelStatusIssue( channel="twitch", account_id=aid, kind="conflicting_access_control", message=f"Twitch account '{aid}' has both allowed_roles='all' and non-empty allow_from", fix="Choose one access control mode: either allow_from or allowed_roles, not both", ) ) snapshot = runtime_snapshots.get(f"twitch:{aid}") if snapshot is not None: last_error = getattr(snapshot, "last_error", None) if last_error: issues.append( ChannelStatusIssue( channel="twitch", account_id=aid, kind="runtime_error", message=f"Twitch account '{aid}' runtime error: {last_error}", fix="Check logs and restart the channel", ) ) running = getattr(snapshot, "running", False) or getattr(snapshot, "state", None) == "running" last_start_at = getattr(snapshot, "last_start_at", None) last_inbound_at = getattr(snapshot, "last_inbound_at", None) if not running and not last_start_at and not last_inbound_at: issues.append( ChannelStatusIssue( channel="twitch", account_id=aid, kind="never_connected", message=f"Twitch account '{aid}' has never successfully connected", ) ) if running and last_start_at: uptime_seconds = time.time() - last_start_at if uptime_seconds > 7 * 24 * 3600: issues.append( ChannelStatusIssue( channel="twitch", account_id=aid, kind="long_uptime", message=f"Twitch account '{aid}' has been running for over 7 days", fix="Consider restarting the channel to refresh the IRC connection", ) ) return issues