whalibmob 5.7.3 → 5.9.1

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/cli.js CHANGED
@@ -280,6 +280,47 @@ function kv(label, value) {
280
280
 
281
281
  function hr() { out(' ' + '─'.repeat(56)); }
282
282
 
283
+ // Why a group action did or did not go through, per participant. The server
284
+ // decides each one separately, so a run that half worked has to say which half.
285
+ const PARTICIPANT_ERRORS = {
286
+ 400: 'bad request',
287
+ 401: 'not authorised',
288
+ 403: 'their privacy settings do not allow it',
289
+ 404: 'not on WhatsApp',
290
+ 408: 'not a member',
291
+ 409: 'already a member',
292
+ 500: 'server error'
293
+ };
294
+
295
+ // A participant, with the phone number behind their LID when the server told
296
+ // us one — a bare LID says nothing about who the person is.
297
+ function participantLine(p) {
298
+ const role = p.role && p.role !== 'member' ? ' [' + p.role + ']' : '';
299
+ const pn = (p.phoneNumber && p.phoneNumber !== p.jid) ? ' (' + p.phoneNumber + ')' : '';
300
+ return p.jid + pn + role;
301
+ }
302
+
303
+ // A chat setting either reached app state — and so every other device — or it
304
+ // did not, and stayed here. Saying which costs one word and saves the user
305
+ // wondering why their phone did not follow.
306
+ function chatResult(label, synced) {
307
+ return label + (synced ? '' : ' (this session only — no app state key)');
308
+ }
309
+
310
+ function printParticipantResults(verb, results) {
311
+ const okList = results.filter(r => r.ok);
312
+ const badList = results.filter(r => !r.ok);
313
+ if (okList.length) out(' ' + verb + ' ' + okList.map(String).join(', '));
314
+ for (const r of badList) {
315
+ const why = PARTICIPANT_ERRORS[r.error] || 'error ' + r.error;
316
+ out(' failed ' + r.jid + ' — ' + why + ' (' + r.status + ')' +
317
+ (r.needsInvite ? ' · can be invited instead' : '') +
318
+ (r.invited === true ? ' · invitation sent' : '') +
319
+ (r.invited === false ? ' · invitation failed: ' + r.inviteError : ''));
320
+ }
321
+ if (!okList.length && !badList.length) out(' the server answered about nobody');
322
+ }
323
+
283
324
  // ─── helpers ──────────────────────────────────────────────────────────────────
284
325
 
285
326
  function defaultSessionDir() {
@@ -382,8 +423,10 @@ const HELP = `
382
423
  /unpin <jid> unpin chat
383
424
  /archive <jid> archive chat
384
425
  /unarchive <jid> unarchive chat
385
- /star <jid> <msgId> star a message
386
- /unstar <jid> <msgId> unstar a message
426
+ /star <jid> <msgId> [me] star a message ("me" if you sent it)
427
+ /unstar <jid> <msgId> [me] unstar a message
428
+ /appstate [collection...] pull pins/archives/mutes/stars from your phone
429
+ /appstate --snapshot re-read all of it from scratch
387
430
  /ephemeral <jid> <seconds> set disappearing timer for chat
388
431
  /ephemeral-default <seconds> set default timer for ALL new chats
389
432
  /block <jid> block contact
@@ -394,6 +437,7 @@ const HELP = `
394
437
  /group create <name> <jid...> create group
395
438
  /group leave <jid> leave group
396
439
  /group add <jid> <member...> add participants
440
+ /group add-invite <jid> <member...> add, and invite whoever cannot be added
397
441
  /group remove <jid> <member...> remove participants
398
442
  /group promote <jid> <member...> promote to admin
399
443
  /group demote <jid> <member...> demote from admin
@@ -409,6 +453,13 @@ const HELP = `
409
453
  /group pending <jid> list pending join requests
410
454
  /group approve <jid> <member...> approve pending join requests
411
455
  /group reject <jid> <member...> reject pending join requests
456
+ /group send-invite <jid> <member> <code> <expiration>
457
+ send a personal invitation
458
+ /group accept-invite <jid> <inviter> <code> [expiration]
459
+ accept a personal invitation
460
+ /group preview-invite <jid> <inviter> <code> [expiration]
461
+ preview a group from a personal invitation
462
+ /group revoke-invite <jid> <member> withdraw a personal invitation
412
463
  /group settings <jid> <setting> <policy>
413
464
  settings: edit_group_info send_messages
414
465
  add_participants approve_participants
@@ -497,6 +548,11 @@ function attachEvents(client) {
497
548
  case 'contact':
498
549
  kv('type', 'contact name: ' + d.displayName);
499
550
  break;
551
+ case 'groupInvite':
552
+ kv('type', 'group invitation ' + (d.groupName || d.groupJid));
553
+ kv('accept with', '/group accept-invite ' + d.groupJid + ' ' +
554
+ (msg.participant || msg.from) + ' ' + d.inviteCode + ' ' + d.inviteExpiration);
555
+ break;
500
556
  default:
501
557
  kv('type', d.type);
502
558
  }
@@ -520,6 +576,37 @@ function attachEvents(client) {
520
576
  _rl && (_rl.resume(), _rl.prompt(true));
521
577
  });
522
578
 
579
+ // Changes made on the phone or another linked device. `remote` marks them as
580
+ // somebody else's doing — our own calls emit the same events without it.
581
+ const chatChange = (label) => (u) => {
582
+ if (!u || !u.remote) return;
583
+ _rl && _rl.pause();
584
+ out(' ' + label(u));
585
+ _rl && (_rl.resume(), _rl.prompt(true));
586
+ };
587
+ client.on('chat_pinned', chatChange(u => (u.pinned ? 'pinned' : 'unpinned') + ' ' + u.jid));
588
+ client.on('chat_archived', chatChange(u => (u.archived ? 'archived' : 'unarchived') + ' ' + u.jid));
589
+ client.on('chat_read', chatChange(u => 'marked ' + (u.read ? 'read' : 'unread') + ' ' + u.jid));
590
+ client.on('chat_muted', chatChange(u => (u.muted ? 'muted' : 'unmuted') + ' ' + u.jid +
591
+ (u.muted && u.until > 0 ? ' until ' + new Date(u.until).toISOString() : '')));
592
+ client.on('message_starred', chatChange(u =>
593
+ (u.starred ? 'starred' : 'unstarred') + ' ' + u.msgId + ' in ' + u.chatJid));
594
+ client.on('contact_update', chatChange(u => 'contact ' + u.jid + (u.name ? ' → ' + u.name : '')));
595
+ client.on('push_name_update', chatChange(u => 'your name is now ' + u.name));
596
+
597
+ client.on('app_state_key_missing', (e) => {
598
+ _rl && _rl.pause();
599
+ out(' app state: waiting for a sync key from your phone (' + e.collection + ')');
600
+ _rl && (_rl.resume(), _rl.prompt(true));
601
+ });
602
+
603
+ client.on('app_state_keys', (e) => {
604
+ _rl && _rl.pause();
605
+ out(' app state: received ' + e.keys.length + ' sync key(s) from your phone —' +
606
+ ' pins, archives, mutes and stars will sync from now on');
607
+ _rl && (_rl.resume(), _rl.prompt(true));
608
+ });
609
+
523
610
  client.on('decrypt_error', (e) => {
524
611
  _rl && _rl.pause();
525
612
  out(' DECRYPT_ERROR from ' + e.from + ' id ' + e.id + ' : ' + (e.err && e.err.message));
@@ -1325,11 +1412,37 @@ async function handleLine(line) {
1325
1412
  out('marked read');
1326
1413
  break;
1327
1414
 
1415
+ case '/appstate': {
1416
+ requireConn();
1417
+ const snapshot = p.includes('--snapshot');
1418
+ const names = p.slice(1).filter(a => a !== '--snapshot');
1419
+ out('syncing app state' + (snapshot ? ' from scratch' : '') + '...');
1420
+ const r = await _client.syncAppState(names.length ? names : null, { snapshot });
1421
+ if (r.waitingForKeys) {
1422
+ out(' no app state key for this session.');
1423
+ out(' On a linked (pairing-code) session the key comes from your phone —');
1424
+ out(' open WhatsApp there and leave it connected for a moment.');
1425
+ out(' On an SMS session this device IS the primary, so there is no app');
1426
+ out(' state to read unless you have linked a companion to it.');
1427
+ break;
1428
+ }
1429
+ hr();
1430
+ for (const [name, info] of Object.entries(r.collections)) {
1431
+ if (info.waitingForKey) { kv(name, 'waiting for key ' + info.waitingForKey); continue; }
1432
+ kv(name, 'v' + info.version + ' ' + info.applied + ' change(s)' +
1433
+ (info.snapshot ? ' (full re-read)' : '') +
1434
+ (info.skipped ? ' ' + info.skipped + ' unreadable' : '') +
1435
+ (info.macOk === false ? ' — partial' : ''));
1436
+ }
1437
+ kv('total', r.applied + ' change(s) applied');
1438
+ hr();
1439
+ break;
1440
+ }
1441
+
1328
1442
  case '/unread':
1329
1443
  requireConn();
1330
1444
  if (!p[1]) { fail('usage: /unread <jid>'); break; }
1331
- _client.markChatUnread(normalizeJid(p[1]));
1332
- out('marked unread');
1445
+ out(chatResult('marked unread', await _client.markChatUnread(normalizeJid(p[1]))));
1333
1446
  break;
1334
1447
 
1335
1448
  case '/mute': {
@@ -1337,61 +1450,53 @@ async function handleLine(line) {
1337
1450
  const jid = normalizeJid(p[1]);
1338
1451
  if (!jid) { fail('usage: /mute <jid> [minutes]'); break; }
1339
1452
  const ms = p[2] ? parseInt(p[2], 10) * 60000 : 0;
1340
- await _client.muteChat(jid, ms);
1341
- out('muted ' + jid);
1453
+ out(chatResult('muted ' + jid, await _client.muteChat(jid, ms)));
1342
1454
  break;
1343
1455
  }
1344
1456
 
1345
1457
  case '/unmute':
1346
1458
  requireConn();
1347
1459
  if (!p[1]) { fail('usage: /unmute <jid>'); break; }
1348
- await _client.unmuteChat(normalizeJid(p[1]));
1349
- out('unmuted');
1460
+ out(chatResult('unmuted', await _client.unmuteChat(normalizeJid(p[1]))));
1350
1461
  break;
1351
1462
 
1352
1463
  case '/pin':
1353
1464
  requireConn();
1354
1465
  if (!p[1]) { fail('usage: /pin <jid>'); break; }
1355
- _client.pinChat(normalizeJid(p[1]));
1356
- out('pinned');
1466
+ out(chatResult('pinned', await _client.pinChat(normalizeJid(p[1]))));
1357
1467
  break;
1358
1468
 
1359
1469
  case '/unpin':
1360
1470
  requireConn();
1361
1471
  if (!p[1]) { fail('usage: /unpin <jid>'); break; }
1362
- _client.unpinChat(normalizeJid(p[1]));
1363
- out('unpinned');
1472
+ out(chatResult('unpinned', await _client.unpinChat(normalizeJid(p[1]))));
1364
1473
  break;
1365
1474
 
1366
1475
  case '/archive':
1367
1476
  requireConn();
1368
1477
  if (!p[1]) { fail('usage: /archive <jid>'); break; }
1369
- _client.archiveChat(normalizeJid(p[1]));
1370
- out('archived');
1478
+ out(chatResult('archived', await _client.archiveChat(normalizeJid(p[1]))));
1371
1479
  break;
1372
1480
 
1373
1481
  case '/unarchive':
1374
1482
  requireConn();
1375
1483
  if (!p[1]) { fail('usage: /unarchive <jid>'); break; }
1376
- _client.unarchiveChat(normalizeJid(p[1]));
1377
- out('unarchived');
1484
+ out(chatResult('unarchived', await _client.unarchiveChat(normalizeJid(p[1]))));
1378
1485
  break;
1379
1486
 
1380
1487
  case '/star': {
1381
1488
  requireConn();
1382
- const [, jR, msgId] = p;
1383
- if (!jR || !msgId) { fail('usage: /star <jid> <msgId>'); break; }
1384
- _client.starMessage(msgId, normalizeJid(jR));
1385
- out('starred');
1489
+ const [, jR, msgId, mine] = p;
1490
+ if (!jR || !msgId) { fail('usage: /star <jid> <msgId> [me]'); break; }
1491
+ out(chatResult('starred', await _client.starMessage(msgId, normalizeJid(jR), mine === 'me')));
1386
1492
  break;
1387
1493
  }
1388
1494
 
1389
1495
  case '/unstar': {
1390
1496
  requireConn();
1391
- const [, jR, msgId] = p;
1392
- if (!jR || !msgId) { fail('usage: /unstar <jid> <msgId>'); break; }
1393
- _client.unstarMessage(msgId, normalizeJid(jR));
1394
- out('unstarred');
1497
+ const [, jR, msgId, mine] = p;
1498
+ if (!jR || !msgId) { fail('usage: /unstar <jid> <msgId> [me]'); break; }
1499
+ out(chatResult('unstarred', await _client.unstarMessage(msgId, normalizeJid(jR), mine === 'me')));
1395
1500
  break;
1396
1501
  }
1397
1502
 
@@ -1476,29 +1581,25 @@ async function handleLine(line) {
1476
1581
  const gj = asGroupJid(p[2]);
1477
1582
  const jids = p.slice(3).map(normalizeJid);
1478
1583
  if (!gj || !jids.length) { fail('usage: /group add <jid> <member...>'); break; }
1479
- await _client.addGroupParticipants(gj, jids);
1480
- out('added ' + jids.join(', '));
1584
+ printParticipantResults('added', await _client.addGroupParticipants(gj, jids));
1481
1585
  }
1482
1586
  else if (sub === 'remove') {
1483
1587
  const gj = asGroupJid(p[2]);
1484
1588
  const jids = p.slice(3).map(normalizeJid);
1485
1589
  if (!gj || !jids.length) { fail('usage: /group remove <jid> <member...>'); break; }
1486
- await _client.removeGroupParticipants(gj, jids);
1487
- out('removed ' + jids.join(', '));
1590
+ printParticipantResults('removed', await _client.removeGroupParticipants(gj, jids));
1488
1591
  }
1489
1592
  else if (sub === 'promote') {
1490
1593
  const gj = asGroupJid(p[2]);
1491
1594
  const jids = p.slice(3).map(normalizeJid);
1492
1595
  if (!gj || !jids.length) { fail('usage: /group promote <jid> <member...>'); break; }
1493
- await _client.promoteGroupParticipants(gj, jids);
1494
- out('promoted');
1596
+ printParticipantResults('promoted', await _client.promoteGroupParticipants(gj, jids));
1495
1597
  }
1496
1598
  else if (sub === 'demote') {
1497
1599
  const gj = asGroupJid(p[2]);
1498
1600
  const jids = p.slice(3).map(normalizeJid);
1499
1601
  if (!gj || !jids.length) { fail('usage: /group demote <jid> <member...>'); break; }
1500
- await _client.demoteGroupParticipants(gj, jids);
1501
- out('demoted');
1602
+ printParticipantResults('demoted', await _client.demoteGroupParticipants(gj, jids));
1502
1603
  }
1503
1604
  else if (sub === 'subject') {
1504
1605
  const gj = asGroupJid(p[2]);
@@ -1546,10 +1647,7 @@ async function handleLine(line) {
1546
1647
  kv('created', r.creation ? new Date(r.creation * 1000).toISOString() : '—');
1547
1648
  kv('description', r.description || '—');
1548
1649
  kv('participants', '(' + r.participants.length + ')');
1549
- for (const pt of r.participants) {
1550
- const role = pt.role !== 'member' ? ' [' + pt.role + ']' : '';
1551
- out(' ' + pt.jid + role);
1552
- }
1650
+ for (const pt of r.participants) out(' ' + participantLine(pt));
1553
1651
  hr();
1554
1652
  }
1555
1653
  else if (sub === 'meta') {
@@ -1566,11 +1664,18 @@ async function handleLine(line) {
1566
1664
  kv('ephemeral', r.ephemeral ? r.ephemeral + 's' : 'off');
1567
1665
  kv('only admins send', r.onlyAdminsSend ? 'yes' : 'no');
1568
1666
  kv('only admins edit', r.onlyAdminsEdit ? 'yes' : 'no');
1667
+ kv('join approval', r.joinApprovalMode ? 'required' : 'not required');
1668
+ kv('who can add', r.memberAddMode === 'admin_add' ? 'admins only'
1669
+ : r.memberAddMode === 'all_member_add' ? 'any member' : '—');
1670
+ if (r.isCommunity) kv('community', 'yes');
1671
+ if (r.linkedParent) kv('part of', r.linkedParent);
1672
+ // A suspended group answers every send with a refusal and nothing
1673
+ // else, so it has to be said out loud rather than left to be guessed.
1674
+ if (r.isSuspended) kv('suspended', 'yes — this group has been taken down');
1675
+ if (r.isIncognito) kv('incognito', 'yes — phone numbers are hidden');
1676
+ kv('size', String(r.size));
1569
1677
  kv('participants', '(' + r.participants.length + ')');
1570
- for (const p of r.participants) {
1571
- const role = p.role !== 'member' ? ' [' + p.role + ']' : '';
1572
- out(' ' + p.jid + role);
1573
- }
1678
+ for (const p of r.participants) out(' ' + participantLine(p));
1574
1679
  hr();
1575
1680
  }
1576
1681
  else if (sub === 'participants') {
@@ -1579,10 +1684,7 @@ async function handleLine(line) {
1579
1684
  const r = await _client.getGroupMetadata(gj);
1580
1685
  if (!r) { out(' no data'); break; }
1581
1686
  out(' ' + r.subject + ' (' + r.participants.length + ' participants)');
1582
- for (const pt of r.participants) {
1583
- const role = pt.role !== 'member' ? ' [' + pt.role + ']' : '';
1584
- out(' ' + pt.jid + role);
1585
- }
1687
+ for (const pt of r.participants) out(' ' + participantLine(pt));
1586
1688
  }
1587
1689
  else if (sub === 'photo') {
1588
1690
  const gj = asGroupJid(p[2]);
@@ -1590,8 +1692,8 @@ async function handleLine(line) {
1590
1692
  if (!gj || !file) { fail('usage: /group photo <jid> <file>'); break; }
1591
1693
  if (!fs.existsSync(file)) { fail('file not found: ' + file); break; }
1592
1694
  const buf = fs.readFileSync(file);
1593
- await _client.changeGroupPicture(gj, buf);
1594
- out('group picture updated');
1695
+ const picId = await _client.changeGroupPicture(gj, buf);
1696
+ out('group picture updated' + (picId ? ' id=' + picId : ''));
1595
1697
  }
1596
1698
  else if (sub === 'pending') {
1597
1699
  const gj = asGroupJid(p[2]);
@@ -1599,21 +1701,75 @@ async function handleLine(line) {
1599
1701
  const list = await _client.queryGroupPendingParticipants(gj);
1600
1702
  if (!list || !list.length) { out(' no pending requests'); break; }
1601
1703
  out(' pending (' + list.length + ')');
1602
- list.forEach(j => out(' ' + j));
1704
+ list.forEach(r => out(' ' + r.jid +
1705
+ (r.requestedAt ? ' ' + new Date(r.requestedAt * 1000).toISOString() : '')));
1603
1706
  }
1604
1707
  else if (sub === 'approve') {
1605
1708
  const gj = asGroupJid(p[2]);
1606
1709
  const jids = p.slice(3).map(normalizeJid);
1607
1710
  if (!gj || !jids.length) { fail('usage: /group approve <jid> <member...>'); break; }
1608
- const ok = await _client.approveGroupParticipants(gj, true, jids);
1609
- out('approved ' + (ok.length ? ok.join(', ') : jids.join(', ')));
1711
+ printParticipantResults('approved',
1712
+ await _client.approveGroupParticipants(gj, true, jids));
1610
1713
  }
1611
1714
  else if (sub === 'reject') {
1612
1715
  const gj = asGroupJid(p[2]);
1613
1716
  const jids = p.slice(3).map(normalizeJid);
1614
1717
  if (!gj || !jids.length) { fail('usage: /group reject <jid> <member...>'); break; }
1615
- const ok = await _client.approveGroupParticipants(gj, false, jids);
1616
- out('rejected ' + (ok.length ? ok.join(', ') : jids.join(', ')));
1718
+ printParticipantResults('rejected',
1719
+ await _client.approveGroupParticipants(gj, false, jids));
1720
+ }
1721
+ else if (sub === 'add-invite') {
1722
+ const gj = asGroupJid(p[2]);
1723
+ const jids = p.slice(3).map(normalizeJid);
1724
+ if (!gj || !jids.length) { fail('usage: /group add-invite <jid> <member...>'); break; }
1725
+ printParticipantResults('added', await _client.addGroupParticipantsOrInvite(gj, jids));
1726
+ }
1727
+ else if (sub === 'send-invite') {
1728
+ const gj = asGroupJid(p[2]);
1729
+ const member = normalizeJid(p[3]);
1730
+ const code = p[4];
1731
+ const exp = parseInt(p[5], 10) || 0;
1732
+ if (!gj || !member || !code) {
1733
+ fail('usage: /group send-invite <jid> <member> <code> <expiration>');
1734
+ break;
1735
+ }
1736
+ const r = await _client.sendGroupInvite(member, gj, code, exp);
1737
+ out('invitation sent to ' + member + ' id=' + (r && r.id));
1738
+ }
1739
+ else if (sub === 'accept-invite') {
1740
+ const gj = asGroupJid(p[2]);
1741
+ const inviter = normalizeJid(p[3]);
1742
+ const code = p[4];
1743
+ const exp = parseInt(p[5], 10) || 0;
1744
+ if (!gj || !inviter || !code) {
1745
+ fail('usage: /group accept-invite <jid> <inviter> <code> [expiration]');
1746
+ break;
1747
+ }
1748
+ out('joined ' + await _client.acceptGroupInviteMessage(gj, inviter, code, exp));
1749
+ }
1750
+ else if (sub === 'preview-invite') {
1751
+ const gj = asGroupJid(p[2]);
1752
+ const inviter = normalizeJid(p[3]);
1753
+ const code = p[4];
1754
+ const exp = parseInt(p[5], 10) || 0;
1755
+ if (!gj || !inviter || !code) {
1756
+ fail('usage: /group preview-invite <jid> <inviter> <code> [expiration]');
1757
+ break;
1758
+ }
1759
+ const r = await _client.queryGroupInviteMessageInfo(gj, inviter, code, exp);
1760
+ hr();
1761
+ kv('jid', r.jid);
1762
+ kv('subject', r.subject);
1763
+ kv('participants', String(r.size));
1764
+ kv('description', r.description || '—');
1765
+ hr();
1766
+ }
1767
+ else if (sub === 'revoke-invite') {
1768
+ const gj = asGroupJid(p[2]);
1769
+ const member = normalizeJid(p[3]);
1770
+ if (!gj || !member) { fail('usage: /group revoke-invite <jid> <member>'); break; }
1771
+ await _client.revokeGroupInviteForParticipant(gj, member);
1772
+ out('invitation to ' + member + ' withdrawn');
1617
1773
  }
1618
1774
  else if (sub === 'settings') {
1619
1775
  const gj = asGroupJid(p[2]);
@@ -1651,10 +1807,7 @@ async function handleLine(line) {
1651
1807
  kv('admins only send', g.onlyAdminsSend ? 'yes' : 'no');
1652
1808
  kv('admins only edit', g.onlyAdminsEdit ? 'yes' : 'no');
1653
1809
  kv('participants', '(' + g.participants.length + ')');
1654
- for (const pt of g.participants) {
1655
- const role = pt.role !== 'member' ? ' [' + pt.role + ']' : '';
1656
- out(' ' + pt.jid + role);
1657
- }
1810
+ for (const pt of g.participants) out(' ' + participantLine(pt));
1658
1811
  }
1659
1812
  hr();
1660
1813
  break;
@@ -2210,6 +2363,11 @@ async function main() {
2210
2363
  case 'reaction': kv('type', 'reaction emoji: ' + d.emoji); break;
2211
2364
  case 'location': kv('type', 'location lat: ' + d.latitude + ' lon: ' + d.longitude + (d.name ? ' name: ' + d.name : '')); break;
2212
2365
  case 'contact': kv('type', 'contact name: ' + d.displayName); break;
2366
+ case 'groupInvite':
2367
+ kv('type', 'group invitation ' + (d.groupName || d.groupJid));
2368
+ kv('accept with', '/group accept-invite ' + d.groupJid + ' ' +
2369
+ (msg.participant || msg.from) + ' ' + d.inviteCode + ' ' + d.inviteExpiration);
2370
+ break;
2213
2371
  default: kv('type', d.type);
2214
2372
  }
2215
2373
  }
package/index.js CHANGED
@@ -11,6 +11,10 @@ const { SenderKeyStore, SenderKeyCrypto } = require('./lib/signal/SenderKey');
11
11
  const { DeviceManager } = require('./lib/DeviceManager');
12
12
  const { encryptMedia, decryptMedia, uploadMedia, downloadMedia } = require('./lib/MediaService');
13
13
  const { MessageSender, makeJid, generateMessageId } = require('./lib/messages/MessageSender');
14
+ const { GroupParticipantResult, GroupJoinRequest } = require('./lib/GroupParticipant');
15
+ const { AppStateStore, COLLECTIONS: APP_STATE_COLLECTIONS } = require('./lib/appstate/AppStateStore');
16
+ const AppStateSync = require('./lib/appstate/AppStateSync');
17
+ const { PATCH_INTEGRITY: LT_HASH } = require('./lib/appstate/LTHash');
14
18
  const {
15
19
  makeCacheableSignalKeyStore,
16
20
  addTransactionCapability,
@@ -98,7 +102,15 @@ module.exports = {
98
102
  MessageSender,
99
103
  makeJid,
100
104
  generateMessageId,
101
- // Auth utilities (mirrors Baileys' auth-utils)
105
+ // Group results
106
+ GroupParticipantResult,
107
+ GroupJoinRequest,
108
+ // App state
109
+ AppStateStore,
110
+ AppStateSync,
111
+ APP_STATE_COLLECTIONS,
112
+ LT_HASH,
113
+ // Auth utilities
102
114
  makeCacheableSignalKeyStore,
103
115
  addTransactionCapability,
104
116
  assertMeId,