patreon-dl 1.0.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.
Files changed (223) hide show
  1. package/README.md +422 -0
  2. package/bin/patreon-dl.js +5 -0
  3. package/dist/cli/CLIOptionValidator.d.ts +9 -0
  4. package/dist/cli/CLIOptionValidator.d.ts.map +1 -0
  5. package/dist/cli/CLIOptionValidator.js +85 -0
  6. package/dist/cli/CLIOptionValidator.js.map +1 -0
  7. package/dist/cli/CLIOptions.d.ts +20 -0
  8. package/dist/cli/CLIOptions.d.ts.map +1 -0
  9. package/dist/cli/CLIOptions.js +75 -0
  10. package/dist/cli/CLIOptions.js.map +1 -0
  11. package/dist/cli/CommandLineParser.d.ts +11 -0
  12. package/dist/cli/CommandLineParser.d.ts.map +1 -0
  13. package/dist/cli/CommandLineParser.js +212 -0
  14. package/dist/cli/CommandLineParser.js.map +1 -0
  15. package/dist/cli/ConfigFileParser.d.ts +9 -0
  16. package/dist/cli/ConfigFileParser.d.ts.map +1 -0
  17. package/dist/cli/ConfigFileParser.js +163 -0
  18. package/dist/cli/ConfigFileParser.js.map +1 -0
  19. package/dist/cli/index.d.ts +7 -0
  20. package/dist/cli/index.d.ts.map +1 -0
  21. package/dist/cli/index.js +162 -0
  22. package/dist/cli/index.js.map +1 -0
  23. package/dist/downloaders/Bootstrap.d.ts +29 -0
  24. package/dist/downloaders/Bootstrap.d.ts.map +1 -0
  25. package/dist/downloaders/Bootstrap.js +51 -0
  26. package/dist/downloaders/Bootstrap.js.map +1 -0
  27. package/dist/downloaders/Downloader.d.ts +59 -0
  28. package/dist/downloaders/Downloader.d.ts.map +1 -0
  29. package/dist/downloaders/Downloader.js +357 -0
  30. package/dist/downloaders/Downloader.js.map +1 -0
  31. package/dist/downloaders/DownloaderEvent.d.ts +47 -0
  32. package/dist/downloaders/DownloaderEvent.d.ts.map +1 -0
  33. package/dist/downloaders/DownloaderEvent.js +6 -0
  34. package/dist/downloaders/DownloaderEvent.js.map +1 -0
  35. package/dist/downloaders/DownloaderOptions.d.ts +39 -0
  36. package/dist/downloaders/DownloaderOptions.d.ts.map +1 -0
  37. package/dist/downloaders/DownloaderOptions.js +69 -0
  38. package/dist/downloaders/DownloaderOptions.js.map +1 -0
  39. package/dist/downloaders/PostDownloader.d.ts +8 -0
  40. package/dist/downloaders/PostDownloader.d.ts.map +1 -0
  41. package/dist/downloaders/PostDownloader.js +428 -0
  42. package/dist/downloaders/PostDownloader.js.map +1 -0
  43. package/dist/downloaders/ProductDownloader.d.ts +8 -0
  44. package/dist/downloaders/ProductDownloader.d.ts.map +1 -0
  45. package/dist/downloaders/ProductDownloader.js +171 -0
  46. package/dist/downloaders/ProductDownloader.js.map +1 -0
  47. package/dist/downloaders/cache/StatusCache.d.ts +43 -0
  48. package/dist/downloaders/cache/StatusCache.d.ts.map +1 -0
  49. package/dist/downloaders/cache/StatusCache.js +206 -0
  50. package/dist/downloaders/cache/StatusCache.js.map +1 -0
  51. package/dist/downloaders/index.d.ts +7 -0
  52. package/dist/downloaders/index.d.ts.map +1 -0
  53. package/dist/downloaders/index.js +6 -0
  54. package/dist/downloaders/index.js.map +1 -0
  55. package/dist/downloaders/task/DownloadTask.d.ts +89 -0
  56. package/dist/downloaders/task/DownloadTask.d.ts.map +1 -0
  57. package/dist/downloaders/task/DownloadTask.js +240 -0
  58. package/dist/downloaders/task/DownloadTask.js.map +1 -0
  59. package/dist/downloaders/task/DownloadTaskBatch.d.ts +45 -0
  60. package/dist/downloaders/task/DownloadTaskBatch.d.ts.map +1 -0
  61. package/dist/downloaders/task/DownloadTaskBatch.js +195 -0
  62. package/dist/downloaders/task/DownloadTaskBatch.js.map +1 -0
  63. package/dist/downloaders/task/DownloadTaskBatchEvent.d.ts +32 -0
  64. package/dist/downloaders/task/DownloadTaskBatchEvent.d.ts.map +1 -0
  65. package/dist/downloaders/task/DownloadTaskBatchEvent.js +2 -0
  66. package/dist/downloaders/task/DownloadTaskBatchEvent.js.map +1 -0
  67. package/dist/downloaders/task/DownloadTaskFactory.d.ts +20 -0
  68. package/dist/downloaders/task/DownloadTaskFactory.d.ts.map +1 -0
  69. package/dist/downloaders/task/DownloadTaskFactory.js +177 -0
  70. package/dist/downloaders/task/DownloadTaskFactory.js.map +1 -0
  71. package/dist/downloaders/task/FFmpegDownloadTask.d.ts +27 -0
  72. package/dist/downloaders/task/FFmpegDownloadTask.d.ts.map +1 -0
  73. package/dist/downloaders/task/FFmpegDownloadTask.js +206 -0
  74. package/dist/downloaders/task/FFmpegDownloadTask.js.map +1 -0
  75. package/dist/downloaders/task/FetcherDownloadTask.d.ts +21 -0
  76. package/dist/downloaders/task/FetcherDownloadTask.d.ts.map +1 -0
  77. package/dist/downloaders/task/FetcherDownloadTask.js +213 -0
  78. package/dist/downloaders/task/FetcherDownloadTask.js.map +1 -0
  79. package/dist/downloaders/task/index.d.ts +4 -0
  80. package/dist/downloaders/task/index.d.ts.map +1 -0
  81. package/dist/downloaders/task/index.js +3 -0
  82. package/dist/downloaders/task/index.js.map +1 -0
  83. package/dist/downloaders/templates/CampaignInfo.d.ts +3 -0
  84. package/dist/downloaders/templates/CampaignInfo.d.ts.map +1 -0
  85. package/dist/downloaders/templates/CampaignInfo.js +58 -0
  86. package/dist/downloaders/templates/CampaignInfo.js.map +1 -0
  87. package/dist/downloaders/templates/PostInfo.d.ts +4 -0
  88. package/dist/downloaders/templates/PostInfo.d.ts.map +1 -0
  89. package/dist/downloaders/templates/PostInfo.js +45 -0
  90. package/dist/downloaders/templates/PostInfo.js.map +1 -0
  91. package/dist/downloaders/templates/ProductInfo.d.ts +3 -0
  92. package/dist/downloaders/templates/ProductInfo.d.ts.map +1 -0
  93. package/dist/downloaders/templates/ProductInfo.js +20 -0
  94. package/dist/downloaders/templates/ProductInfo.js.map +1 -0
  95. package/dist/entities/Attachment.d.ts +7 -0
  96. package/dist/entities/Attachment.d.ts.map +1 -0
  97. package/dist/entities/Attachment.js +2 -0
  98. package/dist/entities/Attachment.js.map +1 -0
  99. package/dist/entities/Campaign.d.ts +19 -0
  100. package/dist/entities/Campaign.d.ts.map +1 -0
  101. package/dist/entities/Campaign.js +2 -0
  102. package/dist/entities/Campaign.js.map +1 -0
  103. package/dist/entities/Downloadable.d.ts +6 -0
  104. package/dist/entities/Downloadable.d.ts.map +1 -0
  105. package/dist/entities/Downloadable.js +5 -0
  106. package/dist/entities/Downloadable.js.map +1 -0
  107. package/dist/entities/MediaItem.d.ts +95 -0
  108. package/dist/entities/MediaItem.d.ts.map +1 -0
  109. package/dist/entities/MediaItem.js +2 -0
  110. package/dist/entities/MediaItem.js.map +1 -0
  111. package/dist/entities/Post.d.ts +87 -0
  112. package/dist/entities/Post.d.ts.map +1 -0
  113. package/dist/entities/Post.js +2 -0
  114. package/dist/entities/Post.js.map +1 -0
  115. package/dist/entities/Product.d.ts +17 -0
  116. package/dist/entities/Product.d.ts.map +1 -0
  117. package/dist/entities/Product.js +2 -0
  118. package/dist/entities/Product.js.map +1 -0
  119. package/dist/entities/Reward.d.ts +14 -0
  120. package/dist/entities/Reward.d.ts.map +1 -0
  121. package/dist/entities/Reward.js +2 -0
  122. package/dist/entities/Reward.js.map +1 -0
  123. package/dist/entities/User.d.ts +15 -0
  124. package/dist/entities/User.d.ts.map +1 -0
  125. package/dist/entities/User.js +2 -0
  126. package/dist/entities/User.js.map +1 -0
  127. package/dist/entities/index.d.ts +9 -0
  128. package/dist/entities/index.d.ts.map +1 -0
  129. package/dist/entities/index.js +6 -0
  130. package/dist/entities/index.js.map +1 -0
  131. package/dist/index.d.ts +8 -0
  132. package/dist/index.d.ts.map +1 -0
  133. package/dist/index.js +8 -0
  134. package/dist/index.js.map +1 -0
  135. package/dist/parsers/PageParser.d.ts +6 -0
  136. package/dist/parsers/PageParser.d.ts.map +1 -0
  137. package/dist/parsers/PageParser.js +23 -0
  138. package/dist/parsers/PageParser.js.map +1 -0
  139. package/dist/parsers/Parser.d.ts +43 -0
  140. package/dist/parsers/Parser.d.ts.map +1 -0
  141. package/dist/parsers/Parser.js +439 -0
  142. package/dist/parsers/Parser.js.map +1 -0
  143. package/dist/parsers/PostParser.d.ts +7 -0
  144. package/dist/parsers/PostParser.d.ts.map +1 -0
  145. package/dist/parsers/PostParser.js +259 -0
  146. package/dist/parsers/PostParser.js.map +1 -0
  147. package/dist/parsers/ProductParser.d.ts +7 -0
  148. package/dist/parsers/ProductParser.d.ts.map +1 -0
  149. package/dist/parsers/ProductParser.js +70 -0
  150. package/dist/parsers/ProductParser.js.map +1 -0
  151. package/dist/utils/AttachmentFilenameResolver.d.ts +9 -0
  152. package/dist/utils/AttachmentFilenameResolver.d.ts.map +1 -0
  153. package/dist/utils/AttachmentFilenameResolver.js +73 -0
  154. package/dist/utils/AttachmentFilenameResolver.js.map +1 -0
  155. package/dist/utils/FSHelper.d.ts +57 -0
  156. package/dist/utils/FSHelper.d.ts.map +1 -0
  157. package/dist/utils/FSHelper.js +214 -0
  158. package/dist/utils/FSHelper.js.map +1 -0
  159. package/dist/utils/Fetcher.d.ts +45 -0
  160. package/dist/utils/Fetcher.d.ts.map +1 -0
  161. package/dist/utils/Fetcher.js +192 -0
  162. package/dist/utils/Fetcher.js.map +1 -0
  163. package/dist/utils/FetcherProgressMonitor.d.ts +18 -0
  164. package/dist/utils/FetcherProgressMonitor.d.ts.map +1 -0
  165. package/dist/utils/FetcherProgressMonitor.js +56 -0
  166. package/dist/utils/FetcherProgressMonitor.js.map +1 -0
  167. package/dist/utils/FilenameFormatHelper.d.ts +44 -0
  168. package/dist/utils/FilenameFormatHelper.d.ts.map +1 -0
  169. package/dist/utils/FilenameFormatHelper.js +98 -0
  170. package/dist/utils/FilenameFormatHelper.js.map +1 -0
  171. package/dist/utils/FllenameResolver.d.ts +20 -0
  172. package/dist/utils/FllenameResolver.d.ts.map +1 -0
  173. package/dist/utils/FllenameResolver.js +55 -0
  174. package/dist/utils/FllenameResolver.js.map +1 -0
  175. package/dist/utils/Formatter.d.ts +21 -0
  176. package/dist/utils/Formatter.d.ts.map +1 -0
  177. package/dist/utils/Formatter.js +112 -0
  178. package/dist/utils/Formatter.js.map +1 -0
  179. package/dist/utils/MediaFilenameResolver.d.ts +9 -0
  180. package/dist/utils/MediaFilenameResolver.d.ts.map +1 -0
  181. package/dist/utils/MediaFilenameResolver.js +90 -0
  182. package/dist/utils/MediaFilenameResolver.js.map +1 -0
  183. package/dist/utils/Misc.d.ts +14 -0
  184. package/dist/utils/Misc.d.ts.map +1 -0
  185. package/dist/utils/Misc.js +4 -0
  186. package/dist/utils/Misc.js.map +1 -0
  187. package/dist/utils/ObjectHelper.d.ts +4 -0
  188. package/dist/utils/ObjectHelper.d.ts.map +1 -0
  189. package/dist/utils/ObjectHelper.js +30 -0
  190. package/dist/utils/ObjectHelper.js.map +1 -0
  191. package/dist/utils/PackageInfo.d.ts +10 -0
  192. package/dist/utils/PackageInfo.d.ts.map +1 -0
  193. package/dist/utils/PackageInfo.js +33 -0
  194. package/dist/utils/PackageInfo.js.map +1 -0
  195. package/dist/utils/URLHelper.d.ts +40 -0
  196. package/dist/utils/URLHelper.d.ts.map +1 -0
  197. package/dist/utils/URLHelper.js +192 -0
  198. package/dist/utils/URLHelper.js.map +1 -0
  199. package/dist/utils/index.d.ts +2 -0
  200. package/dist/utils/index.d.ts.map +1 -0
  201. package/dist/utils/index.js +2 -0
  202. package/dist/utils/index.js.map +1 -0
  203. package/dist/utils/logging/ChainLogger.d.ts +11 -0
  204. package/dist/utils/logging/ChainLogger.d.ts.map +1 -0
  205. package/dist/utils/logging/ChainLogger.js +50 -0
  206. package/dist/utils/logging/ChainLogger.js.map +1 -0
  207. package/dist/utils/logging/ConsoleLogger.d.ts +31 -0
  208. package/dist/utils/logging/ConsoleLogger.d.ts.map +1 -0
  209. package/dist/utils/logging/ConsoleLogger.js +126 -0
  210. package/dist/utils/logging/ConsoleLogger.js.map +1 -0
  211. package/dist/utils/logging/FileLogger.d.ts +26 -0
  212. package/dist/utils/logging/FileLogger.d.ts.map +1 -0
  213. package/dist/utils/logging/FileLogger.js +147 -0
  214. package/dist/utils/logging/FileLogger.js.map +1 -0
  215. package/dist/utils/logging/Logger.d.ts +12 -0
  216. package/dist/utils/logging/Logger.d.ts.map +1 -0
  217. package/dist/utils/logging/Logger.js +15 -0
  218. package/dist/utils/logging/Logger.js.map +1 -0
  219. package/dist/utils/logging/index.d.ts +7 -0
  220. package/dist/utils/logging/index.d.ts.map +1 -0
  221. package/dist/utils/logging/index.js +7 -0
  222. package/dist/utils/logging/index.js.map +1 -0
  223. package/package.json +78 -0
