diff --git a/foodie_utils.py b/foodie_utils.py index 64ab9da..c29e42f 100644 --- a/foodie_utils.py +++ b/foodie_utils.py @@ -194,11 +194,22 @@ def generate_article_tweet(author, post, persona): return tweet def post_tweet(author, tweet, reply_to_id=None): + from foodie_config import X_API_CREDENTIALS + import logging + import tweepy + from datetime import datetime, timezone + credentials = next((cred for cred in X_API_CREDENTIALS if cred["username"] == author["username"]), None) if not credentials: logging.error(f"No X credentials found for {author['username']}") return False + logging.debug(f"Attempting to post tweet for {author['username']} (handle: {credentials['x_username']})") + logging.debug(f"Credentials: api_key={credentials['api_key'][:4]}..., access_token={credentials['access_token'][:4]}...") + logging.debug(f"Tweet content: {tweet}") + if reply_to_id: + logging.debug(f"Replying to tweet ID: {reply_to_id}") + post_counts = load_post_counts() author_count = next((entry for entry in post_counts if entry["username"] == author["username"]), None) if author_count["monthly_count"] >= 500: @@ -217,15 +228,23 @@ def post_tweet(author, tweet, reply_to_id=None): ) response = client.create_tweet( text=tweet, - in_reply_to_tweet_id=reply_to_id # Add threading support + in_reply_to_tweet_id=reply_to_id ) author_count["monthly_count"] += 1 author_count["daily_count"] += 1 save_post_counts(post_counts) - logging.info(f"Posted tweet for {author['username']}: {tweet}") - return {"id": response.data["id"]} # Return dict with tweet ID + logging.info(f"Posted tweet for {author['username']} (handle: {credentials['x_username']}): {tweet}") + logging.debug(f"Tweet ID: {response.data['id']}") + return {"id": response.data["id"]} + except tweepy.TweepyException as e: + logging.error(f"Failed to post tweet for {author['username']} (handle: {credentials['x_username']}): {e}") + if hasattr(e, 'response') and e.response: + logging.error(f"Twitter API response: {e.response.text}") + if "forbidden" in str(e).lower(): + logging.error(f"Possible causes: invalid credentials, insufficient permissions, or account restrictions for {credentials['x_username']}") + return False except Exception as e: - logging.error(f"Failed to post tweet for {author['username']}: {e}") + logging.error(f"Unexpected error posting tweet for {author['username']} (handle: {credentials['x_username']}): {e}", exc_info=True) return False def select_best_persona(interest_score, content=""):