signal-sdk 0.1.1 → 0.1.3

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.
Files changed (54) hide show
  1. package/README.md +23 -11
  2. package/dist/MultiAccountManager.js +11 -19
  3. package/dist/SignalBot.js +40 -36
  4. package/dist/SignalCli.d.ts +25 -301
  5. package/dist/SignalCli.js +226 -971
  6. package/dist/__tests__/DeviceManager.test.d.ts +1 -0
  7. package/dist/__tests__/DeviceManager.test.js +135 -0
  8. package/dist/__tests__/MultiAccountManager.coverage.test.d.ts +1 -0
  9. package/dist/__tests__/MultiAccountManager.coverage.test.js +33 -0
  10. package/dist/__tests__/MultiAccountManager.test.js +3 -3
  11. package/dist/__tests__/SignalBot.additional.test.js +40 -37
  12. package/dist/__tests__/SignalBot.coverage.test.d.ts +1 -0
  13. package/dist/__tests__/SignalBot.coverage.test.js +385 -0
  14. package/dist/__tests__/SignalBot.test.js +8 -8
  15. package/dist/__tests__/SignalCli.advanced.test.js +47 -58
  16. package/dist/__tests__/SignalCli.connections.test.d.ts +1 -0
  17. package/dist/__tests__/SignalCli.connections.test.js +110 -0
  18. package/dist/__tests__/SignalCli.e2e.test.js +28 -32
  19. package/dist/__tests__/SignalCli.events.test.d.ts +1 -0
  20. package/dist/__tests__/SignalCli.events.test.js +113 -0
  21. package/dist/__tests__/SignalCli.integration.test.js +6 -5
  22. package/dist/__tests__/SignalCli.methods.test.js +150 -66
  23. package/dist/__tests__/SignalCli.parsing.test.js +4 -13
  24. package/dist/__tests__/SignalCli.simple.test.d.ts +1 -0
  25. package/dist/__tests__/SignalCli.simple.test.js +77 -0
  26. package/dist/__tests__/SignalCli.test.js +133 -74
  27. package/dist/__tests__/config.test.js +19 -29
  28. package/dist/__tests__/errors.test.js +2 -2
  29. package/dist/__tests__/retry.test.js +10 -8
  30. package/dist/__tests__/robustness.test.d.ts +1 -0
  31. package/dist/__tests__/robustness.test.js +59 -0
  32. package/dist/__tests__/security.test.d.ts +1 -0
  33. package/dist/__tests__/security.test.js +50 -0
  34. package/dist/config.js +3 -3
  35. package/dist/interfaces.d.ts +27 -0
  36. package/dist/managers/AccountManager.d.ts +27 -0
  37. package/dist/managers/AccountManager.js +147 -0
  38. package/dist/managers/BaseManager.d.ts +9 -0
  39. package/dist/managers/BaseManager.js +17 -0
  40. package/dist/managers/ContactManager.d.ts +15 -0
  41. package/dist/managers/ContactManager.js +123 -0
  42. package/dist/managers/DeviceManager.d.ts +11 -0
  43. package/dist/managers/DeviceManager.js +139 -0
  44. package/dist/managers/GroupManager.d.ts +12 -0
  45. package/dist/managers/GroupManager.js +78 -0
  46. package/dist/managers/MessageManager.d.ts +18 -0
  47. package/dist/managers/MessageManager.js +301 -0
  48. package/dist/managers/StickerManager.d.ts +8 -0
  49. package/dist/managers/StickerManager.js +39 -0
  50. package/dist/retry.js +3 -3
  51. package/dist/validators.d.ts +9 -0
  52. package/dist/validators.js +20 -0
  53. package/package.json +11 -4
  54. package/scripts/install.js +1 -1
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const DeviceManager_1 = require("../managers/DeviceManager");
37
+ const events_1 = require("events");
38
+ const child_process_1 = require("child_process");
39
+ const qrcodeTerminal = __importStar(require("qrcode-terminal"));
40
+ jest.mock('child_process');
41
+ jest.mock('qrcode-terminal');
42
+ describe('DeviceManager', () => {
43
+ let deviceManager;
44
+ let mockSendRequest;
45
+ let mockLogger;
46
+ let mockConfig;
47
+ let mockProcess;
48
+ beforeEach(() => {
49
+ jest.clearAllMocks();
50
+ mockSendRequest = jest.fn();
51
+ mockLogger = {
52
+ debug: jest.fn(),
53
+ info: jest.fn(),
54
+ error: jest.fn(),
55
+ warn: jest.fn()
56
+ };
57
+ mockConfig = {
58
+ requestTimeout: 1000
59
+ };
60
+ deviceManager = new DeviceManager_1.DeviceManager(mockSendRequest, '+1234567890', mockLogger, mockConfig, 'signal-cli');
61
+ mockProcess = {
62
+ stdout: new events_1.EventEmitter(),
63
+ stderr: new events_1.EventEmitter(),
64
+ on: jest.fn(),
65
+ };
66
+ child_process_1.spawn.mockReturnValue(mockProcess);
67
+ });
68
+ it('should list devices', async () => {
69
+ const mockDevices = [{ id: 1, name: 'Device 1' }];
70
+ mockSendRequest.mockResolvedValue(mockDevices);
71
+ const result = await deviceManager.listDevices();
72
+ expect(result).toBe(mockDevices);
73
+ expect(mockSendRequest).toHaveBeenCalledWith('listDevices', { account: '+1234567890' });
74
+ });
75
+ it('should add device', async () => {
76
+ await deviceManager.addDevice('sgnl://link', 'New Device');
77
+ expect(mockSendRequest).toHaveBeenCalledWith('addDevice', {
78
+ account: '+1234567890',
79
+ uri: 'sgnl://link',
80
+ deviceName: 'New Device'
81
+ });
82
+ });
83
+ it('should remove device', async () => {
84
+ await deviceManager.removeDevice(2);
85
+ expect(mockSendRequest).toHaveBeenCalledWith('removeDevice', {
86
+ account: '+1234567890',
87
+ deviceId: 2
88
+ });
89
+ });
90
+ it('should update device', async () => {
91
+ await deviceManager.updateDevice({ deviceId: 2, deviceName: 'Updated' });
92
+ expect(mockSendRequest).toHaveBeenCalledWith('updateDevice', {
93
+ account: '+1234567890',
94
+ deviceId: 2,
95
+ deviceName: 'Updated'
96
+ });
97
+ });
98
+ describe('deviceLink', () => {
99
+ it('should handle successful linking', async () => {
100
+ const linkPromise = deviceManager.deviceLink({ name: 'Test Link' });
101
+ // Simulate stdout output
102
+ mockProcess.stdout.emit('data', Buffer.from('sgnl://link-uri\n'));
103
+ mockProcess.stdout.emit('data', Buffer.from('Device registered\n'));
104
+ // Simulate process exit
105
+ const closeCallback = child_process_1.spawn.mock.calls[0] ? child_process_1.spawn.mock.results[0].value.on.mock.calls.find((c) => c[0] === 'close')[1] : null;
106
+ // Actually we need to capture the 'close' event handler
107
+ const closeHandler = mockProcess.on.mock.calls.find(call => call[0] === 'close')[1];
108
+ closeHandler(0);
109
+ const result = await linkPromise;
110
+ expect(result.success).toBe(true);
111
+ expect(result.isLinked).toBe(true);
112
+ expect(result.qrCode?.uri).toBe('sgnl://link-uri');
113
+ });
114
+ it('should handle QR code display in console', async () => {
115
+ const linkPromise = deviceManager.deviceLink({
116
+ name: 'Test Link',
117
+ qrCodeOutput: 'console'
118
+ });
119
+ mockProcess.stdout.emit('data', Buffer.from('sgnl://link-uri\n'));
120
+ expect(qrcodeTerminal.generate).toHaveBeenCalledWith('sgnl://link-uri', { small: true });
121
+ const closeHandler = mockProcess.on.mock.calls.find(call => call[0] === 'close')[1];
122
+ closeHandler(0);
123
+ await linkPromise;
124
+ });
125
+ it('should handle linking failure', async () => {
126
+ const linkPromise = deviceManager.deviceLink({ name: 'Fail' });
127
+ mockProcess.stderr.emit('data', Buffer.from('ERROR: Something went wrong\n'));
128
+ const closeHandler = mockProcess.on.mock.calls.find(call => call[0] === 'close')[1];
129
+ closeHandler(1);
130
+ const result = await linkPromise;
131
+ expect(result.success).toBe(false);
132
+ expect(result.error).toBeDefined();
133
+ });
134
+ });
135
+ });
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const MultiAccountManager_1 = require("../MultiAccountManager");
4
+ const SignalCli_1 = require("../SignalCli");
5
+ const events_1 = require("events");
6
+ jest.mock('../SignalCli');
7
+ describe('MultiAccountManager Coverage', () => {
8
+ let manager;
9
+ let mockSignalCli;
10
+ beforeEach(() => {
11
+ jest.clearAllMocks();
12
+ mockSignalCli = new events_1.EventEmitter();
13
+ mockSignalCli.connect = jest.fn().mockResolvedValue(undefined);
14
+ mockSignalCli.disconnect = jest.fn();
15
+ mockSignalCli.removeAllListeners = jest.fn();
16
+ SignalCli_1.SignalCli.mockImplementation(() => mockSignalCli);
17
+ manager = new MultiAccountManager_1.MultiAccountManager();
18
+ });
19
+ it('should handle account events and bubbling', async () => {
20
+ await manager.addAccount('+1234567890');
21
+ const msgSpy = jest.fn();
22
+ manager.on('message', msgSpy);
23
+ mockSignalCli.emit('message', { envelope: { source: '+someone' } });
24
+ expect(msgSpy).toHaveBeenCalledWith('+1234567890', expect.objectContaining({ envelope: { source: '+someone' } }));
25
+ });
26
+ it('should handle account disconnection bubbling', async () => {
27
+ await manager.addAccount('+1234567890');
28
+ const discSpy = jest.fn();
29
+ manager.on('disconnected', discSpy);
30
+ mockSignalCli.emit('disconnected');
31
+ expect(discSpy).toHaveBeenCalledWith('+1234567890');
32
+ });
33
+ });
@@ -13,7 +13,7 @@ describe('MultiAccountManager', () => {
13
13
  jest.clearAllMocks();
14
14
  manager = new MultiAccountManager_1.MultiAccountManager({
15
15
  dataPath: '/tmp/test-data',
16
- verbose: false
16
+ verbose: false,
17
17
  });
18
18
  });
