Skip to content

Commit

Permalink
Merge pull request #4618 from kishanprmr/slack-react-message
Browse files Browse the repository at this point in the history
feat(slack): add reaction to message action
  • Loading branch information
abuaboud committed May 3, 2024
2 parents 24abbe1 + c7e0311 commit 92c6427
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 102 deletions.
66 changes: 66 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -68,6 +68,7 @@
"@sendgrid/mail": "8.0.0",
"@sentry/node": "7.64.0",
"@sinclair/typebox": "0.26.8",
"@slack/web-api": "7.0.4",
"@supabase/supabase-js": "2.33.1",
"@types/imapflow": "1.0.18",
"@types/showdown": "2.0.6",
Expand Down
2 changes: 1 addition & 1 deletion packages/pieces/community/slack/package.json
@@ -1,4 +1,4 @@
{
"name": "@activepieces/piece-slack",
"version": "0.5.7"
"version": "0.5.8"
}
198 changes: 98 additions & 100 deletions packages/pieces/community/slack/src/index.ts
@@ -1,9 +1,5 @@
import { createCustomApiCallAction } from '@activepieces/pieces-common';
import {
OAuth2PropertyValue,
PieceAuth,
createPiece,
} from '@activepieces/pieces-framework';
import { OAuth2PropertyValue, PieceAuth, createPiece } from '@activepieces/pieces-framework';
import { PieceCategory } from '@activepieces/shared';
import crypto from 'node:crypto';
import { requestActionDirectMessageAction } from './lib/actions/request-action-direct-message';
Expand All @@ -21,107 +17,109 @@ import { findUserByEmailAction } from './lib/actions/find-user-by-email';
import { updateProfileAction } from './lib/actions/update-profile';
import { createChannelAction } from './lib/actions/create-channel';
import { newChannelTrigger } from './lib/triggers/new-channel';
import { addRectionToMessageAction } from './lib/actions/add-reaction-to-message';

export const slackAuth = PieceAuth.OAuth2({
description: '',
authUrl:
'https://slack.com/oauth/v2/authorize?user_scope=search:read,users.profile:write',
tokenUrl: 'https://slack.com/api/oauth.v2.access',
required: true,
scope: [
'channels:read',
'channels:manage',
'channels:history',
'chat:write',
'groups:read',
'groups:write',
'reactions:read',
'mpim:read',
'mpim:write',
'im:write',
'users:read',
'files:write',
'files:read',
'users:read.email',
],
description: '',
authUrl: 'https://slack.com/oauth/v2/authorize?user_scope=search:read,users.profile:write',
tokenUrl: 'https://slack.com/api/oauth.v2.access',
required: true,
scope: [
'channels:read',
'channels:manage',
'channels:history',
'chat:write',
'groups:read',
'groups:write',
'reactions:read',
'mpim:read',
'mpim:write',
'im:write',
'users:read',
'files:write',
'files:read',
'users:read.email',
'reactions:write',
],
});

