Page MenuHomePhabricator

D13754.id.diff
No OneTemporary

D13754.id.diff

diff --git a/keyserver/src/keyserver.js b/keyserver/src/keyserver.js
--- a/keyserver/src/keyserver.js
+++ b/keyserver/src/keyserver.js
@@ -25,11 +25,13 @@
import { jsonEndpoints } from './endpoints.js';
import { logEndpointMetrics } from './middleware/endpoint-profiling.js';
import { emailSubscriptionResponder } from './responders/comm-landing-responders.js';
+import { taggedCommFarcasterResponder } from './responders/farcaster-webhook-responders.js';
import {
jsonHandler,
downloadHandler,
htmlHandler,
uploadHandler,
+ webhookPayloadHandler,
} from './responders/handlers.js';
import landingHandler from './responders/landing-handler.js';
import { errorReportDownloadResponder } from './responders/report-responders.js';
@@ -297,6 +299,11 @@
keyserverRouter.use(cors(keyserverCorsOptions));
}
+ keyserverRouter.post(
+ '/fc_comm_tagged',
+ webhookPayloadHandler(taggedCommFarcasterResponder),
+ );
+
for (const endpoint in jsonEndpoints) {
// $FlowFixMe Flow thinks endpoint is string
const responder = jsonEndpoints[endpoint];
diff --git a/keyserver/src/responders/farcaster-webhook-responders.js b/keyserver/src/responders/farcaster-webhook-responders.js
new file mode 100644
--- /dev/null
+++ b/keyserver/src/responders/farcaster-webhook-responders.js
@@ -0,0 +1,20 @@
+// @flow
+
+import type { $Request } from 'express';
+
+import { neynarWebhookCastCreatedEventValidator } from 'lib/types/validators/farcaster-webhook-validators.js';
+import { assertWithValidator } from 'lib/utils/validation-utils.js';
+
+const taggedCommFarcasterInputValidator =
+ neynarWebhookCastCreatedEventValidator;
+
+async function taggedCommFarcasterResponder(request: $Request): Promise<void> {
+ const event = assertWithValidator(
+ request.body,
+ taggedCommFarcasterInputValidator,
+ );
+
+ console.log(event);
+}
+
+export { taggedCommFarcasterResponder, taggedCommFarcasterInputValidator };
diff --git a/keyserver/src/responders/handlers.js b/keyserver/src/responders/handlers.js
--- a/keyserver/src/responders/handlers.js
+++ b/keyserver/src/responders/handlers.js
@@ -111,6 +111,29 @@
};
}
+type WebhookPayloadResponder = (request: $Request) => Promise<void>;
+function webhookPayloadHandler(
+ responder: WebhookPayloadResponder,
+): (req: $Request, res: $Response) => Promise<void> {
+ return async (req: $Request, res: $Response) => {
+ try {
+ if (!req.body || typeof req.body !== 'object') {
+ throw new ServerError('invalid_parameters');
+ }
+
+ const responderResult = await responder(req);
+
+ if (res.headersSent) {
+ return;
+ }
+ const result = { ...responderResult };
+ res.json({ success: true, ...result });
+ } catch (e) {
+ await handleException(e, res);
+ }
+ };
+}
+
function httpGetHandler(
responder: HTTPGetResponder,
): (req: $Request, res: $Response) => Promise<void> {
@@ -245,4 +268,5 @@
downloadHandler,
htmlHandler,
uploadHandler,
+ webhookPayloadHandler,
};
diff --git a/lib/types/farcaster-types.js b/lib/types/farcaster-types.js
--- a/lib/types/farcaster-types.js
+++ b/lib/types/farcaster-types.js
@@ -41,3 +41,35 @@
+description: string,
...
};
+
+export type NeynarWebhookCastAuthor = {
+ +object: 'user',
+ +fid: string,
+ +custody_address: string,
+ +username: string,
+ +display_name: string,
+ +pfp_url: string,
+ +profile: Object,
+};
+
+export type NeynarWebhookCastCreatedData = {
+ +object: 'cast',
+ +hash: string,
+ +thread_hash: string,
+ +text: string,
+ +embeds: $ReadOnlyArray<Object>,
+ +channel?: ?NeynarWebhookChannel,
+ ...
+};
+
+export type NeynarWebhookChannel = {
+ +id: string,
+ +name: string,
+ +image_url: string,
+};
+
+export type NeynarWebhookCastCreatedEvent = {
+ +created_at: number,
+ +type: 'cast.created',
+ +data: NeynarWebhookCastCreatedData,
+};
diff --git a/lib/types/validators/farcaster-webhook-validators.js b/lib/types/validators/farcaster-webhook-validators.js
new file mode 100644
--- /dev/null
+++ b/lib/types/validators/farcaster-webhook-validators.js
@@ -0,0 +1,45 @@
+// @flow
+
+import t, { type TInterface } from 'tcomb';
+
+import type {
+ NeynarWebhookCastCreatedData,
+ NeynarWebhookChannel,
+ NeynarWebhookCastAuthor,
+ NeynarWebhookCastCreatedEvent,
+} from '../farcaster-types.js';
+
+export const neynarWebhookCastAuthorValidator: TInterface<NeynarWebhookCastAuthor> =
+ t.interface<NeynarWebhookCastAuthor>({
+ object: t.enums.of(['user']),
+ fid: t.String,
+ custody_address: t.String,
+ username: t.String,
+ display_name: t.String,
+ pfp_url: t.String,
+ profile: t.Object,
+ });
+
+export const neynarWebhookChannelValidator: TInterface<NeynarWebhookChannel> =
+ t.interface<NeynarWebhookChannel>({
+ id: t.String,
+ name: t.String,
+ image_url: t.String,
+ });
+
+export const neynarWebhookCastCreatedDataValidator: TInterface<NeynarWebhookCastCreatedData> =
+ t.interface<NeynarWebhookCastCreatedData>({
+ object: t.enums.of(['cast']),
+ hash: t.String,
+ thread_hash: t.String,
+ text: t.String,
+ embeds: t.list(t.Object),
+ channel: t.maybe(neynarWebhookChannelValidator),
+ });
+
+export const neynarWebhookCastCreatedEventValidator: TInterface<NeynarWebhookCastCreatedEvent> =
+ t.interface<NeynarWebhookCastCreatedEvent>({
+ created_at: t.Number,
+ type: t.enums.of(['cast.created']),
+ data: neynarWebhookCastCreatedDataValidator,
+ });

File Metadata

Mime Type
text/plain
Expires
Wed, Oct 23, 2:29 PM (15 h, 55 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2346781
Default Alt Text
D13754.id.diff (5 KB)

Event Timeline