212 lines
6.2 KiB
Python
212 lines
6.2 KiB
Python
![]() |
#!/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()
|