seogeneratorserver/process_real.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

219 lines
7.0 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ========================================
// SCRIPT: process_real.js
// VRAI PROCESSEUR GOOGLE SHEETS + DIGITALOCEAN
// ========================================
const { readCSVDataWithXMLFileName, fetchXMLFromDigitalOceanSimple } = require('./lib/DigitalOceanWorkflow');
const { handleFullWorkflow } = require('./lib/Main');
/**
* Fonction principale qui fait VRAIMENT tout le processus
* 1. Récupère données depuis Google Sheets (ligne rowNumber)
* 2. Récupère XML depuis DigitalOcean (selon xmlFileName du GSheet)
* 3. Lance le workflow complet
*/
async function processRealData(rowNumber) {
console.log(`🚀 === TRAITEMENT RÉEL LIGNE ${rowNumber} ===\n`);
// Réduire verbosité console
process.env.LOG_LEVEL = 'INFO';
try {
// 1. RÉCUPÉRER DONNÉES GOOGLE SHEETS
console.log('1⃣ Récupération données Google Sheets...');
const csvData = await readCSVDataWithXMLFileName(rowNumber);
console.log(`✅ Données récupérées:`);
console.log(` MC0: ${csvData.mc0}`);
console.log(` T0: ${csvData.t0}`);
console.log(` XML File: ${csvData.xmlFileName}`);
console.log(` Personnalité: ${csvData.personality?.nom || 'N/A'}`);
// 2. RÉCUPÉRER XML DEPUIS DIGITALOCEAN
console.log('\n2⃣ Récupération XML DigitalOcean...');
if (!csvData.xmlFileName) {
throw new Error('Nom fichier XML manquant dans Google Sheets (colonne J)');
}
const xmlContent = await fetchXMLFromDigitalOceanSimple(csvData.xmlFileName);
console.log(`✅ XML récupéré: ${csvData.xmlFileName} (${xmlContent.length} caractères)`);
// 3. PRÉPARER DONNÉES WORKFLOW
console.log('\n3⃣ Préparation workflow...');
const workflowData = {
csvData: csvData,
xmlTemplate: Buffer.from(xmlContent).toString('base64'),
source: 'real_gsheets_digitalocean',
rowNumber: rowNumber
};
// 4. LANCER WORKFLOW COMPLET
console.log('4⃣ Lancement workflow (6 LLMs)...');
const startTime = Date.now();
const result = await handleFullWorkflow(workflowData);
const duration = Date.now() - startTime;
// 5. AFFICHER RÉSULTATS
console.log(`\n🎯 === RÉSULTATS (${Math.round(duration/1000)}s) ===`);
console.log(`✅ Success: ${result.success}`);
console.log(`📊 Éléments générés: ${result.elementsGenerated}`);
console.log(`📝 Mots total: ${result.stats?.wordCount || 'N/A'}`);
console.log(`🤖 LLMs utilisés: ${result.llmsUsed?.join(', ') || 'N/A'}`);
console.log(`📄 XML final: ${result.xmlContent?.length || 0} caractères`);
console.log(`🔍 Validation: ${result.validationReport?.status || 'N/A'}`);
console.log(`💾 Article ID: ${result.articleStorage?.articleId || 'N/A'}`);
if (result.validationReport?.errors?.length > 0) {
console.log(`\n⚠️ Erreurs détectées:`);
result.validationReport.errors.forEach(error => {
console.log(` - ${error.type}: ${error.message}`);
});
}
return result;
} catch (error) {
console.error(`\n❌ Erreur traitement ligne ${rowNumber}:`, error.message);
console.log('\n📋 Vérifiez les logs détaillés dans:', `logs/seo-generator-${new Date().toISOString().split('T')[0]}.log`);
throw error;
}
}
/**
* Traiter plusieurs lignes en séquence
*/
async function processMultipleRealRows(rowNumbers) {
console.log(`🔄 === TRAITEMENT MULTI-LIGNES ===`);
console.log(`Lignes à traiter: ${rowNumbers.join(', ')}\n`);
const results = [];
for (const rowNumber of rowNumbers) {
try {
console.log(`\n📍 === LIGNE ${rowNumber} ===`);
const result = await processRealData(rowNumber);
results.push({
rowNumber,
success: true,
result
});
console.log(`✅ Ligne ${rowNumber} terminée\n`);
} catch (error) {
console.error(`❌ Ligne ${rowNumber} échouée: ${error.message}\n`);
results.push({
rowNumber,
success: false,
error: error.message
});
}
}
// Résumé final
const successCount = results.filter(r => r.success).length;
console.log(`\n🎯 === RÉSUMÉ FINAL ===`);
console.log(`✅ Réussis: ${successCount}/${rowNumbers.length}`);
console.log(`❌ Échoués: ${rowNumbers.length - successCount}/${rowNumbers.length}`);
return results;
}
/**
* Test simple d'une ligne sans traitement complet
*/
async function debugRealRow(rowNumber) {
console.log(`🔍 === DEBUG LIGNE ${rowNumber} ===\n`);
try {
// 1. Test Google Sheets
console.log('1⃣ Test Google Sheets...');
const csvData = await readCSVDataWithXMLFileName(rowNumber);
console.log('✅ Google Sheets OK');
console.log(` Données: ${csvData.mc0} | ${csvData.xmlFileName}`);
// 2. Test DigitalOcean
console.log('\n2⃣ Test DigitalOcean...');
const xmlContent = await fetchXMLFromDigitalOceanSimple(csvData.xmlFileName);
console.log('✅ DigitalOcean OK');
console.log(` XML: ${xmlContent.length} caractères`);
console.log(` Début: ${xmlContent.substring(0, 100)}...`);
return { csvData, xmlContent };
} catch (error) {
console.error(`❌ Debug échoué:`, error.message);
throw error;
}
}
// Usage en ligne de commande
if (require.main === module) {
const args = process.argv.slice(2);
if (args.includes('--help')) {
console.log(`
Usage: node process_real.js [options] [rowNumber(s)]
Options:
--help Afficher cette aide
--debug Mode debug (pas de traitement complet)
--multi Traiter plusieurs lignes (ex: --multi 2,3,4)
Exemples:
node process_real.js 2 # Traiter ligne 2
node process_real.js --debug 2 # Debug ligne 2 seulement
node process_real.js --multi 2,3,4 # Traiter lignes 2,3,4
`);
process.exit(0);
}
const isDebug = args.includes('--debug');
const isMulti = args.includes('--multi');
let targetRows = [];
if (isMulti) {
const multiIndex = args.indexOf('--multi');
const rowsArg = args[multiIndex + 1];
if (rowsArg) {
targetRows = rowsArg.split(',').map(n => parseInt(n.trim()));
}
} else {
const rowNumber = parseInt(args.find(arg => !arg.startsWith('--'))) || 2;
targetRows = [rowNumber];
}
// Lancer le traitement
(async () => {
try {
if (isDebug) {
for (const row of targetRows) {
await debugRealRow(row);
}
} else if (isMulti) {
await processMultipleRealRows(targetRows);
} else {
await processRealData(targetRows[0]);
}
console.log('\n🎉 Terminé avec succès !');
} catch (error) {
console.error('\n💥 Échec:', error.message);
process.exit(1);
}
})();
}
module.exports = {
processRealData,
processMultipleRealRows,
debugRealRow
};