mirror of
https://github.com/neynarxyz/create-farcaster-mini-app.git
synced 2025-11-21 18:28:00 -05:00
use neynar notifs
This commit is contained in:
@@ -3,6 +3,7 @@ import { NextRequest } from "next/server";
|
||||
import { z } from "zod";
|
||||
import { setUserNotificationDetails } from "~/lib/kv";
|
||||
import { sendFrameNotification } from "~/lib/notifs";
|
||||
import { sendNeynarFrameNotification } from "~/lib/neynar";
|
||||
|
||||
const requestSchema = z.object({
|
||||
fid: z.number(),
|
||||
@@ -10,6 +11,10 @@ const requestSchema = z.object({
|
||||
});
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
// If Neynar is enabled, we don't need to store notification details
|
||||
// as they will be managed by Neynar's system
|
||||
const neynarEnabled = process.env.NEYNAR_API_KEY && process.env.NEYNAR_CLIENT_ID;
|
||||
|
||||
const requestJson = await request.json();
|
||||
const requestBody = requestSchema.safeParse(requestJson);
|
||||
|
||||
@@ -20,13 +25,18 @@ export async function POST(request: NextRequest) {
|
||||
);
|
||||
}
|
||||
|
||||
await setUserNotificationDetails(
|
||||
requestBody.data.fid,
|
||||
requestBody.data.notificationDetails
|
||||
);
|
||||
// Only store notification details if not using Neynar
|
||||
if (!neynarEnabled) {
|
||||
await setUserNotificationDetails(
|
||||
Number(requestBody.data.fid),
|
||||
requestBody.data.notificationDetails
|
||||
);
|
||||
}
|
||||
|
||||
const sendResult = await sendFrameNotification({
|
||||
fid: requestBody.data.fid,
|
||||
// Use appropriate notification function based on Neynar status
|
||||
const sendNotification = neynarEnabled ? sendNeynarFrameNotification : sendFrameNotification;
|
||||
const sendResult = await sendNotification({
|
||||
fid: Number(requestBody.data.fid),
|
||||
title: "Test notification",
|
||||
body: "Sent at " + new Date().toISOString(),
|
||||
});
|
||||
|
||||
@@ -11,6 +11,13 @@ import {
|
||||
import { sendFrameNotification } from "~/lib/notifs";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
// If Neynar is enabled, we don't need to handle webhooks here
|
||||
// as they will be handled by Neynar's webhook endpoint
|
||||
const neynarEnabled = process.env.NEYNAR_API_KEY && process.env.NEYNAR_CLIENT_ID;
|
||||
if (neynarEnabled) {
|
||||
return Response.json({ success: true });
|
||||
}
|
||||
|
||||
const requestJson = await request.json();
|
||||
|
||||
let data;
|
||||
@@ -45,6 +52,8 @@ export async function POST(request: NextRequest) {
|
||||
const fid = data.fid;
|
||||
const event = data.event;
|
||||
|
||||
// Only handle notifications if Neynar is not enabled
|
||||
// When Neynar is enabled, notifications are handled through their webhook
|
||||
switch (event.event) {
|
||||
case "frame_added":
|
||||
if (event.notificationDetails) {
|
||||
@@ -57,12 +66,12 @@ export async function POST(request: NextRequest) {
|
||||
} else {
|
||||
await deleteUserNotificationDetails(fid);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "frame_removed":
|
||||
await deleteUserNotificationDetails(fid);
|
||||
|
||||
break;
|
||||
|
||||
case "notifications_enabled":
|
||||
await setUserNotificationDetails(fid, event.notificationDetails);
|
||||
await sendFrameNotification({
|
||||
@@ -70,11 +79,10 @@ export async function POST(request: NextRequest) {
|
||||
title: "Ding ding ding",
|
||||
body: "Notifications are now enabled",
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
case "notifications_disabled":
|
||||
await deleteUserNotificationDetails(fid);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,9 @@ import { NeynarAPIClient } from '@neynar/nodejs-sdk';
|
||||
|
||||
let neynarClient: NeynarAPIClient | null = null;
|
||||
|
||||
// Example usage:
|
||||
// const client = getNeynarClient();
|
||||
// const user = await client.lookupUserByFid(fid);
|
||||
export function getNeynarClient() {
|
||||
if (!neynarClient) {
|
||||
const apiKey = process.env.NEYNAR_API_KEY;
|
||||
@@ -13,6 +16,46 @@ export function getNeynarClient() {
|
||||
return neynarClient;
|
||||
}
|
||||
|
||||
// Example usage:
|
||||
// const client = getNeynarClient();
|
||||
// const user = await client.lookupUserByFid(fid);
|
||||
type SendFrameNotificationResult =
|
||||
| {
|
||||
state: "error";
|
||||
error: unknown;
|
||||
}
|
||||
| { state: "no_token" }
|
||||
| { state: "rate_limit" }
|
||||
| { state: "success" };
|
||||
|
||||
export async function sendNeynarFrameNotification({
|
||||
fid,
|
||||
title,
|
||||
body,
|
||||
}: {
|
||||
fid: number;
|
||||
title: string;
|
||||
body: string;
|
||||
}): Promise<SendFrameNotificationResult> {
|
||||
try {
|
||||
const client = getNeynarClient();
|
||||
const targetFids = [fid];
|
||||
const notification = {
|
||||
title,
|
||||
body,
|
||||
target_url: process.env.NEXT_PUBLIC_URL,
|
||||
};
|
||||
|
||||
const result = await client.publishFrameNotifications({
|
||||
targetFids,
|
||||
notification
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
return { state: "success" };
|
||||
} else if (result.status === 429) {
|
||||
return { state: "rate_limit" };
|
||||
} else {
|
||||
return { state: "error", error: result.error || "Unknown error" };
|
||||
}
|
||||
} catch (error) {
|
||||
return { state: "error", error };
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,13 @@ export async function generateFarcasterMetadata() {
|
||||
};
|
||||
}
|
||||
|
||||
// Determine webhook URL based on whether Neynar is enabled
|
||||
const neynarApiKey = process.env.NEYNAR_API_KEY;
|
||||
const neynarClientId = process.env.NEYNAR_CLIENT_ID;
|
||||
const webhookUrl = neynarApiKey && neynarClientId
|
||||
? `https://api.neynar.com/f/app/${neynarClientId}/event`
|
||||
: `${appUrl}/api/webhook`;
|
||||
|
||||
return {
|
||||
accountAssociation,
|
||||
frame: {
|
||||
@@ -73,7 +80,7 @@ export async function generateFarcasterMetadata() {
|
||||
buttonTitle: process.env.NEXT_PUBLIC_FRAME_BUTTON_TEXT || "Launch Frame",
|
||||
splashImageUrl: process.env.NEXT_PUBLIC_FRAME_SPLASH_IMAGE_URL || `${appUrl}/splash.png`,
|
||||
splashBackgroundColor: "#f7f7f7",
|
||||
webhookUrl: `${appUrl}/api/webhook`,
|
||||
webhookUrl,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user