patreon-dl 2.4.2 → 2.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -225,6 +225,11 @@ Note that you can override an option from a configuration file with one provided
225
225
 
226
226
  ## Changelog
227
227
 
228
+ v2.4.3
229
+ - Fix YouTube embeds failing to download due to YT changes
230
+ - Add fallback download logic to Vimeo download script
231
+ - Fix error when downloading video ([#75](https://github.com/patrickkfkan/patreon-dl/issues/75))
232
+
228
233
  v2.4.2
229
234
  - Fix YouTube embeds failing to download due to YT changes
230
235
  - Fix slow YouTube downloads ([#66](https://github.com/patrickkfkan/patreon-dl/issues/66))
@@ -16,12 +16,13 @@
16
16
  * --yt-dlp "</path/to/yt-dlp>": if yt-dlp is not in the PATH
17
17
  *
18
18
  * Upon encountering a post with embedded Vimeo content, 'patreon-dl' will call this script. The following then happens:
19
- * - This script obtains the video URL from 'embed.html' or 'embed.url'. The former is always preferable since it is what's actually
20
- * played within the Patreon post, and furthermore 'embed.url' sometimes returns "Page not found"
21
- * (see issue: https://github.com/patrickkfkan/patreon-dl/issues/65).
19
+ * - This script obtains the video URL from 'embed.html' or 'embed.url'. The former ("player URL") is always preferable
20
+ * since it is what's actually played within the Patreon post, and furthermore 'embed.url' sometimes returns
21
+ * "Page not found" (see issue: https://github.com/patrickkfkan/patreon-dl/issues/65).
22
22
  * - The URL is passed to yt-dlp.
23
23
  * - yt-dlp downloads the video from URL and saves it to 'dest.dir'. The filename is determined by the specified
24
24
  * format '%(title)s.%(ext)s' (see: https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#output-template).
25
+ * - Fallback to embed URL if player URL fails to download.
25
26
  *
26
27
  */
27
28
 
@@ -164,8 +165,17 @@ if (!url) {
164
165
  process.exit(1);
165
166
  }
166
167
 
168
+ async function doDownload(_url) {
169
+ let code = await download(_url, o, videoPassword, ytdlpPath);
170
+ if (code !== 0 && _url !== embedURL && embedURL) {
171
+ console.log(`Download failed - retrying with embed URL "${embedURL}"`);
172
+ return await doDownload(embedURL);
173
+ }
174
+ return code;
175
+ }
176
+
167
177
  console.log(`Going to download video from "${url}"`);
168
178
 
169
- download(url, o, videoPassword, ytdlpPath).then((code) => {
179
+ doDownload(url).then((code) => {
170
180
  process.exit(code);
171
181
  });
@@ -14,7 +14,7 @@ import Formatter from '../../utils/Formatter.js';
14
14
  import URLHelper from '../../utils/URLHelper.js';
15
15
  import DownloadTask from './DownloadTask.js';
16
16
  import spawn from '@patrickkfkan/cross-spawn';
17
- import stringArgv from 'string-argv';
17
+ import split from 'argv-split'; // Switched from 'string-argv' which does not split nested quotes properly
18
18
  class ExternalDownloaderTask extends DownloadTask {
19
19
  constructor(params) {
20
20
  super(params);
@@ -171,7 +171,7 @@ class ExternalDownloaderTask extends DownloadTask {
171
171
  'cookie': config.cookie || '',
172
172
  'dest.dir': destDir
173
173
  };
174
- const args = stringArgv(dl.exec);
174
+ const args = split(dl.exec);
175
175
  const cmd = args.shift();
176
176
  if (!cmd) {
177
177
  __log('warn', 'Could not create task: no command specified');
@@ -1 +1 @@
1
- {"version":3,"file":"ExternalDownloaderTask.js","sourceRoot":"","sources":["../../../src/downloaders/task/ExternalDownloaderTask.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ChildProcess } from 'child_process';\nimport { type PostEmbed } from '../../entities/Post.js';\nimport Formatter from '../../utils/Formatter.js';\nimport URLHelper from '../../utils/URLHelper.js';\nimport {type LogLevel} from '../../utils/logging/Logger.js';\nimport type Logger from '../../utils/logging/Logger.js';\nimport { type EmbedDownloader } from '../DownloaderOptions.js';\nimport DownloadTask, { type DownloadTaskCallbacks, type DownloadTaskParams } from './DownloadTask.js';\nimport spawn from '@patrickkfkan/cross-spawn';\nimport stringArgv from 'string-argv';\nimport { type DownloaderConfig } from '../Downloader.js';\n\nexport interface ExternalDownloaderTaskParams extends DownloadTaskParams {\n name: string;\n exec: {\n command: string;\n args: string[];\n };\n}\n\nexport default class ExternalDownloaderTask extends DownloadTask {\n\n protected name: string;\n\n #exec: ExternalDownloaderTaskParams['exec'];\n #proc: ChildProcess | null;\n #abortController: AbortController | null;\n #abortingCallback: (() => void) | null;\n\n constructor(params: ExternalDownloaderTaskParams) {\n super(params);\n this.#exec = params.exec;\n this.#abortController = null;\n this.#abortingCallback = null;\n this.#proc = null;\n this.name = params.name;\n }\n\n protected resolveDestPath() {\n return Promise.resolve('(not applicable)');\n } \n\n protected doStart() {\n return new Promise<void>((resolve) => {\n\n if (this.status === 'aborted') {\n resolve();\n return;\n }\n\n try {\n this.#abortController = new AbortController();\n const commandStr = this.#getCommandString();\n\n if (this.dryRun) {\n this.notifyStart();\n this.log('debug', `(dry-run) -> Skip command \"${commandStr}\"`);\n this.notifyComplete();\n resolve();\n return;\n }\n\n this.log('debug', `Going to execute \"${commandStr}\"`);\n const proc = spawn(this.#exec.command, this.#exec.args);\n this.log('debug', `[pid: ${proc.pid}] Exec \"${commandStr}\"`);\n let resolved = false;\n let lastErrMsg: string | null = null;\n\n proc.stdout?.on('data', (data) => {\n this.log('debug', `[pid ${proc.pid}] stdout:`, data.toString());\n });\n\n proc.stderr?.on('data', (data) => {\n this.log('warn', `[pid ${proc.pid}] stderr:`, data.toString());\n lastErrMsg = data;\n });\n\n proc.on('error', (err) => {\n resolved = true;\n if (this.#abortingCallback) {\n this.#abortingCallback();\n return;\n }\n this.notifyError(err);\n resolve();\n });\n\n proc.on('exit', (code, signal) => {\n if (resolved) {\n return;\n }\n resolved = true;\n if (this.#abortingCallback) {\n this.log('debug', `[pid: ${proc.pid}] Process exit due to abort`);\n this.#abortingCallback();\n return;\n }\n const signalStr = signal !== null ? `; signal: ${signal}` : '';\n this.log('debug', `[pid: ${proc.pid}] Process exit (code: ${code}${signalStr})`);\n if (code === 0) {\n this.notifyComplete();\n }\n else {\n const e = lastErrMsg ? `. Last captured error message: ${lastErrMsg}` : '';\n this.notifyError(`Process failed with exit code ${code} (pid: ${proc.pid})${e}`);\n }\n resolve();\n });\n\n this.#proc = proc;\n this.notifyStart();\n\n this.#abortController.signal.onabort = () => {\n if (proc.pid) {\n proc.kill('SIGKILL');\n }\n else if (this.#abortingCallback) {\n this.#abortingCallback();\n resolve();\n }\n };\n }\n catch (error: any) {\n if (this.#abortingCallback) {\n this.#abortingCallback();\n return;\n }\n this.notifyError(error);\n resolve();\n }\n })\n .finally(() => {\n if (this.#proc) {\n this.#proc.removeAllListeners();\n this.#proc.stdout?.removeAllListeners();\n this.#proc.stderr?.removeAllListeners();\n this.#proc = null;\n }\n this.#abortController = null;\n });\n }\n\n protected async doAbort() {\n return new Promise<void>((resolve) => {\n if (this.#abortController) {\n this.#abortingCallback = () => {\n this.#abortingCallback = null;\n this.notifyAbort();\n resolve();\n };\n this.#abortController.abort();\n }\n else {\n resolve();\n }\n });\n }\n\n protected async doDestroy() {\n this.#proc?.removeAllListeners();\n this.#proc = null;\n return Promise.resolve();\n }\n\n protected doGetProgress() {\n return undefined;\n }\n\n #getCommandString() {\n const quotedArgs = this.#exec.args.map((arg) => {\n const _arg = arg.trim();\n if (_arg.startsWith('\"') && _arg.endsWith('\"')) {\n return _arg;\n }\n if (_arg.includes('=') && _arg.startsWith('-')) {\n const equalPosition = _arg.indexOf('=');\n const argKey = _arg.substring(0, equalPosition);\n let argValue = _arg.substring(equalPosition);\n if (argValue.includes(' ')) {\n argValue = `\"${argValue}\"`;\n }\n return `${argKey}=${argValue}`;\n }\n if (_arg.includes(' ')) {\n return `\"${_arg}\"`;\n }\n return _arg;\n });\n return [\n this.#exec.command,\n ...quotedArgs\n ].join(' ');\n }\n\n static fromEmbedDownloader(\n config: DownloaderConfig<any>,\n dl: EmbedDownloader,\n embed: PostEmbed,\n destDir: string,\n callbacks: DownloadTaskCallbacks | null,\n logger: Logger | null | undefined\n ) {\n if (!embed.url) {\n return null;\n }\n const originator = `embed.downloader.${embed.provider}`;\n const __log = (level: LogLevel, ...message: any[]) => {\n logger?.log({\n level,\n originator,\n message\n });\n };\n if (!URLHelper.validateURL(embed.url)) {\n __log('warn', `Could not create task: invalid URL \"${embed.url}\"`);\n return null;\n }\n const dict = {\n 'post.id': embed.postId,\n 'post.url': embed.postURL,\n 'embed.provider': embed.provider,\n 'embed.provider.url': embed.providerURL,\n 'embed.url': embed.url,\n 'embed.subject': embed.subject,\n 'embed.html': embed.html,\n 'cookie': config.cookie || '',\n 'dest.dir': destDir\n };\n\n const args = stringArgv(dl.exec);\n const cmd = args.shift();\n if (!cmd) {\n __log('warn', 'Could not create task: no command specified');\n return null;\n }\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n const interpolated = Formatter.format(arg, dict).result.trim();\n if (!interpolated && arg !== '{cookie}') {\n __log('warn', `Could not create task: got empty string for command arg '${arg}'`);\n return null;\n }\n args[i] = interpolated;\n }\n\n return new ExternalDownloaderTask({\n name: originator,\n exec: {\n command: cmd,\n args\n },\n config,\n callbacks,\n logger,\n src: embed.url,\n srcEntity: embed\n });\n }\n}\n"]}
1
+ {"version":3,"file":"ExternalDownloaderTask.js","sourceRoot":"","sources":["../../../src/downloaders/task/ExternalDownloaderTask.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ChildProcess } from 'child_process';\nimport { type PostEmbed } from '../../entities/Post.js';\nimport Formatter from '../../utils/Formatter.js';\nimport URLHelper from '../../utils/URLHelper.js';\nimport {type LogLevel} from '../../utils/logging/Logger.js';\nimport type Logger from '../../utils/logging/Logger.js';\nimport { type EmbedDownloader } from '../DownloaderOptions.js';\nimport DownloadTask, { type DownloadTaskCallbacks, type DownloadTaskParams } from './DownloadTask.js';\nimport spawn from '@patrickkfkan/cross-spawn';\nimport split from 'argv-split'; // Switched from 'string-argv' which does not split nested quotes properly\nimport { type DownloaderConfig } from '../Downloader.js';\n\nexport interface ExternalDownloaderTaskParams extends DownloadTaskParams {\n name: string;\n exec: {\n command: string;\n args: string[];\n };\n}\n\nexport default class ExternalDownloaderTask extends DownloadTask {\n\n protected name: string;\n\n #exec: ExternalDownloaderTaskParams['exec'];\n #proc: ChildProcess | null;\n #abortController: AbortController | null;\n #abortingCallback: (() => void) | null;\n\n constructor(params: ExternalDownloaderTaskParams) {\n super(params);\n this.#exec = params.exec;\n this.#abortController = null;\n this.#abortingCallback = null;\n this.#proc = null;\n this.name = params.name;\n }\n\n protected resolveDestPath() {\n return Promise.resolve('(not applicable)');\n } \n\n protected doStart() {\n return new Promise<void>((resolve) => {\n\n if (this.status === 'aborted') {\n resolve();\n return;\n }\n\n try {\n this.#abortController = new AbortController();\n const commandStr = this.#getCommandString();\n\n if (this.dryRun) {\n this.notifyStart();\n this.log('debug', `(dry-run) -> Skip command \"${commandStr}\"`);\n this.notifyComplete();\n resolve();\n return;\n }\n\n this.log('debug', `Going to execute \"${commandStr}\"`);\n const proc = spawn(this.#exec.command, this.#exec.args);\n this.log('debug', `[pid: ${proc.pid}] Exec \"${commandStr}\"`);\n let resolved = false;\n let lastErrMsg: string | null = null;\n\n proc.stdout?.on('data', (data) => {\n this.log('debug', `[pid ${proc.pid}] stdout:`, data.toString());\n });\n\n proc.stderr?.on('data', (data) => {\n this.log('warn', `[pid ${proc.pid}] stderr:`, data.toString());\n lastErrMsg = data;\n });\n\n proc.on('error', (err) => {\n resolved = true;\n if (this.#abortingCallback) {\n this.#abortingCallback();\n return;\n }\n this.notifyError(err);\n resolve();\n });\n\n proc.on('exit', (code, signal) => {\n if (resolved) {\n return;\n }\n resolved = true;\n if (this.#abortingCallback) {\n this.log('debug', `[pid: ${proc.pid}] Process exit due to abort`);\n this.#abortingCallback();\n return;\n }\n const signalStr = signal !== null ? `; signal: ${signal}` : '';\n this.log('debug', `[pid: ${proc.pid}] Process exit (code: ${code}${signalStr})`);\n if (code === 0) {\n this.notifyComplete();\n }\n else {\n const e = lastErrMsg ? `. Last captured error message: ${lastErrMsg}` : '';\n this.notifyError(`Process failed with exit code ${code} (pid: ${proc.pid})${e}`);\n }\n resolve();\n });\n\n this.#proc = proc;\n this.notifyStart();\n\n this.#abortController.signal.onabort = () => {\n if (proc.pid) {\n proc.kill('SIGKILL');\n }\n else if (this.#abortingCallback) {\n this.#abortingCallback();\n resolve();\n }\n };\n }\n catch (error: any) {\n if (this.#abortingCallback) {\n this.#abortingCallback();\n return;\n }\n this.notifyError(error);\n resolve();\n }\n })\n .finally(() => {\n if (this.#proc) {\n this.#proc.removeAllListeners();\n this.#proc.stdout?.removeAllListeners();\n this.#proc.stderr?.removeAllListeners();\n this.#proc = null;\n }\n this.#abortController = null;\n });\n }\n\n protected async doAbort() {\n return new Promise<void>((resolve) => {\n if (this.#abortController) {\n this.#abortingCallback = () => {\n this.#abortingCallback = null;\n this.notifyAbort();\n resolve();\n };\n this.#abortController.abort();\n }\n else {\n resolve();\n }\n });\n }\n\n protected async doDestroy() {\n this.#proc?.removeAllListeners();\n this.#proc = null;\n return Promise.resolve();\n }\n\n protected doGetProgress() {\n return undefined;\n }\n\n #getCommandString() {\n const quotedArgs = this.#exec.args.map((arg) => {\n const _arg = arg.trim();\n if (_arg.startsWith('\"') && _arg.endsWith('\"')) {\n return _arg;\n }\n if (_arg.includes('=') && _arg.startsWith('-')) {\n const equalPosition = _arg.indexOf('=');\n const argKey = _arg.substring(0, equalPosition);\n let argValue = _arg.substring(equalPosition);\n if (argValue.includes(' ')) {\n argValue = `\"${argValue}\"`;\n }\n return `${argKey}=${argValue}`;\n }\n if (_arg.includes(' ')) {\n return `\"${_arg}\"`;\n }\n return _arg;\n });\n return [\n this.#exec.command,\n ...quotedArgs\n ].join(' ');\n }\n\n static fromEmbedDownloader(\n config: DownloaderConfig<any>,\n dl: EmbedDownloader,\n embed: PostEmbed,\n destDir: string,\n callbacks: DownloadTaskCallbacks | null,\n logger: Logger | null | undefined\n ) {\n if (!embed.url) {\n return null;\n }\n const originator = `embed.downloader.${embed.provider}`;\n const __log = (level: LogLevel, ...message: any[]) => {\n logger?.log({\n level,\n originator,\n message\n });\n };\n if (!URLHelper.validateURL(embed.url)) {\n __log('warn', `Could not create task: invalid URL \"${embed.url}\"`);\n return null;\n }\n const dict = {\n 'post.id': embed.postId,\n 'post.url': embed.postURL,\n 'embed.provider': embed.provider,\n 'embed.provider.url': embed.providerURL,\n 'embed.url': embed.url,\n 'embed.subject': embed.subject,\n 'embed.html': embed.html,\n 'cookie': config.cookie || '',\n 'dest.dir': destDir\n };\n\n const args = split(dl.exec);\n const cmd = args.shift();\n if (!cmd) {\n __log('warn', 'Could not create task: no command specified');\n return null;\n }\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n const interpolated = Formatter.format(arg, dict).result.trim();\n if (!interpolated && arg !== '{cookie}') {\n __log('warn', `Could not create task: got empty string for command arg '${arg}'`);\n return null;\n }\n args[i] = interpolated;\n }\n\n return new ExternalDownloaderTask({\n name: originator,\n exec: {\n command: cmd,\n args\n },\n config,\n callbacks,\n logger,\n src: embed.url,\n srcEntity: embed\n });\n }\n}\n"]}
@@ -199,20 +199,20 @@ _FFmpegDownloadTaskBase_fileExistsAction = new WeakMap(), _FFmpegDownloadTaskBas
199
199
  }
200
200
  const _options = options ? [...options] : [];
201
201
  if (proxyURL) {
202
- const protocolWhitelistOptIndex = _options.findIndex((opt) => opt.startsWith('-protocol_whitelist'));
203
- if (protocolWhitelistOptIndex >= 0) {
204
- const whitelistEntries = _options[protocolWhitelistOptIndex].substring('-protocol_whitelist'.length).trim().split(',').map((entry) => entry.trim());
202
+ const whitelistIndex = _options.findIndex((opt) => opt.startsWith('-protocol_whitelist')) + 1;
203
+ if (whitelistIndex > 0 && _options[whitelistIndex]) {
204
+ const whitelistEntries = _options[whitelistIndex].trim().split(',').map((entry) => entry.trim());
205
205
  if (!whitelistEntries.includes('httpproxy')) {
206
- _options[protocolWhitelistOptIndex] += ',httpproxy';
206
+ _options[whitelistIndex] += ',httpproxy';
207
207
  }
208
208
  }
209
209
  else {
210
- _options.push('-protocol_whitelist http,https,tcp,tls,httpproxy');
210
+ _options.push('-protocol_whitelist', 'http,https,tcp,tls,httpproxy');
211
211
  }
212
212
  _options.push('-http_proxy', proxyURL);
213
213
  }
214
214
  if (_options.length > 0) {
215
- _options.forEach((opt) => command.inputOption(opt));
215
+ command.inputOptions(..._options);
216
216
  }
217
217
  });
218
218
  if (!__hasFFmpegOption(outputOptions, '-c')) {
@@ -1 +1 @@
1
- {"version":3,"file":"FFmpegDownloadTaskBase.js","sourceRoot":"","sources":["../../../src/downloaders/task/FFmpegDownloadTaskBase.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport ffmpeg, { type FfmpegCommand } from 'fluent-ffmpeg';\nimport DownloadTask, { type DownloadProgress, type DownloadTaskParams } from './DownloadTask.js';\nimport { type FileExistsAction } from './../DownloaderOptions.js';\nimport { type Downloadable } from '../../entities/Downloadable.js';\nimport FSHelper from '../../utils/FSHelper.js';\nimport { createProxyAgent } from '../../utils/Proxy.js';\n\nexport interface FFmpegDownloadTaskBaseParams<T extends Downloadable> extends DownloadTaskParams<T> {\n fileExistsAction: FileExistsAction;\n}\n\nexport interface FFmpegCommandParams {\n inputs: {\n input: string;\n options?: string[];\n }[];\n output: string;\n outputOptions?: string[];\n noProxy?: boolean;\n}\n\n// https://github.com/fluent-ffmpeg/node-fluent-ffmpeg\nexport interface FFmpegProgress {\n frames: number; // Total processed frame count\n currentFps: number; // Framerate at which FFmpeg is currently processing\n currentKbps: number; // Throughput at which FFmpeg is currently processing\n targetSize: number; // Current size of the target file in kilobytes\n timemark: string; // The timestamp of the current frame e.g '00:02:23.08'\n percent: number;\n}\n\nexport default abstract class FFmpegDownloadTaskBase<T extends Downloadable> extends DownloadTask<T> {\n\n abstract name: string;\n\n #fileExistsAction: FileExistsAction;\n #ffmpegCommand: FfmpegCommand | null;\n #commandLine: string | null;\n\n #abortController: AbortController | null;\n #abortingCallback: (() => void) | null;\n\n constructor(params: FFmpegDownloadTaskBaseParams<T>) {\n super(params);\n this.#fileExistsAction = params.fileExistsAction;\n this.#commandLine = null;\n\n this.#abortController = null;\n this.#abortingCallback = null;\n }\n\n protected abstract getFFmpegCommandParams(): Promise<FFmpegCommandParams>;\n protected abstract getTargetDuration(): number | null;\n\n protected doStart() {\n return new Promise<void>((resolve) => {\n void (async () => {\n if (this.status === 'aborted') {\n resolve();\n return;\n }\n \n let tmpFilePath: string | null = null;\n const __cleanup = () => {\n if (tmpFilePath && (this.dryRun || fs.existsSync(tmpFilePath))) {\n this.log('debug', `Clean up ${tmpFilePath}`);\n this.fsHelper.unlink(tmpFilePath);\n }\n };\n \n try {\n this.#abortController = new AbortController();\n \n const ffmpegCommandParams = await this.getFFmpegCommandParams();\n \n const destFilePath = ffmpegCommandParams.output;\n this.resolvedDestPath = destFilePath;\n \n let lastDownloadedFilePath: string | null = null;\n if (this.#fileExistsAction === 'saveAsCopy' || this.#fileExistsAction === 'saveAsCopyIfNewer') {\n const { filePath, preceding } = this.fsHelper.checkFileExistsAndIncrement(destFilePath);\n this.resolvedDestPath = filePath;\n lastDownloadedFilePath = preceding;\n }\n else if (this.#fileExistsAction === 'skip' && fs.existsSync(destFilePath)) {\n this.notifySkip({\n name: 'destFileExists',\n message: `Destination file exists (${destFilePath})`,\n existingDestFilePath: destFilePath\n });\n resolve();\n return;\n }\n \n const _destFilePath = this.resolvedDestPath;\n const _tmpFilePath = tmpFilePath = FSHelper.createTmpFilePath(_destFilePath, this.srcEntity.id);\n \n let hasError = false;\n \n this.#ffmpegCommand = this.#constructFFmpegCommand(_tmpFilePath, ffmpegCommandParams);\n\n this.#ffmpegCommand.on('start', (commandLine: string) => {\n this.#commandLine = commandLine;\n this.notifyStart();\n });\n \n this.#ffmpegCommand.on('progress', (progress: FFmpegProgress) => {\n this.notifyProgress(this.#convertFFmpegProgress(progress));\n });\n \n this.#ffmpegCommand.on('end', () => {\n void (async () => {\n if (!hasError) {\n let proceedWithCommit = true;\n if (this.#fileExistsAction === 'saveAsCopyIfNewer' && lastDownloadedFilePath && fs.existsSync(lastDownloadedFilePath)) {\n // Compare checksum of downloaded file with that of last downloaded\n const compareMsg = `(saveAsCopyIfNewer) Compare \"${_tmpFilePath}\" with \"${lastDownloadedFilePath}\"`;\n proceedWithCommit = !(await this.fsHelper.compareFiles(_tmpFilePath, lastDownloadedFilePath));\n if (!proceedWithCommit) {\n this.log('debug', `${compareMsg}: Files match`);\n this.notifySkip({\n name: 'destFileExists',\n message: `Destination file exists with same content (${lastDownloadedFilePath})`,\n existingDestFilePath: lastDownloadedFilePath\n });\n }\n else {\n this.log('debug', `${compareMsg}: Files do not match`);\n }\n }\n if (proceedWithCommit) {\n const filesizeStr = !this.dryRun ? `; filesize: ${fs.lstatSync(_tmpFilePath).size} bytes` : '';\n this.log('debug', `Commit \"${_tmpFilePath}\" to \"${_destFilePath}${filesizeStr}`);\n this.fsHelper.rename(_tmpFilePath, _destFilePath);\n this.notifyComplete();\n }\n __cleanup();\n resolve();\n }\n })();\n });\n \n this.#ffmpegCommand.on('error', (error: any) => {\n if (this.#abortingCallback) {\n this.#abortingCallback();\n }\n else {\n hasError = true;\n this.notifyError(error);\n }\n __cleanup();\n resolve();\n });\n \n this.#abortController.signal.onabort = () => {\n if (this.#ffmpegCommand) {\n this.#ffmpegCommand.kill('SIGKILL');\n }\n else if (this.#abortingCallback) {\n this.#abortingCallback();\n __cleanup();\n resolve();\n }\n };\n \n this.#ffmpegCommand.run();\n }\n catch (error: any) {\n this.notifyError(error);\n __cleanup();\n resolve();\n }\n })();\n })\n .finally(() => {\n if (this.#ffmpegCommand) {\n this.#ffmpegCommand.removeAllListeners();\n this.#ffmpegCommand = null;\n }\n this.#abortController = null;\n });\n }\n\n #constructFFmpegCommand(tmpFilePath: string, params: FFmpegCommandParams) {\n const __hasFFmpegOption = (options: string[] | undefined, key: string) => {\n if (!options) {\n return false;\n }\n return options.some((s) => s.trim().startsWith(`${key} `));\n };\n\n const { inputs, outputOptions, noProxy = false } = params;\n\n if (inputs.length === 0) {\n throw Error('Unable to create FFmpeg command: no input specified');\n }\n\n const command = ffmpeg();\n\n let proxyURL = '';\n const proxyAgentInfo = !noProxy ? createProxyAgent(this.config) : null;\n if (proxyAgentInfo) {\n // FFmpeg only supports HTTP proxy\n if (proxyAgentInfo.protocol === 'http') {\n proxyURL = proxyAgentInfo.proxyURL;\n }\n else {\n this.log('warn', `${proxyAgentInfo.protocol.toUpperCase()} proxy ignored - FFmpeg supports HTTP proxy only`)\n }\n }\n\n command.input(inputs[0].input);\n inputs.forEach(({input, options}, index) => {\n if (index > 0) {\n command.input(input);\n }\n const _options = options ? [...options] : [];\n if (proxyURL) {\n const protocolWhitelistOptIndex = _options.findIndex((opt) => opt.startsWith('-protocol_whitelist'));\n if (protocolWhitelistOptIndex >= 0) {\n const whitelistEntries = _options[protocolWhitelistOptIndex].substring('-protocol_whitelist'.length).trim().split(',').map((entry) => entry.trim());\n if (!whitelistEntries.includes('httpproxy')) {\n _options[protocolWhitelistOptIndex] += ',httpproxy';\n }\n }\n else {\n _options.push('-protocol_whitelist http,https,tcp,tls,httpproxy');\n }\n _options.push('-http_proxy', proxyURL);\n }\n if (_options.length > 0) {\n _options.forEach((opt) => command.inputOption(opt));\n }\n });\n\n if (!__hasFFmpegOption(outputOptions, '-c')) {\n command.outputOption('-c copy');\n }\n if (!__hasFFmpegOption(outputOptions, '-f')) {\n command.outputOption('-f mp4');\n }\n outputOptions?.forEach((opt) => command.outputOption(opt));\n\n if (this.dryRun) {\n const output = process.platform === 'win32' ? 'NUL' : '/dev/null';\n this.log('debug', `(dry-run) FFmpeg output to \"${output}\"`);\n command.output(output);\n }\n else {\n command.output(tmpFilePath);\n }\n\n this.log('debug', 'FFmpeg command args:', command._getArguments());\n\n return command;\n }\n\n protected async doAbort() {\n return new Promise<void>((resolve) => {\n if (this.#abortController) {\n this.#abortingCallback = () => {\n this.#abortingCallback = null;\n this.notifyAbort();\n resolve();\n };\n this.#abortController.abort();\n }\n else {\n resolve();\n }\n });\n }\n\n protected async doDestroy() {\n this.#commandLine = null;\n return Promise.resolve();\n }\n\n protected doGetProgress() {\n return undefined;\n }\n\n get commandLine() {\n return this.#commandLine;\n }\n\n #convertFFmpegProgress(progress: FFmpegProgress): DownloadProgress | null {\n if (this.resolvedDestFilename && this.resolvedDestPath) {\n const targetDuration = this.getTargetDuration();\n const downloaded = this.#timemarkToSeconds(progress.timemark);\n return {\n destFilename: this.resolvedDestFilename,\n destFilePath: this.resolvedDestPath,\n lengthUnit: 'second',\n length: targetDuration !== null ? Number(targetDuration.toFixed(2)) : undefined,\n lengthDownloaded: Number(downloaded.toFixed(2)),\n percent: targetDuration !== null ? Number((downloaded / targetDuration * 100).toFixed(2)) : undefined,\n sizeDownloaded: Number(progress.targetSize.toFixed(2)),\n speed: Number(progress.currentKbps.toFixed(2))\n };\n }\n return null;\n }\n\n /**\n * https://github.com/fluent-ffmpeg/node-fluent-ffmpeg/blob/master/lib/utils.js\n *\n * Convert a [[hh:]mm:]ss[.xxx] timemark into seconds\n *\n * @param {String} timemark timemark string\n * @return Number\n */\n #timemarkToSeconds(timemark: string) {\n if (typeof timemark === 'number') {\n return timemark;\n }\n\n if (timemark.indexOf(':') === -1 && timemark.indexOf('.') >= 0) {\n return Number(timemark);\n }\n\n const parts = timemark.split(':');\n\n // Add seconds\n let secs = Number(parts.pop());\n\n if (parts.length) {\n // Add minutes\n secs += Number(parts.pop()) * 60;\n }\n\n if (parts.length) {\n // Add hours\n secs += Number(parts.pop()) * 3600;\n }\n\n return secs;\n }\n}\n"]}
1
+ {"version":3,"file":"FFmpegDownloadTaskBase.js","sourceRoot":"","sources":["../../../src/downloaders/task/FFmpegDownloadTaskBase.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport ffmpeg, { type FfmpegCommand } from 'fluent-ffmpeg';\nimport DownloadTask, { type DownloadProgress, type DownloadTaskParams } from './DownloadTask.js';\nimport { type FileExistsAction } from './../DownloaderOptions.js';\nimport { type Downloadable } from '../../entities/Downloadable.js';\nimport FSHelper from '../../utils/FSHelper.js';\nimport { createProxyAgent } from '../../utils/Proxy.js';\n\nexport interface FFmpegDownloadTaskBaseParams<T extends Downloadable> extends DownloadTaskParams<T> {\n fileExistsAction: FileExistsAction;\n}\n\nexport interface FFmpegCommandParams {\n inputs: {\n input: string;\n options?: string[];\n }[];\n output: string;\n outputOptions?: string[];\n noProxy?: boolean;\n}\n\n// https://github.com/fluent-ffmpeg/node-fluent-ffmpeg\nexport interface FFmpegProgress {\n frames: number; // Total processed frame count\n currentFps: number; // Framerate at which FFmpeg is currently processing\n currentKbps: number; // Throughput at which FFmpeg is currently processing\n targetSize: number; // Current size of the target file in kilobytes\n timemark: string; // The timestamp of the current frame e.g '00:02:23.08'\n percent: number;\n}\n\nexport default abstract class FFmpegDownloadTaskBase<T extends Downloadable> extends DownloadTask<T> {\n\n abstract name: string;\n\n #fileExistsAction: FileExistsAction;\n #ffmpegCommand: FfmpegCommand | null;\n #commandLine: string | null;\n\n #abortController: AbortController | null;\n #abortingCallback: (() => void) | null;\n\n constructor(params: FFmpegDownloadTaskBaseParams<T>) {\n super(params);\n this.#fileExistsAction = params.fileExistsAction;\n this.#commandLine = null;\n\n this.#abortController = null;\n this.#abortingCallback = null;\n }\n\n protected abstract getFFmpegCommandParams(): Promise<FFmpegCommandParams>;\n protected abstract getTargetDuration(): number | null;\n\n protected doStart() {\n return new Promise<void>((resolve) => {\n void (async () => {\n if (this.status === 'aborted') {\n resolve();\n return;\n }\n \n let tmpFilePath: string | null = null;\n const __cleanup = () => {\n if (tmpFilePath && (this.dryRun || fs.existsSync(tmpFilePath))) {\n this.log('debug', `Clean up ${tmpFilePath}`);\n this.fsHelper.unlink(tmpFilePath);\n }\n };\n \n try {\n this.#abortController = new AbortController();\n \n const ffmpegCommandParams = await this.getFFmpegCommandParams();\n \n const destFilePath = ffmpegCommandParams.output;\n this.resolvedDestPath = destFilePath;\n \n let lastDownloadedFilePath: string | null = null;\n if (this.#fileExistsAction === 'saveAsCopy' || this.#fileExistsAction === 'saveAsCopyIfNewer') {\n const { filePath, preceding } = this.fsHelper.checkFileExistsAndIncrement(destFilePath);\n this.resolvedDestPath = filePath;\n lastDownloadedFilePath = preceding;\n }\n else if (this.#fileExistsAction === 'skip' && fs.existsSync(destFilePath)) {\n this.notifySkip({\n name: 'destFileExists',\n message: `Destination file exists (${destFilePath})`,\n existingDestFilePath: destFilePath\n });\n resolve();\n return;\n }\n \n const _destFilePath = this.resolvedDestPath;\n const _tmpFilePath = tmpFilePath = FSHelper.createTmpFilePath(_destFilePath, this.srcEntity.id);\n \n let hasError = false;\n \n this.#ffmpegCommand = this.#constructFFmpegCommand(_tmpFilePath, ffmpegCommandParams);\n\n this.#ffmpegCommand.on('start', (commandLine: string) => {\n this.#commandLine = commandLine;\n this.notifyStart();\n });\n \n this.#ffmpegCommand.on('progress', (progress: FFmpegProgress) => {\n this.notifyProgress(this.#convertFFmpegProgress(progress));\n });\n \n this.#ffmpegCommand.on('end', () => {\n void (async () => {\n if (!hasError) {\n let proceedWithCommit = true;\n if (this.#fileExistsAction === 'saveAsCopyIfNewer' && lastDownloadedFilePath && fs.existsSync(lastDownloadedFilePath)) {\n // Compare checksum of downloaded file with that of last downloaded\n const compareMsg = `(saveAsCopyIfNewer) Compare \"${_tmpFilePath}\" with \"${lastDownloadedFilePath}\"`;\n proceedWithCommit = !(await this.fsHelper.compareFiles(_tmpFilePath, lastDownloadedFilePath));\n if (!proceedWithCommit) {\n this.log('debug', `${compareMsg}: Files match`);\n this.notifySkip({\n name: 'destFileExists',\n message: `Destination file exists with same content (${lastDownloadedFilePath})`,\n existingDestFilePath: lastDownloadedFilePath\n });\n }\n else {\n this.log('debug', `${compareMsg}: Files do not match`);\n }\n }\n if (proceedWithCommit) {\n const filesizeStr = !this.dryRun ? `; filesize: ${fs.lstatSync(_tmpFilePath).size} bytes` : '';\n this.log('debug', `Commit \"${_tmpFilePath}\" to \"${_destFilePath}${filesizeStr}`);\n this.fsHelper.rename(_tmpFilePath, _destFilePath);\n this.notifyComplete();\n }\n __cleanup();\n resolve();\n }\n })();\n });\n \n this.#ffmpegCommand.on('error', (error: any) => {\n if (this.#abortingCallback) {\n this.#abortingCallback();\n }\n else {\n hasError = true;\n this.notifyError(error);\n }\n __cleanup();\n resolve();\n });\n \n this.#abortController.signal.onabort = () => {\n if (this.#ffmpegCommand) {\n this.#ffmpegCommand.kill('SIGKILL');\n }\n else if (this.#abortingCallback) {\n this.#abortingCallback();\n __cleanup();\n resolve();\n }\n };\n \n this.#ffmpegCommand.run();\n }\n catch (error: any) {\n this.notifyError(error);\n __cleanup();\n resolve();\n }\n })();\n })\n .finally(() => {\n if (this.#ffmpegCommand) {\n this.#ffmpegCommand.removeAllListeners();\n this.#ffmpegCommand = null;\n }\n this.#abortController = null;\n });\n }\n\n #constructFFmpegCommand(tmpFilePath: string, params: FFmpegCommandParams) {\n const __hasFFmpegOption = (options: string[] | undefined, key: string) => {\n if (!options) {\n return false;\n }\n return options.some((s) => s.trim().startsWith(`${key} `));\n };\n\n const { inputs, outputOptions, noProxy = false } = params;\n\n if (inputs.length === 0) {\n throw Error('Unable to create FFmpeg command: no input specified');\n }\n\n const command = ffmpeg();\n\n let proxyURL = '';\n const proxyAgentInfo = !noProxy ? createProxyAgent(this.config) : null;\n if (proxyAgentInfo) {\n // FFmpeg only supports HTTP proxy\n if (proxyAgentInfo.protocol === 'http') {\n proxyURL = proxyAgentInfo.proxyURL;\n }\n else {\n this.log('warn', `${proxyAgentInfo.protocol.toUpperCase()} proxy ignored - FFmpeg supports HTTP proxy only`)\n }\n }\n\n command.input(inputs[0].input);\n inputs.forEach(({input, options}, index) => {\n if (index > 0) {\n command.input(input);\n }\n const _options = options ? [...options] : [];\n if (proxyURL) {\n const whitelistIndex = _options.findIndex((opt) => opt.startsWith('-protocol_whitelist')) + 1;\n if (whitelistIndex > 0 && _options[whitelistIndex]) {\n const whitelistEntries = _options[whitelistIndex].trim().split(',').map((entry) => entry.trim());\n if (!whitelistEntries.includes('httpproxy')) {\n _options[whitelistIndex] += ',httpproxy';\n }\n }\n else {\n _options.push('-protocol_whitelist', 'http,https,tcp,tls,httpproxy');\n }\n _options.push('-http_proxy', proxyURL);\n }\n if (_options.length > 0) {\n command.inputOptions(..._options)\n }\n });\n\n if (!__hasFFmpegOption(outputOptions, '-c')) {\n command.outputOption('-c copy');\n }\n if (!__hasFFmpegOption(outputOptions, '-f')) {\n command.outputOption('-f mp4');\n }\n outputOptions?.forEach((opt) => command.outputOption(opt));\n\n if (this.dryRun) {\n const output = process.platform === 'win32' ? 'NUL' : '/dev/null';\n this.log('debug', `(dry-run) FFmpeg output to \"${output}\"`);\n command.output(output);\n }\n else {\n command.output(tmpFilePath);\n }\n\n this.log('debug', 'FFmpeg command args:', command._getArguments());\n\n return command;\n }\n\n protected async doAbort() {\n return new Promise<void>((resolve) => {\n if (this.#abortController) {\n this.#abortingCallback = () => {\n this.#abortingCallback = null;\n this.notifyAbort();\n resolve();\n };\n this.#abortController.abort();\n }\n else {\n resolve();\n }\n });\n }\n\n protected async doDestroy() {\n this.#commandLine = null;\n return Promise.resolve();\n }\n\n protected doGetProgress() {\n return undefined;\n }\n\n get commandLine() {\n return this.#commandLine;\n }\n\n #convertFFmpegProgress(progress: FFmpegProgress): DownloadProgress | null {\n if (this.resolvedDestFilename && this.resolvedDestPath) {\n const targetDuration = this.getTargetDuration();\n const downloaded = this.#timemarkToSeconds(progress.timemark);\n return {\n destFilename: this.resolvedDestFilename,\n destFilePath: this.resolvedDestPath,\n lengthUnit: 'second',\n length: targetDuration !== null ? Number(targetDuration.toFixed(2)) : undefined,\n lengthDownloaded: Number(downloaded.toFixed(2)),\n percent: targetDuration !== null ? Number((downloaded / targetDuration * 100).toFixed(2)) : undefined,\n sizeDownloaded: Number(progress.targetSize.toFixed(2)),\n speed: Number(progress.currentKbps.toFixed(2))\n };\n }\n return null;\n }\n\n /**\n * https://github.com/fluent-ffmpeg/node-fluent-ffmpeg/blob/master/lib/utils.js\n *\n * Convert a [[hh:]mm:]ss[.xxx] timemark into seconds\n *\n * @param {String} timemark timemark string\n * @return Number\n */\n #timemarkToSeconds(timemark: string) {\n if (typeof timemark === 'number') {\n return timemark;\n }\n\n if (timemark.indexOf(':') === -1 && timemark.indexOf('.') >= 0) {\n return Number(timemark);\n }\n\n const parts = timemark.split(':');\n\n // Add seconds\n let secs = Number(parts.pop());\n\n if (parts.length) {\n // Add minutes\n secs += Number(parts.pop()) * 60;\n }\n\n if (parts.length) {\n // Add hours\n secs += Number(parts.pop()) * 3600;\n }\n\n return secs;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"FetcherDownloadTask.d.ts","sourceRoot":"","sources":["../../../src/downloaders/task/FetcherDownloadTask.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAGlD,OAAO,KAAK,gBAAgB,MAAM,iCAAiC,CAAC;AACpE,OAAO,YAAY,EAAE,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAA+B,MAAM,mBAAmB,CAAC;AAE9H,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,MAAM,WAAW,yBAAyB,CAAC,CAAC,SAAS,YAAY,CAAE,SAAQ,kBAAkB;IAC3F,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC1C,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAED,MAAM,CAAC,OAAO,OAAO,mBAAmB,CAAC,CAAC,SAAS,YAAY,CAAE,SAAQ,YAAY;;IAEnF,SAAS,CAAC,IAAI,SAAyB;gBAW3B,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC;cAqChC,eAAe,CAAC,MAAM,CAAC,EAAE,WAAW;IASpD,SAAS,CAAC,OAAO;cAsJD,OAAO;cAeP,SAAS;IAKzB,SAAS,CAAC,aAAa;CA+DxB"}
1
+ {"version":3,"file":"FetcherDownloadTask.d.ts","sourceRoot":"","sources":["../../../src/downloaders/task/FetcherDownloadTask.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAC;AAGlD,OAAO,KAAK,gBAAgB,MAAM,iCAAiC,CAAC;AACpE,OAAO,YAAY,EAAE,EAAE,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAA+B,MAAM,mBAAmB,CAAC;AAE9H,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,WAAW,yBAAyB,CAAC,CAAC,SAAS,YAAY,CAAE,SAAQ,kBAAkB;IAC3F,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC1C,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAED,MAAM,CAAC,OAAO,OAAO,mBAAmB,CAAC,CAAC,SAAS,YAAY,CAAE,SAAQ,YAAY;;IAEnF,SAAS,CAAC,IAAI,SAAyB;gBAW3B,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC;cAkChC,eAAe,CAAC,MAAM,CAAC,EAAE,WAAW;IAUpD,SAAS,CAAC,OAAO;cAuJD,OAAO;cAeP,SAAS;IAKzB,SAAS,CAAC,aAAa;CA+DxB"}
@@ -15,7 +15,6 @@ import fs from 'fs';
15
15
  import { minimatch } from 'minimatch';
16
16
  import DownloadTask from './DownloadTask.js';
17
17
  import M3U8DownloadTask from './M3U8DownloadTask.js';
18
- import { createProxyAgent } from '../../utils/Proxy.js';
19
18
  class FetcherDownloadTask extends DownloadTask {
20
19
  constructor(params) {
21
20
  super(params);
@@ -41,6 +40,7 @@ class FetcherDownloadTask extends DownloadTask {
41
40
  url: this.src,
42
41
  destDir: __classPrivateFieldGet(this, _FetcherDownloadTask_destDir, "f"),
43
42
  destFilenameResolver: __classPrivateFieldGet(this, _FetcherDownloadTask_destFilenameResolver, "f"),
43
+ setReferer: this.srcEntity.type === 'video',
44
44
  signal
45
45
  });
46
46
  }
@@ -70,6 +70,7 @@ class FetcherDownloadTask extends DownloadTask {
70
70
  url: this.src,
71
71
  srcEntity: this.srcEntity,
72
72
  destFilePath,
73
+ setReferer: this.srcEntity.type === 'video',
73
74
  signal: __classPrivateFieldGet(this, _FetcherDownloadTask_abortController, "f").signal
74
75
  });
75
76
  // Skip download?
@@ -208,12 +209,9 @@ class FetcherDownloadTask extends DownloadTask {
208
209
  _FetcherDownloadTask_fetcher = new WeakMap(), _FetcherDownloadTask_destDir = new WeakMap(), _FetcherDownloadTask_destFilenameResolver = new WeakMap(), _FetcherDownloadTask_fileExistsAction = new WeakMap(), _FetcherDownloadTask_abortController = new WeakMap(), _FetcherDownloadTask_progressMonitor = new WeakMap(), _FetcherDownloadTask_abortingCallback = new WeakMap(), _FetcherDownloadTask_instances = new WeakSet(), _FetcherDownloadTask_checkAndSpawnFFmpegDownloadTask = async function _FetcherDownloadTask_checkAndSpawnFFmpegDownloadTask(currentDestFilePath, preferredOutputFilePath) {
209
210
  if (this.srcEntity.type === 'video' && __classPrivateFieldGet(this, _FetcherDownloadTask_instances, "m", _FetcherDownloadTask_isM3U8FilePath).call(this, currentDestFilePath) && this.callbacks) {
210
211
  // Spawn FFmpeg task to download actual stream
211
- const { protocol: proxyProtocol } = createProxyAgent(this.config) || {};
212
212
  const spawn = await DownloadTask.create(M3U8DownloadTask, {
213
213
  config: this.config,
214
- // MUST pass original m3u8 URL if HTTP proxy is to be used, otherwise FFmpeg will complain
215
- // about http_proxy option not available (due to input being a file).
216
- src: proxyProtocol === 'http' ? this.src : currentDestFilePath,
214
+ src: this.src,
217
215
  srcEntity: this.srcEntity,
218
216
  callbacks: this.callbacks,
219
217
  logger: this.logger,
@@ -1 +1 @@
1
- {"version":3,"file":"FetcherDownloadTask.js","sourceRoot":"","sources":["../../../src/downloaders/task/FetcherDownloadTask.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\nimport fs from 'fs';\nimport { minimatch } from 'minimatch';\nimport type Fetcher from '../../utils/Fetcher.js';\nimport {type FetcherProgress} from '../../utils/FetcherProgressMonitor.js';\nimport type FetcherProgressMonitor from '../../utils/FetcherProgressMonitor.js';\nimport type FilenameResolver from '../../utils/FllenameResolver.js';\nimport DownloadTask, { type DownloadTaskParams, type DownloadProgress, type DownloadTaskSkipReason } from './DownloadTask.js';\nimport M3U8DownloadTask from './M3U8DownloadTask.js';\nimport { type Downloadable } from '../../entities/Downloadable.js';\nimport { type FileExistsAction } from '../DownloaderOptions.js';\nimport { createProxyAgent } from '../../utils/Proxy.js';\n\nexport interface FetcherDownloadTaskParams<T extends Downloadable> extends DownloadTaskParams {\n fetcher: Fetcher;\n destDir: string;\n destFilenameResolver: FilenameResolver<T>;\n fileExistsAction: FileExistsAction;\n}\n\nexport default class FetcherDownloadTask<T extends Downloadable> extends DownloadTask {\n\n protected name = 'FetcherDownloadTask';\n\n #fetcher: Fetcher;\n\n #destDir: string;\n #destFilenameResolver: FilenameResolver<T>;\n #fileExistsAction: FileExistsAction;\n #abortController: AbortController | null;\n #progressMonitor: FetcherProgressMonitor | null;\n #abortingCallback: (() => void) | null;\n\n constructor(params: FetcherDownloadTaskParams<T>) {\n super(params);\n this.#fetcher = params.fetcher;\n this.#destDir = params.destDir;\n this.#destFilenameResolver = params.destFilenameResolver;\n this.#fileExistsAction = params.fileExistsAction;\n this.#abortController = null;\n this.#progressMonitor = null;\n this.#abortingCallback = null;\n }\n\n async #checkAndSpawnFFmpegDownloadTask(\n currentDestFilePath: string,\n preferredOutputFilePath: string) {\n\n if (this.srcEntity.type === 'video' && this.#isM3U8FilePath(currentDestFilePath) && this.callbacks) {\n // Spawn FFmpeg task to download actual stream\n const { protocol: proxyProtocol } = createProxyAgent(this.config) || {};\n const spawn = await DownloadTask.create(M3U8DownloadTask, {\n config: this.config,\n // MUST pass original m3u8 URL if HTTP proxy is to be used, otherwise FFmpeg will complain\n // about http_proxy option not available (due to input being a file).\n src: proxyProtocol === 'http' ? this.src : currentDestFilePath,\n srcEntity: this.srcEntity,\n callbacks: this.callbacks,\n logger: this.logger,\n destFilePath: this.fsHelper.changeFilePathExtension(preferredOutputFilePath, '.mp4'),\n fileExistsAction: this.#fileExistsAction\n });\n this.callbacks.onSpawn(this, spawn);\n }\n }\n\n #isM3U8FilePath(filePath: string) {\n return path.extname(filePath) === '.m3u8';\n }\n\n protected async resolveDestPath(signal?: AbortSignal) {\n return await this.#fetcher.resolveDestFilePath({\n url: this.src,\n destDir: this.#destDir,\n destFilenameResolver: this.#destFilenameResolver,\n signal\n });\n }\n\n protected doStart() {\n return new Promise<void>((resolve) => {\n void (async () => {\n if (!this.resolvedDestPath) {\n this.notifyError(Error('Destination file path not resolved'));\n resolve();\n return;\n }\n if (this.status === 'aborted') {\n resolve();\n return;\n }\n \n this.#abortController = new AbortController();\n \n /**\n * Change status to downloading ahead of notifyStart(), so that task can be\n * aborted even though we have not yet obtained progress monitor from `Fetcher.download()`.\n */\n this.status = 'downloading';\n let skipped = false;\n const fileExistsAction = this.#fileExistsAction;\n try {\n const destFilePath = this.resolvedDestPath;\n const { monitor, start, abort } = await this.#fetcher.prepareDownload({\n url: this.src,\n srcEntity: this.srcEntity,\n destFilePath,\n signal: this.#abortController.signal\n });\n \n // Skip download?\n let skipDownload: { skip: false; } | { skip: true; reason: DownloadTaskSkipReason } = { skip: false };\n let lastDownloadedFilePath: string | null = null;\n const includeByFilename = this.#checkIncludeMediaByFilenameOption();\n if (!includeByFilename.ok) {\n skipDownload = {\n skip: true,\n reason: includeByFilename.reason\n };\n }\n else if (fileExistsAction === 'saveAsCopy' || fileExistsAction === 'saveAsCopyIfNewer') {\n const inc = this.fsHelper.checkFileExistsAndIncrement(destFilePath);\n this.resolvedDestPath = inc.filePath;\n lastDownloadedFilePath = inc.preceding;\n }\n else if (fileExistsAction === 'skip' && fs.existsSync(destFilePath)) {\n const isM3U8 = this.srcEntity.type === 'video' && this.#isM3U8FilePath(destFilePath);\n const mp4FilePath = this.fsHelper.changeFilePathExtension(destFilePath, '.mp4');\n if (isM3U8 && !fs.existsSync(mp4FilePath)) {\n this.log('debug', `Ignoring 'fileExistsAction: skip' for URL \"${this.src}\": target download is M3U8 playlist and its ` +\n `associated media file \"${mp4FilePath}\" does not exist`);\n }\n else {\n skipDownload = {\n skip: true,\n reason: {\n name: 'destFileExists',\n message: `Destination file exists (${destFilePath})`,\n existingDestFilePath: destFilePath\n }\n };\n }\n }\n \n const __handleSkip = (skipAction: () => void) => {\n if (skipDownload.skip) {\n skipped = true;\n skipAction();\n const reason = skipDownload.reason;\n this.notifySkip(reason);\n resolve();\n return true;\n }\n return false;\n };\n \n if (__handleSkip(abort)) {\n return;\n }\n \n monitor.on('progress', (progress) => {\n this.notifyProgress(this.#convertFetcherProgress(progress));\n });\n \n this.#progressMonitor = monitor;\n \n this.notifyStart();\n \n const { tmpFilePath, commit, discard } = await start({ destFilePath: this.resolvedDestPath });\n \n let proceedWithCommit = true;\n if (fileExistsAction === 'saveAsCopyIfNewer' && lastDownloadedFilePath && fs.existsSync(lastDownloadedFilePath)) {\n // Compare checksum of downloaded file with that of last download\n const compareMsg = `(saveAsCopyIfNewer) Compare \"${tmpFilePath}\" with \"${lastDownloadedFilePath}\"`;\n proceedWithCommit = !(await this.fsHelper.compareFiles(tmpFilePath, lastDownloadedFilePath));\n if (!proceedWithCommit) {\n this.log('debug', `${compareMsg}: Files match`);\n skipDownload = {\n skip: true,\n reason: {\n name: 'destFileExists',\n message: `Destination file exists with same content (${lastDownloadedFilePath})`,\n existingDestFilePath: lastDownloadedFilePath\n }\n };\n this.resolvedDestPath = lastDownloadedFilePath;\n __handleSkip(discard);\n }\n else {\n this.log('debug', `${compareMsg}: Files do not match`);\n }\n }\n \n if (proceedWithCommit) {\n commit();\n }\n \n await this.#checkAndSpawnFFmpegDownloadTask(this.resolvedDestPath, destFilePath);\n \n if (proceedWithCommit) {\n this.notifyComplete();\n resolve();\n }\n }\n catch (error: any) {\n if (this.#abortController.signal.aborted) {\n if (!skipped) {\n this.notifyAbort();\n if (this.#abortingCallback) {\n this.#abortingCallback();\n }\n }\n }\n else {\n this.notifyError(error);\n }\n resolve();\n }\n })();\n })\n .finally(() => {\n if (this.#progressMonitor) {\n this.#progressMonitor.removeAllListeners();\n this.#progressMonitor = null;\n }\n this.#abortController = null;\n });\n }\n\n protected async doAbort() {\n return new Promise<void>((resolve) => {\n if (this.#abortController) {\n this.#abortingCallback = () => {\n this.#abortingCallback = null;\n resolve();\n };\n this.#abortController.abort();\n }\n else {\n resolve();\n }\n });\n }\n\n protected async doDestroy() {\n this.#destDir = '';\n return Promise.resolve();\n }\n\n protected doGetProgress() {\n if (this.#progressMonitor) {\n return this.#convertFetcherProgress(this.#progressMonitor.getProgress());\n }\n return undefined;\n }\n\n #convertFetcherProgress(progress: FetcherProgress): DownloadProgress {\n return {\n destFilename: progress.destFilename,\n destFilePath: progress.destFilePath,\n lengthUnit: 'byte',\n length: progress.length,\n lengthDownloaded: progress.transferred,\n percent: progress.percentage,\n sizeDownloaded: Number((progress.transferred / 1000).toFixed(2)),\n speed: Number((progress.speed / 1000).toFixed(2))\n };\n }\n\n #checkIncludeMediaByFilenameOption(): { ok: true; } | { ok: false; reason: DownloadTaskSkipReason; } {\n const itemType = this.srcEntity.type;\n let prop: keyof typeof this.config.include.mediaByFilename | null;\n switch (itemType) {\n case 'image':\n prop = 'images';\n break;\n case 'audio':\n prop = 'audio';\n break;\n case 'attachment':\n prop = 'attachments';\n break;\n default:\n prop = null;\n }\n const pattern = prop ? this.config.include.mediaByFilename[prop] : null;\n const dest = this.resolvedDestFilename?.toLowerCase();\n if (prop && pattern) {\n const confName = `include.mediaByFilename.${prop}`;\n if (!dest) {\n this.log('warn', `Skipped config '${confName}': destination filename unavailable`);\n return { ok: true };\n }\n const patternMatched = minimatch(dest, pattern);\n const matchString = patternMatched ? 'OK' : 'failed';\n this.log('debug', `Config '${confName}': test \"${pattern}\" <-> \"${dest}\" ${matchString}`);\n if (patternMatched) {\n return { ok: true };\n }\n return {\n ok: false,\n reason: {\n name: 'includeMediaByFilenameUnfulfilled',\n itemType,\n pattern,\n destFilename: dest,\n message: `Media filename does not match pattern provided in config->${confName}`\n } as DownloadTaskSkipReason\n };\n }\n return { ok: true };\n }\n}\n"]}
1
+ {"version":3,"file":"FetcherDownloadTask.js","sourceRoot":"","sources":["../../../src/downloaders/task/FetcherDownloadTask.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\nimport fs from 'fs';\nimport { minimatch } from 'minimatch';\nimport type Fetcher from '../../utils/Fetcher.js';\nimport {type FetcherProgress} from '../../utils/FetcherProgressMonitor.js';\nimport type FetcherProgressMonitor from '../../utils/FetcherProgressMonitor.js';\nimport type FilenameResolver from '../../utils/FllenameResolver.js';\nimport DownloadTask, { type DownloadTaskParams, type DownloadProgress, type DownloadTaskSkipReason } from './DownloadTask.js';\nimport M3U8DownloadTask from './M3U8DownloadTask.js';\nimport { type Downloadable } from '../../entities/Downloadable.js';\nimport { type FileExistsAction } from '../DownloaderOptions.js';\n\nexport interface FetcherDownloadTaskParams<T extends Downloadable> extends DownloadTaskParams {\n fetcher: Fetcher;\n destDir: string;\n destFilenameResolver: FilenameResolver<T>;\n fileExistsAction: FileExistsAction;\n}\n\nexport default class FetcherDownloadTask<T extends Downloadable> extends DownloadTask {\n\n protected name = 'FetcherDownloadTask';\n\n #fetcher: Fetcher;\n\n #destDir: string;\n #destFilenameResolver: FilenameResolver<T>;\n #fileExistsAction: FileExistsAction;\n #abortController: AbortController | null;\n #progressMonitor: FetcherProgressMonitor | null;\n #abortingCallback: (() => void) | null;\n\n constructor(params: FetcherDownloadTaskParams<T>) {\n super(params);\n this.#fetcher = params.fetcher;\n this.#destDir = params.destDir;\n this.#destFilenameResolver = params.destFilenameResolver;\n this.#fileExistsAction = params.fileExistsAction;\n this.#abortController = null;\n this.#progressMonitor = null;\n this.#abortingCallback = null;\n }\n\n async #checkAndSpawnFFmpegDownloadTask(\n currentDestFilePath: string,\n preferredOutputFilePath: string) {\n\n if (this.srcEntity.type === 'video' && this.#isM3U8FilePath(currentDestFilePath) && this.callbacks) {\n // Spawn FFmpeg task to download actual stream\n const spawn = await DownloadTask.create(M3U8DownloadTask, {\n config: this.config,\n src: this.src,\n srcEntity: this.srcEntity,\n callbacks: this.callbacks,\n logger: this.logger,\n destFilePath: this.fsHelper.changeFilePathExtension(preferredOutputFilePath, '.mp4'),\n fileExistsAction: this.#fileExistsAction\n });\n this.callbacks.onSpawn(this, spawn);\n }\n }\n\n #isM3U8FilePath(filePath: string) {\n return path.extname(filePath) === '.m3u8';\n }\n\n protected async resolveDestPath(signal?: AbortSignal) {\n return await this.#fetcher.resolveDestFilePath({\n url: this.src,\n destDir: this.#destDir,\n destFilenameResolver: this.#destFilenameResolver,\n setReferer: this.srcEntity.type === 'video',\n signal\n });\n }\n\n protected doStart() {\n return new Promise<void>((resolve) => {\n void (async () => {\n if (!this.resolvedDestPath) {\n this.notifyError(Error('Destination file path not resolved'));\n resolve();\n return;\n }\n if (this.status === 'aborted') {\n resolve();\n return;\n }\n \n this.#abortController = new AbortController();\n \n /**\n * Change status to downloading ahead of notifyStart(), so that task can be\n * aborted even though we have not yet obtained progress monitor from `Fetcher.download()`.\n */\n this.status = 'downloading';\n let skipped = false;\n const fileExistsAction = this.#fileExistsAction;\n try {\n const destFilePath = this.resolvedDestPath;\n const { monitor, start, abort } = await this.#fetcher.prepareDownload({\n url: this.src,\n srcEntity: this.srcEntity,\n destFilePath,\n setReferer: this.srcEntity.type === 'video',\n signal: this.#abortController.signal\n });\n \n // Skip download?\n let skipDownload: { skip: false; } | { skip: true; reason: DownloadTaskSkipReason } = { skip: false };\n let lastDownloadedFilePath: string | null = null;\n const includeByFilename = this.#checkIncludeMediaByFilenameOption();\n if (!includeByFilename.ok) {\n skipDownload = {\n skip: true,\n reason: includeByFilename.reason\n };\n }\n else if (fileExistsAction === 'saveAsCopy' || fileExistsAction === 'saveAsCopyIfNewer') {\n const inc = this.fsHelper.checkFileExistsAndIncrement(destFilePath);\n this.resolvedDestPath = inc.filePath;\n lastDownloadedFilePath = inc.preceding;\n }\n else if (fileExistsAction === 'skip' && fs.existsSync(destFilePath)) {\n const isM3U8 = this.srcEntity.type === 'video' && this.#isM3U8FilePath(destFilePath);\n const mp4FilePath = this.fsHelper.changeFilePathExtension(destFilePath, '.mp4');\n if (isM3U8 && !fs.existsSync(mp4FilePath)) {\n this.log('debug', `Ignoring 'fileExistsAction: skip' for URL \"${this.src}\": target download is M3U8 playlist and its ` +\n `associated media file \"${mp4FilePath}\" does not exist`);\n }\n else {\n skipDownload = {\n skip: true,\n reason: {\n name: 'destFileExists',\n message: `Destination file exists (${destFilePath})`,\n existingDestFilePath: destFilePath\n }\n };\n }\n }\n \n const __handleSkip = (skipAction: () => void) => {\n if (skipDownload.skip) {\n skipped = true;\n skipAction();\n const reason = skipDownload.reason;\n this.notifySkip(reason);\n resolve();\n return true;\n }\n return false;\n };\n \n if (__handleSkip(abort)) {\n return;\n }\n \n monitor.on('progress', (progress) => {\n this.notifyProgress(this.#convertFetcherProgress(progress));\n });\n \n this.#progressMonitor = monitor;\n \n this.notifyStart();\n \n const { tmpFilePath, commit, discard } = await start({ destFilePath: this.resolvedDestPath });\n \n let proceedWithCommit = true;\n if (fileExistsAction === 'saveAsCopyIfNewer' && lastDownloadedFilePath && fs.existsSync(lastDownloadedFilePath)) {\n // Compare checksum of downloaded file with that of last download\n const compareMsg = `(saveAsCopyIfNewer) Compare \"${tmpFilePath}\" with \"${lastDownloadedFilePath}\"`;\n proceedWithCommit = !(await this.fsHelper.compareFiles(tmpFilePath, lastDownloadedFilePath));\n if (!proceedWithCommit) {\n this.log('debug', `${compareMsg}: Files match`);\n skipDownload = {\n skip: true,\n reason: {\n name: 'destFileExists',\n message: `Destination file exists with same content (${lastDownloadedFilePath})`,\n existingDestFilePath: lastDownloadedFilePath\n }\n };\n this.resolvedDestPath = lastDownloadedFilePath;\n __handleSkip(discard);\n }\n else {\n this.log('debug', `${compareMsg}: Files do not match`);\n }\n }\n \n if (proceedWithCommit) {\n commit();\n }\n \n await this.#checkAndSpawnFFmpegDownloadTask(this.resolvedDestPath, destFilePath);\n \n if (proceedWithCommit) {\n this.notifyComplete();\n resolve();\n }\n }\n catch (error: any) {\n if (this.#abortController.signal.aborted) {\n if (!skipped) {\n this.notifyAbort();\n if (this.#abortingCallback) {\n this.#abortingCallback();\n }\n }\n }\n else {\n this.notifyError(error);\n }\n resolve();\n }\n })();\n })\n .finally(() => {\n if (this.#progressMonitor) {\n this.#progressMonitor.removeAllListeners();\n this.#progressMonitor = null;\n }\n this.#abortController = null;\n });\n }\n\n protected async doAbort() {\n return new Promise<void>((resolve) => {\n if (this.#abortController) {\n this.#abortingCallback = () => {\n this.#abortingCallback = null;\n resolve();\n };\n this.#abortController.abort();\n }\n else {\n resolve();\n }\n });\n }\n\n protected async doDestroy() {\n this.#destDir = '';\n return Promise.resolve();\n }\n\n protected doGetProgress() {\n if (this.#progressMonitor) {\n return this.#convertFetcherProgress(this.#progressMonitor.getProgress());\n }\n return undefined;\n }\n\n #convertFetcherProgress(progress: FetcherProgress): DownloadProgress {\n return {\n destFilename: progress.destFilename,\n destFilePath: progress.destFilePath,\n lengthUnit: 'byte',\n length: progress.length,\n lengthDownloaded: progress.transferred,\n percent: progress.percentage,\n sizeDownloaded: Number((progress.transferred / 1000).toFixed(2)),\n speed: Number((progress.speed / 1000).toFixed(2))\n };\n }\n\n #checkIncludeMediaByFilenameOption(): { ok: true; } | { ok: false; reason: DownloadTaskSkipReason; } {\n const itemType = this.srcEntity.type;\n let prop: keyof typeof this.config.include.mediaByFilename | null;\n switch (itemType) {\n case 'image':\n prop = 'images';\n break;\n case 'audio':\n prop = 'audio';\n break;\n case 'attachment':\n prop = 'attachments';\n break;\n default:\n prop = null;\n }\n const pattern = prop ? this.config.include.mediaByFilename[prop] : null;\n const dest = this.resolvedDestFilename?.toLowerCase();\n if (prop && pattern) {\n const confName = `include.mediaByFilename.${prop}`;\n if (!dest) {\n this.log('warn', `Skipped config '${confName}': destination filename unavailable`);\n return { ok: true };\n }\n const patternMatched = minimatch(dest, pattern);\n const matchString = patternMatched ? 'OK' : 'failed';\n this.log('debug', `Config '${confName}': test \"${pattern}\" <-> \"${dest}\" ${matchString}`);\n if (patternMatched) {\n return { ok: true };\n }\n return {\n ok: false,\n reason: {\n name: 'includeMediaByFilenameUnfulfilled',\n itemType,\n pattern,\n destFilename: dest,\n message: `Media filename does not match pattern provided in config->${confName}`\n } as DownloadTaskSkipReason\n };\n }\n return { ok: true };\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"M3U8DownloadTask.d.ts","sourceRoot":"","sources":["../../../src/downloaders/task/M3U8DownloadTask.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,sBAAsB,EAAE,EAAE,KAAK,mBAAmB,EAAE,KAAK,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAElI,MAAM,WAAW,sBAAuB,SAAQ,4BAA4B,CAAC,cAAc,CAAC;IAC1F,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,sBAAsB,CAAC,cAAc,CAAC;;IAElF,IAAI,SAAsB;gBAId,MAAM,EAAE,sBAAsB;IAK1C,SAAS,CAAC,eAAe;cAIT,sBAAsB,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAYtE,SAAS,CAAC,iBAAiB,IAAI,MAAM,GAAG,IAAI;CAG7C"}
1
+ {"version":3,"file":"M3U8DownloadTask.d.ts","sourceRoot":"","sources":["../../../src/downloaders/task/M3U8DownloadTask.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE,OAAO,sBAAsB,EAAE,EAAE,KAAK,mBAAmB,EAAE,KAAK,4BAA4B,EAAE,MAAM,6BAA6B,CAAC;AAElI,MAAM,WAAW,sBAAuB,SAAQ,4BAA4B,CAAC,cAAc,CAAC;IAC1F,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,sBAAsB,CAAC,cAAc,CAAC;;IAElF,IAAI,SAAsB;gBAId,MAAM,EAAE,sBAAsB;IAK1C,SAAS,CAAC,eAAe;cAIT,sBAAsB,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAiBtE,SAAS,CAAC,iBAAiB,IAAI,MAAM,GAAG,IAAI;CAG7C"}
@@ -10,6 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
12
  var _M3U8DownloadTask_destFilePath;
13
+ import { SITE_URL } from '../../utils/URLHelper.js';
13
14
  import FFmpegDownloadTaskBase from './FFmpegDownloadTaskBase.js';
14
15
  class M3U8DownloadTask extends FFmpegDownloadTaskBase {
15
16
  constructor(params) {
@@ -26,7 +27,12 @@ class M3U8DownloadTask extends FFmpegDownloadTaskBase {
26
27
  inputs: [
27
28
  {
28
29
  input: this.src,
29
- options: ['-protocol_whitelist file,http,https,tcp,tls']
30
+ options: [
31
+ '-protocol_whitelist',
32
+ 'http,https,tcp,tls',
33
+ '-headers',
34
+ `Referer: ${SITE_URL}`
35
+ ]
30
36
  }
31
37
  ],
32
38
  output: __classPrivateFieldGet(this, _M3U8DownloadTask_destFilePath, "f")
@@ -1 +1 @@
1
- {"version":3,"file":"M3U8DownloadTask.js","sourceRoot":"","sources":["../../../src/downloaders/task/M3U8DownloadTask.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,OAAO,sBAAuF,MAAM,6BAA6B,CAAC;AAMlI,MAAqB,gBAAiB,SAAQ,sBAAsC;IAMlF,YAAY,MAA8B;QACxC,KAAK,CAAC,MAAM,CAAC,CAAC;QALhB,SAAI,GAAG,kBAAkB,CAAC;QAE1B,iDAAsB;QAIpB,uBAAA,IAAI,kCAAiB,MAAM,CAAC,YAAY,MAAA,CAAC;IAC3C,CAAC;IAES,eAAe;QACvB,OAAO,OAAO,CAAC,OAAO,CAAC,uBAAA,IAAI,sCAAc,CAAC,CAAC;IAC7C,CAAC;IAES,KAAK,CAAC,sBAAsB;QACpC,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,MAAM,EAAE;gBACN;oBACE,KAAK,EAAE,IAAI,CAAC,GAAG;oBACf,OAAO,EAAE,CAAE,6CAA6C,CAAE;iBAC3D;aACF;YACD,MAAM,EAAE,uBAAA,IAAI,sCAAc;SAC3B,CAAC,CAAC;IACL,CAAC;IAES,iBAAiB;QACzB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;IACjC,CAAC;CACF;;eA9BoB,gBAAgB","sourcesContent":["import { type VideoMediaItem } from '../../entities/MediaItem.js';\nimport FFmpegDownloadTaskBase, { type FFmpegCommandParams, type FFmpegDownloadTaskBaseParams } from './FFmpegDownloadTaskBase.js';\n\nexport interface M3U8DownloadTaskParams extends FFmpegDownloadTaskBaseParams<VideoMediaItem> {\n destFilePath: string;\n}\n\nexport default class M3U8DownloadTask extends FFmpegDownloadTaskBase<VideoMediaItem> {\n\n name = 'M3U8DownloadTask';\n\n #destFilePath: string;\n\n constructor(params: M3U8DownloadTaskParams) {\n super(params);\n this.#destFilePath = params.destFilePath;\n }\n\n protected resolveDestPath() {\n return Promise.resolve(this.#destFilePath);\n }\n\n protected async getFFmpegCommandParams(): Promise<FFmpegCommandParams> {\n return Promise.resolve({\n inputs: [\n {\n input: this.src,\n options: [ '-protocol_whitelist file,http,https,tcp,tls' ]\n }\n ],\n output: this.#destFilePath\n });\n }\n\n protected getTargetDuration(): number | null {\n return this.srcEntity.duration;\n }\n}\n"]}
1
+ {"version":3,"file":"M3U8DownloadTask.js","sourceRoot":"","sources":["../../../src/downloaders/task/M3U8DownloadTask.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,sBAAuF,MAAM,6BAA6B,CAAC;AAMlI,MAAqB,gBAAiB,SAAQ,sBAAsC;IAMlF,YAAY,MAA8B;QACxC,KAAK,CAAC,MAAM,CAAC,CAAC;QALhB,SAAI,GAAG,kBAAkB,CAAC;QAE1B,iDAAsB;QAIpB,uBAAA,IAAI,kCAAiB,MAAM,CAAC,YAAY,MAAA,CAAC;IAC3C,CAAC;IAES,eAAe;QACvB,OAAO,OAAO,CAAC,OAAO,CAAC,uBAAA,IAAI,sCAAc,CAAC,CAAC;IAC7C,CAAC;IAES,KAAK,CAAC,sBAAsB;QACpC,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,MAAM,EAAE;gBACN;oBACE,KAAK,EAAE,IAAI,CAAC,GAAG;oBACf,OAAO,EAAE;wBACP,qBAAqB;wBACrB,oBAAoB;wBACpB,UAAU;wBACV,YAAY,QAAQ,EAAE;qBACvB;iBACF;aACF;YACD,MAAM,EAAE,uBAAA,IAAI,sCAAc;SAC3B,CAAC,CAAC;IACL,CAAC;IAES,iBAAiB;QACzB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;IACjC,CAAC;CACF;;eAnCoB,gBAAgB","sourcesContent":["import { type VideoMediaItem } from '../../entities/MediaItem.js';\nimport { SITE_URL } from '../../utils/URLHelper.js';\nimport FFmpegDownloadTaskBase, { type FFmpegCommandParams, type FFmpegDownloadTaskBaseParams } from './FFmpegDownloadTaskBase.js';\n\nexport interface M3U8DownloadTaskParams extends FFmpegDownloadTaskBaseParams<VideoMediaItem> {\n destFilePath: string;\n}\n\nexport default class M3U8DownloadTask extends FFmpegDownloadTaskBase<VideoMediaItem> {\n\n name = 'M3U8DownloadTask';\n\n #destFilePath: string;\n\n constructor(params: M3U8DownloadTaskParams) {\n super(params);\n this.#destFilePath = params.destFilePath;\n }\n\n protected resolveDestPath() {\n return Promise.resolve(this.#destFilePath);\n }\n\n protected async getFFmpegCommandParams(): Promise<FFmpegCommandParams> {\n return Promise.resolve({\n inputs: [\n {\n input: this.src,\n options: [\n '-protocol_whitelist',\n 'http,https,tcp,tls',\n '-headers',\n `Referer: ${SITE_URL}`\n ]\n }\n ],\n output: this.#destFilePath\n });\n }\n\n protected getTargetDuration(): number | null {\n return this.srcEntity.duration;\n }\n}\n"]}
@@ -8,6 +8,7 @@ export interface PrepareDownloadParams<T extends Downloadable> {
8
8
  url: string;
9
9
  srcEntity: T;
10
10
  destFilePath: string;
11
+ setReferer?: boolean;
11
12
  signal: AbortSignal;
12
13
  }
13
14
  export interface StartDownloadOverrides {
@@ -36,6 +37,7 @@ export default class Fetcher {
36
37
  url: string;
37
38
  destDir: string;
38
39
  destFilenameResolver: FilenameResolver<T>;
40
+ setReferer?: boolean;
39
41
  signal?: AbortSignal;
40
42
  }): Promise<string>;
41
43
  prepareDownload<T extends Downloadable>(params: PrepareDownloadParams<T>): Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"Fetcher.d.ts","sourceRoot":"","sources":["../../src/utils/Fetcher.ts"],"names":[],"mappings":"AAKA,OAAO,sBAAsB,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAC,KAAK,QAAQ,EAAC,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAG9C,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAIrE,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,YAAY;IAC3D,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,CAAC,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,YAAa,SAAQ,KAAK;IAErC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;gBAEH,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAMzD;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC;AAC7C,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,cAAc,IACrD,CAAC,SAAS,MAAM,GAAG,MAAM,GACzB,CAAC,SAAS,MAAM,GAAG,GAAG,GACtB,KAAK,CAAC;AAIR,MAAM,CAAC,OAAO,OAAO,OAAO;;IAE1B,IAAI,SAAa;gBAQL,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ3D,GAAG,CAAC,CAAC,SAAS,cAAc,EAAE,IAAI,EAAE;QACxC,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,CAAC,CAAC;QACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC9B,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,WAAW,CAAA;KACrB,EAAE,EAAE,SAAI,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAoDpC,mBAAmB,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,EAAE;QACxD,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC;QAChB,oBAAoB,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB;IA4BK,eAAe,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC;;4BA8B7C,sBAAsB;;;;;;;IAoIvD,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;CAGlD"}
1
+ {"version":3,"file":"Fetcher.d.ts","sourceRoot":"","sources":["../../src/utils/Fetcher.ts"],"names":[],"mappings":"AAKA,OAAO,sBAAsB,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAC,KAAK,QAAQ,EAAC,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAG9C,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAKrE,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,YAAY;IAC3D,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,CAAC,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,YAAa,SAAQ,KAAK;IAErC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;gBAEH,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAMzD;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC;AAC7C,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,cAAc,IACrD,CAAC,SAAS,MAAM,GAAG,MAAM,GACzB,CAAC,SAAS,MAAM,GAAG,GAAG,GACtB,KAAK,CAAC;AAIR,MAAM,CAAC,OAAO,OAAO,OAAO;;IAE1B,IAAI,SAAa;gBAQL,MAAM,EAAE,gBAAgB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAQ3D,GAAG,CAAC,CAAC,SAAS,cAAc,EAAE,IAAI,EAAE;QACxC,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,CAAC,CAAC;QACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC9B,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE,WAAW,CAAA;KACrB,EAAE,EAAE,SAAI,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;IAoDpC,mBAAmB,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,EAAE;QACxD,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE,MAAM,CAAC;QAChB,oBAAoB,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;QAC1C,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB;IA4BK,eAAe,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC;;4BA8B7C,sBAAsB;;;;;;;IAwIvD,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC;CAGlD"}
@@ -20,6 +20,7 @@ import { commonLog } from './logging/Logger.js';
20
20
  import FSHelper from './FSHelper.js';
21
21
  import Progress from './Progress.js';
22
22
  import { createProxyAgent } from './Proxy.js';
23
+ import { SITE_URL } from './URLHelper.js';
23
24
  export class FetcherError extends Error {
24
25
  constructor(message, url, method) {
25
26
  super(message);
@@ -96,9 +97,9 @@ class Fetcher {
96
97
  }
97
98
  }
98
99
  async resolveDestFilePath(params) {
99
- const { url, destDir, destFilenameResolver, signal } = params;
100
+ const { url, destDir, destFilenameResolver, setReferer = false, signal } = params;
100
101
  const request = new Request(url, { method: 'HEAD' });
101
- __classPrivateFieldGet(this, _Fetcher_instances, "m", _Fetcher_setHeaders).call(this, request, 'html', { setCookie: false, setHost: false });
102
+ __classPrivateFieldGet(this, _Fetcher_instances, "m", _Fetcher_setHeaders).call(this, request, 'html', { setCookie: false, setHost: false, setReferer });
102
103
  const internalAbortController = new AbortController();
103
104
  const abortHandler = () => internalAbortController.abort();
104
105
  if (signal) {
@@ -120,9 +121,9 @@ class Fetcher {
120
121
  return undefined;
121
122
  }
122
123
  async prepareDownload(params) {
123
- const { url, srcEntity, destFilePath, signal } = params;
124
+ const { url, srcEntity, destFilePath, setReferer = false, signal } = params;
124
125
  const request = new Request(url, { method: 'GET' });
125
- __classPrivateFieldGet(this, _Fetcher_instances, "m", _Fetcher_setHeaders).call(this, request, 'html', { setCookie: false, setHost: false });
126
+ __classPrivateFieldGet(this, _Fetcher_instances, "m", _Fetcher_setHeaders).call(this, request, 'html', { setCookie: false, setHost: false, setReferer });
126
127
  const internalAbortController = new AbortController();
127
128
  let removeAbortHandler = undefined;
128
129
  if (signal) {
@@ -232,12 +233,16 @@ _Fetcher_cookie = new WeakMap(), _Fetcher_logger = new WeakMap(), _Fetcher_dryRu
232
233
  }, _Fetcher_setHeaders = function _Fetcher_setHeaders(request, type, opts) {
233
234
  const setCookie = pickDefined(opts?.setCookie, true);
234
235
  const setHost = pickDefined(opts?.setHost, true);
236
+ const setReferer = pickDefined(opts?.setReferer, false);
235
237
  if (__classPrivateFieldGet(this, _Fetcher_cookie, "f") && setCookie) {
236
238
  request.headers.set('Cookie', __classPrivateFieldGet(this, _Fetcher_cookie, "f"));
237
239
  }
238
240
  if (setHost) {
239
241
  request.headers.set('Host', 'www.patreon.com');
240
242
  }
243
+ if (setReferer) {
244
+ request.headers.set('referer', SITE_URL);
245
+ }
241
246
  request.headers.set('User-Agent', USER_AGENT);
242
247
  if (type === 'json') {
243
248
  request.headers.set('Content-Type', 'application/vnd.api+json');
@@ -1 +1 @@
1
- {"version":3,"file":"Fetcher.js","sourceRoot":"","sources":["../../src/utils/Fetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport { pipeline } from 'stream/promises';\nimport { fetch, Request, type Response } from 'undici';\nimport path from 'path';\nimport { type Dispatcher } from 'undici';\nimport FetcherProgressMonitor from './FetcherProgressMonitor.js';\nimport { type Downloadable } from '../entities/Downloadable.js';\nimport type FilenameResolver from './FllenameResolver.js';\nimport { pickDefined } from './Misc.js';\nimport {type LogLevel} from './logging/Logger.js';\nimport type Logger from './logging/Logger.js';\nimport { commonLog } from './logging/Logger.js';\nimport FSHelper from './FSHelper.js';\nimport { type DownloaderConfig } from '../downloaders/Downloader.js';\nimport Progress from './Progress.js';\nimport { createProxyAgent } from './Proxy.js';\n\nexport interface PrepareDownloadParams<T extends Downloadable> {\n url: string;\n srcEntity: T;\n destFilePath: string;\n signal: AbortSignal;\n}\n\nexport interface StartDownloadOverrides {\n destFilePath?: string;\n tmpFilePath?: string;\n}\n\nexport class FetcherError extends Error {\n\n url: string;\n method: string;\n\n constructor(message: string, url: string, method: string) {\n super(message);\n this.name = 'FetcherError';\n this.url = url;\n this.method = method;\n }\n}\n\nexport type FetcherGetType = 'html' | 'json';\nexport type FetcherGetResultOf<T extends FetcherGetType> =\n T extends 'html' ? string :\n T extends 'json' ? any :\n never;\n\nconst USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0';\n\nexport default class Fetcher {\n\n name = 'Fetcher';\n\n #cookie?: string;\n #logger?: Logger | null;\n #dryRun: boolean;\n #fsHelper: FSHelper;\n #proxyAgent?: Dispatcher;\n\n constructor(config: DownloaderConfig<any>, logger?: Logger | null) {\n this.#cookie = config.cookie;\n this.#logger = logger;\n this.#dryRun = config.dryRun;\n this.#fsHelper = new FSHelper(config, logger);\n this.#proxyAgent = createProxyAgent(config)?.agent || undefined;\n }\n\n async get<T extends FetcherGetType>(args: {\n url: string,\n type: T,\n payload?: Record<string, any>,\n maxRetries: number,\n signal?: AbortSignal\n }, rt = 0): Promise<FetcherGetResultOf<T>> {\n\n const { url, type, payload, maxRetries, signal } = args;\n\n const urlObj = new URL(url);\n if (payload) {\n for (const [ p, v ] of Object.entries(payload)) {\n urlObj.searchParams.set(p, v);\n }\n }\n const request = new Request(urlObj, { method: 'GET' });\n this.#setHeaders(request, type);\n const internalAbortController = new AbortController();\n let removeAbortHandler: undefined | (() => void) = undefined;\n if (signal) {\n const abortHandler = () => internalAbortController.abort();\n signal.addEventListener('abort', abortHandler, {once: true});\n removeAbortHandler = () => signal.removeEventListener('abort', abortHandler);\n }\n try {\n const res = await fetch(request, { signal: internalAbortController.signal, dispatcher: this.#proxyAgent });\n return await (type === 'html' ? res.text() : res.json()) as FetcherGetResultOf<T>;\n }\n catch (error: any) {\n if (signal?.aborted) {\n throw error;\n }\n if (rt < maxRetries) {\n if (removeAbortHandler) removeAbortHandler();\n return await this.get({ url, type, payload, maxRetries, signal }, rt + 1);\n }\n let errMsg;\n if (error instanceof Error) {\n const errMsgParts = [error.message];\n let _err = error.cause;\n while (_err) {\n errMsgParts.push(_err instanceof Error ? _err.message : JSON.stringify(_err));\n _err = _err instanceof Error ? _err.cause : null;\n }\n errMsg = errMsgParts.join(': ');\n }\n else {\n errMsg = String(error);\n }\n const retriedMsg = rt > 0 ? ` (retried ${rt} times)` : '';\n throw new FetcherError(`${errMsg}${retriedMsg}`, urlObj.toString(), request.method);\n }\n finally {\n if (removeAbortHandler) removeAbortHandler();\n }\n }\n\n async resolveDestFilePath<T extends Downloadable>(params: {\n url: string;\n destDir: string;\n destFilenameResolver: FilenameResolver<T>;\n signal?: AbortSignal;\n }) {\n const { url, destDir, destFilenameResolver, signal } = params;\n const request = new Request(url, { method: 'HEAD' });\n this.#setHeaders(request, 'html', { setCookie: false, setHost: false });\n const internalAbortController = new AbortController();\n const abortHandler = () => internalAbortController.abort();\n if (signal) {\n signal.addEventListener('abort', abortHandler, {once: true});\n }\n\n try {\n const res = await fetch(request, { signal: internalAbortController.signal, dispatcher: this.#proxyAgent });\n\n if (this.#assertResponseOK(res, url, request.method, false)) {\n const destFilename = destFilenameResolver.resolve(res);\n const destFilePath = path.resolve(destDir, destFilename);\n return destFilePath;\n }\n }\n finally {\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n }\n\n return undefined as never;\n }\n\n async prepareDownload<T extends Downloadable>(params: PrepareDownloadParams<T>) {\n const { url, srcEntity, destFilePath, signal } = params;\n const request = new Request(url, { method: 'GET' });\n this.#setHeaders(request, 'html', { setCookie: false, setHost: false });\n const internalAbortController = new AbortController();\n let removeAbortHandler: undefined | (() => void) = undefined;\n if (signal) {\n const abortHandler = () => internalAbortController.abort();\n signal.addEventListener('abort', abortHandler, {once: true});\n removeAbortHandler = () => signal.removeEventListener('abort', abortHandler);\n }\n\n try {\n let res = await fetch(request, { signal: internalAbortController.signal, dispatcher: this.#proxyAgent });\n\n // Special handling for attachment\n if (params.srcEntity.type === 'attachment' && !res.ok && res.redirected && res.url) {\n const redirectReq = new Request(res.url, { method: 'GET' });\n this.#setHeaders(redirectReq, 'html', { setCookie: false, setHost: false });\n res = await fetch(redirectReq, { signal: internalAbortController.signal, dispatcher: this.#proxyAgent });\n }\n\n if (this.#assertResponseOK(res, url, request.method)) {\n const destFilename = path.parse(destFilePath).base;\n const progress = new Progress(res, {\n reportInterval: 300\n });\n const monitor = new FetcherProgressMonitor(progress, destFilename, destFilePath);\n\n const _res = res;\n const start = (overrides?: StartDownloadOverrides) => {\n const _destFilePath = overrides?.destFilePath || destFilePath;\n const _tmpFilePath = overrides?.tmpFilePath || FSHelper.createTmpFilePath(_destFilePath, srcEntity.id);\n return this.#startDownload(_res, _tmpFilePath, _destFilePath, progress, removeAbortHandler)\n };\n const abort = () => {\n if (removeAbortHandler) removeAbortHandler();\n internalAbortController.abort();\n };\n\n return {\n monitor,\n start,\n abort\n };\n }\n }\n catch (error: unknown) {\n if (removeAbortHandler) removeAbortHandler();\n throw error;\n }\n\n return undefined as never;\n }\n\n async #startDownload(\n response: Response & { body: NodeJS.ReadableStream },\n tmpFilePath: string,\n destFilePath: string,\n progress: Progress,\n cleanup?: () => void) {\n\n try {\n let size = 0;\n if (this.#dryRun) {\n try {\n for await (const chunk of response.body) {\n size += chunk.length;\n }\n }\n catch (_error: unknown) {\n // Do nothing\n }\n }\n else {\n this.log('debug', `Pipe \"${response.url}\" to \"${tmpFilePath}\"`);\n await pipeline(\n response.body,\n progress.stream,\n fs.createWriteStream(tmpFilePath)\n );\n size = fs.lstatSync(tmpFilePath).size;\n }\n\n const commit = () => {\n this.#commitDownload(tmpFilePath, destFilePath, size, cleanup);\n };\n\n const discard = () => {\n this.#cleanupDownload(tmpFilePath, cleanup);\n };\n\n return {\n tmpFilePath,\n commit,\n discard\n };\n }\n catch (error) {\n this.#cleanupDownload(tmpFilePath, cleanup);\n throw error;\n }\n }\n\n #commitDownload(tmpFilePath: string, destFilePath: string, size: number, cleanup?: () => void) {\n try {\n this.log('debug', `Commit \"${tmpFilePath}\" to \"${destFilePath}; filesize: ${size} bytes`);\n this.#fsHelper.rename(tmpFilePath, destFilePath);\n }\n finally {\n this.#cleanupDownload(tmpFilePath, cleanup);\n }\n }\n\n #cleanupDownload(tmpFilePath: string, extra?: () => void) {\n try {\n if (this.#dryRun || fs.existsSync(tmpFilePath)) {\n this.log('debug', `Clean up \"${tmpFilePath}\"`);\n this.#fsHelper.unlink(tmpFilePath);\n }\n }\n catch (error) {\n this.log('error', `Error cleaning up \"${tmpFilePath}:`, error);\n }\n finally {\n if (extra) extra();\n }\n }\n\n #setHeaders(request: Request, type: 'html' | 'json', opts?: { setCookie?: boolean; setHost?: boolean; }) {\n const setCookie = pickDefined(opts?.setCookie, true);\n const setHost = pickDefined(opts?.setHost, true);\n if (this.#cookie && setCookie) {\n request.headers.set('Cookie', this.#cookie);\n }\n if (setHost) {\n request.headers.set('Host', 'www.patreon.com');\n }\n request.headers.set('User-Agent', USER_AGENT);\n if (type === 'json') {\n request.headers.set('Content-Type', 'application/vnd.api+json');\n }\n else {\n request.headers.set('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8');\n }\n }\n\n #assertResponseOK(response: Response | null, originURL: string, method: string, requireBody: false): response is Response;\n #assertResponseOK(response: Response | null, originURL: string, method: string, requireBody?: true): response is Response & { body: NodeJS.ReadableStream };\n #assertResponseOK(response: Response | null, originURL: string, method: string, requireBody = true) {\n if (!response) {\n throw new FetcherError('No response', originURL, method);\n }\n if (!response.ok) {\n throw new FetcherError(`${response.status} - ${response.statusText}`, originURL, method);\n }\n if (requireBody && !response.body) {\n throw new FetcherError('Empty response body', originURL, method);\n }\n return true;\n }\n\n protected log(level: LogLevel, ...msg: Array<any>) {\n commonLog(this.#logger, level, this.name, ...msg);\n }\n}\n"]}
1
+ {"version":3,"file":"Fetcher.js","sourceRoot":"","sources":["../../src/utils/Fetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport { pipeline } from 'stream/promises';\nimport { fetch, Request, type Response } from 'undici';\nimport path from 'path';\nimport { type Dispatcher } from 'undici';\nimport FetcherProgressMonitor from './FetcherProgressMonitor.js';\nimport { type Downloadable } from '../entities/Downloadable.js';\nimport type FilenameResolver from './FllenameResolver.js';\nimport { pickDefined } from './Misc.js';\nimport {type LogLevel} from './logging/Logger.js';\nimport type Logger from './logging/Logger.js';\nimport { commonLog } from './logging/Logger.js';\nimport FSHelper from './FSHelper.js';\nimport { type DownloaderConfig } from '../downloaders/Downloader.js';\nimport Progress from './Progress.js';\nimport { createProxyAgent } from './Proxy.js';\nimport { SITE_URL } from './URLHelper.js';\n\nexport interface PrepareDownloadParams<T extends Downloadable> {\n url: string;\n srcEntity: T;\n destFilePath: string;\n setReferer?: boolean;\n signal: AbortSignal;\n}\n\nexport interface StartDownloadOverrides {\n destFilePath?: string;\n tmpFilePath?: string;\n}\n\nexport class FetcherError extends Error {\n\n url: string;\n method: string;\n\n constructor(message: string, url: string, method: string) {\n super(message);\n this.name = 'FetcherError';\n this.url = url;\n this.method = method;\n }\n}\n\nexport type FetcherGetType = 'html' | 'json';\nexport type FetcherGetResultOf<T extends FetcherGetType> =\n T extends 'html' ? string :\n T extends 'json' ? any :\n never;\n\nconst USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0';\n\nexport default class Fetcher {\n\n name = 'Fetcher';\n\n #cookie?: string;\n #logger?: Logger | null;\n #dryRun: boolean;\n #fsHelper: FSHelper;\n #proxyAgent?: Dispatcher;\n\n constructor(config: DownloaderConfig<any>, logger?: Logger | null) {\n this.#cookie = config.cookie;\n this.#logger = logger;\n this.#dryRun = config.dryRun;\n this.#fsHelper = new FSHelper(config, logger);\n this.#proxyAgent = createProxyAgent(config)?.agent || undefined;\n }\n\n async get<T extends FetcherGetType>(args: {\n url: string,\n type: T,\n payload?: Record<string, any>,\n maxRetries: number,\n signal?: AbortSignal\n }, rt = 0): Promise<FetcherGetResultOf<T>> {\n\n const { url, type, payload, maxRetries, signal } = args;\n\n const urlObj = new URL(url);\n if (payload) {\n for (const [ p, v ] of Object.entries(payload)) {\n urlObj.searchParams.set(p, v);\n }\n }\n const request = new Request(urlObj, { method: 'GET' });\n this.#setHeaders(request, type);\n const internalAbortController = new AbortController();\n let removeAbortHandler: undefined | (() => void) = undefined;\n if (signal) {\n const abortHandler = () => internalAbortController.abort();\n signal.addEventListener('abort', abortHandler, {once: true});\n removeAbortHandler = () => signal.removeEventListener('abort', abortHandler);\n }\n try {\n const res = await fetch(request, { signal: internalAbortController.signal, dispatcher: this.#proxyAgent });\n return await (type === 'html' ? res.text() : res.json()) as FetcherGetResultOf<T>;\n }\n catch (error: any) {\n if (signal?.aborted) {\n throw error;\n }\n if (rt < maxRetries) {\n if (removeAbortHandler) removeAbortHandler();\n return await this.get({ url, type, payload, maxRetries, signal }, rt + 1);\n }\n let errMsg;\n if (error instanceof Error) {\n const errMsgParts = [error.message];\n let _err = error.cause;\n while (_err) {\n errMsgParts.push(_err instanceof Error ? _err.message : JSON.stringify(_err));\n _err = _err instanceof Error ? _err.cause : null;\n }\n errMsg = errMsgParts.join(': ');\n }\n else {\n errMsg = String(error);\n }\n const retriedMsg = rt > 0 ? ` (retried ${rt} times)` : '';\n throw new FetcherError(`${errMsg}${retriedMsg}`, urlObj.toString(), request.method);\n }\n finally {\n if (removeAbortHandler) removeAbortHandler();\n }\n }\n\n async resolveDestFilePath<T extends Downloadable>(params: {\n url: string;\n destDir: string;\n destFilenameResolver: FilenameResolver<T>;\n setReferer?: boolean;\n signal?: AbortSignal;\n }) {\n const { url, destDir, destFilenameResolver, setReferer = false, signal } = params;\n const request = new Request(url, { method: 'HEAD' });\n this.#setHeaders(request, 'html', { setCookie: false, setHost: false, setReferer });\n const internalAbortController = new AbortController();\n const abortHandler = () => internalAbortController.abort();\n if (signal) {\n signal.addEventListener('abort', abortHandler, {once: true});\n }\n\n try {\n const res = await fetch(request, { signal: internalAbortController.signal, dispatcher: this.#proxyAgent });\n\n if (this.#assertResponseOK(res, url, request.method, false)) {\n const destFilename = destFilenameResolver.resolve(res);\n const destFilePath = path.resolve(destDir, destFilename);\n return destFilePath;\n }\n }\n finally {\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n }\n\n return undefined as never;\n }\n\n async prepareDownload<T extends Downloadable>(params: PrepareDownloadParams<T>) {\n const { url, srcEntity, destFilePath, setReferer = false, signal } = params;\n const request = new Request(url, { method: 'GET' });\n this.#setHeaders(request, 'html', { setCookie: false, setHost: false, setReferer });\n const internalAbortController = new AbortController();\n let removeAbortHandler: undefined | (() => void) = undefined;\n if (signal) {\n const abortHandler = () => internalAbortController.abort();\n signal.addEventListener('abort', abortHandler, {once: true});\n removeAbortHandler = () => signal.removeEventListener('abort', abortHandler);\n }\n\n try {\n let res = await fetch(request, { signal: internalAbortController.signal, dispatcher: this.#proxyAgent });\n\n // Special handling for attachment\n if (params.srcEntity.type === 'attachment' && !res.ok && res.redirected && res.url) {\n const redirectReq = new Request(res.url, { method: 'GET' });\n this.#setHeaders(redirectReq, 'html', { setCookie: false, setHost: false });\n res = await fetch(redirectReq, { signal: internalAbortController.signal, dispatcher: this.#proxyAgent });\n }\n\n if (this.#assertResponseOK(res, url, request.method)) {\n const destFilename = path.parse(destFilePath).base;\n const progress = new Progress(res, {\n reportInterval: 300\n });\n const monitor = new FetcherProgressMonitor(progress, destFilename, destFilePath);\n\n const _res = res;\n const start = (overrides?: StartDownloadOverrides) => {\n const _destFilePath = overrides?.destFilePath || destFilePath;\n const _tmpFilePath = overrides?.tmpFilePath || FSHelper.createTmpFilePath(_destFilePath, srcEntity.id);\n return this.#startDownload(_res, _tmpFilePath, _destFilePath, progress, removeAbortHandler)\n };\n const abort = () => {\n if (removeAbortHandler) removeAbortHandler();\n internalAbortController.abort();\n };\n\n return {\n monitor,\n start,\n abort\n };\n }\n }\n catch (error: unknown) {\n if (removeAbortHandler) removeAbortHandler();\n throw error;\n }\n\n return undefined as never;\n }\n\n async #startDownload(\n response: Response & { body: NodeJS.ReadableStream },\n tmpFilePath: string,\n destFilePath: string,\n progress: Progress,\n cleanup?: () => void) {\n\n try {\n let size = 0;\n if (this.#dryRun) {\n try {\n for await (const chunk of response.body) {\n size += chunk.length;\n }\n }\n catch (_error: unknown) {\n // Do nothing\n }\n }\n else {\n this.log('debug', `Pipe \"${response.url}\" to \"${tmpFilePath}\"`);\n await pipeline(\n response.body,\n progress.stream,\n fs.createWriteStream(tmpFilePath)\n );\n size = fs.lstatSync(tmpFilePath).size;\n }\n\n const commit = () => {\n this.#commitDownload(tmpFilePath, destFilePath, size, cleanup);\n };\n\n const discard = () => {\n this.#cleanupDownload(tmpFilePath, cleanup);\n };\n\n return {\n tmpFilePath,\n commit,\n discard\n };\n }\n catch (error) {\n this.#cleanupDownload(tmpFilePath, cleanup);\n throw error;\n }\n }\n\n #commitDownload(tmpFilePath: string, destFilePath: string, size: number, cleanup?: () => void) {\n try {\n this.log('debug', `Commit \"${tmpFilePath}\" to \"${destFilePath}; filesize: ${size} bytes`);\n this.#fsHelper.rename(tmpFilePath, destFilePath);\n }\n finally {\n this.#cleanupDownload(tmpFilePath, cleanup);\n }\n }\n\n #cleanupDownload(tmpFilePath: string, extra?: () => void) {\n try {\n if (this.#dryRun || fs.existsSync(tmpFilePath)) {\n this.log('debug', `Clean up \"${tmpFilePath}\"`);\n this.#fsHelper.unlink(tmpFilePath);\n }\n }\n catch (error) {\n this.log('error', `Error cleaning up \"${tmpFilePath}:`, error);\n }\n finally {\n if (extra) extra();\n }\n }\n\n #setHeaders(request: Request, type: 'html' | 'json', opts?: { setCookie?: boolean; setHost?: boolean; setReferer?: boolean; }) {\n const setCookie = pickDefined(opts?.setCookie, true);\n const setHost = pickDefined(opts?.setHost, true);\n const setReferer = pickDefined(opts?.setReferer, false);\n if (this.#cookie && setCookie) {\n request.headers.set('Cookie', this.#cookie);\n }\n if (setHost) {\n request.headers.set('Host', 'www.patreon.com');\n }\n if (setReferer) {\n request.headers.set('referer', SITE_URL);\n }\n request.headers.set('User-Agent', USER_AGENT);\n if (type === 'json') {\n request.headers.set('Content-Type', 'application/vnd.api+json');\n }\n else {\n request.headers.set('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8');\n }\n }\n\n #assertResponseOK(response: Response | null, originURL: string, method: string, requireBody: false): response is Response;\n #assertResponseOK(response: Response | null, originURL: string, method: string, requireBody?: true): response is Response & { body: NodeJS.ReadableStream };\n #assertResponseOK(response: Response | null, originURL: string, method: string, requireBody = true) {\n if (!response) {\n throw new FetcherError('No response', originURL, method);\n }\n if (!response.ok) {\n throw new FetcherError(`${response.status} - ${response.statusText}`, originURL, method);\n }\n if (requireBody && !response.body) {\n throw new FetcherError('Empty response body', originURL, method);\n }\n return true;\n }\n\n protected log(level: LogLevel, ...msg: Array<any>) {\n commonLog(this.#logger, level, this.name, ...msg);\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { type UserIdOrVanityParam } from '../entities';
2
+ export declare const SITE_URL = "https://www.patreon.com";
2
3
  export declare enum PostSortOrder {
3
4
  PublisedAtDesc = "-published_at",
4
5
  PublishedAtAsc = "published_at",
@@ -1 +1 @@
1
- {"version":3,"file":"URLHelper.d.ts","sourceRoot":"","sources":["../../src/utils/URLHelper.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AA2IvD,oBAAY,aAAa;IACvB,cAAc,kBAAkB;IAChC,cAAc,iBAAiB;IAC/B,eAAe,qBAAqB;CACrC;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,GAAG;IACF,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B,GAAG;IACF,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B,GAAG;IACF,IAAI,EAAE,mBAAmB,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B,GAAG;IACF,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,SAAS;IAE5B,MAAM,CAAC,sBAAsB,CAAC,SAAS,EAAE,MAAM;IAU/C,MAAM,CAAC,wBAAwB,CAAC,IAAI,EAAE,mBAAmB;IAQzD,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,mBAAmB;IAQtD,MAAM,CAAC,sBAAsB,CAAC,YAAY,EAAE,MAAM;IAIlD,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM;IAIzC,MAAM,CAAC,uBAAuB,CAAC,UAAU,EAAE,MAAM;IAIjD,MAAM,CAAC,oBAAoB,CAAC,MAAM,EAAE;QAClC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,EAAE,aAAa,CAAC;KACtB;IAkCD,MAAM,CAAC,2BAA2B,CAAC,MAAM,EAAE;QACzC,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,KAAK,CAAA;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG;QACF,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,IAAI,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAA;KACf;IA4BD,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAyGlD,MAAM,CAAC,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IASpD,MAAM,CAAC,mBAAmB,CAAC,GAAG,EAAE,MAAM;IAKtC,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG;CAU5B"}
1
+ {"version":3,"file":"URLHelper.d.ts","sourceRoot":"","sources":["../../src/utils/URLHelper.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,QAAQ,4BAA4B,CAAC;AAyIlD,oBAAY,aAAa;IACvB,cAAc,kBAAkB;IAChC,cAAc,iBAAiB;IAC/B,eAAe,qBAAqB;CACrC;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,GAAG;IACF,IAAI,EAAE,aAAa,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B,GAAG;IACF,IAAI,EAAE,eAAe,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B,GAAG;IACF,IAAI,EAAE,mBAAmB,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC/B,GAAG;IACF,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAA;AAED,MAAM,CAAC,OAAO,OAAO,SAAS;IAE5B,MAAM,CAAC,sBAAsB,CAAC,SAAS,EAAE,MAAM;IAU/C,MAAM,CAAC,wBAAwB,CAAC,IAAI,EAAE,mBAAmB;IAQzD,MAAM,CAAC,qBAAqB,CAAC,IAAI,EAAE,mBAAmB;IAQtD,MAAM,CAAC,sBAAsB,CAAC,YAAY,EAAE,MAAM;IAIlD,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM;IAIzC,MAAM,CAAC,uBAAuB,CAAC,UAAU,EAAE,MAAM;IAIjD,MAAM,CAAC,oBAAoB,CAAC,MAAM,EAAE;QAClC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC9B,IAAI,CAAC,EAAE,aAAa,CAAC;KACtB;IAkCD,MAAM,CAAC,2BAA2B,CAAC,MAAM,EAAE;QACzC,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,KAAK,CAAA;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG;QACF,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,IAAI,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAA;KACf;IA4BD,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAyGlD,MAAM,CAAC,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IASpD,MAAM,CAAC,mBAAmB,CAAC,GAAG,EAAE,MAAM;IAKtC,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG;CAU5B"}
@@ -1,6 +1,6 @@
1
1
  import path from 'path';
2
2
  import { URL } from 'url';
3
- const SITE_URL = 'https://www.patreon.com';
3
+ export const SITE_URL = 'https://www.patreon.com';
4
4
  const COLLECTION_URL = `${SITE_URL}/collection`;
5
5
  const PRODUCT_API_URL = `${SITE_URL}/api/product`;
6
6
  const POSTS_API_URL = `${SITE_URL}/api/posts`;
@@ -1 +1 @@
1
- {"version":3,"file":"URLHelper.js","sourceRoot":"","sources":["../../src/utils/URLHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\nimport { URL } from 'url';\nimport { type UserIdOrVanityParam } from '../entities';\n\nconst SITE_URL = 'https://www.patreon.com';\nconst COLLECTION_URL = `${SITE_URL}/collection`;\nconst PRODUCT_API_URL = `${SITE_URL}/api/product`;\nconst POSTS_API_URL = `${SITE_URL}/api/posts`;\nconst USER_API_URL = `${SITE_URL}/api/user`;\nconst CAMPAIGN_API_URL = `${SITE_URL}/api/campaigns`;\nconst POST_COMMENTS_API_URL = `${SITE_URL}/api/posts/{POST_ID}/comments2`\nconst POST_COMMENT_REPLIES_API_URL = `${SITE_URL}/api/comments/{COMMENT_ID}/replies2`\n\nconst PRODUCT_URL_REGEX = /https:\\/\\/www\\.patreon\\.com\\/([^/]+?)\\/shop\\/(([^/]+)-(\\d+))$/;\nconst POSTS_BY_USER_URL_REGEX = /https:\\/\\/www\\.patreon\\.com\\/([^/]+?)\\/posts$/;\nconst POSTS_BY_USER_URL_REGEX_2 = /https:\\/\\/www\\.patreon\\.com\\/(?:c|cw)\\/([^/]+?)\\/posts$/;\nconst COLLECTION_URL_REGEX = /https:\\/\\/www\\.patreon\\.com\\/collection\\/(\\d+)$/;\nconst POST_URL_REGEX = /https:\\/\\/www\\.patreon\\.com\\/posts\\/(([^/]+)-(\\d+))$/;\nconst POST_URL_REGEX_2 = /https:\\/\\/www\\.patreon\\.com\\/posts\\/(\\d+)$/; // No slug\n\nconst PRODUCT_API_URL_SEARCH_PARAMS = {\n PRODUCT_VARIANT: [\n 'name',\n 'id',\n 'price_cents',\n 'description',\n 'is_hidden',\n 'published_at_datetime',\n 'url',\n 'share_url',\n 'access_metadata',\n 'reward_ids',\n 'moderation_status'\n ],\n INCLUDE: [\n 'content_media',\n 'preview_media',\n 'content_media.custom_thumbnail_media',\n 'campaign',\n 'content_media.teaser_media'\n ]\n};\n\nconst POSTS_API_URL_SEARCH_PARAMS = {\n INCLUDE: [\n 'campaign',\n 'access_rules',\n 'access_rules.tier.null',\n 'attachments_media',\n 'audio',\n 'audio_preview.null',\n 'images',\n 'media',\n 'native_video_insights',\n 'poll.choices',\n 'poll.current_user_responses.user',\n 'poll.current_user_responses.choice',\n 'poll.current_user_responses.poll',\n 'user',\n 'user_defined_tags',\n 'ti_checks'\n ]\n};\n\nconst POST_COMMENTS_API_URL_SEARCH_PARAMS = {\n INCLUDE: [\n 'parent',\n 'post',\n 'on_behalf_of_campaign.null',\n 'commenter.campaign.null',\n 'first_reply.commenter.campaign.null',\n 'first_reply.parent',\n 'first_reply.post',\n 'first_reply.on_behalf_of_campaign.null'\n ],\n FIELDS: {\n COMMENT: [\n 'body',\n 'created',\n 'deleted_at',\n 'is_by_patron',\n 'is_by_creator',\n 'is_liked_by_creator',\n 'vote_sum',\n 'current_user_vote',\n 'reply_count',\n 'visibility_state'\n ],\n CAMPAIGN: [],\n POST: [\n 'comment_count',\n 'current_user_can_comment',\n 'url'\n ],\n POST_TAG: [\n 'tag_type',\n 'value'\n ],\n USER: [\n 'image_url',\n 'full_name',\n 'url'\n ]\n },\n COUNT: 50,\n SORT: '-created'\n};\n\nconst POST_COMMENT_REPLIES_API_URL_SEARCH_PARAMS = {\n INCLUDE: [\n 'commenter.campaign',\n 'parent',\n 'post',\n 'on_behalf_of_campaign'\n ],\n FIELDS: {\n CAMPAIGN: [],\n COMMENT: [\n 'body',\n 'created',\n 'deleted_at',\n 'is_by_patron',\n 'is_by_creator',\n 'is_liked_by_creator',\n 'vote_sum',\n 'current_user_vote',\n 'visibility_state'\n ],\n POST: [\n 'comment_count'\n ],\n USER: [\n 'image_url',\n 'full_name',\n 'url'\n ]\n },\n COUNT: 50,\n SORT: 'created'\n}\n\nexport enum PostSortOrder {\n PublisedAtDesc = '-published_at',\n PublishedAtAsc = 'published_at',\n CollectionOrder = 'collection_order'\n}\n\nexport type URLAnalysis = {\n type: 'product';\n productId: string;\n slug: string;\n} | {\n type: 'postsByUser';\n vanity: string;\n filters?: Record<string, any>;\n} | {\n type: 'postsByUserId';\n userId: string;\n filters?: Record<string, any>;\n} | {\n type: 'postsByCollection';\n collectionId: string;\n filters?: Record<string, any>;\n} | {\n type: 'post';\n postId: string;\n slug?: string;\n}\n\nexport default class URLHelper {\n\n static constructProductAPIURL(productId: string) {\n const url = `${PRODUCT_API_URL}/${productId}`;\n const urlObj = new URL(url);\n urlObj.searchParams.set('fields[product-variant]', PRODUCT_API_URL_SEARCH_PARAMS.PRODUCT_VARIANT.join(','));\n urlObj.searchParams.set('include', PRODUCT_API_URL_SEARCH_PARAMS.INCLUDE.join(','));\n urlObj.searchParams.set('json-api-version', '1.0');\n\n return urlObj.toString();\n }\n\n static constructCampaignPageURL(user: UserIdOrVanityParam) {\n if (user.vanity) {\n return `${SITE_URL}/${user.vanity}`;\n }\n\n return `${SITE_URL}/user?u=${user.userId}`;\n }\n\n static constructUserPostsURL(user: UserIdOrVanityParam) {\n if (user.vanity) {\n return `${SITE_URL}/${user.vanity}/posts`;\n }\n\n return `${SITE_URL}/user/posts?u=${user.userId}`;\n }\n\n static constructCollectionURL(collectionId: string) {\n return `${COLLECTION_URL}/${collectionId}`;\n }\n\n static constructUserAPIURL(userId: string) {\n return `${USER_API_URL}/${userId}`;\n }\n\n static constructCampaignAPIURL(campaignId: string) {\n return `${CAMPAIGN_API_URL}/${campaignId}`;\n }\n\n static constructPostsAPIURL(params: {\n postId?: string;\n campaignId?: string;\n currentUserId?: string;\n filters?: Record<string, any>;\n sort?: PostSortOrder;\n }) {\n if (!params.postId && !params.campaignId) {\n throw Error('Posts API URL requires at least \\'postId\\' or \\'campaignId\\'');\n }\n const urlObj = params.postId ? new URL(`${POSTS_API_URL}/${params.postId}`) : new URL(POSTS_API_URL);\n const defaultFilters: Record<string, any> = {\n 'contains_exclusive_posts': true,\n 'is_draft': false\n };\n if (params.campaignId) {\n defaultFilters['campaign_id'] = params.campaignId;\n }\n if (params.currentUserId) {\n defaultFilters['accessible_by_user_id'] = params.currentUserId;\n }\n const allFilters = {\n ...defaultFilters,\n ...params.filters || {}\n };\n const searchParams: Record<string, any> = {\n 'include': POSTS_API_URL_SEARCH_PARAMS.INCLUDE.join(','),\n 'sort': params.sort || PostSortOrder.PublisedAtDesc,\n 'json-api-version': '1.0'\n };\n for (const [ key, value ] of Object.entries(allFilters)) {\n searchParams[`filter[${key}]`] = value;\n }\n for (const [ key, value ] of Object.entries(searchParams)) {\n urlObj.searchParams.set(key, value);\n }\n\n return urlObj.toString();\n }\n\n static constructPostCommentsAPIURL(params: {\n postId: string,\n replies?: false\n count?: number;\n } | {\n commentId: string,\n replies: true,\n count?: number\n }) {\n let urlObj: URL;\n if (params.replies) {\n urlObj = new URL(POST_COMMENT_REPLIES_API_URL.replace('{COMMENT_ID}', params.commentId));\n }\n else {\n urlObj = new URL(POST_COMMENTS_API_URL.replace('{POST_ID}', params.postId));\n }\n const fields: Record<string, string> = {};\n const bundle = params.replies ? POST_COMMENT_REPLIES_API_URL_SEARCH_PARAMS : POST_COMMENTS_API_URL_SEARCH_PARAMS;\n for (const [k, v] of Object.entries(bundle.FIELDS)) {\n fields[`fields[${k.toLowerCase()}]`] = v.join(',') || '[]'\n }\n const searchParams: Record<string, any> = {\n 'include': bundle.INCLUDE.join(','),\n ...fields,\n 'page[count]': params.count || bundle.COUNT,\n 'sort': bundle.SORT,\n 'json-api-version': '1.0',\n 'json-api-use-default-includes': false\n };\n for (const [ key, value ] of Object.entries(searchParams)) {\n urlObj.searchParams.set(key, value);\n }\n\n return urlObj.toString();\n }\n\n static analyzeURL(url: string): URLAnalysis | null {\n\n const base = this.stripSearchParamsFromURL(url);\n const searchParams = new URL(url).searchParams;\n\n const __getFiltersFromSearchParams = (searchParams: URLSearchParams) => {\n const filters: Record<string, any> = {};\n const filterRegex = /filters\\[(.+?)\\]/g;\n for (const [ key, value ] of searchParams) {\n const match = filterRegex.exec(key);\n if (match && match[1]) {\n filters[match[1]] = value;\n }\n filterRegex.lastIndex = 0;\n }\n return filters;\n };\n\n const productURLMatch = PRODUCT_URL_REGEX.exec(base);\n if (productURLMatch?.length === 5) {\n const productId = productURLMatch[4];\n const slug = productURLMatch[2];\n return {\n type: 'product',\n productId,\n slug\n };\n }\n\n const __getPostsURLMatchVanity = (regex: RegExp) => {\n const match = regex.exec(base);\n if (match && match[1]) {\n return match[1];\n }\n return null;\n }\n const postsURLMatchVanity =\n __getPostsURLMatchVanity(POSTS_BY_USER_URL_REGEX) ||\n __getPostsURLMatchVanity(POSTS_BY_USER_URL_REGEX_2);\n if (postsURLMatchVanity) {\n const vanity = postsURLMatchVanity;\n const filters = __getFiltersFromSearchParams(searchParams);\n let result: URLAnalysis & { type: 'postsByUser' | 'postsByUserId' };\n // Test if match https://www.patreon.com/user/posts?u={userId}\n const userId = searchParams.get('u')?.trim();\n if (vanity === 'user' && userId) {\n result = {\n type: 'postsByUserId',\n userId\n };\n }\n else {\n result = {\n type: 'postsByUser',\n vanity\n };\n }\n if (Object.keys(filters).length > 0) {\n result.filters = filters;\n }\n\n return result;\n }\n\n const collectionURLMatch = COLLECTION_URL_REGEX.exec(base);\n if (collectionURLMatch && collectionURLMatch[1]) {\n const collectionId = collectionURLMatch[1];\n const filters = __getFiltersFromSearchParams(searchParams);\n if (!filters['collection_id']) {\n filters['collection_id'] = collectionId;\n }\n const result: URLAnalysis & { type: 'postsByCollection' } = {\n type: 'postsByCollection',\n collectionId\n };\n if (Object.keys(filters).length > 0) {\n result.filters = filters;\n }\n\n return result;\n }\n\n const postURLMatch = POST_URL_REGEX.exec(base);\n if (postURLMatch?.length === 4) {\n const postId = postURLMatch[3];\n const slug = postURLMatch[1];\n return {\n type: 'post',\n postId,\n slug\n };\n }\n\n const postURLMatch2 = POST_URL_REGEX_2.exec(base);\n if (postURLMatch2?.length === 2) {\n const postId = postURLMatch2[1];\n return {\n type: 'post',\n postId\n };\n }\n\n return null;\n }\n\n static stripSearchParamsFromURL(url: string): string {\n const urlObj = new URL(url);\n let stripped = `${urlObj.origin}${urlObj.pathname}`;\n while (stripped.endsWith('/')) {\n stripped = stripped.substring(0, stripped.length - 1);\n }\n return stripped;\n }\n\n static getExtensionFromURL(url: string) {\n const urlObj = new URL(url);\n return path.extname(urlObj.pathname.split('/').pop() || '');\n }\n\n static validateURL(url: any) {\n let urlObj;\n try {\n urlObj = new URL(url);\n }\n catch (_error: unknown) {\n return false;\n }\n return !!urlObj;\n }\n}\n"]}
1
+ {"version":3,"file":"URLHelper.js","sourceRoot":"","sources":["../../src/utils/URLHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\nimport { URL } from 'url';\nimport { type UserIdOrVanityParam } from '../entities';\n\nexport const SITE_URL = 'https://www.patreon.com';\nconst COLLECTION_URL = `${SITE_URL}/collection`;\nconst PRODUCT_API_URL = `${SITE_URL}/api/product`;\nconst POSTS_API_URL = `${SITE_URL}/api/posts`;\nconst USER_API_URL = `${SITE_URL}/api/user`;\nconst CAMPAIGN_API_URL = `${SITE_URL}/api/campaigns`;\nconst POST_COMMENTS_API_URL = `${SITE_URL}/api/posts/{POST_ID}/comments2`\nconst POST_COMMENT_REPLIES_API_URL = `${SITE_URL}/api/comments/{COMMENT_ID}/replies2`\n\nconst PRODUCT_URL_REGEX = /https:\\/\\/www\\.patreon\\.com\\/([^/]+?)\\/shop\\/(([^/]+)-(\\d+))$/;\nconst POSTS_BY_USER_URL_REGEX = /https:\\/\\/www\\.patreon\\.com\\/([^/]+?)\\/posts$/;\nconst POSTS_BY_USER_URL_REGEX_2 = /https:\\/\\/www\\.patreon\\.com\\/(?:c|cw)\\/([^/]+?)\\/posts$/;\nconst COLLECTION_URL_REGEX = /https:\\/\\/www\\.patreon\\.com\\/collection\\/(\\d+)$/;\nconst POST_URL_REGEX = /https:\\/\\/www\\.patreon\\.com\\/posts\\/(([^/]+)-(\\d+))$/;\nconst POST_URL_REGEX_2 = /https:\\/\\/www\\.patreon\\.com\\/posts\\/(\\d+)$/; // No slug\n\nconst PRODUCT_API_URL_SEARCH_PARAMS = {\n PRODUCT_VARIANT: [\n 'name',\n 'id',\n 'price_cents',\n 'description',\n 'is_hidden',\n 'published_at_datetime',\n 'url',\n 'share_url',\n 'access_metadata',\n 'reward_ids',\n 'moderation_status'\n ],\n INCLUDE: [\n 'content_media',\n 'preview_media',\n 'content_media.custom_thumbnail_media',\n 'campaign',\n 'content_media.teaser_media'\n ]\n};\n\nconst POSTS_API_URL_SEARCH_PARAMS = {\n INCLUDE: [\n 'campaign',\n 'access_rules',\n 'access_rules.tier.null',\n 'attachments_media',\n 'audio',\n 'audio_preview.null',\n 'images',\n 'media',\n 'native_video_insights',\n 'poll.choices',\n 'poll.current_user_responses.user',\n 'poll.current_user_responses.choice',\n 'poll.current_user_responses.poll',\n 'user',\n 'user_defined_tags',\n 'ti_checks'\n ]\n};\n\nconst POST_COMMENTS_API_URL_SEARCH_PARAMS = {\n INCLUDE: [\n 'parent',\n 'post',\n 'on_behalf_of_campaign.null',\n 'commenter.campaign.null',\n 'first_reply.commenter.campaign.null',\n 'first_reply.parent',\n 'first_reply.post',\n 'first_reply.on_behalf_of_campaign.null'\n ],\n FIELDS: {\n COMMENT: [\n 'body',\n 'created',\n 'deleted_at',\n 'is_by_patron',\n 'is_by_creator',\n 'is_liked_by_creator',\n 'vote_sum',\n 'current_user_vote',\n 'reply_count',\n 'visibility_state'\n ],\n CAMPAIGN: [],\n POST: [\n 'comment_count',\n 'current_user_can_comment',\n 'url'\n ],\n POST_TAG: [\n 'tag_type',\n 'value'\n ],\n USER: [\n 'image_url',\n 'full_name',\n 'url'\n ]\n },\n COUNT: 50,\n SORT: '-created'\n};\n\nconst POST_COMMENT_REPLIES_API_URL_SEARCH_PARAMS = {\n INCLUDE: [\n 'commenter.campaign',\n 'parent',\n 'post',\n 'on_behalf_of_campaign'\n ],\n FIELDS: {\n CAMPAIGN: [],\n COMMENT: [\n 'body',\n 'created',\n 'deleted_at',\n 'is_by_patron',\n 'is_by_creator',\n 'is_liked_by_creator',\n 'vote_sum',\n 'current_user_vote',\n 'visibility_state'\n ],\n POST: [\n 'comment_count'\n ],\n USER: [\n 'image_url',\n 'full_name',\n 'url'\n ]\n },\n COUNT: 50,\n SORT: 'created'\n}\n\nexport enum PostSortOrder {\n PublisedAtDesc = '-published_at',\n PublishedAtAsc = 'published_at',\n CollectionOrder = 'collection_order'\n}\n\nexport type URLAnalysis = {\n type: 'product';\n productId: string;\n slug: string;\n} | {\n type: 'postsByUser';\n vanity: string;\n filters?: Record<string, any>;\n} | {\n type: 'postsByUserId';\n userId: string;\n filters?: Record<string, any>;\n} | {\n type: 'postsByCollection';\n collectionId: string;\n filters?: Record<string, any>;\n} | {\n type: 'post';\n postId: string;\n slug?: string;\n}\n\nexport default class URLHelper {\n\n static constructProductAPIURL(productId: string) {\n const url = `${PRODUCT_API_URL}/${productId}`;\n const urlObj = new URL(url);\n urlObj.searchParams.set('fields[product-variant]', PRODUCT_API_URL_SEARCH_PARAMS.PRODUCT_VARIANT.join(','));\n urlObj.searchParams.set('include', PRODUCT_API_URL_SEARCH_PARAMS.INCLUDE.join(','));\n urlObj.searchParams.set('json-api-version', '1.0');\n\n return urlObj.toString();\n }\n\n static constructCampaignPageURL(user: UserIdOrVanityParam) {\n if (user.vanity) {\n return `${SITE_URL}/${user.vanity}`;\n }\n\n return `${SITE_URL}/user?u=${user.userId}`;\n }\n\n static constructUserPostsURL(user: UserIdOrVanityParam) {\n if (user.vanity) {\n return `${SITE_URL}/${user.vanity}/posts`;\n }\n\n return `${SITE_URL}/user/posts?u=${user.userId}`;\n }\n\n static constructCollectionURL(collectionId: string) {\n return `${COLLECTION_URL}/${collectionId}`;\n }\n\n static constructUserAPIURL(userId: string) {\n return `${USER_API_URL}/${userId}`;\n }\n\n static constructCampaignAPIURL(campaignId: string) {\n return `${CAMPAIGN_API_URL}/${campaignId}`;\n }\n\n static constructPostsAPIURL(params: {\n postId?: string;\n campaignId?: string;\n currentUserId?: string;\n filters?: Record<string, any>;\n sort?: PostSortOrder;\n }) {\n if (!params.postId && !params.campaignId) {\n throw Error('Posts API URL requires at least \\'postId\\' or \\'campaignId\\'');\n }\n const urlObj = params.postId ? new URL(`${POSTS_API_URL}/${params.postId}`) : new URL(POSTS_API_URL);\n const defaultFilters: Record<string, any> = {\n 'contains_exclusive_posts': true,\n 'is_draft': false\n };\n if (params.campaignId) {\n defaultFilters['campaign_id'] = params.campaignId;\n }\n if (params.currentUserId) {\n defaultFilters['accessible_by_user_id'] = params.currentUserId;\n }\n const allFilters = {\n ...defaultFilters,\n ...params.filters || {}\n };\n const searchParams: Record<string, any> = {\n 'include': POSTS_API_URL_SEARCH_PARAMS.INCLUDE.join(','),\n 'sort': params.sort || PostSortOrder.PublisedAtDesc,\n 'json-api-version': '1.0'\n };\n for (const [ key, value ] of Object.entries(allFilters)) {\n searchParams[`filter[${key}]`] = value;\n }\n for (const [ key, value ] of Object.entries(searchParams)) {\n urlObj.searchParams.set(key, value);\n }\n\n return urlObj.toString();\n }\n\n static constructPostCommentsAPIURL(params: {\n postId: string,\n replies?: false\n count?: number;\n } | {\n commentId: string,\n replies: true,\n count?: number\n }) {\n let urlObj: URL;\n if (params.replies) {\n urlObj = new URL(POST_COMMENT_REPLIES_API_URL.replace('{COMMENT_ID}', params.commentId));\n }\n else {\n urlObj = new URL(POST_COMMENTS_API_URL.replace('{POST_ID}', params.postId));\n }\n const fields: Record<string, string> = {};\n const bundle = params.replies ? POST_COMMENT_REPLIES_API_URL_SEARCH_PARAMS : POST_COMMENTS_API_URL_SEARCH_PARAMS;\n for (const [k, v] of Object.entries(bundle.FIELDS)) {\n fields[`fields[${k.toLowerCase()}]`] = v.join(',') || '[]'\n }\n const searchParams: Record<string, any> = {\n 'include': bundle.INCLUDE.join(','),\n ...fields,\n 'page[count]': params.count || bundle.COUNT,\n 'sort': bundle.SORT,\n 'json-api-version': '1.0',\n 'json-api-use-default-includes': false\n };\n for (const [ key, value ] of Object.entries(searchParams)) {\n urlObj.searchParams.set(key, value);\n }\n\n return urlObj.toString();\n }\n\n static analyzeURL(url: string): URLAnalysis | null {\n\n const base = this.stripSearchParamsFromURL(url);\n const searchParams = new URL(url).searchParams;\n\n const __getFiltersFromSearchParams = (searchParams: URLSearchParams) => {\n const filters: Record<string, any> = {};\n const filterRegex = /filters\\[(.+?)\\]/g;\n for (const [ key, value ] of searchParams) {\n const match = filterRegex.exec(key);\n if (match && match[1]) {\n filters[match[1]] = value;\n }\n filterRegex.lastIndex = 0;\n }\n return filters;\n };\n\n const productURLMatch = PRODUCT_URL_REGEX.exec(base);\n if (productURLMatch?.length === 5) {\n const productId = productURLMatch[4];\n const slug = productURLMatch[2];\n return {\n type: 'product',\n productId,\n slug\n };\n }\n\n const __getPostsURLMatchVanity = (regex: RegExp) => {\n const match = regex.exec(base);\n if (match && match[1]) {\n return match[1];\n }\n return null;\n }\n const postsURLMatchVanity =\n __getPostsURLMatchVanity(POSTS_BY_USER_URL_REGEX) ||\n __getPostsURLMatchVanity(POSTS_BY_USER_URL_REGEX_2);\n if (postsURLMatchVanity) {\n const vanity = postsURLMatchVanity;\n const filters = __getFiltersFromSearchParams(searchParams);\n let result: URLAnalysis & { type: 'postsByUser' | 'postsByUserId' };\n // Test if match https://www.patreon.com/user/posts?u={userId}\n const userId = searchParams.get('u')?.trim();\n if (vanity === 'user' && userId) {\n result = {\n type: 'postsByUserId',\n userId\n };\n }\n else {\n result = {\n type: 'postsByUser',\n vanity\n };\n }\n if (Object.keys(filters).length > 0) {\n result.filters = filters;\n }\n\n return result;\n }\n\n const collectionURLMatch = COLLECTION_URL_REGEX.exec(base);\n if (collectionURLMatch && collectionURLMatch[1]) {\n const collectionId = collectionURLMatch[1];\n const filters = __getFiltersFromSearchParams(searchParams);\n if (!filters['collection_id']) {\n filters['collection_id'] = collectionId;\n }\n const result: URLAnalysis & { type: 'postsByCollection' } = {\n type: 'postsByCollection',\n collectionId\n };\n if (Object.keys(filters).length > 0) {\n result.filters = filters;\n }\n\n return result;\n }\n\n const postURLMatch = POST_URL_REGEX.exec(base);\n if (postURLMatch?.length === 4) {\n const postId = postURLMatch[3];\n const slug = postURLMatch[1];\n return {\n type: 'post',\n postId,\n slug\n };\n }\n\n const postURLMatch2 = POST_URL_REGEX_2.exec(base);\n if (postURLMatch2?.length === 2) {\n const postId = postURLMatch2[1];\n return {\n type: 'post',\n postId\n };\n }\n\n return null;\n }\n\n static stripSearchParamsFromURL(url: string): string {\n const urlObj = new URL(url);\n let stripped = `${urlObj.origin}${urlObj.pathname}`;\n while (stripped.endsWith('/')) {\n stripped = stripped.substring(0, stripped.length - 1);\n }\n return stripped;\n }\n\n static getExtensionFromURL(url: string) {\n const urlObj = new URL(url);\n return path.extname(urlObj.pathname.split('/').pop() || '');\n }\n\n static validateURL(url: any) {\n let urlObj;\n try {\n urlObj = new URL(url);\n }\n catch (_error: unknown) {\n return false;\n }\n return !!urlObj;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "patreon-dl",
3
- "version": "2.4.2",
3
+ "version": "2.4.3",
4
4
  "description": "Patreon Downloader",
5
5
  "type": "module",
6
6
  "exports": "./dist/index.js",
@@ -56,7 +56,8 @@
56
56
  "@types/cli-color": "^2.0.5",
57
57
  "@types/deep-freeze": "^0.1.5",
58
58
  "@types/jsdom": "^21.1.7",
59
- "bgutils-js": "^3.1.0",
59
+ "argv-split": "^3.2.1",
60
+ "bgutils-js": "^3.2.0",
60
61
  "bottleneck": "^2.19.5",
61
62
  "capitalize": "^2.0.4",
62
63
  "cheerio": "^1.0.0",
@@ -84,10 +85,9 @@
84
85
  "sanitize-filename": "^1.6.3",
85
86
  "semver": "^7.5.4",
86
87
  "speedometer": "^1.1.0",
87
- "string-argv": "^0.3.2",
88
88
  "undici": "^7.3.0",
89
89
  "yargs-parser": "^21.1.1",
90
- "youtubei.js": "^13.3.0"
90
+ "youtubei.js": "^13.4.0"
91
91
  },
92
92
  "keywords": [
93
93
  "patreon",