first commit

This commit is contained in:
2025-09-07 22:57:43 +00:00
commit 3bd542adbf
122 changed files with 45056 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
const { PrismaClient } = require('../app/generated/prisma');
async function main() {
const prisma = new PrismaClient();
const id = process.argv[2];
if (!id) {
console.error('Usage: node scripts/check_content_id.js <contentId>');
process.exit(1);
}
const norm = (s) => (s ?? '').trim();
const idNorm = norm(id);
const content = await prisma.content.findUnique({ where: { id } });
const contentNorm = id === idNorm ? content : await prisma.content.findUnique({ where: { id: idNorm } });
let map = null, mapNorm = null;
try { map = await prisma.contentHandle.findUnique({ where: { contentId: id } }); } catch {}
try { if (id !== idNorm) mapNorm = await prisma.contentHandle.findUnique({ where: { contentId: idNorm } }); } catch {}
const vpEq = await prisma.viewPerDay.count({ where: { contented: id } });
const vpEqNorm = id === idNorm ? vpEq : await prisma.viewPerDay.count({ where: { contented: idNorm } });
const vpLike = await prisma.viewPerDay.count({ where: { contented: { contains: id } } });
const vpLikeNorm = id === idNorm ? vpLike : await prisma.viewPerDay.count({ where: { contented: { contains: idNorm } } });
const sample = await prisma.viewPerDay.findMany({ where: { contented: { contains: idNorm } }, orderBy: { date: 'desc' }, take: 5 });
console.log(JSON.stringify({
input: id,
normalized: idNorm,
contentExists: !!content || !!contentNorm,
contentIdExact: !!content,
contentIdNormalized: !!contentNorm,
mapExists: !!map || !!mapNorm,
mapExact: !!map,
mapNormalized: !!mapNorm,
viewCounts: { eq: vpEq, eqNorm: vpEqNorm, like: vpLike, likeNorm: vpLikeNorm },
sample
}, null, 2));
await prisma.$disconnect();
}
main().catch((e) => { console.error(e); process.exit(1); });

View File

@@ -0,0 +1,21 @@
const { PrismaClient } = require('../app/generated/prisma');
(async () => {
const prisma = new PrismaClient();
try {
const totalRows = await prisma.viewPerDay.count();
const distinct = await prisma.viewPerDay.findMany({ select: { contented: true }, distinct: ['contented'] });
const top = await prisma.viewPerDay.groupBy({
by: ['contented'],
_count: { contented: true },
orderBy: { _count: { contented: 'desc' } },
take: 10,
});
console.log(JSON.stringify({ totalRows, distinctIds: distinct.length, top }, null, 2));
} catch (e) {
console.error(e);
process.exit(1);
} finally {
await prisma.$disconnect();
}
})();

54
scripts/seed_allview.js Normal file
View File

@@ -0,0 +1,54 @@
const fs = require('node:fs');
const path = require('node:path');
const Papa = require('papaparse');
const { PrismaClient } = require('../app/generated/prisma');
function getField(row, candidates) {
for (const key of candidates) {
if (key in row && row[key] !== undefined && row[key] !== null && String(row[key]).trim() !== '') {
return row[key];
}
}
return undefined;
}
async function main() {
const prisma = new PrismaClient();
const yearFilter = process.argv[2] ? Number(process.argv[2]) : null;
const csvPath = path.resolve(process.cwd(), 'datas/allview.csv');
if (!fs.existsSync(csvPath)) {
console.error('datas/allview.csv not found');
process.exit(1);
}
const csv = fs.readFileSync(csvPath, 'utf8');
const parsed = Papa.parse(csv, { header: true, skipEmptyLines: true });
if (parsed.errors && parsed.errors.length) {
console.error('CSV parse errors:', parsed.errors);
process.exit(1);
}
const minDate = new Date('2020-01-01');
let ok = 0, bad = 0;
for (const r of parsed.data) {
const dateStr = String(getField(r, ['날짜', 'Date', 'date', 'DATE']) || '').trim();
const contented = String(getField(r, ['콘텐츠', 'Contented', 'contented', 'Content', 'content', 'Id', 'ID']) || '').trim();
const viewsRaw = getField(r, ['조회수', 'Validviewday', 'validViewDay', 'validViews', 'views', 'Views']);
const v = Number(viewsRaw ?? 0);
const d = new Date(dateStr);
if (!dateStr || !contented || isNaN(d.getTime()) || d < minDate) { bad++; continue; }
if (yearFilter && d.getFullYear() !== yearFilter) { bad++; continue; }
await prisma.viewPerDay.upsert({
where: { date_contented: { date: d, contented } },
update: { validViewDay: v },
create: { date: d, contented, validViewDay: v },
});
ok++;
}
await prisma.$disconnect();
console.log(`ViewPerDay seeded from allview.csv${yearFilter?` (year=${yearFilter})`:''}: ok=${ok}, skipped/bad=${bad}`);
}
main().catch((e) => { console.error(e); process.exit(1); });

