combined fetch for metadata and verification (#16330)
refs TryGhost/Team#2582 -removed duplicative fetch request -added mention as type in oembed service
This commit is contained in:
parent
cd0115deec
commit
9e58181398
@ -6,14 +6,15 @@ module.exports = class WebmentionMetadata {
|
||||
* @returns {Promise<import('@tryghost/webmentions/lib/MentionsAPI').WebmentionMetadata>}
|
||||
*/
|
||||
async fetch(url) {
|
||||
const data = await oembedService.fetchOembedDataFromUrl(url.href, 'bookmark');
|
||||
const data = await oembedService.fetchOembedDataFromUrl(url.href, 'mention');
|
||||
const result = {
|
||||
siteTitle: data.metadata.publisher,
|
||||
title: data.metadata.title,
|
||||
excerpt: data.metadata.description,
|
||||
author: data.metadata.author,
|
||||
image: data.metadata.thumbnail ? new URL(data.metadata.thumbnail) : null,
|
||||
favicon: data.metadata.icon ? new URL(data.metadata.icon) : null
|
||||
favicon: data.metadata.icon ? new URL(data.metadata.icon) : null,
|
||||
body: data.body
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
const logging = require('@tryghost/logging');
|
||||
const oembedService = require('../oembed');
|
||||
|
||||
module.exports = class WebmentionRequest {
|
||||
/**
|
||||
* @param {URL} url
|
||||
* @returns {Promise<{html: string}>}
|
||||
*/
|
||||
async fetch(url) {
|
||||
try {
|
||||
const data = await oembedService.fetchPageHtml(url.href);
|
||||
return {
|
||||
html: data.body
|
||||
};
|
||||
} catch (err) {
|
||||
logging.warn(err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
@ -1,6 +1,5 @@
|
||||
const MentionController = require('./MentionController');
|
||||
const WebmentionMetadata = require('./WebmentionMetadata');
|
||||
const WebmentionRequest = require('./WebmentionRequest');
|
||||
const {
|
||||
MentionsAPI,
|
||||
MentionSendingService,
|
||||
@ -33,7 +32,6 @@ module.exports = {
|
||||
DomainEvents
|
||||
});
|
||||
const webmentionMetadata = new WebmentionMetadata();
|
||||
const webmentionRequest = new WebmentionRequest();
|
||||
const discoveryService = new MentionDiscoveryService({externalRequest});
|
||||
const resourceService = new ResourceService({
|
||||
urlUtils,
|
||||
@ -49,7 +47,6 @@ module.exports = {
|
||||
const api = new MentionsAPI({
|
||||
repository,
|
||||
webmentionMetadata,
|
||||
webmentionRequest,
|
||||
resourceService,
|
||||
routingService
|
||||
});
|
||||
@ -100,6 +97,6 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
});
|
||||
sendingService.listen(events);
|
||||
sendingService.listen(events);
|
||||
}
|
||||
};
|
||||
|
@ -319,7 +319,7 @@ class OEmbed {
|
||||
}
|
||||
}
|
||||
|
||||
if (type !== 'bookmark') {
|
||||
if (type !== 'bookmark' && type !== 'mention') {
|
||||
// if not a bookmark request, first
|
||||
// check against known oembed list
|
||||
const {url: providerUrl, provider} = findUrlWithProvider(url);
|
||||
@ -336,6 +336,12 @@ class OEmbed {
|
||||
return this.fetchBookmarkData(url, body);
|
||||
}
|
||||
|
||||
// mentions need to return bookmark data (metadata) and body (html) for link verification
|
||||
if (type === 'mention') {
|
||||
const bookmark = await this.fetchBookmarkData(url, body);
|
||||
return {...bookmark, body};
|
||||
}
|
||||
|
||||
// attempt to fetch oembed
|
||||
|
||||
// In case response was a redirect, see if we were
|
||||
|
@ -66,6 +66,7 @@ const Mention = require('./Mention');
|
||||
* @prop {string} author
|
||||
* @prop {URL} image
|
||||
* @prop {URL} favicon
|
||||
* @prop {string} body
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -73,11 +74,6 @@ const Mention = require('./Mention');
|
||||
* @prop {(url: URL) => Promise<WebmentionMetadata>} fetch
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {object} IWebmentionRequest
|
||||
* @prop {(url: URL) => Promise<{html: string}>} fetch
|
||||
*/
|
||||
|
||||
module.exports = class MentionsAPI {
|
||||
/** @type {IMentionRepository} */
|
||||
#repository;
|
||||
@ -87,8 +83,6 @@ module.exports = class MentionsAPI {
|
||||
#routingService;
|
||||
/** @type {IWebmentionMetadata} */
|
||||
#webmentionMetadata;
|
||||
/** @type {IWebmentionRequest} */
|
||||
#webmentionRequest;
|
||||
|
||||
/**
|
||||
* @param {object} deps
|
||||
@ -96,14 +90,12 @@ module.exports = class MentionsAPI {
|
||||
* @param {IResourceService} deps.resourceService
|
||||
* @param {IRoutingService} deps.routingService
|
||||
* @param {IWebmentionMetadata} deps.webmentionMetadata
|
||||
* @param {IWebmentionRequest} deps.webmentionRequest
|
||||
*/
|
||||
constructor(deps) {
|
||||
this.#repository = deps.repository;
|
||||
this.#resourceService = deps.resourceService;
|
||||
this.#routingService = deps.routingService;
|
||||
this.#webmentionMetadata = deps.webmentionMetadata;
|
||||
this.#webmentionRequest = deps.webmentionRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,10 +190,9 @@ module.exports = class MentionsAPI {
|
||||
});
|
||||
}
|
||||
|
||||
const responseBody = await this.#webmentionRequest.fetch(webmention.source);
|
||||
if (responseBody?.html) {
|
||||
if (metadata?.body) {
|
||||
try {
|
||||
mention.verify(responseBody.html);
|
||||
mention.verify(metadata.body);
|
||||
} catch (e) {
|
||||
logging.error(e);
|
||||
}
|
||||
|
@ -27,15 +27,8 @@ const mockWebmentionMetadata = {
|
||||
excerpt: 'How many times have you woken up and almost cancelled your church plans? Well this breakfast is about to change everything, a hearty, faith restoring egg dish that will get your tastebuds in a twist.',
|
||||
author: 'Dr Egg Man',
|
||||
image: new URL('https://unsplash.com/photos/QAND9huzD04'),
|
||||
favicon: new URL('https://ghost.org/favicon.ico')
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const mockWebmentionRequest = {
|
||||
async fetch() {
|
||||
return {
|
||||
html: `<p>Some HTML and a <a href='http://target.com/'>mentioned url</a></p>`
|
||||
favicon: new URL('https://ghost.org/favicon.ico'),
|
||||
body: `<html><body><p>Some HTML and a <a href='http://target.com/'>mentioned url</a></p></body></html>`
|
||||
};
|
||||
}
|
||||
};
|
||||
@ -57,8 +50,7 @@ describe('MentionsAPI', function () {
|
||||
repository,
|
||||
routingService: mockRoutingService,
|
||||
resourceService: mockResourceService,
|
||||
webmentionMetadata: mockWebmentionMetadata,
|
||||
webmentionRequest: mockWebmentionRequest
|
||||
webmentionMetadata: mockWebmentionMetadata
|
||||
});
|
||||
|
||||
const mention = await api.processWebmention({
|
||||
@ -83,8 +75,7 @@ describe('MentionsAPI', function () {
|
||||
repository,
|
||||
routingService: mockRoutingService,
|
||||
resourceService: mockResourceService,
|
||||
webmentionMetadata: mockWebmentionMetadata,
|
||||
webmentionRequest: mockWebmentionRequest
|
||||
webmentionMetadata: mockWebmentionMetadata
|
||||
});
|
||||
|
||||
const mention = await api.processWebmention({
|
||||
@ -108,8 +99,7 @@ describe('MentionsAPI', function () {
|
||||
repository,
|
||||
routingService: mockRoutingService,
|
||||
resourceService: mockResourceService,
|
||||
webmentionMetadata: mockWebmentionMetadata,
|
||||
webmentionRequest: mockWebmentionRequest
|
||||
webmentionMetadata: mockWebmentionMetadata
|
||||
});
|
||||
|
||||
const mentionOne = await api.processWebmention({
|
||||
@ -141,8 +131,7 @@ describe('MentionsAPI', function () {
|
||||
repository,
|
||||
routingService: mockRoutingService,
|
||||
resourceService: mockResourceService,
|
||||
webmentionMetadata: mockWebmentionMetadata,
|
||||
webmentionRequest: mockWebmentionRequest
|
||||
webmentionMetadata: mockWebmentionMetadata
|
||||
});
|
||||
|
||||
const mentionOne = await api.processWebmention({
|
||||
@ -178,8 +167,7 @@ describe('MentionsAPI', function () {
|
||||
repository,
|
||||
routingService: mockRoutingService,
|
||||
resourceService: mockResourceService,
|
||||
webmentionMetadata: mockWebmentionMetadata,
|
||||
webmentionRequest: mockWebmentionRequest
|
||||
webmentionMetadata: mockWebmentionMetadata
|
||||
});
|
||||
|
||||
const mentionOne = await api.processWebmention({
|
||||
@ -215,8 +203,7 @@ describe('MentionsAPI', function () {
|
||||
repository,
|
||||
routingService: mockRoutingService,
|
||||
resourceService: mockResourceService,
|
||||
webmentionMetadata: mockWebmentionMetadata,
|
||||
webmentionRequest: mockWebmentionRequest
|
||||
webmentionMetadata: mockWebmentionMetadata
|
||||
});
|
||||
|
||||
const mentionOne = await api.processWebmention({
|
||||
@ -253,8 +240,7 @@ describe('MentionsAPI', function () {
|
||||
}
|
||||
},
|
||||
resourceService: mockResourceService,
|
||||
webmentionMetadata: mockWebmentionMetadata,
|
||||
webmentionRequest: mockWebmentionRequest
|
||||
webmentionMetadata: mockWebmentionMetadata
|
||||
});
|
||||
|
||||
let errored = false;
|
||||
@ -283,8 +269,7 @@ describe('MentionsAPI', function () {
|
||||
}
|
||||
},
|
||||
resourceService: mockResourceService,
|
||||
webmentionMetadata: mockWebmentionMetadata,
|
||||
webmentionRequest: mockWebmentionRequest
|
||||
webmentionMetadata: mockWebmentionMetadata
|
||||
});
|
||||
|
||||
await api.processWebmention({
|
||||
@ -307,8 +292,7 @@ describe('MentionsAPI', function () {
|
||||
};
|
||||
}
|
||||
},
|
||||
webmentionMetadata: mockWebmentionMetadata,
|
||||
webmentionRequest: mockWebmentionRequest
|
||||
webmentionMetadata: mockWebmentionMetadata
|
||||
});
|
||||
|
||||
const mention = await api.processWebmention({
|
||||
@ -341,8 +325,7 @@ describe('MentionsAPI', function () {
|
||||
};
|
||||
}
|
||||
},
|
||||
webmentionMetadata: mockWebmentionMetadata,
|
||||
webmentionRequest: mockWebmentionRequest
|
||||
webmentionMetadata: mockWebmentionMetadata
|
||||
});
|
||||
|
||||
checkFirstMention: {
|
||||
@ -393,8 +376,7 @@ describe('MentionsAPI', function () {
|
||||
fetch: sinon.stub()
|
||||
.onFirstCall().resolves(mockWebmentionMetadata.fetch())
|
||||
.onSecondCall().rejects()
|
||||
},
|
||||
webmentionRequest: mockWebmentionRequest
|
||||
}
|
||||
});
|
||||
|
||||
checkFirstMention: {
|
||||
|
Loading…
Reference in New Issue
Block a user