feat: sistema de series/autores/franquicias + sidebar navegacion

This commit is contained in:
Renato
2026-08-05 02:30:53 +08:00
parent c16666035c
commit a237d08f59
10 changed files with 634 additions and 4 deletions
+61
View File
@@ -0,0 +1,61 @@
const Database = require("better-sqlite3");
const db = new Database("./data/worst-scan.db", { readonly: true });
const posts = db.prepare("SELECT gid, title, title_jpn, artist, parody, tags FROM posts WHERE published=1").all();
// Análisis de artistas
const artists = {};
// Análisis de parodias
const parodias = {};
// Detección de series por título base (quitar capítulos/volúmenes/números)
const seriesByTitle = {};
function normalizarSerie(title) {
if (!title) return null;
// Quitar marcadores de capítulo/volumen
let t = title
.replace(/[\[\(].*?[\]\)]/g, "") // quitar corchetes [..] y paréntesis (..)
.replace(/\b(chapter|ch|cap|tomo|vol|volume|part|#)\s*\.?\s*\d+[a-z]?\b/gi, "")
.replace(/\b\d+\s*(chapter|ch|cap|tomo|vol|volume|part)\b/gi, "")
.replace(/\b\d+\b/g, "") // números sueltos
.replace(/[^a-z0-9áéíóúüñ\s]/gi, "")
.trim()
.toLowerCase();
t = t.replace(/\s+/g, " ").trim();
return t.length >= 4 ? t : null;
}
for (const p of posts) {
const artist = (p.artist || "sin artista").trim();
artists[artist] = (artists[artist] || 0) + 1;
const parody = (p.parody || "sin parodia").trim();
parodias[parody] = (parodias[parody] || 0) + 1;
const serie = normalizarSerie(p.title);
if (serie) {
if (!seriesByTitle[serie]) seriesByTitle[serie] = [];
seriesByTitle[serie].push(p.title.slice(0, 60));
}
}
console.log("=== TOTAL POSTS PUBLICADOS ===", posts.length);
console.log("\n=== ARTISTAS (con >1 obra) ===");
Object.entries(artists).filter(([,c]) => c > 1).sort((a,b) => b[1]-a[1]).forEach(([a,c]) => console.log(` ${a}: ${c} obras`));
console.log("Artistas unicos:", Object.keys(artists).length);
console.log("\n=== PARODIAS (franquicias, con >1 obra) ===");
Object.entries(parodias).filter(([,c]) => c > 1).sort((a,b) => b[1]-a[1]).forEach(([a,c]) => console.log(` ${a}: ${c} obras`));
console.log("\n=== POSIBLES SERIES (título base repetido, >1 obra) ===");
const seriesMulti = Object.entries(seriesByTitle).filter(([,t]) => t.length > 1);
if (seriesMulti.length === 0) {
console.log(" Ninguna serie con título base repetido detectada");
} else {
seriesMulti.sort((a,b) => b[1].length - a[1].length).forEach(([s, titles]) => {
console.log(` SERIE: "${s}" (${titles.length})`);
titles.forEach(t => console.log(` - ${t}`));
});
}
db.close();