Files

116 lines
5.6 KiB
JavaScript

#!/usr/bin/env node
'use strict';
const fs = require('fs').promises;
const path = require('path');
const { publishManifest } = require('./lib/publisher');
const { discoverWeebCentral } = require('./adapters/weebcentral');
const { lookupAniList } = require('./metadata/anilist');
const { runArchive } = require('./jobs/weebcentral-archive');
const { runQueue } = require('./jobs/weebcentral-queue');
function flag(args, name, fallback) {
const index = args.indexOf(name);
return index < 0 ? fallback : args[index + 1];
}
async function main() {
const args = process.argv.slice(2);
const command = args.shift();
if (command === 'publish') {
const file = args[0];
if (!file) throw new Error('Usage: publish <manifest.json> [--library path] [--metadata-search title] [--replace]');
const manifest = JSON.parse(await fs.readFile(path.resolve(file), 'utf8'));
const metadataSearch = flag(args, '--metadata-search');
if (metadataSearch) {
const metadata = await lookupAniList(metadataSearch);
manifest.series.metadata = { ...metadata, title: manifest.series.title };
manifest.series.scraper = { ...(manifest.series.scraper || {}), ids: { ...(manifest.series.scraper?.ids || {}), anilist: metadata['x-anilist']?.id } };
}
const result = await publishManifest(manifest, { libraryRoot: flag(args, '--library'), replace: args.includes('--replace') });
console.log(JSON.stringify(result, null, 2));
return;
}
if (command === 'discover-weebcentral') {
const url = args[0];
if (!url) throw new Error('Usage: discover-weebcentral <series-url> --out manifest.json [--limit 3]');
const manifest = await discoverWeebCentral(url, { limit: Number(flag(args, '--limit', 3)) });
const out = flag(args, '--out');
if (out) await fs.writeFile(path.resolve(out), JSON.stringify(manifest, null, 2) + '\n');
else console.log(JSON.stringify(manifest, null, 2));
return;
}
if (command === 'metadata-anilist') {
const search = args.join(' ');
if (!search) throw new Error('Usage: metadata-anilist <title>');
console.log(JSON.stringify(await lookupAniList(search), null, 2));
return;
}
if (command === 'archive-weebcentral') {
const url = args[0];
if (!url) throw new Error('Usage: archive-weebcentral <series-url> [--library path] [--metadata-search title]');
await runArchive({
seriesUrl: url,
libraryRoot: flag(args, '--library', 'library'),
metadataSearch: flag(args, '--metadata-search'),
minMs: Number(flag(args, '--min-ms', 8000)),
maxMs: Number(flag(args, '--max-ms', 15000)),
chapterMinMs: Number(flag(args, '--chapter-min-ms', 30000)),
chapterMaxMs: Number(flag(args, '--chapter-max-ms', 60000)),
});
return;
}
if (command === 'status-weebcentral') {
const url = args[0];
if (!url) throw new Error('Usage: status-weebcentral <series-url> [--library path]');
const sourceId = url.split('/series/')[1]?.split('/')[0];
if (!sourceId) throw new Error('Could not read WeebCentral series id');
const workRoot = path.resolve(flag(args, '--library', 'library'), `.mcscraper-work-${sourceId}`);
const state = JSON.parse(await fs.readFile(path.join(workRoot, 'job.json'), 'utf8'));
console.log(JSON.stringify({
status: state.status || 'unknown',
completed: state.completed?.length || 0,
total: state.total || null,
percent: state.total ? Math.round((state.completed?.length || 0) * 1000 / state.total) / 10 : null,
lastChapter: state.lastChapter || null,
current: state.current || null,
lastProblem: state.lastProblem || null,
lastError: state.lastError || null,
problemCount: state.problemCount || 0,
rate: state.rate || null,
updated: state.updated || null,
log: path.join(workRoot, 'job.log'),
}, null, 2));
return;
}
if (command === 'run-wishlist') {
const entries = [
['The Gamer', '01J76XY9DYH4MH2HZG2PPF74A6', 'The-Gamer'],
['Kanojo Okarishimasu', '01J76XYC7KP5M48JAY8S4ZNDX5', 'Kanojo-Okarishimasu'],
['Toradora', '01J76XY7J4Z4G6E42GED6QEQXZ', 'Toradora'],
['Solo Leveling', '01J76XYCPSY3C4BNPBRY8JMCBE', 'Solo-Leveling'],
['Gantz', '01J76XY7EREQ4B1Q5Z5RJ749V6', 'Gantz'],
['One Piece', '01J76XY7E9FNDZ1DBBM6PBJPFK', 'One-Piece'],
].map(([title, id, slug]) => ({ id, title, url: `https://weebcentral.com/series/${id}/${slug}` }));
await runQueue({
entries,
waitForFolder: flag(args, '--wait-for', 'Berserk'),
libraryRoot: flag(args, '--library', 'library'),
minMs: Number(flag(args, '--min-ms', 3000)),
maxMs: Number(flag(args, '--max-ms', 7000)),
chapterMinMs: Number(flag(args, '--chapter-min-ms', 12000)),
chapterMaxMs: Number(flag(args, '--chapter-max-ms', 25000)),
});
return;
}
if (command === 'status-queue') {
const queueRoot = path.resolve(flag(args, '--library', 'library'), '.mcscraper-queue');
const state = JSON.parse(await fs.readFile(path.join(queueRoot, 'queue.json'), 'utf8'));
console.log(JSON.stringify({ ...state, log: path.join(queueRoot, 'queue.log') }, null, 2));
return;
}
console.log('Commands:\n publish <manifest.json> [--library path] [--metadata-search title] [--replace]\n discover-weebcentral <url> [--limit 3] [--out file]\n archive-weebcentral <url> [--library path] [--metadata-search title]\n status-weebcentral <url> [--library path]\n run-wishlist [--library path] [--wait-for Berserk]\n status-queue [--library path]\n metadata-anilist <title>');
}
main().catch(error => { console.error(`[scraper] ${error.message}`); process.exitCode = 1; });