2024-03-22 16:15:38 +01:00
|
|
|
import { Comment } from '@plebbit/plebbit-react-hooks';
|
|
|
|
|
import extName from 'ext-name';
|
|
|
|
|
import { canEmbed } from '../../components/embed';
|
|
|
|
|
import memoize from 'memoizee';
|
2024-03-26 13:17:55 +01:00
|
|
|
import { isValidURL } from './url-utils';
|
2024-03-22 16:15:38 +01:00
|
|
|
|
|
|
|
|
export interface CommentMediaInfo {
|
|
|
|
|
url: string;
|
|
|
|
|
type: string;
|
|
|
|
|
thumbnail?: string;
|
|
|
|
|
patternThumbnailUrl?: string;
|
2024-09-07 14:11:33 +02:00
|
|
|
post?: Comment;
|
2024-03-22 16:15:38 +01:00
|
|
|
}
|
|
|
|
|
|
2024-04-28 17:40:05 +02:00
|
|
|
export const getDisplayMediaInfoType = (type: string, t: any) => {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case 'image':
|
|
|
|
|
return t('image');
|
2024-07-20 16:25:20 +02:00
|
|
|
case 'animated gif':
|
|
|
|
|
return t('animated_gif');
|
|
|
|
|
case 'static gif':
|
2024-09-03 14:27:29 +02:00
|
|
|
return t('gif');
|
2024-04-28 17:40:05 +02:00
|
|
|
case 'iframe':
|
|
|
|
|
return t('iframe');
|
|
|
|
|
case 'video':
|
|
|
|
|
return t('video');
|
|
|
|
|
case 'audio':
|
|
|
|
|
return t('audio');
|
|
|
|
|
default:
|
|
|
|
|
return t('webpage');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-22 16:15:38 +01:00
|
|
|
export const getHasThumbnail = (commentMediaInfo: CommentMediaInfo | undefined, link: string | undefined): boolean => {
|
|
|
|
|
const iframeThumbnail = commentMediaInfo?.patternThumbnailUrl || commentMediaInfo?.thumbnail;
|
|
|
|
|
return link &&
|
|
|
|
|
commentMediaInfo &&
|
|
|
|
|
(commentMediaInfo.type === 'image' ||
|
|
|
|
|
commentMediaInfo.type === 'video' ||
|
2024-04-08 19:34:09 +02:00
|
|
|
commentMediaInfo.type === 'audio' ||
|
2024-03-26 13:17:55 +01:00
|
|
|
commentMediaInfo.type === 'gif' ||
|
2024-03-22 16:15:38 +01:00
|
|
|
(commentMediaInfo.type === 'webpage' && commentMediaInfo.thumbnail) ||
|
|
|
|
|
(commentMediaInfo.type === 'iframe' && iframeThumbnail))
|
|
|
|
|
? true
|
|
|
|
|
: false;
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-26 13:17:55 +01:00
|
|
|
const getYouTubeVideoId = (url: URL): string | null => {
|
|
|
|
|
if (url.host.includes('youtu.be')) {
|
|
|
|
|
return url.pathname.slice(1);
|
|
|
|
|
} else if (url.searchParams.has('v')) {
|
|
|
|
|
return url.searchParams.get('v');
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getPatternThumbnailUrl = (url: URL): string | undefined => {
|
|
|
|
|
const videoId = getYouTubeVideoId(url);
|
|
|
|
|
if (videoId) {
|
|
|
|
|
return `https://img.youtube.com/vi/${videoId}/0.jpg`;
|
|
|
|
|
}
|
|
|
|
|
if (url.host.includes('streamable.com')) {
|
|
|
|
|
const videoId = url.pathname.split('/')[1];
|
|
|
|
|
return `https://cdn-cf-east.streamable.com/image/${videoId}.jpg`;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-04-24 08:48:31 +02:00
|
|
|
export const getLinkMediaInfo = memoize(
|
2024-04-10 12:19:02 +02:00
|
|
|
(link: string): CommentMediaInfo | undefined => {
|
|
|
|
|
if (!isValidURL(link)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const url = new URL(link);
|
|
|
|
|
let patternThumbnailUrl: string | undefined;
|
|
|
|
|
let type: string = 'webpage';
|
|
|
|
|
let mime: string | undefined;
|
2024-03-26 13:17:55 +01:00
|
|
|
|
2024-09-17 18:01:11 +02:00
|
|
|
if (url.pathname === '/_next/image' && url.search.startsWith('?url=')) {
|
|
|
|
|
return { url: link, type: 'image' };
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-10 12:19:02 +02:00
|
|
|
try {
|
2024-04-26 16:07:35 +02:00
|
|
|
const fileName = url.pathname.slice(url.pathname.lastIndexOf('/') + 1).toLowerCase();
|
|
|
|
|
mime = extName(fileName)[0]?.mime;
|
2024-04-10 12:19:02 +02:00
|
|
|
if (mime) {
|
|
|
|
|
if (mime.startsWith('image')) {
|
|
|
|
|
type = mime === 'image/gif' ? 'gif' : 'image';
|
|
|
|
|
} else if (mime.startsWith('video')) {
|
|
|
|
|
type = 'video';
|
|
|
|
|
} else if (mime.startsWith('audio')) {
|
|
|
|
|
type = 'audio';
|
|
|
|
|
}
|
2024-03-26 13:17:55 +01:00
|
|
|
}
|
2024-04-10 12:19:02 +02:00
|
|
|
|
|
|
|
|
if (canEmbed(url) || url.host.startsWith('yt.')) {
|
|
|
|
|
type = 'iframe';
|
|
|
|
|
patternThumbnailUrl = getPatternThumbnailUrl(url);
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error(e);
|
2024-03-26 13:17:55 +01:00
|
|
|
}
|
|
|
|
|
|
2024-04-10 12:19:02 +02:00
|
|
|
return { url: link, type, patternThumbnailUrl };
|
|
|
|
|
},
|
|
|
|
|
{ max: 1000 },
|
|
|
|
|
);
|
2024-03-26 13:17:55 +01:00
|
|
|
|
2024-04-10 12:19:02 +02:00
|
|
|
export const getCommentMediaInfo = (comment: Comment): CommentMediaInfo | undefined => {
|
2024-03-22 16:15:38 +01:00
|
|
|
if (!comment?.thumbnailUrl && !comment?.link) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-03-26 13:17:55 +01:00
|
|
|
const linkInfo = comment.link ? getLinkMediaInfo(comment.link) : undefined;
|
|
|
|
|
if (linkInfo) {
|
2024-09-07 14:11:33 +02:00
|
|
|
return {
|
|
|
|
|
...linkInfo,
|
|
|
|
|
thumbnail: comment.thumbnailUrl || linkInfo.thumbnail,
|
|
|
|
|
post: comment,
|
|
|
|
|
};
|
2024-03-22 16:15:38 +01:00
|
|
|
}
|
2024-03-26 13:17:55 +01:00
|
|
|
return;
|
2024-03-22 16:15:38 +01:00
|
|
|
};
|
2024-09-07 14:11:33 +02:00
|
|
|
|
|
|
|
|
export const getMediaDimensions = (commentMediaInfo: CommentMediaInfo | undefined): string => {
|
|
|
|
|
if (!commentMediaInfo) return '';
|
|
|
|
|
|
|
|
|
|
const { type, url, post } = commentMediaInfo;
|
|
|
|
|
|
|
|
|
|
if (type === 'iframe' && url) {
|
|
|
|
|
const embedUrl = new URL(url);
|
|
|
|
|
if (canEmbed(embedUrl)) {
|
|
|
|
|
// hardcoded dimensions from embed.module.css
|
|
|
|
|
if (embedUrl.hostname.includes('youtube.com') || embedUrl.hostname.includes('youtu.be')) {
|
|
|
|
|
return '800x450';
|
|
|
|
|
} else if (embedUrl.hostname.includes('instagram.com')) {
|
|
|
|
|
return '360x420';
|
|
|
|
|
} else if (embedUrl.hostname.includes('reddit.com')) {
|
|
|
|
|
return '500x520';
|
|
|
|
|
} else if (embedUrl.hostname.includes('tiktok.com')) {
|
|
|
|
|
return '400x780';
|
|
|
|
|
} else if (embedUrl.hostname.includes('x.com') || embedUrl.hostname.includes('twitter.com')) {
|
|
|
|
|
return '550x580';
|
|
|
|
|
} else if (embedUrl.hostname.includes('soundcloud.com')) {
|
|
|
|
|
return '700x166';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (type === 'audio') {
|
|
|
|
|
return '700x240'; // hardcoded dimensions from embed.module.css
|
|
|
|
|
} else if (type === 'image' || type === 'video' || type === 'gif') {
|
|
|
|
|
// media dimensions calculated by API
|
|
|
|
|
if (post?.linkWidth && post?.linkHeight) {
|
|
|
|
|
return `${post.linkWidth}x${post.linkHeight}`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return '';
|
|
|
|
|
};
|