pixivflow 2.5.0 → 2.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 +72 -0
- package/README_EN.md +55 -0
- package/config/fly-two-bots.example.json +240 -0
- package/dist/commands/SchedulerCommand.d.ts +1 -0
- package/dist/commands/SchedulerCommand.d.ts.map +1 -1
- package/dist/commands/SchedulerCommand.js +78 -22
- package/dist/commands/SchedulerCommand.js.map +1 -1
- package/dist/config/defaults.d.ts +5 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +6 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/loader.d.ts +1 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +4 -2
- package/dist/config/loader.js.map +1 -1
- package/dist/config/path-resolution.d.ts.map +1 -1
- package/dist/config/path-resolution.js +4 -0
- package/dist/config/path-resolution.js.map +1 -1
- package/dist/config/types.d.ts +91 -3
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/validation.d.ts.map +1 -1
- package/dist/config/validation.js +92 -0
- package/dist/config/validation.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/delivery/DeliveryDispatcher.d.ts +11 -0
- package/dist/delivery/DeliveryDispatcher.d.ts.map +1 -0
- package/dist/delivery/DeliveryDispatcher.js +31 -0
- package/dist/delivery/DeliveryDispatcher.js.map +1 -0
- package/dist/delivery/DeliveryOutbox.d.ts +23 -0
- package/dist/delivery/DeliveryOutbox.d.ts.map +1 -0
- package/dist/delivery/DeliveryOutbox.js +172 -0
- package/dist/delivery/DeliveryOutbox.js.map +1 -0
- package/dist/delivery/HttpMultipartDelivery.d.ts +18 -0
- package/dist/delivery/HttpMultipartDelivery.d.ts.map +1 -0
- package/dist/delivery/HttpMultipartDelivery.js +217 -0
- package/dist/delivery/HttpMultipartDelivery.js.map +1 -0
- package/dist/delivery/types.d.ts +31 -0
- package/dist/delivery/types.d.ts.map +1 -0
- package/dist/delivery/types.js +3 -0
- package/dist/delivery/types.js.map +1 -0
- package/dist/download/DownloadManager.d.ts +2 -0
- package/dist/download/DownloadManager.d.ts.map +1 -1
- package/dist/download/DownloadManager.js +30 -2
- package/dist/download/DownloadManager.js.map +1 -1
- package/dist/download/IllustrationDownloader.d.ts +2 -1
- package/dist/download/IllustrationDownloader.d.ts.map +1 -1
- package/dist/download/IllustrationDownloader.js +29 -4
- package/dist/download/IllustrationDownloader.js.map +1 -1
- package/dist/download/NovelDownloader.d.ts +2 -1
- package/dist/download/NovelDownloader.d.ts.map +1 -1
- package/dist/download/NovelDownloader.js +9 -1
- package/dist/download/NovelDownloader.js.map +1 -1
- package/dist/download/handlers/IllustrationTargetHandler.d.ts +4 -1
- package/dist/download/handlers/IllustrationTargetHandler.d.ts.map +1 -1
- package/dist/download/handlers/IllustrationTargetHandler.js +27 -10
- package/dist/download/handlers/IllustrationTargetHandler.js.map +1 -1
- package/dist/download/handlers/NovelTargetHandler.d.ts +4 -1
- package/dist/download/handlers/NovelTargetHandler.d.ts.map +1 -1
- package/dist/download/handlers/NovelTargetHandler.js +26 -11
- package/dist/download/handlers/NovelTargetHandler.js.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/dist/scheduler/MultiScheduleManager.d.ts +39 -0
- package/dist/scheduler/MultiScheduleManager.d.ts.map +1 -0
- package/dist/scheduler/MultiScheduleManager.js +182 -0
- package/dist/scheduler/MultiScheduleManager.js.map +1 -0
- package/dist/scheduler/Scheduler.d.ts +13 -1
- package/dist/scheduler/Scheduler.d.ts.map +1 -1
- package/dist/scheduler/Scheduler.js +31 -7
- package/dist/scheduler/Scheduler.js.map +1 -1
- package/dist/scheduler/schedules.d.ts +8 -0
- package/dist/scheduler/schedules.d.ts.map +1 -0
- package/dist/scheduler/schedules.js +32 -0
- package/dist/scheduler/schedules.js.map +1 -0
- package/dist/storage/Database.d.ts +5 -4
- package/dist/storage/Database.d.ts.map +1 -1
- package/dist/storage/Database.js +13 -9
- package/dist/storage/Database.js.map +1 -1
- package/dist/storage/DatabaseMigration.d.ts.map +1 -1
- package/dist/storage/DatabaseMigration.js +11 -0
- package/dist/storage/DatabaseMigration.js.map +1 -1
- package/dist/storage/repositories/SchedulerRepository.d.ts +4 -4
- package/dist/storage/repositories/SchedulerRepository.d.ts.map +1 -1
- package/dist/storage/repositories/SchedulerRepository.js +18 -12
- package/dist/storage/repositories/SchedulerRepository.js.map +1 -1
- package/dist/utils/config-validator-unified.d.ts.map +1 -1
- package/dist/utils/config-validator-unified.js +117 -0
- package/dist/utils/config-validator-unified.js.map +1 -1
- package/dist/utils/errors.d.ts +8 -0
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +16 -1
- package/dist/utils/errors.js.map +1 -1
- package/dist/webui/package.json +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DeliveryOutbox = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
7
|
+
const logger_1 = require("../logger");
|
|
8
|
+
const errors_1 = require("../utils/errors");
|
|
9
|
+
/** Durable, provider-independent delivery outbox for cache-mode downloads. */
|
|
10
|
+
class DeliveryOutbox {
|
|
11
|
+
directory;
|
|
12
|
+
dispatcher;
|
|
13
|
+
deleteAfterDelivery;
|
|
14
|
+
constructor(directory, dispatcher, deleteAfterDelivery = true) {
|
|
15
|
+
this.directory = directory;
|
|
16
|
+
this.dispatcher = dispatcher;
|
|
17
|
+
this.deleteAfterDelivery = deleteAfterDelivery;
|
|
18
|
+
}
|
|
19
|
+
async deliver(artifact, target) {
|
|
20
|
+
if (target.storageMode !== 'cache')
|
|
21
|
+
return;
|
|
22
|
+
const deliveryTarget = target.delivery?.target?.trim();
|
|
23
|
+
if (!deliveryTarget) {
|
|
24
|
+
throw new errors_1.ConfigError('cache storageMode requires target.delivery.target');
|
|
25
|
+
}
|
|
26
|
+
if (!this.dispatcher.hasTarget(deliveryTarget)) {
|
|
27
|
+
throw new errors_1.ConfigError(`Delivery target is not configured: ${deliveryTarget}`);
|
|
28
|
+
}
|
|
29
|
+
if (artifact.files.length === 0) {
|
|
30
|
+
throw new Error(`No files were produced for ${artifact.type} ${artifact.pixivId}`);
|
|
31
|
+
}
|
|
32
|
+
await node_fs_1.promises.mkdir(this.directory, { recursive: true });
|
|
33
|
+
const now = new Date().toISOString();
|
|
34
|
+
const entry = {
|
|
35
|
+
version: 1,
|
|
36
|
+
id: (0, node_crypto_1.randomUUID)(),
|
|
37
|
+
createdAt: now,
|
|
38
|
+
updatedAt: now,
|
|
39
|
+
attempts: 0,
|
|
40
|
+
status: 'pending',
|
|
41
|
+
deliveryTarget,
|
|
42
|
+
artifact: {
|
|
43
|
+
...artifact,
|
|
44
|
+
files: [...new Set(artifact.files.map((file) => (0, node_path_1.resolve)(file)))],
|
|
45
|
+
cleanupFiles: [...new Set((artifact.cleanupFiles ?? []).map((file) => (0, node_path_1.resolve)(file)))],
|
|
46
|
+
},
|
|
47
|
+
request: {
|
|
48
|
+
fields: target.delivery?.fields,
|
|
49
|
+
context: {
|
|
50
|
+
title: artifact.title,
|
|
51
|
+
pixivId: artifact.pixivId,
|
|
52
|
+
type: artifact.type,
|
|
53
|
+
tag: target.filterTag ?? target.tag,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
const manifestPath = (0, node_path_1.join)(this.directory, `${artifact.type}-${artifact.pixivId}-${entry.id}.json`);
|
|
58
|
+
await this.writeNewManifest(manifestPath, entry);
|
|
59
|
+
try {
|
|
60
|
+
await this.processManifest(manifestPath, entry);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
64
|
+
throw new errors_1.PendingDeliveryError(`Delivery failed; files retained for retry in ${manifestPath}: ${message}`, error instanceof Error ? error : undefined);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async retryPending() {
|
|
68
|
+
let names;
|
|
69
|
+
try {
|
|
70
|
+
names = (await node_fs_1.promises.readdir(this.directory)).filter((name) => name.endsWith('.json')).sort();
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (error.code === 'ENOENT')
|
|
74
|
+
return { succeeded: 0, failed: 0 };
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
let succeeded = 0;
|
|
78
|
+
let failed = 0;
|
|
79
|
+
for (const name of names) {
|
|
80
|
+
const manifestPath = (0, node_path_1.join)(this.directory, name);
|
|
81
|
+
try {
|
|
82
|
+
const entry = await this.readManifest(manifestPath);
|
|
83
|
+
await this.processManifest(manifestPath, entry);
|
|
84
|
+
succeeded++;
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
failed++;
|
|
88
|
+
logger_1.logger.warn('Pending delivery remains queued', {
|
|
89
|
+
manifestPath,
|
|
90
|
+
error: error instanceof Error ? error.message : String(error),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { succeeded, failed };
|
|
95
|
+
}
|
|
96
|
+
async processManifest(manifestPath, entry) {
|
|
97
|
+
if (entry.status === 'pending') {
|
|
98
|
+
await this.assertFilesExist(entry.artifact.files);
|
|
99
|
+
try {
|
|
100
|
+
const result = await this.dispatcher.deliver(entry.deliveryTarget, {
|
|
101
|
+
...entry.request,
|
|
102
|
+
files: entry.artifact.files,
|
|
103
|
+
});
|
|
104
|
+
entry.result = { status: result.status };
|
|
105
|
+
entry.status = 'delivered';
|
|
106
|
+
entry.attempts++;
|
|
107
|
+
entry.updatedAt = new Date().toISOString();
|
|
108
|
+
delete entry.lastError;
|
|
109
|
+
await this.writeManifest(manifestPath, entry);
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
entry.attempts++;
|
|
113
|
+
entry.updatedAt = new Date().toISOString();
|
|
114
|
+
entry.lastError = error instanceof Error ? error.message : String(error);
|
|
115
|
+
await this.writeManifest(manifestPath, entry);
|
|
116
|
+
throw error;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (this.deleteAfterDelivery) {
|
|
120
|
+
await this.deleteFiles([...entry.artifact.files, ...(entry.artifact.cleanupFiles ?? [])]);
|
|
121
|
+
}
|
|
122
|
+
await node_fs_1.promises.unlink(manifestPath).catch((error) => {
|
|
123
|
+
if (error.code !== 'ENOENT')
|
|
124
|
+
throw error;
|
|
125
|
+
});
|
|
126
|
+
logger_1.logger.info('Delivery outbox item completed', {
|
|
127
|
+
deliveryTarget: entry.deliveryTarget,
|
|
128
|
+
pixivId: entry.artifact.pixivId,
|
|
129
|
+
type: entry.artifact.type,
|
|
130
|
+
status: entry.result?.status,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
async assertFilesExist(files) {
|
|
134
|
+
for (const file of files) {
|
|
135
|
+
try {
|
|
136
|
+
await node_fs_1.promises.access(file);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
throw new Error(`Pending delivery file is missing: ${file}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async deleteFiles(files) {
|
|
144
|
+
for (const file of new Set(files)) {
|
|
145
|
+
await node_fs_1.promises.unlink(file).catch((error) => {
|
|
146
|
+
if (error.code !== 'ENOENT')
|
|
147
|
+
throw error;
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async readManifest(manifestPath) {
|
|
152
|
+
const parsed = JSON.parse(await node_fs_1.promises.readFile(manifestPath, 'utf8'));
|
|
153
|
+
if (parsed.version !== 1 ||
|
|
154
|
+
!parsed.deliveryTarget ||
|
|
155
|
+
!parsed.artifact ||
|
|
156
|
+
!Array.isArray(parsed.artifact.files) ||
|
|
157
|
+
!parsed.request?.context) {
|
|
158
|
+
throw new Error(`Invalid delivery outbox manifest: ${manifestPath}`);
|
|
159
|
+
}
|
|
160
|
+
return parsed;
|
|
161
|
+
}
|
|
162
|
+
async writeNewManifest(manifestPath, entry) {
|
|
163
|
+
const temporaryPath = `${manifestPath}.${process.pid}.${(0, node_crypto_1.randomUUID)()}.tmp`;
|
|
164
|
+
await node_fs_1.promises.writeFile(temporaryPath, JSON.stringify(entry, null, 2), 'utf8');
|
|
165
|
+
await node_fs_1.promises.rename(temporaryPath, manifestPath);
|
|
166
|
+
}
|
|
167
|
+
async writeManifest(manifestPath, entry) {
|
|
168
|
+
await node_fs_1.promises.writeFile(manifestPath, JSON.stringify(entry, null, 2), 'utf8');
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
exports.DeliveryOutbox = DeliveryOutbox;
|
|
172
|
+
//# sourceMappingURL=DeliveryOutbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DeliveryOutbox.js","sourceRoot":"","sources":["../../src/delivery/DeliveryOutbox.ts"],"names":[],"mappings":";;;AAAA,qCAAyC;AACzC,yCAA0C;AAC1C,6CAAyC;AAEzC,sCAAmC;AACnC,4CAAoE;AAuBpE,8EAA8E;AAC9E,MAAa,cAAc;IAEN;IACA;IACA;IAHnB,YACmB,SAAiB,EACjB,UAA8B,EAC9B,sBAAsB,IAAI;QAF1B,cAAS,GAAT,SAAS,CAAQ;QACjB,eAAU,GAAV,UAAU,CAAoB;QAC9B,wBAAmB,GAAnB,mBAAmB,CAAO;IAC1C,CAAC;IAEJ,KAAK,CAAC,OAAO,CAAC,QAA4B,EAAE,MAAoB;QAC9D,IAAI,MAAM,CAAC,WAAW,KAAK,OAAO;YAAE,OAAO;QAE3C,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACvD,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,oBAAW,CAAC,mDAAmD,CAAC,CAAC;QAC7E,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,oBAAW,CAAC,sCAAsC,cAAc,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,8BAA8B,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QACrF,CAAC;QAED,MAAM,kBAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,KAAK,GAAoB;YAC7B,OAAO,EAAE,CAAC;YACV,EAAE,EAAE,IAAA,wBAAU,GAAE;YAChB,SAAS,EAAE,GAAG;YACd,SAAS,EAAE,GAAG;YACd,QAAQ,EAAE,CAAC;YACX,MAAM,EAAE,SAAS;YACjB,cAAc;YACd,QAAQ,EAAE;gBACR,GAAG,QAAQ;gBACX,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,mBAAO,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAChE,YAAY,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAA,mBAAO,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aACvF;YACD,OAAO,EAAE;gBACP,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM;gBAC/B,OAAO,EAAE;oBACP,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,OAAO,EAAE,QAAQ,CAAC,OAAO;oBACzB,IAAI,EAAE,QAAQ,CAAC,IAAI;oBACnB,GAAG,EAAE,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,GAAG;iBACpC;aACF;SACF,CAAC;QACF,MAAM,YAAY,GAAG,IAAA,gBAAI,EACvB,IAAI,CAAC,SAAS,EACd,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,OAAO,IAAI,KAAK,CAAC,EAAE,OAAO,CACxD,CAAC;QACF,MAAM,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QAEjD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,IAAI,6BAAoB,CAC5B,gDAAgD,YAAY,KAAK,OAAO,EAAE,EAC1E,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAC3C,CAAC;QACJ,CAAC;IACH,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,KAAe,CAAC;QACpB,IAAI,CAAC;YACH,KAAK,GAAG,CAAC,MAAM,kBAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7F,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;YAC3F,MAAM,KAAK,CAAC;QACd,CAAC;QAED,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,YAAY,GAAG,IAAA,gBAAI,EAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAChD,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;gBACpD,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;gBAChD,SAAS,EAAE,CAAC;YACd,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,EAAE,CAAC;gBACT,eAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE;oBAC7C,YAAY;oBACZ,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;iBAC9D,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAC/B,CAAC;IAEO,KAAK,CAAC,eAAe,CAAC,YAAoB,EAAE,KAAsB;QACxE,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClD,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE;oBACjE,GAAG,KAAK,CAAC,OAAO;oBAChB,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK;iBAC5B,CAAC,CAAC;gBACH,KAAK,CAAC,MAAM,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;gBACzC,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC;gBAC3B,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACjB,KAAK,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBAC3C,OAAO,KAAK,CAAC,SAAS,CAAC;gBACvB,MAAM,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;YAChD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACjB,KAAK,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBAC3C,KAAK,CAAC,SAAS,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACzE,MAAM,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;gBAC9C,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7B,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5F,CAAC;QACD,MAAM,kBAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,KAA4B,EAAE,EAAE;YACnE,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,KAAK,CAAC;QAC3C,CAAC,CAAC,CAAC;QACH,eAAM,CAAC,IAAI,CAAC,gCAAgC,EAAE;YAC5C,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,OAAO;YAC/B,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI;YACzB,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,MAAM;SAC7B,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,KAAe;QAC5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,kBAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CAAC,qCAAqC,IAAI,EAAE,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,KAAe;QACvC,KAAK,MAAM,IAAI,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,MAAM,kBAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAA4B,EAAE,EAAE;gBAC3D,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;oBAAE,MAAM,KAAK,CAAC;YAC3C,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,YAAoB;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,kBAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAoB,CAAC;QACtF,IACE,MAAM,CAAC,OAAO,KAAK,CAAC;YACpB,CAAC,MAAM,CAAC,cAAc;YACtB,CAAC,MAAM,CAAC,QAAQ;YAChB,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YACrC,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,EACxB,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,qCAAqC,YAAY,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,YAAoB,EAAE,KAAsB;QACzE,MAAM,aAAa,GAAG,GAAG,YAAY,IAAI,OAAO,CAAC,GAAG,IAAI,IAAA,wBAAU,GAAE,MAAM,CAAC;QAC3E,MAAM,kBAAE,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC1E,MAAM,kBAAE,CAAC,MAAM,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IAC/C,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,YAAoB,EAAE,KAAsB;QACtE,MAAM,kBAAE,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC3E,CAAC;CACF;AAzKD,wCAyKC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { HttpMultipartDeliveryConfig } from '../config';
|
|
2
|
+
import { DeliveryProvider, DeliveryRequest, DeliveryResult } from './types';
|
|
3
|
+
/** Generic streaming HTTP multipart delivery provider. */
|
|
4
|
+
export declare class HttpMultipartDelivery implements DeliveryProvider {
|
|
5
|
+
private readonly config;
|
|
6
|
+
private readonly dispatcher?;
|
|
7
|
+
constructor(config: HttpMultipartDeliveryConfig, proxyUrl?: string);
|
|
8
|
+
deliver(request: DeliveryRequest): Promise<DeliveryResult>;
|
|
9
|
+
private attempt;
|
|
10
|
+
private assertSuccess;
|
|
11
|
+
private resolveHeaders;
|
|
12
|
+
private resolveFields;
|
|
13
|
+
private interpolateEnvironment;
|
|
14
|
+
private createMultipartBody;
|
|
15
|
+
private escapeDispositionValue;
|
|
16
|
+
private preview;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=HttpMultipartDelivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpMultipartDelivery.d.ts","sourceRoot":"","sources":["../../src/delivery/HttpMultipartDelivery.ts"],"names":[],"mappings":"AAIA,OAAO,EAAsB,2BAA2B,EAAE,MAAM,WAAW,CAAC;AAE5E,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE5E,0DAA0D;AAC1D,qBAAa,qBAAsB,YAAW,gBAAgB;IAI1D,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHzB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAU;gBAGnB,MAAM,EAAE,2BAA2B,EACpD,QAAQ,CAAC,EAAE,MAAM;IASb,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;YA8BlD,OAAO;IAyCrB,OAAO,CAAC,aAAa;IA0BrB,OAAO,CAAC,cAAc;IAMtB,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,sBAAsB;YAUhB,mBAAmB;IAkDjC,OAAO,CAAC,sBAAsB;IAI9B,OAAO,CAAC,OAAO;CAIhB"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.HttpMultipartDelivery = void 0;
|
|
37
|
+
const fs = __importStar(require("node:fs"));
|
|
38
|
+
const path = __importStar(require("node:path"));
|
|
39
|
+
const node_crypto_1 = require("node:crypto");
|
|
40
|
+
const node_stream_1 = require("node:stream");
|
|
41
|
+
const logger_1 = require("../logger");
|
|
42
|
+
/** Generic streaming HTTP multipart delivery provider. */
|
|
43
|
+
class HttpMultipartDelivery {
|
|
44
|
+
config;
|
|
45
|
+
dispatcher;
|
|
46
|
+
constructor(config, proxyUrl) {
|
|
47
|
+
this.config = config;
|
|
48
|
+
if (proxyUrl) {
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
50
|
+
const { ProxyAgent } = require('undici');
|
|
51
|
+
this.dispatcher = new ProxyAgent(proxyUrl);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async deliver(request) {
|
|
55
|
+
if (request.files.length === 0) {
|
|
56
|
+
throw new Error('HTTP multipart delivery requires at least one file');
|
|
57
|
+
}
|
|
58
|
+
const maxAttempts = Math.max(1, this.config.maxAttempts ?? 3);
|
|
59
|
+
const retryDelayMs = Math.max(0, this.config.retryDelayMs ?? 2000);
|
|
60
|
+
let lastError;
|
|
61
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
62
|
+
try {
|
|
63
|
+
return await this.attempt(request);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
lastError = error;
|
|
67
|
+
logger_1.logger.warn(`HTTP multipart delivery attempt ${attempt}/${maxAttempts} failed`, {
|
|
68
|
+
url: this.config.url,
|
|
69
|
+
error: error instanceof Error ? error.message : String(error),
|
|
70
|
+
files: request.files.length,
|
|
71
|
+
});
|
|
72
|
+
if (attempt < maxAttempts) {
|
|
73
|
+
await new Promise((resolve) => setTimeout(resolve, retryDelayMs * attempt));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
throw new Error(`HTTP multipart delivery failed after ${maxAttempts} attempts: ${lastError instanceof Error ? lastError.message : String(lastError)}`);
|
|
78
|
+
}
|
|
79
|
+
async attempt(request) {
|
|
80
|
+
const fields = this.resolveFields({ ...(this.config.fields ?? {}), ...(request.fields ?? {}) }, request);
|
|
81
|
+
const multipart = await this.createMultipartBody(request.files, fields);
|
|
82
|
+
const headers = {
|
|
83
|
+
...this.resolveHeaders(this.config.headers ?? {}),
|
|
84
|
+
'Content-Type': `multipart/form-data; boundary=${multipart.boundary}`,
|
|
85
|
+
'Content-Length': String(multipart.contentLength),
|
|
86
|
+
};
|
|
87
|
+
const options = {
|
|
88
|
+
method: this.config.method ?? 'POST',
|
|
89
|
+
body: multipart.body,
|
|
90
|
+
headers,
|
|
91
|
+
duplex: 'half',
|
|
92
|
+
};
|
|
93
|
+
if (this.dispatcher)
|
|
94
|
+
options.dispatcher = this.dispatcher;
|
|
95
|
+
const response = await fetch(this.interpolateEnvironment(this.config.url), options);
|
|
96
|
+
const text = await response.text();
|
|
97
|
+
let body = text;
|
|
98
|
+
if (text) {
|
|
99
|
+
try {
|
|
100
|
+
body = JSON.parse(text);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// Non-JSON responses are valid when only HTTP status is configured.
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
this.assertSuccess(response, body);
|
|
107
|
+
logger_1.logger.info('HTTP multipart delivery succeeded', {
|
|
108
|
+
url: this.config.url,
|
|
109
|
+
status: response.status,
|
|
110
|
+
files: request.files.length,
|
|
111
|
+
});
|
|
112
|
+
return { status: response.status, body };
|
|
113
|
+
}
|
|
114
|
+
assertSuccess(response, body) {
|
|
115
|
+
const expectedStatuses = this.config.success?.statuses;
|
|
116
|
+
const statusOk = expectedStatuses
|
|
117
|
+
? expectedStatuses.includes(response.status)
|
|
118
|
+
: response.ok;
|
|
119
|
+
if (!statusOk) {
|
|
120
|
+
throw new Error(`delivery endpoint returned HTTP ${response.status}: ${this.preview(body)}`);
|
|
121
|
+
}
|
|
122
|
+
const jsonPath = this.config.success?.jsonPath;
|
|
123
|
+
if (jsonPath) {
|
|
124
|
+
const actual = jsonPath.split('.').reduce((value, key) => {
|
|
125
|
+
if (!value || typeof value !== 'object')
|
|
126
|
+
return undefined;
|
|
127
|
+
return value[key];
|
|
128
|
+
}, body);
|
|
129
|
+
const expected = Object.prototype.hasOwnProperty.call(this.config.success, 'equals')
|
|
130
|
+
? this.config.success?.equals
|
|
131
|
+
: true;
|
|
132
|
+
if (!Object.is(actual, expected)) {
|
|
133
|
+
throw new Error(`delivery response ${jsonPath} did not equal ${JSON.stringify(expected)}: ${this.preview(body)}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
resolveHeaders(headers) {
|
|
138
|
+
return Object.fromEntries(Object.entries(headers).map(([key, value]) => [key, this.interpolateEnvironment(value)]));
|
|
139
|
+
}
|
|
140
|
+
resolveFields(fields, request) {
|
|
141
|
+
const variables = {
|
|
142
|
+
title: request.context.title,
|
|
143
|
+
pixivId: request.context.pixivId,
|
|
144
|
+
type: request.context.type,
|
|
145
|
+
tag: request.context.tag ?? '',
|
|
146
|
+
};
|
|
147
|
+
return Object.fromEntries(Object.entries(fields).map(([name, value]) => {
|
|
148
|
+
const values = Array.isArray(value) ? value : [value];
|
|
149
|
+
const rendered = values.map((item) => String(item).replace(/\{\{(title|pixivId|type|tag)\}\}/g, (_, key) => variables[key]));
|
|
150
|
+
switch (this.config.arrayFormat ?? 'comma') {
|
|
151
|
+
case 'repeat':
|
|
152
|
+
return [name, rendered];
|
|
153
|
+
case 'json':
|
|
154
|
+
return [name, [JSON.stringify(rendered)]];
|
|
155
|
+
default:
|
|
156
|
+
return [name, [rendered.join(',')]];
|
|
157
|
+
}
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
160
|
+
interpolateEnvironment(value) {
|
|
161
|
+
return value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (_match, name) => {
|
|
162
|
+
const resolved = process.env[name];
|
|
163
|
+
if (resolved === undefined) {
|
|
164
|
+
throw new Error(`Required delivery environment variable is not set: ${name}`);
|
|
165
|
+
}
|
|
166
|
+
return resolved;
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
async createMultipartBody(files, fields) {
|
|
170
|
+
const boundary = `pixivflow-${(0, node_crypto_1.randomUUID)()}`;
|
|
171
|
+
const fileField = this.escapeDispositionValue(this.config.fileField ?? 'files');
|
|
172
|
+
const fileParts = [];
|
|
173
|
+
let contentLength = 0;
|
|
174
|
+
for (const file of files) {
|
|
175
|
+
const filename = this.escapeDispositionValue(path.basename(file));
|
|
176
|
+
const header = Buffer.from(`--${boundary}\r\n` +
|
|
177
|
+
`Content-Disposition: form-data; name="${fileField}"; filename="${filename}"\r\n` +
|
|
178
|
+
'Content-Type: application/octet-stream\r\n\r\n');
|
|
179
|
+
const stat = await fs.promises.stat(file);
|
|
180
|
+
fileParts.push({ header, path: file, size: stat.size });
|
|
181
|
+
contentLength += header.length + stat.size + 2;
|
|
182
|
+
}
|
|
183
|
+
const fieldParts = [];
|
|
184
|
+
for (const [name, values] of Object.entries(fields)) {
|
|
185
|
+
for (const value of values) {
|
|
186
|
+
const part = Buffer.from(`--${boundary}\r\n` +
|
|
187
|
+
`Content-Disposition: form-data; name="${this.escapeDispositionValue(name)}"\r\n\r\n` +
|
|
188
|
+
`${value}\r\n`);
|
|
189
|
+
fieldParts.push(part);
|
|
190
|
+
contentLength += part.length;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const closing = Buffer.from(`--${boundary}--\r\n`);
|
|
194
|
+
contentLength += closing.length;
|
|
195
|
+
const body = node_stream_1.Readable.from((async function* () {
|
|
196
|
+
for (const file of fileParts) {
|
|
197
|
+
yield file.header;
|
|
198
|
+
for await (const chunk of fs.createReadStream(file.path))
|
|
199
|
+
yield chunk;
|
|
200
|
+
yield Buffer.from('\r\n');
|
|
201
|
+
}
|
|
202
|
+
for (const part of fieldParts)
|
|
203
|
+
yield part;
|
|
204
|
+
yield closing;
|
|
205
|
+
})());
|
|
206
|
+
return { boundary, body, contentLength };
|
|
207
|
+
}
|
|
208
|
+
escapeDispositionValue(value) {
|
|
209
|
+
return value.replace(/[\r\n]/g, ' ').replace(/"/g, '%22');
|
|
210
|
+
}
|
|
211
|
+
preview(body) {
|
|
212
|
+
const value = typeof body === 'string' ? body : JSON.stringify(body);
|
|
213
|
+
return value.slice(0, 500);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
exports.HttpMultipartDelivery = HttpMultipartDelivery;
|
|
217
|
+
//# sourceMappingURL=HttpMultipartDelivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpMultipartDelivery.js","sourceRoot":"","sources":["../../src/delivery/HttpMultipartDelivery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { DeliveryFieldValue } from '../config';
|
|
2
|
+
export type DeliveryItemType = 'illustration' | 'novel';
|
|
3
|
+
/** Files produced for one Pixiv work and needed by a delivery provider. */
|
|
4
|
+
export interface DownloadedArtifact {
|
|
5
|
+
pixivId: string;
|
|
6
|
+
type: DeliveryItemType;
|
|
7
|
+
title: string;
|
|
8
|
+
/** Files sent to the configured delivery target. */
|
|
9
|
+
files: string[];
|
|
10
|
+
/** Local sidecars deleted with cache files after successful delivery. */
|
|
11
|
+
cleanupFiles?: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface DeliveryContext {
|
|
14
|
+
title: string;
|
|
15
|
+
pixivId: string;
|
|
16
|
+
type: DeliveryItemType;
|
|
17
|
+
tag?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface DeliveryRequest {
|
|
20
|
+
files: string[];
|
|
21
|
+
fields?: Record<string, DeliveryFieldValue>;
|
|
22
|
+
context: DeliveryContext;
|
|
23
|
+
}
|
|
24
|
+
export interface DeliveryResult {
|
|
25
|
+
status?: number;
|
|
26
|
+
body?: unknown;
|
|
27
|
+
}
|
|
28
|
+
export interface DeliveryProvider {
|
|
29
|
+
deliver(request: DeliveryRequest): Promise<DeliveryResult>;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/delivery/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,OAAO,CAAC;AAExD,2EAA2E;AAC3E,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,yEAAyE;IACzE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,gBAAgB,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC5C,OAAO,EAAE,eAAe,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC5D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/delivery/types.ts"],"names":[],"mappings":""}
|
|
@@ -43,6 +43,7 @@ export declare class DownloadManager implements IDownloadManager {
|
|
|
43
43
|
private readonly novelHandler;
|
|
44
44
|
private cancelled;
|
|
45
45
|
private cancelReason;
|
|
46
|
+
private readonly deliveryOutbox;
|
|
46
47
|
/**
|
|
47
48
|
* Request cooperative cancellation of the current run. In-flight item
|
|
48
49
|
* finishes; no further targets/items are started. runAllTargets() will
|
|
@@ -56,5 +57,6 @@ export declare class DownloadManager implements IDownloadManager {
|
|
|
56
57
|
runAllTargets(): Promise<void>;
|
|
57
58
|
private dispatchTarget;
|
|
58
59
|
private updateProgress;
|
|
60
|
+
private buildProxyUrl;
|
|
59
61
|
}
|
|
60
62
|
//# sourceMappingURL=DownloadManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DownloadManager.d.ts","sourceRoot":"","sources":["../../src/download/DownloadManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAgB,MAAM,WAAW,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"DownloadManager.d.ts","sourceRoot":"","sources":["../../src/download/DownloadManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAgB,MAAM,WAAW,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAgB1D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IAmCpD,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,WAAW;IArC9B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmB;IACpD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAyB;IAChE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAC1C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAwB;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAA4B;IAChE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAGlD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAEhD;;;;OAIG;IACI,MAAM,CAAC,MAAM,GAAE,MAAoB,GAAG,IAAI;IAQ1C,WAAW,IAAI,OAAO;gBAKV,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,SAAS,EACnB,WAAW,EAAE,YAAY;IAqE5C,mBAAmB,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIlF,UAAU;IAIV,aAAa;YAsDZ,cAAc;IAa5B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,aAAa;CAetB"}
|
|
@@ -11,6 +11,9 @@ const DownloadExecutor_1 = require("./exec/DownloadExecutor");
|
|
|
11
11
|
const ErrorRecovery_1 = require("./recovery/ErrorRecovery");
|
|
12
12
|
const DownloadPipeline_1 = require("./pipeline/DownloadPipeline");
|
|
13
13
|
const errors_1 = require("../utils/errors");
|
|
14
|
+
const DeliveryDispatcher_1 = require("../delivery/DeliveryDispatcher");
|
|
15
|
+
const DeliveryOutbox_1 = require("../delivery/DeliveryOutbox");
|
|
16
|
+
const node_path_1 = require("node:path");
|
|
14
17
|
const IllustrationTargetHandler_1 = require("./handlers/IllustrationTargetHandler");
|
|
15
18
|
const NovelTargetHandler_1 = require("./handlers/NovelTargetHandler");
|
|
16
19
|
/**
|
|
@@ -54,6 +57,7 @@ class DownloadManager {
|
|
|
54
57
|
// Cooperative cancellation state (see cancel())
|
|
55
58
|
cancelled = false;
|
|
56
59
|
cancelReason = '';
|
|
60
|
+
deliveryOutbox;
|
|
57
61
|
/**
|
|
58
62
|
* Request cooperative cancellation of the current run. In-flight item
|
|
59
63
|
* finishes; no further targets/items are started. runAllTargets() will
|
|
@@ -99,8 +103,11 @@ class DownloadManager {
|
|
|
99
103
|
recovery: this.errorRecovery,
|
|
100
104
|
isCancelled: () => this.cancelled,
|
|
101
105
|
});
|
|
102
|
-
|
|
103
|
-
|
|
106
|
+
const databasePath = config.storage?.databasePath ?? './data/pixiv-downloader.db';
|
|
107
|
+
const deliveryDispatcher = new DeliveryDispatcher_1.DeliveryDispatcher(config.delivery, this.buildProxyUrl(config.network));
|
|
108
|
+
this.deliveryOutbox = new DeliveryOutbox_1.DeliveryOutbox((0, node_path_1.join)((0, node_path_1.dirname)(databasePath), 'delivery-outbox'), deliveryDispatcher, config.delivery?.deleteAfterDelivery !== false);
|
|
109
|
+
this.illustrationHandler = new IllustrationTargetHandler_1.IllustrationTargetHandler(client, database, this.rankingService, this.illustrationDownloader, this.pipeline, this.deliveryOutbox);
|
|
110
|
+
this.novelHandler = new NovelTargetHandler_1.NovelTargetHandler(client, database, this.rankingService, this.pipeline, this.novelDownloader, this.deliveryOutbox);
|
|
104
111
|
}
|
|
105
112
|
setProgressCallback(callback) {
|
|
106
113
|
this.progressReporter.setCallback(callback);
|
|
@@ -109,6 +116,10 @@ class DownloadManager {
|
|
|
109
116
|
await this.fileService.initialise();
|
|
110
117
|
}
|
|
111
118
|
async runAllTargets() {
|
|
119
|
+
const pending = await this.deliveryOutbox.retryPending();
|
|
120
|
+
if (pending.succeeded > 0 || pending.failed > 0) {
|
|
121
|
+
logger_1.logger.info('Processed pending deliveries', { ...pending });
|
|
122
|
+
}
|
|
112
123
|
const totalTargets = this.config.targets.length;
|
|
113
124
|
if (totalTargets === 0) {
|
|
114
125
|
this.progressReporter.complete(0, '所有目标处理完成');
|
|
@@ -163,6 +174,23 @@ class DownloadManager {
|
|
|
163
174
|
updateProgress(current, total, message) {
|
|
164
175
|
this.progressReporter.update(current, total, message);
|
|
165
176
|
}
|
|
177
|
+
buildProxyUrl(network) {
|
|
178
|
+
const proxy = network?.proxy;
|
|
179
|
+
if (!proxy?.enabled) {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
const protocol = proxy.protocol ?? 'http';
|
|
183
|
+
if (protocol !== 'http' && protocol !== 'https') {
|
|
184
|
+
logger_1.logger.warn(`HTTP multipart delivery does not support ${protocol} proxy through undici; delivering directly`);
|
|
185
|
+
return undefined;
|
|
186
|
+
}
|
|
187
|
+
const url = new URL(`${protocol}://${proxy.host}:${proxy.port}`);
|
|
188
|
+
if (proxy.username)
|
|
189
|
+
url.username = proxy.username;
|
|
190
|
+
if (proxy.password)
|
|
191
|
+
url.password = proxy.password;
|
|
192
|
+
return url.toString();
|
|
193
|
+
}
|
|
166
194
|
}
|
|
167
195
|
exports.DownloadManager = DownloadManager;
|
|
168
196
|
//# sourceMappingURL=DownloadManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DownloadManager.js","sourceRoot":"","sources":["../../src/download/DownloadManager.ts"],"names":[],"mappings":";;;AACA,sCAAmC;AAKnC,qDAAkD;AAClD,qEAAkE;AAClE,uDAAoD;AACpD,gEAA6D;AAC7D,4DAAyD;AACzD,8DAA2D;AAC3D,4DAAuF;AACvF,kEAA+D;AAC/D,4CAA0D;AAC1D,oFAAiF;AACjF,sEAAmE;AAEnE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAa,eAAe;
|
|
1
|
+
{"version":3,"file":"DownloadManager.js","sourceRoot":"","sources":["../../src/download/DownloadManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { IPixivClient } from '../interfaces/IPixivClient';
|
|
|
2
2
|
import { IDatabase } from '../interfaces/IDatabase';
|
|
3
3
|
import { IFileService } from '../interfaces/IFileService';
|
|
4
4
|
import { PixivIllust } from '../pixiv/PixivClient';
|
|
5
|
+
import { DownloadedArtifact } from '../delivery/types';
|
|
5
6
|
/**
|
|
6
7
|
* Service for downloading illustrations
|
|
7
8
|
*/
|
|
@@ -15,7 +16,7 @@ export declare class IllustrationDownloader {
|
|
|
15
16
|
/**
|
|
16
17
|
* Download an illustration
|
|
17
18
|
*/
|
|
18
|
-
downloadIllustration(illust: PixivIllust, tag: string): Promise<
|
|
19
|
+
downloadIllustration(illust: PixivIllust, tag: string): Promise<DownloadedArtifact | null>;
|
|
19
20
|
/**
|
|
20
21
|
* Download an ugoira (animation) work: fetch metadata, download the frame
|
|
21
22
|
* zip (original size when available), and save the frame-delay sidecar so
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IllustrationDownloader.d.ts","sourceRoot":"","sources":["../../src/download/IllustrationDownloader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAmB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"IllustrationDownloader.d.ts","sourceRoot":"","sources":["../../src/download/IllustrationDownloader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE1D,OAAO,EAAE,WAAW,EAAmB,MAAM,sBAAsB,CAAC;AAMpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;GAEG;AACH,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAJX,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,SAAS,EACnB,WAAW,EAAE,YAAY,EACzB,mBAAmB,EAAE,MAAM,EAC3B,WAAW,EAAE,MAAM;IAGtC;;OAEG;IACG,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAwKhG;;;;OAIG;YACW,cAAc;IA8F5B;;OAEG;YACW,6BAA6B;IAgC3C;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAkB5B;;OAEG;IACH,OAAO,CAAC,eAAe;IAiBvB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAQzB"}
|