@@ -0,0 +1,171 @@
1
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
+ };
6
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
7
+ if (kind === "m") throw new TypeError("Private method is not writable");
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
10
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
11
+ };
12
+ var _ProductDownloader_startPromise;
13
+ import ProductParser from '../parsers/ProductParser.js';
14
+ import FSHelper from '../utils/FSHelper.js';
15
+ import URLHelper from '../utils/URLHelper.js';
16
+ import Downloader from './Downloader.js';
17
+ import StatusCache from './cache/StatusCache.js';
18
+ import { generateProductSummary } from './templates/ProductInfo.js';
19
+ import path from 'path';
20
+ import { TargetSkipReason } from './DownloaderEvent.js';
21
+ export default class ProductDownloader extends Downloader {
22
+ constructor() {
23
+ super(...arguments);
24
+ this.name = 'ProductDownloader';
25
+ _ProductDownloader_startPromise.set(this, null);
26
+ }
27
+ start(params) {
28
+ if (__classPrivateFieldGet(this, _ProductDownloader_startPromise, "f")) {
29
+ throw Error('Downloader already running');
30
+ }
31
+ __classPrivateFieldSet(this, _ProductDownloader_startPromise, new Promise(async (resolve) => {
32
+ const { signal } = params || {};
33
+ let batch = null;
34
+ if (this.checkAbortSignal(signal, resolve)) {
35
+ return;
36
+ }
37
+ const abortHandler = async () => {
38
+ this.log('info', 'Abort signal received');
39
+ if (batch) {
40
+ await batch.abort();
41
+ }
42
+ };
43
+ if (signal) {
44
+ signal.addEventListener('abort', abortHandler, { once: true });
45
+ }
46
+ this.log('info', `Target product ID '${this.config.productId}'`);
47
+ // Step 1: get product API data
48
+ const url = URLHelper.constructProductAPIURL(this.config.productId);
49
+ this.log('debug', `Fetch product data from API URL "${url}"`);
50
+ this.emit('fetchBegin', { targetType: 'product' });
51
+ const { json, error: requestAPIError } = await this.commonFetchAPI(url, signal);
52
+ if (!json) {
53
+ if (this.checkAbortSignal(signal, resolve)) {
54
+ return;
55
+ }
56
+ this.log('error', 'Failed to fetch product data');
57
+ this.emit('end', { aborted: false, error: requestAPIError });
58
+ resolve();
59
+ return;
60
+ }
61
+ // Step 2: parse product API data
62
+ const productParser = new ProductParser(this.logger);
63
+ const product = productParser.parseProductAPIResponse(json, url, this.config.productId);
64
+ // Step 3: Save campaign info
65
+ await this.saveCampaignInfo(product.campaign, signal);
66
+ if (this.checkAbortSignal(signal, resolve)) {
67
+ return;
68
+ }
69
+ this.emit('targetBegin', { target: product });
70
+ // Step 4: Product directories
71
+ const productDirs = FSHelper.getProductDirs(product, this.config);
72
+ this.log('debug', 'Product directories: ', productDirs);
73
+ // Step 5: Check with status cache
74
+ const statusCache = StatusCache.getInstance(productDirs.statusCache, this.logger, this.config.useStatusCache);
75
+ if (statusCache.validate(product, productDirs.root, this.config)) {
76
+ this.log('info', `Skipped downloading product #${product.id}: already downloaded and nothing has changed since last download`);
77
+ this.emit('targetEnd', {
78
+ target: product,
79
+ isSkipped: true,
80
+ skipReason: TargetSkipReason.AlreadyDownloaded,
81
+ skipMessage: 'Target already downloaded and nothing has changed since last download'
82
+ });
83
+ this.emit('end', { aborted: false });
84
+ resolve();
85
+ return;
86
+ }
87
+ // Step 6: Check accessibility
88
+ if (!product.isAccessible) {
89
+ if (this.config.include.lockedContent) {
90
+ this.log('warn', `Product #${product.id} is not accessible by current user`);
91
+ }
92
+ else {
93
+ this.log('warn', `Skipped downloading product #${product.id}: not accessible by current user`);
94
+ this.emit('targetEnd', {
95
+ target: product,
96
+ isSkipped: true,
97
+ skipReason: TargetSkipReason.Inaccessible,
98
+ skipMessage: 'Target is not accessible by current user'
99
+ });
100
+ this.emit('end', { aborted: false });
101
+ resolve();
102
+ return;
103
+ }
104
+ }
105
+ FSHelper.createDir(productDirs.root);
106
+ // Step 7: save product info
107
+ if (this.config.include.contentInfo) {
108
+ this.log('info', 'Save product info');
109
+ this.emit('phaseBegin', { target: product, phase: 'saveInfo' });
110
+ FSHelper.createDir(productDirs.info);
111
+ const summary = generateProductSummary(product);
112
+ const summaryFile = path.resolve(productDirs.info, 'info.txt');
113
+ const saveSummaryResult = await FSHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);
114
+ this.logWriteTextFileResult(saveSummaryResult, product, 'product summary');
115
+ const productRawFile = path.resolve(productDirs.info, 'product-api.json');
116
+ const saveProductRawResult = await FSHelper.writeTextFile(productRawFile, product.raw, this.config.fileExistsAction.infoAPI);
117
+ this.logWriteTextFileResult(saveProductRawResult, product, 'product API data');
118
+ this.emit('phaseEnd', { target: product, phase: 'saveInfo' });
119
+ }
120
+ // Step 8: Download product media items
121
+ this.log('info', 'Download: ' +
122
+ `preview items: ${this.config.include.previewMedia ? 'yes' : 'no'}; ` +
123
+ `content items: ${this.config.include.contentMedia ? 'yes' : 'no'}`);
124
+ if (this.config.include.previewMedia || this.config.include.contentMedia) {
125
+ this.emit('phaseBegin', { target: product, phase: 'saveMedia' });
126
+ batch = this.createDownloadTaskBatch(`Product #${product.id} (${product.name})`, this.config.include.previewMedia ? {
127
+ target: product.previewMedia,
128
+ targetName: `product #${product.id} -> preview media`,
129
+ destDir: productDirs.previewMedia,
130
+ fileExistsAction: this.config.fileExistsAction.content
131
+ } : null, this.config.include.contentMedia ? {
132
+ target: product.contentMedia,
133
+ targetName: `product #${product.id} -> content media`,
134
+ destDir: productDirs.contentMedia,
135
+ fileExistsAction: this.config.fileExistsAction.content
136
+ } : null);
137
+ this.log('info', `Download batch created (#${batch.id}): ${batch.getTasks('pending').length} downloads pending`);
138
+ this.emit('phaseBegin', { target: product, phase: 'batchDownload', batch });
139
+ await batch.start();
140
+ // Step 9: Update status cache
141
+ statusCache.updateOnDownload(product, productDirs.root, batch.getTasks('error').length > 0, this.config);
142
+ await batch.destroy();
143
+ batch = null;
144
+ this.emit('phaseEnd', { target: product, phase: 'batchDownload' });
145
+ this.emit('phaseEnd', { target: product, phase: 'saveMedia' });
146
+ }
147
+ if (this.checkAbortSignal(signal, resolve)) {
148
+ return;
149
+ }
150
+ // Done
151
+ if (signal) {
152
+ signal.removeEventListener('abort', abortHandler);
153
+ }
154
+ this.log('info', `Done downloading product #${product.id}`);
155
+ this.emit('targetEnd', { target: product, isSkipped: false });
156
+ this.emit('end', { aborted: false });
157
+ __classPrivateFieldSet(this, _ProductDownloader_startPromise, null, "f");
158
+ resolve();
159
+ })
160
+ .finally(async () => {
161
+ if (this.logger) {
162
+ await this.logger.end();
163
+ }
164
+ __classPrivateFieldSet(this, _ProductDownloader_startPromise, null, "f");
165
+ }), "f");
166
+ return __classPrivateFieldGet(this, _ProductDownloader_startPromise, "f");
167
+ }
168
+ }
169
+ _ProductDownloader_startPromise = new WeakMap();
170
+ ProductDownloader.version = '1.0.0';
171
+ //# sourceMappingURL=ProductDownloader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProductDownloader.js","sourceRoot":"","sources":["../../src/downloaders/ProductDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import ProductParser from '../parsers/ProductParser.js';\nimport FSHelper from '../utils/FSHelper.js';\nimport URLHelper from '../utils/URLHelper.js';\nimport Downloader, { DownloaderStartParams } from './Downloader.js';\nimport DownloadTaskBatch from './task/DownloadTaskBatch.js';\nimport StatusCache from './cache/StatusCache.js';\nimport { generateProductSummary } from './templates/ProductInfo.js';\nimport path from 'path';\nimport { TargetSkipReason } from './DownloaderEvent.js';\n\nexport default class ProductDownloader extends Downloader<'product'> {\n\n static version = '1.0.0';\n\n name = 'ProductDownloader';\n\n #startPromise: Promise<void> | null = null;\n\n start(params?: DownloaderStartParams): Promise<void> {\n\n if (this.#startPromise) {\n throw Error('Downloader already running');\n }\n\n this.#startPromise = new Promise<void>(async (resolve) => {\n\n const { signal } = params || {};\n let batch: DownloadTaskBatch | null = null;\n\n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n\n const abortHandler = async () => {\n this.log('info', 'Abort signal received');\n if (batch) {\n await batch.abort();\n }\n };\n if (signal) {\n signal.addEventListener('abort', abortHandler, { once: true });\n }\n\n this.log('info', `Target product ID '${this.config.productId}'`);\n\n // Step 1: get product API data\n const url = URLHelper.constructProductAPIURL(this.config.productId);\n this.log('debug', `Fetch product data from API URL \"${url}\"`);\n this.emit('fetchBegin', { targetType: 'product' });\n\n const { json, error: requestAPIError } = await this.commonFetchAPI(url, signal);\n if (!json) {\n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n this.log('error', 'Failed to fetch product data');\n this.emit('end', { aborted: false, error: requestAPIError });\n resolve();\n return;\n }\n\n // Step 2: parse product API data\n const productParser = new ProductParser(this.logger);\n const product = productParser.parseProductAPIResponse(json, url, this.config.productId);\n\n // Step 3: Save campaign info\n await this.saveCampaignInfo(product.campaign, signal);\n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n\n this.emit('targetBegin', { target: product });\n\n // Step 4: Product directories\n const productDirs = FSHelper.getProductDirs(product, this.config);\n this.log('debug', 'Product directories: ', productDirs);\n\n // Step 5: Check with status cache\n const statusCache = StatusCache.getInstance(productDirs.statusCache, this.logger, this.config.useStatusCache);\n if (statusCache.validate(product, productDirs.root, this.config)) {\n this.log('info', `Skipped downloading product #${product.id}: already downloaded and nothing has changed since last download`);\n this.emit('targetEnd', {\n target: product,\n isSkipped: true,\n skipReason: TargetSkipReason.AlreadyDownloaded,\n skipMessage: 'Target already downloaded and nothing has changed since last download'\n });\n this.emit('end', { aborted: false });\n resolve();\n return;\n }\n\n // Step 6: Check accessibility\n if (!product.isAccessible) {\n if (this.config.include.lockedContent) {\n this.log('warn', `Product #${product.id} is not accessible by current user`);\n }\n else {\n this.log('warn', `Skipped downloading product #${product.id}: not accessible by current user`);\n this.emit('targetEnd', {\n target: product,\n isSkipped: true,\n skipReason: TargetSkipReason.Inaccessible,\n skipMessage: 'Target is not accessible by current user'\n });\n this.emit('end', { aborted: false });\n resolve();\n return;\n }\n }\n\n FSHelper.createDir(productDirs.root);\n\n // Step 7: save product info\n if (this.config.include.contentInfo) {\n this.log('info', 'Save product info');\n this.emit('phaseBegin', { target: product, phase: 'saveInfo' });\n FSHelper.createDir(productDirs.info);\n const summary = generateProductSummary(product);\n const summaryFile = path.resolve(productDirs.info, 'info.txt');\n const saveSummaryResult = await FSHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, product, 'product summary');\n\n const productRawFile = path.resolve(productDirs.info, 'product-api.json');\n const saveProductRawResult = await FSHelper.writeTextFile(\n productRawFile, product.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(saveProductRawResult, product, 'product API data');\n this.emit('phaseEnd', { target: product, phase: 'saveInfo' });\n }\n\n // Step 8: Download product media items\n this.log('info', 'Download: ' +\n `preview items: ${this.config.include.previewMedia ? 'yes' : 'no'}; ` +\n `content items: ${this.config.include.contentMedia ? 'yes' : 'no'}`);\n\n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseBegin', { target: product, phase: 'saveMedia' });\n batch = this.createDownloadTaskBatch(\n `Product #${product.id} (${product.name})`,\n\n this.config.include.previewMedia ? {\n target: product.previewMedia,\n targetName: `product #${product.id} -> preview media`,\n destDir: productDirs.previewMedia,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n this.config.include.contentMedia ? {\n target: product.contentMedia,\n targetName: `product #${product.id} -> content media`,\n destDir: productDirs.contentMedia,\n fileExistsAction: this.config.fileExistsAction.content\n } : null\n );\n\n this.log('info', `Download batch created (#${batch.id}): ${batch.getTasks('pending').length} downloads pending`);\n this.emit('phaseBegin', { target: product, phase: 'batchDownload', batch });\n\n await batch.start();\n\n // Step 9: Update status cache\n statusCache.updateOnDownload(product, productDirs.root, batch.getTasks('error').length > 0, this.config);\n\n await batch.destroy();\n batch = null;\n this.emit('phaseEnd', { target: product, phase: 'batchDownload' });\n this.emit('phaseEnd', { target: product, phase: 'saveMedia' });\n }\n\n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n\n // Done\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n this.log('info', `Done downloading product #${product.id}`);\n this.emit('targetEnd', { target: product, isSkipped: false });\n this.emit('end', { aborted: false });\n this.#startPromise = null;\n resolve();\n })\n .finally(async () => {\n if (this.logger) {\n await this.logger.end();\n }\n this.#startPromise = null;\n });\n\n return this.#startPromise;\n }\n}\n"]}
@@ -0,0 +1,43 @@
1
+ import { Post } from '../../entities/Post.js';
2
+ import { Product } from '../../entities/Product.js';
3
+ import Logger, { LogLevel } from '../../utils/logging/Logger.js';
4
+ import { DownloaderConfig } from '../Downloader.js';
5
+ export interface StatusCacheData {
6
+ products: Record<string, StatusCacheEntry<Product>>;
7
+ posts: Record<string, StatusCacheEntry<Post>>;
8
+ }
9
+ export interface StatusCacheEntry<T extends Product | Post> {
10
+ type: T['type'];
11
+ downloaderVersion: string;
12
+ lastDownloaded: string;
13
+ lastDownloadHasErrors: boolean;
14
+ lastDownloadConfig: {
15
+ include: {
16
+ lockedContent: boolean;
17
+ contentInfo: boolean;
18
+ previewMedia: boolean;
19
+ contentMedia: boolean;
20
+ allMediaVariants: boolean;
21
+ };
22
+ };
23
+ lastDestDir: string;
24
+ lastTargetInfo: StatusCacheTargetInfo<T>;
25
+ }
26
+ export type StatusCacheTargetInfo<T extends Product | Post> = {
27
+ id: T['id'];
28
+ } & (T extends Post ? {
29
+ isViewable: T['isViewable'];
30
+ editedAt: T['editedAt'];
31
+ } : T extends Product ? {
32
+ isAccessible: T['isAccessible'];
33
+ } : {});
34
+ export default class StatusCache {
35
+ #private;
36
+ name: 'StatusCache';
37
+ constructor(statusCacheDir: string, logger: Logger | null | undefined, enabled: boolean);
38
+ static getInstance(statusCacheDir: string, logger?: Logger | null, enabled?: boolean): StatusCache;
39
+ validate<T extends Product | Post>(target: T, destDir: string, config: DownloaderConfig<any>): boolean;
40
+ updateOnDownload<T extends Product | Post>(target: T, destDir: string, downloadHasErrors: boolean, config: DownloaderConfig<any>): void;
41
+ protected log(level: LogLevel, ...msg: any[]): void;
42
+ }
43
+ //# sourceMappingURL=StatusCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusCache.d.ts","sourceRoot":"","sources":["../../../src/downloaders/cache/StatusCache.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAG9C,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,MAAM,EAAE,EAAE,QAAQ,EAAa,MAAM,+BAA+B,CAAC;AAM5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;IACpD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,OAAO,GAAG,IAAI;IACxD,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,qBAAqB,EAAE,OAAO,CAAC;IAC/B,kBAAkB,EAAE;QAClB,OAAO,EAAE;YACP,aAAa,EAAE,OAAO,CAAC;YACvB,WAAW,EAAE,OAAO,CAAC;YACrB,YAAY,EAAE,OAAO,CAAC;YACtB,YAAY,EAAE,OAAO,CAAC;YACtB,gBAAgB,EAAE,OAAO,CAAC;SAC3B,CAAC;KACH,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAC;CAC1C;AAKD,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,OAAO,GAAG,IAAI,IACxD;IACE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;CACb,GAAG,CACF,CAAC,SAAS,IAAI,GAAG;IACf,UAAU,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC;IAC5B,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;CACzB,GACD,CAAC,SAAS,OAAO,GAAG;IAClB,YAAY,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC;CACjC,GACD,EAAE,CACH,CAAA;AAEH,MAAM,CAAC,OAAO,OAAO,WAAW;;IAE9B,IAAI,EAAE,aAAa,CAAC;gBAUR,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,OAAO,EAAE,OAAO;IA2BvF,MAAM,CAAC,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,UAAO;IAcjF,QAAQ,CAAC,CAAC,SAAS,OAAO,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC;IAoH5F,gBAAgB,CAAC,CAAC,SAAS,OAAO,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC;IA2ChI,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,GAAG,EAAE,GAAG,EAAE;CAI7C"}
@@ -0,0 +1,206 @@
1
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
+ if (kind === "m") throw new TypeError("Private method is not writable");
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
+ };
7
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
+ };
12
+ var _StatusCache_instances, _a, _StatusCache_instances_1, _StatusCache_dir, _StatusCache_file, _StatusCache_data, _StatusCache_logger, _StatusCache_enabled, _StatusCache_validatePostCacheEntry, _StatusCache_validateProductCacheEntry, _StatusCache_getCacheEntry, _StatusCache_validateByDownloaderVer;
13
+ import fse from 'fs-extra';
14
+ import { major as semverMajor, minor as semverMinor } from 'semver';
15
+ import dateFormat from 'dateformat';
16
+ import { commonLog } from '../../utils/logging/Logger.js';
17
+ import ObjectHelper from '../../utils/ObjectHelper.js';
18
+ import ProductDownloader from '../ProductDownloader.js';
19
+ import PostDownloader from '../PostDownloader.js';
20
+ import path from 'path';
21
+ import FSHelper from '../../utils/FSHelper.js';
22
+ const STATUS_CACHE_FILENAME = 'status-cache.json';
23
+ const INSTANCE_CACHE_SIZE = 5;
24
+ export default class StatusCache {
25
+ constructor(statusCacheDir, logger, enabled) {
26
+ _StatusCache_instances.add(this);
27
+ _StatusCache_dir.set(this, void 0);
28
+ _StatusCache_file.set(this, void 0);
29
+ _StatusCache_data.set(this, void 0);
30
+ _StatusCache_logger.set(this, void 0);
31
+ _StatusCache_enabled.set(this, void 0);
32
+ __classPrivateFieldSet(this, _StatusCache_logger, logger, "f");
33
+ const file = path.resolve(statusCacheDir, STATUS_CACHE_FILENAME);
34
+ let data;
35
+ if (fse.existsSync(file)) {
36
+ data = fse.readJSONSync(file);
37
+ this.log('debug', `Loaded status cache file "${file}"`);
38
+ }
39
+ else {
40
+ FSHelper.createDir(statusCacheDir);
41
+ this.log('debug', `"${file}" does not exist. Start with empty data`);
42
+ data = {
43
+ products: {},
44
+ posts: {}
45
+ };
46
+ }
47
+ if (!enabled) {
48
+ this.log('debug', 'Status cache entry validation disabled');
49
+ }
50
+ __classPrivateFieldSet(this, _StatusCache_dir, statusCacheDir, "f");
51
+ __classPrivateFieldSet(this, _StatusCache_file, file, "f");
52
+ __classPrivateFieldSet(this, _StatusCache_data, data, "f");
53
+ __classPrivateFieldSet(this, _StatusCache_enabled, enabled, "f");
54
+ }
55
+ static getInstance(statusCacheDir, logger, enabled = true) {
56
+ const cachedInstance = __classPrivateFieldGet(this, _a, "f", _StatusCache_instances_1).find((sc) => __classPrivateFieldGet(sc, _StatusCache_dir, "f") === statusCacheDir && __classPrivateFieldGet(sc, _StatusCache_logger, "f") === logger && __classPrivateFieldGet(sc, _StatusCache_enabled, "f") === enabled);
57
+ if (cachedInstance) {
58
+ return cachedInstance;
59
+ }
60
+ const instance = new StatusCache(statusCacheDir, logger, enabled);
61
+ __classPrivateFieldGet(this, _a, "f", _StatusCache_instances_1).push(instance);
62
+ if (__classPrivateFieldGet(this, _a, "f", _StatusCache_instances_1).length > INSTANCE_CACHE_SIZE) {
63
+ __classPrivateFieldGet(this, _a, "f", _StatusCache_instances_1).shift();
64
+ }
65
+ return instance;
66
+ }
67
+ validate(target, destDir, config) {
68
+ if (!__classPrivateFieldGet(this, _StatusCache_enabled, "f")) {
69
+ return false;
70
+ }
71
+ const entry = target.type === 'product' ? __classPrivateFieldGet(this, _StatusCache_instances, "m", _StatusCache_getCacheEntry).call(this, target.id, 'product') :
72
+ target.type === 'post' ? __classPrivateFieldGet(this, _StatusCache_instances, "m", _StatusCache_getCacheEntry).call(this, target.id, 'post') :
73
+ null;
74
+ if (!entry) {
75
+ this.log('debug', `Status cache entry does not exist for ${target.type} #${target.id}`);
76
+ return false;
77
+ }
78
+ this.log('debug', `Validate status cache entry for ${target.type} #${target.id}; last downloaded: ${entry.lastDownloaded}; dest dir: "${entry.lastDestDir}"`);
79
+ if (!entry.lastDestDir) {
80
+ this.log('debug', '-> Invalidated: \'lastDestDir\' missing in status cache entry');
81
+ return false;
82
+ }
83
+ // `entry.lastDestDir` is relative to the dir of status cache. Resolve to absolute.
84
+ const lastDestDir = path.resolve(__classPrivateFieldGet(this, _StatusCache_dir, "f"), entry.lastDestDir);
85
+ if (lastDestDir !== destDir) {
86
+ this.log('debug', `-> Invalidated: destination directory has changed from "${lastDestDir}" to "${destDir}"`);
87
+ return false;
88
+ }
89
+ if (!fse.existsSync(lastDestDir)) {
90
+ this.log('debug', `-> Invalidated: destination directory "${lastDestDir}" does not exist`);
91
+ return false;
92
+ }
93
+ if (!__classPrivateFieldGet(this, _StatusCache_instances, "m", _StatusCache_validateByDownloaderVer).call(this, entry.downloaderVersion, ProductDownloader.version)) {
94
+ this.log('debug', '-> Invalidated: downloader version has changed (major / minor)');
95
+ return false;
96
+ }
97
+ if (entry.lastDownloadHasErrors) {
98
+ this.log('debug', '-> Invalidated: last download has errors');
99
+ return false;
100
+ }
101
+ if (!entry.lastDownloadConfig?.include) {
102
+ this.log('debug', '-> Invalidated: \'lastDownloadConfig.include\' missing in status cache entry');
103
+ return false;
104
+ }
105
+ const __compareConfigInclude = (prop) => {
106
+ const last = entry.lastDownloadConfig.include[prop];
107
+ const now = config.include[prop];
108
+ if (!last && now) { // Only check for 'false' -> 'true'
109
+ this.log('debug', `-> Invalidated: downloader config 'include.${prop}' has changed from '${last}' -> '${now}'`);
110
+ return false;
111
+ }
112
+ return true;
113
+ };
114
+ const includeProps = ['lockedContent', 'contentInfo', 'previewMedia', 'contentMedia', 'allMediaVariants'];
115
+ for (const prop of includeProps) {
116
+ if (!__compareConfigInclude(prop)) {
117
+ return false;
118
+ }
119
+ }
120
+ if (!entry.lastTargetInfo) {
121
+ this.log('debug', '-> Invalidated: \'lastTargetInfo\' missing in status cache entry');
122
+ return false;
123
+ }
124
+ if (target.type === 'post' && entry.type === 'post' && !__classPrivateFieldGet(this, _StatusCache_instances, "m", _StatusCache_validatePostCacheEntry).call(this, entry, target)) {
125
+ return false;
126
+ }
127
+ if (target.type === 'product' && entry.type === 'product' && !__classPrivateFieldGet(this, _StatusCache_instances, "m", _StatusCache_validateProductCacheEntry).call(this, entry, target)) {
128
+ return false;
129
+ }
130
+ this.log('debug', '-> Validated');
131
+ return true;
132
+ }
133
+ updateOnDownload(target, destDir, downloadHasErrors, config) {
134
+ const commonData = {
135
+ lastDownloaded: dateFormat('isoDateTime'),
136
+ lastDownloadHasErrors: downloadHasErrors,
137
+ // Convert `destDir` to path relative to status cache dir
138
+ lastDestDir: path.relative(__classPrivateFieldGet(this, _StatusCache_dir, "f"), destDir),
139
+ lastDownloadConfig: {
140
+ include: {
141
+ lockedContent: config.include.lockedContent,
142
+ contentInfo: config.include.contentInfo,
143
+ previewMedia: config.include.previewMedia,
144
+ contentMedia: config.include.contentMedia,
145
+ allMediaVariants: config.include.allMediaVariants
146
+ }
147
+ }
148
+ };
149
+ if (target.type === 'product') {
150
+ __classPrivateFieldGet(this, _StatusCache_data, "f").products[target.id] = {
151
+ type: 'product',
152
+ downloaderVersion: ProductDownloader.version,
153
+ ...commonData,
154
+ lastTargetInfo: {
155
+ id: target.id,
156
+ isAccessible: target.isAccessible
157
+ }
158
+ };
159
+ }
160
+ else if (target.type === 'post') {
161
+ __classPrivateFieldGet(this, _StatusCache_data, "f").posts[target.id] = {
162
+ type: 'post',
163
+ downloaderVersion: PostDownloader.version,
164
+ ...commonData,
165
+ lastTargetInfo: {
166
+ id: target.id,
167
+ isViewable: target.isViewable,
168
+ editedAt: target.editedAt
169
+ }
170
+ };
171
+ }
172
+ this.log('debug', `Update status cache for ${target.type} #${target.id}`);
173
+ fse.writeJsonSync(__classPrivateFieldGet(this, _StatusCache_file, "f"), __classPrivateFieldGet(this, _StatusCache_data, "f"), { spaces: 2 });
174
+ }
175
+ log(level, ...msg) {
176
+ commonLog(__classPrivateFieldGet(this, _StatusCache_logger, "f"), level, this.name, ...msg);
177
+ }
178
+ }
179
+ _a = StatusCache, _StatusCache_dir = new WeakMap(), _StatusCache_file = new WeakMap(), _StatusCache_data = new WeakMap(), _StatusCache_logger = new WeakMap(), _StatusCache_enabled = new WeakMap(), _StatusCache_instances = new WeakSet(), _StatusCache_validatePostCacheEntry = function _StatusCache_validatePostCacheEntry(entry, post) {
180
+ if (entry.lastTargetInfo.isViewable !== post.isViewable) {
181
+ this.log('debug', `-> Invalidated: viewability has changed (before: ${entry.lastTargetInfo.isViewable}; now: ${post.isViewable})`);
182
+ return false;
183
+ }
184
+ if (entry.lastTargetInfo.editedAt !== post.editedAt) {
185
+ this.log('debug', `-> Invalidated: post has been edited (before: ${entry.lastTargetInfo.editedAt}; now: ${post.editedAt})`);
186
+ return false;
187
+ }
188
+ return true;
189
+ }, _StatusCache_validateProductCacheEntry = function _StatusCache_validateProductCacheEntry(entry, product) {
190
+ if (entry.lastTargetInfo.isAccessible !== product.isAccessible) {
191
+ this.log('debug', `-> Invalidated: product accessibility has changed (before: ${entry.lastTargetInfo.isAccessible}; now: ${product.isAccessible})`);
192
+ return false;
193
+ }
194
+ return true;
195
+ }, _StatusCache_getCacheEntry = function _StatusCache_getCacheEntry(targetId, targetType) {
196
+ const key = targetType === 'product' ? `products.${targetId}` : `posts.${targetId}`;
197
+ return ObjectHelper.getProperty(__classPrivateFieldGet(this, _StatusCache_data, "f"), key) || null;
198
+ }, _StatusCache_validateByDownloaderVer = function _StatusCache_validateByDownloaderVer(entryValue, currentValue) {
199
+ if (!entryValue) {
200
+ return false;
201
+ }
202
+ return semverMajor(entryValue) === semverMajor(currentValue) &&
203
+ semverMinor(entryValue) === semverMinor(currentValue);
204
+ };
205
+ _StatusCache_instances_1 = { value: [] };
206
+ //# sourceMappingURL=StatusCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusCache.js","sourceRoot":"","sources":["../../../src/downloaders/cache/StatusCache.ts"],"names":[],"mappings":"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","sourcesContent":["import fse from 'fs-extra';\nimport { Post } from '../../entities/Post.js';\nimport { major as semverMajor, minor as semverMinor } from 'semver';\nimport dateFormat from 'dateformat';\nimport { Product } from '../../entities/Product.js';\nimport Logger, { LogLevel, commonLog } from '../../utils/logging/Logger.js';\nimport ObjectHelper from '../../utils/ObjectHelper.js';\nimport ProductDownloader from '../ProductDownloader.js';\nimport PostDownloader from '../PostDownloader.js';\nimport path from 'path';\nimport FSHelper from '../../utils/FSHelper.js';\nimport { DownloaderConfig } from '../Downloader.js';\n\nexport interface StatusCacheData {\n products: Record<string, StatusCacheEntry<Product>>;\n posts: Record<string, StatusCacheEntry<Post>>;\n}\n\nexport interface StatusCacheEntry<T extends Product | Post> {\n type: T['type'];\n downloaderVersion: string;\n lastDownloaded: string;\n lastDownloadHasErrors: boolean;\n lastDownloadConfig: {\n include: {\n lockedContent: boolean;\n contentInfo: boolean;\n previewMedia: boolean;\n contentMedia: boolean;\n allMediaVariants: boolean;\n };\n };\n lastDestDir: string;\n lastTargetInfo: StatusCacheTargetInfo<T>;\n}\n\nconst STATUS_CACHE_FILENAME = 'status-cache.json';\nconst INSTANCE_CACHE_SIZE = 5;\n\nexport type StatusCacheTargetInfo<T extends Product | Post> =\n {\n id: T['id'];\n } & (\n T extends Post ? {\n isViewable: T['isViewable'];\n editedAt: T['editedAt'];\n } :\n T extends Product ? {\n isAccessible: T['isAccessible'];\n } :\n {}\n )\n\nexport default class StatusCache {\n\n name: 'StatusCache';\n\n static #instances: StatusCache[] = [];\n\n #dir: string;\n #file: string;\n #data: StatusCacheData;\n #logger?: Logger | null;\n #enabled: boolean;\n\n constructor(statusCacheDir: string, logger: Logger | null | undefined, enabled: boolean) {\n this.#logger = logger;\n\n const file = path.resolve(statusCacheDir, STATUS_CACHE_FILENAME);\n let data: StatusCacheData;\n if (fse.existsSync(file)) {\n data = fse.readJSONSync(file);\n this.log('debug', `Loaded status cache file \"${file}\"`);\n }\n else {\n FSHelper.createDir(statusCacheDir);\n this.log('debug', `\"${file}\" does not exist. Start with empty data`);\n data = {\n products: {},\n posts: {}\n };\n }\n if (!enabled) {\n this.log('debug', 'Status cache entry validation disabled');\n }\n\n this.#dir = statusCacheDir;\n this.#file = file;\n this.#data = data;\n this.#enabled = enabled;\n }\n\n static getInstance(statusCacheDir: string, logger?: Logger | null, enabled = true) {\n const cachedInstance = this.#instances.find(\n (sc) => sc.#dir === statusCacheDir && sc.#logger === logger && sc.#enabled === enabled);\n if (cachedInstance) {\n return cachedInstance;\n }\n const instance = new StatusCache(statusCacheDir, logger, enabled);\n this.#instances.push(instance);\n if (this.#instances.length > INSTANCE_CACHE_SIZE) {\n this.#instances.shift();\n }\n return instance;\n }\n\n validate<T extends Product | Post>(target: T, destDir: string, config: DownloaderConfig<any>) {\n if (!this.#enabled) {\n return false;\n }\n\n const entry =\n target.type === 'product' ? this.#getCacheEntry(target.id, 'product') :\n target.type === 'post' ? this.#getCacheEntry(target.id, 'post') :\n null;\n\n if (!entry) {\n this.log('debug', `Status cache entry does not exist for ${target.type} #${target.id}`);\n return false;\n }\n\n this.log('debug', `Validate status cache entry for ${target.type} #${target.id}; last downloaded: ${entry.lastDownloaded}; dest dir: \"${entry.lastDestDir}\"`);\n\n if (!entry.lastDestDir) {\n this.log('debug', '-> Invalidated: \\'lastDestDir\\' missing in status cache entry');\n return false;\n }\n // `entry.lastDestDir` is relative to the dir of status cache. Resolve to absolute.\n const lastDestDir = path.resolve(this.#dir, entry.lastDestDir);\n if (lastDestDir !== destDir) {\n this.log('debug', `-> Invalidated: destination directory has changed from \"${lastDestDir}\" to \"${destDir}\"`);\n return false;\n }\n if (!fse.existsSync(lastDestDir)) {\n this.log('debug', `-> Invalidated: destination directory \"${lastDestDir}\" does not exist`);\n return false;\n }\n\n if (!this.#validateByDownloaderVer(entry.downloaderVersion, ProductDownloader.version)) {\n this.log('debug', '-> Invalidated: downloader version has changed (major / minor)');\n return false;\n }\n\n if (entry.lastDownloadHasErrors) {\n this.log('debug', '-> Invalidated: last download has errors');\n return false;\n }\n\n if (!entry.lastDownloadConfig?.include) {\n this.log('debug', '-> Invalidated: \\'lastDownloadConfig.include\\' missing in status cache entry');\n return false;\n }\n\n const __compareConfigInclude = (prop: keyof StatusCacheEntry<T>['lastDownloadConfig']['include'] & keyof DownloaderConfig<any>['include']) => {\n const last = entry.lastDownloadConfig.include[prop];\n const now = config.include[prop];\n if (!last && now) { // Only check for 'false' -> 'true'\n this.log('debug', `-> Invalidated: downloader config 'include.${prop}' has changed from '${last}' -> '${now}'`);\n return false;\n }\n return true;\n };\n\n const includeProps: Array<keyof StatusCacheEntry<T>['lastDownloadConfig']['include']> =\n [ 'lockedContent', 'contentInfo', 'previewMedia', 'contentMedia', 'allMediaVariants' ];\n for (const prop of includeProps) {\n if (!__compareConfigInclude(prop)) {\n return false;\n }\n }\n\n if (!entry.lastTargetInfo) {\n this.log('debug', '-> Invalidated: \\'lastTargetInfo\\' missing in status cache entry');\n return false;\n }\n\n if (target.type === 'post' && entry.type === 'post' && !this.#validatePostCacheEntry(entry, target)) {\n return false;\n }\n if (target.type === 'product' && entry.type === 'product' && !this.#validateProductCacheEntry(entry, target)) {\n return false;\n }\n\n this.log('debug', '-> Validated');\n return true;\n }\n\n #validatePostCacheEntry(entry: StatusCacheEntry<Post>, post: Post) {\n if (entry.lastTargetInfo.isViewable !== post.isViewable) {\n this.log('debug', `-> Invalidated: viewability has changed (before: ${entry.lastTargetInfo.isViewable}; now: ${post.isViewable})`);\n return false;\n }\n if (entry.lastTargetInfo.editedAt !== post.editedAt) {\n this.log('debug', `-> Invalidated: post has been edited (before: ${entry.lastTargetInfo.editedAt}; now: ${post.editedAt})`);\n return false;\n }\n return true;\n }\n\n #validateProductCacheEntry(entry: StatusCacheEntry<Product>, product: Product) {\n if (entry.lastTargetInfo.isAccessible !== product.isAccessible) {\n this.log('debug', `-> Invalidated: product accessibility has changed (before: ${entry.lastTargetInfo.isAccessible}; now: ${product.isAccessible})`);\n return false;\n }\n return true;\n }\n\n #getCacheEntry(targetId: string, targetType: 'post'): StatusCacheEntry<Post> | null;\n #getCacheEntry(targetId: string, targetType: 'product'): StatusCacheEntry<Product> | null;\n #getCacheEntry(targetId: string, targetType: 'product' | 'post') {\n const key = targetType === 'product' ? `products.${targetId}` : `posts.${targetId}`;\n return ObjectHelper.getProperty(this.#data, key) || null;\n }\n\n #validateByDownloaderVer(entryValue: string, currentValue: string) {\n if (!entryValue) {\n return false;\n }\n return semverMajor(entryValue) === semverMajor(currentValue) &&\n semverMinor(entryValue) === semverMinor(currentValue);\n }\n\n updateOnDownload<T extends Product | Post>(target: T, destDir: string, downloadHasErrors: boolean, config: DownloaderConfig<any>) {\n const commonData = {\n lastDownloaded: dateFormat('isoDateTime'),\n lastDownloadHasErrors: downloadHasErrors,\n // Convert `destDir` to path relative to status cache dir\n lastDestDir: path.relative(this.#dir, destDir),\n lastDownloadConfig: {\n include: {\n lockedContent: config.include.lockedContent,\n contentInfo: config.include.contentInfo,\n previewMedia: config.include.previewMedia,\n contentMedia: config.include.contentMedia,\n allMediaVariants: config.include.allMediaVariants\n }\n }\n };\n if (target.type === 'product') {\n this.#data.products[target.id] = {\n type: 'product',\n downloaderVersion: ProductDownloader.version,\n ...commonData,\n lastTargetInfo: {\n id: target.id,\n isAccessible: target.isAccessible\n }\n };\n }\n else if (target.type === 'post') {\n this.#data.posts[target.id] = {\n type: 'post',\n downloaderVersion: PostDownloader.version,\n ...commonData,\n lastTargetInfo: {\n id: target.id,\n isViewable: target.isViewable,\n editedAt: target.editedAt\n }\n };\n }\n this.log('debug', `Update status cache for ${target.type} #${target.id}`);\n fse.writeJsonSync(this.#file, this.#data, { spaces: 2 });\n }\n\n protected log(level: LogLevel, ...msg: any[]) {\n commonLog(this.#logger, level, this.name, ...msg);\n }\n\n}\n"]}
@@ -0,0 +1,7 @@
1
+ export * from './Bootstrap.js';
2
+ export * from './Downloader.js';
3
+ export * from './DownloaderEvent.js';
4
+ export { FileExistsAction, DownloaderInit, DownloaderOptions } from './DownloaderOptions.js';
5
+ export { default as PostDownloader } from './PostDownloader.js';
6
+ export { default as ProductDownloader } from './ProductDownloader.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/downloaders/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './Bootstrap.js';
2
+ export * from './Downloader.js';
3
+ export * from './DownloaderEvent.js';
4
+ export { default as PostDownloader } from './PostDownloader.js';
5
+ export { default as ProductDownloader } from './ProductDownloader.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/downloaders/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AAErC,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,wBAAwB,CAAC","sourcesContent":["export * from './Bootstrap.js';\nexport * from './Downloader.js';\nexport * from './DownloaderEvent.js';\nexport { FileExistsAction, DownloaderInit, DownloaderOptions } from './DownloaderOptions.js';\nexport { default as PostDownloader } from './PostDownloader.js';\nexport { default as ProductDownloader } from './ProductDownloader.js';\n"]}
@@ -0,0 +1,89 @@
1
+ import { Downloadable } from '../../entities/Downloadable.js';
2
+ import Logger, { LogLevel } from '../../utils/logging/Logger.js';
3
+ export declare class DownloadTaskError extends Error {
4
+ task: IDownloadTask;
5
+ cause?: Error;
6
+ constructor(message: string, task: IDownloadTask, cause?: Error);
7
+ }
8
+ export type DownloadTaskSkipReason = {
9
+ message: string;
10
+ } & ({
11
+ name: 'destFileExists';
12
+ existingDestFilePath: string;
13
+ } | {
14
+ name: 'other';
15
+ });
16
+ export interface DownloadProgress {
17
+ destFilename: string;
18
+ destFilePath: string;
19
+ lengthUnit: string;
20
+ length: number;
21
+ lengthDownloaded: number;
22
+ percent: number;
23
+ sizeDownloaded: number;
24
+ speed: number;
25
+ }
26
+ export interface DownloadTaskParams<T extends Downloadable = Downloadable> {
27
+ src: string;
28
+ srcEntity: T;
29
+ maxRetries: number;
30
+ callbacks: DownloadTaskCallbacks | null;
31
+ logger?: Logger | null;
32
+ }
33
+ export interface DownloadTaskCallbacks {
34
+ onStart: (task: DownloadTask) => void;
35
+ onProgress: (task: DownloadTask, progress: DownloadProgress | null) => void;
36
+ onComplete: (task: DownloadTask) => void;
37
+ onAbort: (task: DownloadTask) => void;
38
+ onSkip: (task: DownloadTask, reason: DownloadTaskSkipReason) => void;
39
+ onError: (error: DownloadTaskError, willRetry: boolean) => void;
40
+ onSpawn: (origin: DownloadTask, spawn: DownloadTask) => void;
41
+ }
42
+ export type DownloadTaskStatus = 'pending' | 'pending-retry' | // Pending retry on error
43
+ 'downloading' | 'error' | 'completed' | 'aborted' | 'skipped';
44
+ export interface IDownloadTask {
45
+ id: number;
46
+ src: string;
47
+ srcEntity: Downloadable;
48
+ retryCount: number;
49
+ resolvedDestFilename: string | null;
50
+ resolvedDestPath: string | null;
51
+ getProgress: () => DownloadProgress | null;
52
+ }
53
+ export default abstract class DownloadTask<T extends Downloadable = Downloadable> implements IDownloadTask {
54
+ #private;
55
+ protected abstract name: string;
56
+ constructor(params: DownloadTaskParams<T>);
57
+ protected abstract doStart(): Promise<void>;
58
+ protected abstract doAbort(): Promise<void>;
59
+ protected abstract doDestroy(): Promise<void>;
60
+ protected abstract doGetProgress(): DownloadProgress | null | undefined;
61
+ start(): Promise<void>;
62
+ abort(): Promise<void>;
63
+ getProgress(): DownloadProgress | null;
64
+ protected notifyStart(): void;
65
+ protected notifyProgress(progress: DownloadProgress | null): void;
66
+ protected notifyComplete(): void;
67
+ protected notifyAbort(): void;
68
+ protected notifySkip(reason: DownloadTaskSkipReason): void;
69
+ protected notifyError(error: any): void;
70
+ isRunning(): boolean;
71
+ isAborting(): boolean;
72
+ hasEnded(): boolean;
73
+ get id(): number;
74
+ set id(value: number);
75
+ get src(): string;
76
+ get resolvedDestFilename(): string | null;
77
+ get resolvedDestPath(): string | null;
78
+ protected set resolvedDestPath(value: string | null);
79
+ get srcEntity(): T;
80
+ protected get maxRetries(): number;
81
+ get retryCount(): number;
82
+ get status(): DownloadTaskStatus;
83
+ protected set status(value: DownloadTaskStatus);
84
+ protected get callbacks(): DownloadTaskCallbacks | null;
85
+ setCallbacks(value: DownloadTaskCallbacks | null): void;
86
+ protected log(level: LogLevel, ...msg: Array<any>): void;
87
+ protected get logger(): Logger | null | undefined;
88
+ }
89
+ //# sourceMappingURL=DownloadTask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DownloadTask.d.ts","sourceRoot":"","sources":["../../../src/downloaders/task/DownloadTask.ts"],"names":[],"mappings":"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"}