from __future__ import annotations import asyncio import logging import tweepy logger = logging.getLogger(__name__) X_API_V2_BASE = "https://api.x.com" X_UPLOAD_BASE = "https://upload.twitter.com" def create_tweepy_client(account: dict) -> tweepy.Client: return tweepy.Client( consumer_key=account["api_key"], consumer_secret=account["api_secret"], access_token=account["access_token"], access_token_secret=account["access_secret"], return_type=dict, wait_on_rate_limit=False, ) async def verify_credentials( account: dict, timeout_seconds: float = 5.0 ) -> dict | None: try: client = create_tweepy_client(account) response = await asyncio.to_thread( client.get_me, user_fields=["id", "username", "name", "profile_image_url"], ) data = response.get("data", {}) if data: return { "user_id": data.get("id", ""), "username": data.get("username", ""), "name": data.get("name", ""), "profile_image_url": data.get("profile_image_url", ""), } except tweepy.Unauthorized: logger.warning("X API: OAuth 1.0a credentials invalid or revoked") except tweepy.TooManyRequests: logger.warning("X API: rate limited during credential verification") except Exception: logger.exception("X API: credential verification failed") return None async def probe(account: dict, timeout_seconds: float = 5.0) -> bool: user = await verify_credentials(account, timeout_seconds) return user is not None async def get_user_by_username(account: dict, username: str) -> dict | None: client = create_tweepy_client(account) try: response = await asyncio.to_thread( client.get_user, username=username, user_fields=[ "id", "username", "name", "description", "public_metrics", "profile_image_url", ], ) return response.get("data", {}) except Exception as e: logger.warning("Twitter get_user_by_username error: %s", e) return None async def get_users_by_ids(account: dict, user_ids: list[str]) -> list[dict]: client = create_tweepy_client(account) try: response = await asyncio.to_thread( client.get_users, ids=user_ids, user_fields=["id", "username", "name", "profile_image_url"], ) return response.get("data", []) except Exception as e: logger.warning("Twitter get_users_by_ids error: %s", e) return []