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
package/README.md
CHANGED
|
@@ -54,6 +54,33 @@ pixivflow download
|
|
|
54
54
|
pixivflow scheduler # 按 cron 配置长期挂机自动收集
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
### 单进程多计划与配置热重载
|
|
58
|
+
|
|
59
|
+
`schedules[]` 可以为不同 target 组设置各自的 Cron。所有计划由一个 Node
|
|
60
|
+
进程托管,共享 Pixiv 客户端、SQLite 与文件服务;执行阶段使用有界串行队列,
|
|
61
|
+
适合 512 MiB 小内存机器。配置文件默认被监听,SSH/同步工具替换文件后会先完整
|
|
62
|
+
校验,再一次性替换全部调度项;无效 JSON、错误 Cron 或未知 target id 不会破坏
|
|
63
|
+
当前运行中的计划。正在执行的任务继续使用旧快照,下一次任务使用新快照。
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"scheduler": { "enabled": false, "cron": "0 3 * * *" },
|
|
68
|
+
"schedules": [
|
|
69
|
+
{ "id": "bot1", "enabled": true, "cron": "10 5 * * *", "targetIds": ["bot1-art", "bot1-novel"] },
|
|
70
|
+
{ "id": "bot2", "enabled": true, "cron": "30 5 * * *", "targetIds": ["bot2-art", "bot2-novel"] }
|
|
71
|
+
],
|
|
72
|
+
"targets": [
|
|
73
|
+
{ "id": "bot1-art", "type": "illustration", "mode": "ranking", "rankingDate": "YESTERDAY" },
|
|
74
|
+
{ "id": "bot1-novel", "type": "novel", "mode": "ranking", "rankingDate": "YESTERDAY" }
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
旧的单 `scheduler` 配置继续兼容。`pixiv`、`network`、`storage` 涉及长生命周期
|
|
80
|
+
连接或路径,修改后需要重启;`schedules`、`targets`、`delivery`、`download` 可以
|
|
81
|
+
热重载。完整双 Bot 缓存投递模板见
|
|
82
|
+
[`config/fly-two-bots.example.json`](config/fly-two-bots.example.json)。
|
|
83
|
+
|
|
57
84
|
## 下载目标
|
|
58
85
|
|
|
59
86
|
在配置文件的 `targets` 中定义要收集的内容,多个条件可以组合:
|
|
@@ -69,6 +96,51 @@ pixivflow scheduler # 按 cron 配置长期挂机自动收集
|
|
|
69
96
|
已下载的作品由 SQLite 数据库记录并自动跳过;文件存在但缺少记录时会自动补齐,
|
|
70
97
|
两者互不冲突。
|
|
71
98
|
|
|
99
|
+
### 本地留存与缓存交付
|
|
100
|
+
|
|
101
|
+
每个 target 可选择 `storageMode: "persistent"`(默认,本地永久留存)或
|
|
102
|
+
`storageMode: "cache"`(下载后交给命名 delivery target,成功才删除本地文件)。
|
|
103
|
+
交付层不绑定具体服务;下面只是把一个 HTTP multipart 投稿接口翻译成配置:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"delivery": {
|
|
108
|
+
"targets": {
|
|
109
|
+
"tg-example": {
|
|
110
|
+
"type": "httpMultipart",
|
|
111
|
+
"url": "https://telesubmit-multi-bot.fly.dev/api/bot1/v1/submissions",
|
|
112
|
+
"headers": { "Authorization": "Bearer ${TG_SUBMIT_TOKEN}" },
|
|
113
|
+
"fileField": "files",
|
|
114
|
+
"fields": { "title": "{{title}}" },
|
|
115
|
+
"success": { "statuses": [201], "jsonPath": "ok", "equals": true },
|
|
116
|
+
"arrayFormat": "comma",
|
|
117
|
+
"maxAttempts": 3,
|
|
118
|
+
"retryDelayMs": 2000
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"deleteAfterDelivery": true
|
|
122
|
+
},
|
|
123
|
+
"targets": [
|
|
124
|
+
{ "type": "illustration", "tag": "收藏", "storageMode": "persistent" },
|
|
125
|
+
{
|
|
126
|
+
"type": "illustration",
|
|
127
|
+
"tag": "更新",
|
|
128
|
+
"storageMode": "cache",
|
|
129
|
+
"delivery": {
|
|
130
|
+
"target": "tg-example",
|
|
131
|
+
"fields": { "tags": ["公告", "更新"], "anonymous": false }
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
headers 和 URL 支持任意 `${ENV_NAME}` 环境变量插值。交付失败时文件和
|
|
139
|
+
outbox 清单保留在 SQLite 数据库同级的 `delivery-outbox/`;下一次运行会先
|
|
140
|
+
自动重试,成功后再清理。
|
|
141
|
+
对上面的 TG 示例,可把 `/gen_token` 得到的 `tp_...` 放入
|
|
142
|
+
`TG_SUBMIT_TOKEN` 环境变量;这只是示例服务自己的认证流程。
|
|
143
|
+
|
|
72
144
|
交互式配置向导:`pixivflow setup`。
|
|
73
145
|
|
|
74
146
|
## 常用命令
|
package/README_EN.md
CHANGED
|
@@ -56,6 +56,21 @@ pixivflow download
|
|
|
56
56
|
pixivflow scheduler # long-running cron collection
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
### Multiple schedules and atomic hot reload
|
|
60
|
+
|
|
61
|
+
`schedules[]` hosts independently timed target groups in one Node process.
|
|
62
|
+
Plans share Pixiv authentication, SQLite, and file services, while a bounded
|
|
63
|
+
serial queue prevents overlapping downloads from producing memory spikes.
|
|
64
|
+
The active config is watched by default: replace it over SSH and PixivFlow
|
|
65
|
+
fully validates the new snapshot before swapping the entire cron table. An
|
|
66
|
+
invalid edit leaves the previous schedules running. In-flight work finishes
|
|
67
|
+
on its old snapshot; the next run sees the new one.
|
|
68
|
+
|
|
69
|
+
Legacy single-`scheduler` configs remain supported. `schedules`, `targets`,
|
|
70
|
+
`delivery`, and `download` are hot-reloadable; changes to `pixiv`, `network`,
|
|
71
|
+
or `storage` require a process restart. See the ready-to-edit
|
|
72
|
+
[`config/fly-two-bots.example.json`](config/fly-two-bots.example.json) template.
|
|
73
|
+
|
|
59
74
|
## Download targets
|
|
60
75
|
|
|
61
76
|
Define what to collect in the `targets` section of your config. Conditions
|
|
@@ -73,6 +88,46 @@ Downloaded items are tracked in a SQLite database and skipped automatically;
|
|
|
73
88
|
files that exist without a database record are reconciled, so the two never
|
|
74
89
|
conflict.
|
|
75
90
|
|
|
91
|
+
### Persistent and cache delivery modes
|
|
92
|
+
|
|
93
|
+
Each target can use `storageMode: "persistent"` (the default, keep files) or
|
|
94
|
+
`storageMode: "cache"` (send files to a named delivery target and delete them
|
|
95
|
+
only after success). The delivery layer is service-independent; this example
|
|
96
|
+
merely translates an HTTP multipart submission API into configuration:
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"delivery": {
|
|
101
|
+
"targets": {
|
|
102
|
+
"sharing-api": {
|
|
103
|
+
"type": "httpMultipart",
|
|
104
|
+
"url": "https://example.test/submissions",
|
|
105
|
+
"headers": { "Authorization": "Bearer ${SHARING_TOKEN}" },
|
|
106
|
+
"fileField": "files",
|
|
107
|
+
"fields": { "title": "{{title}}" },
|
|
108
|
+
"success": { "statuses": [201], "jsonPath": "ok", "equals": true }
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"targets": [
|
|
113
|
+
{ "type": "illustration", "tag": "archive", "storageMode": "persistent" },
|
|
114
|
+
{
|
|
115
|
+
"type": "illustration",
|
|
116
|
+
"tag": "updates",
|
|
117
|
+
"storageMode": "cache",
|
|
118
|
+
"delivery": {
|
|
119
|
+
"target": "sharing-api",
|
|
120
|
+
"fields": { "tags": ["announcement", "update"], "anonymous": false }
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Headers and URLs accept arbitrary `${ENV_NAME}` interpolation. Failed delivery
|
|
128
|
+
keeps both files and the durable outbox manifest beside the SQLite database;
|
|
129
|
+
the next run retries them before processing new targets.
|
|
130
|
+
|
|
76
131
|
Interactive configuration wizard: `pixivflow setup`.
|
|
77
132
|
|
|
78
133
|
## Common commands
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
{
|
|
2
|
+
"logLevel": "info",
|
|
3
|
+
"pixiv": {
|
|
4
|
+
"clientId": "MOBrBDS8blbauoSck0ZfDbtuzpyT",
|
|
5
|
+
"clientSecret": "lsACyCD94FhDUtGTXi3QzcFE2uU1hqtDaKeqrdwj",
|
|
6
|
+
"deviceToken": "pixiv",
|
|
7
|
+
"refreshToken": "YOUR_REFRESH_TOKEN",
|
|
8
|
+
"userAgent": "PixivAndroidApp/5.0.234 (Android 11; Pixel 6)"
|
|
9
|
+
},
|
|
10
|
+
"network": {
|
|
11
|
+
"timeoutMs": 30000,
|
|
12
|
+
"retries": 3,
|
|
13
|
+
"retryDelay": 2000
|
|
14
|
+
},
|
|
15
|
+
"storage": {
|
|
16
|
+
"databasePath": "./pixivflow.db",
|
|
17
|
+
"downloadDirectory": "./cache",
|
|
18
|
+
"illustrationDirectory": "./cache/illustrations",
|
|
19
|
+
"novelDirectory": "./cache/novels"
|
|
20
|
+
},
|
|
21
|
+
"scheduler": {
|
|
22
|
+
"enabled": false,
|
|
23
|
+
"cron": "0 3 * * *",
|
|
24
|
+
"timezone": "Asia/Shanghai"
|
|
25
|
+
},
|
|
26
|
+
"schedules": [
|
|
27
|
+
{
|
|
28
|
+
"id": "bot1-daily",
|
|
29
|
+
"name": "Bot 1 daily ranking",
|
|
30
|
+
"enabled": false,
|
|
31
|
+
"cron": "10 5 * * *",
|
|
32
|
+
"timezone": "Asia/Shanghai",
|
|
33
|
+
"targetIds": [
|
|
34
|
+
"bot1-illust-tag-a",
|
|
35
|
+
"bot1-novel-tag-a",
|
|
36
|
+
"bot1-illust-tag-b",
|
|
37
|
+
"bot1-novel-tag-b"
|
|
38
|
+
],
|
|
39
|
+
"timeout": 1200000,
|
|
40
|
+
"maxConsecutiveFailures": 5,
|
|
41
|
+
"failureRetryDelay": 30000
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"id": "bot2-daily",
|
|
45
|
+
"name": "Bot 2 daily ranking",
|
|
46
|
+
"enabled": false,
|
|
47
|
+
"cron": "30 5 * * *",
|
|
48
|
+
"timezone": "Asia/Shanghai",
|
|
49
|
+
"targetIds": [
|
|
50
|
+
"bot2-illust-tag-c",
|
|
51
|
+
"bot2-novel-tag-c",
|
|
52
|
+
"bot2-illust-tag-d",
|
|
53
|
+
"bot2-novel-tag-d"
|
|
54
|
+
],
|
|
55
|
+
"timeout": 1200000,
|
|
56
|
+
"maxConsecutiveFailures": 5,
|
|
57
|
+
"failureRetryDelay": 30000
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"schedulerRuntime": {
|
|
61
|
+
"watchConfig": true,
|
|
62
|
+
"reloadDebounceMs": 500,
|
|
63
|
+
"queueLimit": 2
|
|
64
|
+
},
|
|
65
|
+
"download": {
|
|
66
|
+
"concurrency": 1,
|
|
67
|
+
"requestDelay": 1000,
|
|
68
|
+
"dynamicConcurrency": false,
|
|
69
|
+
"minConcurrency": 1,
|
|
70
|
+
"maxRetries": 3,
|
|
71
|
+
"retryDelay": 3000,
|
|
72
|
+
"timeout": 90000
|
|
73
|
+
},
|
|
74
|
+
"delivery": {
|
|
75
|
+
"targets": {
|
|
76
|
+
"telepost-bot1": {
|
|
77
|
+
"type": "httpMultipart",
|
|
78
|
+
"url": "http://127.0.0.1:8080/api/bot1/v1/submissions",
|
|
79
|
+
"headers": {
|
|
80
|
+
"Authorization": "Bearer ${TELEPOST_BOT1_SUBMIT_TOKEN}"
|
|
81
|
+
},
|
|
82
|
+
"fileField": "files",
|
|
83
|
+
"fields": {
|
|
84
|
+
"title": "{{title}}",
|
|
85
|
+
"tags": [
|
|
86
|
+
"Pixiv",
|
|
87
|
+
"{{tag}}"
|
|
88
|
+
],
|
|
89
|
+
"note": "Pixiv ID: {{pixivId}}",
|
|
90
|
+
"anonymous": true,
|
|
91
|
+
"idempotency_key": "pixiv:bot1:{{type}}:{{pixivId}}"
|
|
92
|
+
},
|
|
93
|
+
"success": {
|
|
94
|
+
"statuses": [
|
|
95
|
+
201
|
|
96
|
+
],
|
|
97
|
+
"jsonPath": "ok",
|
|
98
|
+
"equals": true
|
|
99
|
+
},
|
|
100
|
+
"maxAttempts": 3,
|
|
101
|
+
"retryDelayMs": 3000
|
|
102
|
+
},
|
|
103
|
+
"telepost-bot2": {
|
|
104
|
+
"type": "httpMultipart",
|
|
105
|
+
"url": "http://127.0.0.1:8080/api/bot2/v1/submissions",
|
|
106
|
+
"headers": {
|
|
107
|
+
"Authorization": "Bearer ${TELEPOST_BOT2_SUBMIT_TOKEN}"
|
|
108
|
+
},
|
|
109
|
+
"fileField": "files",
|
|
110
|
+
"fields": {
|
|
111
|
+
"title": "{{title}}",
|
|
112
|
+
"tags": [
|
|
113
|
+
"Pixiv",
|
|
114
|
+
"{{tag}}"
|
|
115
|
+
],
|
|
116
|
+
"note": "Pixiv ID: {{pixivId}}",
|
|
117
|
+
"anonymous": true,
|
|
118
|
+
"idempotency_key": "pixiv:bot2:{{type}}:{{pixivId}}"
|
|
119
|
+
},
|
|
120
|
+
"success": {
|
|
121
|
+
"statuses": [
|
|
122
|
+
201
|
|
123
|
+
],
|
|
124
|
+
"jsonPath": "ok",
|
|
125
|
+
"equals": true
|
|
126
|
+
},
|
|
127
|
+
"maxAttempts": 3,
|
|
128
|
+
"retryDelayMs": 3000
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"deleteAfterDelivery": true
|
|
132
|
+
},
|
|
133
|
+
"targets": [
|
|
134
|
+
{
|
|
135
|
+
"id": "bot1-illust-tag-a",
|
|
136
|
+
"type": "illustration",
|
|
137
|
+
"mode": "ranking",
|
|
138
|
+
"rankingMode": "day",
|
|
139
|
+
"rankingDate": "YESTERDAY",
|
|
140
|
+
"filterTag": "TAG_A",
|
|
141
|
+
"limit": 1,
|
|
142
|
+
"storageMode": "cache",
|
|
143
|
+
"delivery": {
|
|
144
|
+
"target": "telepost-bot1"
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"id": "bot1-novel-tag-a",
|
|
149
|
+
"type": "novel",
|
|
150
|
+
"mode": "ranking",
|
|
151
|
+
"rankingMode": "day",
|
|
152
|
+
"rankingDate": "YESTERDAY",
|
|
153
|
+
"filterTag": "TAG_A",
|
|
154
|
+
"limit": 1,
|
|
155
|
+
"storageMode": "cache",
|
|
156
|
+
"delivery": {
|
|
157
|
+
"target": "telepost-bot1"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"id": "bot1-illust-tag-b",
|
|
162
|
+
"type": "illustration",
|
|
163
|
+
"mode": "ranking",
|
|
164
|
+
"rankingMode": "day",
|
|
165
|
+
"rankingDate": "YESTERDAY",
|
|
166
|
+
"filterTag": "TAG_B",
|
|
167
|
+
"limit": 1,
|
|
168
|
+
"storageMode": "cache",
|
|
169
|
+
"delivery": {
|
|
170
|
+
"target": "telepost-bot1"
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
"id": "bot1-novel-tag-b",
|
|
175
|
+
"type": "novel",
|
|
176
|
+
"mode": "ranking",
|
|
177
|
+
"rankingMode": "day",
|
|
178
|
+
"rankingDate": "YESTERDAY",
|
|
179
|
+
"filterTag": "TAG_B",
|
|
180
|
+
"limit": 1,
|
|
181
|
+
"storageMode": "cache",
|
|
182
|
+
"delivery": {
|
|
183
|
+
"target": "telepost-bot1"
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"id": "bot2-illust-tag-c",
|
|
188
|
+
"type": "illustration",
|
|
189
|
+
"mode": "ranking",
|
|
190
|
+
"rankingMode": "day",
|
|
191
|
+
"rankingDate": "YESTERDAY",
|
|
192
|
+
"filterTag": "TAG_C",
|
|
193
|
+
"limit": 1,
|
|
194
|
+
"storageMode": "cache",
|
|
195
|
+
"delivery": {
|
|
196
|
+
"target": "telepost-bot2"
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"id": "bot2-novel-tag-c",
|
|
201
|
+
"type": "novel",
|
|
202
|
+
"mode": "ranking",
|
|
203
|
+
"rankingMode": "day",
|
|
204
|
+
"rankingDate": "YESTERDAY",
|
|
205
|
+
"filterTag": "TAG_C",
|
|
206
|
+
"limit": 1,
|
|
207
|
+
"storageMode": "cache",
|
|
208
|
+
"delivery": {
|
|
209
|
+
"target": "telepost-bot2"
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"id": "bot2-illust-tag-d",
|
|
214
|
+
"type": "illustration",
|
|
215
|
+
"mode": "ranking",
|
|
216
|
+
"rankingMode": "day",
|
|
217
|
+
"rankingDate": "YESTERDAY",
|
|
218
|
+
"filterTag": "TAG_D",
|
|
219
|
+
"limit": 1,
|
|
220
|
+
"storageMode": "cache",
|
|
221
|
+
"delivery": {
|
|
222
|
+
"target": "telepost-bot2"
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"id": "bot2-novel-tag-d",
|
|
227
|
+
"type": "novel",
|
|
228
|
+
"mode": "ranking",
|
|
229
|
+
"rankingMode": "day",
|
|
230
|
+
"rankingDate": "YESTERDAY",
|
|
231
|
+
"filterTag": "TAG_D",
|
|
232
|
+
"limit": 1,
|
|
233
|
+
"storageMode": "cache",
|
|
234
|
+
"delivery": {
|
|
235
|
+
"target": "telepost-bot2"
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
],
|
|
239
|
+
"initialDelay": 0
|
|
240
|
+
}
|
|
@@ -17,6 +17,7 @@ export declare class SchedulerCommand extends BaseCommand {
|
|
|
17
17
|
longRunning: boolean;
|
|
18
18
|
};
|
|
19
19
|
execute(context: CommandContext, args: CommandArgs): Promise<CommandResult>;
|
|
20
|
+
private getImmutableFingerprint;
|
|
20
21
|
getUsage(): string;
|
|
21
22
|
}
|
|
22
23
|
//# sourceMappingURL=SchedulerCommand.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchedulerCommand.d.ts","sourceRoot":"","sources":["../../src/commands/SchedulerCommand.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"SchedulerCommand.d.ts","sourceRoot":"","sources":["../../src/commands/SchedulerCommand.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAYrE;;GAEG;AACH,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,CAAC,IAAI,eAAe;IAC5B,QAAQ,CAAC,WAAW,oDAAoD;IACxE,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAgB;IAC1C,QAAQ,CAAC,QAAQ;;;;MAIf;IAEI,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC;IAmIjF,OAAO,CAAC,uBAAuB;IAQ/B,QAAQ,IAAI,MAAM;CAYnB"}
|
|
@@ -12,8 +12,10 @@ const AuthClient_1 = require("../pixiv/AuthClient");
|
|
|
12
12
|
const PixivClient_1 = require("../pixiv/PixivClient");
|
|
13
13
|
const FileService_1 = require("../download/FileService");
|
|
14
14
|
const DownloadManager_1 = require("../download/DownloadManager");
|
|
15
|
-
const Scheduler_1 = require("../scheduler/Scheduler");
|
|
16
15
|
const token_maintenance_1 = require("../utils/token-maintenance");
|
|
16
|
+
const MultiScheduleManager_1 = require("../scheduler/MultiScheduleManager");
|
|
17
|
+
const schedules_1 = require("../scheduler/schedules");
|
|
18
|
+
const placeholders_1 = require("../config/placeholders");
|
|
17
19
|
/**
|
|
18
20
|
* Scheduler command - Start scheduler (default if enabled in config)
|
|
19
21
|
*/
|
|
@@ -28,45 +30,87 @@ class SchedulerCommand extends Command_1.BaseCommand {
|
|
|
28
30
|
};
|
|
29
31
|
async execute(context, args) {
|
|
30
32
|
try {
|
|
31
|
-
const configPath = (0, config_1.getConfigPath)();
|
|
32
|
-
|
|
33
|
+
const configPath = (0, config_1.getConfigPath)(args.options.config);
|
|
34
|
+
// Keep TODAY/YESTERDAY placeholders intact. They are resolved afresh for
|
|
35
|
+
// every plan execution, not frozen at daemon startup.
|
|
36
|
+
const config = (0, config_1.loadConfig)(configPath, false, false);
|
|
33
37
|
const database = new Database_1.Database(config.storage.databasePath);
|
|
34
38
|
database.migrate();
|
|
35
39
|
const auth = new AuthClient_1.PixivAuth(config.pixiv, config.network, database, configPath);
|
|
36
40
|
const pixivClient = new PixivClient_1.PixivClient(auth, config);
|
|
37
41
|
const fileService = new FileService_1.FileService(config.storage);
|
|
38
|
-
|
|
39
|
-
await downloadManager.initialise();
|
|
42
|
+
await fileService.initialise();
|
|
40
43
|
// Start token maintenance service for automatic token refresh
|
|
41
44
|
const tokenMaintenance = (0, token_maintenance_1.createTokenMaintenanceService)(auth, config.pixiv, config.network, config);
|
|
42
45
|
if (tokenMaintenance) {
|
|
43
46
|
tokenMaintenance.start();
|
|
44
47
|
}
|
|
45
|
-
|
|
48
|
+
let activeDownloadManager = null;
|
|
49
|
+
const immutableFingerprint = this.getImmutableFingerprint(config);
|
|
50
|
+
const runJob = async (snapshot, schedule) => {
|
|
51
|
+
const runtimeConfig = (0, placeholders_1.processConfigPlaceholders)(snapshot);
|
|
52
|
+
const targets = (0, schedules_1.selectScheduleTargets)(runtimeConfig.targets, schedule);
|
|
53
|
+
const scopedConfig = { ...runtimeConfig, targets };
|
|
54
|
+
if (targets.length === 0) {
|
|
55
|
+
context.logger.warn('Scheduled plan has no selected targets; skipping', {
|
|
56
|
+
scheduleId: schedule.id,
|
|
57
|
+
targetIds: schedule.targetIds,
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const downloadManager = new DownloadManager_1.DownloadManager(scopedConfig, pixivClient, database, fileService);
|
|
62
|
+
activeDownloadManager = downloadManager;
|
|
63
|
+
await downloadManager.initialise();
|
|
46
64
|
// Apply initial delay if configured
|
|
47
|
-
if (
|
|
48
|
-
context.logger.info(`Waiting ${
|
|
49
|
-
|
|
65
|
+
if (runtimeConfig.initialDelay && runtimeConfig.initialDelay > 0) {
|
|
66
|
+
context.logger.info(`Waiting ${runtimeConfig.initialDelay}ms before starting download...`, {
|
|
67
|
+
scheduleId: schedule.id,
|
|
68
|
+
});
|
|
69
|
+
await new Promise(resolve => setTimeout(resolve, runtimeConfig.initialDelay));
|
|
50
70
|
}
|
|
51
71
|
context.logger.info('='.repeat(60));
|
|
52
|
-
context.logger.info('Starting scheduled Pixiv download
|
|
72
|
+
context.logger.info('Starting scheduled Pixiv download plan', {
|
|
73
|
+
scheduleId: schedule.id,
|
|
74
|
+
targets: targets.map(target => target.id ?? target.tag ?? target.filterTag ?? target.type),
|
|
75
|
+
});
|
|
53
76
|
context.logger.info('='.repeat(60));
|
|
54
77
|
const startTime = Date.now();
|
|
55
|
-
|
|
78
|
+
try {
|
|
79
|
+
await downloadManager.runAllTargets();
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
if (activeDownloadManager === downloadManager)
|
|
83
|
+
activeDownloadManager = null;
|
|
84
|
+
}
|
|
56
85
|
const duration = Math.round((Date.now() - startTime) / 1000);
|
|
57
86
|
context.logger.info('='.repeat(60));
|
|
58
|
-
context.logger.info(`Scheduled download
|
|
87
|
+
context.logger.info(`Scheduled download plan finished (took ${duration}s)`, {
|
|
88
|
+
scheduleId: schedule.id,
|
|
89
|
+
});
|
|
59
90
|
context.logger.info('='.repeat(60));
|
|
60
91
|
};
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
92
|
+
const manager = new MultiScheduleManager_1.MultiScheduleManager({
|
|
93
|
+
configPath,
|
|
94
|
+
loadConfig: () => {
|
|
95
|
+
const next = (0, config_1.loadConfig)(configPath, false, false);
|
|
96
|
+
if (this.getImmutableFingerprint(next) !== immutableFingerprint) {
|
|
97
|
+
throw new Error('pixiv/network/storage changes require a process restart; schedules, targets, delivery and download settings can be hot-reloaded');
|
|
98
|
+
}
|
|
99
|
+
return next;
|
|
100
|
+
},
|
|
101
|
+
execute: runJob,
|
|
102
|
+
database,
|
|
103
|
+
telemetry: {
|
|
104
|
+
beginRun: () => database.getOverviewStats().totalDownloads,
|
|
105
|
+
endRun: () => database.getOverviewStats().totalDownloads,
|
|
106
|
+
requestCancel: (reason) => activeDownloadManager?.cancel(reason),
|
|
107
|
+
},
|
|
65
108
|
});
|
|
66
|
-
|
|
109
|
+
const status = manager.start(config);
|
|
67
110
|
const cleanup = () => {
|
|
68
111
|
context.logger.info('Shutting down PixivFlow');
|
|
69
|
-
|
|
112
|
+
manager.stop();
|
|
113
|
+
activeDownloadManager?.cancel('process shutdown');
|
|
70
114
|
if (tokenMaintenance) {
|
|
71
115
|
tokenMaintenance.stop();
|
|
72
116
|
}
|
|
@@ -75,9 +119,14 @@ class SchedulerCommand extends Command_1.BaseCommand {
|
|
|
75
119
|
};
|
|
76
120
|
process.on('SIGINT', cleanup);
|
|
77
121
|
process.on('SIGTERM', cleanup);
|
|
122
|
+
process.on('SIGHUP', () => {
|
|
123
|
+
context.logger.info('Received SIGHUP; reloading scheduler configuration');
|
|
124
|
+
manager.reload();
|
|
125
|
+
});
|
|
78
126
|
// Keep process alive
|
|
79
127
|
return this.success('Scheduler started', {
|
|
80
|
-
message: '
|
|
128
|
+
message: 'Multi-plan scheduler is running with atomic config hot reload. Press Ctrl+C to stop.',
|
|
129
|
+
schedules: status.schedules,
|
|
81
130
|
});
|
|
82
131
|
}
|
|
83
132
|
catch (error) {
|
|
@@ -87,14 +136,21 @@ class SchedulerCommand extends Command_1.BaseCommand {
|
|
|
87
136
|
return this.failure(error instanceof Error ? error.message : String(error), { error });
|
|
88
137
|
}
|
|
89
138
|
}
|
|
139
|
+
getImmutableFingerprint(config) {
|
|
140
|
+
return JSON.stringify({
|
|
141
|
+
pixiv: config.pixiv,
|
|
142
|
+
network: config.network,
|
|
143
|
+
storage: config.storage,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
90
146
|
getUsage() {
|
|
91
147
|
return `scheduler
|
|
92
148
|
|
|
93
149
|
Start the scheduler to run download jobs periodically according to config.
|
|
94
150
|
|
|
95
|
-
The scheduler
|
|
96
|
-
|
|
97
|
-
|
|
151
|
+
The scheduler hosts all enabled schedules in one process. Valid changes to
|
|
152
|
+
schedules, targets, delivery and download settings are loaded automatically.
|
|
153
|
+
Pixiv credentials, network and storage changes require a restart.
|
|
98
154
|
|
|
99
155
|
Examples:
|
|
100
156
|
pixivflow scheduler # Start scheduler`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SchedulerCommand.js","sourceRoot":"","sources":["../../src/commands/SchedulerCommand.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,uCAAwC;AACxC,yCAA6C;AAE7C,
|
|
1
|
+
{"version":3,"file":"SchedulerCommand.js","sourceRoot":"","sources":["../../src/commands/SchedulerCommand.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,11 @@ export declare const DEFAULT_CONFIG: {
|
|
|
18
18
|
readonly cron: "0 3 * * *";
|
|
19
19
|
readonly timezone: "Asia/Shanghai";
|
|
20
20
|
};
|
|
21
|
+
readonly schedulerRuntime: {
|
|
22
|
+
readonly watchConfig: true;
|
|
23
|
+
readonly reloadDebounceMs: 500;
|
|
24
|
+
readonly queueLimit: 8;
|
|
25
|
+
};
|
|
21
26
|
readonly download: {
|
|
22
27
|
readonly concurrency: 3;
|
|
23
28
|
readonly requestDelay: 500;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C,eAAO,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BjB,CAAC;AAEX;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,gBAAgB,CAyBxD"}
|
package/dist/config/defaults.js
CHANGED
|
@@ -21,6 +21,11 @@ exports.DEFAULT_CONFIG = {
|
|
|
21
21
|
cron: '0 3 * * *',
|
|
22
22
|
timezone: 'Asia/Shanghai',
|
|
23
23
|
},
|
|
24
|
+
schedulerRuntime: {
|
|
25
|
+
watchConfig: true,
|
|
26
|
+
reloadDebounceMs: 500,
|
|
27
|
+
queueLimit: 8,
|
|
28
|
+
},
|
|
24
29
|
download: {
|
|
25
30
|
concurrency: 3,
|
|
26
31
|
requestDelay: 500,
|
|
@@ -48,6 +53,7 @@ function generateDefaultConfig() {
|
|
|
48
53
|
network: exports.DEFAULT_CONFIG.network,
|
|
49
54
|
storage: exports.DEFAULT_CONFIG.storage,
|
|
50
55
|
scheduler: exports.DEFAULT_CONFIG.scheduler,
|
|
56
|
+
schedulerRuntime: exports.DEFAULT_CONFIG.schedulerRuntime,
|
|
51
57
|
download: exports.DEFAULT_CONFIG.download,
|
|
52
58
|
targets: [
|
|
53
59
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":";AAAA;;GAEG;;;
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAwCH,sDAyBC;AA7DY,QAAA,cAAc,GAAG;IAC5B,QAAQ,EAAE,MAAe;IACzB,OAAO,EAAE;QACP,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,CAAC;QACV,UAAU,EAAE,IAAI;KACjB;IACD,OAAO,EAAE;QACP,YAAY,EAAE,4BAA4B;QAC1C,iBAAiB,EAAE,aAAa;KACjC;IACD,SAAS,EAAE;QACT,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,eAAe;KAC1B;IACD,gBAAgB,EAAE;QAChB,WAAW,EAAE,IAAI;QACjB,gBAAgB,EAAE,GAAG;QACrB,UAAU,EAAE,CAAC;KACd;IACD,QAAQ,EAAE;QACR,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,GAAG;QACjB,kBAAkB,EAAE,IAAI;QACxB,cAAc,EAAE,CAAC;QACjB,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE,KAAK;KACf;IACD,YAAY,EAAE,CAAC;CACP,CAAC;AAEX;;GAEG;AACH,SAAgB,qBAAqB;IACnC,OAAO;QACL,QAAQ,EAAE,sBAAc,CAAC,QAAQ;QACjC,KAAK,EAAE;YACL,QAAQ,EAAE,8BAA8B;YACxC,YAAY,EAAE,0CAA0C;YACxD,WAAW,EAAE,OAAO;YACpB,YAAY,EAAE,oBAAoB;YAClC,SAAS,EAAE,+CAA+C;SAC3D;QACD,OAAO,EAAE,sBAAc,CAAC,OAAO;QAC/B,OAAO,EAAE,sBAAc,CAAC,OAAO;QAC/B,SAAS,EAAE,sBAAc,CAAC,SAAS;QACnC,gBAAgB,EAAE,sBAAc,CAAC,gBAAgB;QACjD,QAAQ,EAAE,sBAAc,CAAC,QAAQ;QACjC,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,cAAc;gBACpB,GAAG,EAAE,MAAM;gBACX,KAAK,EAAE,EAAE;gBACT,YAAY,EAAE,wBAAwB;aACvC;SACF;QACD,YAAY,EAAE,sBAAc,CAAC,YAAY;KAC1C,CAAC;AACJ,CAAC"}
|
package/dist/config/loader.d.ts
CHANGED
|
@@ -13,5 +13,5 @@ export declare function getConfigPath(configPath?: string): string;
|
|
|
13
13
|
* @param configPath - Path to config file
|
|
14
14
|
* @param skipValidation - If true, skip configuration validation (useful for login commands)
|
|
15
15
|
*/
|
|
16
|
-
export declare function loadConfig(configPath?: string, skipValidation?: boolean): StandaloneConfig;
|
|
16
|
+
export declare function loadConfig(configPath?: string, skipValidation?: boolean, resolveDynamicPlaceholders?: boolean): StandaloneConfig;
|
|
17
17
|
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAO3C;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAwBzD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAO3C;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAwBzD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,UAAU,CAAC,EAAE,MAAM,EACnB,cAAc,GAAE,OAAe,EAC/B,0BAA0B,GAAE,OAAc,GACzC,gBAAgB,CAsLlB"}
|