From d91ce83d392801fd592adeb08a7674b4017ffe82 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 24 Mar 2023 18:37:55 +0100 Subject: Add filter:html.client.json-ld.result hook --- server/lib/client-html.ts | 28 +++++++++++++--------- server/tests/fixtures/peertube-plugin-test/main.js | 15 ++++++++++++ server/tests/plugins/filter-hooks.ts | 21 ++++++++++++++++ shared/models/plugins/server/server-hook.model.ts | 2 ++ 4 files changed, 55 insertions(+), 11 deletions(-) diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts index 4fd9a4263..81b3fff02 100644 --- a/server/lib/client-html.ts +++ b/server/lib/client-html.ts @@ -27,9 +27,10 @@ import { AccountModel } from '../models/account/account' import { VideoModel } from '../models/video/video' import { VideoChannelModel } from '../models/video/video-channel' import { VideoPlaylistModel } from '../models/video/video-playlist' -import { MAccountActor, MChannelActor } from '../types/models' +import { MAccountActor, MChannelActor, MVideo, MVideoPlaylist } from '../types/models' import { getActivityStreamDuration } from './activitypub/activity' import { getBiggestActorImage } from './actor-image' +import { Hooks } from './plugins/hooks' import { ServerConfigManager } from './server-config-manager' type Tags = { @@ -64,6 +65,11 @@ type Tags = { } } +type HookContext = { + video?: MVideo + playlist?: MVideoPlaylist +} + class ClientHtml { private static htmlCache: { [path: string]: string } = {} @@ -129,7 +135,7 @@ class ClientHtml { const twitterCard = CONFIG.SERVICES.TWITTER.WHITELISTED ? 'player' : 'summary_large_image' const schemaType = 'VideoObject' - customHtml = ClientHtml.addTags(customHtml, { + customHtml = await ClientHtml.addTags(customHtml, { url, originUrl, escapedSiteName: escapeHTML(siteName), @@ -141,7 +147,7 @@ class ClientHtml { ogType, twitterCard, schemaType - }) + }, { video }) return customHtml } @@ -193,7 +199,7 @@ class ClientHtml { const twitterCard = CONFIG.SERVICES.TWITTER.WHITELISTED ? 'player' : 'summary' const schemaType = 'ItemList' - customHtml = ClientHtml.addTags(customHtml, { + customHtml = await ClientHtml.addTags(customHtml, { url, originUrl, escapedSiteName: escapeHTML(siteName), @@ -206,7 +212,7 @@ class ClientHtml { ogType, twitterCard, schemaType - }) + }, { playlist: videoPlaylist }) return customHtml } @@ -290,7 +296,7 @@ class ClientHtml { const twitterCard = 'summary' const schemaType = 'ProfilePage' - customHtml = ClientHtml.addTags(customHtml, { + customHtml = await ClientHtml.addTags(customHtml, { url, originUrl, escapedTitle: escapeHTML(title), @@ -301,7 +307,7 @@ class ClientHtml { twitterCard, schemaType, disallowIndexation: !entity.Actor.isOwned() - }) + }, {}) return customHtml } @@ -469,7 +475,7 @@ class ClientHtml { return metaTags } - private static generateSchemaTags (tags: Tags) { + private static async generateSchemaTags (tags: Tags, context: HookContext) { const schema = { '@context': 'http://schema.org', '@type': tags.schemaType, @@ -495,14 +501,14 @@ class ClientHtml { schema['contentUrl'] = tags.url } - return schema + return Hooks.wrapObject(schema, 'filter:html.client.json-ld.result', context) } - private static addTags (htmlStringPage: string, tagsValues: Tags) { + private static async addTags (htmlStringPage: string, tagsValues: Tags, context: HookContext) { const openGraphMetaTags = this.generateOpenGraphMetaTags(tagsValues) const standardMetaTags = this.generateStandardMetaTags(tagsValues) const twitterCardMetaTags = this.generateTwitterCardMetaTags(tagsValues) - const schemaTags = this.generateSchemaTags(tagsValues) + const schemaTags = await this.generateSchemaTags(tagsValues, context) const { url, escapedTitle, embed, originUrl, disallowIndexation } = tagsValues diff --git a/server/tests/fixtures/peertube-plugin-test/main.js b/server/tests/fixtures/peertube-plugin-test/main.js index 84b479548..36dd08d27 100644 --- a/server/tests/fixtures/peertube-plugin-test/main.js +++ b/server/tests/fixtures/peertube-plugin-test/main.js @@ -312,6 +312,8 @@ async function register ({ registerHook, registerSetting, settingsManager, stora } }) + // --------------------------------------------------------------------------- + registerHook({ target: 'filter:html.embed.video.allowed.result', handler: (result, params) => { @@ -332,6 +334,19 @@ async function register ({ registerHook, registerSetting, settingsManager, stora } }) + // --------------------------------------------------------------------------- + + registerHook({ + target: 'filter:html.client.json-ld.result', + handler: (jsonld, context) => { + if (!context || !context.video) return jsonld + + return Object.assign(jsonld, { recordedAt: 'http://example.com/recordedAt' }) + } + }) + + // --------------------------------------------------------------------------- + registerHook({ target: 'filter:api.server.stats.get.result', handler: (result) => { diff --git a/server/tests/plugins/filter-hooks.ts b/server/tests/plugins/filter-hooks.ts index 4d26ff8b7..43749b0b5 100644 --- a/server/tests/plugins/filter-hooks.ts +++ b/server/tests/plugins/filter-hooks.ts @@ -605,6 +605,27 @@ describe('Test plugin filter hooks', function () { }) }) + describe('Client HTML filters', function () { + let videoUUID: string + + before(async function () { + this.timeout(60000) + + const { uuid } = await servers[0].videos.quickUpload({ name: 'html video' }) + videoUUID = uuid + }) + + it('Should run filter:html.client.json-ld.result', async function () { + const res = await makeGetRequest({ url: servers[0].url, path: '/w/' + videoUUID, expectedStatus: HttpStatusCode.OK_200 }) + expect(res.text).to.contain('"recordedAt":"http://example.com/recordedAt"') + }) + + it('Should not run filter:html.client.json-ld.result with an account', async function () { + const res = await makeGetRequest({ url: servers[0].url, path: '/a/root', expectedStatus: HttpStatusCode.OK_200 }) + expect(res.text).not.to.contain('"recordedAt":"http://example.com/recordedAt"') + }) + }) + describe('Search filters', function () { before(async function () { diff --git a/shared/models/plugins/server/server-hook.model.ts b/shared/models/plugins/server/server-hook.model.ts index d2ebe936e..91509f2b9 100644 --- a/shared/models/plugins/server/server-hook.model.ts +++ b/shared/models/plugins/server/server-hook.model.ts @@ -107,6 +107,8 @@ export const serverFilterHookObject = { 'filter:html.embed.video.allowed.result': true, 'filter:html.embed.video-playlist.allowed.result': true, + 'filter:html.client.json-ld.result': true, + 'filter:job-queue.process.params': true, 'filter:job-queue.process.result': true, -- cgit v1.2.3