2025-08-21 16:07:49 +02:00
|
|
|
#!/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
|
2025-09-01 00:14:00 +02:00
|
|
|
import re
|
2025-08-21 16:07:49 +02:00
|
|
|
|
|
|
|
# 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__)
|
|
|
|
|
2025-09-01 00:14:00 +02:00
|
|
|
# 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 {}
|
|
|
|
|
2025-08-21 16:07:49 +02:00
|
|
|
# Constants
|
|
|
|
OUTDATED_PAGES_FILE = "outdated_pages.json"
|
2025-09-01 00:14:00 +02:00
|
|
|
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")
|
2025-08-21 16:07:49 +02:00
|
|
|
|
|
|
|
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:
|
2025-09-01 00:14:00 +02:00
|
|
|
logger.error("MASTODON_ACCESS_TOKEN not found in .env file or environment variables")
|
2025-08-21 16:07:49 +02:00
|
|
|
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()
|