488e407a65
* feat(twitter): add device-follow command for /i/timeline notification stream (#1628) Closes #1628. Adds the twitter device-follow command, which reads the curated tweet list aggregated under a bell-icon "new posts from @userA and N others" notification. Direct GET /i/timeline redirects to /home, so the data is only reachable via the legacy v1.1 REST endpoint /i/api/2/notifications/device_follow.json , none of the existing twitter commands cover this stream: - twitter timeline home for-you / following feed (different endpoint) - twitter notifications the notification list itself, not aggregated tweets inside any one notification - twitter search search-based, can't reproduce the aggregation Endpoint discovery + field-mapping originally proposed by @traddo in #1628; this PR upstreams a clean implementation that: - Strategy.COOKIE + ct0 from CDP cookie jar + the public web bearer token from clis/twitter/utils.js (same auth path as twitter timeline) - Hits /i/api/2/notifications/device_follow.json directly via page.evaluate fetch on the x.com origin so SameSite=Lax cookies are preserved - Joins each entry.content.item.content.tweet.id to globalObjects.tweets[id] and resolves the author via globalObjects.users[tweet.user_id_str] - Returns the canonical twitter row columns (id, author, text, likes, retweets, replies, views, created_at, url), matching twitter timeline minus has_media / media_urls / card / quoted_tweet which the legacy v1.1 endpoint does not surface - Sets views: null rather than a 0 sentinel; the legacy endpoint does not return view counts even with include_ext_views=true, and the GraphQL TweetResultByRestId round-trip per tweet was judged too expensive for a list command (typed-errors §3: no scalar sentinels that lie about real engagement) - parseLimit enforces strict 1-200 integer validation with no silent clamping; the only baseline addition is the silent-sentinel on the "unknown" author fallback, which matches the exact precedent in twitter/timeline.js:76 that is already baselined Tests: 17 unit tests in device-follow.test.js cover parseLimit strict validation, URL parameter shape, entry/tweet join, user-resolution fallback, dedup via the seen set, empty-stream shape, the canonical column registration, AuthRequiredError on missing ct0, and CommandExecutionError on non-2xx fetch. Live verified the endpoint shape end-to-end against the logged-in session: HTTP 200 with the expected {globalObjects: {tweets, users}, timeline: {id: 'tweet_notifications', instructions: [{addEntries: {entries: []}}]}} envelope. The tester account has no bell-notification follows enabled, so entries is empty, but the shape and auth path are confirmed against the documented spec. * fix(twitter): harden device-follow typed boundaries * fix(twitter): fail fast on device-follow drift --------- Co-authored-by: jackwener <jakevingoo@gmail.com>