import summaly from "@iceshrimp/summaly"; import { fetchMeta } from "../../misc/fetch-meta.js"; import Logger from "../../services/logger.js"; import config from "../../config/index.js"; import { query } from "../../prelude/url.js"; import { getJson } from "../../misc/fetch.js"; const logger = new Logger("url-preview"); export const urlPreviewHandler = async (ctx)=>{ const url = ctx.query.url; if (typeof url !== "string") { ctx.status = 400; return; } const lang = ctx.query.lang; if (Array.isArray(lang)) { ctx.status = 400; return; } const meta = await fetchMeta(); logger.info(meta.summalyProxy ? `(Proxy) Getting preview of ${url}@${lang} ...` : `Getting preview of ${url}@${lang} ...`); try { const summary = meta.summalyProxy ? await getJson(`${meta.summalyProxy}?${query({ url: url, lang: lang ?? "en-US" })}`) : await summaly.default(url, { followRedirects: false, lang: lang ?? "en-US", userAgent: config.userAgent }); logger.succ(`Got preview of ${url}: ${summary.title}`); if (summary.url && !(summary.url.startsWith("http://") || summary.url.startsWith("https://"))) { throw new Error("unsupported schema included"); } if (summary.player?.url && !(summary.player.url.startsWith("http://") || summary.player.url.startsWith("https://"))) { throw new Error("unsupported schema included"); } summary.icon = wrap(summary.icon); summary.thumbnail = wrap(summary.thumbnail); // Cache 7days ctx.set("Cache-Control", "max-age=604800, immutable"); ctx.body = summary; } catch (err) { logger.warn(`Failed to get preview of ${url}: ${err}`); ctx.status = 200; ctx.set("Cache-Control", "max-age=86400, immutable"); ctx.body = "{}"; } }; function wrap(url) { return url != null ? `${config.url}/proxy/preview.webp?${query({ url, preview: "1" })}` : null; }