fix(media): classify mp4-formatted gif previews as video

This commit is contained in:
Tommaso Casaburi
2026-05-02 23:42:20 +07:00
parent ab6dce563a
commit 36bb1f726d
2 changed files with 13 additions and 7 deletions
@@ -128,6 +128,7 @@ describe('media-utils', () => {
url: 'https://ibb.co/abc123',
});
expect(getLinkMediaInfo('https://example.com/file.gif')).toMatchObject({ type: 'gif' });
expect(getLinkMediaInfo('https://external-preview.redd.it/example.gif?width=480&format=mp4')).toMatchObject({ type: 'video' });
expect(getLinkMediaInfo('https://example.com/file.png')).toMatchObject({ type: 'image' });
expect(getLinkMediaInfo('https://example.com/file.mp4')).toMatchObject({ type: 'video' });
expect(getLinkMediaInfo('https://example.com/file.mp3')).toMatchObject({ type: 'audio' });
+12 -7
View File
@@ -79,6 +79,7 @@ const getPatternThumbnailUrl = (url: URL): string | undefined => {
const KNOWN_IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'ico', 'tiff'];
const KNOWN_VIDEO_EXTENSIONS = ['mp4', 'webm', 'mov', 'avi', 'mkv', 'flv', 'wmv', 'm4v'];
const KNOWN_AUDIO_EXTENSIONS = ['mp3', 'wav', 'ogg', 'flac', 'aac', 'm4a', 'wma'];
const KNOWN_MEDIA_EXTENSIONS = new Set([...KNOWN_IMAGE_EXTENSIONS, ...KNOWN_VIDEO_EXTENSIONS, ...KNOWN_AUDIO_EXTENSIONS]);
// some sites don't show thumbnails, so the backend-side thumbnail fetching needs to be disabled, or it might fetch non-thumbnails such as emojis
const THUMBNAIL_BLACKLISTED_DOMAINS = ['twitter.com', 'x.com'];
@@ -114,6 +115,16 @@ const getAllowedThumbnailUrl = (value: string, baseUrl: string): string | undefi
}
};
const getDirectMediaExtension = (url: URL): string => {
const format = url.searchParams.get('format')?.toLowerCase() ?? '';
if (KNOWN_MEDIA_EXTENSIONS.has(format)) {
return format;
}
const pathParts = url.pathname.toLowerCase().split('.');
return pathParts.length > 1 ? pathParts[pathParts.length - 1] : '';
};
export const getLinkMediaInfo = memoize(
(link: string): CommentMediaInfo | undefined => {
if (!isValidURL(link)) {
@@ -134,9 +145,7 @@ export const getLinkMediaInfo = memoize(
}
try {
// Extract file extension
const pathParts = url.pathname.toLowerCase().split('.');
const extension = pathParts.length > 1 ? pathParts[pathParts.length - 1] : '';
const extension = getDirectMediaExtension(url);
// Only classify as media if we explicitly know the extension
if (KNOWN_IMAGE_EXTENSIONS.includes(extension)) {
@@ -148,10 +157,6 @@ export const getLinkMediaInfo = memoize(
}
// Unknown extensions remain as 'webpage'
if (!url.pathname.includes('.')) {
type = 'webpage';
}
if (canEmbed(url) || url.host.startsWith('yt.')) {
type = 'iframe';
patternThumbnailUrl = getPatternThumbnailUrl(url);