@moontaiworks/fanbox-dl 1.6.0 → 1.7.0
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 +51 -37
- package/dist/cjs/downloader/asset/download.d.ts +3 -1
- package/dist/cjs/downloader/asset/download.d.ts.map +1 -1
- package/dist/cjs/downloader/asset/download.js +11 -14
- package/dist/cjs/downloader/asset/download.js.map +1 -1
- package/dist/cjs/downloader/cli/options.d.ts +2 -1
- package/dist/cjs/downloader/cli/options.d.ts.map +1 -1
- package/dist/cjs/downloader/cli/options.js +3 -1
- package/dist/cjs/downloader/cli/options.js.map +1 -1
- package/dist/cjs/downloader/creator/discover-posts.d.ts.map +1 -1
- package/dist/cjs/downloader/creator/discover-posts.js +5 -3
- package/dist/cjs/downloader/creator/discover-posts.js.map +1 -1
- package/dist/cjs/downloader/creator/sync.d.ts +2 -1
- package/dist/cjs/downloader/creator/sync.d.ts.map +1 -1
- package/dist/cjs/downloader/creator/sync.js +25 -26
- package/dist/cjs/downloader/creator/sync.js.map +1 -1
- package/dist/cjs/downloader/fs/filesystem.d.ts +3 -0
- package/dist/cjs/downloader/fs/filesystem.d.ts.map +1 -1
- package/dist/cjs/downloader/fs/filesystem.js +27 -2
- package/dist/cjs/downloader/fs/filesystem.js.map +1 -1
- package/dist/cjs/downloader/index.d.ts +1 -1
- package/dist/cjs/downloader/index.d.ts.map +1 -1
- package/dist/cjs/downloader/index.js +13 -16
- package/dist/cjs/downloader/index.js.map +1 -1
- package/dist/cjs/downloader/manifest/creator-manager.d.ts +3 -0
- package/dist/cjs/downloader/manifest/creator-manager.d.ts.map +1 -1
- package/dist/cjs/downloader/manifest/creator-manager.js +24 -1
- package/dist/cjs/downloader/manifest/creator-manager.js.map +1 -1
- package/dist/cjs/downloader/manifest/creator.d.ts +6 -0
- package/dist/cjs/downloader/manifest/creator.d.ts.map +1 -1
- package/dist/cjs/downloader/manifest/creator.js +11 -1
- package/dist/cjs/downloader/manifest/creator.js.map +1 -1
- package/dist/cjs/downloader/post/article.d.ts.map +1 -1
- package/dist/cjs/downloader/post/article.js +25 -22
- package/dist/cjs/downloader/post/article.js.map +1 -1
- package/dist/cjs/downloader/post/sync.d.ts +3 -2
- package/dist/cjs/downloader/post/sync.d.ts.map +1 -1
- package/dist/cjs/downloader/post/sync.js +123 -85
- package/dist/cjs/downloader/post/sync.js.map +1 -1
- package/dist/cjs/downloader/post/verify.d.ts +9 -0
- package/dist/cjs/downloader/post/verify.d.ts.map +1 -0
- package/dist/cjs/downloader/post/verify.js +64 -0
- package/dist/cjs/downloader/post/verify.js.map +1 -0
- package/dist/esm/downloader/asset/download.d.ts +3 -1
- package/dist/esm/downloader/asset/download.d.ts.map +1 -1
- package/dist/esm/downloader/asset/download.js +12 -15
- package/dist/esm/downloader/asset/download.js.map +1 -1
- package/dist/esm/downloader/cli/options.d.ts +2 -1
- package/dist/esm/downloader/cli/options.d.ts.map +1 -1
- package/dist/esm/downloader/cli/options.js +3 -1
- package/dist/esm/downloader/cli/options.js.map +1 -1
- package/dist/esm/downloader/creator/discover-posts.d.ts.map +1 -1
- package/dist/esm/downloader/creator/discover-posts.js +5 -3
- package/dist/esm/downloader/creator/discover-posts.js.map +1 -1
- package/dist/esm/downloader/creator/sync.d.ts +2 -1
- package/dist/esm/downloader/creator/sync.d.ts.map +1 -1
- package/dist/esm/downloader/creator/sync.js +25 -26
- package/dist/esm/downloader/creator/sync.js.map +1 -1
- package/dist/esm/downloader/fs/filesystem.d.ts +3 -0
- package/dist/esm/downloader/fs/filesystem.d.ts.map +1 -1
- package/dist/esm/downloader/fs/filesystem.js +24 -2
- package/dist/esm/downloader/fs/filesystem.js.map +1 -1
- package/dist/esm/downloader/index.d.ts +1 -1
- package/dist/esm/downloader/index.d.ts.map +1 -1
- package/dist/esm/downloader/index.js +13 -16
- package/dist/esm/downloader/index.js.map +1 -1
- package/dist/esm/downloader/manifest/creator-manager.d.ts +3 -0
- package/dist/esm/downloader/manifest/creator-manager.d.ts.map +1 -1
- package/dist/esm/downloader/manifest/creator-manager.js +24 -1
- package/dist/esm/downloader/manifest/creator-manager.js.map +1 -1
- package/dist/esm/downloader/manifest/creator.d.ts +6 -0
- package/dist/esm/downloader/manifest/creator.d.ts.map +1 -1
- package/dist/esm/downloader/manifest/creator.js +11 -1
- package/dist/esm/downloader/manifest/creator.js.map +1 -1
- package/dist/esm/downloader/post/article.d.ts.map +1 -1
- package/dist/esm/downloader/post/article.js +25 -22
- package/dist/esm/downloader/post/article.js.map +1 -1
- package/dist/esm/downloader/post/sync.d.ts +3 -2
- package/dist/esm/downloader/post/sync.d.ts.map +1 -1
- package/dist/esm/downloader/post/sync.js +123 -85
- package/dist/esm/downloader/post/sync.js.map +1 -1
- package/dist/esm/downloader/post/verify.d.ts +9 -0
- package/dist/esm/downloader/post/verify.d.ts.map +1 -0
- package/dist/esm/downloader/post/verify.js +61 -0
- package/dist/esm/downloader/post/verify.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,15 +9,32 @@ A cli downloader or a read-only TypeScript SDK for building pixivFANBOX applicat
|
|
|
9
9
|
|
|
10
10
|
## CLI Downloader
|
|
11
11
|
|
|
12
|
-
Run the downloader through your package manager,
|
|
12
|
+
Run the downloader through your package manager, install it globally, or use
|
|
13
|
+
the published Docker image:
|
|
13
14
|
|
|
14
15
|
```bash
|
|
15
|
-
npx @moontaiworks/fanbox-dl download --
|
|
16
|
+
npx @moontaiworks/fanbox-dl download --help
|
|
16
17
|
```
|
|
17
18
|
|
|
18
19
|
```bash
|
|
19
20
|
npm install -g @moontaiworks/fanbox-dl
|
|
20
|
-
fanbox-dl download --
|
|
21
|
+
fanbox-dl download --help
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
docker run --rm \
|
|
26
|
+
-v "$PWD/fanbox-downloads:/downloads" \
|
|
27
|
+
ghcr.io/moontaiworks/fanbox-dl:latest \
|
|
28
|
+
download --output /downloads --help
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The same image is also published to Docker Hub:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
docker run --rm \
|
|
35
|
+
-v "$PWD/fanbox-downloads:/downloads" \
|
|
36
|
+
moontai0724/fanbox-dl:latest \
|
|
37
|
+
download --output /downloads --help
|
|
21
38
|
```
|
|
22
39
|
|
|
23
40
|
Authenticated downloads read `FANBOX_SESSION_ID` by default:
|
|
@@ -36,48 +53,43 @@ npx @moontaiworks/fanbox-dl download \
|
|
|
36
53
|
--cookie-file ./cookies.txt
|
|
37
54
|
```
|
|
38
55
|
|
|
39
|
-
Preview the selected creators and posts without downloading:
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
npx @moontaiworks/fanbox-dl download --creator creator-id --dry-run
|
|
43
|
-
```
|
|
44
|
-
|
|
45
56
|
At least one creator selector is required: `--creator`, `--following`, or
|
|
46
57
|
`--supporting`.
|
|
47
58
|
|
|
48
59
|
### CLI Options
|
|
49
60
|
|
|
50
|
-
| Option | Description
|
|
51
|
-
| -------------------------------- |
|
|
52
|
-
| `--creator <id>` | Add a creator ID to download. Can be repeated.
|
|
53
|
-
| `--following` | Download posts from followed creators. Requires authentication.
|
|
54
|
-
| `--supporting` | Download posts from supporting creators. Requires authentication.
|
|
55
|
-
| `--ignore-creator <id>` | Exclude a creator ID from the selected creators. Can be repeated.
|
|
56
|
-
| `--cookie <value>` | Raw `FANBOXSESSID`, `FANBOXSESSID=...`, or a full Cookie header.
|
|
57
|
-
| `--cookie-file <path>` | Read a raw cookie value or Netscape `cookies.txt`. FANBOX cookies are selected automatically.
|
|
58
|
-
| `--user-agent <value>` | Send the same User-Agent as the browser session that produced your cookie.
|
|
59
|
-
| `--output <path>` | Directory where downloaded creators and posts are stored.
|
|
60
|
-
| `--
|
|
61
|
-
| `--
|
|
62
|
-
| `--
|
|
63
|
-
| `--concurrency <n>` | Maximum number of concurrent requests. Must be greater than `0`.
|
|
64
|
-
| `--http2-session-multiplier <n>` | Multiplier used with concurrency to set HTTP/2 sessions per origin. Must be greater than `0`.
|
|
65
|
-
| `--request-interval-ms <n>` | Delay between request starts, in milliseconds.
|
|
66
|
-
| `--rate-limit-pause-ms <n>` | Pause duration after HTTP 429
|
|
67
|
-
| `--max-retries <n>` | Retry attempts for retryable request failures.
|
|
68
|
-
| `--log-
|
|
69
|
-
| `--
|
|
70
|
-
| `--help` | Show CLI help. | `--help` | None |
|
|
61
|
+
| Option | Description | Example | Default |
|
|
62
|
+
| -------------------------------- | ---------------------------------------------------------------------------------------------------------- | -------------------------------- | ------------------- |
|
|
63
|
+
| `--creator <id>` | Add a creator ID to download. Can be repeated. | `--creator alpha --creator beta` | None |
|
|
64
|
+
| `--following` | Download posts from followed creators. Requires authentication. | `--following` | `false` |
|
|
65
|
+
| `--supporting` | Download posts from supporting creators. Requires authentication. | `--supporting` | `false` |
|
|
66
|
+
| `--ignore-creator <id>` | Exclude a creator ID from the selected creators. Can be repeated. | `--ignore-creator beta` | None |
|
|
67
|
+
| `--cookie <value>` | Raw `FANBOXSESSID`, `FANBOXSESSID=...`, or a full Cookie header. | `--cookie "FANBOXSESSID=..."` | `FANBOX_SESSION_ID` |
|
|
68
|
+
| `--cookie-file <path>` | Read a raw cookie value or Netscape `cookies.txt`. FANBOX cookies are selected automatically. | `--cookie-file ./cookies.txt` | None |
|
|
69
|
+
| `--user-agent <value>` | Send the same User-Agent as the browser session that produced your cookie. | `--user-agent "Mozilla/5.0 ..."` | random string |
|
|
70
|
+
| `--output <path>` | Directory where downloaded creators and posts are stored. | `--output ./fanbox-downloads` | `fanbox-downloads` |
|
|
71
|
+
| `--flat-posts` | Store post files directly under each creator directory instead of one directory per post. | `--flat-posts` | `false` |
|
|
72
|
+
| `--max-filename-bytes <n>` | Maximum filename byte length, including the `.part` temporary suffix. | `--max-filename-bytes 200` | `256` |
|
|
73
|
+
| `--flat-parent-min-bytes <n>` | Minimum optional parent/post-title bytes to preserve in `--flat-posts` filenames. | `--flat-parent-min-bytes 50` | `35` |
|
|
74
|
+
| `--concurrency <n>` | Maximum number of concurrent requests. Must be greater than `0`. | `--concurrency 10` | `10` |
|
|
75
|
+
| `--http2-session-multiplier <n>` | Multiplier used with concurrency to set HTTP/2 sessions per origin. Must be greater than `0`. | `--http2-session-multiplier 10` | `10` |
|
|
76
|
+
| `--request-interval-ms <n>` | Delay between request starts, in milliseconds. | `--request-interval-ms 1000` | `500` |
|
|
77
|
+
| `--rate-limit-pause-ms <n>` | Pause duration after HTTP 429. When omitted, `Retry-After` can be honored by the transport. | `--rate-limit-pause-ms 60000` | None |
|
|
78
|
+
| `--max-retries <n>` | Retry attempts for retryable request failures. | `--max-retries 3` | `3` |
|
|
79
|
+
| `--log-level <level>` | Show logs at this level or higher. One of `fatal`, `error`, `warn`, `info`, `debug`, `trace`, or `silent`. | `--log-level trace` | `info` |
|
|
80
|
+
| `--help` | Show CLI help. | `--help` | None |
|
|
71
81
|
|
|
72
82
|
### CLI Notes
|
|
73
83
|
|
|
74
|
-
The downloader stores each
|
|
75
|
-
|
|
76
|
-
|
|
84
|
+
The downloader stores each creator under its creator ID. By default, each post
|
|
85
|
+
gets its own directory named from the post date, post ID, and title. The post
|
|
86
|
+
content is written as Markdown alongside downloaded cover images, post images,
|
|
87
|
+
and attached files. Asset file names include a zero-padded sequence number, so
|
|
88
|
+
files are easy to browse in order.
|
|
77
89
|
|
|
78
|
-
It keeps a per-creator `manifest.json`, skips unchanged posts,
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
It keeps a per-creator `manifest.json`, skips unchanged or restricted posts,
|
|
91
|
+
skips assets that already exist, records SHA-256 hashes for downloaded assets,
|
|
92
|
+
and resumes `.part` files with HTTP Range requests when supported.
|
|
81
93
|
|
|
82
94
|
Passing `--cookie` is convenient but may leave the session value in shell
|
|
83
95
|
history. `--cookie-file` accepts either a raw cookie value or a Netscape
|
|
@@ -104,7 +116,9 @@ your own browser session and keep it outside source control.
|
|
|
104
116
|
import { FanboxClient } from "@moontaiworks/fanbox-dl";
|
|
105
117
|
|
|
106
118
|
const fanbox = new FanboxClient({
|
|
107
|
-
|
|
119
|
+
headers: {
|
|
120
|
+
Cookie: `FANBOXSESSID=${process.env.FANBOX_SESSION_ID}`,
|
|
121
|
+
},
|
|
108
122
|
});
|
|
109
123
|
|
|
110
124
|
const creators = await fanbox.listFollowingCreators();
|
|
@@ -10,9 +10,11 @@ interface DownloadAssetOptions {
|
|
|
10
10
|
destination: string;
|
|
11
11
|
fallbackDateTime: string;
|
|
12
12
|
mediaContent: MediaContent;
|
|
13
|
+
timeOffset: number;
|
|
13
14
|
}
|
|
14
|
-
export declare function downloadAsset({ headers, logger, transport }: DownloadAssetDeps, { destination, fallbackDateTime, mediaContent }: DownloadAssetOptions): Promise<{
|
|
15
|
+
export declare function downloadAsset({ headers, logger, transport }: DownloadAssetDeps, { destination, fallbackDateTime, mediaContent, timeOffset, }: DownloadAssetOptions): Promise<{
|
|
15
16
|
bytes: number;
|
|
17
|
+
modifiedTime: string;
|
|
16
18
|
sha256: string;
|
|
17
19
|
}>;
|
|
18
20
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../../../src/downloader/asset/download.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"download.d.ts","sourceRoot":"","sources":["../../../../src/downloader/asset/download.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAO9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,UAAU,oBAAoB;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACpB;AAkBD,wBAAsB,aAAa,CACjC,EAAE,OAAY,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,iBAAiB,EACtD,EACE,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,UAAU,GACX,EAAE,oBAAoB;;;;GAwDxB"}
|
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.downloadAsset = downloadAsset;
|
|
7
|
-
const node_crypto_1 = require("node:crypto");
|
|
8
7
|
const node_fs_1 = require("node:fs");
|
|
9
8
|
const promises_1 = require("node:fs/promises");
|
|
10
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
@@ -20,14 +19,14 @@ class AssetDownloadError extends Error {
|
|
|
20
19
|
this.url = url;
|
|
21
20
|
}
|
|
22
21
|
}
|
|
23
|
-
async function downloadAsset({ headers = {}, logger, transport }, { destination, fallbackDateTime, mediaContent }) {
|
|
22
|
+
async function downloadAsset({ headers = {}, logger, transport }, { destination, fallbackDateTime, mediaContent, timeOffset, }) {
|
|
24
23
|
if (await (0, filesystem_js_1.exists)(destination)) {
|
|
25
24
|
logger.debug(`Asset ${mediaContent.id} already exists at ${destination}`);
|
|
26
|
-
const [{ size: bytes }, sha256] = await Promise.all([
|
|
27
|
-
(0,
|
|
28
|
-
hashFile(destination),
|
|
25
|
+
const [{ mtime, size: bytes }, sha256] = await Promise.all([
|
|
26
|
+
(0, promises_1.stat)(destination),
|
|
27
|
+
(0, filesystem_js_1.hashFile)(destination),
|
|
29
28
|
]);
|
|
30
|
-
return { bytes, sha256 };
|
|
29
|
+
return { bytes, modifiedTime: (0, filesystem_js_1.formatFileTimestamp)(mtime), sha256 };
|
|
31
30
|
}
|
|
32
31
|
logger.debug(`Downloading ${mediaContent.type} asset ${mediaContent.id} to ${destination}`);
|
|
33
32
|
await (0, promises_1.mkdir)(node_path_1.default.dirname(destination), { recursive: true });
|
|
@@ -44,20 +43,18 @@ async function downloadAsset({ headers = {}, logger, transport }, { destination,
|
|
|
44
43
|
}
|
|
45
44
|
await write(tempFilePath, response, downloadedBytes);
|
|
46
45
|
const modified = response.headers.get("Last-Modified");
|
|
47
|
-
const timestamp = modified ? new Date(modified) : new Date(fallbackDateTime);
|
|
46
|
+
const timestamp = offsetTimestamp(modified ? new Date(modified) : new Date(fallbackDateTime), timeOffset);
|
|
48
47
|
await (0, promises_1.utimes)(tempFilePath, timestamp, timestamp);
|
|
49
48
|
const [{ size: bytes }, sha256] = await Promise.all([
|
|
50
49
|
(0, filesystem_js_1.filesize)(tempFilePath),
|
|
51
|
-
hashFile(tempFilePath),
|
|
50
|
+
(0, filesystem_js_1.hashFile)(tempFilePath),
|
|
52
51
|
]);
|
|
53
52
|
await (0, promises_1.rename)(tempFilePath, destination);
|
|
54
|
-
|
|
53
|
+
const { mtime } = await (0, promises_1.stat)(destination);
|
|
54
|
+
return { bytes, modifiedTime: (0, filesystem_js_1.formatFileTimestamp)(mtime), sha256 };
|
|
55
55
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
for await (const chunk of (0, node_fs_1.createReadStream)(filePath))
|
|
59
|
-
hash.update(chunk);
|
|
60
|
-
return hash.digest("hex");
|
|
56
|
+
function offsetTimestamp(timestamp, timeOffset) {
|
|
57
|
+
return new Date(timestamp.getTime() + timeOffset * 1000);
|
|
61
58
|
}
|
|
62
59
|
async function write(path, response, partialBytes) {
|
|
63
60
|
return (0, promises_2.pipeline)(response.body ?? "", (0, node_fs_1.createWriteStream)(path, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../../../src/downloader/asset/download.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"download.js","sourceRoot":"","sources":["../../../../src/downloader/asset/download.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Logger } from "pino";
|
|
2
|
-
export declare const DOWNLOAD_HELP = "Usage: fanbox-dl download [options]\n\nDownload FANBOX posts for selected creators.\n\nSelectors:\n --creator <id> Add a creator ID. Can be repeated.\n --following Add all followed creators.\n --supporting Add all supporting creators.\n --ignore-creator <id> Exclude a creator ID. Can be repeated.\n\nAuth:\n --cookie <value> Raw session ID or FANBOXSESSID=... cookie.\n --cookie-file <path> Read raw cookie or Netscape cookies.txt.\n --user-agent <value> Send the User-Agent from your logged-in browser.\n FANBOX_SESSION_ID Environment fallback.\n
|
|
2
|
+
export declare const DOWNLOAD_HELP = "Usage: fanbox-dl download [options]\n\nDownload FANBOX posts for selected creators.\n\nSelectors:\n --creator <id> Add a creator ID. Can be repeated.\n --following Add all followed creators.\n --supporting Add all supporting creators.\n --ignore-creator <id> Exclude a creator ID. Can be repeated.\n\nAuth:\n --cookie <value> Raw session ID or FANBOXSESSID=... cookie.\n --cookie-file <path> Read raw cookie or Netscape cookies.txt.\n --user-agent <value> Send the User-Agent from your logged-in browser.\n FANBOX_SESSION_ID Environment fallback.\n\nDownload:\n --output <path> Output directory. Default: fanbox-downloads.\n --flat-posts Store post files directly under each creator.\n --max-filename-bytes <n> Max filename bytes including .part temp suffix. Default: 256.\n --flat-parent-min-bytes <n>\n Min optional parent/post name bytes to preserve in flat-posts filenames. Default: 35.\n --verify Verify skipped complete posts against local files.\n\nRequests:\n --concurrency <n> Concurrent requests. Default: 10.\n --http2-session-multiplier <n>\n HTTP/2 sessions per origin multiplier based on concurrency. Default: 10.\n --request-interval-ms <n> Delay between request starts. Default: 500.\n --rate-limit-pause-ms <n> Force overwrite pause ms when 429.\n --max-retries <n> Retry attempts. Default: 3.\n\nOutput:\n --log-level <level> fatal|error|warn|info|debug|trace|silent. Default: info.\n --help Show this help.\n";
|
|
3
3
|
export interface DownloadOptions {
|
|
4
4
|
concurrency: number;
|
|
5
5
|
cookie?: string;
|
|
@@ -16,6 +16,7 @@ export interface DownloadOptions {
|
|
|
16
16
|
requestIntervalMs: number;
|
|
17
17
|
supporting: boolean;
|
|
18
18
|
userAgent?: string;
|
|
19
|
+
verify: boolean;
|
|
19
20
|
}
|
|
20
21
|
interface ParseDownloadOptionsDeps {
|
|
21
22
|
logger: Logger;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../../src/downloader/cli/options.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAKnC,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../../src/downloader/cli/options.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAKnC,eAAO,MAAM,aAAa,ynDAmCzB,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,UAAU,wBAAwB;IAChC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,oBAAoB,CAClC,EAAE,MAAM,EAAE,EAAE,wBAAwB,EACpC,IAAI,EAAE,MAAM,EAAE,GACb,eAAe,CA4CjB"}
|
|
@@ -21,7 +21,6 @@ Auth:
|
|
|
21
21
|
--cookie-file <path> Read raw cookie or Netscape cookies.txt.
|
|
22
22
|
--user-agent <value> Send the User-Agent from your logged-in browser.
|
|
23
23
|
FANBOX_SESSION_ID Environment fallback.
|
|
24
|
-
FANBOX_USER_AGENT User-Agent environment fallback.
|
|
25
24
|
|
|
26
25
|
Download:
|
|
27
26
|
--output <path> Output directory. Default: fanbox-downloads.
|
|
@@ -29,6 +28,7 @@ Download:
|
|
|
29
28
|
--max-filename-bytes <n> Max filename bytes including .part temp suffix. Default: 256.
|
|
30
29
|
--flat-parent-min-bytes <n>
|
|
31
30
|
Min optional parent/post name bytes to preserve in flat-posts filenames. Default: 35.
|
|
31
|
+
--verify Verify skipped complete posts against local files.
|
|
32
32
|
|
|
33
33
|
Requests:
|
|
34
34
|
--concurrency <n> Concurrent requests. Default: 10.
|
|
@@ -67,6 +67,7 @@ function parseDownloadOptions({ logger }, args) {
|
|
|
67
67
|
requestIntervalMs: parseNonNegativeInteger("request-interval-ms", values["request-interval-ms"]),
|
|
68
68
|
supporting: values.supporting,
|
|
69
69
|
userAgent: values["user-agent"],
|
|
70
|
+
verify: values.verify,
|
|
70
71
|
};
|
|
71
72
|
}
|
|
72
73
|
function parseCookie({ logger }, values) {
|
|
@@ -110,6 +111,7 @@ function parseDownloadArgs(args) {
|
|
|
110
111
|
"request-interval-ms": { default: "500", type: "string" },
|
|
111
112
|
supporting: { default: false, type: "boolean" },
|
|
112
113
|
"user-agent": { type: "string" },
|
|
114
|
+
verify: { default: false, type: "boolean" },
|
|
113
115
|
},
|
|
114
116
|
strict: true,
|
|
115
117
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../../src/downloader/cli/options.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../../src/downloader/cli/options.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover-posts.d.ts","sourceRoot":"","sources":["../../../../src/downloader/creator/discover-posts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAEV,WAAW,EACZ,MAAM,uBAAuB,CAAC;AAE/B,UAAU,gCAAgC;IACxC,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,2BAA2B;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,oBAAoB,CACxC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,gCAAgC,EACpD,EACE,SAAS,EACT,OAAO,EACP,sBAAsB,EACtB,KAAW,GACZ,EAAE,2BAA2B,GAC7B,OAAO,CAAC,WAAW,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"discover-posts.d.ts","sourceRoot":"","sources":["../../../../src/downloader/creator/discover-posts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAEV,WAAW,EACZ,MAAM,uBAAuB,CAAC;AAE/B,UAAU,gCAAgC;IACxC,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,2BAA2B;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,oBAAoB,CACxC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,gCAAgC,EACpD,EACE,SAAS,EACT,OAAO,EACP,sBAAsB,EACtB,KAAW,GACZ,EAAE,2BAA2B,GAC7B,OAAO,CAAC,WAAW,EAAE,CAAC,CA6BxB"}
|
|
@@ -14,11 +14,13 @@ async function discoverCreatorPosts({ client, logger }, { creatorId, firstId, fi
|
|
|
14
14
|
logger.debug(`Discovered ${posts.length} posts for creator ${creatorId}`);
|
|
15
15
|
if (posts.length < limit)
|
|
16
16
|
return posts;
|
|
17
|
-
const
|
|
17
|
+
const lastPost = posts.at(-1);
|
|
18
|
+
if (!lastPost)
|
|
19
|
+
return posts;
|
|
18
20
|
const remains = await discoverCreatorPosts({ client, logger }, {
|
|
19
21
|
creatorId,
|
|
20
|
-
firstId:
|
|
21
|
-
firstPublishedDatetime:
|
|
22
|
+
firstId: lastPost.id,
|
|
23
|
+
firstPublishedDatetime: lastPost.publishedDatetime,
|
|
22
24
|
limit,
|
|
23
25
|
});
|
|
24
26
|
return [...posts, ...remains.slice(1)];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover-posts.js","sourceRoot":"","sources":["../../../../src/downloader/creator/discover-posts.ts"],"names":[],"mappings":";;AAoBA,
|
|
1
|
+
{"version":3,"file":"discover-posts.js","sourceRoot":"","sources":["../../../../src/downloader/creator/discover-posts.ts"],"names":[],"mappings":";;AAoBA,oDAqCC;AArCM,KAAK,UAAU,oBAAoB,CACxC,EAAE,MAAM,EAAE,MAAM,EAAoC,EACpD,EACE,SAAS,EACT,OAAO,EACP,sBAAsB,EACtB,KAAK,GAAG,GAAG,GACiB;IAE9B,MAAM,CAAC,KAAK,CACV,mBAAmB,KAAK,eAAe,OAAO,IAAI,OAAO,gBAAgB,SAAS,EAAE,CACrF,CAAC;IACF,MAAM,uBAAuB,GAAG;QAC9B,SAAS;QACT,OAAO;QACP,sBAAsB;QACtB,KAAK;QACL,IAAI,EAAE,QAAQ;KACkB,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;IACrE,MAAM,CAAC,KAAK,CAAC,cAAc,KAAK,CAAC,MAAM,sBAAsB,SAAS,EAAE,CAAC,CAAC;IAC1E,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK;QAAE,OAAO,KAAK,CAAC;IAEvC,MAAM,QAAQ,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE5B,MAAM,OAAO,GAAG,MAAM,oBAAoB,CACxC,EAAE,MAAM,EAAE,MAAM,EAAE,EAClB;QACE,SAAS;QACT,OAAO,EAAE,QAAQ,CAAC,EAAE;QACpB,sBAAsB,EAAE,QAAQ,CAAC,iBAAiB;QAClD,KAAK;KACN,CACF,CAAC;IAEF,OAAO,CAAC,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -10,7 +10,8 @@ interface SyncCreatorDeps {
|
|
|
10
10
|
manifest: CreatorManifest;
|
|
11
11
|
pathManager: PathManager;
|
|
12
12
|
transport: HttpTransport;
|
|
13
|
+
verify?: boolean;
|
|
13
14
|
}
|
|
14
|
-
export declare function syncCreator({ client, headers, logger, manifest, pathManager, transport, }: SyncCreatorDeps): Promise<void>;
|
|
15
|
+
export declare function syncCreator({ client, headers, logger, manifest, pathManager, transport, verify, }: SyncCreatorDeps): Promise<void>;
|
|
15
16
|
export {};
|
|
16
17
|
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../../src/downloader/creator/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../../src/downloader/creator/sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,wBAAwB,CAAC;AAUhF,UAAU,eAAe;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,eAAe,CAAC;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,aAAa,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,WAAW,CAAC,EAChC,MAAM,EACN,OAAO,EACP,MAAM,EACN,QAAQ,EACR,WAAW,EACX,SAAS,EACT,MAAc,GACf,EAAE,eAAe,iBAoEjB"}
|
|
@@ -3,15 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.syncCreator = syncCreator;
|
|
4
4
|
const sync_js_1 = require("../post/sync.js");
|
|
5
5
|
const discover_posts_js_1 = require("./discover-posts.js");
|
|
6
|
-
async function syncCreator({ client, headers, logger, manifest, pathManager, transport, }) {
|
|
6
|
+
async function syncCreator({ client, headers, logger, manifest, pathManager, transport, verify = false, }) {
|
|
7
7
|
const postSummaries = await (0, discover_posts_js_1.discoverCreatorPosts)({ client, logger }, { creatorId: manifest.creatorId });
|
|
8
8
|
logger.info(`Discovered total ${postSummaries.length} posts for creator ${manifest.creatorId}`);
|
|
9
9
|
const processingPosts = [];
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
logger.debug(`Initializing ${
|
|
13
|
-
const preCheckResult = (0, sync_js_1.preSyncPostCheck)({ logger, manifest }, postSummary);
|
|
14
|
-
if (preCheckResult.status
|
|
10
|
+
for (const [index, postSummary] of postSummaries.entries()) {
|
|
11
|
+
const postIndex = index + 1;
|
|
12
|
+
logger.debug(`Initializing ${postIndex}/${postSummaries.length} post ${postSummary.id} for creator ${manifest.creatorId}`);
|
|
13
|
+
const preCheckResult = await (0, sync_js_1.preSyncPostCheck)({ logger, manifest, verify }, postSummary);
|
|
14
|
+
if (preCheckResult.status === "complete" ||
|
|
15
|
+
preCheckResult.status === "skipped") {
|
|
15
16
|
manifest.posts[postSummary.id] = preCheckResult;
|
|
16
17
|
continue;
|
|
17
18
|
}
|
|
@@ -19,16 +20,8 @@ async function syncCreator({ client, headers, logger, manifest, pathManager, tra
|
|
|
19
20
|
const post = await client
|
|
20
21
|
.getPost({ postId: postSummary.id })
|
|
21
22
|
.catch(async (err) => {
|
|
22
|
-
manifest.
|
|
23
|
-
|
|
24
|
-
error: String(err),
|
|
25
|
-
id: postSummary.id,
|
|
26
|
-
restricted: postSummary.isRestricted,
|
|
27
|
-
status: "failed",
|
|
28
|
-
updatedDatetime: postSummary.updatedDatetime,
|
|
29
|
-
};
|
|
30
|
-
logger.error({ err }, `Error occurred while fetch post manifest of ${index}/${postSummaries.length} post ${postSummary.id}, skipping.`);
|
|
31
|
-
await manifest.save();
|
|
23
|
+
logger.error({ err }, `Error occurred while fetch post manifest of ${postIndex}/${postSummaries.length} post ${postSummary.id}, skipping.`);
|
|
24
|
+
await saveFailedPostManifest(manifest, postSummary, err);
|
|
32
25
|
});
|
|
33
26
|
if (!post)
|
|
34
27
|
continue;
|
|
@@ -38,20 +31,26 @@ async function syncCreator({ client, headers, logger, manifest, pathManager, tra
|
|
|
38
31
|
return manifest.save();
|
|
39
32
|
})
|
|
40
33
|
.catch((err) => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
error: String(err),
|
|
44
|
-
id: postSummary.id,
|
|
45
|
-
restricted: postSummary.isRestricted,
|
|
46
|
-
status: "failed",
|
|
47
|
-
updatedDatetime: postSummary.updatedDatetime,
|
|
48
|
-
};
|
|
49
|
-
logger.error({ err }, `Error occurred while syncing ${index}/${postSummaries.length} post ${postSummary.id}, skipping.`);
|
|
50
|
-
return manifest.save();
|
|
34
|
+
logger.error({ err }, `Error occurred while syncing ${postIndex}/${postSummaries.length} post ${postSummary.id}, skipping.`);
|
|
35
|
+
return saveFailedPostManifest(manifest, postSummary, err);
|
|
51
36
|
});
|
|
52
37
|
processingPosts.push(syncPostPromise);
|
|
53
38
|
}
|
|
54
39
|
logger.info(`All ${postSummaries.length} posts of creator ${manifest.creatorId} have been initialized for sync, waiting for all to complete...`);
|
|
55
40
|
await Promise.all(processingPosts);
|
|
56
41
|
}
|
|
42
|
+
function failedPostManifestData(postSummary, err) {
|
|
43
|
+
return {
|
|
44
|
+
assets: {},
|
|
45
|
+
error: String(err),
|
|
46
|
+
id: postSummary.id,
|
|
47
|
+
restricted: postSummary.isRestricted,
|
|
48
|
+
status: "failed",
|
|
49
|
+
updatedDatetime: postSummary.updatedDatetime,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async function saveFailedPostManifest(manifest, postSummary, err) {
|
|
53
|
+
manifest.posts[postSummary.id] = failedPostManifestData(postSummary, err);
|
|
54
|
+
await manifest.save();
|
|
55
|
+
}
|
|
57
56
|
//# sourceMappingURL=sync.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../../src/downloader/creator/sync.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../../../src/downloader/creator/sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,5 +2,8 @@ export declare function exists(filePath: string): Promise<boolean>;
|
|
|
2
2
|
export declare function filesize(path: string): Promise<import("fs").Stats | {
|
|
3
3
|
size: number;
|
|
4
4
|
}>;
|
|
5
|
+
export declare function formatFileTimestamp(timestamp: Date): string;
|
|
6
|
+
export declare function hashFile(filePath: string): Promise<string>;
|
|
5
7
|
export declare function isNotFoundError(error: unknown): boolean;
|
|
8
|
+
export declare function normalizeFileTimestamp(timestamp: Date): Date;
|
|
6
9
|
//# sourceMappingURL=filesystem.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../../../src/downloader/fs/filesystem.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../../../src/downloader/fs/filesystem.ts"],"names":[],"mappings":"AAIA,wBAAsB,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQ/D;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM;;GAM1C;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,IAAI,GAAG,MAAM,CAE3D;AAED,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOhE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEvD;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,IAAI,GAAG,IAAI,CAE5D"}
|
|
@@ -2,19 +2,44 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.exists = exists;
|
|
4
4
|
exports.filesize = filesize;
|
|
5
|
+
exports.formatFileTimestamp = formatFileTimestamp;
|
|
6
|
+
exports.hashFile = hashFile;
|
|
5
7
|
exports.isNotFoundError = isNotFoundError;
|
|
8
|
+
exports.normalizeFileTimestamp = normalizeFileTimestamp;
|
|
9
|
+
const node_crypto_1 = require("node:crypto");
|
|
10
|
+
const node_fs_1 = require("node:fs");
|
|
6
11
|
const promises_1 = require("node:fs/promises");
|
|
7
12
|
async function exists(filePath) {
|
|
8
13
|
return (0, promises_1.stat)(filePath)
|
|
9
14
|
.then(() => true)
|
|
10
|
-
.catch(() =>
|
|
15
|
+
.catch((error) => {
|
|
16
|
+
if (isNotFoundError(error))
|
|
17
|
+
return false;
|
|
18
|
+
throw error;
|
|
19
|
+
});
|
|
11
20
|
}
|
|
12
21
|
async function filesize(path) {
|
|
13
|
-
return (0, promises_1.stat)(path).catch(() =>
|
|
22
|
+
return (0, promises_1.stat)(path).catch((error) => {
|
|
23
|
+
if (isNotFoundError(error))
|
|
24
|
+
return { size: 0 };
|
|
25
|
+
throw error;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function formatFileTimestamp(timestamp) {
|
|
29
|
+
return normalizeFileTimestamp(timestamp).toISOString();
|
|
30
|
+
}
|
|
31
|
+
async function hashFile(filePath) {
|
|
32
|
+
const hash = (0, node_crypto_1.createHash)("sha256");
|
|
33
|
+
for await (const chunk of (0, node_fs_1.createReadStream)(filePath))
|
|
34
|
+
hash.update(chunk);
|
|
35
|
+
return hash.digest("hex");
|
|
14
36
|
}
|
|
15
37
|
function isNotFoundError(error) {
|
|
16
38
|
return isNodeError(error) && error.code === "ENOENT";
|
|
17
39
|
}
|
|
40
|
+
function normalizeFileTimestamp(timestamp) {
|
|
41
|
+
return new Date(Math.trunc(timestamp.getTime() / 1000) * 1000);
|
|
42
|
+
}
|
|
18
43
|
function isNodeError(error) {
|
|
19
44
|
return error instanceof Error && "code" in error;
|
|
20
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../../../../src/downloader/fs/filesystem.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../../../../src/downloader/fs/filesystem.ts"],"names":[],"mappings":";;AAIA,wBAQC;AAED,4BAMC;AAED,kDAEC;AAED,4BAOC;AAED,0CAEC;AAED,wDAEC;AAzCD,6CAAyC;AACzC,qCAA2C;AAC3C,+CAAwC;AAEjC,KAAK,UAAU,MAAM,CAAC,QAAgB;IAC3C,OAAO,IAAA,eAAI,EAAC,QAAQ,CAAC;SAClB,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;SAChB,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QACxB,IAAI,eAAe,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QAEzC,MAAM,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;AACP,CAAC;AAEM,KAAK,UAAU,QAAQ,CAAC,IAAY;IACzC,OAAO,IAAA,eAAI,EAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QACzC,IAAI,eAAe,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;QAE/C,MAAM,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,mBAAmB,CAAC,SAAe;IACjD,OAAO,sBAAsB,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;AACzD,CAAC;AAEM,KAAK,UAAU,QAAQ,CAAC,QAAgB;IAC7C,MAAM,IAAI,GAAG,IAAA,wBAAU,EAAC,QAAQ,CAAC,CAAC;IAElC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAA,0BAAgB,EAAC,QAAQ,CAAC;QAClD,IAAI,CAAC,MAAM,CAAC,KAAe,CAAC,CAAC;IAE/B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,SAAgB,eAAe,CAAC,KAAc;IAC5C,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;AACvD,CAAC;AAED,SAAgB,sBAAsB,CAAC,SAAe;IACpD,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,IAAK,CAAC,GAAG,IAAK,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,CAAC;AACnD,CAAC"}
|
|
@@ -5,5 +5,5 @@ export interface RunCliDependencies {
|
|
|
5
5
|
logger: Logger;
|
|
6
6
|
transport?: HttpTransport;
|
|
7
7
|
}
|
|
8
|
-
export declare function download({ logger, transport: customTransport }: RunCliDependencies, options: DownloadOptions): Promise<
|
|
8
|
+
export declare function download({ logger, transport: customTransport }: RunCliDependencies, options: DownloadOptions): Promise<boolean>;
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/downloader/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAInC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/downloader/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAInC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAMxD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AAED,wBAAsB,QAAQ,CAC5B,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE,kBAAkB,EAC1D,OAAO,EAAE,eAAe,oBA2EzB"}
|
|
@@ -30,7 +30,6 @@ async function download({ logger, transport: customTransport }, options) {
|
|
|
30
30
|
rootPath: options.output,
|
|
31
31
|
});
|
|
32
32
|
const client = new client_js_1.FanboxClient({ headers, transport });
|
|
33
|
-
const failed = [];
|
|
34
33
|
const creatorIds = await (0, resolver_js_1.resolveCreatorIds)({ client, logger }, options);
|
|
35
34
|
const creatorManifestManager = new creator_manager_js_1.CreatorManifestManager({
|
|
36
35
|
logger,
|
|
@@ -40,32 +39,30 @@ async function download({ logger, transport: customTransport }, options) {
|
|
|
40
39
|
for (const creatorId of creatorIds) {
|
|
41
40
|
logger.debug(`Initializing download for creator ${creatorId}`);
|
|
42
41
|
const creatorManifest = await creatorManifestManager.load(creatorId);
|
|
43
|
-
const creatorPathManager = pathManager.dir([
|
|
44
|
-
{ context: creatorId, required: true },
|
|
45
|
-
]);
|
|
46
42
|
const syncCreatorPromise = (0, sync_js_1.syncCreator)({
|
|
47
43
|
client,
|
|
48
44
|
headers,
|
|
49
45
|
logger,
|
|
50
46
|
manifest: creatorManifest,
|
|
51
|
-
pathManager:
|
|
47
|
+
pathManager: pathManager.dir([{ context: creatorId, required: true }]),
|
|
52
48
|
transport,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
verify: options.verify,
|
|
50
|
+
})
|
|
51
|
+
.then(() => {
|
|
52
|
+
creatorManifestManager.markSucceeded(creatorId);
|
|
53
|
+
})
|
|
54
|
+
.catch((err) => {
|
|
55
|
+
logger.error({ err }, `Error occurred while syncing creator ${creatorId}, skipping.`);
|
|
56
|
+
creatorManifestManager.markFailed(creatorId, err);
|
|
56
57
|
});
|
|
57
58
|
processingCreators.push(syncCreatorPromise);
|
|
58
|
-
const success = !hasFailures(creatorManifest);
|
|
59
|
-
if (!success)
|
|
60
|
-
failed.push(creatorId);
|
|
61
59
|
}
|
|
62
60
|
logger.info(`All ${creatorIds.length} creators have been initialized for download, waiting for all to complete...`);
|
|
63
61
|
await Promise.all(processingCreators);
|
|
64
62
|
await creatorManifestManager.saveAll();
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return Object.values(manifest.posts).some((post) => post?.status === "failed");
|
|
63
|
+
const failedCreatorIds = creatorManifestManager.getFailedCreatorIds();
|
|
64
|
+
logger.info({ failedCreatorIds }, `Download completed for ${creatorIds.length} creators, with ${failedCreatorIds.length} failures.`);
|
|
65
|
+
const hasFailedCreators = failedCreatorIds.length > 0;
|
|
66
|
+
return hasFailedCreators;
|
|
70
67
|
}
|
|
71
68
|
//# sourceMappingURL=index.js.map
|