Page MenuHomePhabricator

D13775.diff
No OneTemporary

D13775.diff

diff --git a/keyserver/src/responders/farcaster-webhook-responders.js b/keyserver/src/responders/farcaster-webhook-responders.js
--- a/keyserver/src/responders/farcaster-webhook-responders.js
+++ b/keyserver/src/responders/farcaster-webhook-responders.js
@@ -2,16 +2,77 @@
import { createHmac } from 'crypto';
import type { $Request } from 'express';
+import { getRustAPI } from 'rust-node-addon';
+import { extractKeyserverIDFromID } from 'lib/keyserver-conn/keyserver-call-utils.js';
+import { threadTypes } from 'lib/types/thread-types-enum.js';
+import { type NewThreadResponse } from 'lib/types/thread-types.js';
import { neynarWebhookCastCreatedEventValidator } from 'lib/types/validators/farcaster-webhook-validators.js';
import { ServerError } from 'lib/utils/errors.js';
import { assertWithValidator } from 'lib/utils/validation-utils.js';
-import { getNeynarConfig } from '../utils/fc-cache.js';
+import {
+ getFarcasterChannelTagBlob,
+ createOrUpdateFarcasterChannelTag,
+ farcasterChannelTagBlobValidator,
+} from '../creators/farcaster-channel-tag-creator.js';
+import { createThread } from '../creators/thread-creator.js';
+import { verifyUserIDs } from '../fetchers/user-fetchers.js';
+import { createScriptViewer } from '../session/scripts.js';
+import { thisKeyserverAdmin, thisKeyserverID } from '../user/identity.js';
+import { getNeynarConfig, neynarClient } from '../utils/fc-cache.js';
const taggedCommFarcasterInputValidator =
neynarWebhookCastCreatedEventValidator;
+const noChannelCommunityID = '80887273';
+
+async function createTaggedFarcasterCommunity(
+ channelID: string,
+ taggerFID: string,
+): Promise<NewThreadResponse> {
+ const neynarChannel =
+ await neynarClient?.fetchFarcasterChannelByID(channelID);
+ if (!neynarChannel) {
+ throw new ServerError('channel_not_found');
+ }
+
+ const keyserverAdmin = await thisKeyserverAdmin();
+ let communityAdminID = keyserverAdmin.id;
+ const leadFID = neynarChannel.lead.fid.toString();
+
+ const rustAPI = await getRustAPI();
+ const farcasterUsers = await rustAPI.getFarcasterUsers([leadFID, taggerFID]);
+
+ const validUserIDs = await verifyUserIDs(
+ farcasterUsers.map(user => user.userID),
+ );
+
+ const validFarcasterUsers = farcasterUsers.filter(user =>
+ validUserIDs.includes(user.userID),
+ );
+
+ if (validFarcasterUsers.length > 0) {
+ communityAdminID =
+ farcasterUsers.find(user => user.farcasterID === leadFID)?.userID ||
+ farcasterUsers[0].userID;
+ }
+
+ const adminViewer = createScriptViewer(communityAdminID);
+ const newThreadResponse = await createThread(adminViewer, {
+ type: threadTypes.COMMUNITY_ROOT,
+ name: neynarChannel.name,
+ description: neynarChannel.description,
+ });
+
+ await createOrUpdateFarcasterChannelTag(adminViewer, {
+ commCommunityID: newThreadResponse.newThreadID,
+ farcasterChannelID: channelID,
+ });
+
+ return newThreadResponse;
+}
+
async function taggedCommFarcasterResponder(req: $Request): Promise<void> {
const body = req.body;
@@ -35,6 +96,49 @@
if (!isValid) {
throw new ServerError('invalid_webhook_signature');
}
+
+ const isAuthoritativeFarcasterBot = !!process.env.AUTHORITATIVE_FARCASTER_BOT;
+ const eventChannelID = event.data.channel?.id;
+ const eventTaggerFID = event.data.author.fid;
+
+ if (!eventChannelID && !isAuthoritativeFarcasterBot) {
+ return;
+ }
+
+ let channelCommunityID = noChannelCommunityID;
+ if (eventChannelID) {
+ const blobDownload = await getFarcasterChannelTagBlob(eventChannelID);
+ if (blobDownload.found) {
+ const blobText = await blobDownload.blob.text();
+ const blobObject = JSON.parse(blobText);
+ const farcasterChannelTagBlob = assertWithValidator(
+ blobObject,
+ farcasterChannelTagBlobValidator,
+ );
+
+ const { commCommunityID } = farcasterChannelTagBlob;
+ const commCommunityKeyserverID =
+ extractKeyserverIDFromID(commCommunityID);
+ const keyserverID = await thisKeyserverID();
+
+ if (keyserverID !== commCommunityKeyserverID) {
+ return;
+ }
+ channelCommunityID = commCommunityID.split('|')[1];
+ } else if (!blobDownload.found && blobDownload.status === 404) {
+ if (!isAuthoritativeFarcasterBot) {
+ return;
+ }
+ const newThreadResponse = await createTaggedFarcasterCommunity(
+ eventChannelID,
+ eventTaggerFID.toString(),
+ );
+ channelCommunityID = newThreadResponse.newThreadID;
+ } else {
+ throw new ServerError('blob_fetch_failed');
+ }
+ }
+ console.log(channelCommunityID);
}
export { taggedCommFarcasterResponder, taggedCommFarcasterInputValidator };

File Metadata

Mime Type
text/plain
Expires
Thu, Oct 24, 12:29 AM (21 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2354875
Default Alt Text
D13775.diff (4 KB)

Event Timeline