export const slack = createPiece({
displayName: 'Slack',
description: 'Channel-based messaging platform',
minimumSupportedRelease: '0.20.0',
logoUrl: 'https://cdn.activepieces.com/pieces/slack.png',
categories: [PieceCategory.COMMUNICATION],
auth: slackAuth,
events: {
parseAndReply: ({ payload }) => {
const payloadBody = payload.body as PayloadBody;
if (payloadBody.challenge) {
return {
reply: {
body: payloadBody['challenge'],
headers: {},
},
};
}
return {
event: payloadBody?.event?.type,
identifierValue: payloadBody.team_id,
};
},
verify: ({ webhookSecret, payload }) => {
// Construct the signature base string
const timestamp = payload.headers['x-slack-request-timestamp'];
const signature = payload.headers['x-slack-signature'];
const signatureBaseString = `v0:${timestamp}:${payload.rawBody}`;
const hmac = crypto.createHmac('sha256', webhookSecret);
hmac.update(signatureBaseString);
const computedSignature = `v0=${hmac.digest('hex')}`;
return signature === computedSignature;
},
},
authors: [
'rita-gorokhod',
'AdamSelene',
'Abdallah-Alwarawreh',
'kishanprmr',
'MoShizzle',
'AbdulTheActivePiecer',
'khaledmashaly',
'abuaboud',
],
actions: [
slackSendDirectMessageAction,
slackSendMessageAction,
requestApprovalDirectMessageAction,
requestSendApprovalMessageAction,
requestActionDirectMessageAction,
requestActionMessageAction,
uploadFile,
searchMessages,
findUserByEmailAction,
updateMessage,
createChannelAction,
updateProfileAction,
createCustomApiCallAction({
baseUrl: () => {
return 'https://slack.com/api';
},
auth: slackAuth,
authMapping: (auth) => {
return {
Authorization: `Bearer ${(auth as OAuth2PropertyValue).access_token}`,
};
},
}),
],
triggers: [newMessage, newReactionAdded, newChannelTrigger],
displayName: 'Slack',
description: 'Channel-based messaging platform',
minimumSupportedRelease: '0.20.0',
logoUrl: 'https://cdn.activepieces.com/pieces/slack.png',
categories: [PieceCategory.COMMUNICATION],
auth: slackAuth,
events: {
parseAndReply: ({ payload }) => {
const payloadBody = payload.body as PayloadBody;
if (payloadBody.challenge) {
return {
reply: {
body: payloadBody['challenge'],
headers: {},
},
};
}
return {
event: payloadBody?.event?.type,
identifierValue: payloadBody.team_id,
};
},
verify: ({ webhookSecret, payload }) => {
// Construct the signature base string
const timestamp = payload.headers['x-slack-request-timestamp'];
const signature = payload.headers['x-slack-signature'];
const signatureBaseString = `v0:${timestamp}:${payload.rawBody}`;
const hmac = crypto.createHmac('sha256', webhookSecret);
hmac.update(signatureBaseString);
const computedSignature = `v0=${hmac.digest('hex')}`;
return signature === computedSignature;
},
},
authors: [
'rita-gorokhod',
'AdamSelene',
'Abdallah-Alwarawreh',
'kishanprmr',
'MoShizzle',
'AbdulTheActivePiecer',
'khaledmashaly',
'abuaboud',
],
actions: [
addRectionToMessageAction,
slackSendDirectMessageAction,
slackSendMessageAction,
requestApprovalDirectMessageAction,
requestSendApprovalMessageAction,
requestActionDirectMessageAction,
requestActionMessageAction,
uploadFile,
searchMessages,
findUserByEmailAction,
updateMessage,
createChannelAction,
updateProfileAction,
createCustomApiCallAction({
baseUrl: () => {
return 'https://slack.com/api';
},
auth: slackAuth,
authMapping: (auth) => {
return {
Authorization: `Bearer ${(auth as OAuth2PropertyValue).access_token}`,
};
},
}),
],
triggers: [newMessage, newReactionAdded, newChannelTrigger],
});

type PayloadBody = {
challenge: string;
event: {
type: string;
};
team_id: string;
challenge: string;
event: {
type: string;
};
team_id: string;
};
@@ -0,0 +1,42 @@
import { slackAuth } from '../../';
import { createAction, Property } from '@activepieces/pieces-framework';
import { slackChannel, slackInfo } from '../common/props';

import { WebClient } from '@slack/web-api';

export const addRectionToMessageAction = createAction({
auth: slackAuth,
name: 'slack-add-reaction-to-message',
displayName: 'Add Reaction to Message',
description: 'Add an emoji reaction to a message.',

props: {
info: slackInfo,
channel: slackChannel,
ts: Property.ShortText({
displayName: 'Message ts',
description:
'Provide the ts (timestamp) value of the message to update, e.g. `1710304378.475129`.',
required: true,
}),
reaction: Property.ShortText({
displayName: 'Reaction (emoji) name',
required: true,
description: 'e.g.`thumbsup`',
}),
},

async run(context) {
const { channel, ts, reaction } = context.propsValue;

const slack = new WebClient(context.auth.access_token);

const response = await slack.reactions.add({
channel,
timestamp: ts,
name: reaction,
});

return response;
},
});
Expand Up @@ -242,8 +242,9 @@ describe('Platform API', () => {
expect(response?.statusCode).toBe(StatusCodes.OK)
const responseBody = response?.json()

expect(Object.keys(responseBody)).toHaveLength(4)
expect(Object.keys(responseBody)).toHaveLength(5)
expect(responseBody.id).toBe(mockPlatform.id)
expect(responseBody.gitSyncEnabled).toBeDefined()
expect(responseBody.name).toBe(mockPlatform.name)
expect(responseBody.defaultLocale).toBe(mockPlatform.defaultLocale)
expect(responseBody.projectRolesEnabled).toBe(mockPlatform.projectRolesEnabled)
Expand Down

0 comments on commit 92c6427

Please sign in to comment.