@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.
- package/LICENSE +41 -0
- package/actions/add-emoji-reaction/add-emoji-reaction.mjs +48 -0
- package/actions/approve-workflow/approve-workflow.mjs +92 -0
- package/actions/archive-channel/archive-channel.mjs +38 -0
- package/actions/common/build-blocks.mjs +182 -0
- package/actions/common/send-message.mjs +264 -0
- package/actions/create-channel/create-channel.mjs +40 -0
- package/actions/create-reminder/create-reminder.mjs +52 -0
- package/actions/delete-file/delete-file.mjs +39 -0
- package/actions/delete-message/delete-message.mjs +45 -0
- package/actions/find-message/find-message.mjs +83 -0
- package/actions/find-user-by-email/find-user-by-email.mjs +32 -0
- package/actions/get-current-user/get-current-user.mjs +68 -0
- package/actions/get-file/get-file.mjs +59 -0
- package/actions/invite-user-to-channel/invite-user-to-channel.mjs +45 -0
- package/actions/kick-user/kick-user.mjs +56 -0
- package/actions/list-channels/list-channels.mjs +52 -0
- package/actions/list-files/list-files.mjs +93 -0
- package/actions/list-group-members/list-group-members.mjs +68 -0
- package/actions/list-members-in-channel/list-members-in-channel.mjs +71 -0
- package/actions/list-replies/list-replies.mjs +74 -0
- package/actions/list-users/list-users.mjs +60 -0
- package/actions/reply-to-a-message/reply-to-a-message.mjs +54 -0
- package/actions/send-block-kit-message/send-block-kit-message.mjs +48 -0
- package/actions/send-large-message/send-large-message.mjs +95 -0
- package/actions/send-message/send-message.mjs +56 -0
- package/actions/send-message-advanced/send-message-advanced.mjs +75 -0
- package/actions/send-message-to-channel/send-message-to-channel.mjs +45 -0
- package/actions/send-message-to-user-or-group/send-message-to-user-or-group.mjs +93 -0
- package/actions/set-channel-description/set-channel-description.mjs +37 -0
- package/actions/set-channel-topic/set-channel-topic.mjs +37 -0
- package/actions/set-status/set-status.mjs +49 -0
- package/actions/update-group-members/update-group-members.mjs +72 -0
- package/actions/update-message/update-message.mjs +59 -0
- package/actions/update-profile/update-profile.mjs +94 -0
- package/actions/upload-file/upload-file.mjs +104 -0
- package/common/constants.mjs +31 -0
- package/package.json +22 -0
- package/slack_v2.app.mjs +1112 -0
- package/sources/common/base.mjs +184 -0
- package/sources/common/constants.mjs +58 -0
- package/sources/new-channel-created/new-channel-created.mjs +32 -0
- package/sources/new-channel-created/test-event.mjs +44 -0
- package/sources/new-interaction-event-received/README.md +85 -0
- package/sources/new-interaction-event-received/new-interaction-event-received.mjs +105 -0
- package/sources/new-interaction-event-received/test-event.mjs +86 -0
- package/sources/new-keyword-mention/new-keyword-mention.mjs +99 -0
- package/sources/new-keyword-mention/test-event.mjs +28 -0
- package/sources/new-message-in-channels/new-message-in-channels.mjs +106 -0
- package/sources/new-message-in-channels/test-event.mjs +45 -0
- package/sources/new-reaction-added/new-reaction-added.mjs +119 -0
- package/sources/new-reaction-added/test-event.mjs +193 -0
- package/sources/new-saved-message/new-saved-message.mjs +32 -0
- package/sources/new-saved-message/test-event.mjs +37 -0
- package/sources/new-user-added/new-user-added.mjs +32 -0
- package/sources/new-user-added/test-event.mjs +48 -0
- package/sources/new-user-mention/new-user-mention.mjs +124 -0
- 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
|
+

|
|
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
|
+

|
|
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
|
+

|
|
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
|
+

|
|
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&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&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
|
+
};
|