|
|
|
@ -178,16 +178,22 @@ def generate_article_tweet(author, post, persona): |
|
|
|
# Strip leading or trailing quotation marks |
|
|
|
# Strip leading or trailing quotation marks |
|
|
|
tweet = tweet.strip('"\'') |
|
|
|
tweet = tweet.strip('"\'') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Remove the URL if it already exists in the tweet to avoid duplication |
|
|
|
|
|
|
|
tweet = re.sub(rf'\s*{re.escape(url)}$', '', tweet).strip() |
|
|
|
|
|
|
|
|
|
|
|
# Ensure tweet fits within 280 characters, accounting for URL (Twitter shortens to 23 chars) |
|
|
|
# Ensure tweet fits within 280 characters, accounting for URL (Twitter shortens to 23 chars) |
|
|
|
url_length = 23 |
|
|
|
url_length = 23 |
|
|
|
max_tweet_length = 280 - url_length - 1 # Subtract 1 for the space before URL |
|
|
|
max_tweet_length = 280 - url_length - 1 # Subtract 1 for the space before URL |
|
|
|
if len(tweet) > max_tweet_length: |
|
|
|
if len(tweet) > max_tweet_length: |
|
|
|
tweet = tweet[:max_tweet_length-3] + "... " + url |
|
|
|
tweet = tweet[:max_tweet_length-3] + "..." |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Append the URL exactly once |
|
|
|
|
|
|
|
tweet = tweet + " " + url |
|
|
|
|
|
|
|
|
|
|
|
logging.info(f"Generated tweet: {tweet}") |
|
|
|
logging.info(f"Generated tweet: {tweet}") |
|
|
|
return tweet |
|
|
|
return tweet |
|
|
|
|
|
|
|
|
|
|
|
def post_tweet(author, tweet): |
|
|
|
def post_tweet(author, tweet, reply_to_id=None): |
|
|
|
credentials = next((cred for cred in X_API_CREDENTIALS if cred["username"] == author["username"]), None) |
|
|
|
credentials = next((cred for cred in X_API_CREDENTIALS if cred["username"] == author["username"]), None) |
|
|
|
if not credentials: |
|
|
|
if not credentials: |
|
|
|
logging.error(f"No X credentials found for {author['username']}") |
|
|
|
logging.error(f"No X credentials found for {author['username']}") |
|
|
|
@ -209,12 +215,15 @@ def post_tweet(author, tweet): |
|
|
|
access_token=credentials["access_token"], |
|
|
|
access_token=credentials["access_token"], |
|
|
|
access_token_secret=credentials["access_token_secret"] |
|
|
|
access_token_secret=credentials["access_token_secret"] |
|
|
|
) |
|
|
|
) |
|
|
|
response = client.create_tweet(text=tweet) |
|
|
|
response = client.create_tweet( |
|
|
|
|
|
|
|
text=tweet, |
|
|
|
|
|
|
|
in_reply_to_tweet_id=reply_to_id # Add threading support |
|
|
|
|
|
|
|
) |
|
|
|
author_count["monthly_count"] += 1 |
|
|
|
author_count["monthly_count"] += 1 |
|
|
|
author_count["daily_count"] += 1 |
|
|
|
author_count["daily_count"] += 1 |
|
|
|
save_post_counts(post_counts) |
|
|
|
save_post_counts(post_counts) |
|
|
|
logging.info(f"Posted tweet for {author['username']}: {tweet}") |
|
|
|
logging.info(f"Posted tweet for {author['username']}: {tweet}") |
|
|
|
return True |
|
|
|
return {"id": response.data["id"]} # Return dict with tweet ID |
|
|
|
except Exception as e: |
|
|
|
except Exception as e: |
|
|
|
logging.error(f"Failed to post tweet for {author['username']}: {e}") |
|
|
|
logging.error(f"Failed to post tweet for {author['username']}: {e}") |
|
|
|
return False |
|
|
|
return False |
|
|
|
|