diff --git a/foodie_weekly_thread.py b/foodie_weekly_thread.py index 004456b..2469ffa 100644 --- a/foodie_weekly_thread.py +++ b/foodie_weekly_thread.py @@ -7,6 +7,7 @@ import signal import sys import fcntl import time +import re from datetime import datetime, timedelta, timezone from openai import OpenAI from foodie_utils import AUTHORS, SUMMARY_MODEL, load_json_file, save_json_file, update_system_activity @@ -107,11 +108,11 @@ def generate_intro_tweet(author): logging.debug(f"Generating intro tweet for {author_handle}") prompt = ( - f"Generate a concise tweet (under 280 characters) for {author_handle}. " + f"Generate a concise tweet (under 200 characters) for {author_handle}. " f"Introduce a thread of their top 10 foodie posts of the week on InsiderFoodie.com. " - f"Make it engaging, create curiosity, and include a call to action to visit InsiderFoodie.com, follow {author_handle}, or like the thread. " - f"Avoid using the word 'elevate'—use more humanized language like 'level up' or 'bring to life'. " - f"Do not include emojis, hashtags, or reward-driven incentives (e.g., giveaways)." + f"Make it engaging, create curiosity, and include a call to action to visit InsiderFoodie.com or follow {author_handle}. " + f"Avoid using the word 'elevate'—use humanized language like 'level up' or 'bring to life'. " + f"Strictly exclude emojis, hashtags, or reward-driven incentives (e.g., giveaways)." ) for attempt in range(MAX_RETRIES): @@ -122,10 +123,11 @@ def generate_intro_tweet(author): {"role": "system", "content": "You are a social media expert crafting engaging tweets."}, {"role": "user", "content": prompt} ], - max_tokens=100, + max_tokens=150, temperature=0.7 ) tweet = response.choices[0].message.content.strip() + tweet = re.sub(r'[\U0001F000-\U0001FFFF]', '', tweet) # Remove emojis if len(tweet) > 280: tweet = tweet[:277] + "..." logging.debug(f"Generated intro tweet: {tweet}") @@ -137,8 +139,7 @@ def generate_intro_tweet(author): else: logging.error(f"Failed to generate intro tweet after {MAX_RETRIES} attempts") fallback = ( - f"This week's top 10 foodie finds by {author_handle}! Check out the best on InsiderFoodie.com. " - f"Follow {author_handle} for more and like this thread to stay in the loop! Visit us at https://insiderfoodie.com" + f"Top 10 foodie posts this week by {author_handle}! Visit InsiderFoodie.com and follow {author_handle} for more." ) logging.info(f"Using fallback intro tweet: {fallback}") return fallback @@ -153,13 +154,13 @@ def generate_final_cta(author): logging.debug(f"Generating final CTA tweet for {author_handle}") prompt = ( - f"Generate a concise tweet (under 280 characters) for {author_handle}. " + f"Generate a concise tweet (under 200 characters) for {author_handle}. " f"Conclude a thread of their top 10 foodie posts of the week on InsiderFoodie.com. " - f"Make it engaging, value-driven, and urgent, in the style of Neil Patel. " + f"Make it engaging, value-driven, in the style of Neil Patel. " f"Include a call to action to visit InsiderFoodie.com and follow {author_handle}. " - f"Mention that the top 10 foodie trends are shared every Monday. " + f"Mention that top 10 foodie trends are shared every Monday. " f"Avoid using the word 'elevate'—use humanized language like 'level up' or 'bring to life'. " - f"Do not include emojis, hashtags, or reward-driven incentives (e.g., giveaways)." + f"Strictly exclude emojis, hashtags, or reward-driven incentives (e.g., giveaways)." ) for attempt in range(MAX_RETRIES): @@ -170,10 +171,11 @@ def generate_final_cta(author): {"role": "system", "content": "You are a social media expert crafting engaging tweets."}, {"role": "user", "content": prompt} ], - max_tokens=100, + max_tokens=150, temperature=0.7 ) tweet = response.choices[0].message.content.strip() + tweet = re.sub(r'[\U0001F000-\U0001FFFF]', '', tweet) # Remove emojis if len(tweet) > 280: tweet = tweet[:277] + "..." logging.debug(f"Generated final CTA tweet: {tweet}") @@ -185,8 +187,8 @@ def generate_final_cta(author): else: logging.error(f"Failed to generate final CTA tweet after {MAX_RETRIES} attempts") fallback = ( - f"Want more foodie insights like these? Check out insiderfoodie.com and follow {author_handle} " - f"for the world’s top 10 foodie trends every Monday. Don’t miss out!" + f"Want more foodie insights? Visit insiderfoodie.com and follow {author_handle} " + f"for top 10 foodie trends every Monday." ) logging.info(f"Using fallback final CTA tweet: {fallback}") return fallback @@ -293,8 +295,9 @@ def generate_weekly_thread(): continue # Select top 2 posts (to fit within 3-tweet limit: lead + 2 posts) - author_posts = sorted(author_posts, key=lambda x: datetime.fromisoformat(x["timestamp"]), reverse=True)[:2] - logging.info(f"Selected {len(author_posts)} posts for {username}") + author_posts = sorted(author_posts, key=lambda x: datetime.fromisoformat(x["timestamp"]), reverse=True) + selected_posts = author_posts[:2] + logging.info(f"Found {len(author_posts)} posts for {username}, selected {len(selected_posts)}") # Generate thread content try: @@ -306,11 +309,13 @@ def generate_weekly_thread(): # Generate thread tweets (up to 2) thread_tweets = [] - for i, post in enumerate(author_posts, 1): + for i, post in enumerate(selected_posts, 1): thread_tweet = ( f"{i}. {post['title']} " f"Read more: {post['url']}" ) + if len(thread_tweet) > 280: + thread_tweet = f"{i}. {post['title'][:200]}... Read more: {post['url']}" thread_tweets.append(thread_tweet) logging.info(f"Generated thread tweet {i} for {username}: {thread_tweet}") @@ -319,8 +324,8 @@ def generate_weekly_thread(): if not final_cta: logging.error(f"Failed to generate final CTA tweet for {username}, using fallback") final_cta = ( - f"Want more foodie insights like these? Check out insiderfoodie.com and follow @{X_API_CREDENTIALS[username]['x_username']} " - f"for the world’s top 10 foodie trends every Monday. Don’t miss out!" + f"Want more foodie insights? Visit insiderfoodie.com and follow {X_API_CREDENTIALS[username]['x_username']} " + f"for top 10 foodie trends every Monday." ) # Collect thread content for this author