patreon-dl 1.6.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/README.md +26 -3
  2. package/dist/cli/CLIOptionValidator.d.ts +4 -2
  3. package/dist/cli/CLIOptionValidator.d.ts.map +1 -1
  4. package/dist/cli/CLIOptionValidator.js +15 -1
  5. package/dist/cli/CLIOptionValidator.js.map +1 -1
  6. package/dist/cli/CLIOptions.d.ts +4 -4
  7. package/dist/cli/CLIOptions.d.ts.map +1 -1
  8. package/dist/cli/CLIOptions.js +59 -7
  9. package/dist/cli/CLIOptions.js.map +1 -1
  10. package/dist/cli/CommandLineParser.d.ts +2 -2
  11. package/dist/cli/CommandLineParser.d.ts.map +1 -1
  12. package/dist/cli/CommandLineParser.js +15 -3
  13. package/dist/cli/CommandLineParser.js.map +1 -1
  14. package/dist/cli/ConfigFileParser.d.ts +2 -2
  15. package/dist/cli/ConfigFileParser.d.ts.map +1 -1
  16. package/dist/cli/ConfigFileParser.js +20 -3
  17. package/dist/cli/ConfigFileParser.js.map +1 -1
  18. package/dist/cli/helper/YouTubeConfigurator.d.ts.map +1 -1
  19. package/dist/cli/helper/YouTubeConfigurator.js +23 -20
  20. package/dist/cli/helper/YouTubeConfigurator.js.map +1 -1
  21. package/dist/cli/index.d.ts.map +1 -1
  22. package/dist/cli/index.js +27 -10
  23. package/dist/cli/index.js.map +1 -1
  24. package/dist/downloaders/Bootstrap.d.ts +2 -2
  25. package/dist/downloaders/Bootstrap.d.ts.map +1 -1
  26. package/dist/downloaders/Bootstrap.js.map +1 -1
  27. package/dist/downloaders/Downloader.d.ts +11 -10
  28. package/dist/downloaders/Downloader.d.ts.map +1 -1
  29. package/dist/downloaders/Downloader.js +117 -95
  30. package/dist/downloaders/Downloader.js.map +1 -1
  31. package/dist/downloaders/DownloaderEvent.d.ts +6 -5
  32. package/dist/downloaders/DownloaderEvent.d.ts.map +1 -1
  33. package/dist/downloaders/DownloaderEvent.js +1 -0
  34. package/dist/downloaders/DownloaderEvent.js.map +1 -1
  35. package/dist/downloaders/DownloaderOptions.d.ts +14 -3
  36. package/dist/downloaders/DownloaderOptions.d.ts.map +1 -1
  37. package/dist/downloaders/DownloaderOptions.js +24 -4
  38. package/dist/downloaders/DownloaderOptions.js.map +1 -1
  39. package/dist/downloaders/PostDownloader.d.ts +2 -2
  40. package/dist/downloaders/PostDownloader.d.ts.map +1 -1
  41. package/dist/downloaders/PostDownloader.js +389 -420
  42. package/dist/downloaders/PostDownloader.js.map +1 -1
  43. package/dist/downloaders/PostsFetcher.d.ts +58 -0
  44. package/dist/downloaders/PostsFetcher.d.ts.map +1 -0
  45. package/dist/downloaders/PostsFetcher.js +354 -0
  46. package/dist/downloaders/PostsFetcher.js.map +1 -0
  47. package/dist/downloaders/ProductDownloader.d.ts +2 -2
  48. package/dist/downloaders/ProductDownloader.d.ts.map +1 -1
  49. package/dist/downloaders/ProductDownloader.js +140 -134
  50. package/dist/downloaders/ProductDownloader.js.map +1 -1
  51. package/dist/downloaders/cache/StatusCache.d.ts +11 -9
  52. package/dist/downloaders/cache/StatusCache.d.ts.map +1 -1
  53. package/dist/downloaders/cache/StatusCache.js +13 -8
  54. package/dist/downloaders/cache/StatusCache.js.map +1 -1
  55. package/dist/downloaders/task/DownloadTask.d.ts +16 -5
  56. package/dist/downloaders/task/DownloadTask.d.ts.map +1 -1
  57. package/dist/downloaders/task/DownloadTask.js +48 -30
  58. package/dist/downloaders/task/DownloadTask.js.map +1 -1
  59. package/dist/downloaders/task/DownloadTaskBatch.d.ts +4 -4
  60. package/dist/downloaders/task/DownloadTaskBatch.d.ts.map +1 -1
  61. package/dist/downloaders/task/DownloadTaskBatch.js +24 -19
  62. package/dist/downloaders/task/DownloadTaskBatch.js.map +1 -1
  63. package/dist/downloaders/task/DownloadTaskBatchEvent.d.ts +1 -1
  64. package/dist/downloaders/task/DownloadTaskBatchEvent.d.ts.map +1 -1
  65. package/dist/downloaders/task/DownloadTaskBatchEvent.js.map +1 -1
  66. package/dist/downloaders/task/DownloadTaskFactory.d.ts +8 -9
  67. package/dist/downloaders/task/DownloadTaskFactory.d.ts.map +1 -1
  68. package/dist/downloaders/task/DownloadTaskFactory.js +24 -16
  69. package/dist/downloaders/task/DownloadTaskFactory.js.map +1 -1
  70. package/dist/downloaders/task/ExternalDownloaderTask.d.ts +6 -5
  71. package/dist/downloaders/task/ExternalDownloaderTask.d.ts.map +1 -1
  72. package/dist/downloaders/task/ExternalDownloaderTask.js +14 -5
  73. package/dist/downloaders/task/ExternalDownloaderTask.js.map +1 -1
  74. package/dist/downloaders/task/FFmpegDownloadTaskBase.d.ts +3 -3
  75. package/dist/downloaders/task/FFmpegDownloadTaskBase.d.ts.map +1 -1
  76. package/dist/downloaders/task/FFmpegDownloadTaskBase.js +109 -95
  77. package/dist/downloaders/task/FFmpegDownloadTaskBase.js.map +1 -1
  78. package/dist/downloaders/task/FetcherDownloadTask.d.ts +5 -5
  79. package/dist/downloaders/task/FetcherDownloadTask.d.ts.map +1 -1
  80. package/dist/downloaders/task/FetcherDownloadTask.js +156 -104
  81. package/dist/downloaders/task/FetcherDownloadTask.js.map +1 -1
  82. package/dist/downloaders/task/M3U8DownloadTask.d.ts +2 -2
  83. package/dist/downloaders/task/M3U8DownloadTask.d.ts.map +1 -1
  84. package/dist/downloaders/task/M3U8DownloadTask.js +4 -3
  85. package/dist/downloaders/task/M3U8DownloadTask.js.map +1 -1
  86. package/dist/downloaders/task/YouTubeDownloadTask.d.ts +2 -2
  87. package/dist/downloaders/task/YouTubeDownloadTask.d.ts.map +1 -1
  88. package/dist/downloaders/task/YouTubeDownloadTask.js +3 -1
  89. package/dist/downloaders/task/YouTubeDownloadTask.js.map +1 -1
  90. package/dist/downloaders/templates/CampaignInfo.d.ts +1 -1
  91. package/dist/downloaders/templates/CampaignInfo.d.ts.map +1 -1
  92. package/dist/downloaders/templates/CampaignInfo.js.map +1 -1
  93. package/dist/downloaders/templates/PostInfo.d.ts +1 -1
  94. package/dist/downloaders/templates/PostInfo.d.ts.map +1 -1
  95. package/dist/downloaders/templates/PostInfo.js.map +1 -1
  96. package/dist/downloaders/templates/ProductInfo.d.ts +1 -1
  97. package/dist/downloaders/templates/ProductInfo.d.ts.map +1 -1
  98. package/dist/downloaders/templates/ProductInfo.js.map +1 -1
  99. package/dist/entities/Campaign.d.ts +3 -3
  100. package/dist/entities/Campaign.d.ts.map +1 -1
  101. package/dist/entities/Campaign.js.map +1 -1
  102. package/dist/entities/Downloadable.d.ts +3 -3
  103. package/dist/entities/Downloadable.d.ts.map +1 -1
  104. package/dist/entities/Downloadable.js.map +1 -1
  105. package/dist/entities/Post.d.ts +4 -4
  106. package/dist/entities/Post.d.ts.map +1 -1
  107. package/dist/entities/Post.js.map +1 -1
  108. package/dist/entities/Product.d.ts +2 -2
  109. package/dist/entities/Product.d.ts.map +1 -1
  110. package/dist/entities/Product.js.map +1 -1
  111. package/dist/entities/Reward.d.ts +1 -1
  112. package/dist/entities/Reward.d.ts.map +1 -1
  113. package/dist/entities/Reward.js.map +1 -1
  114. package/dist/entities/User.d.ts +1 -1
  115. package/dist/entities/User.d.ts.map +1 -1
  116. package/dist/entities/User.js.map +1 -1
  117. package/dist/parsers/PageParser.js.map +1 -1
  118. package/dist/parsers/Parser.d.ts +8 -7
  119. package/dist/parsers/Parser.d.ts.map +1 -1
  120. package/dist/parsers/Parser.js +6 -4
  121. package/dist/parsers/Parser.js.map +1 -1
  122. package/dist/parsers/PostParser.d.ts +2 -1
  123. package/dist/parsers/PostParser.d.ts.map +1 -1
  124. package/dist/parsers/PostParser.js +15 -12
  125. package/dist/parsers/PostParser.js.map +1 -1
  126. package/dist/parsers/ProductParser.d.ts +1 -1
  127. package/dist/parsers/ProductParser.d.ts.map +1 -1
  128. package/dist/parsers/ProductParser.js.map +1 -1
  129. package/dist/utils/AttachmentFilenameResolver.d.ts +1 -2
  130. package/dist/utils/AttachmentFilenameResolver.d.ts.map +1 -1
  131. package/dist/utils/AttachmentFilenameResolver.js +2 -1
  132. package/dist/utils/AttachmentFilenameResolver.js.map +1 -1
  133. package/dist/utils/DateTime.d.ts +24 -0
  134. package/dist/utils/DateTime.d.ts.map +1 -0
  135. package/dist/utils/DateTime.js +106 -0
  136. package/dist/utils/DateTime.js.map +1 -0
  137. package/dist/utils/FSHelper.d.ts +29 -12
  138. package/dist/utils/FSHelper.d.ts.map +1 -1
  139. package/dist/utils/FSHelper.js +99 -30
  140. package/dist/utils/FSHelper.js.map +1 -1
  141. package/dist/utils/Fetcher.d.ts +6 -4
  142. package/dist/utils/Fetcher.d.ts.map +1 -1
  143. package/dist/utils/Fetcher.js +35 -19
  144. package/dist/utils/Fetcher.js.map +1 -1
  145. package/dist/utils/FetcherProgressMonitor.d.ts +10 -4
  146. package/dist/utils/FetcherProgressMonitor.d.ts.map +1 -1
  147. package/dist/utils/FetcherProgressMonitor.js +16 -13
  148. package/dist/utils/FetcherProgressMonitor.js.map +1 -1
  149. package/dist/utils/FilenameFormatHelper.d.ts +6 -6
  150. package/dist/utils/FilenameFormatHelper.d.ts.map +1 -1
  151. package/dist/utils/FilenameFormatHelper.js +2 -1
  152. package/dist/utils/FilenameFormatHelper.js.map +1 -1
  153. package/dist/utils/FllenameResolver.d.ts +0 -1
  154. package/dist/utils/FllenameResolver.d.ts.map +1 -1
  155. package/dist/utils/FllenameResolver.js.map +1 -1
  156. package/dist/utils/Formatter.js +2 -1
  157. package/dist/utils/Formatter.js.map +1 -1
  158. package/dist/utils/InnertubeLoader.d.ts +2 -2
  159. package/dist/utils/InnertubeLoader.d.ts.map +1 -1
  160. package/dist/utils/InnertubeLoader.js +61 -4
  161. package/dist/utils/InnertubeLoader.js.map +1 -1
  162. package/dist/utils/MediaFilenameResolver.d.ts +1 -2
  163. package/dist/utils/MediaFilenameResolver.d.ts.map +1 -1
  164. package/dist/utils/MediaFilenameResolver.js +2 -1
  165. package/dist/utils/MediaFilenameResolver.js.map +1 -1
  166. package/dist/utils/Misc.d.ts +8 -6
  167. package/dist/utils/Misc.d.ts.map +1 -1
  168. package/dist/utils/Misc.js.map +1 -1
  169. package/dist/utils/ObjectHelper.d.ts +5 -1
  170. package/dist/utils/ObjectHelper.d.ts.map +1 -1
  171. package/dist/utils/ObjectHelper.js +17 -3
  172. package/dist/utils/ObjectHelper.js.map +1 -1
  173. package/dist/utils/PackageInfo.js.map +1 -1
  174. package/dist/utils/Progress.d.ts +19 -0
  175. package/dist/utils/Progress.d.ts.map +1 -0
  176. package/dist/utils/Progress.js +112 -0
  177. package/dist/utils/Progress.js.map +1 -0
  178. package/dist/utils/Sleeper.d.ts +9 -0
  179. package/dist/utils/Sleeper.d.ts.map +1 -0
  180. package/dist/utils/Sleeper.js +68 -0
  181. package/dist/utils/Sleeper.js.map +1 -0
  182. package/dist/utils/URLHelper.d.ts +2 -2
  183. package/dist/utils/URLHelper.d.ts.map +1 -1
  184. package/dist/utils/URLHelper.js +9 -0
  185. package/dist/utils/URLHelper.js.map +1 -1
  186. package/dist/utils/YouTubeCredentialsCapturer.d.ts +0 -1
  187. package/dist/utils/YouTubeCredentialsCapturer.d.ts.map +1 -1
  188. package/dist/utils/YouTubeCredentialsCapturer.js +3 -2
  189. package/dist/utils/YouTubeCredentialsCapturer.js.map +1 -1
  190. package/dist/utils/index.d.ts +3 -1
  191. package/dist/utils/index.d.ts.map +1 -1
  192. package/dist/utils/index.js +2 -0
  193. package/dist/utils/index.js.map +1 -1
  194. package/dist/utils/logging/ChainLogger.d.ts +1 -1
  195. package/dist/utils/logging/ChainLogger.d.ts.map +1 -1
  196. package/dist/utils/logging/ChainLogger.js +2 -1
  197. package/dist/utils/logging/ChainLogger.js.map +1 -1
  198. package/dist/utils/logging/ConsoleLogger.d.ts +3 -2
  199. package/dist/utils/logging/ConsoleLogger.d.ts.map +1 -1
  200. package/dist/utils/logging/ConsoleLogger.js +23 -10
  201. package/dist/utils/logging/ConsoleLogger.js.map +1 -1
  202. package/dist/utils/logging/FileLogger.d.ts +3 -3
  203. package/dist/utils/logging/FileLogger.d.ts.map +1 -1
  204. package/dist/utils/logging/FileLogger.js +2 -1
  205. package/dist/utils/logging/FileLogger.js.map +1 -1
  206. package/dist/utils/logging/Logger.js.map +1 -1
  207. package/package.json +20 -14
