patreon-dl 2.0.0 → 2.1.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 (85) hide show
  1. package/README.md +7 -0
  2. package/dist/downloaders/Downloader.d.ts +2 -2
  3. package/dist/downloaders/Downloader.d.ts.map +1 -1
  4. package/dist/downloaders/Downloader.js +26 -8
  5. package/dist/downloaders/Downloader.js.map +1 -1
  6. package/dist/downloaders/PostDownloader.d.ts.map +1 -1
  7. package/dist/downloaders/PostDownloader.js +8 -4
  8. package/dist/downloaders/PostDownloader.js.map +1 -1
  9. package/dist/downloaders/ProductDownloader.d.ts.map +1 -1
  10. package/dist/downloaders/ProductDownloader.js +5 -1
  11. package/dist/downloaders/ProductDownloader.js.map +1 -1
  12. package/dist/downloaders/task/DownloadTask.d.ts +9 -1
  13. package/dist/downloaders/task/DownloadTask.d.ts.map +1 -1
  14. package/dist/downloaders/task/DownloadTask.js +67 -4
  15. package/dist/downloaders/task/DownloadTask.js.map +1 -1
  16. package/dist/downloaders/task/DownloadTaskBatch.d.ts +7 -0
  17. package/dist/downloaders/task/DownloadTaskBatch.d.ts.map +1 -1
  18. package/dist/downloaders/task/DownloadTaskBatch.js +30 -2
  19. package/dist/downloaders/task/DownloadTaskBatch.js.map +1 -1
  20. package/dist/downloaders/task/DownloadTaskFactory.d.ts +5 -2
  21. package/dist/downloaders/task/DownloadTaskFactory.d.ts.map +1 -1
  22. package/dist/downloaders/task/DownloadTaskFactory.js +12 -12
  23. package/dist/downloaders/task/DownloadTaskFactory.js.map +1 -1
  24. package/dist/downloaders/task/ExternalDownloaderTask.d.ts +1 -0
  25. package/dist/downloaders/task/ExternalDownloaderTask.d.ts.map +1 -1
  26. package/dist/downloaders/task/ExternalDownloaderTask.js +3 -0
  27. package/dist/downloaders/task/ExternalDownloaderTask.js.map +1 -1
  28. package/dist/downloaders/task/FFmpegDownloadTaskBase.js +1 -1
  29. package/dist/downloaders/task/FFmpegDownloadTaskBase.js.map +1 -1
  30. package/dist/downloaders/task/FetcherDownloadTask.d.ts +1 -0
  31. package/dist/downloaders/task/FetcherDownloadTask.d.ts.map +1 -1
  32. package/dist/downloaders/task/FetcherDownloadTask.js +20 -7
  33. package/dist/downloaders/task/FetcherDownloadTask.js.map +1 -1
  34. package/dist/downloaders/task/M3U8DownloadTask.d.ts +1 -0
  35. package/dist/downloaders/task/M3U8DownloadTask.d.ts.map +1 -1
  36. package/dist/downloaders/task/M3U8DownloadTask.js +3 -0
  37. package/dist/downloaders/task/M3U8DownloadTask.js.map +1 -1
  38. package/dist/downloaders/task/YouTubeDownloadTask.d.ts +1 -0
  39. package/dist/downloaders/task/YouTubeDownloadTask.d.ts.map +1 -1
  40. package/dist/downloaders/task/YouTubeDownloadTask.js +4 -0
  41. package/dist/downloaders/task/YouTubeDownloadTask.js.map +1 -1
  42. package/dist/entities/Downloadable.d.ts +1 -2
  43. package/dist/entities/Downloadable.d.ts.map +1 -1
  44. package/dist/entities/Downloadable.js.map +1 -1
  45. package/dist/entities/MediaItem.d.ts +5 -1
  46. package/dist/entities/MediaItem.d.ts.map +1 -1
  47. package/dist/entities/MediaItem.js.map +1 -1
  48. package/dist/entities/index.d.ts +0 -1
  49. package/dist/entities/index.d.ts.map +1 -1
  50. package/dist/entities/index.js +0 -1
  51. package/dist/entities/index.js.map +1 -1
  52. package/dist/parsers/Parser.d.ts +6 -6
  53. package/dist/parsers/Parser.d.ts.map +1 -1
  54. package/dist/parsers/Parser.js +32 -23
  55. package/dist/parsers/Parser.js.map +1 -1
  56. package/dist/parsers/PostParser.d.ts.map +1 -1
  57. package/dist/parsers/PostParser.js +7 -2
  58. package/dist/parsers/PostParser.js.map +1 -1
  59. package/dist/utils/FSHelper.d.ts +1 -1
  60. package/dist/utils/FSHelper.d.ts.map +1 -1
  61. package/dist/utils/FSHelper.js +2 -2
  62. package/dist/utils/FSHelper.js.map +1 -1
  63. package/dist/utils/Fetcher.d.ts +9 -4
  64. package/dist/utils/Fetcher.d.ts.map +1 -1
  65. package/dist/utils/Fetcher.js +27 -29
  66. package/dist/utils/Fetcher.js.map +1 -1
  67. package/dist/utils/FilenameFormatHelper.d.ts +0 -2
  68. package/dist/utils/FilenameFormatHelper.d.ts.map +1 -1
  69. package/dist/utils/FilenameFormatHelper.js +0 -9
  70. package/dist/utils/FilenameFormatHelper.js.map +1 -1
  71. package/dist/utils/URLHelper.d.ts.map +1 -1
  72. package/dist/utils/URLHelper.js +13 -4
  73. package/dist/utils/URLHelper.js.map +1 -1
  74. package/dist/utils/logging/ConsoleLogger.d.ts.map +1 -1
  75. package/dist/utils/logging/ConsoleLogger.js +4 -0
  76. package/dist/utils/logging/ConsoleLogger.js.map +1 -1
  77. package/package.json +2 -1
  78. package/dist/entities/Attachment.d.ts +0 -7
  79. package/dist/entities/Attachment.d.ts.map +0 -1
  80. package/dist/entities/Attachment.js +0 -2
  81. package/dist/entities/Attachment.js.map +0 -1
  82. package/dist/utils/AttachmentFilenameResolver.d.ts +0 -8
  83. package/dist/utils/AttachmentFilenameResolver.d.ts.map +0 -1
  84. package/dist/utils/AttachmentFilenameResolver.js +0 -70
  85. package/dist/utils/AttachmentFilenameResolver.js.map +0 -1
package/README.md CHANGED
@@ -95,6 +95,7 @@ https://www.patreon.com/<creator>/shop/<slug>-<product_id>
95
95
 
96
96
  // Download posts by creator
97
97
  https://www.patreon.com/<creator>/posts
98
+ https://www.patreon.com/c/<creator>/posts
98
99
  https://www.patreon.com/user/posts?u=<user_id>
99
100
 
100
101
  // Dowload a single post
@@ -649,6 +650,12 @@ Each event emitted by a download task batch has a payload, which is an object wi
649
650
 
650
651
  ## Changelog
651
652
 
