/** * Lee una carpeta de álbum y dice qué hay dentro. **No escribe nada.** * * node scripts/album/leer.mjs "S:\\senza paura\\album - cupido-sin-flechas" * node scripts/album/leer.mjs --json > album.json * * El desmontaje está en `carpeta.mjs`, que es el mismo que usa el importador. * Esto solo lo cuenta: qué ha entendido de cada canción y qué no ha encontrado. * Se mira antes de importar, porque el material no está en un formato sino en * cinco —los `.txt` vienen de pegar lo que devuelve Suno, y Suno ha ido * cambiando lo que pone alrededor—. */ import path from 'node:path'; import fs from 'node:fs'; import { leerAlbum } from './carpeta.mjs'; const CARPETA = process.argv[2]; const COMO_JSON = process.argv.includes('--json'); if (!CARPETA || !fs.existsSync(CARPETA)) { console.error('uso: node scripts/album/leer.mjs "" [--json]'); process.exit(1); } const album = leerAlbum(CARPETA); if (COMO_JSON) { console.log(JSON.stringify(album, null, 2)); process.exit(0); } const si = (v) => (v ? '·' : 'FALTA'); const corto = (t, n) => (t ? (t.length > n ? t.slice(0, n - 1) + '…' : t) : ''); console.log(`\n${album.titulo} (${album.slug})`); console.log(`${album.canciones.length} canciones en ${path.basename(CARPETA)}\n`); for (const c of album.canciones) { console.log(`── ${c.titulo} ${c.slug}`); if (c.titulo !== c.carpeta) console.log(` carpeta: ${c.carpeta}`); if (!c.letra) { console.log(' letra: FALTA el .txt'); } else { const l = c.letra.limpia?.split('\n').filter((x) => x.trim()).length ?? 0; console.log( ` letra: ${l} versos limpios${c.letra.conEtiquetas ? ' · con etiquetas' : ''}` ); console.log(` estilo: ${corto(c.letra.estilo, 96) || 'FALTA'}`); const ajustes = Object.entries(c.letra.ajustes) .map(([k, v]) => `${k} ${v}%`) .join(' · '); if (ajustes) console.log(` ajustes: ${ajustes}`); } console.log( ` audio: mp3 ${si(c.audio.mp3)} wav ${si(c.audio.wav)}` + (c.audio.otras.length ? ` (+${c.audio.otras.length} tomas)` : '') ); console.log( ` portada: ${c.portada ? path.basename(c.portada.ruta) : 'FALTA'}` + `${c.portada?.recortar ? ' (miniatura 16:9, hay que recortarla)' : ''}` ); console.log(` vídeo: ${c.video ? path.basename(c.video) : 'FALTA'}`); console.log(''); } const sin = (f) => album.canciones.filter(f).map((c) => c.titulo); const faltan = [ ['sin .txt', sin((c) => !c.letra)], ['sin prompt de estilo', sin((c) => c.letra && !c.letra.estilo)], ['sin letra limpia', sin((c) => c.letra && !c.letra.limpia)], ['sin mp3 máster', sin((c) => !c.audio.mp3)], ['sin portada', sin((c) => !c.portada)], ['con la miniatura por portada', sin((c) => c.portada?.recortar)], ['sin vídeo', sin((c) => !c.video)] ].filter(([, cuales]) => cuales.length > 0); if (faltan.length === 0) { console.log('No falta nada.'); } else { console.log('Lo que falta:'); for (const [que, cuales] of faltan) console.log(` ${que}: ${cuales.join(', ')}`); }