Commit Graph

110 Commits

Author SHA1 Message Date
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
jackwener
74f06638ee fix: resolve lint errors (E741 ambiguous var, F401 unused import) 2026-03-11 17:33:36 +08:00
jackwener
a139b1052c chore: bump version to 0.6.4 2026-03-11 17:09:35 +08:00
jackwener
1de88ea2ed fix: update Likes queryId and response path (fixes #8)
- Update Likes fallback queryId: aeJWz7GtGNHHO2Z3GrjCWg -> dv5-II7_Bup_PHish7p6fw
- Fix response path: data.user.result.timeline.timeline.instructions
  (Twitter renamed timeline_v2 to timeline; code now tries both)
- Verified via Playwright: API returns 200 with correct tweet entries

Fixes #8
2026-03-11 17:08:14 +08:00
jackwener
60e1e7c580 feat: improve cookie extraction diagnostics and add doctor command
- Add _diagnose_keychain_issues() for macOS Keychain/SSH detection
- Extraction functions now return (cookies, diagnostics) tuples
- Error messages include actionable Keychain hints (e.g. unlock-keychain)
- Add 'twitter doctor' diagnostic command for troubleshooting
- Enhance bug_report.yml with browser/access method/diagnostics fields
- Expand README troubleshooting (EN+CN) with Keychain/SSH solutions
- Add 5 new tests for Keychain diagnostics

Closes #11
2026-03-11 16:53:06 +08:00
jackwener
47be88e62d fix: use importlib.metadata for __version__ (was hardcoded stale) 2026-03-11 14:11:07 +08:00
jackwener
e96d5142f2 chore: bump version to 0.6.2 2026-03-11 13:36:22 +08:00
jackwener
9f735cb96b chore: Update twitter-cli package version to 0.6.1 in uv.lock. 2026-03-11 13:29:31 +08:00
jackwener
d3441cf6ad chore: bump version to v0.6.1 2026-03-11 13:09:11 +08:00
jackwener
3a50be26af chore: add GitHub issue templates (bug report + feature request) 2026-03-11 13:04:21 +08:00
jackwener
6d6108436f chore: bump version to 0.6.0
Changes since 0.5.1:
- feat: Chrome multi-profile cookie extraction (#6)
- fix: warn on private likes (#8)
- fix: add logger definition (CI fix)
- refactor: specific ImportError handling (#10)
- docs: upgrade instructions in README and SKILL.md
2026-03-11 12:57:34 +08:00
jackwener
53a700ec60 feat: support Chrome multi-profile cookie extraction
Auto-iterates all Chrome/Arc/Edge/Brave profiles (Default, Profile 1,
Profile 2, ...) to find Twitter cookies. Falls back to the default
browser_cookie3 behavior when no profile dirs are found.

Set TWITTER_CHROME_PROFILE env var to specify a profile explicitly:
  TWITTER_CHROME_PROFILE='Profile 2' twitter feed

Closes #6
2026-03-11 12:53:25 +08:00
jackwener
84504b1477 docs: add upgrade instructions to README and SKILL.md 2026-03-11 12:43:51 +08:00
jackwener
93840ba99b fix: add logger definition to cli.py (fix CI lint F821) 2026-03-11 12:37:28 +08:00
aidiff-kobe
f01ce77f20 refactor: Use specific ImportError instead of broad Exception (#10)
Changed the exception handling in _best_chrome_target() to catch
specific ImportError instead of broad Exception. This improves
code clarity and avoids masking unexpected errors.

Also added a debug log message to help diagnose when curl_cffi
is not available.

Co-authored-by: Security Bot <agent@example.com>
2026-03-11 12:36:13 +08:00
jackwener
e9efa11fa5 fix: warn when querying other users' likes (private since Jun 2024)
Twitter/X made all likes private since June 2024. The likes command now:
- Detects if the target user differs from the authenticated user
- Shows a clear warning that only your own likes are visible
- Updated SKILL.md and README.md with likes privacy limitation

Closes #8
2026-03-11 12:34:17 +08:00
jackwener
f31830f058 fix: fix ClawHub publish workflow
- Add export VERSION (NODE_ENV was not getting version)
- Fix API endpoint: api.clawhub.io → clawhub.ai
- Add NODE_TLS_REJECT_UNAUTHORIZED=0 for SSL cert issue
2026-03-11 01:11:54 +08:00
jackwener
e38f2033e9 chore: bump version to 0.5.1 2026-03-11 00:45:55 +08:00
jackwener
1f267008ad fix: update stale Followers/Following queryIds and retry on 422
Twitter now returns HTTP 422 GRAPHQL_VALIDATION_FAILED (not just 404)
when a queryId goes stale. Updated fallback IDs and added 422 to the
stale-queryId retry logic in both _graphql_get and _graphql_post.
2026-03-11 00:45:13 +08:00
jackwener
5c1015f1fd fix: handle changed /account/multi/list.json response format
Twitter changed the response format from a list with nested 'user'
objects to {"users": [{user_id, name, screen_name, ...}]} with
minimal fields. Now extracts screen_name from the new format and
fetches the full profile via GraphQL UserByScreenName endpoint.
2026-03-11 00:40:07 +08:00
jackwener
8505428264 docs: update cross-references (xhs-cli → xiaohongshu-cli) 2026-03-11 00:33:14 +08:00
jackwener
34d2491ba2 chore: bump version to 0.5.0
- refactor: split client.py into graphql.py + parser.py
- refactor: structured exception hierarchy (exceptions.py)
- feat: integration smoke tests
- docs: updated project structure
2026-03-11 00:30:19 +08:00
jackwener
21b4c28d63 docs: update project structure in README (add graphql.py, parser.py, exceptions.py, output.py) 2026-03-10 23:45:14 +08:00
jackwener
f125d0fe7f refactor: replace all RuntimeError with specific exception types
- 5x RuntimeError → TwitterAPIError (create_tweet, fetch_me, quote_tweet, follow/unfollow)
- 2x RuntimeError(str(exc)) → bare raise (preserve original TwitterAPIError in _graphql_get/post)
2026-03-10 23:32:10 +08:00
jackwener
c2b9be4669 refactor: split client.py into graphql.py + parser.py modules
Split the monolithic client.py (1341 lines) into three focused modules:

- graphql.py (~200 lines): queryId resolution, URL building, JS bundle
  scanning, feature flag management
- parser.py (~270 lines): Tweet/User/Media/Article parsing, utility functions
  (_deep_get, _parse_int, _extract_cursor, _extract_media)
- client.py (~700 lines): TwitterClient class with HTTP engine, anti-detection,
  session management, and all public API methods

Backward compatibility: client.py re-exports all previously public symbols
so existing test imports work without modification. 88/88 tests pass.
2026-03-10 23:18:59 +08:00