import aiohttp from ..logger import logger from ..models import Issue, Repository async def fetch_forgejo_issue(repository: Repository, issue_number: int) -> Issue: """ Fetch an issue from a Forgejo instance. Args: repository (Repository): The repository to fetch the issue from. issue_number (int): The issue number. Returns: Issue: An Issue object containing the issue details. Raises: aiohttp.ClientResponseError: If the request to the Forgejo API fails. ValueError: If the response from the Forgejo API is empty """ headers: dict[str, str] = {"User-Agent": repository.user_agent} if repository.provider.token is not None: headers["Authorization"] = f"token {repository.provider.token}" else: logger.info("Forgejo API key is not set for provider '%s'. Using unauthenticated request.", repository.provider.url) url = f"{repository.provider.api_url}/repos/{repository.owner}/{repository.name}/issues/{issue_number}" async with aiohttp.ClientSession() as session: async with session.get(url, headers=headers) as response: if response.status != 200: raise aiohttp.ClientResponseError( request_info=response.request_info, history=response.history, status=response.status, message=f"Failed to fetch issue '{issue_number}' from '{repository.url}'.", ) data = await response.json() if data is None: raise ValueError("Received empty response from Forgejo API.") pull_request = data.get("pull_request") if pull_request is not None: if pull_request["merged"] is True: issue_type = "pull_request_merged" elif pull_request["draft"] is True: issue_type = "pull_request_draft" elif data.get("state", "open") == "closed": issue_type = "pull_request_closed" else: issue_type = "pull_request" elif data.get("state", "open") == "closed": issue_type = "issue_closed" else: issue_type = "issue" return Issue( repository=repository, number=data["number"], author=data["user"]["login"], author_avatar=data["user"]["avatar_url"], author_url=data["user"]["html_url"], link=data["html_url"], title=data["title"], body=data["body"] or "", type=issue_type, labels=[label["name"] for label in data.get("labels", [])], draft=bool(data["pull_request"].get("draft", False) if data.get("pull_request") is not None else False), creation_date=data["created_at"], milestone=data.get("milestone", {}).get("title") if data.get("milestone") is not None else None, merge_date=data.get("pull_request").get("merged_at") if data.get("pull_request") is not None else None, response=response, )