@pontalabs/baileys 1.0.6 → 1.0.7

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 (185) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +839 -267
  3. package/WAProto/GenerateStatics.sh +4 -3
  4. package/WAProto/WAProto.proto +511 -1215
  5. package/WAProto/index.d.ts +55 -14017
  6. package/WAProto/index.js +29 -97689
  7. package/lib/Defaults/index.d.ts +74 -72
  8. package/lib/Defaults/index.js +108 -94
  9. package/lib/Signal/Group/ciphertext-message.d.ts +7 -8
  10. package/lib/Signal/Group/ciphertext-message.js +16 -9
  11. package/lib/Signal/Group/group-session-builder.d.ts +13 -11
  12. package/lib/Signal/Group/group-session-builder.js +61 -19
  13. package/lib/Signal/Group/group_cipher.d.ts +16 -14
  14. package/lib/Signal/Group/group_cipher.js +70 -41
  15. package/lib/Signal/Group/index.d.ts +11 -12
  16. package/lib/Signal/Group/index.js +61 -12
  17. package/lib/Signal/Group/keyhelper.d.ts +14 -9
  18. package/lib/Signal/Group/keyhelper.js +58 -10
  19. package/lib/Signal/Group/sender-chain-key.d.ts +13 -13
  20. package/lib/Signal/Group/sender-chain-key.js +34 -13
  21. package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -16
  22. package/lib/Signal/Group/sender-key-distribution-message.js +36 -28
  23. package/lib/Signal/Group/sender-key-message.d.ts +18 -18
  24. package/lib/Signal/Group/sender-key-message.js +45 -38
  25. package/lib/Signal/Group/sender-key-name.d.ts +15 -14
  26. package/lib/Signal/Group/sender-key-name.js +31 -20
  27. package/lib/Signal/Group/sender-key-record.d.ts +25 -24
  28. package/lib/Signal/Group/sender-key-record.js +35 -18
  29. package/lib/Signal/Group/sender-key-state.d.ts +34 -29
  30. package/lib/Signal/Group/sender-key-state.js +100 -37
  31. package/lib/Signal/Group/sender-message-key.d.ts +10 -11
  32. package/lib/Signal/Group/sender-message-key.js +22 -15
  33. package/lib/Signal/libsignal.d.ts +8 -5
  34. package/lib/Signal/libsignal.js +142 -288
  35. package/lib/Signal/lid-mapping.d.ts +28 -23
  36. package/lib/Signal/lid-mapping.js +184 -277
  37. package/lib/Socket/Client/index.d.ts +2 -3
  38. package/lib/Socket/Client/index.js +22 -3
  39. package/lib/Socket/Client/types.d.ts +15 -15
  40. package/lib/Socket/Client/types.js +15 -8
  41. package/lib/Socket/Client/websocket.d.ts +12 -12
  42. package/lib/Socket/Client/websocket.js +37 -29
  43. package/lib/Socket/business.d.ts +178 -208
  44. package/lib/Socket/business.js +127 -91
  45. package/lib/Socket/chats.d.ts +93 -120
  46. package/lib/Socket/chats.js +652 -727
  47. package/lib/Socket/community.js +10 -2
  48. package/lib/Socket/groups.d.ts +111 -143
  49. package/lib/Socket/groups.js +186 -165
  50. package/lib/Socket/index.d.ts +183 -252
  51. package/lib/Socket/index.js +18 -38
  52. package/lib/Socket/messages-recv.d.ts +167 -196
  53. package/lib/Socket/messages-recv.js +1567 -1443
  54. package/lib/Socket/messages-send.d.ts +158 -192
  55. package/lib/Socket/messages-send.js +1208 -1102
  56. package/lib/Socket/newsletter.d.ts +138 -163
  57. package/lib/Socket/newsletter.js +249 -153
  58. package/lib/Socket/socket.d.ts +36 -50
  59. package/lib/Socket/socket.js +820 -749
  60. package/lib/Store/index.d.ts +4 -4
  61. package/lib/Store/index.js +24 -4
  62. package/lib/Store/make-in-memory-store.d.ts +104 -44
  63. package/lib/Store/make-in-memory-store.js +213 -199
  64. package/lib/Store/make-ordered-dictionary.d.ts +12 -13
  65. package/lib/Store/make-ordered-dictionary.js +45 -38
  66. package/lib/Store/object-repository.d.ts +10 -11
  67. package/lib/Store/object-repository.js +16 -9
  68. package/lib/Types/Auth.d.ts +97 -93
  69. package/lib/Types/Auth.js +3 -2
  70. package/lib/Types/Bussines.js +3 -2
  71. package/lib/Types/Call.d.ts +13 -14
  72. package/lib/Types/Call.js +3 -2
  73. package/lib/Types/Chat.d.ts +97 -78
  74. package/lib/Types/Chat.js +9 -8
  75. package/lib/Types/Contact.d.ts +9 -12
  76. package/lib/Types/Contact.js +3 -2
  77. package/lib/Types/Events.d.ts +176 -206
  78. package/lib/Types/Events.js +3 -2
  79. package/lib/Types/GroupMetadata.d.ts +48 -53
  80. package/lib/Types/GroupMetadata.js +3 -2
  81. package/lib/Types/Label.d.ts +14 -13
  82. package/lib/Types/Label.js +30 -24
  83. package/lib/Types/LabelAssociation.d.ts +20 -15
  84. package/lib/Types/LabelAssociation.js +12 -6
  85. package/lib/Types/Message.d.ts +412 -248
  86. package/lib/Types/Message.js +19 -17
  87. package/lib/Types/Product.d.ts +71 -58
  88. package/lib/Types/Product.js +3 -2
  89. package/lib/Types/Signal.d.ts +82 -71
  90. package/lib/Types/Signal.js +3 -2
  91. package/lib/Types/Socket.d.ts +81 -76
  92. package/lib/Types/Socket.js +3 -3
  93. package/lib/Types/State.d.ts +19 -75
  94. package/lib/Types/State.js +14 -56
  95. package/lib/Types/USync.d.ts +8 -8
  96. package/lib/Types/USync.js +3 -2
  97. package/lib/Types/index.d.ts +62 -47
  98. package/lib/Types/index.js +50 -26
  99. package/lib/Utils/auth-utils.d.ts +10 -13
  100. package/lib/Utils/auth-utils.js +472 -213
  101. package/lib/Utils/business.d.ts +20 -14
  102. package/lib/Utils/business.js +134 -110
  103. package/lib/Utils/chat-utils.d.ts +70 -88
  104. package/lib/Utils/chat-utils.js +403 -466
  105. package/lib/Utils/crypto.d.ts +46 -27
  106. package/lib/Utils/crypto.js +188 -117
  107. package/lib/Utils/decode-wa-message.d.ts +45 -58
  108. package/lib/Utils/decode-wa-message.js +311 -212
  109. package/lib/Utils/event-buffer.d.ts +17 -14
  110. package/lib/Utils/event-buffer.js +296 -321
  111. package/lib/Utils/generics.d.ts +92 -66
  112. package/lib/Utils/generics.js +436 -270
  113. package/lib/Utils/history.d.ts +23 -24
  114. package/lib/Utils/history.js +76 -106
  115. package/lib/Utils/index.d.ts +21 -24
  116. package/lib/Utils/index.js +41 -24
  117. package/lib/Utils/link-preview.d.ts +14 -12
  118. package/lib/Utils/link-preview.js +75 -40
  119. package/lib/Utils/logger.d.ts +11 -10
  120. package/lib/Utils/logger.js +7 -3
  121. package/lib/Utils/lt-hash.d.ts +14 -8
  122. package/lib/Utils/lt-hash.js +53 -3
  123. package/lib/Utils/make-mutex.d.ts +7 -7
  124. package/lib/Utils/make-mutex.js +44 -28
  125. package/lib/Utils/message-retry-manager.d.ts +88 -115
  126. package/lib/Utils/message-retry-manager.js +160 -265
  127. package/lib/Utils/messages-media.d.ts +107 -105
  128. package/lib/Utils/messages-media.js +619 -548
  129. package/lib/Utils/messages.d.ts +66 -52
  130. package/lib/Utils/messages.js +1558 -1730
  131. package/lib/Utils/noise-handler.d.ts +18 -18
  132. package/lib/Utils/noise-handler.js +130 -176
  133. package/lib/Utils/process-message.d.ts +32 -43
  134. package/lib/Utils/process-message.js +282 -484
  135. package/lib/Utils/rich-message-utils.js +724 -1220
  136. package/lib/Utils/signal.d.ts +32 -37
  137. package/lib/Utils/signal.js +105 -140
  138. package/lib/Utils/use-multi-file-auth-state.d.ts +5 -5
  139. package/lib/Utils/use-multi-file-auth-state.js +120 -70
  140. package/lib/Utils/use-single-file-auth-state.d.ts +13 -11
  141. package/lib/Utils/use-single-file-auth-state.js +66 -92
  142. package/lib/Utils/validate-connection.d.ts +13 -11
  143. package/lib/Utils/validate-connection.js +113 -128
  144. package/lib/WABinary/constants.d.ts +27 -25
  145. package/lib/WABinary/constants.js +1292 -1451
  146. package/lib/WABinary/decode.d.ts +9 -7
  147. package/lib/WABinary/decode.js +189 -163
  148. package/lib/WABinary/encode.d.ts +3 -3
  149. package/lib/WABinary/encode.js +155 -110
  150. package/lib/WABinary/generic-utils.d.ts +27 -14
  151. package/lib/WABinary/generic-utils.js +105 -177
  152. package/lib/WABinary/index.d.ts +5 -6
  153. package/lib/WABinary/index.js +25 -6
  154. package/lib/WABinary/jid-utils.d.ts +54 -41
  155. package/lib/WABinary/jid-utils.js +152 -83
  156. package/lib/WABinary/types.d.ts +13 -10
  157. package/lib/WABinary/types.js +3 -2
  158. package/lib/WAM/BinaryInfo.d.ts +15 -8
  159. package/lib/WAM/BinaryInfo.js +14 -7
  160. package/lib/WAM/constants.d.ts +37 -30
  161. package/lib/WAM/constants.js +11983 -19465
  162. package/lib/WAM/encode.d.ts +3 -3
  163. package/lib/WAM/encode.js +109 -95
  164. package/lib/WAM/index.d.ts +3 -4
  165. package/lib/WAM/index.js +23 -4
  166. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +9 -9
  167. package/lib/WAUSync/Protocols/USyncContactProtocol.js +21 -37
  168. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -19
  169. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +26 -18
  170. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -11
  171. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +20 -12
  172. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -11
  173. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +24 -16
  174. package/lib/WAUSync/Protocols/index.d.ts +6 -6
  175. package/lib/WAUSync/Protocols/index.js +26 -6
  176. package/lib/WAUSync/USyncQuery.d.ts +28 -27
  177. package/lib/WAUSync/USyncQuery.js +62 -68
  178. package/lib/WAUSync/USyncUser.d.ts +10 -15
  179. package/lib/WAUSync/USyncUser.js +19 -20
  180. package/lib/WAUSync/index.d.ts +3 -4
  181. package/lib/WAUSync/index.js +23 -4
  182. package/lib/index.d.ts +12 -11
  183. package/lib/index.js +39 -12
  184. package/package.json +42 -86
  185. package/engine-requirements.js +0 -10
