seogeneratorserver/lib/ManualTrigger.js
StillHammer dbf1a3de8c Add technical plan for multi-format export system
Added plan.md with complete architecture for format-agnostic content generation:
- Support for Markdown, HTML, Plain Text, JSON formats
- New FormatExporter module with neutral data structure
- Integration strategy with existing ContentAssembly and ArticleStorage
- Bonus features: SEO metadata generation, readability scoring, WordPress Gutenberg format
- Implementation roadmap with 4 phases (6h total estimated)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 16:14:29 +08:00

120 lines
4.5 KiB
JavaScript

const { logSh } = require('./ErrorReporting'); // Using unified logSh from ErrorReporting
/**
* 🚀 TRIGGER MANUEL - Lit ligne 2 et lance le workflow
* Exécute cette fonction depuis l'éditeur Apps Script
*/
function runWorkflowLigne(numeroLigne = 2) {
cleanLogSheet(); // Nettoie les logs pour ce test
try {
logSh('🎬 >>> DÉMARRAGE WORKFLOW MANUEL <<<', 'INFO');
// 1. LIRE AUTOMATIQUEMENT LA LIGNE INDIQUÉ
const csvData = readCSVDataFromRow(numeroLigne);
logSh(`✅ Données lues - MC0: ${csvData.mc0}`, 'INFO');
logSh(`✅ Titre: ${csvData.t0}`, 'INFO');
logSh(`✅ Personnalité: ${csvData.personality.nom}`, 'INFO');
// 2. XML TEMPLATE SIMPLE POUR TEST (ou lit depuis Digital Ocean si configuré)
const xmlTemplate = getXMLTemplateForTest(csvData);
logSh(`✅ XML template: ${xmlTemplate.length} caractères`, 'INFO');
// 3. 🎯 LANCER LE WORKFLOW PRINCIPAL
const workflowData = {
csvData: csvData,
xmlTemplate: Utilities.base64Encode(xmlTemplate),
source: 'manuel_ligne2'
};
const result = handleFullWorkflow(workflowData);
logSh('🏆 === WORKFLOW MANUEL TERMINÉ ===', 'INFO');
// ← EXTRAIRE LES VRAIES DONNÉES
let actualData;
if (result && result.getContentText) {
// C'est un ContentService, extraire le JSON
actualData = JSON.parse(result.getContentText());
} else {
actualData = result;
}
logSh(`Type result: ${typeof result}`, 'DEBUG');
logSh(`Result keys: ${Object.keys(result || {})}`, 'DEBUG');
logSh(`ActualData keys: ${Object.keys(actualData || {})}`, 'DEBUG');
logSh(`ActualData: ${JSON.stringify(actualData)}`, 'DEBUG');
if (actualData && actualData.stats) {
logSh(`📊 Éléments générés: ${actualData.stats.contentPieces}`, 'INFO');
logSh(`📝 Nombre de mots: ${actualData.stats.wordCount}`, 'INFO');
} else {
logSh('⚠️ Format résultat inattendu', 'WARNING');
logSh('ActualData: ' + JSON.stringify(actualData, null, 2), 'DEBUG'); // Using logSh instead of console.log
}
return actualData;
} catch (error) {
logSh(`❌ ERREUR WORKFLOW MANUEL: ${error.toString()}`, 'ERROR');
logSh(`Stack: ${error.stack}`, 'ERROR');
throw error;
}
}
/**
* HELPER - Lire CSV depuis une ligne spécifique
*/
function readCSVDataFromRow(rowNumber) {
const sheetId = '1iA2GvWeUxX-vpnAMfVm3ZMG9LhaC070SdGssEcXAh2c';
const spreadsheet = SpreadsheetApp.openById(sheetId);
const articlesSheet = spreadsheet.getSheetByName('instructions');
// Lire la ligne complète (colonnes A à H)
const range = articlesSheet.getRange(rowNumber, 1, 1, 9);
const [slug, t0, mc0, tMinus1, lMinus1, mcPlus1, tPlus1, lPlus1, xmlFileName] = range.getValues()[0];
logSh(`📖 Lecture ligne ${rowNumber}: ${slug}`, 'DEBUG');
// Récupérer personnalités et sélectionner automatiquement
const personalitiesSheet = spreadsheet.getSheetByName('Personnalites');
const personalities = getPersonalities(personalitiesSheet);
const selectedPersonality = selectPersonalityWithAI(mc0, t0, personalities);
return {
rowNumber: rowNumber,
slug: slug || 'test-slug',
t0: t0 || 'Titre par défaut',
mc0: mc0 || 'mot-clé test',
tMinus1: tMinus1 || 'parent',
lMinus1: lMinus1 || '/parent',
mcPlus1: mcPlus1 || 'mot1,mot2,mot3,mot4',
tPlus1: tPlus1 || 'Titre1,Titre2,Titre3,Titre4',
lPlus1: lPlus1 || '/lien1,/lien2,/lien3,/lien4',
personality: selectedPersonality,
xmlFileName: xmlFileName ? xmlFileName.toString().trim() : null
};
}
/**
* HELPER - XML Template simple pour test (ou depuis Digital Ocean)
*/
function getXMLTemplateForTest(csvData) {
logSh("csvData.xmlFileName: " + csvData.xmlFileName, 'DEBUG'); // Using logSh instead of console.log
if (csvData.xmlFileName) {
logSh("Tentative Digital Ocean...", 'INFO'); // Using logSh instead of console.log
try {
return fetchXMLFromDigitalOceanSimple(csvData.xmlFileName);
} catch (error) {
// ← ENLÈVE LE CATCH SILENCIEUX
logSh("Erreur DO: " + error.toString(), 'WARNING'); // Using logSh instead of console.log
logSh(`❌ ERREUR DO DÉTAILLÉE: ${error.toString()}`, 'ERROR');
// Continue sans Digital Ocean
}
}
logSh("❌ FATAL: Aucun template XML disponible", 'ERROR');
throw new Error("FATAL: Template XML indisponible (Digital Ocean inaccessible + pas de fallback) - arrêt du workflow");
}