More embed improvements
This commit is contained in:
parent
3d7fd137b4
commit
d341fe44d7
@ -23,27 +23,27 @@ export const getProxyUrl = (url: URL, width: number, height: number) => {
|
|||||||
return `${endpointPublic}/external/resize/${encodeURIComponent(url.href)}?width=${width}&height=${height}`;
|
return `${endpointPublic}/external/resize/${encodeURIComponent(url.href)}?width=${width}&height=${height}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getMetaDescriptions = async (text: string) => {
|
const getMeta = ($: cheerio.CheerioAPI, name: string): string | undefined => {
|
||||||
|
let elem = $(`meta[property="${name}"]`);
|
||||||
|
if (!elem.length) elem = $(`meta[name="${name}"]`);
|
||||||
|
return elem.attr("content") || elem.text();
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getMetaDescriptions = (text: string) => {
|
||||||
const $ = cheerio.load(text);
|
const $ = cheerio.load(text);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: $('meta[property="og:title"]').attr("content"),
|
title: getMeta($, "og:title") || $("title").first().text(),
|
||||||
provider_name: $('meta[property="og:site_name"]').text(),
|
provider_name: getMeta($, "og:site_name"),
|
||||||
author: $('meta[property="article:author"]').attr("content"),
|
author: getMeta($, "article:author"),
|
||||||
description:
|
description: getMeta($, "og:description") || getMeta($, "description"),
|
||||||
$('meta[property="og:description"]').attr("content") ||
|
image: getMeta($, "og:image") || getMeta($, "twitter:image"),
|
||||||
$('meta[property="description"]').attr("content"),
|
image_fallback: $(`image`).attr("src"),
|
||||||
image: $('meta[property="og:image"]').attr("content") || $(`meta[property="twitter:image"]`).attr("content"),
|
video_fallback: $(`video`).attr("src"),
|
||||||
width: parseInt(
|
width: parseInt(getMeta($, "og:image:width")!) || 0,
|
||||||
$('meta[property="og:image:width"]').attr("content") ||
|
height: parseInt(getMeta($, "og:image:height")!) || 0,
|
||||||
"",
|
url: getMeta($, "og:url"),
|
||||||
) || undefined,
|
youtube_embed: getMeta($, "og:video:secure_url"),
|
||||||
height: parseInt(
|
|
||||||
$('meta[property="og:image:height"]').attr("content") ||
|
|
||||||
"",
|
|
||||||
) || undefined,
|
|
||||||
url: $('meta[property="og:url"]').attr("content"),
|
|
||||||
youtube_embed: $(`meta[property="og:video:secure_url"]`).attr("content"),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -60,24 +60,43 @@ const doFetch = async (url: URL) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const genericImageHandler = async (url: URL): Promise<Embed | null> => {
|
const genericImageHandler = async (url: URL): Promise<Embed | null> => {
|
||||||
|
const type = await fetch(url, {
|
||||||
|
...DEFAULT_FETCH_OPTIONS,
|
||||||
|
method: "HEAD",
|
||||||
|
});
|
||||||
|
|
||||||
|
let width, height, image;
|
||||||
|
|
||||||
|
if (type.headers.get("content-type")?.indexOf("image") !== -1) {
|
||||||
|
const result = await probe(url.href);
|
||||||
|
width = result.width;
|
||||||
|
height = result.height;
|
||||||
|
image = url.href;
|
||||||
|
}
|
||||||
|
else if (type.headers.get("content-type")?.indexOf("video") !== -1) {
|
||||||
|
// TODO
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// have to download the page, unfortunately
|
||||||
const response = await doFetch(url);
|
const response = await doFetch(url);
|
||||||
if (!response) return null;
|
if (!response) return null;
|
||||||
const metas = await getMetaDescriptions(await response.text());
|
const metas = getMetaDescriptions(await response.text());
|
||||||
|
width = metas.width;
|
||||||
if (!metas.width || !metas.height) {
|
height = metas.height;
|
||||||
const result = await probe(url.href);
|
image = metas.image || metas.image_fallback;
|
||||||
metas.width = result.width;
|
|
||||||
metas.height = result.height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!width || !height || !image) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: url.href,
|
url: url.href,
|
||||||
type: EmbedType.image,
|
type: EmbedType.image,
|
||||||
thumbnail: {
|
thumbnail: {
|
||||||
width: metas.width,
|
width: width,
|
||||||
height: metas.height,
|
height: height,
|
||||||
url: url.href,
|
url: url.href,
|
||||||
proxy_url: getProxyUrl(new URL(metas.image || url.href), metas.width, metas.height),
|
proxy_url: getProxyUrl(new URL(image), width, height),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -85,27 +104,32 @@ const genericImageHandler = async (url: URL): Promise<Embed | null> => {
|
|||||||
export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | null>; } = {
|
export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | null>; } = {
|
||||||
// the url does not have a special handler
|
// the url does not have a special handler
|
||||||
"default": async (url: URL) => {
|
"default": async (url: URL) => {
|
||||||
|
const type = await fetch(url, {
|
||||||
|
...DEFAULT_FETCH_OPTIONS,
|
||||||
|
method: "HEAD",
|
||||||
|
});
|
||||||
|
if (type.headers.get("content-type")?.indexOf("image") !== -1)
|
||||||
|
return await genericImageHandler(url);
|
||||||
|
|
||||||
const response = await doFetch(url);
|
const response = await doFetch(url);
|
||||||
if (!response) return null;
|
if (!response) return null;
|
||||||
|
|
||||||
if (response.headers.get("content-type")?.indexOf("image") !== -1) {
|
const metas = getMetaDescriptions(await response.text());
|
||||||
// this is an image
|
|
||||||
|
|
||||||
const size = imageSize(await response.buffer());
|
// TODO: handle video
|
||||||
|
|
||||||
return {
|
if (!metas.image) metas.image = metas.image_fallback;
|
||||||
url: url.href,
|
|
||||||
type: EmbedType.image,
|
if (metas.image && (!metas.width || !metas.height)) {
|
||||||
image: {
|
const result = await probe(metas.image);
|
||||||
width: size.width,
|
metas.width = result.width;
|
||||||
height: size.height,
|
metas.height = result.height;
|
||||||
url: url.href,
|
}
|
||||||
proxy_url: getProxyUrl(url, size.width!, size.height!),
|
|
||||||
}
|
if (!metas.image && (!metas.title || !metas.description)) {
|
||||||
};
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const metas = await getMetaDescriptions(await response.text());
|
|
||||||
return {
|
return {
|
||||||
url: url.href,
|
url: url.href,
|
||||||
type: EmbedType.link,
|
type: EmbedType.link,
|
||||||
@ -114,7 +138,7 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | null>
|
|||||||
width: metas.width,
|
width: metas.width,
|
||||||
height: metas.height,
|
height: metas.height,
|
||||||
url: metas.image,
|
url: metas.image,
|
||||||
proxy_url: getProxyUrl(new URL(metas.image!), metas.width!, metas.height!),
|
proxy_url: metas.image ? getProxyUrl(new URL(metas.image), metas.width!, metas.height!) : undefined,
|
||||||
},
|
},
|
||||||
description: metas.description,
|
description: metas.description,
|
||||||
};
|
};
|
||||||
@ -132,7 +156,7 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | null>
|
|||||||
"open.spotify.com": async (url: URL) => {
|
"open.spotify.com": async (url: URL) => {
|
||||||
const response = await doFetch(url);
|
const response = await doFetch(url);
|
||||||
if (!response) return null;
|
if (!response) return null;
|
||||||
const metas = await getMetaDescriptions(await response.text());
|
const metas = getMetaDescriptions(await response.text());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: url.href,
|
url: url.href,
|
||||||
@ -142,7 +166,7 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | null>
|
|||||||
thumbnail: {
|
thumbnail: {
|
||||||
width: 640,
|
width: 640,
|
||||||
height: 640,
|
height: 640,
|
||||||
proxy_url: getProxyUrl(new URL(metas.image!), 640, 640),
|
proxy_url: metas.image ? getProxyUrl(new URL(metas.image!), 640, 640) : undefined,
|
||||||
url: metas.image,
|
url: metas.image,
|
||||||
},
|
},
|
||||||
provider: {
|
provider: {
|
||||||
@ -156,7 +180,7 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | null>
|
|||||||
"www.pixiv.net": async (url: URL) => {
|
"www.pixiv.net": async (url: URL) => {
|
||||||
const response = await doFetch(url);
|
const response = await doFetch(url);
|
||||||
if (!response) return null;
|
if (!response) return null;
|
||||||
const metas = await getMetaDescriptions(await response.text());
|
const metas = getMetaDescriptions(await response.text());
|
||||||
|
|
||||||
// TODO: doesn't show images. think it's a bug in the cdn
|
// TODO: doesn't show images. think it's a bug in the cdn
|
||||||
return {
|
return {
|
||||||
@ -168,7 +192,7 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | null>
|
|||||||
width: metas.width,
|
width: metas.width,
|
||||||
height: metas.height,
|
height: metas.height,
|
||||||
url: url.href,
|
url: url.href,
|
||||||
proxy_url: getProxyUrl(new URL(metas.image!), metas.width!, metas.height!),
|
proxy_url: metas.image ? getProxyUrl(new URL(metas.image!), metas.width!, metas.height!) : undefined,
|
||||||
},
|
},
|
||||||
provider: {
|
provider: {
|
||||||
url: "https://pixiv.net",
|
url: "https://pixiv.net",
|
||||||
@ -180,7 +204,7 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | null>
|
|||||||
"store.steampowered.com": async (url: URL) => {
|
"store.steampowered.com": async (url: URL) => {
|
||||||
const response = await doFetch(url);
|
const response = await doFetch(url);
|
||||||
if (!response) return null;
|
if (!response) return null;
|
||||||
const metas = await getMetaDescriptions(await response.text());
|
const metas = getMetaDescriptions(await response.text());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: url.href,
|
url: url.href,
|
||||||
@ -192,7 +216,7 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | null>
|
|||||||
width: 460,
|
width: 460,
|
||||||
height: 215,
|
height: 215,
|
||||||
url: metas.image,
|
url: metas.image,
|
||||||
proxy_url: getProxyUrl(new URL(metas.image!), 460, 215),
|
proxy_url: metas.image ? getProxyUrl(new URL(metas.image!), 460, 215) : undefined,
|
||||||
},
|
},
|
||||||
provider: {
|
provider: {
|
||||||
url: "https://store.steampowered.com",
|
url: "https://store.steampowered.com",
|
||||||
@ -219,7 +243,7 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | null>
|
|||||||
"www.youtube.com": async (url: URL): Promise<Embed | null> => {
|
"www.youtube.com": async (url: URL): Promise<Embed | null> => {
|
||||||
const response = await doFetch(url);
|
const response = await doFetch(url);
|
||||||
if (!response) return null;
|
if (!response) return null;
|
||||||
const metas = await getMetaDescriptions(await response.text());
|
const metas = getMetaDescriptions(await response.text());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
video: {
|
video: {
|
||||||
@ -235,7 +259,7 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | null>
|
|||||||
width: metas.width,
|
width: metas.width,
|
||||||
height: metas.height,
|
height: metas.height,
|
||||||
url: metas.image,
|
url: metas.image,
|
||||||
proxy_url: getProxyUrl(new URL(metas.image!), metas.width!, metas.height!),
|
proxy_url: metas.image ? getProxyUrl(new URL(metas.image!), metas.width!, metas.height!) : undefined,
|
||||||
},
|
},
|
||||||
provider: {
|
provider: {
|
||||||
url: "https://www.youtube.com",
|
url: "https://www.youtube.com",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user