@oneuptime/common 7.0.3707 → 7.0.3708
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/Server/Services/WorkspaceNotificationRuleService.ts +205 -11
- package/Server/Services/WorkspaceProjectAuthTokenService.ts +1 -0
- package/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts +18 -7
- package/Server/Utils/Workspace/Slack/Slack.ts +352 -45
- package/Server/Utils/Workspace/Slack/app-manifest.json +9 -4
- package/Server/Utils/Workspace/WorkspaceBase.ts +31 -2
- package/Types/Workflow/Component.ts +1 -0
- package/Types/Workflow/Components/BaseModel.ts +30 -0
- package/Types/Workflow/Components/Manual.ts +10 -0
- package/Types/Workflow/Components/Schedule.ts +1 -0
- package/Types/Workflow/Components/Webhook.ts +26 -0
- package/UI/Components/Workflow/RunForm.tsx +23 -25
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +136 -8
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +1 -0
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js +14 -5
- package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +251 -36
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/app-manifest.json +9 -4
- package/build/dist/Server/Utils/Workspace/WorkspaceBase.js +12 -2
- package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
- package/build/dist/Types/Workflow/Components/BaseModel.js +30 -0
- package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Manual.js +10 -0
- package/build/dist/Types/Workflow/Components/Manual.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Schedule.js +1 -0
- package/build/dist/Types/Workflow/Components/Schedule.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Webhook.js +26 -0
- package/build/dist/Types/Workflow/Components/Webhook.js.map +1 -1
- package/build/dist/UI/Components/Workflow/RunForm.js +16 -14
- package/build/dist/UI/Components/Workflow/RunForm.js.map +1 -1
- package/package.json +2 -2
- /package/Server/Utils/Workspace/Slack/{app-manifest-temp.json → app-manifest.example.json} +0 -0
|
@@ -15,125 +15,270 @@ import WorkspaceBase, { WorkspaceChannel } from "../WorkspaceBase";
|
|
|
15
15
|
import WorkspaceType from "../../../../Types/Workspace/WorkspaceType";
|
|
16
16
|
|
|
17
17
|
export default class SlackUtil extends WorkspaceBase {
|
|
18
|
-
public static override async
|
|
18
|
+
public static override async joinChannel(data: {
|
|
19
19
|
authToken: string;
|
|
20
|
-
|
|
20
|
+
channelId: string;
|
|
21
|
+
}): Promise<void> {
|
|
22
|
+
logger.debug("Joining channel with data:");
|
|
23
|
+
logger.debug(data);
|
|
24
|
+
|
|
25
|
+
// Join channel
|
|
26
|
+
const response: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
27
|
+
await API.post(
|
|
28
|
+
URL.fromString("https://slack.com/api/conversations.join"),
|
|
29
|
+
{
|
|
30
|
+
channel: data.channelId,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
Authorization: `Bearer ${data.authToken}`,
|
|
34
|
+
["Content-Type"]: "application/x-www-form-urlencoded",
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
logger.debug("Response from Slack API for joining channel:");
|
|
39
|
+
logger.debug(response);
|
|
40
|
+
|
|
41
|
+
if (response instanceof HTTPErrorResponse) {
|
|
42
|
+
logger.error("Error response from Slack API:");
|
|
43
|
+
logger.error(response);
|
|
44
|
+
throw response;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
48
|
+
logger.error("Invalid response from Slack API:");
|
|
49
|
+
logger.error(response.jsonData);
|
|
50
|
+
throw new BadRequestException("Invalid response");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
logger.debug("Channel joined successfully with data:");
|
|
54
|
+
logger.debug(data);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public static override async inviteUserToChannelByChannelId(data: {
|
|
58
|
+
authToken: string;
|
|
59
|
+
channelId: string;
|
|
21
60
|
workspaceUserId: string;
|
|
22
61
|
}): Promise<void> {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
authToken: data.authToken,
|
|
26
|
-
channelId: data.channelName,
|
|
27
|
-
})
|
|
28
|
-
).id;
|
|
62
|
+
logger.debug("Inviting user to channel with data:");
|
|
63
|
+
logger.debug(data);
|
|
29
64
|
|
|
30
65
|
const response: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
31
66
|
await API.post(
|
|
32
67
|
URL.fromString("https://slack.com/api/conversations.invite"),
|
|
33
68
|
{
|
|
34
|
-
channel: channelId,
|
|
69
|
+
channel: data.channelId,
|
|
35
70
|
users: data.workspaceUserId,
|
|
36
71
|
},
|
|
37
72
|
{
|
|
38
73
|
Authorization: `Bearer ${data.authToken}`,
|
|
74
|
+
["Content-Type"]: "application/x-www-form-urlencoded",
|
|
39
75
|
},
|
|
40
76
|
);
|
|
41
77
|
|
|
78
|
+
logger.debug("Response from Slack API for inviting user:");
|
|
79
|
+
logger.debug(response);
|
|
80
|
+
|
|
42
81
|
if (response instanceof HTTPErrorResponse) {
|
|
82
|
+
logger.error("Error response from Slack API:");
|
|
83
|
+
logger.error(response);
|
|
43
84
|
throw response;
|
|
44
85
|
}
|
|
45
86
|
|
|
46
87
|
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
88
|
+
logger.error("Invalid response from Slack API:");
|
|
89
|
+
logger.error(response.jsonData);
|
|
47
90
|
throw new BadRequestException("Invalid response");
|
|
48
91
|
}
|
|
92
|
+
|
|
93
|
+
logger.debug("User invited to channel successfully.");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public static override async inviteUserToChannelByChannelName(data: {
|
|
97
|
+
authToken: string;
|
|
98
|
+
channelName: string;
|
|
99
|
+
workspaceUserId: string;
|
|
100
|
+
}): Promise<void> {
|
|
101
|
+
if (data.channelName && data.channelName.startsWith("#")) {
|
|
102
|
+
// trim # from channel name
|
|
103
|
+
data.channelName = data.channelName.substring(1);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
logger.debug("Inviting user to channel with data:");
|
|
107
|
+
logger.debug(data);
|
|
108
|
+
|
|
109
|
+
const channelId: string = (
|
|
110
|
+
await this.getWorkspaceChannelFromChannelName({
|
|
111
|
+
authToken: data.authToken,
|
|
112
|
+
channelName: data.channelName,
|
|
113
|
+
})
|
|
114
|
+
).id;
|
|
115
|
+
|
|
116
|
+
return this.inviteUserToChannelByChannelId({
|
|
117
|
+
authToken: data.authToken,
|
|
118
|
+
channelId: channelId,
|
|
119
|
+
workspaceUserId: data.workspaceUserId,
|
|
120
|
+
});
|
|
49
121
|
}
|
|
50
122
|
|
|
51
123
|
public static override async createChannelsIfDoesNotExist(data: {
|
|
52
124
|
authToken: string;
|
|
53
125
|
channelNames: Array<string>;
|
|
54
126
|
}): Promise<Array<WorkspaceChannel>> {
|
|
55
|
-
|
|
127
|
+
logger.debug("Creating channels if they do not exist with data:");
|
|
128
|
+
logger.debug(data);
|
|
129
|
+
|
|
56
130
|
const workspaceChannels: Array<WorkspaceChannel> = [];
|
|
57
131
|
const existingWorkspaceChannels: Dictionary<WorkspaceChannel> =
|
|
58
132
|
await this.getAllWorkspaceChannels({
|
|
59
133
|
authToken: data.authToken,
|
|
60
134
|
});
|
|
61
135
|
|
|
62
|
-
|
|
136
|
+
logger.debug("Existing workspace channels:");
|
|
137
|
+
logger.debug(existingWorkspaceChannels);
|
|
138
|
+
|
|
139
|
+
for (let channelName of data.channelNames) {
|
|
140
|
+
// if channel name starts with #, remove it
|
|
141
|
+
if (channelName && channelName.startsWith("#")) {
|
|
142
|
+
channelName = channelName.substring(1);
|
|
143
|
+
}
|
|
144
|
+
|
|
63
145
|
if (existingWorkspaceChannels[channelName]) {
|
|
64
146
|
logger.debug(`Channel ${channelName} already exists.`);
|
|
65
|
-
|
|
66
147
|
workspaceChannels.push(existingWorkspaceChannels[channelName]!);
|
|
67
|
-
|
|
68
148
|
continue;
|
|
69
149
|
}
|
|
70
150
|
|
|
151
|
+
logger.debug(`Channel ${channelName} does not exist. Creating channel.`);
|
|
71
152
|
const channel: WorkspaceChannel = await this.createChannel({
|
|
72
153
|
authToken: data.authToken,
|
|
73
154
|
channelName: channelName,
|
|
74
155
|
});
|
|
75
156
|
|
|
76
157
|
if (channel) {
|
|
158
|
+
logger.debug(`Channel ${channelName} created successfully.`);
|
|
77
159
|
workspaceChannels.push(channel);
|
|
78
160
|
}
|
|
79
161
|
}
|
|
80
162
|
|
|
163
|
+
logger.debug("Channels created or found:");
|
|
164
|
+
logger.debug(workspaceChannels);
|
|
81
165
|
return workspaceChannels;
|
|
82
166
|
}
|
|
83
167
|
|
|
168
|
+
public static override async getWorkspaceChannelFromChannelName(data: {
|
|
169
|
+
authToken: string;
|
|
170
|
+
channelName: string;
|
|
171
|
+
}): Promise<WorkspaceChannel> {
|
|
172
|
+
logger.debug("Getting workspace channel ID from channel name with data:");
|
|
173
|
+
logger.debug(data);
|
|
174
|
+
|
|
175
|
+
const channels: Dictionary<WorkspaceChannel> =
|
|
176
|
+
await this.getAllWorkspaceChannels({
|
|
177
|
+
authToken: data.authToken,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
logger.debug("All workspace channels:");
|
|
181
|
+
logger.debug(channels);
|
|
182
|
+
|
|
183
|
+
if (!channels[data.channelName]) {
|
|
184
|
+
logger.error("Channel not found.");
|
|
185
|
+
throw new Error("Channel not found.");
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
logger.debug("Workspace channel ID obtained:");
|
|
189
|
+
logger.debug(channels[data.channelName]!.id);
|
|
190
|
+
|
|
191
|
+
return channels[data.channelName]!;
|
|
192
|
+
}
|
|
193
|
+
|
|
84
194
|
public static override async getWorkspaceChannelFromChannelId(data: {
|
|
85
195
|
authToken: string;
|
|
86
196
|
channelId: string;
|
|
87
197
|
}): Promise<WorkspaceChannel> {
|
|
198
|
+
logger.debug("Getting workspace channel from channel ID with data:");
|
|
199
|
+
logger.debug(data);
|
|
200
|
+
|
|
88
201
|
const response: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
89
|
-
await API.
|
|
202
|
+
await API.post<JSONObject>(
|
|
90
203
|
URL.fromString("https://slack.com/api/conversations.info"),
|
|
91
204
|
{
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
},
|
|
205
|
+
channel: data.channelId,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
Authorization: `Bearer ${data.authToken}`,
|
|
209
|
+
["Content-Type"]: "application/x-www-form-urlencoded",
|
|
98
210
|
},
|
|
99
211
|
);
|
|
100
212
|
|
|
213
|
+
logger.debug("Response from Slack API for getting channel info:");
|
|
214
|
+
logger.debug(response);
|
|
215
|
+
|
|
101
216
|
if (response instanceof HTTPErrorResponse) {
|
|
217
|
+
logger.error("Error response from Slack API:");
|
|
218
|
+
logger.error(response);
|
|
102
219
|
throw response;
|
|
103
220
|
}
|
|
104
221
|
|
|
222
|
+
// check for ok response
|
|
223
|
+
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
224
|
+
logger.error("Invalid response from Slack API:");
|
|
225
|
+
logger.error(response.jsonData);
|
|
226
|
+
throw new BadRequestException("Invalid response");
|
|
227
|
+
}
|
|
228
|
+
|
|
105
229
|
if (
|
|
106
230
|
!((response.jsonData as JSONObject)?.["channel"] as JSONObject)?.["name"]
|
|
107
231
|
) {
|
|
232
|
+
logger.error("Invalid response from Slack API:");
|
|
233
|
+
logger.error(response.jsonData);
|
|
108
234
|
throw new Error("Invalid response");
|
|
109
235
|
}
|
|
110
236
|
|
|
111
|
-
|
|
237
|
+
const channel: WorkspaceChannel = {
|
|
112
238
|
name: ((response.jsonData as JSONObject)["channel"] as JSONObject)[
|
|
113
239
|
"name"
|
|
114
240
|
] as string,
|
|
115
241
|
id: data.channelId,
|
|
116
242
|
workspaceType: WorkspaceType.Slack,
|
|
117
243
|
};
|
|
244
|
+
|
|
245
|
+
logger.debug("Workspace channel obtained:");
|
|
246
|
+
logger.debug(channel);
|
|
247
|
+
return channel;
|
|
118
248
|
}
|
|
119
249
|
|
|
120
250
|
public static override async getAllWorkspaceChannels(data: {
|
|
121
251
|
authToken: string;
|
|
122
252
|
}): Promise<Dictionary<WorkspaceChannel>> {
|
|
253
|
+
logger.debug("Getting all workspace channels with data:");
|
|
254
|
+
logger.debug(data);
|
|
255
|
+
|
|
123
256
|
const response: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
124
|
-
await API.
|
|
257
|
+
await API.post<JSONObject>(
|
|
125
258
|
URL.fromString("https://slack.com/api/conversations.list"),
|
|
259
|
+
{},
|
|
126
260
|
{
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
},
|
|
261
|
+
Authorization: `Bearer ${data.authToken}`,
|
|
262
|
+
["Content-Type"]: "application/x-www-form-urlencoded",
|
|
130
263
|
},
|
|
131
264
|
);
|
|
132
265
|
|
|
266
|
+
logger.debug("Response from Slack API for getting all channels:");
|
|
267
|
+
logger.debug(response);
|
|
268
|
+
|
|
133
269
|
if (response instanceof HTTPErrorResponse) {
|
|
270
|
+
logger.error("Error response from Slack API:");
|
|
271
|
+
logger.error(response);
|
|
134
272
|
throw response;
|
|
135
273
|
}
|
|
136
274
|
|
|
275
|
+
// check for ok response
|
|
276
|
+
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
277
|
+
logger.error("Invalid response from Slack API:");
|
|
278
|
+
logger.error(response.jsonData);
|
|
279
|
+
throw new BadRequestException("Invalid response");
|
|
280
|
+
}
|
|
281
|
+
|
|
137
282
|
const channels: Dictionary<WorkspaceChannel> = {};
|
|
138
283
|
|
|
139
284
|
for (const channel of (response.jsonData as JSONObject)[
|
|
@@ -150,29 +295,42 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
150
295
|
};
|
|
151
296
|
}
|
|
152
297
|
|
|
298
|
+
logger.debug("All workspace channels obtained:");
|
|
299
|
+
logger.debug(channels);
|
|
153
300
|
return channels;
|
|
154
301
|
}
|
|
155
302
|
|
|
156
303
|
public static override async sendMessage(data: {
|
|
157
304
|
workspaceMessagePayload: WorkspaceMessagePayload;
|
|
158
305
|
authToken: string; // which auth token should we use to send.
|
|
306
|
+
userId: string;
|
|
159
307
|
}): Promise<void> {
|
|
160
|
-
logger.debug("
|
|
308
|
+
logger.debug("Sending message to Slack with data:");
|
|
161
309
|
logger.debug(data);
|
|
162
310
|
|
|
163
311
|
const blocks: Array<JSONObject> = this.getBlocksFromWorkspaceMessagePayload(
|
|
164
312
|
data.workspaceMessagePayload,
|
|
165
313
|
);
|
|
166
314
|
|
|
315
|
+
logger.debug("Blocks generated from workspace message payload:");
|
|
316
|
+
logger.debug(blocks);
|
|
317
|
+
|
|
167
318
|
const existingWorkspaceChannels: Dictionary<WorkspaceChannel> =
|
|
168
319
|
await this.getAllWorkspaceChannels({
|
|
169
320
|
authToken: data.authToken,
|
|
170
321
|
});
|
|
171
322
|
|
|
323
|
+
logger.debug("Existing workspace channels:");
|
|
324
|
+
logger.debug(existingWorkspaceChannels);
|
|
325
|
+
|
|
172
326
|
const channelIdsToPostTo: Array<string> = [];
|
|
173
327
|
|
|
174
|
-
for (
|
|
175
|
-
|
|
328
|
+
for (let channelName of data.workspaceMessagePayload.channelNames) {
|
|
329
|
+
if (channelName && channelName.startsWith("#")) {
|
|
330
|
+
// trim # from channel name
|
|
331
|
+
channelName = channelName.substring(1);
|
|
332
|
+
}
|
|
333
|
+
|
|
176
334
|
let channel: WorkspaceChannel | null = null;
|
|
177
335
|
|
|
178
336
|
if (existingWorkspaceChannels[channelName]) {
|
|
@@ -186,15 +344,35 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
186
344
|
}
|
|
187
345
|
}
|
|
188
346
|
|
|
347
|
+
logger.debug("Channel IDs to post to:");
|
|
348
|
+
logger.debug(channelIdsToPostTo);
|
|
349
|
+
|
|
189
350
|
for (const channelId of channelIdsToPostTo) {
|
|
190
351
|
try {
|
|
191
|
-
//
|
|
352
|
+
// check if the user is in the channel.
|
|
353
|
+
const isUserInChannel: boolean = await this.isUserInChannel({
|
|
354
|
+
authToken: data.authToken,
|
|
355
|
+
channelId: channelId,
|
|
356
|
+
userId: data.userId,
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
if (!isUserInChannel) {
|
|
360
|
+
// add user to the channel
|
|
361
|
+
await this.joinChannel({
|
|
362
|
+
authToken: data.authToken,
|
|
363
|
+
channelId: channelId,
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
192
367
|
await this.sendPayloadBlocksToChannel({
|
|
193
368
|
authToken: data.authToken,
|
|
194
369
|
channelId: channelId,
|
|
195
370
|
blocks: blocks,
|
|
196
371
|
});
|
|
372
|
+
|
|
373
|
+
logger.debug(`Message sent to channel ID ${channelId} successfully.`);
|
|
197
374
|
} catch (e) {
|
|
375
|
+
logger.error(`Error sending message to channel ID ${channelId}:`);
|
|
198
376
|
logger.error(e);
|
|
199
377
|
}
|
|
200
378
|
}
|
|
@@ -205,6 +383,9 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
205
383
|
channelId: string;
|
|
206
384
|
blocks: Array<JSONObject>;
|
|
207
385
|
}): Promise<void> {
|
|
386
|
+
logger.debug("Sending payload blocks to channel with data:");
|
|
387
|
+
logger.debug(JSON.stringify(data, null, 2));
|
|
388
|
+
|
|
208
389
|
const response: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
209
390
|
await API.post(
|
|
210
391
|
URL.fromString("https://slack.com/api/chat.postMessage"),
|
|
@@ -214,22 +395,35 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
214
395
|
},
|
|
215
396
|
{
|
|
216
397
|
Authorization: `Bearer ${data.authToken}`,
|
|
398
|
+
["Content-Type"]: "application/json",
|
|
217
399
|
},
|
|
218
400
|
);
|
|
219
401
|
|
|
402
|
+
logger.debug("Response from Slack API for sending message:");
|
|
403
|
+
logger.debug(response);
|
|
404
|
+
|
|
220
405
|
if (response instanceof HTTPErrorResponse) {
|
|
406
|
+
logger.error("Error response from Slack API:");
|
|
407
|
+
logger.error(response);
|
|
221
408
|
throw response;
|
|
222
409
|
}
|
|
223
410
|
|
|
224
411
|
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
412
|
+
logger.error("Invalid response from Slack API:");
|
|
413
|
+
logger.error(response.jsonData);
|
|
225
414
|
throw new BadRequestException("Invalid response");
|
|
226
415
|
}
|
|
416
|
+
|
|
417
|
+
logger.debug("Payload blocks sent to channel successfully.");
|
|
227
418
|
}
|
|
228
419
|
|
|
229
420
|
public static override async createChannel(data: {
|
|
230
421
|
authToken: string;
|
|
231
422
|
channelName: string;
|
|
232
423
|
}): Promise<WorkspaceChannel> {
|
|
424
|
+
logger.debug("Creating channel with data:");
|
|
425
|
+
logger.debug(data);
|
|
426
|
+
|
|
233
427
|
const response: HTTPResponse<JSONObject> | HTTPErrorResponse =
|
|
234
428
|
await API.post(
|
|
235
429
|
URL.fromString("https://slack.com/api/conversations.create"),
|
|
@@ -238,21 +432,36 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
238
432
|
},
|
|
239
433
|
{
|
|
240
434
|
Authorization: `Bearer ${data.authToken}`,
|
|
435
|
+
["Content-Type"]: "application/x-www-form-urlencoded",
|
|
241
436
|
},
|
|
242
437
|
);
|
|
243
438
|
|
|
439
|
+
logger.debug("Response from Slack API for creating channel:");
|
|
440
|
+
logger.debug(response);
|
|
441
|
+
|
|
244
442
|
if (response instanceof HTTPErrorResponse) {
|
|
443
|
+
logger.error("Error response from Slack API:");
|
|
444
|
+
logger.error(response);
|
|
245
445
|
throw response;
|
|
246
446
|
}
|
|
247
447
|
|
|
448
|
+
// check for ok response
|
|
449
|
+
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
450
|
+
logger.error("Invalid response from Slack API:");
|
|
451
|
+
logger.error(response.jsonData);
|
|
452
|
+
throw new BadRequestException("Invalid response");
|
|
453
|
+
}
|
|
454
|
+
|
|
248
455
|
if (
|
|
249
456
|
!((response.jsonData as JSONObject)?.["channel"] as JSONObject)?.["id"] ||
|
|
250
457
|
!((response.jsonData as JSONObject)?.["channel"] as JSONObject)?.["name"]
|
|
251
458
|
) {
|
|
459
|
+
logger.error("Invalid response from Slack API:");
|
|
460
|
+
logger.error(response.jsonData);
|
|
252
461
|
throw new Error("Invalid response");
|
|
253
462
|
}
|
|
254
463
|
|
|
255
|
-
|
|
464
|
+
const channel: WorkspaceChannel = {
|
|
256
465
|
id: ((response.jsonData as JSONObject)["channel"] as JSONObject)[
|
|
257
466
|
"id"
|
|
258
467
|
] as string,
|
|
@@ -261,36 +470,127 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
261
470
|
] as string,
|
|
262
471
|
workspaceType: WorkspaceType.Slack,
|
|
263
472
|
};
|
|
473
|
+
|
|
474
|
+
logger.debug("Channel created successfully:");
|
|
475
|
+
logger.debug(channel);
|
|
476
|
+
return channel;
|
|
264
477
|
}
|
|
265
478
|
|
|
266
479
|
public static override getHeaderBlock(data: {
|
|
267
480
|
payloadHeaderBlock: WorkspacePayloadHeader;
|
|
268
481
|
}): JSONObject {
|
|
269
|
-
|
|
482
|
+
logger.debug("Getting header block with data:");
|
|
483
|
+
logger.debug(data);
|
|
484
|
+
|
|
485
|
+
const headerBlock: JSONObject = {
|
|
270
486
|
type: "header",
|
|
271
487
|
text: {
|
|
272
488
|
type: "plain_text",
|
|
273
489
|
text: data.payloadHeaderBlock.text,
|
|
274
490
|
},
|
|
275
491
|
};
|
|
492
|
+
|
|
493
|
+
logger.debug("Header block generated:");
|
|
494
|
+
logger.debug(headerBlock);
|
|
495
|
+
return headerBlock;
|
|
276
496
|
}
|
|
277
497
|
|
|
278
498
|
public static override getMarkdownBlock(data: {
|
|
279
499
|
payloadMarkdownBlock: WorkspacePayloadMarkdown;
|
|
280
500
|
}): JSONObject {
|
|
281
|
-
|
|
501
|
+
logger.debug("Getting markdown block with data:");
|
|
502
|
+
logger.debug(data);
|
|
503
|
+
|
|
504
|
+
const markdownBlock: JSONObject = {
|
|
282
505
|
type: "section",
|
|
283
506
|
text: {
|
|
284
507
|
type: "mrkdwn",
|
|
285
508
|
text: data.payloadMarkdownBlock.text,
|
|
286
509
|
},
|
|
287
510
|
};
|
|
511
|
+
|
|
512
|
+
logger.debug("Markdown block generated:");
|
|
513
|
+
logger.debug(markdownBlock);
|
|
514
|
+
return markdownBlock;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
public static override async isUserInChannel(data: {
|
|
518
|
+
authToken: string;
|
|
519
|
+
channelId: string;
|
|
520
|
+
userId: string;
|
|
521
|
+
}): Promise<boolean> {
|
|
522
|
+
const members: Array<string> = [];
|
|
523
|
+
|
|
524
|
+
logger.debug("Checking if user is in channel with data:");
|
|
525
|
+
logger.debug(data);
|
|
526
|
+
|
|
527
|
+
let cursor: string | undefined = undefined;
|
|
528
|
+
|
|
529
|
+
do {
|
|
530
|
+
// check if the user is in the channel, return true if they are, false if they are not
|
|
531
|
+
|
|
532
|
+
const requestBody: JSONObject = {
|
|
533
|
+
channel: data.channelId,
|
|
534
|
+
limit: 1000,
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
if (cursor) {
|
|
538
|
+
requestBody["cursor"] = cursor;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
const response: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
542
|
+
await API.post<JSONObject>(
|
|
543
|
+
URL.fromString("https://slack.com/api/conversations.members"),
|
|
544
|
+
requestBody,
|
|
545
|
+
{
|
|
546
|
+
Authorization: `Bearer ${data.authToken}`,
|
|
547
|
+
["Content-Type"]: "application/x-www-form-urlencoded",
|
|
548
|
+
},
|
|
549
|
+
);
|
|
550
|
+
|
|
551
|
+
logger.debug("Response from Slack API for getting channel members:");
|
|
552
|
+
logger.debug(response);
|
|
553
|
+
|
|
554
|
+
if (response instanceof HTTPErrorResponse) {
|
|
555
|
+
logger.error("Error response from Slack API:");
|
|
556
|
+
logger.error(response);
|
|
557
|
+
throw response;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// check for ok response
|
|
561
|
+
|
|
562
|
+
if ((response.jsonData as JSONObject)?.["ok"] !== true) {
|
|
563
|
+
logger.error("Invalid response from Slack API:");
|
|
564
|
+
logger.error(response.jsonData);
|
|
565
|
+
throw new BadRequestException("Invalid response");
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// check if the user is in the channel
|
|
569
|
+
const membersOnThisPage: Array<string> = (
|
|
570
|
+
response.jsonData as JSONObject
|
|
571
|
+
)["members"] as Array<string>;
|
|
572
|
+
|
|
573
|
+
members.push(...membersOnThisPage);
|
|
574
|
+
|
|
575
|
+
cursor = (
|
|
576
|
+
(response.jsonData as JSONObject)["response_metadata"] as JSONObject
|
|
577
|
+
)?.["next_cursor"] as string;
|
|
578
|
+
} while (cursor);
|
|
579
|
+
|
|
580
|
+
if (members.includes(data.userId)) {
|
|
581
|
+
return true;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return false;
|
|
288
585
|
}
|
|
289
586
|
|
|
290
587
|
public static override getButtonBlock(data: {
|
|
291
588
|
payloadButtonBlock: WorkspaceMessagePayloadButton;
|
|
292
589
|
}): JSONObject {
|
|
293
|
-
|
|
590
|
+
logger.debug("Getting button block with data:");
|
|
591
|
+
logger.debug(data);
|
|
592
|
+
|
|
593
|
+
const buttonBlock: JSONObject = {
|
|
294
594
|
type: "button",
|
|
295
595
|
text: {
|
|
296
596
|
type: "plain_text",
|
|
@@ -299,27 +599,34 @@ export default class SlackUtil extends WorkspaceBase {
|
|
|
299
599
|
value: data.payloadButtonBlock.title,
|
|
300
600
|
action_id: data.payloadButtonBlock.title,
|
|
301
601
|
};
|
|
602
|
+
|
|
603
|
+
logger.debug("Button block generated:");
|
|
604
|
+
logger.debug(buttonBlock);
|
|
605
|
+
return buttonBlock;
|
|
302
606
|
}
|
|
303
607
|
|
|
304
608
|
public static override async sendMessageToChannelViaIncomingWebhook(data: {
|
|
305
609
|
url: URL;
|
|
306
610
|
text: string;
|
|
307
611
|
}): Promise<HTTPResponse<JSONObject> | HTTPErrorResponse> {
|
|
308
|
-
|
|
612
|
+
logger.debug("Sending message to channel via incoming webhook with data:");
|
|
613
|
+
logger.debug(data);
|
|
309
614
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
615
|
+
const apiResult: HTTPResponse<JSONObject> | HTTPErrorResponse | null =
|
|
616
|
+
await API.post(data.url, {
|
|
617
|
+
blocks: [
|
|
618
|
+
{
|
|
619
|
+
type: "section",
|
|
620
|
+
text: {
|
|
621
|
+
type: "mrkdwn",
|
|
622
|
+
text: `${data.text}`,
|
|
623
|
+
},
|
|
318
624
|
},
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
});
|
|
625
|
+
],
|
|
626
|
+
});
|
|
322
627
|
|
|
628
|
+
logger.debug("Response from Slack API for sending message via webhook:");
|
|
629
|
+
logger.debug(apiResult);
|
|
323
630
|
return apiResult;
|
|
324
631
|
}
|
|
325
632
|
}
|
|
@@ -45,12 +45,17 @@
|
|
|
45
45
|
],
|
|
46
46
|
"scopes": {
|
|
47
47
|
"user": [
|
|
48
|
-
"
|
|
49
|
-
"identity.basic",
|
|
50
|
-
"email"
|
|
48
|
+
"users:read"
|
|
51
49
|
],
|
|
52
50
|
"bot": [
|
|
53
|
-
"commands"
|
|
51
|
+
"commands",
|
|
52
|
+
"channels:history",
|
|
53
|
+
"channels:join",
|
|
54
|
+
"channels:manage",
|
|
55
|
+
"channels:read",
|
|
56
|
+
"channels:write.invites",
|
|
57
|
+
"channels:write.topic",
|
|
58
|
+
"chat:write"
|
|
54
59
|
]
|
|
55
60
|
}
|
|
56
61
|
},
|