653
+ v2.1.0
654
+ - Fix attachment downloads following API changes ([#40](https://github.com/patrickkfkan/patreon-dl/issues/40))
655
+ - Add support for URL format: `https://www.patreon.com/c/<creator>/posts`
656
+ - Check and resolve conflicting destination paths ([#38](https://github.com/patrickkfkan/patreon-dl/issues/38))
657
+ - Parse inline content media ([#40](https://github.com/patrickkfkan/patreon-dl/issues/40))
658
+
652
659
  v2.0.0
653
660
  - Replace [node-fetch](https://github.com/node-fetch/node-fetch) with Fetch API; required Node.js version bumped to v18 or higher.
654
661
  - Update dependencies and libraries
@@ -29,8 +29,8 @@ export default abstract class Downloader<T extends DownloaderType> extends Event
29
29
  protected config: DownloaderConfig<T>;
30
30
  protected logger?: Logger | null;
31
31
  constructor(bootstrap: DownloaderBootstrapData<T>, options?: DownloaderOptions);
32
- protected createDownloadTaskBatch(name: string, ...createTasks: Array<CreateDownloadTaskParams | null>): DownloadTaskBatch;
33
- protected addToDownloadTaskBatch(batch: DownloadTaskBatch, ...createTasks: Array<CreateDownloadTaskParams | null>): DownloadTaskBatch;
32
+ protected createDownloadTaskBatch(name: string, signal?: AbortSignal, ...createTasks: Array<CreateDownloadTaskParams | null>): Promise<DownloadTaskBatch>;
33
+ protected addToDownloadTaskBatch(batch: DownloadTaskBatch, signal?: AbortSignal, ...createTasks: Array<CreateDownloadTaskParams | null>): Promise<DownloadTaskBatch>;
34
34
  abstract start(params: DownloaderStartParams): Promise<void>;
35
35
  static getInstance(url: string, options?: DownloaderOptions): Promise<import("./PostDownloader.js").default | import("./ProductDownloader.js").default>;
36
36
  static getCampaign(creator: string | UserIdOrVanityParam, signal?: AbortSignal, logger?: Logger | null): Promise<Campaign | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"Downloader.d.ts","sourceRoot":"","sources":["../../src/downloaders/Downloader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Downloader.d.ts","sourceRoot":"","sources":["../../src/downloaders/Downloader.ts"],"names":[],"mappings":"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"}
@@ -50,7 +50,7 @@ class Downloader extends EventEmitter {
50
50
  }
51
51
  __classPrivateFieldSet(this, _Downloader_hasEmittedEndEventOnAbort, false, "f");
52
52
  }
53
- createDownloadTaskBatch(name, ...createTasks) {
53
+ createDownloadTaskBatch(name, signal, ...createTasks) {
54
54
  const __getDownloadIdString = (task, batch) => {
55
55
  let result = `#${batch.id}.${task.id}`;
56
56
  if (task.retryCount > 0) {
@@ -61,7 +61,8 @@ class Downloader extends EventEmitter {
61
61
  const batch = new DownloadTaskBatch({
62
62
  name,
63
63
  fetcher: this.fetcher,
64
- limiter: this.config.request
64
+ limiter: this.config.request,
65
+ logger: this.logger
65
66
  });
66
67
  batch.on('taskStart', ({ task }) => {
67
68
  const retryOrBeginStr = task.retryCount > 0 ? 'retry' : 'begin';
@@ -125,9 +126,9 @@ class Downloader extends EventEmitter {
125
126
  ].join('; ');
126
127
  this.log('info', `Download batch complete (#${batch.id}): ${counts}`);
127
128
  });
128
- return this.addToDownloadTaskBatch(batch, ...createTasks);
129
+ return this.addToDownloadTaskBatch(batch, signal, ...createTasks);
129
130
  }
130
- addToDownloadTaskBatch(batch, ...createTasks) {
131
+ async addToDownloadTaskBatch(batch, signal, ...createTasks) {
131
132
  let failedCreateTaskCount = 0;
132
133
  for (const task of createTasks) {
133
134
  if (!task) {
@@ -142,19 +143,32 @@ class Downloader extends EventEmitter {
142
143
  let createdCount = 0;
143
144
  for (const tt of target) {
144
145
  try {
145
- const tasks = DownloadTaskFactory.createFromDownloadable({
146
+ const tasks = await DownloadTaskFactory.createFromDownloadable({
146
147
  config: this.config,
147
148
  item: tt,
148
149
  destDir,
149
150
  fetcher: this.fetcher,
150
151
  fileExistsAction: task.fileExistsAction,
152
+ limiter: batch.limiter,
153
+ signal,
151
154
  logger: this.logger
152
155
  });
153
- batch.addTasks(tasks);
156
+ // Filter out tasks that are DOA (errors that occurred in DownloadTask.create())
157
+ for (const task of tasks) {
158
+ if (task.doa) {
159
+ this.log('error', `Failed to create download task for item #${tt.id} in ${targetName}:`, task.doa.msg, task.doa.cause);
160
+ failedCreateTaskCount++;
161
+ }
162
+ }
163
+ batch.addTasks(tasks.filter((task) => !task.doa));
154
164
  createdCount += tasks.length;
155
165
  }
156
166
  catch (error) {
157
- this.log('error', `Failed to create download task for item #${tt.id} in ${targetName}:`, error);
167
+ if (signal?.aborted) {
168
+ this.log('warn', 'Operation aborted');
169
+ return batch;
170
+ }
171
+ this.log('error', `Failed to create download task(s) for item #${tt.id} in ${targetName}:`, error);
158
172
  failedCreateTaskCount++;
159
173
  }
160
174
  }
@@ -262,12 +276,16 @@ class Downloader extends EventEmitter {
262
276
  campaignMedia.push(reward.image);
263
277
  }
264
278
  }
265
- batch = this.createDownloadTaskBatch(`Campaign #${campaign.id} (${campaign.name})`, {
279
+ batch = await this.createDownloadTaskBatch(`Campaign #${campaign.id} (${campaign.name})`, signal, {
266
280
  target: campaignMedia,
267
281
  targetName: `campaign #${campaign.id} -> images`,
268
282
  destDir: campaignDirs.info,
269
283
  fileExistsAction: this.config.fileExistsAction.info
270
284
  });
285
+ if (this.checkAbortSignal(signal, resolve)) {
286
+ return;
287
+ }
288
+ batch.prestart();
271
289
  this.emit('phaseBegin', { target: campaign, phase: 'batchDownload', batch });
272
290
  await batch.start();
273
291
  await batch.destroy();
@@ -1 +1 @@
1
- {"version":3,"file":"Downloader.js","sourceRoot":"","sources":["../../src/downloaders/Downloader.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport { EventEmitter } from 'events';\nimport deepFreeze from 'deep-freeze';\nimport Fetcher from '../utils/Fetcher.js';\nimport Bootstrap, { type DownloaderBootstrapData, type DownloaderType } from './Bootstrap.js';\nimport { type DownloaderInit, type DownloaderOptions, type FileExistsAction, getDownloaderInit } from './DownloaderOptions.js';\nimport { type DownloaderEvent, type DownloaderEventPayloadOf } from './DownloaderEvent.js';\nimport {type LogLevel} from '../utils/logging/Logger.js';\nimport type Logger from '../utils/logging/Logger.js';\nimport { commonLog } from '../utils/logging/Logger.js';\nimport { type Campaign } from '../entities/Campaign.js';\nimport FSHelper, { type WriteTextFileResult } from '../utils/FSHelper.js';\nimport DownloadTaskBatch from './task/DownloadTaskBatch.js';\nimport { type IDownloadTask } from './task/DownloadTask.js';\nimport DownloadTaskFactory from './task/DownloadTaskFactory.js';\nimport FilenameFormatHelper from '../utils/FilenameFormatHelper.js';\nimport { type Downloadable } from '../entities/Downloadable.js';\nimport { generateCampaignSummary } from './templates/CampaignInfo.js';\nimport path from 'path';\nimport URLHelper from '../utils/URLHelper.js';\nimport ffmpeg from 'fluent-ffmpeg';\nimport InnertubeLoader from '../utils/InnertubeLoader.js';\nimport FFmpegDownloadTaskBase from './task/FFmpegDownloadTaskBase.js';\nimport { type UserIdOrVanityParam } from '../entities/User.js';\nimport ExternalDownloaderTask from './task/ExternalDownloaderTask.js';\n\nexport type DownloaderConfig<T extends DownloaderType> =\n DownloaderInit &\n Omit<DownloaderBootstrapData<T>, 'type'>;\n\nexport interface DownloaderStartParams {\n signal?: AbortSignal;\n}\n\ninterface CreateDownloadTaskParams {\n target: Downloadable[];\n targetName: string;\n destDir: string;\n fileExistsAction: FileExistsAction;\n}\n\nexport default abstract class Downloader<T extends DownloaderType> extends EventEmitter {\n\n abstract name: string;\n\n protected fetcher: Fetcher;\n protected fsHelper: FSHelper;\n protected config: DownloaderConfig<T>;\n protected logger?: Logger | null;\n\n #hasEmittedEndEventOnAbort: boolean;\n\n constructor(bootstrap: DownloaderBootstrapData<T>, options?: DownloaderOptions) {\n super();\n this.#validateOptions(options);\n\n this.config = {\n ...bootstrap,\n ...getDownloaderInit(options)\n };\n\n this.fetcher = new Fetcher(this.config, options?.cookie, options?.logger);\n this.fsHelper = new FSHelper(this.config, this.logger);\n this.logger = options?.logger;\n\n if (this.config.pathToFFmpeg) {\n ffmpeg.setFfmpegPath(this.config.pathToFFmpeg);\n }\n\n InnertubeLoader.setLogger(this.logger);\n if (this.config.pathToYouTubeCredentials) {\n InnertubeLoader.loadCredentials(this.config.pathToYouTubeCredentials);\n }\n\n this.#hasEmittedEndEventOnAbort = false;\n }\n\n protected createDownloadTaskBatch(name: string, ...createTasks: Array<CreateDownloadTaskParams | null>): DownloadTaskBatch {\n\n const __getDownloadIdString = (task: IDownloadTask, batch: DownloadTaskBatch) => {\n let result = `#${batch.id}.${task.id}`;\n if (task.retryCount > 0) {\n result += `-r${task.retryCount}`;\n }\n return result;\n };\n\n const batch = new DownloadTaskBatch({\n name,\n fetcher: this.fetcher,\n limiter: this.config.request\n });\n\n batch.on('taskStart', ({task}) => {\n const retryOrBeginStr = task.retryCount > 0 ? 'retry' : 'begin';\n const isExternal = task instanceof ExternalDownloaderTask;\n const destStr = isExternal ? ' -> Unknown destination (external process)' : task.resolvedDestFilename ? ` -> ${task.resolvedDestFilename}` : '';\n this.log('info', `Download ${retryOrBeginStr} (${__getDownloadIdString(task, batch)}): [type: ${task.srcEntity.type}; ID: #${task.srcEntity.id}]${destStr}`);\n if (task instanceof FFmpegDownloadTaskBase) {\n const retryOrBeginStr = task.retryCount > 0 ? 'Retry' : 'Begin';\n this.log('info', `${retryOrBeginStr} downloading through FFmpeg (${__getDownloadIdString(task, batch)}): ${task.commandLine}`);\n }\n });\n\n batch.on('taskComplete', ({task}) => {\n const isExternal = task instanceof ExternalDownloaderTask;\n const destStr = isExternal ? ': Unknown destination (external process)' : task.resolvedDestPath ? `: \"${task.resolvedDestPath}\"` : '';\n this.log('info', `Download complete (${__getDownloadIdString(task, batch)})${destStr}`);\n });\n\n batch.on('taskError', ({error, willRetry}) => {\n const { task, cause, message } = error;\n const retryStr = willRetry ? '- will retry' : '';\n this.log('error', `Download error (${__getDownloadIdString(task, batch)}):`, cause || message, `(${task.src})`, retryStr);\n });\n\n batch.on('taskAbort', ({task}) => {\n this.log('warn', `Download aborted (${__getDownloadIdString(task, batch)})`);\n });\n\n batch.on('taskSkip', ({task, reason}) => {\n this.log('warn', `Download skipped (${__getDownloadIdString(task, batch)}): ${reason.message}`);\n });\n\n batch.on('taskSpawn', ({origin, spawn}) => {\n this.log('info', `Download spawned: #${batch.id}.${origin.id} -> #${batch.id}.${spawn.id}`);\n });\n\n /**\n * Uncomment this block to log download progress\n\n batch.on('taskProgress', ({task, progress}) => {\n if (progress) {\n if (progress.length) {\n this.log('info', `Download progress (${__getDownloadIdString(task, batch)}): ${progress.lengthDownloaded} / ${progress.length} ${progress.lengthUnit}s / ${progress.percent}% (${progress.speed} kB/s)`,);\n }\n else {\n this.log('info', `Download progress (${__getDownloadIdString(task, batch)}): ${progress.lengthDownloaded} / ? ${progress.lengthUnit}s (${progress.speed} kB/s)`,);\n }\n }\n else {\n this.log('warn', `Download progress not available (${__getDownloadIdString(task, batch)})`);\n }\n });\n\n */\n\n batch.on('complete', () => {\n const total = batch.getTasks().length;\n const completed = batch.getTasks('completed').length;\n const error = batch.getTasks('error').length;\n const aborted = batch.getTasks('aborted').length;\n const skipped = batch.getTasks('skipped').length;\n const counts = [\n `${total} downloads`,\n `${completed} completed`,\n `${error} errors`,\n `${skipped} skipped`,\n `${aborted} aborted`\n ].join('; ');\n this.log('info', `Download batch complete (#${batch.id}): ${counts}`);\n });\n\n return this.addToDownloadTaskBatch(batch, ...createTasks);\n }\n\n protected addToDownloadTaskBatch(batch: DownloadTaskBatch, ...createTasks: Array<CreateDownloadTaskParams | null>) {\n let failedCreateTaskCount = 0;\n for (const task of createTasks) {\n if (!task) {\n continue;\n }\n const { target, targetName, destDir } = task;\n this.log('info', `Create download tasks for ${targetName}`);\n if (task.target.length === 0) {\n this.log('warn', `No items in ${targetName}`);\n continue;\n }\n let createdCount = 0;\n for (const tt of target) {\n try {\n const tasks = DownloadTaskFactory.createFromDownloadable({\n config: this.config,\n item: tt,\n destDir,\n fetcher: this.fetcher,\n fileExistsAction: task.fileExistsAction,\n logger: this.logger\n });\n batch.addTasks(tasks);\n createdCount += tasks.length;\n }\n catch (error) {\n this.log('error', `Failed to create download task for item #${tt.id} in ${targetName}:`, error);\n failedCreateTaskCount++;\n }\n }\n if (createdCount > 0) {\n this.fsHelper.createDir(destDir);\n }\n }\n if (failedCreateTaskCount > 0) {\n this.log('warn', `${failedCreateTaskCount} items could not be processed for downloading`);\n }\n return batch;\n }\n\n abstract start(params: DownloaderStartParams): Promise<void>;\n\n static async getInstance(url: string, options?: DownloaderOptions) {\n const bootstrap = Bootstrap.getDownloaderBootstrapDataByURL(url);\n if (!bootstrap) {\n throw Error('Could not determine downloader type from URL');\n }\n switch (bootstrap.type) {\n case 'product': {\n const ProductDownloader = (await import('./ProductDownloader.js')).default;\n return new ProductDownloader(bootstrap, options);\n }\n case 'post': {\n const PostDownloader = (await import('./PostDownloader.js')).default;\n return new PostDownloader(bootstrap, options);\n }\n }\n }\n\n static async getCampaign(\n creator: string | UserIdOrVanityParam,\n signal?: AbortSignal,\n logger?: Logger | null\n ) {\n // Backwards compatibility - if 'creator' is string type, then it is vanity\n const url = URLHelper.constructUserPostsURL(typeof creator === 'object' ? creator : { vanity: creator });\n const downloader = await this.getInstance(url, { logger });\n const PostDownloader = (await import('./PostDownloader.js')).default;\n if (downloader instanceof PostDownloader) {\n return downloader.__getCampaign(signal);\n }\n throw Error('Type mismatch: PostDownloader expected');\n }\n\n #validateOptions(options?: DownloaderOptions) {\n if (!options) {\n return true;\n }\n\n // Check FFmpeg path exists\n if (options.pathToFFmpeg) {\n if (!fs.existsSync(options.pathToFFmpeg)) {\n throw Error(`Path to FFmpeg executable \"${options.pathToFFmpeg}\" does not exist`);\n }\n else if (!fs.lstatSync(options.pathToFFmpeg).isFile()) {\n throw Error(`Path to FFmpeg executable \"${options.pathToFFmpeg}\" does not point to a file`);\n }\n }\n\n // Check outDir is a directory\n if (options.outDir) {\n if (fs.existsSync(options.outDir) && !fs.lstatSync(options.outDir).isDirectory()) {\n throw Error(`\"${options.outDir}\" is not a directory`);\n }\n }\n\n // Check formats are valid\n const campaignDirNameFormat = options.dirNameFormat?.campaign;\n if (campaignDirNameFormat) {\n const validate = FilenameFormatHelper.validateCampaignDirNameFormat(campaignDirNameFormat);\n if (!validate.validateOK) {\n throw Error(`Campaign directory name format '${campaignDirNameFormat}' is invalid (matched against ${validate.regex})`);\n }\n }\n const contentDirNameFormat = options.dirNameFormat?.content;\n if (contentDirNameFormat) {\n const validate = FilenameFormatHelper.validateContentDirNameFormat(contentDirNameFormat);\n if (!validate.validateOK) {\n throw Error(`Content directory name format '${contentDirNameFormat}' is invalid (matched against ${validate.regex})`);\n }\n }\n const mediaFilenameFormat = options.filenameFormat?.media;\n if (mediaFilenameFormat) {\n const validate = FilenameFormatHelper.validateMediaFilenameFormat(mediaFilenameFormat);\n if (!validate.validateOK) {\n throw Error(`Media filename format '${mediaFilenameFormat}' is invalid (matched against ${validate.regex})`);\n }\n }\n\n return true;\n }\n\n protected saveCampaignInfo(campaign: Campaign | null, signal?: AbortSignal) {\n\n return new Promise<void>((resolve) => {\n void (async () => {\n if (!this.config.include.campaignInfo) {\n resolve();\n return;\n }\n \n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n let batch: DownloadTaskBatch | null = null;\n const abortHandler = () => {\n void (async () => {\n if (batch) {\n await batch.abort();\n }\n })();\n };\n if (signal) {\n signal.addEventListener('abort', abortHandler, { once: true });\n }\n \n if (!campaign) {\n this.log('warn', 'Skipped saving campaign info: target unavailable');\n resolve();\n return;\n }\n \n this.log('info', `Save campaign info #${campaign.id}`);\n this.emit('targetBegin', { target: campaign });\n this.emit('phaseBegin', { target: campaign, phase: 'saveInfo' });\n \n // Step 1: create campaign directories\n const campaignDirs = this.fsHelper.getCampaignDirs(campaign);\n this.log('debug', 'Campaign directories: ', campaignDirs);\n this.fsHelper.createDir(campaignDirs.root);\n this.fsHelper.createDir(campaignDirs.info);\n \n // Step 2: save summary and raw json\n const summary = generateCampaignSummary(campaign);\n const summaryFile = path.resolve(campaignDirs.info, 'info.txt');\n const saveSummaryResult = await this.fsHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, campaign, 'campaign summary');\n \n // Campaign / creator raw data might not be complete. Fetch directly from API.\n // Strictly speaking, we should check for 'error' in results, but since it's not going to be fatal we'll just skip it.\n const { json: fetchedCampaignAPIData } = await this.fetchCampaign(campaign.id, signal);\n const { json: fetchedCreatorAPIData } = campaign.creator ? await this.fetchUser(campaign.creator.id, signal) : { json: null };\n \n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n const campaignRawFile = path.resolve(campaignDirs.info, 'campaign-api.json');\n const saveCampaignRawResult = await this.fsHelper.writeTextFile(\n campaignRawFile, fetchedCampaignAPIData || campaign.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(saveCampaignRawResult, campaign, 'campaign API data');\n \n if (campaign.creator) {\n const creatorRawFile = path.resolve(campaignDirs.info, 'creator-api.json');\n const saveCreatorRawResult = await this.fsHelper.writeTextFile(\n creatorRawFile, fetchedCreatorAPIData || campaign.creator.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(saveCreatorRawResult, campaign.creator, 'creator API data');\n }\n \n this.emit('phaseEnd', { target: campaign, phase: 'saveInfo' });\n \n // Step 3: download campaign media items\n this.emit('phaseBegin', { target: campaign, phase: 'saveMedia' });\n const campaignMedia: Downloadable[] = [\n campaign.avatarImage,\n campaign.coverPhoto\n ];\n if (campaign.creator) {\n campaignMedia.push(\n campaign.creator.image,\n campaign.creator.thumbnail\n );\n }\n for (const reward of campaign.rewards) {\n if (reward.image) {\n campaignMedia.push(reward.image);\n }\n }\n batch = this.createDownloadTaskBatch(\n `Campaign #${campaign.id} (${campaign.name})`,\n {\n target: campaignMedia,\n targetName: `campaign #${campaign.id} -> images`,\n destDir: campaignDirs.info,\n fileExistsAction: this.config.fileExistsAction.info\n }\n );\n this.emit('phaseBegin', { target: campaign, phase: 'batchDownload', batch });\n await batch.start();\n await batch.destroy();\n this.emit('phaseEnd', { target: campaign, phase: 'batchDownload' });\n this.emit('phaseEnd', { target: campaign, phase: 'saveMedia' });\n \n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n // Done\n this.log('info', 'Done saving campaign info');\n this.emit('targetEnd', { target: campaign, isSkipped: false });\n \n resolve();\n })();\n });\n\n }\n\n protected log(level: LogLevel, ...msg: any[]) {\n commonLog(this.logger, level, this.name, ...msg);\n }\n\n getConfig() {\n return deepFreeze(this.config);\n }\n\n protected checkAbortSignal(signal: AbortSignal | undefined, resolve: () => void) {\n if (signal && signal.aborted) {\n if (!this.#hasEmittedEndEventOnAbort) {\n this.emit('end', { aborted: true, message: 'Download aborted' });\n this.#hasEmittedEndEventOnAbort = true;\n }\n resolve();\n return true;\n }\n return false;\n }\n\n protected logWriteTextFileResult(result: WriteTextFileResult, target: {id: string}, targetName: string) {\n switch (result.status) {\n case 'completed':\n this.log('info', `Saved ${targetName} to \"${result.filePath}\"`);\n break;\n case 'skipped':\n this.log('warn', `Skipped saving ${targetName} #${target.id}: ${result.message}`);\n break;\n case 'error':\n this.log('error', `Error saving ${targetName} #${target.id} to \"${result.filePath}\":`, result.error);\n }\n }\n\n protected async commonFetchAPI(url: string, signal?: AbortSignal) {\n let json, requestAPIError: any;\n try {\n json = await this.fetcher.get({ url, type: 'json', maxRetries: this.config.request.maxRetries, signal });\n }\n catch (error) {\n if (signal?.aborted) {\n this.log('warn', 'API request aborted');\n }\n else {\n this.log('error', `Error requesting API URL \"${url}\": `, error);\n requestAPIError = error;\n }\n json = null;\n }\n return { json, error: requestAPIError };\n }\n\n protected fetchCampaign(campaignId: string, signal?: AbortSignal) {\n const url = URLHelper.constructCampaignAPIURL(campaignId);\n this.log('debug', `Fetch campaign data from API URL \"${url}\"`);\n return this.commonFetchAPI(url, signal);\n }\n\n protected fetchUser(userId: string, signal?: AbortSignal) {\n const url = URLHelper.constructUserAPIURL(userId);\n this.log('debug', `Fetch user data from API URL \"${url}\"`);\n return this.commonFetchAPI(url, signal);\n }\n\n on<T extends DownloaderEvent>(event: T, listener: (args: DownloaderEventPayloadOf<T>) => void): this;\n on(event: string | symbol, listener: (...args: any[]) => void): this {\n return super.on(event, listener);\n }\n\n once<T extends DownloaderEvent>(event: T, listener: (args: DownloaderEventPayloadOf<T>) => void): this;\n once(event: string | symbol, listener: (...args: any[]) => void): this {\n return super.once(event, listener);\n }\n\n off<T extends DownloaderEvent>(event: T, listener: (args: DownloaderEventPayloadOf<T>) => void): this;\n off(event: string | symbol, listener: (...args: any[]) => void): this {\n return super.off(event, listener);\n }\n\n emit<T extends DownloaderEvent>(event: T, args: DownloaderEventPayloadOf<T>): boolean;\n emit(event: string | symbol, ...args: any[]): boolean {\n return super.emit(event, ...args);\n }\n}\n"]}
1
+ {"version":3,"file":"Downloader.js","sourceRoot":"","sources":["../../src/downloaders/Downloader.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport { EventEmitter } from 'events';\nimport deepFreeze from 'deep-freeze';\nimport Fetcher from '../utils/Fetcher.js';\nimport Bootstrap, { type DownloaderBootstrapData, type DownloaderType } from './Bootstrap.js';\nimport { type DownloaderInit, type DownloaderOptions, type FileExistsAction, getDownloaderInit } from './DownloaderOptions.js';\nimport { type DownloaderEvent, type DownloaderEventPayloadOf } from './DownloaderEvent.js';\nimport {type LogLevel} from '../utils/logging/Logger.js';\nimport type Logger from '../utils/logging/Logger.js';\nimport { commonLog } from '../utils/logging/Logger.js';\nimport { type Campaign } from '../entities/Campaign.js';\nimport FSHelper, { type WriteTextFileResult } from '../utils/FSHelper.js';\nimport DownloadTaskBatch from './task/DownloadTaskBatch.js';\nimport DownloadTask, { type IDownloadTask } from './task/DownloadTask.js';\nimport DownloadTaskFactory from './task/DownloadTaskFactory.js';\nimport FilenameFormatHelper from '../utils/FilenameFormatHelper.js';\nimport { type Downloadable } from '../entities/Downloadable.js';\nimport { generateCampaignSummary } from './templates/CampaignInfo.js';\nimport path from 'path';\nimport URLHelper from '../utils/URLHelper.js';\nimport ffmpeg from 'fluent-ffmpeg';\nimport InnertubeLoader from '../utils/InnertubeLoader.js';\nimport FFmpegDownloadTaskBase from './task/FFmpegDownloadTaskBase.js';\nimport { type UserIdOrVanityParam } from '../entities/User.js';\nimport ExternalDownloaderTask from './task/ExternalDownloaderTask.js';\nimport Bottleneck from 'bottleneck';\n\nexport type DownloaderConfig<T extends DownloaderType> =\n DownloaderInit &\n Omit<DownloaderBootstrapData<T>, 'type'>;\n\nexport interface DownloaderStartParams {\n signal?: AbortSignal;\n}\n\ninterface CreateDownloadTaskParams {\n target: Downloadable[];\n targetName: string;\n destDir: string;\n fileExistsAction: FileExistsAction;\n}\n\nexport default abstract class Downloader<T extends DownloaderType> extends EventEmitter {\n\n abstract name: string;\n\n protected fetcher: Fetcher;\n protected fsHelper: FSHelper;\n protected config: DownloaderConfig<T>;\n protected logger?: Logger | null;\n\n #hasEmittedEndEventOnAbort: boolean;\n\n constructor(bootstrap: DownloaderBootstrapData<T>, options?: DownloaderOptions) {\n super();\n this.#validateOptions(options);\n\n this.config = {\n ...bootstrap,\n ...getDownloaderInit(options)\n };\n\n this.fetcher = new Fetcher(this.config, options?.cookie, options?.logger);\n this.fsHelper = new FSHelper(this.config, this.logger);\n this.logger = options?.logger;\n\n if (this.config.pathToFFmpeg) {\n ffmpeg.setFfmpegPath(this.config.pathToFFmpeg);\n }\n\n InnertubeLoader.setLogger(this.logger);\n if (this.config.pathToYouTubeCredentials) {\n InnertubeLoader.loadCredentials(this.config.pathToYouTubeCredentials);\n }\n\n this.#hasEmittedEndEventOnAbort = false;\n }\n\n protected createDownloadTaskBatch(name: string, signal?: AbortSignal, ...createTasks: Array<CreateDownloadTaskParams | null>): Promise<DownloadTaskBatch> {\n\n const __getDownloadIdString = (task: IDownloadTask, batch: DownloadTaskBatch) => {\n let result = `#${batch.id}.${task.id}`;\n if (task.retryCount > 0) {\n result += `-r${task.retryCount}`;\n }\n return result;\n };\n\n const batch = new DownloadTaskBatch({\n name,\n fetcher: this.fetcher,\n limiter: this.config.request,\n logger: this.logger\n });\n\n batch.on('taskStart', ({task}) => {\n const retryOrBeginStr = task.retryCount > 0 ? 'retry' : 'begin';\n const isExternal = task instanceof ExternalDownloaderTask;\n const destStr = isExternal ? ' -> Unknown destination (external process)' : task.resolvedDestFilename ? ` -> ${task.resolvedDestFilename}` : '';\n this.log('info', `Download ${retryOrBeginStr} (${__getDownloadIdString(task, batch)}): [type: ${task.srcEntity.type}; ID: #${task.srcEntity.id}]${destStr}`);\n if (task instanceof FFmpegDownloadTaskBase) {\n const retryOrBeginStr = task.retryCount > 0 ? 'Retry' : 'Begin';\n this.log('info', `${retryOrBeginStr} downloading through FFmpeg (${__getDownloadIdString(task, batch)}): ${task.commandLine}`);\n }\n });\n\n batch.on('taskComplete', ({task}) => {\n const isExternal = task instanceof ExternalDownloaderTask;\n const destStr = isExternal ? ': Unknown destination (external process)' : task.resolvedDestPath ? `: \"${task.resolvedDestPath}\"` : '';\n this.log('info', `Download complete (${__getDownloadIdString(task, batch)})${destStr}`);\n });\n\n batch.on('taskError', ({error, willRetry}) => {\n const { task, cause, message } = error;\n const retryStr = willRetry ? '- will retry' : '';\n this.log('error', `Download error (${__getDownloadIdString(task, batch)}):`, cause || message, `(${task.src})`, retryStr);\n });\n\n batch.on('taskAbort', ({task}) => {\n this.log('warn', `Download aborted (${__getDownloadIdString(task, batch)})`);\n });\n\n batch.on('taskSkip', ({task, reason}) => {\n this.log('warn', `Download skipped (${__getDownloadIdString(task, batch)}): ${reason.message}`);\n });\n\n batch.on('taskSpawn', ({origin, spawn}) => {\n this.log('info', `Download spawned: #${batch.id}.${origin.id} -> #${batch.id}.${spawn.id}`);\n });\n\n /**\n * Uncomment this block to log download progress\n\n batch.on('taskProgress', ({task, progress}) => {\n if (progress) {\n if (progress.length) {\n this.log('info', `Download progress (${__getDownloadIdString(task, batch)}): ${progress.lengthDownloaded} / ${progress.length} ${progress.lengthUnit}s / ${progress.percent}% (${progress.speed} kB/s)`,);\n }\n else {\n this.log('info', `Download progress (${__getDownloadIdString(task, batch)}): ${progress.lengthDownloaded} / ? ${progress.lengthUnit}s (${progress.speed} kB/s)`,);\n }\n }\n else {\n this.log('warn', `Download progress not available (${__getDownloadIdString(task, batch)})`);\n }\n });\n\n */\n\n batch.on('complete', () => {\n const total = batch.getTasks().length;\n const completed = batch.getTasks('completed').length;\n const error = batch.getTasks('error').length;\n const aborted = batch.getTasks('aborted').length;\n const skipped = batch.getTasks('skipped').length;\n const counts = [\n `${total} downloads`,\n `${completed} completed`,\n `${error} errors`,\n `${skipped} skipped`,\n `${aborted} aborted`\n ].join('; ');\n this.log('info', `Download batch complete (#${batch.id}): ${counts}`);\n });\n\n return this.addToDownloadTaskBatch(batch, signal, ...createTasks);\n }\n\n protected async addToDownloadTaskBatch(batch: DownloadTaskBatch, signal?: AbortSignal, ...createTasks: Array<CreateDownloadTaskParams | null>) {\n let failedCreateTaskCount = 0;\n for (const task of createTasks) {\n if (!task) {\n continue;\n }\n const { target, targetName, destDir } = task;\n this.log('info', `Create download tasks for ${targetName}`);\n if (task.target.length === 0) {\n this.log('warn', `No items in ${targetName}`);\n continue;\n }\n let createdCount = 0;\n for (const tt of target) {\n try {\n const tasks = await DownloadTaskFactory.createFromDownloadable({\n config: this.config,\n item: tt,\n destDir,\n fetcher: this.fetcher,\n fileExistsAction: task.fileExistsAction,\n limiter: batch.limiter,\n signal,\n logger: this.logger\n });\n // Filter out tasks that are DOA (errors that occurred in DownloadTask.create())\n for (const task of tasks) {\n if (task.doa) {\n this.log('error', `Failed to create download task for item #${tt.id} in ${targetName}:`, task.doa.msg, task.doa.cause);\n failedCreateTaskCount++;\n }\n }\n batch.addTasks(tasks.filter((task) => !task.doa));\n createdCount += tasks.length;\n }\n catch (error) {\n if (signal?.aborted) {\n this.log('warn', 'Operation aborted');\n return batch;\n }\n this.log('error', `Failed to create download task(s) for item #${tt.id} in ${targetName}:`, error);\n failedCreateTaskCount++;\n }\n }\n if (createdCount > 0) {\n this.fsHelper.createDir(destDir);\n }\n }\n if (failedCreateTaskCount > 0) {\n this.log('warn', `${failedCreateTaskCount} items could not be processed for downloading`);\n }\n return batch;\n }\n\n abstract start(params: DownloaderStartParams): Promise<void>;\n\n static async getInstance(url: string, options?: DownloaderOptions) {\n const bootstrap = Bootstrap.getDownloaderBootstrapDataByURL(url);\n if (!bootstrap) {\n throw Error('Could not determine downloader type from URL');\n }\n switch (bootstrap.type) {\n case 'product': {\n const ProductDownloader = (await import('./ProductDownloader.js')).default;\n return new ProductDownloader(bootstrap, options);\n }\n case 'post': {\n const PostDownloader = (await import('./PostDownloader.js')).default;\n return new PostDownloader(bootstrap, options);\n }\n }\n }\n\n static async getCampaign(\n creator: string | UserIdOrVanityParam,\n signal?: AbortSignal,\n logger?: Logger | null\n ) {\n // Backwards compatibility - if 'creator' is string type, then it is vanity\n const url = URLHelper.constructUserPostsURL(typeof creator === 'object' ? creator : { vanity: creator });\n const downloader = await this.getInstance(url, { logger });\n const PostDownloader = (await import('./PostDownloader.js')).default;\n if (downloader instanceof PostDownloader) {\n return downloader.__getCampaign(signal);\n }\n throw Error('Type mismatch: PostDownloader expected');\n }\n\n #validateOptions(options?: DownloaderOptions) {\n if (!options) {\n return true;\n }\n\n // Check FFmpeg path exists\n if (options.pathToFFmpeg) {\n if (!fs.existsSync(options.pathToFFmpeg)) {\n throw Error(`Path to FFmpeg executable \"${options.pathToFFmpeg}\" does not exist`);\n }\n else if (!fs.lstatSync(options.pathToFFmpeg).isFile()) {\n throw Error(`Path to FFmpeg executable \"${options.pathToFFmpeg}\" does not point to a file`);\n }\n }\n\n // Check outDir is a directory\n if (options.outDir) {\n if (fs.existsSync(options.outDir) && !fs.lstatSync(options.outDir).isDirectory()) {\n throw Error(`\"${options.outDir}\" is not a directory`);\n }\n }\n\n // Check formats are valid\n const campaignDirNameFormat = options.dirNameFormat?.campaign;\n if (campaignDirNameFormat) {\n const validate = FilenameFormatHelper.validateCampaignDirNameFormat(campaignDirNameFormat);\n if (!validate.validateOK) {\n throw Error(`Campaign directory name format '${campaignDirNameFormat}' is invalid (matched against ${validate.regex})`);\n }\n }\n const contentDirNameFormat = options.dirNameFormat?.content;\n if (contentDirNameFormat) {\n const validate = FilenameFormatHelper.validateContentDirNameFormat(contentDirNameFormat);\n if (!validate.validateOK) {\n throw Error(`Content directory name format '${contentDirNameFormat}' is invalid (matched against ${validate.regex})`);\n }\n }\n const mediaFilenameFormat = options.filenameFormat?.media;\n if (mediaFilenameFormat) {\n const validate = FilenameFormatHelper.validateMediaFilenameFormat(mediaFilenameFormat);\n if (!validate.validateOK) {\n throw Error(`Media filename format '${mediaFilenameFormat}' is invalid (matched against ${validate.regex})`);\n }\n }\n\n return true;\n }\n\n protected saveCampaignInfo(campaign: Campaign | null, signal?: AbortSignal) {\n\n return new Promise<void>((resolve) => {\n void (async () => {\n if (!this.config.include.campaignInfo) {\n resolve();\n return;\n }\n \n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n let batch: DownloadTaskBatch | null = null;\n const abortHandler = () => {\n void (async () => {\n if (batch) {\n await batch.abort();\n }\n })();\n };\n if (signal) {\n signal.addEventListener('abort', abortHandler, { once: true });\n }\n \n if (!campaign) {\n this.log('warn', 'Skipped saving campaign info: target unavailable');\n resolve();\n return;\n }\n \n this.log('info', `Save campaign info #${campaign.id}`);\n this.emit('targetBegin', { target: campaign });\n this.emit('phaseBegin', { target: campaign, phase: 'saveInfo' });\n \n // Step 1: create campaign directories\n const campaignDirs = this.fsHelper.getCampaignDirs(campaign);\n this.log('debug', 'Campaign directories: ', campaignDirs);\n this.fsHelper.createDir(campaignDirs.root);\n this.fsHelper.createDir(campaignDirs.info);\n \n // Step 2: save summary and raw json\n const summary = generateCampaignSummary(campaign);\n const summaryFile = path.resolve(campaignDirs.info, 'info.txt');\n const saveSummaryResult = await this.fsHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, campaign, 'campaign summary');\n \n // Campaign / creator raw data might not be complete. Fetch directly from API.\n // Strictly speaking, we should check for 'error' in results, but since it's not going to be fatal we'll just skip it.\n const { json: fetchedCampaignAPIData } = await this.fetchCampaign(campaign.id, signal);\n const { json: fetchedCreatorAPIData } = campaign.creator ? await this.fetchUser(campaign.creator.id, signal) : { json: null };\n \n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n const campaignRawFile = path.resolve(campaignDirs.info, 'campaign-api.json');\n const saveCampaignRawResult = await this.fsHelper.writeTextFile(\n campaignRawFile, fetchedCampaignAPIData || campaign.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(saveCampaignRawResult, campaign, 'campaign API data');\n \n if (campaign.creator) {\n const creatorRawFile = path.resolve(campaignDirs.info, 'creator-api.json');\n const saveCreatorRawResult = await this.fsHelper.writeTextFile(\n creatorRawFile, fetchedCreatorAPIData || campaign.creator.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(saveCreatorRawResult, campaign.creator, 'creator API data');\n }\n \n this.emit('phaseEnd', { target: campaign, phase: 'saveInfo' });\n \n // Step 3: download campaign media items\n this.emit('phaseBegin', { target: campaign, phase: 'saveMedia' });\n const campaignMedia: Downloadable[] = [\n campaign.avatarImage,\n campaign.coverPhoto\n ];\n if (campaign.creator) {\n campaignMedia.push(\n campaign.creator.image,\n campaign.creator.thumbnail\n );\n }\n for (const reward of campaign.rewards) {\n if (reward.image) {\n campaignMedia.push(reward.image);\n }\n }\n batch = await this.createDownloadTaskBatch(\n `Campaign #${campaign.id} (${campaign.name})`,\n signal,\n {\n target: campaignMedia,\n targetName: `campaign #${campaign.id} -> images`,\n destDir: campaignDirs.info,\n fileExistsAction: this.config.fileExistsAction.info\n }\n );\n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n batch.prestart();\n this.emit('phaseBegin', { target: campaign, phase: 'batchDownload', batch });\n await batch.start();\n await batch.destroy();\n this.emit('phaseEnd', { target: campaign, phase: 'batchDownload' });\n this.emit('phaseEnd', { target: campaign, phase: 'saveMedia' });\n \n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n // Done\n this.log('info', 'Done saving campaign info');\n this.emit('targetEnd', { target: campaign, isSkipped: false });\n \n resolve();\n })();\n });\n\n }\n\n protected log(level: LogLevel, ...msg: any[]) {\n commonLog(this.logger, level, this.name, ...msg);\n }\n\n getConfig() {\n return deepFreeze(this.config);\n }\n\n protected checkAbortSignal(signal: AbortSignal | undefined, resolve: () => void) {\n if (signal && signal.aborted) {\n if (!this.#hasEmittedEndEventOnAbort) {\n this.emit('end', { aborted: true, message: 'Download aborted' });\n this.#hasEmittedEndEventOnAbort = true;\n }\n resolve();\n return true;\n }\n return false;\n }\n\n protected logWriteTextFileResult(result: WriteTextFileResult, target: {id: string}, targetName: string) {\n switch (result.status) {\n case 'completed':\n this.log('info', `Saved ${targetName} to \"${result.filePath}\"`);\n break;\n case 'skipped':\n this.log('warn', `Skipped saving ${targetName} #${target.id}: ${result.message}`);\n break;\n case 'error':\n this.log('error', `Error saving ${targetName} #${target.id} to \"${result.filePath}\":`, result.error);\n }\n }\n\n protected async commonFetchAPI(url: string, signal?: AbortSignal) {\n let json, requestAPIError: any;\n try {\n json = await this.fetcher.get({ url, type: 'json', maxRetries: this.config.request.maxRetries, signal });\n }\n catch (error) {\n if (signal?.aborted) {\n this.log('warn', 'API request aborted');\n }\n else {\n this.log('error', `Error requesting API URL \"${url}\": `, error);\n requestAPIError = error;\n }\n json = null;\n }\n return { json, error: requestAPIError };\n }\n\n protected fetchCampaign(campaignId: string, signal?: AbortSignal) {\n const url = URLHelper.constructCampaignAPIURL(campaignId);\n this.log('debug', `Fetch campaign data from API URL \"${url}\"`);\n return this.commonFetchAPI(url, signal);\n }\n\n protected fetchUser(userId: string, signal?: AbortSignal) {\n const url = URLHelper.constructUserAPIURL(userId);\n this.log('debug', `Fetch user data from API URL \"${url}\"`);\n return this.commonFetchAPI(url, signal);\n }\n\n on<T extends DownloaderEvent>(event: T, listener: (args: DownloaderEventPayloadOf<T>) => void): this;\n on(event: string | symbol, listener: (...args: any[]) => void): this {\n return super.on(event, listener);\n }\n\n once<T extends DownloaderEvent>(event: T, listener: (args: DownloaderEventPayloadOf<T>) => void): this;\n once(event: string | symbol, listener: (...args: any[]) => void): this {\n return super.once(event, listener);\n }\n\n off<T extends DownloaderEvent>(event: T, listener: (args: DownloaderEventPayloadOf<T>) => void): this;\n off(event: string | symbol, listener: (...args: any[]) => void): this {\n return super.off(event, listener);\n }\n\n emit<T extends DownloaderEvent>(event: T, args: DownloaderEventPayloadOf<T>): boolean;\n emit(event: string | symbol, ...args: any[]): boolean {\n return super.emit(event, ...args);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"PostDownloader.d.ts","sourceRoot":"","sources":["../../src/downloaders/PostDownloader.ts"],"names":[],"mappings":"AACA,OAAO,UAAU,EAAE,EAAyB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAGhG,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAShD,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,UAAU,CAAC,IAAI,CAAC;;IAE1D,MAAM,CAAC,OAAO,SAAW;IAEzB,IAAI,SAAoB;IAIxB,KAAK,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAsd9C,aAAa,CAAC,MAAM,CAAC,EAAE,WAAW;CAyHzC"}
1
+ {"version":3,"file":"PostDownloader.d.ts","sourceRoot":"","sources":["../../src/downloaders/PostDownloader.ts"],"names":[],"mappings":"AACA,OAAO,UAAU,EAAE,EAAyB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAGhG,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAShD,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,UAAU,CAAC,IAAI,CAAC;;IAE1D,MAAM,CAAC,OAAO,SAAW;IAEzB,IAAI,SAAoB;IAIxB,KAAK,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IA4d9C,aAAa,CAAC,MAAM,CAAC,EAAE,WAAW;CA0HzC"}
@@ -351,7 +351,10 @@ class PostDownloader extends Downloader {
351
351
  if (this.config.include.previewMedia ||
352
352
  this.config.include.contentMedia ||
353
353
  this.config.include.contentInfo) {
354
- batch = __classPrivateFieldGet(this, _PostDownloader_instances, "m", _PostDownloader_createDownloadTaskBatchForPost).call(this, post, postDirs);
354
+ batch = await __classPrivateFieldGet(this, _PostDownloader_instances, "m", _PostDownloader_createDownloadTaskBatchForPost).call(this, post, postDirs, signal);
355
+ if (this.checkAbortSignal(signal, resolve)) {
356
+ return;
357
+ }
355
358
  if (this.config.include.contentInfo) {
356
359
  const infoElements = [];
357
360
  if (post.coverImage) {
@@ -361,7 +364,7 @@ class PostDownloader extends Downloader {
361
364
  infoElements.push(post.thumbnail);
362
365
  }
363
366
  if (infoElements.length > 0) {
364
- this.addToDownloadTaskBatch(batch, {
367
+ await this.addToDownloadTaskBatch(batch, signal, {
365
368
  target: infoElements,
366
369
  targetName: `post #${post.id} -> info elements`,
367
370
  destDir: postDirs.info,
@@ -369,6 +372,7 @@ class PostDownloader extends Downloader {
369
372
  });
370
373
  }
371
374
  }
375
+ batch.prestart();
372
376
  this.log('info', `Download batch created (#${batch.id}): ${batch.getTasks('pending').length} downloads pending`);
373
377
  this.emit('phaseBegin', { target: post, phase: 'batchDownload', batch });
374
378
  await batch.start();
@@ -480,7 +484,7 @@ class PostDownloader extends Downloader {
480
484
  }
481
485
  _PostDownloader_startPromise = new WeakMap(), _PostDownloader_instances = new WeakSet(), _PostDownloader_isFetchingMultiplePosts = function _PostDownloader_isFetchingMultiplePosts(postFetch) {
482
486
  return postFetch.type === 'byUser' || postFetch.type === 'byUserId' || postFetch.type === 'byCollection';
483
- }, _PostDownloader_createDownloadTaskBatchForPost = function _PostDownloader_createDownloadTaskBatchForPost(post, postDirs) {
487
+ }, _PostDownloader_createDownloadTaskBatchForPost = function _PostDownloader_createDownloadTaskBatchForPost(post, postDirs, signal) {
484
488
  const incPreview = this.config.include.previewMedia;
485
489
  const incContent = this.config.include.contentMedia;
486
490
  const __incPreview = (mediaType) => {
@@ -495,7 +499,7 @@ _PostDownloader_startPromise = new WeakMap(), _PostDownloader_instances = new We
495
499
  }
496
500
  return incContent.includes(mediaType);
497
501
  };
498
- const batch = this.createDownloadTaskBatch(`Post #${post.id} (${post.title})`, __incPreview('audio') && post.audioPreview ? {
502
+ const batch = this.createDownloadTaskBatch(`Post #${post.id} (${post.title})`, signal, __incPreview('audio') && post.audioPreview ? {
499
503
  target: [post.audioPreview],
500
504
  targetName: `post #${post.id} -> audio preview`,
501
505
  destDir: postDirs.audioPreview,
@@ -1 +1 @@
1
- {"version":3,"file":"PostDownloader.js","sourceRoot":"","sources":["../../src/downloaders/PostDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import URLHelper from '../utils/URLHelper.js';\nimport Downloader, { type DownloaderConfig, type DownloaderStartParams } from './Downloader.js';\nimport type DownloadTaskBatch from './task/DownloadTaskBatch.js';\nimport PostParser from '../parsers/PostParser.js';\nimport { type Post } from '../entities/Post.js';\nimport { type Downloadable, isYouTubeEmbed } from '../entities/Downloadable.js';\nimport StatusCache from './cache/StatusCache.js';\nimport { generatePostEmbedSummary, generatePostSummary } from './templates/PostInfo.js';\nimport path from 'path';\nimport { TargetSkipReason } from './DownloaderEvent.js';\nimport DownloadTaskFactory from './task/DownloadTaskFactory.js';\nimport PostsFetcher from './PostsFetcher.js';\n\nexport default class PostDownloader extends Downloader<Post> {\n\n static version = '1.1.1';\n\n name = 'PostDownloader';\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>((resolve) => {\n void (async () => {\n const { signal } = params || {};\n const postFetch = this.config.postFetch;\n let batch: DownloadTaskBatch | null = null;\n \n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n const abortHandler = () => {\n void (async () => {\n this.log('info', 'Abort signal received');\n if (batch) {\n await batch.abort();\n }\n })();\n };\n if (signal) {\n signal.addEventListener('abort', abortHandler, { once: true });\n }\n \n if (postFetch.type === 'byUser') {\n this.log('info', `Targeting posts by '${postFetch.vanity}'`);\n }\n else if (postFetch.type === 'byUserId') {\n this.log('info', `Targeting posts by user #${postFetch.userId}`);\n }\n else if (postFetch.type === 'byCollection') {\n this.log('info', `Targeting posts in collection #${postFetch.collectionId}`);\n }\n else { // Single\n this.log('info', `Targeting post #${postFetch.postId}`);\n }\n if (this.#isFetchingMultiplePosts(postFetch) && postFetch.filters) {\n const filterStr = Object.entries(postFetch.filters).map(([ key, value ]) => `${key}=${value}`).join('; ');\n if (filterStr) {\n this.log('info', `Filters: ${filterStr}`);\n }\n }\n \n // Step 1: Get posts (if by user) or target post\n const postsFetcher = new PostsFetcher({\n config: this.config,\n fetcher: this.fetcher,\n logger: this.logger,\n signal\n });\n postsFetcher.on('statusChange', ({current}) => {\n if (current.status === 'running') {\n this.emit('fetchBegin', { targetType: postsFetcher.getTargetType() });\n }\n });\n postsFetcher.begin();\n \n // Step 2: download posts in each fetched collection\n let downloaded = 0;\n let skippedUnviewable = 0;\n let skippedRedundant = 0;\n let skippedUnmetMediaTypeCriteria = 0;\n let skippedNotInTier = 0;\n let skippedPublishDateOutOfRange = 0;\n let campaignSaved = false;\n const postsParser = new PostParser(this.logger);\n while (postsFetcher.hasNext()) {\n const { collection, aborted, error } = await postsFetcher.next();\n if (!collection || aborted) {\n break;\n }\n if (!collection && error) {\n this.emit('end', { aborted: false, error, message: 'PostsFetcher error' });\n resolve();\n return;\n }\n if (!campaignSaved && collection.posts[0]?.campaign) {\n await this.saveCampaignInfo(collection.posts[0].campaign, signal);\n campaignSaved = true;\n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n }\n \n for (const _post of collection.posts) {\n \n let post = _post;\n \n if (this.#isFetchingMultiplePosts(postFetch)) {\n // Refresh to ensure media links have not expired\n this.log('debug', `Refresh post #${_post.id}`);\n const postURL = URLHelper.constructPostsAPIURL({ postId: _post.id });\n const { json } = await this.commonFetchAPI(postURL, signal);\n let refreshed: Post | null = null;\n if (json) {\n refreshed = postsParser.parsePostsAPIResponse(json, postURL).posts[0] || null;\n if (!refreshed) {\n this.log('warn', `Refreshed post #${_post.id} but got empty value - going to use existing data`);\n }\n else if (refreshed.id !== _post.id) {\n this.log('warn', `Refreshed post #${_post.id} but ID mismatch - going to use existing data`);\n refreshed = null;\n }\n }\n else if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n else {\n this.log('warn', `Failed to refresh post #${_post.id} - going to use existing data`);\n }\n if (refreshed) {\n this.log('debug', `Use refreshed post data #${refreshed.id}`);\n post = refreshed;\n }\n }\n \n this.emit('targetBegin', { target: post });\n \n // Step 4.1: post directories\n const postDirs = this.fsHelper.getPostDirs(post);\n this.log('debug', 'Post directories:', postDirs);\n \n // Step 4.2: Check with status cache\n const statusCache = StatusCache.getInstance(this.config, postDirs.statusCache, this.logger);\n if (statusCache.validate(post, postDirs.root, this.config)) {\n this.log('info', `Skipped downloading post #${post.id}: already downloaded and nothing has changed since last download`);\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.AlreadyDownloaded,\n skipMessage: 'Target already downloaded and nothing has changed since last download'\n });\n skippedRedundant++;\n continue;\n }\n \n this.log('info', `Download post #${post.id} (${post.title})`);\n \n // Step 4.3: Check whether we should download post\n // -- 4.3.1: Viewability\n if (!post.isViewable) {\n if (this.config.include.lockedContent) {\n this.log('warn', `Post #${post.id} is not viewable by current user`);\n }\n else {\n this.log('warn', `Skipped downloading post #${post.id}: not viewable by current user`);\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.Inaccessible,\n skipMessage: 'Target is not viewable by current user'\n });\n skippedUnviewable++;\n continue;\n }\n }\n \n // -- 4.3.2: Config option 'include.postsWithMediaType'\n const postsWithMediaType = this.config.include.postsWithMediaType;\n if (postsWithMediaType !== 'any') {\n const hasAttachments = post.attachments.length > 0;\n const hasAudio = !!post.audio || !!post.audioPreview;\n const hasImages = post.images.length > 0;\n const hasVideo = !!post.video || !!post.videoPreview || !!(post.embed && post.embed.type === 'videoEmbed');\n \n let skip = false;\n if (postsWithMediaType === 'none') {\n skip = hasAttachments || hasAudio || hasImages || hasVideo;\n }\n else if (Array.isArray(postsWithMediaType)) {\n skip = !(\n (postsWithMediaType.includes('attachment') && hasAttachments) ||\n (postsWithMediaType.includes('audio') && hasAudio) ||\n (postsWithMediaType.includes('image') && hasImages) ||\n (postsWithMediaType.includes('video') && hasVideo));\n }\n \n if (skip) {\n this.log('warn', `Skipped downloading post #${post.id}: unmet media type criteria`);\n this.log('debug', 'Match criteria failed:', `config.include.postsWithMediaType: ${JSON.stringify(postsWithMediaType)} <-> post #${post.id}:`, {\n hasAttachments,\n hasAudio,\n hasImages,\n hasVideo\n });\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.UnmetMediaTypeCriteria,\n skipMessage: 'Target does not meet media type criteria'\n });\n skippedUnmetMediaTypeCriteria++;\n continue;\n }\n }\n \n // -- 4.3.3: Config option 'include.postsInTier'\n const postsInTier = this.config.include.postsInTier;\n const isAnyTier = postsInTier === 'any' || postsInTier.includes('any');\n if (!isAnyTier) {\n const applicableTierIds = postsInTier.filter((id) => post.campaign?.rewards.find((r) => r.id === id));\n if (!post.campaign) {\n this.log('warn', 'config.include.postsInTier: ignored - post missing campaign info');\n }\n else {\n this.log('debug', 'config.include.postsInTier: applicable tier IDs:', applicableTierIds);\n }\n let skip = false;\n if (!post.campaign) {\n skip = false;\n }\n else if (applicableTierIds.length === 0) {\n skip = true;\n }\n else if (!post.tiers.find((tier) => tier.id === 'patrons')) {\n skip = applicableTierIds.every((id) => !post.tiers.find((tier) => tier.id === id));\n }\n if (skip) {\n this.log('warn', `Skipped downloading post #${post.id}: not in tier`);\n this.log('debug', 'Match criteria failed:', `config.include.postsInTier: ${JSON.stringify(applicableTierIds)} <-> post #${post.id}:`, post.tiers);\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.NotInTier,\n skipMessage: 'Target not in tier'\n });\n skippedNotInTier++;\n continue;\n }\n if (post.campaign) {\n this.log('debug', 'Match criteria OK:', `config.include.postsInTier: ${JSON.stringify(applicableTierIds)} <-> post #${post.id}:`, post.tiers);\n }\n }\n\n // -- 4.3.4: Config option 'include.postsPublished'\n const postsPublishedAfter = this.config.include.postsPublished.after;\n const postsPublishedBefore = this.config.include.postsPublished.before;\n if (postsPublishedAfter || postsPublishedBefore) {\n const targetPublishedAt = post.publishedAt;\n let parsedPublishedAt: Date | null = null;\n if (!targetPublishedAt) {\n this.log('warn', `config.include.postsPublished: ignored - post #${post.id} missing publish date`);\n }\n else {\n try {\n parsedPublishedAt = new Date(targetPublishedAt);\n }\n catch (error: any) {\n this.log('error', `Failed to parse publish date of post #${post.id} (\"${targetPublishedAt}\"): `, error);\n this.log('warn', `config.include.postsPublished: ignored - publish date of post #${post.id} could not be parsed`);\n }\n }\n let skip = false;\n if (parsedPublishedAt) {\n const isAfter = postsPublishedAfter ? parsedPublishedAt.getTime() >= postsPublishedAfter.valueOf().getTime() : true;\n const isBefore = postsPublishedBefore ? parsedPublishedAt.getTime() < postsPublishedBefore.valueOf().getTime() : true;\n skip = !isAfter || !isBefore;\n let eq: string | null = null;\n if (postsPublishedAfter && postsPublishedBefore) {\n eq = `${postsPublishedAfter.toString()} <= *${targetPublishedAt}* < ${postsPublishedBefore.toString()}`;\n }\n else if (postsPublishedAfter) {\n eq = `${postsPublishedAfter.toString()} <= *${targetPublishedAt}*`;\n }\n else if (postsPublishedBefore) {\n eq = `*${targetPublishedAt}* < ${postsPublishedBefore.toString()}`;\n }\n if (eq) {\n if (skip) {\n this.log('warn', `Skipped downloading post #${post.id}: publish date out of range`);\n this.log('debug', `Publish date test failed for post #${post.id}: ${eq}`);\n }\n else {\n this.log('debug', `Publish date test OK for post #${post.id}: ${eq}`);\n }\n }\n if (skip) {\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.PublishDateOutOfRange,\n skipMessage: 'Publish date out of range'\n });\n skippedPublishDateOutOfRange++;\n continue;\n }\n }\n }\n\n \n // Step 4.4: Save post info\n if (this.config.include.contentInfo) {\n this.log('info', `Save post info #${post.id}`);\n this.emit('phaseBegin', { target: post, phase: 'saveInfo' });\n this.fsHelper.createDir(postDirs.info);\n // Post raw data might not be complete or consistent with other posts in the collection.\n // Fetch directly from API.\n // Strictly speaking, we should check for 'error' in results, but since it's not going to be fatal we'll just skip it.\n const { json: fetchedPostAPIData } = await this.commonFetchAPI(\n URLHelper.constructPostsAPIURL({\n postId: post.id,\n campaignId: post.campaign?.id\n }),\n signal\n );\n \n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n // Save summary and raw json\n const summary = generatePostSummary(post);\n const summaryFile = path.resolve(postDirs.info, 'info.txt');\n const saveSummaryResult = await this.fsHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, post, 'post summary');\n \n const postRawFile = path.resolve(postDirs.info, 'post-api.json');\n const savePostRawResult = await this.fsHelper.writeTextFile(\n postRawFile, fetchedPostAPIData || post.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(savePostRawResult, post, 'post API data');\n this.emit('phaseEnd', { target: post, phase: 'saveInfo' });\n \n // (Downloading of info media items deferred to the next step)\n }\n \n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseBegin', { target: post, phase: 'saveMedia' });\n }\n \n // Step 4.5: save embed info\n if (post.embed && this.config.include.contentMedia) {\n this.log('info', `Save embed info of post #${post.id}`);\n this.fsHelper.createDir(postDirs.embed);\n const embedSummary = generatePostEmbedSummary(post.embed);\n let embedFilename;\n switch (post.embed.type) {\n case 'videoEmbed':\n embedFilename = 'embedded-video.txt';\n break;\n case 'linkEmbed':\n embedFilename = 'embedded-link.txt';\n break;\n default:\n embedFilename = 'embedded-unknown.txt';\n }\n const embedFile = path.resolve(postDirs.embed, embedFilename);\n const saveSummaryResult = await this.fsHelper.writeTextFile(embedFile, embedSummary, this.config.fileExistsAction.content);\n this.logWriteTextFileResult(saveSummaryResult, post, 'embed info');\n }\n \n // Step 4.6: create download tasks\n if (this.config.include.previewMedia ||\n this.config.include.contentMedia ||\n this.config.include.contentInfo) {\n \n batch = this.#createDownloadTaskBatchForPost(post, postDirs);\n \n if (this.config.include.contentInfo) {\n const infoElements: Downloadable[] = [];\n if (post.coverImage) {\n infoElements.push(post.coverImage);\n }\n if (post.thumbnail) {\n infoElements.push(post.thumbnail);\n }\n if (infoElements.length > 0) {\n this.addToDownloadTaskBatch(batch,\n {\n target: infoElements,\n targetName: `post #${post.id} -> info elements`,\n destDir: postDirs.info,\n fileExistsAction: this.config.fileExistsAction.info\n }\n );\n }\n }\n \n this.log('info', `Download batch created (#${batch.id}): ${batch.getTasks('pending').length} downloads pending`);\n this.emit('phaseBegin', { target: post, phase: 'batchDownload', batch });\n \n await batch.start();\n \n // Step 4.7: Update status cache\n statusCache.updateOnDownload(post, postDirs.root, batch.getTasks('error').length > 0, this.config);\n \n await batch.destroy();\n batch = null;\n this.emit('phaseEnd', { target: post, phase: 'batchDownload'});\n }\n \n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseEnd', { target: post, phase: 'saveMedia' });\n }\n \n downloaded++;\n this.emit('targetEnd', { target: post, isSkipped: false });\n \n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n }\n }\n \n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n // Done\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n if (postFetch.type === 'byUser') {\n this.log('info', `Done downloading posts by '${postFetch.vanity}'`);\n }\n else if (postFetch.type === 'byUserId') {\n this.log('info', `Done downloading posts by user #${postFetch.userId}`);\n }\n else if (postFetch.type === 'byCollection') {\n this.log('info', `Done downloading posts in collection #${postFetch.collectionId}`);\n }\n else {\n this.log('info', `Done downloading post #${postFetch.postId}`);\n }\n let endMessage = 'Done';\n if (this.#isFetchingMultiplePosts(postFetch)) {\n const skippedStrParts: string[] = [];\n if (skippedUnviewable) {\n skippedStrParts.push(`${skippedUnviewable} unviewable`);\n }\n if (skippedRedundant) {\n skippedStrParts.push(`${skippedRedundant} redundant`);\n }\n if (skippedUnmetMediaTypeCriteria) {\n skippedStrParts.push(`${skippedUnmetMediaTypeCriteria} with unmet media type criteria`);\n }\n if (skippedNotInTier) {\n skippedStrParts.push(`${skippedNotInTier} not in tier`);\n }\n if (skippedPublishDateOutOfRange) {\n skippedStrParts.push(`${skippedPublishDateOutOfRange} with publish date out of range`);\n }\n const skippedStr = skippedStrParts.length > 0 ? ` (skipped: ${skippedStrParts.join(', ')})` : '';\n endMessage = `Total ${downloaded} / ${postsFetcher.getTotal()} posts processed${skippedStr}`;\n this.log('info', endMessage);\n }\n this.emit('end', { aborted: false, message: endMessage });\n this.#startPromise = null;\n resolve();\n })();\n })\n .finally(() => {\n void (async () => {\n if (this.logger) {\n await this.logger.end();\n }\n this.#startPromise = null;\n })();\n });\n\n return this.#startPromise;\n }\n\n #isFetchingMultiplePosts(postFetch: DownloaderConfig<Post>['postFetch']): postFetch is DownloaderConfig<Post>['postFetch'] & { type: 'byUser' | 'byUserId' | 'byCollection' } {\n return postFetch.type === 'byUser' || postFetch.type === 'byUserId' || postFetch.type === 'byCollection';\n }\n\n async __getCampaign(signal?: AbortSignal) {\n let url: string | null;\n const postFetch = this.config.postFetch;\n switch (postFetch.type) {\n case 'byUser':\n url = URLHelper.constructCampaignPageURL({ vanity: postFetch.vanity });\n break;\n case 'byUserId':\n url = URLHelper.constructCampaignPageURL({ userId: postFetch.userId });\n break;\n default:\n url = null;\n }\n if (!url) {\n throw Error('Internal error: invalid config');\n }\n const postsFetcher = new PostsFetcher({\n config: this.config,\n fetcher: this.fetcher,\n logger: this.logger,\n signal\n });\n const { campaignId } = await postsFetcher.getInitialData(url);\n const postsParser = new PostParser(this.logger);\n const res = await this.fetchCampaign(campaignId);\n if (signal?.aborted) {\n throw new Error('Aborted');\n }\n if (res.error) {\n throw res.error;\n }\n return postsParser.parseCampaignAPIResponse(res.json);\n }\n\n #createDownloadTaskBatchForPost(post: Post, postDirs: ReturnType<typeof this.fsHelper['getPostDirs']>) {\n\n const incPreview = this.config.include.previewMedia;\n const incContent = this.config.include.contentMedia;\n\n const __incPreview = (mediaType: 'audio' | 'video' | 'image') => {\n if (typeof incPreview === 'boolean') {\n return incPreview;\n }\n return incPreview.includes(mediaType);\n };\n\n const __incContent = (mediaType: 'audio' | 'video' | 'image' | 'attachment') => {\n if (typeof incContent === 'boolean') {\n return incContent;\n }\n return incContent.includes(mediaType);\n };\n\n const batch = this.createDownloadTaskBatch(\n `Post #${post.id} (${post.title})`,\n\n __incPreview('audio') && post.audioPreview ? {\n target: [ post.audioPreview ],\n targetName: `post #${post.id} -> audio preview`,\n destDir: postDirs.audioPreview,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incPreview('video') && post.videoPreview ? {\n target: [ post.videoPreview ],\n targetName: `post #${post.id} -> video preview`,\n destDir: postDirs.videoPreview,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n /**\n * If post is not viewable by current user, its images will be\n * blurry and we should categorize them as image previews.\n */\n __incPreview('image') && post.images.length > 0 && !post.isViewable ? {\n target: post.images,\n targetName: `post #${post.id} -> image previews`,\n destDir: postDirs.imagePreviews,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('audio') && post.audio ? {\n target: [ post.audio ],\n targetName: `post #${post.id} -> audio`,\n destDir: postDirs.audio,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('video') && post.video ? {\n target: [ post.video ],\n targetName: `post #${post.id} -> video`,\n destDir: postDirs.video,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('image') && post.images.length > 0 && post.isViewable ? {\n target: post.images,\n targetName: `post #${post.id} -> images`,\n destDir: postDirs.images,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('attachment') && post.attachments.length > 0 ? {\n target: post.attachments,\n targetName: `post #${post.id} -> attachments`,\n destDir: postDirs.attachments,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('video') && post.embed &&\n (isYouTubeEmbed(post.embed) || DownloadTaskFactory.findEmbedDownloader(this.config.embedDownloaders, post.embed.provider)) ?\n {\n target: [ post.embed ],\n targetName: `post #${post.id} -> embedded ${post.embed.provider} video`,\n destDir: postDirs.embed,\n fileExistsAction: this.config.fileExistsAction.content\n } : null\n );\n\n return batch;\n }\n}\n"]}
1
+ {"version":3,"file":"PostDownloader.js","sourceRoot":"","sources":["../../src/downloaders/PostDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import URLHelper from '../utils/URLHelper.js';\nimport Downloader, { type DownloaderConfig, type DownloaderStartParams } from './Downloader.js';\nimport type DownloadTaskBatch from './task/DownloadTaskBatch.js';\nimport PostParser from '../parsers/PostParser.js';\nimport { type Post } from '../entities/Post.js';\nimport { type Downloadable, isYouTubeEmbed } from '../entities/Downloadable.js';\nimport StatusCache from './cache/StatusCache.js';\nimport { generatePostEmbedSummary, generatePostSummary } from './templates/PostInfo.js';\nimport path from 'path';\nimport { TargetSkipReason } from './DownloaderEvent.js';\nimport DownloadTaskFactory from './task/DownloadTaskFactory.js';\nimport PostsFetcher from './PostsFetcher.js';\n\nexport default class PostDownloader extends Downloader<Post> {\n\n static version = '1.1.1';\n\n name = 'PostDownloader';\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>((resolve) => {\n void (async () => {\n const { signal } = params || {};\n const postFetch = this.config.postFetch;\n let batch: DownloadTaskBatch | null = null;\n \n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n const abortHandler = () => {\n void (async () => {\n this.log('info', 'Abort signal received');\n if (batch) {\n await batch.abort();\n }\n })();\n };\n if (signal) {\n signal.addEventListener('abort', abortHandler, { once: true });\n }\n \n if (postFetch.type === 'byUser') {\n this.log('info', `Targeting posts by '${postFetch.vanity}'`);\n }\n else if (postFetch.type === 'byUserId') {\n this.log('info', `Targeting posts by user #${postFetch.userId}`);\n }\n else if (postFetch.type === 'byCollection') {\n this.log('info', `Targeting posts in collection #${postFetch.collectionId}`);\n }\n else { // Single\n this.log('info', `Targeting post #${postFetch.postId}`);\n }\n if (this.#isFetchingMultiplePosts(postFetch) && postFetch.filters) {\n const filterStr = Object.entries(postFetch.filters).map(([ key, value ]) => `${key}=${value}`).join('; ');\n if (filterStr) {\n this.log('info', `Filters: ${filterStr}`);\n }\n }\n \n // Step 1: Get posts (if by user) or target post\n const postsFetcher = new PostsFetcher({\n config: this.config,\n fetcher: this.fetcher,\n logger: this.logger,\n signal\n });\n postsFetcher.on('statusChange', ({current}) => {\n if (current.status === 'running') {\n this.emit('fetchBegin', { targetType: postsFetcher.getTargetType() });\n }\n });\n postsFetcher.begin();\n \n // Step 2: download posts in each fetched collection\n let downloaded = 0;\n let skippedUnviewable = 0;\n let skippedRedundant = 0;\n let skippedUnmetMediaTypeCriteria = 0;\n let skippedNotInTier = 0;\n let skippedPublishDateOutOfRange = 0;\n let campaignSaved = false;\n const postsParser = new PostParser(this.logger);\n while (postsFetcher.hasNext()) {\n const { collection, aborted, error } = await postsFetcher.next();\n if (!collection || aborted) {\n break;\n }\n if (!collection && error) {\n this.emit('end', { aborted: false, error, message: 'PostsFetcher error' });\n resolve();\n return;\n }\n if (!campaignSaved && collection.posts[0]?.campaign) {\n await this.saveCampaignInfo(collection.posts[0].campaign, signal);\n campaignSaved = true;\n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n }\n \n for (const _post of collection.posts) {\n \n let post = _post;\n \n if (this.#isFetchingMultiplePosts(postFetch)) {\n // Refresh to ensure media links have not expired\n this.log('debug', `Refresh post #${_post.id}`);\n const postURL = URLHelper.constructPostsAPIURL({ postId: _post.id });\n const { json } = await this.commonFetchAPI(postURL, signal);\n let refreshed: Post | null = null;\n if (json) {\n refreshed = postsParser.parsePostsAPIResponse(json, postURL).posts[0] || null;\n if (!refreshed) {\n this.log('warn', `Refreshed post #${_post.id} but got empty value - going to use existing data`);\n }\n else if (refreshed.id !== _post.id) {\n this.log('warn', `Refreshed post #${_post.id} but ID mismatch - going to use existing data`);\n refreshed = null;\n }\n }\n else if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n else {\n this.log('warn', `Failed to refresh post #${_post.id} - going to use existing data`);\n }\n if (refreshed) {\n this.log('debug', `Use refreshed post data #${refreshed.id}`);\n post = refreshed;\n }\n }\n \n this.emit('targetBegin', { target: post });\n \n // Step 4.1: post directories\n const postDirs = this.fsHelper.getPostDirs(post);\n this.log('debug', 'Post directories:', postDirs);\n \n // Step 4.2: Check with status cache\n const statusCache = StatusCache.getInstance(this.config, postDirs.statusCache, this.logger);\n if (statusCache.validate(post, postDirs.root, this.config)) {\n this.log('info', `Skipped downloading post #${post.id}: already downloaded and nothing has changed since last download`);\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.AlreadyDownloaded,\n skipMessage: 'Target already downloaded and nothing has changed since last download'\n });\n skippedRedundant++;\n continue;\n }\n \n this.log('info', `Download post #${post.id} (${post.title})`);\n \n // Step 4.3: Check whether we should download post\n // -- 4.3.1: Viewability\n if (!post.isViewable) {\n if (this.config.include.lockedContent) {\n this.log('warn', `Post #${post.id} is not viewable by current user`);\n }\n else {\n this.log('warn', `Skipped downloading post #${post.id}: not viewable by current user`);\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.Inaccessible,\n skipMessage: 'Target is not viewable by current user'\n });\n skippedUnviewable++;\n continue;\n }\n }\n \n // -- 4.3.2: Config option 'include.postsWithMediaType'\n const postsWithMediaType = this.config.include.postsWithMediaType;\n if (postsWithMediaType !== 'any') {\n const hasAttachments = post.attachments.length > 0;\n const hasAudio = !!post.audio || !!post.audioPreview;\n const hasImages = post.images.length > 0;\n const hasVideo = !!post.video || !!post.videoPreview || !!(post.embed && post.embed.type === 'videoEmbed');\n \n let skip = false;\n if (postsWithMediaType === 'none') {\n skip = hasAttachments || hasAudio || hasImages || hasVideo;\n }\n else if (Array.isArray(postsWithMediaType)) {\n skip = !(\n (postsWithMediaType.includes('attachment') && hasAttachments) ||\n (postsWithMediaType.includes('audio') && hasAudio) ||\n (postsWithMediaType.includes('image') && hasImages) ||\n (postsWithMediaType.includes('video') && hasVideo));\n }\n \n if (skip) {\n this.log('warn', `Skipped downloading post #${post.id}: unmet media type criteria`);\n this.log('debug', 'Match criteria failed:', `config.include.postsWithMediaType: ${JSON.stringify(postsWithMediaType)} <-> post #${post.id}:`, {\n hasAttachments,\n hasAudio,\n hasImages,\n hasVideo\n });\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.UnmetMediaTypeCriteria,\n skipMessage: 'Target does not meet media type criteria'\n });\n skippedUnmetMediaTypeCriteria++;\n continue;\n }\n }\n \n // -- 4.3.3: Config option 'include.postsInTier'\n const postsInTier = this.config.include.postsInTier;\n const isAnyTier = postsInTier === 'any' || postsInTier.includes('any');\n if (!isAnyTier) {\n const applicableTierIds = postsInTier.filter((id) => post.campaign?.rewards.find((r) => r.id === id));\n if (!post.campaign) {\n this.log('warn', 'config.include.postsInTier: ignored - post missing campaign info');\n }\n else {\n this.log('debug', 'config.include.postsInTier: applicable tier IDs:', applicableTierIds);\n }\n let skip = false;\n if (!post.campaign) {\n skip = false;\n }\n else if (applicableTierIds.length === 0) {\n skip = true;\n }\n else if (!post.tiers.find((tier) => tier.id === 'patrons')) {\n skip = applicableTierIds.every((id) => !post.tiers.find((tier) => tier.id === id));\n }\n if (skip) {\n this.log('warn', `Skipped downloading post #${post.id}: not in tier`);\n this.log('debug', 'Match criteria failed:', `config.include.postsInTier: ${JSON.stringify(applicableTierIds)} <-> post #${post.id}:`, post.tiers);\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.NotInTier,\n skipMessage: 'Target not in tier'\n });\n skippedNotInTier++;\n continue;\n }\n if (post.campaign) {\n this.log('debug', 'Match criteria OK:', `config.include.postsInTier: ${JSON.stringify(applicableTierIds)} <-> post #${post.id}:`, post.tiers);\n }\n }\n\n // -- 4.3.4: Config option 'include.postsPublished'\n const postsPublishedAfter = this.config.include.postsPublished.after;\n const postsPublishedBefore = this.config.include.postsPublished.before;\n if (postsPublishedAfter || postsPublishedBefore) {\n const targetPublishedAt = post.publishedAt;\n let parsedPublishedAt: Date | null = null;\n if (!targetPublishedAt) {\n this.log('warn', `config.include.postsPublished: ignored - post #${post.id} missing publish date`);\n }\n else {\n try {\n parsedPublishedAt = new Date(targetPublishedAt);\n }\n catch (error: any) {\n this.log('error', `Failed to parse publish date of post #${post.id} (\"${targetPublishedAt}\"): `, error);\n this.log('warn', `config.include.postsPublished: ignored - publish date of post #${post.id} could not be parsed`);\n }\n }\n let skip = false;\n if (parsedPublishedAt) {\n const isAfter = postsPublishedAfter ? parsedPublishedAt.getTime() >= postsPublishedAfter.valueOf().getTime() : true;\n const isBefore = postsPublishedBefore ? parsedPublishedAt.getTime() < postsPublishedBefore.valueOf().getTime() : true;\n skip = !isAfter || !isBefore;\n let eq: string | null = null;\n if (postsPublishedAfter && postsPublishedBefore) {\n eq = `${postsPublishedAfter.toString()} <= *${targetPublishedAt}* < ${postsPublishedBefore.toString()}`;\n }\n else if (postsPublishedAfter) {\n eq = `${postsPublishedAfter.toString()} <= *${targetPublishedAt}*`;\n }\n else if (postsPublishedBefore) {\n eq = `*${targetPublishedAt}* < ${postsPublishedBefore.toString()}`;\n }\n if (eq) {\n if (skip) {\n this.log('warn', `Skipped downloading post #${post.id}: publish date out of range`);\n this.log('debug', `Publish date test failed for post #${post.id}: ${eq}`);\n }\n else {\n this.log('debug', `Publish date test OK for post #${post.id}: ${eq}`);\n }\n }\n if (skip) {\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.PublishDateOutOfRange,\n skipMessage: 'Publish date out of range'\n });\n skippedPublishDateOutOfRange++;\n continue;\n }\n }\n }\n\n \n // Step 4.4: Save post info\n if (this.config.include.contentInfo) {\n this.log('info', `Save post info #${post.id}`);\n this.emit('phaseBegin', { target: post, phase: 'saveInfo' });\n this.fsHelper.createDir(postDirs.info);\n // Post raw data might not be complete or consistent with other posts in the collection.\n // Fetch directly from API.\n // Strictly speaking, we should check for 'error' in results, but since it's not going to be fatal we'll just skip it.\n const { json: fetchedPostAPIData } = await this.commonFetchAPI(\n URLHelper.constructPostsAPIURL({\n postId: post.id,\n campaignId: post.campaign?.id\n }),\n signal\n );\n \n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n // Save summary and raw json\n const summary = generatePostSummary(post);\n const summaryFile = path.resolve(postDirs.info, 'info.txt');\n const saveSummaryResult = await this.fsHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, post, 'post summary');\n \n const postRawFile = path.resolve(postDirs.info, 'post-api.json');\n const savePostRawResult = await this.fsHelper.writeTextFile(\n postRawFile, fetchedPostAPIData || post.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(savePostRawResult, post, 'post API data');\n this.emit('phaseEnd', { target: post, phase: 'saveInfo' });\n \n // (Downloading of info media items deferred to the next step)\n }\n \n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseBegin', { target: post, phase: 'saveMedia' });\n }\n \n // Step 4.5: save embed info\n if (post.embed && this.config.include.contentMedia) {\n this.log('info', `Save embed info of post #${post.id}`);\n this.fsHelper.createDir(postDirs.embed);\n const embedSummary = generatePostEmbedSummary(post.embed);\n let embedFilename;\n switch (post.embed.type) {\n case 'videoEmbed':\n embedFilename = 'embedded-video.txt';\n break;\n case 'linkEmbed':\n embedFilename = 'embedded-link.txt';\n break;\n default:\n embedFilename = 'embedded-unknown.txt';\n }\n const embedFile = path.resolve(postDirs.embed, embedFilename);\n const saveSummaryResult = await this.fsHelper.writeTextFile(embedFile, embedSummary, this.config.fileExistsAction.content);\n this.logWriteTextFileResult(saveSummaryResult, post, 'embed info');\n }\n \n // Step 4.6: create download tasks\n if (this.config.include.previewMedia ||\n this.config.include.contentMedia ||\n this.config.include.contentInfo) {\n \n batch = await this.#createDownloadTaskBatchForPost(post, postDirs, signal);\n\n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n if (this.config.include.contentInfo) {\n const infoElements: Downloadable[] = [];\n if (post.coverImage) {\n infoElements.push(post.coverImage);\n }\n if (post.thumbnail) {\n infoElements.push(post.thumbnail);\n }\n if (infoElements.length > 0) {\n await this.addToDownloadTaskBatch(batch,\n signal,\n {\n target: infoElements,\n targetName: `post #${post.id} -> info elements`,\n destDir: postDirs.info,\n fileExistsAction: this.config.fileExistsAction.info\n }\n );\n }\n }\n \n batch.prestart();\n this.log('info', `Download batch created (#${batch.id}): ${batch.getTasks('pending').length} downloads pending`);\n this.emit('phaseBegin', { target: post, phase: 'batchDownload', batch });\n \n await batch.start();\n \n // Step 4.7: Update status cache\n statusCache.updateOnDownload(post, postDirs.root, batch.getTasks('error').length > 0, this.config);\n \n await batch.destroy();\n batch = null;\n this.emit('phaseEnd', { target: post, phase: 'batchDownload'});\n }\n \n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseEnd', { target: post, phase: 'saveMedia' });\n }\n \n downloaded++;\n this.emit('targetEnd', { target: post, isSkipped: false });\n \n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n }\n }\n \n if (this.checkAbortSignal(signal, resolve)) {\n return;\n }\n \n // Done\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n if (postFetch.type === 'byUser') {\n this.log('info', `Done downloading posts by '${postFetch.vanity}'`);\n }\n else if (postFetch.type === 'byUserId') {\n this.log('info', `Done downloading posts by user #${postFetch.userId}`);\n }\n else if (postFetch.type === 'byCollection') {\n this.log('info', `Done downloading posts in collection #${postFetch.collectionId}`);\n }\n else {\n this.log('info', `Done downloading post #${postFetch.postId}`);\n }\n let endMessage = 'Done';\n if (this.#isFetchingMultiplePosts(postFetch)) {\n const skippedStrParts: string[] = [];\n if (skippedUnviewable) {\n skippedStrParts.push(`${skippedUnviewable} unviewable`);\n }\n if (skippedRedundant) {\n skippedStrParts.push(`${skippedRedundant} redundant`);\n }\n if (skippedUnmetMediaTypeCriteria) {\n skippedStrParts.push(`${skippedUnmetMediaTypeCriteria} with unmet media type criteria`);\n }\n if (skippedNotInTier) {\n skippedStrParts.push(`${skippedNotInTier} not in tier`);\n }\n if (skippedPublishDateOutOfRange) {\n skippedStrParts.push(`${skippedPublishDateOutOfRange} with publish date out of range`);\n }\n const skippedStr = skippedStrParts.length > 0 ? ` (skipped: ${skippedStrParts.join(', ')})` : '';\n endMessage = `Total ${downloaded} / ${postsFetcher.getTotal()} posts processed${skippedStr}`;\n this.log('info', endMessage);\n }\n this.emit('end', { aborted: false, message: endMessage });\n this.#startPromise = null;\n resolve();\n })();\n })\n .finally(() => {\n void (async () => {\n if (this.logger) {\n await this.logger.end();\n }\n this.#startPromise = null;\n })();\n });\n\n return this.#startPromise;\n }\n\n #isFetchingMultiplePosts(postFetch: DownloaderConfig<Post>['postFetch']): postFetch is DownloaderConfig<Post>['postFetch'] & { type: 'byUser' | 'byUserId' | 'byCollection' } {\n return postFetch.type === 'byUser' || postFetch.type === 'byUserId' || postFetch.type === 'byCollection';\n }\n\n async __getCampaign(signal?: AbortSignal) {\n let url: string | null;\n const postFetch = this.config.postFetch;\n switch (postFetch.type) {\n case 'byUser':\n url = URLHelper.constructCampaignPageURL({ vanity: postFetch.vanity });\n break;\n case 'byUserId':\n url = URLHelper.constructCampaignPageURL({ userId: postFetch.userId });\n break;\n default:\n url = null;\n }\n if (!url) {\n throw Error('Internal error: invalid config');\n }\n const postsFetcher = new PostsFetcher({\n config: this.config,\n fetcher: this.fetcher,\n logger: this.logger,\n signal\n });\n const { campaignId } = await postsFetcher.getInitialData(url);\n const postsParser = new PostParser(this.logger);\n const res = await this.fetchCampaign(campaignId);\n if (signal?.aborted) {\n throw new Error('Aborted');\n }\n if (res.error) {\n throw res.error;\n }\n return postsParser.parseCampaignAPIResponse(res.json);\n }\n\n #createDownloadTaskBatchForPost(post: Post, postDirs: ReturnType<typeof this.fsHelper['getPostDirs']>, signal?: AbortSignal) {\n\n const incPreview = this.config.include.previewMedia;\n const incContent = this.config.include.contentMedia;\n\n const __incPreview = (mediaType: 'audio' | 'video' | 'image') => {\n if (typeof incPreview === 'boolean') {\n return incPreview;\n }\n return incPreview.includes(mediaType);\n };\n\n const __incContent = (mediaType: 'audio' | 'video' | 'image' | 'attachment') => {\n if (typeof incContent === 'boolean') {\n return incContent;\n }\n return incContent.includes(mediaType);\n };\n\n const batch = this.createDownloadTaskBatch(\n `Post #${post.id} (${post.title})`,\n signal,\n\n __incPreview('audio') && post.audioPreview ? {\n target: [ post.audioPreview ],\n targetName: `post #${post.id} -> audio preview`,\n destDir: postDirs.audioPreview,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incPreview('video') && post.videoPreview ? {\n target: [ post.videoPreview ],\n targetName: `post #${post.id} -> video preview`,\n destDir: postDirs.videoPreview,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n /**\n * If post is not viewable by current user, its images will be\n * blurry and we should categorize them as image previews.\n */\n __incPreview('image') && post.images.length > 0 && !post.isViewable ? {\n target: post.images,\n targetName: `post #${post.id} -> image previews`,\n destDir: postDirs.imagePreviews,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('audio') && post.audio ? {\n target: [ post.audio ],\n targetName: `post #${post.id} -> audio`,\n destDir: postDirs.audio,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('video') && post.video ? {\n target: [ post.video ],\n targetName: `post #${post.id} -> video`,\n destDir: postDirs.video,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('image') && post.images.length > 0 && post.isViewable ? {\n target: post.images,\n targetName: `post #${post.id} -> images`,\n destDir: postDirs.images,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('attachment') && post.attachments.length > 0 ? {\n target: post.attachments,\n targetName: `post #${post.id} -> attachments`,\n destDir: postDirs.attachments,\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('video') && post.embed &&\n (isYouTubeEmbed(post.embed) || DownloadTaskFactory.findEmbedDownloader(this.config.embedDownloaders, post.embed.provider)) ?\n {\n target: [ post.embed ],\n targetName: `post #${post.id} -> embedded ${post.embed.provider} video`,\n destDir: postDirs.embed,\n fileExistsAction: this.config.fileExistsAction.content\n } : null\n );\n\n return batch;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ProductDownloader.d.ts","sourceRoot":"","sources":["../../src/downloaders/ProductDownloader.ts"],"names":[],"mappings":"AAEA,OAAO,UAAU,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAMzE,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGtD,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,UAAU,CAAC,OAAO,CAAC;;IAEhE,MAAM,CAAC,OAAO,SAAW;IAEzB,IAAI,SAAuB;IAI3B,KAAK,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CAgMrD"}
1
+ {"version":3,"file":"ProductDownloader.d.ts","sourceRoot":"","sources":["../../src/downloaders/ProductDownloader.ts"],"names":[],"mappings":"AAEA,OAAO,UAAU,EAAE,EAAE,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAMzE,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAGtD,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,UAAU,CAAC,OAAO,CAAC;;IAEhE,MAAM,CAAC,OAAO,SAAW;IAEzB,IAAI,SAAuB;IAI3B,KAAK,CAAC,MAAM,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;CAsMrD"}