innovators-bot2 2.0.0 → 2.0.2

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 (4) hide show
  1. package/README.md +222 -10
  2. package/example.js +509 -52
  3. package/index.js +609 -19
  4. package/package.json +2 -1
package/index.js CHANGED
@@ -61,6 +61,8 @@ class WhatsAppClient extends EventEmitter {
61
61
  maxMessagesPerChat: config.maxMessagesPerChat || 1000,
62
62
  ttl: config.messageTTL || 24 * 60 * 60 * 1000
63
63
  });
64
+ // Initialize contacts cache
65
+ this.contactsCache = new NodeCache({ stdTTL: 0, checkperiod: 20 }); // No TTL, manual cleanup on logout
64
66
  }
65
67
 
66
68
  /**
@@ -150,13 +152,11 @@ class WhatsAppClient extends EventEmitter {
150
152
  console.error(`Error fetching metadata for group ${jid}:`, error);
151
153
  return null;
152
154
  }
153
- }
155
+ },
154
156
  });
155
157
 
156
158
  this.store = this.sock.signalRepository.lidMapping;
157
159
 
158
-
159
-
160
160
  this.sock.ev.on('connection.update', async (update) => {
161
161
  const { connection, lastDisconnect, qr } = update;
162
162
 
@@ -167,13 +167,13 @@ class WhatsAppClient extends EventEmitter {
167
167
  if (this._connectionState !== 'connected') {
168
168
  const user = getCurrentSenderInfo(this.sock.authState)
169
169
  if (user) {
170
+ this.isConnected = true;
170
171
  const userInfo = {
171
172
  name: user.pushName || 'Unknown',
172
173
  phone: user.phoneNumber,
173
174
  platform: user.platform || 'Unknown',
174
- isOnline: true
175
+ isOnline: true,
175
176
  };
176
- this.isConnected = true;
177
177
  this._connectionState = 'connected';
178
178
  this.emit('connected', userInfo);
179
179
  }
@@ -387,6 +387,8 @@ class WhatsAppClient extends EventEmitter {
387
387
 
388
388
  // 👍 Handle message reactions
389
389
  this.sock.ev.on('messages.reaction', async (reactions) => {
390
+
391
+
390
392
  try {
391
393
  for (const reaction of reactions) {
392
394
  // Get the chat JID, preferring PN over LID
@@ -509,6 +511,34 @@ class WhatsAppClient extends EventEmitter {
509
511
  }
510
512
  });
511
513
 
514
+ // Handle contacts from history sync
515
+ this.sock.ev.on('messaging-history.set', ({ contacts: newContacts }) => {
516
+ if (newContacts && newContacts.length > 0) {
517
+ for (const contact of newContacts) {
518
+ this.contactsCache.set(contact.id, contact);
519
+ }
520
+ this.emit('contacts-received', newContacts);
521
+
522
+ }
523
+ });
524
+
525
+ // Handle contacts upsert (new contacts added)
526
+ this.sock.ev.on('contacts.upsert', (newContacts) => {
527
+ for (const contact of newContacts) {
528
+ this.contactsCache.set(contact.id, contact);
529
+ }
530
+ this.emit('contacts-upsert', newContacts);
531
+ });
532
+
533
+ // Handle contacts update (profile picture changes, etc.)
534
+ this.sock.ev.on('contacts.update', (updates) => {
535
+ for (const update of updates) {
536
+ const existing = this.contactsCache.get(update.id) || {};
537
+ this.contactsCache.set(update.id, { ...existing, ...update });
538
+ }
539
+ this.emit('contacts-update', updates);
540
+ });
541
+
512
542
  } catch (error) {
513
543
  console.error('Error in connect:', error);
514
544
  this.emit('error', error);
@@ -654,6 +684,10 @@ class WhatsAppClient extends EventEmitter {
654
684
  throw new Error('Unsupported file type: ' + fileExtension);
655
685
  }
656
686
 
687
+ if (options.mentions) {
688
+ mediaMessage.mentions = options.mentions;
689
+ }
690
+
657
691
  return await this.sock.sendMessage(chatId, mediaMessage, { ai: true });
658
692
  } catch (error) {
659
693
  console.error('Error sending media:', error);
@@ -684,11 +718,20 @@ class WhatsAppClient extends EventEmitter {
684
718
  const fileName = path.basename(filePath);
685
719
  const mimeType = mime.getType(filePath);
686
720
 
687
- return await this.sock.sendMessage(chatId, {
721
+ const messageContent = {
688
722
  document: fileBuffer,
689
723
  caption: caption,
690
724
  mimetype: mimeType,
691
725
  fileName: fileName,
726
+ };
727
+
728
+ if (typeof caption === 'object' && caption !== null) {
729
+ if (caption.caption) messageContent.caption = caption.caption;
730
+ if (caption.mentions) messageContent.mentions = caption.mentions;
731
+ }
732
+
733
+ return await this.sock.sendMessage(chatId, {
734
+ ...messageContent,
692
735
  }, { ai: true });
693
736
  } catch (error) {
694
737
  console.error('Error sending document:', error);
@@ -719,8 +762,16 @@ class WhatsAppClient extends EventEmitter {
719
762
  const {
720
763
  text,
721
764
  imagePath,
765
+ image,
766
+ video,
767
+ document,
768
+ location,
769
+ product,
770
+ mimetype,
771
+ jpegThumbnail,
722
772
  caption,
723
773
  title,
774
+ subtitle,
724
775
  footer,
725
776
  interactiveButtons = [],
726
777
  hasMediaAttachment = false,
@@ -729,24 +780,40 @@ class WhatsAppClient extends EventEmitter {
729
780
  let messageContent = {};
730
781
 
731
782
  try {
783
+ const base = {
784
+ title: title,
785
+ subtitle: subtitle,
786
+ footer: footer,
787
+ interactiveButtons: interactiveButtons,
788
+ hasMediaAttachment: hasMediaAttachment,
789
+ };
790
+
732
791
  if (imagePath) {
733
- // Handle message with image
792
+ // Handle message with local image path
734
793
  const imageBuffer = fs.readFileSync(imagePath);
735
794
  messageContent = {
795
+ ...base,
736
796
  image: imageBuffer,
737
797
  caption: caption,
738
- title: title,
739
- footer: footer,
740
- interactiveButtons: interactiveButtons,
741
- hasMediaAttachment: hasMediaAttachment,
798
+ };
799
+ } else if (image || video || document || location || product) {
800
+ // Pass-through media objects (e.g. { image: { url } })
801
+ messageContent = {
802
+ ...base,
803
+ ...(image ? { image } : {}),
804
+ ...(video ? { video } : {}),
805
+ ...(document ? { document } : {}),
806
+ ...(location ? { location } : {}),
807
+ ...(product ? { product } : {}),
808
+ ...(mimetype ? { mimetype } : {}),
809
+ ...(jpegThumbnail ? { jpegThumbnail } : {}),
810
+ caption: caption,
742
811
  };
743
812
  } else {
744
813
  // Handle text-only message
745
814
  messageContent = {
815
+ ...base,
746
816
  text: text,
747
- title: title,
748
- footer: footer,
749
- interactiveButtons: interactiveButtons,
750
817
  };
751
818
  }
752
819
 
@@ -1183,6 +1250,12 @@ class WhatsAppClient extends EventEmitter {
1183
1250
  this.sock = null;
1184
1251
  }
1185
1252
 
1253
+ // Clear store interval
1254
+ if (this._storeInterval) {
1255
+ clearInterval(this._storeInterval);
1256
+ this._storeInterval = null;
1257
+ }
1258
+
1186
1259
  // Add a small delay before reconnecting
1187
1260
  await new Promise(resolve => setTimeout(resolve, 1000));
1188
1261
 
@@ -1332,6 +1405,7 @@ class WhatsAppClient extends EventEmitter {
1332
1405
 
1333
1406
  // Update connection state and emit event
1334
1407
  this.isConnected = false;
1408
+
1335
1409
  this.emit('logout', 'Logged out successfully');
1336
1410
 
1337
1411
  return true;
@@ -1343,11 +1417,11 @@ class WhatsAppClient extends EventEmitter {
1343
1417
  }
1344
1418
 
1345
1419
  /**
1346
- * Download media from a message
1347
- * @param {object} message - The message object containing media (must have raw property)
1348
- * @returns {Promise<object|null>} Object with buffer, mimetype, and extension, or null if no media
1349
- * @throws {Error} If client is not connected or download fails
1350
- */
1420
+ * Download media from a message
1421
+ * @param {object} message - The message object containing media (must have raw property)
1422
+ * @returns {Promise<object|null>} Object with buffer, mimetype, and extension, or null if no media
1423
+ * @throws {Error} If client is not connected or download fails
1424
+ */
1351
1425
  async downloadMedia(message) {
1352
1426
  if (!this.isConnected) {
1353
1427
  throw new Error('Client is not connected');
@@ -1461,6 +1535,522 @@ class WhatsAppClient extends EventEmitter {
1461
1535
  }
1462
1536
  }
1463
1537
 
1538
+ // ═══════════════════════════════════════════════════════════
1539
+ // 📁 GROUP MANAGEMENT METHODS
1540
+ // ═══════════════════════════════════════════════════════════
1541
+
1542
+ /**
1543
+ * Create a new WhatsApp group
1544
+ * @param {string} name - The name/subject of the group
1545
+ * @param {Array<string>} participants - Array of participant JIDs (e.g., ['1234@s.whatsapp.net'])
1546
+ * @returns {Promise<object>} The created group info (includes gid/id)
1547
+ * @throws {Error} If client is not connected or group creation fails
1548
+ */
1549
+ async createGroup(name, participants = []) {
1550
+ if (!this.isConnected) {
1551
+ throw new Error('Client is not connected');
1552
+ }
1553
+
1554
+ try {
1555
+ const group = await this.sock.groupCreate(name, participants);
1556
+ return group;
1557
+ } catch (error) {
1558
+ console.error('Error creating group:', error);
1559
+ throw error;
1560
+ }
1561
+ }
1562
+
1563
+ /**
1564
+ * Change the subject (name) of a group
1565
+ * @param {string} groupId - The group JID
1566
+ * @param {string} newSubject - The new subject/name for the group
1567
+ * @returns {Promise<void>}
1568
+ * @throws {Error} If client is not connected or update fails
1569
+ */
1570
+ async changeGroupSubject(groupId, newSubject) {
1571
+ if (!this.isConnected) {
1572
+ throw new Error('Client is not connected');
1573
+ }
1574
+
1575
+ try {
1576
+ await this.sock.groupUpdateSubject(groupId, newSubject);
1577
+ // Update the cache with the new subject
1578
+ const cached = this.groupMetadataCache.get(groupId);
1579
+ if (cached) {
1580
+ cached.subject = newSubject;
1581
+ this.updateGroupMetadataCache(groupId, cached);
1582
+ }
1583
+ } catch (error) {
1584
+ console.error('Error changing group subject:', error);
1585
+ throw error;
1586
+ }
1587
+ }
1588
+
1589
+ /**
1590
+ * Change the description of a group
1591
+ * @param {string} groupId - The group JID
1592
+ * @param {string} newDescription - The new description for the group
1593
+ * @returns {Promise<void>}
1594
+ * @throws {Error} If client is not connected or update fails
1595
+ */
1596
+ async changeGroupDescription(groupId, newDescription) {
1597
+ if (!this.isConnected) {
1598
+ throw new Error('Client is not connected');
1599
+ }
1600
+
1601
+ try {
1602
+ await this.sock.groupUpdateDescription(groupId, newDescription);
1603
+ // Update the cache with the new description
1604
+ const cached = this.groupMetadataCache.get(groupId);
1605
+ if (cached) {
1606
+ cached.desc = newDescription;
1607
+ this.updateGroupMetadataCache(groupId, cached);
1608
+ }
1609
+ } catch (error) {
1610
+ console.error('Error changing group description:', error);
1611
+ throw error;
1612
+ }
1613
+ }
1614
+
1615
+ /**
1616
+ * Change group settings (announcement mode, locked/unlocked)
1617
+ * @param {string} groupId - The group JID
1618
+ * @param {string} setting - The setting to apply: 'announcement' (only admins send), 'not_announcement' (everyone sends), 'locked' (only admins edit info), 'unlocked' (everyone edits info)
1619
+ * @returns {Promise<void>}
1620
+ * @throws {Error} If client is not connected or update fails
1621
+ */
1622
+ async changeGroupSettings(groupId, setting) {
1623
+ if (!this.isConnected) {
1624
+ throw new Error('Client is not connected');
1625
+ }
1626
+
1627
+ const validSettings = ['announcement', 'not_announcement', 'locked', 'unlocked'];
1628
+ if (!validSettings.includes(setting)) {
1629
+ throw new Error(`Invalid setting: ${setting}. Must be one of: ${validSettings.join(', ')}`);
1630
+ }
1631
+
1632
+ try {
1633
+ await this.sock.groupSettingUpdate(groupId, setting);
1634
+ } catch (error) {
1635
+ console.error('Error changing group settings:', error);
1636
+ throw error;
1637
+ }
1638
+ }
1639
+
1640
+ /**
1641
+ * Get the invite code for a group
1642
+ * @param {string} groupId - The group JID
1643
+ * @returns {Promise<string>} The invite code (use with https://chat.whatsapp.com/{code})
1644
+ * @throws {Error} If client is not connected or fetch fails
1645
+ */
1646
+ async getGroupInviteCode(groupId) {
1647
+ if (!this.isConnected) {
1648
+ throw new Error('Client is not connected');
1649
+ }
1650
+
1651
+ try {
1652
+ const code = await this.sock.groupInviteCode(groupId);
1653
+ return code;
1654
+ } catch (error) {
1655
+ console.error('Error getting group invite code:', error);
1656
+ throw error;
1657
+ }
1658
+ }
1659
+
1660
+ /**
1661
+ * Revoke the current invite code for a group (generates a new one)
1662
+ * @param {string} groupId - The group JID
1663
+ * @returns {Promise<string>} The new invite code
1664
+ * @throws {Error} If client is not connected or revoke fails
1665
+ */
1666
+ async revokeGroupInviteCode(groupId) {
1667
+ if (!this.isConnected) {
1668
+ throw new Error('Client is not connected');
1669
+ }
1670
+
1671
+ try {
1672
+ const newCode = await this.sock.groupRevokeInvite(groupId);
1673
+ return newCode;
1674
+ } catch (error) {
1675
+ console.error('Error revoking group invite code:', error);
1676
+ throw error;
1677
+ }
1678
+ }
1679
+
1680
+ /**
1681
+ * Leave a group
1682
+ * @param {string} groupId - The group JID
1683
+ * @returns {Promise<void>}
1684
+ * @throws {Error} If client is not connected or leave fails
1685
+ */
1686
+ async leaveGroup(groupId) {
1687
+ if (!this.isConnected) {
1688
+ throw new Error('Client is not connected');
1689
+ }
1690
+
1691
+ try {
1692
+ await this.sock.groupLeave(groupId);
1693
+ // Clean up the cache for this group
1694
+ this.clearGroupMetadataCache(groupId);
1695
+ } catch (error) {
1696
+ console.error('Error leaving group:', error);
1697
+ throw error;
1698
+ }
1699
+ }
1700
+
1701
+ /**
1702
+ * Join a group using an invitation code
1703
+ * @param {string} inviteCode - The invite code (without https://chat.whatsapp.com/)
1704
+ * @returns {Promise<string>} The group JID that was joined
1705
+ * @throws {Error} If client is not connected or join fails
1706
+ */
1707
+ async joinGroupByInviteCode(inviteCode) {
1708
+ if (!this.isConnected) {
1709
+ throw new Error('Client is not connected');
1710
+ }
1711
+
1712
+ try {
1713
+ // Strip URL prefix if accidentally included
1714
+ const code = inviteCode.replace('https://chat.whatsapp.com/', '');
1715
+ const response = await this.sock.groupAcceptInvite(code);
1716
+ return response;
1717
+ } catch (error) {
1718
+ console.error('Error joining group by invite code:', error);
1719
+ throw error;
1720
+ }
1721
+ }
1722
+
1723
+ /**
1724
+ * Get group info by invite code (without joining)
1725
+ * @param {string} inviteCode - The invite code (without https://chat.whatsapp.com/)
1726
+ * @returns {Promise<object>} The group information
1727
+ * @throws {Error} If client is not connected or fetch fails
1728
+ */
1729
+
1730
+ async getGroupInfoByInviteCode(inviteCode) {
1731
+ if (!this.isConnected) {
1732
+ throw new Error('Client is not connected');
1733
+ }
1734
+
1735
+ try {
1736
+ // Strip URL prefix if accidentally included
1737
+ const code = inviteCode.replace('https://chat.whatsapp.com/', '');
1738
+ const response = await this.sock.groupGetInviteInfo(code);
1739
+ return response;
1740
+ } catch (error) {
1741
+ console.error('Error getting group info by invite code:', error);
1742
+ throw error;
1743
+ }
1744
+ }
1745
+
1746
+ /**
1747
+ * Get the list of pending join requests for a group
1748
+ * @param {string} groupId - The group JID
1749
+ * @returns {Promise<Array>} Array of pending join requests
1750
+ * @throws {Error} If client is not connected or fetch fails
1751
+ */
1752
+
1753
+ async getGroupJoinRequests(groupId) {
1754
+ if (!this.isConnected) {
1755
+ throw new Error('Client is not connected');
1756
+ }
1757
+
1758
+ try {
1759
+ const response = await this.sock.groupRequestParticipantsList(groupId);
1760
+ return response;
1761
+ } catch (error) {
1762
+ console.error('Error getting group join requests:', error);
1763
+ throw error;
1764
+ }
1765
+ }
1766
+
1767
+ /**
1768
+ * Approve or reject group join requests
1769
+ * @param {string} groupId - The group JID
1770
+ * @param {Array<string>} participantIds - Array of participant JIDs to approve/reject
1771
+ * @param {string} action - 'approve' or 'reject'
1772
+ * @returns {Promise<object>} The response from the action
1773
+ * @throws {Error} If client is not connected or action fails
1774
+ */
1775
+ async handleGroupJoinRequest(groupId, participantIds, action) {
1776
+ if (!this.isConnected) {
1777
+ throw new Error('Client is not connected');
1778
+ }
1779
+
1780
+ const validActions = ['approve', 'reject'];
1781
+ if (!validActions.includes(action)) {
1782
+ throw new Error(`Invalid action: ${action}. Must be one of: ${validActions.join(', ')}`);
1783
+ }
1784
+
1785
+ try {
1786
+ const response = await this.sock.groupRequestParticipantsUpdate(groupId, participantIds, action);
1787
+ return response;
1788
+ } catch (error) {
1789
+ console.error(`Error ${action}ing group join request:`, error);
1790
+ throw error;
1791
+ }
1792
+ }
1793
+
1794
+ /**
1795
+ * Toggle ephemeral (disappearing) messages in a group
1796
+ * @param {string} groupId - The group JID
1797
+ * @param {number} ephemeralExpiration - Duration in seconds (0 = off, 86400 = 24h, 604800 = 7d, 7776000 = 90d)
1798
+ * @returns {Promise<void>}
1799
+ * @throws {Error} If client is not connected or toggle fails
1800
+ */
1801
+ async toggleGroupEphemeral(groupId, ephemeralExpiration) {
1802
+ if (!this.isConnected) {
1803
+ throw new Error('Client is not connected');
1804
+ }
1805
+
1806
+ try {
1807
+ await this.sock.groupToggleEphemeral(groupId, ephemeralExpiration);
1808
+ } catch (error) {
1809
+ console.error('Error toggling group ephemeral:', error);
1810
+ throw error;
1811
+ }
1812
+ }
1813
+
1814
+ /**
1815
+ * Change who can add members to a group
1816
+ * @param {string} groupId - The group JID
1817
+ * @param {string} mode - 'all_member_add' (all members can add) or 'admin_add' (only admins can add)
1818
+ * @returns {Promise<void>}
1819
+ * @throws {Error} If client is not connected or update fails
1820
+ */
1821
+ async changeGroupAddMode(groupId, mode) {
1822
+ if (!this.isConnected) {
1823
+ throw new Error('Client is not connected');
1824
+ }
1825
+
1826
+ const validModes = ['all_member_add', 'admin_add'];
1827
+ if (!validModes.includes(mode)) {
1828
+ throw new Error(`Invalid mode: ${mode}. Must be one of: ${validModes.join(', ')}`);
1829
+ }
1830
+
1831
+ try {
1832
+ await this.sock.groupMemberAddMode(groupId, mode);
1833
+ } catch (error) {
1834
+ console.error('Error changing group add mode:', error);
1835
+ throw error;
1836
+ }
1837
+ }
1838
+
1839
+ // ═══════════════════════════════════════════════════════════
1840
+ // 🔒 PRIVACY METHODS
1841
+ // ═══════════════════════════════════════════════════════════
1842
+
1843
+ /**
1844
+ * Block a user
1845
+ * @param {string} jid - The JID of the user to block
1846
+ * @returns {Promise<void>}
1847
+ * @throws {Error} If client is not connected or block fails
1848
+ */
1849
+ async blockUser(jid) {
1850
+ if (!this.isConnected) {
1851
+ throw new Error('Client is not connected');
1852
+ }
1853
+
1854
+ try {
1855
+ await this.sock.updateBlockStatus(jid, 'block');
1856
+ } catch (error) {
1857
+ console.error('Error blocking user:', error);
1858
+ throw error;
1859
+ }
1860
+ }
1861
+
1862
+ /**
1863
+ * Unblock a user
1864
+ * @param {string} jid - The JID of the user to unblock
1865
+ * @returns {Promise<void>}
1866
+ * @throws {Error} If client is not connected or unblock fails
1867
+ */
1868
+ async unblockUser(jid) {
1869
+ if (!this.isConnected) {
1870
+ throw new Error('Client is not connected');
1871
+ }
1872
+
1873
+ try {
1874
+ await this.sock.updateBlockStatus(jid, 'unblock');
1875
+ } catch (error) {
1876
+ console.error('Error unblocking user:', error);
1877
+ throw error;
1878
+ }
1879
+ }
1880
+
1881
+ /**
1882
+ * Get current privacy settings
1883
+ * @param {boolean} [forceGet=true] - Whether to force-fetch the latest settings
1884
+ * @returns {Promise<object>} The privacy settings object
1885
+ * @throws {Error} If client is not connected or fetch fails
1886
+ */
1887
+ async getPrivacySettings(forceGet = true) {
1888
+ if (!this.isConnected) {
1889
+ throw new Error('Client is not connected');
1890
+ }
1891
+
1892
+ try {
1893
+ const settings = await this.sock.fetchPrivacySettings(forceGet);
1894
+ return settings;
1895
+ } catch (error) {
1896
+ console.error('Error fetching privacy settings:', error);
1897
+ throw error;
1898
+ }
1899
+ }
1900
+
1901
+ /**
1902
+ * Get the list of blocked contacts
1903
+ * @returns {Promise<Array<string>>} Array of blocked JIDs
1904
+ * @throws {Error} If client is not connected or fetch fails
1905
+ */
1906
+ async getBlockList() {
1907
+ if (!this.isConnected) {
1908
+ throw new Error('Client is not connected');
1909
+ }
1910
+
1911
+ try {
1912
+ const blocklist = await this.sock.fetchBlocklist();
1913
+ return blocklist;
1914
+ } catch (error) {
1915
+ console.error('Error fetching block list:', error);
1916
+ throw error;
1917
+ }
1918
+ }
1919
+
1920
+ /**
1921
+ * Update last seen privacy setting
1922
+ * @param {string} value - 'all' | 'contacts' | 'contact_blacklist' | 'none'
1923
+ * @returns {Promise<void>}
1924
+ * @throws {Error} If client is not connected or update fails
1925
+ */
1926
+ async updateLastSeenPrivacy(value) {
1927
+ if (!this.isConnected) {
1928
+ throw new Error('Client is not connected');
1929
+ }
1930
+
1931
+ try {
1932
+ await this.sock.updateLastSeenPrivacy(value);
1933
+ } catch (error) {
1934
+ console.error('Error updating last seen privacy:', error);
1935
+ throw error;
1936
+ }
1937
+ }
1938
+
1939
+ /**
1940
+ * Update online status privacy setting
1941
+ * @param {string} value - 'all' | 'match_last_seen'
1942
+ * @returns {Promise<void>}
1943
+ * @throws {Error} If client is not connected or update fails
1944
+ */
1945
+ async updateOnlinePrivacy(value) {
1946
+ if (!this.isConnected) {
1947
+ throw new Error('Client is not connected');
1948
+ }
1949
+
1950
+ try {
1951
+ await this.sock.updateOnlinePrivacy(value);
1952
+ } catch (error) {
1953
+ console.error('Error updating online privacy:', error);
1954
+ throw error;
1955
+ }
1956
+ }
1957
+
1958
+ /**
1959
+ * Update profile picture privacy setting
1960
+ * @param {string} value - 'all' | 'contacts' | 'contact_blacklist' | 'none'
1961
+ * @returns {Promise<void>}
1962
+ * @throws {Error} If client is not connected or update fails
1963
+ */
1964
+ async updateProfilePicturePrivacy(value) {
1965
+ if (!this.isConnected) {
1966
+ throw new Error('Client is not connected');
1967
+ }
1968
+
1969
+ try {
1970
+ await this.sock.updateProfilePicturePrivacy(value);
1971
+ } catch (error) {
1972
+ console.error('Error updating profile picture privacy:', error);
1973
+ throw error;
1974
+ }
1975
+ }
1976
+
1977
+ /**
1978
+ * Update status privacy setting
1979
+ * @param {string} value - 'all' | 'contacts' | 'contact_blacklist' | 'none'
1980
+ * @returns {Promise<void>}
1981
+ * @throws {Error} If client is not connected or update fails
1982
+ */
1983
+ async updateStatusPrivacy(value) {
1984
+ if (!this.isConnected) {
1985
+ throw new Error('Client is not connected');
1986
+ }
1987
+
1988
+ try {
1989
+ await this.sock.updateStatusPrivacy(value);
1990
+ } catch (error) {
1991
+ console.error('Error updating status privacy:', error);
1992
+ throw error;
1993
+ }
1994
+ }
1995
+
1996
+ /**
1997
+ * Update read receipts privacy setting
1998
+ * @param {string} value - 'all' | 'none'
1999
+ * @returns {Promise<void>}
2000
+ * @throws {Error} If client is not connected or update fails
2001
+ */
2002
+
2003
+ async updateReadReceiptsPrivacy(value) {
2004
+ if (!this.isConnected) {
2005
+ throw new Error('Client is not connected');
2006
+ }
2007
+
2008
+ try {
2009
+ await this.sock.updateReadReceiptsPrivacy(value);
2010
+ } catch (error) {
2011
+ console.error('Error updating read receipts privacy:', error);
2012
+ throw error;
2013
+ }
2014
+ }
2015
+
2016
+ /**
2017
+ * Update groups add privacy setting (who can add you to groups)
2018
+ * @param {string} value - 'all' | 'contacts' | 'contact_blacklist'
2019
+ * @returns {Promise<void>}
2020
+ * @throws {Error} If client is not connected or update fails
2021
+ */
2022
+
2023
+ async updateGroupsAddPrivacy(value) {
2024
+ if (!this.isConnected) {
2025
+ throw new Error('Client is not connected');
2026
+ }
2027
+ try {
2028
+ await this.sock.updateGroupsAddPrivacy(value);
2029
+ } catch (error) {
2030
+ console.error('Error updating groups add privacy:', error);
2031
+ throw error;
2032
+ }
2033
+ }
2034
+
2035
+ /**
2036
+ * Update default disappearing mode for new chats
2037
+ * @param {number} duration - Duration in seconds (0 = off, 86400 = 24h, 604800 = 7d, 7776000 = 90d)
2038
+ * @returns {Promise<void>}
2039
+ * @throws {Error} If client is not connected or update fails
2040
+ */
2041
+
2042
+ async updateDefaultDisappearingMode(duration) {
2043
+ if (!this.isConnected) {
2044
+ throw new Error('Client is not connected');
2045
+ }
2046
+ try {
2047
+ await this.sock.updateDefaultDisappearingMode(duration);
2048
+ } catch (error) {
2049
+ console.error('Error updating default disappearing mode:', error);
2050
+ throw error;
2051
+ }
2052
+ }
2053
+
1464
2054
  /**
1465
2055
  * Add EXIF metadata to an existing WebP buffer
1466
2056
  * @param {Buffer} buffer - WebP buffer