manhuagui-cli 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -75,26 +75,61 @@ node dist/index.js https://www.manhuagui.com/comic/12345/ --resume
75
75
 
76
76
  ### 选项
77
77
 
78
- | 选项 | 简写 | 说明 |
79
- | ------------------ | ---- | ------------------------------------ |
80
- | `--section <name>` | `-s` | 指定要下载的章节组名称(默认:全部) |
81
- | `--chapter <name>` | `-c` | 指定要下载的章节名称 |
82
- | `--resume` | `-r` | 断点续传模式 |
83
- | `--help` | `-h` | 显示帮助信息 |
84
- | `--version` | `-v` | 显示版本号 |
85
-
86
- ## 环境变量
87
-
88
- 复制 `.env.example` `.env`,根据需要修改:
89
-
90
- | 变量 | 默认值 | 说明 |
91
- | ------------------- | ---------- | ---------------------------------- |
92
- | `OUTPUT_BASE` | `./output` | 下载输出目录 |
93
- | `IMAGE_CONCURRENCY` | `2` | 章节内图片并发下载数 |
94
- | `DOWNLOAD_DELAY` | `3000` | 图片批次之间延迟(毫秒,0 禁用) |
95
- | `CHAPTER_DELAY_MIN` | `5000` | 章节间最小延迟(毫秒) |
96
- | `CHAPTER_DELAY_MAX` | `15000` | 章节间最大延迟(毫秒) |
97
- | `USER_AGENTS` | — | 自定义 User-Agent 列表(每行一个) |
78
+ | 选项 | 简写 | 说明 |
79
+ | --------------------- | ----- | --------------------------------------------- |
80
+ | `--section <name>` | `-s` | 指定要下载的章节组名称(默认:全部) |
81
+ | `--chapter <name>` | `-c` | 指定要下载的章节名称 |
82
+ | `--output <dir>` | `-o` | 下载输出目录 |
83
+ | `--concurrency <n>` | `-C` | 章节内图片并发下载数 |
84
+ | `--retry <n>` | | 图片下载重试次数 |
85
+ | `--log-level <level>` | | 日志级别:`debug` \| `info` \| `warn` \| `error` |
86
+ | `--resume` | `-r` | 断点续传模式 |
87
+ | `--dry-run` | `-d` | 预览模式(不实际下载) |
88
+ | `--help` | `-h` | 显示帮助信息 |
89
+ | `--version` | `-v` | 显示版本号 |
90
+
91
+ ## 配置
92
+
93
+ 所有配置项按以下优先级生效(高优先级覆盖低优先级):
94
+
95
+ ```
96
+ CLI 参数 > 配置文件 > 环境变量 > 默认值
97
+ ```
98
+
99
+ ### 配置文件
100
+
101
+ 支持两个位置的 JSON 配置文件,项目级覆盖全局级:
102
+
103
+ - **项目级**: `<当前目录>/.manhuaguirc.json`
104
+ - **全局**: `~/.config/manhuagui-cli/config.json`(Windows: `%USERPROFILE%\.config\manhuagui-cli\config.json`)
105
+
106
+ ```json
107
+ {
108
+ "outputBase": "./downloads",
109
+ "imageConcurrency": 4,
110
+ "retryCount": 5,
111
+ "logLevel": "debug"
112
+ }
113
+ ```
114
+
115
+ 全部可选,未指定的项使用默认值。
116
+
117
+ ### 环境变量
118
+
119
+ 复制 `.env.example` 为 `.env`,根据需要修改。也支持直接设置系统环境变量。
120
+
121
+ | 变量 | 默认值 | 说明 |
122
+ | --------------------- | ---------- | ---------------------------------------- |
123
+ | `OUTPUT_BASE` | `./output` | 下载输出目录 |
124
+ | `IMAGE_CONCURRENCY` | `2` | 章节内图片并发下载数 |
125
+ | `DOWNLOAD_DELAY` | `3000` | 图片批次之间延迟(毫秒,0 禁用) |
126
+ | `CHAPTER_DELAY_MIN` | `5000` | 章节间最小延迟(毫秒) |
127
+ | `CHAPTER_DELAY_MAX` | `15000` | 章节间最大延迟(毫秒) |
128
+ | `RETRY_COUNT` | `3` | 图片下载重试次数 |
129
+ | `RETRY_BACKOFF_BASE` | `1000` | 重试退避基准毫秒(第 N 次重试等待 N×base) |
130
+ | `IMAGE_LOAD_DELAY` | `200` | 翻页后等待图片加载时间(毫秒) |
131
+ | `LOG_LEVEL` | `info` | 日志级别:`debug` \| `info` \| `warn` \| `error` |
132
+ | `USER_AGENTS` | — | 自定义 User-Agent 列表(每行一个) |
98
133
 
