Merge pull request #22 from jackwener/fix/show-command-improvements

fix: improve show command cache design and reliability
This commit is contained in:
jakevin
2026-03-14 04:12:18 +08:00
committed by GitHub
2 changed files with 24 additions and 19 deletions

View File

@@ -6,7 +6,7 @@ import json
import logging import logging
import time import time
from pathlib import Path from pathlib import Path
from typing import List, Optional from typing import List, Optional, Tuple
from .models import Tweet from .models import Tweet
@@ -50,19 +50,17 @@ def _load_cache() -> Optional[List[dict]]:
return None return None
def get_tweet_id_by_index(index: int) -> Optional[str]: def resolve_cached_tweet(index: int) -> Tuple[Optional[str], int]:
"""Return tweet ID at *index* (1-based), or None if not found.""" """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() entries = _load_cache()
if entries is None: if entries is None:
return None return None, 0
for entry in entries: for entry in entries:
if entry.get("index") == index: if entry.get("index") == index:
tweet_id = entry.get("id") tweet_id = entry.get("id")
return str(tweet_id) if tweet_id is not None else None return (str(tweet_id) if tweet_id is not None else None), len(entries)
return None return None, len(entries)
def get_cache_size() -> int:
"""Return number of tweets in the current cache (0 if unavailable)."""
entries = _load_cache()
return len(entries) if entries is not None else 0

View File

@@ -45,7 +45,7 @@ from rich.console import Console
from . import __version__ from . import __version__
from .auth import get_cookies from .auth import get_cookies
from .cache import get_cache_size, get_tweet_id_by_index, save_tweet_cache from .cache import resolve_cached_tweet, save_tweet_cache
from .client import TwitterClient from .client import TwitterClient
from .config import load_config from .config import load_config
from .filter import filter_tweets from .filter import filter_tweets
@@ -349,17 +349,18 @@ def _fetch_and_display(fetch_fn, label, emoji, max_count, as_json, as_yaml, outp
click.echo(tweets_to_compact_json(filtered)) click.echo(tweets_to_compact_json(filtered))
return return
save_tweet_cache(filtered)
if emit_structured(tweets_to_data(filtered), as_json=as_json, as_yaml=as_yaml): if emit_structured(tweets_to_data(filtered), as_json=as_json, as_yaml=as_yaml):
return return
save_tweet_cache(filtered)
print_tweet_table( print_tweet_table(
filtered, filtered,
console, console,
title="%s %s%d tweets" % (emoji, label, len(filtered)), title="%s %s%d tweets" % (emoji, label, len(filtered)),
full_text=full_text, full_text=full_text,
) )
console.print("[dim]💡 Use `twitter show <N>` to view tweet #N from this list.[/dim]") _print_show_hint()
console.print() console.print()
@@ -443,14 +444,15 @@ def feed(ctx, feed_type, max_count, as_json, as_yaml, input_file, output_file, d
click.echo(tweets_to_compact_json(filtered)) click.echo(tweets_to_compact_json(filtered))
return return
save_tweet_cache(filtered)
if emit_structured(tweets_to_data(filtered), as_json=as_json, as_yaml=as_yaml): if emit_structured(tweets_to_data(filtered), as_json=as_json, as_yaml=as_yaml):
return return
title = "👥 Following" if feed_type == "following" else "📱 Twitter" title = "👥 Following" if feed_type == "following" else "📱 Twitter"
title += "%d tweets" % len(filtered) title += "%d tweets" % len(filtered)
save_tweet_cache(filtered)
print_tweet_table(filtered, console, title=title, full_text=full_text) print_tweet_table(filtered, console, title=title, full_text=full_text)
console.print("[dim]💡 Use `twitter show <N>` to view tweet #N from this list.[/dim]") _print_show_hint()
console.print() console.print()
@@ -725,6 +727,12 @@ def _emit_tweet_detail(tweets, compact, as_json, as_yaml, full_text):
console.print() console.print()
def _print_show_hint():
# type: () -> None
"""Print a hint about the `show` command."""
console.print("[dim]💡 Use `twitter show <N>` to view tweet #N from this list.[/dim]")
@cli.command() @cli.command()
@click.argument("index", type=click.IntRange(1)) @click.argument("index", type=click.IntRange(1))
@click.option("--max", "-n", "max_count", type=int, default=None, help="Max replies to fetch.") @click.option("--max", "-n", "max_count", type=int, default=None, help="Max replies to fetch.")
@@ -736,9 +744,8 @@ def show(ctx, index, max_count, full_text, as_json, as_yaml):
"""View tweet #INDEX from the last feed/search results.""" """View tweet #INDEX from the last feed/search results."""
compact = ctx.obj.get("compact", False) compact = ctx.obj.get("compact", False)
tweet_id = get_tweet_id_by_index(index) tweet_id, cache_size = resolve_cached_tweet(index)
if tweet_id is None: if tweet_id is None:
cache_size = get_cache_size()
if cache_size == 0: if cache_size == 0:
raise click.UsageError( raise click.UsageError(
"No cached results found. Run `twitter feed`, `twitter search`, " "No cached results found. Run `twitter feed`, `twitter search`, "