|
|
|
|
@ -16,7 +16,6 @@ load_dotenv() |
|
|
|
|
|
|
|
|
|
LOCK_FILE = "/home/shane/foodie_automator/locks/foodie_engagement_tweet.lock" |
|
|
|
|
LOG_FILE = "/home/shane/foodie_automator/logs/foodie_engagement_tweet.log" |
|
|
|
|
REFERENCE_DATE_FILE = "/home/shane/foodie_automator/engagement_reference_date.json" |
|
|
|
|
LOG_PRUNE_DAYS = 30 |
|
|
|
|
MAX_RETRIES = 3 |
|
|
|
|
RETRY_BACKOFF = 2 |
|
|
|
|
@ -101,29 +100,6 @@ except Exception as e: |
|
|
|
|
logging.error(f"Failed to load author_backgrounds.json: {e}", exc_info=True) |
|
|
|
|
sys.exit(1) |
|
|
|
|
|
|
|
|
|
def get_reference_date(): |
|
|
|
|
"""Load or initialize the reference date for the 2-day interval.""" |
|
|
|
|
os.makedirs(os.path.dirname(REFERENCE_DATE_FILE), exist_ok=True) |
|
|
|
|
if os.path.exists(REFERENCE_DATE_FILE): |
|
|
|
|
try: |
|
|
|
|
with open(REFERENCE_DATE_FILE, 'r') as f: |
|
|
|
|
data = json.load(f) |
|
|
|
|
reference_date = datetime.fromisoformat(data["reference_date"]).replace(tzinfo=timezone.utc) |
|
|
|
|
logging.info(f"Loaded reference date: {reference_date.date()}") |
|
|
|
|
return reference_date |
|
|
|
|
except (json.JSONDecodeError, KeyError, ValueError) as e: |
|
|
|
|
logging.error(f"Failed to load reference date from {REFERENCE_DATE_FILE}: {e}. Initializing new date.") |
|
|
|
|
|
|
|
|
|
# Initialize with current date (start of day) |
|
|
|
|
reference_date = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0) |
|
|
|
|
try: |
|
|
|
|
with open(REFERENCE_DATE_FILE, 'w') as f: |
|
|
|
|
json.dump({"reference_date": reference_date.isoformat()}, f) |
|
|
|
|
logging.info(f"Initialized reference date: {reference_date.date()}") |
|
|
|
|
except Exception as e: |
|
|
|
|
logging.error(f"Failed to save reference date to {REFERENCE_DATE_FILE}: {e}. Using current date.") |
|
|
|
|
return reference_date |
|
|
|
|
|
|
|
|
|
def generate_engagement_tweet(author): |
|
|
|
|
"""Generate an engagement tweet using author background themes.""" |
|
|
|
|
credentials = X_API_CREDENTIALS.get(author["username"]) |
|
|
|
|
@ -180,61 +156,46 @@ def generate_engagement_tweet(author): |
|
|
|
|
return template |
|
|
|
|
|
|
|
|
|
def post_engagement_tweet(): |
|
|
|
|
"""Post engagement tweets for authors every 2 days.""" |
|
|
|
|
"""Post engagement tweets for authors daily.""" |
|
|
|
|
try: |
|
|
|
|
logging.info("Starting foodie_engagement_tweet.py") |
|
|
|
|
print("Starting foodie_engagement_tweet.py") |
|
|
|
|
|
|
|
|
|
# Get reference date |
|
|
|
|
reference_date = get_reference_date() |
|
|
|
|
current_date = datetime.now(timezone.utc) |
|
|
|
|
days_since_reference = (current_date - reference_date).days |
|
|
|
|
logging.info(f"Days since reference date ({reference_date.date()}): {days_since_reference}") |
|
|
|
|
print(f"Days since reference date ({reference_date.date()}): {days_since_reference}") |
|
|
|
|
|
|
|
|
|
# Post only if the number of days since the reference date is divisible by 2 |
|
|
|
|
if days_since_reference % 2 == 0: |
|
|
|
|
logging.info("Today is an engagement tweet day (every 2 days). Posting...") |
|
|
|
|
print("Today is an engagement tweet day (every 2 days). Posting...") |
|
|
|
|
|
|
|
|
|
# Load post counts to check limits |
|
|
|
|
post_counts = load_post_counts() |
|
|
|
|
# Load post counts to check limits |
|
|
|
|
post_counts = load_post_counts() |
|
|
|
|
|
|
|
|
|
for author in AUTHORS: |
|
|
|
|
try: |
|
|
|
|
# Check post limits |
|
|
|
|
author_count = next((entry for entry in post_counts if entry["username"] == author["username"]), None) |
|
|
|
|
if not author_count: |
|
|
|
|
logging.error(f"No post count entry for {author['username']}, skipping") |
|
|
|
|
continue |
|
|
|
|
if author_count["monthly_count"] >= 500: |
|
|
|
|
logging.warning(f"Monthly post limit (500) reached for {author['username']}, skipping") |
|
|
|
|
continue |
|
|
|
|
if author_count["daily_count"] >= 20: |
|
|
|
|
logging.warning(f"Daily post limit (20) reached for {author['username']}, skipping") |
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
tweet = generate_engagement_tweet(author) |
|
|
|
|
if not tweet: |
|
|
|
|
logging.error(f"Failed to generate engagement tweet for {author['username']}, skipping") |
|
|
|
|
continue |
|
|
|
|
for author in AUTHORS: |
|
|
|
|
try: |
|
|
|
|
# Check post limits |
|
|
|
|
author_count = next((entry for entry in post_counts if entry["username"] == author["username"]), None) |
|
|
|
|
if not author_count: |
|
|
|
|
logging.error(f"No post count entry for {author['username']}, skipping") |
|
|
|
|
continue |
|
|
|
|
if author_count["monthly_count"] >= 500: |
|
|
|
|
logging.warning(f"Monthly post limit (500) reached for {author['username']}, skipping") |
|
|
|
|
continue |
|
|
|
|
if author_count["daily_count"] >= 15: |
|
|
|
|
logging.warning(f"Daily post limit (15) reached for {author['username']}, skipping") |
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
logging.info(f"Posting engagement tweet for {author['username']}: {tweet}") |
|
|
|
|
print(f"Posting engagement tweet for {author['username']}: {tweet}") |
|
|
|
|
if post_tweet(author, tweet): |
|
|
|
|
logging.info(f"Successfully posted engagement tweet for {author['username']}") |
|
|
|
|
# Update post counts |
|
|
|
|
author_count["monthly_count"] += 1 |
|
|
|
|
author_count["daily_count"] += 1 |
|
|
|
|
save_post_counts(post_counts) |
|
|
|
|
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) |
|
|
|
|
tweet = generate_engagement_tweet(author) |
|
|
|
|
if not tweet: |
|
|
|
|
logging.error(f"Failed to generate engagement tweet for {author['username']}, skipping") |
|
|
|
|
continue |
|
|
|
|
else: |
|
|
|
|
logging.info(f"Today is not an engagement tweet day (every 2 days). Days since reference: {days_since_reference}. Skipping...") |
|
|
|
|
print(f"Today is not an engagement tweet day (every 2 days). Days since reference: {days_since_reference}. Skipping...") |
|
|
|
|
|
|
|
|
|
logging.info(f"Posting engagement tweet for {author['username']}: {tweet}") |
|
|
|
|
print(f"Posting engagement tweet for {author['username']}: {tweet}") |
|
|
|
|
if post_tweet(author, tweet): |
|
|
|
|
logging.info(f"Successfully posted engagement tweet for {author['username']}") |
|
|
|
|
# Update post counts |
|
|
|
|
author_count["monthly_count"] += 1 |
|
|
|
|
author_count["daily_count"] += 1 |
|
|
|
|
save_post_counts(post_counts) |
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
logging.info("Completed foodie_engagement_tweet.py") |
|
|
|
|
print("Completed foodie_engagement_tweet.py") |
|
|
|
|
|