@frogbotai/piece-slack 0.29.0 → 0.31.0
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/README.md +3 -2
- package/dist/actions.d.ts +2 -2
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +286 -196
- package/dist/actions.js.map +1 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +47 -35
- package/dist/client.js.map +1 -1
- package/dist/config.js +17 -5
- package/dist/config.js.map +1 -1
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +1 -0
- package/dist/define.js.map +1 -1
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +25 -17
- package/dist/files.js.map +1 -1
- package/dist/index.d.ts +2 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +37 -48
- package/dist/index.js.map +1 -1
- package/dist/options.js +36 -21
- package/dist/options.js.map +1 -1
- package/dist/questions/blocks.js +148 -74
- package/dist/questions/blocks.js.map +1 -1
- package/dist/questions/index.js +2 -1
- package/dist/questions/index.js.map +1 -1
- package/dist/questions/notify.js +19 -13
- package/dist/questions/notify.js.map +1 -1
- package/dist/questions/parse.js +110 -59
- package/dist/questions/parse.js.map +1 -1
- package/dist/questions/render.js +16 -7
- package/dist/questions/render.js.map +1 -1
- package/dist/questions/settled.js +9 -3
- package/dist/questions/settled.js.map +1 -1
- package/dist/questions/slackThread.js +12 -6
- package/dist/questions/slackThread.js.map +1 -1
- package/dist/questions/state.js +18 -5
- package/dist/questions/state.js.map +1 -1
- package/dist/questions/updated.js +32 -24
- package/dist/questions/updated.js.map +1 -1
- package/dist/triggers.d.ts.map +1 -1
- package/dist/triggers.js +150 -126
- package/dist/triggers.js.map +1 -1
- package/dist/webhook.d.ts.map +1 -1
- package/dist/webhook.js +28 -43
- package/dist/webhook.js.map +1 -1
- package/package.json +4 -4
package/dist/actions.js
CHANGED
|
@@ -1,29 +1,33 @@
|
|
|
1
|
+
import { createPieceFile, filesCollectionSlug } from 'frogbot/pieces';
|
|
1
2
|
import { z } from 'zod';
|
|
2
|
-
import { slackApiResult, slackResponse, slackValue, slackValues
|
|
3
|
+
import { slackApiResult, slackResponse, slackValue, slackValues } from './client.js';
|
|
3
4
|
import { defineAction } from './define.js';
|
|
4
5
|
import { loadSlackFile, slackFile } from './files.js';
|
|
5
6
|
import { channelOptions, userOptions } from './options.js';
|
|
6
|
-
const channel = z.string().min(1).meta({
|
|
7
|
-
|
|
7
|
+
const channel = z.string().min(1).meta({
|
|
8
|
+
label: 'Channel'
|
|
9
|
+
});
|
|
10
|
+
const user = z.string().min(1).meta({
|
|
11
|
+
label: 'User'
|
|
12
|
+
});
|
|
8
13
|
const timestamp = z.string().regex(/^(?:.*\/p\d{16}|\d+\.\d{6})$/, 'Invalid Slack timestamp.');
|
|
9
14
|
const blocks = z.array(slackValue).default([]);
|
|
10
15
|
const messageResult = slackResponse.extend({
|
|
11
16
|
channel: z.string().optional(),
|
|
12
|
-
ts: z.string().optional()
|
|
17
|
+
ts: z.string().optional()
|
|
13
18
|
});
|
|
14
19
|
function normalizeTimestamp(value) {
|
|
15
20
|
const link = value.match(/\/p(\d+)(\d{6})$/);
|
|
16
21
|
return link ? `${link[1]}.${link[2]}` : value;
|
|
17
22
|
}
|
|
18
|
-
async function upload({ client, file, channelId, title, initialComment, threadTimestamp, token = 'bot', signal
|
|
19
|
-
const created = await client.request('files.getUploadURLExternal', {
|
|
23
|
+
async function upload({ client, file, channelId, title, initialComment, threadTimestamp, token = 'bot', signal }) {
|
|
24
|
+
const created = await client.request('files.getUploadURLExternal', {
|
|
25
|
+
filename: file.name,
|
|
26
|
+
length: file.data.size
|
|
27
|
+
}, token);
|
|
20
28
|
const uploadUrl = typeof created.upload_url === 'string' ? new URL(created.upload_url) : undefined;
|
|
21
29
|
const fileId = typeof created.file_id === 'string' ? created.file_id : undefined;
|
|
22
|
-
if (!uploadUrl ||
|
|
23
|
-
!fileId ||
|
|
24
|
-
uploadUrl.protocol !== 'https:' ||
|
|
25
|
-
uploadUrl.username ||
|
|
26
|
-
uploadUrl.password) {
|
|
30
|
+
if (!uploadUrl || !fileId || uploadUrl.protocol !== 'https:' || uploadUrl.username || uploadUrl.password) {
|
|
27
31
|
throw new Error('Slack returned an invalid file upload target.');
|
|
28
32
|
}
|
|
29
33
|
if (uploadUrl.hostname !== 'files.slack.com' && !uploadUrl.hostname.endsWith('.slack.com')) {
|
|
@@ -33,15 +37,19 @@ async function upload({ client, file, channelId, title, initialComment, threadTi
|
|
|
33
37
|
method: 'POST',
|
|
34
38
|
body: file.data,
|
|
35
39
|
redirect: 'error',
|
|
36
|
-
signal
|
|
40
|
+
signal
|
|
37
41
|
});
|
|
38
|
-
if (!response.ok)
|
|
39
|
-
throw new Error(`Slack file upload failed (${response.status}).`);
|
|
42
|
+
if (!response.ok) throw new Error(`Slack file upload failed (${response.status}).`);
|
|
40
43
|
return client.request('files.completeUploadExternal', {
|
|
41
|
-
files: [
|
|
44
|
+
files: [
|
|
45
|
+
{
|
|
46
|
+
id: fileId,
|
|
47
|
+
title
|
|
48
|
+
}
|
|
49
|
+
],
|
|
42
50
|
channel_id: channelId,
|
|
43
51
|
initial_comment: initialComment,
|
|
44
|
-
thread_ts: threadTimestamp
|
|
52
|
+
thread_ts: threadTimestamp
|
|
45
53
|
}, token);
|
|
46
54
|
}
|
|
47
55
|
const messageFields = {
|
|
@@ -50,17 +58,22 @@ const messageFields = {
|
|
|
50
58
|
profilePicture: z.url().optional(),
|
|
51
59
|
iconEmoji: z.string().optional(),
|
|
52
60
|
blocks,
|
|
53
|
-
unfurlLinks: z.boolean().default(true)
|
|
61
|
+
unfurlLinks: z.boolean().default(true)
|
|
54
62
|
};
|
|
55
|
-
const sendDirectMessageInput = z.object({
|
|
63
|
+
const sendDirectMessageInput = z.object({
|
|
64
|
+
userId: user,
|
|
65
|
+
...messageFields
|
|
66
|
+
});
|
|
56
67
|
export const sendDirectMessage = defineAction({
|
|
57
68
|
slug: 'sendDirectMessage',
|
|
58
69
|
description: 'Send a direct message to a Slack user.',
|
|
59
70
|
input: sendDirectMessageInput,
|
|
60
71
|
output: messageResult,
|
|
61
72
|
idempotent: false,
|
|
62
|
-
options: {
|
|
63
|
-
|
|
73
|
+
options: {
|
|
74
|
+
userId: userOptions
|
|
75
|
+
},
|
|
76
|
+
async run ({ client, input }) {
|
|
64
77
|
return client.request('chat.postMessage', {
|
|
65
78
|
channel: input.userId,
|
|
66
79
|
text: input.text,
|
|
@@ -68,12 +81,11 @@ export const sendDirectMessage = defineAction({
|
|
|
68
81
|
icon_url: input.profilePicture,
|
|
69
82
|
icon_emoji: input.iconEmoji,
|
|
70
83
|
blocks: input.blocks,
|
|
71
|
-
unfurl_links: input.unfurlLinks
|
|
84
|
+
unfurl_links: input.unfurlLinks
|
|
72
85
|
});
|
|
73
|
-
}
|
|
86
|
+
}
|
|
74
87
|
});
|
|
75
|
-
const sendChannelInput = z
|
|
76
|
-
.object({
|
|
88
|
+
const sendChannelInput = z.object({
|
|
77
89
|
channel,
|
|
78
90
|
text: z.string().optional(),
|
|
79
91
|
sendAsBot: z.boolean().default(true),
|
|
@@ -84,10 +96,9 @@ const sendChannelInput = z
|
|
|
84
96
|
file: slackFile.optional(),
|
|
85
97
|
replyBroadcast: z.boolean().default(false),
|
|
86
98
|
unfurlLinks: z.boolean().default(true),
|
|
87
|
-
blocks
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
message: 'A message or Block Kit blocks are required.',
|
|
99
|
+
blocks
|
|
100
|
+
}).refine(({ text, blocks: value })=>Boolean(text) || value.length > 0, {
|
|
101
|
+
message: 'A message or Block Kit blocks are required.'
|
|
91
102
|
});
|
|
92
103
|
export const sendChannelMessage = defineAction({
|
|
93
104
|
slug: 'sendChannelMessage',
|
|
@@ -95,8 +106,10 @@ export const sendChannelMessage = defineAction({
|
|
|
95
106
|
input: sendChannelInput,
|
|
96
107
|
output: slackResponse,
|
|
97
108
|
idempotent: false,
|
|
98
|
-
options: {
|
|
99
|
-
|
|
109
|
+
options: {
|
|
110
|
+
channel: channelOptions
|
|
111
|
+
},
|
|
112
|
+
async run ({ client, input, req }) {
|
|
100
113
|
const token = input.sendAsBot ? 'bot' : 'user';
|
|
101
114
|
if (input.file) {
|
|
102
115
|
const file = await loadSlackFile(req, input.file);
|
|
@@ -105,11 +118,9 @@ export const sendChannelMessage = defineAction({
|
|
|
105
118
|
file,
|
|
106
119
|
channelId: input.channel,
|
|
107
120
|
initialComment: input.text,
|
|
108
|
-
threadTimestamp: input.threadTimestamp
|
|
109
|
-
? normalizeTimestamp(input.threadTimestamp)
|
|
110
|
-
: undefined,
|
|
121
|
+
threadTimestamp: input.threadTimestamp ? normalizeTimestamp(input.threadTimestamp) : undefined,
|
|
111
122
|
token,
|
|
112
|
-
signal: req.signal
|
|
123
|
+
signal: req.signal
|
|
113
124
|
});
|
|
114
125
|
}
|
|
115
126
|
return client.request('chat.postMessage', {
|
|
@@ -121,15 +132,15 @@ export const sendChannelMessage = defineAction({
|
|
|
121
132
|
icon_emoji: input.iconEmoji,
|
|
122
133
|
reply_broadcast: input.replyBroadcast,
|
|
123
134
|
unfurl_links: input.unfurlLinks,
|
|
124
|
-
blocks: input.blocks
|
|
135
|
+
blocks: input.blocks
|
|
125
136
|
}, token);
|
|
126
|
-
}
|
|
137
|
+
}
|
|
127
138
|
});
|
|
128
139
|
const addReactionInput = z.object({
|
|
129
140
|
channel,
|
|
130
141
|
timestamp,
|
|
131
142
|
reaction: z.string().min(1),
|
|
132
|
-
reactAsUser: z.boolean().default(false)
|
|
143
|
+
reactAsUser: z.boolean().default(false)
|
|
133
144
|
});
|
|
134
145
|
export const addReaction = defineAction({
|
|
135
146
|
slug: 'addReaction',
|
|
@@ -137,20 +148,22 @@ export const addReaction = defineAction({
|
|
|
137
148
|
input: addReactionInput,
|
|
138
149
|
output: slackResponse,
|
|
139
150
|
idempotent: true,
|
|
140
|
-
options: {
|
|
141
|
-
|
|
151
|
+
options: {
|
|
152
|
+
channel: channelOptions
|
|
153
|
+
},
|
|
154
|
+
async run ({ client, input }) {
|
|
142
155
|
return client.request('reactions.add', {
|
|
143
156
|
channel: input.channel,
|
|
144
157
|
timestamp: normalizeTimestamp(input.timestamp),
|
|
145
|
-
name: input.reaction
|
|
158
|
+
name: input.reaction
|
|
146
159
|
}, input.reactAsUser ? 'user' : 'bot');
|
|
147
|
-
}
|
|
160
|
+
}
|
|
148
161
|
});
|
|
149
162
|
const uploadFileInput = z.object({
|
|
150
163
|
file: slackFile,
|
|
151
164
|
title: z.string().optional(),
|
|
152
165
|
filename: z.string().optional(),
|
|
153
|
-
channel: channel.optional()
|
|
166
|
+
channel: channel.optional()
|
|
154
167
|
});
|
|
155
168
|
export const uploadFile = defineAction({
|
|
156
169
|
slug: 'uploadFile',
|
|
@@ -158,65 +171,66 @@ export const uploadFile = defineAction({
|
|
|
158
171
|
input: uploadFileInput,
|
|
159
172
|
output: slackResponse,
|
|
160
173
|
idempotent: false,
|
|
161
|
-
options: {
|
|
162
|
-
|
|
174
|
+
options: {
|
|
175
|
+
channel: channelOptions
|
|
176
|
+
},
|
|
177
|
+
async run ({ client, input, req }) {
|
|
163
178
|
const loaded = await loadSlackFile(req, {
|
|
164
179
|
...input.file,
|
|
165
|
-
name: input.filename ?? input.file.name
|
|
180
|
+
name: input.filename ?? input.file.name
|
|
166
181
|
});
|
|
167
182
|
return upload({
|
|
168
183
|
client,
|
|
169
184
|
file: loaded,
|
|
170
185
|
channelId: input.channel,
|
|
171
186
|
title: input.title,
|
|
172
|
-
signal: req.signal
|
|
187
|
+
signal: req.signal
|
|
173
188
|
});
|
|
174
|
-
}
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
const getFileInput = z.object({
|
|
192
|
+
fileId: z.string().min(1)
|
|
175
193
|
});
|
|
176
|
-
const getFileInput = z.object({ fileId: z.string().min(1) });
|
|
177
194
|
export const getFile = defineAction({
|
|
178
195
|
slug: 'getFile',
|
|
179
196
|
description: 'Get Slack file metadata and safely download its contents.',
|
|
180
197
|
input: getFileInput,
|
|
181
198
|
output: slackValue,
|
|
182
199
|
idempotent: true,
|
|
183
|
-
async run({ client, input, req }) {
|
|
184
|
-
const response = await client.request('files.info', {
|
|
200
|
+
async run ({ client, input, req }) {
|
|
201
|
+
const response = await client.request('files.info', {
|
|
202
|
+
file: input.fileId
|
|
203
|
+
});
|
|
185
204
|
const file = response.file;
|
|
186
|
-
if (!file ||
|
|
187
|
-
typeof file !== 'object' ||
|
|
188
|
-
!('url_private_download' in file) ||
|
|
189
|
-
typeof file.url_private_download !== 'string') {
|
|
205
|
+
if (!file || typeof file !== 'object' || !('url_private_download' in file) || typeof file.url_private_download !== 'string') {
|
|
190
206
|
throw new Error('Slack file has no download URL.');
|
|
191
207
|
}
|
|
192
208
|
const url = new URL(file.url_private_download);
|
|
193
|
-
if (url.protocol !== 'https:' ||
|
|
194
|
-
url.hostname !== 'files.slack.com' ||
|
|
195
|
-
url.username ||
|
|
196
|
-
url.password) {
|
|
209
|
+
if (url.protocol !== 'https:' || url.hostname !== 'files.slack.com' || url.username || url.password) {
|
|
197
210
|
throw new Error('Slack file download URL is untrusted.');
|
|
198
211
|
}
|
|
199
212
|
const downloaded = await fetch(url, {
|
|
200
|
-
headers: {
|
|
213
|
+
headers: {
|
|
214
|
+
authorization: `Bearer ${client.token()}`
|
|
215
|
+
},
|
|
201
216
|
redirect: 'error',
|
|
202
|
-
signal: req.signal
|
|
217
|
+
signal: req.signal
|
|
203
218
|
});
|
|
204
|
-
if (!downloaded.ok)
|
|
205
|
-
throw new Error(`Slack file download failed (${downloaded.status}).`);
|
|
219
|
+
if (!downloaded.ok) throw new Error(`Slack file download failed (${downloaded.status}).`);
|
|
206
220
|
const data = Buffer.from(await downloaded.arrayBuffer());
|
|
207
221
|
const name = 'name' in file && typeof file.name === 'string' ? file.name : `slack-${input.fileId}`;
|
|
208
222
|
const mimeType = downloaded.headers.get('content-type')?.split(';')[0] || 'application/octet-stream';
|
|
209
|
-
|
|
210
|
-
if (!collection) {
|
|
211
|
-
throw new Error('[frogbot] Slack file downloads require the files collection.');
|
|
212
|
-
}
|
|
223
|
+
filesCollectionSlug(req, 'Slack');
|
|
213
224
|
req.signal?.throwIfAborted();
|
|
214
|
-
const saved = await req
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
225
|
+
const saved = await createPieceFile(req, 'Slack', {
|
|
226
|
+
file: {
|
|
227
|
+
data,
|
|
228
|
+
name,
|
|
229
|
+
mimetype: mimeType,
|
|
230
|
+
size: data.length
|
|
231
|
+
},
|
|
218
232
|
req,
|
|
219
|
-
overrideAccess: false
|
|
233
|
+
overrideAccess: false
|
|
220
234
|
});
|
|
221
235
|
return {
|
|
222
236
|
...file,
|
|
@@ -225,96 +239,104 @@ export const getFile = defineAction({
|
|
|
225
239
|
name,
|
|
226
240
|
mimeType,
|
|
227
241
|
size: data.length,
|
|
228
|
-
url: typeof saved.url === 'string' ? saved.url : undefined
|
|
229
|
-
}
|
|
242
|
+
url: typeof saved.url === 'string' ? saved.url : undefined
|
|
243
|
+
}
|
|
230
244
|
};
|
|
231
|
-
}
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
const searchMessagesInput = z.object({
|
|
248
|
+
query: z.string().min(1)
|
|
232
249
|
});
|
|
233
|
-
const searchMessagesInput = z.object({ query: z.string().min(1) });
|
|
234
250
|
export const searchMessages = defineAction({
|
|
235
251
|
slug: 'searchMessages',
|
|
236
252
|
description: 'Search all Slack messages matching a query.',
|
|
237
253
|
input: searchMessagesInput,
|
|
238
254
|
output: slackValues,
|
|
239
255
|
idempotent: true,
|
|
240
|
-
async run({ client, input }) {
|
|
256
|
+
async run ({ client, input }) {
|
|
241
257
|
const matches = [];
|
|
242
258
|
let cursor = '*';
|
|
243
259
|
do {
|
|
244
|
-
const response = await client.request('search.messages', {
|
|
260
|
+
const response = await client.request('search.messages', {
|
|
261
|
+
query: input.query,
|
|
262
|
+
count: 100,
|
|
263
|
+
cursor
|
|
264
|
+
}, 'user');
|
|
245
265
|
const messages = response.messages;
|
|
246
|
-
if (!messages || typeof messages !== 'object')
|
|
247
|
-
break;
|
|
266
|
+
if (!messages || typeof messages !== 'object') break;
|
|
248
267
|
if ('matches' in messages && Array.isArray(messages.matches)) {
|
|
249
|
-
for (const match of messages.matches)
|
|
268
|
+
for (const match of messages.matches){
|
|
250
269
|
if (match && typeof match === 'object' && !Array.isArray(match)) {
|
|
251
270
|
matches.push(Object.fromEntries(Object.entries(match)));
|
|
252
271
|
}
|
|
253
272
|
}
|
|
254
273
|
}
|
|
255
274
|
const pagination = 'pagination' in messages ? messages.pagination : undefined;
|
|
256
|
-
cursor =
|
|
257
|
-
|
|
258
|
-
? String(pagination.next_cursor || '') || undefined
|
|
259
|
-
: undefined;
|
|
260
|
-
} while (cursor);
|
|
275
|
+
cursor = pagination && typeof pagination === 'object' && 'next_cursor' in pagination ? String(pagination.next_cursor || '') || undefined : undefined;
|
|
276
|
+
}while (cursor)
|
|
261
277
|
return matches;
|
|
262
|
-
}
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
const emailInput = z.object({
|
|
281
|
+
email: z.email()
|
|
263
282
|
});
|
|
264
|
-
const emailInput = z.object({ email: z.email() });
|
|
265
283
|
export const findUserByEmail = defineAction({
|
|
266
284
|
slug: 'findUserByEmail',
|
|
267
285
|
description: 'Find a Slack user by exact email address.',
|
|
268
286
|
input: emailInput,
|
|
269
287
|
output: slackResponse,
|
|
270
288
|
idempotent: true,
|
|
271
|
-
async run({ client, input }) {
|
|
289
|
+
async run ({ client, input }) {
|
|
272
290
|
return client.request('users.lookupByEmail', input);
|
|
273
|
-
}
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
const handleInput = z.object({
|
|
294
|
+
handle: z.string().min(1)
|
|
274
295
|
});
|
|
275
|
-
const handleInput = z.object({ handle: z.string().min(1) });
|
|
276
296
|
export const findUserByHandle = defineAction({
|
|
277
297
|
slug: 'findUserByHandle',
|
|
278
298
|
description: 'Find a Slack user by display-name handle.',
|
|
279
299
|
input: handleInput,
|
|
280
300
|
output: slackValue,
|
|
281
301
|
idempotent: true,
|
|
282
|
-
async run({ client, input }) {
|
|
302
|
+
async run ({ client, input }) {
|
|
283
303
|
const handle = input.handle.replace(/^@/, '');
|
|
284
304
|
const members = await client.paginate({
|
|
285
305
|
path: 'users.list',
|
|
286
306
|
item: 'members',
|
|
287
|
-
body: {
|
|
307
|
+
body: {
|
|
308
|
+
limit: 1000
|
|
309
|
+
}
|
|
288
310
|
});
|
|
289
|
-
const found = members.find((member)
|
|
290
|
-
if (!member || typeof member !== 'object' || !('profile' in member))
|
|
291
|
-
return false;
|
|
311
|
+
const found = members.find((member)=>{
|
|
312
|
+
if (!member || typeof member !== 'object' || !('profile' in member)) return false;
|
|
292
313
|
const profile = member.profile;
|
|
293
|
-
return
|
|
294
|
-
typeof profile === 'object' &&
|
|
295
|
-
'display_name' in profile &&
|
|
296
|
-
profile.display_name === handle);
|
|
314
|
+
return profile && typeof profile === 'object' && 'display_name' in profile && profile.display_name === handle;
|
|
297
315
|
});
|
|
298
316
|
if (!found || typeof found !== 'object') {
|
|
299
317
|
throw new Error(`Could not find user with handle @${handle}`);
|
|
300
318
|
}
|
|
301
319
|
return found;
|
|
302
|
-
}
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
const findUserByIdInput = z.object({
|
|
323
|
+
id: z.string().min(1)
|
|
303
324
|
});
|
|
304
|
-
const findUserByIdInput = z.object({ id: z.string().min(1) });
|
|
305
325
|
export const findUserById = defineAction({
|
|
306
326
|
slug: 'findUserById',
|
|
307
327
|
description: 'Find a Slack user profile by ID.',
|
|
308
328
|
input: findUserByIdInput,
|
|
309
329
|
output: slackResponse,
|
|
310
330
|
idempotent: true,
|
|
311
|
-
async run({ client, input }) {
|
|
312
|
-
return client.request('users.profile.get', {
|
|
313
|
-
|
|
331
|
+
async run ({ client, input }) {
|
|
332
|
+
return client.request('users.profile.get', {
|
|
333
|
+
user: input.id
|
|
334
|
+
});
|
|
335
|
+
}
|
|
314
336
|
});
|
|
315
337
|
const listUsersInput = z.object({
|
|
316
338
|
includeBots: z.boolean().default(false),
|
|
317
|
-
includeDisabled: z.boolean().default(false)
|
|
339
|
+
includeDisabled: z.boolean().default(false)
|
|
318
340
|
});
|
|
319
341
|
export const listUsers = defineAction({
|
|
320
342
|
slug: 'listUsers',
|
|
@@ -322,60 +344,79 @@ export const listUsers = defineAction({
|
|
|
322
344
|
input: listUsersInput,
|
|
323
345
|
output: slackValues,
|
|
324
346
|
idempotent: true,
|
|
325
|
-
async run({ client, input }) {
|
|
347
|
+
async run ({ client, input }) {
|
|
326
348
|
const members = await client.paginate({
|
|
327
349
|
path: 'users.list',
|
|
328
350
|
item: 'members',
|
|
329
|
-
body: {
|
|
351
|
+
body: {
|
|
352
|
+
limit: 1000
|
|
353
|
+
}
|
|
330
354
|
});
|
|
331
|
-
return members.filter((member)
|
|
332
|
-
if (!member || typeof member !== 'object')
|
|
333
|
-
|
|
334
|
-
if (!input.
|
|
335
|
-
return false;
|
|
336
|
-
if (!input.includeDisabled && 'deleted' in member && member.deleted === true)
|
|
337
|
-
return false;
|
|
355
|
+
return members.filter((member)=>{
|
|
356
|
+
if (!member || typeof member !== 'object') return false;
|
|
357
|
+
if (!input.includeBots && 'is_bot' in member && member.is_bot === true) return false;
|
|
358
|
+
if (!input.includeDisabled && 'deleted' in member && member.deleted === true) return false;
|
|
338
359
|
return true;
|
|
339
360
|
});
|
|
340
|
-
}
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
const updateMessageInput = z.object({
|
|
364
|
+
channel,
|
|
365
|
+
timestamp,
|
|
366
|
+
text: z.string().min(1),
|
|
367
|
+
blocks
|
|
341
368
|
});
|
|
342
|
-
const updateMessageInput = z.object({ channel, timestamp, text: z.string().min(1), blocks });
|
|
343
369
|
export const updateMessage = defineAction({
|
|
344
370
|
slug: 'updateMessage',
|
|
345
371
|
description: 'Update an existing Slack message.',
|
|
346
372
|
input: updateMessageInput,
|
|
347
373
|
output: slackResponse,
|
|
348
374
|
idempotent: true,
|
|
349
|
-
options: {
|
|
350
|
-
|
|
375
|
+
options: {
|
|
376
|
+
channel: channelOptions
|
|
377
|
+
},
|
|
378
|
+
async run ({ client, input }) {
|
|
351
379
|
return client.request('chat.update', {
|
|
352
380
|
channel: input.channel,
|
|
353
381
|
ts: normalizeTimestamp(input.timestamp),
|
|
354
382
|
text: input.text,
|
|
355
|
-
blocks: input.blocks
|
|
383
|
+
blocks: input.blocks
|
|
356
384
|
});
|
|
357
|
-
}
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
const deleteMessageInput = z.object({
|
|
388
|
+
channel,
|
|
389
|
+
timestamp
|
|
358
390
|
});
|
|
359
|
-
const deleteMessageInput = z.object({ channel, timestamp });
|
|
360
391
|
export const deleteMessage = defineAction({
|
|
361
392
|
slug: 'deleteMessage',
|
|
362
393
|
description: 'Delete a Slack message after confirming it exists.',
|
|
363
394
|
input: deleteMessageInput,
|
|
364
395
|
output: slackResponse,
|
|
365
396
|
idempotent: false,
|
|
366
|
-
options: {
|
|
367
|
-
|
|
397
|
+
options: {
|
|
398
|
+
channel: channelOptions
|
|
399
|
+
},
|
|
400
|
+
async run ({ client, input }) {
|
|
368
401
|
const ts = normalizeTimestamp(input.timestamp);
|
|
369
|
-
const history = await client.request('conversations.history', {
|
|
402
|
+
const history = await client.request('conversations.history', {
|
|
403
|
+
channel: input.channel,
|
|
404
|
+
oldest: ts,
|
|
405
|
+
limit: 1,
|
|
406
|
+
inclusive: true
|
|
407
|
+
}, 'user');
|
|
370
408
|
if (!Array.isArray(history.messages) || history.messages.length === 0) {
|
|
371
409
|
throw new Error('No message found for the provided timestamp.');
|
|
372
410
|
}
|
|
373
|
-
return client.request('chat.delete', {
|
|
374
|
-
|
|
411
|
+
return client.request('chat.delete', {
|
|
412
|
+
channel: input.channel,
|
|
413
|
+
ts
|
|
414
|
+
}, 'user');
|
|
415
|
+
}
|
|
375
416
|
});
|
|
376
417
|
const createChannelInput = z.object({
|
|
377
418
|
channelName: z.string().min(1),
|
|
378
|
-
isPrivate: z.boolean().default(false)
|
|
419
|
+
isPrivate: z.boolean().default(false)
|
|
379
420
|
});
|
|
380
421
|
export const createChannel = defineAction({
|
|
381
422
|
slug: 'createChannel',
|
|
@@ -383,18 +424,18 @@ export const createChannel = defineAction({
|
|
|
383
424
|
input: createChannelInput,
|
|
384
425
|
output: slackResponse,
|
|
385
426
|
idempotent: false,
|
|
386
|
-
async run({ client, input }) {
|
|
427
|
+
async run ({ client, input }) {
|
|
387
428
|
return client.request('conversations.create', {
|
|
388
429
|
name: input.channelName,
|
|
389
|
-
is_private: input.isPrivate
|
|
430
|
+
is_private: input.isPrivate
|
|
390
431
|
});
|
|
391
|
-
}
|
|
432
|
+
}
|
|
392
433
|
});
|
|
393
434
|
const updateProfileInput = z.object({
|
|
394
435
|
firstName: z.string().optional(),
|
|
395
436
|
lastName: z.string().optional(),
|
|
396
437
|
email: z.email().optional(),
|
|
397
|
-
userId: z.string().optional()
|
|
438
|
+
userId: z.string().optional()
|
|
398
439
|
});
|
|
399
440
|
export const updateProfile = defineAction({
|
|
400
441
|
slug: 'updateProfile',
|
|
@@ -402,19 +443,23 @@ export const updateProfile = defineAction({
|
|
|
402
443
|
input: updateProfileInput,
|
|
403
444
|
output: slackResponse,
|
|
404
445
|
idempotent: true,
|
|
405
|
-
async run({ client, input }) {
|
|
446
|
+
async run ({ client, input }) {
|
|
406
447
|
return client.request('users.profile.set', {
|
|
407
|
-
profile: {
|
|
408
|
-
|
|
448
|
+
profile: {
|
|
449
|
+
first_name: input.firstName,
|
|
450
|
+
last_name: input.lastName,
|
|
451
|
+
email: input.email
|
|
452
|
+
},
|
|
453
|
+
user: input.userId
|
|
409
454
|
}, 'user');
|
|
410
|
-
}
|
|
455
|
+
}
|
|
411
456
|
});
|
|
412
457
|
const getChannelHistoryInput = z.object({
|
|
413
458
|
channel,
|
|
414
459
|
oldest: z.number().optional(),
|
|
415
460
|
latest: z.number().optional(),
|
|
416
461
|
inclusive: z.boolean().default(false),
|
|
417
|
-
includeAllMetadata: z.boolean().default(false)
|
|
462
|
+
includeAllMetadata: z.boolean().default(false)
|
|
418
463
|
});
|
|
419
464
|
export const getChannelHistory = defineAction({
|
|
420
465
|
slug: 'getChannelHistory',
|
|
@@ -422,8 +467,10 @@ export const getChannelHistory = defineAction({
|
|
|
422
467
|
input: getChannelHistoryInput,
|
|
423
468
|
output: slackValues,
|
|
424
469
|
idempotent: true,
|
|
425
|
-
options: {
|
|
426
|
-
|
|
470
|
+
options: {
|
|
471
|
+
channel: channelOptions
|
|
472
|
+
},
|
|
473
|
+
async run ({ client, input }) {
|
|
427
474
|
return client.paginate({
|
|
428
475
|
path: 'conversations.history',
|
|
429
476
|
item: 'messages',
|
|
@@ -433,15 +480,15 @@ export const getChannelHistory = defineAction({
|
|
|
433
480
|
latest: input.latest,
|
|
434
481
|
inclusive: input.inclusive,
|
|
435
482
|
include_all_metadata: input.includeAllMetadata,
|
|
436
|
-
limit: 200
|
|
437
|
-
}
|
|
483
|
+
limit: 200
|
|
484
|
+
}
|
|
438
485
|
});
|
|
439
|
-
}
|
|
486
|
+
}
|
|
440
487
|
});
|
|
441
488
|
const setUserStatusInput = z.object({
|
|
442
489
|
text: z.string().max(100),
|
|
443
490
|
emoji: z.string().optional(),
|
|
444
|
-
expiration: z.number().int().optional()
|
|
491
|
+
expiration: z.number().int().optional()
|
|
445
492
|
});
|
|
446
493
|
export const setUserStatus = defineAction({
|
|
447
494
|
slug: 'setUserStatus',
|
|
@@ -449,88 +496,118 @@ export const setUserStatus = defineAction({
|
|
|
449
496
|
input: setUserStatusInput,
|
|
450
497
|
output: slackResponse,
|
|
451
498
|
idempotent: true,
|
|
452
|
-
async run({ client, input }) {
|
|
499
|
+
async run ({ client, input }) {
|
|
453
500
|
return client.request('users.profile.set', {
|
|
454
501
|
profile: {
|
|
455
502
|
status_text: input.text,
|
|
456
503
|
status_emoji: input.emoji,
|
|
457
|
-
status_expiration: input.expiration
|
|
458
|
-
}
|
|
504
|
+
status_expiration: input.expiration
|
|
505
|
+
}
|
|
459
506
|
}, 'user');
|
|
460
|
-
}
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
const markdownToSlackInput = z.object({
|
|
510
|
+
markdown: z.string()
|
|
511
|
+
});
|
|
512
|
+
const markdownToSlackOutput = z.object({
|
|
513
|
+
text: z.string()
|
|
461
514
|
});
|
|
462
|
-
const markdownToSlackInput = z.object({ markdown: z.string() });
|
|
463
|
-
const markdownToSlackOutput = z.object({ text: z.string() });
|
|
464
515
|
export const markdownToSlack = defineAction({
|
|
465
516
|
slug: 'markdownToSlack',
|
|
466
517
|
description: 'Convert Markdown text to Slack mrkdwn.',
|
|
467
518
|
input: markdownToSlackInput,
|
|
468
519
|
output: markdownToSlackOutput,
|
|
469
520
|
idempotent: true,
|
|
470
|
-
|
|
471
|
-
const text = input.markdown
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
521
|
+
run ({ input }) {
|
|
522
|
+
const text = input.markdown.replace(/\[([^\]]+)]\((https?:\/\/[^)]+)\)/g, '<$2|$1>').replace(/\*\*([^*]+)\*\*/g, '*$1*').replace(/^[-+] /gm, '• ');
|
|
523
|
+
return Promise.resolve({
|
|
524
|
+
text
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
const listThreadMessagesInput = z.object({
|
|
529
|
+
channel,
|
|
530
|
+
threadTimestamp: timestamp
|
|
477
531
|
});
|
|
478
|
-
const listThreadMessagesInput = z.object({ channel, threadTimestamp: timestamp });
|
|
479
532
|
export const listThreadMessages = defineAction({
|
|
480
533
|
slug: 'listThreadMessages',
|
|
481
534
|
description: 'Retrieve all messages in a Slack thread.',
|
|
482
535
|
input: listThreadMessagesInput,
|
|
483
536
|
output: slackValues,
|
|
484
537
|
idempotent: true,
|
|
485
|
-
options: {
|
|
486
|
-
|
|
538
|
+
options: {
|
|
539
|
+
channel: channelOptions
|
|
540
|
+
},
|
|
541
|
+
async run ({ client, input }) {
|
|
487
542
|
return client.paginate({
|
|
488
543
|
path: 'conversations.replies',
|
|
489
544
|
item: 'messages',
|
|
490
|
-
body: {
|
|
545
|
+
body: {
|
|
546
|
+
channel: input.channel,
|
|
547
|
+
ts: normalizeTimestamp(input.threadTimestamp)
|
|
548
|
+
}
|
|
491
549
|
});
|
|
492
|
-
}
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
const setChannelTopicInput = z.object({
|
|
553
|
+
channel,
|
|
554
|
+
topic: z.string()
|
|
493
555
|
});
|
|
494
|
-
const setChannelTopicInput = z.object({ channel, topic: z.string() });
|
|
495
556
|
export const setChannelTopic = defineAction({
|
|
496
557
|
slug: 'setChannelTopic',
|
|
497
558
|
description: 'Set a Slack channel topic.',
|
|
498
559
|
input: setChannelTopicInput,
|
|
499
560
|
output: slackResponse,
|
|
500
561
|
idempotent: true,
|
|
501
|
-
options: {
|
|
502
|
-
|
|
503
|
-
return client.request('conversations.setTopic', input);
|
|
562
|
+
options: {
|
|
563
|
+
channel: channelOptions
|
|
504
564
|
},
|
|
565
|
+
async run ({ client, input }) {
|
|
566
|
+
return client.request('conversations.setTopic', input);
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
const getMessageInput = z.object({
|
|
570
|
+
channel,
|
|
571
|
+
timestamp
|
|
505
572
|
});
|
|
506
|
-
const getMessageInput = z.object({ channel, timestamp });
|
|
507
573
|
export const getMessage = defineAction({
|
|
508
574
|
slug: 'getMessage',
|
|
509
575
|
description: 'Get a Slack message by channel and timestamp.',
|
|
510
576
|
input: getMessageInput,
|
|
511
577
|
output: slackResponse,
|
|
512
578
|
idempotent: true,
|
|
513
|
-
options: {
|
|
514
|
-
|
|
579
|
+
options: {
|
|
580
|
+
channel: channelOptions
|
|
581
|
+
},
|
|
582
|
+
async run ({ client, input }) {
|
|
515
583
|
return client.request('conversations.history', {
|
|
516
584
|
channel: input.channel,
|
|
517
585
|
oldest: normalizeTimestamp(input.timestamp),
|
|
518
586
|
limit: 1,
|
|
519
|
-
inclusive: true
|
|
587
|
+
inclusive: true
|
|
520
588
|
});
|
|
521
|
-
}
|
|
589
|
+
}
|
|
590
|
+
});
|
|
591
|
+
const inviteUserToChannelInput = z.object({
|
|
592
|
+
channel,
|
|
593
|
+
userId: user
|
|
522
594
|
});
|
|
523
|
-
const inviteUserToChannelInput = z.object({ channel, userId: user });
|
|
524
595
|
export const inviteUserToChannel = defineAction({
|
|
525
596
|
slug: 'inviteUserToChannel',
|
|
526
597
|
description: 'Invite an existing user to a Slack channel.',
|
|
527
598
|
input: inviteUserToChannelInput,
|
|
528
599
|
output: slackResponse,
|
|
529
600
|
idempotent: false,
|
|
530
|
-
options: {
|
|
531
|
-
|
|
532
|
-
|
|
601
|
+
options: {
|
|
602
|
+
channel: channelOptions,
|
|
603
|
+
userId: userOptions
|
|
533
604
|
},
|
|
605
|
+
async run ({ client, input }) {
|
|
606
|
+
return client.request('conversations.invite', {
|
|
607
|
+
channel: input.channel,
|
|
608
|
+
users: input.userId
|
|
609
|
+
});
|
|
610
|
+
}
|
|
534
611
|
});
|
|
535
612
|
export const getUserGroupByHandle = defineAction({
|
|
536
613
|
slug: 'getUserGroupByHandle',
|
|
@@ -538,18 +615,15 @@ export const getUserGroupByHandle = defineAction({
|
|
|
538
615
|
input: handleInput,
|
|
539
616
|
output: slackValue,
|
|
540
617
|
idempotent: true,
|
|
541
|
-
async run({ client, input }) {
|
|
618
|
+
async run ({ client, input }) {
|
|
542
619
|
return findUserGroup(client, input.handle);
|
|
543
|
-
}
|
|
620
|
+
}
|
|
544
621
|
});
|
|
545
622
|
async function findUserGroup(client, value) {
|
|
546
623
|
const handle = value.replace(/^@/, '').toLowerCase();
|
|
547
624
|
const response = await client.request('usergroups.list');
|
|
548
625
|
const groups = Array.isArray(response.usergroups) ? response.usergroups : [];
|
|
549
|
-
const found = groups.find((group)
|
|
550
|
-
typeof group === 'object' &&
|
|
551
|
-
'handle' in group &&
|
|
552
|
-
String(group.handle).toLowerCase() === handle);
|
|
626
|
+
const found = groups.find((group)=>group && typeof group === 'object' && 'handle' in group && String(group.handle).toLowerCase() === handle);
|
|
553
627
|
if (!found || typeof found !== 'object') {
|
|
554
628
|
throw new Error(`User group with handle '@${handle}' not found.`);
|
|
555
629
|
}
|
|
@@ -557,7 +631,7 @@ async function findUserGroup(client, value) {
|
|
|
557
631
|
}
|
|
558
632
|
const updateUserGroupMembersInput = handleInput.extend({
|
|
559
633
|
userIds: z.array(z.string()).optional(),
|
|
560
|
-
appendUsers: z.boolean().default(true)
|
|
634
|
+
appendUsers: z.boolean().default(true)
|
|
561
635
|
});
|
|
562
636
|
export const updateUserGroupMembers = defineAction({
|
|
563
637
|
slug: 'updateUserGroupMembers',
|
|
@@ -565,23 +639,39 @@ export const updateUserGroupMembers = defineAction({
|
|
|
565
639
|
input: updateUserGroupMembersInput,
|
|
566
640
|
output: slackResponse,
|
|
567
641
|
idempotent: false,
|
|
568
|
-
async run({ client, input }) {
|
|
642
|
+
async run ({ client, input }) {
|
|
569
643
|
const group = await findUserGroup(client, input.handle);
|
|
570
644
|
const id = 'id' in group ? String(group.id) : '';
|
|
571
|
-
const existing = input.appendUsers && 'users' in group && Array.isArray(group.users)
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
645
|
+
const existing = input.appendUsers && 'users' in group && Array.isArray(group.users) ? group.users.map(String) : [];
|
|
646
|
+
const users = [
|
|
647
|
+
...new Set([
|
|
648
|
+
...existing,
|
|
649
|
+
...(input.userIds ?? []).filter(Boolean)
|
|
650
|
+
])
|
|
651
|
+
].join(', ');
|
|
652
|
+
return client.request('usergroups.users.update', {
|
|
653
|
+
usergroup: id,
|
|
654
|
+
users
|
|
655
|
+
}, 'user');
|
|
656
|
+
}
|
|
577
657
|
});
|
|
578
658
|
const customApiInput = z.object({
|
|
579
|
-
method: z.enum([
|
|
659
|
+
method: z.enum([
|
|
660
|
+
'GET',
|
|
661
|
+
'POST',
|
|
662
|
+
'PUT',
|
|
663
|
+
'PATCH',
|
|
664
|
+
'DELETE'
|
|
665
|
+
]),
|
|
580
666
|
path: z.string().regex(/^[a-zA-Z][a-zA-Z0-9._-]*$/),
|
|
581
667
|
headers: z.record(z.string(), z.string()).default({}),
|
|
582
|
-
queryParams: z.record(z.string(), z.union([
|
|
668
|
+
queryParams: z.record(z.string(), z.union([
|
|
669
|
+
z.string(),
|
|
670
|
+
z.number(),
|
|
671
|
+
z.boolean()
|
|
672
|
+
])).default({}),
|
|
583
673
|
body: z.record(z.string(), z.unknown()).optional(),
|
|
584
|
-
useUserToken: z.boolean().default(false)
|
|
674
|
+
useUserToken: z.boolean().default(false)
|
|
585
675
|
});
|
|
586
676
|
export const customApiCall = defineAction({
|
|
587
677
|
slug: 'customApiCall',
|
|
@@ -589,10 +679,9 @@ export const customApiCall = defineAction({
|
|
|
589
679
|
input: customApiInput,
|
|
590
680
|
output: slackApiResult,
|
|
591
681
|
idempotent: false,
|
|
592
|
-
async run({ client, input }) {
|
|
682
|
+
async run ({ client, input }) {
|
|
593
683
|
const query = new URLSearchParams();
|
|
594
|
-
for (const [key, value] of Object.entries(input.queryParams))
|
|
595
|
-
query.set(key, String(value));
|
|
684
|
+
for (const [key, value] of Object.entries(input.queryParams))query.set(key, String(value));
|
|
596
685
|
const suffix = query.size ? `?${query}` : '';
|
|
597
686
|
const headers = new Headers(input.headers);
|
|
598
687
|
headers.delete('authorization');
|
|
@@ -606,9 +695,9 @@ export const customApiCall = defineAction({
|
|
|
606
695
|
method: input.method,
|
|
607
696
|
headers,
|
|
608
697
|
body: input.body === undefined ? undefined : JSON.stringify(input.body),
|
|
609
|
-
token: input.useUserToken ? 'user' : 'bot'
|
|
698
|
+
token: input.useUserToken ? 'user' : 'bot'
|
|
610
699
|
});
|
|
611
|
-
}
|
|
700
|
+
}
|
|
612
701
|
});
|
|
613
702
|
export const slackActions = [
|
|
614
703
|
addReaction,
|
|
@@ -634,6 +723,7 @@ export const slackActions = [
|
|
|
634
723
|
inviteUserToChannel,
|
|
635
724
|
getUserGroupByHandle,
|
|
636
725
|
updateUserGroupMembers,
|
|
637
|
-
customApiCall
|
|
726
|
+
customApiCall
|
|
638
727
|
];
|
|
728
|
+
|
|
639
729
|
//# sourceMappingURL=actions.js.map
|