patreon-dl 3.0.0 → 3.2.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 +30 -5
- package/bin/patreon-dl-vimeo.js +17 -7
- package/dist/browse/api/CampaignAPIMixin.d.ts +2 -0
- package/dist/browse/api/CampaignAPIMixin.js +43 -13
- package/dist/browse/api/CampaignAPIMixin.js.map +1 -1
- package/dist/browse/api/ContentAPIMixin.d.ts +4 -1
- package/dist/browse/api/ContentAPIMixin.js +84 -16
- package/dist/browse/api/ContentAPIMixin.js.map +1 -1
- package/dist/browse/api/FilterAPIMixin.d.ts +2 -1
- package/dist/browse/api/MediaAPIMixin.d.ts +1 -0
- package/dist/browse/api/SettingsAPIMixin.d.ts +1 -0
- package/dist/browse/api/index.d.ts +17 -2
- package/dist/browse/api/index.js +11 -0
- package/dist/browse/api/index.js.map +1 -1
- package/dist/browse/db/CampaignDBMixin.d.ts +4 -4
- package/dist/browse/db/ContentDBMixin.d.ts +12 -12
- package/dist/browse/db/EnvDBMixin.d.ts +1 -1
- package/dist/browse/db/MediaDBMixin.d.ts +1 -1
- package/dist/browse/db/UserDBMixin.d.ts +1 -1
- package/dist/browse/db/index.d.ts +19 -19
- package/dist/browse/web/assets/index-BqQSEIOs.js +209 -0
- package/dist/browse/web/assets/index-USVypdWT.css +1 -0
- package/dist/browse/web/index.html +2 -2
- package/dist/browse/web/utils/RawDataExtractor.d.ts +5 -0
- package/dist/browse/web/utils/RawDataExtractor.js +17 -0
- package/dist/browse/web/utils/RawDataExtractor.js.map +1 -0
- package/dist/cli/CLIOptionValidator.d.ts +1 -1
- package/dist/cli/CLIOptions.d.ts +1 -1
- package/dist/cli/CLIOptions.js +2 -1
- package/dist/cli/CLIOptions.js.map +1 -1
- package/dist/cli/CommandLineParser.js +2 -1
- package/dist/cli/CommandLineParser.js.map +1 -1
- package/dist/cli/ConfigFileParser.js +4 -2
- package/dist/cli/ConfigFileParser.js.map +1 -1
- package/dist/cli/index.js +24 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/server/ServerCLIOptions.d.ts +1 -1
- package/dist/downloaders/Downloader.d.ts +17 -4
- package/dist/downloaders/Downloader.js +35 -10
- package/dist/downloaders/Downloader.js.map +1 -1
- package/dist/downloaders/DownloaderOptions.d.ts +1 -0
- package/dist/downloaders/DownloaderOptions.js +4 -1
- package/dist/downloaders/DownloaderOptions.js.map +1 -1
- package/dist/downloaders/PostDownloader.js +13 -6
- package/dist/downloaders/PostDownloader.js.map +1 -1
- package/dist/downloaders/PostsFetcher.js +10 -3
- package/dist/downloaders/PostsFetcher.js.map +1 -1
- package/dist/downloaders/ProductDownloader.js +3 -2
- package/dist/downloaders/ProductDownloader.js.map +1 -1
- package/dist/downloaders/task/DownloadTask.js +1 -1
- package/dist/downloaders/task/DownloadTask.js.map +1 -1
- package/dist/downloaders/task/DownloadTaskFactory.d.ts +1 -0
- package/dist/downloaders/task/DownloadTaskFactory.js +2 -1
- package/dist/downloaders/task/DownloadTaskFactory.js.map +1 -1
- package/dist/downloaders/task/FFmpegDownloadTaskBase.d.ts +1 -0
- package/dist/downloaders/task/FFmpegDownloadTaskBase.js +37 -2
- package/dist/downloaders/task/FFmpegDownloadTaskBase.js.map +1 -1
- package/dist/downloaders/task/FetcherDownloadTask.d.ts +1 -0
- package/dist/downloaders/task/FetcherDownloadTask.js +30 -18
- package/dist/downloaders/task/FetcherDownloadTask.js.map +1 -1
- package/dist/downloaders/task/M3U8DownloadTask.js +10 -6
- package/dist/downloaders/task/M3U8DownloadTask.js.map +1 -1
- package/dist/downloaders/task/YouTubeDownloadTask.js +9 -2
- package/dist/downloaders/task/YouTubeDownloadTask.js.map +1 -1
- package/dist/downloaders/task/YouTubeStreamDownloadTask.js +31 -14
- package/dist/downloaders/task/YouTubeStreamDownloadTask.js.map +1 -1
- package/dist/parsers/PageParser.js +35 -0
- package/dist/parsers/PageParser.js.map +1 -1
- package/dist/utils/FSHelper.js +6 -5
- package/dist/utils/FSHelper.js.map +1 -1
- package/dist/utils/Fetcher.d.ts +8 -1
- package/dist/utils/Fetcher.js +31 -5
- package/dist/utils/Fetcher.js.map +1 -1
- package/dist/utils/logging/ConsoleLogger.js +6 -0
- package/dist/utils/logging/ConsoleLogger.js.map +1 -1
- package/dist/utils/yt/InnertubeLoader.d.ts +0 -1
- package/dist/utils/yt/InnertubeLoader.js +9 -196
- package/dist/utils/yt/InnertubeLoader.js.map +1 -1
- package/package.json +4 -6
- package/dist/browse/web/assets/index-DCSXR5HZ.css +0 -1
- package/dist/browse/web/assets/index-DTUJdO9u.js +0 -250
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ This repo contains the `patreon-dl` library and its command-line tool. For GUI a
|
|
|
8
8
|
|
|
9
9
|
### Features
|
|
10
10
|
- Access to patron-only content through cookie. This refers to content you have access to under your account. It does not include locked content that you don't have a subscription for.
|
|
11
|
-
- Download posts by user, in a collection or single post
|
|
11
|
+
- Download posts by user, in a collection or single post.
|
|
12
12
|
- Download products (aka shop purchases)
|
|
13
13
|
- Items included in downloads:
|
|
14
14
|
- videos
|
|
@@ -17,9 +17,10 @@ This repo contains the `patreon-dl` library and its command-line tool. For GUI a
|
|
|
17
17
|
- attachments
|
|
18
18
|
- embedded videos
|
|
19
19
|
- YouTube downloader built-in
|
|
20
|
-
- Supports [external downloader](#embedded-videos---external-downloader)
|
|
20
|
+
- Supports [external downloader](#embedded-videos--links---external-downloader)
|
|
21
21
|
- Save campaign and content info
|
|
22
22
|
- Extensively configurable
|
|
23
|
+
- Browse downloaded content through integrated web server
|
|
23
24
|
|
|
24
25
|
You can run `patreon-dl` from the command-line or [use it as a library](./docs/Library.md) for your project. Node.js v20 or higher required.
|
|
25
26
|
|
|
@@ -29,6 +30,8 @@ You can run `patreon-dl` from the command-line or [use it as a library](./docs/L
|
|
|
29
30
|
- YouTube video link - in which case the video is downloaded; or
|
|
30
31
|
- An external downloader is configured for the link provider.
|
|
31
32
|
|
|
33
|
+
For information on external downloaders, see the [Embedded videos / links - external downloader](#embedded-videos--links---external-downloader) section. Example config is provided for fetching YouTube (replacing the built-in downloader) and Vimeo videos.
|
|
34
|
+
|
|
32
35
|
### FFmpeg dependency
|
|
33
36
|
|
|
34
37
|
[FFmpeg](https://ffmpeg.org) is required when downloading:
|
|
@@ -49,9 +52,9 @@ $ patreon-dl --configure-youtube
|
|
|
49
52
|
|
|
50
53
|
### Embedded videos / links - external downloader
|
|
51
54
|
|
|
52
|
-
You can specify external programs to download embedded videos or from embedded links. For YouTube videos, this will replace the built-in downloader.
|
|
55
|
+
You can specify external programs to download embedded videos or from embedded links. For YouTube videos, this will replace the built-in downloader.
|
|
53
56
|
|
|
54
|
-
|
|
57
|
+
See the [example config](./example-embed.conf) on how to configure an external downloader to fetch YouTube and Vimeo videos through [yt-dlp](https://github.com/yt-dlp/yt-dlp). For Vimeo videos, a [helper script](./bin/patreon-dl-vimeo.js) bundled with `patreon-dl` is used.
|
|
55
58
|
|
|
56
59
|
## Installation
|
|
57
60
|
|
|
@@ -242,7 +245,7 @@ $ patreon-dl-server [OPTION]
|
|
|
242
245
|
| `--log-file <file>` | `-f` | Save logs to `<file>`. |
|
|
243
246
|
|
|
244
247
|
|
|
245
|
-
### Example
|
|
248
|
+
### Example usage
|
|
246
249
|
|
|
247
250
|
Say you downloaded something with `patreon-dl`:
|
|
248
251
|
|
|
@@ -264,6 +267,28 @@ Note the URL shown in the output. Open this URL in a web browser to begin viewin
|
|
|
264
267
|
|
|
265
268
|
## Changelog
|
|
266
269
|
|
|
270
|
+
v3.2.0
|
|
271
|
+
- Fix:
|
|
272
|
+
- "Initial data not found" error in `patreon.com/cw` pages ([#85](https://github.com/patrickkfkan/patreon-dl/issues/85)) and custom-domain pages
|
|
273
|
+
- FFmpeg v7.x compatibility issues ([#86](https://github.com/patrickkfkan/patreon-dl/issues/86))
|
|
274
|
+
- Dry-run mode executing ops that should have been skipped
|
|
275
|
+
- Wrong log file path returned in some cases
|
|
276
|
+
- Various YouTube downloading issues
|
|
277
|
+
- Add:
|
|
278
|
+
- Support passing options to `yt-dlp` in Vimeo download script
|
|
279
|
+
- Support case-sensitivity flag in `config.include.mediaByFilename` options
|
|
280
|
+
- Browse:
|
|
281
|
+
- Show inline images within post body
|
|
282
|
+
- Show YouTube embed HTML content if video not downloaded ([#87](https://github.com/patrickkfkan/patreon-dl/issues/87))
|
|
283
|
+
- Display "show more" toggle for long post bodies
|
|
284
|
+
- API:
|
|
285
|
+
- `Downloader.getCampaign(params)`: enable lookup by `params.campaignId`
|
|
286
|
+
|
|
287
|
+
v3.1.0
|
|
288
|
+
- Defer database initialization until downloader starts
|
|
289
|
+
- UI: fix post column width possibly exceeding screen width
|
|
290
|
+
- Add `request.userAgent` option
|
|
291
|
+
|
|
267
292
|
v3.0.0
|
|
268
293
|
- Add support for browsing downloaded content through integrated web server. Note: this feature will not work for downloads made with previous versions of `patreon-dl`.
|
|
269
294
|
|
package/bin/patreon-dl-vimeo.js
CHANGED
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
* --video-password "<password>": for password-protected videos
|
|
16
16
|
* --yt-dlp "</path/to/yt-dlp>": if yt-dlp is not in the PATH
|
|
17
17
|
*
|
|
18
|
+
* You can pass options directly to yt-dlp. To do so, add '--' to the end of the exec line, followed by the options.
|
|
19
|
+
* For example:
|
|
20
|
+
* exec = patreon-dl-vimeo -o "{dest.dir}/%(title)s.%(ext)s" --embed-html "{embed.html}" --embed-url "{embed.url}" -- --cookies-from-browser firefox
|
|
21
|
+
*
|
|
18
22
|
* Upon encountering a post with embedded Vimeo content, 'patreon-dl' will call this script. The following then happens:
|
|
19
23
|
* - This script obtains the video URL from 'embed.html' or 'embed.url'. The former ("player URL") is always preferable
|
|
20
24
|
* since it is what's actually played within the Patreon post, and furthermore 'embed.url' sometimes returns
|
|
@@ -81,18 +85,23 @@ function getCommandString(cmd, args) {
|
|
|
81
85
|
].join(' ');
|
|
82
86
|
}
|
|
83
87
|
|
|
84
|
-
async function download(url, o, videoPassword, ytdlpPath) {
|
|
88
|
+
async function download(url, o, videoPassword, ytdlpPath, ytdlpArgs) {
|
|
85
89
|
let proc;
|
|
86
90
|
const ytdlp = ytdlpPath || 'yt-dlp';
|
|
91
|
+
const parsedYtdlpArgs = parseArgs(ytdlpArgs);
|
|
87
92
|
try {
|
|
88
93
|
return await new Promise((resolve, reject) => {
|
|
89
94
|
let settled = false;
|
|
90
|
-
const args = [
|
|
91
|
-
|
|
92
|
-
'
|
|
93
|
-
|
|
95
|
+
const args = [];
|
|
96
|
+
if (!parsedYtdlpArgs['o'] && !parsedYtdlpArgs['output']) {
|
|
97
|
+
args.push('-o', o);
|
|
98
|
+
}
|
|
99
|
+
if (!parsedYtdlpArgs['referrer']) {
|
|
100
|
+
args.push('--referer', 'https://patreon.com/');
|
|
101
|
+
}
|
|
102
|
+
args.push(...ytdlpArgs);
|
|
94
103
|
const printArgs = [...args];
|
|
95
|
-
if (videoPassword) {
|
|
104
|
+
if (videoPassword && !parsedYtdlpArgs['video-password']) {
|
|
96
105
|
args.push('--video-password', videoPassword);
|
|
97
106
|
printArgs.push('--video-password', '******');
|
|
98
107
|
}
|
|
@@ -147,6 +156,7 @@ const o = _o?.trim() ? path.resolve(_o.trim()) : null;
|
|
|
147
156
|
const embedHTML = _embedHTML?.trim();
|
|
148
157
|
const embedURL = _embedURL?.trim();
|
|
149
158
|
const ytdlpPath = _ytdlpPath?.trim() ? path.resolve(_ytdlpPath.trim()) : null;
|
|
159
|
+
const ytdlpArgs = args['_'];
|
|
150
160
|
|
|
151
161
|
if (!o) {
|
|
152
162
|
console.error('No output file specified');
|
|
@@ -166,7 +176,7 @@ if (!url) {
|
|
|
166
176
|
}
|
|
167
177
|
|
|
168
178
|
async function doDownload(_url) {
|
|
169
|
-
let code = await download(_url, o, videoPassword, ytdlpPath);
|
|
179
|
+
let code = await download(_url, o, videoPassword, ytdlpPath, ytdlpArgs);
|
|
170
180
|
if (code !== 0 && _url !== embedURL && embedURL) {
|
|
171
181
|
console.log(`Download failed - retrying with embed URL "${embedURL}"`);
|
|
172
182
|
return await doDownload(embedURL);
|
|
@@ -11,9 +11,11 @@ export declare function CampaignAPIMixin<TBase extends APIConstructor>(Base: TBa
|
|
|
11
11
|
withCounts?: false;
|
|
12
12
|
}): Promise<Campaign | null>;
|
|
13
13
|
getCampaign(params: GetCampaignParams): Promise<Campaign | CampaignWithCounts | null>;
|
|
14
|
+
"__#132@#sanitizeCampaign"(campaign: Campaign): void;
|
|
14
15
|
name: string;
|
|
15
16
|
db: import("../db").DBInstance;
|
|
16
17
|
logger?: import("../..").Logger | null;
|
|
18
|
+
sanitizeHTML(html: string): string;
|
|
17
19
|
log(level: import("../..").LogLevel, ...msg: any[]): void;
|
|
18
20
|
};
|
|
19
21
|
} & TBase;
|
|
@@ -1,18 +1,48 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
1
6
|
const DEFAULT_CAMPAIGN_LIST_SIZE = 10;
|
|
2
7
|
const DEFAULT_CAMPAIGN_LIST_SORT_BY = 'a-z';
|
|
3
8
|
export function CampaignAPIMixin(Base) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
var _CampaignAPI_instances, _CampaignAPI_sanitizeCampaign, _a;
|
|
10
|
+
return _a = class CampaignAPI extends Base {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
_CampaignAPI_instances.add(this);
|
|
14
|
+
}
|
|
15
|
+
async getCampaignList(params) {
|
|
16
|
+
const { sortBy = DEFAULT_CAMPAIGN_LIST_SORT_BY, limit = DEFAULT_CAMPAIGN_LIST_SIZE, offset = 0 } = params;
|
|
17
|
+
const list = await this.db.getCampaignList({
|
|
18
|
+
sortBy,
|
|
19
|
+
limit,
|
|
20
|
+
offset
|
|
21
|
+
});
|
|
22
|
+
for (const campaign of list.campaigns) {
|
|
23
|
+
__classPrivateFieldGet(this, _CampaignAPI_instances, "m", _CampaignAPI_sanitizeCampaign).call(this, campaign);
|
|
24
|
+
}
|
|
25
|
+
return list;
|
|
26
|
+
}
|
|
27
|
+
async getCampaign(params) {
|
|
28
|
+
const campaign = await this.db.getCampaign(params);
|
|
29
|
+
if (campaign) {
|
|
30
|
+
__classPrivateFieldGet(this, _CampaignAPI_instances, "m", _CampaignAPI_sanitizeCampaign).call(this, campaign);
|
|
31
|
+
}
|
|
32
|
+
return campaign;
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
_CampaignAPI_instances = new WeakSet(),
|
|
36
|
+
_CampaignAPI_sanitizeCampaign = function _CampaignAPI_sanitizeCampaign(campaign) {
|
|
37
|
+
if (campaign.summary) {
|
|
38
|
+
campaign.summary = this.sanitizeHTML(campaign.summary);
|
|
39
|
+
}
|
|
40
|
+
for (const reward of campaign.rewards) {
|
|
41
|
+
if (reward.description) {
|
|
42
|
+
reward.description = this.sanitizeHTML(reward.description);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
_a;
|
|
17
47
|
}
|
|
18
48
|
//# sourceMappingURL=CampaignAPIMixin.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CampaignAPIMixin.js","sourceRoot":"","sources":["../../../src/browse/api/CampaignAPIMixin.ts"],"names":[],"mappings":"AAKA,MAAM,0BAA0B,GAAG,EAAE,CAAC;AACtC,MAAM,6BAA6B,GAAuB,KAAK,CAAC;AAGhE,MAAM,UAAU,gBAAgB,CAA+B,IAAW
|
|
1
|
+
{"version":3,"file":"CampaignAPIMixin.js","sourceRoot":"","sources":["../../../src/browse/api/CampaignAPIMixin.ts"],"names":[],"mappings":";;;;;AAKA,MAAM,0BAA0B,GAAG,EAAE,CAAC;AACtC,MAAM,6BAA6B,GAAuB,KAAK,CAAC;AAGhE,MAAM,UAAU,gBAAgB,CAA+B,IAAW;;IACxE,YAAO,MAAM,WAAY,SAAQ,IAAI;YAA9B;;;YAmCP,CAAC;YAlCC,KAAK,CAAC,eAAe,CAAC,MAA6B;gBACjD,MAAM,EAAE,MAAM,GAAG,6BAA6B,EAAE,KAAK,GAAG,0BAA0B,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC;gBAC1G,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC;oBACzC,MAAM;oBACN,KAAK;oBACL,MAAM;iBACP,CAAC,CAAC;gBACH,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;oBACtC,uBAAA,IAAI,6DAAkB,MAAtB,IAAI,EAAmB,QAAQ,CAAC,CAAC;gBACnC,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;YAKD,KAAK,CAAC,WAAW,CAAC,MAAyB;gBACzC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;gBACnD,IAAI,QAAQ,EAAE,CAAC;oBACb,uBAAA,IAAI,6DAAkB,MAAtB,IAAI,EAAmB,QAAQ,CAAC,CAAC;gBACnC,CAAC;gBACD,OAAO,QAAQ,CAAC;YAClB,CAAC;SAYF;;+EAVmB,QAAkB;YAClC,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACrB,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACzD,CAAC;YACD,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;gBACtC,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;oBACvB,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;gBAC7D,CAAC;YACH,CAAC;QACH,CAAC;WACF;AACH,CAAC","sourcesContent":["import { type APIConstructor } from \".\";\nimport { type Campaign } from \"../../entities/index.js\";\nimport { type CampaignList, type CampaignListSortBy, type CampaignWithCounts, type GetCampaignListParams, type GetCampaignParams } from \"../types/Campaign.js\";\n\n\nconst DEFAULT_CAMPAIGN_LIST_SIZE = 10;\nconst DEFAULT_CAMPAIGN_LIST_SORT_BY: CampaignListSortBy = 'a-z';\n\n\nexport function CampaignAPIMixin<TBase extends APIConstructor>(Base: TBase) {\n return class CampaignAPI extends Base {\n async getCampaignList(params: GetCampaignListParams): Promise<CampaignList> {\n const { sortBy = DEFAULT_CAMPAIGN_LIST_SORT_BY, limit = DEFAULT_CAMPAIGN_LIST_SIZE, offset = 0 } = params;\n const list = await this.db.getCampaignList({\n sortBy,\n limit,\n offset\n });\n for (const campaign of list.campaigns) {\n this.#sanitizeCampaign(campaign);\n }\n return list;\n }\n\n async getCampaign(params: GetCampaignParams & { withCounts: true }): Promise<CampaignWithCounts | null>;\n async getCampaign(params: GetCampaignParams & { withCounts?: false }): Promise<Campaign | null>;\n async getCampaign(params: GetCampaignParams): Promise<Campaign | CampaignWithCounts | null>;\n async getCampaign(params: GetCampaignParams) {\n const campaign = await this.db.getCampaign(params);\n if (campaign) {\n this.#sanitizeCampaign(campaign);\n }\n return campaign;\n }\n\n #sanitizeCampaign(campaign: Campaign) {\n if (campaign.summary) {\n campaign.summary = this.sanitizeHTML(campaign.summary);\n }\n for (const reward of campaign.rewards) {\n if (reward.description) {\n reward.description = this.sanitizeHTML(reward.description);\n }\n }\n }\n }\n}"]}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { type APIConstructor } from ".";
|
|
2
|
+
import { type Post } from "../../entities";
|
|
2
3
|
import { type ContentType, type GetContentListParams } from "../types/Content.js";
|
|
3
4
|
export declare function ContentAPIMixin<TBase extends APIConstructor>(Base: TBase): {
|
|
4
5
|
new (...args: any[]): {
|
|
5
6
|
getContentList<T extends ContentType>(params: GetContentListParams<T>): Promise<import("../types/Content.js").ContentList<T>>;
|
|
6
7
|
getPost(id: string): Promise<import("../types/Content.js").PostWithComments | null>;
|
|
7
|
-
getProduct(id: string): Promise<import("
|
|
8
|
+
getProduct(id: string): Promise<import("../../entities").Product | null>;
|
|
9
|
+
"__#133@#processPostContentInlineMedia"(post: Post): void;
|
|
8
10
|
name: string;
|
|
9
11
|
db: import("../db").DBInstance;
|
|
10
12
|
logger?: import("../..").Logger | null;
|
|
13
|
+
sanitizeHTML(html: string): string;
|
|
11
14
|
log(level: import("../..").LogLevel, ...msg: any[]): void;
|
|
12
15
|
};
|
|
13
16
|
} & TBase;
|
|
@@ -1,22 +1,90 @@
|
|
|
1
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
2
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
3
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
|
+
};
|
|
6
|
+
import { load as cheerioLoad } from 'cheerio';
|
|
7
|
+
import RawDataExtractor from '../web/utils/RawDataExtractor.js';
|
|
1
8
|
const DEFAULT_CONTENT_LIST_SIZE = 10;
|
|
2
9
|
const DEFAULT_CONTENT_LIST_SORT_BY = 'a-z';
|
|
3
10
|
export function ContentAPIMixin(Base) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
offset
|
|
11
|
+
var _ContentAPI_instances, _ContentAPI_processPostContentInlineMedia, _a;
|
|
12
|
+
return _a = class ContentAPI extends Base {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
_ContentAPI_instances.add(this);
|
|
16
|
+
}
|
|
17
|
+
async getContentList(params) {
|
|
18
|
+
const { sortBy = DEFAULT_CONTENT_LIST_SORT_BY, limit = DEFAULT_CONTENT_LIST_SIZE, offset = 0 } = params;
|
|
19
|
+
const list = await this.db.getContentList({
|
|
20
|
+
...params,
|
|
21
|
+
sortBy,
|
|
22
|
+
limit,
|
|
23
|
+
offset,
|
|
24
|
+
});
|
|
25
|
+
for (const item of list.items) {
|
|
26
|
+
switch (item.type) {
|
|
27
|
+
case 'post':
|
|
28
|
+
__classPrivateFieldGet(this, _ContentAPI_instances, "m", _ContentAPI_processPostContentInlineMedia).call(this, item);
|
|
29
|
+
item.content = this.sanitizeHTML(item.content || '');
|
|
30
|
+
break;
|
|
31
|
+
case 'product': {
|
|
32
|
+
const description = RawDataExtractor.getProductRichTextDescription(item);
|
|
33
|
+
item.description = description ? this.sanitizeHTML(description) : null;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return list;
|
|
39
|
+
}
|
|
40
|
+
async getPost(id) {
|
|
41
|
+
const post = await this.db.getContent(id, 'post');
|
|
42
|
+
if (post) {
|
|
43
|
+
__classPrivateFieldGet(this, _ContentAPI_instances, "m", _ContentAPI_processPostContentInlineMedia).call(this, post);
|
|
44
|
+
post.content = this.sanitizeHTML(post.content || '');
|
|
45
|
+
}
|
|
46
|
+
return post;
|
|
47
|
+
}
|
|
48
|
+
getProduct(id) {
|
|
49
|
+
return this.db.getContent(id, 'product');
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
_ContentAPI_instances = new WeakSet(),
|
|
53
|
+
_ContentAPI_processPostContentInlineMedia = function _ContentAPI_processPostContentInlineMedia(post) {
|
|
54
|
+
const html = post.content || '';
|
|
55
|
+
if (!html || post.images.length === 0) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const $ = cheerioLoad(html);
|
|
59
|
+
const replacedMediaIds = [];
|
|
60
|
+
$('img').each((_, _el) => {
|
|
61
|
+
const el = $(_el);
|
|
62
|
+
const id = el.attr('data-media-id');
|
|
63
|
+
const matched = id ? post.images.find(img => img.id === id && img.downloaded) : null;
|
|
64
|
+
const src = matched ? `/media/${matched.id}` : el.attr('src');
|
|
65
|
+
const imgEl = $('<img>').attr('src', src);
|
|
66
|
+
const aEl = $('<a>')
|
|
67
|
+
.attr('href', src)
|
|
68
|
+
.attr('class', 'lightgallery-item')
|
|
69
|
+
.append(imgEl);
|
|
70
|
+
const wrapperEl = $('<div>')
|
|
71
|
+
.attr('class', 'post-card__inline-media-wrapper')
|
|
72
|
+
.append(aEl);
|
|
73
|
+
if (!matched) {
|
|
74
|
+
const caption = "(Externally hosted - not stored locally)";
|
|
75
|
+
wrapperEl.append($('<span>').attr('class', 'post-card__inline-media-caption').append(caption));
|
|
76
|
+
}
|
|
77
|
+
el.replaceWith(wrapperEl);
|
|
78
|
+
if (id && matched) {
|
|
79
|
+
replacedMediaIds.push(id);
|
|
80
|
+
}
|
|
12
81
|
});
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
};
|
|
82
|
+
if (replacedMediaIds.length > 0) {
|
|
83
|
+
post.content = $.html();
|
|
84
|
+
// Remove images that have been inlined
|
|
85
|
+
post.images = post.images.filter((img) => !replacedMediaIds.includes(img.id));
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
_a;
|
|
21
89
|
}
|
|
22
90
|
//# sourceMappingURL=ContentAPIMixin.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentAPIMixin.js","sourceRoot":"","sources":["../../../src/browse/api/ContentAPIMixin.ts"],"names":[],"mappings":"
|
|
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 Post } from \"../../entities\";\nimport { type ContentListSortBy, type ContentType, type GetContentListParams } from \"../types/Content.js\";\nimport RawDataExtractor from '../web/utils/RawDataExtractor.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 async 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 = await 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 async getPost(id: string) {\n const post = await 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 #processPostContentInlineMedia(post: Post) {\n const html = post.content || '';\n if (!html || post.images.length === 0) {\n return;\n }\n const $ = cheerioLoad(html);\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 post.content = $.html();\n // Remove images that have been inlined\n post.images = post.images.filter((img) => !replacedMediaIds.includes(img.id));\n }\n }\n }\n}"]}
|
|
@@ -3,12 +3,13 @@ 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): Promise<FilterData<PostFilterSearchParams>>;
|
|
6
|
-
"__#
|
|
6
|
+
"__#134@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
|
|
7
7
|
getProductFilterData(campaignId: string): Promise<FilterData<ProductFilterSearchParams>>;
|
|
8
8
|
getMediaFilterData(campaignId: string): Promise<FilterData<MediaFilterSearchParams>>;
|
|
9
9
|
name: string;
|
|
10
10
|
db: import("../db").DBInstance;
|
|
11
11
|
logger?: import("../..").Logger | null;
|
|
12
|
+
sanitizeHTML(html: string): string;
|
|
12
13
|
log(level: import("../..").LogLevel, ...msg: any[]): void;
|
|
13
14
|
};
|
|
14
15
|
} & TBase;
|
|
@@ -7,6 +7,7 @@ export declare function MediaAPIMixin<TBase extends APIConstructor>(Base: TBase)
|
|
|
7
7
|
name: string;
|
|
8
8
|
db: import("../db").DBInstance;
|
|
9
9
|
logger?: import("../..").Logger | null;
|
|
10
|
+
sanitizeHTML(html: string): string;
|
|
10
11
|
log(level: import("../..").LogLevel, ...msg: any[]): void;
|
|
11
12
|
};
|
|
12
13
|
} & TBase;
|
|
@@ -12,6 +12,7 @@ export declare function SettingsAPIMixin<TBase extends APIConstructor>(Base: TBa
|
|
|
12
12
|
name: string;
|
|
13
13
|
db: import("../db").DBInstance;
|
|
14
14
|
logger?: import("../..").Logger | null;
|
|
15
|
+
sanitizeHTML(html: string): string;
|
|
15
16
|
log(level: import("../..").LogLevel, ...msg: any[]): void;
|
|
16
17
|
};
|
|
17
18
|
} & TBase;
|
|
@@ -11,18 +11,20 @@ export declare class APIBase {
|
|
|
11
11
|
constructor(db: DBInstance, logger?: Logger | null);
|
|
12
12
|
static getInstance(db: DBInstance, logger?: Logger | null): {
|
|
13
13
|
getPostFilterData(campaignId: string): Promise<import("../types/Filter.js").FilterData<import("../types/Filter.js").PostFilterSearchParams>>;
|
|
14
|
-
"__#
|
|
14
|
+
"__#134@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
|
|
15
15
|
getProductFilterData(campaignId: string): Promise<import("../types/Filter.js").FilterData<import("../types/Filter.js").ProductFilterSearchParams>>;
|
|
16
16
|
getMediaFilterData(campaignId: string): Promise<import("../types/Filter.js").FilterData<import("../types/Filter.js").MediaFilterSearchParams>>;
|
|
17
17
|
name: string;
|
|
18
18
|
db: DBInstance;
|
|
19
19
|
logger?: Logger | null;
|
|
20
|
+
sanitizeHTML(html: string): string;
|
|
20
21
|
log(level: LogLevel, ...msg: any[]): void;
|
|
21
22
|
} & {
|
|
22
23
|
getMediaList<T extends import("../types/Content.js").ContentType>(params: import("../types/Media.js").GetMediaListParams<T>): Promise<import("../types/Media.js").MediaList<T>>;
|
|
23
24
|
name: string;
|
|
24
25
|
db: DBInstance;
|
|
25
26
|
logger?: Logger | null;
|
|
27
|
+
sanitizeHTML(html: string): string;
|
|
26
28
|
log(level: LogLevel, ...msg: any[]): void;
|
|
27
29
|
} & {
|
|
28
30
|
getBrowseSettings(): Promise<{
|
|
@@ -35,14 +37,17 @@ export declare class APIBase {
|
|
|
35
37
|
name: string;
|
|
36
38
|
db: DBInstance;
|
|
37
39
|
logger?: Logger | null;
|
|
40
|
+
sanitizeHTML(html: string): string;
|
|
38
41
|
log(level: LogLevel, ...msg: any[]): void;
|
|
39
42
|
} & {
|
|
40
43
|
getContentList<T extends import("../types/Content.js").ContentType>(params: import("../types/Content.js").GetContentListParams<T>): Promise<import("../types/Content.js").ContentList<T>>;
|
|
41
44
|
getPost(id: string): Promise<import("../types/Content.js").PostWithComments | null>;
|
|
42
45
|
getProduct(id: string): Promise<import("../../index.js").Product | null>;
|
|
46
|
+
"__#133@#processPostContentInlineMedia"(post: import("../../index.js").Post): void;
|
|
43
47
|
name: string;
|
|
44
48
|
db: DBInstance;
|
|
45
49
|
logger?: Logger | null;
|
|
50
|
+
sanitizeHTML(html: string): string;
|
|
46
51
|
log(level: LogLevel, ...msg: any[]): void;
|
|
47
52
|
} & {
|
|
48
53
|
getCampaignList(params: import("../types/Campaign.js").GetCampaignListParams): Promise<import("../types/Campaign.js").CampaignList>;
|
|
@@ -53,22 +58,26 @@ export declare class APIBase {
|
|
|
53
58
|
withCounts?: false;
|
|
54
59
|
}): Promise<import("../../index.js").Campaign | null>;
|
|
55
60
|
getCampaign(params: import("../types/Campaign.js").GetCampaignParams): Promise<import("../../index.js").Campaign | import("../types/Campaign.js").CampaignWithCounts | null>;
|
|
61
|
+
"__#132@#sanitizeCampaign"(campaign: import("../../index.js").Campaign): void;
|
|
56
62
|
name: string;
|
|
57
63
|
db: DBInstance;
|
|
58
64
|
logger?: Logger | null;
|
|
65
|
+
sanitizeHTML(html: string): string;
|
|
59
66
|
log(level: LogLevel, ...msg: any[]): void;
|
|
60
67
|
} & APIBase;
|
|
68
|
+
sanitizeHTML(html: string): string;
|
|
61
69
|
log(level: LogLevel, ...msg: any[]): void;
|
|
62
70
|
}
|
|
63
71
|
declare const API: {
|
|
64
72
|
new (...args: any[]): {
|
|
65
73
|
getPostFilterData(campaignId: string): Promise<import("../types/Filter.js").FilterData<import("../types/Filter.js").PostFilterSearchParams>>;
|
|
66
|
-
"__#
|
|
74
|
+
"__#134@#getPostTypeTitle"(postType: string): "Link" | "Audio" | "Image" | "Video" | "Other" | "Text" | "Podcast" | "Poll";
|
|
67
75
|
getProductFilterData(campaignId: string): Promise<import("../types/Filter.js").FilterData<import("../types/Filter.js").ProductFilterSearchParams>>;
|
|
68
76
|
getMediaFilterData(campaignId: string): Promise<import("../types/Filter.js").FilterData<import("../types/Filter.js").MediaFilterSearchParams>>;
|
|
69
77
|
name: string;
|
|
70
78
|
db: DBInstance;
|
|
71
79
|
logger?: Logger | null;
|
|
80
|
+
sanitizeHTML(html: string): string;
|
|
72
81
|
log(level: LogLevel, ...msg: any[]): void;
|
|
73
82
|
};
|
|
74
83
|
} & {
|
|
@@ -77,6 +86,7 @@ declare const API: {
|
|
|
77
86
|
name: string;
|
|
78
87
|
db: DBInstance;
|
|
79
88
|
logger?: Logger | null;
|
|
89
|
+
sanitizeHTML(html: string): string;
|
|
80
90
|
log(level: LogLevel, ...msg: any[]): void;
|
|
81
91
|
};
|
|
82
92
|
} & {
|
|
@@ -91,6 +101,7 @@ declare const API: {
|
|
|
91
101
|
name: string;
|
|
92
102
|
db: DBInstance;
|
|
93
103
|
logger?: Logger | null;
|
|
104
|
+
sanitizeHTML(html: string): string;
|
|
94
105
|
log(level: LogLevel, ...msg: any[]): void;
|
|
95
106
|
};
|
|
96
107
|
} & {
|
|
@@ -98,9 +109,11 @@ declare const API: {
|
|
|
98
109
|
getContentList<T extends import("../types/Content.js").ContentType>(params: import("../types/Content.js").GetContentListParams<T>): Promise<import("../types/Content.js").ContentList<T>>;
|
|
99
110
|
getPost(id: string): Promise<import("../types/Content.js").PostWithComments | null>;
|
|
100
111
|
getProduct(id: string): Promise<import("../../index.js").Product | null>;
|
|
112
|
+
"__#133@#processPostContentInlineMedia"(post: import("../../index.js").Post): void;
|
|
101
113
|
name: string;
|
|
102
114
|
db: DBInstance;
|
|
103
115
|
logger?: Logger | null;
|
|
116
|
+
sanitizeHTML(html: string): string;
|
|
104
117
|
log(level: LogLevel, ...msg: any[]): void;
|
|
105
118
|
};
|
|
106
119
|
} & {
|
|
@@ -113,9 +126,11 @@ declare const API: {
|
|
|
113
126
|
withCounts?: false;
|
|
114
127
|
}): Promise<import("../../index.js").Campaign | null>;
|
|
115
128
|
getCampaign(params: import("../types/Campaign.js").GetCampaignParams): Promise<import("../../index.js").Campaign | import("../types/Campaign.js").CampaignWithCounts | null>;
|
|
129
|
+
"__#132@#sanitizeCampaign"(campaign: import("../../index.js").Campaign): void;
|
|
116
130
|
name: string;
|
|
117
131
|
db: DBInstance;
|
|
118
132
|
logger?: Logger | null;
|
|
133
|
+
sanitizeHTML(html: string): string;
|
|
119
134
|
log(level: LogLevel, ...msg: any[]): void;
|
|
120
135
|
};
|
|
121
136
|
} & typeof APIBase;
|
package/dist/browse/api/index.js
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
import _sanitizeHTML from 'sanitize-html';
|
|
1
2
|
import { commonLog } from '../../utils/logging/Logger.js';
|
|
2
3
|
import { CampaignAPIMixin } from './CampaignAPIMixin.js';
|
|
3
4
|
import { ContentAPIMixin } from './ContentAPIMixin.js';
|
|
4
5
|
import { SettingsAPIMixin } from './SettingsAPIMixin.js';
|
|
5
6
|
import { MediaAPIMixin } from './MediaAPIMixin.js';
|
|
6
7
|
import { FilterAPIMixin } from './FilterAPIMixin.js';
|
|
8
|
+
const SANITIZE_HTML_OPTIONS = {
|
|
9
|
+
allowedTags: _sanitizeHTML.defaults.allowedTags.concat(['img']),
|
|
10
|
+
allowedAttributes: {
|
|
11
|
+
..._sanitizeHTML.defaults.allowedAttributes,
|
|
12
|
+
'*': ['class']
|
|
13
|
+
}
|
|
14
|
+
};
|
|
7
15
|
export class APIBase {
|
|
8
16
|
constructor(db, logger) {
|
|
9
17
|
this.name = 'API';
|
|
@@ -16,6 +24,9 @@ export class APIBase {
|
|
|
16
24
|
}
|
|
17
25
|
return this.instance;
|
|
18
26
|
}
|
|
27
|
+
sanitizeHTML(html) {
|
|
28
|
+
return _sanitizeHTML(html, SANITIZE_HTML_OPTIONS);
|
|
29
|
+
}
|
|
19
30
|
log(level, ...msg) {
|
|
20
31
|
const limiterStopOnError = msg.find((m) => m instanceof Error && m.message === 'LimiterStopOnError');
|
|
21
32
|
if (limiterStopOnError) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/browse/api/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/browse/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAiB,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAKrD,MAAM,qBAAqB,GAAG;IAC5B,WAAW,EAAE,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC;IAC/D,iBAAiB,EAAE;QACjB,GAAG,aAAa,CAAC,QAAQ,CAAC,iBAAiB;QAC3C,GAAG,EAAE,CAAC,OAAO,CAAC;KACf;CACF,CAAC;AAEF,MAAM,OAAO,OAAO;IAOlB,YAAY,EAAc,EAAE,MAAsB;QANlD,SAAI,GAAG,KAAK,CAAC;QAOX,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,EAAc,EAAE,MAAsB;QACvD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,YAAY,CAAC,IAAY;QACvB,OAAO,aAAa,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;IACpD,CAAC;IAED,GAAG,CAAC,KAAe,EAAE,GAAG,GAAU;QAChC,MAAM,kBAAkB,GAAG,GAAG,CAAC,IAAI,CACjC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,OAAO,KAAK,oBAAoB,CAChE,CAAC;QACF,IAAI,kBAAkB,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QACD,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,CAAC;IACnD,CAAC;;AA5BgB,gBAAQ,GAAuB,IAAI,AAA3B,CAA4B;AA+BvD,MAAM,GAAG,GAAG,cAAc,CAAC,aAAa,CAAC,gBAAgB,CAAC,eAAe,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAExG,eAAe,GAAG,CAAC","sourcesContent":["import _sanitizeHTML from 'sanitize-html';\nimport type Logger from '../../utils/logging/Logger.js';\nimport { commonLog, type LogLevel } from '../../utils/logging/Logger.js';\nimport { CampaignAPIMixin } from './CampaignAPIMixin.js';\nimport { type DBInstance } from '../db';\nimport { ContentAPIMixin } from './ContentAPIMixin.js';\nimport { SettingsAPIMixin } from './SettingsAPIMixin.js';\nimport { MediaAPIMixin } from './MediaAPIMixin.js';\nimport { FilterAPIMixin } from './FilterAPIMixin.js';\n\nexport type APIConstructor = new (...args: any[]) => APIBase;\nexport type APIInstance = InstanceType<typeof API>;\n\nconst SANITIZE_HTML_OPTIONS = {\n allowedTags: _sanitizeHTML.defaults.allowedTags.concat(['img']),\n allowedAttributes: {\n ..._sanitizeHTML.defaults.allowedAttributes,\n '*': ['class']\n }\n};\n\nexport class APIBase {\n name = 'API';\n\n protected static instance: APIInstance | null = null;\n db: DBInstance;\n logger?: Logger | null;\n\n constructor(db: DBInstance, logger?: Logger | null) {\n this.db = db;\n this.logger = logger;\n }\n\n static getInstance(db: DBInstance, logger?: Logger | null) {\n if (!this.instance) {\n this.instance = new API(db, logger);\n }\n return this.instance;\n }\n\n sanitizeHTML(html: string) {\n return _sanitizeHTML(html, SANITIZE_HTML_OPTIONS);\n }\n\n log(level: LogLevel, ...msg: any[]) {\n const limiterStopOnError = msg.find(\n (m) => m instanceof Error && m.message === 'LimiterStopOnError'\n );\n if (limiterStopOnError) {\n return;\n }\n commonLog(this.logger, level, this.name, ...msg);\n }\n}\n\nconst API = FilterAPIMixin(MediaAPIMixin(SettingsAPIMixin(ContentAPIMixin(CampaignAPIMixin(APIBase)))));\n\nexport default API;\n"]}
|
|
@@ -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): Promise<void>;
|
|
9
9
|
getCampaign(params: GetCampaignParams): Promise<Campaign | null>;
|
|
10
|
-
"__#
|
|
11
|
-
"__#
|
|
10
|
+
"__#118@#saveRewards"(campaign: Campaign): Promise<void>;
|
|
11
|
+
"__#118@#doSaveReward"(campaign: Campaign, reward: Reward): Promise<void>;
|
|
12
12
|
getCampaignList(params: GetCampaignListParams): Promise<CampaignList>;
|
|
13
|
-
"__#
|
|
13
|
+
"__#118@#getCampaignWithCounts"(params: GetCampaignParams): Promise<CampaignWithCounts | null>;
|
|
14
14
|
checkCampaignExists(id: string): Promise<boolean>;
|
|
15
15
|
saveUser(user: import("../../index.js").User | null): Promise<void>;
|
|
16
16
|
getUserByID(id: string): Promise<import("../../index.js").User | null>;
|
|
@@ -51,7 +51,7 @@ export declare function CampaignDBMixin<TBase extends UserDBConstructor>(Base: T
|
|
|
51
51
|
run(sql: import("sqlite").ISqlite.SqlType, ...params: any[]): Promise<import("sqlite").ISqlite.RunResult<import("sqlite3").Statement>>;
|
|
52
52
|
get<T = any>(sql: import("sqlite").ISqlite.SqlType, ...params: any[]): Promise<T | undefined>;
|
|
53
53
|
all<T = any[]>(sql: import("sqlite").ISqlite.SqlType, ...params: any[]): Promise<T>;
|
|
54
|
-
"__#
|
|
54
|
+
"__#120@#interpolateSqlParams"(sql: import("sqlite").ISqlite.SqlType | string, params: any[]): string;
|
|
55
55
|
log(level: import("../../index.js").LogLevel, ...msg: any[]): void;
|
|
56
56
|
};
|
|
57
57
|
} & TBase;
|