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.
This commit is contained in:
@@ -418,16 +418,38 @@ class TwitterClient:
|
||||
|
||||
def fetch_me(self):
|
||||
# type: () -> UserProfile
|
||||
"""Fetch the currently authenticated user's profile."""
|
||||
"""Fetch the currently authenticated user's profile.
|
||||
|
||||
Twitter's /account/multi/list.json endpoint changed its response format:
|
||||
- Old: list of dicts with nested "user" objects (rich fields)
|
||||
- New: {"users": [...]} with minimal fields (user_id, name, screen_name)
|
||||
|
||||
When the response only has minimal fields, we use the screen_name to
|
||||
fetch the full profile via the GraphQL UserByScreenName endpoint.
|
||||
"""
|
||||
url = "https://x.com/i/api/1.1/account/multi/list.json"
|
||||
data = self._api_get(url)
|
||||
if isinstance(data, list) and data:
|
||||
|
||||
screen_name = None
|
||||
|
||||
# New format: {"users": [{"user_id": ..., "screen_name": ..., ...}]}
|
||||
if isinstance(data, dict) and "users" in data:
|
||||
users = data["users"]
|
||||
if isinstance(users, list) and users:
|
||||
user_data = users[0]
|
||||
screen_name = user_data.get("screen_name")
|
||||
|
||||
# Old format: [{"user": {"id_str": ..., ...}}]
|
||||
elif isinstance(data, list) and data:
|
||||
user_data = data[0].get("user", {})
|
||||
if user_data:
|
||||
# Old format had rich fields — try to build profile directly
|
||||
sn = user_data.get("screen_name", "")
|
||||
if user_data.get("followers_count") is not None:
|
||||
return UserProfile(
|
||||
id=str(user_data.get("id_str", "")),
|
||||
name=user_data.get("name", ""),
|
||||
screen_name=user_data.get("screen_name", ""),
|
||||
screen_name=sn,
|
||||
bio=user_data.get("description", ""),
|
||||
location=user_data.get("location", ""),
|
||||
url=_deep_get(user_data, "entities", "url", "urls", 0, "expanded_url") or "",
|
||||
@@ -439,6 +461,13 @@ class TwitterClient:
|
||||
profile_image_url=user_data.get("profile_image_url_https", ""),
|
||||
created_at=user_data.get("created_at", ""),
|
||||
)
|
||||
screen_name = sn
|
||||
|
||||
# Use screen_name to fetch full profile via GraphQL
|
||||
if screen_name:
|
||||
logger.info("Fetching full profile for @%s via GraphQL", screen_name)
|
||||
return self.fetch_user(screen_name)
|
||||
|
||||
raise TwitterAPIError(0, "Failed to fetch current user info")
|
||||
|
||||
def quote_tweet(self, tweet_id, text):
|
||||
|
||||
Reference in New Issue
Block a user