52 lines
1.8 KiB
Python
52 lines
1.8 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import json
|
||
|
|
import time
|
||
|
|
from pathlib import Path
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
|
||
|
|
class StickerCache:
|
||
|
|
def __init__(self, cache_dir: str | None = None, max_entries: int = 500):
|
||
|
|
self._cache_dir = Path(cache_dir or str(Path.home() / ".yuxi" / "imessage" / "stickers"))
|
||
|
|
self._max_entries = max_entries
|
||
|
|
self._index: dict[str, dict[str, Any]] = {}
|
||
|
|
self._cache_dir.mkdir(parents=True, exist_ok=True)
|
||
|
|
self._load_index()
|
||
|
|
|
||
|
|
def add(self, sticker_id: str, url: str, metadata: dict[str, Any] | None = None) -> None:
|
||
|
|
entry = {
|
||
|
|
"sticker_id": sticker_id,
|
||
|
|
"url": url,
|
||
|
|
"metadata": metadata or {},
|
||
|
|
"cached_at": time.time(),
|
||
|
|
}
|
||
|
|
self._index[sticker_id] = entry
|
||
|
|
if len(self._index) > self._max_entries:
|
||
|
|
oldest = min(self._index.values(), key=lambda e: e["cached_at"])
|
||
|
|
self._index.pop(oldest["sticker_id"], None)
|
||
|
|
self._save_index()
|
||
|
|
|
||
|
|
def get(self, sticker_id: str) -> dict[str, Any] | None:
|
||
|
|
return self._index.get(sticker_id)
|
||
|
|
|
||
|
|
def get_url(self, sticker_id: str) -> str | None:
|
||
|
|
entry = self._index.get(sticker_id)
|
||
|
|
return entry["url"] if entry else None
|
||
|
|
|
||
|
|
def clear(self) -> None:
|
||
|
|
self._index.clear()
|
||
|
|
self._save_index()
|
||
|
|
|
||
|
|
def _load_index(self) -> None:
|
||
|
|
index_path = self._cache_dir / "sticker_index.json"
|
||
|
|
if index_path.exists():
|
||
|
|
try:
|
||
|
|
self._index = json.loads(index_path.read_text(encoding="utf-8"))
|
||
|
|
except (json.JSONDecodeError, OSError):
|
||
|
|
self._index = {}
|
||
|
|
|
||
|
|
def _save_index(self) -> None:
|
||
|
|
index_path = self._cache_dir / "sticker_index.json"
|
||
|
|
index_path.write_text(json.dumps(self._index, ensure_ascii=False, indent=2), encoding="utf-8")
|