Skip to content

Commit

Permalink
add frog
Browse files Browse the repository at this point in the history
  • Loading branch information
RamRamez committed Aug 20, 2024
1 parent 07fc3fc commit a27c5eb
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 80 deletions.
Binary file modified bun.lockb
Binary file not shown.
82 changes: 26 additions & 56 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,28 @@
import neynarClient from "./neynarClient";
import type {NeynarFrameCreationRequest} from "@neynar/nodejs-sdk/build/neynar-api/v2";
import routes from "./src/routes/routes.js";
import bot from "./src/routes/bot.js";
import {frogApp} from "./src/routes/frog.js";

const server = Bun.serve({
port: 3000,
async fetch(req) {
try {
console.log("Received request! Date: " + new Date() + ' ' + req);
const body = await req.text();
const hookData = JSON.parse(body);

const creationRequest: NeynarFrameCreationRequest = {
name: `gm ${hookData.data.author.username}`,
pages: [
{
image: {
url: "https://moralis.io/wp-content/uploads/web3wiki/638-gm/637aeda23eca28502f6d3eae_61QOyzDqTfxekyfVuvH7dO5qeRpU50X-Hs46PiZFReI.jpeg",
aspect_ratio: "1:1",
},
title: "Page title",
buttons: [],
input: {
text: {
enabled: false,
},
},
uuid: "gm",
version: "vNext",
},
],
};
const frame = await neynarClient.publishNeynarFrame(creationRequest);

if (!process.env.SIGNER_UUID) {
throw new Error("Make sure you set SIGNER_UUID in your .env file");
}

const reply = await neynarClient.publishCast(
process.env.SIGNER_UUID,
`gm ${hookData.data.author.username}`,
{
embeds: [
{
url: frame.link,
},
],
replyTo: hookData.data.hash,
if (typeof Bun !== 'undefined') {
const server = Bun.serve({
fetch: async (req) => {
try {
const url = new URL(req.url);
console.log("Received request! Date: " + new Date() + ' ' + req);
switch (url.pathname) {
case routes.home:
return new Response('This is my Farcaster praise bot', { status: 200 });
case routes.bot:
return await bot(req);
case routes.frog:
return await frogApp.fetch(req);
default:
return new Response('Not Found', { status: 404 });
}
);
console.log("Response sent! Date: " + new Date() + ' ' + reply);
return new Response(`Replied to the cast with hash: ${reply.hash}`);
} catch (e: any) {
return new Response(e.message, { status: 500 });
}
},
});

console.log(`Listening on localhost:${server.port}`);
} catch (e: any) {
return new Response(e.message, { status: 500 });
}
},
port: 3000,
})
console.log(`Listening on localhost:${server.port}`);
}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"module": "index.ts",
"type": "module",
"scripts": {
"dev": "frog dev",
"start": "bun run index.ts"
},
"devDependencies": {
Expand All @@ -12,6 +13,8 @@
"typescript": "^5.0.0"
},
"dependencies": {
"@neynar/nodejs-sdk": "^1.40.0"
"@neynar/nodejs-sdk": "^1.40.0",
"frog": "latest",
"hono": "latest"
}
}
File renamed without changes.
39 changes: 39 additions & 0 deletions src/routes/bot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import neynarClient from "../helpers/neynarClient.js";
import routes from "./routes.js";

const bot = async (req: Request) => {
if (!process.env.SIGNER_UUID) {
throw new Error("Make sure you set SIGNER_UUID in your .env file");
}
const body = await req.text();
const hookData = JSON.parse(body);

const reply = await neynarClient.publishCast(
process.env.SIGNER_UUID,
`gm ${hookData.data.author.username}`,
{
embeds: [
{
url: process.env.APP_URL + routes.frog,
},
],
replyTo: hookData.data.hash,
}
);

// const reply = await neynarClient.publishCast(
// process.env.SIGNER_UUID,
// `gm Ramin`,
// {
// embeds: [
// {
// url: process.env.APP_URL + routes.frog,
// },
// ],
// }
// );
console.log("Response sent! Date: " + new Date() + ' ' + reply);
return new Response(`Replied to the cast with hash: ${reply.hash}`);
}

export default bot;
65 changes: 65 additions & 0 deletions src/routes/frog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Button, Frog, TextInput } from 'frog'
import { devtools } from 'frog/dev'
import { serveStatic } from 'frog/serve-static'
import routes from "./routes.js";

export const frogApp = new Frog({
// Supply a Hub to enable frame verification.
// hub: neynar({ apiKey: 'NEYNAR_FROG_FM' }),
basePath: routes.frog,
title: 'Praise in Farcaster',
})

frogApp.frame('/', (c) => {
const { buttonValue, inputText, status } = c
const fruit = inputText || buttonValue
console.log('frogApp fruit:', fruit);
return c.res({
image: (
<div
style={{
alignItems: 'center',
background:
status === 'response'
? 'linear-gradient(to right, #432889, #17101F)'
: 'black',
backgroundSize: '100% 100%',
display: 'flex',
flexDirection: 'column',
flexWrap: 'nowrap',
height: '100%',
justifyContent: 'center',
textAlign: 'center',
width: '100%',
}}
>
<div
style={{
color: 'white',
fontSize: 60,
fontStyle: 'normal',
letterSpacing: '-0.025em',
lineHeight: 1.4,
marginTop: 30,
padding: '0 120px',
whiteSpace: 'pre-wrap',
}}
>
{status === 'response'
? `Nice choice.${fruit ? ` ${fruit.toUpperCase()}!!` : ''}`
: 'Welcome!'}
</div>
</div>
),
intents: [
<TextInput placeholder="Enter custom fruit..." />,
<Button value="apples">Apples</Button>,
<Button value="oranges">Oranges</Button>,
<Button value="bananas">Bananas</Button>,
status === 'response' && <Button.Reset>Reset</Button.Reset>,
],
})
})

frogApp.use('/*', serveStatic({ root: './public' }))
devtools(frogApp, { serveStatic })
7 changes: 7 additions & 0 deletions src/routes/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const routes = {
home: '/',
bot: '/bot',
frog: '/frog',
}

export default routes;
27 changes: 4 additions & 23 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,8 @@
{
"compilerOptions": {
// Enable latest features
"lib": ["ESNext", "DOM"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,

// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,

// Best practices
"module": "NodeNext",
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,

// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx"
}
}
}

0 comments on commit a27c5eb

Please sign in to comment.