patreon-dl 3.7.1 → 3.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +15 -0
  2. package/dist/browse/api/CampaignAPIMixin.d.ts +1 -1
  3. package/dist/browse/api/ContentAPIMixin.d.ts +3 -3
  4. package/dist/browse/api/FilterAPIMixin.d.ts +1 -1
  5. package/dist/browse/api/index.d.ts +10 -10
  6. package/dist/browse/db/CampaignDBMixin.d.ts +3 -3
  7. package/dist/browse/db/ContentDBMixin.d.ts +13 -13
  8. package/dist/browse/db/ContentDBMixin.js +1 -1
  9. package/dist/browse/db/ContentDBMixin.js.map +1 -1
  10. package/dist/browse/db/MediaDBMixin.js +1 -1
  11. package/dist/browse/db/MediaDBMixin.js.map +1 -1
  12. package/dist/browse/db/index.d.ts +16 -16
  13. package/dist/browse/web/assets/index-CtZbx-Du.js +218 -0
  14. package/dist/browse/web/index.html +1 -1
  15. package/dist/cli/CommandLineParser.d.ts +4 -0
  16. package/dist/cli/CommandLineParser.js +65 -32
  17. package/dist/cli/CommandLineParser.js.map +1 -1
  18. package/dist/cli/helper/PostList.d.ts +6 -0
  19. package/dist/cli/helper/PostList.js +106 -0
  20. package/dist/cli/helper/PostList.js.map +1 -0
  21. package/dist/cli/index.js +73 -53
  22. package/dist/cli/index.js.map +1 -1
  23. package/dist/downloaders/Bootstrap.d.ts +5 -0
  24. package/dist/downloaders/Bootstrap.js +10 -0
  25. package/dist/downloaders/Bootstrap.js.map +1 -1
  26. package/dist/downloaders/Downloader.d.ts +4 -4
  27. package/dist/downloaders/Downloader.js +6 -59
  28. package/dist/downloaders/Downloader.js.map +1 -1
  29. package/dist/downloaders/IncludeCriteriaHelper.d.ts +25 -0
  30. package/dist/downloaders/IncludeCriteriaHelper.js +160 -0
  31. package/dist/downloaders/IncludeCriteriaHelper.js.map +1 -0
  32. package/dist/downloaders/InitialData.js +20 -6
  33. package/dist/downloaders/InitialData.js.map +1 -1
  34. package/dist/downloaders/PostDownloader.js +67 -103
  35. package/dist/downloaders/PostDownloader.js.map +1 -1
  36. package/dist/downloaders/PostsFetcher.js +7 -5
  37. package/dist/downloaders/PostsFetcher.js.map +1 -1
  38. package/dist/downloaders/ProductDownloader.js +31 -21
  39. package/dist/downloaders/ProductDownloader.js.map +1 -1
  40. package/dist/downloaders/task/YouTubeDownloadTask.js +1 -3
  41. package/dist/downloaders/task/YouTubeDownloadTask.js.map +1 -1
  42. package/dist/parsers/PageParser.js +7 -2
  43. package/dist/parsers/PageParser.js.map +1 -1
  44. package/dist/parsers/PostParser.d.ts +4 -1
  45. package/dist/parsers/PostParser.js +54 -5
  46. package/dist/parsers/PostParser.js.map +1 -1
  47. package/dist/utils/Fetcher.d.ts +1 -0
  48. package/dist/utils/Fetcher.js +5 -0
  49. package/dist/utils/Fetcher.js.map +1 -1
  50. package/dist/utils/URLHelper.d.ts +4 -0
  51. package/dist/utils/URLHelper.js +17 -0
  52. package/dist/utils/URLHelper.js.map +1 -1
  53. package/dist/utils/YouTubeCredentialsCapturer.js +1 -1
  54. package/dist/utils/YouTubeCredentialsCapturer.js.map +1 -1
  55. package/dist/utils/logging/ConsoleLogger.js +5 -0
  56. package/dist/utils/logging/ConsoleLogger.js.map +1 -1
  57. package/dist/utils/yt/InnertubeLoader.d.ts +4 -6
  58. package/dist/utils/yt/InnertubeLoader.js +14 -14
  59. package/dist/utils/yt/InnertubeLoader.js.map +1 -1
  60. package/dist/utils/yt/PoToken.js +53 -27
  61. package/dist/utils/yt/PoToken.js.map +1 -1
  62. package/package.json +12 -8
  63. package/dist/browse/web/assets/index-B1h15ViZ.js +0 -218
package/README.md CHANGED
@@ -120,6 +120,8 @@ $ patreon-dl [OPTION]... URL
120
120
  | `--dry-run` | | Run without writing files to disk (except logs, if any). Intended for testing / debugging. |
