|
|
|
|
@ -62,12 +62,19 @@ def save_json_file(filename, key, value): |
|
|
|
|
# Remove duplicates by title |
|
|
|
|
data = [item for item in data if item["title"] != key] |
|
|
|
|
data.append(entry) |
|
|
|
|
# Special handling for used_images.json to save as a flat list |
|
|
|
|
# Special handling for used_images.json to save as a flat list with one URL per line |
|
|
|
|
if filename.endswith('used_images.json'): |
|
|
|
|
# Update the used_images set directly to keep it in sync |
|
|
|
|
used_images.add(key) |
|
|
|
|
with open(filename, 'w') as f: |
|
|
|
|
json.dump(list(used_images), f) |
|
|
|
|
f.write('[\n') |
|
|
|
|
urls = list(used_images) |
|
|
|
|
for i, url in enumerate(urls): |
|
|
|
|
f.write(f'"{url}"') |
|
|
|
|
if i < len(urls) - 1: |
|
|
|
|
f.write(',\n') |
|
|
|
|
else: |
|
|
|
|
f.write('\n') |
|
|
|
|
f.write(']') |
|
|
|
|
else: |
|
|
|
|
with open(filename, 'w') as f: |
|
|
|
|
for item in data: |
|
|
|
|
@ -139,20 +146,23 @@ def generate_article_tweet(author, post, persona): |
|
|
|
|
|
|
|
|
|
prompt = ( |
|
|
|
|
f"Craft a sharp tweet (under 230 characters) for {author_handle} with the voice of '{persona}'. " |
|
|
|
|
f"Distill the essence of the article '{title}' and include the raw URL '{url}' at the end. " |
|
|
|
|
f"Distill the essence of the article '{title}' into a concise, engaging message. " |
|
|
|
|
f"Include the raw URL '{url}' at the end. " |
|
|
|
|
f"Do not wrap the tweet in quotation marks. " |
|
|
|
|
f"Make it bold, spark curiosity, and invite engagement with a human touch. " |
|
|
|
|
f"Swap 'elevate' for dynamic terms like 'ignite' or 'unleash'. " |
|
|
|
|
f"Absolutely do not include hashtags, emojis, or phrases like '[Read more]' or 'Read more'. " |
|
|
|
|
f"Skip any extra fluff or formatting around the URL—just append the raw URL after a space." |
|
|
|
|
f"Skip any extra fluff or formatting around the URL—just append the raw URL after a space. " |
|
|
|
|
f"Example: 'Love food trends? Check this out! {url}'" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
response = openai.chat.completions.create( |
|
|
|
|
response = client.chat.completions.create( |
|
|
|
|
model=SUMMARY_MODEL, |
|
|
|
|
messages=[ |
|
|
|
|
{"role": "system", "content": "You are a social media viral expert crafting engaging tweets."}, |
|
|
|
|
{"role": "user", "content": prompt} |
|
|
|
|
], |
|
|
|
|
max_tokens=100, |
|
|
|
|
max_tokens=80, |
|
|
|
|
temperature=0.7 |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
@ -161,12 +171,19 @@ def generate_article_tweet(author, post, persona): |
|
|
|
|
# Post-generation check: Strip any emojis using regex |
|
|
|
|
tweet = re.sub(r'[\U0001F600-\U0001F64F\U0001F300-\U0001F5FF\U0001F680-\U0001F6FF\U0001F700-\U0001F77F\U0001F780-\U0001F7FF\U0001F800-\U0001F8FF\U0001F900-\U0001F9FF\U0001FA00-\U0001FA6F\U0001FA70-\U0001FAFF\U00002702-\U000027B0\U000024C2-\U0001F251]', '', tweet).strip() |
|
|
|
|
|
|
|
|
|
# Optionally, strip "[Read more]" or similar phrases as an additional failsafe |
|
|
|
|
# Strip "[Read more]" or similar phrases as an additional failsafe |
|
|
|
|
tweet = re.sub(r'\[Read more\]\(.*?\)|\bRead more\b', '', tweet).strip() |
|
|
|
|
|
|
|
|
|
if len(tweet) > 280: |
|
|
|
|
tweet = tweet[:277] + "..." |
|
|
|
|
# Strip leading or trailing quotation marks |
|
|
|
|
tweet = tweet.strip('"\'') |
|
|
|
|
|
|
|
|
|
# Ensure tweet fits within 280 characters, accounting for URL (Twitter shortens to 23 chars) |
|
|
|
|
url_length = 23 |
|
|
|
|
max_tweet_length = 280 - url_length - 1 # Subtract 1 for the space before URL |
|
|
|
|
if len(tweet) > max_tweet_length: |
|
|
|
|
tweet = tweet[:max_tweet_length-3] + "... " + url |
|
|
|
|
|
|
|
|
|
logging.info(f"Generated tweet: {tweet}") |
|
|
|
|
return tweet |
|
|
|
|
|
|
|
|
|
def post_tweet(author, tweet): |
|
|
|
|
@ -1015,7 +1032,15 @@ if os.path.exists(used_images_file): |
|
|
|
|
def save_used_images(): |
|
|
|
|
try: |
|
|
|
|
with open(used_images_file, 'w') as f: |
|
|
|
|
json.dump(list(used_images), f) |
|
|
|
|
f.write('[\n') |
|
|
|
|
urls = list(used_images) |
|
|
|
|
for i, url in enumerate(urls): |
|
|
|
|
f.write(f'"{url}"') |
|
|
|
|
if i < len(urls) - 1: |
|
|
|
|
f.write(',\n') |
|
|
|
|
else: |
|
|
|
|
f.write('\n') |
|
|
|
|
f.write(']') |
|
|
|
|
logging.info(f"Saved {len(used_images)} used image URLs to {used_images_file}") |
|
|
|
|
except Exception as e: |
|
|
|
|
logging.warning(f"Failed to save used images to {used_images_file}: {e}") |
|
|
|
|
|