patreon-dl 3.6.0 → 3.7.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 (76) hide show
  1. package/NOTICE +23 -0
  2. package/README.md +16 -5
  3. package/bin/EmbedlyDownloader.js +1 -1
  4. package/bin/patreon-dl-vimeo.js +7 -4
  5. package/dist/browse/api/CampaignAPIMixin.d.ts +1 -1
  6. package/dist/browse/api/ContentAPIMixin.d.ts +4 -1
  7. package/dist/browse/api/ContentAPIMixin.js +44 -11
  8. package/dist/browse/api/ContentAPIMixin.js.map +1 -1
  9. package/dist/browse/api/FilterAPIMixin.d.ts +1 -1
  10. package/dist/browse/api/SettingsAPIMixin.d.ts +1 -0
  11. package/dist/browse/api/SettingsAPIMixin.js +4 -2
  12. package/dist/browse/api/SettingsAPIMixin.js.map +1 -1
  13. package/dist/browse/api/index.d.ts +12 -6
  14. package/dist/browse/db/CampaignDBMixin.d.ts +3 -3
  15. package/dist/browse/db/ContentDBMixin.d.ts +14 -14
  16. package/dist/browse/db/ContentDBMixin.js +12 -5
  17. package/dist/browse/db/ContentDBMixin.js.map +1 -1
  18. package/dist/browse/db/index.d.ts +17 -17
  19. package/dist/browse/server/handler/SettingsAPIRequestHandler.js +2 -1
  20. package/dist/browse/server/handler/SettingsAPIRequestHandler.js.map +1 -1
  21. package/dist/browse/types/Settings.d.ts +3 -0
  22. package/dist/browse/types/Settings.js.map +1 -1
  23. package/dist/browse/web/assets/index-CW4CUoWl.css +1 -0
  24. package/dist/browse/web/assets/{index-Dw_64hkR.js → index-CziUWlSw.js} +31 -31
  25. package/dist/browse/web/index.html +2 -2
  26. package/dist/cli/CLIOptions.js +10 -1
  27. package/dist/cli/CLIOptions.js.map +1 -1
  28. package/dist/cli/CommandLineParser.d.ts +1 -0
  29. package/dist/cli/CommandLineParser.js +11 -3
  30. package/dist/cli/CommandLineParser.js.map +1 -1
  31. package/dist/downloaders/Bootstrap.d.ts +6 -0
  32. package/dist/downloaders/Bootstrap.js +26 -0
  33. package/dist/downloaders/Bootstrap.js.map +1 -1
  34. package/dist/downloaders/Downloader.d.ts +5 -4
  35. package/dist/downloaders/Downloader.js +3 -1
  36. package/dist/downloaders/Downloader.js.map +1 -1
  37. package/dist/downloaders/InitialData.js +1 -0
  38. package/dist/downloaders/InitialData.js.map +1 -1
  39. package/dist/downloaders/PostDownloader.js +16 -0
  40. package/dist/downloaders/PostDownloader.js.map +1 -1
  41. package/dist/downloaders/PostsFetcher.js +29 -12
  42. package/dist/downloaders/PostsFetcher.js.map +1 -1
  43. package/dist/downloaders/ProductDownloader.js +8 -0
  44. package/dist/downloaders/ProductDownloader.js.map +1 -1
  45. package/dist/downloaders/ProductsFetcher.js +32 -15
  46. package/dist/downloaders/ProductsFetcher.js.map +1 -1
  47. package/dist/downloaders/task/DownloadTaskFactory.d.ts +4 -0
  48. package/dist/downloaders/task/DownloadTaskFactory.js +3 -2
  49. package/dist/downloaders/task/DownloadTaskFactory.js.map +1 -1
  50. package/dist/downloaders/task/YouTubeDownloadTask.js +7 -2
  51. package/dist/downloaders/task/YouTubeDownloadTask.js.map +1 -1
  52. package/dist/entities/Post.d.ts +1 -1
  53. package/dist/entities/Post.js.map +1 -1
  54. package/dist/entities/Product.d.ts +1 -1
  55. package/dist/entities/Product.js.map +1 -1
  56. package/dist/parsers/PostParser.d.ts +1 -1
  57. package/dist/parsers/PostParser.js +69 -13
  58. package/dist/parsers/PostParser.js.map +1 -1
  59. package/dist/parsers/ProductParser.d.ts +1 -1
  60. package/dist/parsers/ProductParser.js +5 -6
  61. package/dist/parsers/ProductParser.js.map +1 -1
  62. package/dist/utils/FilenameFormatHelper.d.ts +2 -2
  63. package/dist/utils/FilenameFormatHelper.js +45 -2
  64. package/dist/utils/FilenameFormatHelper.js.map +1 -1
  65. package/dist/utils/MediaFilenameResolver.d.ts +4 -1
  66. package/dist/utils/MediaFilenameResolver.js +6 -4
  67. package/dist/utils/MediaFilenameResolver.js.map +1 -1
  68. package/dist/utils/URLHelper.js +8 -8
  69. package/dist/utils/URLHelper.js.map +1 -1
  70. package/dist/utils/YouTubeCredentialsCapturer.js +1 -1
  71. package/dist/utils/YouTubeCredentialsCapturer.js.map +1 -1
  72. package/dist/utils/yt/InnertubeLoader.d.ts +19 -1
  73. package/dist/utils/yt/InnertubeLoader.js +55 -15
  74. package/dist/utils/yt/InnertubeLoader.js.map +1 -1
  75. package/package.json +2 -1
  76. package/dist/browse/web/assets/index-DjOKbT1U.css +0 -1
@@ -49,6 +49,9 @@ _ProductDownloader_startPromise = new WeakMap(), _ProductDownloader_instances =
49
49
  if (productFetch.type === 'byShop') {
50
50
  this.log('info', `Targeting products by '${productFetch.vanity}'`);
51
51
  }
52
+ else if (productFetch.type === 'byFile') {
53
+ this.log('info', `Target product given by API data in "${productFetch.filePath}"`);
54
+ }
52
55
  else {
53
56
  this.log('info', `Targeting product #${productFetch.productId}`);
54
57
  }
@@ -183,6 +186,9 @@ _ProductDownloader_startPromise = new WeakMap(), _ProductDownloader_instances =
183
186
  if (productFetch.type === 'byShop') {
184
187
  this.log('info', `Done downloading products by '${productFetch.vanity}'`);
185
188
  }
189
+ else if (productFetch.type === 'byFile') {
190
+ this.log('info', `Done downloading product given in "${productFetch.filePath}"`);
191
+ }
186
192
  else {
187
193
  this.log('info', `Done downloading product #${productFetch.productId}`);
188
194
  }
