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