@ -25,6 +25,8 @@ LOG_FILE = "/home/shane/foodie_automator/logs/foodie_engagement_tweet.log"
LOG_PRUNE_DAYS = 30
MAX_RETRIES = 3
RETRY_BACKOFF = 2
URL = " https://insiderfoodie.com "
URL_SHORTENED_LENGTH = 23 # Twitter's shortened URL length
def setup_logging ( ) :
""" Initialize logging with pruning of old logs. """
@ -191,7 +193,7 @@ def generate_engagement_tweet(author):
f " Generate an engagement tweet for { author_handle } asking a question about { theme } to engage the public. "
f " Keep it under 230 characters to ensure room for the URL. "
f " Use { persona_config [ ' tone ' ] } . "
f " Include a call to action to follow { author_handle } or like the tweet, and mention InsiderFoodie.com with a link to https://insiderfoodie.com . "
f " Include a call to action to follow { author_handle } or like the tweet, followed by the URL { URL } (do not mention InsiderFoodie.com separately in the text) . "
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 " Return only the tweet text. "
@ -205,15 +207,32 @@ def generate_engagement_tweet(author):
{ " role " : " system " , " content " : " You are a social media expert crafting engaging tweets. " } ,
{ " role " : " user " , " content " : prompt }
] ,
max_tokens = 80 , # Reduced to ensure shorter tweets
max_tokens = 80 ,
temperature = 0.7
)
tweet = response . choices [ 0 ] . message . content . strip ( )
# Ensure tweet length is within limits (accounting for URL)
url_length = 23 # Twitter shortens URLs
if len ( tweet ) > ( 280 - url_length ) :
tweet = tweet [ : ( 280 - url_length - 3 ) ] + " ... "
logging . debug ( f " Generated engagement tweet for { username } : { tweet } " )
# Check for duplicate URLs and remove if present
url_count = tweet . lower ( ) . count ( URL . lower ( ) )
if url_count > 1 :
logging . warning ( f " Generated tweet for { username } contains duplicate URLs: { tweet } " )
# Keep only the last occurrence of the URL
last_url_pos = tweet . rfind ( URL )
tweet = tweet [ : last_url_pos ] . replace ( URL , " " ) . strip ( ) + " " + URL
logging . debug ( f " Revised tweet after removing duplicate URL: { tweet } " )
# Ensure the URL is at the end of the tweet
if not tweet . endswith ( URL ) :
tweet = tweet . replace ( URL , " " ) . strip ( ) + " " + URL
# Calculate tweet length considering Twitter's URL shortening
tweet_without_url = tweet . replace ( URL , " " )
total_length = len ( tweet_without_url ) + URL_SHORTENED_LENGTH
if total_length > 280 :
logging . warning ( f " Tweet for { username } exceeds 280 characters ( { total_length } ), truncating " )
tweet_without_url = tweet_without_url [ : ( 280 - URL_SHORTENED_LENGTH - 3 ) ]
tweet = tweet_without_url + " ... " + " " + URL
total_length = len ( tweet_without_url ) + 3 + URL_SHORTENED_LENGTH
logging . debug ( f " Final tweet for { username } (length { total_length } ): { tweet } " )
return tweet
except Exception as e :
logging . warning ( f " Failed to generate engagement tweet for { username } (attempt { attempt + 1 } ): { e } " )
@ -222,11 +241,14 @@ def generate_engagement_tweet(author):
else :
logging . error ( f " Failed to generate engagement tweet after { MAX_RETRIES } attempts " )
fallback = (
f " What ' s the hottest { theme } ? Share and follow { author_handle } for more on InsiderFoodie.com! "
f " https://insiderfoodie.com "
f " What ' s the hottest { theme } ? Share and follow { author_handle } for more! { URL } "
)
if len ( fallback ) > ( 280 - url_length ) :
fallback = fallback [ : ( 280 - url_length - 3 ) ] + " ... "
# Ensure fallback tweet is within length limits
tweet_without_url = fallback . replace ( URL , " " )
total_length = len ( tweet_without_url ) + URL_SHORTENED_LENGTH
if total_length > 280 :
tweet_without_url = tweet_without_url [ : ( 280 - URL_SHORTENED_LENGTH - 3 ) ]
fallback = tweet_without_url + " ... " + " " + URL
logging . info ( f " Using fallback engagement tweet: { fallback } " )
return fallback
return None