#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ post_outdated_page.py This script reads the outdated_pages.json file generated by wiki_compare.py, randomly selects an outdated French wiki page, and posts a message on Mastodon suggesting that the page needs updating. Usage: python post_outdated_page.py [--dry-run] Options: --dry-run Run the script without actually posting to Mastodon Output: - A post on Mastodon about an outdated French wiki page - Log messages about the selected page and posting status """ import json import random import argparse import logging import os from datetime import datetime import requests import re # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) logger = logging.getLogger(__name__) # Function to read variables from .env file def read_env_file(env_file_path=".env"): """ Read environment variables from a .env file Args: env_file_path (str): Path to the .env file Returns: dict: Dictionary of environment variables """ env_vars = {} try: with open(env_file_path, 'r', encoding='utf-8') as f: for line in f: line = line.strip() # Skip comments and empty lines if not line or line.startswith('#'): continue # Match variable assignments (KEY=VALUE) match = re.match(r'^([A-Za-z0-9_]+)=(.*)$', line) if match: key, value = match.groups() # Remove quotes if present value = value.strip('\'"') env_vars[key] = value logger.info(f"Successfully loaded environment variables from {env_file_path}") return env_vars except IOError as e: logger.error(f"Error reading .env file {env_file_path}: {e}") return {} # Constants OUTDATED_PAGES_FILE = "outdated_pages.json" MASTODON_API_URL = "https://mastodon.cipherbliss.com/api/v1/statuses" # Replace with actual instance # Read MASTODON_ACCESS_TOKEN from .env file env_vars = read_env_file(".env") if not env_vars and os.path.exists(os.path.join(os.path.dirname(__file__), ".env")): # Try with absolute path if relative path fails env_vars = read_env_file(os.path.join(os.path.dirname(__file__), ".env")) MASTODON_ACCESS_TOKEN = env_vars.get("MASTODON_ACCESS_TOKEN") or os.environ.get("MASTODON_ACCESS_TOKEN") def load_outdated_pages(): """ Load the outdated pages from the JSON file Returns: list: List of dictionaries containing outdated page information """ try: with open(OUTDATED_PAGES_FILE, 'r', encoding='utf-8') as f: pages = json.load(f) logger.info(f"Successfully loaded {len(pages)} outdated pages from {OUTDATED_PAGES_FILE}") return pages except (IOError, json.JSONDecodeError) as e: logger.error(f"Error loading outdated pages from {OUTDATED_PAGES_FILE}: {e}") return [] def select_random_outdated_page(pages): """ Randomly select an outdated French page from the list Args: pages (list): List of dictionaries containing outdated page information Returns: dict: Randomly selected outdated page or None if no suitable pages found """ # Filter pages to include only those with a French page (not missing) pages_with_fr = [page for page in pages if page.get('fr_page') is not None] if not pages_with_fr: logger.warning("No outdated French pages found") return None # Randomly select a page selected_page = random.choice(pages_with_fr) logger.info(f"Randomly selected page for key '{selected_page['key']}'") return selected_page def create_mastodon_post(page): """ Create a Mastodon post about the outdated wiki page Args: page (dict): Dictionary containing outdated page information Returns: str: Formatted Mastodon post text """ key = page['key'] reason = page['reason'] fr_url = page['fr_page']['url'] en_url = page['en_page']['url'] # Format the post post = f"""📝 La page wiki OSM pour la clĂ© #{key} a besoin d'une mise Ă  jour ! Raison : {reason} Vous pouvez aider en mettant Ă  jour la page française : {fr_url} Page anglaise de rĂ©fĂ©rence : {en_url} #OpenStreetMap #OSM #Wiki #Contribution #Traduction""" return post def post_to_mastodon(post_text, dry_run=False): """ Post the message to Mastodon Args: post_text (str): Text to post dry_run (bool): If True, don't actually post to Mastodon Returns: bool: True if posting was successful or dry run, False otherwise """ if dry_run: logger.info("DRY RUN: Would have posted to Mastodon:") logger.info(post_text) return True if not MASTODON_ACCESS_TOKEN: logger.error("MASTODON_ACCESS_TOKEN not found in .env file or environment variables") return False headers = { "Authorization": f"Bearer {MASTODON_ACCESS_TOKEN}", "Content-Type": "application/json" } data = { "status": post_text, "visibility": "public" } try: response = requests.post(MASTODON_API_URL, headers=headers, json=data) response.raise_for_status() logger.info("Successfully posted to Mastodon") return True except requests.exceptions.RequestException as e: logger.error(f"Error posting to Mastodon: {e}") return False def main(): """Main function to execute the script""" parser = argparse.ArgumentParser(description="Post about an outdated OSM wiki page on Mastodon") parser.add_argument("--dry-run", action="store_true", help="Run without actually posting to Mastodon") args = parser.parse_args() logger.info("Starting post_outdated_page.py") # Load outdated pages outdated_pages = load_outdated_pages() if not outdated_pages: logger.error("No outdated pages found. Run wiki_compare.py first.") return # Select a random outdated page selected_page = select_random_outdated_page(outdated_pages) if not selected_page: logger.error("Could not select an outdated page.") return # Create the post text post_text = create_mastodon_post(selected_page) # Post to Mastodon success = post_to_mastodon(post_text, args.dry_run) if success: logger.info("Script completed successfully") else: logger.error("Script completed with errors") if __name__ == "__main__": main()