@pipedream/slack_v2 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/LICENSE +41 -0
  2. package/actions/add-emoji-reaction/add-emoji-reaction.mjs +48 -0
  3. package/actions/approve-workflow/approve-workflow.mjs +92 -0
  4. package/actions/archive-channel/archive-channel.mjs +38 -0
  5. package/actions/common/build-blocks.mjs +182 -0
  6. package/actions/common/send-message.mjs +264 -0
  7. package/actions/create-channel/create-channel.mjs +40 -0
  8. package/actions/create-reminder/create-reminder.mjs +52 -0
  9. package/actions/delete-file/delete-file.mjs +39 -0
  10. package/actions/delete-message/delete-message.mjs +45 -0
  11. package/actions/find-message/find-message.mjs +83 -0
  12. package/actions/find-user-by-email/find-user-by-email.mjs +32 -0
  13. package/actions/get-current-user/get-current-user.mjs +68 -0
  14. package/actions/get-file/get-file.mjs +59 -0
  15. package/actions/invite-user-to-channel/invite-user-to-channel.mjs +45 -0
  16. package/actions/kick-user/kick-user.mjs +56 -0
  17. package/actions/list-channels/list-channels.mjs +52 -0
  18. package/actions/list-files/list-files.mjs +93 -0
  19. package/actions/list-group-members/list-group-members.mjs +68 -0
  20. package/actions/list-members-in-channel/list-members-in-channel.mjs +71 -0
  21. package/actions/list-replies/list-replies.mjs +74 -0
  22. package/actions/list-users/list-users.mjs +60 -0
  23. package/actions/reply-to-a-message/reply-to-a-message.mjs +54 -0
  24. package/actions/send-block-kit-message/send-block-kit-message.mjs +48 -0
  25. package/actions/send-large-message/send-large-message.mjs +95 -0
  26. package/actions/send-message/send-message.mjs +56 -0
  27. package/actions/send-message-advanced/send-message-advanced.mjs +75 -0
  28. package/actions/send-message-to-channel/send-message-to-channel.mjs +45 -0
  29. package/actions/send-message-to-user-or-group/send-message-to-user-or-group.mjs +93 -0
  30. package/actions/set-channel-description/set-channel-description.mjs +37 -0
  31. package/actions/set-channel-topic/set-channel-topic.mjs +37 -0
  32. package/actions/set-status/set-status.mjs +49 -0
  33. package/actions/update-group-members/update-group-members.mjs +72 -0
  34. package/actions/update-message/update-message.mjs +59 -0
  35. package/actions/update-profile/update-profile.mjs +94 -0
  36. package/actions/upload-file/upload-file.mjs +104 -0
  37. package/common/constants.mjs +31 -0
  38. package/package.json +22 -0
  39. package/slack_v2.app.mjs +1112 -0
  40. package/sources/common/base.mjs +184 -0
  41. package/sources/common/constants.mjs +58 -0
  42. package/sources/new-channel-created/new-channel-created.mjs +32 -0
  43. package/sources/new-channel-created/test-event.mjs +44 -0
  44. package/sources/new-interaction-event-received/README.md +85 -0
  45. package/sources/new-interaction-event-received/new-interaction-event-received.mjs +105 -0
  46. package/sources/new-interaction-event-received/test-event.mjs +86 -0
  47. package/sources/new-keyword-mention/new-keyword-mention.mjs +99 -0
  48. package/sources/new-keyword-mention/test-event.mjs +28 -0
  49. package/sources/new-message-in-channels/new-message-in-channels.mjs +106 -0
  50. package/sources/new-message-in-channels/test-event.mjs +45 -0
  51. package/sources/new-reaction-added/new-reaction-added.mjs +119 -0
  52. package/sources/new-reaction-added/test-event.mjs +193 -0
  53. package/sources/new-saved-message/new-saved-message.mjs +32 -0
  54. package/sources/new-saved-message/test-event.mjs +37 -0
  55. package/sources/new-user-added/new-user-added.mjs +32 -0
  56. package/sources/new-user-added/test-event.mjs +48 -0
  57. package/sources/new-user-mention/new-user-mention.mjs +124 -0
  58. package/sources/new-user-mention/test-event.mjs +28 -0
