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
package/README.md CHANGED
@@ -14,10 +14,10 @@
14
14
 
15
15
  [![npm version](https://badge.fury.io/js/signal-sdk.svg)](https://badge.fury.io/js/signal-sdk)
16
16
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
17
- [![signal-cli](https://img.shields.io/badge/signal--cli-v0.13.22-blue.svg)](https://github.com/AsamK/signal-cli)
17
+ [![signal-cli](https://img.shields.io/badge/signal--cli-v0.13.23-blue.svg)](https://github.com/AsamK/signal-cli)
18
18
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.8+-blue.svg)](https://www.typescriptlang.org/)
19
19
  [![Node.js](https://img.shields.io/badge/Node.js-18+-green.svg)](https://nodejs.org/)
20
- [![Tests](https://img.shields.io/badge/tests-310%20passing-brightgreen.svg)](./src/__tests__)
20
+ [![Tests](https://img.shields.io/badge/tests-393%20passing-brightgreen.svg)](./src/__tests__)
21
21
  [![Donate on Liberapay](https://img.shields.io/badge/Liberapay-Donate-yellow.svg)](https://liberapay.com/devbyben/donate)
22
22
 
23
23
  </div>
@@ -70,7 +70,8 @@
70
70
  - **Progress Tracking** - Monitor upload progress
71
71
  - **Polls** - Create, vote, and terminate polls
72
72
  - **Attachment Retrieval** - Retrieve attachments, avatars, and stickers
73
- - **Account Management** - Update account settings
73
+ - **Account Management** - Update account settings, PIN, and registration
74
+ - **Note to Self** - Send private notes to your own account
74
75
  - **Stories** - View and interact with Signal stories
75
76
  - **Group Information** - Retrieve detailed group permissions
76
77
 
@@ -213,7 +214,7 @@ bot.on("ready", () => {
213
214
  });
214
215
 
215
216
  bot.on("message", (message) => {
216
- console.log(`Received: ${message.text} from ${message.sender}`);
217
+ console.log(`Received: ${message.text} from ${message.source}`);
217
218
  });
218
219
 
219
220
  // Start the bot
@@ -362,9 +363,9 @@ await bot.start();
362
363
 
363
364
  - **Node.js**: >=18.0.0
364
365
  - **TypeScript**: 5.8+ with strict mode
365
- - **Test Coverage**: 225 passing tests across 9 suites
366
- - **Code Coverage**: 57.52% overall, critical modules at 96-100%
367
- - **signal-cli**: Compatible with v0.13.22
366
+ - **Test Coverage**: 393 passing tests across 21 suites
367
+ - **Code Coverage**: 83.54% overall, critical modules at 96-100%
368
+ - **signal-cli**: Compatible with v0.13.23
368
369
 
369
370
  ## Testing
370
371
 
@@ -372,9 +373,9 @@ The SDK has comprehensive test coverage to ensure reliability and quality.
372
373
 
373
374
  ### Test Statistics
374
375
 
375
- - **Total Tests**: 225 passing
376
- - **Test Suites**: 9 suites
377
- - **Overall Coverage**: 57.52%
376
+ - **Total Tests**: 393 passing
377
+ - **Test Suites**: 21 suites
378
+ - **Overall Coverage**: 83.54%
378
379
 
379
380
  ### Coverage by Module
380
381
 
@@ -570,7 +571,7 @@ This project is licensed under the MIT License - see the [LICENSE](./LICENSE) fi
570
571
 
571
572
  ## API Methods
572
573
 
573
- Compatible with signal-cli v0.13.22 - **100% Feature Coverage**
574
+ Compatible with signal-cli v0.13.23 - **100% Feature Coverage**
574
575
 
575
576
  | Category | Method | Description | Status |
576
577
  | --------------- | -------------------------- | ---------------------------------- | ------ |
@@ -595,6 +596,8 @@ Compatible with signal-cli v0.13.22 - **100% Feature Coverage**
595
596
  | | `getUserStatus` | Check registration status | ✅ |
596
597
  | **Account** | `updateAccount` | Update account settings | ✅ |
597
598
  | | `listAccountsDetailed` | List accounts with detailed info | ✅ |
599
+ | **Devices** | `listDevices` | List linked devices | ✅ |
600
+ | | `updateDevice` | Update device name (v0.13.23+) | ✅ |
598
601
  | **Attachments** | `getAttachment` | Retrieve attachment by ID | ✅ |
599
602
  | | `getAvatar` | Retrieve avatar by ID | ✅ |
600
603
  | | `getSticker` | Retrieve sticker by ID | ✅ |
@@ -605,6 +608,15 @@ Compatible with signal-cli v0.13.22 - **100% Feature Coverage**
605
608
  | | `startChangeNumber` | Start phone number change | ✅ |
606
609
  | | `finishChangeNumber` | Complete phone number change | ✅ |
607
610
  | | `sendMessageWithProgress` | Enhanced messaging with progress | ✅ |
611
+ | | `sendNoteToSelf` | Send message to own conversation | ✅ |
612
+ | | `unregister` | Unregister account from server | ✅ |
613
+ | **Identities** | `listIdentities` | List known identities | ✅ |
614
+ | | `trustIdentity` | Mark identity as trusted | ✅ |
615
+ | | `getSafetyNumber` | Get safety number for contact | ✅ |
616
+ | | `verifySafetyNumber` | Verify and trust safety number | ✅ |
617
+ | **Multi-Account**| `addAccount` | Add account to manager | ✅ |
618
+ | | `connectAll` | Connect all managed accounts | ✅ |
619
+ | | `getStatus` | Get status for all accounts | ✅ |
608
620
 
609
621
  [Complete API documentation](./docs/api-reference.md)
610
622
 
@@ -45,7 +45,7 @@ class MultiAccountManager extends events_1.EventEmitter {
45
45
  this.options = options;
46
46
  this.logger = new config_1.Logger({
47
47
  level: options.verbose ? 'debug' : 'info',
48
- enableFile: false
48
+ enableFile: false,
49
49
  });
50
50
  this.logger.info('MultiAccountManager initialized');
51
51
  }
@@ -65,7 +65,7 @@ class MultiAccountManager extends events_1.EventEmitter {
65
65
  const signalConfig = {
66
66
  signalCliPath: this.options.signalCliPath,
67
67
  verbose: this.options.verbose,
68
- ...config
68
+ ...config,
69
69
  };
70
70
  const instance = new SignalCli_1.SignalCli(account, undefined, signalConfig);
71
71
  // Forward events from this instance
@@ -75,7 +75,7 @@ class MultiAccountManager extends events_1.EventEmitter {
75
75
  account,
76
76
  instance,
77
77
  connected: false,
78
- lastActivity: Date.now()
78
+ lastActivity: Date.now(),
79
79
  };
80
80
  this.accounts.set(account, managedAccount);
81
81
  this.emit('accountAdded', account);
@@ -186,7 +186,7 @@ class MultiAccountManager extends events_1.EventEmitter {
186
186
  */
187
187
  async connectAll() {
188
188
  this.logger.info('Connecting all accounts');
189
- const promises = Array.from(this.accounts.keys()).map(account => this.connect(account).catch(error => {
189
+ const promises = Array.from(this.accounts.keys()).map((account) => this.connect(account).catch((error) => {
190
190
  this.logger.error(`Failed to connect ${account}:`, error);
191
191
  }));
192
192
  await Promise.all(promises);
@@ -197,7 +197,7 @@ class MultiAccountManager extends events_1.EventEmitter {
197
197
  */
198
198
  async disconnectAll() {
199
199
  this.logger.info('Disconnecting all accounts');
200
- const promises = Array.from(this.accounts.keys()).map(account => this.disconnect(account).catch(error => {
200
+ const promises = Array.from(this.accounts.keys()).map((account) => this.disconnect(account).catch((error) => {
201
201
  this.logger.error(`Failed to disconnect ${account}:`, error);
202
202
  }));
203
203
  await Promise.all(promises);
@@ -235,14 +235,14 @@ class MultiAccountManager extends events_1.EventEmitter {
235
235
  account: managedAccount.account,
236
236
  connected: managedAccount.connected,
237
237
  lastActivity: managedAccount.lastActivity,
238
- uptime: Date.now() - managedAccount.lastActivity
238
+ uptime: Date.now() - managedAccount.lastActivity,
239
239
  };
240
240
  }
241
241
  // Return status for all accounts
242
242
  const status = {
243
243
  totalAccounts: this.accounts.size,
244
244
  connectedAccounts: 0,
245
- accounts: []
245
+ accounts: [],
246
246
  };
247
247
  for (const [account, managed] of this.accounts) {
248
248
  if (managed.connected) {
@@ -252,7 +252,7 @@ class MultiAccountManager extends events_1.EventEmitter {
252
252
  account,
253
253
  connected: managed.connected,
254
254
  lastActivity: managed.lastActivity,
255
- uptime: Date.now() - managed.lastActivity
255
+ uptime: Date.now() - managed.lastActivity,
256
256
  });
257
257
  }
258
258
  return status;
@@ -264,16 +264,8 @@ class MultiAccountManager extends events_1.EventEmitter {
264
264
  */
265
265
  setupEventForwarding(account, instance) {
266
266
  // Forward all events with account prefix
267
- const events = [
268
- 'message',
269
- 'receipt',
270
- 'typing',
271
- 'reaction',
272
- 'error',
273
- 'connected',
274
- 'disconnected'
275
- ];
276
- events.forEach(event => {
267
+ const events = ['message', 'receipt', 'typing', 'reaction', 'error', 'connected', 'disconnected'];
268
+ events.forEach((event) => {
277
269
  instance.on(event, (...args) => {
278
270
  // Emit with account information
279
271
  this.emit(event, account, ...args);
@@ -281,7 +273,7 @@ class MultiAccountManager extends events_1.EventEmitter {
281
273
  this.emit('accountEvent', {
282
274
  account,
283
275
  event,
284
- data: args
276
+ data: args,
285
277
  });
286
278
  // Update last activity
287
279
  const managedAccount = this.accounts.get(account);
package/dist/SignalBot.js CHANGED
@@ -78,7 +78,7 @@ class SignalBot extends events_1.EventEmitter {
78
78
  commandsExecuted: 0,
79
79
  startTime: Date.now(),
80
80
  lastActivity: Date.now(),
81
- activeUsers: 0
81
+ activeUsers: 0,
82
82
  };
83
83
  this.setupDefaultCommands();
84
84
  }
@@ -93,7 +93,8 @@ class SignalBot extends events_1.EventEmitter {
93
93
  const tempFilePath = path.join(process.cwd(), tempFileName);
94
94
  const file = fs.createWriteStream(tempFilePath);
95
95
  const client = imageUrl.startsWith('https:') ? https : http;
96
- client.get(imageUrl, (response) => {
96
+ client
97
+ .get(imageUrl, (response) => {
97
98
  if (response.statusCode !== 200) {
98
99
  fs.unlink(tempFilePath, () => { }); // Clean up on error
99
100
  reject(new Error(`Failed to download image: ${response.statusCode}`));
@@ -108,7 +109,8 @@ class SignalBot extends events_1.EventEmitter {
108
109
  fs.unlink(tempFilePath, () => { }); // Clean up on error
109
110
  reject(err);
110
111
  });
111
- }).on('error', (err) => {
112
+ })
113
+ .on('error', (err) => {
112
114
  fs.unlink(tempFilePath, () => { }); // Clean up on error
113
115
  reject(err);
114
116
  });
@@ -124,7 +126,8 @@ class SignalBot extends events_1.EventEmitter {
124
126
  return new Promise((resolve, reject) => {
125
127
  const downloadWithRedirect = (url, maxRedirects = 5) => {
126
128
  const client = url.startsWith('https:') ? https : http;
127
- client.get(url, (response) => {
129
+ client
130
+ .get(url, (response) => {
128
131
  // Handle redirections (3xx status codes)
129
132
  if (response.statusCode && response.statusCode >= 300 && response.statusCode < 400) {
130
133
  if (maxRedirects <= 0) {
@@ -137,7 +140,9 @@ class SignalBot extends events_1.EventEmitter {
137
140
  return;
138
141
  }
139
142
  // Resolve relative URLs
140
- const finalUrl = redirectUrl.startsWith('http') ? redirectUrl : new URL(redirectUrl, url).href;
143
+ const finalUrl = redirectUrl.startsWith('http')
144
+ ? redirectUrl
145
+ : new URL(redirectUrl, url).href;
141
146
  this.log(`🔄 Following redirect to: ${finalUrl}`, 'DEBUG');
142
147
  downloadWithRedirect(finalUrl, maxRedirects - 1);
143
148
  return;
@@ -162,7 +167,8 @@ class SignalBot extends events_1.EventEmitter {
162
167
  fs.unlink(tempFilePath, () => { }); // Clean up on error
163
168
  reject(err);
164
169
  });
165
- }).on('error', (err) => {
170
+ })
171
+ .on('error', (err) => {
166
172
  reject(err);
167
173
  });
168
174
  };
@@ -189,7 +195,7 @@ class SignalBot extends events_1.EventEmitter {
189
195
  recipient,
190
196
  message,
191
197
  attachments: [tempFilePath],
192
- cleanup: [tempFilePath] // Mark files for cleanup after sending
198
+ cleanup: [tempFilePath], // Mark files for cleanup after sending
193
199
  });
194
200
  this.processActionQueue();
195
201
  }
@@ -319,7 +325,7 @@ class SignalBot extends events_1.EventEmitter {
319
325
  this.log('- Stopping Signal Bot...');
320
326
  this.isRunning = false;
321
327
  // Clear all active timers
322
- this.activeTimers.forEach(timer => clearTimeout(timer));
328
+ this.activeTimers.forEach((timer) => clearTimeout(timer));
323
329
  this.activeTimers = [];
324
330
  this.signalCli.disconnect();
325
331
  this.emit('stopped');
@@ -329,7 +335,7 @@ class SignalBot extends events_1.EventEmitter {
329
335
  this.log('- Gracefully shutting down Signal Bot...');
330
336
  this.isRunning = false;
331
337
  // Clear all active timers
332
- this.activeTimers.forEach(timer => clearTimeout(timer));
338
+ this.activeTimers.forEach((timer) => clearTimeout(timer));
333
339
  this.activeTimers = [];
334
340
  try {
335
341
  await this.signalCli.gracefulShutdown();
@@ -376,7 +382,7 @@ class SignalBot extends events_1.EventEmitter {
376
382
  getStats() {
377
383
  return {
378
384
  ...this.stats,
379
- activeUsers: this.userCooldowns.size
385
+ activeUsers: this.userCooldowns.size,
380
386
  };
381
387
  }
382
388
  /**
@@ -404,11 +410,11 @@ class SignalBot extends events_1.EventEmitter {
404
410
  description: 'Displays available commands',
405
411
  handler: async (message, args) => {
406
412
  const userCommands = Array.from(this.commands.values())
407
- .filter(cmd => !cmd.adminOnly || message.isFromAdmin)
408
- .map(cmd => `${this.config.settings.commandPrefix}${cmd.name} - ${cmd.description}`)
413
+ .filter((cmd) => !cmd.adminOnly || message.isFromAdmin)
414
+ .map((cmd) => `${this.config.settings.commandPrefix}${cmd.name} - ${cmd.description}`)
409
415
  .join('\n');
410
416
  return `Signal Bot Commands\n\n${userCommands}\n\n${message.isFromAdmin ? '| You have admin privileges' : ''}`;
411
- }
417
+ },
412
418
  });
413
419
  // Stats command
414
420
  this.addCommand({
@@ -417,12 +423,12 @@ class SignalBot extends events_1.EventEmitter {
417
423
  handler: async () => {
418
424
  const stats = this.getStats();
419
425
  const uptime = this.formatUptime(Date.now() - stats.startTime);
420
- return `Bot Statistics\n\n` +
426
+ return (`Bot Statistics\n\n` +
421
427
  `1. Messages Received: ${stats.messagesReceived}\n` +
422
428
  `2. Commands Executed: ${stats.commandsExecuted}\n` +
423
429
  `3. Uptime: ${uptime}\n` +
424
- `4. Active Users: ${stats.activeUsers}`;
425
- }
430
+ `4. Active Users: ${stats.activeUsers}`);
431
+ },
426
432
  });
427
433
  // Ping command
428
434
  this.addCommand({
@@ -431,7 +437,7 @@ class SignalBot extends events_1.EventEmitter {
431
437
  handler: async (message) => {
432
438
  const responseTime = Date.now() - message.timestamp;
433
439
  return `Pong! Response time: ${responseTime}ms`;
434
- }
440
+ },
435
441
  });
436
442
  // Info command (admin only)
437
443
  this.addCommand({
@@ -439,13 +445,13 @@ class SignalBot extends events_1.EventEmitter {
439
445
  description: 'Detailed bot information (admin)',
440
446
  adminOnly: true,
441
447
  handler: async () => {
442
- return `Bot Information\n\n` +
448
+ return (`Bot Information\n\n` +
443
449
  `- Number: ${this.config.phoneNumber}\n` +
444
450
  `- Group: ${this.config.group ? this.config.group.name : 'N/A'}\n` +
445
451
  `- Admins: ${this.config.admins.length}\n` +
446
452
  `- Commands: ${this.commands.size}\n` +
447
- `- Prefix: ${this.config.settings.commandPrefix}`;
448
- }
453
+ `- Prefix: ${this.config.settings.commandPrefix}`);
454
+ },
449
455
  });
450
456
  }
451
457
  async setupBotGroup() {
@@ -462,7 +468,7 @@ class SignalBot extends events_1.EventEmitter {
462
468
  }
463
469
  // Search for an existing group
464
470
  const groups = await this.signalCli.listGroups();
465
- const existingGroup = groups.find(group => group.name === this.config.group.name && group.isMember);
471
+ const existingGroup = groups.find((group) => group.name === this.config.group.name && group.isMember);
466
472
  if (existingGroup) {
467
473
  // Try different possible field names for the group ID
468
474
  const groupData = existingGroup;
@@ -471,7 +477,7 @@ class SignalBot extends events_1.EventEmitter {
471
477
  this.log(`- Existing group found: ${this.config.group.name} (${possibleGroupId})`);
472
478
  // Check if all admins are in the group and add them if not
473
479
  const currentMembers = existingGroup.members?.map((m) => m.number || m) || [];
474
- const missingAdmins = this.config.admins.filter(admin => !currentMembers.includes(admin));
480
+ const missingAdmins = this.config.admins.filter((admin) => !currentMembers.includes(admin));
475
481
  // Prepare update options
476
482
  const updateOptions = {};
477
483
  if (missingAdmins.length > 0) {
@@ -517,10 +523,7 @@ class SignalBot extends events_1.EventEmitter {
517
523
  }
518
524
  // Create a new group only if none exists
519
525
  this.log(`- Creating group: ${this.config.group.name}`);
520
- const initialMembers = [
521
- ...this.config.admins,
522
- ...(this.config.group.initialMembers || [])
523
- ].filter((member, index, array) => array.indexOf(member) === index);
526
+ const initialMembers = [...this.config.admins, ...(this.config.group.initialMembers || [])].filter((member, index, array) => array.indexOf(member) === index);
524
527
  try {
525
528
  const newGroup = await this.signalCli.createGroup(this.config.group.name, initialMembers);
526
529
  const newGroupData = newGroup;
@@ -531,7 +534,7 @@ class SignalBot extends events_1.EventEmitter {
531
534
  const configOptions = {
532
535
  description: this.config.group.description,
533
536
  permissionAddMember: 'ONLY_ADMINS',
534
- permissionEditDetails: 'ONLY_ADMINS'
537
+ permissionEditDetails: 'ONLY_ADMINS',
535
538
  };
536
539
  if (avatarPath) {
537
540
  configOptions.avatar = avatarPath;
@@ -556,7 +559,7 @@ class SignalBot extends events_1.EventEmitter {
556
559
  this.log(` 2. Add the bot number (${this.config.phoneNumber}) to the group`, 'INFO');
557
560
  this.log(` 3. Add all admins to the group: ${this.config.admins.join(', ')}`, 'INFO');
558
561
  this.log(` 4. Restart the bot`, 'INFO');
559
- this.log(` Available groups: ${groups.map(g => g.name).join(', ')}`, 'INFO');
562
+ this.log(` Available groups: ${groups.map((g) => g.name).join(', ')}`, 'INFO');
560
563
  // Don't use a fallback group - this is misleading behavior
561
564
  throw new Error(`Group "${this.config.group.name}" does not exist and cannot be created automatically. Please create it manually as described above.`);
562
565
  }
@@ -617,7 +620,7 @@ class SignalBot extends events_1.EventEmitter {
617
620
  text: messageData.envelope.dataMessage.message || '',
618
621
  timestamp: messageData.envelope.timestamp,
619
622
  groupInfo: messageData.envelope.dataMessage.groupInfo,
620
- isFromAdmin: this.isAdmin(messageData.envelope.sourceNumber || messageData.envelope.source)
623
+ isFromAdmin: this.isAdmin(messageData.envelope.sourceNumber || messageData.envelope.source),
621
624
  };
622
625
  // Ignore own messages
623
626
  if (parsedMessage.source === this.config.phoneNumber) {
@@ -697,8 +700,9 @@ class SignalBot extends events_1.EventEmitter {
697
700
  }
698
701
  }
699
702
  async sendCommandResponse(message, response) {
700
- const recipient = message.groupInfo ?
701
- (message.groupInfo.id || message.groupInfo.groupId || message.source) : message.source;
703
+ const recipient = message.groupInfo
704
+ ? message.groupInfo.id || message.groupInfo.groupId || message.source
705
+ : message.source;
702
706
  await this.sendMessage(recipient, response);
703
707
  }
704
708
  isOnCooldown(userId) {
@@ -707,7 +711,7 @@ class SignalBot extends events_1.EventEmitter {
707
711
  return false;
708
712
  const now = Date.now();
709
713
  const cooldownMs = (this.config.settings.cooldownSeconds || 2) * 1000;
710
- return (now - lastCommand) < cooldownMs;
714
+ return now - lastCommand < cooldownMs;
711
715
  }
712
716
  async processActionQueue() {
713
717
  if (this.isProcessingQueue || this.actionQueue.length === 0) {
@@ -727,13 +731,13 @@ class SignalBot extends events_1.EventEmitter {
727
731
  case 'sendMessageWithAttachment':
728
732
  this.log(`Executing sendMessageWithAttachment to ${action.recipient} with ${action.attachments.length} file(s)...`, 'DEBUG');
729
733
  await this.signalCli.sendMessage(action.recipient, action.message, {
730
- attachments: action.attachments
734
+ attachments: action.attachments,
731
735
  });
732
736
  // Wait a bit for signal-cli to finish processing the files before cleanup
733
737
  // signal-cli responds immediately but continues processing files in background
734
738
  if (action.cleanup && action.cleanup.length > 0) {
735
739
  const cleanupTimer = setTimeout(() => {
736
- action.cleanup.forEach(filePath => {
740
+ action.cleanup.forEach((filePath) => {
737
741
  this.cleanupTempFile(filePath);
738
742
  });
739
743
  // Remove timer from active list
@@ -752,7 +756,7 @@ class SignalBot extends events_1.EventEmitter {
752
756
  break;
753
757
  }
754
758
  // Wait a bit between actions to be safe
755
- await new Promise(resolve => {
759
+ await new Promise((resolve) => {
756
760
  const timer = setTimeout(resolve, 250);
757
761
  if (timer.unref)
758
762
  timer.unref();
@@ -762,7 +766,7 @@ class SignalBot extends events_1.EventEmitter {
762
766
  this.log(`ERROR: Failed to execute action ${action.type}: ${error?.message || error}`, 'ERROR');
763
767
  // Clean up temporary files even on error
764
768
  if (action.type === 'sendMessageWithAttachment' && action.cleanup && action.cleanup.length > 0) {
765
- action.cleanup.forEach(filePath => {
769
+ action.cleanup.forEach((filePath) => {
766
770
  this.cleanupTempFile(filePath);
767
771
  });
768
772
  }