dsh-plugin-streamnest 0.0.0-stage → 0.0.2

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.
Files changed (150) hide show
  1. package/LICENSE +27 -0
  2. package/README.en.md +106 -0
  3. package/README.md +105 -2
  4. package/assets/logo.svg +5 -0
  5. package/assets/reference-projects.json +16 -0
  6. package/assets/screenshots/deepseek-harness-installed.png +0 -0
  7. package/lib/THIRD_PARTY_LICENSES.txt +2068 -0
  8. package/lib/apps/api/src/app.module.js +52 -0
  9. package/lib/apps/api/src/app.module.js.map +1 -0
  10. package/lib/apps/api/src/common/api-error.filter.js +22 -0
  11. package/lib/apps/api/src/common/api-error.filter.js.map +1 -0
  12. package/lib/apps/api/src/common/business-error.js +21 -0
  13. package/lib/apps/api/src/common/business-error.js.map +1 -0
  14. package/lib/apps/api/src/common/network.js +89 -0
  15. package/lib/apps/api/src/common/network.js.map +1 -0
  16. package/lib/apps/api/src/common/process.js +101 -0
  17. package/lib/apps/api/src/common/process.js.map +1 -0
  18. package/lib/apps/api/src/common/validation.js +30 -0
  19. package/lib/apps/api/src/common/validation.js.map +1 -0
  20. package/lib/apps/api/src/create-application.js +65 -0
  21. package/lib/apps/api/src/create-application.js.map +1 -0
  22. package/lib/apps/api/src/main.js +9 -0
  23. package/lib/apps/api/src/main.js.map +1 -0
  24. package/lib/apps/api/src/media/arguments.js +120 -0
  25. package/lib/apps/api/src/media/arguments.js.map +1 -0
  26. package/lib/apps/api/src/media/delete-downloads.js +129 -0
  27. package/lib/apps/api/src/media/delete-downloads.js.map +1 -0
  28. package/lib/apps/api/src/media/directory-sync.js +152 -0
  29. package/lib/apps/api/src/media/directory-sync.js.map +1 -0
  30. package/lib/apps/api/src/media/dto/media.dto.js +268 -0
  31. package/lib/apps/api/src/media/dto/media.dto.js.map +1 -0
  32. package/lib/apps/api/src/media/engines/aria2-progress.js +11 -0
  33. package/lib/apps/api/src/media/engines/aria2-progress.js.map +1 -0
  34. package/lib/apps/api/src/media/engines/aria2.js +85 -0
  35. package/lib/apps/api/src/media/engines/aria2.js.map +1 -0
  36. package/lib/apps/api/src/media/engines/direct-state.js +42 -0
  37. package/lib/apps/api/src/media/engines/direct-state.js.map +1 -0
  38. package/lib/apps/api/src/media/engines/direct.js +269 -0
  39. package/lib/apps/api/src/media/engines/direct.js.map +1 -0
  40. package/lib/apps/api/src/media/engines/js-runtime.js +125 -0
  41. package/lib/apps/api/src/media/engines/js-runtime.js.map +1 -0
  42. package/lib/apps/api/src/media/engines/types.js +2 -0
  43. package/lib/apps/api/src/media/engines/types.js.map +1 -0
  44. package/lib/apps/api/src/media/formats.js +106 -0
  45. package/lib/apps/api/src/media/formats.js.map +1 -0
  46. package/lib/apps/api/src/media/media.controller.js +312 -0
  47. package/lib/apps/api/src/media/media.controller.js.map +1 -0
  48. package/lib/apps/api/src/media/media.engine.js +446 -0
  49. package/lib/apps/api/src/media/media.engine.js.map +1 -0
  50. package/lib/apps/api/src/media/media.service.js +563 -0
  51. package/lib/apps/api/src/media/media.service.js.map +1 -0
  52. package/lib/apps/api/src/media/parsing/browser-paths.js +105 -0
  53. package/lib/apps/api/src/media/parsing/browser-paths.js.map +1 -0
  54. package/lib/apps/api/src/media/parsing/browser-pool.service.js +84 -0
  55. package/lib/apps/api/src/media/parsing/browser-pool.service.js.map +1 -0
  56. package/lib/apps/api/src/media/parsing/cache.service.js +123 -0
  57. package/lib/apps/api/src/media/parsing/cache.service.js.map +1 -0
  58. package/lib/apps/api/src/media/parsing/cookie.service.js +243 -0
  59. package/lib/apps/api/src/media/parsing/cookie.service.js.map +1 -0
  60. package/lib/apps/api/src/media/parsing/platform-data.js +131 -0
  61. package/lib/apps/api/src/media/parsing/platform-data.js.map +1 -0
  62. package/lib/apps/api/src/media/parsing/platform-parser.service.js +230 -0
  63. package/lib/apps/api/src/media/parsing/platform-parser.service.js.map +1 -0
  64. package/lib/apps/api/src/media/parsing/youtube-retry.js +24 -0
  65. package/lib/apps/api/src/media/parsing/youtube-retry.js.map +1 -0
  66. package/lib/apps/api/src/media/thumbnail.service.js +189 -0
  67. package/lib/apps/api/src/media/thumbnail.service.js.map +1 -0
  68. package/lib/apps/api/src/media/wechat/api.js +251 -0
  69. package/lib/apps/api/src/media/wechat/api.js.map +1 -0
  70. package/lib/apps/api/src/media/wechat/decode.js +121 -0
  71. package/lib/apps/api/src/media/wechat/decode.js.map +1 -0
  72. package/lib/apps/api/src/media/wechat/wechat.service.js +61 -0
  73. package/lib/apps/api/src/media/wechat/wechat.service.js.map +1 -0
  74. package/lib/apps/api/src/runtime/assets.json +98 -0
  75. package/lib/apps/api/src/runtime/runtime-archive.js +44 -0
  76. package/lib/apps/api/src/runtime/runtime-archive.js.map +1 -0
  77. package/lib/apps/api/src/runtime/runtime-discovery.js +163 -0
  78. package/lib/apps/api/src/runtime/runtime-discovery.js.map +1 -0
  79. package/lib/apps/api/src/runtime/runtime-installer.js +93 -0
  80. package/lib/apps/api/src/runtime/runtime-installer.js.map +1 -0
  81. package/lib/apps/api/src/runtime/runtime-manager.js +180 -0
  82. package/lib/apps/api/src/runtime/runtime-manager.js.map +1 -0
  83. package/lib/apps/api/src/runtime/runtime-manifest.js +48 -0
  84. package/lib/apps/api/src/runtime/runtime-manifest.js.map +1 -0
  85. package/lib/apps/api/src/runtime/runtime.service.js +2 -0
  86. package/lib/apps/api/src/runtime/runtime.service.js.map +1 -0
  87. package/lib/apps/api/src/storage/legacy-vault.js +66 -0
  88. package/lib/apps/api/src/storage/legacy-vault.js.map +1 -0
  89. package/lib/apps/api/src/storage/task-record.js +87 -0
  90. package/lib/apps/api/src/storage/task-record.js.map +1 -0
  91. package/lib/apps/api/src/storage/vault.store.js +321 -0
  92. package/lib/apps/api/src/storage/vault.store.js.map +1 -0
  93. package/lib/apps/api/src/system/browser-profiles.js +117 -0
  94. package/lib/apps/api/src/system/browser-profiles.js.map +1 -0
  95. package/lib/apps/api/src/system/journal.service.js +87 -0
  96. package/lib/apps/api/src/system/journal.service.js.map +1 -0
  97. package/lib/apps/api/src/system/native.service.js +106 -0
  98. package/lib/apps/api/src/system/native.service.js.map +1 -0
  99. package/lib/apps/api/src/system/system.controller.js +162 -0
  100. package/lib/apps/api/src/system/system.controller.js.map +1 -0
  101. package/lib/apps/api/src/system/system.dto.js +127 -0
  102. package/lib/apps/api/src/system/system.dto.js.map +1 -0
  103. package/lib/apps/api/src/system/system.service.js +191 -0
  104. package/lib/apps/api/src/system/system.service.js.map +1 -0
  105. package/lib/apps/shared/src/brand.js +9 -0
  106. package/lib/apps/shared/src/brand.js.map +1 -0
  107. package/lib/apps/shared/src/browser-profiles.js +15 -0
  108. package/lib/apps/shared/src/browser-profiles.js.map +1 -0
  109. package/lib/apps/shared/src/contracts.js +13 -0
  110. package/lib/apps/shared/src/contracts.js.map +1 -0
  111. package/lib/apps/shared/src/cookies.js +23 -0
  112. package/lib/apps/shared/src/cookies.js.map +1 -0
  113. package/lib/apps/shared/src/links.js +7 -0
  114. package/lib/apps/shared/src/links.js.map +1 -0
  115. package/lib/apps/shared/src/media-files.js +17 -0
  116. package/lib/apps/shared/src/media-files.js.map +1 -0
  117. package/lib/apps/shared/src/messages.js +255 -0
  118. package/lib/apps/shared/src/messages.js.map +1 -0
  119. package/lib/apps/shared/src/parse-errors.js +69 -0
  120. package/lib/apps/shared/src/parse-errors.js.map +1 -0
  121. package/lib/apps/shared/src/preferences.js +26 -0
  122. package/lib/apps/shared/src/preferences.js.map +1 -0
  123. package/lib/apps/shared/src/system.js +7 -0
  124. package/lib/apps/shared/src/system.js.map +1 -0
  125. package/lib/apps/shared/src/task-messages.js +21 -0
  126. package/lib/apps/shared/src/task-messages.js.map +1 -0
  127. package/lib/apps/shared/src/thumbnail.js +16 -0
  128. package/lib/apps/shared/src/thumbnail.js.map +1 -0
  129. package/lib/client.js +43785 -0
  130. package/lib/index.js +1 -0
  131. package/lib/packages/harness/src/index.js +46 -0
  132. package/lib/packages/harness/src/index.js.map +1 -0
  133. package/lib/packages/harness/src/tools/business-errors.js +47 -0
  134. package/lib/packages/harness/src/tools/business-errors.js.map +1 -0
  135. package/lib/packages/harness/src/tools/permissions.js +24 -0
  136. package/lib/packages/harness/src/tools/permissions.js.map +1 -0
  137. package/lib/packages/harness/src/tools/register.js +356 -0
  138. package/lib/packages/harness/src/tools/register.js.map +1 -0
  139. package/lib/packages/harness/src/tools/schemas.js +248 -0
  140. package/lib/packages/harness/src/tools/schemas.js.map +1 -0
  141. package/lib/packages/harness/src/tools/system-schemas.js +88 -0
  142. package/lib/packages/harness/src/tools/system-schemas.js.map +1 -0
  143. package/lib/packages/harness/src/tools/system-tools.js +193 -0
  144. package/lib/packages/harness/src/tools/system-tools.js.map +1 -0
  145. package/licenses/downvid.LICENSE +22 -0
  146. package/licenses/wx_channels_download.LICENSE +35 -0
  147. package/package.json +150 -3
  148. package/packages/harness/cordis.patch.yml +3 -0
  149. package/packages/harness/locale/en.json +6 -0
  150. package/packages/harness/locale/zh.json +6 -0
