Files
nyeki-api/nyekiapi/lib/integrations/github.py
T
2026-07-16 02:12:29 -03:00

82 lines
2.2 KiB
Python

from typing import TypedDict
from urllib.parse import quote
from nyekiapi.lib import settings, project, cache
from nyekiapi.lib.requests import httpx
from nyekiapi.lib.integrations import Profile
CACHE_BY_ID_KEY = "github:profile:id:%s"
CACHE_BY_NAME_KEY = "github:profile:name:%s"
class GithubProfile(TypedDict):
login: str
name: str | None
avatar_url: str
html_url: str
async def get_profile_by_id(id: str) -> Profile:
profile = await cache.get(CACHE_BY_ID_KEY % id)
if profile is not None:
return Profile.from_json(profile)
response = await httpx.get(
f"https://api.github.com/user/{quote(id)}",
headers={
"Authorization": f"Bearer {settings.GITHUB_TOKEN}",
"User-Agent": f"NyekiAPI/{project.PROJECT_VERSION}",
},
)
response.raise_for_status()
data: GithubProfile = response.json()
profile = Profile(
id=id,
url=data["html_url"],
name=data.get("name") or data["login"],
username=data["login"],
avatar_url=data["avatar_url"],
banner_url=None,
)
await cache.set(CACHE_BY_ID_KEY % profile.id, profile, expires_in=10 * 60)
await cache.set(CACHE_BY_NAME_KEY % profile.username, profile, expires_in=10 * 60)
return profile
async def get_profile_by_name(username: str) -> Profile:
profile = await cache.get(CACHE_BY_NAME_KEY % username)
if profile is not None:
return Profile.from_json(profile)
response = await httpx.get(
f"https://api.github.com/users/{quote(username)}",
headers={
"Authorization": f"Bearer {settings.GITHUB_TOKEN}",
"User-Agent": f"NyekiAPI/{project.PROJECT_VERSION}",
},
)
response.raise_for_status()
data: GithubProfile = response.json()
profile = Profile(
id=str(data["id"]),
url=data["html_url"],
name=data.get("name") or data["login"],
username=data["login"],
avatar_url=data["avatar_url"],
banner_url=None,
)
await cache.set(CACHE_BY_ID_KEY % profile.id, profile, expires_in=10 * 60)
await cache.set(CACHE_BY_NAME_KEY % profile.username, profile, expires_in=10 * 60)
return profile