|
|
|
@ -47,7 +47,7 @@ IMAGE_EXPIRATION_DAYS = 7 # 7 days, consistent with foodie_automator_rss.py |
|
|
|
def load_json_file(file_path, expiration_hours=None, default=None): |
|
|
|
def load_json_file(file_path, expiration_hours=None, default=None): |
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
logger = logging.getLogger(__name__) |
|
|
|
if default is None: |
|
|
|
if default is None: |
|
|
|
default = [] |
|
|
|
default = [] if "rate_limit_info" not in file_path else {} |
|
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(file_path): |
|
|
|
if not os.path.exists(file_path): |
|
|
|
logger.info(f"File {file_path} does not exist. Returning default: {default}") |
|
|
|
logger.info(f"File {file_path} does not exist. Returning default: {default}") |
|
|
|
@ -57,6 +57,14 @@ def load_json_file(file_path, expiration_hours=None, default=None): |
|
|
|
with open(file_path, 'r') as f: |
|
|
|
with open(file_path, 'r') as f: |
|
|
|
data = json.load(f) |
|
|
|
data = json.load(f) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Handle rate_limit_info.json differently |
|
|
|
|
|
|
|
if "rate_limit_info" in file_path: |
|
|
|
|
|
|
|
if not isinstance(data, dict): |
|
|
|
|
|
|
|
logger.warning(f"Data in {file_path} is not a dictionary, resetting to default") |
|
|
|
|
|
|
|
return default |
|
|
|
|
|
|
|
return data |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# For other files, expect a list |
|
|
|
if not isinstance(data, list): |
|
|
|
if not isinstance(data, list): |
|
|
|
logger.warning(f"Data in {file_path} is not a list, resetting to default") |
|
|
|
logger.warning(f"Data in {file_path} is not a list, resetting to default") |
|
|
|
return default |
|
|
|
return default |
|
|
|
@ -1689,6 +1697,29 @@ def is_any_script_running(): |
|
|
|
logger.error(f"Failed to check system_activity.json: {e}") |
|
|
|
logger.error(f"Failed to check system_activity.json: {e}") |
|
|
|
return False |
|
|
|
return False |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def initialize_rate_limit_info(): |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
Initialize rate_limit_info.json with proper structure for all authors. |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
rate_limit_file = '/home/shane/foodie_automator/rate_limit_info.json' |
|
|
|
|
|
|
|
current_time = time.time() |
|
|
|
|
|
|
|
tweet_window_seconds = 86400 # 24 hours |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Initialize with all authors |
|
|
|
|
|
|
|
rate_limit_info = {} |
|
|
|
|
|
|
|
for author in AUTHORS: |
|
|
|
|
|
|
|
username = author['username'] |
|
|
|
|
|
|
|
rate_limit_info[username] = { |
|
|
|
|
|
|
|
'tweet_remaining': 17, # Free tier max |
|
|
|
|
|
|
|
'tweet_reset': current_time + tweet_window_seconds, |
|
|
|
|
|
|
|
'tweets_posted_in_run': 0 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Save the initialized data |
|
|
|
|
|
|
|
save_json_file(rate_limit_file, rate_limit_info) |
|
|
|
|
|
|
|
logger.info(f"Initialized rate_limit_info.json with {len(rate_limit_info)} authors") |
|
|
|
|
|
|
|
return rate_limit_info |
|
|
|
|
|
|
|
|
|
|
|
def check_author_rate_limit(author, max_tweets=17, tweet_window_seconds=86400): |
|
|
|
def check_author_rate_limit(author, max_tweets=17, tweet_window_seconds=86400): |
|
|
|
""" |
|
|
|
""" |
|
|
|
Check if an author can post based on their X API Free tier quota (17 tweets per 24 hours per user). |
|
|
|
Check if an author can post based on their X API Free tier quota (17 tweets per 24 hours per user). |
|
|
|
@ -1702,14 +1733,9 @@ def check_author_rate_limit(author, max_tweets=17, tweet_window_seconds=86400): |
|
|
|
rate_limit_info = load_json_file(rate_limit_file, default={}) |
|
|
|
rate_limit_info = load_json_file(rate_limit_file, default={}) |
|
|
|
username = author['username'] |
|
|
|
username = author['username'] |
|
|
|
|
|
|
|
|
|
|
|
# Initialize author entry if missing |
|
|
|
# Initialize author entry if missing or if file is empty |
|
|
|
if username not in rate_limit_info: |
|
|
|
if not rate_limit_info or username not in rate_limit_info: |
|
|
|
rate_limit_info[username] = { |
|
|
|
rate_limit_info = initialize_rate_limit_info() |
|
|
|
'tweet_remaining': max_tweets, |
|
|
|
|
|
|
|
'tweet_reset': current_time + tweet_window_seconds, |
|
|
|
|
|
|
|
'tweets_posted_in_run': 0 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
save_json_file(rate_limit_file, rate_limit_info) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
author_info = rate_limit_info[username] |
|
|
|
author_info = rate_limit_info[username] |
|
|
|
|
|
|
|
|
|
|
|
|