From 34dfe6b823632454a72a6269b62fb6ea5190c850 Mon Sep 17 00:00:00 2001 From: Manoj K Date: Thu, 24 Jul 2025 23:18:28 +0530 Subject: [PATCH] Fix: integration account handling and improve webhook event processing --- .../app/routes/api.v1.integration_account.tsx | 4 +-- .../webapp/app/routes/webhook.$sourceName.tsx | 30 ++++++++++--------- .../webapp/app/services/oauth/oauth.server.ts | 4 +-- apps/webapp/app/services/webhook.server.ts | 6 ---- .../trigger/integrations/integration-run.ts | 1 + integrations/slack/package.json | 2 +- integrations/slack/pnpm-lock.yaml | 10 +++---- integrations/slack/src/create-activity.ts | 16 +++++----- integrations/slack/src/index.ts | 11 +++++-- 9 files changed, 44 insertions(+), 40 deletions(-) diff --git a/apps/webapp/app/routes/api.v1.integration_account.tsx b/apps/webapp/app/routes/api.v1.integration_account.tsx index 529f856..396cc93 100644 --- a/apps/webapp/app/routes/api.v1.integration_account.tsx +++ b/apps/webapp/app/routes/api.v1.integration_account.tsx @@ -56,7 +56,7 @@ const { action, loader } = createHybridActionApiRoute( workspace?.id, ); - if (!setupResult || !setupResult.accountId) { + if (!setupResult.account || !setupResult.account.id) { return json( { error: "Failed to setup integration with the provided API key" }, { status: 400 }, @@ -64,7 +64,7 @@ const { action, loader } = createHybridActionApiRoute( } await tasks.trigger("scheduler", { - integrationAccountId: setupResult?.id, + integrationAccountId: setupResult?.account?.id, }); return json({ success: true, setupResult }); diff --git a/apps/webapp/app/routes/webhook.$sourceName.tsx b/apps/webapp/app/routes/webhook.$sourceName.tsx index 117c052..2beb296 100644 --- a/apps/webapp/app/routes/webhook.$sourceName.tsx +++ b/apps/webapp/app/routes/webhook.$sourceName.tsx @@ -34,19 +34,20 @@ export async function action({ request, params }: ActionFunctionArgs) { eventBody: typeof eventBody === 'object' ? JSON.stringify(eventBody).substring(0, 200) : eventBody, }); - const result = await webhookService.handleEvents( + // Check if the event is a URL verification challenge (Slack) + if (eventBody.type === "url_verification") { + logger.log("Responding to Slack URL verification challenge"); + return json({ challenge: eventBody.challenge }); + } + + await webhookService.handleEvents( sourceName, integrationAccountId, eventHeaders, eventBody ); - // Handle URL verification challenge (returns different response) - if (result.challenge) { - return json({ challenge: result.challenge }); - } - - return json({ status: result.status }); + return json({ status: 'acknowledged' }, { status: 200 }); } catch (error) { logger.error('Webhook processing failed', { error, params }); @@ -77,19 +78,20 @@ export async function loader({ request, params }: LoaderFunctionArgs) { eventBody: JSON.stringify(eventBody).substring(0, 200), }); - const result = await webhookService.handleEvents( + // Check if the event is a URL verification challenge (Slack) + if (eventBody.type === "url_verification") { + logger.log("Responding to Slack URL verification challenge"); + return json({ challenge: eventBody.challenge }); + } + + await webhookService.handleEvents( sourceName, integrationAccountId, eventHeaders, eventBody ); - // Handle URL verification challenge (returns different response) - if (result.challenge) { - return json({ challenge: result.challenge }); - } - - return json({ status: result.status }); + return json({ status: 'acknowledged' }, { status: 200 }); } catch (error) { logger.error('Webhook GET processing failed', { error, params }); diff --git a/apps/webapp/app/services/oauth/oauth.server.ts b/apps/webapp/app/services/oauth/oauth.server.ts index 0980729..d109417 100644 --- a/apps/webapp/app/services/oauth/oauth.server.ts +++ b/apps/webapp/app/services/oauth/oauth.server.ts @@ -127,7 +127,7 @@ export async function callbackHandler(params: CallbackParams) { }, ); - const integrationAccount = await runIntegrationTrigger( + const setupResult = await runIntegrationTrigger( integrationDefinition, { event: IntegrationEventType.SETUP, @@ -144,7 +144,7 @@ export async function callbackHandler(params: CallbackParams) { ); await tasks.trigger("scheduler", { - integrationAccountId: integrationAccount?.id, + integrationAccountId: setupResult?.account?.id, }); return new Response(null, { diff --git a/apps/webapp/app/services/webhook.server.ts b/apps/webapp/app/services/webhook.server.ts index 7bee9e6..3151f46 100644 --- a/apps/webapp/app/services/webhook.server.ts +++ b/apps/webapp/app/services/webhook.server.ts @@ -21,12 +21,6 @@ export class WebhookService { where: "WebhookService.handleEvents", }); - // Check if the event is a URL verification challenge (Slack) - if (eventBody.type === "url_verification") { - logger.log("Responding to Slack URL verification challenge"); - return { challenge: eventBody.challenge, status: "verified" }; - } - let integrationAccount: | (IntegrationAccount & { integrationDefinition: IntegrationDefinitionV2; diff --git a/apps/webapp/app/trigger/integrations/integration-run.ts b/apps/webapp/app/trigger/integrations/integration-run.ts index 2fc9b10..d8d0e6e 100644 --- a/apps/webapp/app/trigger/integrations/integration-run.ts +++ b/apps/webapp/app/trigger/integrations/integration-run.ts @@ -343,6 +343,7 @@ async function handleMessageResponse( responses.account = account; } + const unhandled: Message[] = []; // Warn for unknown message types for (const type of Object.keys(grouped)) { if (!["activity", "state", "identifier", "account"].includes(type)) { diff --git a/integrations/slack/package.json b/integrations/slack/package.json index ed10e0e..ee6184c 100644 --- a/integrations/slack/package.json +++ b/integrations/slack/package.json @@ -58,6 +58,6 @@ "commander": "^12.0.0", "openai": "^4.0.0", "react-query": "^3.39.3", - "@redplanethq/sdk": "0.1.1" + "@redplanethq/sdk": "0.1.2" } } diff --git a/integrations/slack/pnpm-lock.yaml b/integrations/slack/pnpm-lock.yaml index 0e1b352..8b09636 100644 --- a/integrations/slack/pnpm-lock.yaml +++ b/integrations/slack/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@redplanethq/sdk': - specifier: 0.1.1 - version: 0.1.1 + specifier: 0.1.2 + version: 0.1.2 axios: specifier: ^1.7.9 version: 1.9.0 @@ -465,8 +465,8 @@ packages: resolution: {integrity: sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@redplanethq/sdk@0.1.1': - resolution: {integrity: sha512-tfR1c9p7vNeCL5jsF9QlEZcRFLsihaHe/ZQWVKZYXzAZ6GugoIFBaayGfVvjNjyEnN3nlrl3usKBX+hhaKzg0g==} + '@redplanethq/sdk@0.1.2': + resolution: {integrity: sha512-Si+ae2OV0UNy7yvLECjJ1Y/6HHhRO0yU9svIFvBzMlaR/57SDP+KJZLyfWx/PJX+hOuWipyoYTLA9aYULt6z2w==} engines: {node: '>=18.0.0'} '@rollup/rollup-android-arm-eabi@4.40.2': @@ -2683,7 +2683,7 @@ snapshots: '@pkgr/core@0.2.4': {} - '@redplanethq/sdk@0.1.1': + '@redplanethq/sdk@0.1.2': dependencies: commander: 14.0.0 diff --git a/integrations/slack/src/create-activity.ts b/integrations/slack/src/create-activity.ts index d6d2698..fd2bbe6 100644 --- a/integrations/slack/src/create-activity.ts +++ b/integrations/slack/src/create-activity.ts @@ -52,11 +52,10 @@ async function getConversationInfo(accessToken: string, channel: string) { export const createActivityEvent = async ( // eslint-disable-next-line @typescript-eslint/no-explicit-any - eventBody: any, + eventData: any, config: any, ) => { - const { eventData } = eventBody; - if (eventData.event.type === 'message' && eventData.event.channel === 'D06UAK42494') { + if (eventData.event.type === 'message' && eventData.event.channel === 'D08TQATE3F0') { const event = eventData.event; if (!config) { @@ -65,7 +64,7 @@ export const createActivityEvent = async ( const accessToken = config.access_token; - const text = `DM with SOL channel Content: '${event.text}'`; + const text = `I DMed to you Content: '${event.text}'`; const permalinkResponse = await axios.get( `https://slack.com/api/chat.getPermalink?channel=${event.channel}&message_ts=${event.ts}`, @@ -81,7 +80,7 @@ export const createActivityEvent = async ( taskId: null, }; - return createActivityMessage(activity); + return [createActivityMessage(activity)]; } if (eventData.event.type === 'reaction_added' && eventData.event.reaction === 'eyes') { @@ -121,7 +120,7 @@ export const createActivityEvent = async ( conversationContext = `channel ${conversationInfo.name}(${conversationInfo.id})`; } - const text = `Message to User from ${userIdMap.get(eventMessage.user)?.real_name}(${eventMessage.user}) in ${conversationContext} at ${eventMessage.ts}. Content: '${eventMessageText}'`; + const text = `User ${userIdMap.get(eventMessage.user)?.real_name}(${eventMessage.user}) reacted with eyes emoji in ${conversationContext} at ${eventMessage.ts}. Content: '${eventMessageText}'`; const permalinkResponse = await axios.get( `https://slack.com/api/chat.getPermalink?channel=${channel}&message_ts=${ts}`, @@ -137,9 +136,10 @@ export const createActivityEvent = async ( integrationAccountId: config.integrationAccountId, }; - return createActivityMessage(activity); + return [createActivityMessage(activity)]; } - return { message: `Processed activity from slack` }; + + return []; }; function getMentionUsers(message: string): string[] { diff --git a/integrations/slack/src/index.ts b/integrations/slack/src/index.ts index 3f421fc..990d262 100644 --- a/integrations/slack/src/index.ts +++ b/integrations/slack/src/index.ts @@ -13,13 +13,20 @@ export async function run(eventPayload: IntegrationEventPayload) { return await integrationCreate(eventPayload.eventBody); case IntegrationEventType.IDENTIFY: - return eventPayload.eventBody.event.user; + return [ + { + type: 'identifier', + data: + eventPayload.eventBody.event.event.user || + eventPayload.eventBody.event.event.message.user, + }, + ]; case IntegrationEventType.PROCESS: return createActivityEvent(eventPayload.eventBody.eventData, eventPayload.config); default: - return { message: `The event payload type is ${eventPayload.event}` }; + return [{ type: 'error', data: `The event payload type is ${eventPayload.event}` }]; } }