From fd9ed5763703a9abc44b05fe671e2c0a60d961b1 Mon Sep 17 00:00:00 2001 From: wlt233 <1486185683@qq.com> Date: Mon, 26 May 2025 11:12:37 +0800 Subject: [PATCH] fix bug: replace api with AsyncClient --- src/twi_api.py | 57 ++++++++++++++++++++++++++------------------------ src/twitter.py | 2 +- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/twi_api.py b/src/twi_api.py index 09eca3c..119517e 100644 --- a/src/twi_api.py +++ b/src/twi_api.py @@ -78,7 +78,7 @@ def login(): @retry(tries=3, delay=5) -def get_list(list_id): +async def get_list(list_id): logger.info(f"Getting list https://x.com/i/lists/{list_id}") with open("./config/config.json", "r", encoding="utf-8") as f: config = json.load(f) with open("./config/headers.json", "r", encoding="utf-8") as f: headers = json.load(f) @@ -88,23 +88,24 @@ def get_list(list_id): 'variables': '{"listId":"' + str(list_id) + '","count":20}', 'features': '{"rweb_video_screen_enabled":false,"profile_label_improvements_pcf_label_in_post_enabled":true,"rweb_tipjar_consumption_enabled":true,"verified_phone_label_enabled":false,"creator_subscriptions_tweet_preview_api_enabled":true,"responsive_web_graphql_timeline_navigation_enabled":true,"responsive_web_graphql_skip_user_profile_image_extensions_enabled":false,"premium_content_api_read_enabled":false,"communities_web_enable_tweet_community_results_fetch":true,"c9s_tweet_anatomy_moderator_badge_enabled":true,"responsive_web_grok_analyze_button_fetch_trends_enabled":false,"responsive_web_grok_analyze_post_followups_enabled":true,"responsive_web_jetfuel_frame":false,"responsive_web_grok_share_attachment_enabled":true,"articles_preview_enabled":true,"responsive_web_edit_tweet_api_enabled":true,"graphql_is_translatable_rweb_tweet_is_translatable_enabled":true,"view_counts_everywhere_api_enabled":true,"longform_notetweets_consumption_enabled":true,"responsive_web_twitter_article_tweet_consumption_enabled":true,"tweet_awards_web_tipping_enabled":false,"responsive_web_grok_show_grok_translated_post":false,"responsive_web_grok_analysis_button_from_backend":true,"creator_subscriptions_quote_tweet_preview_enabled":false,"freedom_of_speech_not_reach_fetch_enabled":true,"standardized_nudges_misinfo":true,"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled":true,"longform_notetweets_rich_text_read_enabled":true,"longform_notetweets_inline_media_enabled":true,"responsive_web_grok_image_annotation_enabled":true,"responsive_web_enhance_cards_enabled":false}', } - resp = httpx.get( - 'https://x.com/i/api/graphql/XYC5oRL-TmZ4zwomyY6T-g/ListLatestTweetsTimeline', - params=params, - headers=headers, - proxy=config["proxy"] if "proxy" in config else None, - ) - if resp.status_code != 200: - logger.error(f"Error fetching list {list_id}: {resp.status_code} {resp.text}") - os.remove("./config/headers.json") - return None - logger.info(f"Got {list_id}") - return resp.json() - + + async with httpx.AsyncClient(proxy=config["proxy"] if "proxy" in config else None) as client: + resp = await client.get( + 'https://x.com/i/api/graphql/XYC5oRL-TmZ4zwomyY6T-g/ListLatestTweetsTimeline', + params=params, + headers=headers + ) + if resp.status_code != 200: + logger.error(f"Error fetching list {list_id}: {resp.status_code} {resp.text}") + os.remove("./config/headers.json") + return None + logger.info(f"Got {list_id}") + return resp.json() + return None @retry(tries=3, delay=5) -def get_detail(tweet_id): +async def get_detail(tweet_id): logger.info(f"Getting tweet detail https://x.com/{{}}/status/{tweet_id}") with open("./config/config.json", "r", encoding="utf-8") as f: config = json.load(f) with open("./config/headers.json", "r", encoding="utf-8") as f: headers = json.load(f) @@ -115,15 +116,17 @@ def get_detail(tweet_id): 'features': '{"rweb_video_screen_enabled":false,"profile_label_improvements_pcf_label_in_post_enabled":true,"rweb_tipjar_consumption_enabled":true,"verified_phone_label_enabled":false,"creator_subscriptions_tweet_preview_api_enabled":true,"responsive_web_graphql_timeline_navigation_enabled":true,"responsive_web_graphql_skip_user_profile_image_extensions_enabled":false,"premium_content_api_read_enabled":false,"communities_web_enable_tweet_community_results_fetch":true,"c9s_tweet_anatomy_moderator_badge_enabled":true,"responsive_web_grok_analyze_button_fetch_trends_enabled":false,"responsive_web_grok_analyze_post_followups_enabled":true,"responsive_web_jetfuel_frame":false,"responsive_web_grok_share_attachment_enabled":true,"articles_preview_enabled":true,"responsive_web_edit_tweet_api_enabled":true,"graphql_is_translatable_rweb_tweet_is_translatable_enabled":true,"view_counts_everywhere_api_enabled":true,"longform_notetweets_consumption_enabled":true,"responsive_web_twitter_article_tweet_consumption_enabled":true,"tweet_awards_web_tipping_enabled":false,"responsive_web_grok_show_grok_translated_post":false,"responsive_web_grok_analysis_button_from_backend":true,"creator_subscriptions_quote_tweet_preview_enabled":false,"freedom_of_speech_not_reach_fetch_enabled":true,"standardized_nudges_misinfo":true,"tweet_with_visibility_results_prefer_gql_limited_actions_policy_enabled":true,"longform_notetweets_rich_text_read_enabled":true,"longform_notetweets_inline_media_enabled":true,"responsive_web_grok_image_annotation_enabled":true,"responsive_web_enhance_cards_enabled":false}', 'fieldToggles': '{"withArticleRichContentState":true,"withArticlePlainText":false,"withGrokAnalyze":false,"withDisallowedReplyControls":false}', } - resp = httpx.get( - 'https://x.com/i/api/graphql/u5Tij6ERlSH2LZvCUqallw/TweetDetail', - params=params, - headers=headers, - proxy=config["proxy"] if "proxy" in config else None, - ) - if resp.status_code != 200: - logger.error(f"Error fetching tweet detail {tweet_id}: {resp.status_code} {resp.text}") - # os.remove("./config/headers.json") - return None - logger.info(f"Got {tweet_id}") - return resp.json() \ No newline at end of file + + async with httpx.AsyncClient(proxy=config["proxy"] if "proxy" in config else None) as client: + resp = await client.get( + 'https://x.com/i/api/graphql/u5Tij6ERlSH2LZvCUqallw/TweetDetail', + params=params, + headers=headers + ) + if resp.status_code != 200: + logger.error(f"Error fetching tweet detail {tweet_id}: {resp.status_code} {resp.text}") + os.remove("./config/headers.json") + return None + logger.info(f"Got {tweet_id}") + return resp.json() + return None \ No newline at end of file diff --git a/src/twitter.py b/src/twitter.py index 92edcd6..5f8a7fa 100644 --- a/src/twitter.py +++ b/src/twitter.py @@ -48,7 +48,7 @@ async def task_handler(args): LATEST_CHECK_TIME[args["name"]] = time.time() list_id = int(args["url"].split("/")[-1]) - data = get_list(list_id) + data = await get_list(list_id) if data: tweets = parse_timeline(data) new_tweets = check_new_tweets(tweets, list_id)