From 9558e3bf848213bc75a58297d234d823b72a274a Mon Sep 17 00:00:00 2001 From: gitcommitshow Date: Fri, 1 Mar 2024 00:46:09 +0530 Subject: [PATCH] feat: add slack source --- src/v0/sources/slack/mapping.json | 10 +++++ src/v0/sources/slack/transform.js | 72 +++++++++++++++++++++++++++++++ src/v0/sources/slack/util.js | 15 +++++++ 3 files changed, 97 insertions(+) create mode 100644 src/v0/sources/slack/mapping.json create mode 100644 src/v0/sources/slack/transform.js create mode 100644 src/v0/sources/slack/util.js diff --git a/src/v0/sources/slack/mapping.json b/src/v0/sources/slack/mapping.json new file mode 100644 index 0000000000..c6c162c7c6 --- /dev/null +++ b/src/v0/sources/slack/mapping.json @@ -0,0 +1,10 @@ +[ + { + "sourceKeys": "ts", + "destKeys": ["timestamp", "originalTimestamp"] + }, + { + "sourceKeys": "type", + "destKeys": "event" + } +] diff --git a/src/v0/sources/slack/transform.js b/src/v0/sources/slack/transform.js new file mode 100644 index 0000000000..296c44d5f2 --- /dev/null +++ b/src/v0/sources/slack/transform.js @@ -0,0 +1,72 @@ +const sha256 = require('sha256'); +const { TransformationError } = require('@rudderstack/integrations-lib'); +const Message = require('../message'); +const { mapping, formEventName } = require('./util'); +const { generateUUID, removeUndefinedAndNullValues } = require('../../util'); +const { JSON_MIME_TYPE } = require('../../util/constant'); + +function processNormalEvent(slackPayload) { + const message = new Message(`SLACK`); + // we are setting event type as track always + message.setEventType('track'); + message.setEventName(formEventName(slackPayload.type)); + if (slackPayload.user) { + const stringifiedUserId = + typeof slackPayload.user === 'string' ? slackPayload.user : slackPayload.user.id; + message.setProperty( + 'anonymousId', + stringifiedUserId ? sha256(stringifiedUserId).toString().substring(0, 36) : generateUUID(), + ); + // setting the userId got from Monday into externalId + message.context.externalId = [ + { + type: 'slackUserId', + id: stringifiedUserId, + }, + ]; + } else { + throw new TransformationError('UserId not found'); + } + + message.setPropertiesV2(slackPayload, mapping); + /* deleting properties already mapped in + the payload's root */ + delete message.properties.triggerTime; + delete message.properties.userId; + return message; +} + +// the payload for the challenge event will be as follows: +// { +// challenge : "some_key" +// } +// this will be sent when the webhook is added to an item in monday. + +function isChallengeEvent(event) { + return !!event?.challenge; +} + +// sending challenge event object back to Monday +function processChallengeEvent(event) { + return { + outputToSource: { + body: Buffer.from(JSON.stringify(event)).toString('base64'), + contentType: JSON_MIME_TYPE, + }, + statusCode: 200, + }; +} + +// we will check here if the event is a challenge event or not +// and process accordingly. +// For challenge event the recieved challenge object is sent back +// to Monday to verify the webhook url. +// Ref: https://developer.monday.com/api-reference/docs/webhooks-1#how-to-verify-a-webhook-url +function process(event) { + const response = isChallengeEvent(event) + ? processChallengeEvent(event) + : processNormalEvent(event); + return removeUndefinedAndNullValues(response); +} + +exports.process = process; diff --git a/src/v0/sources/slack/util.js b/src/v0/sources/slack/util.js new file mode 100644 index 0000000000..45978d0a68 --- /dev/null +++ b/src/v0/sources/slack/util.js @@ -0,0 +1,15 @@ +/* eslint-disable no-restricted-syntax */ +const path = require('path'); +const fs = require('fs'); + +const mapping = JSON.parse(fs.readFileSync(path.resolve(__dirname, './mapping.json'), 'utf-8')); + +// turning underscore-seperated Monday events into Rudder format +function formEventName(evtName) { + return evtName + .split('_') + .map((s) => s.charAt(0).toUpperCase() + s.slice(1)) + .join(' '); +} + +module.exports = { mapping, formEventName };