update cta hooks
This commit is contained in:
+20
-18
@@ -20,21 +20,20 @@ from selenium.common.exceptions import TimeoutException
|
||||
from duckduckgo_search import DDGS
|
||||
from foodie_config import (
|
||||
AUTHORS, RECIPE_KEYWORDS, PROMO_KEYWORDS, HOME_KEYWORDS, PRODUCT_KEYWORDS,
|
||||
PERSONA_CONFIGS, CATEGORIES, CTAS, get_clean_source_name, X_API_CREDENTIALS
|
||||
PERSONA_CONFIGS, CATEGORIES, get_clean_source_name, X_API_CREDENTIALS
|
||||
)
|
||||
from foodie_utils import (
|
||||
load_json_file, save_json_file, get_image, generate_image_query,
|
||||
upload_image_to_wp, select_best_persona, determine_paragraph_count,
|
||||
is_interesting, generate_title_from_summary, summarize_with_gpt4o,
|
||||
generate_category_from_summary, post_to_wp, prepare_post_data,
|
||||
smart_image_and_filter, insert_link_naturally, get_flickr_image # Updated function name
|
||||
smart_image_and_filter, insert_link_naturally, get_flickr_image
|
||||
)
|
||||
from foodie_hooks import get_dynamic_hook, select_best_cta
|
||||
from foodie_hooks import get_dynamic_hook, select_best_cta, get_viral_share_prompt # Added import
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
# Flag to indicate if we're in the middle of posting
|
||||
is_posting = False
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
@@ -179,7 +178,6 @@ def fetch_duckduckgo_news_context(trend_title, hours=24):
|
||||
return trend_title
|
||||
|
||||
def curate_from_google_trends(geo_list=['US']):
|
||||
# Fetch Google Trends data for each geo
|
||||
all_trends = []
|
||||
for geo in geo_list:
|
||||
trends = scrape_google_trends(geo=geo)
|
||||
@@ -189,7 +187,7 @@ def curate_from_google_trends(geo_list=['US']):
|
||||
if not all_trends:
|
||||
print("No Google Trends data available")
|
||||
logging.info("No Google Trends data available")
|
||||
return None, None, random.randint(600, 1800) # Return a default sleep time
|
||||
return None, None, random.randint(600, 1800)
|
||||
|
||||
attempts = 0
|
||||
max_attempts = 10
|
||||
@@ -210,7 +208,6 @@ def curate_from_google_trends(geo_list=['US']):
|
||||
print(f"Trying Google Trend: {title} from {source_name}")
|
||||
logging.info(f"Trying Google Trend: {title} from {source_name}")
|
||||
|
||||
# Check if the trend should be filtered out
|
||||
image_query, relevance_keywords, skip = smart_image_and_filter(title, summary)
|
||||
if skip:
|
||||
print(f"Skipping filtered Google Trend: {title}")
|
||||
@@ -218,7 +215,6 @@ def curate_from_google_trends(geo_list=['US']):
|
||||
attempts += 1
|
||||
continue
|
||||
|
||||
# Calculate interest score
|
||||
scoring_content = f"{title}\n\n{summary}"
|
||||
interest_score = is_interesting(scoring_content)
|
||||
logging.info(f"Interest score for '{title}': {interest_score}")
|
||||
@@ -228,7 +224,6 @@ def curate_from_google_trends(geo_list=['US']):
|
||||
attempts += 1
|
||||
continue
|
||||
|
||||
# Summarize the trend
|
||||
num_paragraphs = determine_paragraph_count(interest_score)
|
||||
extra_prompt = (
|
||||
f"Generate exactly {num_paragraphs} paragraphs.\n"
|
||||
@@ -252,24 +247,27 @@ def curate_from_google_trends(geo_list=['US']):
|
||||
|
||||
final_summary = insert_link_naturally(final_summary, source_name, link)
|
||||
|
||||
# Prepare post data
|
||||
post_data, author, category, image_url, image_source, uploader, pixabay_url = prepare_post_data(final_summary, title)
|
||||
if not post_data:
|
||||
attempts += 1
|
||||
continue
|
||||
|
||||
# Fetch image
|
||||
image_url, image_source, uploader, page_url = get_flickr_image(image_query, relevance_keywords)
|
||||
if not image_url:
|
||||
image_url, image_source, uploader, page_url = get_image(image_query)
|
||||
|
||||
# Generate hooks and initial CTA
|
||||
hook = get_dynamic_hook(post_data["title"]).strip()
|
||||
cta = select_best_cta(post_data["title"], final_summary, post_url=None)
|
||||
|
||||
post_data["content"] = f"{final_summary}\n\n{cta}"
|
||||
# Generate viral share prompt
|
||||
share_prompt = get_viral_share_prompt(post_data["title"], final_summary)
|
||||
share_links_template = (
|
||||
f'<p>{share_prompt} '
|
||||
f'<a href="https://x.com/intent/tweet?url={{post_url}}&text={{share_text}}" target="_blank"><i class="tsi tsi-twitter"></i></a> '
|
||||
f'<a href="https://www.facebook.com/sharer/sharer.php?u={{post_url}}" target="_blank"><i class="tsi tsi-facebook"></i></a></p>'
|
||||
)
|
||||
post_data["content"] = f"{final_summary}\n\n{cta}\n\n{share_links_template}"
|
||||
|
||||
# Post to WordPress and tweet
|
||||
global is_posting
|
||||
is_posting = True
|
||||
try:
|
||||
@@ -284,14 +282,18 @@ def curate_from_google_trends(geo_list=['US']):
|
||||
uploader=uploader,
|
||||
pixabay_url=pixabay_url,
|
||||
interest_score=interest_score,
|
||||
should_post_tweet=True # Post the X tweet on the first call
|
||||
should_post_tweet=True
|
||||
)
|
||||
finally:
|
||||
is_posting = False
|
||||
|
||||
if post_id:
|
||||
share_text = f"Check out this foodie gem! {post_data['title']}"
|
||||
share_text_encoded = quote(share_text)
|
||||
post_url_encoded = quote(post_url)
|
||||
share_links = share_links_template.format(post_url=post_url_encoded, share_text=share_text_encoded)
|
||||
cta = select_best_cta(post_data["title"], final_summary, post_url=post_url)
|
||||
post_data["content"] = f"{final_summary}\n\n{cta}"
|
||||
post_data["content"] = f"{final_summary}\n\n{cta}\n\n{share_links}"
|
||||
is_posting = True
|
||||
try:
|
||||
post_to_wp(
|
||||
@@ -306,7 +308,7 @@ def curate_from_google_trends(geo_list=['US']):
|
||||
pixabay_url=pixabay_url,
|
||||
interest_score=interest_score,
|
||||
post_id=post_id,
|
||||
should_post_tweet=False # Skip X tweet on the update call
|
||||
should_post_tweet=False
|
||||
)
|
||||
finally:
|
||||
is_posting = False
|
||||
@@ -337,7 +339,7 @@ def run_google_trends_automator():
|
||||
geo_list = ['US', 'GB', 'AU']
|
||||
post_data, category, sleep_time = curate_from_google_trends(geo_list=geo_list)
|
||||
if sleep_time is None:
|
||||
sleep_time = random.randint(600, 1800) # Fallback sleep time
|
||||
sleep_time = random.randint(600, 1800)
|
||||
print(f"Sleeping for {sleep_time}s")
|
||||
logging.info(f"Completed run with sleep time: {sleep_time} seconds")
|
||||
time.sleep(sleep_time)
|
||||
|
||||
@@ -17,7 +17,7 @@ import praw
|
||||
from dotenv import load_dotenv
|
||||
from foodie_config import (
|
||||
AUTHORS, RECIPE_KEYWORDS, PROMO_KEYWORDS, HOME_KEYWORDS, PRODUCT_KEYWORDS,
|
||||
PERSONA_CONFIGS, CATEGORIES, CTAS, get_clean_source_name,
|
||||
PERSONA_CONFIGS, CATEGORIES, get_clean_source_name,
|
||||
REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET, REDDIT_USER_AGENT, LIGHT_TASK_MODEL,
|
||||
X_API_CREDENTIALS
|
||||
)
|
||||
@@ -26,13 +26,12 @@ from foodie_utils import (
|
||||
upload_image_to_wp, determine_paragraph_count, insert_link_naturally,
|
||||
summarize_with_gpt4o, generate_category_from_summary, post_to_wp,
|
||||
prepare_post_data, select_best_author, smart_image_and_filter,
|
||||
get_flickr_image # Updated function name
|
||||
get_flickr_image
|
||||
)
|
||||
from foodie_hooks import get_dynamic_hook, select_best_cta
|
||||
from foodie_hooks import get_dynamic_hook, select_best_cta, get_viral_share_prompt # Added import
|
||||
|
||||
load_dotenv()
|
||||
|
||||
# Flag to indicate if we're in the middle of posting
|
||||
is_posting = False
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
@@ -243,7 +242,6 @@ def curate_from_reddit():
|
||||
logging.info(f"Trying Reddit Post: {title} from {source_name}")
|
||||
|
||||
image_query, relevance_keywords, skip = smart_image_and_filter(title, summary)
|
||||
# Check both raw_title and title for keywords
|
||||
if skip or any(keyword in title.lower() or keyword in raw_title.lower() for keyword in RECIPE_KEYWORDS + ["homemade"]):
|
||||
print(f"Skipping filtered Reddit post: {title}")
|
||||
logging.info(f"Skipping filtered Reddit post: {title}")
|
||||
@@ -297,7 +295,6 @@ def curate_from_reddit():
|
||||
attempts += 1
|
||||
continue
|
||||
|
||||
# Fetch image
|
||||
image_url, image_source, uploader, page_url = get_flickr_image(image_query, relevance_keywords)
|
||||
if not image_url:
|
||||
image_url, image_source, uploader, page_url = get_image(image_query)
|
||||
@@ -305,7 +302,14 @@ def curate_from_reddit():
|
||||
hook = get_dynamic_hook(post_data["title"]).strip()
|
||||
cta = select_best_cta(post_data["title"], final_summary, post_url=None)
|
||||
|
||||
post_data["content"] = f"{final_summary}\n\n{cta}"
|
||||
# Generate viral share prompt
|
||||
share_prompt = get_viral_share_prompt(post_data["title"], final_summary)
|
||||
share_links_template = (
|
||||
f'<p>{share_prompt} '
|
||||
f'<a href="https://x.com/intent/tweet?url={{post_url}}&text={{share_text}}" target="_blank"><i class="tsi tsi-twitter"></i></a> '
|
||||
f'<a href="https://www.facebook.com/sharer/sharer.php?u={{post_url}}" target="_blank"><i class="tsi tsi-facebook"></i></a></p>'
|
||||
)
|
||||
post_data["content"] = f"{final_summary}\n\n{cta}\n\n{share_links_template}"
|
||||
|
||||
global is_posting
|
||||
is_posting = True
|
||||
@@ -327,8 +331,12 @@ def curate_from_reddit():
|
||||
is_posting = False
|
||||
|
||||
if post_id:
|
||||
share_text = f"Check out this foodie gem! {post_data['title']}"
|
||||
share_text_encoded = quote(share_text)
|
||||
post_url_encoded = quote(post_url)
|
||||
share_links = share_links_template.format(post_url=post_url_encoded, share_text=share_text_encoded)
|
||||
cta = select_best_cta(post_data["title"], final_summary, post_url=post_url)
|
||||
post_data["content"] = f"{final_summary}\n\n{cta}"
|
||||
post_data["content"] = f"{final_summary}\n\n{cta}\n\n{share_links}"
|
||||
is_posting = True
|
||||
try:
|
||||
post_to_wp(
|
||||
|
||||
+17
-8
@@ -25,14 +25,13 @@ from foodie_utils import (
|
||||
upload_image_to_wp, determine_paragraph_count, insert_link_naturally,
|
||||
is_interesting, generate_title_from_summary, summarize_with_gpt4o,
|
||||
generate_category_from_summary, post_to_wp, prepare_post_data,
|
||||
select_best_author, smart_image_and_filter, get_flickr_image # Updated function name
|
||||
select_best_author, smart_image_and_filter, get_flickr_image
|
||||
)
|
||||
from foodie_hooks import get_dynamic_hook, select_best_cta
|
||||
from foodie_hooks import get_dynamic_hook, select_best_cta, get_viral_share_prompt # Added import
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
# Flag to indicate if we're in the middle of posting
|
||||
is_posting = False
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
@@ -176,7 +175,7 @@ def fetch_rss_feeds():
|
||||
continue
|
||||
logging.info(f"Filtered to {len(articles)} articles from {feed_url}")
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to fetch RSS feed {feed_url}: {e}")
|
||||
logging.error(f"Failed to fetch RSS feed {feed |url}: {e}")
|
||||
continue
|
||||
|
||||
articles.sort(key=lambda x: x["pub_date"], reverse=True)
|
||||
@@ -252,12 +251,10 @@ def curate_from_rss():
|
||||
r'\*\*' + re.escape(title) + r'\*\*|' + re.escape(title),
|
||||
re.IGNORECASE
|
||||
)
|
||||
# Split into paragraphs, process each one, then rejoin
|
||||
paragraphs = final_summary.split('\n')
|
||||
cleaned_paragraphs = []
|
||||
for para in paragraphs:
|
||||
if para.strip():
|
||||
# Remove the title and normalize spaces within the paragraph
|
||||
cleaned_para = title_pattern.sub('', para).strip()
|
||||
cleaned_para = re.sub(r'\s+', ' ', cleaned_para)
|
||||
cleaned_paragraphs.append(cleaned_para)
|
||||
@@ -277,7 +274,15 @@ def curate_from_rss():
|
||||
hook = get_dynamic_hook(post_data["title"]).strip()
|
||||
cta = select_best_cta(post_data["title"], final_summary, post_url=None)
|
||||
|
||||
post_data["content"] = f"{final_summary}\n\n{cta}"
|
||||
# Generate viral share prompt
|
||||
share_prompt = get_viral_share_prompt(post_data["title"], final_summary)
|
||||
share_links_template = (
|
||||
f'<p>{share_prompt} '
|
||||
f'<a href="https://x.com/intent/tweet?url={{post_url}}&text={{share_text}}" target="_blank"><i class="tsi tsi-twitter"></i></a> '
|
||||
f'<a href="https://www.facebook.com/sharer/sharer.php?u={{post_url}}" target="_blank"><i class="tsi tsi-facebook"></i></a></p>'
|
||||
)
|
||||
post_data["content"] = f"{final_summary}\n\n{cta}\n\n{share_links_template}"
|
||||
|
||||
global is_posting
|
||||
is_posting = True
|
||||
try:
|
||||
@@ -298,8 +303,12 @@ def curate_from_rss():
|
||||
is_posting = False
|
||||
|
||||
if post_id:
|
||||
share_text = f"Check out this foodie gem! {post_data['title']}"
|
||||
share_text_encoded = quote(share_text)
|
||||
post_url_encoded = quote(post_url)
|
||||
share_links = share_links_template.format(post_url=post_url_encoded, share_text=share_text_encoded)
|
||||
cta = select_best_cta(post_data["title"], final_summary, post_url=post_url)
|
||||
post_data["content"] = f"{final_summary}\n\n{cta}"
|
||||
post_data["content"] = f"{final_summary}\n\n{cta}\n\n{share_links}"
|
||||
is_posting = True
|
||||
try:
|
||||
post_to_wp(
|
||||
|
||||
+25
-12
@@ -29,13 +29,33 @@ def get_dynamic_hook(article_title):
|
||||
logging.error(f"Dynamic hook generation failed: {e}")
|
||||
return "This food scoop will blow your mind!"
|
||||
|
||||
def get_viral_share_prompt(article_title, content):
|
||||
try:
|
||||
prompt = (
|
||||
"Generate a short, viral share prompt (under 40 characters) to encourage sharing a food-related article on social media. "
|
||||
"Make it bold, quirky, and engaging with a Buzzfeed/Upworthy flair (e.g., 'Obsessed? Share Now'). "
|
||||
"Avoid clichés like 'game-changer' and words like 'elevate'. "
|
||||
"Do not include emojis, the platform name (e.g., Twitter, Facebook), or any HTML. "
|
||||
"Return only the prompt text."
|
||||
)
|
||||
response = client.chat.completions.create(
|
||||
model=LIGHT_TASK_MODEL,
|
||||
messages=[
|
||||
{"role": "system", "content": prompt},
|
||||
{"role": "user", "content": f"Title: {article_title}\nContent: {content}"}
|
||||
],
|
||||
max_tokens=20,
|
||||
temperature=0.9 # Higher temperature for more creativity
|
||||
)
|
||||
share_prompt = response.choices[0].message.content.strip()
|
||||
logging.info(f"Generated viral share prompt: {share_prompt}")
|
||||
return share_prompt
|
||||
except Exception as e:
|
||||
logging.error(f"Viral share prompt generation failed: {e}")
|
||||
return "Love This? Share It"
|
||||
|
||||
def select_best_cta(title, content, post_url=None):
|
||||
cta_templates = [
|
||||
# Share-focused CTAs
|
||||
"Cant Get Enough Share This Now On <a href='https://x.com/intent/tweet?url={url}&text={text}'><i class='tsi tsi-twitter'></i></a>",
|
||||
"This Blew Your Mind Right Tweet It On <a href='https://x.com/intent/tweet?url={url}&text={text}'><i class='tsi tsi-twitter'></i></a>",
|
||||
"Ready to Spill the Tea Share On <a href='https://x.com/intent/tweet?url={url}&text={text}'><i class='tsi tsi-twitter'></i></a>",
|
||||
"Too Wild to Keep Quiet Post It On <a href='https://x.com/intent/tweet?url={url}&text={text}'><i class='tsi tsi-twitter'></i></a>",
|
||||
# Like-focused CTAs
|
||||
"Love This Foodie Find Hit That Like Button",
|
||||
"Think This Dish Is a Game Changer Show Some Love With a Like",
|
||||
@@ -44,12 +64,5 @@ def select_best_cta(title, content, post_url=None):
|
||||
"Dont Miss Out on Foodie Updates Follow Us Today"
|
||||
]
|
||||
|
||||
hook = get_dynamic_hook(title).strip()
|
||||
hook = urllib.parse.quote(hook)
|
||||
url = post_url if post_url else "https://insiderfoodie.com/placeholder"
|
||||
url = urllib.parse.quote(url)
|
||||
|
||||
cta = random.choice(cta_templates)
|
||||
if "https://x.com/intent/tweet" in cta:
|
||||
cta = cta.format(url=url, text=hook)
|
||||
return cta
|
||||
Reference in New Issue
Block a user