@@ -0,0 +1,184 @@
1
+ import slack from "../../slack_v2.app.mjs";
2
+ import {
3
+ NAME_CACHE_MAX_SIZE, NAME_CACHE_TIMEOUT,
4
+ } from "./constants.mjs";
5
+
6
+ export default {
7
+ props: {
8
+ slack,
9
+ db: "$.service.db",
10
+ },
11
+ methods: {
12
+ _getNameCache() {
13
+ return this.db.get("nameCache") ?? {};
14
+ },
15
+ _setNameCache(cacheObj) {
16
+ this.db.set("nameCache", cacheObj);
17
+ },
18
+ _getLastCacheCleanup() {
19
+ return this.db.get("lastCacheCleanup") ?? 0;
20
+ },
21
+ _setLastCacheCleanup(time) {
22
+ this.db.set("lastCacheCleanup", time);
23
+ },
24
+ cleanCache(cacheObj) {
25
+ console.log("Initiating cache check-up...");
26
+ const timeout = Date.now() - NAME_CACHE_TIMEOUT;
27
+
28
+ const entries = Object.entries(cacheObj);
29
+ let cleanArr = entries.filter(
30
+ ([
31
+ , { ts },
32
+ ]) => ts > timeout,
33
+ );
34
+ const diff = entries.length - cleanArr.length;
35
+ if (diff) {
36
+ console.log(`Cleaned up ${diff} outdated cache entries.`);
37
+ }
38
+
39
+ if (cleanArr.length > NAME_CACHE_MAX_SIZE) {
40
+ console.log(`Reduced the cache from ${cleanArr.length} to ${NAME_CACHE_MAX_SIZE / 2} entries.`);
41
+ cleanArr = cleanArr.slice(NAME_CACHE_MAX_SIZE / -2);
42
+ }
43
+
44
+ const cleanObj = Object.fromEntries(cleanArr);
45
+ return cleanObj;
46
+ },
47
+ getCache() {
48
+ let cacheObj = this._getNameCache();
49
+
50
+ const lastCacheCleanup = this._getLastCacheCleanup();
51
+ const time = Date.now();
52
+
53
+ const shouldCleanCache = time - lastCacheCleanup > NAME_CACHE_TIMEOUT / 2;
54
+ if (shouldCleanCache) {
55
+ cacheObj = this.cleanCache(cacheObj);
56
+ this._setLastCacheCleanup(time);
57
+ }
58
+
59
+ return [
60
+ cacheObj,
61
+ shouldCleanCache,
62
+ ];
63
+ },
64
+ async maybeCached(key, refreshVal) {
65
+ let [
66
+ cacheObj,
67
+ wasUpdated,
68
+ ] = this.getCache();
69
+ let record = cacheObj[key];
70
+ const time = Date.now();
71
+ if (!record || time - record.ts > NAME_CACHE_TIMEOUT) {
72
+ record = {
73
+ ts: time,
74
+ val: await refreshVal(),
75
+ };
76
+ cacheObj[key] = record;
77
+ wasUpdated = true;
78
+ }
79
+
80
+ if (wasUpdated) {
81
+ this._setNameCache(cacheObj);
82
+ }
83
+
84
+ return record.val;
85
+ },
86
+ async getUserName(id) {
87
+ return this.maybeCached(`users:${id}`, async () => {
88
+ const info = await this.slack.usersInfo({
89
+ user: id,
90
+ });
91
+ if (!info.ok) throw new Error(info.error);
92
+ return info.user.name;
93
+ });
94
+ },
95
+ async getRealName(id) {
96
+ return this.maybeCached(`users_real_names:${id}`, async () => {
97
+ const info = await this.slack.usersInfo({
98
+ user: id,
99
+ });
100
+ if (!info.ok) throw new Error(info.error);
101
+ return info.user.real_name;
102
+ });
103
+ },
104
+ async getBotName(id) {
105
+ return this.maybeCached(`bots:${id}`, async () => {
106
+ const info = await this.slack.getBotInfo({
107
+ bot: id,
108
+ });
109
+ if (!info.ok) throw new Error(info.error);
110
+ return info.bot.name;
111
+ });
112
+ },
113
+ async getConversationName(id) {
114
+ return this.maybeCached(`conversations:${id}`, async () => {
115
+ const info = await this.slack.conversationsInfo({
116
+ channel: id,
117
+ });
118
+ if (!info.ok) throw new Error(info.error);
119
+ if (info.channel.is_im) {
120
+ return `DM with ${await this.getUserName(info.channel.user)}`;
121
+ }
122
+ return info.channel.name;
123
+ });
124
+ },
125
+ async getTeamName(id) {
126
+ return this.maybeCached(`team:${id}`, async () => {
127
+ try {
128
+ const info = await this.slack.getTeamInfo({
129
+ team: id,
130
+ });
131
+ return info.team.name;
132
+ } catch (err) {
133
+ console.log(
134
+ "Error getting team name, probably need to re-connect the account at pipedream.com/apps",
135
+ err,
136
+ );
137
+ return id;
138
+ }
139
+ });
140
+ },
141
+ async getMessage({
142
+ channel, event_ts: ts,
143
+ }) {
144
+ return await this.maybeCached(
145
+ `lastMessage:${channel}:${ts}`,
146
+ async () => {
147
+ const response = await this.slack.getConversationReplies({
148
+ channel,
149
+ ts,
150
+ limit: 1,
151
+ });
152
+
153
+ if (response.messages.length) {
154
+ response.messages = [
155
+ response.messages[0],
156
+ ];
157
+ }
158
+
159
+ return response;
160
+ },
161
+ );
162
+ },
163
+ processEvent(event) {
164
+ return event;
165
+ },
166
+ },
167
+ async run(event) {
168
+ event = await this.processEvent(event);
169
+
170
+ if (event) {
171
+ if (!event.client_msg_id) {
172
+ event.pipedream_msg_id = `pd_${Date.now()}_${Math.random()
173
+ .toString(36)
174
+ .substr(2, 10)}`;
175
+ }
176
+
177
+ this.$emit(event, {
178
+ id: event.client_msg_id || event.pipedream_msg_id || event.channel.id,
179
+ summary: this.getSummary(event),
180
+ ts: event.event_ts || Date.now(),
181
+ });
182
+ }
183
+ },
184
+ };
@@ -0,0 +1,58 @@
1
+ const events = {
2
+ im: "User",
3
+ message: "Message",
4
+ file: "File",
5
+ channel: "Channel",
6
+ };
7
+
8
+ const eventsOptions = [
9
+ {
10
+ label: "User",
11
+ value: "im",
12
+ },
13
+ {
14
+ label: "Message",
15
+ value: "message",
16
+ },
17
+ {
18
+ label: "File",
19
+ value: "file",
20
+ },
21
+ {
22
+ label: "Channel",
23
+ value: "channel",
24
+ },
25
+ ];
26
+
27
+ const SUBTYPE = {
28
+ NULL: null,
29
+ BOT_MESSAGE: "bot_message",
30
+ FILE_SHARE: "file_share",
31
+ PD_HISTORY_MESSAGE: "pd_history_message",
32
+ MESSAGE_REPLIED: "message_replied",
33
+ };
34
+
35
+ const ALLOWED_SUBTYPES = [
36
+ SUBTYPE.NULL,
37
+ SUBTYPE.BOT_MESSAGE,
38
+ SUBTYPE.FILE_SHARE,
39
+ SUBTYPE.PD_HISTORY_MESSAGE,
40
+ ];
41
+
42
+ const ALLOWED_MESSAGE_IN_CHANNEL_SUBTYPES = [
43
+ SUBTYPE.NULL,
44
+ SUBTYPE.BOT_MESSAGE,
45
+ SUBTYPE.FILE_SHARE,
46
+ SUBTYPE.MESSAGE_REPLIED,
47
+ ];
48
+
49
+ export const NAME_CACHE_MAX_SIZE = 1000;
50
+ export const NAME_CACHE_TIMEOUT = 3600000;
51
+
52
+ export default {
53
+ events,
54
+ eventsOptions,
55
+ SUBTYPE,
56
+ ALLOWED_SUBTYPES,
57
+ ALLOWED_MESSAGE_IN_CHANNEL_SUBTYPES,
58
+ };
@@ -0,0 +1,32 @@
1
+ import common from "../common/base.mjs";
2
+ import sampleEmit from "./test-event.mjs";
3
+
4
+ export default {
5
+ ...common,
6
+ key: "slack_v2-new-channel-created",
7
+ name: "New Channel Created (Instant)",
8
+ version: "0.0.11",
9
+ description: "Emit new event when a new channel is created.",
10
+ type: "source",
11
+ dedupe: "unique",
12
+ props: {
13
+ ...common.props,
14
+ // eslint-disable-next-line pipedream/props-description,pipedream/props-label
15
+ slackApphook: {
16
+ type: "$.interface.apphook",
17
+ appProp: "slack",
18
+ async eventNames() {
19
+ return [
20
+ "channel_created",
21
+ ];
22
+ },
23
+ },
24
+ },
25
+ methods: {
26
+ ...common.methods,
27
+ getSummary({ channel: { name } }) {
28
+ return `New channel created - ${name}`;
29
+ },
30
+ },
31
+ sampleEmit,
32
+ };
@@ -0,0 +1,44 @@
1
+ export default {
2
+ "type": "channel_created",
3
+ "channel": {
4
+ "id": "C024BE91L",
5
+ "name": "fun",
6
+ "is_channel": true,
7
+ "is_group": false,
8
+ "is_im": false,
9
+ "is_mpim": false,
10
+ "is_private": false,
11
+ "created": 1360782804,
12
+ "is_archived": false,
13
+ "is_general": false,
14
+ "unlinked": 0,
15
+ "name_normalized": "fun",
16
+ "is_shared": false,
17
+ "is_frozen": false,
18
+ "is_org_shared": false,
19
+ "is_pending_ext_shared": false,
20
+ "pending_shared": [],
21
+ "context_team_id": "TLZ203R5",
22
+ "updated": 1714140253251,
23
+ "parent_conversation": null,
24
+ "creator": "U024BE7LH",
25
+ "is_ext_shared": false,
26
+ "shared_team_ids": [
27
+ "TLZ203R5"
28
+ ],
29
+ "pending_connected_team_ids": [],
30
+ "topic": {
31
+ "value": "",
32
+ "creator": "",
33
+ "last_set": 0
34
+ },
35
+ "purpose": {
36
+ "value": "",
37
+ "creator": "",
38
+ "last_set": 0
39
+ },
40
+ "previous_names": []
41
+ },
42
+ "event_ts": "1714140253.002700",
43
+ "pipedream_msg_id": "pd_1714140255038_bkbl3pxpkp"
44
+ }
@@ -0,0 +1,85 @@
1
+ # Overview
2
+
3
+ Slack messages can contain interactive elements like buttons, dropdowns, radio buttons, and more. This source subscribes to interactive events, like when a button is clicked in a message.
4
+
5
+ ![Example of a Slack button](https://res.cloudinary.com/pipedreamin/image/upload/v1668443788/docs/components/CleanShot_2022-11-10_at_10.17.172x_dxdz1o.png)
6
+
7
+ Then this source will be triggered when you or another Slack user in your workspace clicks a button, selects an option or fills out a form.
8
+
9
+ ![Example feed of interaction events coming from Slack](https://res.cloudinary.com/pipedreamin/image/upload/v1668443818/docs/components/CleanShot_2022-11-10_at_10.19.152x_eyiims.png)
10
+
11
+ With this trigger, you can build workflows that perform some work with other APIs or services, and then reply back to the original message.
12
+
13
+ # Getting Started
14
+
15
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/RZ3XQENkjeg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
16
+
17
+ Watch this short video to learn how to use this in a workflow, or follow the guide below.
18
+
19
+ First, if you haven’t already - send yourself a message containing one or more interactive elements. Use the ******************Sending the message with an interactive element****************** guide below to send a message containing a button.
20
+
21
+ If you have already sent a message containing an element, skip to **********************************************Configuring the source.**********************************************
22
+
23
+ ## Sending the message with an interactive element
24
+
25
+ The easiest way is to send yourself a message using the ****************************Slack - Send Message Using Block Kit**************************** action:
26
+
27
+ ![Selecting the Send Slack Message with Block Kit](https://res.cloudinary.com/pipedreamin/image/upload/v1668443844/docs/components/CleanShot_2022-11-10_at_10.25.522x_vxiooo.png)
28
+
29
+ Then select a **************Channel************** you’d like to send the message to, and use the **************[Block Kit Builder](https://app.slack.com/block-kit-builder/)************** to build a message, or just copy the example button blocks below:
30
+
31
+ ```jsx
32
+ [
33
+ {
34
+ "type": "actions",
35
+ "elements": [
36
+ {
37
+ "type": "button",
38
+ "text": {
39
+ "type": "plain_text",
40
+ "text": "Click Me",
41
+ "emoji": true
42
+ },
43
+ "value": "click_me_123",
44
+ "action_id": "button_click"
45
+ }
46
+ ]
47
+ }
48
+ ]
49
+ ```
50
+
51
+ Your ******************Slack - Send Message Using Block Kit****************** should look like this:
52
+
53
+ ![Setting up the block kit message with a button block](https://res.cloudinary.com/pipedreamin/image/upload/v1668443887/docs/components/CleanShot_2022-11-10_at_10.29.552x_kvfznm.png)
54
+
55
+ ## Configuring the source
56
+
57
+ By default, this source will listen to ******all****** interactive events from your Slack workspace that your connected Slack account has authorization to view. Please note that only messages created via [Slack - Send Block Kit Message](https://pipedream.com/apps/slack-v2/actions/send-block-kit-message) Action, or via API call from the Pipedream app will emit an interaction event with this trigger. Block kit messages sent directly via the Slack's block kit builder will not trigger an interaction event.
58
+
59
+ You can filter these events by selecting a specific **************channel************** and/or a specific **********action_id.**********
60
+
61
+ ### Filtering interactive events by channel
62
+
63
+ Use the ****************Channels**************** dropdown to search for a specific channel for this source to subscribe to. ********Only******** button clicks, dropdown selects, etc. *in this selected channel* will trigger the source.
64
+
65
+ ### Filtering interactive events by `action_id`
66
+
67
+ For more specificity, you can filter based on the passed `action_id` to the message.
68
+
69
+ The `action_id` is arbitrary. It’s defined on the initial message sending the button, dropdown, or other interactive element’s markup.
70
+
71
+ For example, in the section above using the Block Kit to create a message, we defined the button’s `action_id` as `"button_click"`. But you can choose whichever naming convention you’d like.
72
+
73
+ If you pass `button_click` as a required `action_id` to this source, then only interactivity events with the `action_id` of `"button_click"` will trigger this source.
74
+
75
+ ## Troubleshooting
76
+
77
+ ### I’m clicking buttons, but no events are being received
78
+
79
+ Follow these steps to make sure your source is configured correctly:
80
+
81
+ 1. Make sure that your `action_id` or ****************channels**************** filters apply to that message, remove the filters to make sure that’s not the case.
82
+
83
+ 1. Make sure that the message comes from the same Slack account that this source is configured with.
84
+
85
+ 1. Make sure that the message was sent via Pipedream action (e.g. [Slack - Send Block Kit Message](https://pipedream.com/apps/slack-v2/actions/send-block-kit-message) Action) or via API call from the Pipedream app.
@@ -0,0 +1,105 @@
1
+ import common from "../common/base.mjs";
2
+ import sampleEmit from "./test-event.mjs";
3
+
4
+ export default {
5
+ name: "New Interaction Events (Instant)",
6
+ version: "0.0.21",
7
+ key: "slack_v2-new-interaction-event-received",
8
+ description: "Emit new events on new Slack [interactivity events](https://api.slack.com/interactivity) sourced from [Block Kit interactive elements](https://api.slack.com/interactivity/components), [Slash commands](https://api.slack.com/interactivity/slash-commands), or [Shortcuts](https://api.slack.com/interactivity/shortcuts).",
9
+ type: "source",
10
+ props: {
11
+ ...common.props,
12
+ alert: {
13
+ type: "alert",
14
+ alertType: "info",
15
+ content: "Please note that only messages created via Pipedream's [Send Block Kit Message](https://pipedream.com/apps/slack/actions/send-block-kit-message) Action, or via API call from the Pipedream app will emit an interaction event with this trigger. \n\nBlock kit messages sent directly via the Slack's block kit builder will not trigger an interaction event. \n\nSee the [documentation](https://pipedream.com/apps/slack/triggers/new-interaction-event-received) for more details.",
16
+ },
17
+ action_ids: {
18
+ type: "string[]",
19
+ label: "Action IDs",
20
+ description: "Filter interaction events by specific `action_id`'s to subscribe for new interaction events. If none are specified, all `action_ids` created via Pipedream will emit new events.",
21
+ optional: true,
22
+ default: [],
23
+ },
24
+ conversations: {
25
+ propDefinition: [
26
+ common.props.slack,
27
+ "conversation",
28
+ ],
29
+ type: "string[]",
30
+ label: "Channels",
31
+ description: "Filter interaction events by one or more channels. If none selected, any interaction event in any channel will emit new events.",
32
+ optional: true,
33
+ default: [],
34
+ },
35
+ // eslint-disable-next-line pipedream/props-description,pipedream/props-label
36
+ slackApphook: {
37
+ type: "$.interface.apphook",
38
+ appProp: "slack",
39
+ /**
40
+ * Subscribes to potentially 4 different events:
41
+ * `interaction_events` - all interaction events on the authenticated account
42
+ * `interaction_events:${action_id}` - all interaction events with a specific given action_id
43
+ * `interaction_events:${channel_id}` - all interaction events within a specific channel
44
+ * `interaction_events:${channel_id}:${action_id}` - action_id within a specific channel
45
+ * @returns string[]
46
+ */
47
+ async eventNames() {
48
+ // start with action_ids, since they can be the most specific
49
+ const action_events = this.action_ids.reduce((carry, action_id) => {
50
+ // if channels are provided, spread them
51
+ if (this.conversations && this.conversations.length > 0) {
52
+ return [
53
+ ...carry,
54
+ ...this.conversations.map(
55
+ (channel) => `interaction_events:${channel}:${action_id}`,
56
+ ),
57
+ ];
58
+ }
59
+
60
+ return [
61
+ ...carry,
62
+ `interaction_events:${action_id}`,
63
+ ];
64
+ }, []);
65
+
66
+ if (action_events.length > 0) return action_events;
67
+
68
+ // if no action_ids are specified, move down to channels
69
+ const channel_events = this.conversations.map(
70
+ (channel) => `interaction_events:${channel}`,
71
+ );
72
+
73
+ if (channel_events.length > 0) return channel_events;
74
+
75
+ // if not specific action_ids or channels are specified, subscribe to all events
76
+ return [
77
+ "interaction_events",
78
+ ];
79
+ },
80
+ },
81
+ },
82
+ methods: {},
83
+ async run(event) {
84
+ this.$emit(
85
+ {
86
+ event,
87
+ },
88
+ {
89
+ summary: `New interaction event${
90
+ event?.channel?.id
91
+ ? ` in channel ${event.channel.id}`
92
+ : ""
93
+ }${
94
+ event.actions?.length > 0
95
+ ? ` from action_ids ${event.actions
96
+ .map((action) => action.action_id)
97
+ .join(", ")}`
98
+ : ""
99
+ }`,
100
+ ts: Date.now(),
101
+ },
102
+ );
103
+ },
104
+ sampleEmit,
105
+ };
@@ -0,0 +1,86 @@
1
+ export default {
2
+ "event": {
3
+ "type": "block_actions",
4
+ "user": {
5
+ "id": "US676PZLY",
6
+ "username": "test.user",
7
+ "name": "test.user",
8
+ "team_id": "TS8319547"
9
+ },
10
+ "api_app_id": "AN9231S6L",
11
+ "token": "UYc82mtyZWRhvUXQ6TXrv4wq",
12
+ "container": {
13
+ "type": "message",
14
+ "message_ts": "1716402983.247149",
15
+ "channel_id": "CS8319KD5",
16
+ "is_ephemeral": false
17
+ },
18
+ "trigger_id": "7161731794692.892103311143.4020ed3595908eca11e4076438354dbb",
19
+ "team": {
20
+ "id": "TS8319547",
21
+ "domain": "test-j1q3506"
22
+ },
23
+ "enterprise": null,
24
+ "is_enterprise_install": false,
25
+ "channel": {
26
+ "id": "CS8319KD5",
27
+ "name": "testing"
28
+ },
29
+ "message": {
30
+ "subtype": "bot_message",
31
+ "text": "Click Me button Sent via <https://pipedream.com/@/p_6lCR5Nx?o=a&amp;a=slack|Pipedream>",
32
+ "username": "Pipedream",
33
+ "type": "message",
34
+ "ts": "1716402983.247149",
35
+ "bot_id": "BRTDL45RQ",
36
+ "app_id": "AN9231S6L",
37
+ "blocks": [
38
+ {
39
+ "type": "actions",
40
+ "block_id": "SJp0j",
41
+ "elements": [
42
+ {
43
+ "type": "button",
44
+ "action_id": "button_click",
45
+ "text": {
46
+ "type": "plain_text",
47
+ "text": "Click Me",
48
+ "emoji": true
49
+ },
50
+ "value": "click_me_123"
51
+ }
52
+ ]
53
+ },
54
+ {
55
+ "type": "context",
56
+ "block_id": "ysmBN",
57
+ "elements": [
58
+ {
59
+ "type": "mrkdwn",
60
+ "text": "Sent via <https://pipedream.com/@/p_6lCR5Nx?o=a&amp;a=slack|Pipedream>",
61
+ "verbatim": false
62
+ }
63
+ ]
64
+ }
65
+ ]
66
+ },
67
+ "state": {
68
+ "values": {}
69
+ },
70
+ "response_url": "https://hooks.slack.com/actions/TS8319547/7156351250101/J0w1NoVIXjChEwp4WQab4tcv",
71
+ "actions": [
72
+ {
73
+ "action_id": "button_click",
74
+ "block_id": "SJp0j",
75
+ "text": {
76
+ "type": "plain_text",
77
+ "text": "Click Me",
78
+ "emoji": true
79
+ },
80
+ "value": "click_me_123",
81
+ "type": "button",
82
+ "action_ts": "1716403200.549150"
83
+ }
84
+ ]
85
+ }
86
+ }
@@ -0,0 +1,99 @@
1
+ import common from "../common/base.mjs";
2
+ import constants from "../common/constants.mjs";
3
+ import sampleEmit from "./test-event.mjs";
4
+ import sharedConstants from "../../common/constants.mjs";
5
+
6
+ export default {
7
+ ...common,
8
+ key: "slack_v2-new-keyword-mention",
9
+ name: "New Keyword Mention (Instant)",
10
+ version: "0.1.0",
11
+ description: "Emit new event when a specific keyword is mentioned in a channel",
12
+ type: "source",
13
+ dedupe: "unique",
14
+ props: {
15
+ ...common.props,
16
+ conversations: {
17
+ propDefinition: [
18
+ common.props.slack,
19
+ "conversation",
20
+ () => ({
21
+ types: [
22
+ sharedConstants.CHANNEL_TYPE.PUBLIC,
23
+ sharedConstants.CHANNEL_TYPE.PRIVATE,
24
+ ],
25
+ }),
26
+ ],
27
+ type: "string[]",
28
+ label: "Channels",
29
+ description: "Select one or more channels to monitor for new messages.",
30
+ optional: true,
31
+ },
32
+ // eslint-disable-next-line pipedream/props-description,pipedream/props-label
33
+ slackApphook: {
34
+ type: "$.interface.apphook",
35
+ appProp: "slack",
36
+ async eventNames() {
37
+ return this.conversations || [
38
+ "message",
39
+ ];
40
+ },
41
+ },
42
+ keyword: {
43
+ propDefinition: [
44
+ common.props.slack,
45
+ "keyword",
46
+ ],
47
+ },
48
+ ignoreBot: {
49
+ propDefinition: [
50
+ common.props.slack,
51
+ "ignoreBot",
52
+ ],
53
+ },
54
+ },
55
+ methods: {
56
+ ...common.methods,
57
+ getSummary() {
58
+ return "New keyword mention received";
59
+ },
60
+ async processEvent(event) {
61
+ const {
62
+ type: msgType,
63
+ subtype,
64
+ bot_id: botId,
65
+ text,
66
+ } = event;
67
+
68
+ if (msgType !== "message") {
69
+ console.log(`Ignoring event with unexpected type "${msgType}"`);
70
+ return;
71
+ }
72
+
73
+ // This source is designed to just emit an event for each new message received.
74
+ // Due to inconsistencies with the shape of message_changed and message_deleted
75
+ // events, we are ignoring them for now. If you want to handle these types of
76
+ // events, feel free to change this code!!
77
+ if (subtype && !constants.ALLOWED_SUBTYPES.includes(subtype)) {
78
+ console.log(`Ignoring message with subtype. "${subtype}"`);
79
+ return;
80
+ }
81
+
82
+ if ((this.ignoreBot) && (subtype === constants.SUBTYPE.BOT_MESSAGE || botId)) {
83
+ return;
84
+ }
85
+
86
+ let emitEvent = false;
87
+ if (text.indexOf(this.keyword) !== -1) {
88
+ emitEvent = true;
89
+ } else if (subtype === constants.SUBTYPE.PD_HISTORY_MESSAGE) {
90
+ emitEvent = true;
91
+ }
92
+
93
+ if (emitEvent) {
94
+ return event;
95
+ }
96
+ },
97
+ },
98
+ sampleEmit,
99
+ };