@@ -0,0 +1,87 @@
1
+ import { normalizePreferences } from '../../../shared/src/preferences.js';
2
+ import { storedTaskMessage } from '../../../shared/src/task-messages.js';
3
+ export const TASK_COLUMNS = [
4
+ 'payload',
5
+ 'state',
6
+ 'archived',
7
+ 'created_at',
8
+ 'updated_at',
9
+ 'progress',
10
+ 'downloaded_bytes',
11
+ 'total_bytes',
12
+ 'speed',
13
+ 'eta',
14
+ 'code',
15
+ 'params',
16
+ 'message',
17
+ 'downloader',
18
+ 'search_text',
19
+ 'duplicate_key',
20
+ ];
21
+ export function duplicateKey(task) {
22
+ const request = task.request;
23
+ return JSON.stringify([
24
+ task.media.url,
25
+ request.mode,
26
+ request.formatId ?? '',
27
+ request.audioTrackId ?? '',
28
+ request.audioFormatId ?? '',
29
+ request.subtitleFormat ?? 'srt',
30
+ [...(request.subtitles ?? [])].sort(),
31
+ ]);
32
+ }
33
+ export function progressValues(task) {
34
+ const info = storedTaskMessage(task);
35
+ return [
36
+ task.state,
37
+ task.updatedAt,
38
+ task.progress,
39
+ task.downloadedBytes,
40
+ task.totalBytes,
41
+ task.speed,
42
+ task.eta,
43
+ info.code,
44
+ JSON.stringify(info.params),
45
+ info.message,
46
+ task.downloader ?? null,
47
+ ];
48
+ }
49
+ export function taskValues(task) {
50
+ return [
51
+ JSON.stringify({
52
+ media: task.media,
53
+ request: task.request,
54
+ preferences: task.preferences,
55
+ outputDirectory: task.outputDirectory,
56
+ artifacts: task.artifacts,
57
+ }),
58
+ task.state,
59
+ Number(task.archived),
60
+ task.createdAt,
61
+ ...progressValues(task).slice(1),
62
+ `${task.media.title} ${task.media.platform} ${task.media.url}`.toLowerCase(),
63
+ duplicateKey(task),
64
+ ];
65
+ }
66
+ export function readTask(row) {
67
+ const payload = JSON.parse(String(row.payload));
68
+ return {
69
+ ...payload,
70
+ preferences: normalizePreferences(payload.preferences),
71
+ id: String(row.id),
72
+ state: row.state,
73
+ archived: !!row.archived,
74
+ createdAt: String(row.created_at),
75
+ updatedAt: String(row.updated_at),
76
+ progress: Number(row.progress),
77
+ downloadedBytes: Number(row.downloaded_bytes),
78
+ totalBytes: Number(row.total_bytes),
79
+ speed: Number(row.speed),
80
+ eta: Number(row.eta),
81
+ code: row.code,
82
+ params: JSON.parse(String(row.params)),
83
+ message: String(row.message),
84
+ ...(row.downloader ? { downloader: row.downloader } : {}),
85
+ };
86
+ }
87
+ //# sourceMappingURL=task-record.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-record.js","sourceRoot":"","sources":["../../../../../apps/api/src/storage/task-record.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,321 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { BadRequestException, Inject, Injectable } from '@nestjs/common';
14
+ import { randomUUID } from 'node:crypto';
15
+ import { mkdir, open, readFile } from 'node:fs/promises';
16
+ import { join } from 'node:path';
17
+ import { DatabaseSync } from 'node:sqlite';
18
+ import { setTimeout as delay } from 'node:timers/promises';
19
+ import { businessMessage, BusinessError } from '../../../shared/src/messages.js';
20
+ import { normalizePreferences } from '../../../shared/src/preferences.js';
21
+ import { readLegacyVault } from './legacy-vault.js';
22
+ import { duplicateKey, progressValues, readTask, TASK_COLUMNS, taskValues } from './task-record.js';
23
+ export const DATA_DIRECTORY = Symbol('STREAMNEST_DATA_DIRECTORY');
24
+ const ACTIVE = "('queued', 'downloading', 'processing', 'paused')";
25
+ const PROGRESS_SET = `state=?, updated_at=?, progress=?, downloaded_bytes=?, total_bytes=?,
26
+ speed=?, eta=?, code=?, params=?, message=?, downloader=?`;
27
+ let VaultStore = class VaultStore {
28
+ directory;
29
+ database;
30
+ statements = new Map();
31
+ constructor(directory) {
32
+ this.directory = directory;
33
+ }
34
+ get db() {
35
+ if (!this.database)
36
+ throw new Error('SQLite store is not open.');
37
+ return this.database;
38
+ }
39
+ statement(sql) {
40
+ let statement = this.statements.get(sql);
41
+ if (!statement) {
42
+ statement = this.db.prepare(sql);
43
+ this.statements.set(sql, statement);
44
+ }
45
+ return statement;
46
+ }
47
+ transaction(operation, mode = 'IMMEDIATE') {
48
+ this.db.exec(`BEGIN ${mode}`);
49
+ try {
50
+ const result = operation();
51
+ this.db.exec('COMMIT');
52
+ return result;
53
+ }
54
+ catch (error) {
55
+ this.db.exec('ROLLBACK');
56
+ throw error;
57
+ }
58
+ }
59
+ async initialize(defaults) {
60
+ if (this.database)
61
+ return;
62
+ await mkdir(this.directory, { recursive: true });
63
+ const path = join(this.directory, 'vault.sqlite');
64
+ const file = await open(path, 'a', 0o600);
65
+ await file.close();
66
+ this.database = new DatabaseSync(path);
67
+ try {
68
+ this.db.exec('PRAGMA busy_timeout=5000');
69
+ const deadline = Date.now() + 5_000;
70
+ while (true) {
71
+ try {
72
+ this.db.exec('PRAGMA journal_mode=WAL');
73
+ break;
74
+ }
75
+ catch (error) {
76
+ // Concurrent journal-mode changes can return SQLITE_BUSY without using busy_timeout.
77
+ if (error?.errcode !== 5 || Date.now() >= deadline)
78
+ throw error;
79
+ await delay(50);
80
+ }
81
+ }
82
+ this.db.exec('PRAGMA synchronous=FULL; PRAGMA foreign_keys=ON;');
83
+ const version = Number(this.db.prepare('PRAGMA user_version').get()?.user_version);
84
+ if (version > 1)
85
+ throw new BusinessError('VAULT_INVALID');
86
+ this.transaction(() => this.db.exec(`
87
+ CREATE TABLE IF NOT EXISTS metadata (key TEXT PRIMARY KEY, value TEXT NOT NULL) STRICT;
88
+ CREATE TABLE IF NOT EXISTS preferences (id INTEGER PRIMARY KEY CHECK(id=1), data TEXT NOT NULL) STRICT;
89
+ CREATE TABLE IF NOT EXISTS media (
90
+ seq INTEGER PRIMARY KEY AUTOINCREMENT, id TEXT NOT NULL UNIQUE, data TEXT NOT NULL
91
+ ) STRICT;
92
+ CREATE TABLE IF NOT EXISTS tasks (
93
+ seq INTEGER PRIMARY KEY AUTOINCREMENT, id TEXT NOT NULL UNIQUE,
94
+ payload TEXT NOT NULL, state TEXT NOT NULL, archived INTEGER NOT NULL,
95
+ created_at TEXT NOT NULL, updated_at TEXT NOT NULL, progress REAL NOT NULL,
96
+ downloaded_bytes REAL NOT NULL, total_bytes REAL NOT NULL, speed REAL NOT NULL, eta REAL NOT NULL,
97
+ code TEXT NOT NULL, params TEXT NOT NULL, message TEXT NOT NULL, downloader TEXT,
98
+ search_text TEXT NOT NULL, duplicate_key TEXT NOT NULL
99
+ ) STRICT;
100
+ CREATE INDEX IF NOT EXISTS tasks_archive_order ON tasks(archived, created_at DESC, seq DESC);
101
+ CREATE INDEX IF NOT EXISTS tasks_archive_state_order ON tasks(archived, state, created_at DESC, seq DESC);
102
+ CREATE INDEX IF NOT EXISTS tasks_queue_order ON tasks(state, created_at, seq);
103
+ CREATE INDEX IF NOT EXISTS tasks_duplicate ON tasks(duplicate_key, state);
104
+ CREATE TABLE IF NOT EXISTS record_backups (id TEXT PRIMARY KEY, created_at TEXT NOT NULL) STRICT;
105
+ CREATE TABLE IF NOT EXISTS record_backup_tasks (
106
+ backup_id TEXT NOT NULL REFERENCES record_backups(id), task_id TEXT NOT NULL, data TEXT NOT NULL,
107
+ PRIMARY KEY(backup_id, task_id)
108
+ ) STRICT;
109
+ PRAGMA user_version=1;
110
+ `));
111
+ if (this.statement("SELECT value FROM metadata WHERE key='initialized'").get())
112
+ return;
113
+ const legacy = await readLegacyVault(this.directory);
114
+ this.transaction(() => {
115
+ // Another connection may have imported while the backup was being written.
116
+ if (this.statement("SELECT value FROM metadata WHERE key='initialized'").get())
117
+ return;
118
+ this.setPreferences(normalizePreferences(legacy?.state.preferences ?? defaults));
119
+ for (const media of [...(legacy?.state.media ?? [])].reverse())
120
+ this.insertMedia(media);
121
+ for (const task of [...(legacy?.state.tasks ?? [])].reverse())
122
+ this.insert(task);
123
+ if (legacy) {
124
+ this.statement('INSERT INTO metadata(key,value) VALUES (?,?)').run('legacy_backup', legacy.backup);
125
+ this.statement('INSERT INTO metadata(key,value) VALUES (?,?)').run('legacy_sha256', legacy.digest);
126
+ }
127
+ this.statement('INSERT INTO metadata(key,value) VALUES (?,?)').run('initialized', new Date().toISOString());
128
+ });
129
+ }
130
+ catch (error) {
131
+ this.close();
132
+ throw error;
133
+ }
134
+ }
135
+ preferences() {
136
+ const row = this.statement('SELECT data FROM preferences WHERE id=1').get();
137
+ if (!row)
138
+ throw new BusinessError('VAULT_INVALID');
139
+ return normalizePreferences(JSON.parse(String(row.data)));
140
+ }
141
+ setPreferences(value) {
142
+ this.statement('INSERT INTO preferences(id,data) VALUES (1,?) ON CONFLICT(id) DO UPDATE SET data=excluded.data').run(JSON.stringify(value));
143
+ }
144
+ insertMedia(media) {
145
+ this.statement('INSERT INTO media(id,data) VALUES (?,?) ON CONFLICT(id) DO UPDATE SET data=excluded.data').run(media.id, JSON.stringify(media));
146
+ }
147
+ saveMedia(media) {
148
+ this.transaction(() => {
149
+ this.statement('DELETE FROM media WHERE id=?').run(media.id);
150
+ this.insertMedia(media);
151
+ this.db.exec('DELETE FROM media WHERE seq NOT IN (SELECT seq FROM media ORDER BY seq DESC LIMIT 50)');
152
+ });
153
+ }
154
+ media(id) {
155
+ const row = this.statement('SELECT data FROM media WHERE id=?').get(id);
156
+ return row ? JSON.parse(String(row.data)) : undefined;
157
+ }
158
+ insert(task) {
159
+ this.statement(`INSERT INTO tasks(id,${TASK_COLUMNS.join(',')}) VALUES (${Array(TASK_COLUMNS.length + 1)
160
+ .fill('?')
161
+ .join(',')})`).run(task.id, ...taskValues(task));
162
+ }
163
+ insertTask(task) {
164
+ this.transaction(() => {
165
+ if (this.count() >= 5000)
166
+ throw new BadRequestException(businessMessage('TASK_LIMIT'));
167
+ if (this.statement(`SELECT 1 FROM tasks WHERE duplicate_key=? AND state IN ${ACTIVE} LIMIT 1`).get(duplicateKey(task)))
168
+ throw new BadRequestException(businessMessage('TASK_DUPLICATE'));
169
+ this.insert(task);
170
+ });
171
+ }
172
+ saveTask(task) {
173
+ const result = this.statement(`UPDATE tasks SET ${TASK_COLUMNS.map((column) => `${column}=?`).join(',')} WHERE id=?`).run(...taskValues(task), task.id);
174
+ if (!result.changes)
175
+ throw new BusinessError('TASK_NOT_FOUND');
176
+ }
177
+ saveProgress(tasks) {
178
+ if (!tasks.length)
179
+ return;
180
+ this.transaction(() => {
181
+ const statement = this.statement(`UPDATE tasks SET ${PROGRESS_SET} WHERE id=? AND state IN ('downloading','processing')`);
182
+ for (const task of tasks)
183
+ statement.run(...progressValues(task), task.id);
184
+ });
185
+ }
186
+ pauseInterrupted() {
187
+ const info = businessMessage('TASK_INTERRUPTED');
188
+ this.statement(`UPDATE tasks SET state='paused', speed=0, eta=0, code=?, params=?, message=?
189
+ WHERE state IN ('queued','downloading','processing')`).run(info.code, JSON.stringify(info.params), info.message);
190
+ }
191
+ task(id) {
192
+ const row = this.statement('SELECT * FROM tasks WHERE id=?').get(id);
193
+ return row ? readTask(row) : undefined;
194
+ }
195
+ list(options) {
196
+ const where = ['1=1'];
197
+ const parameters = [];
198
+ if ((options.scope !== 'library' && options.scope !== 'queue') ||
199
+ options.archived !== undefined) {
200
+ where.push('archived=?');
201
+ parameters.push(Number(options.archived ?? false));
202
+ }
203
+ if (options.scope === 'library')
204
+ where.push("state='completed'");
205
+ else if (options.scope === 'queue')
206
+ where.push("state<>'completed'");
207
+ if (options.query?.trim()) {
208
+ where.push('instr(search_text,?)>0');
209
+ parameters.push(options.query.trim().toLowerCase());
210
+ }
211
+ const predicate = where.join(' AND ');
212
+ const offset = options.offset ?? 0;
213
+ const limit = options.limit ?? 25;
214
+ return this.transaction(() => {
215
+ const total = Number(this.statement(`SELECT count(*) AS total FROM tasks WHERE ${predicate}`).get(...parameters)
216
+ ?.total);
217
+ const items = this.statement(`SELECT * FROM tasks WHERE ${predicate} ORDER BY created_at DESC,seq DESC LIMIT ? OFFSET ?`)
218
+ .all(...parameters, limit, offset)
219
+ .map(readTask);
220
+ return {
221
+ items,
222
+ total,
223
+ offset,
224
+ nextOffset: offset + items.length < total ? offset + items.length : null,
225
+ };
226
+ }, 'DEFERRED');
227
+ }
228
+ claimQueued() {
229
+ return this.transaction(() => {
230
+ const row = this.statement("SELECT * FROM tasks WHERE state='queued' ORDER BY created_at,seq LIMIT 1").get();
231
+ if (!row)
232
+ return undefined;
233
+ const task = readTask(row);
234
+ task.state = 'downloading';
235
+ Object.assign(task, businessMessage('TASK_DOWNLOADING'));
236
+ this.saveTask(task);
237
+ return task;
238
+ });
239
+ }
240
+ count() {
241
+ return Number(this.statement('SELECT count(*) AS total FROM tasks').get()?.total);
242
+ }
243
+ endedIds(scope) {
244
+ const predicate = scope === 'library' ? "state='completed'" : "state IN ('completed','failed','cancelled')";
245
+ return this.statement(`SELECT id FROM tasks WHERE ${predicate}`)
246
+ .all()
247
+ .map((row) => String(row.id));
248
+ }
249
+ tasksForSync() {
250
+ return this.statement('SELECT * FROM tasks ORDER BY seq').all().map(readTask);
251
+ }
252
+ syncTasks(removed, imported, updated) {
253
+ return this.transaction(() => {
254
+ const backup = removed.length ? this.backupAndRemove(removed) : undefined;
255
+ if (this.count() + imported.length > 5000)
256
+ throw new BadRequestException(businessMessage('TASK_LIMIT'));
257
+ for (const task of updated)
258
+ this.saveTask(task);
259
+ for (const task of imported)
260
+ this.insert(task);
261
+ return backup?.backupId;
262
+ });
263
+ }
264
+ removeTasks(ids) {
265
+ return this.transaction(() => this.backupAndRemove(ids));
266
+ }
267
+ backupAndRemove(ids) {
268
+ const backupId = randomUUID();
269
+ this.statement('INSERT INTO record_backups(id,created_at) VALUES (?,?)').run(backupId, new Date().toISOString());
270
+ let count = 0;
271
+ for (const id of ids) {
272
+ const task = this.task(id);
273
+ if (!task)
274
+ continue;
275
+ this.statement('INSERT INTO record_backup_tasks(backup_id,task_id,data) VALUES (?,?,?)').run(backupId, id, JSON.stringify(task));
276
+ count += Number(this.statement('DELETE FROM tasks WHERE id=?').run(id).changes);
277
+ }
278
+ return { count, backupId };
279
+ }
280
+ async restoreHistory(id) {
281
+ if (!/^[a-f0-9]{8}-[a-f0-9-]{27}$/i.test(id))
282
+ throw new BusinessError('BACKUP_ID_INVALID');
283
+ let tasks;
284
+ if (this.statement('SELECT 1 FROM record_backups WHERE id=?').get(id)) {
285
+ tasks = this.statement('SELECT data FROM record_backup_tasks WHERE backup_id=?')
286
+ .all(id)
287
+ .map((row) => JSON.parse(String(row.data)));
288
+ }
289
+ else {
290
+ const value = JSON.parse(await readFile(join(this.directory, 'record-backups', `${id}.json`), 'utf8'));
291
+ if (value.version !== 1 || !Array.isArray(value.tasks))
292
+ throw new BusinessError('BACKUP_INVALID');
293
+ tasks = value.tasks;
294
+ }
295
+ if (tasks.some((task) => !task.id ||
296
+ !task.media ||
297
+ !task.request ||
298
+ !['completed', 'failed', 'cancelled'].includes(task.state)))
299
+ throw new BusinessError('BACKUP_INVALID');
300
+ return this.transaction(() => {
301
+ const restored = tasks.filter((task) => !this.task(task.id));
302
+ if (this.count() + restored.length > 5000)
303
+ throw new BadRequestException(businessMessage('TASK_RESTORE_LIMIT'));
304
+ for (const task of restored)
305
+ this.insert(task);
306
+ return { count: restored.length, backupId: id };
307
+ });
308
+ }
309
+ close() {
310
+ this.statements.clear();
311
+ this.database?.close();
312
+ this.database = undefined;
313
+ }
314
+ };
315
+ VaultStore = __decorate([
316
+ Injectable(),
317
+ __param(0, Inject(DATA_DIRECTORY)),
318
+ __metadata("design:paramtypes", [String])
319
+ ], VaultStore);
320
+ export { VaultStore };
321
+ //# sourceMappingURL=vault.store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault.store.js","sourceRoot":"","sources":["../../../../../apps/api/src/storage/vault.store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import { BusinessError, businessMessage } from '../../../shared/src/messages.js';
2
+ import { readdir, readFile, mkdir, writeFile } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import { join, resolve } from 'node:path';
5
+ import { chromiumProfiles } from '../../../shared/src/browser-profiles.js';
6
+ export { chromiumProfiles } from '../../../shared/src/browser-profiles.js';
7
+ function profileDirectory(browser) {
8
+ const home = homedir();
9
+ const names = process.platform === 'darwin'
10
+ ? {
11
+ chrome: 'Google/Chrome',
12
+ edge: 'Microsoft Edge',
13
+ brave: 'BraveSoftware/Brave-Browser',
14
+ chromium: 'Chromium',
15
+ }
16
+ : process.platform === 'win32'
17
+ ? {
18
+ chrome: 'Google/Chrome/User Data',
19
+ edge: 'Microsoft/Edge/User Data',
20
+ brave: 'BraveSoftware/Brave-Browser/User Data',
21
+ chromium: 'Chromium/User Data',
22
+ }
23
+ : {
24
+ chrome: 'google-chrome',
25
+ edge: 'microsoft-edge',
26
+ brave: 'BraveSoftware/Brave-Browser',
27
+ chromium: 'chromium',
28
+ };
29
+ if (!names[browser])
30
+ return;
31
+ return join(process.platform === 'darwin'
32
+ ? join(home, 'Library/Application Support')
33
+ : process.platform === 'win32'
34
+ ? process.env.LOCALAPPDATA || join(home, 'AppData/Local')
35
+ : process.env.XDG_CONFIG_HOME || join(home, '.config'), names[browser]);
36
+ }
37
+ export function browserMetadataPath(browser) {
38
+ const directory = profileDirectory(browser);
39
+ return directory ? join(directory, 'Local State') : undefined;
40
+ }
41
+ export async function saveBrowserProfiles(dataDirectory, browser, sourcePath, profiles) {
42
+ const expected = browserMetadataPath(browser);
43
+ if (!expected || resolve(sourcePath) !== resolve(expected))
44
+ throw new BusinessError('BROWSER_METADATA_INVALID');
45
+ if (!profiles.length ||
46
+ profiles.length > 100 ||
47
+ profiles.some((profile) => !/^(?:Default|Profile \d+)$/.test(profile.id)))
48
+ throw new BusinessError('BROWSER_ACCOUNTS_MISSING');
49
+ const clean = profiles.map(({ id, name, account }) => ({
50
+ id,
51
+ name,
52
+ account,
53
+ label: account ? `${name} · ${account}` : `${name} · ${id}`,
54
+ }));
55
+ const directory = join(dataDirectory, 'browser-accounts');
56
+ await mkdir(directory, { recursive: true, mode: 0o700 });
57
+ await writeFile(join(directory, `${browser}.json`), JSON.stringify({ profiles: clean, readAt: new Date().toISOString() }), { mode: 0o600 });
58
+ return { profiles: clean, ...businessMessage('BROWSER_PROFILES_IMPORTED') };
59
+ }
60
+ export async function browserProfiles(browser, dataDirectory) {
61
+ const directory = profileDirectory(browser);
62
+ if (directory) {
63
+ try {
64
+ const profiles = chromiumProfiles(await readFile(join(directory, 'Local State'), 'utf8'));
65
+ return { profiles, ...businessMessage(profiles.length ? 'NONE' : 'BROWSER_PROFILES_EMPTY') };
66
+ }
67
+ catch (error) {
68
+ const entries = await readdir(directory, { withFileTypes: true }).catch(() => []);
69
+ const profiles = entries
70
+ .filter((entry) => entry.isDirectory() && /^(?:Default|Profile \d+)$/.test(entry.name))
71
+ .map((entry) => ({ id: entry.name, name: entry.name, account: '', label: entry.name }));
72
+ const permission = ['EPERM', 'EACCES'].includes(error.code ?? '');
73
+ let cached = [];
74
+ if (dataDirectory)
75
+ cached = await readFile(join(dataDirectory, 'browser-accounts', `${browser}.json`), 'utf8')
76
+ .then((value) => JSON.parse(value).profiles)
77
+ .catch(() => []);
78
+ return {
79
+ profiles: cached.length ? cached : profiles,
80
+ ...businessMessage(cached.length
81
+ ? 'BROWSER_PROFILES_CACHED'
82
+ : permission
83
+ ? 'BROWSER_PROFILES_PERMISSION'
84
+ : profiles.length
85
+ ? 'BROWSER_PROFILES_NAMES_UNAVAILABLE'
86
+ : 'BROWSER_PROFILES_MISSING'),
87
+ ...(permission
88
+ ? { permissionRequired: true, metadataPath: join(directory, 'Local State') }
89
+ : {}),
90
+ };
91
+ }
92
+ }
93
+ if (browser === 'safari')
94
+ return {
95
+ profiles: [{ id: '', name: 'Safari', account: '', label: 'Safari · 默认配置' }],
96
+ ...businessMessage('BROWSER_SAFARI_DEFAULT'),
97
+ };
98
+ if (browser === 'firefox') {
99
+ const base = process.platform === 'darwin'
100
+ ? join(homedir(), 'Library/Application Support/Firefox')
101
+ : process.platform === 'win32'
102
+ ? join(process.env.APPDATA || join(homedir(), 'AppData/Roaming'), 'Mozilla/Firefox')
103
+ : join(homedir(), '.mozilla/firefox');
104
+ const content = await readFile(join(base, 'profiles.ini'), 'utf8').catch(() => '');
105
+ const profiles = content.split(/\r?\n\[/).flatMap((block) => {
106
+ const name = /^Name=(.+)$/m.exec(block)?.[1]?.trim();
107
+ const path = /^Path=(.+)$/m.exec(block)?.[1]?.trim();
108
+ if (!name || !path)
109
+ return [];
110
+ const id = path.split(/[\\/]/).at(-1);
111
+ return /^[\w .-]{1,100}$/.test(id) ? [{ id, name, account: '', label: name }] : [];
112
+ });
113
+ return { profiles, ...businessMessage(profiles.length ? 'NONE' : 'BROWSER_FIREFOX_MISSING') };
114
+ }
115
+ return { profiles: [], ...businessMessage('BROWSER_PROFILES_UNSUPPORTED') };
116
+ }
117
+ //# sourceMappingURL=browser-profiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-profiles.js","sourceRoot":"","sources":["../../../../../apps/api/src/system/browser-profiles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { Inject, Injectable } from '@nestjs/common';
14
+ import { appendFile, mkdir, readFile, rename, stat, writeFile } from 'node:fs/promises';
15
+ import { join } from 'node:path';
16
+ import { randomUUID } from 'node:crypto';
17
+ import { DATA_DIRECTORY } from '../storage/vault.store.js';
18
+ let JournalService = class JournalService {
19
+ directory;
20
+ path;
21
+ pending = Promise.resolve();
22
+ lastError = '';
23
+ constructor(directory) {
24
+ this.directory = join(directory, 'logs');
25
+ this.path = join(this.directory, 'streamnest.log');
26
+ }
27
+ /** 仅记录允许公开的类别与内部 ID;不写 URL、代理、Cookie、标题或原始输出。 */
28
+ write(event, data = {}) {
29
+ const safe = Object.fromEntries(Object.entries(data).filter(([, value]) => value && /^[\w.-]{1,100}$/.test(value)));
30
+ const line = `${new Date().toISOString()} ${event.replace(/[^\w.-]/g, '').slice(0, 60)} ${JSON.stringify(safe)}\n`;
31
+ const operation = this.pending.then(async () => {
32
+ await mkdir(this.directory, { recursive: true, mode: 0o700 });
33
+ const size = await stat(this.path)
34
+ .then((value) => value.size)
35
+ .catch(() => 0);
36
+ if (size > 512 * 1024)
37
+ await rename(this.path, `${this.path}.previous`);
38
+ await appendFile(this.path, line, { mode: 0o600 });
39
+ });
40
+ this.pending = operation.catch((error) => {
41
+ this.lastError = error.code ?? 'LOG_WRITE_FAILED';
42
+ });
43
+ }
44
+ async read(limit = 200) {
45
+ await this.pending;
46
+ const content = await readFile(this.path, 'utf8').catch((error) => {
47
+ if (error.code === 'ENOENT')
48
+ return '';
49
+ throw error;
50
+ });
51
+ return {
52
+ lines: content
53
+ .trim()
54
+ .split('\n')
55
+ .filter(Boolean)
56
+ .slice(-Math.max(1, Math.min(500, limit))),
57
+ bytes: Buffer.byteLength(content),
58
+ error: this.lastError,
59
+ };
60
+ }
61
+ async clear() {
62
+ const operation = this.pending.then(async () => {
63
+ await mkdir(this.directory, { recursive: true, mode: 0o700 });
64
+ const backup = `cleared-${randomUUID()}.log`;
65
+ try {
66
+ await rename(this.path, join(this.directory, backup));
67
+ }
68
+ catch (error) {
69
+ if (error.code !== 'ENOENT')
70
+ throw error;
71
+ }
72
+ await writeFile(this.path, '', { mode: 0o600 });
73
+ return { cleared: true, backup };
74
+ });
75
+ this.pending = operation.then(() => undefined, (error) => {
76
+ this.lastError = error.code ?? 'LOG_WRITE_FAILED';
77
+ });
78
+ return operation;
79
+ }
80
+ };
81
+ JournalService = __decorate([
82
+ Injectable(),
83
+ __param(0, Inject(DATA_DIRECTORY)),
84
+ __metadata("design:paramtypes", [String])
85
+ ], JournalService);
86
+ export { JournalService };
87
+ //# sourceMappingURL=journal.service.js.map