patreon-dl 3.6.0 → 3.6.1
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 +3 -0
- package/bin/EmbedlyDownloader.js +1 -1
- package/dist/cli/CLIOptions.js +10 -1
- package/dist/cli/CLIOptions.js.map +1 -1
- package/dist/cli/CommandLineParser.d.ts +1 -0
- package/dist/cli/CommandLineParser.js +11 -3
- package/dist/cli/CommandLineParser.js.map +1 -1
- package/dist/downloaders/Bootstrap.d.ts +6 -0
- package/dist/downloaders/Bootstrap.js +26 -0
- package/dist/downloaders/Bootstrap.js.map +1 -1
- package/dist/downloaders/InitialData.js +1 -0
- package/dist/downloaders/InitialData.js.map +1 -1
- package/dist/downloaders/PostDownloader.js +6 -0
- package/dist/downloaders/PostDownloader.js.map +1 -1
- package/dist/downloaders/PostsFetcher.js +29 -12
- package/dist/downloaders/PostsFetcher.js.map +1 -1
- package/dist/downloaders/ProductDownloader.js +6 -0
- package/dist/downloaders/ProductDownloader.js.map +1 -1
- package/dist/downloaders/ProductsFetcher.js +32 -15
- package/dist/downloaders/ProductsFetcher.js.map +1 -1
- package/dist/entities/Post.d.ts +1 -1
- package/dist/entities/Post.js.map +1 -1
- package/dist/entities/Product.d.ts +1 -1
- package/dist/entities/Product.js.map +1 -1
- package/dist/parsers/PostParser.d.ts +1 -1
- package/dist/parsers/PostParser.js +7 -6
- package/dist/parsers/PostParser.js.map +1 -1
- package/dist/parsers/ProductParser.d.ts +1 -1
- package/dist/parsers/ProductParser.js +5 -6
- package/dist/parsers/ProductParser.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostDownloader.js","sourceRoot":"","sources":["../../src/downloaders/PostDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import URLHelper from '../utils/URLHelper.js';\nimport Downloader, { type DownloaderConfig, type DownloaderStartParams } from './Downloader.js';\nimport PostParser from '../parsers/PostParser.js';\nimport { type Collection, type Post } from '../entities/Post.js';\nimport { type Downloadable, isYouTubeEmbed } from '../entities/Downloadable.js';\nimport StatusCache, { type StatusCacheValidationScope } from './cache/StatusCache.js';\nimport { generatePostEmbedSummary, generatePostSummary } from './templates/PostInfo.js';\nimport path from 'path';\nimport { TargetSkipReason } from './DownloaderEvent.js';\nimport DownloadTaskFactory from './task/DownloadTaskFactory.js';\nimport PostsFetcher from './PostsFetcher.js';\nimport CommentParser from '../parsers/CommentParser.js';\nimport { type Comment, type CommentList, type CommentReply, type CommentReplyList } from '../entities/Comment.js';\nimport { generatePostCommentsSummary } from './templates/CommentInfo.js';\nimport { type PostDirectories } from '../utils/FSHelper.js';\nimport { type DBInstance } from '../browse/db/index.js';\nimport { type AttachmentMediaItem } from '../entities/MediaItem.js';\nimport type Logger from '../utils/logging/Logger.js';\nimport { type DeepRequired } from '../utils/Misc.js';\nimport { type Campaign } from '../entities/Campaign.js';\nimport type DownloadTaskBatch from './task/DownloadTaskBatch.js';\nimport { generateCollectionSummary } from './templates/CollectionInfo.js';\n\nexport interface PostDownloaderContext {\n skipSaveCampaign?: boolean;\n keepLoggerOpen?: boolean;\n keepDBOpen?: boolean;\n}\n\nexport default class PostDownloader extends Downloader<Post> {\n\n static version = '1.1.1';\n\n name = 'PostDownloader';\n\n #startPromise: Promise<void> | null = null;\n #context: DeepRequired<PostDownloaderContext>;\n\n constructor(\n config: DownloaderConfig<Post>,\n db: () => Promise<DBInstance>,\n logger?: Logger | null,\n context?: PostDownloaderContext\n ) {\n super(config, db, logger);\n this.#context = {\n skipSaveCampaign: context?.skipSaveCampaign ?? false,\n keepLoggerOpen: context?.keepLoggerOpen ?? false,\n keepDBOpen: context?.keepDBOpen ?? false\n };\n }\n\n doStart(params?: DownloaderStartParams): Promise<void> {\n if (this.#startPromise) {\n throw Error('Downloader already running');\n }\n this.#startPromise = this.#doStart(params)\n .finally(() => {\n this.#startPromise = null;\n });\n return this.#startPromise;\n }\n\n async #doStart(params?: DownloaderStartParams): Promise<void> {\n try {\n const { signal } = params || {};\n const postFetch = this.config.postFetch;\n const db = await this.db();\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n if (postFetch.type === 'byUser') {\n this.log('info', `Targeting posts by '${postFetch.vanity}'`);\n }\n else if (postFetch.type === 'byUserId') {\n this.log('info', `Targeting posts by user #${postFetch.userId}`);\n }\n else if (postFetch.type === 'byCollection') {\n this.log('info', `Targeting posts in collection #${postFetch.collectionId}`);\n }\n else { // Single\n this.log('info', `Targeting post #${postFetch.postId}`);\n }\n if (this.#isFetchingMultiplePosts(postFetch) && postFetch.filters) {\n const filterStr = Object.entries(postFetch.filters).map(([ key, value ]) => `${key}=${value}`).join('; ');\n if (filterStr) {\n this.log('info', `Filters: ${filterStr}`);\n }\n }\n\n // Step 1: Get posts (if by user) or target post\n const postsFetcher = new PostsFetcher({\n config: this.config,\n fetcher: this.fetcher,\n logger: this.logger,\n signal\n });\n postsFetcher.on('statusChange', ({current}) => {\n if (current.status === 'running') {\n this.emit('fetchBegin', { targetType: postsFetcher.getTargetType() });\n }\n });\n postsFetcher.begin();\n\n // Step 2: download posts in each fetched list\n let downloaded = 0;\n let skippedUnviewable = 0;\n let skippedRedundant = 0;\n let skippedUnmetMediaTypeCriteria = 0;\n let skippedNotInTier = 0;\n let skippedPublishDateOutOfRange = 0;\n let campaignSaved = false;\n let stopConditionMet = false;\n const savedCollectionIds: string[] = [];\n const postsParser = new PostParser(this.logger);\n while (postsFetcher.hasNext()) {\n const { list, aborted, error } = await postsFetcher.next();\n if (!list || aborted) {\n break;\n }\n if (!list && error) {\n this.emit('end', { aborted: false, error, message: 'PostsFetcher error' });\n return;\n }\n if (!this.#context.skipSaveCampaign && !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 _post of list.items) {\n\n if (stopConditionMet) {\n break;\n }\n\n let post = _post;\n\n // Collections\n if (post.campaign && post.collections) {\n for (const collection of post.collections) {\n if (!savedCollectionIds.includes(collection.id)) {\n try {\n await this.#saveCollection(collection, post.campaign);\n savedCollectionIds.push(collection.id);\n }\n catch (error) {\n this.log('error', `Failed to save collection #${collection.id}:`, error);\n }\n }\n else {\n this.log('debug', `Collection #${collection.id} already processed`);\n }\n }\n }\n\n if (this.#isFetchingMultiplePosts(postFetch)) {\n // Refresh to ensure media links have not expired\n this.log('debug', `Refresh post #${_post.id}`);\n const postURL = URLHelper.constructPostsAPIURL({ postId: _post.id });\n const { json } = await this.commonFetchAPI(postURL, signal);\n let refreshed: Post | null = null;\n if (json) {\n refreshed = postsParser.parsePostsAPIResponse(json, postURL).items[0] || null;\n if (!refreshed) {\n this.log('warn', `Refreshed post #${_post.id} but got empty value - going to use existing data`);\n }\n else if (refreshed.id !== _post.id) {\n this.log('warn', `Refreshed post #${_post.id} but ID mismatch - going to use existing data`);\n refreshed = null;\n }\n }\n else if (this.checkAbortSignal(signal)) {\n return;\n }\n else {\n this.log('warn', `Failed to refresh post #${_post.id} - going to use existing data`);\n }\n if (refreshed) {\n this.log('debug', `Use refreshed post data #${refreshed.id}`);\n post = refreshed;\n }\n }\n\n this.emit('targetBegin', { target: post });\n\n // Step 4.1: post directories\n const postDirs = this.fsHelper.getPostDirs(post);\n this.log('debug', 'Post directories:', postDirs);\n\n // Step 4.2: Check with status cache\n const statusCache = StatusCache.getInstance(this.config, postDirs.statusCache, this.logger);\n const statusCacheValidation = statusCache.validate(post, postDirs.root, this.config)\n if (!statusCacheValidation.invalidated) {\n this.log('info', `Skipped downloading post #${post.id}: already downloaded and nothing has changed since last download`);\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.AlreadyDownloaded,\n skipMessage: 'Target already downloaded and nothing has changed since last download'\n });\n skippedRedundant++;\n if (this.config.stopOn === 'postPreviouslyDownloaded' || \n this.config.stopOn === 'previouslyDownloaded'\n ) {\n stopConditionMet = true;\n }\n continue;\n }\n \n switch ((await this.#doDownload(\n post,\n postDirs,\n statusCacheValidation.scope,\n statusCache,\n db,\n signal\n )).status) {\n case 'aborted':\n return;\n case 'downloaded':\n downloaded++;\n break;\n case 'skippedNotInTier':\n skippedNotInTier++;\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 'skippedUnmetMediaTypeCriteria':\n skippedUnmetMediaTypeCriteria++;\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.#isFetchingMultiplePosts(postFetch)) {\n this.log('info', `Stop downloader: stop condition \"${this.config.stopOn}\" met`)\n }\n\n // Done\n if (postFetch.type === 'byUser') {\n this.log('info', `Done downloading posts by '${postFetch.vanity}'`);\n }\n else if (postFetch.type === 'byUserId') {\n this.log('info', `Done downloading posts by user #${postFetch.userId}`);\n }\n else if (postFetch.type === 'byCollection') {\n this.log('info', `Done downloading posts in collection #${postFetch.collectionId}`);\n }\n else {\n this.log('info', `Done downloading post #${postFetch.postId}`);\n }\n let endMessage = 'Done';\n if (this.#isFetchingMultiplePosts(postFetch)) {\n const skippedStrParts: string[] = [];\n if (skippedUnviewable) {\n skippedStrParts.push(`${skippedUnviewable} unviewable`);\n }\n if (skippedRedundant) {\n skippedStrParts.push(`${skippedRedundant} redundant`);\n }\n if (skippedUnmetMediaTypeCriteria) {\n skippedStrParts.push(`${skippedUnmetMediaTypeCriteria} with unmet media type criteria`);\n }\n if (skippedNotInTier) {\n skippedStrParts.push(`${skippedNotInTier} not in tier`);\n }\n if (skippedPublishDateOutOfRange) {\n skippedStrParts.push(`${skippedPublishDateOutOfRange} with publish date out of range`);\n }\n const skippedStr = skippedStrParts.length > 0 ? ` (skipped: ${skippedStrParts.join(', ')})` : '';\n endMessage = `Total ${downloaded} / ${postsFetcher.getTotal()} posts processed${skippedStr}`;\n this.log('info', endMessage);\n }\n this.emit('end', { aborted: false, message: endMessage });\n }\n finally {\n if (!this.#context.keepDBOpen) {\n await this.closeDB();\n }\n if (this.logger && !this.#context.keepLoggerOpen) {\n await this.logger.end();\n }\n }\n }\n\n async #doDownload(\n post: Post,\n postDirs: PostDirectories,\n scope: StatusCacheValidationScope<Post>,\n statusCache: StatusCache,\n db: DBInstance,\n signal?: AbortSignal\n ): Promise<{status: 'skippedUnviewable' | 'skippedUnmetMediaTypeCriteria' | 'skippedNotInTier' | 'skippedPublishDateOutOfRange' | 'aborted' | 'downloaded' }> {\n this.log('info', `Download post #${post.id} (${post.title})`);\n\n const downloadPost = scope.includes('post');\n const downloadComments = scope.includes('comments');\n \n // Step 1: Check whether we should download post\n // -- 1.1 Viewability\n if (!post.isViewable) {\n if (this.config.include.lockedContent) {\n this.log('warn', `Post #${post.id} is not viewable by current user`);\n }\n else {\n this.log('warn', `Skipped downloading post #${post.id}: not viewable by current user`);\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.Inaccessible,\n skipMessage: 'Target is not viewable by current user'\n });\n return {\n status: 'skippedUnviewable'\n };\n }\n }\n\n // -- 1.2 Config option 'include.postsWithMediaType'\n const postsWithMediaType = this.config.include.postsWithMediaType;\n if (postsWithMediaType !== 'any') {\n const hasAttachments = post.attachments.length > 0;\n const hasAudio = !!post.audio || !!post.audioPreview;\n const hasImages = post.images.length > 0;\n const hasVideo = !!post.video || !!post.videoPreview || !!(post.embed && (post.embed.type === 'videoEmbed' || isYouTubeEmbed(post.embed)));\n const isPodcast = post.postType === 'podcast'\n\n let skip = false;\n if (postsWithMediaType === 'none') {\n skip = hasAttachments || hasAudio || hasImages || hasVideo;\n }\n else if (Array.isArray(postsWithMediaType)) {\n skip = !(\n (postsWithMediaType.includes('attachment') && hasAttachments) ||\n (postsWithMediaType.includes('audio') && hasAudio) ||\n (postsWithMediaType.includes('image') && hasImages) ||\n (postsWithMediaType.includes('video') && hasVideo) ||\n (postsWithMediaType.includes('podcast') && isPodcast && (hasAudio || hasVideo)));\n }\n\n if (skip) {\n this.log('warn', `Skipped downloading post #${post.id}: unmet media type criteria`);\n this.log('debug', 'Match criteria failed:', `config.include.postsWithMediaType: ${JSON.stringify(postsWithMediaType)} <-> post #${post.id}:`, {\n hasAttachments,\n hasAudio,\n hasImages,\n hasVideo\n });\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.UnmetMediaTypeCriteria,\n skipMessage: 'Target does not meet media type criteria'\n });\n return {\n status: 'skippedUnmetMediaTypeCriteria'\n };\n }\n }\n\n // -- 1.3 Config option 'include.postsInTier'\n const postsInTier = this.config.include.postsInTier;\n const isAnyTier = postsInTier === 'any' || postsInTier.includes('any');\n if (!isAnyTier) {\n const applicableTierIds = postsInTier.filter((id) => post.campaign?.rewards.find((r) => r.id === id));\n if (!post.campaign) {\n this.log('warn', 'config.include.postsInTier: ignored - post missing campaign info');\n }\n else {\n this.log('debug', 'config.include.postsInTier: applicable tier IDs:', applicableTierIds);\n }\n let skip = false;\n if (!post.campaign) {\n skip = false;\n }\n else if (applicableTierIds.length === 0) {\n skip = true;\n }\n else if (!post.tiers.find((tier) => tier.id === 'patrons')) {\n skip = applicableTierIds.every((id) => !post.tiers.find((tier) => tier.id === id));\n }\n if (skip) {\n this.log('warn', `Skipped downloading post #${post.id}: not in tier`);\n this.log('debug', 'Match criteria failed:', `config.include.postsInTier: ${JSON.stringify(applicableTierIds)} <-> post #${post.id}:`, post.tiers);\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.NotInTier,\n skipMessage: 'Target not in tier'\n });\n return {\n status: 'skippedNotInTier'\n };\n }\n if (post.campaign) {\n this.log('debug', 'Match criteria OK:', `config.include.postsInTier: ${JSON.stringify(applicableTierIds)} <-> post #${post.id}:`, post.tiers);\n }\n }\n\n // -- 1.4 Config option 'include.postsPublished'\n if (this.isPublishDateOutOfRange(post)) {\n return {\n status: 'skippedPublishDateOutOfRange'\n };\n }\n\n if (!downloadPost && downloadComments) {\n this.log('info', `Previously downloaded post #${post.id} - refresh comments only`);\n }\n\n let hasDownloadPostError = false;\n if (downloadPost) {\n // Step 2: Save post info\n if (this.config.include.contentInfo) {\n this.log('info', `Save post info #${post.id}`);\n this.emit('phaseBegin', { target: post, phase: 'saveInfo' });\n this.fsHelper.createDir(postDirs.info);\n // Post raw data might not be complete or consistent with other posts in the collection.\n // Fetch directly from API.\n // Strictly speaking, we should check for 'error' in results, but since it's not going to be fatal we'll just skip it.\n const { json: fetchedPostAPIData } = await this.commonFetchAPI(\n URLHelper.constructPostsAPIURL({\n postId: post.id,\n campaignId: post.campaign?.id\n }),\n signal\n );\n\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n\n // Step 3. Save summary and raw json\n const summary = generatePostSummary(post);\n const summaryFile = path.resolve(postDirs.info, 'info.txt');\n const saveSummaryResult = await this.fsHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, post, 'post summary');\n\n const postRawFile = path.resolve(postDirs.info, 'post-api.json');\n const savePostRawResult = await this.fsHelper.writeTextFile(\n postRawFile, fetchedPostAPIData || post.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(savePostRawResult, post, 'post API data');\n this.emit('phaseEnd', { target: post, phase: 'saveInfo' });\n\n // (Downloading of info media items deferred to the next step)\n }\n\n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseBegin', { target: post, phase: 'saveMedia' });\n }\n\n // Step 4: save embed info\n if (post.embed && this.config.include.contentMedia) {\n this.log('info', `Save embed info of post #${post.id}`);\n this.fsHelper.createDir(postDirs.embed);\n const embedSummary = generatePostEmbedSummary(post.embed);\n let embedFilename;\n switch (post.embed.type) {\n case 'videoEmbed':\n embedFilename = 'embedded-video.txt';\n break;\n case 'linkEmbed':\n embedFilename = 'embedded-link.txt';\n break;\n default:\n embedFilename = 'embedded-unknown.txt';\n }\n const embedFile = path.resolve(postDirs.embed, embedFilename);\n const saveSummaryResult = await this.fsHelper.writeTextFile(embedFile, embedSummary, this.config.fileExistsAction.content);\n this.logWriteTextFileResult(saveSummaryResult, post, 'embed info');\n }\n\n // Step 5: create download tasks\n let createTaskErrorCount = 0;\n if (this.config.include.previewMedia ||\n this.config.include.contentMedia ||\n this.config.include.contentInfo) {\n\n const batchResult = await this.#createDownloadTaskBatchForPost(post, postDirs, signal);\n const { batch } = batchResult; \n createTaskErrorCount += batchResult.errorCount;\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 if (this.config.include.contentInfo) {\n const infoElements: Downloadable[] = [];\n if (post.coverImage) {\n infoElements.push(post.coverImage);\n }\n if (post.thumbnail) {\n infoElements.push(post.thumbnail);\n }\n if (infoElements.length > 0) {\n const { errorCount } = await this.addToDownloadTaskBatch(batch,\n signal,\n {\n target: infoElements,\n targetName: `post #${post.id} -> info elements`,\n dirs: {\n campaign: post.campaign ? this.fsHelper.getCampaignDirs(post.campaign).root : null,\n main: postDirs.info,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.info\n }\n );\n createTaskErrorCount += errorCount;\n }\n }\n \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: post, phase: 'batchDownload', batch });\n \n await batch.start();\n\n hasDownloadPostError = batch.getTasks('error').length > 0 || createTaskErrorCount > 0;\n\n await batch.destroy();\n }\n finally {\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n }\n\n this.emit('phaseEnd', { target: post, phase: 'batchDownload'});\n }\n\n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseEnd', { target: post, phase: 'saveMedia' });\n }\n }\n\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n\n // Step 6: Fetch and save comments (only available if post is viewable)\n let comments: Comment[] | null = null;\n if (downloadComments && this.config.include.comments && post.isViewable) {\n if (post.commentCount > 0) {\n comments = await this.#fetchComments(post, signal);\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n if (comments.length > 0) {\n this.fsHelper.createDir(postDirs.info);\n const commentsFile = path.resolve(postDirs.info, 'comments.txt');\n const commentsSummary = generatePostCommentsSummary(comments);\n const saveCommentsResult = await this.fsHelper.writeTextFile(commentsFile, commentsSummary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveCommentsResult, post, `${comments.length} comments`);\n }\n else {\n this.log('warn', `Expecting ${post.commentCount} comments for post #${post.id} but got none`);\n }\n }\n else {\n this.log('info', `No comments available for post #${post.id}`)\n }\n }\n\n // Step 7: Update status cache\n statusCache.updateOnDownload(post, postDirs.root, hasDownloadPostError, this.config);\n\n // Step 8: Save to DB\n let skipDB = false;\n if (!post.isViewable) {\n // Skip if existing db record (if any) refers to viewable post\n const dbPost = db.getContent(post.id, 'post');\n skipDB = dbPost !== null && dbPost.isViewable;\n }\n if (!skipDB) {\n db.saveContent(post);\n if (comments) {\n db.savePostComments(post, comments);\n }\n }\n else {\n this.log('info', `Skip overwrite existing viewable post #${post.id} in DB with current unviewable version`);\n }\n\n this.emit('targetEnd', { target: post, isSkipped: false });\n\n return {\n status: 'downloaded'\n };\n }\n\n #isFetchingMultiplePosts(postFetch: DownloaderConfig<Post>['postFetch']): postFetch is DownloaderConfig<Post>['postFetch'] & { type: 'byUser' | 'byUserId' | 'byCollection' } {\n return postFetch.type === 'byUser' || postFetch.type === 'byUserId' || postFetch.type === 'byCollection';\n }\n\n async __getCampaign(signal?: AbortSignal) {\n let url: string | null;\n const postFetch = this.config.postFetch;\n switch (postFetch.type) {\n case 'byUser':\n url = URLHelper.constructCampaignPageURL({ vanity: postFetch.vanity });\n break;\n case 'byUserId':\n url = URLHelper.constructCampaignPageURL({ userId: postFetch.userId });\n break;\n default:\n url = null;\n }\n if (!url) {\n throw Error('Internal error: invalid config');\n }\n const postsFetcher = new PostsFetcher({\n config: this.config,\n fetcher: this.fetcher,\n logger: this.logger,\n signal\n });\n const { campaignId } = await postsFetcher.getInitialData(url);\n const postsParser = new PostParser(this.logger);\n const res = await this.fetchCampaign(campaignId);\n if (signal?.aborted) {\n throw new Error('Aborted');\n }\n if (res.error) {\n throw res.error;\n }\n return postsParser.parseCampaignAPIResponse(res.json);\n }\n\n async #createDownloadTaskBatchForPost(post: Post, postDirs: ReturnType<typeof this.fsHelper['getPostDirs']>, signal?: AbortSignal) {\n\n const incPreview = this.config.include.previewMedia;\n const incContent = this.config.include.contentMedia;\n\n const __incPreview = (mediaType: 'audio' | 'video' | 'image') => {\n if (typeof incPreview === 'boolean') {\n return incPreview;\n }\n return incPreview.includes(mediaType);\n };\n\n const __incContent = (mediaType: 'audio' | 'video' | 'image' | 'attachment') => {\n if (typeof incContent === 'boolean') {\n return incContent;\n }\n return incContent.includes(mediaType);\n };\n\n const __getEmbedTask = () => {\n if (!post.embed) {\n return null;\n }\n\n const hasEmbedDownloader = DownloadTaskFactory.findEmbedDownloader(this.config.embedDownloaders, post.embed.provider);\n const isDownloadableVideo = isYouTubeEmbed(post.embed) || (post.embed.type === 'videoEmbed' && hasEmbedDownloader);\n const isDownloadableOther = !isYouTubeEmbed(post.embed) && post.embed.type !== 'videoEmbed' && hasEmbedDownloader;\n \n if ((isDownloadableVideo && __incContent('video')) || isDownloadableOther) {\n const embedType = post.embed.type === 'videoEmbed' ? ' video' : post.embed.type === 'linkEmbed' ? ' link' : '';\n return {\n target: [ post.embed ],\n targetName: `post #${post.id} -> embedded ${post.embed.provider}${embedType}`,\n dirs: {\n campaign: post.campaign ? this.fsHelper.getCampaignDirs(post.campaign).root : null,\n main: postDirs.embed,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n };\n }\n \n return null;\n }\n\n const campaignDir = post.campaign ? this.fsHelper.getCampaignDirs(post.campaign).root : null;\n\n await this.#processLinkedAttachments(post);\n const downloadableLinkedAttachments = post.linkedAttachments?.reduce<Downloadable<AttachmentMediaItem>[]>((result, att) => {\n if (att.downloadable) {\n result.push(att.downloadable);\n }\n return result;\n }, []) || [];\n\n const allAttachments = [...post.attachments, ...downloadableLinkedAttachments];\n\n const batchResult = this.createDownloadTaskBatch(\n `Post #${post.id} (${post.title})`,\n signal,\n\n __incPreview('audio') && post.audioPreview ? {\n target: [ post.audioPreview ],\n targetName: `post #${post.id} -> audio preview`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.audioPreview,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incPreview('video') && post.videoPreview ? {\n target: [ post.videoPreview ],\n targetName: `post #${post.id} -> video preview`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.videoPreview,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n /**\n * If post is not viewable by current user, its images will be\n * blurry and we should categorize them as image previews.\n */\n __incPreview('image') && post.images.length > 0 && !post.isViewable ? {\n target: post.images,\n targetName: `post #${post.id} -> image previews`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.imagePreviews,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n /**\n * If post is not viewable, audio data should have no URL, so check and\n * skip if this is the case.\n */\n __incContent('audio') && post.audio && (post.isViewable || (post.audio.type === 'audio' && post.audio.url)) ? {\n target: [ post.audio ],\n targetName: `post #${post.id} -> audio`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.audio,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('video') && post.video ? {\n target: [ post.video ],\n targetName: `post #${post.id} -> video`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.video,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('image') && post.images.length > 0 && post.isViewable ? {\n target: post.images,\n targetName: `post #${post.id} -> images`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.images,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('attachment') && allAttachments.length > 0 ? {\n target: allAttachments,\n targetName: `post #${post.id} -> attachments`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.attachments,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content,\n isAttachment: true\n } : null,\n\n __getEmbedTask()\n );\n\n return batchResult;\n }\n\n async #processLinkedAttachments(post: Post, signal?: AbortSignal) {\n if (!post.linkedAttachments || post.linkedAttachments.length === 0) {\n return;\n }\n this.log('debug', `Process linked attachments of post #${post.id}`);\n for (const la of post.linkedAttachments) {\n const laStr = `[#${post.id} -> #${la.mediaId}]`;\n // Only process linked attachment where its postId is not the same as current one being processed.\n // If same as current one, then linked attachment would already be in the current post data.\n if (la.postId === post.id) {\n this.log('debug', `Linked attachment ${laStr} has same parent post`);\n }\n else {\n const apiURL = URLHelper.constructPostsAPIURL({ postId: la.postId });\n let json;\n try {\n this.log('debug', `Linked attachment ${laStr} belongs to post #${la.postId}`);\n json = (await this.fetcher.get({\n url: apiURL,\n type: 'json',\n maxRetries: this.config.request.maxRetries,\n signal }\n )).json;\n }\n catch (error) {\n if (signal?.aborted) {\n throw error;\n }\n else {\n this.log('error', `Error fetching linked attachment ${laStr} from parent post #${la.postId}: API request failed for \"${apiURL}\": `, error);\n }\n json = null;\n }\n if (json) {\n const parser = new PostParser();\n const parentPost = parser.parsePostsAPIResponse(json, apiURL).items[0];\n if (!parentPost) {\n this.log('error', `Error fetching linked attachment ${laStr} from parent post #${la.postId}: post data not found in response of \"${apiURL}\"`);\n }\n else {\n if (!parentPost.isViewable) {\n this.log('warn', `Parent post #${la.postId} of linked attachment ${laStr} is not viewable by user`);\n }\n else {\n const attachment = parentPost.attachments.find((att) => att.id === la.mediaId);\n if (!attachment) {\n this.log('warn', `Attachment not found in parent post #${la.postId} of linked attachment ${laStr}`);\n }\n else {\n la.downloadable = attachment;\n this.log('debug', `Obtained attachment from parent post #${la.postId} of linked attachment ${laStr}`);\n }\n }\n }\n }\n }\n }\n }\n\n async #fetchComments(post: Post, signal?: AbortSignal, accumulated?: CommentList & { nextURL: string; }): Promise<Comment[]> {\n if (!post.commentCount) {\n this.log('debug', `Comment count is zero for post #${post.id}`);\n return [];\n }\n if (this.checkAbortSignal(signal)) {\n return [];\n }\n let commentsURL;\n if (!accumulated) {\n this.log('info', `Fetch comments for post #${post.id}`);\n commentsURL = URLHelper.constructPostCommentsAPIURL({ postId: post.id });\n }\n else {\n this.log('debug', `Fetch next batch of comments for post #${post.id}`);\n commentsURL = accumulated.nextURL;\n }\n const { json } = await this.commonFetchAPI(commentsURL, signal);\n const parser = new CommentParser(this.logger);\n if (json) {\n const comments = parser.parseCommentsAPIResponse(json, commentsURL);\n this.log('debug', `Fetched ${comments.items.length} comments for post #${post.id}`);\n if (comments.items.length > 0 && comments.nextURL) {\n let _acc;\n if (!accumulated) {\n _acc = {\n url: comments.url,\n items: comments.items,\n nextURL: comments.nextURL,\n total: comments.total\n };\n }\n else {\n _acc = accumulated;\n _acc.url = comments.url;\n _acc.items.push(...comments.items);\n _acc.nextURL = comments.nextURL;\n }\n return this.#fetchComments(post, signal, _acc);\n }\n else {\n const result = accumulated ? [ ...accumulated.items, ...comments.items ] : comments.items;\n this.log('debug', `Total ${result.length} comments fetched for post #${post.id}`);\n for (const comment of result) {\n if (comment.replyCount > 0) {\n comment.replies = await this.#fetchCommentReplies(comment, signal);\n }\n }\n return result;\n }\n }\n else if (this.checkAbortSignal(signal)) {\n return [];\n }\n else {\n this.log('warn', `Failed to fetch comments for post #${post.id}`);\n return [];\n }\n }\n\n async #fetchCommentReplies(comment: Comment, signal?: AbortSignal, accumulated?: CommentReplyList & { nextURL: string; }): Promise<CommentReply[]> {\n if (!comment.replyCount) {\n this.log('debug', `Reply count is zero for comment #${comment.id}`);\n return [];\n }\n if (this.checkAbortSignal(signal)) {\n return [];\n }\n let repliesURL;\n if (!accumulated) {\n this.log('debug', `Fetch replies to comment #${comment.id}`);\n repliesURL = URLHelper.constructPostCommentsAPIURL({ commentId: comment.id, replies: true });\n }\n else {\n this.log('debug', `Fetch next batch of replies to comment #${comment.id}`);\n repliesURL = accumulated.nextURL;\n }\n const { json } = await this.commonFetchAPI(repliesURL, signal);\n const parser = new CommentParser(this.logger);\n if (json) {\n const replies = parser.parseCommentsAPIResponse(json, repliesURL, true);\n this.log('debug', `Fetched ${replies.items.length} replies to comment #${comment.id}`);\n if (replies.items.length > 0 && replies.nextURL) {\n let _acc;\n if (!accumulated) {\n _acc = {\n url: replies.url,\n items: replies.items,\n nextURL: replies.nextURL,\n total: replies.total\n };\n }\n else {\n _acc = accumulated;\n _acc.url = replies.url;\n _acc.items.push(...replies.items);\n _acc.nextURL = replies.nextURL;\n }\n return this.#fetchCommentReplies(comment, signal, _acc);\n }\n else {\n const result = accumulated ? [ ...accumulated.items, ...replies.items ] : replies.items;\n this.log('debug', `Total ${result.length} replies fetched for comment #${comment.id}`);\n return result;\n }\n }\n else if (this.checkAbortSignal(signal)) {\n return [];\n }\n else {\n this.log('warn', `Failed to fetch replies to comment #${comment.id}`);\n return [];\n }\n }\n\n async #saveCollection(collection: Collection, campaign: Campaign, signal?: AbortSignal) {\n const db = await this.db();\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n if (!this.config.include.contentInfo) {\n db.saveCollection(collection, campaign);\n return;\n }\n\n let batch: DownloadTaskBatch | null = null;\n const abortHandler = () => {\n void (async () => {\n if (batch) {\n await batch.abort();\n }\n })();\n };\n if (signal) {\n signal.addEventListener('abort', abortHandler, { once: true });\n }\n\n this.log('info', `Save collection info #${collection.id}`);\n this.emit('targetBegin', { target: collection });\n this.emit('phaseBegin', { target: collection, phase: 'saveInfo' });\n\n // Step 1: create collection directories\n const collectionDirs = this.fsHelper.getCollectionsDir(campaign, collection);\n this.log('debug', 'Campaign directories: ', collectionDirs);\n this.fsHelper.createDir(collectionDirs.root);\n\n // Step 2: save summary and raw json\n const summary = generateCollectionSummary(collection);\n const summaryFile = path.resolve(collectionDirs.root, 'info.txt');\n const saveSummaryResult = await this.fsHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, collection, 'collection summary');\n\n const collectionRawFile = path.resolve(collectionDirs.root, 'collection-api.json');\n const saveCollectionRawResult = await this.fsHelper.writeTextFile(\n collectionRawFile, collection.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(saveCollectionRawResult, collection, 'collection API data');\n\n this.emit('phaseEnd', { target: collection, phase: 'saveInfo' });\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n // Step 3: download collection media items\n if (collection.thumbnail) {\n this.emit('phaseBegin', { target: collection, phase: 'saveMedia' });\n const collectionMedia: Downloadable[] = [\n collection.thumbnail\n ];\n batch = (await this.createDownloadTaskBatch(\n `Collection #${collection.id} (${collection.title})`,\n signal,\n {\n target: collectionMedia,\n targetName: `collection #${campaign.id} -> thumbnail`,\n dirs: {\n campaign: this.fsHelper.getCampaignDirs(campaign).root,\n main: collectionDirs.root,\n thumbnails: null\n },\n fileExistsAction: this.config.fileExistsAction.info\n }\n )).batch;\n if (this.checkAbortSignal(signal)) {\n return;\n }\n batch.prestart();\n this.emit('phaseBegin', { target: collection, phase: 'batchDownload', batch });\n await batch.start();\n await batch.destroy();\n this.emit('phaseEnd', { target: collection, phase: 'batchDownload' });\n this.emit('phaseEnd', { target: collection, phase: 'saveMedia' });\n\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n if (this.checkAbortSignal(signal)) {\n return;\n }\n }\n\n // Step 4: save to DB\n db.saveCollection(collection, campaign);\n\n // Done\n this.log('info', 'Done saving collection info');\n this.emit('targetEnd', { target: collection, isSkipped: false });\n }\n\n}\n"]}
|
|
1
|
+
{"version":3,"file":"PostDownloader.js","sourceRoot":"","sources":["../../src/downloaders/PostDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import URLHelper from '../utils/URLHelper.js';\nimport Downloader, { type DownloaderConfig, type DownloaderStartParams } from './Downloader.js';\nimport PostParser from '../parsers/PostParser.js';\nimport { type Collection, type Post } from '../entities/Post.js';\nimport { type Downloadable, isYouTubeEmbed } from '../entities/Downloadable.js';\nimport StatusCache, { type StatusCacheValidationScope } from './cache/StatusCache.js';\nimport { generatePostEmbedSummary, generatePostSummary } from './templates/PostInfo.js';\nimport path from 'path';\nimport { TargetSkipReason } from './DownloaderEvent.js';\nimport DownloadTaskFactory from './task/DownloadTaskFactory.js';\nimport PostsFetcher from './PostsFetcher.js';\nimport CommentParser from '../parsers/CommentParser.js';\nimport { type Comment, type CommentList, type CommentReply, type CommentReplyList } from '../entities/Comment.js';\nimport { generatePostCommentsSummary } from './templates/CommentInfo.js';\nimport { type PostDirectories } from '../utils/FSHelper.js';\nimport { type DBInstance } from '../browse/db/index.js';\nimport { type AttachmentMediaItem } from '../entities/MediaItem.js';\nimport type Logger from '../utils/logging/Logger.js';\nimport { type DeepRequired } from '../utils/Misc.js';\nimport { type Campaign } from '../entities/Campaign.js';\nimport type DownloadTaskBatch from './task/DownloadTaskBatch.js';\nimport { generateCollectionSummary } from './templates/CollectionInfo.js';\n\nexport interface PostDownloaderContext {\n skipSaveCampaign?: boolean;\n keepLoggerOpen?: boolean;\n keepDBOpen?: boolean;\n}\n\nexport default class PostDownloader extends Downloader<Post> {\n\n static version = '1.1.1';\n\n name = 'PostDownloader';\n\n #startPromise: Promise<void> | null = null;\n #context: DeepRequired<PostDownloaderContext>;\n\n constructor(\n config: DownloaderConfig<Post>,\n db: () => Promise<DBInstance>,\n logger?: Logger | null,\n context?: PostDownloaderContext\n ) {\n super(config, db, logger);\n this.#context = {\n skipSaveCampaign: context?.skipSaveCampaign ?? false,\n keepLoggerOpen: context?.keepLoggerOpen ?? false,\n keepDBOpen: context?.keepDBOpen ?? false\n };\n }\n\n doStart(params?: DownloaderStartParams): Promise<void> {\n if (this.#startPromise) {\n throw Error('Downloader already running');\n }\n this.#startPromise = this.#doStart(params)\n .finally(() => {\n this.#startPromise = null;\n });\n return this.#startPromise;\n }\n\n async #doStart(params?: DownloaderStartParams): Promise<void> {\n try {\n const { signal } = params || {};\n const postFetch = this.config.postFetch;\n const db = await this.db();\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n if (postFetch.type === 'byUser') {\n this.log('info', `Targeting posts by '${postFetch.vanity}'`);\n }\n else if (postFetch.type === 'byUserId') {\n this.log('info', `Targeting posts by user #${postFetch.userId}`);\n }\n else if (postFetch.type === 'byCollection') {\n this.log('info', `Targeting posts in collection #${postFetch.collectionId}`);\n }\n else if (postFetch.type === 'byFile') {\n this.log('info', `Target post given by API data in \"${postFetch.filePath}\"`);\n }\n else { // Single\n this.log('info', `Targeting post #${postFetch.postId}`);\n }\n if (this.#isFetchingMultiplePosts(postFetch) && postFetch.filters) {\n const filterStr = Object.entries(postFetch.filters).map(([ key, value ]) => `${key}=${value}`).join('; ');\n if (filterStr) {\n this.log('info', `Filters: ${filterStr}`);\n }\n }\n\n // Step 1: Get posts (if by user) or target post\n const postsFetcher = new PostsFetcher({\n config: this.config,\n fetcher: this.fetcher,\n logger: this.logger,\n signal\n });\n postsFetcher.on('statusChange', ({current}) => {\n if (current.status === 'running') {\n this.emit('fetchBegin', { targetType: postsFetcher.getTargetType() });\n }\n });\n postsFetcher.begin();\n\n // Step 2: download posts in each fetched list\n let downloaded = 0;\n let skippedUnviewable = 0;\n let skippedRedundant = 0;\n let skippedUnmetMediaTypeCriteria = 0;\n let skippedNotInTier = 0;\n let skippedPublishDateOutOfRange = 0;\n let campaignSaved = false;\n let stopConditionMet = false;\n const savedCollectionIds: string[] = [];\n const postsParser = new PostParser(this.logger);\n while (postsFetcher.hasNext()) {\n const { list, aborted, error } = await postsFetcher.next();\n if (!list || aborted) {\n break;\n }\n if (!list && error) {\n this.emit('end', { aborted: false, error, message: 'PostsFetcher error' });\n return;\n }\n if (!this.#context.skipSaveCampaign && !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 _post of list.items) {\n\n if (stopConditionMet) {\n break;\n }\n\n let post = _post;\n\n // Collections\n if (post.campaign && post.collections) {\n for (const collection of post.collections) {\n if (!savedCollectionIds.includes(collection.id)) {\n try {\n await this.#saveCollection(collection, post.campaign);\n savedCollectionIds.push(collection.id);\n }\n catch (error) {\n this.log('error', `Failed to save collection #${collection.id}:`, error);\n }\n }\n else {\n this.log('debug', `Collection #${collection.id} already processed`);\n }\n }\n }\n\n if (this.#isFetchingMultiplePosts(postFetch)) {\n // Refresh to ensure media links have not expired\n this.log('debug', `Refresh post #${_post.id}`);\n const postURL = URLHelper.constructPostsAPIURL({ postId: _post.id });\n const { json } = await this.commonFetchAPI(postURL, signal);\n let refreshed: Post | null = null;\n if (json) {\n refreshed = postsParser.parsePostsAPIResponse(json, postURL).items[0] || null;\n if (!refreshed) {\n this.log('warn', `Refreshed post #${_post.id} but got empty value - going to use existing data`);\n }\n else if (refreshed.id !== _post.id) {\n this.log('warn', `Refreshed post #${_post.id} but ID mismatch - going to use existing data`);\n refreshed = null;\n }\n }\n else if (this.checkAbortSignal(signal)) {\n return;\n }\n else {\n this.log('warn', `Failed to refresh post #${_post.id} - going to use existing data`);\n }\n if (refreshed) {\n this.log('debug', `Use refreshed post data #${refreshed.id}`);\n post = refreshed;\n }\n }\n\n this.emit('targetBegin', { target: post });\n\n // Step 4.1: post directories\n const postDirs = this.fsHelper.getPostDirs(post);\n this.log('debug', 'Post directories:', postDirs);\n\n // Step 4.2: Check with status cache\n const statusCache = StatusCache.getInstance(this.config, postDirs.statusCache, this.logger);\n const statusCacheValidation = statusCache.validate(post, postDirs.root, this.config)\n if (!statusCacheValidation.invalidated) {\n this.log('info', `Skipped downloading post #${post.id}: already downloaded and nothing has changed since last download`);\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.AlreadyDownloaded,\n skipMessage: 'Target already downloaded and nothing has changed since last download'\n });\n skippedRedundant++;\n if (this.config.stopOn === 'postPreviouslyDownloaded' || \n this.config.stopOn === 'previouslyDownloaded'\n ) {\n stopConditionMet = true;\n }\n continue;\n }\n \n switch ((await this.#doDownload(\n post,\n postDirs,\n statusCacheValidation.scope,\n statusCache,\n db,\n signal\n )).status) {\n case 'aborted':\n return;\n case 'downloaded':\n downloaded++;\n break;\n case 'skippedNotInTier':\n skippedNotInTier++;\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 'skippedUnmetMediaTypeCriteria':\n skippedUnmetMediaTypeCriteria++;\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.#isFetchingMultiplePosts(postFetch)) {\n this.log('info', `Stop downloader: stop condition \"${this.config.stopOn}\" met`)\n }\n\n // Done\n if (postFetch.type === 'byUser') {\n this.log('info', `Done downloading posts by '${postFetch.vanity}'`);\n }\n else if (postFetch.type === 'byUserId') {\n this.log('info', `Done downloading posts by user #${postFetch.userId}`);\n }\n else if (postFetch.type === 'byCollection') {\n this.log('info', `Done downloading posts in collection #${postFetch.collectionId}`);\n }\n else if (postFetch.type === 'byFile') {\n this.log('info', `Done downloading post given in \"${postFetch.filePath}\"`);\n }\n else {\n this.log('info', `Done downloading post #${postFetch.postId}`);\n }\n let endMessage = 'Done';\n if (this.#isFetchingMultiplePosts(postFetch)) {\n const skippedStrParts: string[] = [];\n if (skippedUnviewable) {\n skippedStrParts.push(`${skippedUnviewable} unviewable`);\n }\n if (skippedRedundant) {\n skippedStrParts.push(`${skippedRedundant} redundant`);\n }\n if (skippedUnmetMediaTypeCriteria) {\n skippedStrParts.push(`${skippedUnmetMediaTypeCriteria} with unmet media type criteria`);\n }\n if (skippedNotInTier) {\n skippedStrParts.push(`${skippedNotInTier} not in tier`);\n }\n if (skippedPublishDateOutOfRange) {\n skippedStrParts.push(`${skippedPublishDateOutOfRange} with publish date out of range`);\n }\n const skippedStr = skippedStrParts.length > 0 ? ` (skipped: ${skippedStrParts.join(', ')})` : '';\n endMessage = `Total ${downloaded} / ${postsFetcher.getTotal()} posts processed${skippedStr}`;\n this.log('info', endMessage);\n }\n this.emit('end', { aborted: false, message: endMessage });\n }\n finally {\n if (!this.#context.keepDBOpen) {\n await this.closeDB();\n }\n if (this.logger && !this.#context.keepLoggerOpen) {\n await this.logger.end();\n }\n }\n }\n\n async #doDownload(\n post: Post,\n postDirs: PostDirectories,\n scope: StatusCacheValidationScope<Post>,\n statusCache: StatusCache,\n db: DBInstance,\n signal?: AbortSignal\n ): Promise<{status: 'skippedUnviewable' | 'skippedUnmetMediaTypeCriteria' | 'skippedNotInTier' | 'skippedPublishDateOutOfRange' | 'aborted' | 'downloaded' }> {\n this.log('info', `Download post #${post.id} (${post.title})`);\n\n const downloadPost = scope.includes('post');\n const downloadComments = scope.includes('comments');\n \n // Step 1: Check whether we should download post\n // -- 1.1 Viewability\n if (!post.isViewable) {\n if (this.config.include.lockedContent) {\n this.log('warn', `Post #${post.id} is not viewable by current user`);\n }\n else {\n this.log('warn', `Skipped downloading post #${post.id}: not viewable by current user`);\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.Inaccessible,\n skipMessage: 'Target is not viewable by current user'\n });\n return {\n status: 'skippedUnviewable'\n };\n }\n }\n\n // -- 1.2 Config option 'include.postsWithMediaType'\n const postsWithMediaType = this.config.include.postsWithMediaType;\n if (postsWithMediaType !== 'any') {\n const hasAttachments = post.attachments.length > 0;\n const hasAudio = !!post.audio || !!post.audioPreview;\n const hasImages = post.images.length > 0;\n const hasVideo = !!post.video || !!post.videoPreview || !!(post.embed && (post.embed.type === 'videoEmbed' || isYouTubeEmbed(post.embed)));\n const isPodcast = post.postType === 'podcast'\n\n let skip = false;\n if (postsWithMediaType === 'none') {\n skip = hasAttachments || hasAudio || hasImages || hasVideo;\n }\n else if (Array.isArray(postsWithMediaType)) {\n skip = !(\n (postsWithMediaType.includes('attachment') && hasAttachments) ||\n (postsWithMediaType.includes('audio') && hasAudio) ||\n (postsWithMediaType.includes('image') && hasImages) ||\n (postsWithMediaType.includes('video') && hasVideo) ||\n (postsWithMediaType.includes('podcast') && isPodcast && (hasAudio || hasVideo)));\n }\n\n if (skip) {\n this.log('warn', `Skipped downloading post #${post.id}: unmet media type criteria`);\n this.log('debug', 'Match criteria failed:', `config.include.postsWithMediaType: ${JSON.stringify(postsWithMediaType)} <-> post #${post.id}:`, {\n hasAttachments,\n hasAudio,\n hasImages,\n hasVideo\n });\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.UnmetMediaTypeCriteria,\n skipMessage: 'Target does not meet media type criteria'\n });\n return {\n status: 'skippedUnmetMediaTypeCriteria'\n };\n }\n }\n\n // -- 1.3 Config option 'include.postsInTier'\n const postsInTier = this.config.include.postsInTier;\n const isAnyTier = postsInTier === 'any' || postsInTier.includes('any');\n if (!isAnyTier) {\n const applicableTierIds = postsInTier.filter((id) => post.campaign?.rewards.find((r) => r.id === id));\n if (!post.campaign) {\n this.log('warn', 'config.include.postsInTier: ignored - post missing campaign info');\n }\n else {\n this.log('debug', 'config.include.postsInTier: applicable tier IDs:', applicableTierIds);\n }\n let skip = false;\n if (!post.campaign) {\n skip = false;\n }\n else if (applicableTierIds.length === 0) {\n skip = true;\n }\n else if (!post.tiers.find((tier) => tier.id === 'patrons')) {\n skip = applicableTierIds.every((id) => !post.tiers.find((tier) => tier.id === id));\n }\n if (skip) {\n this.log('warn', `Skipped downloading post #${post.id}: not in tier`);\n this.log('debug', 'Match criteria failed:', `config.include.postsInTier: ${JSON.stringify(applicableTierIds)} <-> post #${post.id}:`, post.tiers);\n this.emit('targetEnd', {\n target: post,\n isSkipped: true,\n skipReason: TargetSkipReason.NotInTier,\n skipMessage: 'Target not in tier'\n });\n return {\n status: 'skippedNotInTier'\n };\n }\n if (post.campaign) {\n this.log('debug', 'Match criteria OK:', `config.include.postsInTier: ${JSON.stringify(applicableTierIds)} <-> post #${post.id}:`, post.tiers);\n }\n }\n\n // -- 1.4 Config option 'include.postsPublished'\n if (this.isPublishDateOutOfRange(post)) {\n return {\n status: 'skippedPublishDateOutOfRange'\n };\n }\n\n if (!downloadPost && downloadComments) {\n this.log('info', `Previously downloaded post #${post.id} - refresh comments only`);\n }\n\n let hasDownloadPostError = false;\n if (downloadPost) {\n // Step 2: Save post info\n if (this.config.include.contentInfo) {\n this.log('info', `Save post info #${post.id}`);\n this.emit('phaseBegin', { target: post, phase: 'saveInfo' });\n this.fsHelper.createDir(postDirs.info);\n // Post raw data might not be complete or consistent with other posts in the collection.\n // Fetch directly from API.\n // Strictly speaking, we should check for 'error' in results, but since it's not going to be fatal we'll just skip it.\n const { json: fetchedPostAPIData } = await this.commonFetchAPI(\n URLHelper.constructPostsAPIURL({\n postId: post.id,\n campaignId: post.campaign?.id\n }),\n signal\n );\n\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n\n // Step 3. Save summary and raw json\n const summary = generatePostSummary(post);\n const summaryFile = path.resolve(postDirs.info, 'info.txt');\n const saveSummaryResult = await this.fsHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, post, 'post summary');\n\n const postRawFile = path.resolve(postDirs.info, 'post-api.json');\n const savePostRawResult = await this.fsHelper.writeTextFile(\n postRawFile, fetchedPostAPIData || post.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(savePostRawResult, post, 'post API data');\n this.emit('phaseEnd', { target: post, phase: 'saveInfo' });\n\n // (Downloading of info media items deferred to the next step)\n }\n\n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseBegin', { target: post, phase: 'saveMedia' });\n }\n\n // Step 4: save embed info\n if (post.embed && this.config.include.contentMedia) {\n this.log('info', `Save embed info of post #${post.id}`);\n this.fsHelper.createDir(postDirs.embed);\n const embedSummary = generatePostEmbedSummary(post.embed);\n let embedFilename;\n switch (post.embed.type) {\n case 'videoEmbed':\n embedFilename = 'embedded-video.txt';\n break;\n case 'linkEmbed':\n embedFilename = 'embedded-link.txt';\n break;\n default:\n embedFilename = 'embedded-unknown.txt';\n }\n const embedFile = path.resolve(postDirs.embed, embedFilename);\n const saveSummaryResult = await this.fsHelper.writeTextFile(embedFile, embedSummary, this.config.fileExistsAction.content);\n this.logWriteTextFileResult(saveSummaryResult, post, 'embed info');\n }\n\n // Step 5: create download tasks\n let createTaskErrorCount = 0;\n if (this.config.include.previewMedia ||\n this.config.include.contentMedia ||\n this.config.include.contentInfo) {\n\n const batchResult = await this.#createDownloadTaskBatchForPost(post, postDirs, signal);\n const { batch } = batchResult; \n createTaskErrorCount += batchResult.errorCount;\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 if (this.config.include.contentInfo) {\n const infoElements: Downloadable[] = [];\n if (post.coverImage) {\n infoElements.push(post.coverImage);\n }\n if (post.thumbnail) {\n infoElements.push(post.thumbnail);\n }\n if (infoElements.length > 0) {\n const { errorCount } = await this.addToDownloadTaskBatch(batch,\n signal,\n {\n target: infoElements,\n targetName: `post #${post.id} -> info elements`,\n dirs: {\n campaign: post.campaign ? this.fsHelper.getCampaignDirs(post.campaign).root : null,\n main: postDirs.info,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.info\n }\n );\n createTaskErrorCount += errorCount;\n }\n }\n \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: post, phase: 'batchDownload', batch });\n \n await batch.start();\n\n hasDownloadPostError = batch.getTasks('error').length > 0 || createTaskErrorCount > 0;\n\n await batch.destroy();\n }\n finally {\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n }\n\n this.emit('phaseEnd', { target: post, phase: 'batchDownload'});\n }\n\n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseEnd', { target: post, phase: 'saveMedia' });\n }\n }\n\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n\n // Step 6: Fetch and save comments (only available if post is viewable)\n let comments: Comment[] | null = null;\n if (downloadComments && this.config.include.comments && post.isViewable) {\n if (post.commentCount > 0) {\n comments = await this.#fetchComments(post, signal);\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n if (comments.length > 0) {\n this.fsHelper.createDir(postDirs.info);\n const commentsFile = path.resolve(postDirs.info, 'comments.txt');\n const commentsSummary = generatePostCommentsSummary(comments);\n const saveCommentsResult = await this.fsHelper.writeTextFile(commentsFile, commentsSummary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveCommentsResult, post, `${comments.length} comments`);\n }\n else {\n this.log('warn', `Expecting ${post.commentCount} comments for post #${post.id} but got none`);\n }\n }\n else {\n this.log('info', `No comments available for post #${post.id}`)\n }\n }\n\n // Step 7: Update status cache\n statusCache.updateOnDownload(post, postDirs.root, hasDownloadPostError, this.config);\n\n // Step 8: Save to DB\n let skipDB = false;\n if (!post.isViewable) {\n // Skip if existing db record (if any) refers to viewable post\n const dbPost = db.getContent(post.id, 'post');\n skipDB = dbPost !== null && dbPost.isViewable;\n }\n if (!skipDB) {\n db.saveContent(post);\n if (comments) {\n db.savePostComments(post, comments);\n }\n }\n else {\n this.log('info', `Skip overwrite existing viewable post #${post.id} in DB with current unviewable version`);\n }\n\n this.emit('targetEnd', { target: post, isSkipped: false });\n\n return {\n status: 'downloaded'\n };\n }\n\n #isFetchingMultiplePosts(postFetch: DownloaderConfig<Post>['postFetch']): postFetch is DownloaderConfig<Post>['postFetch'] & { type: 'byUser' | 'byUserId' | 'byCollection' } {\n return postFetch.type === 'byUser' || postFetch.type === 'byUserId' || postFetch.type === 'byCollection';\n }\n\n async __getCampaign(signal?: AbortSignal) {\n let url: string | null;\n const postFetch = this.config.postFetch;\n switch (postFetch.type) {\n case 'byUser':\n url = URLHelper.constructCampaignPageURL({ vanity: postFetch.vanity });\n break;\n case 'byUserId':\n url = URLHelper.constructCampaignPageURL({ userId: postFetch.userId });\n break;\n default:\n url = null;\n }\n if (!url) {\n throw Error('Internal error: invalid config');\n }\n const postsFetcher = new PostsFetcher({\n config: this.config,\n fetcher: this.fetcher,\n logger: this.logger,\n signal\n });\n const { campaignId } = await postsFetcher.getInitialData(url);\n const postsParser = new PostParser(this.logger);\n const res = await this.fetchCampaign(campaignId);\n if (signal?.aborted) {\n throw new Error('Aborted');\n }\n if (res.error) {\n throw res.error;\n }\n return postsParser.parseCampaignAPIResponse(res.json);\n }\n\n async #createDownloadTaskBatchForPost(post: Post, postDirs: ReturnType<typeof this.fsHelper['getPostDirs']>, signal?: AbortSignal) {\n\n const incPreview = this.config.include.previewMedia;\n const incContent = this.config.include.contentMedia;\n\n const __incPreview = (mediaType: 'audio' | 'video' | 'image') => {\n if (typeof incPreview === 'boolean') {\n return incPreview;\n }\n return incPreview.includes(mediaType);\n };\n\n const __incContent = (mediaType: 'audio' | 'video' | 'image' | 'attachment') => {\n if (typeof incContent === 'boolean') {\n return incContent;\n }\n return incContent.includes(mediaType);\n };\n\n const __getEmbedTask = () => {\n if (!post.embed) {\n return null;\n }\n\n const hasEmbedDownloader = DownloadTaskFactory.findEmbedDownloader(this.config.embedDownloaders, post.embed.provider);\n const isDownloadableVideo = isYouTubeEmbed(post.embed) || (post.embed.type === 'videoEmbed' && hasEmbedDownloader);\n const isDownloadableOther = !isYouTubeEmbed(post.embed) && post.embed.type !== 'videoEmbed' && hasEmbedDownloader;\n \n if ((isDownloadableVideo && __incContent('video')) || isDownloadableOther) {\n const embedType = post.embed.type === 'videoEmbed' ? ' video' : post.embed.type === 'linkEmbed' ? ' link' : '';\n return {\n target: [ post.embed ],\n targetName: `post #${post.id} -> embedded ${post.embed.provider}${embedType}`,\n dirs: {\n campaign: post.campaign ? this.fsHelper.getCampaignDirs(post.campaign).root : null,\n main: postDirs.embed,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n };\n }\n \n return null;\n }\n\n const campaignDir = post.campaign ? this.fsHelper.getCampaignDirs(post.campaign).root : null;\n\n await this.#processLinkedAttachments(post);\n const downloadableLinkedAttachments = post.linkedAttachments?.reduce<Downloadable<AttachmentMediaItem>[]>((result, att) => {\n if (att.downloadable) {\n result.push(att.downloadable);\n }\n return result;\n }, []) || [];\n\n const allAttachments = [...post.attachments, ...downloadableLinkedAttachments];\n\n const batchResult = this.createDownloadTaskBatch(\n `Post #${post.id} (${post.title})`,\n signal,\n\n __incPreview('audio') && post.audioPreview ? {\n target: [ post.audioPreview ],\n targetName: `post #${post.id} -> audio preview`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.audioPreview,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incPreview('video') && post.videoPreview ? {\n target: [ post.videoPreview ],\n targetName: `post #${post.id} -> video preview`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.videoPreview,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n /**\n * If post is not viewable by current user, its images will be\n * blurry and we should categorize them as image previews.\n */\n __incPreview('image') && post.images.length > 0 && !post.isViewable ? {\n target: post.images,\n targetName: `post #${post.id} -> image previews`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.imagePreviews,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n /**\n * If post is not viewable, audio data should have no URL, so check and\n * skip if this is the case.\n */\n __incContent('audio') && post.audio && (post.isViewable || (post.audio.type === 'audio' && post.audio.url)) ? {\n target: [ post.audio ],\n targetName: `post #${post.id} -> audio`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.audio,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('video') && post.video ? {\n target: [ post.video ],\n targetName: `post #${post.id} -> video`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.video,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('image') && post.images.length > 0 && post.isViewable ? {\n target: post.images,\n targetName: `post #${post.id} -> images`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.images,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n __incContent('attachment') && allAttachments.length > 0 ? {\n target: allAttachments,\n targetName: `post #${post.id} -> attachments`,\n dirs: {\n campaign: campaignDir,\n main: postDirs.attachments,\n thumbnails: postDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content,\n isAttachment: true\n } : null,\n\n __getEmbedTask()\n );\n\n return batchResult;\n }\n\n async #processLinkedAttachments(post: Post, signal?: AbortSignal) {\n if (!post.linkedAttachments || post.linkedAttachments.length === 0) {\n return;\n }\n this.log('debug', `Process linked attachments of post #${post.id}`);\n for (const la of post.linkedAttachments) {\n const laStr = `[#${post.id} -> #${la.mediaId}]`;\n // Only process linked attachment where its postId is not the same as current one being processed.\n // If same as current one, then linked attachment would already be in the current post data.\n if (la.postId === post.id) {\n this.log('debug', `Linked attachment ${laStr} has same parent post`);\n }\n else {\n const apiURL = URLHelper.constructPostsAPIURL({ postId: la.postId });\n let json;\n try {\n this.log('debug', `Linked attachment ${laStr} belongs to post #${la.postId}`);\n json = (await this.fetcher.get({\n url: apiURL,\n type: 'json',\n maxRetries: this.config.request.maxRetries,\n signal }\n )).json;\n }\n catch (error) {\n if (signal?.aborted) {\n throw error;\n }\n else {\n this.log('error', `Error fetching linked attachment ${laStr} from parent post #${la.postId}: API request failed for \"${apiURL}\": `, error);\n }\n json = null;\n }\n if (json) {\n const parser = new PostParser();\n const parentPost = parser.parsePostsAPIResponse(json, apiURL).items[0];\n if (!parentPost) {\n this.log('error', `Error fetching linked attachment ${laStr} from parent post #${la.postId}: post data not found in response of \"${apiURL}\"`);\n }\n else {\n if (!parentPost.isViewable) {\n this.log('warn', `Parent post #${la.postId} of linked attachment ${laStr} is not viewable by user`);\n }\n else {\n const attachment = parentPost.attachments.find((att) => att.id === la.mediaId);\n if (!attachment) {\n this.log('warn', `Attachment not found in parent post #${la.postId} of linked attachment ${laStr}`);\n }\n else {\n la.downloadable = attachment;\n this.log('debug', `Obtained attachment from parent post #${la.postId} of linked attachment ${laStr}`);\n }\n }\n }\n }\n }\n }\n }\n\n async #fetchComments(post: Post, signal?: AbortSignal, accumulated?: CommentList & { nextURL: string; }): Promise<Comment[]> {\n if (!post.commentCount) {\n this.log('debug', `Comment count is zero for post #${post.id}`);\n return [];\n }\n if (this.checkAbortSignal(signal)) {\n return [];\n }\n let commentsURL;\n if (!accumulated) {\n this.log('info', `Fetch comments for post #${post.id}`);\n commentsURL = URLHelper.constructPostCommentsAPIURL({ postId: post.id });\n }\n else {\n this.log('debug', `Fetch next batch of comments for post #${post.id}`);\n commentsURL = accumulated.nextURL;\n }\n const { json } = await this.commonFetchAPI(commentsURL, signal);\n const parser = new CommentParser(this.logger);\n if (json) {\n const comments = parser.parseCommentsAPIResponse(json, commentsURL);\n this.log('debug', `Fetched ${comments.items.length} comments for post #${post.id}`);\n if (comments.items.length > 0 && comments.nextURL) {\n let _acc;\n if (!accumulated) {\n _acc = {\n url: comments.url,\n items: comments.items,\n nextURL: comments.nextURL,\n total: comments.total\n };\n }\n else {\n _acc = accumulated;\n _acc.url = comments.url;\n _acc.items.push(...comments.items);\n _acc.nextURL = comments.nextURL;\n }\n return this.#fetchComments(post, signal, _acc);\n }\n else {\n const result = accumulated ? [ ...accumulated.items, ...comments.items ] : comments.items;\n this.log('debug', `Total ${result.length} comments fetched for post #${post.id}`);\n for (const comment of result) {\n if (comment.replyCount > 0) {\n comment.replies = await this.#fetchCommentReplies(comment, signal);\n }\n }\n return result;\n }\n }\n else if (this.checkAbortSignal(signal)) {\n return [];\n }\n else {\n this.log('warn', `Failed to fetch comments for post #${post.id}`);\n return [];\n }\n }\n\n async #fetchCommentReplies(comment: Comment, signal?: AbortSignal, accumulated?: CommentReplyList & { nextURL: string; }): Promise<CommentReply[]> {\n if (!comment.replyCount) {\n this.log('debug', `Reply count is zero for comment #${comment.id}`);\n return [];\n }\n if (this.checkAbortSignal(signal)) {\n return [];\n }\n let repliesURL;\n if (!accumulated) {\n this.log('debug', `Fetch replies to comment #${comment.id}`);\n repliesURL = URLHelper.constructPostCommentsAPIURL({ commentId: comment.id, replies: true });\n }\n else {\n this.log('debug', `Fetch next batch of replies to comment #${comment.id}`);\n repliesURL = accumulated.nextURL;\n }\n const { json } = await this.commonFetchAPI(repliesURL, signal);\n const parser = new CommentParser(this.logger);\n if (json) {\n const replies = parser.parseCommentsAPIResponse(json, repliesURL, true);\n this.log('debug', `Fetched ${replies.items.length} replies to comment #${comment.id}`);\n if (replies.items.length > 0 && replies.nextURL) {\n let _acc;\n if (!accumulated) {\n _acc = {\n url: replies.url,\n items: replies.items,\n nextURL: replies.nextURL,\n total: replies.total\n };\n }\n else {\n _acc = accumulated;\n _acc.url = replies.url;\n _acc.items.push(...replies.items);\n _acc.nextURL = replies.nextURL;\n }\n return this.#fetchCommentReplies(comment, signal, _acc);\n }\n else {\n const result = accumulated ? [ ...accumulated.items, ...replies.items ] : replies.items;\n this.log('debug', `Total ${result.length} replies fetched for comment #${comment.id}`);\n return result;\n }\n }\n else if (this.checkAbortSignal(signal)) {\n return [];\n }\n else {\n this.log('warn', `Failed to fetch replies to comment #${comment.id}`);\n return [];\n }\n }\n\n async #saveCollection(collection: Collection, campaign: Campaign, signal?: AbortSignal) {\n const db = await this.db();\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n if (!this.config.include.contentInfo) {\n db.saveCollection(collection, campaign);\n return;\n }\n\n let batch: DownloadTaskBatch | null = null;\n const abortHandler = () => {\n void (async () => {\n if (batch) {\n await batch.abort();\n }\n })();\n };\n if (signal) {\n signal.addEventListener('abort', abortHandler, { once: true });\n }\n\n this.log('info', `Save collection info #${collection.id}`);\n this.emit('targetBegin', { target: collection });\n this.emit('phaseBegin', { target: collection, phase: 'saveInfo' });\n\n // Step 1: create collection directories\n const collectionDirs = this.fsHelper.getCollectionsDir(campaign, collection);\n this.log('debug', 'Campaign directories: ', collectionDirs);\n this.fsHelper.createDir(collectionDirs.root);\n\n // Step 2: save summary and raw json\n const summary = generateCollectionSummary(collection);\n const summaryFile = path.resolve(collectionDirs.root, 'info.txt');\n const saveSummaryResult = await this.fsHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, collection, 'collection summary');\n\n const collectionRawFile = path.resolve(collectionDirs.root, 'collection-api.json');\n const saveCollectionRawResult = await this.fsHelper.writeTextFile(\n collectionRawFile, collection.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(saveCollectionRawResult, collection, 'collection API data');\n\n this.emit('phaseEnd', { target: collection, phase: 'saveInfo' });\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n // Step 3: download collection media items\n if (collection.thumbnail) {\n this.emit('phaseBegin', { target: collection, phase: 'saveMedia' });\n const collectionMedia: Downloadable[] = [\n collection.thumbnail\n ];\n batch = (await this.createDownloadTaskBatch(\n `Collection #${collection.id} (${collection.title})`,\n signal,\n {\n target: collectionMedia,\n targetName: `collection #${campaign.id} -> thumbnail`,\n dirs: {\n campaign: this.fsHelper.getCampaignDirs(campaign).root,\n main: collectionDirs.root,\n thumbnails: null\n },\n fileExistsAction: this.config.fileExistsAction.info\n }\n )).batch;\n if (this.checkAbortSignal(signal)) {\n return;\n }\n batch.prestart();\n this.emit('phaseBegin', { target: collection, phase: 'batchDownload', batch });\n await batch.start();\n await batch.destroy();\n this.emit('phaseEnd', { target: collection, phase: 'batchDownload' });\n this.emit('phaseEnd', { target: collection, phase: 'saveMedia' });\n\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n if (this.checkAbortSignal(signal)) {\n return;\n }\n }\n\n // Step 4: save to DB\n db.saveCollection(collection, campaign);\n\n // Done\n this.log('info', 'Done saving collection info');\n this.emit('targetEnd', { target: collection, isSkipped: false });\n }\n\n}\n"]}
|
|
@@ -9,13 +9,14 @@ 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 _PostsFetcher_instances, _PostsFetcher_pointers, _PostsFetcher_fetched, _PostsFetcher_total, _PostsFetcher_nextPromises, _PostsFetcher_sleeper, _PostsFetcher_noSleep, _PostsFetcher_setStatus, _PostsFetcher_isRunning, _PostsFetcher_doBegin, _PostsFetcher_handleError, _PostsFetcher_isFetchingMultiplePosts,
|
|
12
|
+
var _PostsFetcher_instances, _PostsFetcher_pointers, _PostsFetcher_fetched, _PostsFetcher_total, _PostsFetcher_nextPromises, _PostsFetcher_sleeper, _PostsFetcher_noSleep, _PostsFetcher_setStatus, _PostsFetcher_isRunning, _PostsFetcher_doBegin, _PostsFetcher_handleError, _PostsFetcher_isFetchingMultiplePosts, _PostsFetcher_getInitialPostsAPIURL, _PostsFetcher_getInitialDataPageURL, _PostsFetcher_fetchAPI;
|
|
13
13
|
import EventEmitter from 'events';
|
|
14
14
|
import { commonLog } from '../utils/logging/Logger.js';
|
|
15
15
|
import URLHelper, { PostSortOrder } from '../utils/URLHelper.js';
|
|
16
16
|
import PostParser from '../parsers/PostParser.js';
|
|
17
17
|
import Sleeper from '../utils/Sleeper.js';
|
|
18
18
|
import { InitialData } from './InitialData.js';
|
|
19
|
+
import fse from 'fs-extra';
|
|
19
20
|
const SLEEPER_INTERVAL = 900000; // 15 mins
|
|
20
21
|
class PostsFetcher extends EventEmitter {
|
|
21
22
|
constructor(params) {
|
|
@@ -186,32 +187,45 @@ _PostsFetcher_pointers = new WeakMap(), _PostsFetcher_fetched = new WeakMap(), _
|
|
|
186
187
|
__classPrivateFieldGet(this, _PostsFetcher_instances, "m", _PostsFetcher_setStatus).call(this, { status: 'running' });
|
|
187
188
|
__classPrivateFieldGet(this, _PostsFetcher_pointers, "f").fetching = 0;
|
|
188
189
|
const postFetch = this.config.postFetch;
|
|
189
|
-
let
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
let postsSrc;
|
|
191
|
+
if (postFetch.type !== 'byFile') {
|
|
192
|
+
try {
|
|
193
|
+
postsSrc = await __classPrivateFieldGet(this, _PostsFetcher_instances, "m", _PostsFetcher_getInitialPostsAPIURL).call(this);
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
__classPrivateFieldGet(this, _PostsFetcher_instances, "m", _PostsFetcher_handleError).call(this, error);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
192
199
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return;
|
|
200
|
+
else {
|
|
201
|
+
postsSrc = postFetch.filePath;
|
|
196
202
|
}
|
|
197
203
|
if (__classPrivateFieldGet(this, _PostsFetcher_instances, "m", _PostsFetcher_isFetchingMultiplePosts).call(this, postFetch)) {
|
|
198
204
|
this.log('info', 'Fetch posts');
|
|
199
|
-
this.log('debug', `Request initial posts from API URL "${
|
|
205
|
+
this.log('debug', `Request initial posts from API URL "${postsSrc}"`);
|
|
206
|
+
}
|
|
207
|
+
else if (postFetch.type === 'byFile') {
|
|
208
|
+
this.log('info', `Read post data from "${postFetch.filePath}"`);
|
|
200
209
|
}
|
|
201
210
|
else {
|
|
202
211
|
this.log('info', 'Fetch target post');
|
|
203
|
-
this.log('debug', `Request post #${postFetch.postId} from API URL "${
|
|
212
|
+
this.log('debug', `Request post #${postFetch.postId} from API URL "${postsSrc}`);
|
|
204
213
|
}
|
|
205
214
|
let json;
|
|
206
215
|
try {
|
|
207
|
-
|
|
216
|
+
if (postFetch.type !== 'byFile') {
|
|
217
|
+
json = await __classPrivateFieldGet(this, _PostsFetcher_instances, "m", _PostsFetcher_fetchAPI).call(this, postsSrc);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
json = fse.readJSONSync(postFetch.filePath);
|
|
221
|
+
}
|
|
208
222
|
}
|
|
209
223
|
catch (error) {
|
|
210
224
|
__classPrivateFieldGet(this, _PostsFetcher_instances, "m", _PostsFetcher_handleError).call(this, error);
|
|
211
225
|
return;
|
|
212
226
|
}
|
|
213
227
|
const postsParser = new PostParser(this.logger);
|
|
214
|
-
const list = postsParser.parsePostsAPIResponse(json,
|
|
228
|
+
const list = postsParser.parsePostsAPIResponse(json, postsSrc);
|
|
215
229
|
__classPrivateFieldSet(this, _PostsFetcher_fetched, [list], "f");
|
|
216
230
|
__classPrivateFieldGet(this, _PostsFetcher_pointers, "f").lastFetched = __classPrivateFieldGet(this, _PostsFetcher_pointers, "f").fetching;
|
|
217
231
|
__classPrivateFieldGet(this, _PostsFetcher_pointers, "f").fetching = null;
|
|
@@ -289,7 +303,10 @@ _PostsFetcher_pointers = new WeakMap(), _PostsFetcher_fetched = new WeakMap(), _
|
|
|
289
303
|
__classPrivateFieldGet(this, _PostsFetcher_instances, "m", _PostsFetcher_setStatus).call(this, { status: 'error', error });
|
|
290
304
|
}, _PostsFetcher_isFetchingMultiplePosts = function _PostsFetcher_isFetchingMultiplePosts(postFetch) {
|
|
291
305
|
return postFetch.type === 'byUser' || postFetch.type === 'byUserId' || postFetch.type === 'byCollection';
|
|
292
|
-
},
|
|
306
|
+
}, _PostsFetcher_getInitialPostsAPIURL = async function _PostsFetcher_getInitialPostsAPIURL() {
|
|
307
|
+
if (this.config.postFetch.type === 'byFile') {
|
|
308
|
+
throw Error('Posts API URL cannot be obtained from file');
|
|
309
|
+
}
|
|
293
310
|
const postFetch = this.config.postFetch;
|
|
294
311
|
if (__classPrivateFieldGet(this, _PostsFetcher_instances, "m", _PostsFetcher_isFetchingMultiplePosts).call(this, postFetch)) {
|
|
295
312
|
const pageURL = __classPrivateFieldGet(this, _PostsFetcher_instances, "m", _PostsFetcher_getInitialDataPageURL).call(this);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostsFetcher.js","sourceRoot":"","sources":["../../src/downloaders/PostsFetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import EventEmitter from 'events';\nimport { type Post } from '../entities/index.js';\nimport { type Logger } from '../utils/logging/index.js';\nimport { type LogLevel, commonLog } from '../utils/logging/Logger.js';\nimport { type DownloaderConfig } from './Downloader.js';\nimport URLHelper, { PostSortOrder } from '../utils/URLHelper.js';\nimport type Fetcher from '../utils/Fetcher.js';\nimport PostParser from '../parsers/PostParser.js';\nimport { type PostList } from '../entities/Post.js';\nimport Sleeper from '../utils/Sleeper.js';\nimport { InitialData } from './InitialData.js';\n\nexport type PostsFetcherStatus = {\n status: 'ready' | 'running' | 'completed' | 'aborted';\n error?: undefined;\n} | {\n status: 'error';\n error: any;\n};\n\nexport type PostsFetcherEvent = 'fetched' | 'statusChange';\nexport type PostsFetcherEventPayload<T extends PostsFetcherEvent> =\n T extends 'fetched' ? {\n list: PostList;\n index: number;\n } :\n T extends 'statusChange' ? {\n current: PostsFetcherStatus;\n old: PostsFetcherStatus;\n } :\n never;\n\nexport interface PostsFetcherResult {\n list: PostList | null;\n error?: any;\n aborted: boolean;\n}\n\nconst SLEEPER_INTERVAL = 900000; // 15 mins\n\nexport default class PostsFetcher extends EventEmitter {\n\n name = 'PostsFetcher';\n\n protected status: PostsFetcherStatus;\n protected config: DownloaderConfig<Post>;\n protected fetcher: Fetcher;\n protected signal?: AbortSignal;\n protected logger?: Logger | null;\n\n #pointers: {\n fetching: number | null;\n lastFetched: number | null;\n returning: number | null;\n lastReturned: number | null; // Last returned in next()\n };\n #fetched: PostList[];\n #total: number | null;\n #nextPromises: Array<Promise<PostsFetcherResult> | undefined>;\n #sleeper: Sleeper | null;\n #noSleep: boolean;\n\n constructor(params: {\n config: DownloaderConfig<Post>,\n fetcher: Fetcher,\n logger?: Logger | null,\n signal?: AbortSignal\n }) {\n super();\n const { config, fetcher, logger, signal } = params;\n this.config = config;\n this.fetcher = fetcher;\n this.logger = logger;\n this.signal = signal;\n this.#fetched = [];\n this.status = { status: 'ready' };\n this.#pointers = {\n fetching: null,\n lastFetched: null,\n returning: null,\n lastReturned: null\n };\n this.#nextPromises = [];\n this.#sleeper = null;\n this.#noSleep = false;\n }\n\n isFetchingMultiple() {\n return this.#isFetchingMultiplePosts(this.config.postFetch);\n }\n\n getTargetType() {\n return this.#isFetchingMultiplePosts(this.config.postFetch) ? 'posts' : 'post';\n }\n\n protected log(level: LogLevel, ...msg: any[]) {\n commonLog(this.logger, level, this.name, ...msg);\n }\n\n #setStatus(status: PostsFetcherStatus) {\n const oldStatus = this.status;\n this.status = status;\n this.emit('statusChange', { current: status, old: oldStatus });\n }\n\n #isRunning() {\n return this.status.status === 'running';\n }\n\n begin() {\n void this.#doBegin();\n }\n\n async #doBegin() {\n if (this.status.status !== 'ready') {\n throw Error('PostsFetcher already running or has ended');\n }\n\n this.#setStatus({ status: 'running' });\n\n this.#pointers.fetching = 0;\n const postFetch = this.config.postFetch;\n let postsAPIURL: string;\n try {\n postsAPIURL = await this.#getInitialPostsAPIUL();\n }\n catch (error) {\n this.#handleError(error);\n return;\n }\n if (this.#isFetchingMultiplePosts(postFetch)) {\n this.log('info', 'Fetch posts');\n this.log('debug', `Request initial posts from API URL \"${postsAPIURL}\"`);\n }\n else {\n this.log('info', 'Fetch target post');\n this.log('debug', `Request post #${postFetch.postId} from API URL \"${postsAPIURL}`);\n }\n\n let json;\n try {\n json = await this.#fetchAPI(postsAPIURL);\n }\n catch (error) {\n this.#handleError(error);\n return;\n }\n\n const postsParser = new PostParser(this.logger);\n const list = postsParser.parsePostsAPIResponse(json, postsAPIURL);\n this.#fetched = [ list ];\n this.#pointers.lastFetched = this.#pointers.fetching;\n this.#pointers.fetching = null;\n this.emit('fetched', { list, index: 0 });\n\n const total = this.#total = this.#fetched[0].total;\n if (this.#isFetchingMultiplePosts(postFetch)) {\n let totalFetched = this.#fetched[0].items.length;\n this.log('info', `Fetched posts: ${totalFetched} / ${total}`);\n let nextURL = this.#fetched[0].nextURL;\n while (nextURL) {\n let json;\n try {\n this.#pointers.fetching = this.#pointers.lastFetched !== null ? this.#pointers.lastFetched + 1 : 1;\n const sleep = !this.#pointers.returning || this.#pointers.returning < this.#pointers.fetching;\n if (sleep && !this.#sleeper) {\n this.log('debug', `Has more posts - will fetch in ${SLEEPER_INTERVAL / 1000} seconds`);\n this.#sleeper = Sleeper.getInstance(SLEEPER_INTERVAL, this.signal);\n await this.#sleeper.start();\n }\n this.log('debug', `Request more posts from API URL \"${nextURL}\"`);\n json = await this.#fetchAPI(nextURL);\n }\n catch (error) {\n this.#handleError(error);\n json = null;\n }\n finally {\n if (this.#sleeper) {\n this.#sleeper.destroy();\n this.#sleeper = null;\n }\n }\n if (!json) {\n nextURL = null;\n }\n else {\n const list = postsParser.parsePostsAPIResponse(json, nextURL);\n this.#fetched.push(list);\n const fetched = list.items.length;\n totalFetched += fetched;\n this.log('info', `Fetched posts: ${totalFetched} / ${total}`);\n nextURL = list.nextURL;\n this.#pointers.lastFetched = this.#pointers.fetching;\n this.#pointers.fetching = null;\n this.emit('fetched', { list, index: this.#fetched.length - 1 });\n }\n }\n if (!this.checkAbortSignal()) {\n if (total && totalFetched < total) {\n this.log('warn', `Done, but some posts were not fetched. Total expected: ${total}; currently fetched: ${totalFetched}`);\n }\n else {\n this.log('info', `Done. ${totalFetched} posts fetched`);\n }\n\n if (this.#isRunning()) {\n this.#setStatus({ status: 'completed' });\n }\n }\n }\n // Set 'completed' if not fetching multiple posts\n else if (!this.checkAbortSignal() && this.#isRunning()) {\n this.#setStatus({ status: 'completed' });\n }\n }\n\n #handleError(error: any) {\n const statusName = this.status.status;\n if (statusName === 'aborted' || statusName === 'completed') {\n return;\n }\n if (this.signal?.aborted) {\n this.log('warn', 'Abort');\n this.#setStatus({ status: 'aborted' });\n return;\n }\n this.log('error', error);\n this.#setStatus({ status: 'error', error });\n }\n\n #isFetchingMultiplePosts(postFetch: DownloaderConfig<Post>['postFetch']): postFetch is DownloaderConfig<Post>['postFetch'] & { type: 'byUser' | 'byUserId' | 'byCollection' } {\n return postFetch.type === 'byUser' || postFetch.type === 'byUserId' || postFetch.type === 'byCollection';\n }\n\n async #getInitialPostsAPIUL() {\n const postFetch = this.config.postFetch;\n if (this.#isFetchingMultiplePosts(postFetch)) {\n const pageURL = this.#getInitialDataPageURL();\n const { campaignId, currentUserId } = await this.getInitialData(pageURL);\n let sort: PostSortOrder | undefined;\n if (postFetch.type === 'byCollection') {\n sort = PostSortOrder.CollectionOrder;\n }\n\n return URLHelper.constructPostsAPIURL({\n campaignId,\n currentUserId: this.config.include.lockedContent ? undefined : currentUserId,\n filters: postFetch.filters,\n sort\n });\n }\n\n return URLHelper.constructPostsAPIURL({ postId: postFetch.postId });\n }\n\n #getInitialDataPageURL() {\n const postFetch = this.config.postFetch;\n switch (postFetch.type) {\n case 'byUser':\n return URLHelper.constructCampaignPageURL({ vanity: postFetch.vanity });\n case 'byUserId':\n return URLHelper.constructCampaignPageURL({ userId: postFetch.userId });\n case 'byCollection':\n return URLHelper.constructCollectionURL(postFetch.collectionId);\n default:\n throw Error(`postFetch type mismatch: expecting 'byUser', 'byUserId' or 'byCollection' but got '${postFetch.type}'`);\n }\n }\n\n getInitialData(url: string) {\n const id = new InitialData(this.config, this.fetcher, this.logger);\n return id.get(url, this.signal);\n }\n\n async #fetchAPI(url: string) {\n return (await this.fetcher.get({ url, type: 'json', maxRetries: this.config.request.maxRetries, signal: this.signal })).json;\n }\n\n protected checkAbortSignal() {\n return this.signal && this.signal.aborted;\n }\n\n hasNext() {\n const lastReturned = this.#pointers.lastReturned !== null ? this.#pointers.lastReturned : -1;\n return this.#isRunning() || (this.#fetched.length > 0 && lastReturned < this.#fetched.length - 1);\n }\n\n async next(): Promise<PostsFetcherResult> {\n this.#pointers.returning = this.#pointers.lastReturned !== null ? this.#pointers.lastReturned + 1 : 0;\n const ptr = this.#pointers.returning;\n this.log('debug', `next() requested (${ptr})`);\n const __parseStatus = (status: PostsFetcherStatus) => {\n let list: PostList | null | undefined;\n let aborted = false;\n let error: any;\n switch (status.status) {\n case 'aborted':\n list = null;\n aborted = true;\n break;\n case 'error':\n if (this.#fetched[ptr]) {\n list = this.#fetched[ptr];\n }\n else {\n list = null;\n error = status.error;\n }\n break;\n case 'completed':\n list = this.#fetched[ptr] || null;\n break;\n default:\n list = this.#fetched[ptr] || undefined;\n }\n return { list, aborted, error };\n };\n if (this.#isRunning() && !this.#fetched[ptr]) {\n let result = this.#nextPromises[ptr];\n if (!result) {\n let resolved = false;\n result = new Promise<PostsFetcherResult>((resolve) => {\n const fetchedListener = () => {\n if (resolved) {\n this.off('fetched', fetchedListener);\n return;\n }\n if (this.#fetched[ptr]) {\n this.off('fetched', fetchedListener);\n resolved = true;\n resolve({\n list: this.#fetched[ptr],\n aborted: false\n });\n }\n };\n const statusListener = (args: { current: PostsFetcherStatus }) => {\n if (resolved) {\n this.off('statusChange', statusListener);\n return;\n }\n const { list, aborted, error } = __parseStatus(args.current);\n if (list !== undefined) {\n this.off('statusChange', statusListener);\n resolved = true;\n resolve({ list, aborted, error });\n }\n };\n this.on('fetched', fetchedListener);\n this.on('statusChange', statusListener);\n if (!this.#noSleep) {\n this.#noSleep = true;\n }\n if (this.#sleeper) {\n this.log('debug', 'Wake up early from sleep');\n this.#sleeper.wake();\n }\n })\n .finally(() => {\n this.#nextPromises[ptr] = undefined;\n this.#noSleep = false;\n this.#pointers.lastReturned = this.#pointers.returning;\n this.#pointers.returning = null;\n if (resolved) {\n this.log('debug', `next() handled (${ptr})`);\n }\n else {\n this.log('debug', `next() handled (${ptr}) - no resolve`);\n }\n });\n this.#nextPromises[ptr] = result;\n }\n return result;\n }\n this.#pointers.lastReturned = this.#pointers.returning;\n this.#pointers.returning = null;\n this.log('debug', `next() handled (${ptr})`);\n return __parseStatus(this.status);\n }\n\n getTotal() {\n return this.#total;\n }\n\n emit<T extends PostsFetcherEvent>(eventName: T, args: PostsFetcherEventPayload<T>): boolean;\n emit(eventName: string | symbol, ...args: any[]): boolean {\n return super.emit(eventName, ...args);\n }\n\n on<T extends PostsFetcherEvent>(eventName: T, listener: (args: PostsFetcherEventPayload<T>) => void): this;\n on(eventName: string | symbol, listener: (...args: any[]) => void): this {\n return super.on(eventName, listener);\n }\n\n off<T extends PostsFetcherEvent>(eventName: T, listener: (args: PostsFetcherEventPayload<T>) => void): this;\n off(eventName: string | symbol, listener: (...args: any[]) => void): this {\n return super.off(eventName, listener);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"PostsFetcher.js","sourceRoot":"","sources":["../../src/downloaders/PostsFetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import EventEmitter from 'events';\nimport { type Post } from '../entities/index.js';\nimport { type Logger } from '../utils/logging/index.js';\nimport { type LogLevel, commonLog } from '../utils/logging/Logger.js';\nimport { type DownloaderConfig } from './Downloader.js';\nimport URLHelper, { PostSortOrder } from '../utils/URLHelper.js';\nimport type Fetcher from '../utils/Fetcher.js';\nimport PostParser from '../parsers/PostParser.js';\nimport { type PostList } from '../entities/Post.js';\nimport Sleeper from '../utils/Sleeper.js';\nimport { InitialData } from './InitialData.js';\nimport fse from 'fs-extra';\n\nexport type PostsFetcherStatus = {\n status: 'ready' | 'running' | 'completed' | 'aborted';\n error?: undefined;\n} | {\n status: 'error';\n error: any;\n};\n\nexport type PostsFetcherEvent = 'fetched' | 'statusChange';\nexport type PostsFetcherEventPayload<T extends PostsFetcherEvent> =\n T extends 'fetched' ? {\n list: PostList;\n index: number;\n } :\n T extends 'statusChange' ? {\n current: PostsFetcherStatus;\n old: PostsFetcherStatus;\n } :\n never;\n\nexport interface PostsFetcherResult {\n list: PostList | null;\n error?: any;\n aborted: boolean;\n}\n\nconst SLEEPER_INTERVAL = 900000; // 15 mins\n\nexport default class PostsFetcher extends EventEmitter {\n\n name = 'PostsFetcher';\n\n protected status: PostsFetcherStatus;\n protected config: DownloaderConfig<Post>;\n protected fetcher: Fetcher;\n protected signal?: AbortSignal;\n protected logger?: Logger | null;\n\n #pointers: {\n fetching: number | null;\n lastFetched: number | null;\n returning: number | null;\n lastReturned: number | null; // Last returned in next()\n };\n #fetched: PostList[];\n #total: number | null;\n #nextPromises: Array<Promise<PostsFetcherResult> | undefined>;\n #sleeper: Sleeper | null;\n #noSleep: boolean;\n\n constructor(params: {\n config: DownloaderConfig<Post>,\n fetcher: Fetcher,\n logger?: Logger | null,\n signal?: AbortSignal\n }) {\n super();\n const { config, fetcher, logger, signal } = params;\n this.config = config;\n this.fetcher = fetcher;\n this.logger = logger;\n this.signal = signal;\n this.#fetched = [];\n this.status = { status: 'ready' };\n this.#pointers = {\n fetching: null,\n lastFetched: null,\n returning: null,\n lastReturned: null\n };\n this.#nextPromises = [];\n this.#sleeper = null;\n this.#noSleep = false;\n }\n\n isFetchingMultiple() {\n return this.#isFetchingMultiplePosts(this.config.postFetch);\n }\n\n getTargetType() {\n return this.#isFetchingMultiplePosts(this.config.postFetch) ? 'posts' : 'post';\n }\n\n protected log(level: LogLevel, ...msg: any[]) {\n commonLog(this.logger, level, this.name, ...msg);\n }\n\n #setStatus(status: PostsFetcherStatus) {\n const oldStatus = this.status;\n this.status = status;\n this.emit('statusChange', { current: status, old: oldStatus });\n }\n\n #isRunning() {\n return this.status.status === 'running';\n }\n\n begin() {\n void this.#doBegin();\n }\n\n async #doBegin() {\n if (this.status.status !== 'ready') {\n throw Error('PostsFetcher already running or has ended');\n }\n\n this.#setStatus({ status: 'running' });\n\n this.#pointers.fetching = 0;\n const postFetch = this.config.postFetch;\n \n let postsSrc: string;\n if (postFetch.type !== 'byFile') {\n try {\n postsSrc = await this.#getInitialPostsAPIURL();\n }\n catch (error) {\n this.#handleError(error);\n return;\n }\n }\n else {\n postsSrc = postFetch.filePath;\n }\n \n if (this.#isFetchingMultiplePosts(postFetch)) {\n this.log('info', 'Fetch posts');\n this.log('debug', `Request initial posts from API URL \"${postsSrc}\"`);\n }\n else if (postFetch.type === 'byFile') {\n this.log('info', `Read post data from \"${postFetch.filePath}\"`);\n }\n else {\n this.log('info', 'Fetch target post');\n this.log('debug', `Request post #${postFetch.postId} from API URL \"${postsSrc}`);\n }\n\n let json;\n try {\n if (postFetch.type !== 'byFile') {\n json = await this.#fetchAPI(postsSrc);\n }\n else {\n json = fse.readJSONSync(postFetch.filePath);\n }\n }\n catch (error) {\n this.#handleError(error);\n return;\n }\n\n const postsParser = new PostParser(this.logger);\n const list = postsParser.parsePostsAPIResponse(json, postsSrc);\n this.#fetched = [ list ];\n this.#pointers.lastFetched = this.#pointers.fetching;\n this.#pointers.fetching = null;\n this.emit('fetched', { list, index: 0 });\n\n const total = this.#total = this.#fetched[0].total;\n if (this.#isFetchingMultiplePosts(postFetch)) {\n let totalFetched = this.#fetched[0].items.length;\n this.log('info', `Fetched posts: ${totalFetched} / ${total}`);\n let nextURL = this.#fetched[0].nextURL;\n while (nextURL) {\n let json;\n try {\n this.#pointers.fetching = this.#pointers.lastFetched !== null ? this.#pointers.lastFetched + 1 : 1;\n const sleep = !this.#pointers.returning || this.#pointers.returning < this.#pointers.fetching;\n if (sleep && !this.#sleeper) {\n this.log('debug', `Has more posts - will fetch in ${SLEEPER_INTERVAL / 1000} seconds`);\n this.#sleeper = Sleeper.getInstance(SLEEPER_INTERVAL, this.signal);\n await this.#sleeper.start();\n }\n this.log('debug', `Request more posts from API URL \"${nextURL}\"`);\n json = await this.#fetchAPI(nextURL);\n }\n catch (error) {\n this.#handleError(error);\n json = null;\n }\n finally {\n if (this.#sleeper) {\n this.#sleeper.destroy();\n this.#sleeper = null;\n }\n }\n if (!json) {\n nextURL = null;\n }\n else {\n const list = postsParser.parsePostsAPIResponse(json, nextURL);\n this.#fetched.push(list);\n const fetched = list.items.length;\n totalFetched += fetched;\n this.log('info', `Fetched posts: ${totalFetched} / ${total}`);\n nextURL = list.nextURL;\n this.#pointers.lastFetched = this.#pointers.fetching;\n this.#pointers.fetching = null;\n this.emit('fetched', { list, index: this.#fetched.length - 1 });\n }\n }\n if (!this.checkAbortSignal()) {\n if (total && totalFetched < total) {\n this.log('warn', `Done, but some posts were not fetched. Total expected: ${total}; currently fetched: ${totalFetched}`);\n }\n else {\n this.log('info', `Done. ${totalFetched} posts fetched`);\n }\n\n if (this.#isRunning()) {\n this.#setStatus({ status: 'completed' });\n }\n }\n }\n // Set 'completed' if not fetching multiple posts\n else if (!this.checkAbortSignal() && this.#isRunning()) {\n this.#setStatus({ status: 'completed' });\n }\n }\n\n #handleError(error: any) {\n const statusName = this.status.status;\n if (statusName === 'aborted' || statusName === 'completed') {\n return;\n }\n if (this.signal?.aborted) {\n this.log('warn', 'Abort');\n this.#setStatus({ status: 'aborted' });\n return;\n }\n this.log('error', error);\n this.#setStatus({ status: 'error', error });\n }\n\n #isFetchingMultiplePosts(postFetch: DownloaderConfig<Post>['postFetch']): postFetch is DownloaderConfig<Post>['postFetch'] & { type: 'byUser' | 'byUserId' | 'byCollection' } {\n return postFetch.type === 'byUser' || postFetch.type === 'byUserId' || postFetch.type === 'byCollection';\n }\n\n async #getInitialPostsAPIURL() {\n if (this.config.postFetch.type === 'byFile') {\n throw Error('Posts API URL cannot be obtained from file');\n }\n const postFetch = this.config.postFetch;\n if (this.#isFetchingMultiplePosts(postFetch)) {\n const pageURL = this.#getInitialDataPageURL();\n const { campaignId, currentUserId } = await this.getInitialData(pageURL);\n let sort: PostSortOrder | undefined;\n if (postFetch.type === 'byCollection') {\n sort = PostSortOrder.CollectionOrder;\n }\n\n return URLHelper.constructPostsAPIURL({\n campaignId,\n currentUserId: this.config.include.lockedContent ? undefined : currentUserId,\n filters: postFetch.filters,\n sort\n });\n }\n\n return URLHelper.constructPostsAPIURL({ postId: postFetch.postId });\n }\n\n #getInitialDataPageURL() {\n const postFetch = this.config.postFetch;\n switch (postFetch.type) {\n case 'byUser':\n return URLHelper.constructCampaignPageURL({ vanity: postFetch.vanity });\n case 'byUserId':\n return URLHelper.constructCampaignPageURL({ userId: postFetch.userId });\n case 'byCollection':\n return URLHelper.constructCollectionURL(postFetch.collectionId);\n default:\n throw Error(`postFetch type mismatch: expecting 'byUser', 'byUserId' or 'byCollection' but got '${postFetch.type}'`);\n }\n }\n\n getInitialData(url: string) {\n const id = new InitialData(this.config, this.fetcher, this.logger);\n return id.get(url, this.signal);\n }\n\n async #fetchAPI(url: string) {\n return (await this.fetcher.get({ url, type: 'json', maxRetries: this.config.request.maxRetries, signal: this.signal })).json;\n }\n\n protected checkAbortSignal() {\n return this.signal && this.signal.aborted;\n }\n\n hasNext() {\n const lastReturned = this.#pointers.lastReturned !== null ? this.#pointers.lastReturned : -1;\n return this.#isRunning() || (this.#fetched.length > 0 && lastReturned < this.#fetched.length - 1);\n }\n\n async next(): Promise<PostsFetcherResult> {\n this.#pointers.returning = this.#pointers.lastReturned !== null ? this.#pointers.lastReturned + 1 : 0;\n const ptr = this.#pointers.returning;\n this.log('debug', `next() requested (${ptr})`);\n const __parseStatus = (status: PostsFetcherStatus) => {\n let list: PostList | null | undefined;\n let aborted = false;\n let error: any;\n switch (status.status) {\n case 'aborted':\n list = null;\n aborted = true;\n break;\n case 'error':\n if (this.#fetched[ptr]) {\n list = this.#fetched[ptr];\n }\n else {\n list = null;\n error = status.error;\n }\n break;\n case 'completed':\n list = this.#fetched[ptr] || null;\n break;\n default:\n list = this.#fetched[ptr] || undefined;\n }\n return { list, aborted, error };\n };\n if (this.#isRunning() && !this.#fetched[ptr]) {\n let result = this.#nextPromises[ptr];\n if (!result) {\n let resolved = false;\n result = new Promise<PostsFetcherResult>((resolve) => {\n const fetchedListener = () => {\n if (resolved) {\n this.off('fetched', fetchedListener);\n return;\n }\n if (this.#fetched[ptr]) {\n this.off('fetched', fetchedListener);\n resolved = true;\n resolve({\n list: this.#fetched[ptr],\n aborted: false\n });\n }\n };\n const statusListener = (args: { current: PostsFetcherStatus }) => {\n if (resolved) {\n this.off('statusChange', statusListener);\n return;\n }\n const { list, aborted, error } = __parseStatus(args.current);\n if (list !== undefined) {\n this.off('statusChange', statusListener);\n resolved = true;\n resolve({ list, aborted, error });\n }\n };\n this.on('fetched', fetchedListener);\n this.on('statusChange', statusListener);\n if (!this.#noSleep) {\n this.#noSleep = true;\n }\n if (this.#sleeper) {\n this.log('debug', 'Wake up early from sleep');\n this.#sleeper.wake();\n }\n })\n .finally(() => {\n this.#nextPromises[ptr] = undefined;\n this.#noSleep = false;\n this.#pointers.lastReturned = this.#pointers.returning;\n this.#pointers.returning = null;\n if (resolved) {\n this.log('debug', `next() handled (${ptr})`);\n }\n else {\n this.log('debug', `next() handled (${ptr}) - no resolve`);\n }\n });\n this.#nextPromises[ptr] = result;\n }\n return result;\n }\n this.#pointers.lastReturned = this.#pointers.returning;\n this.#pointers.returning = null;\n this.log('debug', `next() handled (${ptr})`);\n return __parseStatus(this.status);\n }\n\n getTotal() {\n return this.#total;\n }\n\n emit<T extends PostsFetcherEvent>(eventName: T, args: PostsFetcherEventPayload<T>): boolean;\n emit(eventName: string | symbol, ...args: any[]): boolean {\n return super.emit(eventName, ...args);\n }\n\n on<T extends PostsFetcherEvent>(eventName: T, listener: (args: PostsFetcherEventPayload<T>) => void): this;\n on(eventName: string | symbol, listener: (...args: any[]) => void): this {\n return super.on(eventName, listener);\n }\n\n off<T extends PostsFetcherEvent>(eventName: T, listener: (args: PostsFetcherEventPayload<T>) => void): this;\n off(eventName: string | symbol, listener: (...args: any[]) => void): this {\n return super.off(eventName, listener);\n }\n}\n"]}
|