@@ -272,6 +278,7 @@ _ProductDownloader_startPromise = new WeakMap(), _ProductDownloader_instances =
272
278
  const batchResult = await this.createDownloadTaskBatch(`Product #${product.id} (${product.name})`, signal, previewMedia.length > 0 ? {
273
279
  target: previewMedia,
274
280
  targetName: `product #${product.id} -> preview media`,
281
+ src: product,
275
282
  dirs: {
276
283
  campaign: campaignDir,
277
284
  main: productDirs.previewMedia,
@@ -281,6 +288,7 @@ _ProductDownloader_startPromise = new WeakMap(), _ProductDownloader_instances =
281
288
  } : null, contentMedia.length > 0 ? {
282
289
  target: contentMedia,
283
290
  targetName: `product #${product.id} -> content media`,
291
+ src: product,
284
292
  dirs: {
285
293
  campaign: campaignDir,
286
294
  main: productDirs.contentMedia,
@@ -1 +1 @@
1
- {"version":3,"file":"ProductDownloader.js","sourceRoot":"","sources":["../../src/downloaders/ProductDownloader.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,aAAa,MAAM,6BAA6B,CAAC;AACxD,OAAO,SAAS,MAAM,uBAAuB,CAAC;AAC9C,OAAO,UAAiE,MAAM,iBAAiB,CAAC;AAChG,OAAO,WAAW,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAgB,MAAM,wBAAwB,CAAC;AAEnE,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,eAAe,MAAM,sBAAsB,CAAC;AAInD,MAAqB,iBAAkB,SAAQ,UAAmB;IAAlE;;;QAIE,SAAI,GAAG,mBAAmB,CAAC;QAE3B,0CAAsC,IAAI,EAAC;IAkd7C,CAAC;IAhdC,OAAO,CAAC,MAA8B;QAEpC,IAAI,uBAAA,IAAI,uCAAc,EAAE,CAAC;YACvB,MAAM,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC5C,CAAC;QAED,uBAAA,IAAI,mCAAiB,uBAAA,IAAI,gEAAS,MAAb,IAAI,EAAU,MAAM,CAAC;aACvC,OAAO,CAAC,GAAG,EAAE;YACZ,uBAAA,IAAI,mCAAiB,IAAI,MAAA,CAAC;QAC5B,CAAC,CAAC,MAAA,CAAC;QAEL,OAAO,uBAAA,IAAI,uCAAc,CAAC;IAC5B,CAAC;;4HAED,KAAK,qCAAU,MAA8B;IAC3C,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QAChC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;QAC9C,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,EAAE,EAAE,CAAC;QAE3B,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;YAClC,OAAO;QACT,CAAC;QAED,IAAI,YAAY,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,0BAA0B,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;QACrE,CAAC;aACI,CAAC;YACJ,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAsB,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,sDAAsD;QACtD,MAAM,eAAe,GAAG,IAAI,eAAe,CAAC;YAC1C,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM;SACP,CAAC,CAAC;QACH,eAAe,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,EAAC,OAAO,EAAC,EAAE,EAAE;YAC/C,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACjC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,UAAU,EAAE,eAAe,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC,CAAC,CAAC;QACH,eAAe,CAAC,KAAK,EAAE,CAAC;QAExB,iDAAiD;QACjD,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,iBAAiB,GAAG,CAAC,CAAC;QAC1B,IAAI,gBAAgB,GAAG,CAAC,CAAC;QACzB,IAAI,4BAA4B,GAAG,CAAC,CAAC;QACrC,IAAI,aAAa,GAAG,KAAK,CAAC;QAC1B,IAAI,gBAAgB,GAAG,KAAK,CAAC;QAC7B,MAAM,cAAc,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtD,OAAO,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC;YACjC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,CAAC;YAC9D,IAAI,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC;gBACrB,MAAM;YACR,CAAC;YACD,IAAI,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC;gBACnB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC,CAAC;gBAC9E,OAAO;YACT,CAAC;YACD,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;gBAC9C,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBAC5D,aAAa,GAAG,IAAI,CAAC;gBACrB,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;oBAClC,OAAO;gBACT,CAAC;YACH,CAAC;YAED,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBAElC,IAAI,gBAAgB,EAAE,CAAC;oBACrB,MAAM;gBACR,CAAC;gBAED,IAAI,OAAO,GAAG,QAAQ,CAAC;gBAEvB,IAAI,uBAAA,IAAI,mFAA4B,MAAhC,IAAI,EAA6B,YAAY,CAAC,EAAE,CAAC;oBACnD,iDAAiD;oBACjD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,oBAAoB,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAC;oBACrD,MAAM,UAAU,GAAG,SAAS,CAAC,sBAAsB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBAChE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;oBAC/D,IAAI,SAAS,GAAmB,IAAI,CAAC;oBACrC,IAAI,IAAI,EAAE,CAAC;wBACT,SAAS,GAAG,cAAc,CAAC,wBAAwB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;wBACvF,IAAI,CAAC,SAAS,EAAE,CAAC;4BACf,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAsB,QAAQ,CAAC,EAAE,mDAAmD,CAAC,CAAC;wBACzG,CAAC;6BACI,IAAI,SAAS,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE,EAAE,CAAC;4BACtC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,sBAAsB,QAAQ,CAAC,EAAE,+CAA+C,CAAC,CAAC;4BACnG,SAAS,GAAG,IAAI,CAAC;wBACnB,CAAC;6BACI,CAAC;4BACJ,0DAA0D;4BAC1D,SAAS,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;wBAC/C,CAAC;oBACH,CAAC;yBACI,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;wBACvC,OAAO;oBACT,CAAC;yBACI,CAAC;wBACJ,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,8BAA8B,QAAQ,CAAC,EAAE,+BAA+B,CAAC,CAAC;oBAC7F,CAAC;oBACD,IAAI,SAAS,EAAE,CAAC;wBACd,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,+BAA+B,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;wBACjE,OAAO,GAAG,SAAS,CAAC;oBACtB,CAAC;gBACH,CAAC;gBAED,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;gBAE9C,gCAAgC;gBAChC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;gBAC1D,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,sBAAsB,EAAE,WAAW,CAAC,CAAC;gBAEvD,oCAAoC;gBACpC,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC/F,IAAI,CAAC,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,KAAK,WAAW,CAAC,eAAe,EAAE,CAAC;oBAChF,MAAM,qBAAqB,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;oBAC1F,IAAI,CAAC,qBAAqB,CAAC,WAAW,EAAE,CAAC;wBACvC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,gCAAgC,OAAO,CAAC,EAAE,sBAAsB,CAAC,CAAC;wBACnF,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;4BACrB,MAAM,EAAE,OAAO;4BACf,SAAS,EAAE,IAAI;4BACf,UAAU,EAAE,gBAAgB,CAAC,iBAAiB;4BAC9C,WAAW,EAAE,2BAA2B;yBACzC,CAAC,CAAC;wBACH,gBAAgB,EAAE,CAAC;wBACnB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,sBAAsB,EAAE,CAAC;4BAClD,gBAAgB,GAAG,IAAI,CAAC;wBAC1B,CAAC;wBACD,SAAS;oBACX,CAAC;gBACH,CAAC;gBAED,QAAQ,CAAC,MAAM,uBAAA,IAAI,mEAAY,MAAhB,IAAI,EACjB,OAAO,EACP,WAAW,EACX,WAAW,EACX,EAAE,EACF,MAAM,CACP,CAAC,CAAC,MAAM,EAAE,CAAC;oBACV,KAAK,SAAS;wBACZ,OAAO;oBACT,KAAK,YAAY;wBACf,UAAU,EAAE,CAAC;wBACb,MAAM;oBACR,KAAK,8BAA8B;wBACjC,4BAA4B,EAAE,CAAC;wBAC/B,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,2BAA2B;4BACpD,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,uBAAuB,EAC9C,CAAC;4BACD,gBAAgB,GAAG,IAAI,CAAC;wBAC1B,CAAC;wBACD,MAAM;oBACR,KAAK,mBAAmB;wBACtB,iBAAiB,EAAE,CAAC;wBACpB,MAAM;gBACV,CAAC;gBAED,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;oBAClC,OAAO;gBACT,CAAC;YACH,CAAC;YAED,IAAI,gBAAgB,EAAE,CAAC;gBACrB,MAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;YAClC,OAAO;QACT,CAAC;QAED,IAAI,gBAAgB,IAAI,uBAAA,IAAI,mFAA4B,MAAhC,IAAI,EAA6B,YAAY,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,oCAAoC,IAAI,CAAC,MAAM,CAAC,MAAM,OAAO,CAAC,CAAA;QACjF,CAAC;QAED,OAAO;QACP,IAAI,YAAY,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,iCAAiC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;QAC5E,CAAC;aACI,CAAC;YACJ,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,6BAA6B,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,UAAU,GAAG,MAAM,CAAC;QACxB,IAAI,uBAAA,IAAI,mFAA4B,MAAhC,IAAI,EAA6B,YAAY,CAAC,EAAE,CAAC;YACnD,MAAM,eAAe,GAAa,EAAE,CAAC;YACrC,IAAI,iBAAiB,EAAE,CAAC;gBACtB,eAAe,CAAC,IAAI,CAAC,GAAG,iBAAiB,aAAa,CAAC,CAAC;YAC1D,CAAC;YACD,IAAI,gBAAgB,EAAE,CAAC;gBACrB,eAAe,CAAC,IAAI,CAAC,GAAG,gBAAgB,YAAY,CAAC,CAAC;YACxD,CAAC;YACD,IAAI,4BAA4B,EAAE,CAAC;gBACjC,eAAe,CAAC,IAAI,CAAC,GAAG,4BAA4B,iCAAiC,CAAC,CAAC;YACzF,CAAC;YACD,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACjG,UAAU,GAAG,SAAS,UAAU,MAAM,eAAe,CAAC,QAAQ,EAAE,sBAAsB,UAAU,EAAE,CAAC;YACnG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC/B,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;IAC5D,CAAC;YACO,CAAC;QACP,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACrB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;AACH,CAAC,kCAED,KAAK,wCACH,OAAgB,EAChB,WAA+B,EAC/B,WAAwB,EACxB,EAAc,EACd,MAAoB;IAEpB,mDAAmD;IACnD,uBAAuB;IACvB,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QAC1B,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YACtC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,OAAO,CAAC,EAAE,oCAAoC,CAAC,CAAC;QAC/E,CAAC;aACI,CAAC;YACJ,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,gCAAgC,OAAO,CAAC,EAAE,kCAAkC,CAAC,CAAC;YAC/F,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;gBACrB,MAAM,EAAE,OAAO;gBACf,SAAS,EAAE,IAAI;gBACf,UAAU,EAAE,gBAAgB,CAAC,YAAY;gBACzC,WAAW,EAAE,0CAA0C;aACxD,CAAC,CAAC;YACH,OAAO;gBACL,MAAM,EAAE,mBAAmB;aAC5B,CAAC;QACJ,CAAC;IACH,CAAC;IACD,mDAAmD;IACnD,IAAI,IAAI,CAAC,uBAAuB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,OAAO;YACL,MAAM,EAAE,8BAA8B;SACvC,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAE1C,4BAA4B;IAC5B,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAChD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC/D,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACrH,IAAI,CAAC,sBAAsB,CAAC,iBAAiB,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;QAE3E,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;QAC1E,MAAM,oBAAoB,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAC5D,cAAc,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACrE,IAAI,CAAC,sBAAsB,CAAC,oBAAoB,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAC;QAC/E,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,uCAAuC;IACvC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC;IACpD,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC;IACpD,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,EAAE;QAC5B,CAAC,eAAe,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;QACzG,CAAC,eAAe,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;KAC1G,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,CAAC,GAAyB,EAAE,MAAoB,EAAE,EAAE;QAChE,IAAI,OAAO,GAAG,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO,GAAG,CAAC;QACb,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAW,CAAC,CAAC,CAAC;IAC5C,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;IAChF,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;IAChF,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAEnG,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QACzE,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QACjE,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,uBAAuB,CACpD,YAAY,OAAO,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,GAAG,EAC1C,MAAM,EAEN,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;YACxB,MAAM,EAAE,YAAY;YACpB,UAAU,EAAE,YAAY,OAAO,CAAC,EAAE,mBAAmB;YACrD,IAAI,EAAE;gBACJ,QAAQ,EAAE,WAAW;gBACrB,IAAI,EAAE,WAAW,CAAC,YAAY;gBAC9B,UAAU,EAAE,WAAW,CAAC,UAAU;aACnC;YACD,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO;SACvD,CAAC,CAAC,CAAC,IAAI,EAER,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;YACxB,MAAM,EAAE,YAAY;YACpB,UAAU,EAAE,YAAY,OAAO,CAAC,EAAE,mBAAmB;YACrD,IAAI,EAAE;gBACJ,QAAQ,EAAE,WAAW;gBACrB,IAAI,EAAE,WAAW,CAAC,YAAY;gBAC9B,UAAU,EAAE,WAAW,CAAC,UAAU;aACnC;YACD,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO;YACtD,sBAAsB,EAAE,CAAC,OAAO,CAAC,YAAY;SAC9C,CAAC,CAAC,CAAC,IAAI,CACT,CAAC;QAEF,MAAM,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC;QAE9B,MAAM,YAAY,GAAG,GAAG,EAAE;YACxB,KAAK,CAAC,KAAK,IAAI,EAAE;gBACf,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;gBAC1C,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;gBACtB,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;QACP,CAAC,CAAC;QACF,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,CAAC;YACH,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClC,OAAO;oBACL,MAAM,EAAE,SAAS;iBAClB,CAAC;YACJ,CAAC;YAED,KAAK,CAAC,QAAQ,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,4BAA4B,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,oBAAoB,CAAC,CAAC;YACjH,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC;YAE5E,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;YAEpB,8BAA8B;YAC9B,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,UAAU,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAEvI,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;QACxB,CAAC;gBACO,CAAC;YACP,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,CAAC;QACnE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,OAAO;YACL,MAAM,EAAE,SAAS;SAClB,CAAC;IACJ,CAAC;IAED,qBAAqB;IACrB,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,sBAA4C,CAAC;IACjD,MAAM,SAAS,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;IACvD,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QAC1B,mEAAmE;QACnE,MAAM,GAAG,SAAS,KAAK,IAAI,IAAI,SAAS,CAAC,YAAY,CAAC;IACxD,CAAC;IACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACxB,sBAAsB,GAAG,CAAC,EAAE,EAAE,EAAE;YAC9B,OAAO,CAAC,kBAAkB,GAAG,EAAE,CAAC;YAChC,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC,CAAC;IACJ,CAAC;SACI,CAAC;QACJ,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,+CAA+C,OAAO,CAAC,EAAE,wCAAwC,CAAC,CAAC;QACpH,sBAAsB,GAAG,CAAC,EAAE,EAAE,EAAE;YAC9B,uCAAuC;YACvC,SAAU,CAAC,kBAAkB,GAAG,EAAE,CAAC;YACnC,EAAE,CAAC,WAAW,CAAC,SAAU,CAAC,CAAC;QAC7B,CAAC,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,MAAM,uBAAA,IAAI,2EAAoB,MAAxB,IAAI,EAAqB,OAAO,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;IAExE,OAAO;IACP,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,6BAA6B,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5D,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;IAE9D,OAAO;QACL,MAAM,EAAE,YAAY;KACrB,CAAA;AACH,CAAC;AAED,iDAAiD;AACjD,KAAK,gDACH,OAAgB,EAChB,sBAA4C,EAC5C,MAAoB;IAEpB,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,OAAO,CAAC,WAAW,KAAK,WAAW,CAAC,eAAe,EAAE,CAAC;QAC7F,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,iBAAiB,OAAO,CAAC,WAAW,+BAA+B,CAAC,CAAC;QACvF,OAAO;IACT,CAAC;IACD,IAAI,OAAO,CAAC,WAAW,KAAK,WAAW,CAAC,IAAI,IAAI,OAAO,CAAC,WAAW,KAAK,WAAW,CAAC,UAAU,EAAE,CAAC;QAC/F,MAAM,SAAS,GAAG,SAAS,CAAC,+BAA+B,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACzE,IAAI,SAAS,EAAE,IAAI,KAAK,MAAM,EAAE,CAAC;YAC/B,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,OAAO,CAAC,WAAW,2BAA2B,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YAC1F,MAAM,cAAc,GAAG,CAAC,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC,OAAO,CAAC;YACrE,MAAM,UAAU,GAAG,IAAI,cAAc,CACnC;gBACE,GAAG,IAAI,CAAC,MAAM;gBACd,GAAG,SAAS;aACb,EACD,IAAI,CAAC,EAAE,EACP,IAAI,CAAC,MAAM,EACX;gBACE,gBAAgB,EAAE,IAAI;gBACtB,cAAc,EAAE,IAAI;gBACpB,UAAU,EAAE,IAAI;aACjB,CACF,CAAC;YACF,IAAI,CAAC;gBACH,MAAM,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;gBACnC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,oBAAoB,OAAO,CAAC,WAAW,wBAAwB,CAAC,CAAC;YACpF,CAAC;YACD,OAAO,KAAK,EAAE,CAAC;gBACb,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;oBACpB,MAAM,KAAK,CAAC;gBACd,CAAC;gBACD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,qBAAqB,OAAO,CAAC,WAAW,gCAAgC,OAAO,CAAC,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC;YACnH,CAAC;YACD,IAAI,kBAAkB,GAAuB,SAAS,CAAC;YACvD,IAAI,iBAAiB,GAAG,KAAK,CAAC;YAC9B,IAAI,SAAS,CAAC,SAAS,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC1C,iBAAiB,GAAG,OAAO,CAAC,WAAW,KAAK,WAAW,CAAC,IAAI,CAAC;gBAC7D,kBAAkB,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC;YAClD,CAAC;YACD,IAAI,SAAS,CAAC,SAAS,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;gBAChD,iBAAiB,GAAG,OAAO,CAAC,WAAW,KAAK,WAAW,CAAC,UAAU,CAAC;gBACnE,kBAAkB,GAAG,SAAS,CAAC,SAAS,CAAC,YAAY,CAAC;YACxD,CAAC;YACD,IAAI,iBAAiB,EAAE,CAAC;gBACtB,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,iBAAiB,OAAO,CAAC,WAAW,yBAAyB,OAAO,CAAC,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,CAAC;YAC9H,CAAC;iBACI,IAAI,kBAAkB,EAAE,CAAC;gBAC5B,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;aACI,CAAC;YACJ,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,oBAAoB,OAAO,CAAC,WAAW,+CAA+C,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;QAC1H,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,yBAAyB,OAAO,CAAC,WAAW,mCAAmC,CAAC,CAAC;IACnG,OAAO;AACT,CAAC,yGAE2B,YAAuD;IACjF,OAAO,YAAY,CAAC,IAAI,KAAK,QAAQ,CAAC;AACxC,CAAC;AArdM,yBAAO,GAAG,OAAO,AAAV,CAAW;eAFN,iBAAiB","sourcesContent":["import ProductParser from '../parsers/ProductParser.js';\nimport URLHelper from '../utils/URLHelper.js';\nimport Downloader, { type DownloaderConfig, type DownloaderStartParams } from './Downloader.js';\nimport StatusCache from './cache/StatusCache.js';\nimport { generateProductSummary } from './templates/ProductInfo.js';\nimport path from 'path';\nimport { TargetSkipReason } from './DownloaderEvent.js';\nimport { ProductType, type Product } from '../entities/Product.js';\nimport { type Downloadable } from '../entities/Downloadable.js';\nimport Bootstrap from './Bootstrap.js';\nimport ProductsFetcher from './ProductsFetcher.js';\nimport { type ProductDirectories } from '../utils/FSHelper.js';\nimport { type DBInstance } from '../browse/db/index.js';\n\nexport default class ProductDownloader extends Downloader<Product> {\n\n static version = '1.0.1';\n\n name = 'ProductDownloader';\n\n #startPromise: Promise<void> | null = null;\n\n doStart(params?: DownloaderStartParams): Promise<void> {\n\n if (this.#startPromise) {\n throw Error('Downloader already running');\n }\n\n this.#startPromise = this.#doStart(params)\n .finally(() => {\n this.#startPromise = null;\n });\n\n return this.#startPromise;\n }\n\n async #doStart(params?: DownloaderStartParams): Promise<void> {\n try {\n const { signal } = params || {};\n const productFetch = this.config.productFetch;\n const db = await this.db();\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n if (productFetch.type === 'byShop') {\n this.log('info', `Targeting products by '${productFetch.vanity}'`);\n }\n else {\n this.log('info', `Targeting product #${productFetch.productId}`);\n }\n\n // Step 1: get products (if by shop) or target product\n const productsFetcher = new ProductsFetcher({\n config: this.config,\n fetcher: this.fetcher,\n logger: this.logger,\n signal\n });\n productsFetcher.on('statusChange', ({current}) => {\n if (current.status === 'running') {\n this.emit('fetchBegin', { targetType: productsFetcher.getTargetType() });\n }\n });\n productsFetcher.begin();\n\n // Step 2: download products in each fetched list\n let downloaded = 0;\n let skippedUnviewable = 0;\n let skippedRedundant = 0;\n let skippedPublishDateOutOfRange = 0;\n let campaignSaved = false;\n let stopConditionMet = false;\n const productsParser = new ProductParser(this.logger);\n while (productsFetcher.hasNext()) {\n const { list, aborted, error } = await productsFetcher.next();\n if (!list || aborted) {\n break;\n }\n if (!list && error) {\n this.emit('end', { aborted: false, error, message: 'ProductsFetcher error' });\n return;\n }\n if (!campaignSaved && list.items[0]?.campaign) {\n await this.saveCampaignInfo(list.items[0].campaign, signal);\n campaignSaved = true;\n if (this.checkAbortSignal(signal)) {\n return;\n }\n }\n\n for (const _product of list.items) {\n\n if (stopConditionMet) {\n break;\n }\n\n let product = _product;\n\n if (this.#isFetchingMultipleProducts(productFetch)) {\n // Refresh to ensure media links have not expired\n this.log('debug', `Refresh product #${_product.id}`);\n const productURL = URLHelper.constructProductAPIURL(product.id);\n const { json } = await this.commonFetchAPI(productURL, signal);\n let refreshed: Product | null = null;\n if (json) {\n refreshed = productsParser.parseProductsAPIResponse(json, productURL).items[0] || null;\n if (!refreshed) {\n this.log('warn', `Refreshed product #${_product.id} but got empty value - going to use existing data`);\n }\n else if (refreshed.id !== _product.id) {\n this.log('warn', `Refreshed product #${_product.id} but ID mismatch - going to use existing data`);\n refreshed = null;\n }\n else {\n // Refreshed data does not have productType - reinstate it\n refreshed.productType = _product.productType;\n }\n }\n else if (this.checkAbortSignal(signal)) {\n return;\n }\n else {\n this.log('warn', `Failed to refresh product #${_product.id} - going to use existing data`);\n }\n if (refreshed) {\n this.log('debug', `Use refreshed product data #${refreshed.id}`);\n product = refreshed;\n }\n }\n\n this.emit('targetBegin', { target: product });\n\n // Step 4.1: product directories\n const productDirs = this.fsHelper.getProductDirs(product);\n this.log('debug', 'Product directories:', productDirs);\n\n // Step 4.2: Check with status cache\n const statusCache = StatusCache.getInstance(this.config, productDirs.statusCache, this.logger);\n if (!product.productType || product.productType === ProductType.DigitalCommerce) {\n const statusCacheValidation = statusCache.validate(product, productDirs.root, this.config)\n if (!statusCacheValidation.invalidated) {\n this.log('info', `Skipped downloading product #${product.id}: already downloaded`);\n this.emit('targetEnd', {\n target: product,\n isSkipped: true,\n skipReason: TargetSkipReason.AlreadyDownloaded,\n skipMessage: 'Target already downloaded'\n });\n skippedRedundant++;\n if (this.config.stopOn === 'previouslyDownloaded') {\n stopConditionMet = true;\n }\n continue;\n }\n }\n \n switch ((await this.#doDownload(\n product,\n productDirs,\n statusCache,\n db,\n signal\n )).status) {\n case 'aborted':\n return;\n case 'downloaded':\n downloaded++;\n break;\n case 'skippedPublishDateOutOfRange':\n skippedPublishDateOutOfRange++;\n if (this.config.stopOn === 'postPublishDateOutOfRange' ||\n this.config.stopOn === 'publishDateOutOfRange'\n ) {\n stopConditionMet = true;\n }\n break;\n case 'skippedUnviewable':\n skippedUnviewable++;\n break;\n }\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n }\n\n if (stopConditionMet) {\n break;\n }\n }\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n if (stopConditionMet && this.#isFetchingMultipleProducts(productFetch)) {\n this.log('info', `Stop downloader: stop condition \"${this.config.stopOn}\" met`)\n }\n\n // Done\n if (productFetch.type === 'byShop') {\n this.log('info', `Done downloading products by '${productFetch.vanity}'`);\n }\n else {\n this.log('info', `Done downloading product #${productFetch.productId}`);\n }\n let endMessage = 'Done';\n if (this.#isFetchingMultipleProducts(productFetch)) {\n const skippedStrParts: string[] = [];\n if (skippedUnviewable) {\n skippedStrParts.push(`${skippedUnviewable} unviewable`);\n }\n if (skippedRedundant) {\n skippedStrParts.push(`${skippedRedundant} redundant`);\n }\n if (skippedPublishDateOutOfRange) {\n skippedStrParts.push(`${skippedPublishDateOutOfRange} with publish date out of range`);\n }\n const skippedStr = skippedStrParts.length > 0 ? ` (skipped: ${skippedStrParts.join(', ')})` : '';\n endMessage = `Total ${downloaded} / ${productsFetcher.getTotal()} products processed${skippedStr}`;\n this.log('info', endMessage);\n }\n this.emit('end', { aborted: false, message: endMessage });\n }\n finally {\n await this.closeDB();\n if (this.logger) {\n await this.logger.end();\n }\n }\n }\n\n async #doDownload(\n product: Product,\n productDirs: ProductDirectories,\n statusCache: StatusCache,\n db: DBInstance,\n signal?: AbortSignal\n ): Promise<{status: 'skippedUnviewable' | 'skippedPublishDateOutOfRange' | 'aborted' | 'downloaded' }> {\n // Step 1: Check whether we should download product\n // -- 1.1 Accessibility\n if (!product.isAccessible) {\n if (this.config.include.lockedContent) {\n this.log('warn', `Product #${product.id} is not accessible by current user`);\n }\n else {\n this.log('warn', `Skipped downloading product #${product.id}: not accessible by current user`);\n this.emit('targetEnd', {\n target: product,\n isSkipped: true,\n skipReason: TargetSkipReason.Inaccessible,\n skipMessage: 'Target is not accessible by current user'\n });\n return {\n status: 'skippedUnviewable'\n };\n }\n }\n // -- 1.4 Config option 'include.productsPublished'\n if (this.isPublishDateOutOfRange(product)) {\n return {\n status: 'skippedPublishDateOutOfRange'\n };\n }\n\n this.fsHelper.createDir(productDirs.root);\n\n // Step 2: save product info\n if (this.config.include.contentInfo) {\n this.log('info', 'Save product info');\n this.emit('phaseBegin', { target: product, phase: 'saveInfo' });\n this.fsHelper.createDir(productDirs.info);\n const summary = generateProductSummary(product);\n const summaryFile = path.resolve(productDirs.info, 'info.txt');\n const saveSummaryResult = await this.fsHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, product, 'product summary');\n\n const productRawFile = path.resolve(productDirs.info, 'product-api.json');\n const saveProductRawResult = await this.fsHelper.writeTextFile(\n productRawFile, product.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(saveProductRawResult, product, 'product API data');\n this.emit('phaseEnd', { target: product, phase: 'saveInfo' });\n }\n\n // Step 3: Download product media items\n const incPreview = this.config.include.previewMedia;\n const incContent = this.config.include.contentMedia;\n this.log('info', 'Download:', {\n ['preview items']: incPreview === true ? 'yes' : incPreview === false ? 'no' : JSON.stringify(incPreview),\n ['content items']: incContent === true ? 'yes' : incContent === false ? 'no' : JSON.stringify(incContent)\n });\n\n const __inc = (inc: boolean | Array<any>, target: Downloadable) => {\n if (typeof inc === 'boolean') {\n return inc;\n }\n return (inc.includes(target.type as any));\n };\n\n const previewMedia = product.previewMedia.filter((tt) => __inc(incPreview, tt));\n const contentMedia = product.contentMedia.filter((tt) => __inc(incContent, tt));\n const campaignDir = product.campaign ? this.fsHelper.getCampaignDirs(product.campaign).root : null;\n\n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseBegin', { target: product, phase: 'saveMedia' });\n const batchResult = await this.createDownloadTaskBatch(\n `Product #${product.id} (${product.name})`,\n signal,\n\n previewMedia.length > 0 ? {\n target: previewMedia,\n targetName: `product #${product.id} -> preview media`,\n dirs: {\n campaign: campaignDir,\n main: productDirs.previewMedia,\n thumbnails: productDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n contentMedia.length > 0 ? {\n target: contentMedia,\n targetName: `product #${product.id} -> content media`,\n dirs: {\n campaign: campaignDir,\n main: productDirs.contentMedia,\n thumbnails: productDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content,\n ignoreCreateTaskErrors: !product.isAccessible\n } : null\n );\n\n const { batch } = batchResult;\n\n const abortHandler = () => {\n void (async () => {\n this.log('info', 'Abort signal received');\n if (batch) {\n await batch.abort();\n }\n })();\n };\n if (signal) {\n signal.addEventListener('abort', abortHandler, { once: true });\n }\n \n try {\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n \n batch.prestart();\n this.log('info', `Download batch created (#${batch.id}): ${batch.getTasks('pending').length} downloads pending`);\n this.emit('phaseBegin', { target: product, phase: 'batchDownload', batch });\n\n await batch.start();\n\n // Step 4: Update status cache\n statusCache.updateOnDownload(product, productDirs.root, batch.getTasks('error').length > 0 || batchResult.errorCount > 0, this.config);\n\n await batch.destroy();\n }\n finally {\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n }\n\n this.emit('phaseEnd', { target: product, phase: 'batchDownload' });\n this.emit('phaseEnd', { target: product, phase: 'saveMedia' });\n }\n\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n\n // Step 5: Save to DB\n let skipDB = false;\n let saveReferencedEntityId: (id: string) => void;\n const dbProduct = db.getContent(product.id, 'product');\n if (!product.isAccessible) {\n // Skip if existing db record (if any) refers to accessible product\n skipDB = dbProduct !== null && dbProduct.isAccessible;\n }\n if (!skipDB) {\n db.saveContent(product);\n saveReferencedEntityId = (id) => {\n product.referencedEntityId = id;\n db.saveContent(product);\n };\n }\n else {\n this.log('info', `Skip overwrite existing accessible product #${product.id} in DB with current unviewable version`);\n saveReferencedEntityId = (id) => {\n // Ensure referencedEntityId is updated\n dbProduct!.referencedEntityId = id;\n db.saveContent(dbProduct!);\n };\n }\n\n // Step 6: check product type and download referenced product / collection\n await this.#processProductType(product, saveReferencedEntityId, signal);\n\n // Done\n this.log('info', `Done downloading product #${product.id}`);\n this.emit('targetEnd', { target: product, isSkipped: false });\n\n return {\n status: 'downloaded'\n }\n }\n\n // Carry out further action based on product type\n async #processProductType(\n product: Product,\n saveReferencedEntityId: (id: string) => void,\n signal?: AbortSignal\n ) {\n if (product.productType === undefined || product.productType === ProductType.DigitalCommerce) {\n this.log('debug', `Product type \"${product.productType}\": no further action required`);\n return;\n }\n if (product.productType === ProductType.Post || product.productType === ProductType.Collection) {\n const bootstrap = Bootstrap.getDownloaderBootstrapDataByURL(product.url);\n if (bootstrap?.type === 'post') {\n this.log('info', `Download ${product.productType} referenced by product: ${product.url}`);\n const PostDownloader = (await import('./PostDownloader.js')).default;\n const downloader = new PostDownloader(\n {\n ...this.config,\n ...bootstrap\n },\n this.db,\n this.logger,\n {\n skipSaveCampaign: true,\n keepLoggerOpen: true,\n keepDBOpen: true\n }\n );\n try {\n await downloader.start({ signal });\n this.log('info', `Done downloading ${product.productType} referenced by product`);\n }\n catch (error) {\n if (signal?.aborted) {\n throw error;\n }\n this.log('error', `Error downloading ${product.productType} referenced by product (url: ${product.url})`, error);\n }\n let referencedEntityId: string | undefined = undefined;\n let bootstrapMismatch = false;\n if (bootstrap.postFetch.type === 'single') {\n bootstrapMismatch = product.productType !== ProductType.Post;\n referencedEntityId = bootstrap.postFetch.postId;\n }\n if (bootstrap.postFetch.type === 'byCollection') {\n bootstrapMismatch = product.productType !== ProductType.Collection;\n referencedEntityId = bootstrap.postFetch.collectionId;\n }\n if (bootstrapMismatch) {\n this.log('warn', `Product type \"${product.productType}\" does not match URL \"${product.url}\" (${bootstrap.postFetch.type})`);\n }\n else if (referencedEntityId) {\n saveReferencedEntityId(referencedEntityId);\n }\n }\n else {\n this.log('error', `Product type is \"${product.productType}\" but could not create downloader from URL \"${product.url}\"`);\n }\n return;\n }\n this.log('debug', `Unknown product type \"${product.productType}\": no further action can be taken`);\n return;\n }\n\n #isFetchingMultipleProducts(productFetch: DownloaderConfig<Product>['productFetch']): productFetch is DownloaderConfig<Product>['productFetch'] & { type: 'byShop' } {\n return productFetch.type === 'byShop';\n }\n}\n"]}
1
+ {"version":3,"file":"ProductDownloader.js","sourceRoot":"","sources":["../../src/downloaders/ProductDownloader.ts"],"names":[],"mappings":"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","sourcesContent":["import ProductParser from '../parsers/ProductParser.js';\nimport URLHelper from '../utils/URLHelper.js';\nimport Downloader, { type DownloaderConfig, type DownloaderStartParams } from './Downloader.js';\nimport StatusCache from './cache/StatusCache.js';\nimport { generateProductSummary } from './templates/ProductInfo.js';\nimport path from 'path';\nimport { TargetSkipReason } from './DownloaderEvent.js';\nimport { ProductType, type Product } from '../entities/Product.js';\nimport { type Downloadable } from '../entities/Downloadable.js';\nimport Bootstrap from './Bootstrap.js';\nimport ProductsFetcher from './ProductsFetcher.js';\nimport { type ProductDirectories } from '../utils/FSHelper.js';\nimport { type DBInstance } from '../browse/db/index.js';\n\nexport default class ProductDownloader extends Downloader<Product> {\n\n static version = '1.0.1';\n\n name = 'ProductDownloader';\n\n #startPromise: Promise<void> | null = null;\n\n doStart(params?: DownloaderStartParams): Promise<void> {\n\n if (this.#startPromise) {\n throw Error('Downloader already running');\n }\n\n this.#startPromise = this.#doStart(params)\n .finally(() => {\n this.#startPromise = null;\n });\n\n return this.#startPromise;\n }\n\n async #doStart(params?: DownloaderStartParams): Promise<void> {\n try {\n const { signal } = params || {};\n const productFetch = this.config.productFetch;\n const db = await this.db();\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n if (productFetch.type === 'byShop') {\n this.log('info', `Targeting products by '${productFetch.vanity}'`);\n }\n else if (productFetch.type === 'byFile') {\n this.log('info', `Target product given by API data in \"${productFetch.filePath}\"`);\n }\n else {\n this.log('info', `Targeting product #${productFetch.productId}`);\n }\n\n // Step 1: get products (if by shop) or target product\n const productsFetcher = new ProductsFetcher({\n config: this.config,\n fetcher: this.fetcher,\n logger: this.logger,\n signal\n });\n productsFetcher.on('statusChange', ({current}) => {\n if (current.status === 'running') {\n this.emit('fetchBegin', { targetType: productsFetcher.getTargetType() });\n }\n });\n productsFetcher.begin();\n\n // Step 2: download products in each fetched list\n let downloaded = 0;\n let skippedUnviewable = 0;\n let skippedRedundant = 0;\n let skippedPublishDateOutOfRange = 0;\n let campaignSaved = false;\n let stopConditionMet = false;\n const productsParser = new ProductParser(this.logger);\n while (productsFetcher.hasNext()) {\n const { list, aborted, error } = await productsFetcher.next();\n if (!list || aborted) {\n break;\n }\n if (!list && error) {\n this.emit('end', { aborted: false, error, message: 'ProductsFetcher error' });\n return;\n }\n if (!campaignSaved && list.items[0]?.campaign) {\n await this.saveCampaignInfo(list.items[0].campaign, signal);\n campaignSaved = true;\n if (this.checkAbortSignal(signal)) {\n return;\n }\n }\n\n for (const _product of list.items) {\n\n if (stopConditionMet) {\n break;\n }\n\n let product = _product;\n\n if (this.#isFetchingMultipleProducts(productFetch)) {\n // Refresh to ensure media links have not expired\n this.log('debug', `Refresh product #${_product.id}`);\n const productURL = URLHelper.constructProductAPIURL(product.id);\n const { json } = await this.commonFetchAPI(productURL, signal);\n let refreshed: Product | null = null;\n if (json) {\n refreshed = productsParser.parseProductsAPIResponse(json, productURL).items[0] || null;\n if (!refreshed) {\n this.log('warn', `Refreshed product #${_product.id} but got empty value - going to use existing data`);\n }\n else if (refreshed.id !== _product.id) {\n this.log('warn', `Refreshed product #${_product.id} but ID mismatch - going to use existing data`);\n refreshed = null;\n }\n else {\n // Refreshed data does not have productType - reinstate it\n refreshed.productType = _product.productType;\n }\n }\n else if (this.checkAbortSignal(signal)) {\n return;\n }\n else {\n this.log('warn', `Failed to refresh product #${_product.id} - going to use existing data`);\n }\n if (refreshed) {\n this.log('debug', `Use refreshed product data #${refreshed.id}`);\n product = refreshed;\n }\n }\n\n this.emit('targetBegin', { target: product });\n\n // Step 4.1: product directories\n const productDirs = this.fsHelper.getProductDirs(product);\n this.log('debug', 'Product directories:', productDirs);\n\n // Step 4.2: Check with status cache\n const statusCache = StatusCache.getInstance(this.config, productDirs.statusCache, this.logger);\n if (!product.productType || product.productType === ProductType.DigitalCommerce) {\n const statusCacheValidation = statusCache.validate(product, productDirs.root, this.config)\n if (!statusCacheValidation.invalidated) {\n this.log('info', `Skipped downloading product #${product.id}: already downloaded`);\n this.emit('targetEnd', {\n target: product,\n isSkipped: true,\n skipReason: TargetSkipReason.AlreadyDownloaded,\n skipMessage: 'Target already downloaded'\n });\n skippedRedundant++;\n if (this.config.stopOn === 'previouslyDownloaded') {\n stopConditionMet = true;\n }\n continue;\n }\n }\n \n switch ((await this.#doDownload(\n product,\n productDirs,\n statusCache,\n db,\n signal\n )).status) {\n case 'aborted':\n return;\n case 'downloaded':\n downloaded++;\n break;\n case 'skippedPublishDateOutOfRange':\n skippedPublishDateOutOfRange++;\n if (this.config.stopOn === 'postPublishDateOutOfRange' ||\n this.config.stopOn === 'publishDateOutOfRange'\n ) {\n stopConditionMet = true;\n }\n break;\n case 'skippedUnviewable':\n skippedUnviewable++;\n break;\n }\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n }\n\n if (stopConditionMet) {\n break;\n }\n }\n\n if (this.checkAbortSignal(signal)) {\n return;\n }\n\n if (stopConditionMet && this.#isFetchingMultipleProducts(productFetch)) {\n this.log('info', `Stop downloader: stop condition \"${this.config.stopOn}\" met`)\n }\n\n // Done\n if (productFetch.type === 'byShop') {\n this.log('info', `Done downloading products by '${productFetch.vanity}'`);\n }\n else if (productFetch.type === 'byFile') {\n this.log('info', `Done downloading product given in \"${productFetch.filePath}\"`);\n }\n else {\n this.log('info', `Done downloading product #${productFetch.productId}`);\n }\n let endMessage = 'Done';\n if (this.#isFetchingMultipleProducts(productFetch)) {\n const skippedStrParts: string[] = [];\n if (skippedUnviewable) {\n skippedStrParts.push(`${skippedUnviewable} unviewable`);\n }\n if (skippedRedundant) {\n skippedStrParts.push(`${skippedRedundant} redundant`);\n }\n if (skippedPublishDateOutOfRange) {\n skippedStrParts.push(`${skippedPublishDateOutOfRange} with publish date out of range`);\n }\n const skippedStr = skippedStrParts.length > 0 ? ` (skipped: ${skippedStrParts.join(', ')})` : '';\n endMessage = `Total ${downloaded} / ${productsFetcher.getTotal()} products processed${skippedStr}`;\n this.log('info', endMessage);\n }\n this.emit('end', { aborted: false, message: endMessage });\n }\n finally {\n await this.closeDB();\n if (this.logger) {\n await this.logger.end();\n }\n }\n }\n\n async #doDownload(\n product: Product,\n productDirs: ProductDirectories,\n statusCache: StatusCache,\n db: DBInstance,\n signal?: AbortSignal\n ): Promise<{status: 'skippedUnviewable' | 'skippedPublishDateOutOfRange' | 'aborted' | 'downloaded' }> {\n // Step 1: Check whether we should download product\n // -- 1.1 Accessibility\n if (!product.isAccessible) {\n if (this.config.include.lockedContent) {\n this.log('warn', `Product #${product.id} is not accessible by current user`);\n }\n else {\n this.log('warn', `Skipped downloading product #${product.id}: not accessible by current user`);\n this.emit('targetEnd', {\n target: product,\n isSkipped: true,\n skipReason: TargetSkipReason.Inaccessible,\n skipMessage: 'Target is not accessible by current user'\n });\n return {\n status: 'skippedUnviewable'\n };\n }\n }\n // -- 1.4 Config option 'include.productsPublished'\n if (this.isPublishDateOutOfRange(product)) {\n return {\n status: 'skippedPublishDateOutOfRange'\n };\n }\n\n this.fsHelper.createDir(productDirs.root);\n\n // Step 2: save product info\n if (this.config.include.contentInfo) {\n this.log('info', 'Save product info');\n this.emit('phaseBegin', { target: product, phase: 'saveInfo' });\n this.fsHelper.createDir(productDirs.info);\n const summary = generateProductSummary(product);\n const summaryFile = path.resolve(productDirs.info, 'info.txt');\n const saveSummaryResult = await this.fsHelper.writeTextFile(summaryFile, summary, this.config.fileExistsAction.info);\n this.logWriteTextFileResult(saveSummaryResult, product, 'product summary');\n\n const productRawFile = path.resolve(productDirs.info, 'product-api.json');\n const saveProductRawResult = await this.fsHelper.writeTextFile(\n productRawFile, product.raw, this.config.fileExistsAction.infoAPI);\n this.logWriteTextFileResult(saveProductRawResult, product, 'product API data');\n this.emit('phaseEnd', { target: product, phase: 'saveInfo' });\n }\n\n // Step 3: Download product media items\n const incPreview = this.config.include.previewMedia;\n const incContent = this.config.include.contentMedia;\n this.log('info', 'Download:', {\n ['preview items']: incPreview === true ? 'yes' : incPreview === false ? 'no' : JSON.stringify(incPreview),\n ['content items']: incContent === true ? 'yes' : incContent === false ? 'no' : JSON.stringify(incContent)\n });\n\n const __inc = (inc: boolean | Array<any>, target: Downloadable) => {\n if (typeof inc === 'boolean') {\n return inc;\n }\n return (inc.includes(target.type as any));\n };\n\n const previewMedia = product.previewMedia.filter((tt) => __inc(incPreview, tt));\n const contentMedia = product.contentMedia.filter((tt) => __inc(incContent, tt));\n const campaignDir = product.campaign ? this.fsHelper.getCampaignDirs(product.campaign).root : null;\n\n if (this.config.include.previewMedia || this.config.include.contentMedia) {\n this.emit('phaseBegin', { target: product, phase: 'saveMedia' });\n const batchResult = await this.createDownloadTaskBatch(\n `Product #${product.id} (${product.name})`,\n signal,\n\n previewMedia.length > 0 ? {\n target: previewMedia,\n targetName: `product #${product.id} -> preview media`,\n src: product,\n dirs: {\n campaign: campaignDir,\n main: productDirs.previewMedia,\n thumbnails: productDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content\n } : null,\n\n contentMedia.length > 0 ? {\n target: contentMedia,\n targetName: `product #${product.id} -> content media`,\n src: product,\n dirs: {\n campaign: campaignDir,\n main: productDirs.contentMedia,\n thumbnails: productDirs.thumbnails\n },\n fileExistsAction: this.config.fileExistsAction.content,\n ignoreCreateTaskErrors: !product.isAccessible\n } : null\n );\n\n const { batch } = batchResult;\n\n const abortHandler = () => {\n void (async () => {\n this.log('info', 'Abort signal received');\n if (batch) {\n await batch.abort();\n }\n })();\n };\n if (signal) {\n signal.addEventListener('abort', abortHandler, { once: true });\n }\n \n try {\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n \n batch.prestart();\n this.log('info', `Download batch created (#${batch.id}): ${batch.getTasks('pending').length} downloads pending`);\n this.emit('phaseBegin', { target: product, phase: 'batchDownload', batch });\n\n await batch.start();\n\n // Step 4: Update status cache\n statusCache.updateOnDownload(product, productDirs.root, batch.getTasks('error').length > 0 || batchResult.errorCount > 0, this.config);\n\n await batch.destroy();\n }\n finally {\n if (signal) {\n signal.removeEventListener('abort', abortHandler);\n }\n }\n\n this.emit('phaseEnd', { target: product, phase: 'batchDownload' });\n this.emit('phaseEnd', { target: product, phase: 'saveMedia' });\n }\n\n if (this.checkAbortSignal(signal)) {\n return {\n status: 'aborted'\n };\n }\n\n // Step 5: Save to DB\n let skipDB = false;\n let saveReferencedEntityId: (id: string) => void;\n const dbProduct = db.getContent(product.id, 'product');\n if (!product.isAccessible) {\n // Skip if existing db record (if any) refers to accessible product\n skipDB = dbProduct !== null && dbProduct.isAccessible;\n }\n if (!skipDB) {\n db.saveContent(product);\n saveReferencedEntityId = (id) => {\n product.referencedEntityId = id;\n db.saveContent(product);\n };\n }\n else {\n this.log('info', `Skip overwrite existing accessible product #${product.id} in DB with current unviewable version`);\n saveReferencedEntityId = (id) => {\n // Ensure referencedEntityId is updated\n dbProduct!.referencedEntityId = id;\n db.saveContent(dbProduct!);\n };\n }\n\n // Step 6: check product type and download referenced product / collection\n await this.#processProductType(product, saveReferencedEntityId, signal);\n\n // Done\n this.log('info', `Done downloading product #${product.id}`);\n this.emit('targetEnd', { target: product, isSkipped: false });\n\n return {\n status: 'downloaded'\n }\n }\n\n // Carry out further action based on product type\n async #processProductType(\n product: Product,\n saveReferencedEntityId: (id: string) => void,\n signal?: AbortSignal\n ) {\n if (product.productType === undefined || product.productType === ProductType.DigitalCommerce) {\n this.log('debug', `Product type \"${product.productType}\": no further action required`);\n return;\n }\n if (product.productType === ProductType.Post || product.productType === ProductType.Collection) {\n const bootstrap = Bootstrap.getDownloaderBootstrapDataByURL(product.url);\n if (bootstrap?.type === 'post') {\n this.log('info', `Download ${product.productType} referenced by product: ${product.url}`);\n const PostDownloader = (await import('./PostDownloader.js')).default;\n const downloader = new PostDownloader(\n {\n ...this.config,\n ...bootstrap\n },\n this.db,\n this.logger,\n {\n skipSaveCampaign: true,\n keepLoggerOpen: true,\n keepDBOpen: true\n }\n );\n try {\n await downloader.start({ signal });\n this.log('info', `Done downloading ${product.productType} referenced by product`);\n }\n catch (error) {\n if (signal?.aborted) {\n throw error;\n }\n this.log('error', `Error downloading ${product.productType} referenced by product (url: ${product.url})`, error);\n }\n let referencedEntityId: string | undefined = undefined;\n let bootstrapMismatch = false;\n if (bootstrap.postFetch.type === 'single') {\n bootstrapMismatch = product.productType !== ProductType.Post;\n referencedEntityId = bootstrap.postFetch.postId;\n }\n if (bootstrap.postFetch.type === 'byCollection') {\n bootstrapMismatch = product.productType !== ProductType.Collection;\n referencedEntityId = bootstrap.postFetch.collectionId;\n }\n if (bootstrapMismatch) {\n this.log('warn', `Product type \"${product.productType}\" does not match URL \"${product.url}\" (${bootstrap.postFetch.type})`);\n }\n else if (referencedEntityId) {\n saveReferencedEntityId(referencedEntityId);\n }\n }\n else {\n this.log('error', `Product type is \"${product.productType}\" but could not create downloader from URL \"${product.url}\"`);\n }\n return;\n }\n this.log('debug', `Unknown product type \"${product.productType}\": no further action can be taken`);\n return;\n }\n\n #isFetchingMultipleProducts(productFetch: DownloaderConfig<Product>['productFetch']): productFetch is DownloaderConfig<Product>['productFetch'] & { type: 'byShop' } {\n return productFetch.type === 'byShop';\n }\n}\n"]}
@@ -11,12 +11,14 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
11
11
  };
12
12
  var _ProductsFetcher_instances, _ProductsFetcher_pointers, _ProductsFetcher_fetched, _ProductsFetcher_total, _ProductsFetcher_nextPromises, _ProductsFetcher_sleeper, _ProductsFetcher_noSleep, _ProductsFetcher_setStatus, _ProductsFetcher_isRunning, _ProductsFetcher_doBegin, _ProductsFetcher_handleError, _ProductsFetcher_isFetchingMultipleProducts, _ProductsFetcher_getInitialContext, _ProductsFetcher_fetchAPI;
13
13
  import EventEmitter from 'events';
14
+ import fse from 'fs-extra';
14
15
  import { commonLog } from '../utils/logging/Logger.js';
15
16
  import Downloader from './Downloader.js';
16
17
  import URLHelper from '../utils/URLHelper.js';
17
18
  import ProductParser from '../parsers/ProductParser.js';
18
19
  import Sleeper from '../utils/Sleeper.js';
19
20
  import { InitialData } from './InitialData.js';
21
+ import path from 'path';
20
22
  const SLEEPER_INTERVAL = 900000; // 15 mins
21
23
  class ProductsFetcher extends EventEmitter {
22
24
  constructor(params) {
@@ -187,37 +189,42 @@ _ProductsFetcher_pointers = new WeakMap(), _ProductsFetcher_fetched = new WeakMa
187
189
  __classPrivateFieldGet(this, _ProductsFetcher_instances, "m", _ProductsFetcher_setStatus).call(this, { status: 'running' });
188
190
  __classPrivateFieldGet(this, _ProductsFetcher_pointers, "f").fetching = 0;
189
191
  const productFetch = this.config.productFetch;
190
- let productsAPIURL;
191
- let campaign;
192
- let obtainCampaignFromProduct;
192
+ let ctx;
193
193
  try {
194
- const ctx = await __classPrivateFieldGet(this, _ProductsFetcher_instances, "m", _ProductsFetcher_getInitialContext).call(this);
195
- productsAPIURL = ctx.productsAPIURL;
196
- obtainCampaignFromProduct = ctx.campaign.obtainFromProduct;
197
- campaign = ctx.campaign.data;
194
+ ctx = await __classPrivateFieldGet(this, _ProductsFetcher_instances, "m", _ProductsFetcher_getInitialContext).call(this);
198
195
  }
199
196
  catch (error) {
200
197
  __classPrivateFieldGet(this, _ProductsFetcher_instances, "m", _ProductsFetcher_handleError).call(this, error);
201
198
  return;
202
199
  }
200
+ const obtainCampaignFromProduct = ctx.campaign.obtainFromProduct;
201
+ const campaign = ctx.campaign.data;
203
202
  if (__classPrivateFieldGet(this, _ProductsFetcher_instances, "m", _ProductsFetcher_isFetchingMultipleProducts).call(this, productFetch)) {
204
203
  this.log('info', 'Fetch products');
205
- this.log('debug', `Request initial products from API URL "${productsAPIURL}"`);
204
+ this.log('debug', `Request initial products from API URL "${ctx.src}"`);
205
+ }
206
+ else if (productFetch.type === 'byFile') {
207
+ this.log('info', `Read product data from "${ctx.src}"`);
206
208
  }
207
209
  else {
208
210
  this.log('info', 'Fetch target product');
209
- this.log('debug', `Request product #${productFetch.productId} from API URL "${productsAPIURL}`);
211
+ this.log('debug', `Request product #${productFetch.productId} from API URL "${ctx.src}`);
210
212
  }
211
213
  let json;
212
214
  try {
213
- json = await __classPrivateFieldGet(this, _ProductsFetcher_instances, "m", _ProductsFetcher_fetchAPI).call(this, productsAPIURL);
215
+ if (ctx.srcType === 'url') {
216
+ json = await __classPrivateFieldGet(this, _ProductsFetcher_instances, "m", _ProductsFetcher_fetchAPI).call(this, ctx.src);
217
+ }
218
+ else {
219
+ json = fse.readJsonSync(ctx.src);
220
+ }
214
221
  }
215
222
  catch (error) {
216
223
  __classPrivateFieldGet(this, _ProductsFetcher_instances, "m", _ProductsFetcher_handleError).call(this, error);
217
224
  return;
218
225
  }
219
226
  const productsParser = new ProductParser(this.logger);
220
- const list = productsParser.parseProductsAPIResponse(json, productsAPIURL, obtainCampaignFromProduct ? undefined : campaign);
227
+ const list = productsParser.parseProductsAPIResponse(json, ctx.src, obtainCampaignFromProduct ? undefined : campaign);
221
228
  __classPrivateFieldSet(this, _ProductsFetcher_fetched, [list], "f");
222
229
  __classPrivateFieldGet(this, _ProductsFetcher_pointers, "f").lastFetched = __classPrivateFieldGet(this, _ProductsFetcher_pointers, "f").fetching;
223
230
  __classPrivateFieldGet(this, _ProductsFetcher_pointers, "f").fetching = null;
@@ -297,7 +304,6 @@ _ProductsFetcher_pointers = new WeakMap(), _ProductsFetcher_fetched = new WeakMa
297
304
  return productFetch.type === 'byShop';
298
305
  }, _ProductsFetcher_getInitialContext = async function _ProductsFetcher_getInitialContext() {
299
306
  const productFetch = this.config.productFetch;
300
- let apiURL;
301
307
  switch (productFetch.type) {
302
308
  case 'byShop': {
303
309
  // Shop API does not return full campaign info (missing creator and rewards),
@@ -306,17 +312,28 @@ _ProductsFetcher_pointers = new WeakMap(), _ProductsFetcher_fetched = new WeakMa
306
312
  const { campaignId } = await this.getInitialData(initialDataPageURL);
307
313
  const campaign = await Downloader.getCampaign({ campaignId }, this.signal, this.config);
308
314
  return {
309
- productsAPIURL: URLHelper.constructShopAPIURL({ campaignId }),
315
+ src: URLHelper.constructShopAPIURL({ campaignId }),
316
+ srcType: 'url',
310
317
  campaign: {
311
318
  obtainFromProduct: false,
312
319
  data: campaign
313
320
  }
314
321
  };
315
322
  }
323
+ case 'byFile': {
324
+ return {
325
+ src: path.resolve(productFetch.filePath),
326
+ srcType: 'file',
327
+ campaign: {
328
+ obtainFromProduct: true,
329
+ data: null
330
+ }
331
+ };
332
+ }
316
333
  case 'single': {
317
- apiURL = URLHelper.constructProductAPIURL(productFetch.productId);
318
334
  return {
319
- productsAPIURL: apiURL,
335
+ src: URLHelper.constructProductAPIURL(productFetch.productId),
336
+ srcType: 'url',
320
337
  campaign: {
321
338
  obtainFromProduct: true,
322
339
  data: null
@@ -1 +1 @@
1
- {"version":3,"file":"ProductsFetcher.js","sourceRoot":"","sources":["../../src/downloaders/ProductsFetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import EventEmitter from 'events';\nimport { type Campaign, type Product } from '../entities/index.js';\nimport { type Logger } from '../utils/logging/index.js';\nimport { type LogLevel, commonLog } from '../utils/logging/Logger.js';\nimport Downloader, { type DownloaderConfig } from './Downloader.js';\nimport URLHelper from '../utils/URLHelper.js';\nimport type Fetcher from '../utils/Fetcher.js';\nimport ProductParser from '../parsers/ProductParser.js';\nimport { type ProductList } from '../entities/Product.js';\nimport Sleeper from '../utils/Sleeper.js';\nimport { InitialData } from './InitialData.js';\n\nexport type ProductsFetcherStatus = {\n status: 'ready' | 'running' | 'completed' | 'aborted';\n error?: undefined;\n} | {\n status: 'error';\n error: any;\n};\n\nexport type ProductsFetcherEvent = 'fetched' | 'statusChange';\nexport type ProductsFetcherEventPayload<T extends ProductsFetcherEvent> =\n T extends 'fetched' ? {\n list: ProductList;\n index: number;\n } :\n T extends 'statusChange' ? {\n current: ProductsFetcherStatus;\n old: ProductsFetcherStatus;\n } :\n never;\n\nexport interface ProductsFetcherResult {\n list: ProductList | null;\n error?: any;\n aborted: boolean;\n}\n\nconst SLEEPER_INTERVAL = 900000; // 15 mins\n\nexport default class ProductsFetcher extends EventEmitter {\n\n name = 'ProductsFetcher';\n\n protected status: ProductsFetcherStatus;\n protected config: DownloaderConfig<Product>;\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: ProductList[];\n #total: number | null;\n #nextPromises: Array<Promise<ProductsFetcherResult> | undefined>;\n #sleeper: Sleeper | null;\n #noSleep: boolean;\n\n constructor(params: {\n config: DownloaderConfig<Product>,\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.#isFetchingMultipleProducts(this.config.productFetch);\n }\n\n getTargetType() {\n return this.#isFetchingMultipleProducts(this.config.productFetch) ? 'products' : 'product';\n }\n\n protected log(level: LogLevel, ...msg: any[]) {\n commonLog(this.logger, level, this.name, ...msg);\n }\n\n #setStatus(status: ProductsFetcherStatus) {\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('ProductsFetcher already running or has ended');\n }\n\n this.#setStatus({ status: 'running' });\n\n this.#pointers.fetching = 0;\n const productFetch = this.config.productFetch;\n let productsAPIURL: string;\n let campaign: Campaign | null;\n let obtainCampaignFromProduct: boolean;\n try {\n const ctx = await this.#getInitialContext();\n productsAPIURL = ctx.productsAPIURL;\n obtainCampaignFromProduct = ctx.campaign.obtainFromProduct;\n campaign = ctx.campaign.data;\n }\n catch (error) {\n this.#handleError(error);\n return;\n }\n if (this.#isFetchingMultipleProducts(productFetch)) {\n this.log('info', 'Fetch products');\n this.log('debug', `Request initial products from API URL \"${productsAPIURL}\"`);\n }\n else {\n this.log('info', 'Fetch target product');\n this.log('debug', `Request product #${productFetch.productId} from API URL \"${productsAPIURL}`);\n }\n\n let json;\n try {\n json = await this.#fetchAPI(productsAPIURL);\n }\n catch (error) {\n this.#handleError(error);\n return;\n }\n\n const productsParser = new ProductParser(this.logger);\n const list = productsParser.parseProductsAPIResponse(\n json,\n productsAPIURL,\n obtainCampaignFromProduct ? undefined : campaign\n );\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.#isFetchingMultipleProducts(productFetch)) {\n let totalFetched = this.#fetched[0].items.length;\n this.log('info', `Fetched products: ${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 products - 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 products 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 = productsParser.parseProductsAPIResponse(json, nextURL);\n this.#fetched.push(list);\n const fetched = list.items.length;\n totalFetched += fetched;\n this.log('info', `Fetched products: ${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 products were not fetched. Total expected: ${total}; currently fetched: ${totalFetched}`);\n }\n else {\n this.log('info', `Done. ${totalFetched} products fetched`);\n }\n\n if (this.#isRunning()) {\n this.#setStatus({ status: 'completed' });\n }\n }\n }\n // Set 'completed' if not fetching multiple products\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 #isFetchingMultipleProducts(productFetch: DownloaderConfig<Product>['productFetch']): productFetch is DownloaderConfig<Product>['productFetch'] & { type: 'byShop' } {\n return productFetch.type === 'byShop';\n }\n\n async #getInitialContext() {\n const productFetch = this.config.productFetch;\n let apiURL: string;\n switch (productFetch.type) {\n case 'byShop': {\n // Shop API does not return full campaign info (missing creator and rewards),\n // so we fetch separately.\n const initialDataPageURL = URLHelper.constructCampaignPageURL({ vanity: productFetch.vanity });\n const { campaignId } = await this.getInitialData(initialDataPageURL);\n const campaign = await Downloader.getCampaign({ campaignId }, this.signal, this.config);\n return {\n productsAPIURL: URLHelper.constructShopAPIURL({ campaignId }),\n campaign: {\n obtainFromProduct: false as const,\n data: campaign\n }\n };\n }\n case 'single': {\n apiURL = URLHelper.constructProductAPIURL(productFetch.productId);\n return {\n productsAPIURL: apiURL,\n campaign: {\n obtainFromProduct: true as const,\n data: null\n }\n };\n }\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<ProductsFetcherResult> {\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: ProductsFetcherStatus) => {\n let list: ProductList | 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<ProductsFetcherResult>((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: ProductsFetcherStatus }) => {\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 ProductsFetcherEvent>(eventName: T, args: ProductsFetcherEventPayload<T>): boolean;\n emit(eventName: string | symbol, ...args: any[]): boolean {\n return super.emit(eventName, ...args);\n }\n\n on<T extends ProductsFetcherEvent>(eventName: T, listener: (args: ProductsFetcherEventPayload<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 ProductsFetcherEvent>(eventName: T, listener: (args: ProductsFetcherEventPayload<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":"ProductsFetcher.js","sourceRoot":"","sources":["../../src/downloaders/ProductsFetcher.ts"],"names":[],"mappings":"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","sourcesContent":["import EventEmitter from 'events';\nimport fse from 'fs-extra';\nimport { type Product } from '../entities/index.js';\nimport { type Logger } from '../utils/logging/index.js';\nimport { type LogLevel, commonLog } from '../utils/logging/Logger.js';\nimport Downloader, { type DownloaderConfig } from './Downloader.js';\nimport URLHelper from '../utils/URLHelper.js';\nimport type Fetcher from '../utils/Fetcher.js';\nimport ProductParser from '../parsers/ProductParser.js';\nimport { type ProductList } from '../entities/Product.js';\nimport Sleeper from '../utils/Sleeper.js';\nimport { InitialData } from './InitialData.js';\nimport path from 'path';\n\nexport type ProductsFetcherStatus = {\n status: 'ready' | 'running' | 'completed' | 'aborted';\n error?: undefined;\n} | {\n status: 'error';\n error: any;\n};\n\nexport type ProductsFetcherEvent = 'fetched' | 'statusChange';\nexport type ProductsFetcherEventPayload<T extends ProductsFetcherEvent> =\n T extends 'fetched' ? {\n list: ProductList;\n index: number;\n } :\n T extends 'statusChange' ? {\n current: ProductsFetcherStatus;\n old: ProductsFetcherStatus;\n } :\n never;\n\nexport interface ProductsFetcherResult {\n list: ProductList | null;\n error?: any;\n aborted: boolean;\n}\n\nconst SLEEPER_INTERVAL = 900000; // 15 mins\n\nexport default class ProductsFetcher extends EventEmitter {\n\n name = 'ProductsFetcher';\n\n protected status: ProductsFetcherStatus;\n protected config: DownloaderConfig<Product>;\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: ProductList[];\n #total: number | null;\n #nextPromises: Array<Promise<ProductsFetcherResult> | undefined>;\n #sleeper: Sleeper | null;\n #noSleep: boolean;\n\n constructor(params: {\n config: DownloaderConfig<Product>,\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.#isFetchingMultipleProducts(this.config.productFetch);\n }\n\n getTargetType() {\n return this.#isFetchingMultipleProducts(this.config.productFetch) ? 'products' : 'product';\n }\n\n protected log(level: LogLevel, ...msg: any[]) {\n commonLog(this.logger, level, this.name, ...msg);\n }\n\n #setStatus(status: ProductsFetcherStatus) {\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('ProductsFetcher already running or has ended');\n }\n\n this.#setStatus({ status: 'running' });\n\n this.#pointers.fetching = 0;\n const productFetch = this.config.productFetch;\n let ctx;\n try {\n ctx = await this.#getInitialContext();\n }\n catch (error) {\n this.#handleError(error);\n return;\n }\n const obtainCampaignFromProduct = ctx.campaign.obtainFromProduct;\n const campaign = ctx.campaign.data;\n if (this.#isFetchingMultipleProducts(productFetch)) {\n this.log('info', 'Fetch products');\n this.log('debug', `Request initial products from API URL \"${ctx.src}\"`);\n }\n else if (productFetch.type === 'byFile') {\n this.log('info', `Read product data from \"${ctx.src}\"`);\n }\n else {\n this.log('info', 'Fetch target product');\n this.log('debug', `Request product #${productFetch.productId} from API URL \"${ctx.src}`);\n }\n\n let json;\n try {\n if (ctx.srcType === 'url') {\n json = await this.#fetchAPI(ctx.src);\n }\n else {\n json = fse.readJsonSync(ctx.src);\n }\n }\n catch (error) {\n this.#handleError(error);\n return;\n }\n\n const productsParser = new ProductParser(this.logger);\n const list = productsParser.parseProductsAPIResponse(\n json,\n ctx.src,\n obtainCampaignFromProduct ? undefined : campaign\n );\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.#isFetchingMultipleProducts(productFetch)) {\n let totalFetched = this.#fetched[0].items.length;\n this.log('info', `Fetched products: ${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 products - 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 products 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 = productsParser.parseProductsAPIResponse(json, nextURL);\n this.#fetched.push(list);\n const fetched = list.items.length;\n totalFetched += fetched;\n this.log('info', `Fetched products: ${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 products were not fetched. Total expected: ${total}; currently fetched: ${totalFetched}`);\n }\n else {\n this.log('info', `Done. ${totalFetched} products fetched`);\n }\n\n if (this.#isRunning()) {\n this.#setStatus({ status: 'completed' });\n }\n }\n }\n // Set 'completed' if not fetching multiple products\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 #isFetchingMultipleProducts(productFetch: DownloaderConfig<Product>['productFetch']): productFetch is DownloaderConfig<Product>['productFetch'] & { type: 'byShop' } {\n return productFetch.type === 'byShop';\n }\n\n async #getInitialContext() {\n const productFetch = this.config.productFetch;\n switch (productFetch.type) {\n case 'byShop': {\n // Shop API does not return full campaign info (missing creator and rewards),\n // so we fetch separately.\n const initialDataPageURL = URLHelper.constructCampaignPageURL({ vanity: productFetch.vanity });\n const { campaignId } = await this.getInitialData(initialDataPageURL);\n const campaign = await Downloader.getCampaign({ campaignId }, this.signal, this.config);\n return {\n src: URLHelper.constructShopAPIURL({ campaignId }),\n srcType: 'url' as const,\n campaign: {\n obtainFromProduct: false as const,\n data: campaign\n }\n };\n }\n case 'byFile': {\n return {\n src: path.resolve(productFetch.filePath),\n srcType: 'file' as const,\n campaign: {\n obtainFromProduct: true as const,\n data: null\n }\n };\n }\n case 'single': {\n return {\n src: URLHelper.constructProductAPIURL(productFetch.productId),\n srcType: 'url' as const,\n campaign: {\n obtainFromProduct: true as const,\n data: null\n }\n };\n }\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<ProductsFetcherResult> {\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: ProductsFetcherStatus) => {\n let list: ProductList | 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<ProductsFetcherResult>((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: ProductsFetcherStatus }) => {\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 ProductsFetcherEvent>(eventName: T, args: ProductsFetcherEventPayload<T>): boolean;\n emit(eventName: string | symbol, ...args: any[]): boolean {\n return super.emit(eventName, ...args);\n }\n\n on<T extends ProductsFetcherEvent>(eventName: T, listener: (args: ProductsFetcherEventPayload<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 ProductsFetcherEvent>(eventName: T, listener: (args: ProductsFetcherEventPayload<T>) => void): this;\n off(eventName: string | symbol, listener: (...args: any[]) => void): this {\n return super.off(eventName, listener);\n }\n}\n"]}
@@ -6,6 +6,9 @@ import { type EmbedDownloader, type FileExistsAction } from '../DownloaderOption
6
6
  import type Logger from '../../utils/logging/Logger.js';
7
7
  import { type DownloaderConfig } from '../Downloader.js';
8
8
  import type Bottleneck from 'bottleneck';
9
+ import { type Collection, type Post } from '../../entities/Post.js';
10
+ import { type Product } from '../../entities/Product.js';
11
+ import { type Campaign } from '../../entities/Campaign.js';
9
12
  export default class DownloadTaskFactory {
10
13
  #private;
11
14
  static createFromDownloadable(params: {
@@ -16,6 +19,7 @@ export default class DownloadTaskFactory {
16
19
  thumbnails: string | null;
17
20
  };
18
21
  item: Downloadable;
22
+ src: Post | Product | Campaign | Collection;
19
23
  isAttachment?: boolean;
20
24
  fetcher: Fetcher;
21
25
  fileExistsAction: FileExistsAction;
@@ -55,7 +55,7 @@ const COLLECTION_THUMBNAIL_URL_PRIORITY = [
55
55
  const NULL_VARIANT = '/*NULL*/';
56
56
  class DownloadTaskFactory {
57
57
  static async createFromDownloadable(params) {
58
- const { config, dirs, item, isAttachment = false, fetcher, fileExistsAction, callbacks, limiter, signal, logger } = params;
58
+ const { config, dirs, item, src, isAttachment = false, fetcher, fileExistsAction, callbacks, limiter, signal, logger } = params;
59
59
  const embedDownloaders = config.embedDownloaders;
60
60
  const destFilenameFormat = config.filenameFormat.media;
61
61
  const downloadAllVariants = config.include.allMediaVariants;
@@ -88,7 +88,7 @@ class DownloadTaskFactory {
88
88
  const srcURLs = __classPrivateFieldGet(this, _a, "m", _DownloadTaskFactory_getSrcURLs).call(this, item, downloadAllVariants);
89
89
  const urlToTasks = [];
90
90
  for (const [variant, url] of Object.entries(srcURLs)) {
91
- const destFilenameResolver = new MediaFilenameResolver(item, url, destFilenameFormat, variant !== NULL_VARIANT ? variant : null, downloadAllVariants);
91
+ const destFilenameResolver = new MediaFilenameResolver(item, url, src, destFilenameFormat, variant !== NULL_VARIANT ? variant : null, downloadAllVariants);
92
92
  if (signal?.aborted) {
93
93
  return tasks;
94
94
  }
@@ -162,6 +162,7 @@ class DownloadTaskFactory {
162
162
  config: __config,
163
163
  dirs,
164
164
  item: videoThumbnailMediaItem,
165
+ src,
165
166
  fetcher,
166
167
  fileExistsAction,
167
168
  callbacks,
@@ -1 +1 @@
1
- {"version":3,"file":"DownloadTaskFactory.js","sourceRoot":"","sources":["../../../src/downloaders/task/DownloadTaskFactory.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\nimport { type DummyMediaItem } from '../../entities/MediaItem.js';\nimport type Fetcher from '../../utils/Fetcher.js';\nimport MediaFilenameResolver from '../../utils/MediaFilenameResolver.js';\nimport {type DownloadTaskCallbacks} from './DownloadTask.js';\nimport DownloadTask from './DownloadTask.js';\nimport FetcherDownloadTask from './FetcherDownloadTask.js';\nimport { type Downloadable, isDownloadableWithThumbnail, isEmbed, isYouTubeEmbed } from '../../entities/Downloadable.js';\nimport { type EmbedDownloader, type FileExistsAction } from '../DownloaderOptions.js';\nimport type Logger from '../../utils/logging/Logger.js';\nimport YouTubeDownloadTask from './YouTubeDownloadTask.js';\nimport ExternalDownloaderTask from './ExternalDownloaderTask.js';\nimport { type DownloaderConfig } from '../Downloader.js';\nimport type Bottleneck from 'bottleneck';\nimport ThumbnailFilenameResolver from '../../utils/ThmbnailFilenameResolver.js';\n\nconst DEFAULT_IMAGE_URL_PRIORITY = [\n 'original',\n 'default',\n 'download',\n 'defaultSmall',\n 'thumbnailLarge',\n 'thumbnail',\n 'thumbnailSmall'\n];\n\nconst CAMPAIGN_COVER_PHOTO_URL_PRIORITY = [\n 'xlarge',\n 'large',\n 'medium',\n 'small',\n 'xsmall'\n];\n\nconst POST_COVER_IMAGE_URL_PRIORITY = [\n 'large',\n 'default',\n 'thumb',\n 'thumbSquareLarge',\n 'thumbSquare'\n];\n\nconst POST_THUMBNAIL_URL_PRIORITY = [\n 'large2',\n 'default',\n 'large',\n 'square'\n];\n\nconst COLLECTION_THUMBNAIL_URL_PRIORITY = [\n 'original',\n 'defaultLarge',\n 'default',\n 'url',\n 'defaultSmall',\n 'defaultBlurred',\n 'thumbnailLarge',\n 'thumbnail',\n 'thumbnailSmall'\n];\n\nconst NULL_VARIANT = '/*NULL*/';\n\nexport default class DownloadTaskFactory {\n\n static #getSrcURLs(item: Downloadable, allVariants: boolean) {\n if (item.type === 'image') {\n let urls: Record<string, string | null> = {};\n let priority: string[] = [];\n switch (item.imageType) {\n case 'single':\n return {\n [NULL_VARIANT]: item.imageURL\n };\n case 'default':\n urls = {\n ...item.imageURLs,\n download: item.downloadURL\n };\n priority = DEFAULT_IMAGE_URL_PRIORITY;\n break;\n case 'campaignCoverPhoto':\n urls = item.imageURLs;\n priority = CAMPAIGN_COVER_PHOTO_URL_PRIORITY;\n break;\n case 'postCoverImage':\n urls = item.imageURLs;\n priority = POST_COVER_IMAGE_URL_PRIORITY;\n break;\n case 'postThumbnail':\n urls = item.imageURLs;\n priority = POST_THUMBNAIL_URL_PRIORITY;\n break;\n case 'collectionThumbnail':\n urls = item.imageURLs;\n priority = COLLECTION_THUMBNAIL_URL_PRIORITY;\n }\n if (allVariants) {\n return urls;\n }\n return this.#pickVariant(urls, priority);\n }\n else if (item.type === 'video') {\n let videoVariantName = 'display';\n if (item.size.width && item.size.height) {\n videoVariantName = `${item.size.width}x${item.size.height}`;\n }\n const urls = {\n download: item.downloadURL,\n [videoVariantName]: item.displayURL\n };\n if (allVariants) {\n return urls;\n }\n const priority = [ 'download', videoVariantName ];\n return this.#pickVariant(urls, priority);\n }\n else if (item.type === 'audio') {\n return {\n [NULL_VARIANT]: item.url\n };\n }\n else if (item.type === 'file') {\n return {\n [NULL_VARIANT]: item.downloadURL\n };\n }\n else if (item.type === 'dummy') {\n return item.srcURLs;\n }\n else if (item.type === 'attachment') {\n return {\n [NULL_VARIANT]: item.downloadURL\n };\n }\n\n return {};\n }\n\n static async createFromDownloadable(params: {\n config: DownloaderConfig<any>,\n dirs: {\n campaign: string | null;\n main: string;\n thumbnails: string | null;\n },\n item: Downloadable,\n isAttachment?: boolean,\n fetcher: Fetcher,\n fileExistsAction: FileExistsAction,\n callbacks?: DownloadTaskCallbacks | null,\n limiter: Bottleneck,\n signal?: AbortSignal,\n logger?: Logger | null;\n }) {\n\n const {\n config,\n dirs,\n item,\n isAttachment = false,\n fetcher,\n fileExistsAction,\n callbacks,\n limiter,\n signal,\n logger\n } = params;\n const embedDownloaders = config.embedDownloaders;\n const destFilenameFormat = config.filenameFormat.media;\n const downloadAllVariants = config.include.allMediaVariants;\n const tasks: DownloadTask[] = [];\n\n if (isEmbed(item)) {\n // Check if external downloader configured for embed item\n const embedDownloader = this.findEmbedDownloader(embedDownloaders, item.provider);\n if (embedDownloader) {\n const task = ExternalDownloaderTask.fromEmbedDownloader(config, embedDownloader, item, dirs.main, callbacks || null, logger);\n if (task) {\n tasks.push(task);\n }\n }\n // Use our own implementation if no external downloader configured for YT embeds\n else if (isYouTubeEmbed(item) && item.url) {\n tasks.push(await DownloadTask.create(YouTubeDownloadTask, {\n downloadType: 'main',\n config,\n src: item.url,\n destDir: dirs.main,\n fileExistsAction,\n srcEntity: item,\n fetcher,\n callbacks: callbacks || null,\n logger\n },\n limiter,\n signal));\n }\n }\n else {\n const srcURLs = this.#getSrcURLs(item, downloadAllVariants);\n const urlToTasks: DownloadTask[] = [];\n for (const [ variant, url ] of Object.entries(srcURLs)) {\n const destFilenameResolver = \n new MediaFilenameResolver(item, url, destFilenameFormat,\n variant !== NULL_VARIANT ? variant : null, downloadAllVariants);\n\n if (signal?.aborted) {\n return tasks;\n }\n\n if (url) {\n urlToTasks.push(await DownloadTask.create(FetcherDownloadTask, {\n downloadType: 'variant',\n config,\n fetcher,\n src: url,\n destDir: dirs.main,\n destFilenameResolver,\n fileExistsAction,\n isAttachment,\n srcEntity: item,\n callbacks: callbacks || null,\n logger\n },\n limiter,\n signal));\n }\n }\n if (urlToTasks.length > 0) {\n urlToTasks[0].downloadType = 'main';\n }\n tasks.push(...urlToTasks);\n }\n\n if (config.include.mediaThumbnails && dirs.thumbnails && isDownloadableWithThumbnail(item)) {\n const thumbnailURL = item.thumbnailURL;\n // Thumbnails in `dirs.thumbnails` are for browse function, so\n // no need to follow config's FileExistsAction.\n const fse: FileExistsAction = 'overwrite';\n // Same with FilenameResolver\n const fnr = new ThumbnailFilenameResolver(item);\n tasks.push(await DownloadTask.create(FetcherDownloadTask, {\n downloadType: 'thumbnail',\n config,\n fetcher,\n src: thumbnailURL,\n destDir: dirs.thumbnails,\n destFilenameResolver: fnr,\n fileExistsAction: fse,\n srcEntity: item,\n callbacks: callbacks || null,\n logger\n },\n limiter,\n signal));\n }\n \n // Create a DownloadTask backed by a DummyMediaItem for video thumbnail.\n // Note this is saved in the same dir as the video itself, unlike thumbnails for browse function,\n // so need to follow config's FileExistsAction and filename format.\n if (item.type === 'video' && item.thumbnailURL) {\n let filename: string | null = null;\n if (item.filename) {\n // Video file extension not applicable to thumbnail, so strip it.\n filename = path.parse(item.filename).name;\n }\n const videoThumbnailMediaItem: DummyMediaItem = {\n type: 'dummy',\n id: item.id,\n filename,\n mimeType: null,\n srcURLs: {\n thumbnail: item.thumbnailURL\n }\n };\n const __config = {\n ...config,\n include: {\n ...config.include,\n allMediaVariants: true // Ensure variant name ('thumbnail') appears in dest filename\n }\n };\n tasks.push(\n ...await this.createFromDownloadable({\n config: __config,\n dirs,\n item: videoThumbnailMediaItem,\n fetcher,\n fileExistsAction,\n callbacks,\n limiter,\n signal,\n logger\n })\n );\n }\n\n if (tasks.length === 0) {\n throw Error('No src URL found');\n }\n\n return tasks;\n }\n\n static #pickVariant(urls: Record<string, any>, priority: string[]) {\n for (const variant of priority) {\n if (urls[variant]) {\n return {\n [variant]: urls[variant]\n };\n }\n }\n return {};\n }\n\n static findEmbedDownloader(edl: EmbedDownloader[], provider?: string | null) {\n return edl.find((dl) => dl.provider.toLowerCase() === provider?.trim().toLowerCase());\n }\n}\n"]}
1
+ {"version":3,"file":"DownloadTaskFactory.js","sourceRoot":"","sources":["../../../src/downloaders/task/DownloadTaskFactory.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\nimport { type DummyMediaItem } from '../../entities/MediaItem.js';\nimport type Fetcher from '../../utils/Fetcher.js';\nimport MediaFilenameResolver from '../../utils/MediaFilenameResolver.js';\nimport {type DownloadTaskCallbacks} from './DownloadTask.js';\nimport DownloadTask from './DownloadTask.js';\nimport FetcherDownloadTask from './FetcherDownloadTask.js';\nimport { type Downloadable, isDownloadableWithThumbnail, isEmbed, isYouTubeEmbed } from '../../entities/Downloadable.js';\nimport { type EmbedDownloader, type FileExistsAction } from '../DownloaderOptions.js';\nimport type Logger from '../../utils/logging/Logger.js';\nimport YouTubeDownloadTask from './YouTubeDownloadTask.js';\nimport ExternalDownloaderTask from './ExternalDownloaderTask.js';\nimport { type DownloaderConfig } from '../Downloader.js';\nimport type Bottleneck from 'bottleneck';\nimport ThumbnailFilenameResolver from '../../utils/ThmbnailFilenameResolver.js';\nimport { type Collection, type Post } from '../../entities/Post.js';\nimport { type Product } from '../../entities/Product.js';\nimport { type Campaign } from '../../entities/Campaign.js';\n\nconst DEFAULT_IMAGE_URL_PRIORITY = [\n 'original',\n 'default',\n 'download',\n 'defaultSmall',\n 'thumbnailLarge',\n 'thumbnail',\n 'thumbnailSmall'\n];\n\nconst CAMPAIGN_COVER_PHOTO_URL_PRIORITY = [\n 'xlarge',\n 'large',\n 'medium',\n 'small',\n 'xsmall'\n];\n\nconst POST_COVER_IMAGE_URL_PRIORITY = [\n 'large',\n 'default',\n 'thumb',\n 'thumbSquareLarge',\n 'thumbSquare'\n];\n\nconst POST_THUMBNAIL_URL_PRIORITY = [\n 'large2',\n 'default',\n 'large',\n 'square'\n];\n\nconst COLLECTION_THUMBNAIL_URL_PRIORITY = [\n 'original',\n 'defaultLarge',\n 'default',\n 'url',\n 'defaultSmall',\n 'defaultBlurred',\n 'thumbnailLarge',\n 'thumbnail',\n 'thumbnailSmall'\n];\n\nconst NULL_VARIANT = '/*NULL*/';\n\nexport default class DownloadTaskFactory {\n\n static #getSrcURLs(item: Downloadable, allVariants: boolean) {\n if (item.type === 'image') {\n let urls: Record<string, string | null> = {};\n let priority: string[] = [];\n switch (item.imageType) {\n case 'single':\n return {\n [NULL_VARIANT]: item.imageURL\n };\n case 'default':\n urls = {\n ...item.imageURLs,\n download: item.downloadURL\n };\n priority = DEFAULT_IMAGE_URL_PRIORITY;\n break;\n case 'campaignCoverPhoto':\n urls = item.imageURLs;\n priority = CAMPAIGN_COVER_PHOTO_URL_PRIORITY;\n break;\n case 'postCoverImage':\n urls = item.imageURLs;\n priority = POST_COVER_IMAGE_URL_PRIORITY;\n break;\n case 'postThumbnail':\n urls = item.imageURLs;\n priority = POST_THUMBNAIL_URL_PRIORITY;\n break;\n case 'collectionThumbnail':\n urls = item.imageURLs;\n priority = COLLECTION_THUMBNAIL_URL_PRIORITY;\n }\n if (allVariants) {\n return urls;\n }\n return this.#pickVariant(urls, priority);\n }\n else if (item.type === 'video') {\n let videoVariantName = 'display';\n if (item.size.width && item.size.height) {\n videoVariantName = `${item.size.width}x${item.size.height}`;\n }\n const urls = {\n download: item.downloadURL,\n [videoVariantName]: item.displayURL\n };\n if (allVariants) {\n return urls;\n }\n const priority = [ 'download', videoVariantName ];\n return this.#pickVariant(urls, priority);\n }\n else if (item.type === 'audio') {\n return {\n [NULL_VARIANT]: item.url\n };\n }\n else if (item.type === 'file') {\n return {\n [NULL_VARIANT]: item.downloadURL\n };\n }\n else if (item.type === 'dummy') {\n return item.srcURLs;\n }\n else if (item.type === 'attachment') {\n return {\n [NULL_VARIANT]: item.downloadURL\n };\n }\n\n return {};\n }\n\n static async createFromDownloadable(params: {\n config: DownloaderConfig<any>,\n dirs: {\n campaign: string | null;\n main: string;\n thumbnails: string | null;\n },\n item: Downloadable,\n src: Post | Product | Campaign | Collection,\n isAttachment?: boolean,\n fetcher: Fetcher,\n fileExistsAction: FileExistsAction,\n callbacks?: DownloadTaskCallbacks | null,\n limiter: Bottleneck,\n signal?: AbortSignal,\n logger?: Logger | null;\n }) {\n\n const {\n config,\n dirs,\n item,\n src,\n isAttachment = false,\n fetcher,\n fileExistsAction,\n callbacks,\n limiter,\n signal,\n logger\n } = params;\n const embedDownloaders = config.embedDownloaders;\n const destFilenameFormat = config.filenameFormat.media;\n const downloadAllVariants = config.include.allMediaVariants;\n const tasks: DownloadTask[] = [];\n\n if (isEmbed(item)) {\n // Check if external downloader configured for embed item\n const embedDownloader = this.findEmbedDownloader(embedDownloaders, item.provider);\n if (embedDownloader) {\n const task = ExternalDownloaderTask.fromEmbedDownloader(config, embedDownloader, item, dirs.main, callbacks || null, logger);\n if (task) {\n tasks.push(task);\n }\n }\n // Use our own implementation if no external downloader configured for YT embeds\n else if (isYouTubeEmbed(item) && item.url) {\n tasks.push(await DownloadTask.create(YouTubeDownloadTask, {\n downloadType: 'main',\n config,\n src: item.url,\n destDir: dirs.main,\n fileExistsAction,\n srcEntity: item,\n fetcher,\n callbacks: callbacks || null,\n logger\n },\n limiter,\n signal));\n }\n }\n else {\n const srcURLs = this.#getSrcURLs(item, downloadAllVariants);\n const urlToTasks: DownloadTask[] = [];\n for (const [ variant, url ] of Object.entries(srcURLs)) {\n const destFilenameResolver = \n new MediaFilenameResolver(item, url, src, destFilenameFormat,\n variant !== NULL_VARIANT ? variant : null, downloadAllVariants);\n\n if (signal?.aborted) {\n return tasks;\n }\n\n if (url) {\n urlToTasks.push(await DownloadTask.create(FetcherDownloadTask, {\n downloadType: 'variant',\n config,\n fetcher,\n src: url,\n destDir: dirs.main,\n destFilenameResolver,\n fileExistsAction,\n isAttachment,\n srcEntity: item,\n callbacks: callbacks || null,\n logger\n },\n limiter,\n signal));\n }\n }\n if (urlToTasks.length > 0) {\n urlToTasks[0].downloadType = 'main';\n }\n tasks.push(...urlToTasks);\n }\n\n if (config.include.mediaThumbnails && dirs.thumbnails && isDownloadableWithThumbnail(item)) {\n const thumbnailURL = item.thumbnailURL;\n // Thumbnails in `dirs.thumbnails` are for browse function, so\n // no need to follow config's FileExistsAction.\n const fse: FileExistsAction = 'overwrite';\n // Same with FilenameResolver\n const fnr = new ThumbnailFilenameResolver(item);\n tasks.push(await DownloadTask.create(FetcherDownloadTask, {\n downloadType: 'thumbnail',\n config,\n fetcher,\n src: thumbnailURL,\n destDir: dirs.thumbnails,\n destFilenameResolver: fnr,\n fileExistsAction: fse,\n srcEntity: item,\n callbacks: callbacks || null,\n logger\n },\n limiter,\n signal));\n }\n \n // Create a DownloadTask backed by a DummyMediaItem for video thumbnail.\n // Note this is saved in the same dir as the video itself, unlike thumbnails for browse function,\n // so need to follow config's FileExistsAction and filename format.\n if (item.type === 'video' && item.thumbnailURL) {\n let filename: string | null = null;\n if (item.filename) {\n // Video file extension not applicable to thumbnail, so strip it.\n filename = path.parse(item.filename).name;\n }\n const videoThumbnailMediaItem: DummyMediaItem = {\n type: 'dummy',\n id: item.id,\n filename,\n mimeType: null,\n srcURLs: {\n thumbnail: item.thumbnailURL\n }\n };\n const __config = {\n ...config,\n include: {\n ...config.include,\n allMediaVariants: true // Ensure variant name ('thumbnail') appears in dest filename\n }\n };\n tasks.push(\n ...await this.createFromDownloadable({\n config: __config,\n dirs,\n item: videoThumbnailMediaItem,\n src,\n fetcher,\n fileExistsAction,\n callbacks,\n limiter,\n signal,\n logger\n })\n );\n }\n\n if (tasks.length === 0) {\n throw Error('No src URL found');\n }\n\n return tasks;\n }\n\n static #pickVariant(urls: Record<string, any>, priority: string[]) {\n for (const variant of priority) {\n if (urls[variant]) {\n return {\n [variant]: urls[variant]\n };\n }\n }\n return {};\n }\n\n static findEmbedDownloader(edl: EmbedDownloader[], provider?: string | null) {\n return edl.find((dl) => dl.provider.toLowerCase() === provider?.trim().toLowerCase());\n }\n}\n"]}
@@ -225,8 +225,11 @@ class YouTubeDownloadTask extends FFmpegDownloadTaskBase {
225
225
  this.log('debug', `Choose best-quality stream for YouTube video #${video.basic_info.id}`);
226
226
  const stream = await __classPrivateFieldGet(this, _YouTubeDownloadTask_instances, "m", _YouTubeDownloadTask_pickStream).call(this, video);
227
227
  if (!stream) {
228
- const errMsg = `Stream not found for YouTube video #${video.basic_info.id}`;
228
+ const errMsg = `Stream not found for YouTube video #${video.basic_info.id || videoId}`;
229
229
  this.log('error', errMsg);
230
+ if (video.playability_status) {
231
+ this.log('error', `The playability status of the video is: ${video.playability_status.status} - ${video.playability_status.reason}`);
232
+ }
230
233
  throw Error(errMsg);
231
234
  }
232
235
  // Test streams - YT sometimes imposes a delay before the streams become accessible
@@ -318,7 +321,9 @@ _a = YouTubeDownloadTask, _YouTubeDownloadTask_destDir = new WeakMap(), _YouTube
318
321
  return (await InnertubeLoader.getInstance(this.config)).getVideoInfo(videoId);
319
322
  }, _YouTubeDownloadTask_resolveURL = async function _YouTubeDownloadTask_resolveURL(url) {
320
323
  if (!__classPrivateFieldGet(_a, _a, "f", _YouTubeDownloadTask_innertubeForResolveURL)) {
321
- __classPrivateFieldSet(_a, _a, await InnertubeLib.Innertube.create(), "f", _YouTubeDownloadTask_innertubeForResolveURL);
324
+ __classPrivateFieldSet(_a, _a, await InnertubeLib.Innertube.create({
325
+ player_id: '9f4cc5e4'
326
+ }), "f", _YouTubeDownloadTask_innertubeForResolveURL);
322
327
  }
323
328
  const innertube = __classPrivateFieldGet(_a, _a, "f", _YouTubeDownloadTask_innertubeForResolveURL);
324
329
  const endpoint = await innertube.resolveURL(url);