Files
book-source-creator-skill/book-source-creator/scripts/generate_template.mjs
T

139 lines
4.1 KiB
JavaScript

#!/usr/bin/env node
import fs from 'node:fs/promises';
import path from 'node:path';
import readline from 'node:readline/promises';
import { stdin as input, stdout as output } from 'node:process';
function baseTemplate() {
return {
bookSourceName: '',
bookSourceUrl: '',
bookSourceType: 0,
bookSourceGroup: '',
bookUrlPattern: '',
customOrder: 0,
enabled: true,
enabledExplore: false,
header: '',
loginUrl: '',
bookSourceComment: '',
lastUpdateTime: 0,
weight: 0,
exploreUrl: '',
searchUrl: '',
ruleSearch: {},
ruleExplore: {},
ruleBookInfo: {},
ruleToc: {},
ruleContent: {},
};
}
function mergeAnalysis(analysis) {
const template = baseTemplate();
template.lastUpdateTime = Math.floor(Date.now() / 1000);
if (analysis.name) template.bookSourceName = analysis.name;
if (analysis.url) template.bookSourceUrl = analysis.url;
if (analysis.group) template.bookSourceGroup = analysis.group;
if (analysis.login?.url) {
template.loginUrl = analysis.login.url;
}
if (analysis.search?.url) {
template.searchUrl = analysis.search.url;
}
if (analysis.search?.rules) {
template.ruleSearch = { ...analysis.search.rules };
}
if (analysis.explore?.url) {
template.exploreUrl = analysis.explore.url;
template.enabledExplore = true;
}
if (analysis.explore?.rules) {
template.ruleExplore = { ...analysis.explore.rules };
}
if (analysis.book_info?.rules) {
template.ruleBookInfo = { ...analysis.book_info.rules };
}
if (analysis.toc?.rules) {
template.ruleToc = { ...analysis.toc.rules };
}
if (analysis.content?.rules) {
template.ruleContent = { ...analysis.content.rules };
}
return template;
}
async function interactiveTemplate() {
const rl = readline.createInterface({ input, output });
const template = baseTemplate();
template.bookSourceName = (await rl.question('书源名称: ')).trim() || '示例书源';
template.bookSourceUrl = (await rl.question('网站URL: ')).trim() || 'https://example.com';
template.bookSourceGroup = (await rl.question('分组(可选): ')).trim();
template.bookSourceComment = (await rl.question('注释(可选): ')).trim();
const loginNeeded = (await rl.question('该网站是否需要登录后再分析?(y/n): ')).trim().toLowerCase() === 'y';
if (loginNeeded) {
template.loginUrl = (await rl.question('登录URL(可选): ')).trim();
}
const hasSearch = (await rl.question('是否支持搜索?(y/n): ')).trim().toLowerCase() === 'y';
if (hasSearch) {
template.searchUrl = (await rl.question('搜索URL(使用{{key}}表示关键词): ')).trim() || '/search?q={{key}}';
}
const hasExplore = (await rl.question('是否需要发现功能?(y/n,默认n): ')).trim().toLowerCase() === 'y';
template.enabledExplore = hasExplore;
if (hasExplore) {
template.exploreUrl = (await rl.question('发现URL(使用{{page}}表示页码): ')).trim() || '/list?page={{page}}';
}
template.enabled = (await rl.question('默认启用书源?(y/n,默认y): ')).trim().toLowerCase() !== 'n';
template.lastUpdateTime = Math.floor(Date.now() / 1000);
rl.close();
return template;
}
async function main() {
const [, , firstArg, secondArg] = process.argv;
if (firstArg === '--example') {
console.log(JSON.stringify(mergeAnalysis({
name: '示例小说网站',
url: 'https://novel.example.com',
search: {
url: '/search?q={{key}}&page={{page}}',
rules: {
bookList: '@css:.book-list li',
name: '@css:.book-title@text',
author: '@css:.book-author@text',
coverUrl: '@css:.book-cover img@src',
bookUrl: '@css:.book-link@href',
},
},
}), null, 2));
return;
}
let template;
if (firstArg === '--analysis' && secondArg) {
const analysisPath = path.resolve(secondArg);
const analysis = JSON.parse(await fs.readFile(analysisPath, 'utf8'));
template = mergeAnalysis(analysis);
} else {
template = await interactiveTemplate();
}
console.log(JSON.stringify(template, null, 2));
}
await main();