Files
twitter-cli-cookiefile/twitter_cli/cache.py
jackwener c5f16e4532 fix: improve show command cache design and reliability
- Merge get_tweet_id_by_index + get_cache_size into resolve_cached_tweet
  to eliminate redundant file IO on cache miss
- Move save_tweet_cache before emit_structured so --json/--yaml modes
  also persist the cache for subsequent show commands
- Extract _print_show_hint helper to reduce duplication
- Add trailing newline to cache.py
2026-03-14 04:08:43 +08:00

66 lines
2.2 KiB
Python

"""Short-index cache: persist the last displayed tweet list for quick `show` access."""
from __future__ import annotations
import json
import logging
import time
from pathlib import Path
from typing import List, Optional, Tuple
from .models import Tweet
logger = logging.getLogger(__name__)
_CACHE_DIR = Path.home() / ".twitter-cli"
_CACHE_FILE = _CACHE_DIR / "last_results.json"
_TTL = 3600 # seconds
def save_tweet_cache(tweets: List[Tweet]) -> None:
"""Persist tweet list so indices can be resolved by `show`."""
try:
_CACHE_DIR.mkdir(parents=True, exist_ok=True)
entries = [
{"index": i + 1, "id": t.id, "author": t.author.screen_name, "text": t.text[:80]}
for i, t in enumerate(tweets)
if t.id
]
payload = {"created_at": time.time(), "tweets": entries}
_CACHE_FILE.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")
except OSError as exc:
logger.debug("Failed to write tweet cache: %s", exc)
def _load_cache() -> Optional[List[dict]]:
"""Load and validate the cache file; return tweet entries or None if stale/missing."""
try:
if not _CACHE_FILE.exists():
return None
payload = json.loads(_CACHE_FILE.read_text(encoding="utf-8"))
if not isinstance(payload, dict):
return None
if time.time() - payload.get("created_at", 0) > _TTL:
return None
entries = payload.get("tweets", [])
if not isinstance(entries, list):
return None
return [e for e in entries if isinstance(e, dict)]
except (OSError, json.JSONDecodeError):
return None
def resolve_cached_tweet(index: int) -> Tuple[Optional[str], int]:
"""Resolve a 1-based index to a tweet ID, returning (tweet_id, cache_size).
Returns (tweet_id, cache_size) where tweet_id is None if the index
cannot be resolved (empty/expired cache or out-of-range index).
"""
entries = _load_cache()
if entries is None:
return None, 0
for entry in entries:
if entry.get("index") == index:
tweet_id = entry.get("id")
return (str(tweet_id) if tweet_id is not None else None), len(entries)
return None, len(entries)