@unboundcx/sdk 4.8.6 → 4.8.9
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/index.js +3 -0
- package/package.json +1 -1
- package/services/chat.js +851 -0
package/index.js
CHANGED
|
@@ -33,6 +33,7 @@ import { TriggersService } from './services/triggers.js';
|
|
|
33
33
|
import { InboxService } from './services/inbox.js';
|
|
34
34
|
import { SearchService } from './services/search.js';
|
|
35
35
|
import { DirectoryService } from './services/directory.js';
|
|
36
|
+
import { ChatService } from './services/chat.js';
|
|
36
37
|
|
|
37
38
|
class UnboundSDK extends BaseSDK {
|
|
38
39
|
constructor(options = {}) {
|
|
@@ -107,6 +108,7 @@ class UnboundSDK extends BaseSDK {
|
|
|
107
108
|
this.inbox = new InboxService(this);
|
|
108
109
|
this.search = new SearchService(this);
|
|
109
110
|
this.directory = new DirectoryService(this);
|
|
111
|
+
this.chat = new ChatService(this);
|
|
110
112
|
|
|
111
113
|
// Add additional services that might be missing
|
|
112
114
|
this._initializeAdditionalServices();
|
|
@@ -290,4 +292,5 @@ export { PermissionsService } from './services/permissions.js';
|
|
|
290
292
|
export { InboxService } from './services/inbox.js';
|
|
291
293
|
export { SearchService } from './services/search.js';
|
|
292
294
|
export { DirectoryService } from './services/directory.js';
|
|
295
|
+
export { ChatService } from './services/chat.js';
|
|
293
296
|
export { BaseSDK } from './base.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unboundcx/sdk",
|
|
3
|
-
"version": "4.8.
|
|
3
|
+
"version": "4.8.9",
|
|
4
4
|
"description": "Official JavaScript SDK for the Unbound API - A comprehensive toolkit for integrating with Unbound's communication, AI, and data management services",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
package/services/chat.js
ADDED
|
@@ -0,0 +1,851 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatService — channels, DMs, membership, unreads, DND, messages, search,
|
|
3
|
+
* webhooks, card actions, reports, admin review, admin export, record feeds,
|
|
4
|
+
* channel meet, push devices, and notifyLevel.
|
|
5
|
+
* Backed by /chat/* on app1-api (checkApiAuth). Incoming webhook POST
|
|
6
|
+
* (HMAC) is external and is not an SDK method.
|
|
7
|
+
*/
|
|
8
|
+
export class ChatService {
|
|
9
|
+
constructor(sdk) {
|
|
10
|
+
this.sdk = sdk;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Create a channel.
|
|
15
|
+
* @param {Object} params
|
|
16
|
+
* @param {string} params.name - Channel name (required)
|
|
17
|
+
* @param {string} [params.topic]
|
|
18
|
+
* @param {'public'|'private'|'dm'|'group_dm'|'record'|'meeting'} [params.kind]
|
|
19
|
+
* @param {Object} [params.settings]
|
|
20
|
+
* @param {string[]} [params.groupIds] - Groups whose members are auto-added
|
|
21
|
+
* @returns {Promise<Object>} Created channel
|
|
22
|
+
*/
|
|
23
|
+
async createChannel({ name, topic, kind, settings, groupIds }) {
|
|
24
|
+
this.sdk.validateParams(
|
|
25
|
+
{ name, topic, kind, settings, groupIds },
|
|
26
|
+
{
|
|
27
|
+
name: { type: 'string', required: true },
|
|
28
|
+
topic: { type: 'string', required: false },
|
|
29
|
+
kind: { type: 'string', required: false },
|
|
30
|
+
settings: { type: 'object', required: false },
|
|
31
|
+
groupIds: { type: 'array', required: false },
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const body = { name };
|
|
36
|
+
if (topic !== undefined) body.topic = topic;
|
|
37
|
+
if (kind !== undefined) body.kind = kind;
|
|
38
|
+
if (settings !== undefined) body.settings = settings;
|
|
39
|
+
if (groupIds !== undefined) body.groupIds = groupIds;
|
|
40
|
+
|
|
41
|
+
return this.sdk._fetch('/chat/channels', 'POST', { body });
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* List channels the current user is a member of.
|
|
46
|
+
* @returns {Promise<Object>}
|
|
47
|
+
*/
|
|
48
|
+
async listChannels() {
|
|
49
|
+
return this.sdk._fetch('/chat/channels', 'GET');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Browse joinable (public) channels.
|
|
54
|
+
* @returns {Promise<Object>}
|
|
55
|
+
*/
|
|
56
|
+
async browseChannels() {
|
|
57
|
+
return this.sdk._fetch('/chat/channels/browse', 'GET');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get a channel by id.
|
|
62
|
+
* @param {string} id
|
|
63
|
+
* @returns {Promise<Object>}
|
|
64
|
+
*/
|
|
65
|
+
async getChannel(id) {
|
|
66
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
67
|
+
return this.sdk._fetch(`/chat/channels/${id}`, 'GET');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Update channel name/topic/settings.
|
|
72
|
+
* @param {string} id
|
|
73
|
+
* @param {Object} [params]
|
|
74
|
+
* @param {string} [params.name]
|
|
75
|
+
* @param {string} [params.topic]
|
|
76
|
+
* @param {Object} [params.settings]
|
|
77
|
+
* @returns {Promise<Object>}
|
|
78
|
+
*/
|
|
79
|
+
async updateChannel(id, { name, topic, settings } = {}) {
|
|
80
|
+
this.sdk.validateParams(
|
|
81
|
+
{ id, name, topic, settings },
|
|
82
|
+
{
|
|
83
|
+
id: { type: 'string', required: true },
|
|
84
|
+
name: { type: 'string', required: false },
|
|
85
|
+
topic: { type: 'string', required: false },
|
|
86
|
+
settings: { type: 'object', required: false },
|
|
87
|
+
},
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const body = {};
|
|
91
|
+
if (name !== undefined) body.name = name;
|
|
92
|
+
if (topic !== undefined) body.topic = topic;
|
|
93
|
+
if (settings !== undefined) body.settings = settings;
|
|
94
|
+
|
|
95
|
+
return this.sdk._fetch(`/chat/channels/${id}`, 'PATCH', { body });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Archive a channel (reversible; hard delete is not supported).
|
|
100
|
+
* @param {string} id
|
|
101
|
+
* @returns {Promise<Object>}
|
|
102
|
+
*/
|
|
103
|
+
async archiveChannel(id) {
|
|
104
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
105
|
+
return this.sdk._fetch(`/chat/channels/${id}/archive`, 'POST', {
|
|
106
|
+
body: {},
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Unarchive a channel.
|
|
112
|
+
* @param {string} id
|
|
113
|
+
* @returns {Promise<Object>}
|
|
114
|
+
*/
|
|
115
|
+
async unarchiveChannel(id) {
|
|
116
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
117
|
+
return this.sdk._fetch(`/chat/channels/${id}/unarchive`, 'POST', {
|
|
118
|
+
body: {},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Join a public channel.
|
|
124
|
+
* @param {string} id
|
|
125
|
+
* @returns {Promise<Object>}
|
|
126
|
+
*/
|
|
127
|
+
async joinChannel(id) {
|
|
128
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
129
|
+
return this.sdk._fetch(`/chat/channels/${id}/join`, 'POST', { body: {} });
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Leave a channel.
|
|
134
|
+
* @param {string} id
|
|
135
|
+
* @returns {Promise<Object>}
|
|
136
|
+
*/
|
|
137
|
+
async leaveChannel(id) {
|
|
138
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
139
|
+
return this.sdk._fetch(`/chat/channels/${id}/leave`, 'POST', { body: {} });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* List members of a channel.
|
|
144
|
+
* @param {string} id
|
|
145
|
+
* @returns {Promise<Object>}
|
|
146
|
+
*/
|
|
147
|
+
async listMembers(id) {
|
|
148
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
149
|
+
return this.sdk._fetch(`/chat/channels/${id}/members`, 'GET');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Add a member to a channel.
|
|
154
|
+
* @param {string} id
|
|
155
|
+
* @param {Object} params
|
|
156
|
+
* @param {string} params.userId
|
|
157
|
+
* @param {'owner'|'moderator'|'member'} [params.role]
|
|
158
|
+
* @returns {Promise<Object>}
|
|
159
|
+
*/
|
|
160
|
+
async addMember(id, { userId, role } = {}) {
|
|
161
|
+
this.sdk.validateParams(
|
|
162
|
+
{ id, userId, role },
|
|
163
|
+
{
|
|
164
|
+
id: { type: 'string', required: true },
|
|
165
|
+
userId: { type: 'string', required: true },
|
|
166
|
+
role: { type: 'string', required: false },
|
|
167
|
+
},
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
const body = { userId };
|
|
171
|
+
if (role !== undefined) body.role = role;
|
|
172
|
+
|
|
173
|
+
return this.sdk._fetch(`/chat/channels/${id}/members`, 'POST', { body });
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Remove a member from a channel.
|
|
178
|
+
* @param {string} id
|
|
179
|
+
* @param {string} userId
|
|
180
|
+
* @returns {Promise<Object>}
|
|
181
|
+
*/
|
|
182
|
+
async removeMember(id, userId) {
|
|
183
|
+
this.sdk.validateParams(
|
|
184
|
+
{ id, userId },
|
|
185
|
+
{
|
|
186
|
+
id: { type: 'string', required: true },
|
|
187
|
+
userId: { type: 'string', required: true },
|
|
188
|
+
},
|
|
189
|
+
);
|
|
190
|
+
return this.sdk._fetch(`/chat/channels/${id}/members/${userId}`, 'DELETE');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Get group-default membership links for a channel.
|
|
195
|
+
* @param {string} id
|
|
196
|
+
* @returns {Promise<Object>}
|
|
197
|
+
*/
|
|
198
|
+
async getGroupDefaults(id) {
|
|
199
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
200
|
+
return this.sdk._fetch(`/chat/channels/${id}/group-defaults`, 'GET');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Replace group-default membership links for a channel.
|
|
205
|
+
* @param {string} id
|
|
206
|
+
* @param {Object} params
|
|
207
|
+
* @param {string[]} params.groupIds
|
|
208
|
+
* @returns {Promise<Object>}
|
|
209
|
+
*/
|
|
210
|
+
async setGroupDefaults(id, { groupIds } = {}) {
|
|
211
|
+
this.sdk.validateParams(
|
|
212
|
+
{ id, groupIds },
|
|
213
|
+
{
|
|
214
|
+
id: { type: 'string', required: true },
|
|
215
|
+
groupIds: { type: 'array', required: true },
|
|
216
|
+
},
|
|
217
|
+
);
|
|
218
|
+
return this.sdk._fetch(`/chat/channels/${id}/group-defaults`, 'PUT', {
|
|
219
|
+
body: { groupIds },
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Find-or-create a 1:1 or group DM.
|
|
225
|
+
* @param {Object} params
|
|
226
|
+
* @param {string[]} params.userIds
|
|
227
|
+
* @returns {Promise<Object>}
|
|
228
|
+
*/
|
|
229
|
+
async openDm({ userIds }) {
|
|
230
|
+
this.sdk.validateParams(
|
|
231
|
+
{ userIds },
|
|
232
|
+
{ userIds: { type: 'array', required: true } },
|
|
233
|
+
);
|
|
234
|
+
return this.sdk._fetch('/chat/dms', 'POST', { body: { userIds } });
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Sidebar unread snapshot (channels + previews + counters).
|
|
239
|
+
* @returns {Promise<Object>}
|
|
240
|
+
*/
|
|
241
|
+
async getUnreads() {
|
|
242
|
+
return this.sdk._fetch('/chat/unreads', 'GET');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Get the caller's Do Not Disturb state.
|
|
247
|
+
* @returns {Promise<Object>}
|
|
248
|
+
*/
|
|
249
|
+
async getDnd() {
|
|
250
|
+
return this.sdk._fetch('/chat/dnd', 'GET');
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Set the caller's Do Not Disturb state.
|
|
255
|
+
* @param {Object} params
|
|
256
|
+
* @param {boolean} params.enabled
|
|
257
|
+
* @returns {Promise<Object>}
|
|
258
|
+
*/
|
|
259
|
+
async setDnd({ enabled } = {}) {
|
|
260
|
+
this.sdk.validateParams(
|
|
261
|
+
{ enabled },
|
|
262
|
+
{ enabled: { type: 'boolean', required: true } },
|
|
263
|
+
);
|
|
264
|
+
return this.sdk._fetch('/chat/dnd', 'PATCH', { body: { enabled } });
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Advance the read watermark and recompute unread counters.
|
|
269
|
+
* @param {string} channelId
|
|
270
|
+
* @param {string} messageId
|
|
271
|
+
* @returns {Promise<Object>}
|
|
272
|
+
*/
|
|
273
|
+
async markRead(channelId, messageId) {
|
|
274
|
+
this.sdk.validateParams(
|
|
275
|
+
{ channelId, messageId },
|
|
276
|
+
{
|
|
277
|
+
channelId: { type: 'string', required: true },
|
|
278
|
+
messageId: { type: 'string', required: true },
|
|
279
|
+
},
|
|
280
|
+
);
|
|
281
|
+
return this.sdk._fetch(`/chat/channels/${channelId}/read`, 'POST', {
|
|
282
|
+
body: { messageId },
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Set the watermark to the message before `messageId` (mark as unread).
|
|
288
|
+
* @param {string} channelId
|
|
289
|
+
* @param {string} messageId
|
|
290
|
+
* @returns {Promise<Object>}
|
|
291
|
+
*/
|
|
292
|
+
async markUnread(channelId, messageId) {
|
|
293
|
+
this.sdk.validateParams(
|
|
294
|
+
{ channelId, messageId },
|
|
295
|
+
{
|
|
296
|
+
channelId: { type: 'string', required: true },
|
|
297
|
+
messageId: { type: 'string', required: true },
|
|
298
|
+
},
|
|
299
|
+
);
|
|
300
|
+
return this.sdk._fetch(`/chat/channels/${channelId}/unread`, 'POST', {
|
|
301
|
+
body: { messageId },
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Channels linked to a group via defaults (remove-from-group prompt).
|
|
307
|
+
* @param {Object} params
|
|
308
|
+
* @param {string} params.groupId
|
|
309
|
+
* @param {string} params.userId
|
|
310
|
+
* @returns {Promise<Object>}
|
|
311
|
+
*/
|
|
312
|
+
async getLinkedChannels({ groupId, userId }) {
|
|
313
|
+
this.sdk.validateParams(
|
|
314
|
+
{ groupId, userId },
|
|
315
|
+
{
|
|
316
|
+
groupId: { type: 'string', required: true },
|
|
317
|
+
userId: { type: 'string', required: true },
|
|
318
|
+
},
|
|
319
|
+
);
|
|
320
|
+
return this.sdk._fetch(`/chat/groups/${groupId}/linked-channels`, 'GET', {
|
|
321
|
+
query: { userId },
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* List messages in a channel (cursor pagination).
|
|
327
|
+
* @param {string} channelId
|
|
328
|
+
* @param {Object} [params]
|
|
329
|
+
* @param {string} [params.before]
|
|
330
|
+
* @param {string} [params.after]
|
|
331
|
+
* @param {number} [params.limit]
|
|
332
|
+
* @returns {Promise<Object>}
|
|
333
|
+
*/
|
|
334
|
+
async listMessages(channelId, { before, after, limit } = {}) {
|
|
335
|
+
this.sdk.validateParams(
|
|
336
|
+
{ channelId, before, after, limit },
|
|
337
|
+
{
|
|
338
|
+
channelId: { type: 'string', required: true },
|
|
339
|
+
before: { type: 'string', required: false },
|
|
340
|
+
after: { type: 'string', required: false },
|
|
341
|
+
limit: { type: 'number', required: false },
|
|
342
|
+
},
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
const query = {};
|
|
346
|
+
if (before !== undefined) query.before = before;
|
|
347
|
+
if (after !== undefined) query.after = after;
|
|
348
|
+
if (limit !== undefined) query.limit = limit;
|
|
349
|
+
|
|
350
|
+
return this.sdk._fetch(`/chat/channels/${channelId}/messages`, 'GET', {
|
|
351
|
+
query,
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Send a message to a channel.
|
|
357
|
+
* @param {string} channelId
|
|
358
|
+
* @param {Object} params
|
|
359
|
+
* @param {Object} params.message - ProseMirror JSON (required)
|
|
360
|
+
* @param {string} [params.threadRootId]
|
|
361
|
+
* @param {boolean} [params.alsoSendToChannel]
|
|
362
|
+
* @param {string[]} [params.storageIds]
|
|
363
|
+
* @returns {Promise<Object>} Created message
|
|
364
|
+
*/
|
|
365
|
+
async sendMessage(
|
|
366
|
+
channelId,
|
|
367
|
+
{ message, threadRootId, alsoSendToChannel, storageIds } = {},
|
|
368
|
+
) {
|
|
369
|
+
this.sdk.validateParams(
|
|
370
|
+
{ channelId, message, threadRootId, alsoSendToChannel, storageIds },
|
|
371
|
+
{
|
|
372
|
+
channelId: { type: 'string', required: true },
|
|
373
|
+
message: { type: 'object', required: true },
|
|
374
|
+
threadRootId: { type: 'string', required: false },
|
|
375
|
+
alsoSendToChannel: { type: 'boolean', required: false },
|
|
376
|
+
storageIds: { type: 'array', required: false },
|
|
377
|
+
},
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
const body = { message };
|
|
381
|
+
if (threadRootId !== undefined) body.threadRootId = threadRootId;
|
|
382
|
+
if (alsoSendToChannel !== undefined) {
|
|
383
|
+
body.alsoSendToChannel = alsoSendToChannel;
|
|
384
|
+
}
|
|
385
|
+
if (storageIds !== undefined) body.storageIds = storageIds;
|
|
386
|
+
|
|
387
|
+
return this.sdk._fetch(`/chat/channels/${channelId}/messages`, 'POST', {
|
|
388
|
+
body,
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Edit a message body (ProseMirror JSON).
|
|
394
|
+
* @param {string} id
|
|
395
|
+
* @param {Object} params
|
|
396
|
+
* @param {Object} params.message - ProseMirror JSON (required)
|
|
397
|
+
* @returns {Promise<Object>}
|
|
398
|
+
*/
|
|
399
|
+
async editMessage(id, { message } = {}) {
|
|
400
|
+
this.sdk.validateParams(
|
|
401
|
+
{ id, message },
|
|
402
|
+
{
|
|
403
|
+
id: { type: 'string', required: true },
|
|
404
|
+
message: { type: 'object', required: true },
|
|
405
|
+
},
|
|
406
|
+
);
|
|
407
|
+
return this.sdk._fetch(`/chat/messages/${id}`, 'PATCH', {
|
|
408
|
+
body: { message },
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Delete a message (tombstone).
|
|
414
|
+
* @param {string} id
|
|
415
|
+
* @returns {Promise<Object>}
|
|
416
|
+
*/
|
|
417
|
+
async deleteMessage(id) {
|
|
418
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
419
|
+
return this.sdk._fetch(`/chat/messages/${id}`, 'DELETE');
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Add an emoji reaction to a message.
|
|
424
|
+
* @param {string} id
|
|
425
|
+
* @param {Object} params
|
|
426
|
+
* @param {string} params.emoji
|
|
427
|
+
* @returns {Promise<Object>}
|
|
428
|
+
*/
|
|
429
|
+
async addReaction(id, { emoji } = {}) {
|
|
430
|
+
this.sdk.validateParams(
|
|
431
|
+
{ id, emoji },
|
|
432
|
+
{
|
|
433
|
+
id: { type: 'string', required: true },
|
|
434
|
+
emoji: { type: 'string', required: true },
|
|
435
|
+
},
|
|
436
|
+
);
|
|
437
|
+
return this.sdk._fetch(`/chat/messages/${id}/reactions`, 'POST', {
|
|
438
|
+
body: { emoji },
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Remove an emoji reaction from a message.
|
|
444
|
+
* @param {string} id
|
|
445
|
+
* @param {Object} params
|
|
446
|
+
* @param {string} params.emoji
|
|
447
|
+
* @returns {Promise<Object>}
|
|
448
|
+
*/
|
|
449
|
+
async removeReaction(id, { emoji } = {}) {
|
|
450
|
+
this.sdk.validateParams(
|
|
451
|
+
{ id, emoji },
|
|
452
|
+
{
|
|
453
|
+
id: { type: 'string', required: true },
|
|
454
|
+
emoji: { type: 'string', required: true },
|
|
455
|
+
},
|
|
456
|
+
);
|
|
457
|
+
return this.sdk._fetch(`/chat/messages/${id}/reactions`, 'DELETE', {
|
|
458
|
+
body: { emoji },
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Get a thread (root + replies) for a channel message.
|
|
464
|
+
* @param {string} channelId
|
|
465
|
+
* @param {string} rootId
|
|
466
|
+
* @returns {Promise<Object>}
|
|
467
|
+
*/
|
|
468
|
+
async getThread(channelId, rootId) {
|
|
469
|
+
this.sdk.validateParams(
|
|
470
|
+
{ channelId, rootId },
|
|
471
|
+
{
|
|
472
|
+
channelId: { type: 'string', required: true },
|
|
473
|
+
rootId: { type: 'string', required: true },
|
|
474
|
+
},
|
|
475
|
+
);
|
|
476
|
+
return this.sdk._fetch(
|
|
477
|
+
`/chat/channels/${channelId}/messages/${rootId}/thread`,
|
|
478
|
+
'GET',
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Search messages the current user can read.
|
|
484
|
+
* @param {Object} params
|
|
485
|
+
* @param {string} params.q - Search term (required)
|
|
486
|
+
* @param {string} [params.channelId]
|
|
487
|
+
* @param {string} [params.fromUserId]
|
|
488
|
+
* @param {string} [params.before]
|
|
489
|
+
* @param {string} [params.after]
|
|
490
|
+
* @param {'public'|'private'|'dm'|'group_dm'|'record'|'meeting'} [params.kind]
|
|
491
|
+
* @param {string} [params.nextId]
|
|
492
|
+
* @param {number} [params.limit]
|
|
493
|
+
* @returns {Promise<Object>}
|
|
494
|
+
*/
|
|
495
|
+
async search({
|
|
496
|
+
q,
|
|
497
|
+
channelId,
|
|
498
|
+
fromUserId,
|
|
499
|
+
before,
|
|
500
|
+
after,
|
|
501
|
+
kind,
|
|
502
|
+
nextId,
|
|
503
|
+
limit,
|
|
504
|
+
} = {}) {
|
|
505
|
+
this.sdk.validateParams(
|
|
506
|
+
{ q, channelId, fromUserId, before, after, kind, nextId, limit },
|
|
507
|
+
{
|
|
508
|
+
q: { type: 'string', required: true },
|
|
509
|
+
channelId: { type: 'string', required: false },
|
|
510
|
+
fromUserId: { type: 'string', required: false },
|
|
511
|
+
before: { type: 'string', required: false },
|
|
512
|
+
after: { type: 'string', required: false },
|
|
513
|
+
kind: { type: 'string', required: false },
|
|
514
|
+
nextId: { type: 'string', required: false },
|
|
515
|
+
limit: { type: 'number', required: false },
|
|
516
|
+
},
|
|
517
|
+
);
|
|
518
|
+
|
|
519
|
+
const query = { q };
|
|
520
|
+
if (channelId !== undefined) query.channelId = channelId;
|
|
521
|
+
if (fromUserId !== undefined) query.fromUserId = fromUserId;
|
|
522
|
+
if (before !== undefined) query.before = before;
|
|
523
|
+
if (after !== undefined) query.after = after;
|
|
524
|
+
if (kind !== undefined) query.kind = kind;
|
|
525
|
+
if (nextId !== undefined) query.nextId = nextId;
|
|
526
|
+
if (limit !== undefined) query.limit = limit;
|
|
527
|
+
|
|
528
|
+
return this.sdk._fetch('/chat/search', 'GET', { query });
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Create a channel incoming webhook (signing secret returned once).
|
|
533
|
+
* Button callback URLs are registered here — never taken from message payloads.
|
|
534
|
+
* @param {string} channelId
|
|
535
|
+
* @param {Object} params
|
|
536
|
+
* @param {string} params.name - Display name (required)
|
|
537
|
+
* @param {string} [params.avatar]
|
|
538
|
+
* @param {string} [params.callbackUrl] - Admin-registered button callback URL
|
|
539
|
+
* @returns {Promise<Object>} Created webhook (includes signingSecret once)
|
|
540
|
+
*/
|
|
541
|
+
async createWebhook(channelId, { name, avatar, callbackUrl } = {}) {
|
|
542
|
+
this.sdk.validateParams(
|
|
543
|
+
{ channelId, name, avatar, callbackUrl },
|
|
544
|
+
{
|
|
545
|
+
channelId: { type: 'string', required: true },
|
|
546
|
+
name: { type: 'string', required: true },
|
|
547
|
+
avatar: { type: 'string', required: false },
|
|
548
|
+
callbackUrl: { type: 'string', required: false },
|
|
549
|
+
},
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
const body = { name };
|
|
553
|
+
if (avatar !== undefined) body.avatar = avatar;
|
|
554
|
+
if (callbackUrl !== undefined) body.callbackUrl = callbackUrl;
|
|
555
|
+
|
|
556
|
+
return this.sdk._fetch(`/chat/channels/${channelId}/webhooks`, 'POST', {
|
|
557
|
+
body,
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* List webhooks for a channel.
|
|
563
|
+
* @param {string} channelId
|
|
564
|
+
* @returns {Promise<Object>}
|
|
565
|
+
*/
|
|
566
|
+
async listWebhooks(channelId) {
|
|
567
|
+
this.sdk.validateParams(
|
|
568
|
+
{ channelId },
|
|
569
|
+
{ channelId: { type: 'string', required: true } },
|
|
570
|
+
);
|
|
571
|
+
return this.sdk._fetch(`/chat/channels/${channelId}/webhooks`, 'GET');
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Revoke a channel webhook.
|
|
576
|
+
* @param {string} channelId
|
|
577
|
+
* @param {string} webhookId
|
|
578
|
+
* @returns {Promise<Object>}
|
|
579
|
+
*/
|
|
580
|
+
async revokeWebhook(channelId, webhookId) {
|
|
581
|
+
this.sdk.validateParams(
|
|
582
|
+
{ channelId, webhookId },
|
|
583
|
+
{
|
|
584
|
+
channelId: { type: 'string', required: true },
|
|
585
|
+
webhookId: { type: 'string', required: true },
|
|
586
|
+
},
|
|
587
|
+
);
|
|
588
|
+
return this.sdk._fetch(
|
|
589
|
+
`/chat/channels/${channelId}/webhooks/${webhookId}`,
|
|
590
|
+
'DELETE',
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/**
|
|
595
|
+
* Click a card action button on a message. Acting principal is the caller.
|
|
596
|
+
* @param {string} messageId
|
|
597
|
+
* @param {Object} params
|
|
598
|
+
* @param {string} params.actionId
|
|
599
|
+
* @param {string} [params.value]
|
|
600
|
+
* @returns {Promise<Object>}
|
|
601
|
+
*/
|
|
602
|
+
async clickAction(messageId, { actionId, value } = {}) {
|
|
603
|
+
this.sdk.validateParams(
|
|
604
|
+
{ messageId, actionId, value },
|
|
605
|
+
{
|
|
606
|
+
messageId: { type: 'string', required: true },
|
|
607
|
+
actionId: { type: 'string', required: true },
|
|
608
|
+
value: { type: 'string', required: false },
|
|
609
|
+
},
|
|
610
|
+
);
|
|
611
|
+
|
|
612
|
+
const body = { actionId };
|
|
613
|
+
if (value !== undefined) body.value = value;
|
|
614
|
+
|
|
615
|
+
return this.sdk._fetch(`/chat/messages/${messageId}/actions`, 'POST', {
|
|
616
|
+
body,
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* Report a message.
|
|
622
|
+
* @param {string} id
|
|
623
|
+
* @param {Object} params
|
|
624
|
+
* @param {string} params.reason
|
|
625
|
+
* @returns {Promise<Object>}
|
|
626
|
+
*/
|
|
627
|
+
async reportMessage(id, { reason } = {}) {
|
|
628
|
+
this.sdk.validateParams(
|
|
629
|
+
{ id, reason },
|
|
630
|
+
{
|
|
631
|
+
id: { type: 'string', required: true },
|
|
632
|
+
reason: { type: 'string', required: true },
|
|
633
|
+
},
|
|
634
|
+
);
|
|
635
|
+
return this.sdk._fetch(`/chat/messages/${id}/report`, 'POST', {
|
|
636
|
+
body: { reason },
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* Admin: list all channels (optional search/kind filter).
|
|
642
|
+
* @param {Object} [params]
|
|
643
|
+
* @param {string} [params.q]
|
|
644
|
+
* @param {'public'|'private'|'dm'|'group_dm'|'record'|'meeting'} [params.kind]
|
|
645
|
+
* @returns {Promise<Object>}
|
|
646
|
+
*/
|
|
647
|
+
async adminListChannels({ q, kind } = {}) {
|
|
648
|
+
this.sdk.validateParams(
|
|
649
|
+
{ q, kind },
|
|
650
|
+
{
|
|
651
|
+
q: { type: 'string', required: false },
|
|
652
|
+
kind: { type: 'string', required: false },
|
|
653
|
+
},
|
|
654
|
+
);
|
|
655
|
+
|
|
656
|
+
const query = {};
|
|
657
|
+
if (q !== undefined) query.q = q;
|
|
658
|
+
if (kind !== undefined) query.kind = kind;
|
|
659
|
+
|
|
660
|
+
return this.sdk._fetch('/chat/admin/channels', 'GET', { query });
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Admin: get a channel by id (no membership required).
|
|
665
|
+
* @param {string} id
|
|
666
|
+
* @returns {Promise<Object>}
|
|
667
|
+
*/
|
|
668
|
+
async adminGetChannel(id) {
|
|
669
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
670
|
+
return this.sdk._fetch(`/chat/admin/channels/${id}`, 'GET');
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Admin: export a channel (messages + members).
|
|
675
|
+
* @param {string} id
|
|
676
|
+
* @returns {Promise<Object>}
|
|
677
|
+
*/
|
|
678
|
+
async adminExportChannel(id) {
|
|
679
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
680
|
+
return this.sdk._fetch(`/chat/admin/channels/${id}/export`, 'GET');
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* Admin: list message reports.
|
|
685
|
+
* @param {Object} [params]
|
|
686
|
+
* @param {string} [params.status]
|
|
687
|
+
* @returns {Promise<Object>}
|
|
688
|
+
*/
|
|
689
|
+
async adminListReports({ status } = {}) {
|
|
690
|
+
this.sdk.validateParams(
|
|
691
|
+
{ status },
|
|
692
|
+
{ status: { type: 'string', required: false } },
|
|
693
|
+
);
|
|
694
|
+
|
|
695
|
+
const query = {};
|
|
696
|
+
if (status !== undefined) query.status = status;
|
|
697
|
+
|
|
698
|
+
return this.sdk._fetch('/chat/admin/reports', 'GET', { query });
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Admin: review a message report (set status).
|
|
703
|
+
* @param {string} id
|
|
704
|
+
* @param {Object} params
|
|
705
|
+
* @param {string} params.status
|
|
706
|
+
* @returns {Promise<Object>}
|
|
707
|
+
*/
|
|
708
|
+
async adminReviewReport(id, { status } = {}) {
|
|
709
|
+
this.sdk.validateParams(
|
|
710
|
+
{ id, status },
|
|
711
|
+
{
|
|
712
|
+
id: { type: 'string', required: true },
|
|
713
|
+
status: { type: 'string', required: true },
|
|
714
|
+
},
|
|
715
|
+
);
|
|
716
|
+
return this.sdk._fetch(`/chat/admin/reports/${id}`, 'POST', {
|
|
717
|
+
body: { status },
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* Admin: delete a message (moderation).
|
|
723
|
+
* @param {string} id
|
|
724
|
+
* @returns {Promise<Object>}
|
|
725
|
+
*/
|
|
726
|
+
async adminDeleteMessage(id) {
|
|
727
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
728
|
+
return this.sdk._fetch(`/chat/admin/messages/${id}`, 'DELETE');
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Admin: audit log of review actions.
|
|
733
|
+
* @returns {Promise<Object>}
|
|
734
|
+
*/
|
|
735
|
+
async adminAudit() {
|
|
736
|
+
return this.sdk._fetch('/chat/admin/audit', 'GET');
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
/**
|
|
740
|
+
* Get (find-or-create) the record-feed channel for a related record.
|
|
741
|
+
* @param {string} relatedId
|
|
742
|
+
* @param {Object} params
|
|
743
|
+
* @param {string} params.recordTypeId
|
|
744
|
+
* @returns {Promise<Object>} Record-kind channel
|
|
745
|
+
*/
|
|
746
|
+
async getRecordChannel(relatedId, { recordTypeId } = {}) {
|
|
747
|
+
this.sdk.validateParams(
|
|
748
|
+
{ relatedId, recordTypeId },
|
|
749
|
+
{
|
|
750
|
+
relatedId: { type: 'string', required: true },
|
|
751
|
+
recordTypeId: { type: 'string', required: true },
|
|
752
|
+
},
|
|
753
|
+
);
|
|
754
|
+
return this.sdk._fetch(`/chat/records/${relatedId}`, 'GET', {
|
|
755
|
+
query: { recordTypeId },
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Post a message to a record-feed channel (find-or-create).
|
|
761
|
+
* @param {string} relatedId
|
|
762
|
+
* @param {Object} params
|
|
763
|
+
* @param {Object} params.message - ProseMirror JSON (required)
|
|
764
|
+
* @param {string} params.recordTypeId
|
|
765
|
+
* @returns {Promise<Object>} Created message
|
|
766
|
+
*/
|
|
767
|
+
async postToRecord(relatedId, { message, recordTypeId } = {}) {
|
|
768
|
+
this.sdk.validateParams(
|
|
769
|
+
{ relatedId, message, recordTypeId },
|
|
770
|
+
{
|
|
771
|
+
relatedId: { type: 'string', required: true },
|
|
772
|
+
message: { type: 'object', required: true },
|
|
773
|
+
recordTypeId: { type: 'string', required: true },
|
|
774
|
+
},
|
|
775
|
+
);
|
|
776
|
+
return this.sdk._fetch(`/chat/records/${relatedId}/messages`, 'POST', {
|
|
777
|
+
body: { message, recordTypeId },
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* Get the Meet/Call room for a channel.
|
|
783
|
+
* @param {string} channelId
|
|
784
|
+
* @returns {Promise<Object>}
|
|
785
|
+
*/
|
|
786
|
+
async getChannelMeet(channelId) {
|
|
787
|
+
this.sdk.validateParams(
|
|
788
|
+
{ channelId },
|
|
789
|
+
{ channelId: { type: 'string', required: true } },
|
|
790
|
+
);
|
|
791
|
+
return this.sdk._fetch(`/chat/channels/${channelId}/meet`, 'GET');
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Get the VAPID public key for Web Push subscription.
|
|
796
|
+
* @returns {Promise<Object>}
|
|
797
|
+
*/
|
|
798
|
+
async getVapidPublicKey() {
|
|
799
|
+
return this.sdk._fetch('/chat/push/vapidPublicKey', 'GET');
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Register a push device (web push subscription or native FCM/APNs token).
|
|
804
|
+
* @param {Object} params
|
|
805
|
+
* @param {'webpush'|'fcm'|'apns'} params.kind
|
|
806
|
+
* @param {Object} params.subscription - Push subscription / token JSON
|
|
807
|
+
* @returns {Promise<Object>}
|
|
808
|
+
*/
|
|
809
|
+
async registerPushDevice({ kind, subscription } = {}) {
|
|
810
|
+
this.sdk.validateParams(
|
|
811
|
+
{ kind, subscription },
|
|
812
|
+
{
|
|
813
|
+
kind: { type: 'string', required: true },
|
|
814
|
+
subscription: { type: 'object', required: true },
|
|
815
|
+
},
|
|
816
|
+
);
|
|
817
|
+
return this.sdk._fetch('/chat/push/devices', 'POST', {
|
|
818
|
+
body: { kind, subscription },
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Unregister a push device.
|
|
824
|
+
* @param {string} id
|
|
825
|
+
* @returns {Promise<Object>}
|
|
826
|
+
*/
|
|
827
|
+
async unregisterPushDevice(id) {
|
|
828
|
+
this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
|
|
829
|
+
return this.sdk._fetch(`/chat/push/devices/${id}`, 'DELETE');
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* Set the caller's notifyLevel on a channel (all | mentions | mute).
|
|
834
|
+
* @param {string} channelId
|
|
835
|
+
* @param {Object} params
|
|
836
|
+
* @param {'all'|'mentions'|'mute'} params.notifyLevel
|
|
837
|
+
* @returns {Promise<Object>}
|
|
838
|
+
*/
|
|
839
|
+
async setNotifyLevel(channelId, { notifyLevel } = {}) {
|
|
840
|
+
this.sdk.validateParams(
|
|
841
|
+
{ channelId, notifyLevel },
|
|
842
|
+
{
|
|
843
|
+
channelId: { type: 'string', required: true },
|
|
844
|
+
notifyLevel: { type: 'string', required: true },
|
|
845
|
+
},
|
|
846
|
+
);
|
|
847
|
+
return this.sdk._fetch(`/chat/channels/${channelId}/notify`, 'PATCH', {
|
|
848
|
+
body: { notifyLevel },
|
|
849
|
+
});
|
|
850
|
+
}
|
|
851
|
+
}
|