patreon-dl 3.3.1 → 3.5.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 (146) hide show
  1. package/README.md +48 -4
  2. package/dist/browse/api/CampaignAPIMixin.d.ts +1 -1
  3. package/dist/browse/api/ContentAPIMixin.d.ts +8 -2
  4. package/dist/browse/api/ContentAPIMixin.js +20 -0
  5. package/dist/browse/api/ContentAPIMixin.js.map +1 -1
  6. package/dist/browse/api/FilterAPIMixin.d.ts +1 -1
  7. package/dist/browse/api/FilterAPIMixin.js +29 -2
  8. package/dist/browse/api/FilterAPIMixin.js.map +1 -1
  9. package/dist/browse/api/index.d.ts +18 -6
  10. package/dist/browse/db/CampaignDBMixin.d.ts +3 -3
  11. package/dist/browse/db/CampaignDBMixin.js +13 -1
  12. package/dist/browse/db/CampaignDBMixin.js.map +1 -1
  13. package/dist/browse/db/CollectionFTS.d.ts +2 -0
  14. package/dist/browse/db/CollectionFTS.js +68 -0
  15. package/dist/browse/db/CollectionFTS.js.map +1 -0
  16. package/dist/browse/db/ContentDBMixin.d.ts +25 -12
  17. package/dist/browse/db/ContentDBMixin.js +412 -15
  18. package/dist/browse/db/ContentDBMixin.js.map +1 -1
  19. package/dist/browse/db/Init.js +63 -5
  20. package/dist/browse/db/Init.js.map +1 -1
  21. package/dist/browse/db/MediaDBMixin.js +2 -6
  22. package/dist/browse/db/MediaDBMixin.js.map +1 -1
  23. package/dist/browse/db/PostFTS.d.ts +4 -0
  24. package/dist/browse/db/PostFTS.js +163 -0
  25. package/dist/browse/db/PostFTS.js.map +1 -0
  26. package/dist/browse/db/ProductFTS.d.ts +4 -0
  27. package/dist/browse/db/ProductFTS.js +163 -0
  28. package/dist/browse/db/ProductFTS.js.map +1 -0
  29. package/dist/browse/db/Update.js +3 -1
  30. package/dist/browse/db/Update.js.map +1 -1
  31. package/dist/browse/db/index.d.ts +26 -14
  32. package/dist/browse/db/updaters/DBUpdater_1_2_0.d.ts +2 -0
  33. package/dist/browse/db/updaters/DBUpdater_1_2_0.js +13 -0
  34. package/dist/browse/db/updaters/DBUpdater_1_2_0.js.map +1 -0
  35. package/dist/browse/server/Router.js +12 -1
  36. package/dist/browse/server/Router.js.map +1 -1
  37. package/dist/browse/server/handler/ContentAPIRequestHandler.d.ts +3 -0
  38. package/dist/browse/server/handler/ContentAPIRequestHandler.js +34 -2
  39. package/dist/browse/server/handler/ContentAPIRequestHandler.js.map +1 -1
  40. package/dist/browse/types/Campaign.d.ts +2 -0
  41. package/dist/browse/types/Campaign.js.map +1 -1
  42. package/dist/browse/types/Content.d.ts +43 -2
  43. package/dist/browse/types/Content.js.map +1 -1
  44. package/dist/browse/types/Filter.d.ts +6 -3
  45. package/dist/browse/types/Filter.js.map +1 -1
  46. package/dist/browse/web/assets/{index-b301OTnD.css → index-C4S8SMVg.css} +1 -1
  47. package/dist/browse/web/assets/index-D5kKPxpC.js +209 -0
  48. package/dist/browse/web/index.html +2 -2
  49. package/dist/cli/CLIOptions.js +22 -1
  50. package/dist/cli/CLIOptions.js.map +1 -1
  51. package/dist/cli/CommandLineParser.js +11 -1
  52. package/dist/cli/CommandLineParser.js.map +1 -1
  53. package/dist/cli/ConfigFileParser.js +12 -0
  54. package/dist/cli/ConfigFileParser.js.map +1 -1
  55. package/dist/cli/index.js +20 -2
  56. package/dist/cli/index.js.map +1 -1
  57. package/dist/downloaders/Bootstrap.d.ts +11 -1
  58. package/dist/downloaders/Bootstrap.js +14 -1
  59. package/dist/downloaders/Bootstrap.js.map +1 -1
  60. package/dist/downloaders/Downloader.d.ts +9 -4
  61. package/dist/downloaders/Downloader.js +181 -109
  62. package/dist/downloaders/Downloader.js.map +1 -1
  63. package/dist/downloaders/DownloaderEvent.d.ts +6 -6
  64. package/dist/downloaders/DownloaderEvent.js.map +1 -1
  65. package/dist/downloaders/DownloaderOptions.d.ts +18 -2
  66. package/dist/downloaders/DownloaderOptions.js +15 -0
  67. package/dist/downloaders/DownloaderOptions.js.map +1 -1
  68. package/dist/downloaders/InitialData.d.ts +16 -0
  69. package/dist/downloaders/InitialData.js +94 -0
  70. package/dist/downloaders/InitialData.js.map +1 -0
  71. package/dist/downloaders/PostDownloader.d.ts +12 -3
  72. package/dist/downloaders/PostDownloader.js +338 -278
  73. package/dist/downloaders/PostDownloader.js.map +1 -1
  74. package/dist/downloaders/PostsFetcher.d.ts +5 -5
  75. package/dist/downloaders/PostsFetcher.js +24 -60
  76. package/dist/downloaders/PostsFetcher.js.map +1 -1
  77. package/dist/downloaders/ProductDownloader.d.ts +1 -1
  78. package/dist/downloaders/ProductDownloader.js +368 -166
  79. package/dist/downloaders/ProductDownloader.js.map +1 -1
  80. package/dist/downloaders/ProductsFetcher.d.ts +57 -0
  81. package/dist/downloaders/ProductsFetcher.js +331 -0
  82. package/dist/downloaders/ProductsFetcher.js.map +1 -0
  83. package/dist/downloaders/index.d.ts +1 -1
  84. package/dist/downloaders/index.js.map +1 -1
  85. package/dist/downloaders/task/DownloadTaskFactory.js +15 -1
  86. package/dist/downloaders/task/DownloadTaskFactory.js.map +1 -1
  87. package/dist/downloaders/task/FetcherDownloadTask.js +1 -0
  88. package/dist/downloaders/task/FetcherDownloadTask.js.map +1 -1
  89. package/dist/downloaders/task/M3U8DownloadTask.d.ts +10 -2
  90. package/dist/downloaders/task/M3U8DownloadTask.js +87 -12
  91. package/dist/downloaders/task/M3U8DownloadTask.js.map +1 -1
  92. package/dist/downloaders/task/YouTubeDownloadTask.js +40 -9
  93. package/dist/downloaders/task/YouTubeDownloadTask.js.map +1 -1
  94. package/dist/downloaders/templates/CollectionInfo.d.ts +2 -0
  95. package/dist/downloaders/templates/CollectionInfo.js +20 -0
  96. package/dist/downloaders/templates/CollectionInfo.js.map +1 -0
  97. package/dist/entities/Comment.d.ts +3 -3
  98. package/dist/entities/Comment.js.map +1 -1
  99. package/dist/entities/{Collection.d.ts → List.d.ts} +1 -1
  100. package/dist/entities/List.js +2 -0
  101. package/dist/entities/List.js.map +1 -0
  102. package/dist/entities/MediaItem.d.ts +17 -2
  103. package/dist/entities/MediaItem.js.map +1 -1
  104. package/dist/entities/Post.d.ts +34 -3
  105. package/dist/entities/Post.js.map +1 -1
  106. package/dist/entities/Product.d.ts +25 -0
  107. package/dist/entities/Product.js +6 -1
  108. package/dist/entities/Product.js.map +1 -1
  109. package/dist/entities/index.d.ts +1 -1
  110. package/dist/entities/index.js.map +1 -1
  111. package/dist/parsers/CommentParser.d.ts +3 -3
  112. package/dist/parsers/CommentParser.js.map +1 -1
  113. package/dist/parsers/PageParser.d.ts +1 -0
  114. package/dist/parsers/PageParser.js +54 -8
  115. package/dist/parsers/PageParser.js.map +1 -1
  116. package/dist/parsers/Parser.d.ts +5 -1
  117. package/dist/parsers/Parser.js +70 -0
  118. package/dist/parsers/Parser.js.map +1 -1
  119. package/dist/parsers/PostParser.d.ts +2 -2
  120. package/dist/parsers/PostParser.js +34 -0
  121. package/dist/parsers/PostParser.js.map +1 -1
  122. package/dist/parsers/ProductParser.d.ts +3 -2
  123. package/dist/parsers/ProductParser.js +115 -49
  124. package/dist/parsers/ProductParser.js.map +1 -1
  125. package/dist/utils/FSHelper.d.ts +17 -8
  126. package/dist/utils/FSHelper.js +26 -1
  127. package/dist/utils/FSHelper.js.map +1 -1
  128. package/dist/utils/FilenameFormatHelper.d.ts +2 -1
  129. package/dist/utils/FilenameFormatHelper.js +14 -1
  130. package/dist/utils/FilenameFormatHelper.js.map +1 -1
  131. package/dist/utils/Misc.d.ts +10 -1
  132. package/dist/utils/Misc.js +53 -0
  133. package/dist/utils/Misc.js.map +1 -1
  134. package/dist/utils/URLHelper.d.ts +8 -0
  135. package/dist/utils/URLHelper.js +171 -3
  136. package/dist/utils/URLHelper.js.map +1 -1
  137. package/dist/utils/index.d.ts +1 -1
  138. package/dist/utils/index.js +1 -0
  139. package/dist/utils/index.js.map +1 -1
  140. package/dist/utils/yt/InnertubeLoader.d.ts +2 -0
  141. package/dist/utils/yt/InnertubeLoader.js +90 -2
  142. package/dist/utils/yt/InnertubeLoader.js.map +1 -1
  143. package/package.json +10 -5
  144. package/dist/browse/web/assets/index-C5gLqRAU.js +0 -209
  145. package/dist/entities/Collection.js +0 -2
  146. package/dist/entities/Collection.js.map +0 -1
package/README.md CHANGED
@@ -16,7 +16,7 @@ This repo contains the `patreon-dl` library and its command-line tool. For GUI a
16
16
  - audio
17
17
  - attachments
18
18
  - embedded videos
