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 +5 -0
- package/bin/patreon-dl-vimeo.js +14 -4
- package/dist/downloaders/task/ExternalDownloaderTask.js +2 -2
- package/dist/downloaders/task/ExternalDownloaderTask.js.map +1 -1
- package/dist/downloaders/task/FFmpegDownloadTaskBase.js +6 -6
- package/dist/downloaders/task/FFmpegDownloadTaskBase.js.map +1 -1
- package/dist/downloaders/task/FetcherDownloadTask.d.ts.map +1 -1
- package/dist/downloaders/task/FetcherDownloadTask.js +3 -5
- package/dist/downloaders/task/FetcherDownloadTask.js.map +1 -1
- package/dist/downloaders/task/M3U8DownloadTask.d.ts.map +1 -1
- package/dist/downloaders/task/M3U8DownloadTask.js +7 -1
- package/dist/downloaders/task/M3U8DownloadTask.js.map +1 -1
- package/dist/utils/Fetcher.d.ts +2 -0
- package/dist/utils/Fetcher.d.ts.map +1 -1
- package/dist/utils/Fetcher.js +9 -4
- package/dist/utils/Fetcher.js.map +1 -1
- package/dist/utils/URLHelper.d.ts +1 -0
- package/dist/utils/URLHelper.d.ts.map +1 -1
- package/dist/utils/URLHelper.js +1 -1
- package/dist/utils/URLHelper.js.map +1 -1
- package/package.json +4 -4
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))
|
package/bin/patreon-dl-vimeo.js
CHANGED
|
@@ -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
|
|
20
|
-
* played within the Patreon post, and furthermore 'embed.url' sometimes returns
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
|
203
|
-
if (
|
|
204
|
-
const whitelistEntries = _options[
|
|
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[
|
|
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
|
-
|
|
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":";;;;;;;;;;;;AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,MAA8B,MAAM,eAAe,CAAC;AAC3D,OAAO,YAAgE,MAAM,mBAAmB,CAAC;AAGjG,OAAO,QAAQ,MAAM,yBAAyB,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AA0BxD,MAA8B,sBAA+C,SAAQ,YAAe;IAWlG,YAAY,MAAuC;QACjD,KAAK,CAAC,MAAM,CAAC,CAAC;;QARhB,2DAAoC;QACpC,wDAAqC;QACrC,sDAA4B;QAE5B,0DAAyC;QACzC,2DAAuC;QAIrC,uBAAA,IAAI,4CAAqB,MAAM,CAAC,gBAAgB,MAAA,CAAC;QACjD,uBAAA,IAAI,uCAAgB,IAAI,MAAA,CAAC;QAEzB,uBAAA,IAAI,2CAAoB,IAAI,MAAA,CAAC;QAC7B,uBAAA,IAAI,4CAAqB,IAAI,MAAA,CAAC;IAChC,CAAC;IAKS,OAAO;QACf,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACnC,KAAK,CAAC,KAAK,IAAI,EAAE;gBACf,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;oBAC9B,OAAO,EAAE,CAAC;oBACV,OAAO;gBACT,CAAC;gBAED,IAAI,WAAW,GAAkB,IAAI,CAAC;gBACtC,MAAM,SAAS,GAAG,GAAG,EAAE;oBACrB,IAAI,WAAW,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;wBAC/D,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,WAAW,EAAE,CAAC,CAAC;wBAC7C,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;oBACpC,CAAC;gBACH,CAAC,CAAC;gBAEF,IAAI,CAAC;oBACH,uBAAA,IAAI,2CAAoB,IAAI,eAAe,EAAE,MAAA,CAAC;oBAE9C,MAAM,mBAAmB,GAAG,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;oBAEhE,MAAM,YAAY,GAAG,mBAAmB,CAAC,MAAM,CAAC;oBAChD,IAAI,CAAC,gBAAgB,GAAG,YAAY,CAAC;oBAErC,IAAI,sBAAsB,GAAkB,IAAI,CAAC;oBACjD,IAAI,uBAAA,IAAI,gDAAkB,KAAK,YAAY,IAAI,uBAAA,IAAI,gDAAkB,KAAK,mBAAmB,EAAE,CAAC;wBAC9F,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,2BAA2B,CAAC,YAAY,CAAC,CAAC;wBACxF,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;wBACjC,sBAAsB,GAAG,SAAS,CAAC;oBACrC,CAAC;yBACI,IAAI,uBAAA,IAAI,gDAAkB,KAAK,MAAM,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;wBAC1E,IAAI,CAAC,UAAU,CAAC;4BACd,IAAI,EAAE,gBAAgB;4BACtB,OAAO,EAAE,4BAA4B,YAAY,GAAG;4BACpD,oBAAoB,EAAE,YAAY;yBACnC,CAAC,CAAC;wBACH,OAAO,EAAE,CAAC;wBACV,OAAO;oBACT,CAAC;oBAED,MAAM,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC;oBAC5C,MAAM,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC,iBAAiB,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;oBAEhG,IAAI,QAAQ,GAAG,KAAK,CAAC;oBAErB,uBAAA,IAAI,yCAAkB,uBAAA,IAAI,yFAAwB,MAA5B,IAAI,EAAyB,YAAY,EAAE,mBAAmB,CAAC,MAAA,CAAC;oBAEtF,uBAAA,IAAI,6CAAe,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,WAAmB,EAAE,EAAE;wBACtD,uBAAA,IAAI,uCAAgB,WAAW,MAAA,CAAC;wBAChC,IAAI,CAAC,WAAW,EAAE,CAAC;oBACrB,CAAC,CAAC,CAAC;oBAEH,uBAAA,IAAI,6CAAe,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,QAAwB,EAAE,EAAE;wBAC9D,IAAI,CAAC,cAAc,CAAC,uBAAA,IAAI,wFAAuB,MAA3B,IAAI,EAAwB,QAAQ,CAAC,CAAC,CAAC;oBAC7D,CAAC,CAAC,CAAC;oBAEH,uBAAA,IAAI,6CAAe,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;wBACjC,KAAK,CAAC,KAAK,IAAI,EAAE;4BACf,IAAI,CAAC,QAAQ,EAAE,CAAC;gCACd,IAAI,iBAAiB,GAAG,IAAI,CAAC;gCAC7B,IAAI,uBAAA,IAAI,gDAAkB,KAAK,mBAAmB,IAAI,sBAAsB,IAAI,EAAE,CAAC,UAAU,CAAC,sBAAsB,CAAC,EAAE,CAAC;oCACtH,mEAAmE;oCACnE,MAAM,UAAU,GAAG,gCAAgC,YAAY,WAAW,sBAAsB,GAAG,CAAC;oCACpG,iBAAiB,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,YAAY,EAAE,sBAAsB,CAAC,CAAC,CAAC;oCAC9F,IAAI,CAAC,iBAAiB,EAAE,CAAC;wCACvB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,UAAU,eAAe,CAAC,CAAC;wCAChD,IAAI,CAAC,UAAU,CAAC;4CACd,IAAI,EAAE,gBAAgB;4CACtB,OAAO,EAAE,8CAA8C,sBAAsB,GAAG;4CAChF,oBAAoB,EAAE,sBAAsB;yCAC7C,CAAC,CAAC;oCACL,CAAC;yCACI,CAAC;wCACJ,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,UAAU,sBAAsB,CAAC,CAAC;oCACzD,CAAC;gCACH,CAAC;gCACD,IAAI,iBAAiB,EAAE,CAAC;oCACtB,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;oCAC/F,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,YAAY,SAAS,aAAa,GAAG,WAAW,EAAE,CAAC,CAAC;oCACjF,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;oCAClD,IAAI,CAAC,cAAc,EAAE,CAAC;gCACxB,CAAC;gCACD,SAAS,EAAE,CAAC;gCACZ,OAAO,EAAE,CAAC;4BACZ,CAAC;wBACH,CAAC,CAAC,EAAE,CAAC;oBACP,CAAC,CAAC,CAAC;oBAEH,uBAAA,IAAI,6CAAe,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAU,EAAE,EAAE;wBAC7C,IAAI,uBAAA,IAAI,gDAAkB,EAAE,CAAC;4BAC3B,uBAAA,IAAI,gDAAkB,MAAtB,IAAI,CAAoB,CAAC;wBAC3B,CAAC;6BACI,CAAC;4BACJ,QAAQ,GAAG,IAAI,CAAC;4BAChB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;wBAC1B,CAAC;wBACD,SAAS,EAAE,CAAC;wBACZ,OAAO,EAAE,CAAC;oBACZ,CAAC,CAAC,CAAC;oBAEH,uBAAA,IAAI,+CAAiB,CAAC,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;wBAC1C,IAAI,uBAAA,IAAI,6CAAe,EAAE,CAAC;4BACxB,uBAAA,IAAI,6CAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;wBACtC,CAAC;6BACI,IAAI,uBAAA,IAAI,gDAAkB,EAAE,CAAC;4BAChC,uBAAA,IAAI,gDAAkB,MAAtB,IAAI,CAAoB,CAAC;4BACzB,SAAS,EAAE,CAAC;4BACZ,OAAO,EAAE,CAAC;wBACZ,CAAC;oBACH,CAAC,CAAC;oBAEF,uBAAA,IAAI,6CAAe,CAAC,GAAG,EAAE,CAAC;gBAC5B,CAAC;gBACD,OAAO,KAAU,EAAE,CAAC;oBAClB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;oBACxB,SAAS,EAAE,CAAC;oBACZ,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;QACP,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,IAAI,uBAAA,IAAI,6CAAe,EAAE,CAAC;gBACxB,uBAAA,IAAI,6CAAe,CAAC,kBAAkB,EAAE,CAAC;gBACzC,uBAAA,IAAI,yCAAkB,IAAI,MAAA,CAAC;YAC7B,CAAC;YACD,uBAAA,IAAI,2CAAoB,IAAI,MAAA,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IA4ES,KAAK,CAAC,OAAO;QACrB,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACnC,IAAI,uBAAA,IAAI,+CAAiB,EAAE,CAAC;gBAC1B,uBAAA,IAAI,4CAAqB,GAAG,EAAE;oBAC5B,uBAAA,IAAI,4CAAqB,IAAI,MAAA,CAAC;oBAC9B,IAAI,CAAC,WAAW,EAAE,CAAC;oBACnB,OAAO,EAAE,CAAC;gBACZ,CAAC,MAAA,CAAC;gBACF,uBAAA,IAAI,+CAAiB,CAAC,KAAK,EAAE,CAAC;YAChC,CAAC;iBACI,CAAC;gBACJ,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAES,KAAK,CAAC,SAAS;QACvB,uBAAA,IAAI,uCAAgB,IAAI,MAAA,CAAC;QACzB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAES,aAAa;QACrB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,WAAW;QACb,OAAO,uBAAA,IAAI,2CAAa,CAAC;IAC3B,CAAC;CAsDF;qbA3JyB,WAAmB,EAAE,MAA2B;IACtE,MAAM,iBAAiB,GAAG,CAAC,OAA6B,EAAE,GAAW,EAAE,EAAE;QACvE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;IAC7D,CAAC,CAAC;IAEF,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,MAAM,CAAC;IAE1D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC;IAEzB,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,MAAM,cAAc,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvE,IAAI,cAAc,EAAE,CAAC;QACnB,kCAAkC;QAClC,IAAI,cAAc,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;YACvC,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC;QACrC,CAAC;aACI,CAAC;YACJ,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,cAAc,CAAC,QAAQ,CAAC,WAAW,EAAE,kDAAkD,CAAC,CAAA;QAC9G,CAAC;IACH,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,EAAC,KAAK,EAAE,OAAO,EAAC,EAAE,KAAK,EAAE,EAAE;QACzC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;QACD,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,cAAc,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC,GAAG,CAAC,CAAC;YAC9F,IAAI,cAAc,GAAG,CAAC,IAAI,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBACnD,MAAM,gBAAgB,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;gBACjG,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC5C,QAAQ,CAAC,cAAc,CAAC,IAAI,YAAY,CAAC;gBAC3C,CAAC;YACH,CAAC;iBACI,CAAC;gBACJ,QAAQ,CAAC,IAAI,CAAC,qBAAqB,EAAE,8BAA8B,CAAC,CAAC;YACvE,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,YAAY,CAAC,GAAG,QAAQ,CAAC,CAAA;QACnC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iBAAiB,CAAC,aAAa,EAAE,IAAI,CAAC,EAAE,CAAC;QAC5C,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,CAAC,iBAAiB,CAAC,aAAa,EAAE,IAAI,CAAC,EAAE,CAAC;QAC5C,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;IACD,aAAa,EAAE,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IAE3D,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC;QAClE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,+BAA+B,MAAM,GAAG,CAAC,CAAC;QAC5D,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;SACI,CAAC;QACJ,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,sBAAsB,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAEnE,OAAO,OAAO,CAAC;AACjB,CAAC,yGA+BsB,QAAwB;IAC7C,IAAI,IAAI,CAAC,oBAAoB,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvD,MAAM,cAAc,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAChD,MAAM,UAAU,GAAG,uBAAA,IAAI,oFAAmB,MAAvB,IAAI,EAAoB,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC9D,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,oBAAoB;YACvC,YAAY,EAAE,IAAI,CAAC,gBAAgB;YACnC,UAAU,EAAE,QAAQ;YACpB,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;YAC/E,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAC/C,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,UAAU,GAAG,cAAc,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;YACrG,cAAc,EAAE,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACtD,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;SAC/C,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,iGAUkB,QAAgB;IACjC,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/D,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;IAED,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAElC,cAAc;IACd,IAAI,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;IAE/B,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,cAAc;QACd,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;IACnC,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,YAAY;QACZ,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;IACrC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;eAlT2B,sBAAsB","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;
|
|
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
|
-
|
|
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;
|
|
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: [
|
|
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,
|
|
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"]}
|
package/dist/utils/Fetcher.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/utils/Fetcher.js
CHANGED
|
@@ -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":";;;;;;;;;;;;AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAiB,MAAM,QAAQ,CAAC;AACvD,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,sBAAsB,MAAM,6BAA6B,CAAC;AAGjE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,OAAO,QAAQ,MAAM,eAAe,CAAC;AAErC,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAe1C,MAAM,OAAO,YAAa,SAAQ,KAAK;IAKrC,YAAY,OAAe,EAAE,GAAW,EAAE,MAAc;QACtD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAQD,MAAM,UAAU,GAAG,+HAA+H,CAAC;AAEnJ,MAAqB,OAAO;IAU1B,YAAY,MAA6B,EAAE,MAAsB;;QARjE,SAAI,GAAG,SAAS,CAAC;QAEjB,kCAAiB;QACjB,kCAAwB;QACxB,kCAAiB;QACjB,oCAAoB;QACpB,sCAAyB;QAGvB,uBAAA,IAAI,mBAAW,MAAM,CAAC,MAAM,MAAA,CAAC;QAC7B,uBAAA,IAAI,mBAAW,MAAM,MAAA,CAAC;QACtB,uBAAA,IAAI,mBAAW,MAAM,CAAC,MAAM,MAAA,CAAC;QAC7B,uBAAA,IAAI,qBAAa,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAA,CAAC;QAC9C,uBAAA,IAAI,uBAAe,gBAAgB,CAAC,MAAM,CAAC,EAAE,KAAK,IAAI,SAAS,MAAA,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,GAAG,CAA2B,IAMnC,EAAE,EAAE,GAAG,CAAC;QAEP,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAExD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,MAAM,CAAE,CAAC,EAAE,CAAC,CAAE,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/C,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACvD,uBAAA,IAAI,+CAAY,MAAhB,IAAI,EAAa,OAAO,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,uBAAuB,GAAG,IAAI,eAAe,EAAE,CAAC;QACtD,IAAI,kBAAkB,GAA6B,SAAS,CAAC;QAC7D,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,uBAAuB,CAAC,KAAK,EAAE,CAAC;YAC3D,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;YAC7D,kBAAkB,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC/E,CAAC;QACD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,uBAAuB,CAAC,MAAM,EAAE,UAAU,EAAE,uBAAA,IAAI,2BAAY,EAAE,CAAC,CAAC;YAC3G,OAAO,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAA0B,CAAC;QACpF,CAAC;QACD,OAAO,KAAU,EAAE,CAAC;YAClB,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACpB,MAAM,KAAK,CAAC;YACd,CAAC;YACD,IAAI,EAAE,GAAG,UAAU,EAAE,CAAC;gBACpB,IAAI,kBAAkB;oBAAE,kBAAkB,EAAE,CAAC;gBAC7C,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,CAAC;YAC5E,CAAC;YACD,IAAI,MAAM,CAAC;YACX,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,MAAM,WAAW,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBACpC,IAAI,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC;gBACvB,OAAO,IAAI,EAAE,CAAC;oBACZ,WAAW,CAAC,IAAI,CAAC,IAAI,YAAY,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;oBAC9E,IAAI,GAAG,IAAI,YAAY,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;gBACnD,CAAC;gBACD,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC;iBACI,CAAC;gBACJ,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YACzB,CAAC;YACD,MAAM,UAAU,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,MAAM,IAAI,YAAY,CAAC,GAAG,MAAM,GAAG,UAAU,EAAE,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QACtF,CAAC;gBACO,CAAC;YACP,IAAI,kBAAkB;gBAAE,kBAAkB,EAAE,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAyB,MAMjD;QACC,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,oBAAoB,EAAE,UAAU,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;QAClF,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACrD,uBAAA,IAAI,+CAAY,MAAhB,IAAI,EAAa,OAAO,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QACpF,MAAM,uBAAuB,GAAG,IAAI,eAAe,EAAE,CAAC;QACtD,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,uBAAuB,CAAC,KAAK,EAAE,CAAC;QAC3D,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;QAC/D,CAAC;QAED,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,uBAAuB,CAAC,MAAM,EAAE,UAAU,EAAE,uBAAA,IAAI,2BAAY,EAAE,CAAC,CAAC;YAE3G,IAAI,uBAAA,IAAI,qDAAkB,MAAtB,IAAI,EAAmB,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;gBAC5D,MAAM,YAAY,GAAG,oBAAoB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBACvD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;gBACzD,OAAO,YAAY,CAAC;YACtB,CAAC;QACH,CAAC;gBACO,CAAC;YACP,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAED,OAAO,SAAkB,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,eAAe,CAAyB,MAAgC;QAC5E,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;QAC5E,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACpD,uBAAA,IAAI,+CAAY,MAAhB,IAAI,EAAa,OAAO,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QACpF,MAAM,uBAAuB,GAAG,IAAI,eAAe,EAAE,CAAC;QACtD,IAAI,kBAAkB,GAA6B,SAAS,CAAC;QAC7D,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,uBAAuB,CAAC,KAAK,EAAE,CAAC;YAC3D,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;YAC7D,kBAAkB,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC/E,CAAC;QAED,IAAI,CAAC;YACH,IAAI,GAAG,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,uBAAuB,CAAC,MAAM,EAAE,UAAU,EAAE,uBAAA,IAAI,2BAAY,EAAE,CAAC,CAAC;YAEzG,kCAAkC;YAClC,IAAI,MAAM,CAAC,SAAS,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;gBACnF,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC5D,uBAAA,IAAI,+CAAY,MAAhB,IAAI,EAAa,WAAW,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC5E,GAAG,GAAG,MAAM,KAAK,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,uBAAuB,CAAC,MAAM,EAAE,UAAU,EAAE,uBAAA,IAAI,2BAAY,EAAE,CAAC,CAAC;YAC3G,CAAC;YAED,IAAI,uBAAA,IAAI,qDAAkB,MAAtB,IAAI,EAAmB,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBACrD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC;gBACnD,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,GAAG,EAAE;oBACjC,cAAc,EAAE,GAAG;iBACpB,CAAC,CAAC;gBACH,MAAM,OAAO,GAAG,IAAI,sBAAsB,CAAC,QAAQ,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC;gBAEjF,MAAM,IAAI,GAAG,GAAG,CAAC;gBACjB,MAAM,KAAK,GAAG,CAAC,SAAkC,EAAE,EAAE;oBACnD,MAAM,aAAa,GAAG,SAAS,EAAE,YAAY,IAAI,YAAY,CAAC;oBAC9D,MAAM,YAAY,GAAG,SAAS,EAAE,WAAW,IAAI,QAAQ,CAAC,iBAAiB,CAAC,aAAa,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;oBACvG,OAAO,uBAAA,IAAI,kDAAe,MAAnB,IAAI,EAAgB,IAAI,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAA;gBAC7F,CAAC,CAAC;gBACF,MAAM,KAAK,GAAG,GAAG,EAAE;oBACjB,IAAI,kBAAkB;wBAAE,kBAAkB,EAAE,CAAC;oBAC7C,uBAAuB,CAAC,KAAK,EAAE,CAAC;gBAClC,CAAC,CAAC;gBAEF,OAAO;oBACL,OAAO;oBACP,KAAK;oBACL,KAAK;iBACN,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,KAAc,EAAE,CAAC;YACtB,IAAI,kBAAkB;gBAAE,kBAAkB,EAAE,CAAC;YAC7C,MAAM,KAAK,CAAC;QACd,CAAC;QAED,OAAO,SAAkB,CAAC;IAC5B,CAAC;IAiHS,GAAG,CAAC,KAAe,EAAE,GAAG,GAAe;QAC/C,SAAS,CAAC,uBAAA,IAAI,uBAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,CAAC;IACpD,CAAC;CACF;wOAlHC,KAAK,iCACH,QAAoD,EACpD,WAAmB,EACnB,YAAoB,EACpB,QAAkB,EAClB,OAAoB;IAEpB,IAAI,CAAC;QACH,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,IAAI,uBAAA,IAAI,uBAAQ,EAAE,CAAC;YACjB,IAAI,CAAC;gBACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;oBACxC,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;gBACvB,CAAC;YACH,CAAC;YACD,OAAO,MAAe,EAAE,CAAC;gBACvB,aAAa;YACf,CAAC;QACH,CAAC;aACI,CAAC;YACJ,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,QAAQ,CAAC,GAAG,SAAS,WAAW,GAAG,CAAC,CAAC;YAChE,MAAM,QAAQ,CACZ,QAAQ,CAAC,IAAI,EACb,QAAQ,CAAC,MAAM,EACf,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAClC,CAAC;YACF,IAAI,GAAG,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC;QACxC,CAAC;QAED,MAAM,MAAM,GAAG,GAAG,EAAE;YAClB,uBAAA,IAAI,mDAAgB,MAApB,IAAI,EAAiB,WAAW,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACjE,CAAC,CAAC;QAEF,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,uBAAA,IAAI,oDAAiB,MAArB,IAAI,EAAkB,WAAW,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC,CAAC;QAEF,OAAO;YACL,WAAW;YACX,MAAM;YACN,OAAO;SACR,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,EAAE,CAAC;QACb,uBAAA,IAAI,oDAAiB,MAArB,IAAI,EAAkB,WAAW,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC,6DAEe,WAAmB,EAAE,YAAoB,EAAE,IAAY,EAAE,OAAoB;IAC3F,IAAI,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,WAAW,SAAS,YAAY,eAAe,IAAI,QAAQ,CAAC,CAAC;QAC1F,uBAAA,IAAI,yBAAU,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACnD,CAAC;YACO,CAAC;QACP,uBAAA,IAAI,oDAAiB,MAArB,IAAI,EAAkB,WAAW,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC,+DAEgB,WAAmB,EAAE,KAAkB;IACtD,IAAI,CAAC;QACH,IAAI,uBAAA,IAAI,uBAAQ,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/C,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,WAAW,GAAG,CAAC,CAAC;YAC/C,uBAAA,IAAI,yBAAU,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,sBAAsB,WAAW,GAAG,EAAE,KAAK,CAAC,CAAC;IACjE,CAAC;YACO,CAAC;QACP,IAAI,KAAK;YAAE,KAAK,EAAE,CAAC;IACrB,CAAC;AACH,CAAC,qDAEW,OAAgB,EAAE,IAAqB,EAAE,IAAwE;IAC3H,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;IACxD,IAAI,uBAAA,IAAI,uBAAQ,IAAI,SAAS,EAAE,CAAC;QAC9B,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,uBAAA,IAAI,uBAAQ,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAC9C,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,0BAA0B,CAAC,CAAC;IAClE,CAAC;SACI,CAAC;QACJ,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,uFAAuF,CAAC,CAAC;IACzH,CAAC;AACH,CAAC,iEAIiB,QAAyB,EAAE,SAAiB,EAAE,MAAc,EAAE,WAAW,GAAG,IAAI;IAChG,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,YAAY,CAAC,aAAa,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,YAAY,CAAC,GAAG,QAAQ,CAAC,MAAM,MAAM,QAAQ,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAC3F,CAAC;IACD,IAAI,WAAW,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClC,MAAM,IAAI,YAAY,CAAC,qBAAqB,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;eAlRkB,OAAO","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 +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;
|
|
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"}
|
package/dist/utils/URLHelper.js
CHANGED
|
@@ -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":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAG1B,MAAM,QAAQ,GAAG,yBAAyB,CAAC;AAC3C,MAAM,cAAc,GAAG,GAAG,QAAQ,aAAa,CAAC;AAChD,MAAM,eAAe,GAAG,GAAG,QAAQ,cAAc,CAAC;AAClD,MAAM,aAAa,GAAG,GAAG,QAAQ,YAAY,CAAC;AAC9C,MAAM,YAAY,GAAG,GAAG,QAAQ,WAAW,CAAC;AAC5C,MAAM,gBAAgB,GAAG,GAAG,QAAQ,gBAAgB,CAAC;AACrD,MAAM,qBAAqB,GAAG,GAAG,QAAQ,gCAAgC,CAAA;AACzE,MAAM,4BAA4B,GAAG,GAAG,QAAQ,qCAAqC,CAAA;AAErF,MAAM,iBAAiB,GAAG,+DAA+D,CAAC;AAC1F,MAAM,uBAAuB,GAAG,+CAA+C,CAAC;AAChF,MAAM,yBAAyB,GAAG,yDAAyD,CAAC;AAC5F,MAAM,oBAAoB,GAAG,iDAAiD,CAAC;AAC/E,MAAM,cAAc,GAAG,sDAAsD,CAAC;AAC9E,MAAM,gBAAgB,GAAG,4CAA4C,CAAC,CAAC,UAAU;AAEjF,MAAM,6BAA6B,GAAG;IACpC,eAAe,EAAE;QACf,MAAM;QACN,IAAI;QACJ,aAAa;QACb,aAAa;QACb,WAAW;QACX,uBAAuB;QACvB,KAAK;QACL,WAAW;QACX,iBAAiB;QACjB,YAAY;QACZ,mBAAmB;KACpB;IACD,OAAO,EAAE;QACP,eAAe;QACf,eAAe;QACf,sCAAsC;QACtC,UAAU;QACV,4BAA4B;KAC7B;CACF,CAAC;AAEF,MAAM,2BAA2B,GAAG;IAClC,OAAO,EAAE;QACP,UAAU;QACV,cAAc;QACd,wBAAwB;QACxB,mBAAmB;QACnB,OAAO;QACP,oBAAoB;QACpB,QAAQ;QACR,OAAO;QACP,uBAAuB;QACvB,cAAc;QACd,kCAAkC;QAClC,oCAAoC;QACpC,kCAAkC;QAClC,MAAM;QACN,mBAAmB;QACnB,WAAW;KACZ;CACF,CAAC;AAEF,MAAM,mCAAmC,GAAG;IAC1C,OAAO,EAAE;QACP,QAAQ;QACR,MAAM;QACN,4BAA4B;QAC5B,yBAAyB;QACzB,qCAAqC;QACrC,oBAAoB;QACpB,kBAAkB;QAClB,wCAAwC;KACzC;IACD,MAAM,EAAE;QACN,OAAO,EAAE;YACP,MAAM;YACN,SAAS;YACT,YAAY;YACZ,cAAc;YACd,eAAe;YACf,qBAAqB;YACrB,UAAU;YACV,mBAAmB;YACnB,aAAa;YACb,kBAAkB;SACnB;QACD,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE;YACJ,eAAe;YACf,0BAA0B;YAC1B,KAAK;SACN;QACD,QAAQ,EAAE;YACR,UAAU;YACV,OAAO;SACR;QACD,IAAI,EAAE;YACJ,WAAW;YACX,WAAW;YACX,KAAK;SACN;KACF;IACD,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,UAAU;CACjB,CAAC;AAEF,MAAM,0CAA0C,GAAG;IACjD,OAAO,EAAE;QACP,oBAAoB;QACpB,QAAQ;QACR,MAAM;QACN,uBAAuB;KACxB;IACD,MAAM,EAAE;QACN,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE;YACP,MAAM;YACN,SAAS;YACT,YAAY;YACZ,cAAc;YACd,eAAe;YACf,qBAAqB;YACrB,UAAU;YACV,mBAAmB;YACnB,kBAAkB;SACnB;QACD,IAAI,EAAE;YACJ,eAAe;SAChB;QACD,IAAI,EAAE;YACJ,WAAW;YACX,WAAW;YACX,KAAK;SACN;KACF;IACD,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,SAAS;CAChB,CAAA;AAED,MAAM,CAAN,IAAY,aAIX;AAJD,WAAY,aAAa;IACvB,iDAAgC,CAAA;IAChC,gDAA+B,CAAA;IAC/B,qDAAoC,CAAA;AACtC,CAAC,EAJW,aAAa,KAAb,aAAa,QAIxB;AAwBD,MAAM,CAAC,OAAO,OAAO,SAAS;IAE5B,MAAM,CAAC,sBAAsB,CAAC,SAAiB;QAC7C,MAAM,GAAG,GAAG,GAAG,eAAe,IAAI,SAAS,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,yBAAyB,EAAE,6BAA6B,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5G,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,6BAA6B,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACpF,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;QAEnD,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,wBAAwB,CAAC,IAAyB;QACvD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,GAAG,QAAQ,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QACtC,CAAC;QAED,OAAO,GAAG,QAAQ,WAAW,IAAI,CAAC,MAAM,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,qBAAqB,CAAC,IAAyB;QACpD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,GAAG,QAAQ,IAAI,IAAI,CAAC,MAAM,QAAQ,CAAC;QAC5C,CAAC;QAED,OAAO,GAAG,QAAQ,iBAAiB,IAAI,CAAC,MAAM,EAAE,CAAC;IACnD,CAAC;IAED,MAAM,CAAC,sBAAsB,CAAC,YAAoB;QAChD,OAAO,GAAG,cAAc,IAAI,YAAY,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,mBAAmB,CAAC,MAAc;QACvC,OAAO,GAAG,YAAY,IAAI,MAAM,EAAE,CAAC;IACrC,CAAC;IAED,MAAM,CAAC,uBAAuB,CAAC,UAAkB;QAC/C,OAAO,GAAG,gBAAgB,IAAI,UAAU,EAAE,CAAC;IAC7C,CAAC;IAED,MAAM,CAAC,oBAAoB,CAAC,MAM3B;QACC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YACzC,MAAM,KAAK,CAAC,8DAA8D,CAAC,CAAC;QAC9E,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;QACrG,MAAM,cAAc,GAAwB;YAC1C,0BAA0B,EAAE,IAAI;YAChC,UAAU,EAAE,KAAK;SAClB,CAAC;QACF,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,cAAc,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC;QACpD,CAAC;QACD,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YACzB,cAAc,CAAC,uBAAuB,CAAC,GAAG,MAAM,CAAC,aAAa,CAAC;QACjE,CAAC;QACD,MAAM,UAAU,GAAG;YACjB,GAAG,cAAc;YACjB,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE;SACxB,CAAC;QACF,MAAM,YAAY,GAAwB;YACxC,SAAS,EAAE,2BAA2B,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;YACxD,MAAM,EAAE,MAAM,CAAC,IAAI,IAAI,aAAa,CAAC,cAAc;YACnD,kBAAkB,EAAE,KAAK;SAC1B,CAAC;QACF,KAAK,MAAM,CAAE,GAAG,EAAE,KAAK,CAAE,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YACxD,YAAY,CAAC,UAAU,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC;QACzC,CAAC;QACD,KAAK,MAAM,CAAE,GAAG,EAAE,KAAK,CAAE,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YAC1D,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,2BAA2B,CAAC,MAQlC;QACC,IAAI,MAAW,CAAC;QAChB,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,GAAG,IAAI,GAAG,CAAC,4BAA4B,CAAC,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAC3F,CAAC;aACI,CAAC;YACJ,MAAM,GAAG,IAAI,GAAG,CAAC,qBAAqB,CAAC,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9E,CAAC;QACD,MAAM,MAAM,GAA2B,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,0CAA0C,CAAC,CAAC,CAAC,mCAAmC,CAAC;QACjH,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;YACnD,MAAM,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAA;QAC5D,CAAC;QACD,MAAM,YAAY,GAAwB;YACxC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;YACnC,GAAG,MAAM;YACT,aAAa,EAAE,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK;YAC3C,MAAM,EAAE,MAAM,CAAC,IAAI;YACnB,kBAAkB,EAAE,KAAK;YACzB,+BAA+B,EAAE,KAAK;SACvC,CAAC;QACF,KAAK,MAAM,CAAE,GAAG,EAAE,KAAK,CAAE,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YAC1D,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,GAAW;QAE3B,MAAM,IAAI,GAAG,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC;QAE/C,MAAM,4BAA4B,GAAG,CAAC,YAA6B,EAAE,EAAE;YACrE,MAAM,OAAO,GAAwB,EAAE,CAAC;YACxC,MAAM,WAAW,GAAG,mBAAmB,CAAC;YACxC,KAAK,MAAM,CAAE,GAAG,EAAE,KAAK,CAAE,IAAI,YAAY,EAAE,CAAC;gBAC1C,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACpC,IAAI,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;oBACtB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;gBAC5B,CAAC;gBACD,WAAW,CAAC,SAAS,GAAG,CAAC,CAAC;YAC5B,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC,CAAC;QAEF,MAAM,eAAe,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,IAAI,eAAe,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC;YAClC,MAAM,SAAS,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;YAChC,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,SAAS;gBACT,IAAI;aACL,CAAC;QACJ,CAAC;QAED,MAAM,wBAAwB,GAAG,CAAC,KAAa,EAAE,EAAE;YACjD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtB,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAA;QACD,MAAM,mBAAmB,GACvB,wBAAwB,CAAC,uBAAuB,CAAC;YACjD,wBAAwB,CAAC,yBAAyB,CAAC,CAAC;QACtD,IAAI,mBAAmB,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,mBAAmB,CAAC;YACnC,MAAM,OAAO,GAAG,4BAA4B,CAAC,YAAY,CAAC,CAAC;YAC3D,IAAI,MAA+D,CAAC;YACpE,8DAA8D;YAC9D,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC;YAC7C,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,EAAE,CAAC;gBAChC,MAAM,GAAG;oBACP,IAAI,EAAE,eAAe;oBACrB,MAAM;iBACP,CAAC;YACJ,CAAC;iBACI,CAAC;gBACJ,MAAM,GAAG;oBACP,IAAI,EAAE,aAAa;oBACnB,MAAM;iBACP,CAAC;YACJ,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;YAC3B,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,kBAAkB,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3D,IAAI,kBAAkB,IAAI,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,MAAM,YAAY,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,OAAO,GAAG,4BAA4B,CAAC,YAAY,CAAC,CAAC;YAC3D,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;gBAC9B,OAAO,CAAC,eAAe,CAAC,GAAG,YAAY,CAAC;YAC1C,CAAC;YACD,MAAM,MAAM,GAAgD;gBAC1D,IAAI,EAAE,mBAAmB;gBACzB,YAAY;aACb,CAAC;YACF,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;YAC3B,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,YAAY,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC/B,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC7B,OAAO;gBACL,IAAI,EAAE,MAAM;gBACZ,MAAM;gBACN,IAAI;aACL,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,aAAa,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;YAChC,OAAO;gBACL,IAAI,EAAE,MAAM;gBACZ,MAAM;aACP,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,wBAAwB,CAAC,GAAW;QACzC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,QAAQ,GAAG,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpD,OAAO,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,CAAC,mBAAmB,CAAC,GAAW;QACpC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,GAAQ;QACzB,IAAI,MAAM,CAAC;QACX,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,MAAe,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,CAAC,CAAC,MAAM,CAAC;IAClB,CAAC;CACF","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.
|
|
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
|
-
"
|
|
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.
|
|
90
|
+
"youtubei.js": "^13.4.0"
|
|
91
91
|
},
|
|
92
92
|
"keywords": [
|
|
93
93
|
"patreon",
|