|
import ChatThumbnail from "./ChatThumbnail.svelte"; |
|
import { collections } from "$lib/server/database"; |
|
import { error, type RequestHandler } from "@sveltejs/kit"; |
|
import { ObjectId } from "mongodb"; |
|
import type { SvelteComponent } from "svelte"; |
|
|
|
import { Resvg } from "@resvg/resvg-js"; |
|
import satori from "satori"; |
|
import { html } from "satori-html"; |
|
|
|
import InterRegular from "../../../../../static/fonts/Inter-Regular.ttf"; |
|
import InterBold from "../../../../../static/fonts/Inter-Bold.ttf"; |
|
import sharp from "sharp"; |
|
|
|
export const GET: RequestHandler = (async ({ params }) => { |
|
const assistant = await collections.assistants.findOne({ |
|
_id: new ObjectId(params.assistantId), |
|
}); |
|
|
|
if (!assistant) { |
|
throw error(404, "Assistant not found."); |
|
} |
|
|
|
let avatar = ""; |
|
const fileId = collections.bucket.find({ filename: assistant._id.toString() }); |
|
const file = await fileId.next(); |
|
if (file) { |
|
avatar = await (async () => { |
|
const fileStream = collections.bucket.openDownloadStream(file?._id); |
|
|
|
const fileBuffer = await new Promise<Buffer>((resolve, reject) => { |
|
const chunks: Uint8Array[] = []; |
|
fileStream.on("data", (chunk) => chunks.push(chunk)); |
|
fileStream.on("error", reject); |
|
fileStream.on("end", () => resolve(Buffer.concat(chunks))); |
|
}); |
|
|
|
return fileBuffer; |
|
})() |
|
.then(async (buf) => sharp(buf).jpeg().toBuffer()) |
|
.then(async (buf) => "data:image/jpeg;base64," + buf.toString("base64")); |
|
} |
|
|
|
const renderedComponent = (ChatThumbnail as unknown as SvelteComponent).render({ |
|
name: assistant.name, |
|
description: assistant.description, |
|
createdByName: assistant.createdByName, |
|
avatar, |
|
}); |
|
|
|
const reactLike = html( |
|
"<style>" + renderedComponent.css.code + "</style>" + renderedComponent.html |
|
); |
|
|
|
const svg = await satori(reactLike, { |
|
width: 1200, |
|
height: 648, |
|
fonts: [ |
|
{ |
|
name: "Inter", |
|
data: InterRegular as unknown as ArrayBuffer, |
|
weight: 500, |
|
}, |
|
{ |
|
name: "Inter", |
|
data: InterBold as unknown as ArrayBuffer, |
|
weight: 700, |
|
}, |
|
], |
|
}); |
|
|
|
const png = new Resvg(svg, { |
|
fitTo: { mode: "original" }, |
|
}) |
|
.render() |
|
.asPng(); |
|
|
|
return new Response(png, { |
|
headers: { |
|
"Content-Type": "image/png", |
|
}, |
|
}); |
|
}) satisfies RequestHandler; |
|
|