71 lines
2.9 KiB
Python
71 lines
2.9 KiB
Python
|
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,
|
||
|
)
|