#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ API pour traiter les requêtes de correction depuis la page web. Ce script: 1. Fournit des endpoints pour appliquer des corrections au fichier livre.org 2. Permet d'ajouter des mots au dictionnaire personnalisé 3. Permet de marquer des erreurs comme "à ne pas traiter" dans le CSV """ import os import re import json import csv from flask import Flask, request, jsonify, Blueprint # Créer un Blueprint pour l'API corrections_api = Blueprint('corrections_api', __name__) # Chemin vers les fichiers LIVRE_PATH = 'livre.org' DICT_PATH = 'dictionnaire_personnalise.txt' CSV_PATH = 'resume_erreurs.csv' @corrections_api.route('/api/corrections', methods=['POST']) def handle_corrections(): """Endpoint pour traiter les requêtes de correction.""" data = request.json if not data or 'action' not in data: return jsonify({'success': False, 'message': 'Action non spécifiée'}), 400 action = data['action'] if action == 'apply_correction': return apply_correction(data) elif action == 'ignore_error': return ignore_error(data) elif action == 'add_to_dictionary': return add_to_dictionary(data) else: return jsonify({'success': False, 'message': 'Action non reconnue'}), 400 def apply_correction(data): """Applique une correction au fichier livre.org.""" # Vérifier les paramètres requis required_params = ['error_type', 'chapter', 'error_index', 'correction'] if not all(param in data for param in required_params): return jsonify({'success': False, 'message': 'Paramètres manquants'}), 400 error_type = data['error_type'] chapter = data['chapter'] error_index = data['error_index'] correction = data['correction'] try: # Lire le contenu du fichier with open(LIVRE_PATH, 'r', encoding='utf-8') as file: content = file.read() # Trouver la section du chapitre chapter_pattern = r'^\*\* ' + re.escape(chapter) + r'$(.*?)(?=^\*\* |\Z)' chapter_match = re.search(chapter_pattern, content, re.MULTILINE | re.DOTALL) if not chapter_match: return jsonify({'success': False, 'message': f'Chapitre "{chapter}" non trouvé'}), 404 chapter_content = chapter_match.group(1) chapter_start = chapter_match.start() chapter_end = chapter_match.end() # Appliquer la correction en fonction du type d'erreur if error_type == 'spelling': # Charger les erreurs d'orthographe pour ce chapitre errors = load_spelling_errors(chapter) if error_index >= len(errors): return jsonify({'success': False, 'message': 'Index d\'erreur invalide'}), 400 error = errors[error_index] word = error['word'] # Remplacer le mot dans le contenu du chapitre modified_chapter = re.sub(r'\b' + re.escape(word) + r'\b', correction, chapter_content) # Mettre à jour le contenu complet new_content = content[:chapter_start] + '** ' + chapter + modified_chapter + content[chapter_end:] elif error_type == 'grammar': # Charger les erreurs grammaticales pour ce chapitre errors = load_grammar_errors(chapter) if error_index >= len(errors): return jsonify({'success': False, 'message': 'Index d\'erreur invalide'}), 400 error = errors[error_index] error_text = error['error_text'] context = error['context'] # Trouver le contexte dans le chapitre context_pattern = re.escape(context.replace(error_text, error_text)) context_match = re.search(context_pattern, chapter_content) if not context_match: return jsonify({'success': False, 'message': 'Contexte non trouvé dans le chapitre'}), 404 # Remplacer l'erreur dans le contexte corrected_context = context.replace(error_text, correction) # Remplacer le contexte dans le chapitre modified_chapter = chapter_content.replace(context, corrected_context) # Mettre à jour le contenu complet new_content = content[:chapter_start] + '** ' + chapter + modified_chapter + content[chapter_end:] else: return jsonify({'success': False, 'message': 'Type d\'erreur non reconnu'}), 400 # Écrire le contenu modifié dans le fichier with open(LIVRE_PATH, 'w', encoding='utf-8') as file: file.write(new_content) return jsonify({'success': True, 'message': 'Correction appliquée avec succès'}) except Exception as e: return jsonify({'success': False, 'message': f'Erreur lors de l\'application de la correction: {str(e)}'}), 500 def ignore_error(data): """Marque une erreur comme 'à ne pas traiter' dans le CSV.""" # Vérifier les paramètres requis required_params = ['error_type', 'chapter', 'error_index'] if not all(param in data for param in required_params): return jsonify({'success': False, 'message': 'Paramètres manquants'}), 400 error_type = data['error_type'] chapter = data['chapter'] error_index = data['error_index'] try: # Lire le CSV des erreurs rows = [] with open(CSV_PATH, 'r', newline='', encoding='utf-8') as csvfile: reader = csv.reader(csvfile) headers = next(reader) # Lire les en-têtes # Ajouter les en-têtes à la liste des lignes rows.append(headers) # Parcourir les lignes et mettre à jour celle du chapitre concerné for row in reader: if len(row) > 0 and row[0] == chapter: # Mettre à jour la ligne en fonction du type d'erreur if error_type == 'spelling' and len(row) > 1: # Décrémenter le nombre d'erreurs d'orthographe spelling_errors = int(row[1]) - 1 row[1] = str(max(0, spelling_errors)) # Mettre à jour le total if len(row) > 3: row[3] = str(int(row[3]) - 1) elif error_type == 'grammar' and len(row) > 2: # Décrémenter le nombre d'erreurs grammaticales grammar_errors = int(row[2]) - 1 row[2] = str(max(0, grammar_errors)) # Mettre à jour le total if len(row) > 3: row[3] = str(int(row[3]) - 1) rows.append(row) # Écrire les modifications dans le CSV with open(CSV_PATH, 'w', newline='', encoding='utf-8') as csvfile: writer = csv.writer(csvfile) writer.writerows(rows) return jsonify({'success': True, 'message': 'Erreur ignorée avec succès'}) except Exception as e: return jsonify({'success': False, 'message': f'Erreur lors de l\'ignorance de l\'erreur: {str(e)}'}), 500 def add_to_dictionary(data): """Ajoute un mot au dictionnaire personnalisé.""" # Vérifier les paramètres requis if 'word' not in data: return jsonify({'success': False, 'message': 'Mot non spécifié'}), 400 word = data['word'] try: # Vérifier si le mot est déjà dans le dictionnaire existing_words = set() if os.path.exists(DICT_PATH): with open(DICT_PATH, 'r', encoding='utf-8') as file: for line in file: line = line.strip() if line and not line.startswith('#'): existing_words.add(line.lower()) # Si le mot n'est pas déjà dans le dictionnaire, l'ajouter if word.lower() not in existing_words: with open(DICT_PATH, 'a', encoding='utf-8') as file: file.write(f"\n{word}") return jsonify({'success': True, 'message': 'Mot ajouté au dictionnaire avec succès'}) except Exception as e: return jsonify({'success': False, 'message': f'Erreur lors de l\'ajout du mot au dictionnaire: {str(e)}'}), 500 def load_spelling_errors(chapter): """Charge les erreurs d'orthographe pour un chapitre donné depuis le rapport.""" # Cette fonction devrait charger les erreurs d'orthographe depuis le rapport # Pour simplifier, nous utilisons une implémentation fictive # Dans une implémentation réelle, il faudrait parser le rapport d'erreurs # Exemple d'implémentation fictive from generate_corrections_page import parse_error_report errors_by_chapter = parse_error_report('rapport_orthographe_grammaire.md') if chapter in errors_by_chapter: return errors_by_chapter[chapter]['spelling'] return [] def load_grammar_errors(chapter): """Charge les erreurs grammaticales pour un chapitre donné depuis le rapport.""" # Cette fonction devrait charger les erreurs grammaticales depuis le rapport # Pour simplifier, nous utilisons une implémentation fictive # Dans une implémentation réelle, il faudrait parser le rapport d'erreurs # Exemple d'implémentation fictive from generate_corrections_page import parse_error_report errors_by_chapter = parse_error_report('rapport_orthographe_grammaire.md') if chapter in errors_by_chapter: return errors_by_chapter[chapter]['grammar'] return [] # Pour tester l'API indépendamment if __name__ == '__main__': app = Flask(__name__) app.register_blueprint(corrections_api) app.run(debug=True, port=5001)