99
134
  ## 输出目录结构
100
135
 
package/README_EN.md CHANGED
@@ -75,26 +75,61 @@ node dist/index.js https://www.manhuagui.com/comic/12345/ --resume
75
75
 
76
76
  ### Options
77
77
 
78
- | Option | Alias | Description |
79
- | ------------------ | ----- | ---------------------------------------------- |
80
- | `--section <name>` | `-s` | Download only the named section (default: all) |
81
- | `--chapter <name>` | `-c` | Download only the named chapter |
82
- | `--resume` | `-r` | Resume from previous interrupted download |
83
- | `--help` | `-h` | Show help |
84
- | `--version` | `-v` | Show version |
85
-
86
- ## Environment Variables
87
-
88
- Copy `.env.example` to `.env` and modify as needed:
89
-
90
- | Variable | Default | Description |
91
- | ------------------- | ---------- | -------------------------------------- |
92
- | `OUTPUT_BASE` | `./output` | Download output directory |
93
- | `IMAGE_CONCURRENCY` | `2` | Concurrent image downloads per chapter |
94
- | `DOWNLOAD_DELAY` | `3000` | Delay between image batches (ms) |
95
- | `CHAPTER_DELAY_MIN` | `5000` | Min delay between chapters (ms) |
96
- | `CHAPTER_DELAY_MAX` | `15000` | Max delay between chapters (ms) |
97
- | `USER_AGENTS` | — | Custom User-Agent pool, one per line |
78
+ | Option | Alias | Description |
79
+ | -------------------- | ----- | -------------------------------------------------------------- |
80
+ | `--section <name>` | `-s` | Download only the named section (default: all) |
81
+ | `--chapter <name>` | `-c` | Download only the named chapter |
82
+ | `--output <dir>` | `-o` | Download output directory |
83
+ | `--concurrency <n>` | `-C` | Concurrent image downloads per chapter |
84
+ | `--retry <n>` | | Retry count per image download |
85
+ | `--log-level <level>`| | Log level: `debug` \| `info` \| `warn` \| `error` |
86
+ | `--resume` | `-r` | Resume from previous interrupted download |
87
+ | `--dry-run` | `-d` | Preview mode (list chapters without downloading) |
88
+ | `--help` | `-h` | Show help |
89
+ | `--version` | `-v` | Show version |
90
+
91
+ ## Configuration
92
+
93
+ All settings follow this priority order (higher overrides lower):
94
+
95
+ ```
96
+ CLI args > config files > environment variables > defaults
97
+ ```
98
+
99
+ ### Config Files
100
+
101
+ Two JSON config file locations are supported, project-level overrides global:
102
+
103
+ - **Project-level**: `<cwd>/.manhuaguirc.json`
104
+ - **Global**: `~/.config/manhuagui-cli/config.json` (Windows: `%USERPROFILE%\.config\manhuagui-cli\config.json`)
105
+
106
+ ```json
107
+ {
108
+ "outputBase": "./downloads",
109
+ "imageConcurrency": 4,
110
+ "retryCount": 5,
111
+ "logLevel": "debug"
112
+ }
113
+ ```
114
+
115
+ All fields are optional; defaults are used for any omitted field.
116
+
117
+ ### Environment Variables
118
+
119
+ Copy `.env.example` to `.env` and modify as needed. System environment variables are also supported.
120
+
121
+ | Variable | Default | Description |
122
+ | --------------------- | ---------- | --------------------------------------------------- |
123
+ | `OUTPUT_BASE` | `./output` | Download output directory |
124
+ | `IMAGE_CONCURRENCY` | `2` | Concurrent image downloads per chapter |
125
+ | `DOWNLOAD_DELAY` | `3000` | Delay between image batches (ms, 0 to disable) |
126
+ | `CHAPTER_DELAY_MIN` | `5000` | Min delay between chapters (ms) |
127
+ | `CHAPTER_DELAY_MAX` | `15000` | Max delay between chapters (ms) |
128
+ | `RETRY_COUNT` | `3` | Retry count per image download |
129
+ | `RETRY_BACKOFF_BASE` | `1000` | Retry backoff base (ms), wait `N × base` on Nth retry |
130
+ | `IMAGE_LOAD_DELAY` | `200` | Wait after page turn for image to load (ms) |
131
+ | `LOG_LEVEL` | `info` | Log level: `debug` \| `info` \| `warn` \| `error` |
132
+ | `USER_AGENTS` | — | Custom User-Agent pool, one per line |
98
133
 
