Skip to content

Commit e68de1f

Browse files
committed
Update Slack actions to support Slack v2 OAuth
- List users by real name in dropdowns - List users by real name in action summary - List files using bot token if available - Get files using bot token if available - Show configuration error if bot is not a member of the channel - Add `addToChannel` prop to Send Message actions - Check user's access to channel in message actions - Use RTS API to search messages in Find Message action - List only channels, not DMs, in 'file' actions - List only channels, not DMs, in 'message' triggers - Handle permission error fetching message in New Reaction trigger Context: In Slack's v2 OAuth flow, user access tokens and bot access tokens are issued with separate scopes. User tokens are used to perform actions on behalf of a user, while bot tokens are used for actions performed by the app itself. To send a message to a private channel or DM, the bot must be a member of that channel. Due to permission restrictions, some endpoints require bot tokens for access, such as viewing messages in DMs and listing files. As a result, access to messages and files in DMs is no longer supported.
1 parent 7f84b6d commit e68de1f

File tree

13 files changed

+297
-98
lines changed

13 files changed

+297
-98
lines changed

components/slack/actions/common/send-message.mjs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ export default {
99
"as_user",
1010
],
1111
},
12+
addToChannel: {
13+
propDefinition: [
14+
slack,
15+
"addToChannel",
16+
],
17+
optional: true,
18+
},
1219
post_at: {
1320
propDefinition: [
1421
slack,
@@ -181,6 +188,14 @@ export default {
181188
},
182189
},
183190
async run({ $ }) {
191+
const channelId = await this.getChannelId();
192+
193+
if (this.addToChannel) {
194+
await this.slack.maybeAddAppToChannels([
195+
channelId,
196+
]);
197+
}
198+
184199
let blocks = this.blocks;
185200

186201
if (!blocks) {
@@ -216,7 +231,7 @@ export default {
216231

217232
const obj = {
218233
text: this.text,
219-
channel: await this.getChannelId(),
234+
channel: channelId,
220235
attachments: this.attachments,
221236
unfurl_links: this.unfurl_links,
222237
unfurl_media: this.unfurl_media,
@@ -241,15 +256,7 @@ export default {
241256
const { channel } = await this.slack.conversationsInfo({
242257
channel: resp.channel,
243258
});
244-
let channelName = `#${channel?.name}`;
245-
if (channel.is_im) {
246-
const { profile } = await this.slack.getUserProfile({
247-
user: channel.user,
248-
});
249-
channelName = `@${profile.real_name}`;
250-
} else if (channel.is_mpim) {
251-
channelName = `@${channel.purpose.value}`;
252-
}
259+
const channelName = await this.slack.getChannelDisplayName(channel);
253260
$.export("$summary", `Successfully sent a message to ${channelName}`);
254261
return resp;
255262
},

components/slack/actions/find-message/find-message.mjs

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import { axios } from "@pipedream/platform";
12
import slack from "../../slack.app.mjs";
23

34
export default {
45
key: "slack-find-message",
56
name: "Find Message",
6-
description: "Find a Slack message. [See the documentation](https://api.slack.com/methods/search.messages)",
7+
description: "Find a Slack message. [See the documentation](https://api.slack.com/methods/assistant.search.context)",
78
version: "0.0.26",
89
annotations: {
910
destructiveHint: false,
@@ -19,18 +20,11 @@ export default {
1920
"query",
2021
],
2122
},
22-
teamId: {
23-
propDefinition: [
24-
slack,
25-
"team",
26-
],
27-
optional: true,
28-
},
2923
maxResults: {
3024
type: "integer",
3125
label: "Max Results",
3226
description: "The maximum number of messages to return",
33-
default: 100,
27+
default: 20,
3428
optional: true,
3529
},
3630
sort: {
@@ -54,26 +48,51 @@ export default {
5448
optional: true,
5549
},
5650
},
51+
methods: {
52+
async searchMessages($, params) {
53+
const data = await axios($, {
54+
method: "POST",
55+
url: "https://slack.com/api/assistant.search.context",
56+
data: {
57+
query: params.query,
58+
sort: params.sort,
59+
sort_dir: params.sort_dir,
60+
cursor: params.cursor,
61+
channel_types: params.channel_types,
62+
},
63+
headers: {
64+
"Authorization": `Bearer ${this.slack.getToken()}`,
65+
"Content-Type": "application/json",
66+
},
67+
});
68+
if (!data.ok) {
69+
throw new Error(data.error || "An error occurred while searching messages");
70+
}
71+
return data;
72+
},
73+
},
5774
async run({ $ }) {
5875
const matches = [];
5976
const params = {
6077
query: this.query,
61-
team_id: this.teamId,
6278
sort: this.sort,
6379
sort_dir: this.sortDirection,
64-
page: 1,
80+
channel_types: "public_channel,private_channel",
6581
};
66-
let hasMore;
82+
let cursor;
6783

6884
do {
69-
const { messages } = await this.slack.searchMessages(params);
70-
matches.push(...messages.matches);
85+
if (cursor) {
86+
params.cursor = cursor;
87+
}
88+
const response = await this.searchMessages($, params);
89+
const messages = response.results?.messages || [];
90+
matches.push(...messages);
7191
if (matches.length >= this.maxResults) {
7292
break;
7393
}
74-
hasMore = messages.matches?.length;
75-
params.page++;
76-
} while (hasMore);
94+
cursor = response.response_metadata?.next_cursor;
95+
} while (cursor);
7796

7897
if (matches.length > this.maxResults) {
7998
matches.length = this.maxResults;

components/slack/actions/get-file/get-file.mjs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import constants from "../../common/constants.mjs";
12
import slack from "../../slack.app.mjs";
23

34
export default {
@@ -17,6 +18,19 @@ export default {
1718
propDefinition: [
1819
slack,
1920
"conversation",
21+
() => ({
22+
types: [
23+
constants.CHANNEL_TYPE.PUBLIC,
24+
constants.CHANNEL_TYPE.PRIVATE,
25+
],
26+
}),
27+
],
28+
description: "Select a public or private channel",
29+
},
30+
addToChannel: {
31+
propDefinition: [
32+
slack,
33+
"addToChannel",
2034
],
2135
},
2236
file: {
@@ -30,6 +44,12 @@ export default {
3044
},
3145
},
3246
async run({ $ }) {
47+
if (this.addToChannel) {
48+
await this.slack.maybeAddAppToChannels([
49+
this.conversation,
50+
]);
51+
}
52+
3353
const response = await this.slack.getFileInfo({
3454
file: this.file,
3555
});

components/slack/actions/list-files/list-files.mjs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import constants from "../../common/constants.mjs";
12
import slack from "../../slack.app.mjs";
23

34
export default {
@@ -17,6 +18,19 @@ export default {
1718
propDefinition: [
1819
slack,
1920
"conversation",
21+
() => ({
22+
types: [
23+
constants.CHANNEL_TYPE.PUBLIC,
24+
constants.CHANNEL_TYPE.PRIVATE,
25+
],
26+
}),
27+
],
28+
description: "Select a public or private channel",
29+
},
30+
addToChannel: {
31+
propDefinition: [
32+
slack,
33+
"addToChannel",
2034
],
2135
},
2236
team_id: {
@@ -47,6 +61,12 @@ export default {
4761
},
4862
},
4963
async run({ $ }) {
64+
if (this.addToChannel) {
65+
await this.slack.maybeAddAppToChannels([
66+
this.conversation,
67+
]);
68+
}
69+
5070
const allFiles = [];
5171
const params = {
5272
channel: this.conversation,

components/slack/actions/list-replies/list-replies.mjs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import constants from "../../common/constants.mjs";
12
import slack from "../../slack.app.mjs";
23

34
export default {
@@ -17,7 +18,14 @@ export default {
1718
propDefinition: [
1819
slack,
1920
"conversation",
21+
() => ({
22+
types: [
23+
constants.CHANNEL_TYPE.PUBLIC,
24+
constants.CHANNEL_TYPE.PRIVATE,
25+
],
26+
}),
2027
],
28+
description: "Select a public or private channel",
2129
},
2230
timestamp: {
2331
propDefinition: [

components/slack/actions/send-large-message/send-large-message.mjs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ export default {
3535
...common.props,
3636
},
3737
async run({ $ }) {
38+
if (this.addToChannel) {
39+
await this.slack.maybeAddAppToChannels([
40+
this.conversation,
41+
]);
42+
}
43+
3844
if (this.include_sent_via_pipedream_flag) {
3945
const sentViaPipedreamText = this._makeSentViaPipedreamBlock();
4046
this.text += `\n\n\n${sentViaPipedreamText.elements[0].text}`;
@@ -79,19 +85,10 @@ export default {
7985
} else {
8086
response = await this.slack.postChatMessage(obj);
8187
}
82-
8388
const { channel } = await this.slack.conversationsInfo({
8489
channel: response.channel,
8590
});
86-
let channelName = `#${channel?.name}`;
87-
if (channel.is_im) {
88-
const { profile } = await this.slack.getUserProfile({
89-
user: channel.user,
90-
});
91-
channelName = `@${profile.real_name}`;
92-
} else if (channel.is_mpim) {
93-
channelName = `@${channel.purpose.value}`;
94-
}
91+
const channelName = await this.slack.getChannelDisplayName(channel);
9592
$.export("$summary", `Successfully sent a message to ${channelName}`);
9693
return response;
9794
},

components/slack/actions/send-message-to-user-or-group/send-message-to-user-or-group.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ export default {
5252
],
5353
},
5454
...common.props,
55+
// eslint-disable-next-line pipedream/props-label, pipedream/props-description
56+
addToChannel: {
57+
type: "boolean",
58+
...common.props.addToChannel,
59+
disabled: true,
60+
hidden: true,
61+
},
5562
},
5663
methods: {
5764
...common.methods,

components/slack/actions/update-group-members/update-group-members.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ export default {
5151
async run({ $ }) {
5252
const {
5353
userGroup,
54-
usersToAdd,
55-
usersToRemove,
54+
usersToAdd = [],
55+
usersToRemove = [],
5656
team,
5757
} = this;
5858
let { users } = await this.slack.listGroupMembers({

0 commit comments

Comments
 (0)