@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,29 @@
1
+ /** Read the persisted tctoken JID index and return its entries (never contains the sentinel key itself). */
2
+ export function readTcTokenIndex(keys: any): Promise<any[]>;
3
+ /** Build a SignalDataSet fragment that writes the merged index (persisted ∪ added) under the sentinel key. */
4
+ export function buildMergedTcTokenIndexWrite(keys: any, addedJids: any): Promise<{
5
+ __index: {
6
+ token: any;
7
+ };
8
+ }>;
9
+ export function isTcTokenExpired(timestamp: any): boolean;
10
+ export function shouldSendNewTcToken(senderTimestamp: any): boolean;
11
+ /** Resolve JID to LID for tctoken storage (WA Web stores under LID) */
12
+ export function resolveTcTokenJid(jid: any, getLIDForPN: any): Promise<any>;
13
+ /** Resolve target JID for issuing privacy token based on AB prop 14303 */
14
+ export function resolveIssuanceJid(jid: any, issueToLid: any, getLIDForPN: any, getPNForLID: any): Promise<any>;
15
+ export function buildTcTokenFromJid({ authState, jid, baseContent, getLIDForPN }: {
16
+ authState: any;
17
+ jid: any;
18
+ baseContent?: never[] | undefined;
19
+ getLIDForPN: any;
20
+ }): Promise<any[] | undefined>;
21
+ export function storeTcTokensFromIqResult({ result, fallbackJid, keys, getLIDForPN, onNewJidStored }: {
22
+ result: any;
23
+ fallbackJid: any;
24
+ keys: any;
25
+ getLIDForPN: any;
26
+ onNewJidStored: any;
27
+ }): Promise<void>;
28
+ /** Sentinel key under `tctoken` store holding a JSON array of tracked storage JIDs for cross-session pruning. */
29
+ export const TC_TOKEN_INDEX_KEY: "__index";
@@ -0,0 +1,155 @@
1
+ import { getBinaryNodeChild, getBinaryNodeChildren, isHostedLidUser, isHostedPnUser, isJidMetaAI, isLidUser, isPnUser, jidNormalizedUser } from '../WABinary/index.js';
2
+
3
+ const BOT_PHONE_REGEX = /^1313555\d{4}$|^131655500\d{2}$/;
4
+
5
+ function isRegularUser(jid) {
6
+ if (!jid)
7
+ return false;
8
+ const user = jid.split('@')[0] ?? '';
9
+ if (user === '0')
10
+ return false;
11
+ if (BOT_PHONE_REGEX.test(user))
12
+ return false;
13
+ if (isJidMetaAI(jid))
14
+ return false;
15
+ return !!(isPnUser(jid) || isLidUser(jid) || isHostedPnUser(jid) || isHostedLidUser(jid) || jid.endsWith('@c.us'));
16
+ }
17
+ const TC_TOKEN_BUCKET_DURATION = 604800;
18
+ const TC_TOKEN_NUM_BUCKETS = 4;
19
+
20
+ export const TC_TOKEN_INDEX_KEY = '__index';
21
+
22
+ export async function readTcTokenIndex(keys) {
23
+ const data = await keys.get('tctoken', [TC_TOKEN_INDEX_KEY]);
24
+ const entry = data[TC_TOKEN_INDEX_KEY];
25
+ if (!entry?.token?.length)
26
+ return [];
27
+ try {
28
+ const parsed = JSON.parse(Buffer.from(entry.token).toString());
29
+ if (!Array.isArray(parsed))
30
+ return [];
31
+ return parsed.filter((j) => typeof j === 'string' && j.length > 0 && j !== TC_TOKEN_INDEX_KEY);
32
+ }
33
+ catch {
34
+ return [];
35
+ }
36
+ }
37
+
38
+ export async function buildMergedTcTokenIndexWrite(keys, addedJids) {
39
+ const persisted = await readTcTokenIndex(keys);
40
+ const merged = new Set(persisted);
41
+ for (const jid of addedJids) {
42
+ if (jid && jid !== TC_TOKEN_INDEX_KEY)
43
+ merged.add(jid);
44
+ }
45
+ return {
46
+ [TC_TOKEN_INDEX_KEY]: { token: Buffer.from(JSON.stringify([...merged])) }
47
+ };
48
+ }
49
+
50
+ export function isTcTokenExpired(timestamp) {
51
+ if (timestamp === null || timestamp === undefined)
52
+ return true;
53
+ const ts = typeof timestamp === 'string' ? parseInt(timestamp) : timestamp;
54
+ if (isNaN(ts))
55
+ return true;
56
+ const now = Math.floor(Date.now() / 1000);
57
+ const currentBucket = Math.floor(now / TC_TOKEN_BUCKET_DURATION);
58
+ const cutoffBucket = currentBucket - (TC_TOKEN_NUM_BUCKETS - 1);
59
+ const cutoffTimestamp = cutoffBucket * TC_TOKEN_BUCKET_DURATION;
60
+ return ts < cutoffTimestamp;
61
+ }
62
+ export function shouldSendNewTcToken(senderTimestamp) {
63
+ if (senderTimestamp === undefined)
64
+ return true;
65
+ const now = Math.floor(Date.now() / 1000);
66
+ const currentBucket = Math.floor(now / TC_TOKEN_BUCKET_DURATION);
67
+ const senderBucket = Math.floor(senderTimestamp / TC_TOKEN_BUCKET_DURATION);
68
+ return currentBucket > senderBucket;
69
+ }
70
+
71
+ export async function resolveTcTokenJid(jid, getLIDForPN) {
72
+ if (isLidUser(jid))
73
+ return jid;
74
+ const lid = await getLIDForPN(jid);
75
+ return lid ?? jid;
76
+ }
77
+
78
+ export async function resolveIssuanceJid(jid, issueToLid, getLIDForPN, getPNForLID) {
79
+ if (issueToLid) {
80
+ if (isLidUser(jid))
81
+ return jid;
82
+ const lid = await getLIDForPN(jid);
83
+ return lid ?? jid;
84
+ }
85
+ if (!isLidUser(jid))
86
+ return jid;
87
+ if (getPNForLID) {
88
+ const pn = await getPNForLID(jid);
89
+ return pn ?? jid;
90
+ }
91
+ return jid;
92
+ }
93
+ export async function buildTcTokenFromJid({ authState, jid, baseContent = [], getLIDForPN }) {
94
+ try {
95
+ const storageJid = await resolveTcTokenJid(jid, getLIDForPN);
96
+ const tcTokenData = await authState.keys.get('tctoken', [storageJid]);
97
+ const entry = tcTokenData?.[storageJid];
98
+ const tcTokenBuffer = entry?.token;
99
+ const timestamp = entry?.timestamp;
100
+ if (!tcTokenBuffer?.length || timestamp === undefined || isTcTokenExpired(timestamp)) {
101
+ if (tcTokenBuffer) {
102
+
103
+ const cleared = entry?.senderTimestamp !== undefined
104
+ ? { token: Buffer.alloc(0), senderTimestamp: entry.senderTimestamp }
105
+ : null;
106
+ await authState.keys.set({ tctoken: { [storageJid]: cleared } });
107
+ }
108
+ return baseContent.length > 0 ? baseContent : undefined;
109
+ }
110
+ baseContent.push({
111
+ tag: 'tctoken',
112
+ attrs: { t: String(timestamp) },
113
+ content: tcTokenBuffer
114
+ });
115
+ return baseContent;
116
+ }
117
+ catch (error) {
118
+ return baseContent.length > 0 ? baseContent : undefined;
119
+ }
120
+ }
121
+ export async function storeTcTokensFromIqResult({ result, fallbackJid, keys, getLIDForPN, onNewJidStored }) {
122
+ const tokensNode = getBinaryNodeChild(result, 'tokens');
123
+ if (!tokensNode)
124
+ return;
125
+ const tokenNodes = getBinaryNodeChildren(tokensNode, 'token');
126
+ for (const tokenNode of tokenNodes) {
127
+ if (tokenNode.attrs.type !== 'trusted_contact' || !(tokenNode.content instanceof Uint8Array)) {
128
+ continue;
129
+ }
130
+
131
+ const rawJid = jidNormalizedUser(fallbackJid || tokenNode.attrs.jid);
132
+ if (!isRegularUser(rawJid))
133
+ continue;
134
+ const storageJid = await resolveTcTokenJid(rawJid, getLIDForPN);
135
+ const existingTcData = await keys.get('tctoken', [storageJid]);
136
+ const existingEntry = existingTcData[storageJid];
137
+ const existingTs = existingEntry?.timestamp ? Number(existingEntry.timestamp) : 0;
138
+ const incomingTs = tokenNode.attrs.t ? Number(tokenNode.attrs.t) : 0;
139
+
140
+ if (!incomingTs)
141
+ continue;
142
+ if (existingTs > 0 && existingTs > incomingTs)
143
+ continue;
144
+ await keys.set({
145
+ tctoken: {
146
+ [storageJid]: {
147
+ ...existingEntry,
148
+ token: Buffer.from(tokenNode.content),
149
+ timestamp: tokenNode.attrs.t
150
+ }
151
+ }
152
+ });
153
+ onNewJidStored?.(storageJid);
154
+ }
155
+ }
@@ -0,0 +1,28 @@
1
+ export declare class TTLCache<T = any> {
2
+ constructor(options?: {
3
+ /** lifetime in seconds, the same unit node-cache used; 0 or omitted means no expiry */
4
+ stdTTL?: number;
5
+ /** ceiling on entries, the oldest is evicted once it is reached */
6
+ maxKeys?: number;
7
+ /** alias for maxKeys */
8
+ max?: number;
9
+ /** lifetime in milliseconds, takes precedence over stdTTL */
10
+ ttl?: number;
11
+ });
12
+ get(key: string | number): T | undefined;
13
+ set(key: string | number, value: T, ttl?: number): boolean;
14
+ has(key: string | number): boolean;
15
+ del(keys: string | number | Array<string | number>): number;
16
+ take(key: string | number): T | undefined;
17
+ mget(keys: Array<string | number>): Record<string, T>;
18
+ mset(list: Array<{ key: string | number; value?: T; val?: T; ttl?: number }>): boolean;
19
+ keys(): string[];
20
+ flushAll(): void;
21
+ getStats(): { hits: number; misses: number; keys: number; ksize: number; vsize: number };
22
+ close(): void;
23
+ on(): this;
24
+ off(): this;
25
+ removeAllListeners(): this;
26
+ readonly size: number;
27
+ }
28
+ export default TTLCache;
@@ -0,0 +1,120 @@
1
+ import { LRUCache } from 'lru-cache';
2
+ import { DEFAULT_CACHE_MAX_KEYS } from '../Defaults/index.js';
3
+
4
+ const asKey = (key) => (typeof key === 'string' ? key : String(key));
5
+
6
+ const toMilliseconds = (seconds) => {
7
+ const value = Number(seconds);
8
+ return Number.isFinite(value) && value > 0 ? Math.round(value * 1000) : 0;
9
+ };
10
+
11
+ export class TTLCache {
12
+ #store;
13
+
14
+ #ttl;
15
+
16
+ #hits = 0;
17
+
18
+ #misses = 0;
19
+
20
+ constructor({ stdTTL = 0, maxKeys, max, ttl } = {}) {
21
+ this.#ttl = ttl !== undefined ? Number(ttl) || 0 : toMilliseconds(stdTTL);
22
+ const limit = Number(max ?? maxKeys);
23
+ this.#store = new LRUCache({
24
+ max: Number.isFinite(limit) && limit > 0 ? limit : DEFAULT_CACHE_MAX_KEYS,
25
+ ...(this.#ttl ? { ttl: this.#ttl } : {})
26
+ });
27
+ }
28
+
29
+ get(key) {
30
+ const value = this.#store.get(asKey(key));
31
+ if (value === undefined) {
32
+ this.#misses += 1;
33
+ }
34
+ else {
35
+ this.#hits += 1;
36
+ }
37
+ return value;
38
+ }
39
+
40
+ set(key, value, ttl) {
41
+ const override = toMilliseconds(ttl);
42
+ this.#store.set(asKey(key), value, override ? { ttl: override } : undefined);
43
+ return true;
44
+ }
45
+
46
+ has(key) {
47
+ return this.#store.has(asKey(key));
48
+ }
49
+
50
+ del(keys) {
51
+ const list = Array.isArray(keys) ? keys : [keys];
52
+ let removed = 0;
53
+ for (const key of list) {
54
+ if (this.#store.delete(asKey(key))) {
55
+ removed += 1;
56
+ }
57
+ }
58
+ return removed;
59
+ }
60
+
61
+ take(key) {
62
+ const value = this.get(key);
63
+ this.del(key);
64
+ return value;
65
+ }
66
+
67
+ mget(keys) {
68
+ const found = {};
69
+ for (const key of Array.isArray(keys) ? keys : [keys]) {
70
+ const value = this.get(key);
71
+ if (value !== undefined) {
72
+ found[key] = value;
73
+ }
74
+ }
75
+ return found;
76
+ }
77
+
78
+ mset(list) {
79
+ for (const item of list ?? []) {
80
+ this.set(item.key, item.value ?? item.val, item.ttl);
81
+ }
82
+ return true;
83
+ }
84
+
85
+ keys() {
86
+ return [...this.#store.keys()];
87
+ }
88
+
89
+ flushAll() {
90
+ this.#store.clear();
91
+ this.#hits = 0;
92
+ this.#misses = 0;
93
+ }
94
+
95
+ getStats() {
96
+ return { hits: this.#hits, misses: this.#misses, keys: this.#store.size, ksize: 0, vsize: 0 };
97
+ }
98
+
99
+ close() {
100
+ this.#store.clear();
101
+ }
102
+
103
+ on() {
104
+ return this;
105
+ }
106
+
107
+ off() {
108
+ return this;
109
+ }
110
+
111
+ removeAllListeners() {
112
+ return this;
113
+ }
114
+
115
+ get size() {
116
+ return this.#store.size;
117
+ }
118
+ }
119
+
120
+ export default TTLCache;
@@ -0,0 +1,21 @@
1
+ export interface MongoAuthStateOptions {
2
+ collection?: any;
3
+ db?: any;
4
+ uri?: string;
5
+ clientOptions?: any;
6
+ dbName?: string;
7
+ collectionName?: string;
8
+ session?: string;
9
+ }
10
+ export function useMongoAuthState(opts?: MongoAuthStateOptions): Promise<{
11
+ state: {
12
+ creds: any;
13
+ keys: {
14
+ get: (type: any, ids: any) => Promise<{}>;
15
+ set: (data: any) => Promise<void>;
16
+ };
17
+ };
18
+ saveCreds: () => Promise<void>;
19
+ clearAuth: () => Promise<void>;
20
+ close: () => Promise<void>;
21
+ }>;
@@ -0,0 +1,67 @@
1
+ import { loadOptionalModule, makeAuthStateFromStore } from './auth-store.js';
2
+ export async function useMongoAuthState(opts = {}) {
3
+ const session = opts.session ?? 'default';
4
+ let collection = opts.collection;
5
+ let client;
6
+ if (!collection) {
7
+ let db = opts.db;
8
+ if (!db) {
9
+ if (!opts.uri) {
10
+ throw new Error('useMongoAuthState needs a collection, a db, or a uri');
11
+ }
12
+ const mongodb = await loadOptionalModule('mongodb', 'useMongoAuthState');
13
+ client = new mongodb.MongoClient(opts.uri, opts.clientOptions);
14
+ await client.connect();
15
+ db = client.db(opts.dbName);
16
+ }
17
+ collection = db.collection(opts.collectionName ?? 'baileys_auth');
18
+ }
19
+ await collection.createIndex({ session: 1, type: 1, id: 1 }, { unique: true });
20
+ const store = {
21
+ read: async (type, id) => {
22
+ const doc = await collection.findOne({ session, type, id });
23
+ return doc?.value ?? null;
24
+ },
25
+ readMany: async (type, ids) => {
26
+ if (!ids.length) {
27
+ return {};
28
+ }
29
+ const docs = await collection.find({ session, type, id: { $in: ids } }).toArray();
30
+ const rows = {};
31
+ for (const doc of docs) {
32
+ rows[doc.id] = doc.value;
33
+ }
34
+ return rows;
35
+ },
36
+ write: async (type, id, value) => {
37
+ await collection.updateOne({ session, type, id }, { $set: { value } }, { upsert: true });
38
+ },
39
+ apply: async (writes, removals) => {
40
+ const operations = [];
41
+ for (const entry of writes) {
42
+ operations.push({
43
+ updateOne: {
44
+ filter: { session, type: entry.type, id: entry.id },
45
+ update: { $set: { value: entry.value } },
46
+ upsert: true
47
+ }
48
+ });
49
+ }
50
+ for (const entry of removals) {
51
+ operations.push({
52
+ deleteOne: {
53
+ filter: { session, type: entry.type, id: entry.id }
54
+ }
55
+ });
56
+ }
57
+ await collection.bulkWrite(operations, { ordered: false });
58
+ },
59
+ clear: async () => {
60
+ await collection.deleteMany({ session });
61
+ },
62
+ close: async () => {
63
+ await client?.close();
64
+ }
65
+ };
66
+ return makeAuthStateFromStore(store);
67
+ }
@@ -0,0 +1,11 @@
1
+ export function useMultiFileAuthState(folder: any): Promise<{
2
+ state: {
3
+ creds: any;
4
+ keys: {
5
+ get: (type: any, ids: any) => Promise<{}>;
6
+ set: (data: any) => Promise<void>;
7
+ };
8
+ };
9
+ saveCreds: () => Promise<any>;
10
+ }>;
11
+ export function countAuthFileLocks(): number;
@@ -0,0 +1,106 @@
1
+ import { Mutex } from 'async-mutex';
2
+ import { mkdir, readFile, stat, unlink, writeFile } from 'fs/promises';
3
+ import { join } from 'path';
4
+ import { proto } from '../../WAProto/index.js';
5
+ import { initAuthCreds } from './auth-utils.js';
6
+ import { BufferJSON } from './generics.js';
7
+
8
+ const fileLocks = new Map();
9
+
10
+ const withFileLock = async (path, work) => {
11
+ let entry = fileLocks.get(path);
12
+ if (!entry) {
13
+ entry = { mutex: new Mutex(), waiting: 0 };
14
+ fileLocks.set(path, entry);
15
+ }
16
+ entry.waiting++;
17
+ const release = await entry.mutex.acquire();
18
+ try {
19
+ return await work();
20
+ }
21
+ finally {
22
+ release();
23
+ entry.waiting--;
24
+ if (entry.waiting === 0) {
25
+ fileLocks.delete(path);
26
+ }
27
+ }
28
+ };
29
+
30
+ export const countAuthFileLocks = () => fileLocks.size;
31
+
32
+ export const useMultiFileAuthState = async (folder) => {
33
+
34
+ const writeData = async (data, file) => {
35
+ const filePath = join(folder, fixFileName(file));
36
+ return withFileLock(filePath, () => writeFile(filePath, JSON.stringify(data, BufferJSON.replacer)));
37
+ };
38
+ const readData = async (file) => {
39
+ try {
40
+ const filePath = join(folder, fixFileName(file));
41
+ return await withFileLock(filePath, async () => {
42
+ const data = await readFile(filePath, { encoding: 'utf-8' });
43
+ return JSON.parse(data, BufferJSON.reviver);
44
+ });
45
+ }
46
+ catch (error) {
47
+ return null;
48
+ }
49
+ };
50
+ const removeData = async (file) => {
51
+ try {
52
+ const filePath = join(folder, fixFileName(file));
53
+ return await withFileLock(filePath, async () => {
54
+ try {
55
+ await unlink(filePath);
56
+ }
57
+ catch {
58
+ }
59
+ });
60
+ }
61
+ catch { }
62
+ };
63
+ const folderInfo = await stat(folder).catch(() => { });
64
+ if (folderInfo) {
65
+ if (!folderInfo.isDirectory()) {
66
+ throw new Error(`found something that is not a directory at ${folder}, either delete it or specify a different location`);
67
+ }
68
+ }
69
+ else {
70
+ await mkdir(folder, { recursive: true });
71
+ }
72
+ const fixFileName = (file) => file?.replace(/\//g, '__')?.replace(/:/g, '-');
73
+ const creds = (await readData('creds.json')) || initAuthCreds();
74
+ return {
75
+ state: {
76
+ creds,
77
+ keys: {
78
+ get: async (type, ids) => {
79
+ const data = {};
80
+ await Promise.all(ids.map(async (id) => {
81
+ let value = await readData(`${type}-${id}.json`);
82
+ if (type === 'app-state-sync-key' && value) {
83
+ value = proto.Message.AppStateSyncKeyData.fromObject(value);
84
+ }
85
+ data[id] = value;
86
+ }));
87
+ return data;
88
+ },
89
+ set: async (data) => {
90
+ const tasks = [];
91
+ for (const category in data) {
92
+ for (const id in data[category]) {
93
+ const value = data[category][id];
94
+ const file = `${category}-${id}.json`;
95
+ tasks.push(value ? writeData(value, file) : removeData(file));
96
+ }
97
+ }
98
+ await Promise.all(tasks);
99
+ }
100
+ }
101
+ },
102
+ saveCreds: async () => {
103
+ return writeData(creds, 'creds.json');
104
+ }
105
+ };
106
+ };
@@ -0,0 +1,19 @@
1
+ export interface MySQLAuthStateOptions {
2
+ pool?: any;
3
+ uri?: string;
4
+ config?: any;
5
+ table?: string;
6
+ session?: string;
7
+ }
8
+ export function useMySQLAuthState(opts?: MySQLAuthStateOptions): Promise<{
9
+ state: {
10
+ creds: any;
11
+ keys: {
12
+ get: (type: any, ids: any) => Promise<{}>;
13
+ set: (data: any) => Promise<void>;
14
+ };
15
+ };
16
+ saveCreds: () => Promise<void>;
17
+ clearAuth: () => Promise<void>;
18
+ close: () => Promise<void>;
19
+ }>;
@@ -0,0 +1,79 @@
1
+ import { loadOptionalModule, makeAuthStateFromStore } from './auth-store.js';
2
+ const quoteIdentifier = (name) => {
3
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
4
+ throw new Error(`table name must be a plain identifier, got ${JSON.stringify(name)}`);
5
+ }
6
+ return `\`${name}\``;
7
+ };
8
+ export async function useMySQLAuthState(opts = {}) {
9
+ const table = quoteIdentifier(opts.table ?? 'baileys_auth');
10
+ const session = opts.session ?? 'default';
11
+ let pool = opts.pool;
12
+ let owned = false;
13
+ if (!pool) {
14
+ if (!opts.uri && !opts.config) {
15
+ throw new Error('useMySQLAuthState needs a pool, a uri, or a config');
16
+ }
17
+ const mysql = await loadOptionalModule('mysql2/promise', 'useMySQLAuthState');
18
+ pool = mysql.createPool(opts.config ?? opts.uri);
19
+ owned = true;
20
+ }
21
+ await pool.query(`CREATE TABLE IF NOT EXISTS ${table} (
22
+ session VARCHAR(128) NOT NULL,
23
+ type VARCHAR(128) NOT NULL,
24
+ id VARCHAR(255) NOT NULL,
25
+ value LONGTEXT NOT NULL,
26
+ PRIMARY KEY (session, type, id)
27
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`);
28
+ const store = {
29
+ read: async (type, id) => {
30
+ const [rows] = await pool.query(`SELECT value FROM ${table} WHERE session = ? AND type = ? AND id = ?`, [session, type, id]);
31
+ return rows[0]?.value ?? null;
32
+ },
33
+ readMany: async (type, ids) => {
34
+ if (!ids.length) {
35
+ return {};
36
+ }
37
+ const [rows] = await pool.query(`SELECT id, value FROM ${table} WHERE session = ? AND type = ? AND id IN (?)`, [session, type, ids]);
38
+ const found = {};
39
+ for (const row of rows) {
40
+ found[row.id] = row.value;
41
+ }
42
+ return found;
43
+ },
44
+ write: async (type, id, value) => {
45
+ await pool.query(`INSERT INTO ${table} (session, type, id, value) VALUES (?, ?, ?, ?)
46
+ ON DUPLICATE KEY UPDATE value = VALUES(value)`, [session, type, id, value]);
47
+ },
48
+ apply: async (writes, removals) => {
49
+ const connection = await pool.getConnection();
50
+ try {
51
+ await connection.beginTransaction();
52
+ for (const entry of writes) {
53
+ await connection.query(`INSERT INTO ${table} (session, type, id, value) VALUES (?, ?, ?, ?)
54
+ ON DUPLICATE KEY UPDATE value = VALUES(value)`, [session, entry.type, entry.id, entry.value]);
55
+ }
56
+ for (const entry of removals) {
57
+ await connection.query(`DELETE FROM ${table} WHERE session = ? AND type = ? AND id = ?`, [session, entry.type, entry.id]);
58
+ }
59
+ await connection.commit();
60
+ }
61
+ catch (err) {
62
+ await connection.rollback();
63
+ throw err;
64
+ }
65
+ finally {
66
+ connection.release();
67
+ }
68
+ },
69
+ clear: async () => {
70
+ await pool.query(`DELETE FROM ${table} WHERE session = ?`, [session]);
71
+ },
72
+ close: async () => {
73
+ if (owned) {
74
+ await pool.end();
75
+ }
76
+ }
77
+ };
78
+ return makeAuthStateFromStore(store);
79
+ }
@@ -0,0 +1,19 @@
1
+ export interface PostgresAuthStateOptions {
2
+ pool?: any;
3
+ connectionString?: string;
4
+ config?: any;
5
+ table?: string;
6
+ session?: string;
7
+ }
8
+ export function usePostgresAuthState(opts?: PostgresAuthStateOptions): Promise<{
9
+ state: {
10
+ creds: any;
11
+ keys: {
12
+ get: (type: any, ids: any) => Promise<{}>;
13
+ set: (data: any) => Promise<void>;
14
+ };
15
+ };
16
+ saveCreds: () => Promise<void>;
17
+ clearAuth: () => Promise<void>;
18
+ close: () => Promise<void>;
19
+ }>;