167 lines
5.5 KiB
JavaScript
167 lines
5.5 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
const { Client, Databases, ID } = require('node-appwrite');
|
|
require('dotenv').config({ path: '.env.local' });
|
|
const pdfParse = require('pdf-parse');
|
|
const mammoth = require('mammoth');
|
|
|
|
const client = new Client()
|
|
.setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT)
|
|
.setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID)
|
|
.setKey(process.env.APPWRITE_API_KEY);
|
|
|
|
const databases = new Databases(client);
|
|
const dbId = process.env.APPWRITE_DATABASE_ID;
|
|
const collectionId = 'posts';
|
|
const defaultTipoPublicacionId = '69c2b91400362d5d52b6'; // ID de NOTICIA obtenido anteriormente
|
|
|
|
const DIR_PENDIENTES = '/home/carlos/Documentos/Pendientes';
|
|
const DIR_PROCESADOS = path.join(DIR_PENDIENTES, 'Procesados');
|
|
|
|
if (!fs.existsSync(DIR_PROCESADOS)) {
|
|
fs.mkdirSync(DIR_PROCESADOS);
|
|
}
|
|
|
|
function generateSlug(titulo) {
|
|
return titulo
|
|
.toLowerCase()
|
|
.normalize('NFD')
|
|
.replace(/[\u0300-\u036f]/g, '')
|
|
.replace(/[^a-z0-9\s-]/g, '')
|
|
.trim()
|
|
.replace(/\s+/g, '-')
|
|
.replace(/-+/g, '-')
|
|
.substring(0, 100);
|
|
}
|
|
|
|
function formatContent(text) {
|
|
const paragraphs = text.split(/\n+/);
|
|
const html = paragraphs
|
|
.map(p => p.trim())
|
|
.filter(p => p.length > 0)
|
|
.map(p => `<p>${p}</p>`)
|
|
.join('');
|
|
return html;
|
|
}
|
|
|
|
function extractSummary(text) {
|
|
const paragraphs = text.split(/\n+/).map(p => p.trim()).filter(p => p.length > 30);
|
|
if (paragraphs.length > 0) {
|
|
return paragraphs[0].substring(0, 200) + (paragraphs[0].length > 200 ? '...' : '');
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function determineTipo(filename) {
|
|
const lower = filename.toLowerCase();
|
|
if (lower.includes('evento')) return 'evento';
|
|
if (lower.includes('aviso')) return 'aviso';
|
|
if (lower.includes('comunicado')) return 'comunicado';
|
|
if (lower.includes('galeria')) return 'galeria';
|
|
return 'noticia';
|
|
}
|
|
|
|
function formatTitle(filename) {
|
|
let base = path.basename(filename, path.extname(filename)).replace(/\(1\)/g, '').trim();
|
|
// Capitalize first letter of each word to look better
|
|
return base.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(' ');
|
|
}
|
|
|
|
function extractDate(filename, text) {
|
|
const months = {
|
|
'enero': 0, 'febrero': 1, 'marzo': 2, 'abril': 3, 'mayo': 4, 'junio': 5,
|
|
'julio': 6, 'agosto': 7, 'septiembre': 8, 'octubre': 9, 'noviembre': 10, 'diciembre': 11
|
|
};
|
|
|
|
// Attempt 1: From filename e.g. "28 DE MARZO DEL 2026"
|
|
const regex = /(\d{1,2})\s+DE\s+([A-Z]+)\s+(DEL?|DE)\s+(\d{4})/i;
|
|
let match = filename.match(regex);
|
|
if (!match) {
|
|
// Attempt 2: From the first few lines of text
|
|
const firstLines = text.split('\n').slice(0, 10).join(' ');
|
|
match = firstLines.match(regex);
|
|
}
|
|
|
|
if (match) {
|
|
const day = parseInt(match[1], 10);
|
|
const monthStr = match[2].toLowerCase();
|
|
const year = parseInt(match[4], 10);
|
|
|
|
if (months[monthStr] !== undefined) {
|
|
const date = new Date(year, months[monthStr], day, 12, 0, 0); // Noon to avoid timezone issues
|
|
return date.toISOString();
|
|
}
|
|
}
|
|
|
|
return new Date().toISOString(); // fallback
|
|
}
|
|
|
|
async function processFile(filePath, filename) {
|
|
const ext = path.extname(filename).toLowerCase();
|
|
let text = '';
|
|
|
|
try {
|
|
if (ext === '.pdf') {
|
|
const { execSync } = require('child_process');
|
|
text = execSync(`pdftotext "${filePath}" -`).toString();
|
|
} else if (ext === '.docx') {
|
|
const result = await mammoth.extractRawText({ path: filePath });
|
|
text = result.value;
|
|
} else if (ext === '.txt') {
|
|
text = fs.readFileSync(filePath, 'utf8');
|
|
} else {
|
|
console.log(`Skipping unsupported file: ${filename}`);
|
|
return false;
|
|
}
|
|
|
|
if (!text || text.trim().length === 0) {
|
|
console.log(`File empty or failed to extract: ${filename}`);
|
|
return false;
|
|
}
|
|
|
|
const titulo = formatTitle(filename);
|
|
const slug = generateSlug(titulo) + '-' + Math.random().toString(36).substring(2, 7);
|
|
const contenido = formatContent(text);
|
|
const tipo = determineTipo(filename);
|
|
const resumen_redes = extractSummary(text);
|
|
|
|
const docData = {
|
|
titulo,
|
|
slug,
|
|
contenido,
|
|
resumen_redes,
|
|
estado: 'publicado',
|
|
tipo_publicacion_id: defaultTipoPublicacionId,
|
|
fecha_publicacion: extractDate(filename, text),
|
|
};
|
|
|
|
await databases.createDocument(dbId, collectionId, ID.unique(), docData);
|
|
console.log(`✅ Publicado: ${titulo}`);
|
|
|
|
// Mover a procesados
|
|
fs.renameSync(filePath, path.join(DIR_PROCESADOS, filename));
|
|
return true;
|
|
} catch (error) {
|
|
console.error(`❌ Error procesando ${filename}:`, error.message);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
const files = fs.readdirSync(DIR_PENDIENTES);
|
|
let successCount = 0;
|
|
|
|
for (const file of files) {
|
|
const filePath = path.join(DIR_PENDIENTES, file);
|
|
if (fs.statSync(filePath).isFile()) {
|
|
console.log(`Procesando ${file}...`);
|
|
const ok = await processFile(filePath, file);
|
|
if (ok) successCount++;
|
|
}
|
|
}
|
|
|
|
console.log(`\nImportación finalizada. ${successCount} publicaciones procesadas correctamente.`);
|
|
}
|
|
|
|
main();
|