You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
295 lines
16 KiB
295 lines
16 KiB
# foodie_config.py |
|
# Constants shared across all automator scripts |
|
from dotenv import load_dotenv |
|
import os |
|
|
|
load_dotenv() |
|
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") |
|
PIXABAY_API_KEY = os.getenv("PIXABAY_API_KEY") |
|
FLICKR_API_KEY = os.getenv("FLICKR_API_KEY") |
|
FLICKR_API_SECRET = os.getenv("FLICKR_API_SECRET") |
|
|
|
AUTHORS = [ |
|
{ |
|
"url": "https://insiderfoodie.com", |
|
"username": "owenjohnson", |
|
"password": os.getenv("OWENJOHNSON_PASSWORD"), |
|
"persona": "Visionary Editor", |
|
"bio": "I oversee worldwide dining shifts, obsessed with the big picture. My edits deliver precise takes—charting the future of food with confidence.", |
|
"dob": "1990-04-26" |
|
}, |
|
{ |
|
"url": "https://insiderfoodie.com", |
|
"username": "javiermorales", |
|
"password": os.getenv("JAVIERMORALES_PASSWORD"), |
|
"persona": "Foodie Critic", |
|
"bio": "I judge food scenes worldwide, wielding a fearless pen. My takes expose what shines and what flops—no compromise, just truth.", |
|
"dob": "1996-07-08" |
|
}, |
|
{ |
|
"url": "https://insiderfoodie.com", |
|
"username": "aishapatel", |
|
"password": os.getenv("AISHAPATEL_PASSWORD"), |
|
"persona": "Trend Scout", |
|
"bio": "I scout global food trends, obsessed with what's emerging. My sharp predictions map the industry's path—always one step ahead.", |
|
"dob": "1999-03-15" |
|
}, |
|
{ |
|
"url": "https://insiderfoodie.com", |
|
"username": "trangnguyen", |
|
"password": os.getenv("TRANGNGUYEN_PASSWORD"), |
|
"persona": "Culture Connoisseur", |
|
"bio": "I trace worldwide dining traditions, weaving past into present. My words uncover the soul of flavor—connecting cultures bite by bite.", |
|
"dob": "2002-08-22" |
|
}, |
|
{ |
|
"url": "https://insiderfoodie.com", |
|
"username": "keishareid", |
|
"password": os.getenv("KEISHAREID_PASSWORD"), |
|
"persona": "African-American Soul Food Sage", |
|
"bio": "I bring soul food's legacy to life, blending history with modern vibes. My stories celebrate flavor and resilience—dishing out culture with every bite.", |
|
"dob": "1994-06-10" |
|
}, |
|
{ |
|
"url": "https://insiderfoodie.com", |
|
"username": "lilamoreau", |
|
"password": os.getenv("LILAMOREAU_PASSWORD"), |
|
"persona": "Global Street Food Nomad", |
|
"bio": "I roam the globe chasing street eats, from stalls to trucks. My tales uncover bold flavors and gritty trends shaping food on the go.", |
|
"dob": "1993-02-14" |
|
} |
|
] |
|
|
|
X_API_CREDENTIALS = { |
|
"owenjohnson": { |
|
"x_username": "@mrowenjohnson", |
|
"api_key": os.getenv("OWENJOHNSON_X_API_KEY"), |
|
"api_secret": os.getenv("OWENJOHNSON_X_API_SECRET"), |
|
"access_token": os.getenv("OWENJOHNSON_X_ACCESS_TOKEN"), |
|
"access_token_secret": os.getenv("OWENJOHNSON_X_ACCESS_TOKEN_SECRET"), |
|
"client_secret": os.getenv("OWENJOHNSON_X_CLIENT_SECRET") |
|
}, |
|
"javiermorales": { |
|
"x_username": "@mrjaviermorales", |
|
"api_key": os.getenv("JAVIERMORALES_X_API_KEY"), |
|
"api_secret": os.getenv("JAVIERMORALES_X_API_SECRET"), |
|
"access_token": os.getenv("JAVIERMORALES_X_ACCESS_TOKEN"), |
|
"access_token_secret": os.getenv("JAVIERMORALES_X_ACCESS_TOKEN_SECRET"), |
|
"client_secret": os.getenv("JAVIERMORALES_X_CLIENT_SECRET") |
|
}, |
|
"aishapatel": { |
|
"x_username": "@missaishapatel", |
|
"api_key": os.getenv("AISHAPATEL_X_API_KEY"), |
|
"api_secret": os.getenv("AISHAPATEL_X_API_SECRET"), |
|
"access_token": os.getenv("AISHAPATEL_X_ACCESS_TOKEN"), |
|
"access_token_secret": os.getenv("AISHAPATEL_X_ACCESS_TOKEN_SECRET"), |
|
"client_secret": os.getenv("AISHAPATEL_X_CLIENT_SECRET") |
|
}, |
|
"trangnguyen": { |
|
"x_username": "@mrtrangnguyen", |
|
"api_key": os.getenv("TRANGNGUYEN_X_API_KEY"), |
|
"api_secret": os.getenv("TRANGNGUYEN_X_API_SECRET"), |
|
"access_token": os.getenv("TRANGNGUYEN_X_ACCESS_TOKEN"), |
|
"access_token_secret": os.getenv("TRANGNGUYEN_X_ACCESS_TOKEN_SECRET"), |
|
"client_secret": os.getenv("TRANGNGUYEN_X_CLIENT_SECRET") |
|
}, |
|
"keishareid": { |
|
"x_username": "@misskeishareid", |
|
"api_key": os.getenv("KEISHAREID_X_API_KEY"), |
|
"api_secret": os.getenv("KEISHAREID_X_API_SECRET"), |
|
"access_token": os.getenv("KEISHAREID_X_ACCESS_TOKEN"), |
|
"access_token_secret": os.getenv("KEISHAREID_X_ACCESS_TOKEN_SECRET"), |
|
"client_secret": os.getenv("KEISHAREID_X_CLIENT_SECRET") |
|
}, |
|
"lilamoreau": { |
|
"x_username": "@misslilamoreau", |
|
"api_key": os.getenv("LILAMOREAU_X_API_KEY"), |
|
"api_secret": os.getenv("LILAMOREAU_X_API_SECRET"), |
|
"access_token": os.getenv("LILAMOREAU_X_ACCESS_TOKEN"), |
|
"access_token_secret": os.getenv("LILAMOREAU_X_ACCESS_TOKEN_SECRET"), |
|
"client_secret": os.getenv("LILAMOREAU_X_CLIENT_SECRET") |
|
} |
|
} |
|
|
|
PERSONA_CONFIGS = { |
|
"Visionary Editor": { |
|
"description": "a commanding food editor with a borderless view", |
|
"tone": "a polished and insightful tone, like 'This redefines culinary excellence.'", |
|
"article_prompt": ( |
|
"You're {description}. Summarize this article in {tone}. " |
|
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. " |
|
"Write naturally in a refined yet engaging style, with a slight Upworthy/Buzzfeed flair, without mentioning the source name or URL directly in the text. " |
|
"Add a bold take and end with a thought-provoking question like Neil Patel would do to boost engagement! Do not include emojis in the summary." |
|
), |
|
"x_prompt": ( |
|
"Craft a tweet as {description}. Keep it under 280 characters, using {tone}. " |
|
"For article tweets, include the article title, a quirky hook, and the URL. " |
|
"For engagement tweets, ask a question about food trends, foods, or articles to engage the public. " |
|
"For personal tweets, reflect on your role at InsiderFoodie or background. " |
|
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text." |
|
) |
|
}, |
|
"Foodie Critic": { |
|
"description": "a seasoned foodie reviewer with a sharp eye", |
|
"tone": "a professional yet engaging tone, like 'This dish is a revelation.'", |
|
"article_prompt": ( |
|
"You're {description}. Summarize this article in {tone}. " |
|
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. " |
|
"Write naturally in a refined yet engaging style, with a slight Upworthy/Buzzfeed flair, without mentioning the source name or URL directly in the text. " |
|
"Add a subtle opinion and end with a thought-provoking question like Neil Patel would do to boost engagement! Do not include emojis in the summary." |
|
), |
|
"x_prompt": ( |
|
"Craft a tweet as {description}. Keep it under 280 characters, using {tone}. " |
|
"For article tweets, include the article title, a quirky hook, and the URL. " |
|
"For engagement tweets, ask a question about food trends, foods, or articles to engage the public. " |
|
"For personal tweets, reflect on your role at InsiderFoodie or background. " |
|
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text." |
|
) |
|
}, |
|
"Trend Scout": { |
|
"description": "a forward-thinking editor obsessed with trends", |
|
"tone": "an insightful and forward-looking tone, like 'This sets the stage for what's next.'", |
|
"article_prompt": ( |
|
"You're {description}. Summarize this article in {tone}. " |
|
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. " |
|
"Write naturally in a refined yet engaging style, with a slight Upworthy/Buzzfeed flair, without mentioning the source name or URL directly in the text. " |
|
"Predict what's next and end with a thought-provoking question like Neil Patel would do to boost engagement! Do not include emojis in the summary." |
|
), |
|
"x_prompt": ( |
|
"Craft a tweet as {description}. Keep it under 280 characters, using {tone}. " |
|
"For article tweets, include the article title, a quirky hook, and the URL. " |
|
"For engagement tweets, ask a question about food trends, foods, or articles to engage the public. " |
|
"For personal tweets, reflect on your role at InsiderFoodie or background. " |
|
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text." |
|
) |
|
}, |
|
"Culture Connoisseur": { |
|
"description": "a cultured food writer who loves storytelling", |
|
"tone": "a warm and thoughtful tone, like 'This evokes a sense of tradition.'", |
|
"article_prompt": ( |
|
"You're {description}. Summarize this article in {tone}. " |
|
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. " |
|
"Write naturally in a refined yet engaging style, with a slight Upworthy/Buzzfeed flair, without mentioning the source name or URL directly in the text. " |
|
"Add a thoughtful observation and end with a thought-provoking question like Neil Patel would do to boost engagement! Do not include emojis in the summary." |
|
), |
|
"x_prompt": ( |
|
"Craft a tweet as {description}. Keep it under 280 characters, using {tone}. " |
|
"For article tweets, include the article title, a quirky hook, and the URL. " |
|
"For engagement tweets, ask a question about food trends, foods, or articles to engage the public. " |
|
"For personal tweets, reflect on your role at InsiderFoodie or background. " |
|
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text." |
|
) |
|
}, |
|
"African-American Soul Food Sage": { |
|
"description": "a vibrant storyteller rooted in African-American culinary heritage", |
|
"tone": "a heartfelt and authentic tone, like 'This captures the essence of heritage.'", |
|
"article_prompt": ( |
|
"You're {description}. Summarize this article in {tone}. " |
|
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. " |
|
"Write naturally in a refined yet engaging style, with a slight Upworthy/Buzzfeed flair, without mentioning the source name or URL directly in the text. " |
|
"Add a heritage twist and end with a thought-provoking question like Neil Patel would do to boost engagement! Do not include emojis in the summary." |
|
), |
|
"x_prompt": ( |
|
"Craft a tweet as {description}. Keep it under 280 characters, using {tone}. " |
|
"For article tweets, include the article title, a quirky hook, and the URL. " |
|
"For engagement tweets, ask a question about food trends, foods, or articles to engage the public. " |
|
"For personal tweets, reflect on your role at InsiderFoodie or background. " |
|
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text." |
|
) |
|
}, |
|
"Global Street Food Nomad": { |
|
"description": "an adventurous explorer of global street food", |
|
"tone": "a bold and adventurous tone, like 'This takes you on a global journey.'", |
|
"article_prompt": ( |
|
"You're {description}. Summarize this article in {tone}. " |
|
"Explore a wide range of food-related topics, skip recipes. Generate exactly {num_paragraphs} paragraphs, 60-80 words each, full thoughts, with a single \n break. " |
|
"Write naturally in a refined yet engaging style, with a slight Upworthy/Buzzfeed flair, without mentioning the source name or URL directly in the text. " |
|
"Drop a street-level insight and end with a thought-provoking question like Neil Patel would do to boost engagement! Do not include emojis in the summary." |
|
), |
|
"x_prompt": ( |
|
"Craft a tweet as {description}. Keep it under 280 characters, using {tone}. " |
|
"For article tweets, include the article title, a quirky hook, and the URL. " |
|
"For engagement tweets, ask a question about food trends, foods, or articles to engage the public. " |
|
"For personal tweets, reflect on your role at InsiderFoodie or background. " |
|
"Avoid emojis and clichés like 'game-changer'. Return only the tweet text." |
|
) |
|
} |
|
} |
|
|
|
# File paths |
|
POSTED_RSS_TITLES_FILE = '/home/shane/foodie_automator/posted_rss_titles.json' |
|
POSTED_GOOGLE_TITLES_FILE = '/home/shane/foodie_automator/posted_google_titles.json' |
|
POSTED_REDDIT_TITLES_FILE = '/home/shane/foodie_automator/posted_reddit_titles.json' |
|
USED_IMAGES_FILE = '/home/shane/foodie_automator/used_images.json' |
|
AUTHOR_BACKGROUNDS_FILE = '/home/shane/foodie_automator/author_backgrounds.json' |
|
X_POST_COUNTS_FILE = '/home/shane/foodie_automator/x_post_counts.json' |
|
RECENT_POSTS_FILE = '/home/shane/foodie_automator/recent_posts.json' |
|
|
|
EXPIRATION_DAYS = 3 |
|
IMAGE_EXPIRATION_DAYS = 7 |
|
|
|
RSS_FEEDS = [ |
|
"https://www.eater.com/rss/full.xml", |
|
"https://www.nrn.com/rss.xml", |
|
"https://rss.nytimes.com/services/xml/rss/nyt/DiningandWine.xml", |
|
"https://www.theguardian.com/food/rss" |
|
] |
|
|
|
RSS_FEED_NAMES = { |
|
"https://www.eater.com/rss/full.xml": ("Eater", "https://www.eater.com/"), |
|
"https://www.nrn.com/rss.xml": ("Nation's Restaurant News", "https://www.nrn.com/"), |
|
"https://rss.nytimes.com/services/xml/rss/nyt/DiningandWine.xml": ("The New York Times", "https://www.nytimes.com/section/food"), |
|
"https://www.theguardian.com/food/rss": ("The Guardian", "https://www.theguardian.com/food") |
|
} |
|
|
|
RECIPE_KEYWORDS = ["recipe", "cook", "bake", "baking", "cooking", "ingredient", "method", "mix", "stir", "preheat", "dinners", "make", "dish", "healthy"] |
|
PROMO_KEYWORDS = ["we serve", "our guests", "event", "competition", "franchise", "off", "discount", "sale"] |
|
HOME_KEYWORDS = ["home", "house", "household", "appliance", "kitchen", "gadget"] |
|
PRODUCT_KEYWORDS = ["best", "buy", "storage", "organizer", "shop", "price", "container", "product", "deal", "sale", "discount"] |
|
|
|
CATEGORIES = [ |
|
"Buzz", "Trends", "Lifestyle", "Culture", "Health", "Drink", "Food", "Eats" |
|
] |
|
|
|
REDDIT_CLIENT_ID = os.getenv("REDDIT_CLIENT_ID") |
|
REDDIT_CLIENT_SECRET = os.getenv("REDDIT_CLIENT_SECRET") |
|
REDDIT_USER_AGENT = os.getenv("REDDIT_USER_AGENT") |
|
REDDIT_SUBREDDITS = [ |
|
"food", |
|
"FoodPorn", |
|
"spicy", |
|
"KoreanFood", |
|
"JapaneseFood", |
|
"DessertPorn", |
|
"ChineseFood", |
|
"IndianFood" |
|
] |
|
FAST_FOOD_KEYWORDS = [ |
|
"mcdonald", "burger king", "wendy", "taco bell", "kfc", |
|
"subway", "domino", "pizza hut", "chipotle", "dunkin", |
|
"starbucks", "sonic", "arby", "jack in the box", "popeyes", |
|
"fast food", "chain", "drive-thru" |
|
] |
|
|
|
SUMMARY_MODEL = "gpt-4o" # or "gpt-4.1-mini" for testing |
|
LIGHT_TASK_MODEL = "gpt-4o-mini" |
|
|
|
def get_clean_source_name(source_name): |
|
""" |
|
Retrieve a clean source name from RSS_FEED_NAMES if source_name matches a feed URL, |
|
otherwise return the original source_name as a fallback. |
|
""" |
|
for feed_url, (clean_name, _) in RSS_FEED_NAMES.items(): |
|
if feed_url == source_name: |
|
return clean_name |
|
return source_name |
|
|
|
# Email configuration for alerts |
|
EMAIL_CONFIG = { |
|
'from_email': 'systemalerts@insiderfoodie.com', # System alerts email |
|
'to_email': 'systemalerts@insiderfoodie.com', # Same email for receiving alerts |
|
'smtp_server': 'mail.insiderfoodie.com', # Your SMTP server |
|
'smtp_port': 587, # STARTTLS port |
|
'smtp_username': 'systemalerts', # SMTP username |
|
'smtp_password': os.getenv('INSIDERFOODIE_EMAIL_PASSWORD') # Store password in .env |
|
} |