osm-labo/wiki_compare/suggest_translation.py

212 lines
6.2 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
suggest_translation.py
This script reads the outdated_pages.json file generated by wiki_compare.py,
identifies English wiki pages that don't have a French translation,
and posts a message on Mastodon suggesting that the page needs translation.
Usage:
python suggest_translation.py [--dry-run]
Options:
--dry-run Run the script without actually posting to Mastodon
Output:
- A post on Mastodon suggesting a wiki page for translation
- 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
# 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__)
# Constants
OUTDATED_PAGES_FILE = "outdated_pages.json"
MASTODON_API_URL = "https://mastodon.instance/api/v1/statuses" # Replace with actual instance
MASTODON_ACCESS_TOKEN = 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)} pages from {OUTDATED_PAGES_FILE}")
return pages
except (IOError, json.JSONDecodeError) as e:
logger.error(f"Error loading pages from {OUTDATED_PAGES_FILE}: {e}")
return []
def find_missing_translations(pages):
"""
Find English pages that don't have a French translation
Args:
pages (list): List of dictionaries containing page information
Returns:
list: List of pages that need translation
"""
# Filter pages to include only those with a missing French page
missing_translations = [page for page in pages if
page.get('reason') == 'French page missing' and
page.get('en_page') is not None and
page.get('fr_page') is None]
logger.info(f"Found {len(missing_translations)} pages without French translation")
return missing_translations
def select_random_page_for_translation(pages):
"""
Randomly select a page for translation from the list
Args:
pages (list): List of dictionaries containing page information
Returns:
dict: Randomly selected page or None if no suitable pages found
"""
if not pages:
logger.warning("No pages found that need translation")
return None
# Randomly select a page
selected_page = random.choice(pages)
logger.info(f"Randomly selected page for key '{selected_page['key']}' for translation")
return selected_page
def create_mastodon_post(page):
"""
Create a Mastodon post suggesting a page for translation
Args:
page (dict): Dictionary containing page information
Returns:
str: Formatted Mastodon post text
"""
key = page['key']
en_url = page['en_page']['url']
fr_url = en_url.replace('/wiki/Key:', '/wiki/FR:Key:')
# Get word count and sections from English page
word_count = page['en_page']['word_count']
sections = page['en_page']['sections']
# Format the post
post = f"""🔍 Clé OSM sans traduction française : #{key}
Cette page wiki importante n'a pas encore de traduction française !
📊 Statistiques de la page anglaise :
{word_count} mots
{sections} sections
Vous pouvez aider en créant la traduction française ici :
{fr_url}
Page anglaise à traduire :
{en_url}
#OpenStreetMap #OSM #Wiki #Traduction #Contribution"""
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 environment variable not set")
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="Suggest an OSM wiki page for translation on Mastodon")
parser.add_argument("--dry-run", action="store_true", help="Run without actually posting to Mastodon")
args = parser.parse_args()
logger.info("Starting suggest_translation.py")
# Load pages
pages = load_outdated_pages()
if not pages:
logger.error("No pages found. Run wiki_compare.py first.")
return
# Find pages that need translation
pages_for_translation = find_missing_translations(pages)
if not pages_for_translation:
logger.error("No pages found that need translation.")
return
# Select a random page for translation
selected_page = select_random_page_for_translation(pages_for_translation)
if not selected_page:
logger.error("Could not select a page for translation.")
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()