X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Flib%2Fclient-html.ts;h=058f29f03f1c8c4f2a81ac8cc31dcfa7bb477a69;hb=26818a73ba0d7fd53ca69eba0c8e525f3670b5a8;hp=1e8d030230cd18e90a271a7c6b0e55aeb5873052;hpb=2b621ac0ebe83693bba6354b3482a03ba58143e7;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts index 1e8d03023..058f29f03 100644 --- a/server/lib/client-html.ts +++ b/server/lib/client-html.ts @@ -1,7 +1,8 @@ import express from 'express' -import { readFile } from 'fs-extra' +import { pathExists, readFile } from 'fs-extra' import { join } from 'path' import validator from 'validator' +import { isTestOrDevInstance } from '@server/helpers/core-utils' import { toCompleteUUID } from '@server/helpers/custom-validators/misc' import { mdToOneLinePlainText } from '@server/helpers/markdown' import { ActorImageModel } from '@server/models/actor/actor-image' @@ -26,11 +27,11 @@ 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' -import { isTestInstance } from '@server/helpers/core-utils' type Tags = { ogType: string @@ -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 } @@ -234,7 +240,7 @@ class ClientHtml { const path = ClientHtml.getEmbedPath() // Disable HTML cache in dev mode because webpack can regenerate JS files - if (!isTestInstance() && ClientHtml.htmlCache[path]) { + if (!isTestOrDevInstance() && ClientHtml.htmlCache[path]) { return ClientHtml.htmlCache[path] } @@ -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 } @@ -402,7 +408,20 @@ class ClientHtml { } private static async addAsyncPluginCSS (htmlStringPage: string) { - const globalCSSContent = await readFile(PLUGIN_GLOBAL_CSS_PATH) + if (!pathExists(PLUGIN_GLOBAL_CSS_PATH)) { + logger.info('Plugin Global CSS file is not available (generation may still be in progress), ignoring it.') + return htmlStringPage + } + + let globalCSSContent: Buffer + + try { + globalCSSContent = await readFile(PLUGIN_GLOBAL_CSS_PATH) + } catch (err) { + logger.error('Error retrieving the Plugin Global CSS file, ignoring it.', { err }) + return htmlStringPage + } + if (globalCSSContent.byteLength === 0) return htmlStringPage const fileHash = sha256(globalCSSContent) @@ -469,7 +488,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, @@ -489,20 +508,19 @@ class ClientHtml { schema['uploadDate'] = tags.embed.createdAt if (tags.embed.duration) schema['duration'] = tags.embed.duration - if (tags.embed.views) schema['iterationCount'] = tags.embed.views schema['thumbnailUrl'] = tags.image.url 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 @@ -576,7 +594,7 @@ async function serveIndexHTML (req: express.Request, res: express.Response) { await generateHTMLPage(req, res, req.params.language) return } catch (err) { - logger.error('Cannot generate HTML page.', err) + logger.error('Cannot generate HTML page.', { err }) return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR_500).end() } }