comic-book-dl
Version:
145 lines (144 loc) • 5.7 kB
JavaScript
import path from 'node:path';
import pLimit from 'p-limit';
import ProgressBar from './lib/ProgressBar.js';
import { existsMkdir } from './utils/index.js';
import { matchParse } from './lib/parse/index.js';
import { writeBookInfoFile } from './lib/download.js';
export async function run(config, hooks) {
const match = matchParse(config.targetUrl);
if (!match) {
if (hooks.parseErr)
hooks.parseErr();
return;
}
const { preHandleUrl, getInstance } = match;
if (typeof preHandleUrl === 'function') {
config.targetUrl = preHandleUrl(config.targetUrl);
}
const parseInstance = getInstance(config.targetUrl);
const bookInfo = await parseInstance.parseBookInfo();
if (!bookInfo) {
if (hooks.parseErr)
hooks.parseErr();
return;
}
const bookName = bookInfo.name;
const bookDistPath = path.resolve(config.bookPath, bookInfo.pathName);
existsMkdir(bookDistPath);
const total = bookInfo.chapters.length;
const progressBar = new ProgressBar(bookDistPath, total, config.ignoreConsole);
await progressBar.init();
if (progressBar.curr === total) {
if (hooks.success)
hooks.success(bookName, bookDistPath, null);
return;
}
let chaptersList = bookInfo.chapters;
if (config.userConfig?.ignore) {
const ignoreInfo = config.userConfig?.ignore.find(item => item.name === bookName);
if (ignoreInfo) {
const ignoreChapter = ignoreInfo.chapter ?? [];
chaptersList = chaptersList.filter(chaptersItem => {
return !ignoreChapter.includes(chaptersItem.name);
});
if (progressBar.curr === total - ignoreChapter.length) {
if (hooks.success) {
progressBar.bar?.stop();
hooks.success(bookName, bookDistPath, null);
}
return;
}
}
}
if (hooks.start)
hooks.start(bookName);
if (progressBar.isDownloadInterrupted) {
if (hooks.downloadInterrupted)
hooks?.downloadInterrupted();
const updateProgressInfo = [];
chaptersList = chaptersList.filter((chaptersItem) => {
return !progressBar.progressInfo.some(item => {
try {
let isSameHref = item.href === chaptersItem.href;
const isUrlReg = /(http|https):\/\//;
if (!isSameHref && isUrlReg.test(item.href) && isUrlReg.test(chaptersItem.href)) {
isSameHref = new URL(item.href).pathname === new URL(chaptersItem.href).pathname;
}
const isSameName = item.rawName == chaptersItem.rawName;
if (isSameHref && isSameName) {
chaptersItem.imageList = item.imageList;
chaptersItem.imageListPath = item.imageListPath;
updateProgressInfo.push(item);
}
return isSameHref && isSameName;
}
catch (e) {
return false;
}
});
});
progressBar.resetProgressInfo(updateProgressInfo);
}
const LIMIT_MAX = 6;
const limit = pLimit(LIMIT_MAX);
const errorList = [];
const promiseList = chaptersList.map(item => {
return limit(async () => {
const chaptersItemPath = `${bookDistPath}/chapters/${item.name}`;
existsMkdir(chaptersItemPath);
let getImageListSuccess = true;
const imageList = await parseInstance.getImgList(item.href)
.catch(() => {
getImageListSuccess = false;
errorList.push({
bookName,
chapter: item
});
return [];
});
let imageListPath = [];
const curBar = progressBar.multiBarCreate({
total: imageList.length,
file: `下载「${item.name}」中的图片...`
});
let isAllSuccess = true;
imageListPath = await parseInstance.saveImgList(chaptersItemPath, imageList, (imgUrl, isSuccess) => {
if (!isSuccess) {
isAllSuccess = false;
errorList.push({
bookName,
imgUrl,
chapter: item
});
}
progressBar.multiBarUpdate(curBar);
});
imageListPath = imageListPath.map((itemPath) => {
return `chapters/${item.name}/${itemPath}`;
});
item.imageList = imageList;
item.imageListPath = imageListPath;
progressBar.multiBarRemove(curBar);
await progressBar.updateProgress({
name: item.name,
rawName: item.rawName,
path: chaptersItemPath,
href: item.href,
index: item.index,
imageList,
imageListPath
}, isAllSuccess && getImageListSuccess);
return isAllSuccess && getImageListSuccess;
});
});
const isAllSuccess = await Promise.all(promiseList);
await writeBookInfoFile(bookInfo, bookDistPath, parseInstance);
if (errorList.length > 0) {
if (hooks.error)
hooks.error(bookName, chaptersList, errorList);
}
else if (progressBar.curr === total && isAllSuccess) {
if (hooks.success)
hooks.success(bookName, bookDistPath, chaptersList);
}
}