ghost 5.35.1 → 5.36.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/components/tryghost-adapter-cache-memory-ttl-5.36.0.tgz +0 -0
- package/components/tryghost-adapter-cache-redis-5.36.0.tgz +0 -0
- package/components/{tryghost-adapter-manager-5.35.1.tgz → tryghost-adapter-manager-5.36.0.tgz} +0 -0
- package/components/tryghost-api-framework-5.36.0.tgz +0 -0
- package/components/tryghost-api-version-compatibility-service-5.36.0.tgz +0 -0
- package/components/tryghost-audience-feedback-5.36.0.tgz +0 -0
- package/components/tryghost-bootstrap-socket-5.36.0.tgz +0 -0
- package/components/tryghost-constants-5.36.0.tgz +0 -0
- package/components/{tryghost-custom-theme-settings-service-5.35.1.tgz → tryghost-custom-theme-settings-service-5.36.0.tgz} +0 -0
- package/components/tryghost-data-generator-5.36.0.tgz +0 -0
- package/components/tryghost-domain-events-5.36.0.tgz +0 -0
- package/components/tryghost-dynamic-routing-events-5.36.0.tgz +0 -0
- package/components/{tryghost-email-analytics-provider-mailgun-5.35.1.tgz → tryghost-email-analytics-provider-mailgun-5.36.0.tgz} +0 -0
- package/components/tryghost-email-analytics-service-5.36.0.tgz +0 -0
- package/components/{tryghost-email-content-generator-5.35.1.tgz → tryghost-email-content-generator-5.36.0.tgz} +0 -0
- package/components/{tryghost-email-events-5.35.1.tgz → tryghost-email-events-5.36.0.tgz} +0 -0
- package/components/{tryghost-email-service-5.35.1.tgz → tryghost-email-service-5.36.0.tgz} +0 -0
- package/components/tryghost-email-suppression-list-5.36.0.tgz +0 -0
- package/components/tryghost-event-aware-cache-wrapper-5.36.0.tgz +0 -0
- package/components/{tryghost-express-dynamic-redirects-5.35.1.tgz → tryghost-express-dynamic-redirects-5.36.0.tgz} +0 -0
- package/components/tryghost-extract-api-key-5.36.0.tgz +0 -0
- package/components/tryghost-html-to-plaintext-5.36.0.tgz +0 -0
- package/components/tryghost-i18n-5.36.0.tgz +0 -0
- package/components/tryghost-importer-revue-5.36.0.tgz +0 -0
- package/components/tryghost-job-manager-5.36.0.tgz +0 -0
- package/components/tryghost-link-redirects-5.36.0.tgz +0 -0
- package/components/tryghost-link-replacer-5.36.0.tgz +0 -0
- package/components/tryghost-link-tracking-5.36.0.tgz +0 -0
- package/components/{tryghost-magic-link-5.35.1.tgz → tryghost-magic-link-5.36.0.tgz} +0 -0
- package/components/tryghost-mailgun-client-5.36.0.tgz +0 -0
- package/components/{tryghost-member-attribution-5.35.1.tgz → tryghost-member-attribution-5.36.0.tgz} +0 -0
- package/components/tryghost-member-events-5.36.0.tgz +0 -0
- package/components/tryghost-members-api-5.36.0.tgz +0 -0
- package/components/{tryghost-members-csv-5.35.1.tgz → tryghost-members-csv-5.36.0.tgz} +0 -0
- package/components/{tryghost-members-events-service-5.35.1.tgz → tryghost-members-events-service-5.36.0.tgz} +0 -0
- package/components/tryghost-members-importer-5.36.0.tgz +0 -0
- package/components/tryghost-members-offers-5.36.0.tgz +0 -0
- package/components/tryghost-members-payments-5.36.0.tgz +0 -0
- package/components/{tryghost-members-ssr-5.35.1.tgz → tryghost-members-ssr-5.36.0.tgz} +0 -0
- package/components/tryghost-members-stripe-service-5.36.0.tgz +0 -0
- package/components/tryghost-milestones-5.36.0.tgz +0 -0
- package/components/tryghost-minifier-5.36.0.tgz +0 -0
- package/components/tryghost-mw-api-version-mismatch-5.36.0.tgz +0 -0
- package/components/tryghost-mw-cache-control-5.36.0.tgz +0 -0
- package/components/tryghost-mw-error-handler-5.36.0.tgz +0 -0
- package/components/tryghost-mw-session-from-token-5.36.0.tgz +0 -0
- package/components/tryghost-mw-update-user-last-seen-5.36.0.tgz +0 -0
- package/components/tryghost-mw-vhost-5.36.0.tgz +0 -0
- package/components/tryghost-oembed-service-5.36.0.tgz +0 -0
- package/components/tryghost-package-json-5.36.0.tgz +0 -0
- package/components/tryghost-referrers-5.36.0.tgz +0 -0
- package/components/tryghost-security-5.36.0.tgz +0 -0
- package/components/{tryghost-session-service-5.35.1.tgz → tryghost-session-service-5.36.0.tgz} +0 -0
- package/components/tryghost-settings-path-manager-5.36.0.tgz +0 -0
- package/components/tryghost-slack-notifications-5.36.0.tgz +0 -0
- package/components/tryghost-staff-service-5.36.0.tgz +0 -0
- package/components/tryghost-stats-service-5.36.0.tgz +0 -0
- package/components/tryghost-tiers-5.36.0.tgz +0 -0
- package/components/tryghost-update-check-service-5.36.0.tgz +0 -0
- package/components/tryghost-verification-trigger-5.36.0.tgz +0 -0
- package/components/tryghost-version-notifications-data-service-5.36.0.tgz +0 -0
- package/components/tryghost-webmentions-5.36.0.tgz +0 -0
- package/core/built/admin/assets/{chunk.143.3e5760df9072a9463476.js → chunk.143.d5eaed4616c55cdbdabb.js} +6 -6
- package/core/built/admin/assets/{chunk.178.773722be9deba376bacb.js → chunk.178.8cafcc33fe672738cc5b.js} +4 -4
- package/core/built/admin/assets/{chunk.502.c4afca88c98edad8b268.js → chunk.502.800e1515996bcc900013.js} +3 -3
- package/core/built/admin/assets/{chunk.79.ec143a398298020c87e6.js → chunk.79.53e8aa9671b2d5dae8ba.js} +1 -1
- package/core/built/admin/assets/codemirror/{codemirror-6c43f4894cbd8db73d7f35cde836c58e.js → codemirror-3f3b9966a7237652dd31484694e38ad5.js} +1 -1
- package/core/built/admin/assets/{ghost-1d4b69d04b8a97e8a1bd83ed5bb20777.css → ghost-7ecf5c7934d90798485ee5ac2956f7fe.css} +1 -1
- package/core/built/admin/assets/{ghost-5f530fdaca961aa2ec5c339d5bb13443.js → ghost-b828e9e3c161aae92909c2e163656bb1.js} +281 -261
- package/core/built/admin/assets/{ghost-dark-633bf4628beead68e8a0d1fa668735ff.css → ghost-dark-e50717df8e57d3e7fee67a0bcea895ad.css} +1 -1
- package/core/built/admin/assets/img/mentions-background-fa39b7597e875c165b12190eda606993.png +0 -0
- package/core/built/admin/assets/simplemde/{simplemde-28049a9bd7f432b0648747eb26958a33.js → simplemde-9cd5549b68db674742d6ec2ecd72ac30.js} +1 -1
- package/core/built/admin/assets/vendor-c4684647d4f5213e5dbb6763de430e7e.js +22 -21
- package/core/built/admin/index.html +5 -5
- package/core/server/adapters/cache/MemoryTTL.js +3 -0
- package/core/server/api/endpoints/pages-public.js +1 -2
- package/core/server/api/endpoints/posts-public.js +2 -1
- package/core/server/api/endpoints/tags-public.js +2 -1
- package/core/server/api/endpoints/utils/serializers/input/index.js +4 -0
- package/core/server/api/endpoints/utils/serializers/input/mentions.js +11 -0
- package/core/server/api/endpoints/utils/serializers/output/mappers/posts.js +2 -5
- package/core/server/api/endpoints/utils/serializers/output/utils/clean.js +1 -0
- package/core/server/api/endpoints/utils/serializers/output/utils/extra-attrs.js +19 -11
- package/core/server/data/exporter/table-lists.js +2 -1
- package/core/server/data/migrations/versions/5.36/2023-02-20-12-22-add-milestones-table.js +10 -0
- package/core/server/data/migrations/versions/5.36/2023-02-21-12-29-add-milestone-notifications-column.js +7 -0
- package/core/server/data/migrations/versions/5.36/2023-02-23-10-40-set-outbound-link-tagging-based-on-source-tracking.js +31 -0
- package/core/server/data/schema/schema.js +9 -0
- package/core/server/lib/request-external.js +14 -13
- package/core/server/models/milestone.js +9 -0
- package/core/server/models/user.js +4 -1
- package/core/server/services/email-suppression-list/MailgunEmailSuppressionList.js +2 -0
- package/core/server/services/mentions/BookshelfMentionRepository.js +2 -1
- package/core/server/services/mentions/ResourceService.js +6 -0
- package/core/server/services/mentions/RoutingService.js +2 -1
- package/core/server/services/mentions/service.js +1 -3
- package/core/server/services/milestones/BookshelfMilestoneRepository.js +136 -0
- package/core/server/services/milestones/MilestoneQueries.js +8 -3
- package/core/server/services/milestones/service.js +47 -9
- package/core/server/services/oembed/nft-oembed.js +1 -2
- package/core/server/services/posts-public/service.js +21 -9
- package/core/server/services/tags-public/service.js +21 -10
- package/core/server/services/websockets/service.js +2 -1
- package/core/shared/config/defaults.json +5 -2
- package/core/shared/labs.js +4 -3
- package/package.json +125 -124
- package/yarn.lock +151 -199
- package/components/tryghost-adapter-cache-redis-5.35.1.tgz +0 -0
- package/components/tryghost-api-framework-5.35.1.tgz +0 -0
- package/components/tryghost-api-version-compatibility-service-5.35.1.tgz +0 -0
- package/components/tryghost-audience-feedback-5.35.1.tgz +0 -0
- package/components/tryghost-bootstrap-socket-5.35.1.tgz +0 -0
- package/components/tryghost-constants-5.35.1.tgz +0 -0
- package/components/tryghost-data-generator-5.35.1.tgz +0 -0
- package/components/tryghost-domain-events-5.35.1.tgz +0 -0
- package/components/tryghost-dynamic-routing-events-5.35.1.tgz +0 -0
- package/components/tryghost-email-analytics-service-5.35.1.tgz +0 -0
- package/components/tryghost-email-suppression-list-5.35.1.tgz +0 -0
- package/components/tryghost-extract-api-key-5.35.1.tgz +0 -0
- package/components/tryghost-html-to-plaintext-5.35.1.tgz +0 -0
- package/components/tryghost-i18n-5.35.1.tgz +0 -0
- package/components/tryghost-importer-revue-5.35.1.tgz +0 -0
- package/components/tryghost-job-manager-5.35.1.tgz +0 -0
- package/components/tryghost-link-redirects-5.35.1.tgz +0 -0
- package/components/tryghost-link-replacer-5.35.1.tgz +0 -0
- package/components/tryghost-link-tracking-5.35.1.tgz +0 -0
- package/components/tryghost-mailgun-client-5.35.1.tgz +0 -0
- package/components/tryghost-member-events-5.35.1.tgz +0 -0
- package/components/tryghost-members-api-5.35.1.tgz +0 -0
- package/components/tryghost-members-importer-5.35.1.tgz +0 -0
- package/components/tryghost-members-offers-5.35.1.tgz +0 -0
- package/components/tryghost-members-payments-5.35.1.tgz +0 -0
- package/components/tryghost-members-stripe-service-5.35.1.tgz +0 -0
- package/components/tryghost-milestones-5.35.1.tgz +0 -0
- package/components/tryghost-minifier-5.35.1.tgz +0 -0
- package/components/tryghost-mw-api-version-mismatch-5.35.1.tgz +0 -0
- package/components/tryghost-mw-cache-control-5.35.1.tgz +0 -0
- package/components/tryghost-mw-error-handler-5.35.1.tgz +0 -0
- package/components/tryghost-mw-session-from-token-5.35.1.tgz +0 -0
- package/components/tryghost-mw-update-user-last-seen-5.35.1.tgz +0 -0
- package/components/tryghost-mw-vhost-5.35.1.tgz +0 -0
- package/components/tryghost-oembed-service-5.35.1.tgz +0 -0
- package/components/tryghost-package-json-5.35.1.tgz +0 -0
- package/components/tryghost-public-resource-repository-5.35.1.tgz +0 -0
- package/components/tryghost-referrers-5.35.1.tgz +0 -0
- package/components/tryghost-security-5.35.1.tgz +0 -0
- package/components/tryghost-settings-path-manager-5.35.1.tgz +0 -0
- package/components/tryghost-slack-notifications-5.35.1.tgz +0 -0
- package/components/tryghost-staff-service-5.35.1.tgz +0 -0
- package/components/tryghost-stats-service-5.35.1.tgz +0 -0
- package/components/tryghost-tiers-5.35.1.tgz +0 -0
- package/components/tryghost-update-check-service-5.35.1.tgz +0 -0
- package/components/tryghost-verification-trigger-5.35.1.tgz +0 -0
- package/components/tryghost-version-notifications-data-service-5.35.1.tgz +0 -0
- package/components/tryghost-webmentions-5.35.1.tgz +0 -0
- /package/core/built/admin/assets/{chunk.502.c4afca88c98edad8b268.js.LICENSE.txt → chunk.502.800e1515996bcc900013.js.LICENSE.txt} +0 -0
|
@@ -70,17 +70,15 @@ module.exports = {
|
|
|
70
70
|
if (!id) {
|
|
71
71
|
return null;
|
|
72
72
|
}
|
|
73
|
-
|
|
74
73
|
const post = await models.Post.findOne({id: id.toHexString()});
|
|
75
74
|
|
|
76
75
|
if (!post) {
|
|
77
76
|
return null;
|
|
78
77
|
}
|
|
79
|
-
|
|
80
78
|
return {
|
|
81
79
|
id: id,
|
|
82
80
|
name: post.get('title'),
|
|
83
|
-
type:
|
|
81
|
+
type: post.get('type')
|
|
84
82
|
};
|
|
85
83
|
}
|
|
86
84
|
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
const {Milestone} = require('@tryghost/milestones');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import('@tryghost/milestones/lib/MilestonesService').IMilestoneRepository} IMilestoneRepository
|
|
5
|
+
* @typedef {import('@tryghost/milestones/lib/MilestonesService')} Milestone
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @implements {IMilestoneRepository}
|
|
10
|
+
*/
|
|
11
|
+
module.exports = class BookshelfMilestoneRepository {
|
|
12
|
+
/** @type {Object} */
|
|
13
|
+
#MilestoneModel;
|
|
14
|
+
|
|
15
|
+
/** @type {import('@tryghost/domain-events')} */
|
|
16
|
+
#DomainEvents;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {object} deps
|
|
20
|
+
* @param {object} deps.MilestoneModel Bookshelf Model
|
|
21
|
+
* @param {import('@tryghost/domain-events')} deps.DomainEvents
|
|
22
|
+
*/
|
|
23
|
+
constructor(deps) {
|
|
24
|
+
this.#MilestoneModel = deps.MilestoneModel;
|
|
25
|
+
this.#DomainEvents = deps.DomainEvents;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#modelToMilestone(model) {
|
|
29
|
+
return Milestone.create({
|
|
30
|
+
id: model.get('id'),
|
|
31
|
+
type: model.get('type'),
|
|
32
|
+
value: model.get('value'),
|
|
33
|
+
currency: model.get('currency'),
|
|
34
|
+
createdAt: model.get('created_at'),
|
|
35
|
+
emailSentAt: model.get('email_sent_at')
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {import('@tryghost/milestones/lib/Milestone')} milestone
|
|
41
|
+
* @returns {Promise<void>}
|
|
42
|
+
*/
|
|
43
|
+
async save(milestone) {
|
|
44
|
+
const data = {
|
|
45
|
+
id: milestone.id.toHexString(),
|
|
46
|
+
type: milestone.type,
|
|
47
|
+
value: milestone.value,
|
|
48
|
+
currency: milestone?.currency,
|
|
49
|
+
created_at: milestone?.createdAt,
|
|
50
|
+
email_sent_at: milestone?.emailSentAt
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const existing = await this.#MilestoneModel.findOne({id: data.id}, {require: false});
|
|
54
|
+
|
|
55
|
+
if (!existing) {
|
|
56
|
+
await this.#MilestoneModel.add(data);
|
|
57
|
+
} else {
|
|
58
|
+
await this.#MilestoneModel.edit(data, {
|
|
59
|
+
id: data.id
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
for (const event of milestone.events) {
|
|
63
|
+
this.#DomainEvents.dispatch(event);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @param {'arr'|'members'} type
|
|
69
|
+
* @param {string} [currency]
|
|
70
|
+
*
|
|
71
|
+
* @returns {Promise<import('@tryghost/milestones/lib/Milestone')|null>}
|
|
72
|
+
*/
|
|
73
|
+
async getLatestByType(type, currency = 'usd') {
|
|
74
|
+
let milestone = null;
|
|
75
|
+
|
|
76
|
+
if (type === 'arr') {
|
|
77
|
+
milestone = await this.#MilestoneModel.findAll({filter: `currency:${currency}+type:arr`, order: 'created_at ASC, value DESC'}, {require: false});
|
|
78
|
+
} else {
|
|
79
|
+
milestone = await this.#MilestoneModel.findAll({filter: 'type:members', order: 'created_at ASC, value DESC'}, {require: false});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!milestone || !milestone?.models?.length) {
|
|
83
|
+
return null;
|
|
84
|
+
} else {
|
|
85
|
+
milestone = milestone.models?.[0];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return this.#modelToMilestone(milestone);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @returns {Promise<import('@tryghost/milestones/lib/Milestone')|null>}
|
|
93
|
+
*/
|
|
94
|
+
async getLastEmailSent() {
|
|
95
|
+
let milestone = await this.#MilestoneModel.findAll({filter: 'email_sent_at:-null', order: 'email_sent_at ASC'}, {require: false});
|
|
96
|
+
|
|
97
|
+
if (!milestone || !milestone?.models?.length) {
|
|
98
|
+
return null;
|
|
99
|
+
} else {
|
|
100
|
+
milestone = milestone.models?.[0];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return this.#modelToMilestone(milestone);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @param {number} value
|
|
108
|
+
* @param {string} [currency]
|
|
109
|
+
*
|
|
110
|
+
* @returns {Promise<import('@tryghost/milestones/lib/Milestone')|null>}
|
|
111
|
+
*/
|
|
112
|
+
async getByARR(value, currency = 'usd') {
|
|
113
|
+
// find a milestone of the ARR type by a given value
|
|
114
|
+
const milestone = await this.#MilestoneModel.findOne({type: 'arr', currency: currency, value: value}, {require: false});
|
|
115
|
+
|
|
116
|
+
if (!milestone) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
return this.#modelToMilestone(milestone);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @param {number} value
|
|
124
|
+
*
|
|
125
|
+
* @returns {Promise<import('@tryghost/milestones/lib/Milestone')|null>}
|
|
126
|
+
*/
|
|
127
|
+
async getByCount(value) {
|
|
128
|
+
// find a milestone of the members type by a given value
|
|
129
|
+
const milestone = await this.#MilestoneModel.findOne({type: 'members', value: value}, {require: false});
|
|
130
|
+
|
|
131
|
+
if (!milestone) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
return this.#modelToMilestone(milestone);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
const MIN_DAYS_SINCE_IMPORTED = 7;
|
|
2
|
-
|
|
3
1
|
module.exports = class MilestoneQueries {
|
|
4
2
|
#db;
|
|
5
3
|
|
|
4
|
+
/** @type {number} */
|
|
5
|
+
#minDaysSinceImported;
|
|
6
|
+
|
|
6
7
|
constructor(deps) {
|
|
7
8
|
this.#db = deps.db;
|
|
9
|
+
this.#minDaysSinceImported = deps.minDaysSinceImported;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
/**
|
|
@@ -31,10 +33,13 @@ module.exports = class MilestoneQueries {
|
|
|
31
33
|
* @returns {Promise<boolean>}
|
|
32
34
|
*/
|
|
33
35
|
async hasImportedMembersInPeriod() {
|
|
36
|
+
const importedThreshold = new Date();
|
|
37
|
+
importedThreshold.setDate(importedThreshold.getDate() - this.#minDaysSinceImported);
|
|
38
|
+
|
|
34
39
|
const [hasImportedMembers] = await this.#db.knex('members_subscribe_events')
|
|
35
40
|
.count('id as count')
|
|
36
41
|
.where('source', '=', 'import')
|
|
37
|
-
.where('created_at', '>=',
|
|
42
|
+
.where('created_at', '>=', importedThreshold);
|
|
38
43
|
|
|
39
44
|
return hasImportedMembers?.count > 0;
|
|
40
45
|
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
const DomainEvents = require('@tryghost/domain-events');
|
|
2
|
+
const logging = require('@tryghost/logging');
|
|
3
|
+
const models = require('../../models');
|
|
4
|
+
const BookshelfMilestoneRepository = require('./BookshelfMilestoneRepository');
|
|
5
|
+
|
|
6
|
+
const JOB_TIMEOUT = 1000 * 60 * 60 * 24 * (Math.floor(Math.random() * 4)); // 0 - 4 days;
|
|
2
7
|
|
|
3
8
|
const getStripeLiveEnabled = () => {
|
|
4
9
|
const settingsCache = require('../../../shared/settings-cache');
|
|
@@ -28,19 +33,23 @@ module.exports = {
|
|
|
28
33
|
const db = require('../../data/db');
|
|
29
34
|
const MilestoneQueries = require('./MilestoneQueries');
|
|
30
35
|
|
|
31
|
-
const {
|
|
32
|
-
MilestonesService,
|
|
33
|
-
InMemoryMilestoneRepository
|
|
34
|
-
} = require('@tryghost/milestones');
|
|
36
|
+
const {MilestonesService} = require('@tryghost/milestones');
|
|
35
37
|
const config = require('../../../shared/config');
|
|
36
38
|
const milestonesConfig = config.get('milestones');
|
|
37
39
|
|
|
38
|
-
const repository = new
|
|
39
|
-
|
|
40
|
+
const repository = new BookshelfMilestoneRepository({
|
|
41
|
+
DomainEvents,
|
|
42
|
+
MilestoneModel: models.Milestone
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const queries = new MilestoneQueries({
|
|
46
|
+
db,
|
|
47
|
+
minDaysSinceImported: milestonesConfig?.minDaysSinceImported || 7
|
|
48
|
+
});
|
|
40
49
|
|
|
41
50
|
this.api = new MilestonesService({
|
|
42
51
|
repository,
|
|
43
|
-
milestonesConfig,
|
|
52
|
+
milestonesConfig,
|
|
44
53
|
queries
|
|
45
54
|
});
|
|
46
55
|
}
|
|
@@ -69,10 +78,39 @@ module.exports = {
|
|
|
69
78
|
},
|
|
70
79
|
|
|
71
80
|
/**
|
|
81
|
+
*
|
|
82
|
+
* @param {number} [customTimeout]
|
|
83
|
+
*
|
|
84
|
+
* @returns {Promise<object>}
|
|
85
|
+
*/
|
|
86
|
+
async scheduleRun(customTimeout) {
|
|
87
|
+
const timeOut = customTimeout || JOB_TIMEOUT;
|
|
88
|
+
|
|
89
|
+
const today = new Date();
|
|
90
|
+
const msNow = today.getMilliseconds();
|
|
91
|
+
const newMs = msNow + timeOut;
|
|
92
|
+
const jobDate = today.setMilliseconds(newMs);
|
|
93
|
+
|
|
94
|
+
logging.info(`Running milestone emails job on ${new Date(jobDate).toString()}`);
|
|
95
|
+
|
|
96
|
+
return new Promise((resolve) => {
|
|
97
|
+
setTimeout(async () => {
|
|
98
|
+
const result = await this.run();
|
|
99
|
+
return resolve(result);
|
|
100
|
+
}, timeOut);
|
|
101
|
+
});
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @param {number} [customTimeout]
|
|
106
|
+
* Only used temporary for testing purposes.
|
|
107
|
+
* Will be removed, after job scheduling implementation.
|
|
108
|
+
*
|
|
72
109
|
* @returns {Promise<object>}
|
|
73
110
|
*/
|
|
74
|
-
async initAndRun() {
|
|
111
|
+
async initAndRun(customTimeout) {
|
|
75
112
|
await this.init();
|
|
76
|
-
|
|
113
|
+
|
|
114
|
+
return this.scheduleRun(customTimeout);
|
|
77
115
|
}
|
|
78
116
|
};
|
|
@@ -42,9 +42,8 @@ class NFTOEmbedProvider {
|
|
|
42
42
|
headers['X-API-KEY'] = this.dependencies.config.apiKey;
|
|
43
43
|
}
|
|
44
44
|
const result = await externalRequest(`https://api.opensea.io/api/v1/asset/${transaction}/${asset}/?format=json`, {
|
|
45
|
-
json: true,
|
|
46
45
|
headers
|
|
47
|
-
});
|
|
46
|
+
}).json();
|
|
48
47
|
return {
|
|
49
48
|
version: '1.0',
|
|
50
49
|
type: 'nft',
|
|
@@ -6,24 +6,36 @@ class PostsPublicServiceWrapper {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
// Wire up all the dependencies
|
|
9
|
-
const {Post} = require('../../models');
|
|
10
9
|
const adapterManager = require('../adapter-manager');
|
|
11
10
|
const config = require('../../../shared/config');
|
|
11
|
+
const EventAwareCacheWrapper = require('@tryghost/event-aware-cache-wrapper');
|
|
12
|
+
const EventRegistry = require('../../lib/common/events');
|
|
12
13
|
|
|
13
14
|
let postsCache;
|
|
14
15
|
if (config.get('hostSettings:postsPublicCache:enabled')) {
|
|
15
|
-
|
|
16
|
+
const cache = adapterManager.getAdapter('cache:postsPublic');
|
|
17
|
+
postsCache = new EventAwareCacheWrapper({
|
|
18
|
+
cache: cache,
|
|
19
|
+
resetEvents: ['site.changed'],
|
|
20
|
+
eventRegistry: EventRegistry
|
|
21
|
+
});
|
|
16
22
|
}
|
|
17
23
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
let cache;
|
|
25
|
+
if (postsCache) {
|
|
26
|
+
// @NOTE: exposing cache through getter and setter to not loose the context of "this"
|
|
27
|
+
cache = {
|
|
28
|
+
get() {
|
|
29
|
+
return postsCache.get(...arguments);
|
|
30
|
+
},
|
|
31
|
+
set() {
|
|
32
|
+
return postsCache.set(...arguments);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
24
36
|
|
|
25
37
|
this.api = {
|
|
26
|
-
|
|
38
|
+
cache: cache
|
|
27
39
|
};
|
|
28
40
|
}
|
|
29
41
|
}
|
|
@@ -6,24 +6,35 @@ class TagsPublicServiceWrapper {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
// Wire up all the dependencies
|
|
9
|
-
const {TagPublic} = require('../../models');
|
|
10
9
|
const adapterManager = require('../adapter-manager');
|
|
11
10
|
const config = require('../../../shared/config');
|
|
11
|
+
const EventAwareCacheWrapper = require('@tryghost/event-aware-cache-wrapper');
|
|
12
|
+
const EventRegistry = require('../../lib/common/events');
|
|
12
13
|
|
|
13
14
|
let tagsCache;
|
|
14
15
|
if (config.get('hostSettings:tagsPublicCache:enabled')) {
|
|
15
|
-
|
|
16
|
+
let tagsPublicCache = adapterManager.getAdapter('cache:tagsPublic');
|
|
17
|
+
tagsCache = new EventAwareCacheWrapper({
|
|
18
|
+
cache: tagsPublicCache,
|
|
19
|
+
resetEvents: ['site.changed'],
|
|
20
|
+
eventRegistry: EventRegistry
|
|
21
|
+
});
|
|
16
22
|
}
|
|
17
23
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
let cache;
|
|
25
|
+
if (tagsCache) {
|
|
26
|
+
// @NOTE: exposing cache through getter and setter to not loose the context of "this"
|
|
27
|
+
cache = {
|
|
28
|
+
get() {
|
|
29
|
+
return tagsCache.get(...arguments);
|
|
30
|
+
},
|
|
31
|
+
set() {
|
|
32
|
+
return tagsCache.set(...arguments);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
25
36
|
this.api = {
|
|
26
|
-
|
|
37
|
+
cache: cache
|
|
27
38
|
};
|
|
28
39
|
}
|
|
29
40
|
}
|
|
@@ -15,7 +15,8 @@ module.exports = {
|
|
|
15
15
|
let count = 0;
|
|
16
16
|
|
|
17
17
|
io.on(`connection`, (socket) => {
|
|
18
|
-
|
|
18
|
+
logging.info(`Websockets client connected (id: ${socket.id})`);
|
|
19
|
+
|
|
19
20
|
// on connect, send current value
|
|
20
21
|
socket.emit('addCount', count);
|
|
21
22
|
// listen to to changes in value from client
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
},
|
|
177
177
|
"portal": {
|
|
178
178
|
"url": "https://cdn.jsdelivr.net/ghost/portal@~{version}/umd/portal.min.js",
|
|
179
|
-
"version": "2.
|
|
179
|
+
"version": "2.25"
|
|
180
180
|
},
|
|
181
181
|
"sodoSearch": {
|
|
182
182
|
"url": "https://cdn.jsdelivr.net/ghost/sodo-search@~{version}/umd/sodo-search.min.js",
|
|
@@ -213,6 +213,9 @@
|
|
|
213
213
|
"values": [100, 1000, 10000, 50000, 100000, 250000, 500000, 1000000]
|
|
214
214
|
}
|
|
215
215
|
],
|
|
216
|
-
"members": [100, 1000, 10000, 25000, 50000, 100000, 250000, 500000, 1000000]
|
|
216
|
+
"members": [100, 1000, 10000, 25000, 50000, 100000, 250000, 500000, 1000000],
|
|
217
|
+
"minDaysSinceImported": 7,
|
|
218
|
+
"minDaysSinceLastEmail": 14,
|
|
219
|
+
"maxPercentageFromMilestone": 0.1
|
|
217
220
|
}
|
|
218
221
|
}
|
package/core/shared/labs.js
CHANGED
|
@@ -21,7 +21,8 @@ const GA_FEATURES = [
|
|
|
21
21
|
'audienceFeedback',
|
|
22
22
|
'themeErrorsNotification',
|
|
23
23
|
'emailStability',
|
|
24
|
-
'emailErrors'
|
|
24
|
+
'emailErrors',
|
|
25
|
+
'outboundLinkTagging'
|
|
25
26
|
];
|
|
26
27
|
|
|
27
28
|
// NOTE: this allowlist is meant to be used to filter out any unexpected
|
|
@@ -36,8 +37,8 @@ const ALPHA_FEATURES = [
|
|
|
36
37
|
'urlCache',
|
|
37
38
|
'beforeAfterCard',
|
|
38
39
|
'lexicalEditor',
|
|
39
|
-
'
|
|
40
|
-
'
|
|
40
|
+
'websockets',
|
|
41
|
+
'webmentionEmails'
|
|
41
42
|
];
|
|
42
43
|
|
|
43
44
|
module.exports.GA_KEYS = [...GA_FEATURES];
|