from __future__ import annotations from pydantic import BaseModel, ConfigDict class ResolvedSlackAccount(BaseModel): account_id: str = "default" enabled: bool = True name: str = "" bot_token: str = "" app_token: str = "" user_token: str = "" bot_token_source: str = "none" app_token_source: str = "none" user_token_source: str = "none" bot_user_id: str = "" bot_id: str = "" team: str = "" team_id: str = "" dm_policy: str = "allowlist" group_policy: str = "allowlist" require_mention: bool = False allow_from: set[str] = set() mode: str = "socket" signing_secret: str = "" text_chunk_limit: int = 8000 max_media_size_mb: int = 100 thread_history_scope: str = "channel" thread_inherit_parent: bool = False thread_require_explicit_mention: bool = False show_configured: bool = True quickstart_allow_from: list[str] = [] force_account_binding: bool = False prefer_session_lookup: bool = False model_config = ConfigDict(extra="allow") class SlackChannelMeta(BaseModel): channel_id: str = "" channel_name: str = "" is_im: bool = False is_channel: bool = False is_group: bool = False is_private: bool = False show_configured: bool = True quickstart_allow_from: list[str] = [] force_account_binding: bool = False prefer_session_lookup: bool = False model_config = ConfigDict(extra="allow") class SlackTokenSelector: WRITE_SCOPES = frozenset( { "chat:write", "chat:write.customize", "chat:update", "chat:delete", "reactions:write", "files:write", "users.profile:write", } ) @staticmethod def select_for_operation( account: ResolvedSlackAccount, operation: str = "write", ) -> str: if operation == "write": return account.bot_token or account.user_token if account.bot_token: return account.bot_token return account.user_token or account.bot_token @staticmethod def get_token_for_operation( account: ResolvedSlackAccount, scopes_needed: list[str] | None = None, ) -> tuple[str, str]: if scopes_needed and any(s in SlackTokenSelector.WRITE_SCOPES for s in scopes_needed): if account.bot_token: return account.bot_token, "bot" return account.user_token, "user" if account.bot_token: return account.bot_token, "bot" return account.user_token or account.bot_token, "user"