patreon-dl 3.8.0 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -209
- package/dist/browse/db/CampaignDBMixin.d.ts +3 -3
- package/dist/browse/db/ContentDBMixin.d.ts +13 -13
- package/dist/browse/db/ContentDBMixin.js +1 -1
- package/dist/browse/db/ContentDBMixin.js.map +1 -1
- package/dist/browse/db/MediaDBMixin.js +1 -1
- package/dist/browse/db/MediaDBMixin.js.map +1 -1
- package/dist/browse/db/index.d.ts +16 -16
- package/dist/browse/server/handler/CampaignAPIRequesthandler.js +5 -0
- package/dist/browse/server/handler/CampaignAPIRequesthandler.js.map +1 -1
- package/dist/browse/web/assets/index-CtjPL2rI.js +218 -0
- package/dist/browse/web/index.html +1 -1
- package/dist/cli/CLIOptions.js +6 -2
- package/dist/cli/CLIOptions.js.map +1 -1
- package/dist/cli/ConfigFileParser.js +1 -1
- package/dist/cli/ConfigFileParser.js.map +1 -1
- package/dist/downloaders/Downloader.js +1 -1
- package/dist/downloaders/Downloader.js.map +1 -1
- package/dist/downloaders/PostDownloader.js +5 -5
- package/dist/downloaders/PostDownloader.js.map +1 -1
- package/dist/downloaders/PostsFetcher.js +3 -3
- package/dist/downloaders/PostsFetcher.js.map +1 -1
- package/dist/downloaders/task/DownloadTask.js +11 -1
- package/dist/downloaders/task/DownloadTask.js.map +1 -1
- package/dist/entities/MediaItem.d.ts +1 -0
- package/dist/entities/MediaItem.js.map +1 -1
- package/dist/parsers/PageParser.js +4 -1
- package/dist/parsers/PageParser.js.map +1 -1
- package/dist/parsers/PostParser.d.ts +4 -1
- package/dist/parsers/PostParser.js +82 -5
- package/dist/parsers/PostParser.js.map +1 -1
- package/dist/utils/Fetcher.d.ts +1 -0
- package/dist/utils/Fetcher.js +5 -0
- package/dist/utils/Fetcher.js.map +1 -1
- package/dist/utils/FilenameFormatHelper.d.ts +1 -1
- package/dist/utils/FilenameFormatHelper.js +4 -1
- package/dist/utils/FilenameFormatHelper.js.map +1 -1
- package/dist/utils/Formatter.d.ts +1 -1
- package/dist/utils/Formatter.js +1 -1
- package/dist/utils/Formatter.js.map +1 -1
- package/dist/utils/logging/FileLogger.js +1 -0
- package/dist/utils/logging/FileLogger.js.map +1 -1
- package/package.json +1 -1
- package/dist/browse/web/assets/index-CtZbx-Du.js +0 -218
|
@@ -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 puppeteer from 'puppeteer';\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' | 'm3u8' | 'json';\nexport type FetcherGetResultOf<T extends FetcherGetType> =\n T extends 'html' ? { html: string; lastUrl: string; }:\n T extends 'm3u8' ? { contents: string; lastUrl: string; }:\n T extends 'json' ? { json: any; lastUrl: string; } :\n never;\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 #userAgent: string;\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 this.#userAgent = config.request.userAgent;\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, type === 'm3u8' ? { setReferer: true } : {});\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 const lastUrl = res.url;\n switch (type) {\n case 'html':\n return {\n html: await res.text(),\n lastUrl\n } as FetcherGetResultOf<T>;\n case 'm3u8':\n return {\n contents: await res.text(),\n lastUrl\n } as FetcherGetResultOf<T>;\n case 'json':\n return {\n json: await res.json(),\n lastUrl\n } as FetcherGetResultOf<T>;\n default:\n return undefined as never;\n }\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 as number;\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: FetcherGetType, 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', this.#userAgent);\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 async getPageWithPuppeteer(url: string) {\n this.log('debug', `Fetch \"${url}\" with Puppeteer`);\n const browser = await puppeteer.launch({ headless: true });\n const page = await browser.newPage();\n await page.setUserAgent({ userAgent: this.#userAgent });\n await page.goto(url, { waitUntil: 'networkidle2' });\n const html = await page.evaluate(() => document.documentElement.innerHTML);\n await browser.close();\n return html;\n }\n\n protected log(level: LogLevel, ...msg: Array<any>) {\n commonLog(this.#logger, level, this.name, ...msg);\n }\n\n get proxyAgent() {\n return this.#proxyAgent;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Fetcher.js","sourceRoot":"","sources":["../../src/utils/Fetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport { pipeline } from 'stream/promises';\nimport { fetch, Request, type Response } from 'undici';\nimport path from 'path';\nimport { type Dispatcher } from 'undici';\nimport puppeteer from 'puppeteer';\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' | 'm3u8' | 'json';\nexport type FetcherGetResultOf<T extends FetcherGetType> =\n T extends 'html' ? { html: string; lastUrl: string; }:\n T extends 'm3u8' ? { contents: string; lastUrl: string; }:\n T extends 'json' ? { json: any; lastUrl: string; } :\n never;\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 #userAgent: string;\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 this.#userAgent = config.request.userAgent;\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, type === 'm3u8' ? { setReferer: true } : {});\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 const lastUrl = res.url;\n switch (type) {\n case 'html':\n return {\n html: await res.text(),\n lastUrl\n } as FetcherGetResultOf<T>;\n case 'm3u8':\n return {\n contents: await res.text(),\n lastUrl\n } as FetcherGetResultOf<T>;\n case 'json':\n return {\n json: await res.json(),\n lastUrl\n } as FetcherGetResultOf<T>;\n default:\n return undefined as never;\n }\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 as number;\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 async test(url: string) {\n const request = new Request(url, { method: 'HEAD' });\n const res = await fetch(request, { dispatcher: this.#proxyAgent });\n return res.ok;\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: FetcherGetType, 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', this.#userAgent);\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 async getPageWithPuppeteer(url: string) {\n this.log('debug', `Fetch \"${url}\" with Puppeteer`);\n const browser = await puppeteer.launch({ headless: true });\n const page = await browser.newPage();\n await page.setUserAgent({ userAgent: this.#userAgent });\n await page.goto(url, { waitUntil: 'networkidle2' });\n const html = await page.evaluate(() => document.documentElement.innerHTML);\n await browser.close();\n return html;\n }\n\n protected log(level: LogLevel, ...msg: Array<any>) {\n commonLog(this.#logger, level, this.name, ...msg);\n }\n\n get proxyAgent() {\n return this.#proxyAgent;\n }\n}\n"]}
|
|
@@ -7,7 +7,7 @@ type CampaignDirNameFormatFieldName = 'creator.vanity' | 'creator.name' | 'creat
|
|
|
7
7
|
export declare const CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA: FormatFieldRules<CampaignDirNameFormatFieldName>;
|
|
8
8
|
type ContentDirNameFormatFieldName = 'content.id' | 'content.type' | 'content.slug' | 'content.name' | 'content.publishDate';
|
|
9
9
|
export declare const CONTENT_DIR_NAME_VALIDATION_SCHEMA: FormatFieldRules<ContentDirNameFormatFieldName>;
|
|
10
|
-
type MediaFilenameFormatFieldName = 'media.id' | 'media.type' | 'media.filename' | 'media.variant' | 'src.id' | 'src.type' | 'src.title' | 'src.date';
|
|
10
|
+
type MediaFilenameFormatFieldName = 'media.id' | 'media.type' | 'media.index' | 'media.filename' | 'media.variant' | 'src.id' | 'src.type' | 'src.title' | 'src.date';
|
|
11
11
|
export declare const MEDIA_FILENAME_VALIDATION_SCHEMA: FormatFieldRules<MediaFilenameFormatFieldName>;
|
|
12
12
|
export default class FilenameFormatHelper {
|
|
13
13
|
#private;
|
|
@@ -113,7 +113,9 @@ class FilenameFormatHelper {
|
|
|
113
113
|
break;
|
|
114
114
|
}
|
|
115
115
|
try {
|
|
116
|
-
|
|
116
|
+
if (srcFields['src.date']) {
|
|
117
|
+
srcFields['src.date'] = dateFormat(new Date(srcFields['src.date']), 'yyyy-mm-dd_HH-MM');
|
|
118
|
+
}
|
|
117
119
|
}
|
|
118
120
|
catch (_) {
|
|
119
121
|
// Do nothing
|
|
@@ -121,6 +123,7 @@ class FilenameFormatHelper {
|
|
|
121
123
|
const dict = {
|
|
122
124
|
'media.id': media.id,
|
|
123
125
|
'media.type': media.type,
|
|
126
|
+
'media.index': media.index !== undefined ? String(media.index) : null,
|
|
124
127
|
'media.filename': media.filename,
|
|
125
128
|
'media.variant': media.variant,
|
|
126
129
|
...srcFields
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilenameFormatHelper.js","sourceRoot":"","sources":["../../src/utils/FilenameFormatHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import dateFormat from 'dateformat';\nimport { type Campaign } from '../entities/Campaign.js';\nimport { type MediaLike } from '../entities/MediaItem.js';\nimport { type Product } from '../entities/Product.js';\nimport Formatter, { type FormatFieldName, type FormatFieldRules, type FormatFieldValues } from './Formatter.js';\nimport URLHelper from './URLHelper.js';\nimport { type Collection, type Post } from '../entities/Post.js';\nimport { createSafeSlug, toISODate } from './Misc.js';\nimport FSHelper from './FSHelper.js';\n\ntype CampaignDirNameFormatFieldName =\n 'creator.vanity' |\n 'creator.name' |\n 'creator.id' |\n 'campaign.name' |\n 'campaign.id';\n\nexport const CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA: FormatFieldRules<CampaignDirNameFormatFieldName> = [\n { name: 'creator.vanity', atLeastOneOf: true },\n { name: 'creator.name', atLeastOneOf: true },\n { name: 'creator.id', atLeastOneOf: true },\n { name: 'campaign.name', atLeastOneOf: true },\n { name: 'campaign.id', atLeastOneOf: true }\n];\n\ntype ContentDirNameFormatFieldName =\n 'content.id' |\n 'content.type' |\n 'content.slug' |\n 'content.name' |\n 'content.publishDate';\n\nexport const CONTENT_DIR_NAME_VALIDATION_SCHEMA: FormatFieldRules<ContentDirNameFormatFieldName> = [\n { name: 'content.id', atLeastOneOf: true },\n { name: 'content.type', atLeastOneOf: false },\n { name: 'content.slug', atLeastOneOf: true },\n { name: 'content.name', atLeastOneOf: false },\n { name: 'content.publishDate', atLeastOneOf: false }\n];\n\ntype MediaFilenameFormatFieldName =\n 'media.id' |\n 'media.type' |\n 'media.filename' |\n 'media.variant' |\n 'src.id' |\n 'src.type' |\n 'src.title' |\n 'src.date';\n\nexport const MEDIA_FILENAME_VALIDATION_SCHEMA: FormatFieldRules<MediaFilenameFormatFieldName> = [\n { name: 'media.id', atLeastOneOf: true },\n { name: 'media.type', atLeastOneOf: false },\n { name: 'media.filename', atLeastOneOf: true },\n { name: 'media.variant', atLeastOneOf: false }\n];\n\nconst CAMPAIGN_DIR_NAME_FALLBACK_FORMAT = 'campaign-{campaign.id}';\nconst CONTENT_DIR_NAME_FALLBACK_FORMAT = '{content.type}-{content.id}';\nconst MEDIA_FILENAME_FALLBACK_FORMAT = '{media.type}-{media.id}';\n\nexport default class FilenameFormatHelper {\n\n static getCampaignDirName(campaign: Campaign, format: string): string {\n const dict: FormatFieldValues<CampaignDirNameFormatFieldName> = {\n 'creator.vanity': campaign.creator?.vanity,\n 'creator.name': campaign.creator?.fullName,\n 'creator.id': campaign.creator?.id,\n 'campaign.name': campaign.name,\n 'campaign.id': campaign.id\n };\n\n return this.#getFilename(format, dict, CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA, CAMPAIGN_DIR_NAME_FALLBACK_FORMAT);\n }\n\n static getContentDirName(content: Product | Post, format: string): string {\n const dict: FormatFieldValues<ContentDirNameFormatFieldName> = {\n 'content.id': content.id,\n 'content.type': content.type,\n 'content.slug': null,\n 'content.name': null,\n 'content.publishDate': content.publishedAt ? toISODate(content.publishedAt) : null\n };\n if (content.type === 'post') {\n const urlAnalysis = content.url ? URLHelper.analyzeURL(content.url) : null;\n dict['content.slug'] = urlAnalysis && urlAnalysis.type === 'post' ? urlAnalysis.slug : null;\n dict['content.name'] = content.title;\n }\n else if (content.type === 'product') {\n const urlAnalysis = URLHelper.analyzeURL(content.url);\n dict['content.slug'] = urlAnalysis && urlAnalysis.type === 'product' ? urlAnalysis.slug : null;\n dict['content.name'] = content.name;\n }\n\n return this.#getFilename(format, dict, CONTENT_DIR_NAME_VALIDATION_SCHEMA, CONTENT_DIR_NAME_FALLBACK_FORMAT);\n }\n\n static getCollectionDirName(collection: Collection, format: string): string {\n const slug = collection.title ?\n `${createSafeSlug(collection.title)}-${collection.id}`\n : `collection-${collection.id}`;\n const dict: FormatFieldValues<ContentDirNameFormatFieldName> = {\n 'content.id': collection.id,\n 'content.type': collection.type,\n 'content.slug': slug,\n 'content.name': collection.title,\n 'content.publishDate': collection.createdAt ? toISODate(collection.createdAt) : null\n };\n return this.#getFilename(format, dict, CONTENT_DIR_NAME_VALIDATION_SCHEMA, CONTENT_DIR_NAME_FALLBACK_FORMAT);\n }\n\n static getMediaFilename(\n media: MediaLike & { variant: string | null },\n src: Post | Product | Campaign | Collection,\n format: string,\n ext: string\n ): string {\n let srcFields: Pick<FormatFieldValues<MediaFilenameFormatFieldName>, 'src.id' | 'src.type' | 'src.title' | 'src.date'>;\n switch (src.type) {\n case 'post':\n srcFields = {\n 'src.id': src.id,\n 'src.type': src.type,\n 'src.date': src.publishedAt,\n 'src.title': src.title\n };\n break;\n case 'product':\n srcFields = {\n 'src.id': src.id,\n 'src.type': src.type,\n 'src.date': src.publishedAt,\n 'src.title': src.name\n };\n break;\n case 'campaign':\n srcFields = {\n 'src.id': src.id,\n 'src.type': src.type,\n 'src.date': src.createdAt,\n 'src.title': src.name\n };\n break;\n case 'collection':\n srcFields = {\n 'src.id': src.id,\n 'src.type': src.type,\n 'src.date': src.createdAt,\n 'src.title': src.title\n };\n break;\n }\n try {\n srcFields['src.date'] = dateFormat(new Date(srcFields['src.date']), 'yyyy-mm-dd_HH-MM');\n }\n catch (_) {\n // Do nothing\n }\n const dict: FormatFieldValues<MediaFilenameFormatFieldName> = {\n 'media.id': media.id,\n 'media.type': media.type,\n 'media.filename': media.filename,\n 'media.variant': media.variant,\n ...srcFields\n };\n\n return this.#getFilename(format, dict, MEDIA_FILENAME_VALIDATION_SCHEMA, MEDIA_FILENAME_FALLBACK_FORMAT, ext);\n }\n\n static #getFilename<T extends FormatFieldName>(\n format: string,\n dict: FormatFieldValues<T>,\n rules: FormatFieldRules<T>,\n fallbackFormat: string,\n ext?: string\n ) {\n const { validateOK, result } = Formatter.format(format, dict, rules);\n let base = result;\n\n if (validateOK === false) {\n base = Formatter.format(fallbackFormat, dict).result;\n }\n\n return FSHelper.createFilename({ name: base, ext });\n }\n\n static validateCampaignDirNameFormat(format: string) {\n return Formatter.validate(format, CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA);\n }\n\n static validateContentDirNameFormat(format: string) {\n return Formatter.validate(format, CONTENT_DIR_NAME_VALIDATION_SCHEMA);\n }\n\n static validateMediaFilenameFormat(format: string) {\n return Formatter.validate(format, MEDIA_FILENAME_VALIDATION_SCHEMA);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FilenameFormatHelper.js","sourceRoot":"","sources":["../../src/utils/FilenameFormatHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import dateFormat from 'dateformat';\nimport { type Campaign } from '../entities/Campaign.js';\nimport { type MediaLike } from '../entities/MediaItem.js';\nimport { type Product } from '../entities/Product.js';\nimport Formatter, { type FormatFieldName, type FormatFieldRules, type FormatFieldValues } from './Formatter.js';\nimport URLHelper from './URLHelper.js';\nimport { type Collection, type Post } from '../entities/Post.js';\nimport { createSafeSlug, toISODate } from './Misc.js';\nimport FSHelper from './FSHelper.js';\n\ntype CampaignDirNameFormatFieldName =\n 'creator.vanity' |\n 'creator.name' |\n 'creator.id' |\n 'campaign.name' |\n 'campaign.id';\n\nexport const CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA: FormatFieldRules<CampaignDirNameFormatFieldName> = [\n { name: 'creator.vanity', atLeastOneOf: true },\n { name: 'creator.name', atLeastOneOf: true },\n { name: 'creator.id', atLeastOneOf: true },\n { name: 'campaign.name', atLeastOneOf: true },\n { name: 'campaign.id', atLeastOneOf: true }\n];\n\ntype ContentDirNameFormatFieldName =\n 'content.id' |\n 'content.type' |\n 'content.slug' |\n 'content.name' |\n 'content.publishDate';\n\nexport const CONTENT_DIR_NAME_VALIDATION_SCHEMA: FormatFieldRules<ContentDirNameFormatFieldName> = [\n { name: 'content.id', atLeastOneOf: true },\n { name: 'content.type', atLeastOneOf: false },\n { name: 'content.slug', atLeastOneOf: true },\n { name: 'content.name', atLeastOneOf: false },\n { name: 'content.publishDate', atLeastOneOf: false }\n];\n\ntype MediaFilenameFormatFieldName =\n 'media.id' |\n 'media.type' |\n 'media.index' |\n 'media.filename' |\n 'media.variant' |\n 'src.id' |\n 'src.type' |\n 'src.title' |\n 'src.date';\n\nexport const MEDIA_FILENAME_VALIDATION_SCHEMA: FormatFieldRules<MediaFilenameFormatFieldName> = [\n { name: 'media.id', atLeastOneOf: true },\n { name: 'media.type', atLeastOneOf: false },\n { name: 'media.filename', atLeastOneOf: true },\n { name: 'media.variant', atLeastOneOf: false }\n];\n\nconst CAMPAIGN_DIR_NAME_FALLBACK_FORMAT = 'campaign-{campaign.id}';\nconst CONTENT_DIR_NAME_FALLBACK_FORMAT = '{content.type}-{content.id}';\nconst MEDIA_FILENAME_FALLBACK_FORMAT = '{media.type}-{media.id}';\n\nexport default class FilenameFormatHelper {\n\n static getCampaignDirName(campaign: Campaign, format: string): string {\n const dict: FormatFieldValues<CampaignDirNameFormatFieldName> = {\n 'creator.vanity': campaign.creator?.vanity,\n 'creator.name': campaign.creator?.fullName,\n 'creator.id': campaign.creator?.id,\n 'campaign.name': campaign.name,\n 'campaign.id': campaign.id\n };\n\n return this.#getFilename(format, dict, CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA, CAMPAIGN_DIR_NAME_FALLBACK_FORMAT);\n }\n\n static getContentDirName(content: Product | Post, format: string): string {\n const dict: FormatFieldValues<ContentDirNameFormatFieldName> = {\n 'content.id': content.id,\n 'content.type': content.type,\n 'content.slug': null,\n 'content.name': null,\n 'content.publishDate': content.publishedAt ? toISODate(content.publishedAt) : null\n };\n if (content.type === 'post') {\n const urlAnalysis = content.url ? URLHelper.analyzeURL(content.url) : null;\n dict['content.slug'] = urlAnalysis && urlAnalysis.type === 'post' ? urlAnalysis.slug : null;\n dict['content.name'] = content.title;\n }\n else if (content.type === 'product') {\n const urlAnalysis = URLHelper.analyzeURL(content.url);\n dict['content.slug'] = urlAnalysis && urlAnalysis.type === 'product' ? urlAnalysis.slug : null;\n dict['content.name'] = content.name;\n }\n\n return this.#getFilename(format, dict, CONTENT_DIR_NAME_VALIDATION_SCHEMA, CONTENT_DIR_NAME_FALLBACK_FORMAT);\n }\n\n static getCollectionDirName(collection: Collection, format: string): string {\n const slug = collection.title ?\n `${createSafeSlug(collection.title)}-${collection.id}`\n : `collection-${collection.id}`;\n const dict: FormatFieldValues<ContentDirNameFormatFieldName> = {\n 'content.id': collection.id,\n 'content.type': collection.type,\n 'content.slug': slug,\n 'content.name': collection.title,\n 'content.publishDate': collection.createdAt ? toISODate(collection.createdAt) : null\n };\n return this.#getFilename(format, dict, CONTENT_DIR_NAME_VALIDATION_SCHEMA, CONTENT_DIR_NAME_FALLBACK_FORMAT);\n }\n\n static getMediaFilename(\n media: MediaLike & { variant: string | null },\n src: Post | Product | Campaign | Collection,\n format: string,\n ext: string\n ): string {\n let srcFields: Pick<FormatFieldValues<MediaFilenameFormatFieldName>, 'src.id' | 'src.type' | 'src.title' | 'src.date'>;\n switch (src.type) {\n case 'post':\n srcFields = {\n 'src.id': src.id,\n 'src.type': src.type,\n 'src.date': src.publishedAt,\n 'src.title': src.title\n };\n break;\n case 'product':\n srcFields = {\n 'src.id': src.id,\n 'src.type': src.type,\n 'src.date': src.publishedAt,\n 'src.title': src.name\n };\n break;\n case 'campaign':\n srcFields = {\n 'src.id': src.id,\n 'src.type': src.type,\n 'src.date': src.createdAt,\n 'src.title': src.name\n };\n break;\n case 'collection':\n srcFields = {\n 'src.id': src.id,\n 'src.type': src.type,\n 'src.date': src.createdAt,\n 'src.title': src.title\n };\n break;\n }\n try {\n if (srcFields['src.date']) {\n srcFields['src.date'] = dateFormat(new Date(srcFields['src.date']), 'yyyy-mm-dd_HH-MM');\n }\n }\n catch (_) {\n // Do nothing\n }\n const dict: FormatFieldValues<MediaFilenameFormatFieldName> = {\n 'media.id': media.id,\n 'media.type': media.type,\n 'media.index': media.index !== undefined ? String(media.index) : null,\n 'media.filename': media.filename,\n 'media.variant': media.variant,\n ...srcFields\n };\n\n return this.#getFilename(format, dict, MEDIA_FILENAME_VALIDATION_SCHEMA, MEDIA_FILENAME_FALLBACK_FORMAT, ext);\n }\n\n static #getFilename<T extends FormatFieldName>(\n format: string,\n dict: FormatFieldValues<T>,\n rules: FormatFieldRules<T>,\n fallbackFormat: string,\n ext?: string\n ) {\n const { validateOK, result } = Formatter.format(format, dict, rules);\n let base = result;\n\n if (validateOK === false) {\n base = Formatter.format(fallbackFormat, dict).result;\n }\n\n return FSHelper.createFilename({ name: base, ext });\n }\n\n static validateCampaignDirNameFormat(format: string) {\n return Formatter.validate(format, CAMPAIGN_DIR_NAME_VALIDATION_SCHEMA);\n }\n\n static validateContentDirNameFormat(format: string) {\n return Formatter.validate(format, CONTENT_DIR_NAME_VALIDATION_SCHEMA);\n }\n\n static validateMediaFilenameFormat(format: string) {\n return Formatter.validate(format, MEDIA_FILENAME_VALIDATION_SCHEMA);\n }\n}\n"]}
|
|
@@ -3,7 +3,7 @@ export type FormatFieldRules<T extends FormatFieldName> = {
|
|
|
3
3
|
name: T;
|
|
4
4
|
atLeastOneOf: boolean;
|
|
5
5
|
}[];
|
|
6
|
-
export type FormatFieldValues<T extends FormatFieldName> = Record<T,
|
|
6
|
+
export type FormatFieldValues<T extends FormatFieldName> = Record<T, string | null | undefined>;
|
|
7
7
|
export default class Formatter {
|
|
8
8
|
#private;
|
|
9
9
|
static format<T extends FormatFieldName>(format: string, dict: FormatFieldValues<T>, rules?: FormatFieldRules<T>): {
|
package/dist/utils/Formatter.js
CHANGED
|
@@ -10,7 +10,7 @@ class Formatter {
|
|
|
10
10
|
let result = '';
|
|
11
11
|
const fieldRegex = __classPrivateFieldGet(this, _a, "m", _Formatter_getFieldRegex).call(this, Object.keys(dict));
|
|
12
12
|
const emptyValuePlaceHolder = '/%NULL%/';
|
|
13
|
-
const emptyValAdjCondSepRegex = /\[[^[]*?]\?\s
|
|
13
|
+
const emptyValAdjCondSepRegex = /\[[^[]*?]\?\s*?\/%NULL%\/\s*?\[.*?\]\?|\[[^[]*?]\?\s*?\/%NULL%\/|\/%NULL%\/\s*?\[.*?]\?/g;
|
|
14
14
|
const condSepRegex = /\[(.*?)]\?/g;
|
|
15
15
|
const fields = Object.keys(dict);
|
|
16
16
|
const consumedFields = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Formatter.js","sourceRoot":"","sources":["../../src/utils/Formatter.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AAWtD,MAAqB,SAAS;IAE5B,MAAM,CAAC,MAAM,CAA4B,MAAc,EAAE,IAA0B,EAAE,KAA2B;QAE9G,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,MAAM,UAAU,GAAG,uBAAA,IAAI,oCAAe,MAAnB,IAAI,EAAgB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,MAAM,qBAAqB,GAAG,UAAU,CAAC;QACzC,MAAM,uBAAuB,GAAG,
|
|
1
|
+
{"version":3,"file":"Formatter.js","sourceRoot":"","sources":["../../src/utils/Formatter.ts"],"names":[],"mappings":"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","sourcesContent":["import escapeStringRegexp from 'escape-string-regexp';\n\nexport type FormatFieldName = string;\n\nexport type FormatFieldRules<T extends FormatFieldName> = {\n name: T;\n atLeastOneOf: boolean;\n}[];\n\nexport type FormatFieldValues<T extends FormatFieldName> = Record<T, string | null | undefined>;\n\nexport default class Formatter {\n\n static format<T extends FormatFieldName>(format: string, dict: FormatFieldValues<T>, rules?: FormatFieldRules<T>) {\n\n let result = '';\n\n const fieldRegex = this.#getFieldRegex(Object.keys(dict));\n const emptyValuePlaceHolder = '/%NULL%/';\n const emptyValAdjCondSepRegex = /\\[[^[]*?]\\?\\s*?\\/%NULL%\\/\\s*?\\[.*?\\]\\?|\\[[^[]*?]\\?\\s*?\\/%NULL%\\/|\\/%NULL%\\/\\s*?\\[.*?]\\?/g;\n const condSepRegex = /\\[(.*?)]\\?/g;\n\n const fields = Object.keys(dict);\n const consumedFields: string[] = [];\n\n const __findPositionOfFirstField = (s: string) => {\n const match = fieldRegex.exec(s);\n if (match) {\n const foundField = s.substring(match.index + 1, match.index + match[0].length - 1);\n const placeholder = s.substring(match.index, match.index + match[0].length);\n if (fields.includes(foundField)) {\n return {\n field: foundField as T,\n placeholder,\n placeholderPosition: match.index\n };\n }\n }\n return {\n field: null,\n placeholder: null,\n placeholderPosition: -1\n };\n };\n\n let { field, placeholder, placeholderPosition } = __findPositionOfFirstField(format);\n while (field && placeholder && placeholderPosition >= 0) {\n result += format.substring(0, placeholderPosition);\n const fieldValue = dict[field];\n if (fieldValue) {\n result += fieldValue;\n if (!consumedFields.includes(field)) {\n consumedFields.push(field);\n }\n }\n else {\n result += emptyValuePlaceHolder;\n }\n format = format.substring(placeholderPosition + placeholder.length);\n\n if (format.length === 0) {\n break;\n }\n ({ field, placeholder, placeholderPosition } = __findPositionOfFirstField(format));\n }\n result += format;\n\n // Handle conditional separators\n // - Strip empty value placeholders + adjacent separators\n result = result.replaceAll(emptyValAdjCondSepRegex, '');\n // - Strip remaining empty value placeholders\n result = result.replaceAll(emptyValuePlaceHolder, '');\n // - Remove []? around conditional separators\n result = result.replace(condSepRegex, '$1');\n\n result = result.trim();\n\n // Validate\n let validateOK: boolean | null = null;\n if (rules) {\n const atLeastOneOfFields = rules.reduce<string[]>((result, f) => {\n if (f.atLeastOneOf) {\n result.push(f.name);\n }\n return result;\n }, []);\n\n validateOK = false;\n if (result) {\n for (const field of consumedFields) {\n if (atLeastOneOfFields.includes(field)) {\n validateOK = true;\n break;\n }\n }\n }\n }\n\n return {\n result,\n validateOK\n };\n }\n\n static validate<T extends FormatFieldName>(format: string, schema: FormatFieldRules<T>) {\n const fieldNames = schema.reduce<string[]>((result, s) => {\n if (s.atLeastOneOf) {\n result.push(s.name);\n }\n return result;\n }, []);\n if (fieldNames.length === 0) {\n return {\n validateOK: true\n };\n }\n const fieldRegex = this.#getFieldRegex(fieldNames, 'g');\n const match = fieldRegex.exec(format);\n return {\n validateOK: match && match.length > 0,\n regex: fieldRegex\n };\n }\n\n static #getFieldRegex(fieldNames: string[], flags?: string) {\n const pattern = fieldNames.map((k) => `{${escapeStringRegexp(k)}}`).join('|');\n return new RegExp(pattern, flags);\n }\n}\n"]}
|
|
@@ -63,6 +63,7 @@ class FileLogger extends ConsoleLogger {
|
|
|
63
63
|
this.config.logFilename = pathInfo.filename;
|
|
64
64
|
this.config.logFilePath = pathInfo.filePath;
|
|
65
65
|
this.config.created = pathInfo.created;
|
|
66
|
+
this.config.fileExistsAction = __classPrivateFieldGet(this, _FileLogger_fileExistsAction, "f");
|
|
66
67
|
}
|
|
67
68
|
static getPathInfo(type, params) {
|
|
68
69
|
switch (type) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileLogger.js","sourceRoot":"","sources":["../../../src/utils/logging/FileLogger.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport dateFormat from 'dateformat';\nimport { type LogLevel } from '../../utils/logging/Logger.js';\nimport { type DeepRequired, pickDefined } from '../Misc.js';\nimport ConsoleLogger, { type ConsoleLoggerOptions } from './ConsoleLogger.js';\nimport Formatter from '../Formatter.js';\nimport path from 'path';\nimport FSHelper from '../FSHelper.js';\nimport { EOL } from 'os';\nimport { getDefaultDownloaderOutDir } from '../../downloaders/DownloaderOptions.js';\n\nexport enum FileLoggerType {\n Downloader = 'downloader',\n Server = 'server'\n};\n\nexport type FileLoggerOptions<T extends FileLoggerType> =\n ConsoleLoggerOptions & \n ( T extends FileLoggerType.Downloader ? DownloaderFileLoggerOptions\n : T extends FileLoggerType.Server ? ServerFileLoggerOptions\n : never\n );\n\nexport interface DownloaderFileLoggerOptions {\n init: DownloaderFileLoggerInit;\n logDir?: string;\n logFilename?: string;\n fileExistsAction?: 'append' | 'overwrite';\n}\n\nexport interface ServerFileLoggerOptions {\n logFilePath: string;\n fileExistsAction?: 'append' | 'overwrite';\n}\n\nexport type FileLoggerConfig<T extends FileLoggerType> =\n DeepRequired<FileLoggerOptions<T>> & {\n logDir: string;\n logFilename: string;\n logFilePath: string;\n created: Date;\n };\n\nexport type FileLoggerGetPathInfoParams<T extends FileLoggerType> =\n T extends FileLoggerType.Downloader ? Pick<FileLoggerOptions<T>, 'init' | 'logDir' | 'logFilename' | 'logLevel'>\n : T extends FileLoggerType.Server ? Pick<FileLoggerOptions<T>, 'logFilePath'>\n : never;\n\nconst DEFAULT_DOWNLOADER_LOGGER_CONFIG: Omit<FileLoggerConfig<FileLoggerType.Downloader>, 'init' | 'created'> = {\n enabled: true,\n logDir: '{out.dir}/logs/{target.url.path}',\n logFilename: '{datetime.yyyymmdd}-{log.level}.log',\n fileExistsAction: 'append',\n logFilePath: '',\n logLevel: 'info',\n include: {\n dateTime: true,\n level: true,\n originator: true,\n errorStack: false\n },\n dateTimeFormat: 'mmm dd HH:MM:ss',\n color: false\n};\n\nconst DEFAULT_SERVER_LOGGER_FILE_EXISTS_ACTION = 'append';\n\nexport interface DownloaderFileLoggerInit {\n targetURL: string;\n outDir?: string;\n date?: Date;\n}\n\nexport default class FileLogger<T extends FileLoggerType = FileLoggerType.Downloader> extends ConsoleLogger {\n\n protected config: FileLoggerConfig<T>;\n #fileExistsAction: FileLoggerConfig<T>['fileExistsAction'];\n #stream: fs.WriteStream | null;\n #firstRun: boolean;\n\n constructor(options: FileLoggerOptions<T>) {\n super(options);\n \n const defaultFileExistsAction = this.#isDownloaderOptions(options) ?\n DEFAULT_DOWNLOADER_LOGGER_CONFIG.fileExistsAction\n : DEFAULT_SERVER_LOGGER_FILE_EXISTS_ACTION;\n this.#fileExistsAction = options?.fileExistsAction || defaultFileExistsAction;\n this.#stream = null;\n this.#firstRun = true;\n this.config.color = pickDefined(options?.color, DEFAULT_DOWNLOADER_LOGGER_CONFIG.color);\n\n const pathInfo = this.#isDownloaderOptions(options) ?\n FileLogger.#getPathInfoForDownloaderType(options)\n : FileLogger.#getPathInfoForServerType(options);\n\n this.config.logDir = pathInfo.logDir;\n this.config.logFilename = pathInfo.filename;\n this.config.logFilePath = pathInfo.filePath;\n this.config.created = pathInfo.created;\n }\n\n static getPathInfo<T extends FileLoggerType>(\n type: T,\n params: FileLoggerGetPathInfoParams<T>\n ) {\n switch (type) {\n case FileLoggerType.Downloader:\n return this.#getPathInfoForDownloaderType(params as FileLoggerGetPathInfoParams<FileLoggerType.Downloader>);\n case FileLoggerType.Server:\n return this.#getPathInfoForServerType(params as FileLoggerGetPathInfoParams<FileLoggerType.Server>);\n }\n return undefined as never;\n }\n\n static #getPathInfoForDownloaderType(params: FileLoggerGetPathInfoParams<FileLoggerType.Downloader>) {\n const defaultLogDir = DEFAULT_DOWNLOADER_LOGGER_CONFIG.logDir.replaceAll('/', path.sep);\n const {\n date = new Date(),\n outDir = getDefaultDownloaderOutDir(),\n targetURL\n } = params.init;\n const {\n logDir: dirNameFormat = defaultLogDir,\n logFilename: filenameFormat = DEFAULT_DOWNLOADER_LOGGER_CONFIG.logFilename,\n logLevel = DEFAULT_DOWNLOADER_LOGGER_CONFIG.logLevel } = params;\n\n const __getDateTimeFieldValues = (format: string, addTo: Record<string, string>) => {\n const dateTimeRegex = /{(datetime\\.(.+?))}/g;\n const dateTimeFields: { name: string; pattern: string; }[] = [];\n let m;\n while ((m = dateTimeRegex.exec(format)) !== null) {\n dateTimeFields.push({\n name: m[1],\n pattern: m[2]\n });\n }\n return dateTimeFields.reduce<Record<string, string>>((result, field) => {\n if (!result[field.name]) {\n result[field.name] = FSHelper.sanitizeFilename(dateFormat(date, field.pattern));\n }\n return result;\n }, addTo);\n };\n\n // Prepare variables for generating log dir and filenames\n let urlPath = new URL(targetURL).pathname.trim();\n while (urlPath.startsWith('/')) {\n urlPath = urlPath.slice(1);\n }\n while (urlPath.endsWith('/')) {\n urlPath = urlPath.slice(0, urlPath.length - 1);\n }\n urlPath = FSHelper.sanitizeFilename(urlPath.replaceAll('/', '_'));\n\n const logDirDTValues = __getDateTimeFieldValues(dirNameFormat, {});\n const allDTValues = __getDateTimeFieldValues(filenameFormat, logDirDTValues);\n\n // Pass to Formatter and get log dir and filename\n const logDirDict = {\n 'out.dir': outDir,\n 'target.url.path': urlPath,\n ...allDTValues\n };\n\n const logFilenameDict = {\n 'target.url.path': urlPath,\n 'log.level': logLevel,\n ...allDTValues\n };\n\n const logDir = path.resolve(\n process.cwd(),\n Formatter.format(dirNameFormat, logDirDict).result\n );\n const filename = FSHelper.sanitizeFilename(Formatter.format(filenameFormat, logFilenameDict).result);\n const filePath = path.resolve(logDir, filename);\n const created = date;\n\n return {\n logDir,\n filename,\n filePath,\n created\n };\n }\n\n static #getPathInfoForServerType(params: FileLoggerGetPathInfoParams<FileLoggerType.Server>) {\n const filePath = path.resolve(\n process.cwd(),\n params.logFilePath\n );\n const { dir: logDir, base: filename } = path.parse(filePath);\n return {\n logDir,\n filename,\n filePath,\n created: new Date()\n };\n }\n\n #getStream() {\n if (this.#stream) {\n return this.#stream;\n }\n // Ensure log directory exists\n FSHelper.createDir(this.config.logDir);\n\n // Create write stream\n let flags: 'a' | 'w';\n if (fs.existsSync(this.config.logFilePath) && (!this.#firstRun || this.#fileExistsAction === 'append')) {\n flags = 'a';\n }\n else {\n flags = 'w';\n }\n this.#stream = fs.createWriteStream(this.config.logFilePath, { flags, encoding: 'utf-8', autoClose: false });\n if (this.#firstRun) {\n const initDateTimeStr = dateFormat(this.config.created, 'mmm dd yyyy HH:MM:ss').toUpperCase();\n this.#stream.write(`${EOL}*************** LOG BEGIN ${initDateTimeStr} ***************${EOL}`);\n this.#firstRun = false;\n }\n return this.#stream;\n }\n\n #isDownloaderOptions(options: FileLoggerOptions<FileLoggerType>): options is FileLoggerOptions<FileLoggerType.Downloader> {\n return Reflect.has(options, 'init');\n }\n\n getConfig() {\n return this.config;\n }\n\n static getDefaultConfig() {\n const config = {\n ...DEFAULT_DOWNLOADER_LOGGER_CONFIG\n };\n config.logDir = config.logDir.replaceAll('/', path.sep);\n return config;\n }\n\n protected toOutput(_level: LogLevel, msg: string[]) {\n const stream = this.#getStream();\n stream.write(msg.join(' '));\n stream.write(EOL);\n }\n\n end(): Promise<void> {\n return new Promise((resolve) => {\n if (this.#stream) {\n this.#stream.once('finish', () => {\n this.#stream = null;\n resolve();\n });\n this.#stream.end();\n }\n else {\n resolve();\n }\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FileLogger.js","sourceRoot":"","sources":["../../../src/utils/logging/FileLogger.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,UAAU,MAAM,YAAY,CAAC;AAEpC,OAAO,EAAqB,WAAW,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,aAA4C,MAAM,oBAAoB,CAAC;AAC9E,OAAO,SAAS,MAAM,iBAAiB,CAAC;AACxC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,GAAG,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,0BAA0B,EAAE,MAAM,wCAAwC,CAAC;AAEpF,MAAM,CAAN,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,2CAAyB,CAAA;IACzB,mCAAiB,CAAA;AACnB,CAAC,EAHW,cAAc,KAAd,cAAc,QAGzB;AAAA,CAAC;AAkCF,MAAM,gCAAgC,GAA0E;IAC9G,OAAO,EAAE,IAAI;IACb,MAAM,EAAE,kCAAkC;IAC1C,WAAW,EAAE,qCAAqC;IAClD,gBAAgB,EAAE,QAAQ;IAC1B,WAAW,EAAE,EAAE;IACf,QAAQ,EAAE,MAAM;IAChB,OAAO,EAAE;QACP,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,IAAI;QAChB,UAAU,EAAE,KAAK;KAClB;IACD,cAAc,EAAE,iBAAiB;IACjC,KAAK,EAAE,KAAK;CACb,CAAC;AAEF,MAAM,wCAAwC,GAAG,QAAQ,CAAC;AAQ1D,MAAqB,UAAiE,SAAQ,aAAa;IAOzG,YAAY,OAA6B;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC;;QALjB,+CAA2D;QAC3D,qCAA+B;QAC/B,uCAAmB;QAKjB,MAAM,uBAAuB,GAAG,uBAAA,IAAI,8DAAqB,MAAzB,IAAI,EAAsB,OAAO,CAAC,CAAC,CAAC;YAClE,gCAAgC,CAAC,gBAAgB;YACjD,CAAC,CAAC,wCAAwC,CAAC;QAC7C,uBAAA,IAAI,gCAAqB,OAAO,EAAE,gBAAgB,IAAI,uBAAuB,MAAA,CAAC;QAC9E,uBAAA,IAAI,sBAAW,IAAI,MAAA,CAAC;QACpB,uBAAA,IAAI,wBAAa,IAAI,MAAA,CAAC;QACtB,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,WAAW,CAAC,OAAO,EAAE,KAAK,EAAE,gCAAgC,CAAC,KAAK,CAAC,CAAC;QAExF,MAAM,QAAQ,GAAG,uBAAA,IAAI,8DAAqB,MAAzB,IAAI,EAAsB,OAAO,CAAC,CAAC,CAAC;YACnD,uBAAA,EAAU,oDAA8B,MAAxC,EAAU,EAA+B,OAAO,CAAC;YACjD,CAAC,CAAC,uBAAA,EAAU,gDAA0B,MAApC,EAAU,EAA2B,OAAO,CAAC,CAAC;QAElD,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC;QAC5C,IAAI,CAAC,MAAM,CAAC,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC;QAC5C,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,gBAAgB,GAAG,uBAAA,IAAI,oCAAkB,CAAC;IACxD,CAAC;IAED,MAAM,CAAC,WAAW,CAChB,IAAO,EACP,MAAsC;QAEtC,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,cAAc,CAAC,UAAU;gBAC5B,OAAO,uBAAA,IAAI,oDAA8B,MAAlC,IAAI,EAA+B,MAAgE,CAAC,CAAC;YAC9G,KAAK,cAAc,CAAC,MAAM;gBACxB,OAAO,uBAAA,IAAI,gDAA0B,MAA9B,IAAI,EAA2B,MAA4D,CAAC,CAAC;QACxG,CAAC;QACD,OAAO,SAAkB,CAAC;IAC5B,CAAC;IAoHD,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,gBAAgB;QACrB,MAAM,MAAM,GAAG;YACb,GAAG,gCAAgC;SACpC,CAAC;QACF,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACxD,OAAO,MAAM,CAAC;IAChB,CAAC;IAES,QAAQ,CAAC,MAAgB,EAAE,GAAa;QAChD,MAAM,MAAM,GAAG,uBAAA,IAAI,oDAAW,MAAf,IAAI,CAAa,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC;IAED,GAAG;QACD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,uBAAA,IAAI,0BAAQ,EAAE,CAAC;gBACjB,uBAAA,IAAI,0BAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE;oBAC/B,uBAAA,IAAI,sBAAW,IAAI,MAAA,CAAC;oBACpB,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC,CAAC;gBACH,uBAAA,IAAI,0BAAQ,CAAC,GAAG,EAAE,CAAC;YACrB,CAAC;iBACI,CAAC;gBACJ,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;CACF;6QAlJsC,MAA8D;IACjG,MAAM,aAAa,GAAG,gCAAgC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACxF,MAAM,EACJ,IAAI,GAAG,IAAI,IAAI,EAAE,EACjB,MAAM,GAAG,0BAA0B,EAAE,EACrC,SAAS,EACV,GAAG,MAAM,CAAC,IAAI,CAAC;IAChB,MAAM,EACJ,MAAM,EAAE,aAAa,GAAG,aAAa,EACrC,WAAW,EAAE,cAAc,GAAG,gCAAgC,CAAC,WAAW,EAC1E,QAAQ,GAAG,gCAAgC,CAAC,QAAQ,EAAE,GAAG,MAAM,CAAC;IAElE,MAAM,wBAAwB,GAAG,CAAC,MAAc,EAAE,KAA6B,EAAE,EAAE;QACjF,MAAM,aAAa,GAAG,sBAAsB,CAAC;QAC7C,MAAM,cAAc,GAAyC,EAAE,CAAC;QAChE,IAAI,CAAC,CAAC;QACN,OAAO,CAAC,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACjD,cAAc,CAAC,IAAI,CAAC;gBAClB,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;gBACV,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;aACd,CAAC,CAAC;QACL,CAAC;QACD,OAAO,cAAc,CAAC,MAAM,CAAyB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;YACrE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAClF,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC,CAAC;IAEF,yDAAyD;IACzD,IAAI,OAAO,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACjD,OAAO,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,GAAG,QAAQ,CAAC,gBAAgB,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAElE,MAAM,cAAc,GAAG,wBAAwB,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IACnE,MAAM,WAAW,GAAG,wBAAwB,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;IAE7E,iDAAiD;IACjD,MAAM,UAAU,GAAG;QACjB,SAAS,EAAE,MAAM;QACjB,iBAAiB,EAAE,OAAO;QAC1B,GAAG,WAAW;KACf,CAAC;IAEF,MAAM,eAAe,GAAG;QACtB,iBAAiB,EAAE,OAAO;QAC1B,WAAW,EAAE,QAAQ;QACrB,GAAG,WAAW;KACf,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CACzB,OAAO,CAAC,GAAG,EAAE,EACb,SAAS,CAAC,MAAM,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,MAAM,CACnD,CAAC;IACF,MAAM,QAAQ,GAAG,QAAQ,CAAC,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;IACrG,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC;IAErB,OAAO;QACL,MAAM;QACN,QAAQ;QACR,QAAQ;QACR,OAAO;KACR,CAAC;AACJ,CAAC,uFAEgC,MAA0D;IACzF,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAC3B,OAAO,CAAC,GAAG,EAAE,EACb,MAAM,CAAC,WAAW,CACnB,CAAC;IACF,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC7D,OAAO;QACL,MAAM;QACN,QAAQ;QACR,QAAQ;QACR,OAAO,EAAE,IAAI,IAAI,EAAE;KACpB,CAAC;AACJ,CAAC;IAGC,IAAI,uBAAA,IAAI,0BAAQ,EAAE,CAAC;QACjB,OAAO,uBAAA,IAAI,0BAAQ,CAAC;IACtB,CAAC;IACD,8BAA8B;IAC9B,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEvC,sBAAsB;IACtB,IAAI,KAAgB,CAAC;IACrB,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,uBAAA,IAAI,4BAAU,IAAI,uBAAA,IAAI,oCAAkB,KAAK,QAAQ,CAAC,EAAE,CAAC;QACvG,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;SACI,CAAC;QACJ,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;IACD,uBAAA,IAAI,sBAAW,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,MAAA,CAAC;IAC7G,IAAI,uBAAA,IAAI,4BAAU,EAAE,CAAC;QACnB,MAAM,eAAe,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9F,uBAAA,IAAI,0BAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,6BAA6B,eAAe,mBAAmB,GAAG,EAAE,CAAC,CAAC;QAC/F,uBAAA,IAAI,wBAAa,KAAK,MAAA,CAAC;IACzB,CAAC;IACD,OAAO,uBAAA,IAAI,0BAAQ,CAAC;AACtB,CAAC,6EAEoB,OAA0C;IAC7D,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AACtC,CAAC;eA1JkB,UAAU","sourcesContent":["import fs from 'fs';\nimport dateFormat from 'dateformat';\nimport { type LogLevel } from '../../utils/logging/Logger.js';\nimport { type DeepRequired, pickDefined } from '../Misc.js';\nimport ConsoleLogger, { type ConsoleLoggerOptions } from './ConsoleLogger.js';\nimport Formatter from '../Formatter.js';\nimport path from 'path';\nimport FSHelper from '../FSHelper.js';\nimport { EOL } from 'os';\nimport { getDefaultDownloaderOutDir } from '../../downloaders/DownloaderOptions.js';\n\nexport enum FileLoggerType {\n Downloader = 'downloader',\n Server = 'server'\n};\n\nexport type FileLoggerOptions<T extends FileLoggerType> =\n ConsoleLoggerOptions & \n ( T extends FileLoggerType.Downloader ? DownloaderFileLoggerOptions\n : T extends FileLoggerType.Server ? ServerFileLoggerOptions\n : never\n );\n\nexport interface DownloaderFileLoggerOptions {\n init: DownloaderFileLoggerInit;\n logDir?: string;\n logFilename?: string;\n fileExistsAction?: 'append' | 'overwrite';\n}\n\nexport interface ServerFileLoggerOptions {\n logFilePath: string;\n fileExistsAction?: 'append' | 'overwrite';\n}\n\nexport type FileLoggerConfig<T extends FileLoggerType> =\n DeepRequired<FileLoggerOptions<T>> & {\n logDir: string;\n logFilename: string;\n logFilePath: string;\n created: Date;\n };\n\nexport type FileLoggerGetPathInfoParams<T extends FileLoggerType> =\n T extends FileLoggerType.Downloader ? Pick<FileLoggerOptions<T>, 'init' | 'logDir' | 'logFilename' | 'logLevel'>\n : T extends FileLoggerType.Server ? Pick<FileLoggerOptions<T>, 'logFilePath'>\n : never;\n\nconst DEFAULT_DOWNLOADER_LOGGER_CONFIG: Omit<FileLoggerConfig<FileLoggerType.Downloader>, 'init' | 'created'> = {\n enabled: true,\n logDir: '{out.dir}/logs/{target.url.path}',\n logFilename: '{datetime.yyyymmdd}-{log.level}.log',\n fileExistsAction: 'append',\n logFilePath: '',\n logLevel: 'info',\n include: {\n dateTime: true,\n level: true,\n originator: true,\n errorStack: false\n },\n dateTimeFormat: 'mmm dd HH:MM:ss',\n color: false\n};\n\nconst DEFAULT_SERVER_LOGGER_FILE_EXISTS_ACTION = 'append';\n\nexport interface DownloaderFileLoggerInit {\n targetURL: string;\n outDir?: string;\n date?: Date;\n}\n\nexport default class FileLogger<T extends FileLoggerType = FileLoggerType.Downloader> extends ConsoleLogger {\n\n protected config: FileLoggerConfig<T>;\n #fileExistsAction: FileLoggerConfig<T>['fileExistsAction'];\n #stream: fs.WriteStream | null;\n #firstRun: boolean;\n\n constructor(options: FileLoggerOptions<T>) {\n super(options);\n \n const defaultFileExistsAction = this.#isDownloaderOptions(options) ?\n DEFAULT_DOWNLOADER_LOGGER_CONFIG.fileExistsAction\n : DEFAULT_SERVER_LOGGER_FILE_EXISTS_ACTION;\n this.#fileExistsAction = options?.fileExistsAction || defaultFileExistsAction;\n this.#stream = null;\n this.#firstRun = true;\n this.config.color = pickDefined(options?.color, DEFAULT_DOWNLOADER_LOGGER_CONFIG.color);\n\n const pathInfo = this.#isDownloaderOptions(options) ?\n FileLogger.#getPathInfoForDownloaderType(options)\n : FileLogger.#getPathInfoForServerType(options);\n\n this.config.logDir = pathInfo.logDir;\n this.config.logFilename = pathInfo.filename;\n this.config.logFilePath = pathInfo.filePath;\n this.config.created = pathInfo.created;\n this.config.fileExistsAction = this.#fileExistsAction;\n }\n\n static getPathInfo<T extends FileLoggerType>(\n type: T,\n params: FileLoggerGetPathInfoParams<T>\n ) {\n switch (type) {\n case FileLoggerType.Downloader:\n return this.#getPathInfoForDownloaderType(params as FileLoggerGetPathInfoParams<FileLoggerType.Downloader>);\n case FileLoggerType.Server:\n return this.#getPathInfoForServerType(params as FileLoggerGetPathInfoParams<FileLoggerType.Server>);\n }\n return undefined as never;\n }\n\n static #getPathInfoForDownloaderType(params: FileLoggerGetPathInfoParams<FileLoggerType.Downloader>) {\n const defaultLogDir = DEFAULT_DOWNLOADER_LOGGER_CONFIG.logDir.replaceAll('/', path.sep);\n const {\n date = new Date(),\n outDir = getDefaultDownloaderOutDir(),\n targetURL\n } = params.init;\n const {\n logDir: dirNameFormat = defaultLogDir,\n logFilename: filenameFormat = DEFAULT_DOWNLOADER_LOGGER_CONFIG.logFilename,\n logLevel = DEFAULT_DOWNLOADER_LOGGER_CONFIG.logLevel } = params;\n\n const __getDateTimeFieldValues = (format: string, addTo: Record<string, string>) => {\n const dateTimeRegex = /{(datetime\\.(.+?))}/g;\n const dateTimeFields: { name: string; pattern: string; }[] = [];\n let m;\n while ((m = dateTimeRegex.exec(format)) !== null) {\n dateTimeFields.push({\n name: m[1],\n pattern: m[2]\n });\n }\n return dateTimeFields.reduce<Record<string, string>>((result, field) => {\n if (!result[field.name]) {\n result[field.name] = FSHelper.sanitizeFilename(dateFormat(date, field.pattern));\n }\n return result;\n }, addTo);\n };\n\n // Prepare variables for generating log dir and filenames\n let urlPath = new URL(targetURL).pathname.trim();\n while (urlPath.startsWith('/')) {\n urlPath = urlPath.slice(1);\n }\n while (urlPath.endsWith('/')) {\n urlPath = urlPath.slice(0, urlPath.length - 1);\n }\n urlPath = FSHelper.sanitizeFilename(urlPath.replaceAll('/', '_'));\n\n const logDirDTValues = __getDateTimeFieldValues(dirNameFormat, {});\n const allDTValues = __getDateTimeFieldValues(filenameFormat, logDirDTValues);\n\n // Pass to Formatter and get log dir and filename\n const logDirDict = {\n 'out.dir': outDir,\n 'target.url.path': urlPath,\n ...allDTValues\n };\n\n const logFilenameDict = {\n 'target.url.path': urlPath,\n 'log.level': logLevel,\n ...allDTValues\n };\n\n const logDir = path.resolve(\n process.cwd(),\n Formatter.format(dirNameFormat, logDirDict).result\n );\n const filename = FSHelper.sanitizeFilename(Formatter.format(filenameFormat, logFilenameDict).result);\n const filePath = path.resolve(logDir, filename);\n const created = date;\n\n return {\n logDir,\n filename,\n filePath,\n created\n };\n }\n\n static #getPathInfoForServerType(params: FileLoggerGetPathInfoParams<FileLoggerType.Server>) {\n const filePath = path.resolve(\n process.cwd(),\n params.logFilePath\n );\n const { dir: logDir, base: filename } = path.parse(filePath);\n return {\n logDir,\n filename,\n filePath,\n created: new Date()\n };\n }\n\n #getStream() {\n if (this.#stream) {\n return this.#stream;\n }\n // Ensure log directory exists\n FSHelper.createDir(this.config.logDir);\n\n // Create write stream\n let flags: 'a' | 'w';\n if (fs.existsSync(this.config.logFilePath) && (!this.#firstRun || this.#fileExistsAction === 'append')) {\n flags = 'a';\n }\n else {\n flags = 'w';\n }\n this.#stream = fs.createWriteStream(this.config.logFilePath, { flags, encoding: 'utf-8', autoClose: false });\n if (this.#firstRun) {\n const initDateTimeStr = dateFormat(this.config.created, 'mmm dd yyyy HH:MM:ss').toUpperCase();\n this.#stream.write(`${EOL}*************** LOG BEGIN ${initDateTimeStr} ***************${EOL}`);\n this.#firstRun = false;\n }\n return this.#stream;\n }\n\n #isDownloaderOptions(options: FileLoggerOptions<FileLoggerType>): options is FileLoggerOptions<FileLoggerType.Downloader> {\n return Reflect.has(options, 'init');\n }\n\n getConfig() {\n return this.config;\n }\n\n static getDefaultConfig() {\n const config = {\n ...DEFAULT_DOWNLOADER_LOGGER_CONFIG\n };\n config.logDir = config.logDir.replaceAll('/', path.sep);\n return config;\n }\n\n protected toOutput(_level: LogLevel, msg: string[]) {\n const stream = this.#getStream();\n stream.write(msg.join(' '));\n stream.write(EOL);\n }\n\n end(): Promise<void> {\n return new Promise((resolve) => {\n if (this.#stream) {\n this.#stream.once('finish', () => {\n this.#stream = null;\n resolve();\n });\n this.#stream.end();\n }\n else {\n resolve();\n }\n });\n }\n}\n"]}
|