patreon-dl 3.7.0 → 3.8.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 +29 -1
- package/dist/browse/api/CampaignAPIMixin.d.ts +1 -1
- package/dist/browse/api/ContentAPIMixin.d.ts +3 -3
- package/dist/browse/api/FilterAPIMixin.d.ts +1 -1
- package/dist/browse/api/index.d.ts +10 -10
- package/dist/browse/db/CampaignDBMixin.d.ts +3 -3
- package/dist/browse/db/ContentDBMixin.d.ts +13 -13
- package/dist/browse/db/index.d.ts +16 -16
- package/dist/browse/web/assets/index-CQnQD2xz.css +1 -0
- package/dist/browse/web/assets/index-CtZbx-Du.js +218 -0
- package/dist/browse/web/index.html +2 -2
- package/dist/cli/CLIOptions.js +2 -0
- package/dist/cli/CLIOptions.js.map +1 -1
- package/dist/cli/CommandLineParser.d.ts +4 -0
- package/dist/cli/CommandLineParser.js +65 -32
- package/dist/cli/CommandLineParser.js.map +1 -1
- package/dist/cli/ConfigFileParser.js +2 -0
- package/dist/cli/ConfigFileParser.js.map +1 -1
- package/dist/cli/helper/PostList.d.ts +6 -0
- package/dist/cli/helper/PostList.js +106 -0
- package/dist/cli/helper/PostList.js.map +1 -0
- package/dist/cli/index.js +73 -53
- package/dist/cli/index.js.map +1 -1
- package/dist/downloaders/Bootstrap.d.ts +5 -0
- package/dist/downloaders/Bootstrap.js +10 -0
- package/dist/downloaders/Bootstrap.js.map +1 -1
- package/dist/downloaders/Downloader.d.ts +4 -4
- package/dist/downloaders/Downloader.js +5 -58
- package/dist/downloaders/Downloader.js.map +1 -1
- package/dist/downloaders/DownloaderOptions.d.ts +1 -0
- package/dist/downloaders/DownloaderOptions.js +2 -0
- package/dist/downloaders/DownloaderOptions.js.map +1 -1
- package/dist/downloaders/IncludeCriteriaHelper.d.ts +25 -0
- package/dist/downloaders/IncludeCriteriaHelper.js +160 -0
- package/dist/downloaders/IncludeCriteriaHelper.js.map +1 -0
- package/dist/downloaders/InitialData.js +20 -6
- package/dist/downloaders/InitialData.js.map +1 -1
- package/dist/downloaders/PostDownloader.js +62 -98
- package/dist/downloaders/PostDownloader.js.map +1 -1
- package/dist/downloaders/PostsFetcher.js +4 -2
- package/dist/downloaders/PostsFetcher.js.map +1 -1
- package/dist/downloaders/ProductDownloader.js +31 -21
- package/dist/downloaders/ProductDownloader.js.map +1 -1
- package/dist/downloaders/task/M3U8DownloadTask.d.ts +1 -0
- package/dist/downloaders/task/M3U8DownloadTask.js +137 -39
- package/dist/downloaders/task/M3U8DownloadTask.js.map +1 -1
- package/dist/downloaders/task/YouTubeDownloadTask.js +1 -3
- package/dist/downloaders/task/YouTubeDownloadTask.js.map +1 -1
- package/dist/parsers/PageParser.js +8 -3
- package/dist/parsers/PageParser.js.map +1 -1
- package/dist/utils/Fetcher.d.ts +4 -1
- package/dist/utils/Fetcher.js +6 -1
- package/dist/utils/Fetcher.js.map +1 -1
- package/dist/utils/URLHelper.d.ts +4 -0
- package/dist/utils/URLHelper.js +17 -0
- package/dist/utils/URLHelper.js.map +1 -1
- package/dist/utils/YouTubeCredentialsCapturer.js +1 -1
- package/dist/utils/YouTubeCredentialsCapturer.js.map +1 -1
- package/dist/utils/logging/ConsoleLogger.js +5 -0
- package/dist/utils/logging/ConsoleLogger.js.map +1 -1
- package/dist/utils/yt/InnertubeLoader.d.ts +4 -6
- package/dist/utils/yt/InnertubeLoader.js +14 -14
- package/dist/utils/yt/InnertubeLoader.js.map +1 -1
- package/dist/utils/yt/PoToken.js +53 -27
- package/dist/utils/yt/PoToken.js.map +1 -1
- package/package.json +12 -8
- package/dist/browse/web/assets/index-CW4CUoWl.css +0 -1
- package/dist/browse/web/assets/index-CziUWlSw.js +0 -218
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProductDownloader.js","sourceRoot":"","sources":["../../src/downloaders/ProductDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import ProductParser from '../parsers/ProductParser.js';\nimport URLHelper from '../utils/URLHelper.js';\nimport Downloader, { type DownloaderConfig, type DownloaderStartParams } from './Downloader.js';\nimport StatusCache from './cache/StatusCache.js';\nimport { generateProductSummary } from './templates/ProductInfo.js';\nimport path from 'path';\nimport { TargetSkipReason } from './DownloaderEvent.js';\nimport { ProductType, type Product } from '../entities/Product.js';\nimport { type Downloadable } from '../entities/Downloadable.js';\nimport Bootstrap from './Bootstrap.js';\nimport ProductsFetcher from './ProductsFetcher.js';\nimport { type ProductDirectories } from '../utils/FSHelper.js';\nimport { type DBInstance } from '../browse/db/index.js';\n\nexport default class ProductDownloader extends Downloader<Product> {\n\n static version = '1.0.1';\n\n name = 'ProductDownloader';\n\n #startPromise: Promise<void> | null = null;\n\n doStart(params?: DownloaderStartParams): Promise<void> {\n\n if (this.#startPromise) {\n throw Error('Downloader already running');\n }\n\n this.#startPromise = this.#doStart(params)\n .finally(() => {\n this.#startPromise = null;\n });\n\n return this.#startPromise;\n }\n\n async #doStart(params?: DownloaderStartParams): Promise<void> {\n try {\n const { signal } = params || {};\n const productFetch = this.config.productFetch;\n const db = await this.db();\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n if (productFetch.type === 'byShop') {\n this.log('info', `Targeting products by '${productFetch.vanity}'`);\n }\n else if (productFetch.type === 'byFile') {\n this.log('info', `Target product given by API data in \"${productFetch.filePath}\"`);\n }\n else {\n this.log('info', `Targeting product #${productFetch.productId}`);\n }\n\n // Step 1: get products (if by shop) or target product\n const productsFetcher = new ProductsFetcher({\n config: this.config,\n fetcher: this.fetcher,\n logger: this.logger,\n signal\n });\n productsFetcher.on('statusChange', ({current}) => {\n if (current.status === 'running') {\n this.emit('fetchBegin', { targetType: productsFetcher.getTargetType() });\n }\n });\n productsFetcher.begin();\n\n // Step 2: download products in each fetched list\n let downloaded = 0;\n let skippedUnviewable = 0;\n let skippedRedundant = 0;\n let skippedPublishDateOutOfRange = 0;\n let campaignSaved = false;\n let stopConditionMet = false;\n const productsParser = new ProductParser(this.logger);\n while (productsFetcher.hasNext()) {\n const { list, aborted, error } = await productsFetcher.next();\n if (!list || aborted) {\n break;\n }\n if (!list && error) {\n this.emit('end', { aborted: false, error, message: 'ProductsFetcher error' });\n return;\n }\n if (!campaignSaved && list.items[0]?.campaign) {\n await this.saveCampaignInfo(list.items[0].campaign, signal);\n campaignSaved = true;\n if (this.checkAbortSignal(signal)) {\n return;\n }\n }\n\n for (const _product of list.items) {\n\n if (stopConditionMet) {\n break;\n }\n\n let product = _product;\n\n if (this.#isFetchingMultipleProducts(productFetch)) {\n // Refresh to ensure media links have not expired\n this.log('debug', `Refresh product #${_product.id}`);\n const productURL = URLHelper.constructProductAPIURL(product.id);\n const { json } = await this.commonFetchAPI(productURL, signal);\n let refreshed: Product | null = null;\n if (json) {\n refreshed = productsParser.parseProductsAPIResponse(json, productURL).items[0] || null;\n if (!refreshed) {\n this.log('warn', `Refreshed product #${_product.id} but got empty value - going to use existing data`);\n }\n else if (refreshed.id !== _product.id) {\n this.log('warn', `Refreshed product #${_product.id} but ID mismatch - going to use existing data`);\n refreshed = null;\n }\n else {\n // Refreshed data does not have productType - reinstate it\n refreshed.productType = _product.productType;\n }\n }\n else if (this.checkAbortSignal(signal)) {\n return;\n }\n else {\n this.log('warn', `Failed to refresh product #${_product.id} - going to use existing data`);\n }\n if (refreshed) {\n this.log('debug', `Use refreshed product data #${refreshed.id}`);\n product = refreshed;\n }\n }\n\n this.emit('targetBegin', { target: product });\n\n // Step 4.1: product directories\n const productDirs = this.fsHelper.getProductDirs(product);\n this.log('debug', 'Product directories:', productDirs);\n\n // Step 4.2: Check with status cache\n const statusCache = StatusCache.getInstance(this.config, productDirs.statusCache, this.logger);\n if (!product.productType || product.productType === ProductType.DigitalCommerce) {\n const statusCacheValidation = statusCache.validate(product, productDirs.root, this.config)\n if (!statusCacheValidation.invalidated) {\n this.log('info', `Skipped downloading product #${product.id}: already downloaded`);\n this.emit('targetEnd', {\n target: product,\n isSkipped: true,\n skipReason: TargetSkipReason.AlreadyDownloaded,\n skipMessage: 'Target already downloaded'\n });\n skippedRedundant++;\n if (this.config.stopOn === 'previouslyDownloaded') {\n stopConditionMet = true;\n }\n continue;\n }\n }\n \n switch ((await this.#doDownload(\n product,\n productDirs,\n statusCache,\n db,\n signal\n )).status) {\n case 'aborted':\n return;\n case 'downloaded':\n downloaded++;\n break;\n case 'skippedPublishDateOutOfRange':\n skippedPublishDateOutOfRange++;\n if (this.config.stopOn === 'postPublishDateOutOfRange' ||\n this.config.stopOn === 'publishDateOutOfRange'\n ) {\n stopConditionMet = true;\n }\n break;\n case 'skippedUnviewable':\n skippedUnviewable++;\n break;\n }\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n }\n\n if (stopConditionMet) {\n break;\n }\n }\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n if (stopConditionMet && this.#isFetchingMultipleProducts(productFetch)) {\n this.log('info', `Stop downloader: stop condition \"${this.config.stopOn}\" met`)\n }\n\n // Done\n if (productFetch.type === 'byShop') {\n this.log('info', `Done downloading products by '${productFetch.vanity}'`);\n }\n else if (productFetch.type === 'byFile') {\n this.log('info', `Done downloading product given in \"${productFetch.filePath}\"`);\n }\n else {\n this.log('info', `Done downloading product #${productFetch.productId}`);\n }\n let endMessage = 'Done';\n if (this.#isFetchingMultipleProducts(productFetch)) {\n const skippedStrParts: string[] = [];\n if (skippedUnviewable) {\n skippedStrParts.push(`${skippedUnviewable} unviewable`);\n }\n if (skippedRedundant) {\n skippedStrParts.push(`${skippedRedundant} redundant`);\n }\n if (skippedPublishDateOutOfRange) {\n skippedStrParts.push(`${skippedPublishDateOutOfRange} with publish date out of range`);\n }\n const skippedStr = skippedStrParts.length > 0 ? ` (skipped: ${skippedStrParts.join(', ')})` : '';\n endMessage = `Total ${downloaded} / ${productsFetcher.getTotal()} products processed${skippedStr}`;\n this.log('info', endMessage);\n }\n this.emit('end', { aborted: false, message: endMessage });\n }\n finally {\n await this.closeDB();\n if (this.logger) {\n await this.logger.end();\n }\n }\n }\n\n async #doDownload(\n product: Product,\n productDirs: ProductDirectories,\n statusCache: StatusCache,\n db: DBInstance,\n signal?: AbortSignal\n ): Promise<{status: 'skippedUnviewable' | 'skippedPublishDateOutOfRange' | 'aborted' | 'downloaded' }> {\n // Step 1: Check whether we should download product\n // -- 1.1 Accessibility\n if (!product.isAccessible) {\n if (this.config.include.lockedContent) {\n this.log('warn', `Product #${product.id} is not accessible by current user`);\n }\n else {\n this.log('warn', `Skipped downloading product #${product.id}: not accessible by current user`);\n this.emit('targetEnd', {\n target: product,\n isSkipped: true,\n skipReason: TargetSkipReason.Inaccessible,\n skipMessage: 'Target is not accessible by current user'\n });\n return {\n status: 'skippedUnviewable'\n };\n }\n }\n // -- 1.4 Config option 'include.productsPublished'\n if (this.isPublishDateOutOfRange(product)) {\n return {\n status: 'skippedPublishDateOutOfRange'\n };\n }\n\n this.fsHelper.createDir(productDirs.root);\n\n // Step 2: save product info\n if (this.config.include.contentInfo) {\n this.log('info', 'Save product info');\n this.emit('phaseBegin', { target: product, phase: 'saveInfo' });\n this.fsHelper.createDir(productDirs.info);\n const summary = generateProductSummary(product);\n const summaryFile = path.resolve(productDirs.info, 'info.txt');\n const saveSummaryResult = await this.fsHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, product, 'product summary');\n\n const productRawFile = path.resolve(productDirs.info, 'product-api.json');\n const saveProductRawResult = await this.fsHelper.writeTextFile(\n productRawFile, product.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(saveProductRawResult, product, 'product API data');\n this.emit('phaseEnd', { target: product, phase: 'saveInfo' });\n }\n\n // Step 3: Download product media items\n const incPreview = this.config.include.previewMedia;\n const incContent = this.config.include.contentMedia;\n this.log('info', 'Download:', {\n ['preview items']: incPreview === true ? 'yes' : incPreview === false ? 'no' : JSON.stringify(incPreview),\n ['content items']: incContent === true ? 'yes' : incContent === false ? 'no' : JSON.stringify(incContent)\n });\n\n const __inc = (inc: boolean | Array<any>, target: Downloadable) => {\n if (typeof inc === 'boolean') {\n return inc;\n }\n return (inc.includes(target.type as any));\n };\n\n const previewMedia = product.previewMedia.filter((tt) => __inc(incPreview, tt));\n const contentMedia = product.contentMedia.filter((tt) => __inc(incContent, tt));\n const campaignDir = product.campaign ? this.fsHelper.getCampaignDirs(product.campaign).root : null;\n\n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseBegin', { target: product, phase: 'saveMedia' });\n const batchResult = await this.createDownloadTaskBatch(\n `Product #${product.id} (${product.name})`,\n signal,\n\n previewMedia.length > 0 ? {\n target: previewMedia,\n targetName: `product #${product.id} -> preview media`,\n src: product,\n dirs: {\n campaign: campaignDir,\n main: productDirs.previewMedia,\n thumbnails: productDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n contentMedia.length > 0 ? {\n target: contentMedia,\n targetName: `product #${product.id} -> content media`,\n src: product,\n dirs: {\n campaign: campaignDir,\n main: productDirs.contentMedia,\n thumbnails: productDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content,\n ignoreCreateTaskErrors: !product.isAccessible\n } : null\n );\n\n const { batch } = batchResult;\n\n const abortHandler = () => {\n void (async () => {\n this.log('info', 'Abort signal received');\n if (batch) {\n await batch.abort();\n }\n })();\n };\n if (signal) {\n signal.addEventListener('abort', abortHandler, { once: true });\n }\n \n try {\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n \n batch.prestart();\n this.log('info', `Download batch created (#${batch.id}): ${batch.getTasks('pending').length} downloads pending`);\n this.emit('phaseBegin', { target: product, phase: 'batchDownload', batch });\n\n await batch.start();\n\n // Step 4: Update status cache\n statusCache.updateOnDownload(product, productDirs.root, batch.getTasks('error').length > 0 || batchResult.errorCount > 0, this.config);\n\n await batch.destroy();\n }\n finally {\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n }\n\n this.emit('phaseEnd', { target: product, phase: 'batchDownload' });\n this.emit('phaseEnd', { target: product, phase: 'saveMedia' });\n }\n\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n\n // Step 5: Save to DB\n let skipDB = false;\n let saveReferencedEntityId: (id: string) => void;\n const dbProduct = db.getContent(product.id, 'product');\n if (!product.isAccessible) {\n // Skip if existing db record (if any) refers to accessible product\n skipDB = dbProduct !== null && dbProduct.isAccessible;\n }\n if (!skipDB) {\n db.saveContent(product);\n saveReferencedEntityId = (id) => {\n product.referencedEntityId = id;\n db.saveContent(product);\n };\n }\n else {\n this.log('info', `Skip overwrite existing accessible product #${product.id} in DB with current unviewable version`);\n saveReferencedEntityId = (id) => {\n // Ensure referencedEntityId is updated\n dbProduct!.referencedEntityId = id;\n db.saveContent(dbProduct!);\n };\n }\n\n // Step 6: check product type and download referenced product / collection\n await this.#processProductType(product, saveReferencedEntityId, signal);\n\n // Done\n this.log('info', `Done downloading product #${product.id}`);\n this.emit('targetEnd', { target: product, isSkipped: false });\n\n return {\n status: 'downloaded'\n }\n }\n\n // Carry out further action based on product type\n async #processProductType(\n product: Product,\n saveReferencedEntityId: (id: string) => void,\n signal?: AbortSignal\n ) {\n if (product.productType === undefined || product.productType === ProductType.DigitalCommerce) {\n this.log('debug', `Product type \"${product.productType}\": no further action required`);\n return;\n }\n if (product.productType === ProductType.Post || product.productType === ProductType.Collection) {\n const bootstrap = Bootstrap.getDownloaderBootstrapDataByURL(product.url);\n if (bootstrap?.type === 'post') {\n this.log('info', `Download ${product.productType} referenced by product: ${product.url}`);\n const PostDownloader = (await import('./PostDownloader.js')).default;\n const downloader = new PostDownloader(\n {\n ...this.config,\n ...bootstrap\n },\n this.db,\n this.logger,\n {\n skipSaveCampaign: true,\n keepLoggerOpen: true,\n keepDBOpen: true\n }\n );\n try {\n await downloader.start({ signal });\n this.log('info', `Done downloading ${product.productType} referenced by product`);\n }\n catch (error) {\n if (signal?.aborted) {\n throw error;\n }\n this.log('error', `Error downloading ${product.productType} referenced by product (url: ${product.url})`, error);\n }\n let referencedEntityId: string | undefined = undefined;\n let bootstrapMismatch = false;\n if (bootstrap.postFetch.type === 'single') {\n bootstrapMismatch = product.productType !== ProductType.Post;\n referencedEntityId = bootstrap.postFetch.postId;\n }\n if (bootstrap.postFetch.type === 'byCollection') {\n bootstrapMismatch = product.productType !== ProductType.Collection;\n referencedEntityId = bootstrap.postFetch.collectionId;\n }\n if (bootstrapMismatch) {\n this.log('warn', `Product type \"${product.productType}\" does not match URL \"${product.url}\" (${bootstrap.postFetch.type})`);\n }\n else if (referencedEntityId) {\n saveReferencedEntityId(referencedEntityId);\n }\n }\n else {\n this.log('error', `Product type is \"${product.productType}\" but could not create downloader from URL \"${product.url}\"`);\n }\n return;\n }\n this.log('debug', `Unknown product type \"${product.productType}\": no further action can be taken`);\n return;\n }\n\n #isFetchingMultipleProducts(productFetch: DownloaderConfig<Product>['productFetch']): productFetch is DownloaderConfig<Product>['productFetch'] & { type: 'byShop' } {\n return productFetch.type === 'byShop';\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ProductDownloader.js","sourceRoot":"","sources":["../../src/downloaders/ProductDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import ProductParser from '../parsers/ProductParser.js';\nimport URLHelper from '../utils/URLHelper.js';\nimport Downloader, { type DownloaderConfig, type DownloaderStartParams } from './Downloader.js';\nimport StatusCache from './cache/StatusCache.js';\nimport { generateProductSummary } from './templates/ProductInfo.js';\nimport path from 'path';\nimport { TargetSkipReason } from './DownloaderEvent.js';\nimport { ProductType, type Product } from '../entities/Product.js';\nimport { type Downloadable } from '../entities/Downloadable.js';\nimport Bootstrap from './Bootstrap.js';\nimport ProductsFetcher from './ProductsFetcher.js';\nimport { type ProductDirectories } from '../utils/FSHelper.js';\nimport { type DBInstance } from '../browse/db/index.js';\nimport { IncludeCriteriaHelper } from './IncludeCriteriaHelper.js';\n\nexport default class ProductDownloader extends Downloader<Product> {\n\n static version = '1.0.1';\n\n name = 'ProductDownloader';\n\n #startPromise: Promise<void> | null = null;\n\n doStart(params?: DownloaderStartParams): Promise<void> {\n\n if (this.#startPromise) {\n throw Error('Downloader already running');\n }\n\n this.#startPromise = this.#doStart(params)\n .finally(() => {\n this.#startPromise = null;\n });\n\n return this.#startPromise;\n }\n\n async #doStart(params?: DownloaderStartParams): Promise<void> {\n try {\n const { signal } = params || {};\n const productFetch = this.config.productFetch;\n const db = await this.db();\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n if (productFetch.type === 'byShop') {\n this.log('info', `Targeting products by '${productFetch.vanity}'`);\n }\n else if (productFetch.type === 'byFile') {\n this.log('info', `Target product given by API data in \"${productFetch.filePath}\"`);\n }\n else {\n this.log('info', `Targeting product #${productFetch.productId}`);\n }\n\n // Step 1: get products (if by shop) or target product\n const productsFetcher = new ProductsFetcher({\n config: this.config,\n fetcher: this.fetcher,\n logger: this.logger,\n signal\n });\n productsFetcher.on('statusChange', ({current}) => {\n if (current.status === 'running') {\n this.emit('fetchBegin', { targetType: productsFetcher.getTargetType() });\n }\n });\n productsFetcher.begin();\n\n // Step 2: download products in each fetched list\n let downloaded = 0;\n let skippedUnviewable = 0;\n let skippedRedundant = 0;\n let skippedPublishDateOutOfRange = 0;\n let campaignSaved = false;\n let stopConditionMet = false;\n const productsParser = new ProductParser(this.logger);\n while (productsFetcher.hasNext()) {\n const { list, aborted, error } = await productsFetcher.next();\n if (!list || aborted) {\n break;\n }\n if (!list && error) {\n this.emit('end', { aborted: false, error, message: 'ProductsFetcher error' });\n return;\n }\n if (!campaignSaved && list.items[0]?.campaign) {\n await this.saveCampaignInfo(list.items[0].campaign, signal);\n campaignSaved = true;\n if (this.checkAbortSignal(signal)) {\n return;\n }\n }\n\n for (const _product of list.items) {\n\n if (stopConditionMet) {\n break;\n }\n\n let product = _product;\n\n if (this.#isFetchingMultipleProducts(productFetch)) {\n // Refresh to ensure media links have not expired\n this.log('debug', `Refresh product #${_product.id}`);\n const productURL = URLHelper.constructProductAPIURL(product.id);\n const { json } = await this.commonFetchAPI(productURL, signal);\n let refreshed: Product | null = null;\n if (json) {\n refreshed = productsParser.parseProductsAPIResponse(json, productURL).items[0] || null;\n if (!refreshed) {\n this.log('warn', `Refreshed product #${_product.id} but got empty value - going to use existing data`);\n }\n else if (refreshed.id !== _product.id) {\n this.log('warn', `Refreshed product #${_product.id} but ID mismatch - going to use existing data`);\n refreshed = null;\n }\n else {\n // Refreshed data does not have productType - reinstate it\n refreshed.productType = _product.productType;\n }\n }\n else if (this.checkAbortSignal(signal)) {\n return;\n }\n else {\n this.log('warn', `Failed to refresh product #${_product.id} - going to use existing data`);\n }\n if (refreshed) {\n this.log('debug', `Use refreshed product data #${refreshed.id}`);\n product = refreshed;\n }\n }\n\n this.emit('targetBegin', { target: product });\n\n // Step 4.1: product directories\n const productDirs = this.fsHelper.getProductDirs(product);\n this.log('debug', 'Product directories:', productDirs);\n\n // Step 4.2: Check with status cache\n const statusCache = StatusCache.getInstance(this.config, productDirs.statusCache, this.logger);\n if (!product.productType || product.productType === ProductType.DigitalCommerce) {\n const statusCacheValidation = statusCache.validate(product, productDirs.root, this.config)\n if (!statusCacheValidation.invalidated) {\n this.log('info', `Skipped downloading product #${product.id}: already downloaded`);\n this.emit('targetEnd', {\n target: product,\n isSkipped: true,\n skipReason: TargetSkipReason.AlreadyDownloaded,\n skipMessage: 'Target already downloaded'\n });\n skippedRedundant++;\n if (this.config.stopOn === 'previouslyDownloaded') {\n stopConditionMet = true;\n }\n continue;\n }\n }\n \n switch ((await this.#doDownload(\n product,\n productDirs,\n statusCache,\n db,\n signal\n )).status) {\n case 'aborted':\n return;\n case 'downloaded':\n downloaded++;\n break;\n case 'skippedPublishDateOutOfRange':\n skippedPublishDateOutOfRange++;\n if (this.config.stopOn === 'postPublishDateOutOfRange' ||\n this.config.stopOn === 'publishDateOutOfRange'\n ) {\n stopConditionMet = true;\n }\n break;\n case 'skippedUnviewable':\n skippedUnviewable++;\n break;\n }\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n }\n\n if (stopConditionMet) {\n break;\n }\n }\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n if (stopConditionMet && this.#isFetchingMultipleProducts(productFetch)) {\n this.log('info', `Stop downloader: stop condition \"${this.config.stopOn}\" met`)\n }\n\n // Done\n if (productFetch.type === 'byShop') {\n this.log('info', `Done downloading products by '${productFetch.vanity}'`);\n }\n else if (productFetch.type === 'byFile') {\n this.log('info', `Done downloading product given in \"${productFetch.filePath}\"`);\n }\n else {\n this.log('info', `Done downloading product #${productFetch.productId}`);\n }\n let endMessage = 'Done';\n if (this.#isFetchingMultipleProducts(productFetch)) {\n const skippedStrParts: string[] = [];\n if (skippedUnviewable) {\n skippedStrParts.push(`${skippedUnviewable} unviewable`);\n }\n if (skippedRedundant) {\n skippedStrParts.push(`${skippedRedundant} redundant`);\n }\n if (skippedPublishDateOutOfRange) {\n skippedStrParts.push(`${skippedPublishDateOutOfRange} with publish date out of range`);\n }\n const skippedStr = skippedStrParts.length > 0 ? ` (skipped: ${skippedStrParts.join(', ')})` : '';\n endMessage = `Total ${downloaded} / ${productsFetcher.getTotal()} products processed${skippedStr}`;\n this.log('info', endMessage);\n }\n this.emit('end', { aborted: false, message: endMessage });\n }\n finally {\n await this.closeDB();\n if (this.logger) {\n await this.logger.end();\n }\n }\n }\n\n async #doDownload(\n product: Product,\n productDirs: ProductDirectories,\n statusCache: StatusCache,\n db: DBInstance,\n signal?: AbortSignal\n ): Promise<{status: 'skippedUnviewable' | 'skippedPublishDateOutOfRange' | 'aborted' | 'downloaded' }> {\n // Step 1: Check whether we should download product\n const criteriaHelper = new IncludeCriteriaHelper(this.logger);\n const criteriaCheck = criteriaHelper.checkProduct(product, this.config);\n if (!criteriaCheck.ok) {\n switch (criteriaCheck.reason) {\n case 'unviewable': {\n this.log('warn', `Skipped downloading product #${product.id}: not accessible by current user`);\n this.emit('targetEnd', {\n target: product,\n isSkipped: true,\n skipReason: TargetSkipReason.Inaccessible,\n skipMessage: 'Target is not accessible by current user'\n });\n return {\n status: 'skippedUnviewable'\n };\n }\n case 'publishDateOutOfRange': {\n this.log('warn', `Skipped downloading product #${product.id}: publish date out of range`);\n this.emit('targetEnd', {\n target: product,\n isSkipped: true,\n skipReason: TargetSkipReason.PublishDateOutOfRange,\n skipMessage: 'Publish date out of range'\n });\n return {\n status: 'skippedPublishDateOutOfRange'\n };\n }\n }\n }\n\n if (!product.isAccessible && this.config.include.lockedContent) {\n this.log('warn', `Product #${product.id} is not accessible by current user`);\n }\n\n this.fsHelper.createDir(productDirs.root);\n\n // Step 2: save product info\n if (this.config.include.contentInfo) {\n this.log('info', 'Save product info');\n this.emit('phaseBegin', { target: product, phase: 'saveInfo' });\n this.fsHelper.createDir(productDirs.info);\n const summary = generateProductSummary(product);\n const summaryFile = path.resolve(productDirs.info, 'info.txt');\n const saveSummaryResult = await this.fsHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, product, 'product summary');\n\n const productRawFile = path.resolve(productDirs.info, 'product-api.json');\n const saveProductRawResult = await this.fsHelper.writeTextFile(\n productRawFile, product.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(saveProductRawResult, product, 'product API data');\n this.emit('phaseEnd', { target: product, phase: 'saveInfo' });\n }\n\n // Step 3: Download product media items\n const incPreview = this.config.include.previewMedia;\n const incContent = this.config.include.contentMedia;\n this.log('info', 'Download:', {\n ['preview items']: incPreview === true ? 'yes' : incPreview === false ? 'no' : JSON.stringify(incPreview),\n ['content items']: incContent === true ? 'yes' : incContent === false ? 'no' : JSON.stringify(incContent)\n });\n\n const __inc = (inc: boolean | Array<any>, target: Downloadable) => {\n if (typeof inc === 'boolean') {\n return inc;\n }\n return (inc.includes(target.type as any));\n };\n\n const previewMedia = product.previewMedia.filter((tt) => __inc(incPreview, tt));\n const contentMedia = product.contentMedia.filter((tt) => __inc(incContent, tt));\n const campaignDir = product.campaign ? this.fsHelper.getCampaignDirs(product.campaign).root : null;\n\n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseBegin', { target: product, phase: 'saveMedia' });\n const batchResult = await this.createDownloadTaskBatch(\n `Product #${product.id} (${product.name})`,\n signal,\n\n previewMedia.length > 0 ? {\n target: previewMedia,\n targetName: `product #${product.id} -> preview media`,\n src: product,\n dirs: {\n campaign: campaignDir,\n main: productDirs.previewMedia,\n thumbnails: productDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n contentMedia.length > 0 ? {\n target: contentMedia,\n targetName: `product #${product.id} -> content media`,\n src: product,\n dirs: {\n campaign: campaignDir,\n main: productDirs.contentMedia,\n thumbnails: productDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content,\n ignoreCreateTaskErrors: !product.isAccessible\n } : null\n );\n\n const { batch } = batchResult;\n\n const abortHandler = () => {\n void (async () => {\n this.log('info', 'Abort signal received');\n if (batch) {\n await batch.abort();\n }\n })();\n };\n if (signal) {\n signal.addEventListener('abort', abortHandler, { once: true });\n }\n \n try {\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n \n batch.prestart();\n this.log('info', `Download batch created (#${batch.id}): ${batch.getTasks('pending').length} downloads pending`);\n this.emit('phaseBegin', { target: product, phase: 'batchDownload', batch });\n\n await batch.start();\n\n // Step 4: Update status cache\n statusCache.updateOnDownload(product, productDirs.root, batch.getTasks('error').length > 0 || batchResult.errorCount > 0, this.config);\n\n await batch.destroy();\n }\n finally {\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n }\n\n this.emit('phaseEnd', { target: product, phase: 'batchDownload' });\n this.emit('phaseEnd', { target: product, phase: 'saveMedia' });\n }\n\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n\n // Step 5: Save to DB\n let skipDB = false;\n let saveReferencedEntityId: (id: string) => void;\n const dbProduct = db.getContent(product.id, 'product');\n if (!product.isAccessible) {\n // Skip if existing db record (if any) refers to accessible product\n skipDB = dbProduct !== null && dbProduct.isAccessible;\n }\n if (!skipDB) {\n db.saveContent(product);\n saveReferencedEntityId = (id) => {\n product.referencedEntityId = id;\n db.saveContent(product);\n };\n }\n else {\n this.log('info', `Skip overwrite existing accessible product #${product.id} in DB with current unviewable version`);\n saveReferencedEntityId = (id) => {\n // Ensure referencedEntityId is updated\n dbProduct!.referencedEntityId = id;\n db.saveContent(dbProduct!);\n };\n }\n\n // Step 6: check product type and download referenced product / collection\n await this.#processProductType(product, saveReferencedEntityId, signal);\n\n // Done\n this.log('info', `Done downloading product #${product.id}`);\n this.emit('targetEnd', { target: product, isSkipped: false });\n\n return {\n status: 'downloaded'\n }\n }\n\n // Carry out further action based on product type\n async #processProductType(\n product: Product,\n saveReferencedEntityId: (id: string) => void,\n signal?: AbortSignal\n ) {\n if (product.productType === undefined || product.productType === ProductType.DigitalCommerce) {\n this.log('debug', `Product type \"${product.productType}\": no further action required`);\n return;\n }\n if (product.productType === ProductType.Post || product.productType === ProductType.Collection) {\n const bootstrap = Bootstrap.getDownloaderBootstrapDataByURL(product.url);\n if (bootstrap?.type === 'post') {\n this.log('info', `Download ${product.productType} referenced by product: ${product.url}`);\n const PostDownloader = (await import('./PostDownloader.js')).default;\n const downloader = new PostDownloader(\n {\n ...this.config,\n ...bootstrap\n },\n this.db,\n this.logger,\n {\n skipSaveCampaign: true,\n keepLoggerOpen: true,\n keepDBOpen: true\n }\n );\n try {\n await downloader.start({ signal });\n this.log('info', `Done downloading ${product.productType} referenced by product`);\n }\n catch (error) {\n if (signal?.aborted) {\n throw error;\n }\n this.log('error', `Error downloading ${product.productType} referenced by product (url: ${product.url})`, error);\n }\n let referencedEntityId: string | undefined = undefined;\n let bootstrapMismatch = false;\n if (bootstrap.postFetch.type === 'single') {\n bootstrapMismatch = product.productType !== ProductType.Post;\n referencedEntityId = bootstrap.postFetch.postId;\n }\n if (bootstrap.postFetch.type === 'byCollection') {\n bootstrapMismatch = product.productType !== ProductType.Collection;\n referencedEntityId = bootstrap.postFetch.collectionId;\n }\n if (bootstrapMismatch) {\n this.log('warn', `Product type \"${product.productType}\" does not match URL \"${product.url}\" (${bootstrap.postFetch.type})`);\n }\n else if (referencedEntityId) {\n saveReferencedEntityId(referencedEntityId);\n }\n }\n else {\n this.log('error', `Product type is \"${product.productType}\" but could not create downloader from URL \"${product.url}\"`);\n }\n return;\n }\n this.log('debug', `Unknown product type \"${product.productType}\": no further action can be taken`);\n return;\n }\n\n #isFetchingMultipleProducts(productFetch: DownloaderConfig<Product>['productFetch']): productFetch is DownloaderConfig<Product>['productFetch'] & { type: 'byShop' } {\n return productFetch.type === 'byShop';\n }\n}\n"]}
|
|
@@ -14,6 +14,7 @@ export default class M3U8DownloadTask extends FFmpegDownloadTaskBase<VideoMediaI
|
|
|
14
14
|
#private;
|
|
15
15
|
name: string;
|
|
16
16
|
constructor(params: M3U8DownloadTaskParams);
|
|
17
|
+
start(): Promise<void>;
|
|
17
18
|
protected resolveDestPath(signal?: AbortSignal): Promise<string>;
|
|
18
19
|
protected getFFmpegCommandParams(signal?: AbortSignal): Promise<M3U8FFmpegCommandParams>;
|
|
19
20
|
protected getTargetDuration(): number | null;
|
|
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _M3U8DownloadTask_instances, _M3U8DownloadTask_fetcher, _M3U8DownloadTask_unresolvedDestFilePath, _M3U8DownloadTask_ffmpegCommandParams, _M3U8DownloadTask_pickVariant;
|
|
12
|
+
var _M3U8DownloadTask_instances, _M3U8DownloadTask_skipOnStart, _M3U8DownloadTask_fetcher, _M3U8DownloadTask_unresolvedDestFilePath, _M3U8DownloadTask_ffmpegCommandParams, _M3U8DownloadTask_pickVariant, _M3U8DownloadTask_getProtectionStatus, _M3U8DownloadTask_getResolutionString;
|
|
13
13
|
import { SITE_URL } from '../../utils/URLHelper.js';
|
|
14
14
|
import FFmpegDownloadTaskBase from './FFmpegDownloadTaskBase.js';
|
|
15
15
|
import semver from 'semver';
|
|
@@ -22,12 +22,23 @@ class M3U8DownloadTask extends FFmpegDownloadTaskBase {
|
|
|
22
22
|
super(params);
|
|
23
23
|
_M3U8DownloadTask_instances.add(this);
|
|
24
24
|
this.name = 'M3U8DownloadTask';
|
|
25
|
+
_M3U8DownloadTask_skipOnStart.set(this, void 0);
|
|
25
26
|
_M3U8DownloadTask_fetcher.set(this, void 0);
|
|
26
27
|
_M3U8DownloadTask_unresolvedDestFilePath.set(this, void 0);
|
|
27
28
|
_M3U8DownloadTask_ffmpegCommandParams.set(this, void 0);
|
|
28
29
|
__classPrivateFieldSet(this, _M3U8DownloadTask_fetcher, params.fetcher, "f");
|
|
29
30
|
__classPrivateFieldSet(this, _M3U8DownloadTask_unresolvedDestFilePath, params.destFilePath, "f");
|
|
30
31
|
__classPrivateFieldSet(this, _M3U8DownloadTask_ffmpegCommandParams, null, "f");
|
|
32
|
+
__classPrivateFieldSet(this, _M3U8DownloadTask_skipOnStart, null, "f");
|
|
33
|
+
}
|
|
34
|
+
async start() {
|
|
35
|
+
if (__classPrivateFieldGet(this, _M3U8DownloadTask_skipOnStart, "f")) {
|
|
36
|
+
return this.notifySkip({
|
|
37
|
+
name: 'other',
|
|
38
|
+
message: __classPrivateFieldGet(this, _M3U8DownloadTask_skipOnStart, "f").reason,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return await super.start();
|
|
31
42
|
}
|
|
32
43
|
async resolveDestPath(signal) {
|
|
33
44
|
const params = await this.getFFmpegCommandParams(signal);
|
|
@@ -38,6 +49,11 @@ class M3U8DownloadTask extends FFmpegDownloadTaskBase {
|
|
|
38
49
|
return __classPrivateFieldGet(this, _M3U8DownloadTask_ffmpegCommandParams, "f");
|
|
39
50
|
}
|
|
40
51
|
const input = await __classPrivateFieldGet(this, _M3U8DownloadTask_instances, "m", _M3U8DownloadTask_pickVariant).call(this, signal);
|
|
52
|
+
if (input.src === null) {
|
|
53
|
+
__classPrivateFieldSet(this, _M3U8DownloadTask_skipOnStart, {
|
|
54
|
+
reason: `No downloadable source - ${input.reason}`
|
|
55
|
+
}, "f");
|
|
56
|
+
}
|
|
41
57
|
const inputOptions = [
|
|
42
58
|
'-protocol_whitelist',
|
|
43
59
|
'http,https,tcp,tls',
|
|
@@ -49,22 +65,38 @@ class M3U8DownloadTask extends FFmpegDownloadTaskBase {
|
|
|
49
65
|
inputOptions.push('-extension_picky', '0');
|
|
50
66
|
}
|
|
51
67
|
let output = __classPrivateFieldGet(this, _M3U8DownloadTask_unresolvedDestFilePath, "f");
|
|
52
|
-
if (
|
|
53
|
-
if (input.resolution) {
|
|
54
|
-
|
|
55
|
-
const {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
if (input.src) {
|
|
69
|
+
if (input.protected || input.resolution) {
|
|
70
|
+
const parsedFilePath = path.parse(__classPrivateFieldGet(this, _M3U8DownloadTask_unresolvedDestFilePath, "f"));
|
|
71
|
+
const { ext, dir } = parsedFilePath;
|
|
72
|
+
let filename = parsedFilePath.name;
|
|
73
|
+
if (input.resolution) {
|
|
74
|
+
filename += ` (${input.resolution})`;
|
|
75
|
+
}
|
|
76
|
+
if (input.protected) {
|
|
77
|
+
filename += ' drm';
|
|
78
|
+
}
|
|
79
|
+
output = path.resolve(dir, FSHelper.sanitizeFilename(`${filename}${ext}`));
|
|
60
80
|
}
|
|
81
|
+
const criteria = JSON.stringify({
|
|
82
|
+
'max video resolution': this.config.maxVideoResolution || undefined,
|
|
83
|
+
'include protected media': this.config.include.protectedMedia ? 'yes' : undefined
|
|
84
|
+
});
|
|
85
|
+
const criteriaStr = criteria === '{}' ? '' : ` matching criteria ${JSON.stringify(criteria)}`;
|
|
86
|
+
const streamInfoParts = [
|
|
87
|
+
input.resolution || 'unknown resolution',
|
|
88
|
+
input.protected === true ? 'protected'
|
|
89
|
+
: input.protected === false ? ''
|
|
90
|
+
: 'unknown'
|
|
91
|
+
];
|
|
92
|
+
this.log('info', `Target stream${criteriaStr}:`, streamInfoParts.join(';'));
|
|
61
93
|
}
|
|
62
94
|
__classPrivateFieldSet(this, _M3U8DownloadTask_ffmpegCommandParams, {
|
|
63
95
|
inputs: [
|
|
64
96
|
{
|
|
65
|
-
input: input.src,
|
|
97
|
+
input: input.src || this.src,
|
|
66
98
|
options: inputOptions,
|
|
67
|
-
resolution: input.resolution
|
|
99
|
+
resolution: input.src ? input.resolution : null
|
|
68
100
|
}
|
|
69
101
|
],
|
|
70
102
|
output
|
|
@@ -75,54 +107,120 @@ class M3U8DownloadTask extends FFmpegDownloadTaskBase {
|
|
|
75
107
|
return this.srcEntity.duration;
|
|
76
108
|
}
|
|
77
109
|
}
|
|
78
|
-
_M3U8DownloadTask_fetcher = new WeakMap(), _M3U8DownloadTask_unresolvedDestFilePath = new WeakMap(), _M3U8DownloadTask_ffmpegCommandParams = new WeakMap(), _M3U8DownloadTask_instances = new WeakSet(), _M3U8DownloadTask_pickVariant = async function _M3U8DownloadTask_pickVariant(signal) {
|
|
79
|
-
const
|
|
80
|
-
if (!maxResolution || maxResolution < 0) {
|
|
81
|
-
return {
|
|
82
|
-
src: this.src,
|
|
83
|
-
resolution: null
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
this.log('debug', `Apply maxVideoResolution "${maxResolution}"`);
|
|
87
|
-
const { html: m3u8 } = await __classPrivateFieldGet(this, _M3U8DownloadTask_fetcher, "f").get({
|
|
110
|
+
_M3U8DownloadTask_skipOnStart = new WeakMap(), _M3U8DownloadTask_fetcher = new WeakMap(), _M3U8DownloadTask_unresolvedDestFilePath = new WeakMap(), _M3U8DownloadTask_ffmpegCommandParams = new WeakMap(), _M3U8DownloadTask_instances = new WeakSet(), _M3U8DownloadTask_pickVariant = async function _M3U8DownloadTask_pickVariant(signal) {
|
|
111
|
+
const { contents: m3u8 } = await __classPrivateFieldGet(this, _M3U8DownloadTask_fetcher, "f").get({
|
|
88
112
|
url: this.src,
|
|
89
|
-
type: '
|
|
113
|
+
type: 'm3u8',
|
|
90
114
|
maxRetries: this.config.request.maxRetries,
|
|
91
115
|
signal
|
|
92
116
|
});
|
|
93
117
|
const parser = new m3u8Parser.Parser();
|
|
94
118
|
parser.push(m3u8);
|
|
95
119
|
parser.end();
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
120
|
+
if (!parser.manifest.playlists || parser.manifest.playlists.length === 0) {
|
|
121
|
+
this.log('warn', `No stream found in m3u8 manifest - going to download without stream selection`);
|
|
122
|
+
return {
|
|
123
|
+
src: this.src,
|
|
124
|
+
resolution: 'best quality',
|
|
125
|
+
protected: undefined
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const orderedPlaylistItems = parser.manifest.playlists
|
|
129
|
+
.sort((a, b) => {
|
|
130
|
+
// 1. Get heights or 0
|
|
131
|
+
const heightA = a.attributes.RESOLUTION?.height || 0;
|
|
132
|
+
const heightB = b.attributes.RESOLUTION?.height || 0;
|
|
133
|
+
// 2. If heights are different, sort by height
|
|
134
|
+
if (heightB !== heightA) {
|
|
135
|
+
return heightB - heightA;
|
|
136
|
+
}
|
|
137
|
+
// 3. If heights are the same (or both 0), sort by BANDWIDTH
|
|
138
|
+
const bandwidthA = a.attributes.BANDWIDTH || 0;
|
|
139
|
+
const bandwidthB = b.attributes.BANDWIDTH || 0;
|
|
140
|
+
return bandwidthB - bandwidthA;
|
|
141
|
+
});
|
|
142
|
+
let variants = await __classPrivateFieldGet(this, _M3U8DownloadTask_instances, "m", _M3U8DownloadTask_getProtectionStatus).call(this, orderedPlaylistItems, signal);
|
|
143
|
+
if (variants.every((v) => v.protected === false) && !this.config.maxVideoResolution) {
|
|
100
144
|
return {
|
|
101
145
|
src: this.src,
|
|
102
|
-
resolution:
|
|
146
|
+
resolution: 'best quality',
|
|
147
|
+
protected: false
|
|
103
148
|
};
|
|
104
149
|
}
|
|
150
|
+
this.log('debug', `m3u8 has ${variants?.length ?? 0} variants (src: ${this.src})`);
|
|
151
|
+
// include.protectedMedia
|
|
152
|
+
if (!this.config.include.protectedMedia) {
|
|
153
|
+
const prevLength = variants.length;
|
|
154
|
+
variants = variants.filter((v) => !v.protected);
|
|
155
|
+
if (variants.length === 0) {
|
|
156
|
+
this.log('debug', 'All streams are protected');
|
|
157
|
+
return {
|
|
158
|
+
src: null,
|
|
159
|
+
reason: 'Media is protected'
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
this.log('debug', `${(prevLength - variants.length) / prevLength} streams are protected`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// maxVideoResolution
|
|
167
|
+
const maxResolution = this.config.maxVideoResolution;
|
|
168
|
+
const hasMaxResolutionConfigured = maxResolution && maxResolution > 0;
|
|
105
169
|
const __hasAudio = (variant) => {
|
|
106
170
|
const codecs = variant.attributes.CODECS || "";
|
|
107
171
|
return codecs.includes("mp4a"); // crude check for AAC audio
|
|
108
172
|
};
|
|
109
173
|
const allWithoutAudio = variants.every((v) => !__hasAudio(v));
|
|
110
|
-
|
|
111
|
-
.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
174
|
+
if (hasMaxResolutionConfigured) {
|
|
175
|
+
this.log('debug', `Apply maxVideoResolution "${maxResolution}"`);
|
|
176
|
+
const maxResCandidates = variants
|
|
177
|
+
.filter((v) => (v.attributes.RESOLUTION && v.attributes.RESOLUTION.height <= maxResolution) && (allWithoutAudio || __hasAudio(v)));
|
|
178
|
+
if (maxResCandidates.length === 0) {
|
|
179
|
+
this.log('debug', `No stream in m3u8 manifest has resolution "${maxResolution}" or lower - maxVideoResolution not applied`);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
variants = maxResCandidates;
|
|
183
|
+
}
|
|
119
184
|
}
|
|
120
|
-
const selected =
|
|
121
|
-
this.log('debug', `Video at or below resolution "${maxResolution}": ${selected.uri} (${JSON.stringify(selected.attributes.RESOLUTION)})`);
|
|
185
|
+
const selected = variants[0];
|
|
122
186
|
return {
|
|
123
187
|
src: new URL(selected.uri, this.src).href,
|
|
124
|
-
resolution:
|
|
188
|
+
resolution: __classPrivateFieldGet(this, _M3U8DownloadTask_instances, "m", _M3U8DownloadTask_getResolutionString).call(this, selected),
|
|
189
|
+
protected: selected.protected
|
|
125
190
|
};
|
|
191
|
+
}, _M3U8DownloadTask_getProtectionStatus = async function _M3U8DownloadTask_getProtectionStatus(variants, signal) {
|
|
192
|
+
return await Promise.all(variants.map((variant) => __classPrivateFieldGet(this, _M3U8DownloadTask_fetcher, "f").get({
|
|
193
|
+
url: variant.uri,
|
|
194
|
+
type: 'm3u8',
|
|
195
|
+
maxRetries: this.config.request.maxRetries,
|
|
196
|
+
signal
|
|
197
|
+
})
|
|
198
|
+
.then(({ contents: m3u8 }) => {
|
|
199
|
+
const parser = new m3u8Parser.Parser();
|
|
200
|
+
parser.push(m3u8);
|
|
201
|
+
parser.end();
|
|
202
|
+
const protectionData = parser.manifest.contentProtection;
|
|
203
|
+
const _protected = !!(protectionData && typeof protectionData === 'object' && Object.entries(protectionData).length > 0);
|
|
204
|
+
return {
|
|
205
|
+
...variant,
|
|
206
|
+
protected: _protected
|
|
207
|
+
};
|
|
208
|
+
})
|
|
209
|
+
.catch((error) => {
|
|
210
|
+
if (signal?.aborted) {
|
|
211
|
+
throw error;
|
|
212
|
+
}
|
|
213
|
+
this.log('warn', `Could not determine if stream (${__classPrivateFieldGet(this, _M3U8DownloadTask_instances, "m", _M3U8DownloadTask_getResolutionString).call(this, variant)}) is protected:`, error);
|
|
214
|
+
return {
|
|
215
|
+
...variant,
|
|
216
|
+
protected: undefined
|
|
217
|
+
};
|
|
218
|
+
})));
|
|
219
|
+
}, _M3U8DownloadTask_getResolutionString = function _M3U8DownloadTask_getResolutionString(item) {
|
|
220
|
+
if (item.attributes.RESOLUTION?.width && item.attributes.RESOLUTION?.height) {
|
|
221
|
+
return `${item.attributes.RESOLUTION.width}x${item.attributes.RESOLUTION.height}`;
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
126
224
|
};
|
|
127
225
|
export default M3U8DownloadTask;
|
|
128
226
|
//# sourceMappingURL=M3U8DownloadTask.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"M3U8DownloadTask.js","sourceRoot":"","sources":["../../../src/downloaders/task/M3U8DownloadTask.ts"],"names":[],"mappings":"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","sourcesContent":["import { type VideoMediaItem } from '../../entities/MediaItem.js';\nimport { SITE_URL } from '../../utils/URLHelper.js';\nimport FFmpegDownloadTaskBase, { type FFmpegCommandParams, type FFmpegDownloadTaskBaseParams } from './FFmpegDownloadTaskBase.js';\nimport semver from 'semver';\nimport m3u8Parser from 'm3u8-parser';\nimport type Fetcher from '../../utils/Fetcher.js';\nimport FSHelper from '../../utils/FSHelper.js';\nimport path from 'path';\n\nexport interface M3U8DownloadTaskParams extends FFmpegDownloadTaskBaseParams<VideoMediaItem> {\n fetcher: Fetcher;\n destFilePath: string;\n}\n\ninterface M3U8FFmpegCommandParams extends FFmpegCommandParams {\n inputs: (FFmpegCommandParams['inputs'][number] & { resolution: string | null })[];\n};\n\nexport default class M3U8DownloadTask extends FFmpegDownloadTaskBase<VideoMediaItem> {\n\n name = 'M3U8DownloadTask';\n\n #fetcher: Fetcher;\n #unresolvedDestFilePath: string;\n #ffmpegCommandParams: M3U8FFmpegCommandParams | null;\n\n constructor(params: M3U8DownloadTaskParams) {\n super(params);\n this.#fetcher = params.fetcher;\n this.#unresolvedDestFilePath = params.destFilePath;\n this.#ffmpegCommandParams = null;\n }\n\n protected async resolveDestPath(signal?: AbortSignal) {\n const params = await this.getFFmpegCommandParams(signal);\n return params.output;\n }\n\n protected async getFFmpegCommandParams(signal?: AbortSignal): Promise<M3U8FFmpegCommandParams> {\n if (this.#ffmpegCommandParams) {\n return this.#ffmpegCommandParams;\n }\n const input = await this.#pickVariant(signal);\n const inputOptions = [\n '-protocol_whitelist',\n 'http,https,tcp,tls',\n '-headers',\n `Referer: ${SITE_URL}`\n ];\n // `extension_picky` introduced in v7.1.1\n if (semver.satisfies(this.getFFmpegVersion(), '>=7.1.1')) {\n inputOptions.push('-extension_picky', '0');\n }\n let output = this.#unresolvedDestFilePath;\n if (this.config.maxVideoResolution && this.config.maxVideoResolution > 0) {\n if (input.resolution) {\n this.log('info', `Video found with resolution at or below specified max resolution \"${this.config.maxVideoResolution}\": ${input.resolution}`);\n const { name: filename, ext, dir } = path.parse(this.#unresolvedDestFilePath);\n output = path.resolve(dir, FSHelper.sanitizeFilename(`${filename} (${input.resolution})${ext}`));\n }\n else {\n this.log('info', `No video found with resolution at or below specified max resolution \"${this.config.maxVideoResolution}\" - going to download highest`);\n }\n }\n\n this.#ffmpegCommandParams = {\n inputs: [\n {\n input: input.src,\n options: inputOptions,\n resolution: input.resolution\n }\n ],\n output\n };\n\n return this.#ffmpegCommandParams;\n }\n\n protected getTargetDuration(): number | null {\n return this.srcEntity.duration;\n }\n\n async #pickVariant(signal?: AbortSignal) {\n const maxResolution = this.config.maxVideoResolution;\n if (!maxResolution || maxResolution < 0) {\n return {\n src: this.src,\n resolution: null\n };\n }\n\n this.log('debug', `Apply maxVideoResolution \"${maxResolution}\"`);\n\n const { html: m3u8 } = await this.#fetcher.get({\n url: this.src,\n type: 'html',\n maxRetries: this.config.request.maxRetries,\n signal\n });\n const parser = new m3u8Parser.Parser();\n parser.push(m3u8);\n parser.end();\n\n const variants = parser.manifest.playlists;\n\n this.log('debug', `m3u8 has ${variants?.length ?? 0} variants (src: ${this.src})`);\n \n if (!variants) {\n this.log('debug', `No videos found in m3u8 manifest - going to download video with highest resolution`);\n return {\n src: this.src,\n resolution: null\n };\n }\n \n const __hasAudio = (variant: typeof variants[number]) => {\n const codecs = variant.attributes.CODECS || \"\";\n return codecs.includes(\"mp4a\"); // crude check for AAC audio\n }\n\n const allWithoutAudio = variants.every((v) => !__hasAudio(v));\n\n const filtered = variants\n .filter((v) => (v.attributes.RESOLUTION && v.attributes.RESOLUTION.height <= maxResolution) && (allWithoutAudio || __hasAudio(v)))\n .sort((a, b) => b.attributes.RESOLUTION!.height - a.attributes.RESOLUTION!.height);\n\n if (filtered.length === 0) {\n this.log('debug', `No video found in m3u8 manifest at or below resolution \"${maxResolution}\" - going to download video with highest resolution`);\n return {\n src: this.src,\n resolution: null\n };\n }\n\n const selected = filtered[0];\n\n this.log('debug', `Video at or below resolution \"${maxResolution}\": ${selected.uri} (${JSON.stringify(selected.attributes.RESOLUTION)})`);\n\n return {\n src: new URL(selected.uri, this.src).href,\n resolution: `${selected.attributes.RESOLUTION!.width}x${selected.attributes.RESOLUTION!.height}`\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"M3U8DownloadTask.js","sourceRoot":"","sources":["../../../src/downloaders/task/M3U8DownloadTask.ts"],"names":[],"mappings":"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","sourcesContent":["import { type VideoMediaItem } from '../../entities/MediaItem.js';\nimport { SITE_URL } from '../../utils/URLHelper.js';\nimport FFmpegDownloadTaskBase, { type FFmpegCommandParams, type FFmpegDownloadTaskBaseParams } from './FFmpegDownloadTaskBase.js';\nimport semver from 'semver';\nimport m3u8Parser, { type PlaylistItem } from 'm3u8-parser';\nimport type Fetcher from '../../utils/Fetcher.js';\nimport FSHelper from '../../utils/FSHelper.js';\nimport path from 'path';\n\ninterface Variant extends PlaylistItem {\n protected?: boolean;\n}\n\ntype PickVariantResult = {\n src: null;\n reason: string;\n} | {\n src: string;\n resolution: string | null,\n protected?: boolean;\n};\n\nexport interface M3U8DownloadTaskParams extends FFmpegDownloadTaskBaseParams<VideoMediaItem> {\n fetcher: Fetcher;\n destFilePath: string;\n}\n\ninterface M3U8FFmpegCommandParams extends FFmpegCommandParams {\n inputs: (FFmpegCommandParams['inputs'][number] & { resolution: string | null })[];\n};\n\nexport default class M3U8DownloadTask extends FFmpegDownloadTaskBase<VideoMediaItem> {\n\n name = 'M3U8DownloadTask';\n\n #skipOnStart: {\n reason: string;\n } | null;\n #fetcher: Fetcher;\n #unresolvedDestFilePath: string;\n #ffmpegCommandParams: M3U8FFmpegCommandParams | null;\n\n constructor(params: M3U8DownloadTaskParams) {\n super(params);\n this.#fetcher = params.fetcher;\n this.#unresolvedDestFilePath = params.destFilePath;\n this.#ffmpegCommandParams = null;\n this.#skipOnStart = null;\n }\n\n async start() {\n if (this.#skipOnStart) {\n return this.notifySkip({\n name: 'other',\n message: this.#skipOnStart.reason,\n });\n }\n return await super.start();\n }\n\n protected async resolveDestPath(signal?: AbortSignal) {\n const params = await this.getFFmpegCommandParams(signal);\n return params.output;\n }\n\n protected async getFFmpegCommandParams(signal?: AbortSignal): Promise<M3U8FFmpegCommandParams> {\n if (this.#ffmpegCommandParams) {\n return this.#ffmpegCommandParams;\n }\n\n const input = await this.#pickVariant(signal);\n if (input.src === null) {\n this.#skipOnStart = {\n reason: `No downloadable source - ${input.reason}`\n };\n }\n\n const inputOptions = [\n '-protocol_whitelist',\n 'http,https,tcp,tls',\n '-headers',\n `Referer: ${SITE_URL}`\n ];\n // `extension_picky` introduced in v7.1.1\n if (semver.satisfies(this.getFFmpegVersion(), '>=7.1.1')) {\n inputOptions.push('-extension_picky', '0');\n }\n let output = this.#unresolvedDestFilePath;\n if (input.src) {\n if (input.protected || input.resolution) {\n const parsedFilePath = path.parse(this.#unresolvedDestFilePath);\n const { ext, dir } = parsedFilePath;\n let filename = parsedFilePath.name;\n if (input.resolution) {\n filename += ` (${input.resolution})`;\n }\n if (input.protected) {\n filename += ' drm';\n }\n output = path.resolve(dir, FSHelper.sanitizeFilename(`${filename}${ext}`));\n }\n\n const criteria = JSON.stringify({\n 'max video resolution': this.config.maxVideoResolution || undefined,\n 'include protected media': this.config.include.protectedMedia ? 'yes' : undefined\n });\n const criteriaStr = criteria === '{}' ? '' : ` matching criteria ${JSON.stringify(criteria)}`;\n const streamInfoParts = [\n input.resolution || 'unknown resolution',\n input.protected === true ? 'protected'\n : input.protected === false ? ''\n : 'unknown'\n ];\n this.log('info', `Target stream${criteriaStr}:`, streamInfoParts.join(';'));\n }\n\n this.#ffmpegCommandParams = {\n inputs: [\n {\n input: input.src || this.src,\n options: inputOptions,\n resolution: input.src ? input.resolution : null\n }\n ],\n output\n };\n\n return this.#ffmpegCommandParams;\n }\n\n protected getTargetDuration(): number | null {\n return this.srcEntity.duration;\n }\n\n async #pickVariant(signal?: AbortSignal): Promise<PickVariantResult> {\n const { contents: m3u8 } = await this.#fetcher.get({\n url: this.src,\n type: 'm3u8',\n maxRetries: this.config.request.maxRetries,\n signal\n });\n const parser = new m3u8Parser.Parser();\n parser.push(m3u8);\n parser.end();\n\n if (!parser.manifest.playlists || parser.manifest.playlists.length === 0) {\n this.log('warn', `No stream found in m3u8 manifest - going to download without stream selection`);\n return {\n src: this.src,\n resolution: 'best quality',\n protected: undefined\n };\n }\n\n const orderedPlaylistItems = parser.manifest.playlists\n .sort((a, b) => {\n // 1. Get heights or 0\n const heightA = a.attributes.RESOLUTION?.height || 0;\n const heightB = b.attributes.RESOLUTION?.height || 0;\n\n // 2. If heights are different, sort by height\n if (heightB !== heightA) {\n return heightB - heightA;\n }\n\n // 3. If heights are the same (or both 0), sort by BANDWIDTH\n const bandwidthA = a.attributes.BANDWIDTH || 0;\n const bandwidthB = b.attributes.BANDWIDTH || 0;\n\n return bandwidthB - bandwidthA;\n });\n let variants = await this.#getProtectionStatus(orderedPlaylistItems, signal);\n \n if (variants.every((v) => v.protected === false) && !this.config.maxVideoResolution) {\n return {\n src: this.src,\n resolution: 'best quality',\n protected: false\n };\n }\n\n this.log('debug', `m3u8 has ${variants?.length ?? 0} variants (src: ${this.src})`);\n \n // include.protectedMedia\n if (!this.config.include.protectedMedia) {\n const prevLength = variants.length;\n variants = variants.filter((v) => !v.protected)\n if (variants.length === 0) {\n this.log('debug', 'All streams are protected');\n return {\n src: null,\n reason: 'Media is protected'\n };\n }\n else {\n this.log('debug', `${(prevLength - variants.length) / prevLength} streams are protected`)\n }\n }\n\n // maxVideoResolution\n const maxResolution = this.config.maxVideoResolution;\n const hasMaxResolutionConfigured = maxResolution && maxResolution > 0;\n \n const __hasAudio = (variant: typeof variants[number]) => {\n const codecs = variant.attributes.CODECS || \"\";\n return codecs.includes(\"mp4a\"); // crude check for AAC audio\n }\n\n const allWithoutAudio = variants.every((v) => !__hasAudio(v));\n\n if (hasMaxResolutionConfigured) {\n this.log('debug', `Apply maxVideoResolution \"${maxResolution}\"`);\n const maxResCandidates = variants\n .filter((v) => (v.attributes.RESOLUTION && v.attributes.RESOLUTION.height <= maxResolution) && (allWithoutAudio || __hasAudio(v)));\n if (maxResCandidates.length === 0 ) {\n this.log('debug', `No stream in m3u8 manifest has resolution \"${maxResolution}\" or lower - maxVideoResolution not applied`);\n }\n else {\n variants = maxResCandidates;\n }\n }\n\n const selected = variants[0];\n\n return {\n src: new URL(selected.uri, this.src).href,\n resolution: this.#getResolutionString(selected),\n protected: selected.protected\n };\n }\n\n async #getProtectionStatus(variants: PlaylistItem[], signal?: AbortSignal): Promise<Variant[]> {\n return await Promise.all(variants.map((variant) =>\n this.#fetcher.get({\n url: variant.uri,\n type: 'm3u8',\n maxRetries: this.config.request.maxRetries,\n signal\n })\n .then(({contents: m3u8}) => {\n const parser = new m3u8Parser.Parser();\n parser.push(m3u8);\n parser.end();\n const protectionData = parser.manifest.contentProtection;\n const _protected = !!(protectionData && typeof protectionData === 'object' && Object.entries(protectionData).length > 0);\n return {\n ...variant,\n protected: _protected\n };\n })\n .catch((error: unknown) => {\n if (signal?.aborted) {\n throw error;\n }\n this.log('warn', `Could not determine if stream (${this.#getResolutionString(variant)}) is protected:`, error);\n return {\n ...variant,\n protected: undefined\n };\n })\n ));\n }\n\n #getResolutionString(item: PlaylistItem) {\n if (item.attributes.RESOLUTION?.width && item.attributes.RESOLUTION?.height) {\n return `${item.attributes.RESOLUTION.width}x${item.attributes.RESOLUTION.height}`;\n }\n return null;\n }\n}\n"]}
|
|
@@ -321,9 +321,7 @@ _a = YouTubeDownloadTask, _YouTubeDownloadTask_destDir = new WeakMap(), _YouTube
|
|
|
321
321
|
return (await InnertubeLoader.getInstance(this.config)).getVideoInfo(videoId);
|
|
322
322
|
}, _YouTubeDownloadTask_resolveURL = async function _YouTubeDownloadTask_resolveURL(url) {
|
|
323
323
|
if (!__classPrivateFieldGet(_a, _a, "f", _YouTubeDownloadTask_innertubeForResolveURL)) {
|
|
324
|
-
__classPrivateFieldSet(_a, _a, await InnertubeLib.Innertube.create(
|
|
325
|
-
player_id: '9f4cc5e4'
|
|
326
|
-
}), "f", _YouTubeDownloadTask_innertubeForResolveURL);
|
|
324
|
+
__classPrivateFieldSet(_a, _a, await InnertubeLib.Innertube.create(), "f", _YouTubeDownloadTask_innertubeForResolveURL);
|
|
327
325
|
}
|
|
328
326
|
const innertube = __classPrivateFieldGet(_a, _a, "f", _YouTubeDownloadTask_innertubeForResolveURL);
|
|
329
327
|
const endpoint = await innertube.resolveURL(url);
|