This commit is contained in:
chenxiangtong
2026-03-26 17:38:47 +08:00
commit a05ce6e07e
54 changed files with 5779 additions and 0 deletions

65
src/services/calendar.py Normal file
View File

@@ -0,0 +1,65 @@
import asyncio
import copy
import time
from typing import cast
from astrbot.api import logger
from .base import BaseBangumiService
from .contracts import CalendarDay
from .exceptions import BangumiApiError
class CalendarService(BaseBangumiService):
CALENDAR_CACHE_TTL_SECONDS = 12 * 60 * 60
def __init__(self, *args: object, **kwargs: object) -> None:
super().__init__(*args, **kwargs)
self._calendar_cache: list[CalendarDay] | None = None
self._calendar_cache_expire_at: float = 0.0
self._calendar_cache_lock = asyncio.Lock()
def _is_calendar_cache_valid(self, now: float) -> bool:
return self._calendar_cache is not None and now < self._calendar_cache_expire_at
def invalidate_calendar_cache(self) -> None:
self._calendar_cache = None
self._calendar_cache_expire_at = 0.0
async def get_calendar(self) -> list[CalendarDay]:
now = time.time()
if self._is_calendar_cache_valid(now):
return copy.deepcopy(self._calendar_cache)
# 双重检查 + 锁,避免并发下重复请求远端 API
async with self._calendar_cache_lock:
now = time.time()
if self._is_calendar_cache_valid(now):
return copy.deepcopy(self._calendar_cache)
url = f"{self.base_url}/calendar"
previous_cache = copy.deepcopy(self._calendar_cache)
try:
data = await self._request(url, method="GET")
except (BangumiApiError, RuntimeError, ValueError, TypeError) as e:
logger.error(f"get_calendar 刷新缓存失败: {e}")
if previous_cache is not None:
return previous_cache
return []
if not isinstance(data, list):
logger.warning(f"get_calendar 返回了非 list 类型: {type(data)}")
if previous_cache is not None:
return previous_cache
return []
normalized: list[CalendarDay] = []
for item in data:
if isinstance(item, dict):
normalized.append(cast(CalendarDay, item))
else:
logger.warning(f"get_calendar 列表元素类型异常: {type(item)}")
self._calendar_cache = copy.deepcopy(normalized)
self._calendar_cache_expire_at = now + self.CALENDAR_CACHE_TTL_SECONDS
return copy.deepcopy(self._calendar_cache)