99
134
  ## Output Structure
100
135
 
@@ -0,0 +1,4 @@
1
+ import type { Browser, BrowserContext, Page } from "playwright";
2
+ export declare function createBrowserContext(browser: Browser): Promise<BrowserContext>;
3
+ export declare function handleAdultCheck(page: Page, waitFor?: string): Promise<void>;
4
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/lib/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIhE,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,CAAC,CAQpF;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASlF"}
@@ -0,0 +1,22 @@
1
+ import { config, pickUserAgent } from "./config.js";
2
+ import { randInt } from "./utils.js";
3
+ export async function createBrowserContext(browser) {
4
+ return browser.newContext({
5
+ userAgent: pickUserAgent(),
6
+ viewport: {
7
+ width: randInt(config.viewportMinWidth, config.viewportMaxWidth),
8
+ height: randInt(config.viewportMinHeight, config.viewportMaxHeight),
9
+ },
10
+ });
11
+ }
12
+ export async function handleAdultCheck(page, waitFor) {
13
+ const checkAdult = await page.$("#checkAdult");
14
+ if (checkAdult) {
15
+ await checkAdult.click();
16
+ if (waitFor) {
17
+ await page.waitForSelector(waitFor, { timeout: config.adultSelectorTimeout });
18
+ await page.waitForTimeout(config.adultClickSettleDelay);
19
+ }
20
+ }
21
+ }
22
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/lib/browser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAAgB;IACzD,OAAO,OAAO,CAAC,UAAU,CAAC;QACxB,SAAS,EAAE,aAAa,EAAE;QAC1B,QAAQ,EAAE;YACR,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,CAAC;YAChE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,CAAC;SACpE;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAU,EAAE,OAAgB;IACjE,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;IAC/C,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,oBAAoB,EAAE,CAAC,CAAC;YAC9E,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -1,6 +1,10 @@
1
- import type { Browser } from "playwright";
1
+ import type { Browser, Page as PlaywrightPage, Response } from "playwright";
2
2
  export declare function computePadLength(count: number): number;
3
3
  export declare function extractExtension(url: string): string;
4
4
  export declare function buildFilePath(outputDir: string, index: number, padLen: number, ext: string): string;
5
+ export declare function getPageCount(page: PlaywrightPage): Promise<number>;
6
+ export declare function getSubPageUrls(page: PlaywrightPage): Promise<string[]>;
7
+ export declare function collectImageUrls(page: PlaywrightPage, pageCount: number): Promise<string[]>;
8
+ export declare function validateImageResponse(response: Response | null): void;
5
9
  export declare function extractChapterImages(chapterUrl: string, browser: Browser, outputDir: string): Promise<string[]>;
6
10
  //# sourceMappingURL=chapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chapter.d.ts","sourceRoot":"","sources":["../../src/lib/chapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAA0C,MAAM,YAAY,CAAC;AAqBlF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,MAAM,CAGR;AAmID,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAgCnB"}