19
19
  afterEach(async () => {
@@ -137,7 +137,7 @@ describe('MultiAccountManager', () => {
137
137
  const instance = await manager.addAccount('+33123456789');
138
138
  instance.sendMessage = jest.fn().mockResolvedValue({
139
139
  timestamp: Date.now(),
140
- results: []
140
+ results: [],
141
141
  });
142
142
  await manager.sendMessage('+33123456789', '+33111111111', 'Hello!');
143
143
  expect(instance.sendMessage).toHaveBeenCalledWith('+33111111111', 'Hello!', {});
@@ -149,7 +149,7 @@ describe('MultiAccountManager', () => {
149
149
  const instance = await manager.addAccount('+33123456789');
150
150
  instance.sendMessage = jest.fn().mockResolvedValue({
151
151
  timestamp: Date.now(),
152
- results: []
152
+ results: [],
153
153
  });
154
154
  const options = { attachments: ['file.jpg'] };
155
155
  await manager.sendMessage('+33123456789', '+33111111111', 'Hello!', options);
@@ -20,8 +20,8 @@ describe('SignalBot Additional Tests', () => {
20
20
  logMessages: true,
21
21
  welcomeNewMembers: true,
22
22
  cooldownSeconds: 2,
23
- maxMessageLength: 1000
24
- }
23
+ maxMessageLength: 1000,
24
+ },
25
25
  };
26
26
  });
27
27
  afterEach(async () => {
@@ -31,7 +31,7 @@ describe('SignalBot Additional Tests', () => {
31
31
  bot.removeAllListeners();
32
32
  bot.getSignalCli().removeAllListeners();
33
33
  // Wait a bit for any async operations to complete
34
- await new Promise(resolve => process.nextTick(resolve));
34
+ await new Promise((resolve) => process.nextTick(resolve));
35
35
  }
36
36
  });
37
37
  describe('Command Management', () => {
@@ -41,17 +41,17 @@ describe('SignalBot Additional Tests', () => {
41
41
  bot.addCommand({
42
42
  name: 'custom',
43
43
  description: 'Custom command',
44
- handler: customHandler
44
+ handler: customHandler,
45
45
  });
46
46
  const commands = bot.getCommands();
47
- expect(commands.find(c => c.name === 'custom')).toBeDefined();
47
+ expect(commands.find((c) => c.name === 'custom')).toBeDefined();
48
48
  });
49
49
  test('should remove command successfully', () => {
50
50
  bot = new SignalBot_1.SignalBot(mockConfig);
51
51
  bot.addCommand({
52
52
  name: 'temp',
53
53
  description: 'Temporary command',
54
- handler: async () => 'temp'
54
+ handler: async () => 'temp',
55
55
  });
56
56
  expect(bot.removeCommand('temp')).toBe(true);
57
57
  expect(bot.removeCommand('nonexistent')).toBe(false);
@@ -61,15 +61,15 @@ describe('SignalBot Additional Tests', () => {
61
61
  bot.addCommand({
62
62
  name: 'test',
63
63
  description: 'Test command',
64
- handler: async () => 'test1'
64
+ handler: async () => 'test1',
65
65
  });
66
66
  bot.addCommand({
67
67
  name: 'test',
68
68
  description: 'Test command 2',
69
- handler: async () => 'test2'
69
+ handler: async () => 'test2',
70
70
  });
71
71
  const commands = bot.getCommands();
72
- const testCommands = commands.filter(c => c.name === 'test');
72
+ const testCommands = commands.filter((c) => c.name === 'test');
73
73
  expect(testCommands.length).toBe(1);
74
74
  });
75
75
  });
@@ -100,7 +100,7 @@ describe('SignalBot Additional Tests', () => {
100
100
  });
101
101
  test('should create bot without group config', () => {
102
102
  bot = new SignalBot_1.SignalBot({
103
- phoneNumber: '+1234567890'
103
+ phoneNumber: '+1234567890',
104
104
  });
105
105
  expect(bot).toBeDefined();
106
106
  expect(bot.getBotGroupId()).toBeNull();
@@ -112,8 +112,8 @@ describe('SignalBot Additional Tests', () => {
112
112
  name: 'Test Group',
113
113
  description: 'Test Description',
114
114
  createIfNotExists: true,
115
- initialMembers: ['+1111111111', '+2222222222']
116
- }
115
+ initialMembers: ['+1111111111', '+2222222222'],
116
+ },
117
117
  });
118
118
  expect(bot).toBeDefined();
119
119
  });
@@ -125,7 +125,7 @@ describe('SignalBot Additional Tests', () => {
125
125
  const mockSignalCli = bot.getSignalCli();
126
126
  const sendMessageSpy = jest.spyOn(mockSignalCli, 'sendMessage').mockResolvedValue({
127
127
  results: [{ type: 'SUCCESS' }],
128
- timestamp: Date.now()
128
+ timestamp: Date.now(),
129
129
  });
130
130
  // Send message (queued)
131
131
  const sendPromise = bot.sendMessage('+1111111111', 'Test message');
@@ -142,7 +142,7 @@ describe('SignalBot Additional Tests', () => {
142
142
  const mockSignalCli = bot.getSignalCli();
143
143
  const sendReactionSpy = jest.spyOn(mockSignalCli, 'sendReaction').mockResolvedValue({
144
144
  results: [{ type: 'SUCCESS' }],
145
- timestamp: Date.now()
145
+ timestamp: Date.now(),
146
146
  });
147
147
  // Send reaction (queued)
148
148
  const sendPromise = bot.sendReaction('+1111111111', '+2222222222', 123456, '👍');
@@ -159,16 +159,19 @@ describe('SignalBot Additional Tests', () => {
159
159
  const mockSignalCli = bot.getSignalCli();
160
160
  const sendMessageSpy = jest.spyOn(mockSignalCli, 'sendMessage').mockResolvedValue({
161
161
  results: [{ type: 'SUCCESS' }],
162
- timestamp: Date.now()
162
+ timestamp: Date.now(),
163
163
  });
164
164
  // Send message with attachment (queued)
165
- const sendPromise = bot.sendMessageWithAttachment('+1111111111', 'Message with files', ['file1.txt', 'file2.jpg']);
165
+ const sendPromise = bot.sendMessageWithAttachment('+1111111111', 'Message with files', [
166
+ 'file1.txt',
167
+ 'file2.jpg',
168
+ ]);
166
169
  // Advance timers to process queue and cleanup timer
167
170
  jest.advanceTimersByTime(2500); // 250ms for queue + 2000ms for cleanup
168
171
  await Promise.resolve();
169
172
  await sendPromise;
170
173
  expect(sendMessageSpy).toHaveBeenCalledWith('+1111111111', 'Message with files', {
171
- attachments: ['file1.txt', 'file2.jpg']
174
+ attachments: ['file1.txt', 'file2.jpg'],
172
175
  });
173
176
  jest.useRealTimers();
174
177
  });
@@ -176,7 +179,7 @@ describe('SignalBot Additional Tests', () => {
176
179
  describe('Configuration', () => {
177
180
  test('should use default settings when not provided', () => {
178
181
  bot = new SignalBot_1.SignalBot({
179
- phoneNumber: '+1234567890'
182
+ phoneNumber: '+1234567890',
180
183
  });
181
184
  const commands = bot.getCommands();
182
185
  expect(commands.length).toBeGreaterThan(0); // Should have default commands
@@ -185,8 +188,8 @@ describe('SignalBot Additional Tests', () => {
185
188
  bot = new SignalBot_1.SignalBot({
186
189
  phoneNumber: '+1234567890',
187
190
  settings: {
188
- commandPrefix: '!'
189
- }
191
+ commandPrefix: '!',
192
+ },
190
193
  });
191
194
  expect(bot).toBeDefined();
192
195
  });
@@ -200,8 +203,8 @@ describe('SignalBot Additional Tests', () => {
200
203
  logMessages: false,
201
204
  welcomeNewMembers: false,
202
205
  cooldownSeconds: 5,
203
- maxMessageLength: 2000
204
- }
206
+ maxMessageLength: 2000,
207
+ },
205
208
  });
206
209
  expect(bot).toBeDefined();
207
210
  });
@@ -244,12 +247,12 @@ describe('SignalBot Additional Tests', () => {
244
247
  phoneNumber: '+1234567890',
245
248
  group: {
246
249
  name: 'Test Group',
247
- createIfNotExists: false
248
- }
250
+ createIfNotExists: false,
251
+ },
249
252
  });
250
253
  const mockSignalCli = bot.getSignalCli();
251
254
  jest.spyOn(mockSignalCli, 'listDevices').mockResolvedValue([
252
- { id: 1, name: 'Test Device', created: Date.now(), lastSeen: Date.now() }
255
+ { id: 1, name: 'Test Device', created: Date.now(), lastSeen: Date.now() },
253
256
  ]);
254
257
  jest.spyOn(mockSignalCli, 'connect').mockResolvedValue(undefined);
255
258
  jest.spyOn(mockSignalCli, 'on').mockReturnValue(mockSignalCli);
@@ -270,28 +273,28 @@ describe('SignalBot Additional Tests', () => {
270
273
  test('should include help command', () => {
271
274
  bot = new SignalBot_1.SignalBot(mockConfig);
272
275
  const commands = bot.getCommands();
273
- const helpCmd = commands.find(c => c.name === 'help');
276
+ const helpCmd = commands.find((c) => c.name === 'help');
274
277
  expect(helpCmd).toBeDefined();
275
278
  expect(helpCmd?.description).toBeDefined();
276
279
  });
277
280
  test('should include stats command', () => {
278
281
  bot = new SignalBot_1.SignalBot(mockConfig);
279
282
  const commands = bot.getCommands();
280
- const statsCmd = commands.find(c => c.name === 'stats');
283
+ const statsCmd = commands.find((c) => c.name === 'stats');
281
284
  expect(statsCmd).toBeDefined();
282
285
  expect(statsCmd?.description).toBeDefined();
283
286
  });
284
287
  test('should include ping command', () => {
285
288
  bot = new SignalBot_1.SignalBot(mockConfig);
286
289
  const commands = bot.getCommands();
287
- const pingCmd = commands.find(c => c.name === 'ping');
290
+ const pingCmd = commands.find((c) => c.name === 'ping');
288
291
  expect(pingCmd).toBeDefined();
289
292
  expect(pingCmd?.description).toBeDefined();
290
293
  });
291
294
  test('should include info command', () => {
292
295
  bot = new SignalBot_1.SignalBot(mockConfig);
293
296
  const commands = bot.getCommands();
294
- const infoCmd = commands.find(c => c.name === 'info');
297
+ const infoCmd = commands.find((c) => c.name === 'info');
295
298
  expect(infoCmd).toBeDefined();
296
299
  expect(infoCmd?.description).toBeDefined();
297
300
  });
@@ -305,8 +308,8 @@ describe('SignalBot Additional Tests', () => {
305
308
  description: 'Test Description',
306
309
  createIfNotExists: true,
307
310
  initialMembers: ['+1111111111'],
308
- avatar: 'https://example.com/avatar.jpg'
309
- }
311
+ avatar: 'https://example.com/avatar.jpg',
312
+ },
310
313
  });
311
314
  expect(bot).toBeDefined();
312
315
  });
@@ -318,8 +321,8 @@ describe('SignalBot Additional Tests', () => {
318
321
  description: 'Test Description',
319
322
  createIfNotExists: true,
320
323
  initialMembers: ['+1111111111'],
321
- avatar: '/path/to/local/avatar.jpg'
322
- }
324
+ avatar: '/path/to/local/avatar.jpg',
325
+ },
323
326
  });
324
327
  expect(bot).toBeDefined();
325
328
  });
@@ -328,14 +331,14 @@ describe('SignalBot Additional Tests', () => {
328
331
  test('should handle empty admins list', () => {
329
332
  bot = new SignalBot_1.SignalBot({
330
333
  phoneNumber: '+1234567890',
331
- admins: []
334
+ admins: [],
332
335
  });
333
336
  expect(bot.isAdmin('+1234567890')).toBe(false);
334
337
  });
335
338
  test('should handle undefined settings', () => {
336
339
  bot = new SignalBot_1.SignalBot({
337
340
  phoneNumber: '+1234567890',
338
- settings: undefined
341
+ settings: undefined,
339
342
  });
340
343
  expect(bot).toBeDefined();
341
344
  });
@@ -343,9 +346,9 @@ describe('SignalBot Additional Tests', () => {
343
346
  bot = new SignalBot_1.SignalBot({
344
347
  phoneNumber: '+1234567890',
345
348
  settings: {
346
- commandPrefix: '!'
349
+ commandPrefix: '!',
347
350
  // Other settings will use defaults
348
- }
351
+ },
349
352
  });
350
353
  expect(bot).toBeDefined();
351
354
  });
@@ -0,0 +1 @@
1
+ export {};