diff --git a/keyserver/flow-typed/npm/@hono/node-server_vx.x.x.js b/keyserver/flow-typed/npm/@hono/node-server_vx.x.x.js index 460b747fc..373ee537a 100644 --- a/keyserver/flow-typed/npm/@hono/node-server_vx.x.x.js +++ b/keyserver/flow-typed/npm/@hono/node-server_vx.x.x.js @@ -1,17 +1,29 @@ // flow-typed signature: 27d95010f07acc1758d5b0014afb152c // flow-typed version: <>/@hono/node-server_v1.13.7/flow_v0.202.1 declare module '@hono/node-server' { declare export opaque type Fetch; declare export var serve: ({ +fetch?: ?Fetch, +port?: ?number, ... }) => mixed; declare export class HonoRequest { param(): { +[key: string]: string }; } } + +declare module '@hono/node-server/serve-static' { + + import type { MiddlewareHandler } from 'hono'; + + declare export type ServeStaticOptions = { + +path: ?string, + ... + } + + declare export var serveStatic: ServeStaticOptions => MiddlewareHandler; +} diff --git a/keyserver/flow-typed/npm/frog_v0.18.x.js b/keyserver/flow-typed/npm/frog_v0.18.x.js index fc702ebc8..3fb450042 100644 --- a/keyserver/flow-typed/npm/frog_v0.18.x.js +++ b/keyserver/flow-typed/npm/frog_v0.18.x.js @@ -1,45 +1,47 @@ // flow-typed signature: 8b45e30d3c592dc3c877fcba96c687fb // flow-typed version: <>/frog_v0.18.x/flow_v0.202.1 declare module 'frog' { import type { Fetch, HonoRequest } from '@hono/node-server'; + import type { Hono } from 'hono'; declare type FrameResponse = { +image: React$Node, +intents: $ReadOnlyArray, ... }; declare export var Button: { Link: React$ComponentType<{ +children: React$Node, +href: string, ... }>, ... }; declare opaque type FrogResponse; declare opaque type FrogRequest; declare type FrameContext = { +res: (response: FrameResponse) => FrogResponse, +req: HonoRequest, ... }; declare type FrogOptions = { +title: string, ... }; declare export class Frog { constructor(options?: FrogOptions): this; frame( route: string, callback: (c: FrameContext) => Promise | FrogResponse, ): void; + hono: Hono, fetch: Fetch, } } diff --git a/keyserver/flow-typed/npm/hono_vx.x.x.js b/keyserver/flow-typed/npm/hono_vx.x.x.js new file mode 100644 index 000000000..de2f1347c --- /dev/null +++ b/keyserver/flow-typed/npm/hono_vx.x.x.js @@ -0,0 +1,15 @@ +// flow-typed signature: 06706c2a95e8f8228cf2ed3a7f3a1366 +// flow-typed version: <>/hono_v4.6.9/flow_v0.202.1 + +declare module 'hono' { + + declare export opaque type MiddlewareHandler; + + declare export class Hono { + use( + route: string, + handler: MiddlewareHandler, + ): mixed; + } +} + diff --git a/keyserver/images/default_farcaster_channel_cover.png b/keyserver/images/default_farcaster_channel_cover.png new file mode 100644 index 000000000..8b9d379c4 Binary files /dev/null and b/keyserver/images/default_farcaster_channel_cover.png differ diff --git a/keyserver/src/frog/frog.js b/keyserver/src/frog/frog.js index 83a1cc80d..335f41872 100644 --- a/keyserver/src/frog/frog.js +++ b/keyserver/src/frog/frog.js @@ -1,152 +1,158 @@ // @flow /** @jsxImportSource hono/jsx */ /* eslint-disable react/react-in-jsx-scope */ import { serve } from '@hono/node-server'; +// eslint-disable-next-line import/extensions +import { serveStatic } from '@hono/node-server/serve-static'; import { Button, Frog } from 'frog'; import { inviteLinkURL } from 'lib/facts/links.js'; import { ignorePromiseRejections } from 'lib/utils/promises.js'; import { neynarClient } from '../utils/fc-cache.js'; import { redisCache } from '../utils/redis-cache.js'; function startFrogHonoServer() { const frogApp = new Frog({ title: 'Comm' }); + frogApp.hono.use( + '/default_farcaster_channel_cover.png', + serveStatic({ path: './images/default_farcaster_channel_cover.png' }), + ); + frogApp.frame('/:inviteLink/:channelID/:taggerUsername', async c => { const { inviteLink, channelID, taggerUsername } = c.req.param(); let buttonLink = 'https://comm.app'; const inviteLinkURLPrefix = inviteLinkURL(''); if (inviteLink.startsWith(inviteLinkURLPrefix)) { buttonLink = inviteLink; } let channelInfo = await redisCache.getChannelInfo(channelID); if (!channelInfo) { channelInfo = await neynarClient?.fetchFarcasterChannelByID(channelID); if (channelInfo) { ignorePromiseRejections( redisCache.setChannelInfo(channelID, channelInfo), ); } } - let header_image_url = - 'https://warpcast.com/~/images/DefaultChannelCoverImage.png'; + let header_image_url = '/default_farcaster_channel_cover.png'; if (channelInfo?.header_image_url) { header_image_url = channelInfo.header_image_url; } const displayUsername = taggerUsername.length > 16 ? `${taggerUsername.slice(0, 16)}[...]` : taggerUsername; const channelIcon = channelInfo?.image_url ? ( icon ) : null; return c.res({ image: (
frame background
{channelIcon} Thread Invitation
@{displayUsername} created a thread on Comm
), intents: [ Join chat , ], }); }); serve({ fetch: frogApp.fetch, port: parseInt(process.env.FROG_PORT, 10) || 3001, }); } export { startFrogHonoServer };