6 <title>React Hono Val Town Starter</title>
7 <link rel="stylesheet" href="/public/style.css">
8 <link rel="icon" href="/public/favicon.svg" sizes="any" type="image/svg+xml">
9 </head>
10 <body>
5export default async function(req: Request): Promise<Response> {
6 // url query
7 // ?c=id - for creation image
8 // ?c=id&json - for creation json
9
25 let response;
26 try {
27 response = await blob.get("pondiverse_image" + id);
28 } catch (e) {
29 return new Response(null, { status: 404 });
9 data TEXT,
10 type TEXT,
11 image TEXT,
12 time DATETIME NOT NULL
13 )`,
13 for (const row of res.rows) {
14 console.log("delete", row.id);
15 blob.delete("pondiverse_image" + row.id);
16 }
17
9 // - data (string)
10 // - type (string)
11 // - image (data url string)
12
13 // sanity checks:
15 // - data, hmm this needs to be long i guess.. maybe some crazy upper limit sanity check though
16 // - type, not too long
17 // - image, not toooo large a file size
18 let body;
19 try {
26 const data = body.data;
27 const type = body.type;
28 const image = body.image;
29
30 // Sanity checks
38 }
39
40 if (image.length > 20 * 1024 * 1024) {
41 return Response.json({ ok: false, error: "Thumbnail too large" });
42 }
57 );
58
59 await blob.set("pondiverse_image" + id.lastInsertRowid, image);
60 return Response.json({ ok: true });
61}
12}
13
14type ImageSummary = {
15 sender: string;
16 recipient: (typeof RECIPIENTS)[number] | "both" | "other";
22 anthropic: Anthropic,
23 htmlContent: string,
24 imageSummaries: ImageSummary[],
25) {
26 try {
37 `Analyze the following content from an email and provide a response as a JSON blob (only JSON, no other text) with two parts.
38
39 The email is from the USPS showing mail I'm receiving. Metadata about packages is stored directly in the email. Info about mail pieces is in images, so I've included summaries of those as well.
40
41 Your response should include:
67 And here is info about the mail pieces:
68
69 ${JSON.stringify(imageSummaries)}`,
70 },
71 ],
96 const anthropic = new Anthropic({ apiKey });
97
98 // Process each image attachment serially
99 const summaries = [];
100 for (const [index, attachment] of e.attachments.entries()) {
101 try {
102 const imageData = await attachment.arrayBuffer();
103 const base64Image = btoa(
104 String.fromCharCode(...new Uint8Array(imageData)),
105 );
106
113 content: [
114 {
115 type: "image",
116 source: {
117 type: "base64",
118 media_type: attachment.type,
119 data: base64Image,
120 },
121 },
150 summaries.push(parsedResponse);
151 } catch (error) {
152 console.error(`Image analysis error:`, error);
153 summaries.push({
154 sender: "Error",
155 recipient: "Error",
156 type: "error",
157 notes: `Image ${index + 1} Analysis Failed: ${error.message}`,
158 });
159 }
8 return {
9 version: "next",
10 imageUrl: "https://imagedelivery.net/BXluQx4ige9GuW0Ia56BHw/7502b893-e726-408e-d7d0-9d9974517500/original",
11 button: {
12 title: name,
15 name: name,
16 url: baseUrl + path,
17 splashImageUrl:
18 "https://imagedelivery.net/BXluQx4ige9GuW0Ia56BHw/18baad43-5663-44ee-d9fc-c6d842d9cc00/original",
19 splashBackgroundColor: "#111111",
20 },
42 "iconUrl": baseUrl + "/icon",
43 "homeUrl": baseUrl,
44 "splashImageUrl": baseUrl + "/icon",
45 "splashBackgroundColor": "#111111",
46 "primaryCategory": "developer-tools",
5import * as db from "./db.ts";
6import { embedMetadata, handleFarcasterEndpoints, name } from "./farcaster.ts";
7import { handleImageEndpoints } from "./image.tsx";
8
9const app = new Hono();
10
11handleImageEndpoints(app);
12handleFarcasterEndpoints(app);
13
44 <meta name="fc:frame" content={JSON.stringify(embedMetadata(baseUrl, path))} />
45 <link rel="icon" href={baseUrl + "/icon"} />
46 <meta property="og:image" content={baseUrl + "/image"} />
47 </head>
48 <body className="bg-black text-white">
5import satori from "npm:satori";
6
7export function handleImageEndpoints(app: Hono) {
8 const headers = {
9 "Content-Type": "image/png",
10 "cache-control": "public, max-age=86400",
11 };
12 app.get("/image", async (c) => {
13 return c.body(await homeImage(), 200, headers);
14 });
15 app.get("/icon", async (c) => {
16 return c.body(await iconImage(), 200, headers);
17 });
18}
19
20export async function homeImage() {
21 return await ogImage(
22 <img src="https://imagedelivery.net/BXluQx4ige9GuW0Ia56BHw/7502b893-e726-408e-d7d0-9d9974517500/original" />,
23 );
24}
25
26export async function iconImage() {
27 return await ogImage(
28 <img src="https://imagedelivery.net/BXluQx4ige9GuW0Ia56BHw/18baad43-5663-44ee-d9fc-c6d842d9cc00/original" />,
29 {
30 width: 512,
36//////////
37
38export async function ogImage(body, options = {}) {
39 const svg = await satori(
40 body,
48 if (code === "emoji") {
49 const unicode = segment.codePointAt(0).toString(16).toUpperCase();
50 return `data:image/svg+xml;base64,` + btoa(await loadEmoji(unicode));
51 }
52 return "";
85 const base64 = Buffer.from(svg).toString("base64");
86 // console.log('getIconDataUrl', name, svg, base64)
87 return `data:image/svg+xml;base64,${base64}`;
88};
2title: "Knee Slide Cursor"
3description: "A fun, interactive soccer-themed cursor effect that reacts to your mouse movements! Featuring a smooth knee-slide animation and goal celebration messages."
4imageUrl: "https://chatgpt.com/backend-api/public_content/enc/eyJpZCI6Im1fNjgwZDhkYjBiNzdjODE5MTkxOTM3Y2ZlODk3NThjM2E6ZmlsZV8wMDAwMDAwMGY4NDg2MjMwOTU5NDRkOTE0ZTFhMTk3ZCIsInRzIjoiNDg0OTIxIiwicCI6InB5aSIsInNpZyI6ImE2MTRjMjZlMTA1ODM0ZmFkZGQzZDU4YTcyMDdjZmYzMzAyZGEzMGNhZWI0ZGEyMjI2YWM5ZGFiNDM4MTdlNjIiLCJ2IjoiMCIsImdpem1vX2lkIjpudWxsfQ=="
5url: "https://kneeslide-cursor.val.run"
6author: "dcm31"