import { userAgent } from 'fast-meta-tags'
import timeoutSignal from 'timeout-abort-signal'
import providers from './oembed.json' with { type: 'json' }
import { matchDomain } from './utils.js'
export async function fetchOembed(url, opt) {
const oembedUrl = getOembedUrl(url)
if (!oembedUrl) return null
const t = timeoutSignal(opt?.signal, opt?.timeout)
try {
const res = await fetch(oembedUrl, {
signal: t.signal,
headers: { 'User-Agent': opt?.userAgent || userAgent }
})
if (!res.ok) return null
const data = await res.json()
const description = data.description || null
return {
title: data.title || null,
name: data.provider_name || null,
description: description && description.length > 500 ? description.slice(0, 500) : description,
image: data.thumbnail_url || null
}
} catch {
return null
} finally {
t.destroy()
}
}
function getOembedUrl(url) {
const endpoint = findEndpoint(url)
if (!endpoint) return null
const base = endpoint.replace('{format}', 'json')
return `${base}?url=${encodeURIComponent(url)}`
}
function findEndpoint(url) {
for (const provider of providers) {
for (const endpoint of provider.endpoints) {
if (endpoint.schemes) {
for (const scheme of endpoint.schemes) {
if (match(url, scheme)) return endpoint.url
}
} else if (matchDomain(url, provider.url)) {
return endpoint.url
}
}
}
return null
}
export function match(url, scheme) {
const pattern = scheme
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
.replace(/\*/g, '[^.]*')
const regex = new RegExp(`^${pattern}$`)
return regex.test(url)
}