121
121
  | <code><nobr>--list-tiers &lt;creator&gt;</nobr></code> | | <p>List tiers for the given creator(s). Separate multiple creators with a comma.</p>The purpose of this is to let you find out what tier IDs to set for `posts.in.tier` filtering option under `include` section of [configuration file](#configuration-file). |
122
122
  | <code><nobr>--list-tiers-uid &lt;user ID&gt;</nobr></code> | | Same as `--list-tiers`, but takes user ID instead of vanity. |
123
+ | <code><nobr>--list-posts &lt;creator&gt;</nobr></code> | | <p>List posts by the given creator(s). Separate multiple creators with a comma.</p> |
124
+ | <code><nobr>--list-posts-uid &lt;user ID&gt;</nobr></code> | | Same as `--list-posts`, but takes user ID instead of vanity. |
123
125
  | `--configure-youtube` | | <p>Configure YouTube connection.</p>`patreon-dl` supports downloading embedded YouTube videos. If you have a YouTube Premium account, you can connect `patreon-dl` to it for downloading Premium-quality streams. You will also need to connect to an account if you get a "Login required" error message during download.|
124
126
 
125
127
  ### URL
@@ -150,6 +152,10 @@ https://www.patreon.com/collection/<collection_id>
150
152
 
151
153
  ```
152
154
 
155
+ #### Custom URLs
156
+
157
+ Some creators host their Patreon pages on custom domains. You can provide this custom URL to `patreon-dl`, which will download posts from the associated creator.
158
+
153
159
  #### Multiple URLs
154
160
 
155
161
  You may specify multiple URLs by separating them with a comma. E.g.:
@@ -305,6 +311,15 @@ Note the URL shown in the output. Open this URL in a web browser to begin viewin
305
311
 
306
312
  ## Changelog
307
313
 
314
+ 3.8.1
315
+ - YT embeds: obtain images directly from YT instead of Patreon API data, since the latter could give 0-byte content ([@Fabelwesen](https://github.com/Fabelwesen) - [#120](https://github.com/patrickkfkan/patreon-dl/issues/120)).
316
+
317
+ 3.8.0
318
+ - Add support for custom URLs (creators hosting Patreon pages on their own domains) ([@lucasoskorep](https://github.com/lucasoskorep) - [PR #129](https://github.com/patrickkfkan/patreon-dl/pull/129)).
319
+ - Fix YT download errors ([#132](https://github.com/patrickkfkan/patreon-dl/issues/132)).
320
+ - Browse: set title tag based on content ([#127](https://github.com/patrickkfkan/patreon-dl/issues/127)).
321
+ - CLI: add `--list-posts` / `--list-posts-uid` ([#126](https://github.com/patrickkfkan/patreon-dl/issues/126)).
322
+
308
323
  3.7.1
309
324
  - Check and skip download of Patreon-hosted videos that are protected by DRM; add `include.protectedMedia` / `protected.media` option.
310
325
  - Fix campaign not found when targeting collections ([#124](https://github.com/patrickkfkan/patreon-dl/issues/124)).
@@ -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
- "__#130@#sanitizeCampaign"(campaign: Campaign): void;
14
+ "__#185@#sanitizeCampaign"(campaign: Campaign): void;
15
15
  name: string;
16
16
  db: import("../db").DBInstance;
17
17
  logger?: import("../..").Logger | null;
@@ -14,9 +14,9 @@ export declare function ContentAPIMixin<TBase extends APIConstructor>(Base: TBas
14
14
  } | null;
15
15
  getCollectionList(params: GetCollectionListParams): import("../types/Content.js").CollectionList;
16
16
  getPostTagList(params: GetPostTagListParams): import("../types/Content.js").PostTagList;
17
- "__#131@#processPostContentElements"(post: Post): void;
18
- "__#131@#processInlineMedia"($: CheerioAPI, post: Post): boolean;
19
- "__#131@#processInlineLinks"($: CheerioAPI): boolean;
17
+ "__#186@#processPostContentElements"(post: Post): void;
18
+ "__#186@#processInlineMedia"($: CheerioAPI, post: Post): boolean;
19
+ "__#186@#processInlineLinks"($: CheerioAPI): boolean;
20
20
  name: string;
21
21
  db: import("../db").DBInstance;
22
22
  logger?: import("../..").Logger | null;
@@ -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
- "__#132@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
6
+ "__#187@#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;
@@ -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
- "__#132@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
13
+ "__#187@#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;
@@ -50,9 +50,9 @@ export declare class APIBase {
50
50
  } | null;
51
51
  getCollectionList(params: import("../types/Content.js").GetCollectionListParams): import("../types/Content.js").CollectionList;
52
52
  getPostTagList(params: import("../types/Content.js").GetPostTagListParams): import("../types/Content.js").PostTagList;
53
- "__#131@#processPostContentElements"(post: import("../../index.js").Post): void;
54
- "__#131@#processInlineMedia"($: import("cheerio").CheerioAPI, post: import("../../index.js").Post): boolean;
55
- "__#131@#processInlineLinks"($: import("cheerio").CheerioAPI): boolean;
53
+ "__#186@#processPostContentElements"(post: import("../../index.js").Post): void;
54
+ "__#186@#processInlineMedia"($: import("cheerio").CheerioAPI, post: import("../../index.js").Post): boolean;
55
+ "__#186@#processInlineLinks"($: import("cheerio").CheerioAPI): boolean;
56
56
  name: string;
57
57
  db: DBInstance;
58
58
  logger?: Logger | null;
@@ -67,7 +67,7 @@ export declare class APIBase {
67
67
  withCounts?: false;
68
68
  }): import("../../index.js").Campaign | null;
69
69
  getCampaign(params: import("../types/Campaign.js").GetCampaignParams): import("../../index.js").Campaign | import("../types/Campaign.js").CampaignWithCounts | null;
70
- "__#130@#sanitizeCampaign"(campaign: import("../../index.js").Campaign): void;
70
+ "__#185@#sanitizeCampaign"(campaign: import("../../index.js").Campaign): void;
71
71
  name: string;
72
72
  db: DBInstance;
73
73
  logger?: Logger | null;
@@ -80,7 +80,7 @@ export declare class APIBase {
80
80
  declare const API: {
81
81
  new (...args: any[]): {
82
82
  getPostFilterData(campaignId: string): import("../types/Filter.js").FilterData<import("../types/Filter.js").PostFilterSearchParams>;
83
- "__#132@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
83
+ "__#187@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
84
84
  getProductFilterData(campaignId: string): import("../types/Filter.js").FilterData<import("../types/Filter.js").ProductFilterSearchParams>;
85
85
  getMediaFilterData(campaignId: string): import("../types/Filter.js").FilterData<import("../types/Filter.js").MediaFilterSearchParams>;
86
86
  name: string;
@@ -126,9 +126,9 @@ declare const API: {
126
126
  } | null;
127
127
  getCollectionList(params: import("../types/Content.js").GetCollectionListParams): import("../types/Content.js").CollectionList;
128
128
  getPostTagList(params: import("../types/Content.js").GetPostTagListParams): import("../types/Content.js").PostTagList;
129
- "__#131@#processPostContentElements"(post: import("../../index.js").Post): void;
130
- "__#131@#processInlineMedia"($: import("cheerio").CheerioAPI, post: import("../../index.js").Post): boolean;
131
- "__#131@#processInlineLinks"($: import("cheerio").CheerioAPI): boolean;
129
+ "__#186@#processPostContentElements"(post: import("../../index.js").Post): void;
130
+ "__#186@#processInlineMedia"($: import("cheerio").CheerioAPI, post: import("../../index.js").Post): boolean;
131
+ "__#186@#processInlineLinks"($: import("cheerio").CheerioAPI): boolean;
132
132
  name: string;
133
133
  db: DBInstance;
134
134
  logger?: Logger | null;
@@ -145,7 +145,7 @@ declare const API: {
145
145
  withCounts?: false;
146
146
  }): import("../../index.js").Campaign | null;
147
147
  getCampaign(params: import("../types/Campaign.js").GetCampaignParams): import("../../index.js").Campaign | import("../types/Campaign.js").CampaignWithCounts | null;
148
- "__#130@#sanitizeCampaign"(campaign: import("../../index.js").Campaign): void;
148
+ "__#185@#sanitizeCampaign"(campaign: import("../../index.js").Campaign): void;
149
149
  name: string;
150
150
  db: DBInstance;
151
151
  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
- "__#114@#saveRewards"(campaign: Campaign): void;
11
- "__#114@#doSaveReward"(campaign: Campaign, reward: Reward): void;
10
+ "__#169@#saveRewards"(campaign: Campaign): void;
11
+ "__#169@#doSaveReward"(campaign: Campaign, reward: Reward): void;
12
12
  getCampaignList(params: GetCampaignListParams): CampaignList;
13
- "__#114@#getCampaignWithCounts"(params: GetCampaignParams): CampaignWithCounts | null;
13
+ "__#169@#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;
@@ -5,13 +5,13 @@ import { type CampaignDBConstructor } from './CampaignDBMixin.js';
5
5
  export declare function ContentDBMixin<TBase extends CampaignDBConstructor>(Base: TBase): {
6
6
  new (...args: any[]): {
7
7
  saveContent(content: Post | Product): void;
8
- "__#115@#saveContentMedia"(content: Post | Product): void;
9
- "__#115@#savepostMedia"(post: Post): void;
10
- "__#115@#saveProductMedia"(product: Product): void;
11
- "__#115@#doSaveContentMedia"(content: Post | Product, media: Downloadable, mediaIndex: number, isPreview: boolean): void;
12
- "__#115@#publishedAtToTime"(publishedAt: string | null): number | null;
13
- "__#115@#savePostTiers"(post: Post): void;
14
- "__#115@#doSaveTier"(post: Post, tier: Tier): void;
8
+ "__#170@#saveContentMedia"(content: Post | Product): void;
9
+ "__#170@#savepostMedia"(post: Post): void;
10
+ "__#170@#saveProductMedia"(product: Product): void;
11
+ "__#170@#doSaveContentMedia"(content: Post | Product, media: Downloadable, mediaIndex: number, isPreview: boolean): void;
12
+ "__#170@#publishedAtToTime"(publishedAt: string | null): number | null;
13
+ "__#170@#savePostTiers"(post: Post): void;
14
+ "__#170@#doSaveTier"(post: Post, tier: Tier): void;
15
15
  savePostComments(post: Post, comments: Comment[]): void;
16
16
  checkPostCommentsExist(post: Post): boolean;
17
17
  getContent(id: string, contentType: "post"): PostWithComments | null;
@@ -26,7 +26,7 @@ export declare function ContentDBMixin<TBase extends CampaignDBConstructor>(Base
26
26
  * @param row Must have `details`, `comment_count` and `comments`
27
27
  * @returns
28
28
  */
29
- "__#115@#parseContentRowJoinedComments"(row: any): any;
29
+ "__#170@#parseContentRowJoinedComments"(row: any): any;
30
30
  getContentCountByDate(contentType: ContentType, groupBy: "year" | "month", filter?: {
31
31
  campaign?: Campaign | string | null;
32
32
  date?: Date | null;
@@ -50,19 +50,19 @@ export declare function ContentDBMixin<TBase extends CampaignDBConstructor>(Base
50
50
  collection: Collection;
51
51
  campaignId: string;
52
52
  } | null;
53
- "__#115@#savePostCollection"(post: Post): void;
53
+ "__#170@#savePostCollection"(post: Post): void;
54
54
  getCollectionList(params: GetCollectionListParams): CollectionList;
55
55
  checkCollectionExists(id: string): boolean;
56
56
  checkPostTagExists(id: string, campaign: Campaign | null): boolean;
57
57
  getPostComments(post: Post | string): Comment[] | null;
58
- "__#115@#savePostTags"(post: Post): void;
58
+ "__#170@#savePostTags"(post: Post): void;
59
59
  getPostTagList(params: GetPostTagListParams): PostTagList;
60
60
  saveCampaign(campaign: Campaign | null, downloadDate: Date, overwriteIfExists?: boolean): void;
61
61
  getCampaign(params: import("../types/Campaign").GetCampaignParams): Campaign | null;
62
- "__#114@#saveRewards"(campaign: Campaign): void;
63
- "__#114@#doSaveReward"(campaign: Campaign, reward: import("../../entities").Reward): void;
62
+ "__#169@#saveRewards"(campaign: Campaign): void;
63
+ "__#169@#doSaveReward"(campaign: Campaign, reward: import("../../entities").Reward): void;
64
64
  getCampaignList(params: import("../types/Campaign").GetCampaignListParams): import("../types/Campaign").CampaignList;
65
- "__#114@#getCampaignWithCounts"(params: import("../types/Campaign").GetCampaignParams): import("../types/Campaign").CampaignWithCounts | null;
65
+ "__#169@#getCampaignWithCounts"(params: import("../types/Campaign").GetCampaignParams): import("../types/Campaign").CampaignWithCounts | null;
66
66
  checkCampaignExists(id: string): boolean;
67
67
  saveUser(user: import("../../entities").User | null): void;
68
68
  getUserByID(id: string): import("../../entities").User | null;
@@ -448,7 +448,7 @@ export function ContentDBMixin(Base) {
448
448
  const value = groupBy === 'year' ?
449
449
  String(date.getUTCFullYear())
450
450
  : getYearMonthString(date);
451
- whereValues.push(String(value));
451
+ whereValues.push(value);
452
452
  }
453
453
  const whereClause = `WHERE ${whereClauseParts.join(' AND ')}`;
454
454
  const strftimeFormat = groupBy === 'year' ? '%Y' : '%Y-%m';
@@ -1 +1 @@
1
- {"version":3,"file":"ContentDBMixin.js","sourceRoot":"","sources":["../../../src/browse/db/ContentDBMixin.ts"],"names":[],"mappings":";;;;;AAEA,OAAO,EAAE,kBAAkB,EAAoB,MAAM,qBAAqB,CAAC;AAI3E,MAAM,UAAU,cAAc,CAAsC,IAAW;;IAC7E,YAAO,MAAM,SAAU,SAAQ,IAAI;YAA5B;;;YAgtCP,CAAC;YA/sCC,WAAW,CAAC,OAAuB;gBACjC,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;gBACrE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC;gBAC1E,IAAI,CAAC;oBACH,6DAA6D;oBAC7D,yDAAyD;oBACzD,yDAAyD;oBACzD,iCAAiC;oBACjC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;oBAEvD,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;oBAC1F,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;oBAE/B,IAAI,CAAC,aAAa,EAAE,CAAC;wBACnB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,UAAU,OAAO,CAAC,IAAI,KAAK,KAAK,MAAM,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;wBACvE,IAAI,CAAC,GAAG,CACN;;;;;;;;;;;;aAYC,EACD;4BACE,OAAO,CAAC,EAAE;4BACV,OAAO,CAAC,IAAI;4BACZ,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,IAAI;4BAC5B,KAAK;4BACL,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,IAAI;4BACxE,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;4BAC7E,uBAAA,IAAI,0DAAmB,MAAvB,IAAI,EAAoB,OAAO,CAAC,WAAW,CAAC;4BAC5C,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;yBACxB,CACF,CAAC;oBACJ,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,uCAAuC,CAAC,CAAC;wBACzF,IAAI,CAAC,GAAG,CAAC;;;;;;;;;;;aAWN,EACD;4BACE,OAAO,CAAC,IAAI;4BACZ,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,IAAI;4BAC5B,KAAK;4BACL,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,IAAI,IAAI;4BACxE,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;4BAC7E,uBAAA,IAAI,0DAAmB,MAAvB,IAAI,EAAoB,OAAO,CAAC,WAAW,CAAC;4BAC5C,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;4BACvB,OAAO,CAAC,EAAE;yBACX,CACF,CAAC;oBACJ,CAAC;oBAED,qBAAqB;oBACrB,uBAAA,IAAI,yDAAkB,MAAtB,IAAI,EAAmB,OAAO,CAAC,CAAC;oBAEhC,sCAAsC;oBACtC,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;wBAC5B,uBAAA,IAAI,sDAAe,MAAnB,IAAI,EAAgB,OAAO,CAAC,CAAC;wBAC7B,uBAAA,IAAI,2DAAoB,MAAxB,IAAI,EAAqB,OAAO,CAAC,CAAC;wBAClC,uBAAA,IAAI,qDAAc,MAAlB,IAAI,EAAe,OAAO,CAAC,CAAC;oBAC9B,CAAC;oBAED,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACtB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,GAAG,CACN,OAAO,EACP,2BAA2B,KAAK,MAAM,OAAO,CAAC,EAAE,UAAU,EAC1D,KAAK,CACN,CAAC;oBACF,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;YA2LD,gBAAgB,CAAC,IAAU,EAAE,QAAmB;gBAC9C,IAAI,CAAC;oBACH,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,2BAA2B,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;oBACxD,MAAM,aAAa,GAAG,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;oBACxD,IAAI,CAAC,aAAa,EAAE,CAAC;wBACnB,IAAI,CAAC,GAAG,CACN;;;;;;;aAOC,EACD;4BACE,IAAI,CAAC,EAAE;4BACP,IAAI,CAAC,YAAY;4BACjB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;yBACzB,CACF,CAAC;oBACJ,CAAC;yBACI,CAAC;wBACJ,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,sBAAsB,IAAI,CAAC,EAAE,uCAAuC,CAAC,CAAC;wBACxF,IAAI,CAAC,GAAG,CACN;;;;;;;aAOC,EACD;4BACE,IAAI,CAAC,YAAY;4BACjB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;4BACxB,IAAI,CAAC,EAAE;yBACR,CACF,CAAC;oBACJ,CAAC;gBACH,CAAC;gBACD,OAAO,KAAK,EAAE,CAAC;oBACb,IAAI,CAAC,GAAG,CACN,OAAO,EACP,qCAAqC,IAAI,CAAC,EAAE,SAAS,EACrD,KAAK,CACN,CAAC;oBACF,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;YAED,sBAAsB,CAAC,IAAU;gBAC/B,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB;;;;;WAKC,EACD,CAAE,IAAI,CAAC,EAAE,CAAE,CACZ,CAAC;oBACF,OAAO,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;gBAC1B,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,GAAG,CACN,OAAO,EACP,yCAAyC,IAAI,CAAC,EAAE,eAAe,EAC/D,KAAK,CACN,CAAC;oBACF,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;YAID,UAAU,CAAC,EAAU,EAAE,WAAwB;gBAC7C,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,WAAW,KAAK,EAAE,UAAU,CAAC,CAAC;gBACvD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB;;;;;;;;;;8CAUsC,EACtC,CAAC,EAAE,EAAE,WAAW,CAAC,CAClB,CAAC;gBACF,OAAO,MAAM,CAAC,CAAC,CAAC,uBAAA,IAAI,sEAA+B,MAAnC,IAAI,EAAgC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACrE,CAAC;YAED,sBAAsB,CACpB,OAAuB,EACvB,OAA6B;gBAE7B,IAAI,aAAqB,CAAC;gBAC1B,IAAI,cAAiC,CAAC;gBACtC,IAAI,SAAiB,CAAC;gBACtB,IAAI,UAA6B,CAAC;gBAClC,IAAI,WAAkB,CAAC;gBACvB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC;gBAC1C,MAAM,WAAW,GAAG,uBAAA,IAAI,0DAAmB,MAAvB,IAAI,EAAoB,OAAO,CAAC,WAAW,CAAC,CAAC;gBACjE,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;gBACrE,QAAQ,MAAM,EAAE,CAAC;oBACf,KAAK,KAAK,CAAC;oBACX,KAAK,KAAK,CAAC,CAAC,CAAC;wBACX,MAAM,CAAC,GAAG;;;;;;;;WAQT,CAAC;wBACF,MAAM,CAAC,GAAG;;;;;;;;WAQT,CAAC;wBACF,WAAW,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;wBAC1E,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;4BACrB,aAAa,GAAG,CAAC,CAAC;4BAClB,cAAc,GAAG,KAAK,CAAC;4BACvB,SAAS,GAAG,CAAC,CAAC;4BACd,UAAU,GAAG,KAAK,CAAC;wBACrB,CAAC;6BACI,CAAC,CAAC,MAAM;4BACX,aAAa,GAAG,CAAC,CAAC;4BAClB,cAAc,GAAG,KAAK,CAAC;4BACvB,SAAS,GAAG,CAAC,CAAC;4BACd,UAAU,GAAG,KAAK,CAAC;wBACrB,CAAC;wBACD,MAAM;oBACR,CAAC;oBACD,KAAK,QAAQ,CAAC;oBACd,KAAK,QAAQ,CAAC;oBACd,KAAK,YAAY,CAAC,CAAC,CAAC;wBAClB,MAAM,KAAK,GAAG;;;;;;WAMb,CAAC;wBACF,MAAM,KAAK,GAAG;;;;;;WAMb,CAAC;wBACF,WAAW,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;wBACrD,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;4BACxB,aAAa,GAAG,KAAK,CAAC;4BACtB,cAAc,GAAG,QAAQ,CAAC;4BAC1B,SAAS,GAAG,KAAK,CAAC;4BAClB,UAAU,GAAG,QAAQ,CAAC;wBACxB,CAAC;6BACI,CAAC,CAAC,SAAS;4BACd,aAAa,GAAG,KAAK,CAAC;4BACtB,cAAc,GAAG,QAAQ,CAAC;4BAC1B,SAAS,GAAG,KAAK,CAAC;4BAClB,UAAU,GAAG,QAAQ,CAAC;wBACxB,CAAC;wBACD,MAAM;oBACR,CAAC;gBACH,CAAC;gBACD,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,cAAc,CACnC;oBACE,GAAG,OAAO;oBACV,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,MAAM,EAAE,cAAc;oBACtB,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;iBACpB,EACD;oBACE,YAAY,EAAE,CAAC,aAAa,CAAC;oBAC7B,WAAW;iBACZ,EACD,KAAK,CACN,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;gBACpB,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,cAAc,CAC/B;oBACE,GAAG,OAAO;oBACV,MAAM,EAAE,OAAO,CAAC,MAAM;oBACtB,MAAM,EAAE,UAAU;oBAClB,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;iBACpB,EACD;oBACE,YAAY,EAAE,CAAC,SAAS,CAAC;oBACzB,WAAW;iBACZ,EACD,KAAK,CACN,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;gBAEpB,OAAO;oBACL,QAAQ;oBACR,IAAI;iBAC8B,CAAC;YACvC,CAAC;YAED,cAAc,CACZ,MAA+B,EAC/B,EAAoD,EACpD,YAAY,GAAG,IAAI;gBAEnB,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;gBACzG,MAAM,EAAE,YAAY,EAAE,iBAAiB,GAAG,EAAE,EAAE,WAAW,EAAE,gBAAgB,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;gBAC9F,MAAM,UAAU,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC9F,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAE,MAAuC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC7F,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAE,MAAuC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;gBACvG,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAE,MAAuC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;gBACzF,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,WAAW,YAAY,EAAE;oBAChD,QAAQ,EAAE,UAAU;oBACpB,UAAU;oBACV,aAAa;oBACb,MAAM;oBACN,KAAK,EAAE,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK;oBAC7D,UAAU,EAAE,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK;oBACvE,GAAG,EAAE,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK;oBACzD,MAAM;oBACN,KAAK;oBACL,MAAM;iBACP,CAAC,CAAC;gBACH,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAE,MAAuC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC3G,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAC3C,MAAM,KAAK,CAAC,sDAAsD,CAAC,CAAC;gBACtE,CAAC;gBACD,IAAI,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;oBAC3B,MAAM,KAAK,CAAC,0DAA0D,CAAC,CAAC;gBAC1E,CAAC;gBACD,MAAM,SAAS,GAAa,EAAE,CAAC;gBAC/B,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC9B,SAAS,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAC;gBAClF,CAAC;gBACD,IAAI,UAAU,EAAE,CAAC;oBACf,SAAS,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;gBAC9F,CAAC;gBACD,IAAI,GAAG,EAAE,CAAC;oBACR,SAAS,CAAC,IAAI,CAAC,2HAA2H,CAAC,CAAC;gBAC9I,CAAC;gBACD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACjC,MAAM,WAAW,GAAkD,EAAE,CAAC;gBACtE,IAAI,UAAU,EAAE,CAAC;oBACf,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,qBAAqB,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;gBACzE,CAAC;gBACD,IAAI,WAAW,EAAE,CAAC;oBAChB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;gBACnE,CAAC;gBACD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;oBAC7B,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAC,CAAC,CAAC;gBACxE,CAAC;gBACD,IAAI,aAAa,EAAE,CAAC;oBAClB,MAAM,cAAc,GAClB,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;wBACtC,eAAe,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,OAAO;4BAC7C,CAAC,CAAC,IAAI,CAAC;oBACT,IAAI,CAAC,cAAc,EAAE,CAAC;wBACpB,MAAM,KAAK,CAAC,wFAAwF,CAAC,CAAC;oBACxG,CAAC;oBACD,WAAW,CAAC,IAAI,CAAC;wBACf,MAAM,EAAE,aAAa,cAAc,gDAAgD;wBACnF,KAAK,EAAE,aAAa;qBACrB,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,UAAU,EAAE,CAAC;oBACf,WAAW,CAAC,IAAI,CAAC;wBACf,MAAM,EAAE,+BAA+B;wBACvC,KAAK,EAAE,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE;qBACnE,CAAC,CAAC;gBACL,CAAC;gBACD,IAAI,GAAG,EAAE,CAAC;oBACR,WAAW,CAAC,IAAI,CAAC;wBACf,MAAM,EAAE,2BAA2B;wBACnC,KAAK,EAAE,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;qBAC9C,CAAC,CAAC;gBACL,CAAC;gBACD,MAAM,QAAQ,GAAsD,EAAE,CAAC;gBACvE,IAAI,eAAe,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAClD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,eAAe,EAAC,CAAC,CAAA;gBACtE,CAAC;gBACD,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC9B,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBAC3E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;gBACpD,CAAC;gBACD,MAAM,gBAAgB,GAAa,EAAE,CAAC;gBACtC,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC3B,gBAAgB,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,EAAC,MAAM,EAAE,KAAK,EAAC,EAAE,EAAE,CAAC,GAAG,KAAK,MAAM,CAAE,CAAC,CAAC;gBAClF,CAAC;gBACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACxB,gBAAgB,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,QAAQ,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC7G,CAAC;gBACD,IAAI,MAAM,EAAE,CAAC;oBACX,gBAAgB,CAAC,IAAI,CAAC,GAAG,WAAW,cAAc,CAAC,CAAC;gBACtD,CAAC;gBACD,gBAAgB,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,CAAC;gBAC5C,MAAM,WAAW,GAAG,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjG,MAAM,WAAW,GAAG;oBAClB,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,EAAC,KAAK,EAAC,EAAE,EAAE,CAAC,KAAK,CAAC;oBACtC,GAAG,QAAQ,CAAC,MAAM,CAAsB,CAAC,MAAM,EAAE,EAAC,MAAM,EAAC,EAAE,EAAE;wBAC3D,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;wBACvB,OAAO,MAAM,CAAC;oBAChB,CAAC,EAAE,EAAE,CAAC;iBACP,CAAC;gBACF,IAAI,MAAM,EAAE,CAAC;oBACX,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC3B,CAAC;gBACD,WAAW,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,CAAC;gBACtC,IAAI,aAAqB,CAAC;gBAC1B,QAAQ,MAAM,EAAE,CAAC;oBACf,KAAK,KAAK;wBACR,aAAa,GAAG,WAAW,CAAC;wBAC5B,MAAM;oBACR,KAAK,KAAK;wBACR,aAAa,GAAG,YAAY,CAAC;wBAC7B,MAAM;oBACR,KAAK,QAAQ;wBACX,aAAa,GAAG,mBAAmB,CAAC;wBACpC,MAAM;oBACR,KAAK,QAAQ;wBACX,aAAa,GAAG,kBAAkB,CAAC;wBACnC,MAAM;oBACR,KAAK,YAAY;wBACf,aAAa,GAAG,iBAAiB,WAAW,YAAY,CAAC;wBACzD,MAAM;oBACR;wBACE,aAAa,GAAG,EAAE,CAAC;gBACvB,CAAC;gBACD,IAAI,aAAa,EAAE,CAAC;oBAClB,aAAa,GAAG,YAAY,aAAa,EAAE,CAAC;gBAC9C,CAAC;gBACD,IAAI,iBAAiB,GAAG,EAAE,CAAC;gBAC3B,MAAM,iBAAiB,GAAa,EAAE,CAAC;gBACvC,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;oBAChD,iBAAiB,GAAG,kBAAkB,CAAC;oBACvC,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBACxC,CAAC;qBACI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC7B,iBAAiB,GAAG,SAAS,CAAC;oBAC9B,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAChC,CAAC;gBAED,IAAI,UAAkB,CAAC;gBACvB,IAAI,MAAM,EAAE,CAAC;oBACX,UAAU,GAAG;;cAEP,WAAW;;cAEX,WAAW,kBAAkB,WAAW,2BAA2B,WAAW;;8CAE9C,WAAW,eAAe,WAAW;SAC1E,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,UAAU,GAAG,cAAc,CAAC;gBAC9B,CAAC;gBAED,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CACnB;;;;;UAKE,UAAU;;;UAGV,IAAI;UACJ,WAAW;UACX,aAAa;UACb,iBAAiB;SAClB,EACD,CAAE,GAAG,WAAW,EAAE,GAAG,iBAAiB,CAAE,CACzC,CAAC;gBACF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAmG,CAAC,GAAG,EAAE,EAAE,CAAC,uBAAA,IAAI,sEAA+B,MAAnC,IAAI,EAAgC,GAAG,CAAC,CAAC,CAAC;gBAC5K,MAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CACvC,oCAAoC,UAAU,IAAI,IAAI,IAAI,WAAW,EAAE,EACvE,CAAC,GAAG,WAAW,CAAC,CACnB,CAAC,CAAC,CAAC,IAAI,CAAC;gBACT,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAE,WAAW,CAAC,aAAwB,CAAC,CAAC,CAAC,CAAC,CAAC;gBACtE,OAAO;oBACL,KAAK;oBACL,KAAK;iBACN,CAAC;YACJ,CAAC;YA8BD,qBAAqB,CACnB,WAAwB,EACxB,OAAyB,EACzB,MAEqB;gBAErB,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,IAAI,CAAC;gBAC1C,MAAM,UAAU,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;gBAC9F,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,WAAW,iBAAiB,EAAE;oBACrD,OAAO;oBACP,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;wBACvB,QAAQ,EAAE,UAAU;wBACpB,IAAI,EAAE,MAAM,CAAC,IAAI;qBAClB;iBACF,CAAC,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC;gBAClC,MAAM,gBAAgB,GAAG,CAAC,kBAAkB,CAAC,CAAC;gBAC9C,MAAM,WAAW,GAAa,CAAC,WAAW,CAAC,CAAC;gBAC5C,IAAI,UAAU,EAAE,CAAC;oBACf,gBAAgB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;oBACzC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC/B,CAAC;gBACD,IAAI,IAAI,EAAE,CAAC;oBACT,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;oBAChC,MAAM,KAAK,GAAG,OAAO,KAAK,MAAM,CAAC,CAAC;wBAChC,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;wBAC7B,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;oBAC7B,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;gBAClC,CAAC;gBACD,MAAM,WAAW,GAAG,SAAS,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9D,MAAM,cAAc,GAAG,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAA;gBAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CACnB;;;sBAGc,cAAc;;;;UAI1B,WAAW;;;SAGZ,EACD,CAAC,GAAG,WAAW,CAAC,CACjB,CAAC;gBACF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;oBACxB,EAAE,EAAE,GAAG,CAAC,EAAY;oBACpB,KAAK,EAAE,GAAG,CAAC,aAAuB;iBACnC,CAAC,CAAC,CAAC;YACN,CAAC;YAED,kBAAkB,CAAC,QAA2B;gBAC5C,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACzE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,wCAAwC,UAAU,EAAE,CAAC,CAAC;gBACxE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CACnB;;;;;;;;SAQC,EACD,CAAC,UAAU,CAAC,CACb,CAAC;gBACF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;oBACxB,QAAQ,EAAE,GAAG,CAAC,SAAmB;oBACjC,KAAK,EAAE,GAAG,CAAC,UAAoB;iBAChC,CAAC,CAAC,CAAC;YACN,CAAC;YAED,kBAAkB,CAAC,QAA2B;gBAC5C,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACzE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,wCAAwC,UAAU,EAAE,CAAC,CAAC;gBACxE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CACnB;;;;;;;;;SASC,EACD,CAAC,UAAU,CAAC,CACb,CAAC;gBACF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;oBACxB,MAAM,EAAE,GAAG,CAAC,OAAiB;oBAC7B,KAAK,EAAE,GAAG,CAAC,KAAe;oBAC1B,KAAK,EAAE,GAAG,CAAC,UAAoB;iBAChC,CAAC,CAAC,CAAC;YACN,CAAC;YAED,kBAAkB,CAAC,EAAU,EAAE,WAAwB,EAAE,QAA0B;gBACjF,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,WAAW,KAAK,EAAE,eAAe,CAAC,CAAC;gBACjE,MAAM,gBAAgB,GAAG;oBACvB,gBAAgB;oBAChB,kBAAkB;iBACnB,CAAC;gBACF,MAAM,WAAW,GAAG,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;gBACtC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAC3B,gBAAgB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;oBACzC,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,IAAI,CAAC,CAAC;gBACzC,CAAC;gBACD,MAAM,WAAW,GAAG,SAAS,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9D,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB;;;YAGE,WAAW;WACZ,EACD,WAAW,CACZ,CAAC;oBACF,OAAO,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;gBAC1B,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,GAAG,CACN,OAAO,EACP,sBAAsB,WAAW,KAAK,EAAE,gBAAgB,EACxD,KAAK,CACN,CAAC;oBACF,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;YAED,cAAc,CAAC,UAAsB,EAAE,QAAyB,EAAE,iBAAiB,GAAG,IAAI;gBACxF,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,oBAAoB,UAAU,CAAC,EAAE,KAAK,UAAU,CAAC,KAAK,SAAS,CAAC,CAAC;gBACnF,IAAI,CAAC;oBACH,6DAA6D;oBAC7D,yDAAyD;oBACzD,yDAAyD;oBACzD,iCAAiC;oBACjC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;oBAE/C,MAAM,gBAAgB,GAAG,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;oBACnE,IAAI,gBAAgB,IAAI,CAAC,iBAAiB,EAAE,CAAC;wBAC3C,OAAO;oBACT,CAAC;oBAED,IAAI,UAAU,CAAC,SAAS,EAAE,CAAC;wBACzB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;oBACvC,CAAC;oBAED,IAAI,CAAC,gBAAgB,EAAE,CAAC;wBACtB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,sBAAsB,UAAU,CAAC,KAAK,MAAM,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;wBAChF,IAAI,CAAC,GAAG,CACN;;;;;;;;;;aAUC,EACD;4BACE,UAAU,CAAC,EAAE;4BACb,QAAQ,EAAE,EAAE,IAAI,IAAI;4BACpB,UAAU,CAAC,KAAK;4BAChB,uBAAA,IAAI,0DAAmB,MAAvB,IAAI,EAAoB,UAAU,CAAC,SAAS,CAAC;4BAC7C,uBAAA,IAAI,0DAAmB,MAAvB,IAAI,EAAoB,UAAU,CAAC,QAAQ,CAAC;4BAC5C,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;yBAC3B,CACF,CAAC;oBACJ,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,UAAU,CAAC,EAAE,uCAAuC,CAAC,CAAC;wBACvF,IAAI,CAAC,GAAG,CAAC;;;;;;;;;;aAUN,EACD;4BACE,UAAU,CAAC,KAAK;4BAChB,uBAAA,IAAI,0DAAmB,MAAvB,IAAI,EAAoB,UAAU,CAAC,SAAS,CAAC;4BAC7C,uBAAA,IAAI,0DAAmB,MAAvB,IAAI,EAAoB,UAAU,CAAC,QAAQ,CAAC;4BAC5C,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;4BAC1B,UAAU,CAAC,EAAE;4BACb,QAAQ,EAAE,EAAE,IAAI,IAAI;yBACrB,CACF,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,GAAG,CACN,OAAO,EACP,8BAA8B,UAAU,CAAC,KAAK,MAAM,UAAU,CAAC,EAAE,UAAU,EAC3E,KAAK,CACN,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,WAAW,CAAC,GAAY,EAAE,QAAyB,EAAE,iBAAiB,GAAG,IAAI;gBAC3E,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,kBAAkB,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;gBACrD,IAAI,CAAC;oBACH,6DAA6D;oBAC7D,yDAAyD;oBACzD,yDAAyD;oBACzD,iCAAiC;oBACjC,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC;oBAE/C,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;oBAC5D,IAAI,SAAS,IAAI,CAAC,iBAAiB,EAAE,CAAC;wBACpC,OAAO;oBACT,CAAC;oBAED,IAAI,CAAC,SAAS,EAAE,CAAC;wBACf,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,oBAAoB,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;wBACjD,IAAI,CAAC,GAAG,CACN;;;;;;;;aAQC,EACD;4BACE,GAAG,CAAC,EAAE;4BACN,QAAQ,EAAE,EAAE,IAAI,IAAI;4BACpB,GAAG,CAAC,KAAK;4BACT,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;yBACpB,CACF,CAAC;oBACJ,CAAC;yBAAM,CAAC;wBACN,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,GAAG,CAAC,EAAE,wCAAwC,CAAC,CAAC;wBAC/E,IAAI,CAAC,GAAG,CAAC;;;;;;;;aAQN,EACD;4BACE,GAAG,CAAC,KAAK;4BACT,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC;4BACnB,GAAG,CAAC,EAAE;4BACN,QAAQ,EAAE,EAAE,IAAI,IAAI;yBACrB,CACF,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,GAAG,CACN,OAAO,EACP,4BAA4B,GAAG,CAAC,EAAE,UAAU,EAC5C,KAAK,CACN,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,aAAa,CAAC,EAAU;gBACtB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,mBAAmB,EAAE,UAAU,CAAC,CAAC;gBACnD,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB;;;;;;;WAOC,EACD,CAAC,EAAE,EAAE,EAAE,CAAC,CACT,CAAC;oBACF,IAAI,MAAM,EAAE,CAAC;wBACX,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAe,CAAC;wBAC5D,UAAU,CAAC,QAAQ,GAAG,MAAM,CAAC,UAAU,IAAI,CAAC,CAAC;wBAC7C,OAAO;4BACL,UAAU;4BACV,UAAU,EAAE,MAAM,CAAC,WAAqB;yBACzC,CAAC;oBACJ,CAAC;oBACD,OAAO,IAAI,CAAC;gBACd,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,6BAA6B,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;oBACrE,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YAyCD,iBAAiB,CAAC,MAA+B;gBAC/C,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;gBAC3D,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAEzE,MAAM,gBAAgB,GAAa,CAAE,iBAAiB,CAAE,CAAC;gBACzD,MAAM,WAAW,GAAwB,CAAE,UAAU,CAAE,CAAC;gBACxD,IAAI,MAAM,EAAE,CAAC;oBACX,gBAAgB,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;oBAChD,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC3B,CAAC;gBACD,MAAM,WAAW,GAAG,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAEjG,IAAI,aAAqB,CAAC;gBAC1B,QAAQ,MAAM,EAAE,CAAC;oBACf,KAAK,KAAK;wBACR,aAAa,GAAG,sBAAsB,CAAC;wBACvC,MAAM;oBACR,KAAK,KAAK;wBACR,aAAa,GAAG,uBAAuB,CAAC;wBACxC,MAAM;oBACR,KAAK,cAAc;wBACjB,aAAa,GAAG,iBAAiB,CAAC;wBAClC,MAAM;oBACR,KAAK,cAAc;wBACjB,aAAa,GAAG,gBAAgB,CAAC;wBACjC,MAAM;oBACR;wBACE,aAAa,GAAG,EAAE,CAAC;gBACvB,CAAC;gBACD,IAAI,aAAa,EAAE,CAAC;oBAClB,aAAa,GAAG,YAAY,aAAa,EAAE,CAAC;gBAC9C,CAAC;gBAED,IAAI,iBAAiB,GAAG,EAAE,CAAC;gBAC3B,MAAM,iBAAiB,GAAa,EAAE,CAAC;gBACvC,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;oBAChD,iBAAiB,GAAG,kBAAkB,CAAC;oBACvC,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;gBACxC,CAAC;qBACI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBAC7B,iBAAiB,GAAG,SAAS,CAAC;oBAC9B,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAChC,CAAC;gBAED,IAAI,UAAkB,CAAC;gBACvB,IAAI,MAAM,EAAE,CAAC;oBACX,UAAU,GAAG;;;;;;;SAOZ,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,UAAU,GAAG,iBAAiB,CAAC;gBACjC,CAAC;gBAED,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CACnB;;;UAGE,UAAU;;;UAGV,WAAW;UACX,aAAa;UACb,iBAAiB;SAClB,EACD,CAAC,GAAG,WAAW,EAAE,GAAG,iBAAiB,CAAC,CACvC,CAAC;gBACF,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAC1B,uCAAuC,UAAU,IAAI,WAAW,EAAE,EAClE,CAAC,GAAG,WAAW,CAAC,CACjB,CAAC;gBACF,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAE,WAAW,CAAC,gBAA2B,CAAC,CAAC,CAAC,CAAC,CAAC;gBACzE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;oBACnC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAe,CAAC;oBACzD,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC;oBAC1C,OAAO,UAAU,CAAC;gBACpB,CAAC,CAAC,CAAC;gBACH,OAAO;oBACL,WAAW;oBACX,KAAK;iBACN,CAAC;YACJ,CAAC;YAED,qBAAqB,CAAC,EAAU;gBAC9B,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,wBAAwB,EAAE,eAAe,CAAC,CAAC;gBAC7D,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB;;;;;WAKC,EACD,CAAE,EAAE,CAAE,CACP,CAAC;oBACF,OAAO,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;gBAC1B,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,GAAG,CACN,OAAO,EACP,kCAAkC,EAAE,gBAAgB,EACpD,KAAK,CACN,CAAC;oBACF,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;YAED,kBAAkB,CAAC,EAAU,EAAE,QAAyB;gBACtD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,CAAC,CAAC;gBACvD,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB;;;;;;WAMC,EACD,CAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,IAAI,IAAI,CAAC,CAC5B,CAAC;oBACF,OAAO,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;gBAC1B,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,GAAG,CACN,OAAO,EACP,gCAAgC,EAAE,iBAAiB,EACnD,KAAK,CACN,CAAC;oBACF,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;YAED,eAAe,CAAC,IAAmB;gBACjC,MAAM,MAAM,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzD,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,0BAA0B,MAAM,EAAE,CAAC,CAAC;gBACtD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB,sDAAsD,EACtD,CAAC,MAAM,CAAC,CACT,CAAC;gBACF,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACrD,CAAC;YAmCD,cAAc,CAAC,MAA4B;gBACzC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC;gBAC5B,MAAM,UAAU,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAEzE,MAAM,gBAAgB,GAAa,CAAE,iBAAiB,CAAE,CAAC;gBACzD,MAAM,WAAW,GAAwB,CAAE,UAAU,CAAE,CAAC;gBACxD,MAAM,WAAW,GAAG,SAAS,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9D,MAAM,aAAa,GAAG,6BAA6B,CAAC;gBACpD,MAAM,UAAU,GAAG,eAAe,CAAC;gBAEnC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CACnB;;;UAGE,UAAU;UACV,WAAW;UACX,aAAa;SACd,EACD,CAAC,GAAG,WAAW,CAAC,CACjB,CAAC;gBACF,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAC1B,gCAAgC,UAAU,IAAI,WAAW,EAAE,EAC3D,CAAC,GAAG,WAAW,CAAC,CACjB,CAAC;gBACF,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAE,WAAW,CAAC,SAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;oBAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAY,CAAC;gBAC5C,CAAC,CAAC,CAAC;gBACH,OAAO;oBACL,IAAI;oBACJ,KAAK;iBACN,CAAC;YACJ,CAAC;SACF;;2EAtnCG,OAAuB;YAEvB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,kBAAkB,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;YACzE,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;gBACrB,KAAK,MAAM;oBACT,uBAAA,IAAI,sDAAe,MAAnB,IAAI,EAAgB,OAAO,CAAC,CAAC;oBAC7B,MAAM;gBACR,KAAK,SAAS;oBACZ,uBAAA,IAAI,yDAAkB,MAAtB,IAAI,EAAmB,OAAO,CAAC,CAAC;oBAChC,MAAM;YACV,CAAC;QACH,CAAC;qEAEc,IAAU;YACvB,MAAM,UAAU,GAA8D;gBAC5E,OAAO;gBACP,aAAa;gBACb,OAAO;gBACP,cAAc;gBACd,QAAQ;gBACR,cAAc;gBACd,OAAO;aACR,CAAC;YACF,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBACpB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAClC,CAAC;YACD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACnB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACjC,CAAC;YACD,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;gBAC9B,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBACf,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;oBACxB,MAAM,aAAa,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;yBACxD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;oBACxC,aAAa,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,uBAAA,IAAI,2DAAoB,MAAxB,IAAI,EACvC,IAAI,EACJ,EAAE,EACF,KAAK,EACL,IAAI,KAAK,cAAc;wBACvB,IAAI,KAAK,cAAc;wBACvB,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CACxC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;2EAEiB,OAAgB;YAChC,MAAM,UAAU,GAA2C;gBACzD,cAAc;gBACd,cAAc;aACf,CAAC;YACF,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;gBAC9B,IAAI,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;oBAClB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;oBAC3B,MAAM,aAAa,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;yBACxD,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;oBACxC,aAAa,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,uBAAA,IAAI,2DAAoB,MAAxB,IAAI,EACvC,OAAO,EACP,EAAE,EACF,KAAK,EACL,IAAI,KAAK,cAAc,CACxB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;+EAGC,OAAuB,EACvB,KAAmB,EACnB,UAAkB,EAClB,SAAkB;YAElB,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;gBAChD,OAAO;YACT,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,OAAO,EACd,QAAQ,OAAO,CAAC,IAAI,cAAc,EAClC,IAAI,OAAO,CAAC,IAAI,QAAQ,OAAO,CAAC,EAAE,eAAe,KAAK,CAAC,EAAE,GAAG,CAC7D,CAAC;YACF,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACtB,IAAI,CAAC;gBACH,MAAM,kBAAkB,GAAG,IAAI,CAAC,uBAAuB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBACxE,IAAI,CAAC,kBAAkB,EAAE,CAAC;oBACxB,IAAI,CAAC,GAAG,CACN;;;;;;;;;;aAUC,EACD;wBACE,KAAK,CAAC,EAAE;wBACR,OAAO,CAAC,EAAE;wBACV,OAAO,CAAC,IAAI;wBACZ,UAAU;wBACV,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,IAAI;wBAC5B,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;qBAClB,CACF,CAAC;gBACJ,CAAC;qBACI,CAAC;oBACJ,IAAI,CAAC,GAAG,CAAC,OAAO,EACd,GAAG,OAAO,CAAC,IAAI,6BAA6B,EAC5C,IAAI,OAAO,CAAC,IAAI,QAAQ,OAAO,CAAC,EAAE,eAAe,KAAK,CAAC,EAAE,GAAG,EAC5D,iBAAiB,CAClB,CAAC;oBACF,IAAI,CAAC,GAAG,CACN;;;;;;;;;;aAUC,EACD;wBACE,OAAO,CAAC,EAAE;wBACV,OAAO,CAAC,IAAI;wBACZ,UAAU;wBACV,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,IAAI;wBAC5B,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBACjB,KAAK,CAAC,EAAE;qBACT,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,OAAO,KAAK,EAAE,CAAC;gBACb,IAAI,CAAC,GAAG,CACN,OAAO,EACP,uCAAuC,OAAO,CAAC,IAAI,iBAAiB,OAAO,CAAC,EAAE,eAAe,KAAK,CAAC,EAAE,UAAU,EAC/G,KAAK,CACN,CAAC;gBACF,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;6EAEkB,WAA0B;YAC3C,IAAI,CAAC;gBACH,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC;YACzC,CAAC;YACD,OAAO,KAAK,EAAE,CAAC;gBACb,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,wCAAwC,WAAW,oBAAoB,EAAE,KAAK,CAAC,CAAC;gBACjG,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;qEAEc,IAAU;YACvB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,wBAAwB,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;YAC3D,gCAAgC;YAChC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,wCAAwC,IAAI,CAAC,EAAE,6BAA6B,CAAC,CAAC;YAChG,IAAI,CAAC,GAAG,CAAC,yCAAyC,EAAE;gBAClD,IAAI,CAAC,EAAE;aACR,CAAC,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,uBAAA,IAAI,mDAAY,MAAhB,IAAI,EAAa,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC7D,CAAC;+DAEW,IAAU,EAAE,IAAU;YAChC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,kBAAkB,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC;YACrE,IAAI,CAAC,GAAG,CAAC;;;;;;;OAOR,EACD;gBACE,IAAI,CAAC,EAAE;gBACP,IAAI,CAAC,EAAE;gBACP,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,IAAI;aAC1B,CAAC,CAAC;QACL,CAAC;qGA6Y8B,GAAQ;YACrC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;gBAClC,OAAO,OAAO,CAAC;YACjB,CAAC;YACD,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;gBACrB,KAAK,MAAM,CAAC,CAAC,CAAC;oBACZ,wDAAwD;oBACxD,qEAAqE;oBACrE,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;oBACpD,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;oBACzE,OAAO;wBACL,GAAG,OAAO;wBACV,YAAY;wBACZ,QAAQ;qBACkB,CAAC;gBAC/B,CAAC;gBACD,KAAK,SAAS,CAAC;gBACf;oBACE,OAAO,OAAO,CAAC;YACnB,CAAC;QACH,CAAC;+EAqSmB,IAAU;YAC5B,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,mCAAmC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YAChE,IAAI,CAAC,GAAG,CAAC,+CAA+C,EAAE;gBACxD,IAAI,CAAC,EAAE;aACR,CAAC,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvD,OAAO;YACT,CAAC;YACD,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBAC1C,+DAA+D;gBAC/D,yDAAyD;gBACzD,yDAAyD;gBACzD,iCAAiC;gBACjC,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBACtD,IAAI,CAAC;oBACH,IAAI,CAAC,GAAG,CACN;;;;;;;;aAQC,EACD;wBACE,UAAU,CAAC,EAAE;wBACb,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,IAAI;wBACzB,IAAI,CAAC,EAAE;wBACP,uBAAA,IAAI,0DAAmB,MAAvB,IAAI,EAAoB,UAAU,CAAC,SAAS,CAAC;qBAC9C,CACF,CAAC;gBACJ,CAAC;gBACD,OAAO,KAAK,EAAE,CAAC;oBACb,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,4CAA4C,IAAI,CAAC,EAAE,mBAAmB,UAAU,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;gBACnH,CAAC;YACH,CAAC;QACH,CAAC;mEAkJa,IAAU;YACtB,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,iCAAiC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9D,IAAI,CAAC,GAAG,CAAC,6CAA6C,EAAE;gBACtD,IAAI,CAAC,EAAE;aACR,CAAC,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzC,OAAO;YACT,CAAC;YACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC5B,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBAC5C,IAAI,CAAC;oBACH,IAAI,CAAC,GAAG,CACN;;;;;;;aAOC,EACD;wBACE,GAAG,CAAC,EAAE;wBACN,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,IAAI;wBACzB,IAAI,CAAC,EAAE;qBACR,CACF,CAAC;gBACJ,CAAC;gBACD,OAAO,KAAK,EAAE,CAAC;oBACb,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,0CAA0C,IAAI,CAAC,EAAE,iBAAiB,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;gBACzG,CAAC;YACH,CAAC;QACH,CAAC;WAmCD;AACJ,CAAC","sourcesContent":["import { type Comment, type Downloadable, type Post, type Product, type Tier, type Campaign } from '../../entities';\nimport { type PostTag, type Collection } from '../../entities/Post';\nimport { getYearMonthString, type KeysOfValue } from '../../utils/Misc.js';\nimport { type GetContentContext, type GetPreviousNextContentResult, type ContentList, type ContentType, type GetContentListParams, type PostWithComments, type ContentListSortBy, type GetCollectionListParams, type CollectionList, type GetPostTagListParams, type PostTagList } from '../types/Content.js';\nimport { type CampaignDBConstructor } from './CampaignDBMixin.js';\n\nexport function ContentDBMixin<TBase extends CampaignDBConstructor>(Base: TBase) {\n return class ContentDB extends Base {\n saveContent(content: Post | Product) {\n const title = content.type === 'post' ? content.title : content.name;\n this.log('debug', `Save ${content.type} #${content.id} (${title}) to DB`);\n try {\n // Normally, campaign would have already been saved to DB via\n // downloader logic, but we should still save it one more\n // time just in case. Difference is, we do not overwrite \n // DB entry if it already exists.\n this.saveCampaign(content.campaign, new Date(), false);\n\n const contentExists = this.checkContentExists(content.id, content.type, content.campaign);\n this.exec('BEGIN TRANSACTION');\n\n if (!contentExists) {\n this.log('debug', `INSERT ${content.type} \"${title}\" (${content.id})`);\n this.run(\n `\n INSERT INTO content (\n content_id,\n content_type,\n campaign_id,\n title,\n content_subtype,\n is_viewable,\n published_at,\n details\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `,\n [\n content.id,\n content.type,\n content.campaign?.id || '-1',\n title,\n content.type === 'post' ? content.postType : content.productType || null,\n (content.type === 'post' ? content.isViewable : content.isAccessible) ? 1 : 0,\n this.#publishedAtToTime(content.publishedAt),\n JSON.stringify(content)\n ]\n );\n } else {\n this.log('debug', `${content.type} #${content.id} already exists in DB - update record`);\n this.run(`\n UPDATE content\n SET\n content_type = ?,\n campaign_id = ?,\n title = ?,\n content_subtype = ?,\n is_viewable = ?,\n published_at = ?,\n details = ?\n WHERE content_id = ?\n `,\n [\n content.type,\n content.campaign?.id || '-1',\n title,\n content.type === 'post' ? content.postType : content.productType || null,\n (content.type === 'post' ? content.isViewable : content.isAccessible) ? 1 : 0,\n this.#publishedAtToTime(content.publishedAt),\n JSON.stringify(content),\n content.id\n ]\n );\n }\n\n // Save content media\n this.#saveContentMedia(content);\n\n // Save tiers and collections and tags\n if (content.type === 'post') {\n this.#savePostTiers(content);\n this.#savePostCollection(content);\n this.#savePostTags(content);\n }\n\n this.exec('COMMIT');\n } catch (error) {\n this.log(\n 'error',\n `Failed to save content \"${title}\" (${content.id}) to DB:`,\n error\n );\n this.exec('ROLLBACK');\n }\n }\n\n #saveContentMedia(\n content: Post | Product\n ) {\n this.log('debug', `Save media for ${content.type} #${content.id} to DB`);\n switch (content.type) {\n case 'post':\n this.#savepostMedia(content);\n break;\n case 'product':\n this.#saveProductMedia(content);\n break;\n }\n }\n\n #savepostMedia(post: Post) {\n const mediaProps: KeysOfValue<Post, Downloadable | Downloadable[] | null>[] = [\n 'embed',\n 'attachments',\n 'audio',\n 'audioPreview',\n 'images',\n 'videoPreview',\n 'video'\n ];\n if (post.coverImage) {\n this.saveMedia(post.coverImage);\n }\n if (post.thumbnail) {\n this.saveMedia(post.thumbnail);\n }\n for (const prop of mediaProps) {\n if (post[prop]) {\n const data = post[prop];\n const downloadables = (Array.isArray(data) ? data : [data])\n .filter((data) => data !== undefined);\n downloadables.forEach((dl, index) => this.#doSaveContentMedia(\n post,\n dl,\n index,\n prop === 'audioPreview'||\n prop === 'videoPreview' ||\n (prop === 'images' && !post.isViewable)\n ));\n }\n }\n }\n\n #saveProductMedia(product: Product) {\n const mediaProps: KeysOfValue<Product, Downloadable[]>[] = [\n 'contentMedia',\n 'previewMedia'\n ];\n for (const prop of mediaProps) {\n if (product[prop]) {\n const data = product[prop];\n const downloadables = (Array.isArray(data) ? data : [data])\n .filter((data) => data !== undefined);\n downloadables.forEach((dl, index) => this.#doSaveContentMedia(\n product,\n dl,\n index,\n prop === 'previewMedia'\n ));\n }\n }\n }\n\n #doSaveContentMedia(\n content: Post | Product,\n media: Downloadable,\n mediaIndex: number,\n isPreview: boolean\n ) {\n if (!media.downloaded || !media.downloaded.path) {\n return;\n }\n this.log('debug',\n `Save ${content.type} media to DB`,\n `(${content.type} ID: ${content.id}, media ID: ${media.id})`\n );\n this.saveMedia(media);\n try {\n const contentMediaExists = this.checkContentMediaExists(content, media);\n if (!contentMediaExists) {\n this.run(\n `\n INSERT INTO content_media (\n media_id,\n content_id,\n content_type,\n media_index,\n campaign_id,\n is_preview\n )\n VALUES (?, ?, ?, ?, ?, ?)\n `,\n [\n media.id,\n content.id,\n content.type,\n mediaIndex,\n content.campaign?.id || '-1',\n isPreview ? 1 : 0\n ]\n );\n }\n else {\n this.log('debug',\n `${content.type} media already exists in DB`,\n `(${content.type} ID: ${content.id}, media ID: ${media.id})`,\n '- update record'\n );\n this.run(\n `\n UPDATE content_media\n SET\n content_id = ?,\n content_type = ?,\n media_index = ?,\n campaign_id = ?,\n is_preview = ?\n WHERE\n media_id = ?\n `,\n [\n content.id,\n content.type,\n mediaIndex,\n content.campaign?.id || '-1',\n isPreview ? 1 : 0,\n media.id,\n ]\n );\n }\n }\n catch (error) {\n this.log(\n 'error',\n `Failed to save content media (type: ${content.type}, content_id: ${content.id}, media_id: ${media.id}) to DB:`,\n error\n );\n throw error;\n }\n }\n\n #publishedAtToTime(publishedAt: string | null) {\n try {\n if (!publishedAt) {\n return null;\n }\n return new Date(publishedAt).getTime();\n }\n catch (error) {\n this.log('warn', `Failed to convert publishedAt value \"${publishedAt}\" to date integer:`, error);\n return null;\n }\n }\n\n #savePostTiers(post: Post) {\n this.log('debug', `Save tiers for post #${post.id} to DB`);\n // Clear existing tiers for post\n this.log('debug', `Clear existing tiers in DB for post #${post.id} before saving current ones`);\n this.run(`DELETE FROM post_tier WHERE post_id = ?`, [\n post.id\n ]);\n post.tiers.forEach((tier) => this.#doSaveTier(post, tier));\n }\n\n #doSaveTier(post: Post, tier: Tier) {\n this.log('debug', `Add post tier #${tier.id} (${tier.title}) to DB`);\n this.run(`\n INSERT INTO post_tier (\n post_id,\n tier_id,\n campaign_id\n )\n VALUES (?, ?, ?)\n `,\n [\n post.id,\n tier.id,\n post.campaign?.id || '-1'\n ]);\n }\n\n savePostComments(post: Post, comments: Comment[]) {\n try {\n this.log('debug', `Save comments for post #${post.id}`);\n const commentsExist = this.checkPostCommentsExist(post);\n if (!commentsExist) {\n this.run(\n `\n INSERT INTO post_comments (\n post_id,\n comment_count,\n comments\n )\n VALUES (?, ?, ?)\n `,\n [\n post.id,\n post.commentCount,\n JSON.stringify(comments)\n ]\n );\n }\n else {\n this.log('debug', `Comments for post #${post.id} already exists in DB - update record`);\n this.run(\n `\n UPDATE post_comments\n SET\n comment_count = ?,\n comments = ?\n WHERE\n post_id = ?\n `,\n [\n post.commentCount,\n JSON.stringify(comments),\n post.id\n ]\n );\n }\n }\n catch (error) {\n this.log(\n 'error',\n `Failed to save comments for post #${post.id} to DB:`,\n error\n );\n throw error;\n }\n }\n\n checkPostCommentsExist(post: Post) {\n try {\n const result = this.get(\n `\n SELECT COUNT(*) as count\n FROM post_comments\n WHERE\n post_id = ?\n `,\n [ post.id ]\n );\n return result.count > 0;\n } catch (error) {\n this.log(\n 'error',\n `Failed to check if comments for post #${post.id} exist in DB:`,\n error\n );\n return false;\n }\n }\n\n getContent(id: string, contentType: 'post'): PostWithComments | null;\n getContent(id: string, contentType: 'product'): Product | null;\n getContent(id: string, contentType: ContentType) {\n this.log('debug', `Get ${contentType} #${id} from DB`);\n const result = this.get(\n `\n SELECT\n details,\n IFNULL(post_comments.comment_count, 0) AS comment_count,\n comments\n FROM\n content\n LEFT JOIN\n post_comments ON post_comments.post_id = content.content_id AND content.content_type = 'post'\n WHERE\n content_id = ? AND content_type = ?`,\n [id, contentType]\n );\n return result ? this.#parseContentRowJoinedComments(result) : null;\n }\n\n getPreviousNextContent<T extends ContentType>(\n content: Post | Product,\n context: GetContentContext<T>\n ): GetPreviousNextContentResult<T> {\n let previousWhere: string;\n let previousSortBy: ContentListSortBy;\n let nextWhere: string;\n let nextSortBy: ContentListSortBy;\n let whereValues: any[];\n const sortBy = context.sortBy ?? 'latest';\n const publishedAt = this.#publishedAtToTime(content.publishedAt);\n const title = content.type === 'post' ? content.title : content.name;\n switch (sortBy) {\n case 'a-z':\n case 'z-a': {\n const p = `\n (\n (title < ?)\n OR\n (title = ? AND published_at > ?)\n OR\n (title = ? AND published_at = ? AND content_id > ?)\n )\n `;\n const n = `\n (\n (title > ?)\n OR\n (title = ? AND published_at < ?)\n OR\n (title = ? AND published_at = ? AND content_id < ?)\n )\n `;\n whereValues = [title, title, publishedAt, title, publishedAt, content.id];\n if (sortBy === 'a-z') {\n previousWhere = p;\n previousSortBy = 'z-a';\n nextWhere = n;\n nextSortBy = 'a-z';\n }\n else { // z-a\n previousWhere = n;\n previousSortBy = 'a-z';\n nextWhere = p;\n nextSortBy = 'z-a';\n }\n break;\n }\n case 'latest':\n case 'oldest':\n case 'best_match': {\n const older = `\n (\n (published_at < ?)\n OR\n (published_at = ? AND content_id < ?)\n )\n `;\n const newer = `\n (\n (published_at > ?)\n OR\n (published_at = ? AND content_id > ?)\n )\n `;\n whereValues = [publishedAt, publishedAt, content.id];\n if (sortBy === 'latest') {\n previousWhere = newer;\n previousSortBy = 'oldest';\n nextWhere = older;\n nextSortBy = 'latest';\n }\n else { // oldest\n previousWhere = older;\n previousSortBy = 'latest';\n nextWhere = newer;\n nextSortBy = 'oldest';\n }\n break;\n }\n }\n const previous = (this.getContentList(\n {\n ...context,\n search: context.search,\n sortBy: previousSortBy,\n limit: 1, offset: 0\n },\n {\n whereClauses: [previousWhere],\n whereValues\n },\n false\n )).items[0] || null;\n const next = (this.getContentList(\n {\n ...context,\n search: context.search,\n sortBy: nextSortBy,\n limit: 1, offset: 0\n },\n {\n whereClauses: [nextWhere],\n whereValues\n },\n false\n )).items[0] || null;\n\n return {\n previous,\n next\n } as GetPreviousNextContentResult<T>;\n }\n\n getContentList<T extends ContentType>(\n params: GetContentListParams<T>,\n db?: { whereClauses: string[]; whereValues: any[]; },\n includeTotal = true\n ): ContentList<T> {\n const { campaign, type: contentType, isViewable, datePublished, search, sortBy, limit, offset } = params;\n const { whereClauses: extraWhereClauses = [], whereValues: extraWhereValues = [] } = db || {};\n const campaignId = !campaign ? null : (typeof campaign === 'string' ? campaign : campaign.id);\n const tiers = params.type === 'post' ? (params as GetContentListParams<'post'>).tiers : null;\n const collection = params.type === 'post' ? (params as GetContentListParams<'post'>).collection : null;\n const tag = params.type === 'post' ? (params as GetContentListParams<'post'>).tag : null;\n this.log('debug', `Get ${contentType}s from DB:`, {\n campaign: campaignId,\n isViewable,\n datePublished,\n search,\n tiers: params.type === 'post' ? JSON.stringify(tiers) : 'N/A',\n collection: params.type === 'post' ? JSON.stringify(collection) : 'N/A',\n tag: params.type === 'post' ? JSON.stringify(tag) : 'N/A',\n sortBy,\n limit,\n offset\n });\n const contentSubtypes = params.type === 'post' ? (params as GetContentListParams<'post'>).postTypes : null;\n if (tiers && tiers.length > 0 && !campaign) {\n throw Error('Invalid params: \"tiers\" must be used with \"campaign\"');\n }\n if (search && !contentType) {\n throw Error('Invalid params: \"search\" must be used with \"contentType\"');\n }\n const joinParts: string[] = [];\n if (tiers && tiers.length > 0) {\n joinParts.push('LEFT JOIN post_tier ON post_tier.post_id = content.content_id');\n }\n if (collection) {\n joinParts.push(`LEFT JOIN post_collection ON post_collection.post_id = content.content_id`);\n }\n if (tag) {\n joinParts.push(`LEFT JOIN post_tag_post ON post_tag_post.post_id = content.content_id AND post_tag_post.campaign_id = content.campaign_id`);\n }\n const join = joinParts.join(' ');\n const whereEquals: { column: string; value: string | number; }[] = [];\n if (campaignId) {\n whereEquals.push({ column: 'content.campaign_id', value: campaignId });\n }\n if (contentType) {\n whereEquals.push({ column: 'content_type', value: contentType });\n }\n if (isViewable !== undefined) {\n whereEquals.push({ column: 'is_viewable', value: isViewable ? 1 : 0});\n }\n if (datePublished) {\n const strftimeFormat =\n /^\\d{4}$/.test(datePublished) ? '%Y' :\n /^\\d{4}-\\d{2}$/.test(datePublished) ? '%Y-%m'\n : null;\n if (!strftimeFormat) {\n throw Error('Invalid params: \"datePublished\" must be in format \"YYYY\" or \"YYYY-MM\" (e.g. \"2025-06\")');\n }\n whereEquals.push({\n column: `strftime('${strftimeFormat}', datetime(published_at / 1000, 'unixepoch'))`,\n value: datePublished\n });\n }\n if (collection) {\n whereEquals.push({\n column: 'post_collection.collection_id',\n value: typeof collection === 'string' ? collection : collection.id\n });\n }\n if (tag) {\n whereEquals.push({\n column: 'post_tag_post.post_tag_id',\n value: typeof tag === 'string' ? tag : tag.id\n });\n }\n const whereIns: { column: string; values: (string | number)[] }[] = [];\n if (contentSubtypes && contentSubtypes.length > 0) {\n whereIns.push({ column: 'content_subtype', values: contentSubtypes})\n }\n if (tiers && tiers.length > 0) {\n const ids = tiers.map((tier) => typeof tier === 'string' ? tier : tier.id);\n whereIns.push({ column: 'tier_id', values: ids });\n }\n const whereClauseParts: string[] = [];\n if (whereEquals.length > 0) {\n whereClauseParts.push(...whereEquals.map(({column: field}) => `${field} = ?` ));\n }\n if (whereIns.length > 0) {\n whereClauseParts.push(...whereIns.map((wi) => `${wi.column} IN (${wi.values.map(() => '?').join(', ')})`));\n }\n if (search) {\n whereClauseParts.push(`${contentType}_fts MATCH ?`);\n }\n whereClauseParts.push(...extraWhereClauses);\n const whereClause = whereClauseParts.length > 0 ? 'WHERE ' + whereClauseParts.join(' AND ') : '';\n const whereValues = [\n ...whereEquals.map(({value}) => value),\n ...whereIns.reduce<(string | number)[]>((result, {values}) => {\n result.push(...values);\n return result;\n }, [])\n ];\n if (search) {\n whereValues.push(search); \n }\n whereValues.push(...extraWhereValues);\n let orderByClause: string;\n switch (sortBy) {\n case 'a-z':\n orderByClause = 'title ASC';\n break;\n case 'z-a':\n orderByClause = 'title DESC';\n break;\n case 'latest':\n orderByClause = 'published_at DESC';\n break;\n case 'oldest':\n orderByClause = 'published_at ASC';\n break;\n case 'best_match':\n orderByClause = `ORDER BY bm25(${contentType}_fts) 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\n let fromClause: string;\n if (search) {\n fromClause = `\n FROM\n ${contentType}_fts\n LEFT JOIN\n ${contentType}_fts_source ON ${contentType}_fts_source.fts_rowid = ${contentType}_fts.rowid\n LEFT JOIN\n content ON content.content_id = ${contentType}_fts_source.${contentType}_id\n `;\n } else {\n fromClause = 'FROM content';\n }\n\n const rows = this.all(\n `\n SELECT DISTINCT\n details,\n IFNULL(post_comments.comment_count, 0) AS comment_count,\n comments\n ${fromClause}\n LEFT JOIN\n post_comments ON post_comments.post_id = content.content_id AND content.content_type = 'post'\n ${join}\n ${whereClause}\n ${orderByClause}\n ${limitOffsetClause}\n `,\n [ ...whereValues, ...limitOffsetValues ]\n );\n const items = rows.map<T extends 'post' ? PostWithComments : T extends 'product' ? Product : PostWithComments | Product>((row) => this.#parseContentRowJoinedComments(row));\n const totalResult = includeTotal ? this.get(\n `SELECT COUNT(*) AS content_count ${fromClause} ${join} ${whereClause}`,\n [...whereValues]\n ) : null;\n const total = totalResult ? (totalResult.content_count as number) : 0;\n return {\n items,\n total\n };\n }\n\n /**\n * \n * @param row Must have `details`, `comment_count` and `comments`\n * @returns \n */\n #parseContentRowJoinedComments(row: any) {\n const details = JSON.parse(row.details);\n if (!Reflect.has(details, 'type')) {\n return details;\n }\n switch (details.type) {\n case 'post': {\n // `comment_count` column somehow created as string type\n // Cast it back to number as some were saved as decimals (e.g. \"2.0\")\n const commentCount = Number(row.comment_count) || 0;\n const comments = row.comments !== null ? JSON.parse(row.comments) : null;\n return {\n ...details,\n commentCount,\n comments\n } satisfies PostWithComments;\n }\n case 'product':\n default:\n return details;\n }\n }\n\n getContentCountByDate(\n contentType: ContentType,\n groupBy: 'year' | 'month',\n filter?: {\n campaign?: Campaign | string | null,\n date?: Date | null}\n ) {\n const campaign = filter?.campaign || null;\n const campaignId = !campaign ? null : (typeof campaign === 'string' ? campaign : campaign.id);\n this.log('debug', `Get ${contentType} count by date:`, {\n groupBy,\n filter: !filter ? null : {\n campaign: campaignId,\n date: filter.date\n }\n });\n const date = filter?.date || null;\n const whereClauseParts = ['content_type = ?'];\n const whereValues: string[] = [contentType];\n if (campaignId) {\n whereClauseParts.push('campaign_id = ?');\n whereValues.push(campaignId);\n }\n if (date) {\n whereClauseParts.push(`dt = ?`);\n const value = groupBy === 'year' ?\n String(date.getUTCFullYear())\n : getYearMonthString(date);\n whereValues.push(String(value));\n }\n const whereClause = `WHERE ${whereClauseParts.join(' AND ')}`;\n const strftimeFormat = groupBy === 'year' ? '%Y' : '%Y-%m'\n const rows = this.all(\n `\n SELECT\n COUNT(content_id) AS content_count,\n strftime('${strftimeFormat}',\n datetime(published_at / 1000, 'unixepoch')) AS dt\n FROM\n content\n ${whereClause}\n GROUP BY dt\n ORDER BY dt DESC\n `,\n [...whereValues]\n );\n return rows.map((row) => ({\n dt: row.dt as string,\n count: row.content_count as number\n }));\n }\n\n getPostCountByType(campaign: Campaign | string) {\n const campaignId = typeof campaign === 'string' ? campaign : campaign.id;\n this.log('debug', `Get post count by type for campaign #${campaignId}`);\n const rows = this.all(\n `\n SELECT\n COUNT(content_id) AS post_count, content_subtype AS post_type\n FROM\n content\n WHERE\n content_type = 'post' AND campaign_id = ?\n GROUP BY content_subtype \n `,\n [campaignId]\n );\n return rows.map((row) => ({\n postType: row.post_type as string,\n count: row.post_count as number\n }));\n }\n\n getPostCountByTier(campaign: Campaign | string) {\n const campaignId = typeof campaign === 'string' ? campaign : campaign.id;\n this.log('debug', `Get post count by tier for campaign #${campaignId}`);\n const rows = this.all(\n `\n SELECT\n COUNT(post_id) as post_count, tier_id, reward.title\n FROM post_tier\n RIGHT JOIN reward ON reward.reward_id = post_tier.tier_id AND reward.campaign_id = post_tier.campaign_id\n WHERE\n post_tier.campaign_id = ?\n GROUP BY\n tier_id\n `,\n [campaignId]\n );\n return rows.map((row) => ({\n tierId: row.tier_id as string,\n title: row.title as string,\n count: row.post_count as number\n }));\n }\n\n checkContentExists(id: string, contentType: ContentType, campaign?: Campaign | null) {\n this.log('debug', `Check if ${contentType} #${id} exists in DB`);\n const whereClauseParts = [\n 'content_id = ?',\n 'content_type = ?'\n ];\n const whereValues = [id, contentType];\n if (campaign !== undefined) {\n whereClauseParts.push('campaign_id = ?');\n whereValues.push(campaign?.id || '-1');\n }\n const whereClause = `WHERE ${whereClauseParts.join(' AND ')}`;\n try {\n const result = this.get(\n `\n SELECT COUNT(*) as count\n FROM content\n ${whereClause}\n `,\n whereValues\n );\n return result.count > 0;\n } catch (error) {\n this.log(\n 'error',\n `Failed to check if ${contentType} #${id} exists in DB:`,\n error\n );\n return false;\n }\n }\n\n saveCollection(collection: Collection, campaign: Campaign | null, overwriteIfExists = true) {\n this.log('debug', `Save collection #${collection.id} (${collection.title}) to DB`);\n try {\n // Normally, campaign would have already been saved to DB via\n // downloader logic, but we should still save it one more\n // time just in case. Difference is, we do not overwrite \n // DB entry if it already exists.\n this.saveCampaign(campaign, new Date(), false);\n\n const collectionExists = this.checkCollectionExists(collection.id);\n if (collectionExists && !overwriteIfExists) {\n return;\n }\n\n if (collection.thumbnail) {\n this.saveMedia(collection.thumbnail);\n }\n\n if (!collectionExists) {\n this.log('debug', `INSERT collection \"${collection.title}\" (${collection.id})`);\n this.run(\n `\n INSERT INTO collection (\n collection_id,\n campaign_id,\n title,\n created_at,\n edited_at,\n details\n )\n VALUES (?, ?, ?, ?, ?, ?)\n `,\n [\n collection.id,\n campaign?.id || '-1',\n collection.title,\n this.#publishedAtToTime(collection.createdAt),\n this.#publishedAtToTime(collection.editedAt),\n JSON.stringify(collection)\n ]\n );\n } else {\n this.log('debug', `Collection #${collection.id} already exists in DB - update record`);\n this.run(`\n UPDATE collection\n SET\n title = ?,\n created_at = ?,\n edited_at = ?,\n details = ?\n WHERE\n collection_id = ? AND\n campaign_id = ?\n `,\n [\n collection.title,\n this.#publishedAtToTime(collection.createdAt),\n this.#publishedAtToTime(collection.editedAt),\n JSON.stringify(collection),\n collection.id,\n campaign?.id || '-1'\n ]\n );\n }\n } catch (error) {\n this.log(\n 'error',\n `Failed to save collection \"${collection.title}\" (${collection.id}) to DB:`,\n error\n );\n }\n }\n\n savePostTag(tag: PostTag, campaign: Campaign | null, overwriteIfExists = true) {\n this.log('debug', `Save post_tag \"${tag.id}\" to DB`);\n try {\n // Normally, campaign would have already been saved to DB via\n // downloader logic, but we should still save it one more\n // time just in case. Difference is, we do not overwrite \n // DB entry if it already exists.\n this.saveCampaign(campaign, new Date(), false);\n\n const tagExists = this.checkPostTagExists(tag.id, campaign);\n if (tagExists && !overwriteIfExists) {\n return;\n }\n\n if (!tagExists) {\n this.log('debug', `INSERT post_tag \"${tag.id}\"`);\n this.run(\n `\n INSERT INTO post_tag (\n post_tag_id,\n campaign_id,\n value,\n details\n )\n VALUES (?, ?, ?, ?)\n `,\n [\n tag.id,\n campaign?.id || '-1',\n tag.value,\n JSON.stringify(tag)\n ]\n );\n } else {\n this.log('debug', `post_tag \"${tag.id}\" already exists in DB - update record`);\n this.run(`\n UPDATE post_tag\n SET\n value = ?,\n details = ?\n WHERE\n post_tag_id = ? AND\n campaign_id = ?\n `,\n [\n tag.value,\n JSON.stringify(tag),\n tag.id,\n campaign?.id || '-1'\n ]\n );\n }\n } catch (error) {\n this.log(\n 'error',\n `Failed to save post_tag \"${tag.id}\" to DB:`,\n error\n );\n }\n }\n\n getCollection(id: string) {\n this.log('debug', `Get collection #${id} from DB`);\n try {\n const result = this.get(\n `\n SELECT\n campaign_id,\n details,\n (SELECT COUNT(post_id) AS post_count FROM post_collection WHERE collection_id = ?) AS post_count\n FROM collection\n WHERE collection_id = ?;\n `,\n [id, id]\n );\n if (result) {\n const collection = JSON.parse(result.details) as Collection;\n collection.numPosts = result.post_count || 0;\n return {\n collection,\n campaignId: result.campaign_id as string\n };\n }\n return null;\n } catch (error) {\n this.log('error', `Failed to get collection #${id} from DB:`, error);\n return null;\n }\n }\n\n #savePostCollection(post: Post) {\n this.log('debug', `Clear post_collection for post #${post.id}`);\n this.run(`DELETE FROM post_collection WHERE post_id = ?`, [\n post.id\n ]);\n if (!post.collections || post.collections.length === 0) {\n return;\n }\n for (const collection of post.collections) {\n // Normally, collection would have already been saved to DB via\n // downloader logic, but we should still save it one more\n // time just in case. Difference is, we do not overwrite \n // DB entry if it already exists.\n this.saveCollection(collection, post.campaign, false);\n try {\n this.run(\n `\n INSERT INTO post_collection (\n collection_id,\n campaign_id,\n post_id,\n post_created_at\n )\n VALUES (?, ?, ?, ?)\n `,\n [\n collection.id,\n post.campaign?.id || '-1',\n post.id,\n this.#publishedAtToTime(collection.createdAt)\n ]\n );\n }\n catch (error) {\n this.log('error', `Failed to save post_collection for post #${post.id} -> collection #${collection.id}:`, error);\n }\n }\n }\n\n getCollectionList(params: GetCollectionListParams): CollectionList {\n const { campaign, search, sortBy, limit, offset } = params;\n const campaignId = typeof campaign === 'string' ? campaign : campaign.id;\n\n const whereClauseParts: string[] = [ 'campaign_id = ?' ];\n const whereValues: (string | number)[] = [ campaignId ];\n if (search) {\n whereClauseParts.push('collection_fts MATCH ?');\n whereValues.push(search);\n }\n const whereClause = whereClauseParts.length > 0 ? 'WHERE ' + whereClauseParts.join(' AND ') : '';\n\n let orderByClause: string;\n switch (sortBy) {\n case 'a-z':\n orderByClause = 'collection.title ASC';\n break;\n case 'z-a':\n orderByClause = 'collection.title DESC';\n break;\n case 'last_created':\n orderByClause = 'created_at DESC';\n break;\n case 'last_updated':\n orderByClause = 'edited_at DESC';\n break;\n default:\n orderByClause = '';\n }\n if (orderByClause) {\n orderByClause = `ORDER BY ${orderByClause}`;\n }\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\n let fromClause: string;\n if (search) {\n fromClause = `\n FROM\n collection_fts\n LEFT JOIN\n collection_fts_source ON collection_fts_source.fts_rowid = collection_fts.rowid\n LEFT JOIN\n collection ON collection.collection_id = collection_fts_source.collection_id\n `;\n } else {\n fromClause = 'FROM collection';\n }\n\n const rows = this.all(\n `\n SELECT\n details, post_count\n ${fromClause}\n LEFT JOIN\n (SELECT COUNT(post_id) AS post_count, collection_id FROM post_collection GROUP BY collection_id) pcc ON pcc.collection_id = collection.collection_id\n ${whereClause}\n ${orderByClause}\n ${limitOffsetClause}\n `,\n [...whereValues, ...limitOffsetValues]\n );\n const totalResult = this.get(\n `SELECT COUNT(*) AS collection_count ${fromClause} ${whereClause}`,\n [...whereValues]\n );\n const total = totalResult ? (totalResult.collection_count as number) : 0;\n const collections = rows.map((row) => {\n const collection = JSON.parse(row.details) as Collection;\n collection.numPosts = row.post_count || 0;\n return collection;\n });\n return {\n collections,\n total\n };\n }\n\n checkCollectionExists(id: string) {\n this.log('debug', `Check if collection #${id} exists in DB`);\n try {\n const result = this.get(\n `\n SELECT COUNT(*) as count\n FROM collection\n WHERE\n collection_id = ?\n `,\n [ id ]\n );\n return result.count > 0;\n } catch (error) {\n this.log(\n 'error',\n `Failed to check if collection #${id} exists in DB:`,\n error\n );\n return false;\n }\n }\n\n checkPostTagExists(id: string, campaign: Campaign | null) {\n this.log('debug', `Check if tag \"${id}\" exists in DB`);\n try {\n const result = this.get(\n `\n SELECT COUNT(*) as count\n FROM post_tag\n WHERE\n post_tag_id = ? AND\n campaign_id = ?\n `,\n [ id, campaign?.id || '-1']\n );\n return result.count > 0;\n } catch (error) {\n this.log(\n 'error',\n `Failed to check if post_tag \"${id}\" exists in DB:`,\n error\n );\n return false;\n }\n }\n\n getPostComments(post: Post | string): Comment[] | null {\n const postId = typeof post === 'string' ? post : post.id;\n this.log('debug', `Get comments for post #${postId}`);\n const result = this.get(\n `SELECT comments FROM post_comments WHERE post_id = ?`,\n [postId]\n );\n return result ? JSON.parse(result.comments) : null; \n }\n\n #savePostTags(post: Post) {\n this.log('debug', `Clear post_tag_post for post #${post.id}`);\n this.run(`DELETE FROM post_tag_post WHERE post_id = ?`, [\n post.id\n ]);\n if (!post.tags || post.tags.length === 0) {\n return;\n }\n for (const tag of post.tags) {\n this.savePostTag(tag, post.campaign, false);\n try {\n this.run(\n `\n INSERT INTO post_tag_post (\n post_tag_id,\n campaign_id,\n post_id\n )\n VALUES (?, ?, ?)\n `,\n [\n tag.id,\n post.campaign?.id || '-1',\n post.id\n ]\n );\n }\n catch (error) {\n this.log('error', `Failed to save post_tag_post for post #${post.id} -> post_tag \"${tag.id}\":`, error);\n }\n }\n }\n\n getPostTagList(params: GetPostTagListParams): PostTagList {\n const { campaign } = params;\n const campaignId = typeof campaign === 'string' ? campaign : campaign.id;\n\n const whereClauseParts: string[] = [ 'campaign_id = ?' ];\n const whereValues: (string | number)[] = [ campaignId ]; \n const whereClause = `WHERE ${whereClauseParts.join(' AND ')}`;\n const orderByClause = 'ORDER BY post_tag.value ASC';\n const fromClause = 'FROM post_tag';\n\n const rows = this.all(\n `\n SELECT\n details\n ${fromClause}\n ${whereClause}\n ${orderByClause}\n `,\n [...whereValues]\n );\n const totalResult = this.get(\n `SELECT COUNT(*) AS tag_count ${fromClause} ${whereClause}`,\n [...whereValues]\n );\n const total = totalResult ? (totalResult.tag_count as number) : 0;\n const tags = rows.map((row) => {\n return JSON.parse(row.details) as PostTag;\n });\n return {\n tags,\n total\n };\n }\n };\n}\n"]}
1
+ {"version":3,"file":"ContentDBMixin.js","sourceRoot":"","sources":["../../../src/browse/db/ContentDBMixin.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Comment, type Downloadable, type Post, type Product, type Tier, type Campaign } from '../../entities';\nimport { type PostTag, type Collection } from '../../entities/Post';\nimport { getYearMonthString, type KeysOfValue } from '../../utils/Misc.js';\nimport { type GetContentContext, type GetPreviousNextContentResult, type ContentList, type ContentType, type GetContentListParams, type PostWithComments, type ContentListSortBy, type GetCollectionListParams, type CollectionList, type GetPostTagListParams, type PostTagList } from '../types/Content.js';\nimport { type CampaignDBConstructor } from './CampaignDBMixin.js';\n\nexport function ContentDBMixin<TBase extends CampaignDBConstructor>(Base: TBase) {\n return class ContentDB extends Base {\n saveContent(content: Post | Product) {\n const title = content.type === 'post' ? content.title : content.name;\n this.log('debug', `Save ${content.type} #${content.id} (${title}) to DB`);\n try {\n // Normally, campaign would have already been saved to DB via\n // downloader logic, but we should still save it one more\n // time just in case. Difference is, we do not overwrite \n // DB entry if it already exists.\n this.saveCampaign(content.campaign, new Date(), false);\n\n const contentExists = this.checkContentExists(content.id, content.type, content.campaign);\n this.exec('BEGIN TRANSACTION');\n\n if (!contentExists) {\n this.log('debug', `INSERT ${content.type} \"${title}\" (${content.id})`);\n this.run(\n `\n INSERT INTO content (\n content_id,\n content_type,\n campaign_id,\n title,\n content_subtype,\n is_viewable,\n published_at,\n details\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `,\n [\n content.id,\n content.type,\n content.campaign?.id || '-1',\n title,\n content.type === 'post' ? content.postType : content.productType || null,\n (content.type === 'post' ? content.isViewable : content.isAccessible) ? 1 : 0,\n this.#publishedAtToTime(content.publishedAt),\n JSON.stringify(content)\n ]\n );\n } else {\n this.log('debug', `${content.type} #${content.id} already exists in DB - update record`);\n this.run(`\n UPDATE content\n SET\n content_type = ?,\n campaign_id = ?,\n title = ?,\n content_subtype = ?,\n is_viewable = ?,\n published_at = ?,\n details = ?\n WHERE content_id = ?\n `,\n [\n content.type,\n content.campaign?.id || '-1',\n title,\n content.type === 'post' ? content.postType : content.productType || null,\n (content.type === 'post' ? content.isViewable : content.isAccessible) ? 1 : 0,\n this.#publishedAtToTime(content.publishedAt),\n JSON.stringify(content),\n content.id\n ]\n );\n }\n\n // Save content media\n this.#saveContentMedia(content);\n\n // Save tiers and collections and tags\n if (content.type === 'post') {\n this.#savePostTiers(content);\n this.#savePostCollection(content);\n this.#savePostTags(content);\n }\n\n this.exec('COMMIT');\n } catch (error) {\n this.log(\n 'error',\n `Failed to save content \"${title}\" (${content.id}) to DB:`,\n error\n );\n this.exec('ROLLBACK');\n }\n }\n\n #saveContentMedia(\n content: Post | Product\n ) {\n this.log('debug', `Save media for ${content.type} #${content.id} to DB`);\n switch (content.type) {\n case 'post':\n this.#savepostMedia(content);\n break;\n case 'product':\n this.#saveProductMedia(content);\n break;\n }\n }\n\n #savepostMedia(post: Post) {\n const mediaProps: KeysOfValue<Post, Downloadable | Downloadable[] | null>[] = [\n 'embed',\n 'attachments',\n 'audio',\n 'audioPreview',\n 'images',\n 'videoPreview',\n 'video'\n ];\n if (post.coverImage) {\n this.saveMedia(post.coverImage);\n }\n if (post.thumbnail) {\n this.saveMedia(post.thumbnail);\n }\n for (const prop of mediaProps) {\n if (post[prop]) {\n const data = post[prop];\n const downloadables = (Array.isArray(data) ? data : [data])\n .filter((data) => data !== undefined);\n downloadables.forEach((dl, index) => this.#doSaveContentMedia(\n post,\n dl,\n index,\n prop === 'audioPreview'||\n prop === 'videoPreview' ||\n (prop === 'images' && !post.isViewable)\n ));\n }\n }\n }\n\n #saveProductMedia(product: Product) {\n const mediaProps: KeysOfValue<Product, Downloadable[]>[] = [\n 'contentMedia',\n 'previewMedia'\n ];\n for (const prop of mediaProps) {\n if (product[prop]) {\n const data = product[prop];\n const downloadables = (Array.isArray(data) ? data : [data])\n .filter((data) => data !== undefined);\n downloadables.forEach((dl, index) => this.#doSaveContentMedia(\n product,\n dl,\n index,\n prop === 'previewMedia'\n ));\n }\n }\n }\n\n #doSaveContentMedia(\n content: Post | Product,\n media: Downloadable,\n mediaIndex: number,\n isPreview: boolean\n ) {\n if (!media.downloaded || !media.downloaded.path) {\n return;\n }\n this.log('debug',\n `Save ${content.type} media to DB`,\n `(${content.type} ID: ${content.id}, media ID: ${media.id})`\n );\n this.saveMedia(media);\n try {\n const contentMediaExists = this.checkContentMediaExists(content, media);\n if (!contentMediaExists) {\n this.run(\n `\n INSERT INTO content_media (\n media_id,\n content_id,\n content_type,\n media_index,\n campaign_id,\n is_preview\n )\n VALUES (?, ?, ?, ?, ?, ?)\n `,\n [\n media.id,\n content.id,\n content.type,\n mediaIndex,\n content.campaign?.id || '-1',\n isPreview ? 1 : 0\n ]\n );\n }\n else {\n this.log('debug',\n `${content.type} media already exists in DB`,\n `(${content.type} ID: ${content.id}, media ID: ${media.id})`,\n '- update record'\n );\n this.run(\n `\n UPDATE content_media\n SET\n content_id = ?,\n content_type = ?,\n media_index = ?,\n campaign_id = ?,\n is_preview = ?\n WHERE\n media_id = ?\n `,\n [\n content.id,\n content.type,\n mediaIndex,\n content.campaign?.id || '-1',\n isPreview ? 1 : 0,\n media.id,\n ]\n );\n }\n }\n catch (error) {\n this.log(\n 'error',\n `Failed to save content media (type: ${content.type}, content_id: ${content.id}, media_id: ${media.id}) to DB:`,\n error\n );\n throw error;\n }\n }\n\n #publishedAtToTime(publishedAt: string | null) {\n try {\n if (!publishedAt) {\n return null;\n }\n return new Date(publishedAt).getTime();\n }\n catch (error) {\n this.log('warn', `Failed to convert publishedAt value \"${publishedAt}\" to date integer:`, error);\n return null;\n }\n }\n\n #savePostTiers(post: Post) {\n this.log('debug', `Save tiers for post #${post.id} to DB`);\n // Clear existing tiers for post\n this.log('debug', `Clear existing tiers in DB for post #${post.id} before saving current ones`);\n this.run(`DELETE FROM post_tier WHERE post_id = ?`, [\n post.id\n ]);\n post.tiers.forEach((tier) => this.#doSaveTier(post, tier));\n }\n\n #doSaveTier(post: Post, tier: Tier) {\n this.log('debug', `Add post tier #${tier.id} (${tier.title}) to DB`);\n this.run(`\n INSERT INTO post_tier (\n post_id,\n tier_id,\n campaign_id\n )\n VALUES (?, ?, ?)\n `,\n [\n post.id,\n tier.id,\n post.campaign?.id || '-1'\n ]);\n }\n\n savePostComments(post: Post, comments: Comment[]) {\n try {\n this.log('debug', `Save comments for post #${post.id}`);\n const commentsExist = this.checkPostCommentsExist(post);\n if (!commentsExist) {\n this.run(\n `\n INSERT INTO post_comments (\n post_id,\n comment_count,\n comments\n )\n VALUES (?, ?, ?)\n `,\n [\n post.id,\n post.commentCount,\n JSON.stringify(comments)\n ]\n );\n }\n else {\n this.log('debug', `Comments for post #${post.id} already exists in DB - update record`);\n this.run(\n `\n UPDATE post_comments\n SET\n comment_count = ?,\n comments = ?\n WHERE\n post_id = ?\n `,\n [\n post.commentCount,\n JSON.stringify(comments),\n post.id\n ]\n );\n }\n }\n catch (error) {\n this.log(\n 'error',\n `Failed to save comments for post #${post.id} to DB:`,\n error\n );\n throw error;\n }\n }\n\n checkPostCommentsExist(post: Post) {\n try {\n const result = this.get(\n `\n SELECT COUNT(*) as count\n FROM post_comments\n WHERE\n post_id = ?\n `,\n [ post.id ]\n );\n return result.count > 0;\n } catch (error) {\n this.log(\n 'error',\n `Failed to check if comments for post #${post.id} exist in DB:`,\n error\n );\n return false;\n }\n }\n\n getContent(id: string, contentType: 'post'): PostWithComments | null;\n getContent(id: string, contentType: 'product'): Product | null;\n getContent(id: string, contentType: ContentType) {\n this.log('debug', `Get ${contentType} #${id} from DB`);\n const result = this.get(\n `\n SELECT\n details,\n IFNULL(post_comments.comment_count, 0) AS comment_count,\n comments\n FROM\n content\n LEFT JOIN\n post_comments ON post_comments.post_id = content.content_id AND content.content_type = 'post'\n WHERE\n content_id = ? AND content_type = ?`,\n [id, contentType]\n );\n return result ? this.#parseContentRowJoinedComments(result) : null;\n }\n\n getPreviousNextContent<T extends ContentType>(\n content: Post | Product,\n context: GetContentContext<T>\n ): GetPreviousNextContentResult<T> {\n let previousWhere: string;\n let previousSortBy: ContentListSortBy;\n let nextWhere: string;\n let nextSortBy: ContentListSortBy;\n let whereValues: any[];\n const sortBy = context.sortBy ?? 'latest';\n const publishedAt = this.#publishedAtToTime(content.publishedAt);\n const title = content.type === 'post' ? content.title : content.name;\n switch (sortBy) {\n case 'a-z':\n case 'z-a': {\n const p = `\n (\n (title < ?)\n OR\n (title = ? AND published_at > ?)\n OR\n (title = ? AND published_at = ? AND content_id > ?)\n )\n `;\n const n = `\n (\n (title > ?)\n OR\n (title = ? AND published_at < ?)\n OR\n (title = ? AND published_at = ? AND content_id < ?)\n )\n `;\n whereValues = [title, title, publishedAt, title, publishedAt, content.id];\n if (sortBy === 'a-z') {\n previousWhere = p;\n previousSortBy = 'z-a';\n nextWhere = n;\n nextSortBy = 'a-z';\n }\n else { // z-a\n previousWhere = n;\n previousSortBy = 'a-z';\n nextWhere = p;\n nextSortBy = 'z-a';\n }\n break;\n }\n case 'latest':\n case 'oldest':\n case 'best_match': {\n const older = `\n (\n (published_at < ?)\n OR\n (published_at = ? AND content_id < ?)\n )\n `;\n const newer = `\n (\n (published_at > ?)\n OR\n (published_at = ? AND content_id > ?)\n )\n `;\n whereValues = [publishedAt, publishedAt, content.id];\n if (sortBy === 'latest') {\n previousWhere = newer;\n previousSortBy = 'oldest';\n nextWhere = older;\n nextSortBy = 'latest';\n }\n else { // oldest\n previousWhere = older;\n previousSortBy = 'latest';\n nextWhere = newer;\n nextSortBy = 'oldest';\n }\n break;\n }\n }\n const previous = (this.getContentList(\n {\n ...context,\n search: context.search,\n sortBy: previousSortBy,\n limit: 1, offset: 0\n },\n {\n whereClauses: [previousWhere],\n whereValues\n },\n false\n )).items[0] || null;\n const next = (this.getContentList(\n {\n ...context,\n search: context.search,\n sortBy: nextSortBy,\n limit: 1, offset: 0\n },\n {\n whereClauses: [nextWhere],\n whereValues\n },\n false\n )).items[0] || null;\n\n return {\n previous,\n next\n } as GetPreviousNextContentResult<T>;\n }\n\n getContentList<T extends ContentType>(\n params: GetContentListParams<T>,\n db?: { whereClauses: string[]; whereValues: any[]; },\n includeTotal = true\n ): ContentList<T> {\n const { campaign, type: contentType, isViewable, datePublished, search, sortBy, limit, offset } = params;\n const { whereClauses: extraWhereClauses = [], whereValues: extraWhereValues = [] } = db || {};\n const campaignId = !campaign ? null : (typeof campaign === 'string' ? campaign : campaign.id);\n const tiers = params.type === 'post' ? (params as GetContentListParams<'post'>).tiers : null;\n const collection = params.type === 'post' ? (params as GetContentListParams<'post'>).collection : null;\n const tag = params.type === 'post' ? (params as GetContentListParams<'post'>).tag : null;\n this.log('debug', `Get ${contentType}s from DB:`, {\n campaign: campaignId,\n isViewable,\n datePublished,\n search,\n tiers: params.type === 'post' ? JSON.stringify(tiers) : 'N/A',\n collection: params.type === 'post' ? JSON.stringify(collection) : 'N/A',\n tag: params.type === 'post' ? JSON.stringify(tag) : 'N/A',\n sortBy,\n limit,\n offset\n });\n const contentSubtypes = params.type === 'post' ? (params as GetContentListParams<'post'>).postTypes : null;\n if (tiers && tiers.length > 0 && !campaign) {\n throw Error('Invalid params: \"tiers\" must be used with \"campaign\"');\n }\n if (search && !contentType) {\n throw Error('Invalid params: \"search\" must be used with \"contentType\"');\n }\n const joinParts: string[] = [];\n if (tiers && tiers.length > 0) {\n joinParts.push('LEFT JOIN post_tier ON post_tier.post_id = content.content_id');\n }\n if (collection) {\n joinParts.push(`LEFT JOIN post_collection ON post_collection.post_id = content.content_id`);\n }\n if (tag) {\n joinParts.push(`LEFT JOIN post_tag_post ON post_tag_post.post_id = content.content_id AND post_tag_post.campaign_id = content.campaign_id`);\n }\n const join = joinParts.join(' ');\n const whereEquals: { column: string; value: string | number; }[] = [];\n if (campaignId) {\n whereEquals.push({ column: 'content.campaign_id', value: campaignId });\n }\n if (contentType) {\n whereEquals.push({ column: 'content_type', value: contentType });\n }\n if (isViewable !== undefined) {\n whereEquals.push({ column: 'is_viewable', value: isViewable ? 1 : 0});\n }\n if (datePublished) {\n const strftimeFormat =\n /^\\d{4}$/.test(datePublished) ? '%Y' :\n /^\\d{4}-\\d{2}$/.test(datePublished) ? '%Y-%m'\n : null;\n if (!strftimeFormat) {\n throw Error('Invalid params: \"datePublished\" must be in format \"YYYY\" or \"YYYY-MM\" (e.g. \"2025-06\")');\n }\n whereEquals.push({\n column: `strftime('${strftimeFormat}', datetime(published_at / 1000, 'unixepoch'))`,\n value: datePublished\n });\n }\n if (collection) {\n whereEquals.push({\n column: 'post_collection.collection_id',\n value: typeof collection === 'string' ? collection : collection.id\n });\n }\n if (tag) {\n whereEquals.push({\n column: 'post_tag_post.post_tag_id',\n value: typeof tag === 'string' ? tag : tag.id\n });\n }\n const whereIns: { column: string; values: (string | number)[] }[] = [];\n if (contentSubtypes && contentSubtypes.length > 0) {\n whereIns.push({ column: 'content_subtype', values: contentSubtypes})\n }\n if (tiers && tiers.length > 0) {\n const ids = tiers.map((tier) => typeof tier === 'string' ? tier : tier.id);\n whereIns.push({ column: 'tier_id', values: ids });\n }\n const whereClauseParts: string[] = [];\n if (whereEquals.length > 0) {\n whereClauseParts.push(...whereEquals.map(({column: field}) => `${field} = ?` ));\n }\n if (whereIns.length > 0) {\n whereClauseParts.push(...whereIns.map((wi) => `${wi.column} IN (${wi.values.map(() => '?').join(', ')})`));\n }\n if (search) {\n whereClauseParts.push(`${contentType}_fts MATCH ?`);\n }\n whereClauseParts.push(...extraWhereClauses);\n const whereClause = whereClauseParts.length > 0 ? 'WHERE ' + whereClauseParts.join(' AND ') : '';\n const whereValues = [\n ...whereEquals.map(({value}) => value),\n ...whereIns.reduce<(string | number)[]>((result, {values}) => {\n result.push(...values);\n return result;\n }, [])\n ];\n if (search) {\n whereValues.push(search); \n }\n whereValues.push(...extraWhereValues);\n let orderByClause: string;\n switch (sortBy) {\n case 'a-z':\n orderByClause = 'title ASC';\n break;\n case 'z-a':\n orderByClause = 'title DESC';\n break;\n case 'latest':\n orderByClause = 'published_at DESC';\n break;\n case 'oldest':\n orderByClause = 'published_at ASC';\n break;\n case 'best_match':\n orderByClause = `ORDER BY bm25(${contentType}_fts) 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\n let fromClause: string;\n if (search) {\n fromClause = `\n FROM\n ${contentType}_fts\n LEFT JOIN\n ${contentType}_fts_source ON ${contentType}_fts_source.fts_rowid = ${contentType}_fts.rowid\n LEFT JOIN\n content ON content.content_id = ${contentType}_fts_source.${contentType}_id\n `;\n } else {\n fromClause = 'FROM content';\n }\n\n const rows = this.all(\n `\n SELECT DISTINCT\n details,\n IFNULL(post_comments.comment_count, 0) AS comment_count,\n comments\n ${fromClause}\n LEFT JOIN\n post_comments ON post_comments.post_id = content.content_id AND content.content_type = 'post'\n ${join}\n ${whereClause}\n ${orderByClause}\n ${limitOffsetClause}\n `,\n [ ...whereValues, ...limitOffsetValues ]\n );\n const items = rows.map<T extends 'post' ? PostWithComments : T extends 'product' ? Product : PostWithComments | Product>((row) => this.#parseContentRowJoinedComments(row));\n const totalResult = includeTotal ? this.get(\n `SELECT COUNT(*) AS content_count ${fromClause} ${join} ${whereClause}`,\n [...whereValues]\n ) : null;\n const total = totalResult ? (totalResult.content_count as number) : 0;\n return {\n items,\n total\n };\n }\n\n /**\n * \n * @param row Must have `details`, `comment_count` and `comments`\n * @returns \n */\n #parseContentRowJoinedComments(row: any) {\n const details = JSON.parse(row.details);\n if (!Reflect.has(details, 'type')) {\n return details;\n }\n switch (details.type) {\n case 'post': {\n // `comment_count` column somehow created as string type\n // Cast it back to number as some were saved as decimals (e.g. \"2.0\")\n const commentCount = Number(row.comment_count) || 0;\n const comments = row.comments !== null ? JSON.parse(row.comments) : null;\n return {\n ...details,\n commentCount,\n comments\n } satisfies PostWithComments;\n }\n case 'product':\n default:\n return details;\n }\n }\n\n getContentCountByDate(\n contentType: ContentType,\n groupBy: 'year' | 'month',\n filter?: {\n campaign?: Campaign | string | null,\n date?: Date | null}\n ) {\n const campaign = filter?.campaign || null;\n const campaignId = !campaign ? null : (typeof campaign === 'string' ? campaign : campaign.id);\n this.log('debug', `Get ${contentType} count by date:`, {\n groupBy,\n filter: !filter ? null : {\n campaign: campaignId,\n date: filter.date\n }\n });\n const date = filter?.date || null;\n const whereClauseParts = ['content_type = ?'];\n const whereValues: string[] = [contentType];\n if (campaignId) {\n whereClauseParts.push('campaign_id = ?');\n whereValues.push(campaignId);\n }\n if (date) {\n whereClauseParts.push(`dt = ?`);\n const value = groupBy === 'year' ?\n String(date.getUTCFullYear())\n : getYearMonthString(date);\n whereValues.push(value);\n }\n const whereClause = `WHERE ${whereClauseParts.join(' AND ')}`;\n const strftimeFormat = groupBy === 'year' ? '%Y' : '%Y-%m'\n const rows = this.all(\n `\n SELECT\n COUNT(content_id) AS content_count,\n strftime('${strftimeFormat}',\n datetime(published_at / 1000, 'unixepoch')) AS dt\n FROM\n content\n ${whereClause}\n GROUP BY dt\n ORDER BY dt DESC\n `,\n [...whereValues]\n );\n return rows.map((row) => ({\n dt: row.dt as string,\n count: row.content_count as number\n }));\n }\n\n getPostCountByType(campaign: Campaign | string) {\n const campaignId = typeof campaign === 'string' ? campaign : campaign.id;\n this.log('debug', `Get post count by type for campaign #${campaignId}`);\n const rows = this.all(\n `\n SELECT\n COUNT(content_id) AS post_count, content_subtype AS post_type\n FROM\n content\n WHERE\n content_type = 'post' AND campaign_id = ?\n GROUP BY content_subtype \n `,\n [campaignId]\n );\n return rows.map((row) => ({\n postType: row.post_type as string,\n count: row.post_count as number\n }));\n }\n\n getPostCountByTier(campaign: Campaign | string) {\n const campaignId = typeof campaign === 'string' ? campaign : campaign.id;\n this.log('debug', `Get post count by tier for campaign #${campaignId}`);\n const rows = this.all(\n `\n SELECT\n COUNT(post_id) as post_count, tier_id, reward.title\n FROM post_tier\n RIGHT JOIN reward ON reward.reward_id = post_tier.tier_id AND reward.campaign_id = post_tier.campaign_id\n WHERE\n post_tier.campaign_id = ?\n GROUP BY\n tier_id\n `,\n [campaignId]\n );\n return rows.map((row) => ({\n tierId: row.tier_id as string,\n title: row.title as string,\n count: row.post_count as number\n }));\n }\n\n checkContentExists(id: string, contentType: ContentType, campaign?: Campaign | null) {\n this.log('debug', `Check if ${contentType} #${id} exists in DB`);\n const whereClauseParts = [\n 'content_id = ?',\n 'content_type = ?'\n ];\n const whereValues = [id, contentType];\n if (campaign !== undefined) {\n whereClauseParts.push('campaign_id = ?');\n whereValues.push(campaign?.id || '-1');\n }\n const whereClause = `WHERE ${whereClauseParts.join(' AND ')}`;\n try {\n const result = this.get(\n `\n SELECT COUNT(*) as count\n FROM content\n ${whereClause}\n `,\n whereValues\n );\n return result.count > 0;\n } catch (error) {\n this.log(\n 'error',\n `Failed to check if ${contentType} #${id} exists in DB:`,\n error\n );\n return false;\n }\n }\n\n saveCollection(collection: Collection, campaign: Campaign | null, overwriteIfExists = true) {\n this.log('debug', `Save collection #${collection.id} (${collection.title}) to DB`);\n try {\n // Normally, campaign would have already been saved to DB via\n // downloader logic, but we should still save it one more\n // time just in case. Difference is, we do not overwrite \n // DB entry if it already exists.\n this.saveCampaign(campaign, new Date(), false);\n\n const collectionExists = this.checkCollectionExists(collection.id);\n if (collectionExists && !overwriteIfExists) {\n return;\n }\n\n if (collection.thumbnail) {\n this.saveMedia(collection.thumbnail);\n }\n\n if (!collectionExists) {\n this.log('debug', `INSERT collection \"${collection.title}\" (${collection.id})`);\n this.run(\n `\n INSERT INTO collection (\n collection_id,\n campaign_id,\n title,\n created_at,\n edited_at,\n details\n )\n VALUES (?, ?, ?, ?, ?, ?)\n `,\n [\n collection.id,\n campaign?.id || '-1',\n collection.title,\n this.#publishedAtToTime(collection.createdAt),\n this.#publishedAtToTime(collection.editedAt),\n JSON.stringify(collection)\n ]\n );\n } else {\n this.log('debug', `Collection #${collection.id} already exists in DB - update record`);\n this.run(`\n UPDATE collection\n SET\n title = ?,\n created_at = ?,\n edited_at = ?,\n details = ?\n WHERE\n collection_id = ? AND\n campaign_id = ?\n `,\n [\n collection.title,\n this.#publishedAtToTime(collection.createdAt),\n this.#publishedAtToTime(collection.editedAt),\n JSON.stringify(collection),\n collection.id,\n campaign?.id || '-1'\n ]\n );\n }\n } catch (error) {\n this.log(\n 'error',\n `Failed to save collection \"${collection.title}\" (${collection.id}) to DB:`,\n error\n );\n }\n }\n\n savePostTag(tag: PostTag, campaign: Campaign | null, overwriteIfExists = true) {\n this.log('debug', `Save post_tag \"${tag.id}\" to DB`);\n try {\n // Normally, campaign would have already been saved to DB via\n // downloader logic, but we should still save it one more\n // time just in case. Difference is, we do not overwrite \n // DB entry if it already exists.\n this.saveCampaign(campaign, new Date(), false);\n\n const tagExists = this.checkPostTagExists(tag.id, campaign);\n if (tagExists && !overwriteIfExists) {\n return;\n }\n\n if (!tagExists) {\n this.log('debug', `INSERT post_tag \"${tag.id}\"`);\n this.run(\n `\n INSERT INTO post_tag (\n post_tag_id,\n campaign_id,\n value,\n details\n )\n VALUES (?, ?, ?, ?)\n `,\n [\n tag.id,\n campaign?.id || '-1',\n tag.value,\n JSON.stringify(tag)\n ]\n );\n } else {\n this.log('debug', `post_tag \"${tag.id}\" already exists in DB - update record`);\n this.run(`\n UPDATE post_tag\n SET\n value = ?,\n details = ?\n WHERE\n post_tag_id = ? AND\n campaign_id = ?\n `,\n [\n tag.value,\n JSON.stringify(tag),\n tag.id,\n campaign?.id || '-1'\n ]\n );\n }\n } catch (error) {\n this.log(\n 'error',\n `Failed to save post_tag \"${tag.id}\" to DB:`,\n error\n );\n }\n }\n\n getCollection(id: string) {\n this.log('debug', `Get collection #${id} from DB`);\n try {\n const result = this.get(\n `\n SELECT\n campaign_id,\n details,\n (SELECT COUNT(post_id) AS post_count FROM post_collection WHERE collection_id = ?) AS post_count\n FROM collection\n WHERE collection_id = ?;\n `,\n [id, id]\n );\n if (result) {\n const collection = JSON.parse(result.details) as Collection;\n collection.numPosts = result.post_count || 0;\n return {\n collection,\n campaignId: result.campaign_id as string\n };\n }\n return null;\n } catch (error) {\n this.log('error', `Failed to get collection #${id} from DB:`, error);\n return null;\n }\n }\n\n #savePostCollection(post: Post) {\n this.log('debug', `Clear post_collection for post #${post.id}`);\n this.run(`DELETE FROM post_collection WHERE post_id = ?`, [\n post.id\n ]);\n if (!post.collections || post.collections.length === 0) {\n return;\n }\n for (const collection of post.collections) {\n // Normally, collection would have already been saved to DB via\n // downloader logic, but we should still save it one more\n // time just in case. Difference is, we do not overwrite \n // DB entry if it already exists.\n this.saveCollection(collection, post.campaign, false);\n try {\n this.run(\n `\n INSERT INTO post_collection (\n collection_id,\n campaign_id,\n post_id,\n post_created_at\n )\n VALUES (?, ?, ?, ?)\n `,\n [\n collection.id,\n post.campaign?.id || '-1',\n post.id,\n this.#publishedAtToTime(collection.createdAt)\n ]\n );\n }\n catch (error) {\n this.log('error', `Failed to save post_collection for post #${post.id} -> collection #${collection.id}:`, error);\n }\n }\n }\n\n getCollectionList(params: GetCollectionListParams): CollectionList {\n const { campaign, search, sortBy, limit, offset } = params;\n const campaignId = typeof campaign === 'string' ? campaign : campaign.id;\n\n const whereClauseParts: string[] = [ 'campaign_id = ?' ];\n const whereValues: (string | number)[] = [ campaignId ];\n if (search) {\n whereClauseParts.push('collection_fts MATCH ?');\n whereValues.push(search);\n }\n const whereClause = whereClauseParts.length > 0 ? 'WHERE ' + whereClauseParts.join(' AND ') : '';\n\n let orderByClause: string;\n switch (sortBy) {\n case 'a-z':\n orderByClause = 'collection.title ASC';\n break;\n case 'z-a':\n orderByClause = 'collection.title DESC';\n break;\n case 'last_created':\n orderByClause = 'created_at DESC';\n break;\n case 'last_updated':\n orderByClause = 'edited_at DESC';\n break;\n default:\n orderByClause = '';\n }\n if (orderByClause) {\n orderByClause = `ORDER BY ${orderByClause}`;\n }\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\n let fromClause: string;\n if (search) {\n fromClause = `\n FROM\n collection_fts\n LEFT JOIN\n collection_fts_source ON collection_fts_source.fts_rowid = collection_fts.rowid\n LEFT JOIN\n collection ON collection.collection_id = collection_fts_source.collection_id\n `;\n } else {\n fromClause = 'FROM collection';\n }\n\n const rows = this.all(\n `\n SELECT\n details, post_count\n ${fromClause}\n LEFT JOIN\n (SELECT COUNT(post_id) AS post_count, collection_id FROM post_collection GROUP BY collection_id) pcc ON pcc.collection_id = collection.collection_id\n ${whereClause}\n ${orderByClause}\n ${limitOffsetClause}\n `,\n [...whereValues, ...limitOffsetValues]\n );\n const totalResult = this.get(\n `SELECT COUNT(*) AS collection_count ${fromClause} ${whereClause}`,\n [...whereValues]\n );\n const total = totalResult ? (totalResult.collection_count as number) : 0;\n const collections = rows.map((row) => {\n const collection = JSON.parse(row.details) as Collection;\n collection.numPosts = row.post_count || 0;\n return collection;\n });\n return {\n collections,\n total\n };\n }\n\n checkCollectionExists(id: string) {\n this.log('debug', `Check if collection #${id} exists in DB`);\n try {\n const result = this.get(\n `\n SELECT COUNT(*) as count\n FROM collection\n WHERE\n collection_id = ?\n `,\n [ id ]\n );\n return result.count > 0;\n } catch (error) {\n this.log(\n 'error',\n `Failed to check if collection #${id} exists in DB:`,\n error\n );\n return false;\n }\n }\n\n checkPostTagExists(id: string, campaign: Campaign | null) {\n this.log('debug', `Check if tag \"${id}\" exists in DB`);\n try {\n const result = this.get(\n `\n SELECT COUNT(*) as count\n FROM post_tag\n WHERE\n post_tag_id = ? AND\n campaign_id = ?\n `,\n [ id, campaign?.id || '-1']\n );\n return result.count > 0;\n } catch (error) {\n this.log(\n 'error',\n `Failed to check if post_tag \"${id}\" exists in DB:`,\n error\n );\n return false;\n }\n }\n\n getPostComments(post: Post | string): Comment[] | null {\n const postId = typeof post === 'string' ? post : post.id;\n this.log('debug', `Get comments for post #${postId}`);\n const result = this.get(\n `SELECT comments FROM post_comments WHERE post_id = ?`,\n [postId]\n );\n return result ? JSON.parse(result.comments) : null; \n }\n\n #savePostTags(post: Post) {\n this.log('debug', `Clear post_tag_post for post #${post.id}`);\n this.run(`DELETE FROM post_tag_post WHERE post_id = ?`, [\n post.id\n ]);\n if (!post.tags || post.tags.length === 0) {\n return;\n }\n for (const tag of post.tags) {\n this.savePostTag(tag, post.campaign, false);\n try {\n this.run(\n `\n INSERT INTO post_tag_post (\n post_tag_id,\n campaign_id,\n post_id\n )\n VALUES (?, ?, ?)\n `,\n [\n tag.id,\n post.campaign?.id || '-1',\n post.id\n ]\n );\n }\n catch (error) {\n this.log('error', `Failed to save post_tag_post for post #${post.id} -> post_tag \"${tag.id}\":`, error);\n }\n }\n }\n\n getPostTagList(params: GetPostTagListParams): PostTagList {\n const { campaign } = params;\n const campaignId = typeof campaign === 'string' ? campaign : campaign.id;\n\n const whereClauseParts: string[] = [ 'campaign_id = ?' ];\n const whereValues: (string | number)[] = [ campaignId ]; \n const whereClause = `WHERE ${whereClauseParts.join(' AND ')}`;\n const orderByClause = 'ORDER BY post_tag.value ASC';\n const fromClause = 'FROM post_tag';\n\n const rows = this.all(\n `\n SELECT\n details\n ${fromClause}\n ${whereClause}\n ${orderByClause}\n `,\n [...whereValues]\n );\n const totalResult = this.get(\n `SELECT COUNT(*) AS tag_count ${fromClause} ${whereClause}`,\n [...whereValues]\n );\n const total = totalResult ? (totalResult.tag_count as number) : 0;\n const tags = rows.map((row) => {\n return JSON.parse(row.details) as PostTag;\n });\n return {\n tags,\n total\n };\n }\n };\n}\n"]}
@@ -276,7 +276,7 @@ export function MediaDBMixin(Base) {
276
276
  const value = groupBy === 'year' ?
277
277
  String(date.getUTCFullYear())
278
278
  : getYearMonthString(date);
279
- whereValues.push(String(value));
279
+ whereValues.push(value);
280
280
  }
281
281
  const whereClause = whereClauseParts.join(' AND ');
282
282
  const strftimeFormat = groupBy === 'year' ? '%Y' : '%Y-%m';