19
- - YouTube downloader built-in
19
+ - YouTube downloader built-in with configurable max resolution
20
20
  - Supports [external downloader](#embedded-videos--links---external-downloader)
21
21
  - Save campaign and content info
22
22
  - Extensively configurable
@@ -40,9 +40,29 @@ For information on external downloaders, see the [Embedded videos / links - exte
40
40
 
41
41
  Not all video downloads require FFmpeg, but you should have it installed on your system anyway.
42
42
 
43
- ### Embedded YouTube videos / links - Premium access
43
+ ### Embedded YouTube videos / links
44
44
 
45
- `patreon-dl` supports downloading embedded YouTube videos or from embedded YouTube video links. In addition, if you have a YouTube Premium subscription, you can connect `patreon-dl` to your account and download videos at qualities available only to Premium accounts (e.g. '1080p Premium'). For CLI users, you would configure `patreon-dl` as follows:
45
+ `patreon-dl` supports downloading embedded YouTube videos or from embedded YouTube video links.
46
+
47
+ #### Deno dependency
48
+
49
+ The built-in YouTube downloader runs code retrieved from YouTube or Google servers. If [Deno](https://deno.com/) is installed on your system, it will be used to execute this code within a secure, sandboxed environment. Without Deno, the code runs without isolation, increasing the risk of security vulnerabilities such as unauthorized access, data corruption, or malicious behavior. For this reason, installing Deno is strongly recommended.
50
+
51
+ When needed, the downloader will attempt to invoke the `deno` command. If it’s not found, it will default to unsafe execution. If Deno is installed but the `deno` executable isn’t available in your system’s PATH, you can manually specify its location using the `--deno` CLI option or `path.to.deno` config file option:
52
+
53
+ ```
54
+ // CLI
55
+ $ patreon-dl --deno path/to/deno ...
56
+
57
+ // Config file
58
+ [downloader]
59
+ path.to.deno = "path/to/deno"
60
+ ...
61
+ ```
62
+
63
+ #### Premium access
64
+
65
+ If you have a YouTube Premium subscription, you can connect `patreon-dl` to your account and download videos at qualities available only to Premium accounts (e.g. '1080p Premium'). For CLI users, you would configure `patreon-dl` as follows:
46
66
 
47
67
  ```
48
68
  $ patreon-dl --configure-youtube
@@ -82,6 +102,7 @@ $ patreon-dl [OPTION]... URL
82
102
  | <code><nobr>--config-file &lt;path&gt;</nobr></code> | `-C` | Load [configuration file](#configuration-file) at `<path>` for setting full options |
83
103
  | `--cookie <string>` | `-c` | Cookie for accessing patron-only content; [how to obtain cookie](https://github.com/patrickkfkan/patreon-dl/wiki/How-to-obtain-Cookie). |
84
104
  | `--ffmpeg <path>` | `-f` | Path to FFmpeg executable |
105
+ | `--deno <path>` | `-d` | Path to Deno executable |
85
106
  | `--out-dir <path>` |`-o` | Directory to save content |
86
107
  | `--log-level <level>` | `-l` | Log level of the console logger: `info`, `debug`, `warn` or `error`; set to `none` to disable the logger. |
87
108
  | `--no-prompt` | `-y` | Do not prompt for confirmation to proceed |
@@ -95,7 +116,12 @@ $ patreon-dl [OPTION]... URL
95
116
  #### Supported URL formats
96
117
 
97
118
  ```
98
- // Download a product
119
+ // Download products from a creator's shop
120
+ https://www.patreon.com/<creator>/shop
121
+ https://www.patreon.com/c/<creator>/shop
122
+ https://www.patreon.com/cw/<creator>/shop
123
+
124
+ // Download a single product
99
125
  https://www.patreon.com/<creator>/shop/<slug>-<product_id>
100
126
 
101
127
  // Download posts by creator
@@ -267,6 +293,24 @@ Note the URL shown in the output. Open this URL in a web browser to begin viewin
267
293
 
268
294
  ## Changelog
269
295
 
296
+ v3.5.0
297
+ - Add support for downloading from "shop" URLs (e.g. `https://www.patreon.com/<creator>/shop`). This will download all products from a creator's shop.
298
+ - Add `productsPublished` / `products.published.after` / `products.published.before` option to set publish date criteria of products included in download.
299
+ - Since `stopOn` / `stop.on` option now also applies to products, the `postPreviouslyDownloaded` and `postPublishDateOutOfRange` values have been deprecated in favor of `previouslyDownloaded` and `publishDateOutOfRange`, respectively.
300
+ - Add Collections support. Collection info is now saved when downloading posts. This means you can browse posts by collection. ([#107](https://github.com/patrickkfkan/patreon-dl/issues/107))
301
+ - (Browse) Add search functionality ([#106](https://github.com/patrickkfkan/patreon-dl/issues/106))
302
+ - Add Tags support. Tag info is now saved when downloading posts. This means you can filter posts by tag.
303
+ - Add `include.mediaThumbnails` option
304
+
305
+ v3.4.0
306
+ - Fix "no posts found" on "cw" pages ([patreon-dl-gui#30](https://github.com/patrickkfkan/patreon-dl-gui/issues/30))
307
+ - Fix YouTube streams returning 403 error ([patreon-dl-gui#31](https://github.com/patrickkfkan/patreon-dl-gui/issues/31))
308
+ - Add `pathToDeno` / `--deno` / `path.to.deno` option (used by built-in YouTube downloader)
309
+ - Merged PRs:
310
+ - Allow directory to be a symlink ([@piperswe](https://github.com/piperswe) - [#101](https://github.com/patrickkfkan/patreon-dl/pull/101))
311
+ - Add Github actions ([@piperswe](https://github.com/piperswe) - [#102](https://github.com/patrickkfkan/patreon-dl/pull/102))
312
+ - Add `maxVideoResolution` / `max.video.resolution` option to limit video downloads to a maximum resolution (see [example.conf](./example.conf)) ([@eisenbruch](https://github.com/eisenbruch) - [#105](https://github.com/patrickkfkan/patreon-dl/pull/105)) - extended to include site-hosted videos
313
+
270
314
  v3.3.1
271
315
  - Fix bugs affecting library usage:
272
316
  - `DB.getInstance()` returning same instance despite different DB path
@@ -11,7 +11,7 @@ export declare function CampaignAPIMixin<TBase extends APIConstructor>(Base: TBa
11
11
  withCounts?: false;
12
12
  }): Campaign | null;
13
13
  getCampaign(params: GetCampaignParams): Campaign | CampaignWithCounts | null;
14
- "__#132@#sanitizeCampaign"(campaign: Campaign): void;
14
+ "__#131@#sanitizeCampaign"(campaign: Campaign): void;
15
15
  name: string;
16
16
  db: import("../db").DBInstance;
17
17
  logger?: import("../..").Logger | null;
@@ -1,13 +1,19 @@
1
1
  import { type APIConstructor } from ".";
2
2
  import { type Product, type Post } from "../../entities";
3
- import { type GetContentContext, type ContentType, type GetContentListParams } from "../types/Content.js";
3
+ import { type GetContentContext, type ContentType, type GetContentListParams, type GetCollectionListParams, type GetPostTagListParams } from "../types/Content.js";
4
4
  export declare function ContentAPIMixin<TBase extends APIConstructor>(Base: TBase): {
5
5
  new (...args: any[]): {
6
6
  getContentList<T extends ContentType>(params: GetContentListParams<T>): import("../types/Content.js").ContentList<T>;
7
7
  getPost(id: string): import("../types/Content.js").PostWithComments | null;
8
8
  getProduct(id: string): Product | null;
9
9
  getPreviousNextContent<T extends ContentType>(content: Post | Product, context: GetContentContext<T>): import("../types/Content.js").GetPreviousNextContentResult<T>;
10
- "__#133@#processPostContentInlineMedia"(post: Post): void;
10
+ getCollection(id: string): {
11
+ collection: import("../../entities").Collection;
12
+ campaignId: string;
13
+ } | null;
14
+ getCollectionList(params: GetCollectionListParams): import("../types/Content.js").CollectionList;
15
+ getPostTagList(params: GetPostTagListParams): import("../types/Content.js").PostTagList;
16
+ "__#132@#processPostContentInlineMedia"(post: Post): void;
11
17
  name: string;
12
18
  db: import("../db").DBInstance;
13
19
  logger?: import("../..").Logger | null;
@@ -8,6 +8,8 @@ import RawDataExtractor from '../web/utils/RawDataExtractor.js';
8
8
  import { URLHelper } from '../../utils/index.js';
9
9
  const DEFAULT_CONTENT_LIST_SIZE = 10;
10
10
  const DEFAULT_CONTENT_LIST_SORT_BY = 'a-z';
11
+ const DEFAULT_COLLECTION_LIST_SIZE = 10;
12
+ const DEFAULT_COLLECTION_LIST_SORT_BY = 'a-z';
11
13
  export function ContentAPIMixin(Base) {
12
14
  var _ContentAPI_instances, _ContentAPI_processPostContentInlineMedia, _a;
13
15
  return _a = class ContentAPI extends Base {
@@ -52,6 +54,24 @@ export function ContentAPIMixin(Base) {
52
54
  getPreviousNextContent(content, context) {
53
55
  return this.db.getPreviousNextContent(content, context);
54
56
  }
57
+ getCollection(id) {
58
+ return this.db.getCollection(id);
59
+ }
60
+ getCollectionList(params) {
61
+ const { search = '', sortBy = DEFAULT_COLLECTION_LIST_SORT_BY, limit = DEFAULT_COLLECTION_LIST_SIZE, offset = 0 } = params;
62
+ return this.db.getCollectionList({
63
+ campaign: params.campaign,
64
+ search,
65
+ sortBy,
66
+ limit,
67
+ offset
68
+ });
69
+ }
70
+ getPostTagList(params) {
71
+ return this.db.getPostTagList({
72
+ campaign: params.campaign,
73
+ });
74
+ }
55
75
  },
56
76
  _ContentAPI_instances = new WeakSet(),
57
77
  _ContentAPI_processPostContentInlineMedia = function _ContentAPI_processPostContentInlineMedia(post) {
@@ -1 +1 @@
1
- {"version":3,"file":"ContentAPIMixin.js","sourceRoot":"","sources":["../../../src/browse/api/ContentAPIMixin.ts"],"names":[],"mappings":"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","sourcesContent":["import { load as cheerioLoad } from 'cheerio';\nimport { type APIConstructor } from \".\";\nimport { type Product, type Post } from \"../../entities\";\nimport { type GetContentContext, type ContentListSortBy, type ContentType, type GetContentListParams } from \"../types/Content.js\";\nimport RawDataExtractor from '../web/utils/RawDataExtractor.js';\nimport { URLHelper } from '../../utils/index.js';\n\nconst DEFAULT_CONTENT_LIST_SIZE = 10;\nconst DEFAULT_CONTENT_LIST_SORT_BY: ContentListSortBy = 'a-z';\n\nexport function ContentAPIMixin<TBase extends APIConstructor>(Base: TBase) {\n return class ContentAPI extends Base {\n getContentList<T extends ContentType>(params: GetContentListParams<T>) {\n const { sortBy = DEFAULT_CONTENT_LIST_SORT_BY, limit = DEFAULT_CONTENT_LIST_SIZE, offset = 0 } = params;\n const list = this.db.getContentList({\n ...params,\n sortBy,\n limit,\n offset,\n });\n for (const item of list.items) {\n switch (item.type) {\n case 'post':\n this.#processPostContentInlineMedia(item);\n item.content = this.sanitizeHTML(item.content || '');\n break;\n case 'product': {\n const description = RawDataExtractor.getProductRichTextDescription(item);\n item.description = description ? this.sanitizeHTML(description) : null;\n break;\n }\n }\n }\n return list;\n }\n\n getPost(id: string) {\n const post = this.db.getContent(id, 'post');\n if (post) {\n this.#processPostContentInlineMedia(post);\n post.content = this.sanitizeHTML(post.content || '');\n }\n return post;\n }\n\n getProduct(id: string) {\n return this.db.getContent(id, 'product');\n }\n\n getPreviousNextContent<T extends ContentType>(content: Post | Product, context: GetContentContext<T>) {\n return this.db.getPreviousNextContent(content, context);\n }\n\n #processPostContentInlineMedia(post: Post) {\n const html = post.content || '';\n const hasImages = post.images.length > 0;\n const hasLinkedAttachments = post.linkedAttachments && post.linkedAttachments.length > 0;\n if (!html || (!hasImages && !hasLinkedAttachments)) {\n return;\n }\n\n const $ = cheerioLoad(html);\n const replacedMediaIds: string[] = [];\n let hasModified = false;\n\n if (hasImages) {\n $('img').each((_, _el) => {\n const el = $(_el);\n const id = el.attr('data-media-id');\n const matched = id ? post.images.find(img => img.id === id && img.downloaded) : null;\n const src = matched ? `/media/${matched.id}` : el.attr('src');\n const imgEl = $('<img>').attr('src', src);\n const aEl = $('<a>')\n .attr('href', src)\n .attr('class', 'lightgallery-item')\n .append(imgEl);\n const wrapperEl = $('<div>')\n .attr('class', 'post-card__inline-media-wrapper')\n .append(aEl);\n if (!matched) {\n const caption = \"(Externally hosted - not stored locally)\";\n wrapperEl.append(\n $('<span>').attr('class', 'post-card__inline-media-caption').append(caption)\n );\n }\n el.replaceWith(wrapperEl);\n if (id && matched) {\n replacedMediaIds.push(id);\n }\n });\n if (replacedMediaIds.length > 0) {\n hasModified = true;\n // Remove images that have been inlined\n post.images = post.images.filter((img) => !replacedMediaIds.includes(img.id));\n }\n }\n\n // Linked attachments\n if (hasLinkedAttachments) {\n $('a').each((_, _el) => {\n const aEl = $(_el);\n const href = aEl.attr('href') || '';\n const { validated, ownerId, mediaId } = URLHelper.isAttachmentLink(href);\n if (validated) {\n let modifiedPath: string | undefined;\n if (post.id !== ownerId) {\n const isDownloaded = post.linkedAttachments?.find((att) => att.postId === ownerId && att.mediaId === mediaId)?.downloadable?.downloaded;\n modifiedPath = isDownloaded && `/media/${mediaId}?lapid=${post.id}`;\n }\n else {\n const isDownloaded = post.attachments.find((att) => att.id === mediaId)?.downloaded;\n modifiedPath = isDownloaded && `/media/${mediaId}`;\n }\n if (modifiedPath) {\n aEl.attr('href', modifiedPath);\n hasModified = true;\n }\n }\n });\n }\n\n if (hasModified) {\n post.content = $.html();\n }\n }\n }\n}"]}
1
+ {"version":3,"file":"ContentAPIMixin.js","sourceRoot":"","sources":["../../../src/browse/api/ContentAPIMixin.ts"],"names":[],"mappings":"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","sourcesContent":["import { load as cheerioLoad } from 'cheerio';\nimport { type APIConstructor } from \".\";\nimport { type Product, type Post } from \"../../entities\";\nimport { type GetContentContext, type ContentListSortBy, type ContentType, type GetContentListParams, type GetCollectionListParams, type CollectionListSortBy, type GetPostTagListParams } from \"../types/Content.js\";\nimport RawDataExtractor from '../web/utils/RawDataExtractor.js';\nimport { URLHelper } from '../../utils/index.js';\n\nconst DEFAULT_CONTENT_LIST_SIZE = 10;\nconst DEFAULT_CONTENT_LIST_SORT_BY: ContentListSortBy = 'a-z';\n\nconst DEFAULT_COLLECTION_LIST_SIZE = 10;\nconst DEFAULT_COLLECTION_LIST_SORT_BY: CollectionListSortBy = 'a-z';\n\nexport function ContentAPIMixin<TBase extends APIConstructor>(Base: TBase) {\n return class ContentAPI extends Base {\n getContentList<T extends ContentType>(params: GetContentListParams<T>) {\n const { sortBy = DEFAULT_CONTENT_LIST_SORT_BY, limit = DEFAULT_CONTENT_LIST_SIZE, offset = 0 } = params;\n const list = this.db.getContentList({\n ...params,\n sortBy,\n limit,\n offset,\n });\n for (const item of list.items) {\n switch (item.type) {\n case 'post':\n this.#processPostContentInlineMedia(item);\n item.content = this.sanitizeHTML(item.content || '');\n break;\n case 'product': {\n const description = RawDataExtractor.getProductRichTextDescription(item);\n item.description = description ? this.sanitizeHTML(description) : null;\n break;\n }\n }\n }\n return list;\n }\n\n getPost(id: string) {\n const post = this.db.getContent(id, 'post');\n if (post) {\n this.#processPostContentInlineMedia(post);\n post.content = this.sanitizeHTML(post.content || '');\n }\n return post;\n }\n\n getProduct(id: string) {\n return this.db.getContent(id, 'product');\n }\n\n getPreviousNextContent<T extends ContentType>(content: Post | Product, context: GetContentContext<T>) {\n return this.db.getPreviousNextContent(content, context);\n }\n\n getCollection(id: string) {\n return this.db.getCollection(id);\n }\n\n getCollectionList(params: GetCollectionListParams) {\n const {\n search = '',\n sortBy = DEFAULT_COLLECTION_LIST_SORT_BY,\n limit = DEFAULT_COLLECTION_LIST_SIZE,\n offset = 0\n } = params;\n return this.db.getCollectionList({\n campaign: params.campaign,\n search,\n sortBy,\n limit,\n offset\n });\n }\n\n getPostTagList(params: GetPostTagListParams) {\n return this.db.getPostTagList({\n campaign: params.campaign,\n });\n }\n\n #processPostContentInlineMedia(post: Post) {\n const html = post.content || '';\n const hasImages = post.images.length > 0;\n const hasLinkedAttachments = post.linkedAttachments && post.linkedAttachments.length > 0;\n if (!html || (!hasImages && !hasLinkedAttachments)) {\n return;\n }\n\n const $ = cheerioLoad(html);\n const replacedMediaIds: string[] = [];\n let hasModified = false;\n\n if (hasImages) {\n $('img').each((_, _el) => {\n const el = $(_el);\n const id = el.attr('data-media-id');\n const matched = id ? post.images.find(img => img.id === id && img.downloaded) : null;\n const src = matched ? `/media/${matched.id}` : el.attr('src');\n const imgEl = $('<img>').attr('src', src);\n const aEl = $('<a>')\n .attr('href', src)\n .attr('class', 'lightgallery-item')\n .append(imgEl);\n const wrapperEl = $('<div>')\n .attr('class', 'post-card__inline-media-wrapper')\n .append(aEl);\n if (!matched) {\n const caption = \"(Externally hosted - not stored locally)\";\n wrapperEl.append(\n $('<span>').attr('class', 'post-card__inline-media-caption').append(caption)\n );\n }\n el.replaceWith(wrapperEl);\n if (id && matched) {\n replacedMediaIds.push(id);\n }\n });\n if (replacedMediaIds.length > 0) {\n hasModified = true;\n // Remove images that have been inlined\n post.images = post.images.filter((img) => !replacedMediaIds.includes(img.id));\n }\n }\n\n // Linked attachments\n if (hasLinkedAttachments) {\n $('a').each((_, _el) => {\n const aEl = $(_el);\n const href = aEl.attr('href') || '';\n const { validated, ownerId, mediaId } = URLHelper.isAttachmentLink(href);\n if (validated) {\n let modifiedPath: string | undefined;\n if (post.id !== ownerId) {\n const isDownloaded = post.linkedAttachments?.find((att) => att.postId === ownerId && att.mediaId === mediaId)?.downloadable?.downloaded;\n modifiedPath = isDownloaded && `/media/${mediaId}?lapid=${post.id}`;\n }\n else {\n const isDownloaded = post.attachments.find((att) => att.id === mediaId)?.downloaded;\n modifiedPath = isDownloaded && `/media/${mediaId}`;\n }\n if (modifiedPath) {\n aEl.attr('href', modifiedPath);\n hasModified = true;\n }\n }\n });\n }\n\n if (hasModified) {\n post.content = $.html();\n }\n }\n }\n}"]}
@@ -3,7 +3,7 @@ import { type FilterData, type MediaFilterSearchParams, type PostFilterSearchPar
3
3
  export declare function FilterAPIMixin<TBase extends APIConstructor>(Base: TBase): {
4
4
  new (...args: any[]): {
5
5
  getPostFilterData(campaignId: string): FilterData<PostFilterSearchParams>;
6
- "__#134@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
6
+ "__#133@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
7
7
  getProductFilterData(campaignId: string): FilterData<ProductFilterSearchParams>;
8
8
  getMediaFilterData(campaignId: string): FilterData<MediaFilterSearchParams>;
9
9
  name: string;
@@ -134,7 +134,27 @@ export function FilterAPIMixin(Base) {
134
134
  searchParam: 'date_published',
135
135
  options: datePublishedOptions
136
136
  });
137
- return { sections };
137
+ const { tags } = this.db.getPostTagList({ campaign: campaignId });
138
+ if (tags.length > 0) {
139
+ const tagOptions = tags.map((tag) => ({
140
+ title: tag.value,
141
+ value: tag.id
142
+ }));
143
+ sections.push({
144
+ title: 'Tagged',
145
+ displayHint: 'pill_small',
146
+ searchParam: 'tag_id',
147
+ options: tagOptions
148
+ });
149
+ }
150
+ return {
151
+ sections,
152
+ external: [
153
+ {
154
+ searchParam: 'search'
155
+ }
156
+ ]
157
+ };
138
158
  }
139
159
  getProductFilterData(campaignId) {
140
160
  const productCountByYear = this.db.getContentCountByDate('product', 'year', {
@@ -208,7 +228,14 @@ export function FilterAPIMixin(Base) {
208
228
  searchParam: 'date_published',
209
229
  options: datePublishedOptions
210
230
  });
211
- return { sections };
231
+ return {
232
+ sections,
233
+ external: [
234
+ {
235
+ searchParam: 'search'
236
+ }
237
+ ]
238
+ };
212
239
  }
213
240
  getMediaFilterData(campaignId) {
214
241
  const mediaCountByTier = this.db.getMediaCountByTier(campaignId);
@@ -1 +1 @@
1
- {"version":3,"file":"FilterAPIMixin.js","sourceRoot":"","sources":["../../../src/browse/api/FilterAPIMixin.ts"],"names":[],"mappings":"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","sourcesContent":["import { type APIConstructor } from \".\";\nimport { PostType } from \"../../entities/Post.js\";\nimport { type FilterData, type FilterOption, type FilterSection, type MediaFilterSearchParams, type PostFilterSearchParams, type ProductFilterSearchParams } from \"../types/Filter.js\";\nimport { type ContentListSortBy } from \"../types/Content.js\";\nimport { type MediaListSortBy } from \"../types/Media.js\";\n\nexport function FilterAPIMixin<TBase extends APIConstructor>(Base: TBase) {\n return class FilterAPI extends Base {\n getPostFilterData(\n campaignId: string\n ): FilterData<PostFilterSearchParams> {\n const postCountByTier = this.db.getPostCountByTier(campaignId);\n const postCountByType = this.db.getPostCountByType(campaignId);\n const postCountByYear = this.db.getContentCountByDate('post', 'year', {\n campaign: campaignId\n });\n const postCountThisMonth = (this.db.getContentCountByDate('post', 'month', {\n campaign: campaignId,\n date: new Date()\n }))[0];\n\n const sections: FilterSection<PostFilterSearchParams>[] = [];\n\n const postTypeRecords = postCountByType.map<FilterOption & { count: number; }>(({ postType, count }) => ({\n title: this.#getPostTypeTitle(postType),\n count,\n value: postType\n }))\n .reduce<Record<string, { count: number, value: string; }>>((result, option) => {\n if (option.value) {\n if (result[option.title]) {\n result[option.title].count += option.count;\n result[option.title].value += `,${option.value}`;\n }\n else {\n result[option.title] = { \n count: option.count,\n value: option.value\n };\n }\n }\n return result;\n }, {});\n const postTypeOptions: FilterOption[] = [];\n for (const [title, { count, value }] of Object.entries(postTypeRecords)) {\n postTypeOptions.push({\n title: `${title} (${count})`,\n value\n });\n }\n if (postTypeOptions.length > 0) {\n sections.push({\n title: 'Post type',\n displayHint: 'pill',\n searchParam: 'post_types',\n options: postTypeOptions\n });\n }\n\n const postAccessOptions: FilterOption[] = [\n {\n title: 'Posts you have access to',\n value: 'true',\n },\n {\n title: 'All posts',\n value: null,\n isDefault: true,\n }\n ];\n sections.push({\n title: 'Post access',\n displayHint: 'list',\n searchParam: 'is_viewable',\n options: postAccessOptions\n });\n\n const tierOptions = postCountByTier.map<FilterOption>(({tierId, title, count}) => ({\n title: `${title || (tierId === '-1' ? 'Public' : title)} (${count})`,\n value: tierId,\n }));\n tierOptions.unshift({\n title: 'Any tier',\n value: null,\n isDefault: true\n });\n sections.push({\n displayHint: 'list',\n searchParam: 'tier_ids',\n options: tierOptions\n });\n\n const sortByOptions: FilterOption[] = [\n {\n title: 'Latest',\n value: 'latest' satisfies ContentListSortBy,\n isDefault: true\n },\n {\n title: 'Oldest',\n value: 'oldest' satisfies ContentListSortBy,\n },\n {\n title: 'A-Z',\n value: 'a-z' satisfies ContentListSortBy,\n },\n {\n title: 'Z-A',\n value: 'z-a' satisfies ContentListSortBy,\n }\n ];\n sections.push({\n title: 'Sort by',\n displayHint: 'list',\n searchParam: 'sort_by',\n options: sortByOptions\n });\n\n const datePublishedOptions = postCountByYear.map<FilterOption>(({dt, count}) => ({\n title: `${dt} (${count})`,\n value: dt,\n }));\n if (postCountThisMonth?.count > 0) {\n datePublishedOptions.unshift({\n title: `This month (${postCountThisMonth.count})`,\n value: 'this_month',\n });\n }\n datePublishedOptions.unshift({\n title: 'Any date',\n value: null,\n isDefault: true\n });\n sections.push({\n title: 'Date published',\n displayHint: 'list',\n searchParam: 'date_published',\n options: datePublishedOptions\n });\n\n return { sections };\n }\n\n #getPostTypeTitle(postType: string) {\n switch (postType) {\n case PostType.Audio:\n return 'Audio';\n case PostType.Image:\n return 'Image';\n case PostType.Link:\n return 'Link';\n case PostType.Podcast:\n return 'Podcast';\n case PostType.Poll:\n return 'Poll';\n case PostType.Text:\n return 'Text';\n case PostType.Video:\n case PostType.VideoEmbed:\n return 'Video';\n default:\n return 'Other';\n }\n }\n\n getProductFilterData(\n campaignId: string\n ): FilterData<ProductFilterSearchParams> {\n const productCountByYear = this.db.getContentCountByDate('product', 'year', {\n campaign: campaignId\n });\n const productCountThisMonth = (this.db.getContentCountByDate('product', 'month', {\n campaign: campaignId,\n date: new Date()\n }))[0];\n\n const sections: FilterSection<ProductFilterSearchParams>[] = [];\n \n const productAccessOptions: FilterOption[] = [\n {\n title: 'Products you have access to',\n value: 'true',\n },\n {\n title: 'All products',\n value: null,\n isDefault: true,\n }\n ];\n sections.push({\n title: 'Product access',\n displayHint: 'list',\n searchParam: 'is_viewable',\n options: productAccessOptions\n });\n\n const sortByOptions: FilterOption[] = [\n {\n title: 'Latest',\n value: 'latest' satisfies ContentListSortBy,\n isDefault: true\n },\n {\n title: 'Oldest',\n value: 'oldest' satisfies ContentListSortBy,\n },\n {\n title: 'A-Z',\n value: 'a-z' satisfies ContentListSortBy,\n },\n {\n title: 'Z-A',\n value: 'z-a' satisfies ContentListSortBy,\n }\n ];\n sections.push({\n title: 'Sort by',\n displayHint: 'list',\n searchParam: 'sort_by',\n options: sortByOptions\n });\n\n const datePublishedOptions = productCountByYear.map<FilterOption>(({dt, count}) => ({\n title: `${dt} (${count})`,\n value: dt,\n }));\n if (productCountThisMonth?.count > 0) {\n datePublishedOptions.unshift({\n title: `This month ${productCountThisMonth.count}`,\n value: 'this_month',\n });\n }\n datePublishedOptions.unshift({\n title: 'Any date',\n value: null,\n isDefault: true\n });\n sections.push({\n title: 'Date published',\n displayHint: 'list',\n searchParam: 'date_published',\n options: datePublishedOptions\n });\n\n return { sections };\n }\n\n getMediaFilterData(\n campaignId: string\n ): FilterData<MediaFilterSearchParams> {\n const mediaCountByTier = this.db.getMediaCountByTier(campaignId);\n const mediaCountByType = this.db.getMediaCountByContentType(campaignId);\n const mediaCountByYear = this.db.getMediaCountByDate('year', {\n campaign: campaignId\n });\n const postCountThisMonth = (this.db.getMediaCountByDate('month', {\n campaign: campaignId,\n date: new Date()\n }))[0];\n\n const sections: FilterSection<MediaFilterSearchParams>[] = [];\n\n const sourceTypeRecords = mediaCountByType.map<FilterOption & { count: number; }>(({ contentType, count }) => ({\n title: contentType === 'post' ? 'Posts' : 'Products',\n count,\n value: contentType\n }))\n .reduce<Record<string, { count: number, value: string; }>>((result, option) => {\n if (option.value) {\n if (result[option.title]) {\n result[option.title].count += option.count;\n result[option.title].value += `,${option.value}`;\n }\n else {\n result[option.title] = { \n count: option.count,\n value: option.value\n };\n }\n }\n return result;\n }, {});\n const sourceTypeOptions: FilterOption[] = [];\n for (const [title, { count, value }] of Object.entries(sourceTypeRecords)) {\n sourceTypeOptions.push({\n title: `${title} (${count})`,\n value\n });\n }\n if (sourceTypeOptions.length > 0) {\n sections.push({\n title: 'Show media from',\n displayHint: 'pill',\n searchParam: 'source_type',\n options: sourceTypeOptions\n });\n }\n\n const mediaAccessOptions: FilterOption[] = [\n {\n title: 'Media you have access to',\n value: 'true',\n },\n {\n title: 'All media',\n value: null,\n isDefault: true,\n }\n ];\n sections.push({\n title: 'Media access',\n displayHint: 'list',\n searchParam: 'is_viewable',\n options: mediaAccessOptions\n });\n\n if (sourceTypeOptions.find((o) => o.value === 'post')) {\n const tierOptions = mediaCountByTier.map<FilterOption>(({tierId, title, count}) => ({\n title: `${title || (tierId === '-1' ? 'Public' : title)} (${count})`,\n value: tierId,\n }));\n tierOptions.unshift({\n title: 'Any tier',\n value: null,\n isDefault: true\n });\n const tierSection: FilterSection<MediaFilterSearchParams> = {\n displayHint: 'list',\n searchParam: 'tier_ids',\n options: tierOptions\n };\n const hasProductSourceType = sourceTypeOptions.find((o) => o.value === 'product');\n if (hasProductSourceType) {\n tierSection.enableCondition = {\n searchParam: 'source_type',\n condition: 'not',\n value: 'post'\n };\n }\n sections.push(tierSection);\n }\n\n const sortByOptions: FilterOption[] = [\n {\n title: 'Latest',\n value: 'latest' satisfies MediaListSortBy,\n isDefault: true\n },\n {\n title: 'Oldest',\n value: 'oldest' satisfies MediaListSortBy,\n }\n ];\n sections.push({\n title: 'Sort by',\n displayHint: 'list',\n searchParam: 'sort_by',\n options: sortByOptions\n });\n\n const datePublishedOptions = mediaCountByYear.map<FilterOption>(({dt, count}) => ({\n title: `${dt} (${count})`,\n value: dt,\n }));\n if (postCountThisMonth?.count > 0) {\n datePublishedOptions.unshift({\n title: `This month (${postCountThisMonth.count})`,\n value: 'this_month',\n });\n }\n datePublishedOptions.unshift({\n title: 'Any date',\n value: null,\n isDefault: true\n });\n sections.push({\n title: 'Date published',\n displayHint: 'list',\n searchParam: 'date_published',\n options: datePublishedOptions\n });\n\n return { sections };\n }\n }\n}"]}
1
+ {"version":3,"file":"FilterAPIMixin.js","sourceRoot":"","sources":["../../../src/browse/api/FilterAPIMixin.ts"],"names":[],"mappings":"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","sourcesContent":["import { type APIConstructor } from \".\";\nimport { PostType } from \"../../entities/Post.js\";\nimport { type FilterData, type FilterOption, type FilterSection, type MediaFilterSearchParams, type PostFilterSearchParams, type ProductFilterSearchParams } from \"../types/Filter.js\";\nimport { type ContentListSortBy } from \"../types/Content.js\";\nimport { type MediaListSortBy } from \"../types/Media.js\";\n\nexport function FilterAPIMixin<TBase extends APIConstructor>(Base: TBase) {\n return class FilterAPI extends Base {\n getPostFilterData(\n campaignId: string\n ): FilterData<PostFilterSearchParams> {\n const postCountByTier = this.db.getPostCountByTier(campaignId);\n const postCountByType = this.db.getPostCountByType(campaignId);\n const postCountByYear = this.db.getContentCountByDate('post', 'year', {\n campaign: campaignId\n });\n const postCountThisMonth = (this.db.getContentCountByDate('post', 'month', {\n campaign: campaignId,\n date: new Date()\n }))[0];\n\n const sections: FilterSection<PostFilterSearchParams>[] = [];\n\n const postTypeRecords = postCountByType.map<FilterOption & { count: number; }>(({ postType, count }) => ({\n title: this.#getPostTypeTitle(postType),\n count,\n value: postType\n }))\n .reduce<Record<string, { count: number, value: string; }>>((result, option) => {\n if (option.value) {\n if (result[option.title]) {\n result[option.title].count += option.count;\n result[option.title].value += `,${option.value}`;\n }\n else {\n result[option.title] = { \n count: option.count,\n value: option.value\n };\n }\n }\n return result;\n }, {});\n const postTypeOptions: FilterOption[] = [];\n for (const [title, { count, value }] of Object.entries(postTypeRecords)) {\n postTypeOptions.push({\n title: `${title} (${count})`,\n value\n });\n }\n if (postTypeOptions.length > 0) {\n sections.push({\n title: 'Post type',\n displayHint: 'pill',\n searchParam: 'post_types',\n options: postTypeOptions\n });\n }\n\n const postAccessOptions: FilterOption[] = [\n {\n title: 'Posts you have access to',\n value: 'true',\n },\n {\n title: 'All posts',\n value: null,\n isDefault: true,\n }\n ];\n sections.push({\n title: 'Post access',\n displayHint: 'list',\n searchParam: 'is_viewable',\n options: postAccessOptions\n });\n\n const tierOptions = postCountByTier.map<FilterOption>(({tierId, title, count}) => ({\n title: `${title || (tierId === '-1' ? 'Public' : title)} (${count})`,\n value: tierId,\n }));\n tierOptions.unshift({\n title: 'Any tier',\n value: null,\n isDefault: true\n });\n sections.push({\n displayHint: 'list',\n searchParam: 'tier_ids',\n options: tierOptions\n });\n\n const sortByOptions: FilterOption[] = [\n {\n title: 'Latest',\n value: 'latest' satisfies ContentListSortBy,\n isDefault: true\n },\n {\n title: 'Oldest',\n value: 'oldest' satisfies ContentListSortBy,\n },\n {\n title: 'A-Z',\n value: 'a-z' satisfies ContentListSortBy,\n },\n {\n title: 'Z-A',\n value: 'z-a' satisfies ContentListSortBy,\n }\n ];\n sections.push({\n title: 'Sort by',\n displayHint: 'list',\n searchParam: 'sort_by',\n options: sortByOptions\n });\n\n const datePublishedOptions = postCountByYear.map<FilterOption>(({dt, count}) => ({\n title: `${dt} (${count})`,\n value: dt,\n }));\n if (postCountThisMonth?.count > 0) {\n datePublishedOptions.unshift({\n title: `This month (${postCountThisMonth.count})`,\n value: 'this_month',\n });\n }\n datePublishedOptions.unshift({\n title: 'Any date',\n value: null,\n isDefault: true\n });\n sections.push({\n title: 'Date published',\n displayHint: 'list',\n searchParam: 'date_published',\n options: datePublishedOptions\n });\n\n const { tags } = this.db.getPostTagList({ campaign: campaignId });\n if (tags.length > 0) {\n const tagOptions: FilterOption[] = tags.map((tag) => ({\n title: tag.value,\n value: tag.id\n }));\n sections.push({\n title: 'Tagged',\n displayHint: 'pill_small',\n searchParam: 'tag_id',\n options: tagOptions\n });\n }\n\n return {\n sections,\n external: [\n {\n searchParam: 'search'\n }\n ]\n };\n }\n\n #getPostTypeTitle(postType: string) {\n switch (postType) {\n case PostType.Audio:\n return 'Audio';\n case PostType.Image:\n return 'Image';\n case PostType.Link:\n return 'Link';\n case PostType.Podcast:\n return 'Podcast';\n case PostType.Poll:\n return 'Poll';\n case PostType.Text:\n return 'Text';\n case PostType.Video:\n case PostType.VideoEmbed:\n return 'Video';\n default:\n return 'Other';\n }\n }\n\n getProductFilterData(\n campaignId: string\n ): FilterData<ProductFilterSearchParams> {\n const productCountByYear = this.db.getContentCountByDate('product', 'year', {\n campaign: campaignId\n });\n const productCountThisMonth = (this.db.getContentCountByDate('product', 'month', {\n campaign: campaignId,\n date: new Date()\n }))[0];\n\n const sections: FilterSection<ProductFilterSearchParams>[] = [];\n \n const productAccessOptions: FilterOption[] = [\n {\n title: 'Products you have access to',\n value: 'true',\n },\n {\n title: 'All products',\n value: null,\n isDefault: true,\n }\n ];\n sections.push({\n title: 'Product access',\n displayHint: 'list',\n searchParam: 'is_viewable',\n options: productAccessOptions\n });\n\n const sortByOptions: FilterOption[] = [\n {\n title: 'Latest',\n value: 'latest' satisfies ContentListSortBy,\n isDefault: true\n },\n {\n title: 'Oldest',\n value: 'oldest' satisfies ContentListSortBy,\n },\n {\n title: 'A-Z',\n value: 'a-z' satisfies ContentListSortBy,\n },\n {\n title: 'Z-A',\n value: 'z-a' satisfies ContentListSortBy,\n }\n ];\n sections.push({\n title: 'Sort by',\n displayHint: 'list',\n searchParam: 'sort_by',\n options: sortByOptions\n });\n\n const datePublishedOptions = productCountByYear.map<FilterOption>(({dt, count}) => ({\n title: `${dt} (${count})`,\n value: dt,\n }));\n if (productCountThisMonth?.count > 0) {\n datePublishedOptions.unshift({\n title: `This month ${productCountThisMonth.count}`,\n value: 'this_month',\n });\n }\n datePublishedOptions.unshift({\n title: 'Any date',\n value: null,\n isDefault: true\n });\n sections.push({\n title: 'Date published',\n displayHint: 'list',\n searchParam: 'date_published',\n options: datePublishedOptions\n });\n\n return {\n sections,\n external: [\n {\n searchParam: 'search'\n }\n ]\n };\n }\n\n getMediaFilterData(\n campaignId: string\n ): FilterData<MediaFilterSearchParams> {\n const mediaCountByTier = this.db.getMediaCountByTier(campaignId);\n const mediaCountByType = this.db.getMediaCountByContentType(campaignId);\n const mediaCountByYear = this.db.getMediaCountByDate('year', {\n campaign: campaignId\n });\n const postCountThisMonth = (this.db.getMediaCountByDate('month', {\n campaign: campaignId,\n date: new Date()\n }))[0];\n\n const sections: FilterSection<MediaFilterSearchParams>[] = [];\n\n const sourceTypeRecords = mediaCountByType.map<FilterOption & { count: number; }>(({ contentType, count }) => ({\n title: contentType === 'post' ? 'Posts' : 'Products',\n count,\n value: contentType\n }))\n .reduce<Record<string, { count: number, value: string; }>>((result, option) => {\n if (option.value) {\n if (result[option.title]) {\n result[option.title].count += option.count;\n result[option.title].value += `,${option.value}`;\n }\n else {\n result[option.title] = { \n count: option.count,\n value: option.value\n };\n }\n }\n return result;\n }, {});\n const sourceTypeOptions: FilterOption[] = [];\n for (const [title, { count, value }] of Object.entries(sourceTypeRecords)) {\n sourceTypeOptions.push({\n title: `${title} (${count})`,\n value\n });\n }\n if (sourceTypeOptions.length > 0) {\n sections.push({\n title: 'Show media from',\n displayHint: 'pill',\n searchParam: 'source_type',\n options: sourceTypeOptions\n });\n }\n\n const mediaAccessOptions: FilterOption[] = [\n {\n title: 'Media you have access to',\n value: 'true',\n },\n {\n title: 'All media',\n value: null,\n isDefault: true,\n }\n ];\n sections.push({\n title: 'Media access',\n displayHint: 'list',\n searchParam: 'is_viewable',\n options: mediaAccessOptions\n });\n\n if (sourceTypeOptions.find((o) => o.value === 'post')) {\n const tierOptions = mediaCountByTier.map<FilterOption>(({tierId, title, count}) => ({\n title: `${title || (tierId === '-1' ? 'Public' : title)} (${count})`,\n value: tierId,\n }));\n tierOptions.unshift({\n title: 'Any tier',\n value: null,\n isDefault: true\n });\n const tierSection: FilterSection<MediaFilterSearchParams> = {\n displayHint: 'list',\n searchParam: 'tier_ids',\n options: tierOptions\n };\n const hasProductSourceType = sourceTypeOptions.find((o) => o.value === 'product');\n if (hasProductSourceType) {\n tierSection.enableCondition = {\n searchParam: 'source_type',\n condition: 'not',\n value: 'post'\n };\n }\n sections.push(tierSection);\n }\n\n const sortByOptions: FilterOption[] = [\n {\n title: 'Latest',\n value: 'latest' satisfies MediaListSortBy,\n isDefault: true\n },\n {\n title: 'Oldest',\n value: 'oldest' satisfies MediaListSortBy,\n }\n ];\n sections.push({\n title: 'Sort by',\n displayHint: 'list',\n searchParam: 'sort_by',\n options: sortByOptions\n });\n\n const datePublishedOptions = mediaCountByYear.map<FilterOption>(({dt, count}) => ({\n title: `${dt} (${count})`,\n value: dt,\n }));\n if (postCountThisMonth?.count > 0) {\n datePublishedOptions.unshift({\n title: `This month (${postCountThisMonth.count})`,\n value: 'this_month',\n });\n }\n datePublishedOptions.unshift({\n title: 'Any date',\n value: null,\n isDefault: true\n });\n sections.push({\n title: 'Date published',\n displayHint: 'list',\n searchParam: 'date_published',\n options: datePublishedOptions\n });\n\n return { sections };\n }\n }\n}"]}
@@ -10,7 +10,7 @@ export declare class APIBase {
10
10
  constructor(db: DBInstance, logger?: Logger | null);
11
11
  static getInstance(db: DBInstance, logger?: Logger | null): {
12
12
  getPostFilterData(campaignId: string): import("../types/Filter.js").FilterData<import("../types/Filter.js").PostFilterSearchParams>;
13
- "__#134@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
13
+ "__#133@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
14
14
  getProductFilterData(campaignId: string): import("../types/Filter.js").FilterData<import("../types/Filter.js").ProductFilterSearchParams>;
15
15
  getMediaFilterData(campaignId: string): import("../types/Filter.js").FilterData<import("../types/Filter.js").MediaFilterSearchParams>;
16
16
  name: string;
@@ -43,7 +43,13 @@ export declare class APIBase {
43
43
  getPost(id: string): import("../types/Content.js").PostWithComments | null;
44
44
  getProduct(id: string): import("../../index.js").Product | null;
45
45
  getPreviousNextContent<T extends import("../types/Content.js").ContentType>(content: import("../../index.js").Post | import("../../index.js").Product, context: import("../types/Content.js").GetContentContext<T>): import("../types/Content.js").GetPreviousNextContentResult<T>;
46
- "__#133@#processPostContentInlineMedia"(post: import("../../index.js").Post): void;
46
+ getCollection(id: string): {
47
+ collection: import("../../index.js").Collection;
48
+ campaignId: string;
49
+ } | null;
50
+ getCollectionList(params: import("../types/Content.js").GetCollectionListParams): import("../types/Content.js").CollectionList;
51
+ getPostTagList(params: import("../types/Content.js").GetPostTagListParams): import("../types/Content.js").PostTagList;
52
+ "__#132@#processPostContentInlineMedia"(post: import("../../index.js").Post): void;
47
53
  name: string;
48
54
  db: DBInstance;
49
55
  logger?: Logger | null;
@@ -58,7 +64,7 @@ export declare class APIBase {
58
64
  withCounts?: false;
59
65
  }): import("../../index.js").Campaign | null;
60
66
  getCampaign(params: import("../types/Campaign.js").GetCampaignParams): import("../../index.js").Campaign | import("../types/Campaign.js").CampaignWithCounts | null;
61
- "__#132@#sanitizeCampaign"(campaign: import("../../index.js").Campaign): void;
67
+ "__#131@#sanitizeCampaign"(campaign: import("../../index.js").Campaign): void;
62
68
  name: string;
63
69
  db: DBInstance;
64
70
  logger?: Logger | null;
@@ -71,7 +77,7 @@ export declare class APIBase {
71
77
  declare const API: {
72
78
  new (...args: any[]): {
73
79
  getPostFilterData(campaignId: string): import("../types/Filter.js").FilterData<import("../types/Filter.js").PostFilterSearchParams>;
74
- "__#134@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
80
+ "__#133@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
75
81
  getProductFilterData(campaignId: string): import("../types/Filter.js").FilterData<import("../types/Filter.js").ProductFilterSearchParams>;
76
82
  getMediaFilterData(campaignId: string): import("../types/Filter.js").FilterData<import("../types/Filter.js").MediaFilterSearchParams>;
77
83
  name: string;
@@ -110,7 +116,13 @@ declare const API: {
110
116
  getPost(id: string): import("../types/Content.js").PostWithComments | null;
111
117
  getProduct(id: string): import("../../index.js").Product | null;
112
118
  getPreviousNextContent<T extends import("../types/Content.js").ContentType>(content: import("../../index.js").Post | import("../../index.js").Product, context: import("../types/Content.js").GetContentContext<T>): import("../types/Content.js").GetPreviousNextContentResult<T>;
113
- "__#133@#processPostContentInlineMedia"(post: import("../../index.js").Post): void;
119
+ getCollection(id: string): {
120
+ collection: import("../../index.js").Collection;
121
+ campaignId: string;
122
+ } | null;
123
+ getCollectionList(params: import("../types/Content.js").GetCollectionListParams): import("../types/Content.js").CollectionList;
124
+ getPostTagList(params: import("../types/Content.js").GetPostTagListParams): import("../types/Content.js").PostTagList;
125
+ "__#132@#processPostContentInlineMedia"(post: import("../../index.js").Post): void;
114
126
  name: string;
115
127
  db: DBInstance;
116
128
  logger?: Logger | null;
@@ -127,7 +139,7 @@ declare const API: {
127
139
  withCounts?: false;
128
140
  }): import("../../index.js").Campaign | null;
129
141
  getCampaign(params: import("../types/Campaign.js").GetCampaignParams): import("../../index.js").Campaign | import("../types/Campaign.js").CampaignWithCounts | null;
130
- "__#132@#sanitizeCampaign"(campaign: import("../../index.js").Campaign): void;
142
+ "__#131@#sanitizeCampaign"(campaign: import("../../index.js").Campaign): void;
131
143
  name: string;
132
144
  db: DBInstance;
133
145
  logger?: Logger | null;
@@ -7,10 +7,10 @@ export declare function CampaignDBMixin<TBase extends UserDBConstructor>(Base: T
7
7
  new (...args: any[]): {
8
8
  saveCampaign(campaign: Campaign | null, downloadDate: Date, overwriteIfExists?: boolean): void;
9
9
  getCampaign(params: GetCampaignParams): Campaign | null;
10
- "__#119@#saveRewards"(campaign: Campaign): void;
11
- "__#119@#doSaveReward"(campaign: Campaign, reward: Reward): void;
10
+ "__#115@#saveRewards"(campaign: Campaign): void;
11
+ "__#115@#doSaveReward"(campaign: Campaign, reward: Reward): void;
12
12
  getCampaignList(params: GetCampaignListParams): CampaignList;
13
- "__#119@#getCampaignWithCounts"(params: GetCampaignParams): CampaignWithCounts | null;
13
+ "__#115@#getCampaignWithCounts"(params: GetCampaignParams): CampaignWithCounts | null;
14
14
  checkCampaignExists(id: string): boolean;
15
15
  saveUser(user: import("../../index.js").User | null): void;
16
16
  getUserByID(id: string): import("../../index.js").User | null;
@@ -197,6 +197,12 @@ export function CampaignDBMixin(Base) {
197
197
  select: 'COUNT(content_media.media_id) AS media_count, content_media.campaign_id',
198
198
  groupBy: 'content_media.campaign_id'
199
199
  });
200
+ const collectionCountSelect = `
201
+ SELECT
202
+ COUNT(collection_id) AS collection_count,
203
+ campaign_id
204
+ FROM collection GROUP BY campaign_id
205
+ `;
200
206
  try {
201
207
  const rows = this.all(`
202
208
  SELECT
@@ -204,17 +210,20 @@ export function CampaignDBMixin(Base) {
204
210
  IFNULL(post_count, 0) post_count,
205
211
  IFNULL(product_count, 0) product_count,
206
212
  IFNULL(media_count, 0) media_count,
213
+ IFNULL(collection_count, 0) AS collection_count,
207
214
  COALESCE(post_count, 0) + COALESCE(product_count, 0) content_count
208
215
  FROM campaign
209
216
  LEFT JOIN (${postCountSelect}) postc ON postc.campaign_id = campaign.campaign_id
210
217
  LEFT JOIN (${productCountSelect}) productc ON productc.campaign_id = campaign.campaign_id
211
218
  LEFT JOIN (${mediaCountSelect}) mc ON mc.campaign_id = campaign.campaign_id
219
+ LEFT JOIN (${collectionCountSelect}) cc ON cc.campaign_id = campaign.campaign_id
212
220
  ${orderByClause}
213
221
  ${limitOffsetClause}
214
222
  `, [...limitOffsetValues]);
215
223
  const campaigns = rows.map((row) => ({
216
224
  ...JSON.parse(row.details),
217
225
  postCount: (row.post_count || 0),
226
+ collectionCount: (row.collection_count || 0),
218
227
  productCount: (row.product_count || 0),
219
228
  mediaCount: (row.media_count || 0)
220
229
  }));
@@ -294,18 +303,21 @@ export function CampaignDBMixin(Base) {
294
303
  campaign.details,
295
304
  IFNULL(media_count, 0) AS media_count,
296
305
  IFNULL(post_count, 0) AS post_count,
297
- IFNULL(product_count, 0) AS product_count
306
+ IFNULL(product_count, 0) AS product_count,
307
+ IFNULL(collection_count, 0) AS collection_count
298
308
  FROM
299
309
  campaign
300
310
  ${joinUser}
301
311
  LEFT JOIN (SELECT COUNT(content_id) AS post_count, campaign_id FROM content WHERE content_type = 'post' GROUP BY campaign_id) postc ON postc.campaign_id = campaign.campaign_id
302
312
  LEFT JOIN (SELECT COUNT(content_id) AS product_count, campaign_id FROM content WHERE content_type = 'product' GROUP BY campaign_id) productc ON productc.campaign_id = campaign.campaign_id
303
313
  LEFT JOIN (SELECT COUNT(media_id) AS media_count, campaign_id FROM content_media GROUP BY campaign_id) mc ON mc.campaign_id = campaign.campaign_id
314
+ LEFT JOIN (SELECT COUNT(collection_id) AS collection_count, campaign_id FROM collection GROUP BY campaign_id) collectionc ON collectionc.campaign_id = campaign.campaign_id
304
315
  ${whereClause}
305
316
  `, [...whereValues]);
306
317
  return row ? {
307
318
  ...JSON.parse(row.details),
308
319
  postCount: (row.post_count || 0),
320
+ collectionCount: (row.collection_count || 0),
309
321
  productCount: (row.product_count || 0),
310
322
  mediaCount: (row.media_count || 0)
311
323
  }
@@ -1 +1 @@
1
- {"version":3,"file":"CampaignDBMixin.js","sourceRoot":"","sources":["../../../src/browse/db/CampaignDBMixin.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Reward } from '../../entities/Reward.js';\nimport { type Campaign } from '../../entities/Campaign.js';\nimport { type UserDBConstructor } from './UserDBMixin.js';\nimport { type CampaignList, type CampaignWithCounts, type GetCampaignListParams, type GetCampaignParams } from '../types/Campaign.js';\n\nexport type CampaignDBConstructor = new (\n ...args: any[]\n) => InstanceType<ReturnType<typeof CampaignDBMixin<UserDBConstructor>>>;\n\nconst NULL_CAMPAIGN: Campaign = {\n type: 'campaign',\n id: '-1',\n name: '',\n createdAt: null,\n publishedAt: null,\n avatarImage: {\n type: 'image',\n id: '-1',\n filename: 'avatar',\n createdAt: null,\n mimeType: null,\n downloadURL: null,\n imageType: 'default',\n imageURLs: {\n default: null,\n defaultSmall: null,\n original: null,\n thumbnail: null,\n thumbnailLarge: null,\n thumbnailSmall: null\n },\n thumbnailURL: null\n },\n coverPhoto: {\n type: 'image',\n id: 'campaign:-1:cover',\n filename: 'cover-photo',\n mimeType: null,\n imageType: 'campaignCoverPhoto',\n imageURLs: {\n large: null,\n medium: null,\n small: null,\n xlarge: null,\n xsmall: null\n }\n },\n summary: null,\n url: null,\n currency: null,\n rewards: [],\n creator: null,\n raw: {}\n}\n\nexport function CampaignDBMixin<TBase extends UserDBConstructor>(Base: TBase) {\n return class CampaignDB extends Base {\n saveCampaign(campaign: Campaign | null, downloadDate: Date, overwriteIfExists = true) {\n if (!campaign) {\n campaign = NULL_CAMPAIGN; \n }\n this.log('debug', `Save campaign #${campaign.id} (${campaign.name}) to DB`);\n try {\n const campaignExists = this.checkCampaignExists(campaign.id);\n if (campaignExists && !overwriteIfExists) {\n return;\n }\n\n this.exec('BEGIN TRANSACTION');\n\n // Save creator\n this.saveUser(campaign.creator);\n\n this.saveMedia(campaign.avatarImage);\n this.saveMedia(campaign.coverPhoto);\n\n if (!campaignExists) {\n this.run(\n `\n INSERT INTO campaign (\n campaign_id,\n creator_id,\n campaign_name,\n last_download,\n details\n )\n VALUES (?, ?, ?, ?, ?)\n `,\n [\n campaign.id,\n campaign.creator?.id || '-1',\n campaign.name,\n downloadDate.getTime(),\n JSON.stringify(campaign)\n ]\n );\n } else {\n this.log('debug', `Campaign #${campaign.id} already exists in DB - update record`);\n this.run(`\n UPDATE campaign\n SET\n creator_id = ?,\n campaign_name = ?,\n last_download = ?,\n details = ?\n WHERE campaign_id = ?\n `,\n [\n campaign.creator?.id || '-1',\n campaign.name,\n downloadDate.getTime(),\n JSON.stringify(campaign),\n campaign.id\n ]\n );\n }\n\n // Save rewards\n this.#saveRewards(campaign);\n\n this.exec('COMMIT');\n } catch (error) {\n this.log(\n 'error',\n `Failed to save campaign #${campaign.id} (${campaign.name}) to DB:`,\n error\n );\n this.exec('ROLLBACK');\n }\n }\n\n getCampaign(params: GetCampaignParams)\n {\n const { id, vanity, withCounts = false } = params;\n if (id) {\n this.log('debug', `Get campaign by ID \"${id}\" from DB`);\n }\n else if (vanity) {\n this.log('debug', `Get campaign by vanity \"${vanity}\" from DB`);\n }\n if (!id && !vanity) {\n throw Error('Invalid params: expecting \"id\" or \"vanity\" but got none.')\n }\n if (withCounts) {\n return this.#getCampaignWithCounts(params);\n }\n let result;\n if (id) {\n result = this.get(\n `SELECT details FROM campaign WHERE campaign_id = ?`,\n [params.id]\n );\n }\n else {\n result = this.get(\n `\n SELECT campaign.details\n FROM campaign\n LEFT JOIN user ON user.user_id = campaign.creator_id\n WHERE user.vanity = ?;\n `,\n [params.vanity]\n );\n }\n return result ? JSON.parse(result.details) as Campaign : null;\n }\n\n #saveRewards(campaign: Campaign) {\n if (campaign.id === NULL_CAMPAIGN.id) {\n this.log('warn', 'Skip save rewards to DB because campaign is null');\n return;\n }\n // Clear existing rewards for campaign\n this.log('debug', `Clear existing rewards in DB for campaign #${campaign.id} before saving current ones`);\n this.run(`DELETE FROM reward WHERE campaign_id = ?`, [\n campaign.id\n ]);\n campaign.rewards.forEach((reward) => this.#doSaveReward(campaign, reward));\n }\n\n #doSaveReward(campaign: Campaign, reward: Reward) {\n this.log('debug', `Add reward #${reward.id} (${reward.title}) to DB`);\n try {\n if (reward.image) {\n this.saveMedia(reward.image);\n }\n this.run(`\n INSERT INTO reward (\n reward_id,\n campaign_id,\n title,\n details\n )\n VALUES (?, ?, ?, ?)\n `,\n [\n reward.id,\n campaign.id,\n reward.title,\n JSON.stringify(reward)\n ]);\n }\n catch (error) {\n this.log(\n 'error',\n `Failed to save reward #${reward.id} (${reward.title}) to DB:`,\n error\n );\n throw error;\n }\n }\n\n getCampaignList(params: GetCampaignListParams): CampaignList {\n const { sortBy, limit, offset } = params;\n this.log('debug', 'Get campaigns from DB:', params);\n let orderByClause: string;\n switch (sortBy) {\n case 'a-z':\n orderByClause = 'campaign_name ASC';\n break;\n case 'z-a':\n orderByClause = 'campaign_name DESC';\n break;\n case 'most_content':\n orderByClause = 'content_count DESC';\n break;\n case 'most_media':\n orderByClause = 'media_count DESC';\n break;\n case 'last_downloaded':\n orderByClause = 'last_download DESC';\n break;\n default:\n orderByClause = '';\n }\n if (orderByClause) {\n orderByClause = `ORDER BY ${orderByClause}`;\n }\n let limitOffsetClause = '';\n const limitOffsetValues: number[] = [];\n if (limit !== undefined && offset !== undefined) {\n limitOffsetClause = 'LIMIT ? OFFSET ?';\n limitOffsetValues.push(limit, offset);\n }\n else if (limit !== undefined) {\n limitOffsetClause = 'LIMIT ?';\n limitOffsetValues.push(limit);\n }\n const postCountSelect = `\n SELECT\n COUNT(*) AS post_count,\n campaign_id\n FROM content\n WHERE content_type = 'post' GROUP BY campaign_id\n `;\n const productCountSelect = `\n SELECT\n COUNT(*) AS product_count,\n campaign_id\n FROM content\n WHERE content_type = 'product' GROUP BY campaign_id\n `;\n const mediaCountSelect = this.getMediaListSQL({\n select: 'COUNT(content_media.media_id) AS media_count, content_media.campaign_id',\n groupBy: 'content_media.campaign_id'\n });\n try {\n const rows = this.all(\n `\n SELECT\n details,\n IFNULL(post_count, 0) post_count,\n IFNULL(product_count, 0) product_count,\n IFNULL(media_count, 0) media_count,\n COALESCE(post_count, 0) + COALESCE(product_count, 0) content_count\n FROM campaign\n LEFT JOIN (${postCountSelect}) postc ON postc.campaign_id = campaign.campaign_id\n LEFT JOIN (${productCountSelect}) productc ON productc.campaign_id = campaign.campaign_id \n LEFT JOIN (${mediaCountSelect}) mc ON mc.campaign_id = campaign.campaign_id \n ${orderByClause}\n ${limitOffsetClause}\n `,\n [...limitOffsetValues]\n );\n const campaigns = rows.map((row) => ({\n ...JSON.parse(row.details) as Campaign,\n postCount: (row.post_count || 0) as number,\n productCount: (row.product_count || 0) as number,\n mediaCount: (row.media_count || 0) as number\n }));\n const totalResult = this.get(\n `SELECT COUNT(*) AS campaign_count FROM campaign`\n );\n const total = totalResult ? (totalResult.campaign_count as number) : 0;\n return {\n campaigns,\n total\n };\n } catch (error) {\n const _error = Error(`Failed to get campaigns from DB:`, {\n cause: error\n });\n this.log('error', _error);\n throw _error;\n }\n }\n\n #getCampaignWithCounts(params: GetCampaignParams): CampaignWithCounts | null {\n const { id, vanity } = params;\n const joinUser = vanity ? `LEFT JOIN user ON user.user_id = campaign.creator_id` : ''\n const whereClause = vanity ? `WHERE user.vanity = ?` : `WHERE campaign.campaign_id = ?`;\n const whereValues = vanity ? [ vanity ] : [ id ];\n const row = this.get(\n `\n SELECT\n campaign.details,\n IFNULL(media_count, 0) AS media_count,\n IFNULL(post_count, 0) AS post_count,\n IFNULL(product_count, 0) AS product_count\n FROM\n campaign\n ${joinUser}\n LEFT JOIN (SELECT COUNT(content_id) AS post_count, campaign_id FROM content WHERE content_type = 'post' GROUP BY campaign_id) postc ON postc.campaign_id = campaign.campaign_id\n LEFT JOIN (SELECT COUNT(content_id) AS product_count, campaign_id FROM content WHERE content_type = 'product' GROUP BY campaign_id) productc ON productc.campaign_id = campaign.campaign_id\n LEFT JOIN (SELECT COUNT(media_id) AS media_count, campaign_id FROM content_media GROUP BY campaign_id) mc ON mc.campaign_id = campaign.campaign_id\n ${whereClause}\n `,\n [...whereValues]\n );\n return row ? {\n ...JSON.parse(row.details) as Campaign,\n postCount: (row.post_count || 0) as number,\n productCount: (row.product_count || 0) as number,\n mediaCount: (row.media_count || 0) as number\n }\n : null;\n }\n\n checkCampaignExists(id: string) {\n this.log('debug', `Check if campaign #${id} exists in DB`);\n try {\n const result = this.get(\n `SELECT COUNT(*) as count FROM campaign WHERE campaign_id = ?`,\n [id]\n );\n return result.count > 0;\n } catch (error) {\n this.log(\n 'error',\n `Failed to check if campaign #${id} exists in DB:`,\n error\n );\n return false;\n }\n }\n };\n}\n"]}
1
+ {"version":3,"file":"CampaignDBMixin.js","sourceRoot":"","sources":["../../../src/browse/db/CampaignDBMixin.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Reward } from '../../entities/Reward.js';\nimport { type Campaign } from '../../entities/Campaign.js';\nimport { type UserDBConstructor } from './UserDBMixin.js';\nimport { type CampaignList, type CampaignWithCounts, type GetCampaignListParams, type GetCampaignParams } from '../types/Campaign.js';\n\nexport type CampaignDBConstructor = new (\n ...args: any[]\n) => InstanceType<ReturnType<typeof CampaignDBMixin<UserDBConstructor>>>;\n\nconst NULL_CAMPAIGN: Campaign = {\n type: 'campaign',\n id: '-1',\n name: '',\n createdAt: null,\n publishedAt: null,\n avatarImage: {\n type: 'image',\n id: '-1',\n filename: 'avatar',\n createdAt: null,\n mimeType: null,\n downloadURL: null,\n imageType: 'default',\n imageURLs: {\n default: null,\n defaultSmall: null,\n original: null,\n thumbnail: null,\n thumbnailLarge: null,\n thumbnailSmall: null\n },\n thumbnailURL: null\n },\n coverPhoto: {\n type: 'image',\n id: 'campaign:-1:cover',\n filename: 'cover-photo',\n mimeType: null,\n imageType: 'campaignCoverPhoto',\n imageURLs: {\n large: null,\n medium: null,\n small: null,\n xlarge: null,\n xsmall: null\n }\n },\n summary: null,\n url: null,\n currency: null,\n rewards: [],\n creator: null,\n raw: {}\n}\n\nexport function CampaignDBMixin<TBase extends UserDBConstructor>(Base: TBase) {\n return class CampaignDB extends Base {\n saveCampaign(campaign: Campaign | null, downloadDate: Date, overwriteIfExists = true) {\n if (!campaign) {\n campaign = NULL_CAMPAIGN; \n }\n this.log('debug', `Save campaign #${campaign.id} (${campaign.name}) to DB`);\n try {\n const campaignExists = this.checkCampaignExists(campaign.id);\n if (campaignExists && !overwriteIfExists) {\n return;\n }\n\n this.exec('BEGIN TRANSACTION');\n\n // Save creator\n this.saveUser(campaign.creator);\n\n this.saveMedia(campaign.avatarImage);\n this.saveMedia(campaign.coverPhoto);\n\n if (!campaignExists) {\n this.run(\n `\n INSERT INTO campaign (\n campaign_id,\n creator_id,\n campaign_name,\n last_download,\n details\n )\n VALUES (?, ?, ?, ?, ?)\n `,\n [\n campaign.id,\n campaign.creator?.id || '-1',\n campaign.name,\n downloadDate.getTime(),\n JSON.stringify(campaign)\n ]\n );\n } else {\n this.log('debug', `Campaign #${campaign.id} already exists in DB - update record`);\n this.run(`\n UPDATE campaign\n SET\n creator_id = ?,\n campaign_name = ?,\n last_download = ?,\n details = ?\n WHERE campaign_id = ?\n `,\n [\n campaign.creator?.id || '-1',\n campaign.name,\n downloadDate.getTime(),\n JSON.stringify(campaign),\n campaign.id\n ]\n );\n }\n\n // Save rewards\n this.#saveRewards(campaign);\n\n this.exec('COMMIT');\n } catch (error) {\n this.log(\n 'error',\n `Failed to save campaign #${campaign.id} (${campaign.name}) to DB:`,\n error\n );\n this.exec('ROLLBACK');\n }\n }\n\n getCampaign(params: GetCampaignParams)\n {\n const { id, vanity, withCounts = false } = params;\n if (id) {\n this.log('debug', `Get campaign by ID \"${id}\" from DB`);\n }\n else if (vanity) {\n this.log('debug', `Get campaign by vanity \"${vanity}\" from DB`);\n }\n if (!id && !vanity) {\n throw Error('Invalid params: expecting \"id\" or \"vanity\" but got none.')\n }\n if (withCounts) {\n return this.#getCampaignWithCounts(params);\n }\n let result;\n if (id) {\n result = this.get(\n `SELECT details FROM campaign WHERE campaign_id = ?`,\n [params.id]\n );\n }\n else {\n result = this.get(\n `\n SELECT campaign.details\n FROM campaign\n LEFT JOIN user ON user.user_id = campaign.creator_id\n WHERE user.vanity = ?;\n `,\n [params.vanity]\n );\n }\n return result ? JSON.parse(result.details) as Campaign : null;\n }\n\n #saveRewards(campaign: Campaign) {\n if (campaign.id === NULL_CAMPAIGN.id) {\n this.log('warn', 'Skip save rewards to DB because campaign is null');\n return;\n }\n // Clear existing rewards for campaign\n this.log('debug', `Clear existing rewards in DB for campaign #${campaign.id} before saving current ones`);\n this.run(`DELETE FROM reward WHERE campaign_id = ?`, [\n campaign.id\n ]);\n campaign.rewards.forEach((reward) => this.#doSaveReward(campaign, reward));\n }\n\n #doSaveReward(campaign: Campaign, reward: Reward) {\n this.log('debug', `Add reward #${reward.id} (${reward.title}) to DB`);\n try {\n if (reward.image) {\n this.saveMedia(reward.image);\n }\n this.run(`\n INSERT INTO reward (\n reward_id,\n campaign_id,\n title,\n details\n )\n VALUES (?, ?, ?, ?)\n `,\n [\n reward.id,\n campaign.id,\n reward.title,\n JSON.stringify(reward)\n ]);\n }\n catch (error) {\n this.log(\n 'error',\n `Failed to save reward #${reward.id} (${reward.title}) to DB:`,\n error\n );\n throw error;\n }\n }\n\n getCampaignList(params: GetCampaignListParams): CampaignList {\n const { sortBy, limit, offset } = params;\n this.log('debug', 'Get campaigns from DB:', params);\n let orderByClause: string;\n switch (sortBy) {\n case 'a-z':\n orderByClause = 'campaign_name ASC';\n break;\n case 'z-a':\n orderByClause = 'campaign_name DESC';\n break;\n case 'most_content':\n orderByClause = 'content_count DESC';\n break;\n case 'most_media':\n orderByClause = 'media_count DESC';\n break;\n case 'last_downloaded':\n orderByClause = 'last_download DESC';\n break;\n default:\n orderByClause = '';\n }\n if (orderByClause) {\n orderByClause = `ORDER BY ${orderByClause}`;\n }\n let limitOffsetClause = '';\n const limitOffsetValues: number[] = [];\n if (limit !== undefined && offset !== undefined) {\n limitOffsetClause = 'LIMIT ? OFFSET ?';\n limitOffsetValues.push(limit, offset);\n }\n else if (limit !== undefined) {\n limitOffsetClause = 'LIMIT ?';\n limitOffsetValues.push(limit);\n }\n const postCountSelect = `\n SELECT\n COUNT(*) AS post_count,\n campaign_id\n FROM content\n WHERE content_type = 'post' GROUP BY campaign_id\n `;\n const productCountSelect = `\n SELECT\n COUNT(*) AS product_count,\n campaign_id\n FROM content\n WHERE content_type = 'product' GROUP BY campaign_id\n `;\n const mediaCountSelect = this.getMediaListSQL({\n select: 'COUNT(content_media.media_id) AS media_count, content_media.campaign_id',\n groupBy: 'content_media.campaign_id'\n });\n const collectionCountSelect = `\n SELECT\n COUNT(collection_id) AS collection_count,\n campaign_id\n FROM collection GROUP BY campaign_id\n `;\n try {\n const rows = this.all(\n `\n SELECT\n details,\n IFNULL(post_count, 0) post_count,\n IFNULL(product_count, 0) product_count,\n IFNULL(media_count, 0) media_count,\n IFNULL(collection_count, 0) AS collection_count,\n COALESCE(post_count, 0) + COALESCE(product_count, 0) content_count\n FROM campaign\n LEFT JOIN (${postCountSelect}) postc ON postc.campaign_id = campaign.campaign_id\n LEFT JOIN (${productCountSelect}) productc ON productc.campaign_id = campaign.campaign_id \n LEFT JOIN (${mediaCountSelect}) mc ON mc.campaign_id = campaign.campaign_id \n LEFT JOIN (${collectionCountSelect}) cc ON cc.campaign_id = campaign.campaign_id\n ${orderByClause}\n ${limitOffsetClause}\n `,\n [...limitOffsetValues]\n );\n const campaigns = rows.map((row) => ({\n ...JSON.parse(row.details) as Campaign,\n postCount: (row.post_count || 0) as number,\n collectionCount: (row.collection_count || 0) as number,\n productCount: (row.product_count || 0) as number,\n mediaCount: (row.media_count || 0) as number\n }));\n const totalResult = this.get(\n `SELECT COUNT(*) AS campaign_count FROM campaign`\n );\n const total = totalResult ? (totalResult.campaign_count as number) : 0;\n return {\n campaigns,\n total\n };\n } catch (error) {\n const _error = Error(`Failed to get campaigns from DB:`, {\n cause: error\n });\n this.log('error', _error);\n throw _error;\n }\n }\n\n #getCampaignWithCounts(params: GetCampaignParams): CampaignWithCounts | null {\n const { id, vanity } = params;\n const joinUser = vanity ? `LEFT JOIN user ON user.user_id = campaign.creator_id` : ''\n const whereClause = vanity ? `WHERE user.vanity = ?` : `WHERE campaign.campaign_id = ?`;\n const whereValues = vanity ? [ vanity ] : [ id ];\n const row = this.get(\n `\n SELECT\n campaign.details,\n IFNULL(media_count, 0) AS media_count,\n IFNULL(post_count, 0) AS post_count,\n IFNULL(product_count, 0) AS product_count,\n IFNULL(collection_count, 0) AS collection_count\n FROM\n campaign\n ${joinUser}\n LEFT JOIN (SELECT COUNT(content_id) AS post_count, campaign_id FROM content WHERE content_type = 'post' GROUP BY campaign_id) postc ON postc.campaign_id = campaign.campaign_id\n LEFT JOIN (SELECT COUNT(content_id) AS product_count, campaign_id FROM content WHERE content_type = 'product' GROUP BY campaign_id) productc ON productc.campaign_id = campaign.campaign_id\n LEFT JOIN (SELECT COUNT(media_id) AS media_count, campaign_id FROM content_media GROUP BY campaign_id) mc ON mc.campaign_id = campaign.campaign_id\n LEFT JOIN (SELECT COUNT(collection_id) AS collection_count, campaign_id FROM collection GROUP BY campaign_id) collectionc ON collectionc.campaign_id = campaign.campaign_id\n ${whereClause}\n `,\n [...whereValues]\n );\n return row ? {\n ...JSON.parse(row.details) as Campaign,\n postCount: (row.post_count || 0) as number,\n collectionCount: (row.collection_count || 0) as number,\n productCount: (row.product_count || 0) as number,\n mediaCount: (row.media_count || 0) as number\n }\n : null;\n }\n\n checkCampaignExists(id: string) {\n this.log('debug', `Check if campaign #${id} exists in DB`);\n try {\n const result = this.get(\n `SELECT COUNT(*) as count FROM campaign WHERE campaign_id = ?`,\n [id]\n );\n return result.count > 0;\n } catch (error) {\n this.log(\n 'error',\n `Failed to check if campaign #${id} exists in DB:`,\n error\n );\n return false;\n }\n }\n };\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import { type Database } from "better-sqlite3";
2
+ export declare function initDBCollectionFTS(db: Database): void;