@nerxa/socketon 0.0.0-stage → 1.21.0

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 (289) hide show
  1. package/EXPERIMENTAL.md +350 -0
  2. package/LICENSE +24 -0
  3. package/README.md +6317 -2
  4. package/WAProto/index.d.ts +17301 -0
  5. package/WAProto/index.js +125088 -0
  6. package/engine-requirements.js +14 -0
  7. package/package.json +100 -4
  8. package/src/Defaults/index.d.ts +152 -0
  9. package/src/Defaults/index.js +164 -0
  10. package/src/MessageBuilder/bot-signature.d.ts +22 -0
  11. package/src/MessageBuilder/bot-signature.js +122 -0
  12. package/src/MessageBuilder/extras.d.ts +449 -0
  13. package/src/MessageBuilder/extras.js +1356 -0
  14. package/src/MessageBuilder/index.d.ts +210 -0
  15. package/src/MessageBuilder/index.js +3594 -0
  16. package/src/MessageBuilder/metaai.d.ts +438 -0
  17. package/src/MessageBuilder/metaai.js +890 -0
  18. package/src/Signal/Group/ciphertext-message.d.ts +9 -0
  19. package/src/Signal/Group/ciphertext-message.js +11 -0
  20. package/src/Signal/Group/group-session-builder.d.ts +7 -0
  21. package/src/Signal/Group/group-session-builder.js +27 -0
  22. package/src/Signal/Group/group_cipher.d.ts +11 -0
  23. package/src/Signal/Group/group_cipher.js +78 -0
  24. package/src/Signal/Group/index.d.ts +11 -0
  25. package/src/Signal/Group/index.js +11 -0
  26. package/src/Signal/Group/keyhelper.d.ts +6 -0
  27. package/src/Signal/Group/keyhelper.js +17 -0
  28. package/src/Signal/Group/sender-chain-key.d.ts +13 -0
  29. package/src/Signal/Group/sender-chain-key.js +25 -0
  30. package/src/Signal/Group/sender-key-distribution-message.d.ts +16 -0
  31. package/src/Signal/Group/sender-key-distribution-message.js +62 -0
  32. package/src/Signal/Group/sender-key-message.d.ts +18 -0
  33. package/src/Signal/Group/sender-key-message.js +65 -0
  34. package/src/Signal/Group/sender-key-name.d.ts +11 -0
  35. package/src/Signal/Group/sender-key-name.js +47 -0
  36. package/src/Signal/Group/sender-key-record.d.ts +12 -0
  37. package/src/Signal/Group/sender-key-record.js +40 -0
  38. package/src/Signal/Group/sender-key-state.d.ts +16 -0
  39. package/src/Signal/Group/sender-key-state.js +83 -0
  40. package/src/Signal/Group/sender-message-key.d.ts +11 -0
  41. package/src/Signal/Group/sender-message-key.js +25 -0
  42. package/src/Signal/libsignal.d.ts +54 -0
  43. package/src/Signal/libsignal.js +427 -0
  44. package/src/Signal/lid-mapping.d.ts +20 -0
  45. package/src/Signal/lid-mapping.js +274 -0
  46. package/src/Socket/Client/index.d.ts +2 -0
  47. package/src/Socket/Client/index.js +3 -0
  48. package/src/Socket/Client/tcp.js +177 -0
  49. package/src/Socket/Client/types.d.ts +5 -0
  50. package/src/Socket/Client/types.js +9 -0
  51. package/src/Socket/Client/websocket.d.ts +12 -0
  52. package/src/Socket/Client/websocket.js +53 -0
  53. package/src/Socket/business.d.ts +431 -0
  54. package/src/Socket/business.js +379 -0
  55. package/src/Socket/chats.d.ts +247 -0
  56. package/src/Socket/chats.js +1484 -0
  57. package/src/Socket/communities.d.ts +598 -0
  58. package/src/Socket/communities.js +421 -0
  59. package/src/Socket/email.js +145 -0
  60. package/src/Socket/groups.d.ts +298 -0
  61. package/src/Socket/groups.js +339 -0
  62. package/src/Socket/index.d.ts +581 -0
  63. package/src/Socket/index.js +37 -0
  64. package/src/Socket/messages-recv.d.ts +370 -0
  65. package/src/Socket/messages-recv.js +1864 -0
  66. package/src/Socket/messages-send.d.ts +390 -0
  67. package/src/Socket/messages-send.js +1574 -0
  68. package/src/Socket/mex.d.ts +1 -0
  69. package/src/Socket/mex.js +44 -0
  70. package/src/Socket/mobile-builders.js +72 -0
  71. package/src/Socket/mobile.js +424 -0
  72. package/src/Socket/newsletter.d.ts +468 -0
  73. package/src/Socket/newsletter.js +671 -0
  74. package/src/Socket/socket.d.ts +77 -0
  75. package/src/Socket/socket.js +1106 -0
  76. package/src/Store/index.d.ts +3 -0
  77. package/src/Store/index.js +3 -0
  78. package/src/Store/make-in-memory-store.d.ts +62 -0
  79. package/src/Store/make-in-memory-store.js +396 -0
  80. package/src/Store/make-ordered-dictionary.d.ts +12 -0
  81. package/src/Store/make-ordered-dictionary.js +78 -0
  82. package/src/Store/object-repository.d.ts +10 -0
  83. package/src/Store/object-repository.js +23 -0
  84. package/src/Types/Auth.d.ts +1 -0
  85. package/src/Types/Auth.js +1 -0
  86. package/src/Types/Bussines.d.ts +1 -0
  87. package/src/Types/Bussines.js +1 -0
  88. package/src/Types/Call.d.ts +1 -0
  89. package/src/Types/Call.js +1 -0
  90. package/src/Types/Chat.d.ts +2 -0
  91. package/src/Types/Chat.js +24 -0
  92. package/src/Types/Contact.d.ts +1 -0
  93. package/src/Types/Contact.js +1 -0
  94. package/src/Types/Events.d.ts +1 -0
  95. package/src/Types/Events.js +0 -0
  96. package/src/Types/GroupMetadata.d.ts +5 -0
  97. package/src/Types/GroupMetadata.js +6 -0
  98. package/src/Types/Label.d.ts +2 -0
  99. package/src/Types/Label.js +24 -0
  100. package/src/Types/LabelAssociation.d.ts +2 -0
  101. package/src/Types/LabelAssociation.js +6 -0
  102. package/src/Types/Message.d.ts +13 -0
  103. package/src/Types/Message.js +23 -0
  104. package/src/Types/Mex.d.ts +2 -0
  105. package/src/Types/Mex.js +95 -0
  106. package/src/Types/Product.d.ts +1 -0
  107. package/src/Types/Product.js +1 -0
  108. package/src/Types/Signal.d.ts +1 -0
  109. package/src/Types/Signal.js +0 -0
  110. package/src/Types/Socket.d.ts +1 -0
  111. package/src/Types/Socket.js +0 -0
  112. package/src/Types/State.d.ts +5 -0
  113. package/src/Types/State.js +54 -0
  114. package/src/Types/USync.d.ts +1 -0
  115. package/src/Types/USync.js +0 -0
  116. package/src/Types/index.d.ts +13 -0
  117. package/src/Types/index.js +25 -0
  118. package/src/Utils/auth-store.d.ts +29 -0
  119. package/src/Utils/auth-store.js +76 -0
  120. package/src/Utils/auth-utils.d.ts +58 -0
  121. package/src/Utils/auth-utils.js +273 -0
  122. package/src/Utils/browser-utils.d.ts +9 -0
  123. package/src/Utils/browser-utils.js +28 -0
  124. package/src/Utils/business.d.ts +49 -0
  125. package/src/Utils/business.js +226 -0
  126. package/src/Utils/chat-utils.d.ts +408 -0
  127. package/src/Utils/chat-utils.js +846 -0
  128. package/src/Utils/companion-reg-client-utils.d.ts +4 -0
  129. package/src/Utils/companion-reg-client-utils.js +39 -0
  130. package/src/Utils/crypto.d.ts +39 -0
  131. package/src/Utils/crypto.js +110 -0
  132. package/src/Utils/decode-wa-message.d.ts +99 -0
  133. package/src/Utils/decode-wa-message.js +373 -0
  134. package/src/Utils/event-buffer.d.ts +22 -0
  135. package/src/Utils/event-buffer.js +624 -0
  136. package/src/Utils/generics.d.ts +63 -0
  137. package/src/Utils/generics.js +375 -0
  138. package/src/Utils/group-metadata-cache.d.ts +4 -0
  139. package/src/Utils/group-metadata-cache.js +25 -0
  140. package/src/Utils/history.d.ts +75 -0
  141. package/src/Utils/history.js +131 -0
  142. package/src/Utils/html-app.d.ts +19 -0
  143. package/src/Utils/html-app.js +96 -0
  144. package/src/Utils/html-multiplayer.d.ts +10 -0
  145. package/src/Utils/html-multiplayer.js +94 -0
  146. package/src/Utils/identity-change-handler.d.ts +13 -0
  147. package/src/Utils/identity-change-handler.js +48 -0
  148. package/src/Utils/index.d.ts +44 -0
  149. package/src/Utils/index.js +44 -0
  150. package/src/Utils/link-preview-metadata.d.ts +47 -0
  151. package/src/Utils/link-preview-metadata.js +88 -0
  152. package/src/Utils/link-preview.d.ts +12 -0
  153. package/src/Utils/link-preview.js +79 -0
  154. package/src/Utils/logger.d.ts +2 -0
  155. package/src/Utils/logger.js +2 -0
  156. package/src/Utils/lt-hash.d.ts +6 -0
  157. package/src/Utils/lt-hash.js +3 -0
  158. package/src/Utils/make-mutex.d.ts +6 -0
  159. package/src/Utils/make-mutex.js +32 -0
  160. package/src/Utils/message-retry-manager.d.ts +79 -0
  161. package/src/Utils/message-retry-manager.js +255 -0
  162. package/src/Utils/messages-media.d.ts +136 -0
  163. package/src/Utils/messages-media.js +814 -0
  164. package/src/Utils/messages.d.ts +62 -0
  165. package/src/Utils/messages.js +2223 -0
  166. package/src/Utils/mobile-companion-crypto.js +191 -0
  167. package/src/Utils/modern-messages.d.ts +150 -0
  168. package/src/Utils/modern-messages.js +496 -0
  169. package/src/Utils/native-flow.d.ts +11 -0
  170. package/src/Utils/native-flow.js +115 -0
  171. package/src/Utils/newsletter-status.d.ts +158 -0
  172. package/src/Utils/newsletter-status.js +651 -0
  173. package/src/Utils/noise-handler.d.ts +20 -0
  174. package/src/Utils/noise-handler.js +200 -0
  175. package/src/Utils/offline-node-processor.d.ts +9 -0
  176. package/src/Utils/offline-node-processor.js +33 -0
  177. package/src/Utils/optional-media.d.ts +3 -0
  178. package/src/Utils/optional-media.js +45 -0
  179. package/src/Utils/payment-messages.d.ts +66 -0
  180. package/src/Utils/payment-messages.js +160 -0
  181. package/src/Utils/pre-key-manager.d.ts +25 -0
  182. package/src/Utils/pre-key-manager.js +95 -0
  183. package/src/Utils/process-message.d.ts +60 -0
  184. package/src/Utils/process-message.js +688 -0
  185. package/src/Utils/reporting-utils.d.ts +12 -0
  186. package/src/Utils/reporting-utils.js +256 -0
  187. package/src/Utils/scheduled-message.d.ts +51 -0
  188. package/src/Utils/scheduled-message.js +112 -0
  189. package/src/Utils/sender-key-memory.d.ts +19 -0
  190. package/src/Utils/sender-key-memory.js +51 -0
  191. package/src/Utils/signal.d.ts +82 -0
  192. package/src/Utils/signal.js +193 -0
  193. package/src/Utils/stanza-ack.d.ts +16 -0
  194. package/src/Utils/stanza-ack.js +30 -0
  195. package/src/Utils/status-stickers.d.ts +127 -0
  196. package/src/Utils/status-stickers.js +260 -0
  197. package/src/Utils/sync-action-utils.d.ts +2 -0
  198. package/src/Utils/sync-action-utils.js +44 -0
  199. package/src/Utils/tc-token-utils.d.ts +29 -0
  200. package/src/Utils/tc-token-utils.js +155 -0
  201. package/src/Utils/ttl-cache.d.ts +28 -0
  202. package/src/Utils/ttl-cache.js +120 -0
  203. package/src/Utils/use-mongo-auth-state.d.ts +21 -0
  204. package/src/Utils/use-mongo-auth-state.js +67 -0
  205. package/src/Utils/use-multi-file-auth-state.d.ts +11 -0
  206. package/src/Utils/use-multi-file-auth-state.js +106 -0
  207. package/src/Utils/use-mysql-auth-state.d.ts +19 -0
  208. package/src/Utils/use-mysql-auth-state.js +79 -0
  209. package/src/Utils/use-postgres-auth-state.d.ts +19 -0
  210. package/src/Utils/use-postgres-auth-state.js +79 -0
  211. package/src/Utils/use-redis-auth-state.d.ts +19 -0
  212. package/src/Utils/use-redis-auth-state.js +89 -0
  213. package/src/Utils/use-single-file-auth-state.d.ts +10 -0
  214. package/src/Utils/use-single-file-auth-state.js +108 -0
  215. package/src/Utils/use-sqlite-auth-state.d.ts +12 -0
  216. package/src/Utils/use-sqlite-auth-state.js +120 -0
  217. package/src/Utils/useNekoDBAuth.d.ts +19 -0
  218. package/src/Utils/useNekoDBAuth.js +111 -0
  219. package/src/Utils/username.d.ts +12 -0
  220. package/src/Utils/username.js +58 -0
  221. package/src/Utils/validate-connection.d.ts +43 -0
  222. package/src/Utils/validate-connection.js +277 -0
  223. package/src/Utils/voice-recognition.d.ts +53 -0
  224. package/src/Utils/voice-recognition.js +219 -0
  225. package/src/Voip/audio-feeder.d.ts +24 -0
  226. package/src/Voip/audio-feeder.js +268 -0
  227. package/src/Voip/index.d.ts +88 -0
  228. package/src/Voip/index.js +936 -0
  229. package/src/Voip/relay-transport.d.ts +5 -0
  230. package/src/Voip/relay-transport.js +824 -0
  231. package/src/Voip/signaling.d.ts +11 -0
  232. package/src/Voip/signaling.js +1099 -0
  233. package/src/Voip/types.d.ts +2 -0
  234. package/src/Voip/types.js +12 -0
  235. package/src/Voip/video-feeder.d.ts +24 -0
  236. package/src/Voip/video-feeder.js +268 -0
  237. package/src/Voip/wasm-engine.d.ts +26 -0
  238. package/src/Voip/wasm-engine.js +1307 -0
  239. package/src/Voip/worker-bootstrap.js +1023 -0
  240. package/src/WABinary/constants.d.ts +22 -0
  241. package/src/WABinary/constants.js +1300 -0
  242. package/src/WABinary/decode.d.ts +9 -0
  243. package/src/WABinary/decode.js +261 -0
  244. package/src/WABinary/encode.d.ts +2 -0
  245. package/src/WABinary/encode.js +219 -0
  246. package/src/WABinary/generic-utils.d.ts +76 -0
  247. package/src/WABinary/generic-utils.js +214 -0
  248. package/src/WABinary/index.d.ts +5 -0
  249. package/src/WABinary/index.js +5 -0
  250. package/src/WABinary/jid-utils.d.ts +30 -0
  251. package/src/WABinary/jid-utils.js +97 -0
  252. package/src/WABinary/types.d.ts +1 -0
  253. package/src/WABinary/types.js +0 -0
  254. package/src/WAM/BinaryInfo.d.ts +7 -0
  255. package/src/WAM/BinaryInfo.js +9 -0
  256. package/src/WAM/constants.d.ts +34926 -0
  257. package/src/WAM/constants.js +22852 -0
  258. package/src/WAM/encode.d.ts +1 -0
  259. package/src/WAM/encode.js +148 -0
  260. package/src/WAM/index.d.ts +3 -0
  261. package/src/WAM/index.js +3 -0
  262. package/src/WAUSync/Protocols/USyncContactProtocol.d.ts +36 -0
  263. package/src/WAUSync/Protocols/USyncContactProtocol.js +50 -0
  264. package/src/WAUSync/Protocols/USyncDeviceProtocol.d.ts +22 -0
  265. package/src/WAUSync/Protocols/USyncDeviceProtocol.js +51 -0
  266. package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
  267. package/src/WAUSync/Protocols/USyncDisappearingModeProtocol.js +26 -0
  268. package/src/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
  269. package/src/WAUSync/Protocols/USyncStatusProtocol.js +37 -0
  270. package/src/WAUSync/Protocols/USyncUsernameProtocol.d.ts +9 -0
  271. package/src/WAUSync/Protocols/USyncUsernameProtocol.js +23 -0
  272. package/src/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +38 -0
  273. package/src/WAUSync/Protocols/UsyncBotProfileProtocol.js +49 -0
  274. package/src/WAUSync/Protocols/UsyncLIDProtocol.d.ts +14 -0
  275. package/src/WAUSync/Protocols/UsyncLIDProtocol.js +28 -0
  276. package/src/WAUSync/Protocols/index.d.ts +5 -0
  277. package/src/WAUSync/Protocols/index.js +5 -0
  278. package/src/WAUSync/USyncQuery.d.ts +20 -0
  279. package/src/WAUSync/USyncQuery.js +93 -0
  280. package/src/WAUSync/USyncUser.d.ts +16 -0
  281. package/src/WAUSync/USyncUser.js +30 -0
  282. package/src/WAUSync/index.d.ts +3 -0
  283. package/src/WAUSync/index.js +3 -0
  284. package/src/assets/wasm/README.md +76 -0
  285. package/src/assets/wasm/loader.js +5 -0
  286. package/src/assets/wasm/whatsapp.wasm +0 -0
  287. package/src/assets/wasm/worker-modules.js +273 -0
  288. package/src/index.d.ts +43 -0
  289. package/src/index.js +48 -0
