refactor: code review fixes
Bug fixes: - _extract_cursor: only extract Bottom cursors, preventing Top cursor from corrupting pagination state - _api_request: merge _api_get/_api_post into unified method — POST now has rate-limit code 88 retry (was missing) - fetch_user_likes: add override_base_variables=True Code quality: - Extract BEARER_TOKEN and USER_AGENT into constants.py (was duped in auth.py and client.py) - Add user_profile_to_dict/users_to_json for proper UserProfile serialization (followers/following JSON output was ad-hoc) - Refactor 6 CLI write commands via _write_action helper - Extract _extract_media and _extract_author from _parse_tweet_result - Update CLI module docstring with all 18 commands
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
"""Serialization helpers for Tweet models."""
|
||||
"""Serialization helpers for Tweet and UserProfile models."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from typing import Any, Dict, Iterable, List, Optional
|
||||
|
||||
from .models import Author, Metrics, Tweet, TweetMedia
|
||||
from .models import Author, Metrics, Tweet, TweetMedia, UserProfile
|
||||
|
||||
|
||||
def tweet_to_dict(tweet: Tweet) -> Dict[str, Any]:
|
||||
@@ -129,6 +129,34 @@ def tweets_to_json(tweets: Iterable[Tweet]) -> str:
|
||||
return json.dumps([tweet_to_dict(tweet) for tweet in tweets], ensure_ascii=False, indent=2)
|
||||
|
||||
|
||||
def user_profile_to_dict(user: UserProfile) -> Dict[str, Any]:
|
||||
"""Convert a UserProfile dataclass into a JSON-safe dict."""
|
||||
return {
|
||||
"id": user.id,
|
||||
"name": user.name,
|
||||
"screenName": user.screen_name,
|
||||
"bio": user.bio,
|
||||
"location": user.location,
|
||||
"url": user.url,
|
||||
"followers": user.followers_count,
|
||||
"following": user.following_count,
|
||||
"tweets": user.tweets_count,
|
||||
"likes": user.likes_count,
|
||||
"verified": user.verified,
|
||||
"profileImageUrl": user.profile_image_url,
|
||||
"createdAt": user.created_at,
|
||||
}
|
||||
|
||||
|
||||
def users_to_json(users: Iterable[UserProfile]) -> str:
|
||||
"""Serialize UserProfile objects to pretty JSON."""
|
||||
return json.dumps(
|
||||
[user_profile_to_dict(user) for user in users],
|
||||
ensure_ascii=False,
|
||||
indent=2,
|
||||
)
|
||||
|
||||
|
||||
def _optional_int(value: Any) -> Optional[int]:
|
||||
"""Parse an optional integer value."""
|
||||
if value is None:
|
||||
|
||||
Reference in New Issue
Block a user