|
/**
|
|
* @fileoverview URL Utilities for Rantii
|
|
* @author retoor <retoor@molodetz.nl>
|
|
* @description URL parsing and detection utilities
|
|
* @keywords url, link, youtube, image, detection
|
|
*/
|
|
|
|
const URL_REGEX = /https?:\/\/[^\s<]+[^<.,:;"')\]\s]/gi;
|
|
const YOUTUBE_REGEX = /(?:youtube\.com\/(?:watch\?v=|embed\/|v\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/i;
|
|
const IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.bmp'];
|
|
|
|
function extractUrls(text) {
|
|
const matches = text.match(URL_REGEX);
|
|
return matches || [];
|
|
}
|
|
|
|
function isYoutubeUrl(url) {
|
|
return YOUTUBE_REGEX.test(url);
|
|
}
|
|
|
|
function getYoutubeVideoId(url) {
|
|
const match = url.match(YOUTUBE_REGEX);
|
|
return match ? match[1] : null;
|
|
}
|
|
|
|
function getYoutubeThumbnail(videoId) {
|
|
return `https://img.youtube.com/vi/${videoId}/hqdefault.jpg`;
|
|
}
|
|
|
|
function getYoutubeEmbedUrl(videoId) {
|
|
return `https://www.youtube-nocookie.com/embed/${videoId}`;
|
|
}
|
|
|
|
function isImageUrl(url) {
|
|
const lower = url.toLowerCase();
|
|
return IMAGE_EXTENSIONS.some(ext => lower.includes(ext));
|
|
}
|
|
|
|
function isGifUrl(url) {
|
|
return url.toLowerCase().includes('.gif');
|
|
}
|
|
|
|
function extractImageUrls(text) {
|
|
return extractUrls(text).filter(isImageUrl);
|
|
}
|
|
|
|
function extractYoutubeUrls(text) {
|
|
return extractUrls(text).filter(isYoutubeUrl);
|
|
}
|
|
|
|
function extractNonMediaUrls(text) {
|
|
return extractUrls(text).filter(url => !isImageUrl(url) && !isYoutubeUrl(url));
|
|
}
|
|
|
|
function sanitizeUrl(url) {
|
|
try {
|
|
const parsed = new URL(url);
|
|
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
return null;
|
|
}
|
|
return parsed.href;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function getDomain(url) {
|
|
try {
|
|
const parsed = new URL(url);
|
|
return parsed.hostname;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function makeAbsoluteUrl(url, base) {
|
|
try {
|
|
return new URL(url, base).href;
|
|
} catch {
|
|
return url;
|
|
}
|
|
}
|
|
|
|
function isDevrantImageUrl(url) {
|
|
return url.includes('devrant.com') || url.includes('devrant.io');
|
|
}
|
|
|
|
function buildDevrantImageUrl(imagePath) {
|
|
if (imagePath.startsWith('http')) {
|
|
return imagePath;
|
|
}
|
|
return `https://img.devrant.com/${imagePath}`;
|
|
}
|
|
|
|
function buildAvatarUrl(avatar) {
|
|
if (!avatar || !avatar.i) {
|
|
return null;
|
|
}
|
|
return `https://avatars.devrant.com/${avatar.i}`;
|
|
}
|
|
|
|
export {
|
|
extractUrls,
|
|
isYoutubeUrl,
|
|
getYoutubeVideoId,
|
|
getYoutubeThumbnail,
|
|
getYoutubeEmbedUrl,
|
|
isImageUrl,
|
|
isGifUrl,
|
|
extractImageUrls,
|
|
extractYoutubeUrls,
|
|
extractNonMediaUrls,
|
|
sanitizeUrl,
|
|
getDomain,
|
|
makeAbsoluteUrl,
|
|
isDevrantImageUrl,
|
|
buildDevrantImageUrl,
|
|
buildAvatarUrl
|
|
};
|