@@ -0,0 +1,96 @@
1
+
2
+ export const HTML_APP_MESSAGE_CEILING = 1024 * 1024;
3
+
4
+ export const HTML_APP_BYTE_BUDGET = 960 * 1024;
5
+
6
+ export const HTML_APP_BYTE_LIMIT = HTML_APP_BYTE_BUDGET;
7
+
8
+ export const wireBytes = (html) => Buffer.byteLength(
9
+ JSON.stringify(String(html)).replace(/[\u007f-\uffff]/g, (c) => '\\u' + c.charCodeAt(0).toString(16).padStart(4, '0')),
10
+ 'utf-8'
11
+ );
12
+
13
+ const STORAGE_APIS = ['localStorage', 'sessionStorage', 'indexedDB', 'document.cookie', 'caches'];
14
+
15
+ const strip = (html) => html
16
+ .replace(/<!--[\s\S]*?-->/g, '')
17
+ .replace(/data:[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]*;base64,[A-Za-z0-9+/=]+/gi, 'data:');
18
+
19
+ const hasVisibilityGuard = (source) => /document\.(hidden|visibilityState)|visibilitychange|IntersectionObserver|cancelAnimationFrame|clearInterval/.test(source);
20
+
21
+ export const checkHtmlApp = (html, { height, maxBytes = HTML_APP_BYTE_BUDGET } = {}) => {
22
+ if (typeof html !== 'string') {
23
+ throw new TypeError('checkHtmlApp requires an HTML string');
24
+ }
25
+
26
+ const bytes = Buffer.byteLength(html, 'utf-8');
27
+ const wire = wireBytes(html);
28
+ const source = strip(html);
29
+ const problems = [];
30
+ const warnings = [];
31
+
32
+ if (wire > maxBytes) {
33
+ problems.push(`${Math.round(wire / 1024)}KB on the wire, over the ${Math.round(maxBytes / 1024)}KB budget — a message past ${Math.round(HTML_APP_MESSAGE_CEILING / 1024)}KB is dropped by the receiving client, which logs it and renders nothing, so this one would arrive as silence`);
34
+ }
35
+
36
+ if (wire > bytes * 1.15) {
37
+ warnings.push(`escaping inflates this page from ${Math.round(bytes / 1024)}KB to ${Math.round(wire / 1024)}KB — every non-ASCII character is rewritten as \\uXXXX, so emoji and accents cost up to three times their size`);
38
+ }
39
+
40
+ const remote = [...source.matchAll(/\b(?:src|href)\s*=\s*["']?(https?:)?\/\//gi)];
41
+ if (remote.length) {
42
+ problems.push(`${remote.length} remote subresource${remote.length === 1 ? '' : 's'} — the page runs in an opaque origin with no network, so every one of them fails silently; embed as data: URIs instead`);
43
+ }
44
+
45
+ if (/\bfetch\s*\(|XMLHttpRequest|navigator\.sendBeacon|new\s+EventSource/.test(source)) {
46
+ problems.push('a call over the HTTP stack — fetch, XHR, sendBeacon and EventSource were measured dead in this WebView, and no securitypolicyviolation fires to tell the page why');
47
+ }
48
+
49
+ const socket = /new\s+WebSocket/.test(source);
50
+ const peer = /RTCPeerConnection/.test(source);
51
+ if (socket && !/wss:\/\//.test(source)) {
52
+ problems.push('a WebSocket on something other than wss:// — the page is not a secure context, and a cleartext ws:// endpoint sends the room and every move in the open');
53
+ }
54
+ if ((socket || peer) && !hasVisibilityGuard(source)) {
55
+ warnings.push('a live connection with nothing closing it — the bubble outlives the screen, so close or pause the socket on visibilitychange');
56
+ }
57
+
58
+ const storage = STORAGE_APIS.filter(api => source.includes(api));
59
+ if (storage.length) {
60
+ problems.push(`${storage.join(', ')} — every storage API throws SecurityError in an opaque origin, so the catch branch always runs`);
61
+ }
62
+
63
+ if (/crypto\.subtle/.test(source)) {
64
+ problems.push('crypto.subtle needs a secure context and this page is not one');
65
+ }
66
+
67
+ const rafLoop = /requestAnimationFrame/.test(source);
68
+ const interval = /setInterval\s*\(/.test(source);
69
+ if ((rafLoop || interval) && !hasVisibilityGuard(source)) {
70
+ problems.push('an animation or timer loop with nothing to stop it — the bubble stays alive while the chat scrolls, so it keeps burning CPU and battery off-screen; gate it on document.hidden or an IntersectionObserver');
71
+ }
72
+
73
+ const reportsHeight = /AndroidBridge\s*\.\s*updateSize/.test(source);
74
+ if (height === undefined && !reportsHeight) {
75
+ const pinned = /(?:html|body)[^{}]*\{[^{}]*height\s*:\s*\d/i.test(source);
76
+ if (!pinned) {
77
+ warnings.push('no height settled — pass height or autoHeight to sendHtmlApp, or call AndroidBridge.updateSize yourself, or the host and the page measure each other and the card shudders');
78
+ }
79
+ }
80
+
81
+ if (/aspect-ratio\s*:/i.test(source)) {
82
+ warnings.push('aspect-ratio makes the height depend on the width, which is the layout chase the host cannot settle');
83
+ }
84
+
85
+ if (/<canvas[^>]*style\s*=\s*["'][^"']*height\s*:\s*auto/i.test(source)) {
86
+ warnings.push('a canvas at height:auto resizes with the bubble; give it pixel dimensions');
87
+ }
88
+
89
+ const dataUris = [...html.matchAll(/data:[a-z0-9!#$&^_.+-]+\/[a-z0-9!#$&^_.+-]*;base64,([A-Za-z0-9+/=]+)/gi)];
90
+ const embedded = dataUris.reduce((total, match) => total + match[1].length, 0);
91
+ if (embedded > bytes * 0.6 && dataUris.length) {
92
+ warnings.push(`${Math.round(embedded / 1024)}KB of the page is embedded media — shrink it before the byte budget forces you to`);
93
+ }
94
+
95
+ return { ok: problems.length === 0, bytes, wireBytes: wire, embeddedBytes: embedded, problems, warnings };
96
+ };
@@ -0,0 +1,10 @@
1
+ export interface HtmlMultiplayerOptions {
2
+ url: string
3
+ room: string
4
+ seat?: string | number | null
5
+ reconnectMs?: number
6
+ maxReconnectMs?: number
7
+ }
8
+
9
+ export declare function htmlMultiplayerPrelude(options: HtmlMultiplayerOptions): string
10
+ export declare function withHtmlMultiplayer(html: string, options: HtmlMultiplayerOptions): string
@@ -0,0 +1,94 @@
1
+
2
+ const escapeForScript = (value) => JSON.stringify(value).replace(/</g, '\\u003c').replace(/>/g, '\\u003e');
3
+
4
+ export const htmlMultiplayerPrelude = ({ url, room, seat, reconnectMs = 1500, maxReconnectMs = 15000 } = {}) => {
5
+ if (typeof url !== 'string' || !url.startsWith('wss://')) {
6
+ throw new TypeError('htmlMultiplayerPrelude requires a wss:// url, since the page is not a secure context');
7
+ }
8
+ if (typeof room !== 'string' || room.trim() === '') {
9
+ throw new TypeError('htmlMultiplayerPrelude requires a non-empty room id');
10
+ }
11
+
12
+ const config = escapeForScript({ url, room, seat: seat ?? null, reconnectMs, maxReconnectMs });
13
+
14
+ return `<script>
15
+ (function () {
16
+ var cfg = ${config};
17
+ var listeners = [];
18
+ var queue = [];
19
+ var sock = null;
20
+ var backoff = cfg.reconnectMs;
21
+ var closed = false;
22
+
23
+ var api = {
24
+ room: cfg.room,
25
+ seat: cfg.seat,
26
+ connected: false,
27
+ send: function (payload) {
28
+ var frame = JSON.stringify({ room: cfg.room, seat: cfg.seat, data: payload });
29
+ if (sock && sock.readyState === 1) sock.send(frame); else queue.push(frame);
30
+ },
31
+ on: function (fn) { listeners.push(fn); return function () { listeners = listeners.filter(function (f) { return f !== fn }) } },
32
+ close: function () { closed = true; if (sock) try { sock.close() } catch (e) {} }
33
+ };
34
+
35
+ function emit(kind, detail) {
36
+ for (var i = 0; i < listeners.length; i++) {
37
+ try { listeners[i](kind, detail) } catch (e) {}
38
+ }
39
+ }
40
+
41
+ function open() {
42
+ if (closed || (sock && (sock.readyState === 0 || sock.readyState === 1))) return;
43
+ try { sock = new WebSocket(cfg.url) } catch (e) { emit('error', e); return schedule() }
44
+
45
+ sock.onopen = function () {
46
+ backoff = cfg.reconnectMs;
47
+ api.connected = true;
48
+ sock.send(JSON.stringify({ join: cfg.room, seat: cfg.seat }));
49
+ while (queue.length && sock.readyState === 1) sock.send(queue.shift());
50
+ emit('open', null);
51
+ };
52
+ sock.onmessage = function (event) {
53
+ var parsed = event.data;
54
+ try { parsed = JSON.parse(event.data) } catch (e) {}
55
+ emit('message', parsed);
56
+ };
57
+ sock.onclose = function (event) {
58
+ api.connected = false;
59
+ emit('close', event.code);
60
+ schedule();
61
+ };
62
+ sock.onerror = function () { api.connected = false };
63
+ }
64
+
65
+ function schedule() {
66
+ if (closed || document.hidden) return;
67
+ setTimeout(open, backoff);
68
+ backoff = Math.min(backoff * 2, cfg.maxReconnectMs);
69
+ }
70
+
71
+ document.addEventListener('visibilitychange', function () {
72
+ if (document.hidden) {
73
+ if (sock) try { sock.close() } catch (e) {}
74
+ } else if (!closed) {
75
+ backoff = cfg.reconnectMs;
76
+ open();
77
+ }
78
+ });
79
+
80
+ window.addEventListener('pagehide', function () { api.close() });
81
+
82
+ window.room = api;
83
+ open();
84
+ })();
85
+ </script>
86
+ `;
87
+ };
88
+
89
+ export const withHtmlMultiplayer = (html, options) => {
90
+ if (typeof html !== 'string' || html.trim() === '') {
91
+ throw new TypeError('withHtmlMultiplayer requires an HTML string');
92
+ }
93
+ return htmlMultiplayerPrelude(options) + html;
94
+ };
@@ -0,0 +1,13 @@
1
+ export function handleIdentityChange(node: any, ctx: any): Promise<{
2
+ action: string;
3
+ device?: undefined;
4
+ error?: undefined;
5
+ } | {
6
+ action: string;
7
+ device: number;
8
+ error?: undefined;
9
+ } | {
10
+ action: string;
11
+ error: unknown;
12
+ device?: undefined;
13
+ }>;
@@ -0,0 +1,48 @@
1
+ import { areJidsSameUser, getBinaryNodeChild, jidDecode } from '../WABinary/index.js';
2
+ import { isStringNullOrEmpty } from './generics.js';
3
+ export async function handleIdentityChange(node, ctx) {
4
+ const from = node.attrs.from;
5
+ if (!from) {
6
+ return { action: 'invalid_notification' };
7
+ }
8
+ const identityNode = getBinaryNodeChild(node, 'identity');
9
+ if (!identityNode) {
10
+ return { action: 'no_identity_node' };
11
+ }
12
+ ctx.logger.info({ jid: from }, 'identity changed');
13
+ const decoded = jidDecode(from);
14
+ if (decoded?.device && decoded.device !== 0) {
15
+ ctx.logger.debug({ jid: from, device: decoded.device }, 'ignoring identity change from companion device');
16
+ return { action: 'skipped_companion_device', device: decoded.device };
17
+ }
18
+ const isSelfPrimary = ctx.meId && (areJidsSameUser(from, ctx.meId) || (ctx.meLid && areJidsSameUser(from, ctx.meLid)));
19
+ if (isSelfPrimary) {
20
+ ctx.logger.info({ jid: from }, 'self primary identity changed');
21
+ return { action: 'skipped_self_primary' };
22
+ }
23
+ if (ctx.debounceCache.get(from)) {
24
+ ctx.logger.debug({ jid: from }, 'skipping identity assert (debounced)');
25
+ return { action: 'debounced' };
26
+ }
27
+ ctx.debounceCache.set(from, true);
28
+ const isOfflineNotification = !isStringNullOrEmpty(node.attrs.offline);
29
+ const hasExistingSession = await ctx.validateSession(from);
30
+ if (!hasExistingSession.exists) {
31
+ ctx.logger.debug({ jid: from }, 'no old session, skipping session refresh');
32
+ return { action: 'skipped_no_session' };
33
+ }
34
+ ctx.logger.debug({ jid: from }, 'old session exists, will refresh session');
35
+ if (isOfflineNotification) {
36
+ ctx.logger.debug({ jid: from }, 'skipping session refresh during offline processing');
37
+ return { action: 'skipped_offline' };
38
+ }
39
+ ctx.onBeforeSessionRefresh?.(from);
40
+ try {
41
+ await ctx.assertSessions([from], true);
42
+ return { action: 'session_refreshed' };
43
+ }
44
+ catch (error) {
45
+ ctx.logger.warn({ error, jid: from }, 'failed to assert sessions after identity change');
46
+ return { action: 'session_refresh_failed', error };
47
+ }
48
+ }
@@ -0,0 +1,44 @@
1
+ export * from "./generics.js";
2
+ export * from "./decode-wa-message.js";
3
+ export * from "./messages.js";
4
+ export * from "./messages-media.js";
5
+ export * from "./validate-connection.js";
6
+ export * from "./crypto.js";
7
+ export * from "./signal.js";
8
+ export * from "./noise-handler.js";
9
+ export * from "./history.js";
10
+ export * from "./chat-utils.js";
11
+ export * from "./lt-hash.js";
12
+ export * from "./auth-utils.js";
13
+ export * from "./use-multi-file-auth-state.js";
14
+ export * from "./use-single-file-auth-state.js";
15
+ export * from "./use-sqlite-auth-state.js";
16
+ export * from "./auth-store.js";
17
+ export * from "./use-postgres-auth-state.js";
18
+ export * from "./use-mysql-auth-state.js";
19
+ export * from "./use-mongo-auth-state.js";
20
+ export * from "./use-redis-auth-state.js";
21
+ export * from "./link-preview.js";
22
+ export * from "./event-buffer.js";
23
+ export * from "./process-message.js";
24
+ export * from "./message-retry-manager.js";
25
+ export * from "./ttl-cache.js";
26
+ export * from "./browser-utils.js";
27
+ export * from "./companion-reg-client-utils.js";
28
+ export * from "./identity-change-handler.js";
29
+ export * from "./stanza-ack.js";
30
+ export * from "./useNekoDBAuth.js";
31
+ export * from "./modern-messages.js";
32
+ export * from "./sender-key-memory.js";
33
+ export * from "./group-metadata-cache.js";
34
+ export * from "./newsletter-status.js";
35
+ export * from "./voice-recognition.js";
36
+ export * from "./username.js";
37
+ export * from "./scheduled-message.js";
38
+ export * from "./status-stickers.js";
39
+ export * from "./link-preview-metadata.js";
40
+ export * from "./payment-messages.js";
41
+ export * from "./native-flow.js";
42
+ export * from "./html-app.js";
43
+ export * from "./html-multiplayer.js";
44
+ export * from "./optional-media.js";
@@ -0,0 +1,44 @@
1
+ export * from './generics.js';
2
+ export * from './decode-wa-message.js';
3
+ export * from './messages.js';
4
+ export * from './messages-media.js';
5
+ export * from './validate-connection.js';
6
+ export * from './crypto.js';
7
+ export * from './signal.js';
8
+ export * from './noise-handler.js';
9
+ export * from './history.js';
10
+ export * from './chat-utils.js';
11
+ export * from './lt-hash.js';
12
+ export * from './auth-utils.js';
13
+ export * from './use-multi-file-auth-state.js';
14
+ export * from './use-single-file-auth-state.js';
15
+ export * from './use-sqlite-auth-state.js';
16
+ export * from './auth-store.js';
17
+ export * from './use-postgres-auth-state.js';
18
+ export * from './use-mysql-auth-state.js';
19
+ export * from './use-mongo-auth-state.js';
20
+ export * from './use-redis-auth-state.js';
21
+ export * from './link-preview.js';
22
+ export * from './event-buffer.js';
23
+ export * from './process-message.js';
24
+ export * from './message-retry-manager.js';
25
+ export * from './ttl-cache.js';
26
+ export * from './browser-utils.js';
27
+ export * from './companion-reg-client-utils.js';
28
+ export * from './identity-change-handler.js';
29
+ export * from './stanza-ack.js';
30
+ export * from "./useNekoDBAuth.js";
31
+ export * from './modern-messages.js';
32
+ export * from './sender-key-memory.js';
33
+ export * from './group-metadata-cache.js';
34
+ export * from './newsletter-status.js';
35
+ export * from './voice-recognition.js';
36
+ export * from './username.js';
37
+ export * from './scheduled-message.js';
38
+ export * from './status-stickers.js';
39
+ export * from './link-preview-metadata.js';
40
+ export * from './payment-messages.js';
41
+ export * from './native-flow.js';
42
+ export * from './html-app.js';
43
+ export * from './html-multiplayer.js';
44
+ export * from './optional-media.js';
@@ -0,0 +1,47 @@
1
+ import type { proto } from '../../WAProto/index.js';
2
+
3
+ export declare const SocialMediaPostType: Readonly<{
4
+ NONE: 0;
5
+ REEL: 1;
6
+ LIVE_VIDEO: 2;
7
+ LONG_VIDEO: 3;
8
+ SINGLE_IMAGE: 4;
9
+ CAROUSEL: 5;
10
+ }>;
11
+
12
+ export declare function videoEndCard(options?: {
13
+ username?: string;
14
+ caption?: string;
15
+ thumbnailUrl?: string;
16
+ profilePictureUrl?: string;
17
+ }): proto.Message.IVideoEndCard;
18
+
19
+ export interface SocialPreviewOptions {
20
+ postType?: number;
21
+ videoUrl?: string;
22
+ videoCaption?: string;
23
+ muted?: boolean;
24
+ /** Seconds, not milliseconds — the client stores link_media_duration_seconds. */
25
+ durationSeconds?: number;
26
+ experimentId?: number;
27
+ music?: proto.IEmbeddedMusic;
28
+ endCards?: proto.Message.IVideoEndCard[];
29
+ }
30
+
31
+ export declare function buildSocialPreview(options?: SocialPreviewOptions): {
32
+ linkPreviewMetadata?: proto.Message.ILinkPreviewMetadata;
33
+ videoContentUrl?: string;
34
+ musicMetadata?: proto.IEmbeddedMusic;
35
+ endCardTiles?: proto.Message.IVideoEndCard[];
36
+ };
37
+
38
+ export declare function readSocialPreview(msg: any): {
39
+ postType?: number;
40
+ durationSeconds?: number;
41
+ muted?: boolean;
42
+ videoUrl?: string;
43
+ videoCaption?: string;
44
+ music?: proto.IEmbeddedMusic;
45
+ experimentId?: number;
46
+ endCards?: proto.Message.IVideoEndCard[];
47
+ } | null;
@@ -0,0 +1,88 @@
1
+
2
+ export const SocialMediaPostType = Object.freeze({
3
+ NONE: 0,
4
+ REEL: 1,
5
+ LIVE_VIDEO: 2,
6
+ LONG_VIDEO: 3,
7
+ SINGLE_IMAGE: 4,
8
+ CAROUSEL: 5
9
+ })
10
+
11
+ const drop = (object) => {
12
+ for (const key of Object.keys(object)) {
13
+ if (object[key] === undefined || object[key] === null) {
14
+ delete object[key]
15
+ }
16
+ }
17
+ return object
18
+ }
19
+
20
+ export const videoEndCard = ({ username, caption, thumbnailUrl, profilePictureUrl } = {}) =>
21
+ drop({
22
+ username,
23
+ caption,
24
+ thumbnailImageUrl: thumbnailUrl,
25
+ profilePictureUrl
26
+ })
27
+
28
+ /**
29
+ * The same video url and music node exist twice, once nested in
30
+ * LinkPreviewMetadata and once directly on ExtendedTextMessage. Which one the
31
+ * client reads is not visible from the client, so both carry the same value.
32
+ */
33
+ export const buildSocialPreview = ({
34
+ postType,
35
+ videoUrl,
36
+ videoCaption,
37
+ muted,
38
+ durationSeconds,
39
+ experimentId,
40
+ music,
41
+ endCards
42
+ } = {}) => {
43
+ if (postType !== undefined && !Object.values(SocialMediaPostType).includes(postType)) {
44
+ throw new TypeError(`postType ${postType} is not one of ${Object.keys(SocialMediaPostType).join(', ')}`)
45
+ }
46
+ if (durationSeconds !== undefined && (!Number.isFinite(Number(durationSeconds)) || Number(durationSeconds) < 0)) {
47
+ throw new TypeError('durationSeconds must be a non-negative number of seconds, not milliseconds')
48
+ }
49
+
50
+ const metadata = drop({
51
+ socialMediaPostType: postType,
52
+ linkMediaDuration: durationSeconds === undefined ? undefined : Math.round(Number(durationSeconds)),
53
+ linkInlineVideoMuted: muted === undefined ? undefined : !!muted,
54
+ videoContentUrl: videoUrl,
55
+ videoContentCaption: videoCaption,
56
+ musicMetadata: music,
57
+ fbExperimentId: experimentId
58
+ })
59
+
60
+ return drop({
61
+ linkPreviewMetadata: Object.keys(metadata).length ? metadata : undefined,
62
+ videoContentUrl: videoUrl,
63
+ musicMetadata: music,
64
+ endCardTiles: endCards?.length ? endCards : undefined
65
+ })
66
+ }
67
+
68
+ export const readSocialPreview = (msg) => {
69
+ const message = msg?.message ?? msg
70
+ const text = message?.extendedTextMessage
71
+ if (!text) {
72
+ return null
73
+ }
74
+ const metadata = text.linkPreviewMetadata
75
+ if (!metadata && !text.endCardTiles?.length && !text.videoContentUrl) {
76
+ return null
77
+ }
78
+ return drop({
79
+ postType: metadata?.socialMediaPostType,
80
+ durationSeconds: metadata?.linkMediaDuration,
81
+ muted: metadata?.linkInlineVideoMuted,
82
+ videoUrl: metadata?.videoContentUrl ?? text.videoContentUrl,
83
+ videoCaption: metadata?.videoContentCaption,
84
+ music: metadata?.musicMetadata ?? text.musicMetadata,
85
+ experimentId: metadata?.fbExperimentId,
86
+ endCards: text.endCardTiles?.length ? text.endCardTiles : undefined
87
+ })
88
+ }
@@ -0,0 +1,12 @@
1
+ export function getUrlInfo(text: any, opts?: {
2
+ thumbnailWidth: number;
3
+ fetchOpts: {
4
+ timeout: number;
5
+ };
6
+ }): Promise<{
7
+ 'canonical-url': any;
8
+ 'matched-text': any;
9
+ title: any;
10
+ description: any;
11
+ originalThumbnailUrl: any;
12
+ } | undefined>;
@@ -0,0 +1,79 @@
1
+ import { prepareWAMessageMedia } from './messages.js';
2
+ import { extractImageThumb, getHttpStream } from './messages-media.js';
3
+ const THUMBNAIL_WIDTH_PX = 192;
4
+
5
+ const getCompressedJpegThumbnail = async (url, { thumbnailWidth, fetchOpts }) => {
6
+ const stream = await getHttpStream(url, fetchOpts);
7
+ const result = await extractImageThumb(stream, thumbnailWidth);
8
+ return result;
9
+ };
10
+
11
+ export const getUrlInfo = async (text, opts = {
12
+ thumbnailWidth: THUMBNAIL_WIDTH_PX,
13
+ fetchOpts: { timeout: 3000 }
14
+ }) => {
15
+ try {
16
+
17
+ let retries = 0;
18
+ const maxRetry = 5;
19
+ const { getLinkPreview } = await import('link-preview-js');
20
+ let previewLink = text;
21
+ if (!text.startsWith('https://') && !text.startsWith('http://')) {
22
+ previewLink = 'https://' + previewLink;
23
+ }
24
+ const info = await getLinkPreview(previewLink, {
25
+ ...opts.fetchOpts,
26
+ followRedirects: 'follow',
27
+ handleRedirects: (baseURL, forwardedURL) => {
28
+ const urlObj = new URL(baseURL);
29
+ const forwardedURLObj = new URL(forwardedURL);
30
+ if (retries >= maxRetry) {
31
+ return false;
32
+ }
33
+ if (forwardedURLObj.hostname === urlObj.hostname ||
34
+ forwardedURLObj.hostname === 'www.' + urlObj.hostname ||
35
+ 'www.' + forwardedURLObj.hostname === urlObj.hostname) {
36
+ retries += 1;
37
+ return true;
38
+ }
39
+ else {
40
+ return false;
41
+ }
42
+ },
43
+ headers: opts.fetchOpts?.headers
44
+ });
45
+ if (info && 'title' in info && info.title) {
46
+ const [image] = info.images;
47
+ const urlInfo = {
48
+ 'canonical-url': info.url,
49
+ 'matched-text': text,
50
+ title: info.title,
51
+ description: info.description,
52
+ originalThumbnailUrl: image
53
+ };
54
+ if (opts.uploadImage) {
55
+ const { imageMessage } = await prepareWAMessageMedia({ image: { url: image } }, {
56
+ upload: opts.uploadImage,
57
+ mediaTypeOverride: 'thumbnail-link',
58
+ options: opts.fetchOpts
59
+ });
60
+ urlInfo.jpegThumbnail = imageMessage?.jpegThumbnail ? Buffer.from(imageMessage.jpegThumbnail) : undefined;
61
+ urlInfo.highQualityThumbnail = imageMessage || undefined;
62
+ }
63
+ else {
64
+ try {
65
+ urlInfo.jpegThumbnail = image ? (await getCompressedJpegThumbnail(image, opts)).buffer : undefined;
66
+ }
67
+ catch (error) {
68
+ opts.logger?.debug({ err: error.stack, url: previewLink }, 'error in generating thumbnail');
69
+ }
70
+ }
71
+ return urlInfo;
72
+ }
73
+ }
74
+ catch (error) {
75
+ if (!error.message.includes('receive a valid')) {
76
+ throw error;
77
+ }
78
+ }
79
+ };
@@ -0,0 +1,2 @@
1
+ declare const _default: any;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ import P from 'pino';
2
+ export default P({ timestamp: () => `,"time":"${new Date().toJSON()}"` });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * LT Hash is a summation based hash algorithm that maintains the integrity of a piece of data
3
+ * over a series of mutations. You can add/remove mutations and it'll return a hash equal to
4
+ * if the same series of mutations was made sequentially.
5
+ */
6
+ export const LT_HASH_ANTI_TAMPERING: any;
@@ -0,0 +1,3 @@
1
+ import { LTHashAntiTampering } from '@rexxhayanasi/wangcap-id-bridge';
2
+
3
+ export const LT_HASH_ANTI_TAMPERING = new LTHashAntiTampering();
@@ -0,0 +1,6 @@
1
+ export function makeMutex(): {
2
+ mutex(code: any): any;
3
+ };
4
+ export function makeKeyedMutex(): {
5
+ mutex(key: any, task: any): Promise<any>;
6
+ };
@@ -0,0 +1,32 @@
1
+ import { Mutex as AsyncMutex } from 'async-mutex';
2
+ export const makeMutex = () => {
3
+ const mutex = new AsyncMutex();
4
+ return {
5
+ mutex(code) {
6
+ return mutex.runExclusive(code);
7
+ }
8
+ };
9
+ };
10
+ export const makeKeyedMutex = () => {
11
+ const map = new Map();
12
+ return {
13
+ async mutex(key, task) {
14
+ let entry = map.get(key);
15
+ if (!entry) {
16
+ entry = { mutex: new AsyncMutex(), refCount: 0 };
17
+ map.set(key, entry);
18
+ }
19
+ entry.refCount++;
20
+ try {
21
+ return await entry.mutex.runExclusive(task);
22
+ }
23
+ finally {
24
+ entry.refCount--;
25
+
26
+ if (entry.refCount === 0 && map.get(key) === entry) {
27
+ map.delete(key);
28
+ }
29
+ }
30
+ }
31
+ };
32
+ };