diff --git a/src/core/server/app/handlers/api/oembed/oembed.ts b/src/core/server/app/handlers/api/oembed/oembed.ts index 8898ba793..33f1934ae 100644 --- a/src/core/server/app/handlers/api/oembed/oembed.ts +++ b/src/core/server/app/handlers/api/oembed/oembed.ts @@ -1,21 +1,12 @@ import Joi from "@hapi/joi"; +import { AppOptions } from "coral-server/app"; import { validate } from "coral-server/app/request/body"; import { supportsMediaType } from "coral-server/models/tenant"; +import { translate } from "coral-server/services/i18n"; import { fetchOEmbedResponse } from "coral-server/services/oembed"; import { RequestHandler } from "coral-server/types/express"; -const createNotFoundMessage = (type: "twitter" | "youtube") => { - switch (type) { - case "twitter": - return "Tweet could not be found. Perhaps it was deleted?"; - case "youtube": - return "YouTube video could not be found. Perhaps it was deleted?"; - default: - throw new Error(`invalid type provided: ${type}`); - } -}; - const OEmbedQuerySchema = Joi.object().keys({ url: Joi.string().uri().required(), type: Joi.string().allow("twitter", "youtube").only(), @@ -28,7 +19,9 @@ interface OEmbedQuery { maxWidth?: number; } -export const oembedHandler = (): RequestHandler => { +export type OembedHandler = Pick; + +export const oembedHandler = ({ i18n }: OembedHandler): RequestHandler => { // TODO: add some kind of rate limiting or spam protection return async (req, res, next) => { // Tenant is guaranteed at this point. @@ -46,14 +39,31 @@ export const oembedHandler = (): RequestHandler => { return; } - // Get the oEmbed response. + let style = ` + body { + margin: 0; + font-family: sans-serif; + } + .container * { + margin: 0!important; + } + `; const response = await fetchOEmbedResponse(type, url, maxWidth); if (response === null || !response.html) { + const bundle = i18n.getBundle(tenant.locale); + const message = translate( + bundle, + "Requested media could not be found", + "common-embedNotFound" + ); res.status(404); res.send( ` + - ${createNotFoundMessage(type)} + ${message} ` ); @@ -63,14 +73,6 @@ export const oembedHandler = (): RequestHandler => { const { width, height, html } = response; // Compile the style to be used for the embed. - let style = ` - body { - margin: 0; - } - .container * { - margin: 0!important; - } - `; if (width && height) { style += ` .container { diff --git a/src/core/server/app/router/api/index.ts b/src/core/server/app/router/api/index.ts index 62722bca4..09b8bf3ab 100644 --- a/src/core/server/app/router/api/index.ts +++ b/src/core/server/app/router/api/index.ts @@ -54,7 +54,7 @@ export function createAPIRouter(app: AppOptions, options: RouterOptions) { router.use("/account", createNewAccountRouter(app, options)); router.use("/user", createNewUserRouter(app)); - router.get("/oembed", cspSiteMiddleware(app), oembedHandler()); + router.get("/oembed", cspSiteMiddleware(app), oembedHandler(app)); // Configure the GraphQL route. router.use( diff --git a/src/locales/en-US/common.ftl b/src/locales/en-US/common.ftl index 6a28eda38..aa236ab97 100644 --- a/src/locales/en-US/common.ftl +++ b/src/locales/en-US/common.ftl @@ -5,3 +5,5 @@ common-banEmailTemplate = Hello { $username }, Someone with access to your account has violated our community guidelines. As a result, your account has been banned. You will no longer be able to comment, react or report comments. + +common-embedNotFound = Requested media could not be found. May have been deleted.