diff --git a/api/og-image.ts b/api/og-image.ts deleted file mode 100644 index c4eb2a5..0000000 --- a/api/og-image.ts +++ /dev/null @@ -1,79 +0,0 @@ -import satori from "satori"; -import sharp from "sharp"; -import { html } from "satori-html"; -import fonts from "../src/fonts.js"; -import frames from "../src/frames/index.js"; -import mainLayout from "../src/layouts/main.js"; -import { URLSearchParamsToObject } from '../modules/utils.js'; - -export default async (req) => { - - const url = new URL(req.url); - const params = URLSearchParamsToObject(url.searchParams); - const { message, frameName, dataUri, imageUrl } = params; - - let responseBuffer; - - // Case 1: Handle data URI - if (dataUri) { - const base64Data = dataUri.split(',')[1]; - responseBuffer = Buffer.from(base64Data, 'base64'); - } - // Case 2: Proxy an image - else if (imageUrl) { - // Fetch and process the external image - responseBuffer = await fetchExternalImage(imageUrl); - } - // Default case: Generate image based on frame name and message - else if (frameName && message) { - const targetFrame = frames[frameName]; - const frame = await targetFrame.render(message); - const frameMarkupInLayout = mainLayout(frame.image, message) - - const svg = await satori( - html(frameMarkupInLayout), - { - width: 1200, - height: 630, - fonts: fonts, - } - ); - const svgBuffer = Buffer.from(svg); - const png = sharp(svgBuffer).png(); - responseBuffer = await png.toBuffer(); - } else { - throw new Error("Insufficient parameters provided for image generation."); - } - - return new Response(responseBuffer, - { - status: 200, - headers: { - 'Content-Type': 'image/png', - 'Cache-Control': 'public, max-age=31536000' - } - } - ); -} - -// Assuming `fetch` is already available in your environment -const fetchExternalImage = async (imageUrl) => { - try { - const response = await fetch(imageUrl); - if (!response.ok) { - throw new Error('Failed to fetch image'); - } - // Use .arrayBuffer() and convert it to a Buffer - const arrayBuffer = await response.arrayBuffer(); - const buffer = Buffer.from(arrayBuffer); - return buffer; - } catch (error) { - console.error('Error fetching external image:', error); - return null; - } -}; - - -export const config = { - path: "/og-image" -}; \ No newline at end of file diff --git a/modules/processFrameRequest.ts b/modules/processFrameRequest.ts index f9b5b6e..6781734 100644 --- a/modules/processFrameRequest.ts +++ b/modules/processFrameRequest.ts @@ -1,7 +1,11 @@ +import satori from "satori"; +import sharp from "sharp"; +import { html } from "satori-html"; +import fonts from "../src/fonts.js"; +import mainLayout from "../src/layouts/main.js"; import frames from '../src/frames/index.js'; import { Frame, FrameActionDataParsed, GetFrameHtmlOptions, getFrameHtml } from "frames.js"; import landingPage from '../src/landing-page.js'; -import { objectToURLSearchParams } from '../modules/utils.js'; import { isFrameStolen } from './antitheft.js'; /** @@ -63,7 +67,7 @@ const respondWithFrame = async ( const host = process.env.URL; const frame: Frame = { version: 'vNext', - image: handleImageSource(name, simpleFrame, message), + image: await handleImageSource(simpleFrame, message), buttons: simpleFrame.buttons, inputText: simpleFrame.inputText, postUrl: `${host}/?${postVars.toString()}` @@ -90,26 +94,43 @@ const respondWithFrame = async ( ); }; -function handleImageSource(name, frame, message):string { +async function handleImageSource(frame, message):Promise { const dataUriPattern = /^data:image\/[a-zA-Z]+;base64,/; const absoluteUrlPattern = /^https?:\/\//; const host = process.env.URL; - const { image } = frame; + const { imageURL, imageMarkup } = frame; - if (dataUriPattern.test(image)) { - return `${host}/og-image?${objectToURLSearchParams({ - dataUri: image, - })}`; - } else if (absoluteUrlPattern.test(image)) { - return `${host}/og-image?${objectToURLSearchParams({ - imageUrl: image, - })}`; - } else { - return `${host}/og-image?${objectToURLSearchParams({ - t: new Date().valueOf(), // Current timestamp for cache busting. - frameName: name || '', - message - })}`; + if (imageMarkup) { + const frameMarkupInLayout = mainLayout(imageMarkup, message) + const svg = await satori( + html(frameMarkupInLayout), + { + width: 1200, + height: 630, + fonts: fonts, + } + ); + const svgBuffer = Buffer.from(svg); + const imgOutput = sharp(svgBuffer).webp(); + const imageBuffer = await imgOutput.toBuffer(); + return `data:image/png;base64,${imageBuffer.toString('base64')}`; + } + + // data URI + else if (dataUriPattern.test(imageURL)) { + return imageURL; + } + + // external image: need to proxy it + else if (absoluteUrlPattern.test(imageURL)) { + const ogImageResponse = await fetch(imageURL); + const dataURI = await ogImageResponse.text(); // Assuming og-image returns the data URI in the response body + return dataURI; + } + + // local image + else { + return `${host}/${imageURL}`; } } diff --git a/package.json b/package.json index 35cef93..9d8d809 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "simplest-frame", "type": "module", - "version": "0.11.0", + "version": "0.11.1", "dependencies": { "@netlify/blobs": "^6.4.2", "dompurify": "^3.0.8", diff --git a/public/images/credits.png b/public/images/credits.png deleted file mode 100644 index ea1b65e..0000000 Binary files a/public/images/credits.png and /dev/null differ diff --git a/src/frames/count.ts b/src/frames/count.ts index 3209992..441510d 100644 --- a/src/frames/count.ts +++ b/src/frames/count.ts @@ -9,7 +9,7 @@ export default { const count = await getCount(); const { username, taunt } = await getFramer() || {}; return { - image: html` + imageMarkup: html`
{ return { - image: `${process.env.URL}/images/poster-animated.gif`, + imageURL: 'images/poster-animated.gif', buttons: [ { action: 'post', diff --git a/src/frames/poster.ts b/src/frames/poster.ts index 4a9796e..32540bd 100644 --- a/src/frames/poster.ts +++ b/src/frames/poster.ts @@ -4,7 +4,7 @@ export default { name: 'poster', render: () => { return { - image: `${process.env.URL}/images/poster-animated.gif`, + imageURL: 'images/poster-animated.gif', buttons: [ { action: 'post', diff --git a/src/frames/stolen.ts b/src/frames/stolen.ts index 7ca78e8..d03aebe 100644 --- a/src/frames/stolen.ts +++ b/src/frames/stolen.ts @@ -2,7 +2,7 @@ export default { name: 'stolen', render: () => { return { - image: `${process.env.URL}/images/stolen.png`, + imageURL: 'images/stolen.png', buttons: [ { action: 'post', diff --git a/src/frames/transaction.ts b/src/frames/transaction.ts index 2ee1631..cd1b0f0 100644 --- a/src/frames/transaction.ts +++ b/src/frames/transaction.ts @@ -5,7 +5,7 @@ export default { name: 'transaction', render: async () => { return { - image: html` + imageMarkup: html`