forked from BRETT/BRETT
38 lines
1.2 KiB
TypeScript
38 lines
1.2 KiB
TypeScript
import { createHash } from 'node:crypto'
|
|
import { eq } from 'drizzle-orm'
|
|
import { linkPreviews } from '../db/schema'
|
|
|
|
const CACHE_TTL_MS = 1000 * 60 * 60 * 24
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const url = String(getQuery(event).url ?? '')
|
|
if (!/^https?:\/\//i.test(url) || url.length > 2048) {
|
|
throw createError({ statusCode: 400, statusMessage: 'Ungültige URL' })
|
|
}
|
|
|
|
const urlHash = createHash('sha256').update(url).digest('hex')
|
|
const db = useDb()
|
|
const [cached] = await db
|
|
.select()
|
|
.from(linkPreviews)
|
|
.where(eq(linkPreviews.urlHash, urlHash))
|
|
.limit(1)
|
|
|
|
if (cached && Date.now() - cached.fetchedAt.getTime() < CACHE_TTL_MS) {
|
|
return { image: cached.image, title: cached.title }
|
|
}
|
|
|
|
const preview = await fetchLinkPreview(url)
|
|
// Vorschaubild lokal speichern — die Remote-URL ist nicht stabil
|
|
const image = preview.image
|
|
? (await savePreviewImage(`links/${urlHash}`, preview.image)) ?? preview.image
|
|
: null
|
|
await db
|
|
.insert(linkPreviews)
|
|
.values({ urlHash, url, image, title: preview.title, fetchedAt: new Date() })
|
|
.onDuplicateKeyUpdate({
|
|
set: { image, title: preview.title, fetchedAt: new Date() },
|
|
})
|
|
return { image, title: preview.title }
|
|
})
|