@@ -1,26 +1,33 @@
1
- import { deriveSecrets } from 'libsignal/src/crypto.js';
2
- export class SenderMessageKey {
1
+ "use strict"
2
+ Object.defineProperty(exports, "__esModule", { value: true })
3
+
4
+ const crypto_1 = require("libsignal/src/crypto")
5
+
6
+ class SenderMessageKey {
3
7
  constructor(iteration, seed) {
4
- const derivative = deriveSecrets(seed, Buffer.alloc(32), Buffer.from('WhisperGroup'));
5
- const keys = new Uint8Array(32);
6
- keys.set(new Uint8Array(derivative[0].slice(16)));
7
- keys.set(new Uint8Array(derivative[1].slice(0, 16)), 16);
8
- this.iv = Buffer.from(derivative[0].slice(0, 16));
9
- this.cipherKey = Buffer.from(keys.buffer);
10
- this.iteration = iteration;
11
- this.seed = seed;
8
+ const derivative = (0, crypto_1.deriveSecrets)(seed, Buffer.alloc(32), Buffer.from('WhisperGroup'))
9
+ const keys = new Uint8Array(32)
10
+ keys.set(new Uint8Array(derivative[0].slice(16)))
11
+ keys.set(new Uint8Array(derivative[1].slice(0, 16)), 16)
12
+ this.iv = Buffer.from(derivative[0].slice(0, 16))
13
+ this.cipherKey = Buffer.from(keys.buffer)
14
+ this.iteration = iteration
15
+ this.seed = seed
12
16
  }
13
17
  getIteration() {
14
- return this.iteration;
18
+ return this.iteration
15
19
  }
16
20
  getIv() {
17
- return this.iv;
21
+ return this.iv
18
22
  }
19
23
  getCipherKey() {
20
- return this.cipherKey;
24
+ return this.cipherKey
21
25
  }
22
26
  getSeed() {
23
- return this.seed;
27
+ return this.seed
24
28
  }
25
29
  }
26
- //# sourceMappingURL=sender-message-key.js.map
30
+
31
+ module.exports = {
32
+ SenderMessageKey
33
+ }
@@ -1,5 +1,8 @@
1
- import type { LIDMapping, SignalAuthState } from '../Types/index.js';
2
- import type { SignalRepositoryWithLIDStore } from '../Types/Signal.js';
3
- import type { ILogger } from '../Utils/logger.js';
4
- export declare function makeLibSignalRepository(auth: SignalAuthState, logger: ILogger, pnToLIDFunc?: (jids: string[]) => Promise<LIDMapping[] | undefined>): SignalRepositoryWithLIDStore;
5
- //# sourceMappingURL=libsignal.d.ts.map
1
+ import { SignalAuthState } from '../Types'
2
+ import { SignalRepository } from '../Types/Signal'
3
+
4
+ export declare function makeLibSignalRepository(auth: SignalAuthState, onWhatsAppFunc?: (...jids: string[]) => Promise<{
5
+ jid: string
6
+ exists: boolean
7
+ lid: string
8
+ }[] | undefined>): SignalRepository
@@ -1,80 +1,101 @@
1
- // @ts-ignore
2
- import * as libsignal from 'libsignal';
3
- // @ts-ignore
4
- import { PreKeyWhisperMessage } from 'libsignal/src/protobufs.js';
5
- import { LRUCache } from 'lru-cache';
6
- import { generateSignalPubKey } from '../Utils/index.js';
7
- import { isHostedLidUser, isHostedPnUser, isLidUser, isPnUser, jidDecode, transferDevice, WAJIDDomains } from '../WABinary/index.js';
8
- import { SenderKeyName } from './Group/sender-key-name.js';
9
- import { SenderKeyRecord } from './Group/sender-key-record.js';
10
- import { GroupCipher, GroupSessionBuilder, SenderKeyDistributionMessage } from './Group/index.js';
11
- import { LIDMappingStore } from './lid-mapping.js';
12
- /** Extract identity key from PreKeyWhisperMessage for identity change detection */
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
+ exports.makeLibSignalRepository = makeLibSignalRepository;
37
+ const libsignal = __importStar(require("libsignal"));
38
+ const { PreKeyWhisperMessage } = require("libsignal/src/protobufs");
39
+ const Utils_1 = require("../Utils");
40
+ const WABinary_1 = require("../WABinary");
41
+ const sender_key_name_1 = require("./Group/sender-key-name");
42
+ const sender_key_record_1 = require("./Group/sender-key-record");
43
+ const Group_1 = require("./Group");
44
+ const LIDMappingStore_1 = require("./lid-mapping")
45
+
46
+ // FIX: sebelumnya pontalabs gak punya deteksi perubahan identity key sama
47
+ // sekali. Kalau identity kontak berubah (kontak install ulang WA, atau kena
48
+ // resync multi-device pas ada linked device lain online), sesi lama tetap
49
+ // dipakai terus dan selalu gagal decrypt "Bad MAC" berulang-ulang sampai
50
+ // akhirnya kena threshold retry enableAutoSessionRecreation. Dengan deteksi
51
+ // ini, begitu identity berubah, sesi langsung direset SAAT ITU JUGA - gak
52
+ // perlu nunggu beberapa pesan gagal dulu.
13
53
  function extractIdentityFromPkmsg(ciphertext) {
14
54
  try {
15
55
  if (!ciphertext || ciphertext.length < 2) {
16
56
  return undefined;
17
57
  }
18
- // Version byte check (version 3)
19
58
  const version = ciphertext[0];
20
59
  if ((version & 0xf) !== 3) {
21
60
  return undefined;
22
61
  }
23
- // Parse protobuf (skip version byte)
24
62
  const preKeyProto = PreKeyWhisperMessage.decode(ciphertext.slice(1));
25
- if (preKeyProto.identityKey?.length === 33) {
26
- return new Uint8Array(preKeyProto.identityKey);
63
+ if (preKeyProto.identityKey && preKeyProto.identityKey.length === 33) {
64
+ return Buffer.from(preKeyProto.identityKey);
27
65
  }
28
66
  return undefined;
29
- }
30
- catch {
67
+ } catch {
31
68
  return undefined;
32
69
  }
33
70
  }
34
- export function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
35
- const lidMapping = new LIDMappingStore(auth.keys, logger, pnToLIDFunc);
36
- const storage = signalStorage(auth, lidMapping);
37
- const parsedKeys = auth.keys;
38
- const migratedSessionCache = new LRUCache({
39
- ttl: 3 * 24 * 60 * 60 * 1000, // 7 days
40
- ttlAutopurge: true,
41
- updateAgeOnGet: true
42
- });
43
- const ensureSenderKeyAndCreateSkdm = async (group, meId) => {
44
- const senderName = jidToSignalSenderKeyName(group, meId);
45
- const senderNameStr = senderName.toString();
46
- const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr]);
47
- if (!senderKey) {
48
- await storage.storeSenderKey(senderName, new SenderKeyRecord());
49
- }
50
- const skdm = await new GroupSessionBuilder(storage).create(senderName);
51
- return { senderName, skdm };
52
- };
53
- const repository = {
71
+
72
+ function makeLibSignalRepository(auth, onWhatsAppFunc, logger) {
73
+ const lidMapping = new LIDMappingStore_1.LIDMappingStore(auth.keys, onWhatsAppFunc, logger)
74
+ const storage = signalStorage(auth);
75
+ return {
76
+ lidMapping,
54
77
  decryptGroupMessage({ group, authorJid, msg }) {
55
78
  const senderName = jidToSignalSenderKeyName(group, authorJid);
56
- const cipher = new GroupCipher(storage, senderName);
57
- // Use transaction to ensure atomicity
58
- return parsedKeys.transaction(async () => {
79
+ const cipher = new Group_1.GroupCipher(storage, senderName);
80
+ // Dibungkus transaction() biar atomic - konsisten sama operasi Signal
81
+ // lainnya, cegah race condition kalau ada beberapa pesan grup dari
82
+ // sender yang sama numpuk barengan.
83
+ return auth.keys.transaction(async () => {
59
84
  return cipher.decrypt(msg);
60
85
  }, group);
61
86
  },
62
87
  async processSenderKeyDistributionMessage({ item, authorJid }) {
63
- const builder = new GroupSessionBuilder(storage);
88
+ const builder = new Group_1.GroupSessionBuilder(storage);
64
89
  if (!item.groupId) {
65
90
  throw new Error('Group ID is required for sender key distribution message');
66
91
  }
67
92
  const senderName = jidToSignalSenderKeyName(item.groupId, authorJid);
68
- const senderMsg = new SenderKeyDistributionMessage(null, null, null, null, item.axolotlSenderKeyDistributionMessage);
93
+ const senderMsg = new Group_1.SenderKeyDistributionMessage(null, null, null, null, item.axolotlSenderKeyDistributionMessage);
69
94
  const senderNameStr = senderName.toString();
70
- const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr]);
71
- if (!senderKey) {
72
- await storage.storeSenderKey(senderName, new SenderKeyRecord());
73
- }
74
- return parsedKeys.transaction(async () => {
95
+ return auth.keys.transaction(async () => {
75
96
  const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr]);
76
97
  if (!senderKey) {
77
- await storage.storeSenderKey(senderName, new SenderKeyRecord());
98
+ await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord());
78
99
  }
79
100
  await builder.process(senderName, senderMsg);
80
101
  }, item.groupId);
@@ -82,91 +103,80 @@ export function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
82
103
  async decryptMessage({ jid, type, ciphertext }) {
83
104
  const addr = jidToSignalProtocolAddress(jid);
84
105
  const session = new libsignal.SessionCipher(storage, addr);
85
- // Extract and save sender's identity key before decryption for identity change detection
106
+ // Sebelum decrypt pkmsg (pesan yang buka sesi baru), cek dulu apakah
107
+ // identity key pengirim berubah dibanding yang tersimpan. Kalau iya,
108
+ // sesi lama otomatis direset supaya gak nyoba decrypt pakai sesi basi.
86
109
  if (type === 'pkmsg') {
87
110
  const identityKey = extractIdentityFromPkmsg(ciphertext);
88
111
  if (identityKey) {
89
112
  const addrStr = addr.toString();
90
113
  const identityChanged = await storage.saveIdentity(addrStr, identityKey);
91
114
  if (identityChanged) {
92
- logger.info({ jid, addr: addrStr }, 'identity key changed or new contact, session will be re-established');
115
+ logger?.info?.({ jid, addr: addrStr }, 'identity key changed or new contact, session will be re-established');
93
116
  }
94
117
  }
95
118
  }
96
- async function doDecrypt() {
97
- let result;
98
- switch (type) {
99
- case 'pkmsg':
100
- result = await session.decryptPreKeyWhisperMessage(ciphertext);
101
- break;
102
- case 'msg':
103
- result = await session.decryptWhisperMessage(ciphertext);
104
- break;
119
+ try {
120
+ return await auth.keys.transaction(async () => {
121
+ let result;
122
+ switch (type) {
123
+ case 'pkmsg':
124
+ result = await session.decryptPreKeyWhisperMessage(ciphertext);
125
+ break;
126
+ case 'msg':
127
+ result = await session.decryptWhisperMessage(ciphertext);
128
+ break;
129
+ default:
130
+ throw new Error(`Unknown message type: ${type}`);
131
+ }
132
+ return result;
133
+ }, jid);
134
+ } catch (error) {
135
+ const errText = String(error?.message || error || '')
136
+ if (/bad mac|no session|invalid message|duplicate message|cannot decrypt/i.test(errText)) {
137
+ await storage.removeSession(addr.toString()).catch(() => null)
138
+ logger?.warn?.({ jid, type, errText }, 'reset stale session after decrypt failure')
105
139
  }
106
- return result;
140
+ throw error
107
141
  }
108
- // If it's not a sync message, we need to ensure atomicity
109
- // For regular messages, we use a transaction to ensure atomicity
110
- return parsedKeys.transaction(async () => {
111
- return await doDecrypt();
112
- }, jid);
113
142
  },
114
143
  async encryptMessage({ jid, data }) {
115
144
  const addr = jidToSignalProtocolAddress(jid);
116
145
  const cipher = new libsignal.SessionCipher(storage, addr);
117
- // Use transaction to ensure atomicity
118
- return parsedKeys.transaction(async () => {
146
+ return auth.keys.transaction(async () => {
119
147
  const { type: sigType, body } = await cipher.encrypt(data);
120
148
  const type = sigType === 3 ? 'pkmsg' : 'msg';
121
149
  return { type, ciphertext: Buffer.from(body, 'binary') };
122
150
  }, jid);
123
151
  },
124
152
  async encryptGroupMessage({ group, meId, data }) {
125
- return parsedKeys.transaction(async () => {
126
- const { senderName, skdm } = await ensureSenderKeyAndCreateSkdm(group, meId);
127
- const ciphertext = await new GroupCipher(storage, senderName).encrypt(data);
128
- return { ciphertext, senderKeyDistributionMessage: skdm.serialize() };
129
- }, group);
130
- },
131
- async getSenderKeyDistributionMessage({ group, meId }) {
132
- return parsedKeys.transaction(async () => {
133
- const { skdm } = await ensureSenderKeyAndCreateSkdm(group, meId);
134
- return skdm.serialize();
153
+ return auth.keys.transaction(async () => {
154
+ const senderName = jidToSignalSenderKeyName(group, meId);
155
+ const builder = new Group_1.GroupSessionBuilder(storage);
156
+ const senderNameStr = senderName.toString();
157
+ const { [senderNameStr]: senderKey } = await auth.keys.get('sender-key', [senderNameStr]);
158
+ if (!senderKey) {
159
+ await storage.storeSenderKey(senderName, new sender_key_record_1.SenderKeyRecord());
160
+ }
161
+ const senderKeyDistributionMessage = await builder.create(senderName);
162
+ const session = new Group_1.GroupCipher(storage, senderName);
163
+ const ciphertext = await session.encrypt(data);
164
+ return {
165
+ ciphertext,
166
+ senderKeyDistributionMessage: senderKeyDistributionMessage.serialize()
167
+ };
135
168
  }, group);
136
169
  },
137
- async hasSenderKey({ group, meId }) {
138
- const senderName = jidToSignalSenderKeyName(group, meId).toString();
139
- const { [senderName]: key } = await auth.keys.get('sender-key', [senderName]);
140
- return !!key;
141
- },
142
- async getSessionInfo(jid) {
143
- const addr = jidToSignalProtocolAddress(jid).toString();
144
- const session = (await storage.loadSession(addr));
145
- if (!session) {
146
- return null;
147
- }
148
- const open = session.getOpenSession?.();
149
- const baseKey = open?.indexInfo?.baseKey;
150
- const registrationId = open?.registrationId;
151
- if (!baseKey || typeof registrationId !== 'number') {
152
- return null;
153
- }
154
- return { baseKey: new Uint8Array(baseKey), registrationId };
155
- },
156
170
  async injectE2ESession({ jid, session }) {
157
- logger.trace({ jid }, 'injecting E2EE session');
158
171
  const cipher = new libsignal.SessionBuilder(storage, jidToSignalProtocolAddress(jid));
159
- return parsedKeys.transaction(async () => {
160
- // libsignal runtime accepts an absent prekey (initOutgoing checks `device.preKey && ...`)
161
- // but the bundled .d.ts marks it required.
162
- await cipher.initOutgoing(session);
163
- }, jid);
172
+ await cipher.initOutgoing(session);
164
173
  },
165
174
  jidToSignalProtocolAddress(jid) {
166
175
  return jidToSignalProtocolAddress(jid).toString();
167
176
  },
168
- // Optimized direct access to LID mapping store
169
- lidMapping,
177
+ // Dipakai oleh sendRetryRequest (messages-recv.js) untuk enableAutoSessionRecreation.
178
+ // Sebelumnya dipanggil tapi tidak pernah diimplementasikan di sini, jadi fitur auto
179
+ // session recreation diam-diam selalu gagal (ketangkep try/catch, cuma log warning).
170
180
  async validateSession(jid) {
171
181
  try {
172
182
  const addr = jidToSignalProtocolAddress(jid);
@@ -174,215 +184,60 @@ export function makeLibSignalRepository(auth, logger, pnToLIDFunc) {
174
184
  if (!session) {
175
185
  return { exists: false, reason: 'no session' };
176
186
  }
177
- if (!session.haveOpenSession()) {
187
+ if (typeof session.haveOpenSession === 'function' && !session.haveOpenSession()) {
178
188
  return { exists: false, reason: 'no open session' };
179
189
  }
180
190
  return { exists: true };
181
- }
182
- catch (error) {
191
+ } catch (error) {
183
192
  return { exists: false, reason: 'validation error' };
184
193
  }
185
- },
186
- async deleteSession(jids) {
187
- if (!jids.length)
188
- return;
189
- // Convert JIDs to signal addresses and prepare for bulk deletion
190
- const sessionUpdates = {};
191
- jids.forEach(jid => {
192
- const addr = jidToSignalProtocolAddress(jid);
193
- sessionUpdates[addr.toString()] = null;
194
- });
195
- // Single transaction for all deletions
196
- return parsedKeys.transaction(async () => {
197
- await auth.keys.set({ session: sessionUpdates });
198
- }, `delete-${jids.length}-sessions`);
199
- },
200
- close() {
201
- migratedSessionCache.clear();
202
- lidMapping.close();
203
- },
204
- async migrateSession(fromJid, toJid) {
205
- // TODO: use usync to handle this entire mess
206
- if (!fromJid || (!isLidUser(toJid) && !isHostedLidUser(toJid)))
207
- return { migrated: 0, skipped: 0, total: 0 };
208
- // Only support PN to LID migration
209
- if (!isPnUser(fromJid) && !isHostedPnUser(fromJid)) {
210
- return { migrated: 0, skipped: 0, total: 1 };
211
- }
212
- const { user } = jidDecode(fromJid);
213
- logger.debug({ fromJid }, 'bulk device migration - loading all user devices');
214
- // Get user's device list from storage
215
- const { [user]: userDevices } = await parsedKeys.get('device-list', [user]);
216
- if (!userDevices) {
217
- return { migrated: 0, skipped: 0, total: 0 };
218
- }
219
- const { device: fromDevice } = jidDecode(fromJid);
220
- const fromDeviceStr = fromDevice?.toString() || '0';
221
- if (!userDevices.includes(fromDeviceStr)) {
222
- userDevices.push(fromDeviceStr);
223
- }
224
- // Filter out cached devices before database fetch
225
- const uncachedDevices = userDevices.filter(device => {
226
- const deviceKey = `${user}.${device}`;
227
- return !migratedSessionCache.has(deviceKey);
228
- });
229
- // Bulk check session existence only for uncached devices
230
- const deviceSessionKeys = uncachedDevices.map(device => `${user}.${device}`);
231
- const existingSessions = await parsedKeys.get('session', deviceSessionKeys);
232
- // Step 3: Convert existing sessions to JIDs (only migrate sessions that exist)
233
- const deviceJids = [];
234
- for (const [sessionKey, sessionData] of Object.entries(existingSessions)) {
235
- if (sessionData) {
236
- // Session exists in storage
237
- const deviceStr = sessionKey.split('.')[1];
238
- if (!deviceStr)
239
- continue;
240
- const deviceNum = parseInt(deviceStr);
241
- let jid = deviceNum === 0 ? `${user}@s.whatsapp.net` : `${user}:${deviceNum}@s.whatsapp.net`;
242
- if (deviceNum === 99) {
243
- jid = `${user}:99@hosted`;
244
- }
245
- deviceJids.push(jid);
246
- }
247
- }
248
- logger.debug({
249
- fromJid,
250
- totalDevices: userDevices.length,
251
- devicesWithSessions: deviceJids.length,
252
- devices: deviceJids
253
- }, 'bulk device migration complete - all user devices processed');
254
- // Single transaction for all migrations
255
- return parsedKeys.transaction(async () => {
256
- const migrationOps = deviceJids.map(jid => {
257
- const lidWithDevice = transferDevice(jid, toJid);
258
- const fromDecoded = jidDecode(jid);
259
- const toDecoded = jidDecode(lidWithDevice);
260
- return {
261
- fromJid: jid,
262
- toJid: lidWithDevice,
263
- pnUser: fromDecoded.user,
264
- lidUser: toDecoded.user,
265
- deviceId: fromDecoded.device || 0,
266
- fromAddr: jidToSignalProtocolAddress(jid),
267
- toAddr: jidToSignalProtocolAddress(lidWithDevice)
268
- };
269
- });
270
- const totalOps = migrationOps.length;
271
- let migratedCount = 0;
272
- // Bulk fetch PN sessions - already exist (verified during device discovery)
273
- const pnAddrStrings = Array.from(new Set(migrationOps.map(op => op.fromAddr.toString())));
274
- const pnSessions = await parsedKeys.get('session', pnAddrStrings);
275
- // Prepare bulk session updates (PN → LID migration + deletion)
276
- const sessionUpdates = {};
277
- for (const op of migrationOps) {
278
- const pnAddrStr = op.fromAddr.toString();
279
- const lidAddrStr = op.toAddr.toString();
280
- const pnSession = pnSessions[pnAddrStr];
281
- if (pnSession) {
282
- // Session exists (guaranteed from device discovery)
283
- const fromSession = libsignal.SessionRecord.deserialize(pnSession);
284
- if (fromSession.haveOpenSession()) {
285
- // Queue for bulk update: copy to LID, delete from PN
286
- sessionUpdates[lidAddrStr] = fromSession.serialize();
287
- sessionUpdates[pnAddrStr] = null;
288
- migratedCount++;
289
- }
290
- }
291
- }
292
- // Single bulk session update for all migrations
293
- if (Object.keys(sessionUpdates).length > 0) {
294
- await parsedKeys.set({ session: sessionUpdates });
295
- logger.debug({ migratedSessions: migratedCount }, 'bulk session migration complete');
296
- // Cache device-level migrations
297
- for (const op of migrationOps) {
298
- if (sessionUpdates[op.toAddr.toString()]) {
299
- const deviceKey = `${op.pnUser}.${op.deviceId}`;
300
- migratedSessionCache.set(deviceKey, true);
301
- }
302
- }
303
- }
304
- const skippedCount = totalOps - migratedCount;
305
- return { migrated: migratedCount, skipped: skippedCount, total: totalOps };
306
- }, `migrate-${deviceJids.length}-sessions-${jidDecode(toJid)?.user}`);
307
194
  }
308
195
  };
309
- return repository;
310
196
  }
311
197
  const jidToSignalProtocolAddress = (jid) => {
312
- const decoded = jidDecode(jid);
313
- const { user, device, server, domainType } = decoded;
314
- if (!user) {
315
- throw new Error(`JID decoded but user is empty: "${jid}" -> user: "${user}", server: "${server}", device: ${device}`);
316
- }
317
- const signalUser = domainType !== WAJIDDomains.WHATSAPP ? `${user}_${domainType}` : user;
318
- const finalDevice = device || 0;
319
- if (device === 99 && decoded.server !== 'hosted' && decoded.server !== 'hosted.lid') {
320
- throw new Error('Unexpected non-hosted device JID with device 99. This ID seems invalid. ID:' + jid);
321
- }
322
- return new libsignal.ProtocolAddress(signalUser, finalDevice);
198
+ const { user, device } = (0, WABinary_1.jidDecode)(jid);
199
+ return new libsignal.ProtocolAddress(user, device || 0);
323
200
  };
324
201
  const jidToSignalSenderKeyName = (group, user) => {
325
- return new SenderKeyName(group, jidToSignalProtocolAddress(user));
202
+ return new sender_key_name_1.SenderKeyName(group, jidToSignalProtocolAddress(user));
326
203
  };
327
- function signalStorage({ creds, keys }, lidMapping) {
328
- // Shared function to resolve PN signal address to LID if mapping exists
329
- const resolveLIDSignalAddress = async (id) => {
330
- if (id.includes('.')) {
331
- const [deviceId, device] = id.split('.');
332
- const [user, domainType_] = deviceId.split('_');
333
- const domainType = parseInt(domainType_ || '0');
334
- if (domainType === WAJIDDomains.LID || domainType === WAJIDDomains.HOSTED_LID)
335
- return id;
336
- const pnJid = `${user}${device !== '0' ? `:${device}` : ''}@${domainType === WAJIDDomains.HOSTED ? 'hosted' : 's.whatsapp.net'}`;
337
- const lidForPN = await lidMapping.getLIDForPN(pnJid);
338
- if (lidForPN) {
339
- const lidAddr = jidToSignalProtocolAddress(lidForPN);
340
- return lidAddr.toString();
341
- }
342
- }
343
- return id;
344
- };
204
+ function signalStorage({ creds, keys }) {
345
205
  return {
346
206
  loadSession: async (id) => {
347
- try {
348
- const wireJid = await resolveLIDSignalAddress(id);
349
- const { [wireJid]: sess } = await keys.get('session', [wireJid]);
350
- if (sess) {
351
- return libsignal.SessionRecord.deserialize(sess);
352
- }
353
- }
354
- catch (e) {
355
- return null;
207
+ const { [id]: sess } = await keys.get('session', [id]);
208
+ if (sess) {
209
+ return libsignal.SessionRecord.deserialize(sess);
356
210
  }
357
- return null;
358
211
  },
359
212
  storeSession: async (id, session) => {
360
- const wireJid = await resolveLIDSignalAddress(id);
361
- await keys.set({ session: { [wireJid]: session.serialize() } });
213
+ await keys.set({ session: { [id]: session.serialize() } });
214
+ },
215
+ removeSession: async (id) => {
216
+ await keys.set({ session: { [id]: null } });
362
217
  },
363
218
  isTrustedIdentity: () => {
364
- return true; // TOFU - Trust on First Use (same as WhatsApp Web)
219
+ return true;
365
220
  },
366
221
  loadIdentityKey: async (id) => {
367
- const wireJid = await resolveLIDSignalAddress(id);
368
- const { [wireJid]: key } = await keys.get('identity-key', [wireJid]);
222
+ const { [id]: key } = await keys.get('identity-key', [id]);
369
223
  return key || undefined;
370
224
  },
371
225
  saveIdentity: async (id, identityKey) => {
372
- const wireJid = await resolveLIDSignalAddress(id);
373
- const { [wireJid]: existingKey } = await keys.get('identity-key', [wireJid]);
374
- const keysMatch = existingKey?.length === identityKey.length && existingKey.every((byte, i) => byte === identityKey[i]);
226
+ const { [id]: existingKey } = await keys.get('identity-key', [id]);
227
+ const keysMatch = existingKey && existingKey.length === identityKey.length &&
228
+ Buffer.compare(Buffer.from(existingKey), Buffer.from(identityKey)) === 0;
375
229
  if (existingKey && !keysMatch) {
376
- // Identity changed - clear session and update key
230
+ // Identity berubah - hapus sesi lama (bakal ke-generate ulang dari
231
+ // pkmsg yang lagi diproses) dan simpan identity key yang baru.
377
232
  await keys.set({
378
- session: { [wireJid]: null },
379
- 'identity-key': { [wireJid]: identityKey }
233
+ session: { [id]: null },
234
+ 'identity-key': { [id]: identityKey }
380
235
  });
381
236
  return true;
382
237
  }
383
238
  if (!existingKey) {
384
- // New contact - Trust on First Use (TOFU)
385
- await keys.set({ 'identity-key': { [wireJid]: identityKey } });
239
+ // Kontak baru - Trust On First Use (TOFU), sama kayak WhatsApp Web.
240
+ await keys.set({ 'identity-key': { [id]: identityKey } });
386
241
  return true;
387
242
  }
388
243
  return false;
@@ -409,9 +264,9 @@ function signalStorage({ creds, keys }, lidMapping) {
409
264
  const keyId = senderKeyName.toString();
410
265
  const { [keyId]: key } = await keys.get('sender-key', [keyId]);
411
266
  if (key) {
412
- return SenderKeyRecord.deserialize(key);
267
+ return sender_key_record_1.SenderKeyRecord.deserialize(key);
413
268
  }
414
- return new SenderKeyRecord();
269
+ return new sender_key_record_1.SenderKeyRecord();
415
270
  },
416
271
  storeSenderKey: async (senderKeyName, key) => {
417
272
  const keyId = senderKeyName.toString();
@@ -423,9 +278,8 @@ function signalStorage({ creds, keys }, lidMapping) {
423
278
  const { signedIdentityKey } = creds;
424
279
  return {
425
280
  privKey: Buffer.from(signedIdentityKey.private),
426
- pubKey: Buffer.from(generateSignalPubKey(signedIdentityKey.public))
281
+ pubKey: (0, Utils_1.generateSignalPubKey)(signedIdentityKey.public)
427
282
  };
428
283
  }
429
284
  };
430
285
  }
431
- //# sourceMappingURL=libsignal.js.map