@auxiora/channels 1.0.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/LICENSE +191 -0
- package/dist/adapters/bluebubbles.d.ts +63 -0
- package/dist/adapters/bluebubbles.d.ts.map +1 -0
- package/dist/adapters/bluebubbles.js +197 -0
- package/dist/adapters/bluebubbles.js.map +1 -0
- package/dist/adapters/discord.d.ts +27 -0
- package/dist/adapters/discord.d.ts.map +1 -0
- package/dist/adapters/discord.js +202 -0
- package/dist/adapters/discord.js.map +1 -0
- package/dist/adapters/email.d.ts +39 -0
- package/dist/adapters/email.d.ts.map +1 -0
- package/dist/adapters/email.js +359 -0
- package/dist/adapters/email.js.map +1 -0
- package/dist/adapters/googlechat.d.ts +77 -0
- package/dist/adapters/googlechat.d.ts.map +1 -0
- package/dist/adapters/googlechat.js +232 -0
- package/dist/adapters/googlechat.js.map +1 -0
- package/dist/adapters/matrix.d.ts +37 -0
- package/dist/adapters/matrix.d.ts.map +1 -0
- package/dist/adapters/matrix.js +262 -0
- package/dist/adapters/matrix.js.map +1 -0
- package/dist/adapters/signal.d.ts +32 -0
- package/dist/adapters/signal.d.ts.map +1 -0
- package/dist/adapters/signal.js +216 -0
- package/dist/adapters/signal.js.map +1 -0
- package/dist/adapters/slack.d.ts +29 -0
- package/dist/adapters/slack.d.ts.map +1 -0
- package/dist/adapters/slack.js +202 -0
- package/dist/adapters/slack.js.map +1 -0
- package/dist/adapters/teams.d.ts +66 -0
- package/dist/adapters/teams.d.ts.map +1 -0
- package/dist/adapters/teams.js +227 -0
- package/dist/adapters/teams.js.map +1 -0
- package/dist/adapters/telegram.d.ts +28 -0
- package/dist/adapters/telegram.d.ts.map +1 -0
- package/dist/adapters/telegram.js +170 -0
- package/dist/adapters/telegram.js.map +1 -0
- package/dist/adapters/twilio.d.ts +63 -0
- package/dist/adapters/twilio.d.ts.map +1 -0
- package/dist/adapters/twilio.js +193 -0
- package/dist/adapters/twilio.js.map +1 -0
- package/dist/adapters/whatsapp.d.ts +99 -0
- package/dist/adapters/whatsapp.d.ts.map +1 -0
- package/dist/adapters/whatsapp.js +218 -0
- package/dist/adapters/whatsapp.js.map +1 -0
- package/dist/adapters/zalo.d.ts +64 -0
- package/dist/adapters/zalo.d.ts.map +1 -0
- package/dist/adapters/zalo.js +216 -0
- package/dist/adapters/zalo.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/manager.d.ts +35 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +127 -0
- package/dist/manager.js.map +1 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +32 -0
- package/src/adapters/bluebubbles.ts +294 -0
- package/src/adapters/discord.ts +253 -0
- package/src/adapters/email.ts +457 -0
- package/src/adapters/googlechat.ts +364 -0
- package/src/adapters/matrix.ts +376 -0
- package/src/adapters/signal.ts +313 -0
- package/src/adapters/slack.ts +252 -0
- package/src/adapters/teams.ts +320 -0
- package/src/adapters/telegram.ts +208 -0
- package/src/adapters/twilio.ts +256 -0
- package/src/adapters/whatsapp.ts +342 -0
- package/src/adapters/zalo.ts +319 -0
- package/src/index.ts +78 -0
- package/src/manager.ts +180 -0
- package/src/types.ts +84 -0
- package/tests/bluebubbles.test.ts +438 -0
- package/tests/email.test.ts +136 -0
- package/tests/googlechat.test.ts +439 -0
- package/tests/matrix.test.ts +564 -0
- package/tests/signal.test.ts +404 -0
- package/tests/slack.test.ts +343 -0
- package/tests/teams.test.ts +429 -0
- package/tests/twilio.test.ts +269 -0
- package/tests/whatsapp.test.ts +530 -0
- package/tests/zalo.test.ts +499 -0
- package/tsconfig.json +8 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { SlackAdapter } from '../src/adapters/slack.js';
|
|
3
|
+
|
|
4
|
+
// Mock audit
|
|
5
|
+
vi.mock('@auxiora/audit', () => ({
|
|
6
|
+
audit: vi.fn(),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
// Track registered event handlers
|
|
10
|
+
let messageHandlers: Array<(args: unknown) => Promise<void>> = [];
|
|
11
|
+
let mentionHandlers: Array<(args: unknown) => Promise<void>> = [];
|
|
12
|
+
let errorHandlers: Array<(error: Error) => Promise<void>> = [];
|
|
13
|
+
|
|
14
|
+
// Mock @slack/bolt
|
|
15
|
+
vi.mock('@slack/bolt', () => {
|
|
16
|
+
class MockApp {
|
|
17
|
+
client = {
|
|
18
|
+
auth: { test: vi.fn().mockResolvedValue({ user_id: 'U_BOT' }) },
|
|
19
|
+
chat: { postMessage: vi.fn().mockResolvedValue({ ts: '1234567890.123456' }) },
|
|
20
|
+
};
|
|
21
|
+
message = vi.fn((handler: (args: unknown) => Promise<void>) => {
|
|
22
|
+
messageHandlers.push(handler);
|
|
23
|
+
});
|
|
24
|
+
event = vi.fn((eventName: string, handler: (args: unknown) => Promise<void>) => {
|
|
25
|
+
if (eventName === 'app_mention') {
|
|
26
|
+
mentionHandlers.push(handler);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
error = vi.fn((handler: (error: Error) => Promise<void>) => {
|
|
30
|
+
errorHandlers.push(handler);
|
|
31
|
+
});
|
|
32
|
+
start = vi.fn().mockResolvedValue(undefined);
|
|
33
|
+
stop = vi.fn().mockResolvedValue(undefined);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
App: MockApp,
|
|
38
|
+
LogLevel: { WARN: 'warn' },
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe('SlackAdapter', () => {
|
|
43
|
+
let adapter: SlackAdapter;
|
|
44
|
+
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
messageHandlers = [];
|
|
47
|
+
mentionHandlers = [];
|
|
48
|
+
errorHandlers = [];
|
|
49
|
+
|
|
50
|
+
adapter = new SlackAdapter({
|
|
51
|
+
botToken: 'xoxb-test-token',
|
|
52
|
+
appToken: 'xapp-test-token',
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
afterEach(() => {
|
|
57
|
+
vi.restoreAllMocks();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should have correct metadata', () => {
|
|
61
|
+
expect(adapter.type).toBe('slack');
|
|
62
|
+
expect(adapter.name).toBe('Slack');
|
|
63
|
+
expect(adapter.isConnected()).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should connect and disconnect', async () => {
|
|
67
|
+
await adapter.connect();
|
|
68
|
+
expect(adapter.isConnected()).toBe(true);
|
|
69
|
+
|
|
70
|
+
await adapter.disconnect();
|
|
71
|
+
expect(adapter.isConnected()).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should handle incoming messages', async () => {
|
|
75
|
+
const receivedMessages: unknown[] = [];
|
|
76
|
+
adapter.onMessage(async (msg) => {
|
|
77
|
+
receivedMessages.push(msg);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await adapter.connect();
|
|
81
|
+
|
|
82
|
+
// Simulate a message event
|
|
83
|
+
const handler = messageHandlers[0];
|
|
84
|
+
await handler({
|
|
85
|
+
message: {
|
|
86
|
+
ts: '1700000000.000001',
|
|
87
|
+
channel: 'C123',
|
|
88
|
+
user: 'U_ALICE',
|
|
89
|
+
text: 'Hello Slack!',
|
|
90
|
+
},
|
|
91
|
+
say: vi.fn(),
|
|
92
|
+
client: { auth: { test: vi.fn().mockResolvedValue({ user_id: 'U_BOT' }) } },
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
expect(receivedMessages).toHaveLength(1);
|
|
96
|
+
const msg = receivedMessages[0] as { content: string; senderId: string; channelId: string };
|
|
97
|
+
expect(msg.content).toBe('Hello Slack!');
|
|
98
|
+
expect(msg.senderId).toBe('U_ALICE');
|
|
99
|
+
expect(msg.channelId).toBe('C123');
|
|
100
|
+
|
|
101
|
+
await adapter.disconnect();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should handle app_mention events', async () => {
|
|
105
|
+
const receivedMessages: unknown[] = [];
|
|
106
|
+
adapter.onMessage(async (msg) => {
|
|
107
|
+
receivedMessages.push(msg);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
await adapter.connect();
|
|
111
|
+
|
|
112
|
+
const handler = mentionHandlers[0];
|
|
113
|
+
await handler({
|
|
114
|
+
event: {
|
|
115
|
+
ts: '1700000000.000002',
|
|
116
|
+
channel: 'C123',
|
|
117
|
+
user: 'U_BOB',
|
|
118
|
+
text: '<@U_BOT> hello!',
|
|
119
|
+
},
|
|
120
|
+
client: { auth: { test: vi.fn().mockResolvedValue({ user_id: 'U_BOT' }) } },
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
expect(receivedMessages).toHaveLength(1);
|
|
124
|
+
const msg = receivedMessages[0] as { content: string };
|
|
125
|
+
expect(msg.content).toBe('hello!');
|
|
126
|
+
|
|
127
|
+
await adapter.disconnect();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe('sender filtering', () => {
|
|
131
|
+
it('should allow all messages when allowlists are not set', async () => {
|
|
132
|
+
const receivedMessages: unknown[] = [];
|
|
133
|
+
adapter.onMessage(async (msg) => {
|
|
134
|
+
receivedMessages.push(msg);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
await adapter.connect();
|
|
138
|
+
|
|
139
|
+
const handler = messageHandlers[0];
|
|
140
|
+
await handler({
|
|
141
|
+
message: {
|
|
142
|
+
ts: '1700000000.000003',
|
|
143
|
+
channel: 'C_ANY',
|
|
144
|
+
user: 'U_ANYONE',
|
|
145
|
+
text: 'Anyone!',
|
|
146
|
+
},
|
|
147
|
+
say: vi.fn(),
|
|
148
|
+
client: { auth: { test: vi.fn().mockResolvedValue({ user_id: 'U_BOT' }) } },
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
expect(receivedMessages).toHaveLength(1);
|
|
152
|
+
await adapter.disconnect();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('should allow messages from allowed users in allowed channels', async () => {
|
|
156
|
+
messageHandlers = [];
|
|
157
|
+
mentionHandlers = [];
|
|
158
|
+
const filteredAdapter = new SlackAdapter({
|
|
159
|
+
botToken: 'xoxb-test-token',
|
|
160
|
+
appToken: 'xapp-test-token',
|
|
161
|
+
allowedChannels: ['C123'],
|
|
162
|
+
allowedUsers: ['U_ALICE'],
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const receivedMessages: unknown[] = [];
|
|
166
|
+
filteredAdapter.onMessage(async (msg) => {
|
|
167
|
+
receivedMessages.push(msg);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
await filteredAdapter.connect();
|
|
171
|
+
|
|
172
|
+
const handler = messageHandlers[0];
|
|
173
|
+
await handler({
|
|
174
|
+
message: {
|
|
175
|
+
ts: '1700000000.000004',
|
|
176
|
+
channel: 'C123',
|
|
177
|
+
user: 'U_ALICE',
|
|
178
|
+
text: 'Allowed!',
|
|
179
|
+
},
|
|
180
|
+
say: vi.fn(),
|
|
181
|
+
client: { auth: { test: vi.fn().mockResolvedValue({ user_id: 'U_BOT' }) } },
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
expect(receivedMessages).toHaveLength(1);
|
|
185
|
+
await filteredAdapter.disconnect();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('should block messages from non-allowed channels', async () => {
|
|
189
|
+
const { audit } = await import('@auxiora/audit');
|
|
190
|
+
messageHandlers = [];
|
|
191
|
+
mentionHandlers = [];
|
|
192
|
+
const filteredAdapter = new SlackAdapter({
|
|
193
|
+
botToken: 'xoxb-test-token',
|
|
194
|
+
appToken: 'xapp-test-token',
|
|
195
|
+
allowedChannels: ['C123'],
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const receivedMessages: unknown[] = [];
|
|
199
|
+
filteredAdapter.onMessage(async (msg) => {
|
|
200
|
+
receivedMessages.push(msg);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
await filteredAdapter.connect();
|
|
204
|
+
|
|
205
|
+
const handler = messageHandlers[0];
|
|
206
|
+
await handler({
|
|
207
|
+
message: {
|
|
208
|
+
ts: '1700000000.000005',
|
|
209
|
+
channel: 'C_WRONG',
|
|
210
|
+
user: 'U_ALICE',
|
|
211
|
+
text: 'Wrong channel!',
|
|
212
|
+
},
|
|
213
|
+
say: vi.fn(),
|
|
214
|
+
client: { auth: { test: vi.fn().mockResolvedValue({ user_id: 'U_BOT' }) } },
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
expect(receivedMessages).toHaveLength(0);
|
|
218
|
+
expect(audit).toHaveBeenCalledWith('message.filtered', expect.objectContaining({
|
|
219
|
+
channelType: 'slack',
|
|
220
|
+
channelId: 'C_WRONG',
|
|
221
|
+
reason: 'channel_not_allowed',
|
|
222
|
+
}));
|
|
223
|
+
await filteredAdapter.disconnect();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('should block messages from non-allowed users', async () => {
|
|
227
|
+
const { audit } = await import('@auxiora/audit');
|
|
228
|
+
messageHandlers = [];
|
|
229
|
+
mentionHandlers = [];
|
|
230
|
+
const filteredAdapter = new SlackAdapter({
|
|
231
|
+
botToken: 'xoxb-test-token',
|
|
232
|
+
appToken: 'xapp-test-token',
|
|
233
|
+
allowedUsers: ['U_ALICE'],
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const receivedMessages: unknown[] = [];
|
|
237
|
+
filteredAdapter.onMessage(async (msg) => {
|
|
238
|
+
receivedMessages.push(msg);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
await filteredAdapter.connect();
|
|
242
|
+
|
|
243
|
+
const handler = messageHandlers[0];
|
|
244
|
+
await handler({
|
|
245
|
+
message: {
|
|
246
|
+
ts: '1700000000.000006',
|
|
247
|
+
channel: 'C123',
|
|
248
|
+
user: 'U_EVE',
|
|
249
|
+
text: 'Blocked user!',
|
|
250
|
+
},
|
|
251
|
+
say: vi.fn(),
|
|
252
|
+
client: { auth: { test: vi.fn().mockResolvedValue({ user_id: 'U_BOT' }) } },
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
expect(receivedMessages).toHaveLength(0);
|
|
256
|
+
expect(audit).toHaveBeenCalledWith('message.filtered', expect.objectContaining({
|
|
257
|
+
channelType: 'slack',
|
|
258
|
+
senderId: 'U_EVE',
|
|
259
|
+
reason: 'user_not_allowed',
|
|
260
|
+
}));
|
|
261
|
+
await filteredAdapter.disconnect();
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('should block app_mention from non-allowed channels', async () => {
|
|
265
|
+
const { audit } = await import('@auxiora/audit');
|
|
266
|
+
messageHandlers = [];
|
|
267
|
+
mentionHandlers = [];
|
|
268
|
+
const filteredAdapter = new SlackAdapter({
|
|
269
|
+
botToken: 'xoxb-test-token',
|
|
270
|
+
appToken: 'xapp-test-token',
|
|
271
|
+
allowedChannels: ['C123'],
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const receivedMessages: unknown[] = [];
|
|
275
|
+
filteredAdapter.onMessage(async (msg) => {
|
|
276
|
+
receivedMessages.push(msg);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
await filteredAdapter.connect();
|
|
280
|
+
|
|
281
|
+
const handler = mentionHandlers[0];
|
|
282
|
+
await handler({
|
|
283
|
+
event: {
|
|
284
|
+
ts: '1700000000.000007',
|
|
285
|
+
channel: 'C_WRONG',
|
|
286
|
+
user: 'U_ALICE',
|
|
287
|
+
text: '<@U_BOT> blocked mention!',
|
|
288
|
+
},
|
|
289
|
+
client: { auth: { test: vi.fn().mockResolvedValue({ user_id: 'U_BOT' }) } },
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
expect(receivedMessages).toHaveLength(0);
|
|
293
|
+
expect(audit).toHaveBeenCalledWith('message.filtered', expect.objectContaining({
|
|
294
|
+
channelType: 'slack',
|
|
295
|
+
channelId: 'C_WRONG',
|
|
296
|
+
reason: 'channel_not_allowed',
|
|
297
|
+
}));
|
|
298
|
+
await filteredAdapter.disconnect();
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('should block app_mention from non-allowed users', async () => {
|
|
302
|
+
const { audit } = await import('@auxiora/audit');
|
|
303
|
+
messageHandlers = [];
|
|
304
|
+
mentionHandlers = [];
|
|
305
|
+
const filteredAdapter = new SlackAdapter({
|
|
306
|
+
botToken: 'xoxb-test-token',
|
|
307
|
+
appToken: 'xapp-test-token',
|
|
308
|
+
allowedUsers: ['U_ALICE'],
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const receivedMessages: unknown[] = [];
|
|
312
|
+
filteredAdapter.onMessage(async (msg) => {
|
|
313
|
+
receivedMessages.push(msg);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
await filteredAdapter.connect();
|
|
317
|
+
|
|
318
|
+
const handler = mentionHandlers[0];
|
|
319
|
+
await handler({
|
|
320
|
+
event: {
|
|
321
|
+
ts: '1700000000.000008',
|
|
322
|
+
channel: 'C123',
|
|
323
|
+
user: 'U_EVE',
|
|
324
|
+
text: '<@U_BOT> blocked mention!',
|
|
325
|
+
},
|
|
326
|
+
client: { auth: { test: vi.fn().mockResolvedValue({ user_id: 'U_BOT' }) } },
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
expect(receivedMessages).toHaveLength(0);
|
|
330
|
+
expect(audit).toHaveBeenCalledWith('message.filtered', expect.objectContaining({
|
|
331
|
+
channelType: 'slack',
|
|
332
|
+
senderId: 'U_EVE',
|
|
333
|
+
reason: 'user_not_allowed',
|
|
334
|
+
}));
|
|
335
|
+
await filteredAdapter.disconnect();
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
it('should register error handler', () => {
|
|
340
|
+
const handler = vi.fn();
|
|
341
|
+
adapter.onError(handler);
|
|
342
|
+
});
|
|
343
|
+
});
|