import json from datetime import datetime, timedelta from typing import Any from astrbot.api import logger from ..sqlite import AsyncSQLiteDB class JSONCacheRepository: """基于 achievement_cache 表的通用 JSON 缓存。""" def __init__(self, database: AsyncSQLiteDB): self._database = database async def get( self, key: str, *, max_age: timedelta = timedelta(days=30), ) -> tuple[Any | None, bool]: try: row = await self._database.select_one( "achievement_cache", "key=?", (key,), ) except Exception as exc: logger.error(f"读取 JSON 缓存失败: key={key}, error={exc}") return None, True if not row: return None, True try: payload = json.loads(row.get("content", "{}")) updated_at = datetime.strptime( row.get("updated_at", ""), "%Y-%m-%d %H:%M:%S", ) except (json.JSONDecodeError, TypeError, ValueError) as exc: logger.error(f"解析 JSON 缓存失败: key={key}, error={exc}") return None, True return payload, datetime.now() - updated_at > max_age async def set(self, key: str, payload: Any) -> None: try: content = json.dumps(payload, ensure_ascii=False) except (TypeError, ValueError) as exc: logger.error(f"序列化 JSON 缓存失败: key={key}, error={exc}") return try: await self._database.execute( """ INSERT INTO achievement_cache (key, content, updated_at) VALUES (?, ?, ?) ON CONFLICT(key) DO UPDATE SET content=excluded.content, updated_at=excluded.updated_at """, ( key, content, datetime.now().strftime("%Y-%m-%d %H:%M:%S"), ), ) except Exception as exc: logger.error(f"写入 JSON 缓存失败: key={key}, error={exc}")