package/README.md CHANGED
@@ -19,7 +19,7 @@ A Patreon downloader written in [Node.js](https://nodejs.org).
19
19
  - Save campaign and content info
20
20
  - Extensively configurable
21
21
 
22
- You can run `patreon-dl` from the command-line or use it as a library for your project. Node.js v16.16.0 or higher required.
22
+ You can run `patreon-dl` from the command-line or use it as a library for your project. Node.js v18 or higher required.
23
23
 
24
24
  ### Limitations
25
25
 
@@ -80,6 +80,7 @@ $ patreon-dl [OPTION]... URL
80
80
  | `--out-dir <path>` |`-o` | Directory to save content |
81
81
  | `--log-level <level>` | `-l` | Log level of the console logger: `info`, `debug`, `warn` or `error`; set to `none` to disable the logger. |
82
82
  | `--no-prompt` | `-y` | Do not prompt for confirmation to proceed |
83
+ | `--dry-run` | | Run without writing files to disk (except logs, if any). Intended for testing / debugging. |
83
84
  | <code><nobr>--list-tiers &lt;creator&gt;</nobr></code> | | <p>List tiers for the given creator(s). Separate multiple creators with a comma.</p>The purpose of this is to let you find out what tier IDs to set for `posts.in.tier` filtering option under `include` section of [configuration file](#configuration-file). |
84
85
  | <code><nobr>--list-tiers-uid &lt;user ID&gt;</nobr></code> | | Same as `--list-tiers`, but takes user ID instead of vanity. |
85
86
  | `--configure-youtube` | | <p>Configure YouTube connection.</p>`patreon-dl` supports downloading embedded YouTube videos. If you have a YouTube Premium account, you can connect `patreon-dl` to it for downloading Premium-quality streams. |
@@ -97,6 +98,7 @@ https://www.patreon.com/<creator>/posts
97
98
  https://www.patreon.com/user/posts?u=<user_id>
98
99
 
99
100
  // Dowload a single post
101
+ https://www.patreon.com/posts/<post_id>
100
102
  https://www.patreon.com/posts/<slug>-<post_id>
101
103
 
102
104
  // Download posts in a collection
@@ -162,11 +164,16 @@ include.posts.in.tier = 123456, 789100
162
164
  #
163
165
  # include.locked.content
164
166
  # include.posts.with.media.type
167
+ # include.posts.published.after
168
+ # include.posts.published.before
165
169
  # include.campaign.info
166
170
  # include.content.info
167
171
  # include.preview.media
168
172
  # include.content.media
169
173
  # include.all.media.variants
174
+ # include.images.by.filename
175
+ # include.audio.by.filename
176
+ # include.attachments.by.filename
170
177
 
171
178
  # URL 2
172
179
  https://www.patreon.com/janedoe/posts
@@ -244,11 +251,12 @@ An object with the following properties (all *optional*):
244
251
  | `outDir` | Path to directory where content is saved. Default: current working directory |
245
252
  | `dirNameFormat` | How to name directories: (object)<ul><li>`campaign`: see [Campaign directory name format](#campaign-directory-name-format)</li><li>`content`: see [Content directory name format](#content-directory-name-format)</li></ul> |
246
253
  | `filenameFormat` | Naming of files: (object)<ul><li>`media`: see [Media filename format](#media-filename-format) |
247
- | `include` | What to include in the download: (object) <ul><li>`lockedContent`: whether to process locked content. Default: `true`</li><li>`postInTier`: see [Filtering posts by tier](#filtering-posts-by-tier)</li><li>`postsWithMediaType`: sets the media type criteria for downloading posts. Values can be:<ul><li>`any`: download posts regardless of the type of media they contain. Also applies to posts that do not contain any media.</li><li>`none`: only download posts that do not contain media.</li><li>Array<`image` \| `video` \| `audio` \| `attachment`>: only download posts that contain the specified media type(s).</li></ul>Default: `any`</li><li>`campaignInfo`: whether to save campaign info. Default: `true`</li><li>`contentInfo`: whether to save content info. Default: `true`</li><li>`contentMedia`: the type of content media to download (images, videos, audio, attachments, excluding previews). Values can be:<ul><li>`true`: download all content media.</li><li>`false`: do not download content media.</li><li>Array<`image` \| `video` \| `audio` \| `attachment` \| `file`>: only download the specified media type(s).</li></ul>Default: `true`</li><li>`previewMedia`: the type of preview media to download, if available. Values can be:<ul><li>`true`: download all preview media.</li><li>`false`: do not download preview media.</li><li>Array<`image` \| `video` \| `audio`>: only download the specified media type(s).</li></ul>Default: `true`</li><li>`allMediaVariants`: whether to download all media variants, if available. If `false`, only the best quality variant will be downloaded. Default: `false`</li></ul> |
254
+ | `include` | What to include in the download: (object) <ul><li>`lockedContent`: whether to process locked content. Default: `true`</li><li>`postInTier`: see [Filtering posts by tier](#filtering-posts-by-tier)</li><li>`postsWithMediaType`: sets the media type criteria for downloading posts. Values can be:<ul><li>`any`: download posts regardless of the type of media they contain. Also applies to posts that do not contain any media.</li><li>`none`: only download posts that do not contain media.</li><li>Array<`image` \| `video` \| `audio` \| `attachment`>: only download posts that contain the specified media type(s).</li></ul>Default: `any`</li><li>`postsPublished`: sets the publish date range for posts. Its value is an object with two properties: `after` and `before` (both a [DateTime](./src/utils/DateTime.ts) object). You can specify one or both to indicate an open-ended or closed date range.</li><li>`campaignInfo`: whether to save campaign info. Default: `true`</li><li>`contentInfo`: whether to save content info. Default: `true`</li><li>`contentMedia`: the type of content media to download (images, videos, audio, attachments, excluding previews). Values can be:<ul><li>`true`: download all content media.</li><li>`false`: do not download content media.</li><li>Array<`image` \| `video` \| `audio` \| `attachment` \| `file`>: only download the specified media type(s).</li></ul>Default: `true`</li><li>`previewMedia`: the type of preview media to download, if available. Values can be:<ul><li>`true`: download all preview media.</li><li>`false`: do not download preview media.</li><li>Array<`image` \| `video` \| `audio`>: only download the specified media type(s).</li></ul>Default: `true`</li><li>`allMediaVariants`: whether to download all media variants, if available. If `false`, only the best quality variant will be downloaded. Default: `false`</li><li>`mediaByFilename`: sets the filename pattern to match against media files. Those that do not match the provided pattern will not be downloaded. Its value is an object with three properties corresponding to the media types supported: `images`, `audio` and `attachments`. For example, to download only ZIP attachments, you would set the option like this:<p>```mediaByFilename: { attachments: '*.zip' }```</p>Internally, pattern matching is done by [minimatch](https://github.com/isaacs/minimatch), which supports glob patterns.</li></ul> |
248
255
  | `request` | Rate limiting and retry on error: (object)<ul><li>`maxRetries`: maximum number of retries if a request or download fails. Default: 3</li><li>`maxConcurrent`: maximum number of concurrent downloads. Default: 10</li><li>`minTime`: minimum time to wait between starting requests or downloads (milliseconds). Default: 333</li></ul> |
249
256
  | `fileExistsAction` | What to do when a target file already exists: (object)<ul><li>`info`: in the context of saving info (such as campaign or post info), the action to take when a file belonging to the info already exists. Default: `saveAsCopyIfNewer`</li><li>`infoAPI`: API data is saved as part of info. Because it changes frequently, and usually used for debugging purpose only, you can set a different action when saving an API data file that already exists. Default: `overwrite`</li><li>`content`: in the context of downloading content, the action to take when a file belonging to the content already exists. Default: `skip`</li></ul><p>Supported actions:<ul><li>`overwrite`: overwrite existing file.</li><li>`skip`: skip saving the file.</li><li>`saveAsCopy`: save the file under incremented filename (e.g. "abc.jpg" becomes "abc (1).jpg").</li><li>`saveAsCopyIfNewer`: like `saveAsCopy`, but only do so if the contents have actually changed.</li></ul></p> |
250
257
  | `embedDownloaders` | External downloader for embedded videos. See [External downloaders](#external-downloaders).|
251
258
  |`logger` | See [Logger](#logger) |
259
+ | `dryRun` | Run without writing files to disk (except logs, if any). Default: `false` |
252
260
 
253
261
  #### Campaign directory name format
254
262
 
@@ -631,7 +639,7 @@ Each event emitted by a download task batch has a payload, which is an object wi
631
639
  | Event | Description |
632
640
  |---------------|---------------------------------------|
633
641
  | `taskStart` | <p>Emitted when a download starts.</p><p>Payload properties:<ul><li>`task`: the download task</li></ul></p> |
634
- | `taskProgress`| <p>Emitted when a download progress is updated.</p><p>Payload properties:<ul><li>`task`: the download task</li><li>`progress`: (object)<ul><li>`destFilename`: the destination filename of the download</li><li>`destFilePath`: the destination file path of the download</li><li>`lengthUnit`: the unit measuring the progress. Generally, it would be 'byte', but for videos the unit would be 'second'.</li><li>`length`: length downloaded, measured in `lengthUnit`.</li><li>`percent`: percent downloaded</li><li>`sizeDownloaded`: size of file downloaded (kb)</li><li>`speed`: download speed (kb/s)</li></ul></li></ul></p> |
642
+ | `taskProgress`| <p>Emitted when a download progress is updated.</p><p>Payload properties:<ul><li>`task`: the download task</li><li>`progress`: (object)<ul><li>`destFilename`: the destination filename of the download</li><li>`destFilePath`: the destination file path of the download</li><li>`lengthUnit`: the unit measuring the progress. Generally, it would be 'byte', but for videos the unit would be 'second'.</li><li>`length`: content length, measured in `lengthUnit`.</li><li>`lengthDownloaded`: length downloaded so far, measured in `lengthUnit`.</li><li>`percent`: percent downloaded</li><li>`sizeDownloaded`: size of file downloaded (kB)</li><li>`speed`: download speed (kB/s)</li></ul> <p>Note: sometimes `length` is `undefined`, in which case `percent` will also be `undefined`.</p></li></ul></p> |
635
643
  | `taskComplete` | <p>Emitted when a download is complete.</p><p>Payload properties:<ul><li>`task`: the download task</li></ul></p> |
636
644
  | `taskError` | <p>Emitted when a download error occurs.</p><p>Payload properties:<ul><li>`error`: (object)<ul><li>`task`: the download task</li><li>`cause`: `Error` object or `undefined`</li></ul></li><li>`willRetry`: whether the download will be reattempted</li></ul></p> |
637
645
  | `taskAbort` | <p>Emitted when a download is aborted.</p><p>Payload properties:<ul><li>`task`: the download task</li></ul></p> |
@@ -641,6 +649,21 @@ Each event emitted by a download task batch has a payload, which is an object wi
641
649
 
642
650
  ## Changelog
643
651
 
652
+ v2.0.0
653
+ - Replace [node-fetch](https://github.com/node-fetch/node-fetch) with Fetch API; required Node.js version bumped to v18 or higher.
654
+ - Update dependencies and libraries
655
+ - New `include` options:
656
+ - `include.postsPublished` ([#29](https://github.com/patrickkfkan/patreon-dl/issues/29))
657
+ - `include.mediaByFilename` ([#33](https://github.com/patrickkfkan/patreon-dl/issues/33))
658
+ - Bug fixes:
659
+ - 403 error when downloading YouTube embeds
660
+ - Only first of multiple targets downloaded ([#26](https://github.com/patrickkfkan/patreon-dl/issues/26))
661
+
662
+ v1.7.0
663
+ - Download next batch of posts before expiry of 'next' URL (fixes [#22](https://github.com/patrickkfkan/patreon-dl/issues/22))
664
+ - Add `--dry-run` / `dryRun` option
665
+ - Support URL format `https://www.patreon.com/posts/<post_id>`
666
+
644
667
  v1.6.2
645
668
  - Fix 'campaign ID not found' error due to Patreon changes
646
669
 
@@ -1,4 +1,5 @@
1
- import { CLIOptionParserEntry } from './CLIOptions.js';
1
+ import DateTime from '../utils/DateTime.js';
2
+ import { type CLIOptionParserEntry } from './CLIOptions.js';
2
3
  export default class CLIOptionValidator {
3
4
  #private;
4
5
  static validateRequired(entry?: CLIOptionParserEntry, errMsg?: string): string;
@@ -8,9 +9,10 @@ export default class CLIOptionValidator {
8
9
  static validateStringArray<T>(entry: CLIOptionParserEntry | undefined, match?: readonly T[], delimiter?: string): T[] | undefined;
9
10
  static validateTargetURLs(value: string | string[], delimiter?: string): string[];
10
11
  static validateTargetURL(s: string): string;
11
- static validateIncludeContentWithMediaType(entry?: CLIOptionParserEntry): "none" | "any" | ("attachment" | "audio" | "video" | "image")[] | undefined;
12
+ static validateIncludeContentWithMediaType(entry?: CLIOptionParserEntry): "none" | ("attachment" | "audio" | "video" | "image")[] | "any" | undefined;
12
13
  static validateIncludeContentInTier(entry?: CLIOptionParserEntry): string[] | "any" | undefined;
13
14
  static validateIncludePreviewMedia(entry?: CLIOptionParserEntry): boolean | ("audio" | "video" | "image")[] | undefined;
14
15
  static validateIncludeContentMedia(entry?: CLIOptionParserEntry): boolean | ("attachment" | "file" | "audio" | "video" | "image")[] | undefined;
16
+ static validateDateTime(entry?: CLIOptionParserEntry): DateTime | undefined;
15
17
  }
16
18
  //# sourceMappingURL=CLIOptionValidator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CLIOptionValidator.d.ts","sourceRoot":"","sources":["../../src/cli/CLIOptionValidator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAQvD,MAAM,CAAC,OAAO,OAAO,kBAAkB;;IAErC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,oBAAoB,EAAE,MAAM,CAAC,EAAE,MAAM;IAarE,MAAM,CAAC,cAAc,CAAC,CAAC,SAAS,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,oBAAoB,EAAE,GAAG,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,SAAS;IAW3G,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,oBAAoB;IA0BnD,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,oBAAoB,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM;IAoB9E,MAAM,CAAC,mBAAmB,CAAC,CAAC,EAAE,KAAK,EAAE,oBAAoB,GAAG,SAAS,EAAE,KAAK,CAAC,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,SAAM;IAyB5G,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,SAAS,SAAM,GAAG,MAAM,EAAE;IAQ9E,MAAM,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAM;IAoBlC,MAAM,CAAC,mCAAmC,CAAC,KAAK,CAAC,EAAE,oBAAoB;IASvE,MAAM,CAAC,4BAA4B,CAAC,KAAK,CAAC,EAAE,oBAAoB;IAShE,MAAM,CAAC,2BAA2B,CAAC,KAAK,CAAC,EAAE,oBAAoB;IAS/D,MAAM,CAAC,2BAA2B,CAAC,KAAK,CAAC,EAAE,oBAAoB;CAoBhE"}
1
+ {"version":3,"file":"CLIOptionValidator.d.ts","sourceRoot":"","sources":["../../src/cli/CLIOptionValidator.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,sBAAsB,CAAC;AAE5C,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAQ5D,MAAM,CAAC,OAAO,OAAO,kBAAkB;;IAErC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,oBAAoB,EAAE,MAAM,CAAC,EAAE,MAAM;IAarE,MAAM,CAAC,cAAc,CAAC,CAAC,SAAS,MAAM,EAAE,EAAE,KAAK,CAAC,EAAE,oBAAoB,EAAE,GAAG,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,SAAS;IAW3G,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,oBAAoB;IA0BnD,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,oBAAoB,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM;IAoB9E,MAAM,CAAC,mBAAmB,CAAC,CAAC,EAAE,KAAK,EAAE,oBAAoB,GAAG,SAAS,EAAE,KAAK,CAAC,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,SAAM;IAyB5G,MAAM,CAAC,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,SAAS,SAAM,GAAG,MAAM,EAAE;IAQ9E,MAAM,CAAC,iBAAiB,CAAC,CAAC,EAAE,MAAM;IAoBlC,MAAM,CAAC,mCAAmC,CAAC,KAAK,CAAC,EAAE,oBAAoB;IASvE,MAAM,CAAC,4BAA4B,CAAC,KAAK,CAAC,EAAE,oBAAoB;IAShE,MAAM,CAAC,2BAA2B,CAAC,KAAK,CAAC,EAAE,oBAAoB;IAS/D,MAAM,CAAC,2BAA2B,CAAC,KAAK,CAAC,EAAE,oBAAoB;IAS/D,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,oBAAoB;CAwBrD"}
@@ -4,13 +4,14 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
4
4
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
5
  };
6
6
  var _a, _CLIOptionValidator_logEntryKey;
7
+ import DateTime from '../utils/DateTime.js';
7
8
  import URLHelper from '../utils/URLHelper.js';
8
9
  const CLI_OPTION_SRC_NAME = {
9
10
  cli: 'Command-line',
10
11
  cfg: 'Config file',
11
12
  tgt: 'Targets file'
12
13
  };
13
- export default class CLIOptionValidator {
14
+ class CLIOptionValidator {
14
15
  static validateRequired(entry, errMsg) {
15
16
  if (entry && entry.value) {
16
17
  return entry.value;
@@ -159,6 +160,18 @@ export default class CLIOptionValidator {
159
160
  return this.validateStringArray(entry, ['image', 'video', 'audio', 'attachment', 'file']);
160
161
  }
161
162
  }
163
+ static validateDateTime(entry) {
164
+ if (!entry || !entry.value) {
165
+ return undefined;
166
+ }
167
+ const v = entry.value.trim();
168
+ try {
169
+ return DateTime.from(v);
170
+ }
171
+ catch (error) {
172
+ throw Error(`${__classPrivateFieldGet(this, _a, "m", _CLIOptionValidator_logEntryKey).call(this, entry)} has invalid datetime string "${v}"; must be in this format: ${DateTime.FORMAT}`);
173
+ }
174
+ }
162
175
  }
163
176
  _a = CLIOptionValidator, _CLIOptionValidator_logEntryKey = function _CLIOptionValidator_logEntryKey(entry) {
164
177
  const src = CLI_OPTION_SRC_NAME[entry.src];
@@ -171,4 +184,5 @@ _a = CLIOptionValidator, _CLIOptionValidator_logEntryKey = function _CLIOptionVa
171
184
  return `Value given in ${src.toLowerCase()} on line ${entry.line} starting with '${entry.key}'`;
172
185
  }
173
186
  };
187
+ export default CLIOptionValidator;
174
188
  //# sourceMappingURL=CLIOptionValidator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CLIOptionValidator.js","sourceRoot":"","sources":["../../src/cli/CLIOptionValidator.ts"],"names":[],"mappings":"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","sourcesContent":["import URLHelper from '../utils/URLHelper.js';\nimport { CLIOptionParserEntry } from './CLIOptions.js';\n\nconst CLI_OPTION_SRC_NAME = {\n cli: 'Command-line',\n cfg: 'Config file',\n tgt: 'Targets file'\n};\n\nexport default class CLIOptionValidator {\n\n static validateRequired(entry?: CLIOptionParserEntry, errMsg?: string) {\n if (entry && entry.value) {\n return entry.value;\n }\n if (errMsg) {\n throw Error(errMsg);\n }\n if (entry) {\n throw Error(`${this.#logEntryKey(entry)} requires a value`);\n }\n throw Error('A required option missing');\n }\n\n static validateString<T extends string[]>(entry?: CLIOptionParserEntry, ...match: T): T[number] | undefined {\n if (!entry) {\n return undefined;\n }\n const value = entry.value || undefined;\n if (match.length > 0 && value && !match.includes(value)) {\n throw Error(`${this.#logEntryKey(entry)} must be one of ${match.map((m) => `'${m}'`).join(', ')}`);\n }\n return value;\n }\n\n static validateBoolean(entry?: CLIOptionParserEntry) {\n if (!entry) {\n return undefined;\n }\n const value = entry.value || undefined;\n const trueValues = [ 'yes', '1', 'true' ];\n const falseValues = [ 'no', '0', 'false' ];\n let sanitized: boolean | undefined;\n if (value) {\n if (trueValues.includes(value.toLowerCase())) {\n sanitized = true;\n }\n else if (falseValues.includes(value.toLowerCase())) {\n sanitized = false;\n }\n else {\n const allowedValues = [ ...trueValues, ...falseValues ];\n throw Error(`${this.#logEntryKey(entry)} must be one of ${allowedValues.map((m) => `'${m}'`).join(', ')}; currently '${value}'`);\n }\n }\n else {\n sanitized = undefined;\n }\n return sanitized;\n }\n\n static validateNumber(entry?: CLIOptionParserEntry, min?: number, max?: number) {\n if (!entry) {\n return undefined;\n }\n const value = entry.value || undefined;\n const sanitized = value ? parseInt(value, 10) : undefined;\n if (sanitized !== undefined) {\n if (isNaN(sanitized)) {\n throw Error(`${this.#logEntryKey(entry)} is not a valid number`);\n }\n else if (min !== undefined && sanitized < min) {\n throw Error(`${this.#logEntryKey(entry)} must not be less than ${min}`);\n }\n else if (max !== undefined && sanitized > max) {\n throw Error(`${this.#logEntryKey(entry)} must not be greater than ${max}`);\n }\n }\n return sanitized;\n }\n\n static validateStringArray<T>(entry: CLIOptionParserEntry | undefined, match?: readonly T[], delimiter = ',') {\n const value = entry?.value || undefined;\n if (!entry || !value) {\n return undefined;\n }\n const split = value.split(delimiter).reduce<string[]>((result, v) => {\n v = v.trim().toLowerCase();\n if (v && !result.includes(v)) {\n result.push(v);\n }\n return result;\n }, []);\n if (split.length === 0) {\n return undefined;\n }\n if (match && match.length > 0) {\n for (const v of split) {\n if (!match.includes(v as any)) {\n throw Error(`${this.#logEntryKey(entry)} has invalid delimited value '${v}'; must be one of ${match.map((m) => `'${m}'`).join(', ')}.`);\n }\n }\n }\n return split as T[];\n }\n\n static validateTargetURLs(value: string | string[], delimiter = ','): string[] {\n if (!Array.isArray(value)) {\n const splitted = value.split(delimiter);\n return this.validateTargetURLs(splitted);\n }\n return value.map((v) => this.validateTargetURL(v));\n }\n\n static validateTargetURL(s: string) {\n const _s = s.trim();\n try {\n const type = URLHelper.analyzeURL(_s);\n if (!type) {\n throw Error('Unknown URL');\n }\n }\n catch (error) {\n if (error instanceof Error) {\n error.message += `: ${_s}`;\n throw error;\n }\n else {\n throw Error(`${error}: ${_s}`);\n }\n }\n return _s;\n }\n\n static validateIncludeContentWithMediaType(entry?: CLIOptionParserEntry) {\n try {\n return this.validateString(entry, 'any', 'none');\n }\n catch (error) {\n return this.validateStringArray(entry, [ 'image', 'video', 'audio', 'attachment' ] as const);\n }\n }\n\n static validateIncludeContentInTier(entry?: CLIOptionParserEntry) {\n try {\n return this.validateString(entry, 'any');\n }\n catch (error) {\n return this.validateStringArray<string>(entry);\n }\n }\n\n static validateIncludePreviewMedia(entry?: CLIOptionParserEntry) {\n try {\n return this.validateBoolean(entry);\n }\n catch (error) {\n return this.validateStringArray(entry, [ 'image', 'video', 'audio' ] as const);\n }\n }\n\n static validateIncludeContentMedia(entry?: CLIOptionParserEntry) {\n try {\n return this.validateBoolean(entry);\n }\n catch (error) {\n return this.validateStringArray(entry, [ 'image', 'video', 'audio', 'attachment', 'file' ] as const);\n }\n }\n\n static #logEntryKey(entry: CLIOptionParserEntry) {\n const src = CLI_OPTION_SRC_NAME[entry.src];\n switch (entry.src) {\n case 'cli':\n return `${src} option '${entry.key}'`;\n case 'cfg':\n return `${src} option '[${entry.section}]->${entry.key}'`;\n case 'tgt':\n return `Value given in ${src.toLowerCase()} on line ${entry.line} starting with '${entry.key}'`;\n }\n }\n}\n"]}
1
+ {"version":3,"file":"CLIOptionValidator.js","sourceRoot":"","sources":["../../src/cli/CLIOptionValidator.ts"],"names":[],"mappings":"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","sourcesContent":["import DateTime from '../utils/DateTime.js';\nimport URLHelper from '../utils/URLHelper.js';\nimport { type CLIOptionParserEntry } from './CLIOptions.js';\n\nconst CLI_OPTION_SRC_NAME = {\n cli: 'Command-line',\n cfg: 'Config file',\n tgt: 'Targets file'\n};\n\nexport default class CLIOptionValidator {\n\n static validateRequired(entry?: CLIOptionParserEntry, errMsg?: string) {\n if (entry && entry.value) {\n return entry.value;\n }\n if (errMsg) {\n throw Error(errMsg);\n }\n if (entry) {\n throw Error(`${this.#logEntryKey(entry)} requires a value`);\n }\n throw Error('A required option missing');\n }\n\n static validateString<T extends string[]>(entry?: CLIOptionParserEntry, ...match: T): T[number] | undefined {\n if (!entry) {\n return undefined;\n }\n const value = entry.value || undefined;\n if (match.length > 0 && value && !match.includes(value)) {\n throw Error(`${this.#logEntryKey(entry)} must be one of ${match.map((m) => `'${m}'`).join(', ')}`);\n }\n return value;\n }\n\n static validateBoolean(entry?: CLIOptionParserEntry) {\n if (!entry) {\n return undefined;\n }\n const value = entry.value || undefined;\n const trueValues = [ 'yes', '1', 'true' ];\n const falseValues = [ 'no', '0', 'false' ];\n let sanitized: boolean | undefined;\n if (value) {\n if (trueValues.includes(value.toLowerCase())) {\n sanitized = true;\n }\n else if (falseValues.includes(value.toLowerCase())) {\n sanitized = false;\n }\n else {\n const allowedValues = [ ...trueValues, ...falseValues ];\n throw Error(`${this.#logEntryKey(entry)} must be one of ${allowedValues.map((m) => `'${m}'`).join(', ')}; currently '${value}'`);\n }\n }\n else {\n sanitized = undefined;\n }\n return sanitized;\n }\n\n static validateNumber(entry?: CLIOptionParserEntry, min?: number, max?: number) {\n if (!entry) {\n return undefined;\n }\n const value = entry.value || undefined;\n const sanitized = value ? parseInt(value, 10) : undefined;\n if (sanitized !== undefined) {\n if (isNaN(sanitized)) {\n throw Error(`${this.#logEntryKey(entry)} is not a valid number`);\n }\n else if (min !== undefined && sanitized < min) {\n throw Error(`${this.#logEntryKey(entry)} must not be less than ${min}`);\n }\n else if (max !== undefined && sanitized > max) {\n throw Error(`${this.#logEntryKey(entry)} must not be greater than ${max}`);\n }\n }\n return sanitized;\n }\n\n static validateStringArray<T>(entry: CLIOptionParserEntry | undefined, match?: readonly T[], delimiter = ',') {\n const value = entry?.value || undefined;\n if (!entry || !value) {\n return undefined;\n }\n const split = value.split(delimiter).reduce<string[]>((result, v) => {\n v = v.trim().toLowerCase();\n if (v && !result.includes(v)) {\n result.push(v);\n }\n return result;\n }, []);\n if (split.length === 0) {\n return undefined;\n }\n if (match && match.length > 0) {\n for (const v of split) {\n if (!match.includes(v as any)) {\n throw Error(`${this.#logEntryKey(entry)} has invalid delimited value '${v}'; must be one of ${match.map((m) => `'${m as string}'`).join(', ')}.`);\n }\n }\n }\n return split as T[];\n }\n\n static validateTargetURLs(value: string | string[], delimiter = ','): string[] {\n if (!Array.isArray(value)) {\n const splitted = value.split(delimiter);\n return this.validateTargetURLs(splitted);\n }\n return value.map((v) => this.validateTargetURL(v));\n }\n\n static validateTargetURL(s: string) {\n const _s = s.trim();\n try {\n const type = URLHelper.analyzeURL(_s);\n if (!type) {\n throw Error('Unknown URL');\n }\n }\n catch (error: any) {\n if (error instanceof Error) {\n error.message += `: ${_s}`;\n throw error;\n }\n else {\n throw Error(`${error}: ${_s}`);\n }\n }\n return _s;\n }\n\n static validateIncludeContentWithMediaType(entry?: CLIOptionParserEntry) {\n try {\n return this.validateString(entry, 'any', 'none');\n }\n catch (error) {\n return this.validateStringArray(entry, [ 'image', 'video', 'audio', 'attachment' ] as const);\n }\n }\n\n static validateIncludeContentInTier(entry?: CLIOptionParserEntry) {\n try {\n return this.validateString(entry, 'any');\n }\n catch (error) {\n return this.validateStringArray<string>(entry);\n }\n }\n\n static validateIncludePreviewMedia(entry?: CLIOptionParserEntry) {\n try {\n return this.validateBoolean(entry);\n }\n catch (error) {\n return this.validateStringArray(entry, [ 'image', 'video', 'audio' ] as const);\n }\n }\n\n static validateIncludeContentMedia(entry?: CLIOptionParserEntry) {\n try {\n return this.validateBoolean(entry);\n }\n catch (error) {\n return this.validateStringArray(entry, [ 'image', 'video', 'audio', 'attachment', 'file' ] as const);\n }\n }\n\n static validateDateTime(entry?: CLIOptionParserEntry) {\n if (!entry || !entry.value) {\n return undefined;\n }\n const v = entry.value.trim();\n try {\n return DateTime.from(v);\n }\n catch (error) {\n throw Error(`${this.#logEntryKey(entry)} has invalid datetime string \"${v}\"; must be in this format: ${DateTime.FORMAT}`);\n }\n }\n\n static #logEntryKey(entry: CLIOptionParserEntry) {\n const src = CLI_OPTION_SRC_NAME[entry.src];\n switch (entry.src) {\n case 'cli':\n return `${src} option '${entry.key}'`;\n case 'cfg':\n return `${src} option '[${entry.section}]->${entry.key}'`;\n case 'tgt':\n return `Value given in ${src.toLowerCase()} on line ${entry.line} starting with '${entry.key}'`;\n }\n }\n}\n"]}
@@ -1,7 +1,7 @@
1
- import { DownloaderIncludeOptions, DownloaderOptions } from '../downloaders/DownloaderOptions.js';
2
- import { ConsoleLoggerOptions } from '../utils/logging/ConsoleLogger.js';
3
- import { FileLoggerOptions } from '../utils/logging/FileLogger.js';
4
- import { CommandLineParseResult } from './CommandLineParser.js';
1
+ import { type DownloaderIncludeOptions, type DownloaderOptions } from '../downloaders/DownloaderOptions.js';
2
+ import { type ConsoleLoggerOptions } from '../utils/logging/ConsoleLogger.js';
3
+ import { type FileLoggerOptions } from '../utils/logging/FileLogger.js';
4
+ import { type CommandLineParseResult } from './CommandLineParser.js';
5
5
  import ConfigFileParser from './ConfigFileParser.js';
6
6
  export interface CLITargetURLEntry {
7
7
  url: string;
@@ -1 +1 @@
1
- {"version":3,"file":"CLIOptions.d.ts","sourceRoot":"","sources":["../../src/cli/CLIOptions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAElG,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAA0B,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACnF,OAAO,gBAA2C,MAAM,uBAAuB,CAAC;AAGhF,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IAEZ,OAAO,CAAC,EAAE,wBAAwB,CAAC;CACpC;AAED,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IACnE,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,oBAAoB,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;CACnC;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC;IAClC,GAAG,EAAE,KAAK,CAAA;CACX,GAAG;IACF,GAAG,EAAE,KAAK,CAAC;IACX,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG;IACF,GAAG,EAAE,KAAK,CAAC;IACX,IAAI,EAAE,MAAM,CAAA;CACb,CAAC,GAAG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAA;AAED,wBAAgB,aAAa,IAAI,UAAU,CAkD1C;AAED,wBAAgB,mBAAmB,CAAC,kBAAkB,CAAC,EAAE,sBAAsB,EAAE,iBAAiB,CAAC,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI;;;;;;;;;;;;;;EAsCvJ"}
1
+ {"version":3,"file":"CLIOptions.d.ts","sourceRoot":"","sources":["../../src/cli/CLIOptions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,wBAAwB,EAAE,KAAK,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAE5G,OAAO,EAAE,KAAK,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAExE,OAA0B,EAAE,KAAK,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACxF,OAAO,gBAAgD,MAAM,uBAAuB,CAAC;AAIrF,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IAEZ,OAAO,CAAC,EAAE,wBAAwB,CAAC;CACpC;AAED,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,iBAAiB,EAAE,QAAQ,CAAC;IACnE,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,EAAE,oBAAoB,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAC;CACnC;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC;IAClC,GAAG,EAAE,KAAK,CAAA;CACX,GAAG;IACF,GAAG,EAAE,KAAK,CAAC;IACX,OAAO,EAAE,MAAM,CAAA;CAChB,GAAG;IACF,GAAG,EAAE,KAAK,CAAC;IACX,IAAI,EAAE,MAAM,CAAA;CACb,CAAC,GAAG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAA;AAED,wBAAgB,aAAa,IAAI,UAAU,CAmD1C;AAED,wBAAgB,mBAAmB,CAAC,kBAAkB,CAAC,EAAE,sBAAsB,EAAE,iBAAiB,CAAC,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAC,GAAG,IAAI;;;;;;;;;;;;;;EAsCvJ"}
@@ -4,6 +4,7 @@ import CLIOptionValidator from './CLIOptionValidator.js';
4
4
  import CommandLineParser from './CommandLineParser.js';
5
5
  import ConfigFileParser from './ConfigFileParser.js';
6
6
  import path from 'path';
7
+ import ObjectHelper from '../utils/ObjectHelper.js';
7
8
  export function getCLIOptions() {
8
9
  const commandLineOptions = CommandLineParser.parse();
9
10
  const configFileOptions = commandLineOptions.configFile?.value ? ConfigFileParser.parse(commandLineOptions.configFile.value) : null;
@@ -45,6 +46,7 @@ export function getCLIOptions() {
45
46
  },
46
47
  embedDownloaders: getEmbedDownloaderOptions(configFileOptions),
47
48
  noPrompt: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.noPrompt, configFileOptions?.noPrompt)) || false,
49
+ dryRun: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.dryRun, configFileOptions?.dryRun)) || false,
48
50
  consoleLogger,
49
51
  fileLoggers
50
52
  };
@@ -97,11 +99,20 @@ function getCLIIncludeOptions(commandLineOptions, configFileOptions) {
97
99
  lockedContent: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.lockedContent, configFileOptions?.include?.lockedContent)),
98
100
  postsWithMediaType: CLIOptionValidator.validateIncludeContentWithMediaType(pickDefined(commandLineOptions.include?.postsWithMediaType, configFileOptions?.include?.postsWithMediaType)),
99
101
  postsInTier: CLIOptionValidator.validateIncludeContentInTier(pickDefined(commandLineOptions.include?.postsInTier, configFileOptions?.include?.postsInTier)),
102
+ postsPublished: {
103
+ after: CLIOptionValidator.validateDateTime(pickDefined(commandLineOptions.include?.postsPublished?.after, configFileOptions?.include?.postsPublished?.after)) || null,
104
+ before: CLIOptionValidator.validateDateTime(pickDefined(commandLineOptions.include?.postsPublished?.before, configFileOptions?.include?.postsPublished?.before)) || null,
105
+ },
100
106
  campaignInfo: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.campaignInfo, configFileOptions?.include?.campaignInfo)),
101
107
  contentInfo: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.contentInfo, configFileOptions?.include?.contentInfo)),
102
108
  previewMedia: CLIOptionValidator.validateIncludePreviewMedia(pickDefined(commandLineOptions.include?.previewMedia, configFileOptions?.include?.previewMedia)),
103
109
  contentMedia: CLIOptionValidator.validateIncludeContentMedia(pickDefined(commandLineOptions.include?.contentMedia, configFileOptions?.include?.contentMedia)),
104
- allMediaVariants: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.allMediaVariants, configFileOptions?.include?.allMediaVariants))
110
+ allMediaVariants: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.allMediaVariants, configFileOptions?.include?.allMediaVariants)),
111
+ mediaByFilename: {
112
+ images: CLIOptionValidator.validateString(pickDefined(commandLineOptions.include?.mediaByFilename?.images, configFileOptions?.include?.mediaByFilename?.images)) || null,
113
+ audio: CLIOptionValidator.validateString(pickDefined(commandLineOptions.include?.mediaByFilename?.audio, configFileOptions?.include?.mediaByFilename?.audio)) || null,
114
+ attachments: CLIOptionValidator.validateString(pickDefined(commandLineOptions.include?.mediaByFilename?.attachments, configFileOptions?.include?.mediaByFilename?.attachments)) || null
115
+ }
105
116
  };
106
117
  }
107
118
  function getEmbedDownloaderOptions(configFileOptions) {
@@ -118,11 +129,16 @@ function readTargetsFile(file) {
118
129
  lockedContent: 'include.locked.content',
119
130
  postsWithMediaType: 'include.posts.with.media.type',
120
131
  postsInTier: 'include.posts.in.tier',
132
+ postsPublishedAfter: 'include.posts.published.after',
133
+ postsPublishedBefore: 'include.posts.published.before',
121
134
  campaignInfo: 'include.campaign.info',
122
135
  contentInfo: 'include.content.info',
123
136
  previewMedia: 'include.preview.media',
124
137
  contentMedia: 'include.content.media',
125
- allMediaVariants: 'include.all.media.variants'
138
+ allMediaVariants: 'include.all.media.variants',
139
+ imagesByFilename: 'include.images.by.filename',
140
+ audioByFilename: 'include.audio.by.filename',
141
+ attachmentsByFilename: 'include.attachments.by.filename'
126
142
  };
127
143
  const lines = fs.readFileSync(file)
128
144
  .toString('utf-8')
@@ -144,15 +160,46 @@ function readTargetsFile(file) {
144
160
  if (propValue) {
145
161
  const target = currentTargets.at(-1);
146
162
  if (target) {
147
- if (!target.include) {
148
- target.include = {};
149
- }
150
- target.include[optName] = {
163
+ const entry = {
151
164
  key: matchKey,
152
165
  line: ln,
153
166
  src: 'tgt',
154
167
  value: propValue
155
168
  };
169
+ if (!target.include) {
170
+ target.include = {};
171
+ }
172
+ if (matchKey === includeKeys.postsPublishedAfter || matchKey === includeKeys.postsPublishedBefore) {
173
+ if (!target.include.postsPublished) {
174
+ target.include.postsPublished = {};
175
+ }
176
+ if (matchKey === includeKeys.postsPublishedAfter) {
177
+ target.include.postsPublished.after = entry;
178
+ }
179
+ else {
180
+ target.include.postsPublished.before = entry;
181
+ }
182
+ }
183
+ else if (matchKey === includeKeys.imagesByFilename || matchKey === includeKeys.audioByFilename ||
184
+ matchKey === includeKeys.attachmentsByFilename) {
185
+ if (!target.include.mediaByFilename) {
186
+ target.include.mediaByFilename = {};
187
+ }
188
+ switch (matchKey) {
189
+ case includeKeys.imagesByFilename:
190
+ target.include.mediaByFilename.images = entry;
191
+ break;
192
+ case includeKeys.audioByFilename:
193
+ target.include.mediaByFilename.audio = entry;
194
+ break;
195
+ case includeKeys.attachmentsByFilename:
196
+ target.include.mediaByFilename.attachments = entry;
197
+ break;
198
+ }
199
+ }
200
+ else {
201
+ target.include[optName] = entry;
202
+ }
156
203
  }
157
204
  }
158
205
  }
@@ -170,7 +217,12 @@ function readTargetsFile(file) {
170
217
  for (const target of currentTargets) {
171
218
  const v = { url: target.url };
172
219
  if (target.include) {
173
- v.include = getCLIIncludeOptions(target);
220
+ const includeOpts = ObjectHelper.clean(getCLIIncludeOptions(target), {
221
+ deep: true, cleanNulls: true, cleanEmptyObjects: true
222
+ });
223
+ if (Object.entries(includeOpts).length > 0) {
224
+ v.include = includeOpts;
225
+ }
174
226
  }
175
227
  result.push(v);
176
228
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CLIOptions.js","sourceRoot":"","sources":["../../src/cli/CLIOptions.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport { DownloaderIncludeOptions, DownloaderOptions } from '../downloaders/DownloaderOptions.js';\nimport { pickDefined } from '../utils/Misc.js';\nimport { ConsoleLoggerOptions } from '../utils/logging/ConsoleLogger.js';\nimport { FileLoggerOptions } from '../utils/logging/FileLogger.js';\nimport CLIOptionValidator from './CLIOptionValidator.js';\nimport CommandLineParser, { CommandLineParseResult } from './CommandLineParser.js';\nimport ConfigFileParser, { ConfigFileParseResult } from './ConfigFileParser.js';\nimport path from 'path';\n\nexport interface CLITargetURLEntry {\n url: string;\n // Target-specific 'include' options\n include?: DownloaderIncludeOptions;\n}\n\nexport interface CLIOptions extends Omit<DownloaderOptions, 'logger'> {\n targetURLs: CLITargetURLEntry[];\n noPrompt: boolean;\n consoleLogger: ConsoleLoggerOptions;\n fileLoggers?: FileLoggerOptions[];\n}\n\nexport type CLIOptionParserEntry = ({\n src: 'cli'\n} | {\n src: 'cfg',\n section: string\n} | {\n src: 'tgt',\n line: number\n}) & {\n key: string;\n value?: string;\n}\n\nexport function getCLIOptions(): CLIOptions {\n const commandLineOptions = CommandLineParser.parse();\n\n const configFileOptions = commandLineOptions.configFile?.value ? ConfigFileParser.parse(commandLineOptions.configFile.value) : null;\n\n let targetURLs: CLITargetURLEntry[];\n const targetURLValue = CLIOptionValidator.validateRequired(pickDefined(commandLineOptions.targetURLs, configFileOptions?.targetURLs), 'No target URL specified');\n const targetsFile = path.resolve(targetURLValue);\n if (fs.existsSync(targetsFile)) {\n targetURLs = readTargetsFile(targetsFile);\n }\n else {\n targetURLs = CLIOptionValidator\n .validateTargetURLs(targetURLValue)\n .map((url) => ({ url }));\n }\n\n const { consoleLogger, fileLoggers } = getCLILoggerOptions(commandLineOptions, configFileOptions);\n\n const options: CLIOptions = {\n targetURLs,\n cookie: CLIOptionValidator.validateString(pickDefined(commandLineOptions.cookie, configFileOptions?.cookie)),\n useStatusCache: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.useStatusCache, configFileOptions?.useStatusCache)),\n pathToFFmpeg: CLIOptionValidator.validateString(pickDefined(commandLineOptions.pathToFFmpeg, configFileOptions?.pathToFFmpeg)),\n outDir: CLIOptionValidator.validateString(pickDefined(commandLineOptions.outDir, configFileOptions?.outDir)),\n dirNameFormat: {\n campaign: CLIOptionValidator.validateString(pickDefined(commandLineOptions.dirNameFormat?.campaign, configFileOptions?.dirNameFormat?.campaign)),\n content: CLIOptionValidator.validateString(pickDefined(commandLineOptions.dirNameFormat?.content, configFileOptions?.dirNameFormat?.content))\n },\n filenameFormat: {\n media: CLIOptionValidator.validateString(pickDefined(commandLineOptions.filenameFormat?.media, configFileOptions?.filenameFormat?.media))\n },\n include: getCLIIncludeOptions(commandLineOptions, configFileOptions),\n request: {\n maxRetries: CLIOptionValidator.validateNumber(pickDefined(commandLineOptions?.request?.maxRetries, configFileOptions?.request?.maxRetries)),\n maxConcurrent: CLIOptionValidator.validateNumber(pickDefined(commandLineOptions?.request?.maxConcurrent, configFileOptions?.request?.maxConcurrent)),\n minTime: CLIOptionValidator.validateNumber(pickDefined(commandLineOptions?.request?.minTime, configFileOptions?.request?.minTime))\n },\n fileExistsAction: {\n content: CLIOptionValidator.validateString(pickDefined(commandLineOptions.fileExistsAction?.content, configFileOptions?.fileExistsAction?.content), 'overwrite', 'skip', 'saveAsCopy', 'saveAsCopyIfNewer'),\n info: CLIOptionValidator.validateString(pickDefined(commandLineOptions.fileExistsAction?.info, configFileOptions?.fileExistsAction?.info), 'overwrite', 'skip', 'saveAsCopy', 'saveAsCopyIfNewer'),\n infoAPI: CLIOptionValidator.validateString(pickDefined(commandLineOptions.fileExistsAction?.infoAPI, configFileOptions?.fileExistsAction?.infoAPI), 'overwrite', 'skip', 'saveAsCopy', 'saveAsCopyIfNewer')\n },\n embedDownloaders: getEmbedDownloaderOptions(configFileOptions),\n noPrompt: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.noPrompt, configFileOptions?.noPrompt)) || false,\n consoleLogger,\n fileLoggers\n };\n\n return options;\n}\n\nexport function getCLILoggerOptions(commandLineOptions?: CommandLineParseResult, configFileOptions?: ReturnType<typeof ConfigFileParser['parse']> | null) {\n if (!commandLineOptions) {\n commandLineOptions = CommandLineParser.parse();\n }\n const consoleLogger = {\n enabled: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.consoleLogger?.enabled, configFileOptions?.consoleLogger?.enabled)),\n logLevel: CLIOptionValidator.validateString(pickDefined(commandLineOptions.consoleLogger?.logLevel, configFileOptions?.consoleLogger?.logLevel), 'info', 'debug', 'warn', 'error'),\n include: {\n dateTime: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.consoleLogger?.include?.dateTime, configFileOptions?.consoleLogger?.include?.dateTime)),\n level: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.consoleLogger?.include?.level, configFileOptions?.consoleLogger?.include?.level)),\n originator: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.consoleLogger?.include?.originator, configFileOptions?.consoleLogger?.include?.originator)),\n errorStack: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.consoleLogger?.include?.errorStack, configFileOptions?.consoleLogger?.include?.errorStack))\n },\n dateTimeFormat: CLIOptionValidator.validateString(pickDefined(commandLineOptions.consoleLogger?.dateTimeFormat, configFileOptions?.consoleLogger?.dateTimeFormat)),\n color: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.consoleLogger?.color, configFileOptions?.consoleLogger?.color))\n };\n let fileLoggers;\n if (configFileOptions?.fileLoggers) {\n fileLoggers = configFileOptions.fileLoggers.map((logger): FileLoggerOptions => ({\n enabled: CLIOptionValidator.validateBoolean(logger.enabled),\n logDir: CLIOptionValidator.validateString(logger.logDir),\n logFilename: CLIOptionValidator.validateString(logger.logFilename),\n fileExistsAction: CLIOptionValidator.validateString(logger.fileExistsAction, 'append', 'overwrite'),\n logLevel: CLIOptionValidator.validateString(logger.logLevel, 'info', 'debug', 'warn', 'error'),\n include: {\n dateTime: CLIOptionValidator.validateBoolean(logger.include?.dateTime),\n level: CLIOptionValidator.validateBoolean(logger.include?.level),\n originator: CLIOptionValidator.validateBoolean(logger.include?.originator),\n errorStack: CLIOptionValidator.validateBoolean(logger.include?.errorStack)\n },\n dateTimeFormat: CLIOptionValidator.validateString(logger.dateTimeFormat),\n color: CLIOptionValidator.validateBoolean(logger.color)\n }));\n }\n return {\n consoleLogger,\n fileLoggers\n };\n}\n\nfunction getCLIIncludeOptions(commandLineOptions: CommandLineParseResult, configFileOptions?: ConfigFileParseResult | null) {\n if (!commandLineOptions) {\n commandLineOptions = CommandLineParser.parse();\n }\n return {\n lockedContent: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.lockedContent, configFileOptions?.include?.lockedContent)),\n postsWithMediaType: CLIOptionValidator.validateIncludeContentWithMediaType(pickDefined(commandLineOptions.include?.postsWithMediaType, configFileOptions?.include?.postsWithMediaType)),\n postsInTier: CLIOptionValidator.validateIncludeContentInTier(pickDefined(commandLineOptions.include?.postsInTier, configFileOptions?.include?.postsInTier)),\n campaignInfo: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.campaignInfo, configFileOptions?.include?.campaignInfo)),\n contentInfo: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.contentInfo, configFileOptions?.include?.contentInfo)),\n previewMedia: CLIOptionValidator.validateIncludePreviewMedia(pickDefined(commandLineOptions.include?.previewMedia, configFileOptions?.include?.previewMedia)),\n contentMedia: CLIOptionValidator.validateIncludeContentMedia(pickDefined(commandLineOptions.include?.contentMedia, configFileOptions?.include?.contentMedia)),\n allMediaVariants: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.allMediaVariants, configFileOptions?.include?.allMediaVariants))\n };\n}\n\nfunction getEmbedDownloaderOptions(configFileOptions?: ConfigFileParseResult | null) {\n if (configFileOptions?.embedDownloaders) {\n return configFileOptions?.embedDownloaders.map((dl) => ({\n provider: CLIOptionValidator.validateRequired(dl.provider),\n exec: CLIOptionValidator.validateRequired(dl.exec)\n }));\n }\n return undefined;\n}\n\nfunction readTargetsFile(file: string) {\n const includeKeys: Record<keyof DownloaderIncludeOptions, string> = {\n lockedContent: 'include.locked.content',\n postsWithMediaType: 'include.posts.with.media.type',\n postsInTier: 'include.posts.in.tier',\n campaignInfo: 'include.campaign.info',\n contentInfo: 'include.content.info',\n previewMedia: 'include.preview.media',\n contentMedia: 'include.content.media',\n allMediaVariants: 'include.all.media.variants'\n };\n\n const lines = fs.readFileSync(file)\n .toString('utf-8')\n // Replace Windows line breaks with Unix ones and then split\n .replace(/\\r\\n/g, '\\n').split('\\n')\n .map((line) => line.trim());\n\n const currentTargets: { url: string; include?: Partial<Record<keyof DownloaderIncludeOptions, CLIOptionParserEntry>>; }[] = [];\n for (let ln = 0; ln < lines.length; ln++) {\n const line = lines[ln];\n if (line === '' || line.startsWith('#')) {\n continue;\n }\n try {\n const match = Object.entries(includeKeys).find((e) => line.startsWith(e[1]));\n if (match) {\n const [ optName, matchKey ] = match;\n const eq = line.indexOf('=');\n const propValue = (eq >= matchKey.length ? line.substring(eq + 1) : '').trim();\n if (propValue) {\n const target = currentTargets.at(-1);\n if (target) {\n if (!target.include) {\n target.include = {};\n }\n target.include[optName as keyof DownloaderIncludeOptions] = {\n key: matchKey,\n line: ln,\n src: 'tgt',\n value: propValue\n };\n }\n }\n }\n else {\n const url = CLIOptionValidator.validateTargetURL(line);\n currentTargets.push({ url });\n }\n }\n catch (error) {\n const errMsg = error instanceof Error ? error.message : error;\n throw Error(`Error parsing targets file (line ${ln})${errMsg ? `: ${errMsg}` : ''}`);\n }\n }\n\n const result: CLITargetURLEntry[] = [];\n for (const target of currentTargets) {\n const v: CLITargetURLEntry = { url: target.url };\n if (target.include) {\n v.include = getCLIIncludeOptions(target);\n }\n result.push(v);\n }\n\n return result;\n}\n"]}
1
+ {"version":3,"file":"CLIOptions.js","sourceRoot":"","sources":["../../src/cli/CLIOptions.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs';\nimport { type DownloaderIncludeOptions, type DownloaderOptions } from '../downloaders/DownloaderOptions.js';\nimport { type DeepPartial, type RecursivePropsTo, pickDefined } from '../utils/Misc.js';\nimport { type ConsoleLoggerOptions } from '../utils/logging/ConsoleLogger.js';\nimport { type FileLoggerOptions } from '../utils/logging/FileLogger.js';\nimport CLIOptionValidator from './CLIOptionValidator.js';\nimport CommandLineParser, { type CommandLineParseResult } from './CommandLineParser.js';\nimport ConfigFileParser, { type ConfigFileParseResult } from './ConfigFileParser.js';\nimport path from 'path';\nimport ObjectHelper from '../utils/ObjectHelper.js';\n\nexport interface CLITargetURLEntry {\n url: string;\n // Target-specific 'include' options\n include?: DownloaderIncludeOptions;\n}\n\nexport interface CLIOptions extends Omit<DownloaderOptions, 'logger'> {\n targetURLs: CLITargetURLEntry[];\n noPrompt: boolean;\n consoleLogger: ConsoleLoggerOptions;\n fileLoggers?: FileLoggerOptions[];\n}\n\nexport type CLIOptionParserEntry = ({\n src: 'cli'\n} | {\n src: 'cfg',\n section: string\n} | {\n src: 'tgt',\n line: number\n}) & {\n key: string;\n value?: string;\n}\n\nexport function getCLIOptions(): CLIOptions {\n const commandLineOptions = CommandLineParser.parse();\n\n const configFileOptions = commandLineOptions.configFile?.value ? ConfigFileParser.parse(commandLineOptions.configFile.value) : null;\n\n let targetURLs: CLITargetURLEntry[];\n const targetURLValue = CLIOptionValidator.validateRequired(pickDefined(commandLineOptions.targetURLs, configFileOptions?.targetURLs), 'No target URL specified');\n const targetsFile = path.resolve(targetURLValue);\n if (fs.existsSync(targetsFile)) {\n targetURLs = readTargetsFile(targetsFile);\n }\n else {\n targetURLs = CLIOptionValidator\n .validateTargetURLs(targetURLValue)\n .map((url) => ({ url }));\n }\n\n const { consoleLogger, fileLoggers } = getCLILoggerOptions(commandLineOptions, configFileOptions);\n\n const options: CLIOptions = {\n targetURLs,\n cookie: CLIOptionValidator.validateString(pickDefined(commandLineOptions.cookie, configFileOptions?.cookie)),\n useStatusCache: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.useStatusCache, configFileOptions?.useStatusCache)),\n pathToFFmpeg: CLIOptionValidator.validateString(pickDefined(commandLineOptions.pathToFFmpeg, configFileOptions?.pathToFFmpeg)),\n outDir: CLIOptionValidator.validateString(pickDefined(commandLineOptions.outDir, configFileOptions?.outDir)),\n dirNameFormat: {\n campaign: CLIOptionValidator.validateString(pickDefined(commandLineOptions.dirNameFormat?.campaign, configFileOptions?.dirNameFormat?.campaign)),\n content: CLIOptionValidator.validateString(pickDefined(commandLineOptions.dirNameFormat?.content, configFileOptions?.dirNameFormat?.content))\n },\n filenameFormat: {\n media: CLIOptionValidator.validateString(pickDefined(commandLineOptions.filenameFormat?.media, configFileOptions?.filenameFormat?.media))\n },\n include: getCLIIncludeOptions(commandLineOptions, configFileOptions),\n request: {\n maxRetries: CLIOptionValidator.validateNumber(pickDefined(commandLineOptions?.request?.maxRetries, configFileOptions?.request?.maxRetries)),\n maxConcurrent: CLIOptionValidator.validateNumber(pickDefined(commandLineOptions?.request?.maxConcurrent, configFileOptions?.request?.maxConcurrent)),\n minTime: CLIOptionValidator.validateNumber(pickDefined(commandLineOptions?.request?.minTime, configFileOptions?.request?.minTime))\n },\n fileExistsAction: {\n content: CLIOptionValidator.validateString(pickDefined(commandLineOptions.fileExistsAction?.content, configFileOptions?.fileExistsAction?.content), 'overwrite', 'skip', 'saveAsCopy', 'saveAsCopyIfNewer'),\n info: CLIOptionValidator.validateString(pickDefined(commandLineOptions.fileExistsAction?.info, configFileOptions?.fileExistsAction?.info), 'overwrite', 'skip', 'saveAsCopy', 'saveAsCopyIfNewer'),\n infoAPI: CLIOptionValidator.validateString(pickDefined(commandLineOptions.fileExistsAction?.infoAPI, configFileOptions?.fileExistsAction?.infoAPI), 'overwrite', 'skip', 'saveAsCopy', 'saveAsCopyIfNewer')\n },\n embedDownloaders: getEmbedDownloaderOptions(configFileOptions),\n noPrompt: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.noPrompt, configFileOptions?.noPrompt)) || false,\n dryRun: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.dryRun, configFileOptions?.dryRun)) || false,\n consoleLogger,\n fileLoggers\n };\n\n return options;\n}\n\nexport function getCLILoggerOptions(commandLineOptions?: CommandLineParseResult, configFileOptions?: ReturnType<typeof ConfigFileParser['parse']> | null) {\n if (!commandLineOptions) {\n commandLineOptions = CommandLineParser.parse();\n }\n const consoleLogger = {\n enabled: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.consoleLogger?.enabled, configFileOptions?.consoleLogger?.enabled)),\n logLevel: CLIOptionValidator.validateString(pickDefined(commandLineOptions.consoleLogger?.logLevel, configFileOptions?.consoleLogger?.logLevel), 'info', 'debug', 'warn', 'error'),\n include: {\n dateTime: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.consoleLogger?.include?.dateTime, configFileOptions?.consoleLogger?.include?.dateTime)),\n level: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.consoleLogger?.include?.level, configFileOptions?.consoleLogger?.include?.level)),\n originator: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.consoleLogger?.include?.originator, configFileOptions?.consoleLogger?.include?.originator)),\n errorStack: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.consoleLogger?.include?.errorStack, configFileOptions?.consoleLogger?.include?.errorStack))\n },\n dateTimeFormat: CLIOptionValidator.validateString(pickDefined(commandLineOptions.consoleLogger?.dateTimeFormat, configFileOptions?.consoleLogger?.dateTimeFormat)),\n color: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.consoleLogger?.color, configFileOptions?.consoleLogger?.color))\n };\n let fileLoggers;\n if (configFileOptions?.fileLoggers) {\n fileLoggers = configFileOptions.fileLoggers.map((logger): FileLoggerOptions => ({\n enabled: CLIOptionValidator.validateBoolean(logger.enabled),\n logDir: CLIOptionValidator.validateString(logger.logDir),\n logFilename: CLIOptionValidator.validateString(logger.logFilename),\n fileExistsAction: CLIOptionValidator.validateString(logger.fileExistsAction, 'append', 'overwrite'),\n logLevel: CLIOptionValidator.validateString(logger.logLevel, 'info', 'debug', 'warn', 'error'),\n include: {\n dateTime: CLIOptionValidator.validateBoolean(logger.include?.dateTime),\n level: CLIOptionValidator.validateBoolean(logger.include?.level),\n originator: CLIOptionValidator.validateBoolean(logger.include?.originator),\n errorStack: CLIOptionValidator.validateBoolean(logger.include?.errorStack)\n },\n dateTimeFormat: CLIOptionValidator.validateString(logger.dateTimeFormat),\n color: CLIOptionValidator.validateBoolean(logger.color)\n }));\n }\n return {\n consoleLogger,\n fileLoggers\n };\n}\n\nfunction getCLIIncludeOptions(commandLineOptions: CommandLineParseResult, configFileOptions?: ConfigFileParseResult | null) {\n if (!commandLineOptions) {\n commandLineOptions = CommandLineParser.parse();\n }\n return {\n lockedContent: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.lockedContent, configFileOptions?.include?.lockedContent)),\n postsWithMediaType: CLIOptionValidator.validateIncludeContentWithMediaType(pickDefined(commandLineOptions.include?.postsWithMediaType, configFileOptions?.include?.postsWithMediaType)),\n postsInTier: CLIOptionValidator.validateIncludeContentInTier(pickDefined(commandLineOptions.include?.postsInTier, configFileOptions?.include?.postsInTier)),\n postsPublished: {\n after: CLIOptionValidator.validateDateTime(pickDefined(commandLineOptions.include?.postsPublished?.after, configFileOptions?.include?.postsPublished?.after)) || null,\n before: CLIOptionValidator.validateDateTime(pickDefined(commandLineOptions.include?.postsPublished?.before, configFileOptions?.include?.postsPublished?.before)) || null,\n },\n campaignInfo: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.campaignInfo, configFileOptions?.include?.campaignInfo)),\n contentInfo: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.contentInfo, configFileOptions?.include?.contentInfo)),\n previewMedia: CLIOptionValidator.validateIncludePreviewMedia(pickDefined(commandLineOptions.include?.previewMedia, configFileOptions?.include?.previewMedia)),\n contentMedia: CLIOptionValidator.validateIncludeContentMedia(pickDefined(commandLineOptions.include?.contentMedia, configFileOptions?.include?.contentMedia)),\n allMediaVariants: CLIOptionValidator.validateBoolean(pickDefined(commandLineOptions.include?.allMediaVariants, configFileOptions?.include?.allMediaVariants)),\n mediaByFilename: {\n images: CLIOptionValidator.validateString(pickDefined(commandLineOptions.include?.mediaByFilename?.images, configFileOptions?.include?.mediaByFilename?.images)) || null,\n audio: CLIOptionValidator.validateString(pickDefined(commandLineOptions.include?.mediaByFilename?.audio, configFileOptions?.include?.mediaByFilename?.audio)) || null,\n attachments: CLIOptionValidator.validateString(pickDefined(commandLineOptions.include?.mediaByFilename?.attachments, configFileOptions?.include?.mediaByFilename?.attachments)) || null\n }\n };\n}\n\nfunction getEmbedDownloaderOptions(configFileOptions?: ConfigFileParseResult | null) {\n if (configFileOptions?.embedDownloaders) {\n return configFileOptions?.embedDownloaders.map((dl) => ({\n provider: CLIOptionValidator.validateRequired(dl.provider),\n exec: CLIOptionValidator.validateRequired(dl.exec)\n }));\n }\n return undefined;\n}\n\nfunction readTargetsFile(file: string) {\n const includeKeys = {\n lockedContent: 'include.locked.content',\n postsWithMediaType: 'include.posts.with.media.type',\n postsInTier: 'include.posts.in.tier',\n postsPublishedAfter: 'include.posts.published.after',\n postsPublishedBefore: 'include.posts.published.before',\n campaignInfo: 'include.campaign.info',\n contentInfo: 'include.content.info',\n previewMedia: 'include.preview.media',\n contentMedia: 'include.content.media',\n allMediaVariants: 'include.all.media.variants',\n imagesByFilename: 'include.images.by.filename',\n audioByFilename: 'include.audio.by.filename',\n attachmentsByFilename: 'include.attachments.by.filename'\n };\n\n const lines = fs.readFileSync(file)\n .toString('utf-8')\n // Replace Windows line breaks with Unix ones and then split\n .replace(/\\r\\n/g, '\\n').split('\\n')\n .map((line) => line.trim());\n\n const currentTargets: { url: string; include?: RecursivePropsTo<DeepPartial<DownloaderIncludeOptions>, CLIOptionParserEntry>; }[] = [];\n for (let ln = 0; ln < lines.length; ln++) {\n const line = lines[ln];\n if (line === '' || line.startsWith('#')) {\n continue;\n }\n try {\n const match = Object.entries(includeKeys).find((e) => line.startsWith(e[1]));\n if (match) {\n const [ optName, matchKey ] = match;\n const eq = line.indexOf('=');\n const propValue = (eq >= matchKey.length ? line.substring(eq + 1) : '').trim();\n if (propValue) {\n const target = currentTargets.at(-1);\n if (target) {\n const entry: CLIOptionParserEntry = {\n key: matchKey,\n line: ln,\n src: 'tgt',\n value: propValue\n };\n if (!target.include) {\n target.include = {};\n }\n if (matchKey === includeKeys.postsPublishedAfter || matchKey === includeKeys.postsPublishedBefore) {\n if (!target.include.postsPublished) {\n target.include.postsPublished = {};\n }\n if (matchKey === includeKeys.postsPublishedAfter) {\n target.include.postsPublished.after = entry;\n }\n else {\n target.include.postsPublished.before = entry;\n }\n }\n else if (matchKey === includeKeys.imagesByFilename || matchKey === includeKeys.audioByFilename ||\n matchKey === includeKeys.attachmentsByFilename) {\n if (!target.include.mediaByFilename) {\n target.include.mediaByFilename = {};\n }\n switch (matchKey) {\n case includeKeys.imagesByFilename:\n target.include.mediaByFilename.images = entry;\n break;\n case includeKeys.audioByFilename:\n target.include.mediaByFilename.audio = entry;\n break;\n case includeKeys.attachmentsByFilename:\n target.include.mediaByFilename.attachments = entry;\n break;\n }\n }\n else {\n target.include[optName as keyof DownloaderIncludeOptions] = entry;\n }\n }\n }\n }\n else {\n const url = CLIOptionValidator.validateTargetURL(line);\n currentTargets.push({ url });\n }\n }\n catch (error: any) {\n const errMsg = error instanceof Error ? error.message : error;\n throw Error(`Error parsing targets file (line ${ln})${errMsg ? `: ${errMsg}` : ''}`);\n }\n }\n\n const result: CLITargetURLEntry[] = [];\n for (const target of currentTargets) {\n const v: CLITargetURLEntry = { url: target.url };\n if (target.include) {\n const includeOpts = ObjectHelper.clean(getCLIIncludeOptions(target), {\n deep: true, cleanNulls: true, cleanEmptyObjects: true\n });\n if (Object.entries(includeOpts).length > 0) {\n v.include = includeOpts;\n }\n }\n result.push(v);\n }\n\n return result;\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { CLIOptionParserEntry, CLIOptions } from './CLIOptions.js';
2
- import { DeepPartial, RecursivePropsTo } from '../utils/Misc.js';
1
+ import { type CLIOptionParserEntry, type CLIOptions } from './CLIOptions.js';
2
+ import { type DeepPartial, type RecursivePropsTo } from '../utils/Misc.js';
3
3
  export interface CommandLineParseResult extends RecursivePropsTo<DeepPartial<Omit<CLIOptions, 'targetURLs'>>, CLIOptionParserEntry> {
4
4
  targetURLs?: CLIOptionParserEntry;
5
5
  configFile?: CLIOptionParserEntry;
@@ -1 +1 @@
1
- {"version":3,"file":"CommandLineParser.d.ts","sourceRoot":"","sources":["../../src/cli/CommandLineParser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGjE,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,EAAE,oBAAoB,CAAC;IACjI,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,UAAU,CAAC,EAAE,oBAAoB,CAAC;CACnC;AAyFD,MAAM,CAAC,OAAO,OAAO,iBAAiB;;IAEpC,MAAM,CAAC,KAAK,IAAI,sBAAsB;IA+FtC,MAAM,CAAC,SAAS;IAyChB,MAAM,CAAC,gBAAgB;IAWvB,MAAM,CAAC,SAAS;;;;CAiDjB"}
1
+ {"version":3,"file":"CommandLineParser.d.ts","sourceRoot":"","sources":["../../src/cli/CommandLineParser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7E,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAG3E,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,EAAE,oBAAoB,CAAC;IACjI,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,UAAU,CAAC,EAAE,oBAAoB,CAAC;CACnC;AA+FD,MAAM,CAAC,OAAO,OAAO,iBAAiB;;IAEpC,MAAM,CAAC,KAAK,IAAI,sBAAsB;IAsGtC,MAAM,CAAC,SAAS;IAyChB,MAAM,CAAC,gBAAgB;IAWvB,MAAM,CAAC,SAAS;;;;CAiDjB"}
@@ -18,6 +18,7 @@ const COMMAND_LINE_ARGS = {
18
18
  outDir: 'out-dir',
19
19
  logLevel: 'log-level',
20
20
  noPrompt: 'no-prompt',
21
+ dryRun: 'dry-run',
21
22
  listTiers: 'list-tiers',
22
23
  listTiersByUserId: 'list-tiers-uid'
23
24
  };
@@ -75,6 +76,11 @@ const OPT_DEFS = [
75
76
  alias: 'y',
76
77
  type: Boolean
77
78
  },
79
+ {
80
+ name: COMMAND_LINE_ARGS.dryRun,
81
+ description: 'Run without writing files to disk (except logs, if any). For testing / debugging.',
82
+ type: Boolean
83
+ },
78
84
  {
79
85
  name: COMMAND_LINE_ARGS.listTiers,
80
86
  description: 'List tiers for the given creator(s). Separate multiple creators with a comma.',
@@ -93,7 +99,7 @@ const OPT_DEFS = [
93
99
  type: Boolean
94
100
  }
95
101
  ];
96
- export default class CommandLineParser {
102
+ class CommandLineParser {
97
103
  static parse() {
98
104
  const opts = __classPrivateFieldGet(this, _a, "m", _CommandLineParser_parseArgs).call(this);
99
105
  const argv = process.argv;
@@ -110,10 +116,14 @@ export default class CommandLineParser {
110
116
  };
111
117
  const __getValue = (key) => {
112
118
  let value = opts[key];
113
- if (key === COMMAND_LINE_ARGS.noPrompt && value !== undefined) {
119
+ const booleanTypeArgs = [
120
+ COMMAND_LINE_ARGS.noPrompt,
121
+ COMMAND_LINE_ARGS.dryRun
122
+ ];
123
+ if (booleanTypeArgs.includes(key) && value !== undefined) {
114
124
  value = '1';
115
125
  }
116
- else if (value === null) {
126
+ if (value === null) {
117
127
  throw Error(`Command-line option requires a value for '--${key}'`);
118
128
  }
119
129
  if (value && typeof value === 'string') {
@@ -170,6 +180,7 @@ export default class CommandLineParser {
170
180
  infoAPI: undefined
171
181
  },
172
182
  noPrompt: __getValue(COMMAND_LINE_ARGS.noPrompt),
183
+ dryRun: __getValue(COMMAND_LINE_ARGS.dryRun),
173
184
  consoleLogger: {
174
185
  enabled: consoleLoggerEnabled,
175
186
  logLevel: consoleLoggerLevel,
@@ -277,4 +288,5 @@ _a = CommandLineParser, _CommandLineParser_parseArgs = function _CommandLinePars
277
288
  }
278
289
  return opts;
279
290
  };
291
+ export default CommandLineParser;
280
292
  //# sourceMappingURL=CommandLineParser.js.map