|
|
|
|
@ -216,26 +216,43 @@ def post_tweet(author, tweet, reply_to_id=None): |
|
|
|
|
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']}") |
|
|
|
|
username = author["username"] |
|
|
|
|
if username not in X_API_CREDENTIALS: |
|
|
|
|
logging.error(f"No X credentials found for {username}") |
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
logging.debug(f"Attempting to post tweet for {author['username']} (handle: {credentials['x_username']})") |
|
|
|
|
|
|
|
|
|
credentials = X_API_CREDENTIALS[username] |
|
|
|
|
required_keys = ["api_key", "api_secret", "access_token", "access_token_secret"] |
|
|
|
|
missing_keys = [key for key in required_keys if key not in credentials or not credentials[key]] |
|
|
|
|
if missing_keys: |
|
|
|
|
logging.error(f"Missing X API credentials for {username}: {missing_keys}") |
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
logging.debug(f"Attempting to post tweet for {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) |
|
|
|
|
author_count = next((entry for entry in post_counts if entry["username"] == username), None) |
|
|
|
|
if not author_count: |
|
|
|
|
author_count = { |
|
|
|
|
"username": username, |
|
|
|
|
"month": datetime.now(timezone.utc).strftime("%Y-%m"), |
|
|
|
|
"monthly_count": 0, |
|
|
|
|
"day": datetime.now(timezone.utc).strftime("%Y-%m-%d"), |
|
|
|
|
"daily_count": 0 |
|
|
|
|
} |
|
|
|
|
post_counts.append(author_count) |
|
|
|
|
|
|
|
|
|
if author_count["monthly_count"] >= 500: |
|
|
|
|
logging.warning(f"Monthly post limit (500) reached for {author['username']}") |
|
|
|
|
logging.warning(f"Monthly post limit (500) reached for {username}") |
|
|
|
|
return False |
|
|
|
|
if author_count["daily_count"] >= 20: |
|
|
|
|
logging.warning(f"Daily post limit (20) reached for {author['username']}") |
|
|
|
|
logging.warning(f"Daily post limit (20) reached for {username}") |
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
client = tweepy.Client( |
|
|
|
|
consumer_key=credentials["api_key"], |
|
|
|
|
@ -247,21 +264,22 @@ def post_tweet(author, tweet, reply_to_id=None): |
|
|
|
|
text=tweet, |
|
|
|
|
in_reply_to_tweet_id=reply_to_id |
|
|
|
|
) |
|
|
|
|
# Update post counts |
|
|
|
|
author_count["monthly_count"] += 1 |
|
|
|
|
author_count["daily_count"] += 1 |
|
|
|
|
save_post_counts(post_counts) |
|
|
|
|
logging.info(f"Posted tweet for {author['username']} (handle: {credentials['x_username']}): {tweet}") |
|
|
|
|
logging.info(f"Posted tweet for {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}") |
|
|
|
|
logging.error(f"Failed to post tweet for {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"Unexpected error posting tweet for {author['username']} (handle: {credentials['x_username']}): {e}", exc_info=True) |
|
|
|
|
logging.error(f"Unexpected error posting tweet for {username} (handle: {credentials['x_username']}): {e}", exc_info=True) |
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
def select_best_persona(interest_score, content=""): |
|
|
|
|
|