from __future__ import annotations import logging from yuxi.channel.extensions.helpscout.auth import HelpScoutAuth from yuxi.channel.extensions.helpscout.client import HelpScoutClient from yuxi.channel.extensions.helpscout.config import resolve_account logger = logging.getLogger(__name__) CATEGORY_KEYWORDS: dict[str, list[str]] = { "billing": ["refund", "invoice", "payment", "charge", "subscription", "billing"], "technical": ["bug", "error", "crash", "not working", "broken", "issue", "problem"], "account": ["login", "password", "access", "account", "sign in", "sign up"], "general": ["question", "help", "how to", "what is", "inquiry"], } ASSIGNEE_RULES: dict[str, str] = { "billing": "billing", "technical": "engineering", "account": "support", "general": "support", } class HelpScoutAssigner: async def auto_assign( self, conversation_id: int, body_text: str, account_id: str | None = None, ) -> int | None: account = resolve_account(account_id or "default") category = self._classify_conversation(body_text) team_name = ASSIGNEE_RULES.get(category) logger.debug( "Help Scout auto-assign: conv=%d category=%s team=%s", conversation_id, category, team_name, ) if not team_name: return None client = self._build_client(account) try: teams_resp = await client.list_teams(mailbox=account["mailbox_id"]) teams = teams_resp.get("_embedded", {}).get("teams", []) matched_team = next((t for t in teams if t.get("name", "").lower() == team_name), None) if matched_team: await client.update_conversation(conversation_id, {"assignTo": matched_team["id"]}) logger.info( "Help Scout assigned: conv=%d team=%s(%d)", conversation_id, team_name, matched_team["id"], ) return matched_team["id"] logger.debug("Help Scout team not found: %s for conv=%d", team_name, conversation_id) return None except Exception: logger.exception("Help Scout auto-assign failed: conv=%d", conversation_id) return None finally: await client.close() @staticmethod def _classify_conversation(body_text: str) -> str: text_lower = body_text.lower() for category, keywords in CATEGORY_KEYWORDS.items(): for keyword in keywords: if keyword in text_lower: return category return "general" @staticmethod def _build_client(account: dict) -> HelpScoutClient: auth = HelpScoutAuth(account["app_id"], account["app_secret"]) return HelpScoutClient(auth)