From ce4326ef42edd2ff7dde0da2907de0af7ca586d2 Mon Sep 17 00:00:00 2001 From: jackwener Date: Sat, 14 Mar 2026 13:45:10 +0800 Subject: [PATCH] fix: extract full text from note_tweet for long tweets (fixes #20) Twitter long tweets (>280 chars) store full text in note_tweet.note_tweet_results.result.text rather than legacy.full_text. The parser now prioritizes note_tweet text when available. --- tests/fixtures/home_timeline.json | 7 +++++++ tests/test_parser_fixtures.py | 3 +++ twitter_cli/parser.py | 5 ++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/fixtures/home_timeline.json b/tests/fixtures/home_timeline.json index df44576..978c228 100644 --- a/tests/fixtures/home_timeline.json +++ b/tests/fixtures/home_timeline.json @@ -61,6 +61,13 @@ ] } }, + "note_tweet": { + "note_tweet_results": { + "result": { + "text": "Hello\nworld\n\nThis is the full text of a long tweet that goes beyond the 280 character limit and contains additional content that would be hidden behind Show More in the Twitter UI." + } + } + }, "views": { "count": "1234" } diff --git a/tests/test_parser_fixtures.py b/tests/test_parser_fixtures.py index 7e15afe..8e08a7e 100644 --- a/tests/test_parser_fixtures.py +++ b/tests/test_parser_fixtures.py @@ -26,6 +26,9 @@ def test_parse_home_timeline_fixture(fixture_loader) -> None: assert [tweet.id for tweet in tweets] == ["1", "20"] assert cursor == "cursor-bottom-1" assert tweets[0].media[0].type == "photo" + # note_tweet full text should be preferred over legacy.full_text for long tweets + assert "Show More" in tweets[0].text + assert tweets[0].text.startswith("Hello\nworld\n") assert tweets[0].urls == ["https://example.com/post"] assert tweets[1].is_retweet is True assert tweets[1].retweeted_by == "bob" diff --git a/twitter_cli/parser.py b/twitter_cli/parser.py index 17019b7..bb964a8 100644 --- a/twitter_cli/parser.py +++ b/twitter_cli/parser.py @@ -246,9 +246,12 @@ def parse_tweet_result(result, depth=0): if is_retweet: retweeted_by = user_core.get("screen_name") or user_legacy.get("screen_name", "unknown") + # Prefer note_tweet full text for long tweets ("Show More") + note_text = _deep_get(actual_data, "note_tweet", "note_tweet_results", "result", "text") + return Tweet( id=actual_data.get("rest_id", ""), - text=actual_legacy.get("full_text", ""), + text=note_text or actual_legacy.get("full_text", ""), author=author, metrics=Metrics( likes=_parse_int(actual_legacy.get("favorite_count"), 0),