change weekly to manual posting for X
This commit is contained in:
+57
-34
@@ -15,7 +15,8 @@ from foodie_config import X_API_CREDENTIALS, RECENT_POSTS_FILE
|
|||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
# Output file for weekly thread content
|
||||||
|
WEEKLY_THREADS_FILE = "/home/shane/foodie_automator/weekly_threads.json"
|
||||||
SCRIPT_NAME = "foodie_weekly_thread"
|
SCRIPT_NAME = "foodie_weekly_thread"
|
||||||
LOCK_FILE = "/home/shane/foodie_automator/locks/foodie_weekly_thread.lock"
|
LOCK_FILE = "/home/shane/foodie_automator/locks/foodie_weekly_thread.lock"
|
||||||
LOG_FILE = "/home/shane/foodie_automator/logs/foodie_weekly_thread.log"
|
LOG_FILE = "/home/shane/foodie_automator/logs/foodie_weekly_thread.log"
|
||||||
@@ -267,7 +268,7 @@ def generate_final_cta(author):
|
|||||||
return fallback
|
return fallback
|
||||||
|
|
||||||
def post_weekly_thread():
|
def post_weekly_thread():
|
||||||
"""Generate and post a weekly thread of top posts for each author on Mondays."""
|
"""Generate weekly thread content for each author and save to file on Mondays."""
|
||||||
logging.info("Starting foodie_weekly_thread.py")
|
logging.info("Starting foodie_weekly_thread.py")
|
||||||
|
|
||||||
# Check if today is Monday
|
# Check if today is Monday
|
||||||
@@ -307,7 +308,10 @@ def post_weekly_thread():
|
|||||||
if username in posts_by_author:
|
if username in posts_by_author:
|
||||||
posts_by_author[username].append(post)
|
posts_by_author[username].append(post)
|
||||||
|
|
||||||
# Post threads for each author
|
# Generate thread content for each author and save to file
|
||||||
|
thread_content = []
|
||||||
|
timestamp = datetime.now(timezone.utc).isoformat()
|
||||||
|
|
||||||
for author in AUTHORS:
|
for author in AUTHORS:
|
||||||
username = author["username"]
|
username = author["username"]
|
||||||
author_posts = posts_by_author.get(username, [])
|
author_posts = posts_by_author.get(username, [])
|
||||||
@@ -315,56 +319,73 @@ def post_weekly_thread():
|
|||||||
logging.info(f"No posts found for {username}, skipping")
|
logging.info(f"No posts found for {username}, skipping")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Check if the author can post before generating the thread
|
|
||||||
can_post, remaining, reset = check_author_rate_limit(author)
|
|
||||||
if not can_post:
|
|
||||||
reset_time = datetime.fromtimestamp(reset, tz=timezone.utc).strftime('%Y-%m-%d %H:%M:%S') if reset else "Unknown"
|
|
||||||
logging.info(f"Skipping weekly thread for {username} due to rate limit. Reset at: {reset_time}")
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Select top 2 posts (to fit within 3-tweet limit: lead + 2 posts)
|
# 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]
|
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}")
|
logging.info(f"Selected {len(author_posts)} posts for {username}")
|
||||||
|
|
||||||
# Generate and post thread
|
# Generate thread content
|
||||||
try:
|
try:
|
||||||
# Post lead tweet
|
# Generate intro tweet
|
||||||
intro_tweet = generate_intro_tweet(author)
|
intro_tweet = generate_intro_tweet(author)
|
||||||
if not intro_tweet:
|
if not intro_tweet:
|
||||||
logging.error(f"Failed to generate intro tweet for {username}, skipping")
|
logging.error(f"Failed to generate intro tweet for {username}, skipping")
|
||||||
continue
|
continue
|
||||||
lead_response = post_tweet(author, intro_tweet)
|
|
||||||
if not lead_response:
|
|
||||||
logging.error(f"Failed to post lead tweet for {username}, skipping")
|
|
||||||
continue
|
|
||||||
lead_tweet_id = lead_response["id"]
|
|
||||||
logging.info(f"Posted lead tweet for {username}: {intro_tweet}")
|
|
||||||
|
|
||||||
# Post thread tweets (up to 2)
|
# Generate thread tweets (up to 2)
|
||||||
|
thread_tweets = []
|
||||||
for i, post in enumerate(author_posts, 1):
|
for i, post in enumerate(author_posts, 1):
|
||||||
thread_tweet = (
|
thread_tweet = (
|
||||||
f"{i}. {post['title']} "
|
f"{i}. {post['title']} "
|
||||||
f"Read more: {post['url']}"
|
f"Read more: {post['url']}"
|
||||||
)
|
)
|
||||||
thread_response = post_tweet(author, thread_tweet, reply_to_id=lead_tweet_id)
|
thread_tweets.append(thread_tweet)
|
||||||
if thread_response:
|
logging.info(f"Generated thread tweet {i} for {username}: {thread_tweet}")
|
||||||
lead_tweet_id = thread_response["id"]
|
|
||||||
logging.info(f"Posted thread tweet {i} for {username}: {thread_tweet}")
|
|
||||||
else:
|
|
||||||
logging.warning(f"Failed to post thread tweet {i} for {username}")
|
|
||||||
|
|
||||||
# Post final CTA tweet
|
# Generate final CTA tweet
|
||||||
final_cta = generate_final_cta(author)
|
final_cta = generate_final_cta(author)
|
||||||
if final_cta:
|
if not final_cta:
|
||||||
cta_response = post_tweet(author, final_cta, reply_to_id=lead_tweet_id)
|
logging.error(f"Failed to generate final CTA tweet for {username}, using fallback")
|
||||||
if cta_response:
|
final_cta = (
|
||||||
logging.info(f"Posted final CTA tweet for {username}: {final_cta}")
|
f"Want more foodie insights like these? Check out insiderfoodie.com and follow @{X_API_CREDENTIALS[username]['x_username']} "
|
||||||
else:
|
f"for the world’s top 10 foodie trends every Monday. Don’t miss out!"
|
||||||
logging.warning(f"Failed to post final CTA tweet for {username}")
|
)
|
||||||
|
|
||||||
|
# Collect thread content for this author
|
||||||
|
author_thread = {
|
||||||
|
"username": username,
|
||||||
|
"x_handle": X_API_CREDENTIALS[username]["x_username"],
|
||||||
|
"intro_tweet": intro_tweet,
|
||||||
|
"thread_tweets": thread_tweets,
|
||||||
|
"final_cta": final_cta,
|
||||||
|
"timestamp": timestamp
|
||||||
|
}
|
||||||
|
thread_content.append(author_thread)
|
||||||
|
logging.info(f"Generated thread content for {username}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error posting thread for {username}: {e}", exc_info=True)
|
logging.error(f"Error generating thread content for {username}: {e}", exc_info=True)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Save thread content to file
|
||||||
|
if thread_content:
|
||||||
|
try:
|
||||||
|
# Load existing threads, if any
|
||||||
|
existing_threads = load_json_file(WEEKLY_THREADS_FILE, default=[])
|
||||||
|
# Append new thread content
|
||||||
|
existing_threads.append({
|
||||||
|
"week_start": start_date.isoformat(),
|
||||||
|
"week_end": end_date.isoformat(),
|
||||||
|
"timestamp": timestamp,
|
||||||
|
"threads": thread_content
|
||||||
|
})
|
||||||
|
# Save to file
|
||||||
|
save_json_file(WEEKLY_THREADS_FILE, existing_threads)
|
||||||
|
logging.info(f"Saved thread content for {len(thread_content)} authors to {WEEKLY_THREADS_FILE}")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Failed to save thread content to {WEEKLY_THREADS_FILE}: {e}")
|
||||||
|
else:
|
||||||
|
logging.warning("No thread content generated, nothing to save")
|
||||||
|
|
||||||
logging.info("Completed foodie_weekly_thread.py")
|
logging.info("Completed foodie_weekly_thread.py")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -374,6 +395,8 @@ def main():
|
|||||||
lock_fd = acquire_lock()
|
lock_fd = acquire_lock()
|
||||||
setup_logging()
|
setup_logging()
|
||||||
update_system_activity(SCRIPT_NAME, "running", os.getpid()) # Record start
|
update_system_activity(SCRIPT_NAME, "running", os.getpid()) # Record start
|
||||||
|
# Skip Twitter credentials validation since we're not posting
|
||||||
|
# validate_twitter_credentials()
|
||||||
post_weekly_thread()
|
post_weekly_thread()
|
||||||
update_system_activity(SCRIPT_NAME, "stopped") # Record stop
|
update_system_activity(SCRIPT_NAME, "stopped") # Record stop
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Reference in New Issue
Block a user