patreon-dl 3.6.1 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +23 -0
- package/README.md +13 -5
- package/bin/patreon-dl-vimeo.js +7 -4
- package/dist/browse/api/CampaignAPIMixin.d.ts +1 -1
- package/dist/browse/api/ContentAPIMixin.d.ts +4 -1
- package/dist/browse/api/ContentAPIMixin.js +44 -11
- package/dist/browse/api/ContentAPIMixin.js.map +1 -1
- package/dist/browse/api/FilterAPIMixin.d.ts +1 -1
- package/dist/browse/api/SettingsAPIMixin.d.ts +1 -0
- package/dist/browse/api/SettingsAPIMixin.js +4 -2
- package/dist/browse/api/SettingsAPIMixin.js.map +1 -1
- package/dist/browse/api/index.d.ts +12 -6
- package/dist/browse/db/CampaignDBMixin.d.ts +3 -3
- package/dist/browse/db/ContentDBMixin.d.ts +14 -14
- package/dist/browse/db/ContentDBMixin.js +12 -5
- package/dist/browse/db/ContentDBMixin.js.map +1 -1
- package/dist/browse/db/index.d.ts +17 -17
- package/dist/browse/server/handler/SettingsAPIRequestHandler.js +2 -1
- package/dist/browse/server/handler/SettingsAPIRequestHandler.js.map +1 -1
- package/dist/browse/types/Settings.d.ts +3 -0
- package/dist/browse/types/Settings.js.map +1 -1
- package/dist/browse/web/assets/index-CW4CUoWl.css +1 -0
- package/dist/browse/web/assets/{index-Dw_64hkR.js → index-CziUWlSw.js} +31 -31
- package/dist/browse/web/index.html +2 -2
- package/dist/downloaders/Downloader.d.ts +5 -4
- package/dist/downloaders/Downloader.js +3 -1
- package/dist/downloaders/Downloader.js.map +1 -1
- package/dist/downloaders/PostDownloader.js +10 -0
- package/dist/downloaders/PostDownloader.js.map +1 -1
- package/dist/downloaders/ProductDownloader.js +2 -0
- package/dist/downloaders/ProductDownloader.js.map +1 -1
- package/dist/downloaders/task/DownloadTaskFactory.d.ts +4 -0
- package/dist/downloaders/task/DownloadTaskFactory.js +3 -2
- package/dist/downloaders/task/DownloadTaskFactory.js.map +1 -1
- package/dist/downloaders/task/YouTubeDownloadTask.js +7 -2
- package/dist/downloaders/task/YouTubeDownloadTask.js.map +1 -1
- package/dist/parsers/PostParser.js +62 -7
- package/dist/parsers/PostParser.js.map +1 -1
- package/dist/utils/FilenameFormatHelper.d.ts +2 -2
- package/dist/utils/FilenameFormatHelper.js +45 -2
- package/dist/utils/FilenameFormatHelper.js.map +1 -1
- package/dist/utils/MediaFilenameResolver.d.ts +4 -1
- package/dist/utils/MediaFilenameResolver.js +6 -4
- package/dist/utils/MediaFilenameResolver.js.map +1 -1
- package/dist/utils/URLHelper.js +8 -8
- package/dist/utils/URLHelper.js.map +1 -1
- package/dist/utils/YouTubeCredentialsCapturer.js +1 -1
- package/dist/utils/YouTubeCredentialsCapturer.js.map +1 -1
- package/dist/utils/yt/InnertubeLoader.d.ts +19 -1
- package/dist/utils/yt/InnertubeLoader.js +55 -15
- package/dist/utils/yt/InnertubeLoader.js.map +1 -1
- package/package.json +2 -1
- package/dist/browse/web/assets/index-DjOKbT1U.css +0 -1
package/NOTICE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
NOTICE
|
|
2
|
+
|
|
3
|
+
This project includes the following third-party software:
|
|
4
|
+
|
|
5
|
+
- LightGallery (https://www.lightgalleryjs.com/)
|
|
6
|
+
Copyright © 2016–2025
|
|
7
|
+
Licensed under the GNU General Public License v3.0 (GPLv3)
|
|
8
|
+
Developed by Srinivas Tamada and contributors.
|
|
9
|
+
Source: https://github.com/sachinchoolur/lightGallery
|
|
10
|
+
|
|
11
|
+
- Bottleneck (https://github.com/SGrondin/bottleneck)
|
|
12
|
+
Licensed under the BSD 2-Clause License
|
|
13
|
+
|
|
14
|
+
- Fast-Copy (https://github.com/planttheidea/fast-copy)
|
|
15
|
+
Licensed under the GNU General Public License v3.0 (GPLv3)
|
|
16
|
+
|
|
17
|
+
- argv-split (https://github.com/75lb/argv-split)
|
|
18
|
+
Licensed under the GNU General Public License v2.0 (GPLv2)
|
|
19
|
+
|
|
20
|
+
All other dependencies are used under permissive licenses such as MIT, Apache-2.0, or ISC, and do not require attribution beyond preservation of their license terms in `node_modules`.
|
|
21
|
+
|
|
22
|
+
This project is open source and licensed under the MIT License.
|
|
23
|
+
In accordance with the terms of the above licenses, this NOTICE file provides attribution and license information for included third-party software.
|
package/README.md
CHANGED
|
@@ -60,16 +60,16 @@ path.to.deno = "path/to/deno"
|
|
|
60
60
|
...
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
#### Premium access
|
|
63
|
+
#### Premium access / "Login required" error
|
|
64
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').
|
|
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'). You will also need to connect to an account (not necessarily Premium) if you get a "Login required" error message during download.
|
|
66
|
+
|
|
67
|
+
For CLI users, you would configure `patreon-dl` as follows:
|
|
66
68
|
|
|
67
69
|
```
|
|
68
70
|
$ patreon-dl --configure-youtube
|
|
69
71
|
```
|
|
70
72
|
|
|
71
|
-
> ...or you may just refer to the next section on how to download enhanecd-quality videos without a Premium account.
|
|
72
|
-
|
|
73
73
|
### Embedded videos / links - external downloader
|
|
74
74
|
|
|
75
75
|
You can specify external programs to download embedded videos or from embedded links. For YouTube videos, this will replace the built-in downloader.
|
|
@@ -109,7 +109,7 @@ $ patreon-dl [OPTION]... URL
|
|
|
109
109
|
| `--dry-run` | | Run without writing files to disk (except logs, if any). Intended for testing / debugging. |
|
|
110
110
|
| <code><nobr>--list-tiers <creator></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). |
|
|
111
111
|
| <code><nobr>--list-tiers-uid <user ID></nobr></code> | | Same as `--list-tiers`, but takes user ID instead of vanity. |
|
|
112
|
-
| `--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.
|
|
112
|
+
| `--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.|
|
|
113
113
|
|
|
114
114
|
### URL
|
|
115
115
|
|
|
@@ -293,6 +293,14 @@ Note the URL shown in the output. Open this URL in a web browser to begin viewin
|
|
|
293
293
|
|
|
294
294
|
## Changelog
|
|
295
295
|
|
|
296
|
+
v3.7.0
|
|
297
|
+
- Vimeo download script: fetch full player URL ([#118](https://github.com/patrickkfkan/patreon-dl/issues/118))
|
|
298
|
+
- Fix downloaded posts missing content / teaser ([@Fabelwesen](https://github.com/Fabelwesen) - [#119](https://github.com/patrickkfkan/patreon-dl/issues/119))
|
|
299
|
+
- Add "max content width" option to browse settings ([#122](https://github.com/patrickkfkan/patreon-dl/issues/122))
|
|
300
|
+
- Map inline post links to local server routes (contrib by [@Fabelwesen](https://github.com/Fabelwesen) - [#121](https://github.com/patrickkfkan/patreon-dl/issues/121))
|
|
301
|
+
- Support additional fields in `media.filename.format` ([patreon-dl-gui#51](https://github.com/patrickkfkan/patreon-dl-gui/issues/51))
|
|
302
|
+
- YT downloader: fix error in n/sig decipher function extraction
|
|
303
|
+
|
|
296
304
|
v3.6.1
|
|
297
305
|
- Fix Embedly download script error on retrying with alternative URL.
|
|
298
306
|
|
package/bin/patreon-dl-vimeo.js
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import EmbedlyDownloader from './EmbedlyDownloader.js';
|
|
27
|
+
import * as entities from 'entities';
|
|
27
28
|
|
|
28
29
|
class VimeoDownloader extends EmbedlyDownloader {
|
|
29
30
|
constructor() {
|
|
@@ -33,12 +34,14 @@ class VimeoDownloader extends EmbedlyDownloader {
|
|
|
33
34
|
// Override
|
|
34
35
|
getPlayerURL(html) {
|
|
35
36
|
if (html) {
|
|
36
|
-
const regex = /https:\/\/player\.vimeo\.com\/video\/\d
|
|
37
|
+
const regex = /src=\"(https:\/\/player\.vimeo\.com\/video\/\d+(?:\?.+?)?)\"/g;
|
|
37
38
|
const match = regex.exec(html);
|
|
38
|
-
if (match && match[
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
if (match && match[1]) {
|
|
40
|
+
const url = entities.decodeHTML(match[1]);
|
|
41
|
+
console.log("Found Vimeo player URL from embed HTML:", url);
|
|
42
|
+
return url;
|
|
41
43
|
}
|
|
44
|
+
console.warn("Vimeo player URL not found in embed HTML");
|
|
42
45
|
}
|
|
43
46
|
return super.getPlayerURL(html);
|
|
44
47
|
}
|
|
@@ -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
|
+
"__#130@#sanitizeCampaign"(campaign: Campaign): void;
|
|
15
15
|
name: string;
|
|
16
16
|
db: import("../db").DBInstance;
|
|
17
17
|
logger?: import("../..").Logger | null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type CheerioAPI } from 'cheerio';
|
|
1
2
|
import { type APIConstructor } from ".";
|
|
2
3
|
import { type Product, type Post } from "../../entities";
|
|
3
4
|
import { type GetContentContext, type ContentType, type GetContentListParams, type GetCollectionListParams, type GetPostTagListParams } from "../types/Content.js";
|
|
@@ -13,7 +14,9 @@ export declare function ContentAPIMixin<TBase extends APIConstructor>(Base: TBas
|
|
|
13
14
|
} | null;
|
|
14
15
|
getCollectionList(params: GetCollectionListParams): import("../types/Content.js").CollectionList;
|
|
15
16
|
getPostTagList(params: GetPostTagListParams): import("../types/Content.js").PostTagList;
|
|
16
|
-
"__#
|
|
17
|
+
"__#131@#processPostContentElements"(post: Post): void;
|
|
18
|
+
"__#131@#processInlineMedia"($: CheerioAPI, post: Post): boolean;
|
|
19
|
+
"__#131@#processInlineLinks"($: CheerioAPI): boolean;
|
|
17
20
|
name: string;
|
|
18
21
|
db: import("../db").DBInstance;
|
|
19
22
|
logger?: import("../..").Logger | null;
|
|
@@ -11,7 +11,7 @@ const DEFAULT_CONTENT_LIST_SORT_BY = 'a-z';
|
|
|
11
11
|
const DEFAULT_COLLECTION_LIST_SIZE = 10;
|
|
12
12
|
const DEFAULT_COLLECTION_LIST_SORT_BY = 'a-z';
|
|
13
13
|
export function ContentAPIMixin(Base) {
|
|
14
|
-
var _ContentAPI_instances,
|
|
14
|
+
var _ContentAPI_instances, _ContentAPI_processPostContentElements, _ContentAPI_processInlineMedia, _ContentAPI_processInlineLinks, _a;
|
|
15
15
|
return _a = class ContentAPI extends Base {
|
|
16
16
|
constructor() {
|
|
17
17
|
super(...arguments);
|
|
@@ -28,7 +28,7 @@ export function ContentAPIMixin(Base) {
|
|
|
28
28
|
for (const item of list.items) {
|
|
29
29
|
switch (item.type) {
|
|
30
30
|
case 'post':
|
|
31
|
-
__classPrivateFieldGet(this, _ContentAPI_instances, "m",
|
|
31
|
+
__classPrivateFieldGet(this, _ContentAPI_instances, "m", _ContentAPI_processPostContentElements).call(this, item);
|
|
32
32
|
item.content = this.sanitizeHTML(item.content || '');
|
|
33
33
|
break;
|
|
34
34
|
case 'product': {
|
|
@@ -43,7 +43,7 @@ export function ContentAPIMixin(Base) {
|
|
|
43
43
|
getPost(id) {
|
|
44
44
|
const post = this.db.getContent(id, 'post');
|
|
45
45
|
if (post) {
|
|
46
|
-
__classPrivateFieldGet(this, _ContentAPI_instances, "m",
|
|
46
|
+
__classPrivateFieldGet(this, _ContentAPI_instances, "m", _ContentAPI_processPostContentElements).call(this, post);
|
|
47
47
|
post.content = this.sanitizeHTML(post.content || '');
|
|
48
48
|
}
|
|
49
49
|
return post;
|
|
@@ -74,17 +74,28 @@ export function ContentAPIMixin(Base) {
|
|
|
74
74
|
}
|
|
75
75
|
},
|
|
76
76
|
_ContentAPI_instances = new WeakSet(),
|
|
77
|
-
|
|
77
|
+
_ContentAPI_processPostContentElements = function _ContentAPI_processPostContentElements(post) {
|
|
78
78
|
const html = post.content || '';
|
|
79
|
-
|
|
80
|
-
const hasLinkedAttachments = post.linkedAttachments && post.linkedAttachments.length > 0;
|
|
81
|
-
if (!html || (!hasImages && !hasLinkedAttachments)) {
|
|
79
|
+
if (!html) {
|
|
82
80
|
return;
|
|
83
81
|
}
|
|
84
82
|
const $ = cheerioLoad(html);
|
|
85
|
-
const
|
|
83
|
+
const inlineMediaModified = __classPrivateFieldGet(this, _ContentAPI_instances, "m", _ContentAPI_processInlineMedia).call(this, $, post);
|
|
84
|
+
const inlineLinksModified = __classPrivateFieldGet(this, _ContentAPI_instances, "m", _ContentAPI_processInlineLinks).call(this, $);
|
|
85
|
+
if (inlineMediaModified || inlineLinksModified) {
|
|
86
|
+
post.content = $.html();
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
_ContentAPI_processInlineMedia = function _ContentAPI_processInlineMedia($, post) {
|
|
90
|
+
const hasImages = post.images.length > 0;
|
|
91
|
+
const hasLinkedAttachments = post.linkedAttachments && post.linkedAttachments.length > 0;
|
|
92
|
+
if (!hasImages && !hasLinkedAttachments) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
86
95
|
let hasModified = false;
|
|
96
|
+
// Images
|
|
87
97
|
if (hasImages) {
|
|
98
|
+
const replacedMediaIds = [];
|
|
88
99
|
$('img').each((_, _el) => {
|
|
89
100
|
const el = $(_el);
|
|
90
101
|
const id = el.attr('data-media-id');
|
|
@@ -136,9 +147,31 @@ export function ContentAPIMixin(Base) {
|
|
|
136
147
|
}
|
|
137
148
|
});
|
|
138
149
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
150
|
+
return hasModified;
|
|
151
|
+
},
|
|
152
|
+
_ContentAPI_processInlineLinks = function _ContentAPI_processInlineLinks($) {
|
|
153
|
+
let hasModified = false;
|
|
154
|
+
$('a').each((_, _el) => {
|
|
155
|
+
const el = $(_el);
|
|
156
|
+
const href = el.attr('href') || '';
|
|
157
|
+
let an;
|
|
158
|
+
try {
|
|
159
|
+
an = href.startsWith('https://') ? URLHelper.analyzeURL(href) : null;
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
this.log('warn', `Error analyzing inline link "${href}":`, error);
|
|
163
|
+
an = null;
|
|
164
|
+
}
|
|
165
|
+
if (an && an.type === 'post') {
|
|
166
|
+
const postExistsInDB = this.db.checkContentExists(an.postId, 'post');
|
|
167
|
+
if (postExistsInDB) {
|
|
168
|
+
el.attr('href', `/posts/${an.postId}`);
|
|
169
|
+
el.removeAttr('target');
|
|
170
|
+
hasModified = true;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
return hasModified;
|
|
142
175
|
},
|
|
143
176
|
_a;
|
|
144
177
|
}
|
|
@@ -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, 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}"]}
|
|
1
|
+
{"version":3,"file":"ContentAPIMixin.js","sourceRoot":"","sources":["../../../src/browse/api/ContentAPIMixin.ts"],"names":[],"mappings":"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","sourcesContent":["import { type CheerioAPI, 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.#processPostContentElements(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.#processPostContentElements(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 #processPostContentElements(post: Post) {\n const html = post.content || '';\n \n if (!html) {\n return;\n }\n\n const $ = cheerioLoad(html);\n const inlineMediaModified = this.#processInlineMedia($, post);\n const inlineLinksModified = this.#processInlineLinks($);\n if (inlineMediaModified || inlineLinksModified) {\n post.content = $.html();\n }\n }\n\n #processInlineMedia($: CheerioAPI, post: Post) {\n const hasImages = post.images.length > 0;\n const hasLinkedAttachments = post.linkedAttachments && post.linkedAttachments.length > 0;\n if (!hasImages && !hasLinkedAttachments) {\n return false;\n }\n let hasModified = false;\n \n // Images\n if (hasImages) {\n const replacedMediaIds: string[] = [];\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 return hasModified;\n }\n\n #processInlineLinks($: CheerioAPI) {\n let hasModified = false;\n $('a').each((_, _el) => {\n const el = $(_el);\n const href = el.attr('href') || '';\n let an;\n try {\n an = href.startsWith('https://') ? URLHelper.analyzeURL(href) : null;\n }\n catch (error: unknown) { \n this.log('warn', `Error analyzing inline link \"${href}\":`, error);\n an = null;\n }\n if (an && an.type === 'post') {\n const postExistsInDB = this.db.checkContentExists(an.postId, 'post');\n if (postExistsInDB) {\n el.attr('href', `/posts/${an.postId}`);\n el.removeAttr('target');\n hasModified = true;\n }\n }\n });\n return hasModified;\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
|
+
"__#132@#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;
|
|
@@ -6,6 +6,7 @@ export declare function SettingsAPIMixin<TBase extends APIConstructor>(Base: TBa
|
|
|
6
6
|
theme: string;
|
|
7
7
|
listItemsPerPage: number;
|
|
8
8
|
galleryItemsPerPage: number;
|
|
9
|
+
maxContentWidth: import("../types/Settings.js").MaxContentWidth;
|
|
9
10
|
};
|
|
10
11
|
saveBrowseSettings(settings: BrowseSettings): void;
|
|
11
12
|
getBrowseSettingOptions(): BrowseSettingOptions;
|
|
@@ -41,7 +41,8 @@ const THEMES = [
|
|
|
41
41
|
const DEFAULT_BROWSE_SETTINGS = {
|
|
42
42
|
theme: THEMES[0].value,
|
|
43
43
|
listItemsPerPage: 20,
|
|
44
|
-
galleryItemsPerPage: 100
|
|
44
|
+
galleryItemsPerPage: 100,
|
|
45
|
+
maxContentWidth: 'Standard'
|
|
45
46
|
};
|
|
46
47
|
export function SettingsAPIMixin(Base) {
|
|
47
48
|
return class SettingsAPI extends Base {
|
|
@@ -62,7 +63,8 @@ export function SettingsAPIMixin(Base) {
|
|
|
62
63
|
return {
|
|
63
64
|
themes: THEMES,
|
|
64
65
|
listItemsPerPage: [10, 20, 30, 50],
|
|
65
|
-
galleryItemsPerPage: [50, 100, 150, 200]
|
|
66
|
+
galleryItemsPerPage: [50, 100, 150, 200],
|
|
67
|
+
maxContentWidth: ['Narrower', 'Standard', 'Wider']
|
|
66
68
|
};
|
|
67
69
|
}
|
|
68
70
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SettingsAPIMixin.js","sourceRoot":"","sources":["../../../src/browse/api/SettingsAPIMixin.ts"],"names":[],"mappings":"AAGA,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;AAElD,MAAM,MAAM,GAAkB;IAC5B;QACE,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,WAAW,EAAE,CAAC,iDAAiD,CAAC;KACjE;IACD,GAAG;QACD,OAAO;QACP,UAAU;QACV,OAAO;QACP,QAAQ;QACR,QAAQ;QACR,QAAQ;QACR,SAAS;QACT,QAAQ;QACR,OAAO;QACP,KAAK;QACL,SAAS;QACT,OAAO;QACP,OAAO;QACP,OAAO;QACP,QAAQ;QACR,WAAW;QACX,SAAS;QACT,SAAS;QACT,OAAO;QACP,OAAO;QACP,UAAU;QACV,WAAW;QACX,QAAQ;QACR,OAAO;QACP,MAAM;QACN,QAAQ;KACT,CAAC,GAAG,CAAC,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;QAChF,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,CAAC,sBAAsB,mBAAmB,oBAAoB,CAAC;KAC7E,CAAC,CAAC;CACJ,CAAA;AAED,MAAM,uBAAuB,GAAmB;IAC9C,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK;IACtB,gBAAgB,EAAE,EAAE;IACpB,mBAAmB,EAAE,GAAG;
|
|
1
|
+
{"version":3,"file":"SettingsAPIMixin.js","sourceRoot":"","sources":["../../../src/browse/api/SettingsAPIMixin.ts"],"names":[],"mappings":"AAGA,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;AAElD,MAAM,MAAM,GAAkB;IAC5B;QACE,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,WAAW,EAAE,CAAC,iDAAiD,CAAC;KACjE;IACD,GAAG;QACD,OAAO;QACP,UAAU;QACV,OAAO;QACP,QAAQ;QACR,QAAQ;QACR,QAAQ;QACR,SAAS;QACT,QAAQ;QACR,OAAO;QACP,KAAK;QACL,SAAS;QACT,OAAO;QACP,OAAO;QACP,OAAO;QACP,QAAQ;QACR,WAAW;QACX,SAAS;QACT,SAAS;QACT,OAAO;QACP,OAAO;QACP,UAAU;QACV,WAAW;QACX,QAAQ;QACR,OAAO;QACP,MAAM;QACN,QAAQ;KACT,CAAC,GAAG,CAAC,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;QAChF,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,CAAC,sBAAsB,mBAAmB,oBAAoB,CAAC;KAC7E,CAAC,CAAC;CACJ,CAAA;AAED,MAAM,uBAAuB,GAAmB;IAC9C,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK;IACtB,gBAAgB,EAAE,EAAE;IACpB,mBAAmB,EAAE,GAAG;IACxB,eAAe,EAAE,UAAU;CAC5B,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAA+B,IAAW;IACxE,OAAO,MAAM,WAAY,SAAQ,IAAI;QACnC,iBAAiB;YACf,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAiB,uBAAuB,CAAC,CAAC;YAC9E,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO;oBACL,GAAG,uBAAuB;oBAC1B,GAAG,QAAQ;iBACZ,CAAC;YACJ,CAAC;YACD,OAAO,EAAC,GAAG,uBAAuB,EAAC,CAAC;QACtC,CAAC;QAED,kBAAkB,CAAC,QAAwB;YACzC,OAAO,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,uBAAuB,EAAE,QAAQ,CAAC,CAAC;QACjE,CAAC;QAED,uBAAuB;YACrB,OAAO;gBACL,MAAM,EAAE,MAAM;gBACd,gBAAgB,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;gBAClC,mBAAmB,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;gBACxC,eAAe,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,OAAO,CAAC;aACnD,CAAC;QACJ,CAAC;KACF,CAAA;AACH,CAAC","sourcesContent":["import { type APIConstructor } from \".\";\nimport { type BrowseSettingOptions, type BrowseSettings, type BrowseTheme } from \"../types/Settings.js\";\n\nconst BROWSE_SETTINGS_ENV_KEY = 'browse_settings';\n\nconst THEMES: BrowseTheme[] = [\n {\n name: 'Default',\n value: 'default',\n stylesheets: ['/themes/bootstrap/default/css/bootstrap.min.css']\n },\n ...[\n 'brite',\n 'cerulean',\n 'cosmo',\n 'cyborg',\n 'darkly',\n 'flatly',\n 'journal',\n 'litera',\n 'lumen',\n 'lux',\n 'materia',\n 'minty',\n 'morph',\n 'pulse',\n 'quartz',\n 'sandstone',\n 'simplex',\n 'sketchy',\n 'slate',\n 'solar',\n 'spacelab',\n 'superhero',\n 'united',\n 'vapor',\n 'yeti',\n 'zephyr'\n ].map((bootswatchThemeName) => ({\n name: bootswatchThemeName.charAt(0).toUpperCase() + bootswatchThemeName.slice(1),\n value: bootswatchThemeName,\n stylesheets: [`/themes/bootswatch/${bootswatchThemeName}/bootstrap.min.css`]\n }))\n]\n\nconst DEFAULT_BROWSE_SETTINGS: BrowseSettings = {\n theme: THEMES[0].value,\n listItemsPerPage: 20,\n galleryItemsPerPage: 100,\n maxContentWidth: 'Standard'\n};\n\nexport function SettingsAPIMixin<TBase extends APIConstructor>(Base: TBase) {\n return class SettingsAPI extends Base {\n getBrowseSettings() {\n const settings = this.db.getEnvValue<BrowseSettings>(BROWSE_SETTINGS_ENV_KEY);\n if (settings) {\n return {\n ...DEFAULT_BROWSE_SETTINGS,\n ...settings\n };\n }\n return {...DEFAULT_BROWSE_SETTINGS};\n }\n\n saveBrowseSettings(settings: BrowseSettings) {\n return this.db.saveEnvValue(BROWSE_SETTINGS_ENV_KEY, settings);\n }\n\n getBrowseSettingOptions(): BrowseSettingOptions {\n return {\n themes: THEMES,\n listItemsPerPage: [10, 20, 30, 50],\n galleryItemsPerPage: [50, 100, 150, 200],\n maxContentWidth: ['Narrower', 'Standard', 'Wider']\n };\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
|
+
"__#132@#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;
|
|
@@ -30,6 +30,7 @@ export declare class APIBase {
|
|
|
30
30
|
theme: string;
|
|
31
31
|
listItemsPerPage: number;
|
|
32
32
|
galleryItemsPerPage: number;
|
|
33
|
+
maxContentWidth: import("../types/Settings.js").MaxContentWidth;
|
|
33
34
|
};
|
|
34
35
|
saveBrowseSettings(settings: import("../types/Settings.js").BrowseSettings): void;
|
|
35
36
|
getBrowseSettingOptions(): import("../types/Settings.js").BrowseSettingOptions;
|
|
@@ -49,7 +50,9 @@ export declare class APIBase {
|
|
|
49
50
|
} | null;
|
|
50
51
|
getCollectionList(params: import("../types/Content.js").GetCollectionListParams): import("../types/Content.js").CollectionList;
|
|
51
52
|
getPostTagList(params: import("../types/Content.js").GetPostTagListParams): import("../types/Content.js").PostTagList;
|
|
52
|
-
"__#
|
|
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
56
|
name: string;
|
|
54
57
|
db: DBInstance;
|
|
55
58
|
logger?: Logger | null;
|
|
@@ -64,7 +67,7 @@ export declare class APIBase {
|
|
|
64
67
|
withCounts?: false;
|
|
65
68
|
}): import("../../index.js").Campaign | null;
|
|
66
69
|
getCampaign(params: import("../types/Campaign.js").GetCampaignParams): import("../../index.js").Campaign | import("../types/Campaign.js").CampaignWithCounts | null;
|
|
67
|
-
"__#
|
|
70
|
+
"__#130@#sanitizeCampaign"(campaign: import("../../index.js").Campaign): void;
|
|
68
71
|
name: string;
|
|
69
72
|
db: DBInstance;
|
|
70
73
|
logger?: Logger | null;
|
|
@@ -77,7 +80,7 @@ export declare class APIBase {
|
|
|
77
80
|
declare const API: {
|
|
78
81
|
new (...args: any[]): {
|
|
79
82
|
getPostFilterData(campaignId: string): import("../types/Filter.js").FilterData<import("../types/Filter.js").PostFilterSearchParams>;
|
|
80
|
-
"__#
|
|
83
|
+
"__#132@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
|
|
81
84
|
getProductFilterData(campaignId: string): import("../types/Filter.js").FilterData<import("../types/Filter.js").ProductFilterSearchParams>;
|
|
82
85
|
getMediaFilterData(campaignId: string): import("../types/Filter.js").FilterData<import("../types/Filter.js").MediaFilterSearchParams>;
|
|
83
86
|
name: string;
|
|
@@ -101,6 +104,7 @@ declare const API: {
|
|
|
101
104
|
theme: string;
|
|
102
105
|
listItemsPerPage: number;
|
|
103
106
|
galleryItemsPerPage: number;
|
|
107
|
+
maxContentWidth: import("../types/Settings.js").MaxContentWidth;
|
|
104
108
|
};
|
|
105
109
|
saveBrowseSettings(settings: import("../types/Settings.js").BrowseSettings): void;
|
|
106
110
|
getBrowseSettingOptions(): import("../types/Settings.js").BrowseSettingOptions;
|
|
@@ -122,7 +126,9 @@ declare const API: {
|
|
|
122
126
|
} | null;
|
|
123
127
|
getCollectionList(params: import("../types/Content.js").GetCollectionListParams): import("../types/Content.js").CollectionList;
|
|
124
128
|
getPostTagList(params: import("../types/Content.js").GetPostTagListParams): import("../types/Content.js").PostTagList;
|
|
125
|
-
"__#
|
|
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;
|
|
126
132
|
name: string;
|
|
127
133
|
db: DBInstance;
|
|
128
134
|
logger?: Logger | null;
|
|
@@ -139,7 +145,7 @@ declare const API: {
|
|
|
139
145
|
withCounts?: false;
|
|
140
146
|
}): import("../../index.js").Campaign | null;
|
|
141
147
|
getCampaign(params: import("../types/Campaign.js").GetCampaignParams): import("../../index.js").Campaign | import("../types/Campaign.js").CampaignWithCounts | null;
|
|
142
|
-
"__#
|
|
148
|
+
"__#130@#sanitizeCampaign"(campaign: import("../../index.js").Campaign): void;
|
|
143
149
|
name: string;
|
|
144
150
|
db: DBInstance;
|
|
145
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
|
-
"__#
|
|
11
|
-
"__#
|
|
10
|
+
"__#114@#saveRewards"(campaign: Campaign): void;
|
|
11
|
+
"__#114@#doSaveReward"(campaign: Campaign, reward: Reward): void;
|
|
12
12
|
getCampaignList(params: GetCampaignListParams): CampaignList;
|
|
13
|
-
"__#
|
|
13
|
+
"__#114@#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
|
-
"__#
|
|
9
|
-
"__#
|
|
10
|
-
"__#
|
|
11
|
-
"__#
|
|
12
|
-
"__#
|
|
13
|
-
"__#
|
|
14
|
-
"__#
|
|
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;
|
|
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
|
-
"__#
|
|
29
|
+
"__#115@#parseContentRowJoinedComments"(row: any): any;
|
|
30
30
|
getContentCountByDate(contentType: ContentType, groupBy: "year" | "month", filter?: {
|
|
31
31
|
campaign?: Campaign | string | null;
|
|
32
32
|
date?: Date | null;
|
|
@@ -43,26 +43,26 @@ export declare function ContentDBMixin<TBase extends CampaignDBConstructor>(Base
|
|
|
43
43
|
title: string;
|
|
44
44
|
count: number;
|
|
45
45
|
}[];
|
|
46
|
-
checkContentExists(id: string, contentType: ContentType, campaign
|
|
46
|
+
checkContentExists(id: string, contentType: ContentType, campaign?: Campaign | null): boolean;
|
|
47
47
|
saveCollection(collection: Collection, campaign: Campaign | null, overwriteIfExists?: boolean): void;
|
|
48
48
|
savePostTag(tag: PostTag, campaign: Campaign | null, overwriteIfExists?: boolean): void;
|
|
49
49
|
getCollection(id: string): {
|
|
50
50
|
collection: Collection;
|
|
51
51
|
campaignId: string;
|
|
52
52
|
} | null;
|
|
53
|
-
"__#
|
|
53
|
+
"__#115@#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
|
-
"__#
|
|
58
|
+
"__#115@#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
|
-
"__#
|
|
63
|
-
"__#
|
|
62
|
+
"__#114@#saveRewards"(campaign: Campaign): void;
|
|
63
|
+
"__#114@#doSaveReward"(campaign: Campaign, reward: import("../../entities").Reward): void;
|
|
64
64
|
getCampaignList(params: import("../types/Campaign").GetCampaignListParams): import("../types/Campaign").CampaignList;
|
|
65
|
-
"__#
|
|
65
|
+
"__#114@#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;
|
|
@@ -506,15 +506,22 @@ export function ContentDBMixin(Base) {
|
|
|
506
506
|
}
|
|
507
507
|
checkContentExists(id, contentType, campaign) {
|
|
508
508
|
this.log('debug', `Check if ${contentType} #${id} exists in DB`);
|
|
509
|
+
const whereClauseParts = [
|
|
510
|
+
'content_id = ?',
|
|
511
|
+
'content_type = ?'
|
|
512
|
+
];
|
|
513
|
+
const whereValues = [id, contentType];
|
|
514
|
+
if (campaign !== undefined) {
|
|
515
|
+
whereClauseParts.push('campaign_id = ?');
|
|
516
|
+
whereValues.push(campaign?.id || '-1');
|
|
517
|
+
}
|
|
518
|
+
const whereClause = `WHERE ${whereClauseParts.join(' AND ')}`;
|
|
509
519
|
try {
|
|
510
520
|
const result = this.get(`
|
|
511
521
|
SELECT COUNT(*) as count
|
|
512
522
|
FROM content
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
content_type = ? AND
|
|
516
|
-
campaign_id = ?
|
|
517
|
-
`, [id, contentType, campaign?.id || '-1']);
|
|
523
|
+
${whereClause}
|
|
524
|
+
`, whereValues);
|
|
518
525
|
return result.count > 0;
|
|
519
526
|
}
|
|
520
527
|
catch (error) {
|