fix
This commit is contained in:
+35
-1
@@ -3,7 +3,8 @@ import logging
|
||||
from datetime import datetime, timezone
|
||||
from foodie_utils import (
|
||||
AUTHORS, check_author_rate_limit, load_json_file,
|
||||
get_x_rate_limit_status, update_system_activity, is_any_script_running
|
||||
get_x_rate_limit_status, update_system_activity, is_any_script_running,
|
||||
save_json_file
|
||||
)
|
||||
import time
|
||||
import sys
|
||||
@@ -20,8 +21,41 @@ logging.basicConfig(
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# File to track sent notifications
|
||||
NOTIFICATION_FILE = '/home/shane/foodie_automator/notification_tracking.json'
|
||||
|
||||
def load_notification_tracking():
|
||||
"""Load notification tracking data."""
|
||||
return load_json_file(NOTIFICATION_FILE, default={})
|
||||
|
||||
def save_notification_tracking(tracking_data):
|
||||
"""Save notification tracking data."""
|
||||
save_json_file(NOTIFICATION_FILE, tracking_data)
|
||||
|
||||
def should_send_notification(username, reset_time):
|
||||
"""Check if we should send a notification for this author."""
|
||||
tracking = load_notification_tracking()
|
||||
author_data = tracking.get(username, {})
|
||||
|
||||
# If we've never notified for this author or the reset time has changed
|
||||
if not author_data or author_data.get('reset_time') != reset_time:
|
||||
# Update tracking
|
||||
tracking[username] = {
|
||||
'last_notification': datetime.now(timezone.utc).isoformat(),
|
||||
'reset_time': reset_time
|
||||
}
|
||||
save_notification_tracking(tracking)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def send_capacity_alert(username, remaining, reset_time):
|
||||
"""Send email alert when an author's tweet capacity is full."""
|
||||
# Check if we should send notification
|
||||
if not should_send_notification(username, reset_time):
|
||||
logger.info(f"Skipping duplicate notification for {username}")
|
||||
return
|
||||
|
||||
try:
|
||||
msg = MIMEMultipart()
|
||||
msg['From'] = EMAIL_CONFIG['from_email']
|
||||
|
||||
+21
-22
@@ -164,29 +164,28 @@ def post_engagement_tweet():
|
||||
logging.info("Starting foodie_engagement_tweet.py")
|
||||
posted = False
|
||||
|
||||
for author in AUTHORS:
|
||||
# Check if the author can post before generating the tweet
|
||||
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 engagement tweet for {author['username']} due to rate limit. Reset at: {reset_time}")
|
||||
continue
|
||||
# Get next available author using round-robin
|
||||
author = get_next_author_round_robin()
|
||||
if not author:
|
||||
logging.info("No authors available due to rate limits")
|
||||
sleep_time = random.randint(1200, 1800) # 20–30 minutes
|
||||
return False, sleep_time
|
||||
|
||||
try:
|
||||
tweet = generate_engagement_tweet(author)
|
||||
if not tweet:
|
||||
logging.error(f"Failed to generate engagement tweet for {author['username']}, skipping")
|
||||
continue
|
||||
|
||||
logging.info(f"Posting engagement tweet for {author['username']}: {tweet}")
|
||||
if post_tweet(author, tweet):
|
||||
logging.info(f"Successfully posted engagement tweet for {author['username']}")
|
||||
posted = True
|
||||
else:
|
||||
logging.warning(f"Failed to post engagement tweet for {author['username']}")
|
||||
except Exception as e:
|
||||
logging.error(f"Error posting engagement tweet for {author['username']}: {e}", exc_info=True)
|
||||
continue
|
||||
try:
|
||||
tweet = generate_engagement_tweet(author)
|
||||
if not tweet:
|
||||
logging.error(f"Failed to generate engagement tweet for {author['username']}, skipping")
|
||||
sleep_time = random.randint(1200, 1800) # 20–30 minutes
|
||||
return False, sleep_time
|
||||
|
||||
logging.info(f"Posting engagement tweet for {author['username']}: {tweet}")
|
||||
if post_tweet(author, tweet):
|
||||
logging.info(f"Successfully posted engagement tweet for {author['username']}")
|
||||
posted = True
|
||||
else:
|
||||
logging.warning(f"Failed to post engagement tweet for {author['username']}")
|
||||
except Exception as e:
|
||||
logging.error(f"Error posting engagement tweet for {author['username']}: {e}", exc_info=True)
|
||||
|
||||
logging.info("Completed foodie_engagement_tweet.py")
|
||||
sleep_time = random.randint(1200, 1800) # 20–30 minutes
|
||||
|
||||
+4
-3
@@ -235,7 +235,7 @@ def post_tweet(author, content, media_ids=None, reply_to_id=None, tweet_type="rs
|
||||
author_info = rate_limit_info[username]
|
||||
|
||||
if response.status_code == 201:
|
||||
# Successful post - update remaining tweets
|
||||
# Successful post - update remaining tweets and increment posted count
|
||||
author_info['tweets_posted_in_run'] = author_info.get('tweets_posted_in_run', 0) + 1
|
||||
author_info['tweet_remaining'] = remaining - 1 # Decrement remaining tweets
|
||||
rate_limit_info[username] = author_info
|
||||
@@ -251,6 +251,7 @@ def post_tweet(author, content, media_ids=None, reply_to_id=None, tweet_type="rs
|
||||
reset = int(reset_str)
|
||||
author_info['tweet_remaining'] = remaining
|
||||
author_info['tweet_reset'] = reset
|
||||
# Don't reset tweets_posted_in_run here
|
||||
rate_limit_info[username] = author_info
|
||||
save_json_file(rate_limit_file, rate_limit_info)
|
||||
logger.info(f"Updated rate limit info from API for {username}: {remaining}/17 tweets remaining")
|
||||
@@ -1798,10 +1799,10 @@ def check_author_rate_limit(author, max_tweets=17, tweet_window_seconds=86400):
|
||||
remaining = min(remaining, max_tweets) # Ensure within Free tier limit
|
||||
reset = api_reset
|
||||
|
||||
# Update author info
|
||||
# Update author info but preserve tweets_posted_in_run
|
||||
author_info['tweet_remaining'] = remaining
|
||||
author_info['tweet_reset'] = reset
|
||||
author_info['tweets_posted_in_run'] = 0
|
||||
# Don't reset tweets_posted_in_run here
|
||||
rate_limit_info[username] = author_info
|
||||
save_json_file(rate_limit_file, rate_limit_info)
|
||||
|
||||
|
||||
+26
-20
@@ -93,31 +93,37 @@ def generate_engagement_tweet(author, persona):
|
||||
return tweet
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to generate engagement tweet for {author['username']}: {e}")
|
||||
return f"What’s your take on {theme}? Let’s talk!"
|
||||
return f"What's your take on {theme}? Let's talk!"
|
||||
|
||||
def get_next_author_round_robin():
|
||||
for author in AUTHORS:
|
||||
# Check if the author can post before generating the tweet
|
||||
can_post, remaining, reset = check_author_rate_limit(author)
|
||||
if can_post:
|
||||
return author
|
||||
return None
|
||||
|
||||
def main():
|
||||
global is_posting
|
||||
logging.info("***** X Poster Launched *****")
|
||||
for author in AUTHORS:
|
||||
# Check if the author can post before generating the tweet
|
||||
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 engagement tweet for {author['username']} due to rate limit. Remaining: {remaining}, Reset at: {reset_time}")
|
||||
continue
|
||||
|
||||
# Get next available author using round-robin
|
||||
author = get_next_author_round_robin()
|
||||
if not author:
|
||||
logging.info("No authors available due to rate limits")
|
||||
return random.randint(600, 1800)
|
||||
|
||||
is_posting = True
|
||||
try:
|
||||
tweet = generate_engagement_tweet(author, author["persona"])
|
||||
if post_tweet(author, tweet):
|
||||
logging.info(f"Successfully posted engagement tweet for {author['username']}")
|
||||
else:
|
||||
logging.warning(f"Failed to post engagement tweet for {author['username']}")
|
||||
except Exception as e:
|
||||
logging.error(f"Error posting engagement tweet for {author['username']}: {e}", exc_info=True)
|
||||
finally:
|
||||
is_posting = False
|
||||
time.sleep(random.uniform(3600, 7200))
|
||||
is_posting = True
|
||||
try:
|
||||
tweet = generate_engagement_tweet(author, author["persona"])
|
||||
if post_tweet(author, tweet):
|
||||
logging.info(f"Successfully posted engagement tweet for {author['username']}")
|
||||
else:
|
||||
logging.warning(f"Failed to post engagement tweet for {author['username']}")
|
||||
except Exception as e:
|
||||
logging.error(f"Error posting engagement tweet for {author['username']}: {e}", exc_info=True)
|
||||
finally:
|
||||
is_posting = False
|
||||
|
||||
logging.info("X posting completed")
|
||||
return random.randint(600, 1800)
|
||||
|
||||
Reference in New Issue
Block a user