"""Gitea client for creating issues when questions need human review.""" import httpx from typing import Optional from .config import settings class GiteaClient: """Client for Gitea API interactions.""" def __init__(self): """Initialize Gitea client with credentials.""" self.token = settings.gitea_token self.owner = settings.gitea_owner self.repo = settings.gitea_repo self.base_url = settings.gitea_base_url.rstrip("/") self.headers = { "Authorization": f"token {self.token}", "Content-Type": "application/json", "Accept": "application/json", } async def create_issue( self, title: str, body: str, labels: Optional[list[str]] = None, assignee: Optional[str] = None, ) -> dict: """Create a new issue in the configured repository.""" url = f"{self.base_url}/repos/{self.owner}/{self.repo}/issues" payload: dict = {"title": title, "body": body} if labels: payload["labels"] = labels if assignee: payload["assignee"] = assignee async with httpx.AsyncClient(timeout=30.0) as client: response = await client.post(url, headers=self.headers, json=payload) if response.status_code not in (200, 201): error_detail = response.text raise RuntimeError( f"Gitea API error creating issue: {response.status_code} - {error_detail}" ) return response.json() async def create_unanswered_issue( self, question: str, user_id: str, channel_id: str, attempted_rules: list[str], conversation_id: str, ) -> str: """Create an issue for an unanswered question needing human review.""" title = f"🤔 Unanswered rules question: {question[:80]}{'...' if len(question) > 80 else ''}" body = f"""## Unanswered Question **User:** {user_id} **Channel:** {channel_id} **Conversation ID:** {conversation_id} **Question:** {question} **Searched Rules:** {', '.join(attempted_rules) if attempted_rules else 'None'} **Additional Context:** This question was asked in Discord and the bot could not provide a confident answer. The rules either don't cover this question or the information was ambiguous. --- *This issue was automatically created by the Strat-Chatbot.*""" labels = ["rules-gap", "ai-generated", "needs-review"] issue = await self.create_issue(title=title, body=body, labels=labels) return issue.get("html_url", "") def get_gitea_client() -> Optional[GiteaClient]: """Factory to get Gitea client if token is configured.""" if settings.gitea_token: return GiteaClient() return None