Commit Graph

134 Commits

Author SHA1 Message Date
Lucius
7816f8d813 Feed cursor pagination (#49)
* Expose promoted tweets in feed output

* Add cursor-based feed pagination output
2026-04-10 01:20:18 +08:00
jakevin
e3545ab069 Merge pull request #44 from alextuan1024/fix/article-inline-hyperlinks
fix: preserve inline hyperlinks in article markdown
2026-03-21 17:48:14 +08:00
jackwener
b752c31dfd improve: add early return, escape markdown brackets in labels and parentheses in URLs
- Early return when no entityRanges (skip unnecessary processing)
- Escape [ and ] in link labels to prevent nested bracket issues
- Encode ) in URLs as %29 to prevent malformed markdown links (e.g. Wikipedia)
- Add 3 new test cases for the above edge cases
2026-03-21 17:48:02 +08:00
alextuan1024
b7c7ef826c test(article): cover hyperlink parser edge cases 2026-03-21 14:07:59 +08:00
alextuan1024
c63b5a2ede fix(article): preserve inline hyperlinks in markdown export 2026-03-21 13:34:35 +08:00
jackwener
199a1490f9 fix: SearchTimeline POST + ondemand URL guard + refresh queryIds
Twitter migrated SearchTimeline from GET to POST; update fetch_search
to route through _graphql_post via a new use_post flag on _fetch_timeline,
avoiding duplicating the pagination logic (closes #39, refs #40, #42).

Also guard against get_ondemand_file_url returning None so the error
message is clear instead of crashing on NoneType.split (closes #43-adjacent).

Refresh all FALLBACK_QUERY_IDS from live JS bundles — 18 operations updated.
2026-03-20 18:21:29 +08:00
jackwener
7b8a7dd5de chore bump lockfile version to 0.8.6 2026-03-17 22:54:01 +08:00
jackwener
9b854e6aa6 fix cli article output and reply-to parsing 2026-03-17 22:53:07 +08:00
jakevin
ad40848c18 feat: render article inline images as markdown (#38)
* feat: render article inline images as markdown

* fix: support list-style article entity maps

* test: add real-world article image fixtures

* fix: preserve article markdown blocks with inline images

Co-authored-by: alextuan1024 <alextuan1024@gmail.com>

---------

Co-authored-by: alextuan1024 <alextuan1024@gmail.com>
2026-03-17 18:13:52 +08:00
jackwener
fb1a9b1564 review: preserve subscriber-only flag for retweets 2026-03-17 18:10:04 +08:00
Tao BAI
66115a4837 feat: detect subscriber-only tweets via tweetInterstitial (#33)
Extract visibility metadata from TweetWithVisibilityResults wrapper
before unwrapping. Adds is_subscriber_only field to Tweet model,
with full serialization roundtrip and test coverage.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 18:09:15 +08:00
alextuan1024
90f0635c50 feat: preserve article atomic markdown blocks (#37)
* fix: preserve atomic markdown blocks in articles

* test: add parser unit coverage for article markdown blocks
2026-03-17 18:06:02 +08:00
jackwener
8cb5824ed4 build: bump twitter-cli version to 0.8.5 2026-03-17 18:04:27 +08:00
jackwener
25d5a7b73a review: fix bookmark folders CLI option handling 2026-03-17 18:01:35 +08:00
benny b
ffd2a42f7c feat: add bookmark folders support (#30)
Add `twitter bookmarks folders` command to list bookmark folders
and `twitter bookmarks folders <id>` to fetch tweets from a specific
folder, with --since date filtering and pagination support.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 17:59:08 +08:00
jackwener
e496d8f870 refactor: unify exception handling, add ISO 8601 time, dedup commands, expand tests
- Replace _error_code_for_message() string matching with error_code attribute on exception classes
- Add error_code to all TwitterError subclasses (AuthenticationError, RateLimitError, etc.)
- Add InvalidInputError exception class
- TwitterAPIError derives error_code from HTTP status code automatically
- auth.py: use AuthenticationError instead of RuntimeError
- cli.py: catch (TwitterError, RuntimeError) for backward compat
- Extract _fetch_and_display_users() to deduplicate followers/following commands
- Add format_iso8601() to timeutil.py
- Add createdAtISO field to tweet and user profile serialization
- New test files: test_output.py, test_cache.py, test_timeutil.py
- Expand test_filter.py (topN, score mode, custom weights, empty input)
- Tests: 152 → 194 unit tests, all passing
2026-03-16 18:24:35 +08:00
jackwener
0b91e66998 fix(windows): add ensure_utf8_streams() for Windows GBK encoding + ConPTY docs
- Add ensure_utf8_streams() in output.py: reconfigures stdout/stderr to UTF-8
  on Windows at CLI startup, fixing emoji UnicodeEncodeError on GBK locales
- Call ensure_utf8_streams() in cli() entry point — one-line fix for all
  output paths (click.echo, rich Console, print)
- Add Windows ConPTY troubleshooting to README (English + Chinese):
  document Git Bash workaround, ConPTY pipe capture issue, and encoding notes

Ref: #29 (issuecomment-4065690862)
2026-03-16 17:59:33 +08:00
jackwener
74386cebc8 fix: Windows cookie diagnostics (#28) and rich output pipe capture (#29)
- Add win32 branch in _diagnose_keychain_issues() with DPAPI/admin/shadowcopy hints
- Add _make_console() helper in formatter.py with force_terminal=False for Windows non-TTY
- Replace all 6 Console() defaults with _make_console()
- Add test for Windows-specific diagnostics
2026-03-16 14:27:53 +08:00
jackwener
07e7f83e6f chore: code review cleanup + bump v0.8.4
- Remove _get_client_for_output() compat shim (replaced by direct _get_client calls)
- Remove unused inspect import
- Fix redundant branch in constants.get_accept_language()
- Add TWITTER_BROWSER docs to README (en + zh)
- Update all test monkeypatch signatures
- Bump version to 0.8.4
2026-03-15 19:29:34 +08:00
jackwener
d612066bef feat(auth): add TWITTER_BROWSER env var to specify browser preference
Add TWITTER_BROWSER environment variable to allow users to control
which browser's cookies are prioritized during extraction.

Example: TWITTER_BROWSER=chrome twitter feed

Supported values: arc, chrome, edge, firefox, brave.
The specified browser is moved to the front of the extraction order.

Also adds AGENTS.md developer guide for AI coding assistants.

Co-authored-by: Agassi <413855+agassiyzh@users.noreply.github.com>
2026-03-15 19:09:35 +08:00
jackwener
165bb65048 build: bump twitter-cli version to 0.8.3 in uv.lock 2026-03-14 23:38:03 +08:00
jackwener
fefadc2ea1 ci: remove deprecated ClawHub publish workflow 2026-03-14 20:23:38 +08:00
jackwener
a0a786d71f fix(ci): remove unused import os (F401) 2026-03-14 20:20:29 +08:00
jackwener
18721e7967 docs: deprecate ClawHub install method, recommend Skills CLI instead 2026-03-14 20:05:26 +08:00
jackwener
eec439a801 fix: remove 200-char truncation on quoted tweet in detail view 2026-03-14 20:03:20 +08:00
jackwener
4b94b769ba docs: add npx skills install method for AI agent skill setup 2026-03-14 20:01:41 +08:00
jackwener
ce4326ef42 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.
2026-03-14 13:45:10 +08:00
jackwener
7de8ad0fbd refactor: remove doctor command 2026-03-14 13:41:59 +08:00
jackwener
e0f38cbbb1 fix(ci): restore FALLBACK_QUERY_IDS import, remove unused patch import 2026-03-14 13:32:28 +08:00
jackwener
e64888083e chore: bump version to 0.8.2 2026-03-14 13:28:01 +08:00
jakevin
391a2195f5 Merge pull request #23 from jackwener/fix/improvements-v0.8.2
fix: P0 Windows Edge path, time localization, show --output, cleanup tech debt
2026-03-14 13:27:16 +08:00
jackwener
ec4589c2d1 fix: P0 Windows Edge path, add time localization, show --output, cleanup tech debt
- Fix auth.py subprocess script Windows Edge cookie path inconsistency
- Add timeutil.py for UTC→local time and relative time conversion
- Integrate time localization into formatter.py and serialization.py
- Add --output/-o option to show command for saving tweet detail as JSON
- Remove constants.py legacy aliases (USER_AGENT, SEC_CH_UA)
- Remove client.py backward-compat delegation methods and re-exports
- Update test imports to use parser module directly
2026-03-14 13:26:36 +08:00
jackwener
80e5a62890 chore: bump version to 0.8.1 2026-03-14 04:13:02 +08:00
jakevin
57ae73b4cf Merge pull request #22 from jackwener/fix/show-command-improvements
fix: improve show command cache design and reliability
2026-03-14 04:12:18 +08:00
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
jakevin
0da8101c2f Merge pull request #18 from Pleasurecruise/main
feat: add `show` command with short-index cache
2026-03-14 04:06:47 +08:00
jackwener
b77f1ffe14 docs: align SKILL.md version to 0.8.0 2026-03-13 14:13:41 +08:00
Pleasurecruise
72f62cedea fix: improve show handling, cache validation and tests
Add extensive tests for the `show` command (happy path, empty/expired/malformed cache, out-of-range, zero/negative indices) and a test helper to write cache fixtures. Harden twitter_cli.cache._load_cache to validate payload types (dict/tweets list), filter non-dict entries, and treat malformed payloads as empty; also handle missing tweet id when resolving an index. Refactor CLI output logic by extracting _emit_tweet_detail and reuse it for both `tweet` and `show`; enforce 1-based indices for `show` via click.IntRange(1) and expand the "no cached results" error text to mention other list commands. These changes improve robustness against corrupted caches and increase test coverage for cache-based behavior.
2026-03-12 22:26:52 +00:00
Pleasurecruise
5335516d57 feat: add show command with short-index cache
Persist last displayed tweet lists and allow opening a tweet by index.

- Add twitter_cli/cache.py: stores a short-index cache (~/.twitter-cli/last_results.json) with a 1h TTL and helpers to resolve index->tweet-id and cache size.
- Update twitter_cli/cli.py: save list results to cache, display a hint, and add `twitter show <N>` command which fetches a tweet by cached index and prints detail/replies (supports --full-text, --json, structured output, and max replies).
- Update README.md and SKILL.md to document the new `show` usage.
- Add .idea/ to .gitignore and bump package version in uv.lock to 0.8.0.

This change makes it easy to open items from the last feed/search without copying IDs.
2026-03-12 22:12:27 +00:00
jackwener
41d8ad676e docs: update README and SKILL.md with image upload support
- Add image upload to Features lists (EN + CN)
- Add --image/-i usage examples to Usage sections
- Add 'Post with images' agent workflow in SKILL.md
- Update Limitations: 'text only' → 'images only (no video yet)'
2026-03-13 02:03:03 +08:00
jackwener
e9dfae30df chore: bump version to v0.8.0 2026-03-13 02:01:35 +08:00
jackwener
69cb85a1c2 feat: add image upload support for post/reply/quote commands
- Add upload_media() method to TwitterClient (INIT/APPEND/FINALIZE flow
  via upload.twitter.com, supports JPEG/PNG/GIF/WebP up to 5MB)
- Extend create_tweet() and quote_tweet() with optional media_ids param
- Add --image/-i option to post, reply, and quote CLI commands (max 4)
- Add MediaUploadError exception for upload-specific error handling
- Add 6 unit tests covering upload flow, validation, and media_ids

Co-Authored-By: Catafal <67582323+Catafal@users.noreply.github.com>
2026-03-13 01:59:42 +08:00
jackwener
7d1b519c85 fix: harden search validation and release v0.7.1 2026-03-13 01:04:29 +08:00
jackwener
dc832f2ee2 feat: add advanced search options (--from, --to, --lang, --since, --until, --has, --exclude, --min-likes, --min-retweets)
Closes #17

- New search.py query builder module
- QUERY argument now optional when using advanced filters
- 21 unit tests + 3 CLI integration tests for search
- Bumped version to 0.7.0
2026-03-13 00:15:53 +08:00
jackwener
502cd28a40 chore: release v0.6.6 2026-03-12 14:53:03 +08:00
jackwener
00d18686dd fix: remove unused client import 2026-03-12 14:48:35 +08:00
jakevin
79eadd2579 feat: add twitter article markdown command (#16) 2026-03-12 14:47:49 +08:00
jackwener
1c0e4b0c39 chore: release v0.6.5 2026-03-11 21:00:51 +08:00
jackwener
1313eb0be1 feat: add full-text option for tweet tables 2026-03-11 20:58:12 +08:00
jackwener
88a9f4ce97 fix: tighten pagination and platform-specific auth 2026-03-11 20:32:51 +08:00