diff --git a/.changeset/fuzzy-coins-lay.md b/.changeset/fuzzy-coins-lay.md new file mode 100644 index 00000000000..5929829e41a --- /dev/null +++ b/.changeset/fuzzy-coins-lay.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixes missing images in Twitter article links to ensure proper display by relying on meta tags. diff --git a/apps/meteor/app/oembed/server/providers.ts b/apps/meteor/app/oembed/server/providers.ts index 9760d521b15..1d2bf89bbae 100644 --- a/apps/meteor/app/oembed/server/providers.ts +++ b/apps/meteor/app/oembed/server/providers.ts @@ -3,6 +3,8 @@ import { camelCase } from 'change-case'; import { callbacks } from '../../../lib/callbacks'; import { SystemLogger } from '../../../server/lib/logger/system'; +import { settings } from '../../settings/server'; +import { Info } from '../../utils/rocketchat.info'; class Providers { private providers: OEmbedProvider[]; @@ -11,13 +13,20 @@ class Providers { this.providers = []; } - static getConsumerUrl(provider: OEmbedProvider, url: string): string { + static getConsumerUrl(provider: OEmbedProvider, url: string): string | undefined { + if (!provider.endPoint) { + return; + } const urlObj = new URL(provider.endPoint); urlObj.searchParams.set('url', url); return urlObj.toString(); } + static getCustomHeaders(provider: OEmbedProvider): { [k: string]: string } { + return provider.getHeaderOverrides?.() || {}; + } + registerProvider(provider: OEmbedProvider): number { return this.providers.push(provider); } @@ -75,7 +84,11 @@ providers.registerProvider({ providers.registerProvider({ urls: [new RegExp('https?://(twitter|x)\\.com/[^/]+/status/\\S+')], - endPoint: 'https://publish.twitter.com/oembed', + getHeaderOverrides: () => { + return { + 'User-Agent': `${settings.get('API_Embed_UserAgent')} Rocket.Chat/${Info.version} Googlebot/2.1`, + }; + }, }); providers.registerProvider({ @@ -104,7 +117,12 @@ callbacks.add( const consumerUrl = Providers.getConsumerUrl(provider, url); - return { ...data, urlObj: new URL(consumerUrl) }; + const headerOverrides = Providers.getCustomHeaders(provider); + if (!consumerUrl) { + return { ...data, headerOverrides }; + } + + return { ...data, headerOverrides, urlObj: new URL(consumerUrl) }; }, callbacks.priority.MEDIUM, 'oembed-providers-before', diff --git a/apps/meteor/app/oembed/server/server.ts b/apps/meteor/app/oembed/server/server.ts index 1e758b1371e..d3cdb52c0a8 100644 --- a/apps/meteor/app/oembed/server/server.ts +++ b/apps/meteor/app/oembed/server/server.ts @@ -107,6 +107,7 @@ const getUrlContent = async (urlObj: URL, redirectCount = 5): Promise(message: T) => T; 'oembed:beforeGetUrlContent': (data: { urlObj: URL }) => { urlObj: URL; + headerOverrides?: { [k: string]: string }; }; 'oembed:afterParseContent': (data: { url: string; meta: OEmbedMeta; headers: { [k: string]: string }; content: OEmbedUrlContent }) => { url: string; diff --git a/packages/core-typings/src/IOembed.ts b/packages/core-typings/src/IOembed.ts index 0b781aa07fc..f3eee390426 100644 --- a/packages/core-typings/src/IOembed.ts +++ b/packages/core-typings/src/IOembed.ts @@ -16,7 +16,8 @@ export type OEmbedUrlContent = { export type OEmbedProvider = { urls: RegExp[]; - endPoint: string; + endPoint?: string; + getHeaderOverrides?: () => { [k: string]: string }; }; export type OEmbedUrlContentResult = {