perf: reuse ClientSession, prebuild headers, dedup rate-limit check
This commit is contained in:
48
main.py
48
main.py
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user