Created
June 19, 2024 21:40
-
-
Save Slokh/18a0a9e97a44c3dfc03758d224c6b965 to your computer and use it in GitHub Desktop.
discover farcaster users based on who you follow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
UserDataType, | |
getSSLHubRpcClient, | |
utf8StringToBytes, | |
} from "@farcaster/hub-nodejs"; | |
import { NextRequest } from "next/server"; | |
const client = getSSLHubRpcClient(process.env.HUB_RPC_ENDPOINT as string); | |
export async function GET(request: NextRequest) { | |
const searchParams = request.nextUrl.searchParams; | |
const query = searchParams.get("fidOrUsername"); | |
if (!query) { | |
return Response.json({ error: "No query provided" }, { status: 400 }); | |
} | |
const proof = await client.getUsernameProof({ | |
name: utf8StringToBytes(query)._unsafeUnwrap(), | |
}); | |
if (!proof && Number.isNaN(Number(query))) { | |
return Response.json({ error: "Unknown user" }, { status: 400 }); | |
} | |
const fid = proof.isOk() ? proof.value.fid : Number(query); | |
const following = await getFollowingFids(fid); | |
const followingFollowing = await Promise.all( | |
following.following.slice(0, 300).map(getFollowingFids), | |
); | |
const map = followingFollowing.reduce( | |
(acc, curr) => { | |
for (const followingFid of curr.following) { | |
if ( | |
following.following.includes(followingFid) || | |
followingFid === fid | |
) { | |
continue; | |
} | |
if (!acc[followingFid]) { | |
acc[followingFid] = { | |
fid: followingFid, | |
mutuals: [], | |
}; | |
} | |
acc[followingFid].mutuals.push(curr.fid); | |
} | |
return acc; | |
}, | |
{} as Record< | |
number, | |
{ | |
fid: number; | |
mutuals: number[]; | |
} | |
>, | |
); | |
const sorted = Object.values(map) | |
.sort((a, b) => b.mutuals.length - a.mutuals.length) | |
.slice(0, 25); | |
const users = await Promise.all(sorted.map((user) => getUser(user.fid))); | |
return Response.json({ | |
users: sorted.map((data, i) => ({ | |
...data, | |
...users[i], | |
})), | |
}); | |
} | |
const getFollowingFids = async (fid: number) => { | |
const following = await client.getLinksByFid({ fid }); | |
if (following.isErr()) { | |
return { | |
fid, | |
following: [], | |
}; | |
} | |
return { | |
fid, | |
following: following.value.messages.map( | |
(message) => message.data?.linkBody?.targetFid, | |
) as number[], | |
}; | |
}; | |
const getUser = async (fid: number) => { | |
const user = await client.getUserDataByFid({ fid }); | |
if (user.isErr()) { | |
throw new Error(`Failed to get user ${fid}`); | |
} | |
return { | |
fid, | |
username: user.value.messages.find( | |
(message) => message.data?.userDataBody?.type === UserDataType.USERNAME, | |
)?.data?.userDataBody?.value, | |
displayName: user.value.messages.find( | |
(message) => message.data?.userDataBody?.type === UserDataType.DISPLAY, | |
)?.data?.userDataBody?.value, | |
pfp: user.value.messages.find( | |
(message) => message.data?.userDataBody?.type === UserDataType.PFP, | |
)?.data?.userDataBody?.value, | |
bio: user.value.messages.find( | |
(message) => message.data?.userDataBody?.type === UserDataType.BIO, | |
)?.data?.userDataBody?.value, | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment