ruby-baileys 0.0.0-stage → 1.5.17

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 (296) hide show
  1. package/EXPERIMENTAL.md +350 -0
  2. package/LICENSE +23 -0
  3. package/NOTICE.md +14 -0
  4. package/README.md +6265 -2
  5. package/WAProto/GenerateStatics.sh +3 -0
  6. package/WAProto/WAProto.proto +5479 -0
  7. package/WAProto/fix-imports.js +81 -0
  8. package/WAProto/index.d.ts +16877 -0
  9. package/WAProto/index.js +122159 -0
  10. package/assets/ruby_aspirant.jpg +0 -0
  11. package/assets/ruby_aspirant_4k.jpg +88 -0
  12. package/assets/ruby_aspirant_full.jpg +0 -0
  13. package/assets/ruby_aspirant_render.png +1 -0
  14. package/assets/ruby_aspirants_hd.jpg +0 -0
  15. package/assets/thumb.jpg +0 -0
  16. package/engine-requirements.js +14 -0
  17. package/index.cjs +29 -0
  18. package/index.d.ts +2 -0
  19. package/package.json +178 -4
  20. package/src/Defaults/index.d.ts +153 -0
  21. package/src/Defaults/index.js +165 -0
  22. package/src/MessageBuilder/bot-signature.d.ts +22 -0
  23. package/src/MessageBuilder/bot-signature.js +123 -0
  24. package/src/MessageBuilder/extras.d.ts +396 -0
  25. package/src/MessageBuilder/extras.js +1229 -0
  26. package/src/MessageBuilder/index.d.ts +210 -0
  27. package/src/MessageBuilder/index.js +3521 -0
  28. package/src/MessageBuilder/metaai.d.ts +438 -0
  29. package/src/MessageBuilder/metaai.js +891 -0
  30. package/src/Signal/Group/ciphertext-message.d.ts +10 -0
  31. package/src/Signal/Group/ciphertext-message.js +12 -0
  32. package/src/Signal/Group/group-session-builder.d.ts +8 -0
  33. package/src/Signal/Group/group-session-builder.js +28 -0
  34. package/src/Signal/Group/group_cipher.d.ts +11 -0
  35. package/src/Signal/Group/group_cipher.js +79 -0
  36. package/src/Signal/Group/index.d.ts +12 -0
  37. package/src/Signal/Group/index.js +12 -0
  38. package/src/Signal/Group/keyhelper.d.ts +7 -0
  39. package/src/Signal/Group/keyhelper.js +18 -0
  40. package/src/Signal/Group/sender-chain-key.d.ts +14 -0
  41. package/src/Signal/Group/sender-chain-key.js +26 -0
  42. package/src/Signal/Group/sender-key-distribution-message.d.ts +17 -0
  43. package/src/Signal/Group/sender-key-distribution-message.js +63 -0
  44. package/src/Signal/Group/sender-key-message.d.ts +19 -0
  45. package/src/Signal/Group/sender-key-message.js +66 -0
  46. package/src/Signal/Group/sender-key-name.d.ts +12 -0
  47. package/src/Signal/Group/sender-key-name.js +48 -0
  48. package/src/Signal/Group/sender-key-record.d.ts +13 -0
  49. package/src/Signal/Group/sender-key-record.js +41 -0
  50. package/src/Signal/Group/sender-key-state.d.ts +17 -0
  51. package/src/Signal/Group/sender-key-state.js +84 -0
  52. package/src/Signal/Group/sender-message-key.d.ts +12 -0
  53. package/src/Signal/Group/sender-message-key.js +26 -0
  54. package/src/Signal/libsignal.d.ts +55 -0
  55. package/src/Signal/libsignal.js +429 -0
  56. package/src/Signal/lid-mapping.d.ts +21 -0
  57. package/src/Signal/lid-mapping.js +275 -0
  58. package/src/Socket/Client/index.d.ts +3 -0
  59. package/src/Socket/Client/index.js +3 -0
  60. package/src/Socket/Client/types.d.ts +6 -0
  61. package/src/Socket/Client/types.js +10 -0
  62. package/src/Socket/Client/websocket.d.ts +13 -0
  63. package/src/Socket/Client/websocket.js +54 -0
  64. package/src/Socket/business.d.ts +432 -0
  65. package/src/Socket/business.js +380 -0
  66. package/src/Socket/chats.d.ts +248 -0
  67. package/src/Socket/chats.js +1485 -0
  68. package/src/Socket/communities.d.ts +599 -0
  69. package/src/Socket/communities.js +422 -0
  70. package/src/Socket/groups.d.ts +299 -0
  71. package/src/Socket/groups.js +340 -0
  72. package/src/Socket/index.d.ts +582 -0
  73. package/src/Socket/index.js +48 -0
  74. package/src/Socket/messages-recv.d.ts +371 -0
  75. package/src/Socket/messages-recv.js +1803 -0
  76. package/src/Socket/messages-send.d.ts +391 -0
  77. package/src/Socket/messages-send.js +1575 -0
  78. package/src/Socket/mex.d.ts +2 -0
  79. package/src/Socket/mex.js +45 -0
  80. package/src/Socket/newsletter.d.ts +469 -0
  81. package/src/Socket/newsletter.js +643 -0
  82. package/src/Socket/socket.d.ts +78 -0
  83. package/src/Socket/socket.js +1088 -0
  84. package/src/Store/index.d.ts +4 -0
  85. package/src/Store/index.js +4 -0
  86. package/src/Store/make-in-memory-store.d.ts +63 -0
  87. package/src/Store/make-in-memory-store.js +398 -0
  88. package/src/Store/make-ordered-dictionary.d.ts +13 -0
  89. package/src/Store/make-ordered-dictionary.js +79 -0
  90. package/src/Store/object-repository.d.ts +11 -0
  91. package/src/Store/object-repository.js +24 -0
  92. package/src/Types/Auth.d.ts +2 -0
  93. package/src/Types/Auth.js +2 -0
  94. package/src/Types/Bussines.d.ts +2 -0
  95. package/src/Types/Bussines.js +2 -0
  96. package/src/Types/Call.d.ts +2 -0
  97. package/src/Types/Call.js +2 -0
  98. package/src/Types/Chat.d.ts +3 -0
  99. package/src/Types/Chat.js +25 -0
  100. package/src/Types/Contact.d.ts +2 -0
  101. package/src/Types/Contact.js +2 -0
  102. package/src/Types/Events.d.ts +2 -0
  103. package/src/Types/Events.js +1 -0
  104. package/src/Types/GroupMetadata.d.ts +6 -0
  105. package/src/Types/GroupMetadata.js +7 -0
  106. package/src/Types/Label.d.ts +3 -0
  107. package/src/Types/Label.js +25 -0
  108. package/src/Types/LabelAssociation.d.ts +3 -0
  109. package/src/Types/LabelAssociation.js +7 -0
  110. package/src/Types/Message.d.ts +14 -0
  111. package/src/Types/Message.js +24 -0
  112. package/src/Types/Mex.d.ts +3 -0
  113. package/src/Types/Mex.js +96 -0
  114. package/src/Types/Product.d.ts +2 -0
  115. package/src/Types/Product.js +2 -0
  116. package/src/Types/Signal.d.ts +2 -0
  117. package/src/Types/Signal.js +1 -0
  118. package/src/Types/Socket.d.ts +2 -0
  119. package/src/Types/Socket.js +1 -0
  120. package/src/Types/State.d.ts +6 -0
  121. package/src/Types/State.js +55 -0
  122. package/src/Types/USync.d.ts +2 -0
  123. package/src/Types/USync.js +1 -0
  124. package/src/Types/index.d.ts +14 -0
  125. package/src/Types/index.js +26 -0
  126. package/src/Utils/auth-store.d.ts +30 -0
  127. package/src/Utils/auth-store.js +77 -0
  128. package/src/Utils/auth-utils.d.ts +59 -0
  129. package/src/Utils/auth-utils.js +274 -0
  130. package/src/Utils/browser-utils.d.ts +10 -0
  131. package/src/Utils/browser-utils.js +29 -0
  132. package/src/Utils/business.d.ts +50 -0
  133. package/src/Utils/business.js +227 -0
  134. package/src/Utils/chat-utils.d.ts +409 -0
  135. package/src/Utils/chat-utils.js +847 -0
  136. package/src/Utils/companion-reg-client-utils.d.ts +5 -0
  137. package/src/Utils/companion-reg-client-utils.js +40 -0
  138. package/src/Utils/crypto.d.ts +40 -0
  139. package/src/Utils/crypto.js +111 -0
  140. package/src/Utils/decode-wa-message.d.ts +100 -0
  141. package/src/Utils/decode-wa-message.js +374 -0
  142. package/src/Utils/event-buffer.d.ts +23 -0
  143. package/src/Utils/event-buffer.js +625 -0
  144. package/src/Utils/generics.d.ts +64 -0
  145. package/src/Utils/generics.js +376 -0
  146. package/src/Utils/group-metadata-cache.d.ts +5 -0
  147. package/src/Utils/group-metadata-cache.js +26 -0
  148. package/src/Utils/history.d.ts +76 -0
  149. package/src/Utils/history.js +132 -0
  150. package/src/Utils/html-app.d.ts +19 -0
  151. package/src/Utils/html-app.js +97 -0
  152. package/src/Utils/html-multiplayer.d.ts +10 -0
  153. package/src/Utils/html-multiplayer.js +95 -0
  154. package/src/Utils/identity-change-handler.d.ts +14 -0
  155. package/src/Utils/identity-change-handler.js +49 -0
  156. package/src/Utils/index.d.ts +45 -0
  157. package/src/Utils/index.js +45 -0
  158. package/src/Utils/link-preview-metadata.d.ts +47 -0
  159. package/src/Utils/link-preview-metadata.js +89 -0
  160. package/src/Utils/link-preview.d.ts +13 -0
  161. package/src/Utils/link-preview.js +80 -0
  162. package/src/Utils/logger.d.ts +3 -0
  163. package/src/Utils/logger.js +3 -0
  164. package/src/Utils/lt-hash.d.ts +7 -0
  165. package/src/Utils/lt-hash.js +4 -0
  166. package/src/Utils/make-mutex.d.ts +7 -0
  167. package/src/Utils/make-mutex.js +33 -0
  168. package/src/Utils/message-retry-manager.d.ts +80 -0
  169. package/src/Utils/message-retry-manager.js +256 -0
  170. package/src/Utils/messages-media.d.ts +137 -0
  171. package/src/Utils/messages-media.js +815 -0
  172. package/src/Utils/messages.d.ts +63 -0
  173. package/src/Utils/messages.js +2149 -0
  174. package/src/Utils/modern-messages.d.ts +150 -0
  175. package/src/Utils/modern-messages.js +496 -0
  176. package/src/Utils/native-flow.d.ts +11 -0
  177. package/src/Utils/native-flow.js +116 -0
  178. package/src/Utils/newsletter-status.d.ts +158 -0
  179. package/src/Utils/newsletter-status.js +651 -0
  180. package/src/Utils/noise-handler.d.ts +21 -0
  181. package/src/Utils/noise-handler.js +201 -0
  182. package/src/Utils/offline-node-processor.d.ts +10 -0
  183. package/src/Utils/offline-node-processor.js +34 -0
  184. package/src/Utils/optional-media.d.ts +3 -0
  185. package/src/Utils/optional-media.js +46 -0
  186. package/src/Utils/payment-messages.d.ts +66 -0
  187. package/src/Utils/payment-messages.js +161 -0
  188. package/src/Utils/pre-key-manager.d.ts +26 -0
  189. package/src/Utils/pre-key-manager.js +96 -0
  190. package/src/Utils/process-message.d.ts +61 -0
  191. package/src/Utils/process-message.js +689 -0
  192. package/src/Utils/reporting-utils.d.ts +13 -0
  193. package/src/Utils/reporting-utils.js +257 -0
  194. package/src/Utils/scheduled-message.d.ts +51 -0
  195. package/src/Utils/scheduled-message.js +113 -0
  196. package/src/Utils/sender-key-memory.d.ts +20 -0
  197. package/src/Utils/sender-key-memory.js +52 -0
  198. package/src/Utils/signal.d.ts +83 -0
  199. package/src/Utils/signal.js +194 -0
  200. package/src/Utils/stanza-ack.d.ts +17 -0
  201. package/src/Utils/stanza-ack.js +31 -0
  202. package/src/Utils/status-stickers.d.ts +127 -0
  203. package/src/Utils/status-stickers.js +261 -0
  204. package/src/Utils/sync-action-utils.d.ts +3 -0
  205. package/src/Utils/sync-action-utils.js +45 -0
  206. package/src/Utils/tc-token-utils.d.ts +30 -0
  207. package/src/Utils/tc-token-utils.js +156 -0
  208. package/src/Utils/ttl-cache.d.ts +29 -0
  209. package/src/Utils/ttl-cache.js +121 -0
  210. package/src/Utils/use-mongo-auth-state.d.ts +22 -0
  211. package/src/Utils/use-mongo-auth-state.js +68 -0
  212. package/src/Utils/use-multi-file-auth-state.d.ts +12 -0
  213. package/src/Utils/use-multi-file-auth-state.js +107 -0
  214. package/src/Utils/use-mysql-auth-state.d.ts +20 -0
  215. package/src/Utils/use-mysql-auth-state.js +80 -0
  216. package/src/Utils/use-postgres-auth-state.d.ts +20 -0
  217. package/src/Utils/use-postgres-auth-state.js +80 -0
  218. package/src/Utils/use-redis-auth-state.d.ts +20 -0
  219. package/src/Utils/use-redis-auth-state.js +90 -0
  220. package/src/Utils/use-single-file-auth-state.d.ts +11 -0
  221. package/src/Utils/use-single-file-auth-state.js +109 -0
  222. package/src/Utils/use-sqlite-auth-state.d.ts +13 -0
  223. package/src/Utils/use-sqlite-auth-state.js +121 -0
  224. package/src/Utils/useNekoDBAuth.d.ts +19 -0
  225. package/src/Utils/useNekoDBAuth.js +111 -0
  226. package/src/Utils/username.d.ts +12 -0
  227. package/src/Utils/username.js +59 -0
  228. package/src/Utils/validate-connection.d.ts +44 -0
  229. package/src/Utils/validate-connection.js +208 -0
  230. package/src/Utils/voice-recognition.d.ts +53 -0
  231. package/src/Utils/voice-recognition.js +219 -0
  232. package/src/Voip/audio-feeder.d.ts +25 -0
  233. package/src/Voip/audio-feeder.js +269 -0
  234. package/src/Voip/index.d.ts +89 -0
  235. package/src/Voip/index.js +937 -0
  236. package/src/Voip/relay-transport.d.ts +6 -0
  237. package/src/Voip/relay-transport.js +825 -0
  238. package/src/Voip/signaling.d.ts +12 -0
  239. package/src/Voip/signaling.js +1100 -0
  240. package/src/Voip/types.d.ts +3 -0
  241. package/src/Voip/types.js +13 -0
  242. package/src/Voip/video-feeder.d.ts +25 -0
  243. package/src/Voip/video-feeder.js +269 -0
  244. package/src/Voip/wasm-engine.d.ts +27 -0
  245. package/src/Voip/wasm-engine.js +1308 -0
  246. package/src/Voip/worker-bootstrap.js +1024 -0
  247. package/src/WABinary/constants.d.ts +23 -0
  248. package/src/WABinary/constants.js +1301 -0
  249. package/src/WABinary/decode.d.ts +10 -0
  250. package/src/WABinary/decode.js +262 -0
  251. package/src/WABinary/encode.d.ts +3 -0
  252. package/src/WABinary/encode.js +220 -0
  253. package/src/WABinary/generic-utils.d.ts +77 -0
  254. package/src/WABinary/generic-utils.js +214 -0
  255. package/src/WABinary/index.d.ts +6 -0
  256. package/src/WABinary/index.js +6 -0
  257. package/src/WABinary/jid-utils.d.ts +31 -0
  258. package/src/WABinary/jid-utils.js +98 -0
  259. package/src/WABinary/types.d.ts +2 -0
  260. package/src/WABinary/types.js +1 -0
  261. package/src/WAM/BinaryInfo.d.ts +8 -0
  262. package/src/WAM/BinaryInfo.js +10 -0
  263. package/src/WAM/constants.d.ts +34927 -0
  264. package/src/WAM/constants.js +22853 -0
  265. package/src/WAM/encode.d.ts +2 -0
  266. package/src/WAM/encode.js +149 -0
  267. package/src/WAM/index.d.ts +4 -0
  268. package/src/WAM/index.js +4 -0
  269. package/src/WAUSync/Protocols/USyncContactProtocol.d.ts +37 -0
  270. package/src/WAUSync/Protocols/USyncContactProtocol.js +51 -0
  271. package/src/WAUSync/Protocols/USyncDeviceProtocol.d.ts +23 -0
  272. package/src/WAUSync/Protocols/USyncDeviceProtocol.js +52 -0
  273. package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +13 -0
  274. package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.js +27 -0
  275. package/src/WAUSync/Protocols/USyncStatusProtocol.d.ts +13 -0
  276. package/src/WAUSync/Protocols/USyncStatusProtocol.js +38 -0
  277. package/src/WAUSync/Protocols/USyncUsernameProtocol.d.ts +10 -0
  278. package/src/WAUSync/Protocols/USyncUsernameProtocol.js +24 -0
  279. package/src/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +39 -0
  280. package/src/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -0
  281. package/src/WAUSync/Protocols/UsyncLIDProtocol.d.ts +15 -0
  282. package/src/WAUSync/Protocols/UsyncLIDProtocol.js +29 -0
  283. package/src/WAUSync/Protocols/index.d.ts +6 -0
  284. package/src/WAUSync/Protocols/index.js +6 -0
  285. package/src/WAUSync/USyncQuery.d.ts +21 -0
  286. package/src/WAUSync/USyncQuery.js +94 -0
  287. package/src/WAUSync/USyncUser.d.ts +17 -0
  288. package/src/WAUSync/USyncUser.js +31 -0
  289. package/src/WAUSync/index.d.ts +4 -0
  290. package/src/WAUSync/index.js +4 -0
  291. package/src/assets/wasm/README.md +76 -0
  292. package/src/assets/wasm/loader.js +5 -0
  293. package/src/assets/wasm/whatsapp.wasm +0 -0
  294. package/src/assets/wasm/worker-modules.js +273 -0
  295. package/src/index.d.ts +49 -0
  296. package/src/index.js +54 -0
@@ -0,0 +1,201 @@
1
+ /* Elaina Baileys maintained distribution. Upstream notices and license are preserved in LICENSE and NOTICE.md. */
2
+ import { Boom } from '@hapi/boom';
3
+ import { proto } from '../../WAProto/index.js';
4
+ import { NOISE_MODE, WA_CERT_DETAILS } from '../Defaults/index.js';
5
+ import { decodeBinaryNode } from '../WABinary/index.js';
6
+ import { aesDecryptGCM, aesEncryptGCM, Curve, hkdf, sha256 } from './crypto.js';
7
+ const IV_LENGTH = 12;
8
+ const EMPTY_BUFFER = Buffer.alloc(0);
9
+ const generateIV = (counter) => {
10
+ const iv = new ArrayBuffer(IV_LENGTH);
11
+ new DataView(iv).setUint32(8, counter);
12
+ return new Uint8Array(iv);
13
+ };
14
+ class TransportState {
15
+ constructor(encKey, decKey) {
16
+ this.encKey = encKey;
17
+ this.decKey = decKey;
18
+ this.readCounter = 0;
19
+ this.writeCounter = 0;
20
+ this.iv = new Uint8Array(IV_LENGTH);
21
+ }
22
+ encrypt(plaintext) {
23
+ const c = this.writeCounter++;
24
+ this.iv[8] = (c >>> 24) & 0xff;
25
+ this.iv[9] = (c >>> 16) & 0xff;
26
+ this.iv[10] = (c >>> 8) & 0xff;
27
+ this.iv[11] = c & 0xff;
28
+ return aesEncryptGCM(plaintext, this.encKey, this.iv, EMPTY_BUFFER);
29
+ }
30
+ decrypt(ciphertext) {
31
+ const c = this.readCounter++;
32
+ this.iv[8] = (c >>> 24) & 0xff;
33
+ this.iv[9] = (c >>> 16) & 0xff;
34
+ this.iv[10] = (c >>> 8) & 0xff;
35
+ this.iv[11] = c & 0xff;
36
+ return aesDecryptGCM(ciphertext, this.decKey, this.iv, EMPTY_BUFFER);
37
+ }
38
+ }
39
+ export const makeNoiseHandler = ({ keyPair: { private: privateKey, public: publicKey }, NOISE_HEADER, logger, routingInfo }) => {
40
+ logger = logger.child({ class: 'ns' });
41
+ const data = Buffer.from(NOISE_MODE);
42
+ let hash = data.byteLength === 32 ? data : sha256(data);
43
+ let salt = hash;
44
+ let encKey = hash;
45
+ let decKey = hash;
46
+ let counter = 0;
47
+ let sentIntro = false;
48
+ let inBytes = Buffer.alloc(0);
49
+ let transport = null;
50
+ let isWaitingForTransport = false;
51
+ let pendingOnFrame = null;
52
+ let introHeader;
53
+ if (routingInfo) {
54
+ introHeader = Buffer.alloc(7 + routingInfo.byteLength + NOISE_HEADER.length);
55
+ introHeader.write('ED', 0, 'utf8');
56
+ introHeader.writeUint8(0, 2);
57
+ introHeader.writeUint8(1, 3);
58
+ introHeader.writeUint8(routingInfo.byteLength >> 16, 4);
59
+ introHeader.writeUint16BE(routingInfo.byteLength & 65535, 5);
60
+ introHeader.set(routingInfo, 7);
61
+ introHeader.set(NOISE_HEADER, 7 + routingInfo.byteLength);
62
+ }
63
+ else {
64
+ introHeader = Buffer.from(NOISE_HEADER);
65
+ }
66
+ const authenticate = (data) => {
67
+ if (!transport) {
68
+ hash = sha256(Buffer.concat([hash, data]));
69
+ }
70
+ };
71
+ const encrypt = (plaintext) => {
72
+ if (transport) {
73
+ return transport.encrypt(plaintext);
74
+ }
75
+ const result = aesEncryptGCM(plaintext, encKey, generateIV(counter++), hash);
76
+ authenticate(result);
77
+ return result;
78
+ };
79
+ const decrypt = (ciphertext) => {
80
+ if (transport) {
81
+ return transport.decrypt(ciphertext);
82
+ }
83
+ const result = aesDecryptGCM(ciphertext, decKey, generateIV(counter++), hash);
84
+ authenticate(ciphertext);
85
+ return result;
86
+ };
87
+ const localHKDF = (data) => {
88
+ const key = hkdf(Buffer.from(data), 64, { salt, info: '' });
89
+ return [key.subarray(0, 32), key.subarray(32)];
90
+ };
91
+ const mixIntoKey = (data) => {
92
+ const [write, read] = localHKDF(data);
93
+ salt = write;
94
+ encKey = read;
95
+ decKey = read;
96
+ counter = 0;
97
+ };
98
+ const finishInit = async () => {
99
+ isWaitingForTransport = true;
100
+ const [write, read] = localHKDF(new Uint8Array(0));
101
+ transport = new TransportState(write, read);
102
+ isWaitingForTransport = false;
103
+ logger.trace('Noise handler transitioned to Transport state');
104
+ if (pendingOnFrame) {
105
+ logger.trace({ length: inBytes.length }, 'Flushing buffered frames after transport ready');
106
+ await processData(pendingOnFrame);
107
+ pendingOnFrame = null;
108
+ }
109
+ };
110
+ const processData = async (onFrame) => {
111
+ let size;
112
+ while (true) {
113
+ if (inBytes.length < 3)
114
+ return;
115
+ size = (inBytes[0] << 16) | (inBytes[1] << 8) | inBytes[2];
116
+ if (inBytes.length < size + 3)
117
+ return;
118
+ let frame = inBytes.subarray(3, size + 3);
119
+ inBytes = inBytes.subarray(size + 3);
120
+ if (transport) {
121
+ const result = transport.decrypt(frame);
122
+ frame = await decodeBinaryNode(result);
123
+ }
124
+ if (logger.level === 'trace') {
125
+ logger.trace({ msg: frame?.attrs?.id }, 'recv frame');
126
+ }
127
+ onFrame(frame);
128
+ }
129
+ };
130
+ authenticate(NOISE_HEADER);
131
+ authenticate(publicKey);
132
+ return {
133
+ encrypt,
134
+ decrypt,
135
+ authenticate,
136
+ mixIntoKey,
137
+ finishInit,
138
+ processHandshake: ({ serverHello }, noiseKey) => {
139
+ authenticate(serverHello.ephemeral);
140
+ mixIntoKey(Curve.sharedKey(privateKey, serverHello.ephemeral));
141
+ const decStaticContent = decrypt(serverHello.static);
142
+ mixIntoKey(Curve.sharedKey(privateKey, decStaticContent));
143
+ const certDecoded = decrypt(serverHello.payload);
144
+ const { intermediate: certIntermediate, leaf } = proto.CertChain.decode(certDecoded);
145
+
146
+ if (!leaf?.details || !leaf?.signature) {
147
+ throw new Boom('invalid noise leaf certificate', { statusCode: 400 });
148
+ }
149
+ if (!certIntermediate?.details || !certIntermediate?.signature) {
150
+ throw new Boom('invalid noise intermediate certificate', { statusCode: 400 });
151
+ }
152
+ const details = proto.CertChain.NoiseCertificate.Details.decode(certIntermediate.details);
153
+ const { issuerSerial } = details;
154
+ const verify = Curve.verify(details.key, leaf.details, leaf.signature);
155
+ const verifyIntermediate = Curve.verify(WA_CERT_DETAILS.PUBLIC_KEY, certIntermediate.details, certIntermediate.signature);
156
+ if (!verify) {
157
+ throw new Boom('noise certificate signature invalid', { statusCode: 400 });
158
+ }
159
+ if (!verifyIntermediate) {
160
+ throw new Boom('noise intermediate certificate signature invalid', { statusCode: 400 });
161
+ }
162
+ if (issuerSerial !== WA_CERT_DETAILS.SERIAL) {
163
+ throw new Boom('certification match failed', { statusCode: 400 });
164
+ }
165
+ const keyEnc = encrypt(noiseKey.public);
166
+ mixIntoKey(Curve.sharedKey(noiseKey.private, serverHello.ephemeral));
167
+ return keyEnc;
168
+ },
169
+ encodeFrame: (data) => {
170
+ if (transport) {
171
+ data = transport.encrypt(data);
172
+ }
173
+ const dataLen = data.byteLength;
174
+ const introSize = sentIntro ? 0 : introHeader.length;
175
+ const frame = Buffer.allocUnsafe(introSize + 3 + dataLen);
176
+ if (!sentIntro) {
177
+ frame.set(introHeader);
178
+ sentIntro = true;
179
+ }
180
+ frame[introSize] = (dataLen >>> 16) & 0xff;
181
+ frame[introSize + 1] = (dataLen >>> 8) & 0xff;
182
+ frame[introSize + 2] = dataLen & 0xff;
183
+ frame.set(data, introSize + 3);
184
+ return frame;
185
+ },
186
+ decodeFrame: async (newData, onFrame) => {
187
+ if (isWaitingForTransport) {
188
+ inBytes = Buffer.concat([inBytes, newData]);
189
+ pendingOnFrame = onFrame;
190
+ return;
191
+ }
192
+ if (inBytes.length === 0) {
193
+ inBytes = Buffer.from(newData);
194
+ }
195
+ else {
196
+ inBytes = Buffer.concat([inBytes, newData]);
197
+ }
198
+ await processData(onFrame);
199
+ }
200
+ };
201
+ };
@@ -0,0 +1,10 @@
1
+ /* Elaina Baileys maintained distribution. Upstream notices and license are preserved in LICENSE and NOTICE.md. */
2
+ /**
3
+ * Creates a processor for offline stanza nodes that:
4
+ * - Queues nodes for sequential processing
5
+ * - Yields to the event loop periodically to avoid blocking
6
+ * - Catches handler errors to prevent the processing loop from crashing
7
+ */
8
+ export function makeOfflineNodeProcessor(nodeProcessorMap: any, deps: any, batchSize?: number): {
9
+ enqueue: (type: any, node: any) => void;
10
+ };
@@ -0,0 +1,34 @@
1
+ /* Elaina Baileys maintained distribution. Upstream notices and license are preserved in LICENSE and NOTICE.md. */
2
+
3
+ export function makeOfflineNodeProcessor(nodeProcessorMap, deps, batchSize = 10) {
4
+ const nodes = [];
5
+ let isProcessing = false;
6
+ const enqueue = (type, node) => {
7
+ nodes.push({ type, node });
8
+ if (isProcessing) {
9
+ return;
10
+ }
11
+ isProcessing = true;
12
+ const promise = async () => {
13
+ let processedInBatch = 0;
14
+ while (nodes.length && deps.isWsOpen()) {
15
+ const { type, node } = nodes.shift();
16
+ const nodeProcessor = nodeProcessorMap.get(type);
17
+ if (!nodeProcessor) {
18
+ deps.onUnexpectedError(new Error(`unknown offline node type: ${type}`), 'processing offline node');
19
+ continue;
20
+ }
21
+ await nodeProcessor(node).catch(err => deps.onUnexpectedError(err, `processing offline ${type}`));
22
+ processedInBatch++;
23
+
24
+ if (processedInBatch >= batchSize) {
25
+ processedInBatch = 0;
26
+ await deps.yieldToEventLoop();
27
+ }
28
+ }
29
+ isProcessing = false;
30
+ };
31
+ promise().catch(error => deps.onUnexpectedError(error, 'processing offline nodes'));
32
+ };
33
+ return { enqueue };
34
+ }
@@ -0,0 +1,3 @@
1
+ export declare function loadSharp(): Promise<any>
2
+ export declare function loadFfmpeg(): Promise<any>
3
+ export declare function hasOptionalMedia(name: 'sharp' | 'fluent-ffmpeg'): Promise<boolean>
@@ -0,0 +1,46 @@
1
+ /* Elaina Baileys maintained distribution. Upstream notices and license are preserved in LICENSE and NOTICE.md. */
2
+ const cache = new Map()
3
+
4
+ const MESSAGES = {
5
+ sharp: 'sharp is an optional dependency. Install it with: npm i sharp',
6
+ 'fluent-ffmpeg': 'fluent-ffmpeg is an optional dependency. Install it with: npm i fluent-ffmpeg'
7
+ }
8
+
9
+ const isMissingModule = (error, name) => {
10
+ const code = error?.code
11
+ if (code !== 'ERR_MODULE_NOT_FOUND' && code !== 'MODULE_NOT_FOUND') {
12
+ return false
13
+ }
14
+ const message = String(error?.message ?? '')
15
+ return message.includes(`'${name}'`) || message.includes(`"${name}"`)
16
+ }
17
+
18
+ const loadOptional = (name) => {
19
+ if (!cache.has(name)) {
20
+ cache.set(name, import(name).then(
21
+ loaded => loaded?.default ?? loaded,
22
+ error => {
23
+ cache.delete(name)
24
+ if (isMissingModule(error, name)) {
25
+ throw new Error(MESSAGES[name] ?? `${name} is an optional dependency. Install it with: npm i ${name}`)
26
+ }
27
+ throw error
28
+ }
29
+ ))
30
+ }
31
+ return cache.get(name)
32
+ }
33
+
34
+ export const loadSharp = () => loadOptional('sharp')
35
+
36
+ export const loadFfmpeg = () => loadOptional('fluent-ffmpeg')
37
+
38
+ export const hasOptionalMedia = async (name) => {
39
+ try {
40
+ await loadOptional(name)
41
+ return true
42
+ }
43
+ catch {
44
+ return false
45
+ }
46
+ }
@@ -0,0 +1,66 @@
1
+ import type { proto } from '../../WAProto/index.js';
2
+
3
+ export declare const SplitPaymentStatus: Readonly<{ PENDING: 0; PAID: 1 }>;
4
+ export declare const ReminderFrequency: Readonly<Record<string, number>>;
5
+ export declare const ReminderStatus: Readonly<Record<string, number>>;
6
+ export declare const MONEY_OFFSET: 1000;
7
+
8
+ /** Takes the human amount; the wire value is amount * offset. */
9
+ export declare function money(amount: number, currencyCode: string, offset?: number): proto.IMoney;
10
+ export declare function readMoney(value?: proto.IMoney | null): { amount: number; currencyCode?: string } | undefined;
11
+
12
+ export interface SplitPaymentParticipantOptions {
13
+ jid: string;
14
+ amount?: number;
15
+ currency?: string;
16
+ status?: number;
17
+ }
18
+
19
+ export declare function buildSplitPayment(options: {
20
+ splitId: string | number;
21
+ total?: number;
22
+ currency?: string;
23
+ description?: string;
24
+ requesterJid?: string;
25
+ participants: SplitPaymentParticipantOptions[];
26
+ createdAt?: number;
27
+ }): proto.Message.ISplitPaymentMessage;
28
+
29
+ export declare function buildSplitPaymentUpdate(options: {
30
+ splitId: string | number;
31
+ participantJid: string;
32
+ }): proto.Message.ISplitPaymentUpdateMessage;
33
+
34
+ export declare function buildPaymentReminder(options: {
35
+ reminderId: string | number;
36
+ instanceId?: string | number;
37
+ description?: string;
38
+ frequency?: number;
39
+ status?: number;
40
+ amount?: number;
41
+ currency?: string;
42
+ payeeVpa?: string;
43
+ payeeJid?: string;
44
+ payerJid?: string;
45
+ }): proto.Message.IPaymentReminderMessage;
46
+
47
+ export declare function readSplitPayment(msg: any): {
48
+ splitId?: string;
49
+ total?: { amount: number; currencyCode?: string };
50
+ description?: string;
51
+ requesterJid?: string;
52
+ createdAtMs?: number;
53
+ participants: { jid?: string; amount?: { amount: number; currencyCode?: string }; status?: number }[];
54
+ } | null;
55
+
56
+ export declare function readPaymentReminder(msg: any): {
57
+ reminderId?: string;
58
+ instanceId?: string;
59
+ description?: string;
60
+ frequency?: number;
61
+ status?: number;
62
+ amount?: { amount: number; currencyCode?: string };
63
+ payeeVpa?: string;
64
+ payeeJid?: string;
65
+ payerJid?: string;
66
+ } | null;
@@ -0,0 +1,161 @@
1
+ /* Elaina Baileys maintained distribution. Upstream notices and license are preserved in LICENSE and NOTICE.md. */
2
+
3
+ export const SplitPaymentStatus = Object.freeze({ PENDING: 0, PAID: 1 })
4
+
5
+ export const ReminderFrequency = Object.freeze({
6
+ REMINDER_FREQUENCY_UNKNOWN: 0,
7
+ WEEKLY: 1,
8
+ BI_WEEKLY: 2,
9
+ MONTHLY: 3,
10
+ QUARTERLY: 4
11
+ })
12
+
13
+ export const ReminderStatus = Object.freeze({
14
+ REMINDER_STATUS_UNKNOWN: 0,
15
+ ACTIVE: 1,
16
+ CANCELLED_BY_CREATOR: 2,
17
+ STOPPED_BY_RECEIVER: 3,
18
+ EXPIRED: 4,
19
+ PAID: 5
20
+ })
21
+
22
+ export const MONEY_OFFSET = 1000
23
+
24
+ const drop = (object) => {
25
+ for (const key of Object.keys(object)) {
26
+ if (object[key] === undefined || object[key] === null) {
27
+ delete object[key]
28
+ }
29
+ }
30
+ return object
31
+ }
32
+
33
+ /**
34
+ * Money travels as an integer scaled by offset, so 50000 rupiah at the usual
35
+ * offset of 1000 goes on the wire as 50000000. Passing the scaled value by
36
+ * mistake overcharges by three orders of magnitude, so the amount here is
37
+ * always the human one.
38
+ */
39
+ export const money = (amount, currencyCode, offset = MONEY_OFFSET) => {
40
+ const value = Number(amount)
41
+ if (!Number.isFinite(value) || value < 0) {
42
+ throw new TypeError('money needs a non-negative amount')
43
+ }
44
+ if (typeof currencyCode !== 'string' || currencyCode.length !== 3) {
45
+ throw new TypeError('money needs a three letter currency code, like IDR or USD')
46
+ }
47
+ if (!Number.isInteger(offset) || offset <= 0) {
48
+ throw new TypeError('money offset must be a positive integer')
49
+ }
50
+ return { value: Math.round(value * offset), offset, currencyCode: currencyCode.toUpperCase() }
51
+ }
52
+
53
+ export const readMoney = (value) => {
54
+ if (!value?.offset) {
55
+ return undefined
56
+ }
57
+ return {
58
+ amount: Number(value.value) / Number(value.offset),
59
+ currencyCode: value.currencyCode
60
+ }
61
+ }
62
+
63
+ export const buildSplitPayment = ({ splitId, total, currency, description, requesterJid, participants = [], createdAt } = {}) => {
64
+ if (!splitId) {
65
+ throw new TypeError('buildSplitPayment needs a splitId, the update message is keyed on it')
66
+ }
67
+ if (!participants.length) {
68
+ throw new TypeError('buildSplitPayment needs at least one participant')
69
+ }
70
+ return drop({
71
+ splitId: String(splitId),
72
+ totalAmount: total === undefined ? undefined : money(total, currency),
73
+ description,
74
+ requesterJid,
75
+ participants: participants.map((participant, index) => {
76
+ if (!participant?.jid) {
77
+ throw new TypeError(`participant ${index} needs a jid`)
78
+ }
79
+ return drop({
80
+ jid: participant.jid,
81
+ amount: participant.amount === undefined ? undefined : money(participant.amount, participant.currency ?? currency),
82
+ status: participant.status ?? SplitPaymentStatus.PENDING
83
+ })
84
+ }),
85
+ createdAtMs: createdAt === undefined ? Date.now() : Number(createdAt)
86
+ })
87
+ }
88
+
89
+ export const buildSplitPaymentUpdate = ({ splitId, participantJid } = {}) => {
90
+ if (!splitId || !participantJid) {
91
+ throw new TypeError('buildSplitPaymentUpdate needs both splitId and participantJid')
92
+ }
93
+ return { splitId: String(splitId), participantJid }
94
+ }
95
+
96
+ export const buildPaymentReminder = ({
97
+ reminderId,
98
+ instanceId,
99
+ description,
100
+ frequency = ReminderFrequency.MONTHLY,
101
+ status = ReminderStatus.ACTIVE,
102
+ amount,
103
+ currency,
104
+ payeeVpa,
105
+ payeeJid,
106
+ payerJid
107
+ } = {}) => {
108
+ if (!reminderId) {
109
+ throw new TypeError('buildPaymentReminder needs a reminderId')
110
+ }
111
+ return drop({
112
+ reminderId: String(reminderId),
113
+ instanceId: instanceId === undefined ? undefined : String(instanceId),
114
+ description,
115
+ frequency,
116
+ status,
117
+ amount: amount === undefined ? undefined : money(amount, currency),
118
+ payeeVpa,
119
+ payeeJid,
120
+ payerJid
121
+ })
122
+ }
123
+
124
+ export const readSplitPayment = (msg) => {
125
+ const message = msg?.message ?? msg
126
+ const split = message?.splitPaymentMessage
127
+ if (!split) {
128
+ return null
129
+ }
130
+ return drop({
131
+ splitId: split.splitId,
132
+ total: readMoney(split.totalAmount),
133
+ description: split.description,
134
+ requesterJid: split.requesterJid,
135
+ createdAtMs: split.createdAtMs === undefined ? undefined : Number(split.createdAtMs),
136
+ participants: (split.participants ?? []).map(participant => drop({
137
+ jid: participant.jid,
138
+ amount: readMoney(participant.amount),
139
+ status: participant.status
140
+ }))
141
+ })
142
+ }
143
+
144
+ export const readPaymentReminder = (msg) => {
145
+ const message = msg?.message ?? msg
146
+ const reminder = message?.paymentReminderMessage
147
+ if (!reminder) {
148
+ return null
149
+ }
150
+ return drop({
151
+ reminderId: reminder.reminderId,
152
+ instanceId: reminder.instanceId,
153
+ description: reminder.description,
154
+ frequency: reminder.frequency,
155
+ status: reminder.status,
156
+ amount: readMoney(reminder.amount),
157
+ payeeVpa: reminder.payeeVpa,
158
+ payeeJid: reminder.payeeJid,
159
+ payerJid: reminder.payerJid
160
+ })
161
+ }
@@ -0,0 +1,26 @@
1
+ /* Elaina Baileys maintained distribution. Upstream notices and license are preserved in LICENSE and NOTICE.md. */
2
+ /**
3
+ * Manages pre-key operations with proper concurrency control
4
+ */
5
+ export class PreKeyManager {
6
+ constructor(store: any, logger: any);
7
+ store: any;
8
+ logger: any;
9
+ queues: Map<any, any>;
10
+ /**
11
+ * Get or create a queue for a specific key type
12
+ */
13
+ getQueue(keyType: any): any;
14
+ /**
15
+ * Process pre-key operations (updates and deletions)
16
+ */
17
+ processOperations(data: any, keyType: any, transactionCache: any, mutations: any, isInTransaction: any): Promise<any>;
18
+ /**
19
+ * Process deletions with validation
20
+ */
21
+ processDeletions(keyType: any, ids: any, transactionCache: any, mutations: any, isInTransaction: any): Promise<void>;
22
+ /**
23
+ * Validate and process pre-key deletions outside transactions
24
+ */
25
+ validateDeletions(data: any, keyType: any): Promise<any>;
26
+ }
@@ -0,0 +1,96 @@
1
+ /* Elaina Baileys maintained distribution. Upstream notices and license are preserved in LICENSE and NOTICE.md. */
2
+ import PQueue from 'p-queue';
3
+
4
+ export class PreKeyManager {
5
+ constructor(store, logger) {
6
+ this.store = store;
7
+ this.logger = logger;
8
+ this.queues = new Map();
9
+ }
10
+
11
+ getQueue(keyType) {
12
+ if (!this.queues.has(keyType)) {
13
+ this.queues.set(keyType, new PQueue({ concurrency: 1 }));
14
+ }
15
+ return this.queues.get(keyType);
16
+ }
17
+
18
+ async processOperations(data, keyType, transactionCache, mutations, isInTransaction) {
19
+ const keyData = data[keyType];
20
+ if (!keyData)
21
+ return;
22
+ return this.getQueue(keyType).add(async () => {
23
+
24
+ transactionCache[keyType] = transactionCache[keyType] || {};
25
+ mutations[keyType] = mutations[keyType] || {};
26
+
27
+ const deletions = [];
28
+ const updates = {};
29
+ for (const keyId in keyData) {
30
+ if (keyData[keyId] === null) {
31
+ deletions.push(keyId);
32
+ }
33
+ else {
34
+ updates[keyId] = keyData[keyId];
35
+ }
36
+ }
37
+
38
+ if (Object.keys(updates).length > 0) {
39
+ Object.assign(transactionCache[keyType], updates);
40
+ Object.assign(mutations[keyType], updates);
41
+ }
42
+
43
+ if (deletions.length > 0) {
44
+ await this.processDeletions(keyType, deletions, transactionCache, mutations, isInTransaction);
45
+ }
46
+ });
47
+ }
48
+
49
+ async processDeletions(keyType, ids, transactionCache, mutations, isInTransaction) {
50
+ if (isInTransaction) {
51
+
52
+ for (const keyId of ids) {
53
+ if (transactionCache[keyType]?.[keyId]) {
54
+ transactionCache[keyType][keyId] = null;
55
+ mutations[keyType][keyId] = null;
56
+ }
57
+ else {
58
+ this.logger.warn(`Skipping deletion of non-existent ${keyType} in transaction: ${keyId}`);
59
+ }
60
+ }
61
+ }
62
+ else {
63
+
64
+ const existingKeys = await this.store.get(keyType, ids);
65
+ for (const keyId of ids) {
66
+ if (existingKeys[keyId]) {
67
+ transactionCache[keyType][keyId] = null;
68
+ mutations[keyType][keyId] = null;
69
+ }
70
+ else {
71
+ this.logger.warn(`Skipping deletion of non-existent ${keyType}: ${keyId}`);
72
+ }
73
+ }
74
+ }
75
+ }
76
+
77
+ async validateDeletions(data, keyType) {
78
+ const keyData = data[keyType];
79
+ if (!keyData)
80
+ return;
81
+ return this.getQueue(keyType).add(async () => {
82
+
83
+ const deletionIds = Object.keys(keyData).filter(id => keyData[id] === null);
84
+ if (deletionIds.length === 0)
85
+ return;
86
+
87
+ const existingKeys = await this.store.get(keyType, deletionIds);
88
+ for (const keyId of deletionIds) {
89
+ if (!existingKeys[keyId]) {
90
+ this.logger.warn(`Skipping deletion of non-existent ${keyType}: ${keyId}`);
91
+ delete data[keyType][keyId];
92
+ }
93
+ }
94
+ });
95
+ }
96
+ }