1
+ {"version":3,"file":"chapter.d.ts","sourceRoot":"","sources":["../../src/lib/chapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAkB,IAAI,IAAI,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAO5F,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGpD;AAED,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,MAAM,CAGR;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAaxE;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAa5E;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA8BjG;AAYD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,GAAG,IAAI,CAQrE;AAyGD,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CA4BnB"}
@@ -1,11 +1,12 @@
1
1
  import { writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { CHAPTER_SELECTOR_TIMEOUT, DOWNLOAD_DELAY, IMAGE_CONCURRENCY, IMAGE_LOAD_DELAY, NEXT_PAGE_TIMEOUT, PAD_MIN_LENGTH, PAGE_LOAD_TIMEOUT, pickUserAgent, RETRY_BACKOFF_BASE, RETRY_COUNT, VIEWPORT_MAX_HEIGHT, VIEWPORT_MAX_WIDTH, VIEWPORT_MIN_HEIGHT, VIEWPORT_MIN_WIDTH, } from "./config.js";
3
+ import { createBrowserContext, handleAdultCheck } from "./browser.js";
4
+ import { config } from "./config.js";
4
5
  import { rotateHost } from "./download.js";
5
6
  import { logger } from "./logger.js";
6
- import { ensureDir, randInt, sleep } from "./utils.js";
7
+ import { ensureDir, sleep } from "./utils.js";
7
8
  export function computePadLength(count) {
8
- return Math.max(PAD_MIN_LENGTH, String(count).length);
9
+ return Math.max(config.padMinLength, String(count).length);
9
10
  }
10
11
  export function extractExtension(url) {
11
12
  const match = url.match(/\.(\w{3,4})(?:\?|$)/);
@@ -15,7 +16,7 @@ export function buildFilePath(outputDir, index, padLen, ext) {
15
16
  const padNum = String(index + 1).padStart(padLen, "0");
16
17
  return join(outputDir, `${padNum}.${ext}`);
17
18
  }
18
- async function getPageCount(page) {
19
+ export async function getPageCount(page) {
19
20
  return page.evaluate(() => {
20
21
  const pageSpan = document.querySelector("#page");
21
22
  if (pageSpan?.parentElement) {
@@ -29,8 +30,25 @@ async function getPageCount(page) {
29
30
  return 0;
30
31
  });
31
32
  }
32
- async function collectImageUrls(page, pageCount) {
33
+ export async function getSubPageUrls(page) {
34
+ try {
35
+ await page.waitForSelector("#pagination a", { timeout: config.tabLoadTimeout });
36
+ return await page.evaluate(() => {
37
+ const links = document.querySelectorAll("#pagination a");
38
+ if (links.length <= 1)
39
+ return [];
40
+ return Array.from(links)
41
+ .map((a) => a.href)
42
+ .filter((href) => href.startsWith("http"));
43
+ });
44
+ }
45
+ catch {
46
+ return [];
47
+ }
48
+ }
49
+ export async function collectImageUrls(page, pageCount) {
33
50
  const urls = [];
51
+ const pagePath = page.url().split("#")[0];
34
52
  let currentUrl = await page.$eval("#mangaFile", (img) => img.src);
35
53
  urls.push(currentUrl);
36
54
  for (let i = 1; i < pageCount; i++) {
@@ -42,59 +60,75 @@ async function collectImageUrls(page, pageCount) {
42
60
  await page.waitForFunction((prev) => {
43
61
  const img = document.querySelector("#mangaFile");
44
62
  return img !== null && img.src !== "" && img.src !== prev;
45
- }, prevUrl, { timeout: NEXT_PAGE_TIMEOUT });
46
- await page.waitForTimeout(IMAGE_LOAD_DELAY);
63
+ }, prevUrl, { timeout: config.nextPageTimeout });
64
+ await page.waitForTimeout(config.imageLoadDelay);
65
+ if (page.url().split("#")[0] !== pagePath)
66
+ break;
47
67
  currentUrl = await page.$eval("#mangaFile", (img) => img.src);
48
68
  urls.push(currentUrl);
49
69
  }
50
70
  return urls;
51
71
  }
72
+ async function navigateToChapterPage(page, url) {
73
+ await page.goto(url, {
74
+ waitUntil: "domcontentloaded",
75
+ timeout: config.pageLoadTimeout,
76
+ });
77
+ await handleAdultCheck(page);
78
+ await page.waitForSelector("#mangaFile", { timeout: config.chapterSelectorTimeout });
79
+ }
80
+ export function validateImageResponse(response) {
81
+ if (response?.status() !== 200) {
82
+ throw new Error(`HTTP ${response?.status() ?? "no response"}`);
83
+ }
84
+ const contentType = response?.headers()?.["content-type"] ?? "";
85
+ if (contentType && !contentType.startsWith("image/")) {
86
+ throw new Error(`Unexpected content type: ${contentType}`);
87
+ }
88
+ }
89
+ async function fetchImageAsBase64(page) {
90
+ return page.evaluate(async () => {
91
+ const res = await fetch(window.location.href);
92
+ if (!res.ok)
93
+ throw new Error(`Fetch failed: ${res.status}`);
94
+ const buf = await res.arrayBuffer();
95
+ const bytes = new Uint8Array(buf);
96
+ let binary = "";
97
+ const step = 0x8000;
98
+ for (let j = 0; j < bytes.length; j += step) {
99
+ binary += String.fromCharCode.apply(null, Array.from(bytes.subarray(j, j + step)));
100
+ }
101
+ return btoa(binary);
102
+ });
103
+ }
52
104
  async function downloadImage(dlPage, chapterUrl, url, outputDir, imageIndex, padLen) {
53
105
  const ext = extractExtension(url);
54
106
  const filePath = buildFilePath(outputDir, imageIndex, padLen, ext);
55
107
  let downloadUrl = url;
56
- for (let attempt = 0; attempt < RETRY_COUNT; attempt++) {
108
+ for (let attempt = 0; attempt < config.retryCount; attempt++) {
57
109
  try {
58
110
  const response = await dlPage.goto(downloadUrl, {
59
111
  referer: chapterUrl,
60
112
  waitUntil: "load",
61
- timeout: PAGE_LOAD_TIMEOUT,
62
- });
63
- if (response?.status() !== 200) {
64
- throw new Error(`HTTP ${response?.status() ?? "no response"}`);
65
- }
66
- const contentType = response?.headers()?.["content-type"] ?? "";
67
- if (contentType && !contentType.startsWith("image/")) {
68
- throw new Error(`Unexpected content type: ${contentType}`);
69
- }
70
- const base64 = await dlPage.evaluate(async () => {
71
- const res = await fetch(window.location.href);
72
- if (!res.ok)
73
- throw new Error(`Fetch failed: ${res.status}`);
74
- const buf = await res.arrayBuffer();
75
- const bytes = new Uint8Array(buf);
76
- let binary = "";
77
- const step = 0x8000;
78
- for (let j = 0; j < bytes.length; j += step) {
79
- binary += String.fromCharCode.apply(null, Array.from(bytes.subarray(j, j + step)));
80
- }
81
- return btoa(binary);
113
+ timeout: config.pageLoadTimeout,
82
114
  });
115
+ validateImageResponse(response);
116
+ const base64 = await fetchImageAsBase64(dlPage);
83
117
  writeFileSync(filePath, Buffer.from(base64, "base64"));
84
118
  return true;
85
119
  }
86
120
  catch {
87
- if (attempt < RETRY_COUNT - 1) {
121
+ if (attempt < config.retryCount - 1) {
88
122
  downloadUrl = rotateHost(downloadUrl);
89
- await sleep(RETRY_BACKOFF_BASE * (attempt + 1));
123
+ await sleep(config.retryBackoffBase * (attempt + 1));
90
124
  }
91
125
  }
92
126
  }
93
- logger.warn(`Failed to download after ${RETRY_COUNT} retries: ${url}`);
127
+ logger.warn(`Failed to download after ${config.retryCount} retries: ${url}`);
94
128
  return false;
95
129
  }
96
130
  async function downloadImages(context, chapterUrl, outputDir, urls, padLen) {
97
- const concurrency = Math.min(IMAGE_CONCURRENCY, urls.length);
131
+ const concurrency = Math.min(config.imageConcurrency, urls.length);
98
132
  const downloadPages = await Promise.all(Array.from({ length: concurrency }, () => context.newPage()));
99
133
  try {
100
134
  for (let i = 0; i < urls.length; i += concurrency) {
@@ -102,8 +136,8 @@ async function downloadImages(context, chapterUrl, outputDir, urls, padLen) {
102
136
  const results = await Promise.all(batch.map((url, idx) => downloadImage(downloadPages[idx], chapterUrl, url, outputDir, i + idx, padLen)));
103
137
  if (results.some((r) => !r))
104
138
  return;
105
- if (DOWNLOAD_DELAY > 0) {
106
- await sleep(Math.round(DOWNLOAD_DELAY * (0.5 + Math.random())));
139
+ if (config.downloadDelay > 0) {
140
+ await sleep(Math.round(config.downloadDelay * (0.5 + Math.random())));
107
141
  }
108
142
  }
109
143
  }
@@ -111,26 +145,39 @@ async function downloadImages(context, chapterUrl, outputDir, urls, padLen) {
111
145
  await Promise.all(downloadPages.map((p) => p.close()));
112
146
  }
113
147
  }
148
+ async function collectImageUrlsFromSubPages(page, subPageUrls) {
149
+ const allUrls = [];
150
+ for (let i = 0; i < subPageUrls.length; i++) {
151
+ if (i > 0) {
152
+ await navigateToChapterPage(page, subPageUrls[i]);
153
+ }
154
+ const tabPageCount = await getPageCount(page);
155
+ if (tabPageCount <= 0)
156
+ continue;
157
+ const tabUrls = await collectImageUrls(page, tabPageCount);
158
+ allUrls.push(...tabUrls);
159
+ }
160
+ return allUrls;
161
+ }
114
162
  export async function extractChapterImages(chapterUrl, browser, outputDir) {
115
163
  ensureDir(outputDir);
116
- const context = await browser.newContext({
117
- userAgent: pickUserAgent(),
118
- viewport: {
119
- width: randInt(VIEWPORT_MIN_WIDTH, VIEWPORT_MAX_WIDTH),
120
- height: randInt(VIEWPORT_MIN_HEIGHT, VIEWPORT_MAX_HEIGHT),
121
- },
122
- });
164
+ const context = await createBrowserContext(browser);
123
165
  const page = await context.newPage();
124
166
  try {
125
- await page.goto(chapterUrl, {
126
- waitUntil: "domcontentloaded",
127
- timeout: PAGE_LOAD_TIMEOUT,
128
- });
129
- await page.waitForSelector("#mangaFile", { timeout: CHAPTER_SELECTOR_TIMEOUT });
130
- const pageCount = await getPageCount(page);
131
- if (pageCount <= 0)
167
+ await navigateToChapterPage(page, chapterUrl);
168
+ const subPageUrls = await getSubPageUrls(page);
169
+ let urls;
170
+ if (subPageUrls.length > 0) {
171
+ urls = await collectImageUrlsFromSubPages(page, subPageUrls);
172
+ }
173
+ else {
174
+ const pageCount = await getPageCount(page);
175
+ if (pageCount <= 0)
176
+ return [];
177
+ urls = await collectImageUrls(page, pageCount);
178
+ }
179
+ if (urls.length === 0)
132
180
  return [];
133
- const urls = await collectImageUrls(page, pageCount);
134
181
  const padLen = computePadLength(urls.length);
135
182
  await downloadImages(context, chapterUrl, outputDir, urls, padLen);
136
183
  return urls;
@@ -1 +1 @@
1
- {"version":3,"file":"chapter.js","sourceRoot":"","sources":["../../src/lib/chapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EACL,wBAAwB,EACxB,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAC/C,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,SAAiB,EACjB,KAAa,EACb,MAAc,EACd,GAAW;IAEX,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC,SAAS,EAAE,GAAG,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAAoB;IAC9C,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE;QACxB,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,QAAQ,EAAE,aAAa,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;YACnE,IAAI,KAAK;gBAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3C,CAAC;QAED,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,aAAa,CAA6B,CAAC;QACjF,IAAI,MAAM,EAAE,OAAO,CAAC,MAAM;YAAE,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;QAEzD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAC,IAAoB,EAAE,SAAiB;IACrE,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE,CAAE,GAAwB,CAAC,GAAG,CAAC,CAAC;IACxF,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAEtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,UAAU,CAAC;QAC3B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO;YAAE,MAAM;QAEpB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,CAAC,eAAe,CACxB,CAAC,IAAI,EAAE,EAAE;YACP,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,YAAY,CAA4B,CAAC;YAC5E,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,GAAG,KAAK,EAAE,IAAI,GAAG,CAAC,GAAG,KAAK,IAAI,CAAC;QAC5D,CAAC,EACD,OAAO,EACP,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAC/B,CAAC;QAEF,MAAM,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;QAC5C,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE,CAAE,GAAwB,CAAC,GAAG,CAAC,CAAC;QACpF,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,MAAsB,EACtB,UAAkB,EAClB,GAAW,EACX,SAAiB,EACjB,UAAkB,EAClB,MAAc;IAEd,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,aAAa,CAAC,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IAEnE,IAAI,WAAW,GAAG,GAAG,CAAC;IAEtB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE;gBAC9C,OAAO,EAAE,UAAU;gBACnB,SAAS,EAAE,MAAM;gBACjB,OAAO,EAAE,iBAAiB;aAC3B,CAAC,CAAC;YACH,IAAI,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAG,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,EAAE,MAAM,EAAE,IAAI,aAAa,EAAE,CAAC,CAAC;YACjE,CAAC;YACD,MAAM,WAAW,GAAG,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YAChE,IAAI,WAAW,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACrD,MAAM,IAAI,KAAK,CAAC,4BAA4B,WAAW,EAAE,CAAC,CAAC;YAC7D,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;gBAC9C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC9C,IAAI,CAAC,GAAG,CAAC,EAAE;oBAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC5D,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,WAAW,EAAE,CAAC;gBACpC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;gBAClC,IAAI,MAAM,GAAG,EAAE,CAAC;gBAChB,MAAM,IAAI,GAAG,MAAM,CAAC;gBACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;oBAC5C,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;gBACrF,CAAC;gBACD,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;YACtB,CAAC,CAAC,CAAC;YACH,aAAa,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;YACvD,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,OAAO,GAAG,WAAW,GAAG,CAAC,EAAE,CAAC;gBAC9B,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;gBACtC,MAAM,KAAK,CAAC,kBAAkB,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,4BAA4B,WAAW,aAAa,GAAG,EAAE,CAAC,CAAC;IACvE,OAAO,KAAK,CAAC;AACf,CAAC;AAED,KAAK,UAAU,cAAc,CAC3B,OAAuB,EACvB,UAAkB,EAClB,SAAiB,EACjB,IAAc,EACd,MAAc;IAEd,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,GAAG,CACrC,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAC7D,CAAC;IAEF,IAAI,CAAC;QACH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC;YAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC;YAE7C,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CACrB,aAAa,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,GAAG,GAAG,EAAE,MAAM,CAAC,CAC/E,CACF,CAAC;YAEF,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;gBAAE,OAAO;YAEpC,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;gBACvB,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,UAAkB,EAClB,OAAgB,EAChB,SAAiB;IAEjB,SAAS,CAAC,SAAS,CAAC,CAAC;IAErB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;QACvC,SAAS,EAAE,aAAa,EAAE;QAC1B,QAAQ,EAAE;YACR,KAAK,EAAE,OAAO,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;YACtD,MAAM,EAAE,OAAO,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;SAC1D;KACF,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;IAErC,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YAC1B,SAAS,EAAE,kBAAkB;YAC7B,OAAO,EAAE,iBAAiB;SAC3B,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC,CAAC;QAEhF,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,SAAS,IAAI,CAAC;YAAE,OAAO,EAAE,CAAC;QAE9B,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE7C,MAAM,cAAc,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAEnE,OAAO,IAAI,CAAC;IACd,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"chapter.js","sourceRoot":"","sources":["../../src/lib/chapter.ts"],"names":[],"mappings":"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"}
package/dist/lib/cli.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import type { Section } from "./types.js";
2
+ export declare function applyFilters(sections: Section[], sectionFilter?: string, chapterFilter?: string): Section[];
1
3
  export declare const command: import("citty").CommandDef<{
2
4
  readonly url: {
3
5
  readonly type: "positional";
@@ -26,5 +28,23 @@ export declare const command: import("citty").CommandDef<{
26
28
  readonly alias: "d";
27
29
  readonly default: false;
28
30
  };
31
+ readonly output: {
32
+ readonly type: "string";
33
+ readonly description: "下载输出目录 / Output directory for downloads";
34
+ readonly alias: "o";
35
+ };
36
+ readonly concurrency: {
37
+ readonly type: "string";
38
+ readonly description: "章节内图片并发下载数 / Concurrent image downloads per chapter";
39
+ readonly alias: "C";
40
+ };
41
+ readonly retry: {
42
+ readonly type: "string";
43
+ readonly description: "图片下载重试次数 / Retry count per image";
44
+ };
45
+ readonly "log-level": {
46
+ readonly type: "string";
47
+ readonly description: "日志级别: debug | info | warn | error / Log level";
48
+ };
29
49
  }>;
30
50
  //# sourceMappingURL=cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/lib/cli.ts"],"names":[],"mappings":"AA2SA,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmDlB,CAAC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/lib/cli.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAsB,OAAO,EAAE,MAAM,YAAY,CAAC;AAmB9D,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,OAAO,EAAE,EACnB,aAAa,CAAC,EAAE,MAAM,EACtB,aAAa,CAAC,EAAE,MAAM,GACrB,OAAO,EAAE,CAgBX;AAsPD,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6ElB,CAAC"}