139 lines
4.1 KiB
JavaScript
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();
|