54
scripts/seed_contents.js Normal file
View File

@@ -0,0 +1,54 @@
const fs = require('node:fs');
const path = require('node:path');
const Papa = require('papaparse');
const { PrismaClient } = require('../app/generated/prisma');
async function main() {
const prisma = new PrismaClient();
const csvPath = path.resolve(process.cwd(), 'datas/contents.csv');
const csv = fs.readFileSync(csvPath, 'utf8');
const parsed = Papa.parse(csv, { header: true, skipEmptyLines: true });
if (parsed.errors && parsed.errors.length) {
console.error(parsed.errors);
process.exit(1);
}
for (const r of parsed.data) {
if (!r.Id) continue;
const pubDate = new Date(r.pubDate);
const views = Number(r.views ?? 0);
const validViews = Number(r.validViews ?? 0);
const premiumViews = Number(r.premiumViews ?? 0);
const watchTime = Math.round(Number(r.watchTime ?? 0));
await prisma.content.upsert({
where: { id: r.Id },
update: {
subject: r.subject,
pubDate,
views,
validViews,
premiumViews,
watchTime,
},
create: {
id: r.Id,
subject: r.subject,
pubDate,
views,
validViews,
premiumViews,
watchTime,
},
});
}
await prisma.$disconnect();
console.log('Seeded contents from CSV');
}
main().catch((e) => {
console.error(e);
process.exit(1);
});

82
scripts/seed_mappings.js Normal file
View File

@@ -0,0 +1,82 @@
const fs = require('node:fs');
const path = require('node:path');
const Papa = require('papaparse');
const { PrismaClient } = require('../app/generated/prisma');
async function seedContentHandle(prisma) {
const csvPath = path.resolve(process.cwd(), 'datas/ch2.csv');
if (!fs.existsSync(csvPath)) {
console.warn('content_handle.csv not found, skip');
return;
}
const csv = fs.readFileSync(csvPath, 'utf8');
const parsed = Papa.parse(csv, { header: true, skipEmptyLines: true });
if (parsed.errors && parsed.errors.length) {
console.error('CSV parse errors (content_handle):', parsed.errors);
process.exit(1);
}
let ok = 0, skip = 0;
for (const r of parsed.data) {
// Keep raw Id to match previously seeded content ids (some have spaces)
const contentId = String(r.Id || '');
const handle = (r.Handle || '').trim();
if (!contentId || !handle) { skip++; continue; }
// Ensure user handle exists; if not, skip (email is required to create)
const existsUser = await prisma.userHandle.findUnique({ where: { handle } });
if (!existsUser) { skip++; continue; }
await prisma.contentHandle.upsert({
where: { contentId },
update: { handle },
create: { contentId, handle },
});
ok++;
}
console.log(`ContentHandle seeded: ok=${ok}, skip=${skip}`);
}
async function seedViewPerDay(prisma) {
const csvPath = path.resolve(process.cwd(), 'datas/viewperdate.csv');
if (!fs.existsSync(csvPath)) {
console.warn('viewperdate.csv not found, skip');
return;
}
const csv = fs.readFileSync(csvPath, 'utf8');
const parsed = Papa.parse(csv, { header: true, skipEmptyLines: true });
if (parsed.errors && parsed.errors.length) {
console.error('CSV parse errors (viewperdate):', parsed.errors);
process.exit(1);
}
let ok = 0, bad = 0;
for (const r of parsed.data) {
const dateStr = (r.Date || '').trim();
const contented = (r.Contented || '').trim();
const v = Number(r.Validviewday ?? 0);
if (!dateStr || !contented) { bad++; continue; }
const date = new Date(dateStr);
if (isNaN(date.getTime())) { bad++; continue; }
await prisma.viewPerDay.upsert({
where: { date_contented: { date, contented } },
update: { validViewDay: v },
create: { date, contented, validViewDay: v },
});
ok++;
}
console.log(`ViewPerDay seeded: ok=${ok}, bad=${bad}`);
}
async function main() {
const prisma = new PrismaClient();
await seedContentHandle(prisma);
await prisma.$disconnect();
console.log('Done.');
}
main().catch((e) => {
console.error(e);
process.exit(1);
});