perf: reuse ClientSession, prebuild headers, dedup rate-limit check

This commit is contained in:
sakuradairong
2026-05-17 15:27:06 +08:00
parent fbea066b2d
commit 15c0c0ac5a

48
main.py
View File

@@ -1,10 +1,11 @@
import re
import aiohttp
from astrbot.api.event import filter, AstrMessageEvent
from astrbot.api.star import Context, Star
from astrbot.api.star import Context, Star, star
from astrbot.api import logger, AstrBotConfig
GITHUB_API_BASE = "https://api.github.com"
_REQUEST_TIMEOUT = aiohttp.ClientTimeout(total=10)
_REPO_PATTERN = re.compile(
r'(?<![a-zA-Z0-9.-])github\.com/([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+)'
@@ -26,11 +27,24 @@ _RELEASES_PAGE_PATTERN = re.compile(
def _find_first_url(text: str, pattern: re.Pattern) -> re.Match | None:
return pattern.search(text)
def _check_rate_limited(data: dict | None) -> bool:
return isinstance(data, dict) and data.get("error") == "rate_limited"
@star
class GitparserPlugin(Star):
def __init__(self, context: Context, config: AstrBotConfig):
super().__init__(context)
self.config = config
token = config.get("github_token", "").strip()
self._headers = {"Accept": "application/vnd.github+json"}
if token:
self._headers["Authorization"] = f"Bearer {token}"
self._session = aiohttp.ClientSession()
async def terminate(self):
if self._session and not self._session.closed:
await self._session.close()
@filter.event_message_type(filter.EventMessageType.ALL)
async def parse_github_link(self, event: AstrMessageEvent):
@@ -55,24 +69,18 @@ class GitparserPlugin(Star):
yield result
async def _fetch_api(self, path: str) -> dict | None:
headers = {"Accept": "application/vnd.github+json"}
token = self.config.get("github_token", "").strip()
if token:
headers["Authorization"] = f"Bearer {token}"
url = f"{GITHUB_API_BASE}{path}"
try:
async with aiohttp.ClientSession() as session:
async with session.get(url, headers=headers, timeout=aiohttp.ClientTimeout(total=10)) as resp:
if resp.status == 404:
return None
if resp.status == 429:
logger.warning(f"GitHub API rate limited: {path}")
return {"error": "rate_limited"}
if resp.status != 200:
logger.warning(f"GitHub API error {resp.status}: {path}")
return None
return await resp.json()
async with self._session.get(url, headers=self._headers, timeout=_REQUEST_TIMEOUT) as resp:
if resp.status == 404:
return None
if resp.status == 429:
logger.warning(f"GitHub API rate limited: {path}")
return {"error": "rate_limited"}
if resp.status != 200:
logger.warning(f"GitHub API error {resp.status}: {path}")
return None
return await resp.json()
except aiohttp.ClientError as e:
logger.error(f"HTTP error fetching {path}: {e}")
return None
@@ -84,7 +92,7 @@ class GitparserPlugin(Star):
data = await self._fetch_api(f"/repos/{owner}/{repo}")
if data is None:
return
if isinstance(data, dict) and data.get("error") == "rate_limited":
if _check_rate_limited(data):
yield event.plain_result("GitHub API 限流,请稍后再试")
return
@@ -133,7 +141,7 @@ class GitparserPlugin(Star):
data = await self._fetch_api(f"/repos/{owner}/{repo}/releases/latest")
if data is None:
return
if isinstance(data, dict) and data.get("error") == "rate_limited":
if _check_rate_limited(data):
yield event.plain_result("GitHub API 限流,请稍后再试")
return
yield event.plain_result(self._build_release_message(owner, repo, data))
@@ -142,7 +150,7 @@ class GitparserPlugin(Star):
data = await self._fetch_api(f"/repos/{owner}/{repo}/releases/tags/{tag}")
if data is None:
return
if isinstance(data, dict) and data.get("error") == "rate_limited":
if _check_rate_limited(data):
yield event.plain_result("GitHub API 限流,请稍后再试")
return
yield event.plain_result(self._build_release_message(owner, repo, data, tag))