Skip to content

fix(twitter/profile): recover counts + bio after X relocates them out of legacy (#2188) - #2193

Merged
jackwener merged 2 commits into
jackwener:mainfrom
LeoLin990405:fix/twitter-profile-relocated-fields
Jul 29, 2026
Merged

fix(twitter/profile): recover counts + bio after X relocates them out of legacy (#2188)#2193
jackwener merged 2 commits into
jackwener:mainfrom
LeoLin990405:fix/twitter-profile-relocated-fields

Conversation

@LeoLin990405

@LeoLin990405 LeoLin990405 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Problem — #2188

opencli twitter profile <user> returns followers, following, tweets, likes all 0 and an empty bio, while name / screen_name / created_at / verified are correct.

Root cause: X (Twitter) relocated the count fields (followers_count, friends_count, statuses_count, favourites_count) and the bio (description) out of result.legacy into a new container — the same schema drift #1745 already handled for name/created_at by reading result.core. The adapter still read the counts and bio only from result.legacy, so they silently fell back to 0 / ''.

Fix

Rather than hard-code the (unknown, still-shifting) new path, mapTwitterProfileResult now resolves each affected field from its known homes first (legacycore → top-level result), then falls back to a bounded breadth-first search that returns the shallowest match.

Shallowest-wins alone is not safe: when the field is absent from the user object entirely, an unrestricted BFS would descend into an embedded tweet and report its favourites_count as the user's likes, or its text as the bio. So the search refuses to cross into containers that describe a different entity (pinned_tweet, tweet, status, quoted_status, retweeted_status, entities, extended_entities, media, highlights). A wrong-but-confident number is worse than 0 / ''.

  • Restores the counts and bio against the current payload.
  • Stays robust if X relocates these fields yet again.
  • Legacy-path responses (counts still under result.legacy) resolve identically — the existing test is unchanged.

Tests

mapTwitterProfileResult is a pure exported function. Added offline regression tests (12 total in the file):

npx vitest run clis/twitter/profile.test.js   # 12 passed
npm run typecheck                              # clean
npm run check:typed-error-lint                 # new=0
npm run check:silent-column-drop               # new=0

No change to the cli() registration, so cli-manifest.json is untouched.

@LeoLin990405
LeoLin990405 force-pushed the fix/twitter-profile-relocated-fields branch from 9fbf21b to d40e0d9 Compare July 28, 2026 05:53
LeoLin990405 and others added 2 commits July 29, 2026 19:53
… of legacy (jackwener#2188)

`twitter profile` returned followers/following/tweets/likes = 0 and an empty
bio while name/screen_name/created_at/verified stayed correct. X moved the count
fields (followers_count/friends_count/statuses_count/favourites_count) and the
bio (description) out of `result.legacy` into a new container — the same drift
jackwener#1745 handled for name/created_at by reading `result.core`.

Rather than hard-code the (unknown) new path, resolve each field from its known
homes first (legacy → core → top-level result), then fall back to a bounded
breadth-first search that returns the shallowest match. The BFS refuses to cross
into containers describing a *different* entity (pinned_tweet, entities, media,
…) so it can never report an embedded tweet's favourites_count as the user's
likes or its text as the bio — a wrong-but-confident value would be worse than
0 / ''. This restores the counts/bio today and stays robust if X relocates them
again.

Legacy-path responses resolve identically (existing test unchanged). Adds
offline regression tests for the relocated-field case, legacy precedence over a
deeper decoy, the embedded-tweet guard, all-missing fallbacks, and resolver
type/empty handling.
@jackwener
jackwener force-pushed the fix/twitter-profile-relocated-fields branch from d40e0d9 to 8e7ae7c Compare July 29, 2026 11:54
@jackwener
jackwener merged commit 03c0157 into jackwener:main Jul 29, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants