@japofc/baileys 2.1.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 (342) hide show
  1. package/NOTICE.md +111 -0
  2. package/README.md +1254 -0
  3. package/WAProto/index.d.ts +9 -0
  4. package/WAProto/index.js +142276 -0
  5. package/engine-requirements.js +13 -0
  6. package/lib/Builders/A2UI.d.ts +242 -0
  7. package/lib/Builders/A2UI.js +308 -0
  8. package/lib/Builders/AIRich.d.ts +105 -0
  9. package/lib/Builders/AIRich.js +2286 -0
  10. package/lib/Builders/Button.d.ts +103 -0
  11. package/lib/Builders/Button.js +883 -0
  12. package/lib/Builders/ButtonV2.d.ts +28 -0
  13. package/lib/Builders/ButtonV2.js +144 -0
  14. package/lib/Builders/ButtonV3.d.ts +25 -0
  15. package/lib/Builders/ButtonV3.js +184 -0
  16. package/lib/Builders/Carousel.d.ts +22 -0
  17. package/lib/Builders/Carousel.js +111 -0
  18. package/lib/Builders/JapBaileys.d.ts +34 -0
  19. package/lib/Builders/JapBaileys.js +108 -0
  20. package/lib/Builders/Poll.d.ts +25 -0
  21. package/lib/Builders/Poll.js +128 -0
  22. package/lib/Builders/index.d.ts +17 -0
  23. package/lib/Builders/index.js +11 -0
  24. package/lib/Builders/shared.d.ts +67 -0
  25. package/lib/Builders/shared.js +652 -0
  26. package/lib/Defaults/index.d.ts +154 -0
  27. package/lib/Defaults/index.js +178 -0
  28. package/lib/Framework/Bot.d.ts +61 -0
  29. package/lib/Framework/Bot.js +248 -0
  30. package/lib/Framework/Context.d.ts +21 -0
  31. package/lib/Framework/Context.js +89 -0
  32. package/lib/Framework/MediaManager.d.ts +17 -0
  33. package/lib/Framework/MediaManager.js +151 -0
  34. package/lib/Framework/SessionManager.d.ts +13 -0
  35. package/lib/Framework/SessionManager.js +33 -0
  36. package/lib/Framework/StatsManager.d.ts +26 -0
  37. package/lib/Framework/StatsManager.js +119 -0
  38. package/lib/Framework/Store/SQLiteStore.d.ts +11 -0
  39. package/lib/Framework/Store/SQLiteStore.js +73 -0
  40. package/lib/Framework/index.d.ts +9 -0
  41. package/lib/Framework/index.js +10 -0
  42. package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
  43. package/lib/Signal/Group/ciphertext-message.js +11 -0
  44. package/lib/Signal/Group/group-session-builder.d.ts +7 -0
  45. package/lib/Signal/Group/group-session-builder.js +29 -0
  46. package/lib/Signal/Group/group_cipher.d.ts +10 -0
  47. package/lib/Signal/Group/group_cipher.js +81 -0
  48. package/lib/Signal/Group/index.d.ts +11 -0
  49. package/lib/Signal/Group/index.js +11 -0
  50. package/lib/Signal/Group/keyhelper.d.ts +6 -0
  51. package/lib/Signal/Group/keyhelper.js +17 -0
  52. package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
  53. package/lib/Signal/Group/sender-chain-key.js +25 -0
  54. package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
  55. package/lib/Signal/Group/sender-key-distribution-message.js +62 -0
  56. package/lib/Signal/Group/sender-key-message.d.ts +18 -0
  57. package/lib/Signal/Group/sender-key-message.js +65 -0
  58. package/lib/Signal/Group/sender-key-name.d.ts +11 -0
  59. package/lib/Signal/Group/sender-key-name.js +47 -0
  60. package/lib/Signal/Group/sender-key-record.d.ts +12 -0
  61. package/lib/Signal/Group/sender-key-record.js +40 -0
  62. package/lib/Signal/Group/sender-key-state.d.ts +16 -0
  63. package/lib/Signal/Group/sender-key-state.js +83 -0
  64. package/lib/Signal/Group/sender-message-key.d.ts +11 -0
  65. package/lib/Signal/Group/sender-message-key.js +25 -0
  66. package/lib/Signal/libsignal.d.ts +54 -0
  67. package/lib/Signal/libsignal.js +430 -0
  68. package/lib/Signal/lid-mapping.d.ts +20 -0
  69. package/lib/Signal/lid-mapping.js +276 -0
  70. package/lib/Socket/Client/index.d.ts +2 -0
  71. package/lib/Socket/Client/index.js +2 -0
  72. package/lib/Socket/Client/types.d.ts +5 -0
  73. package/lib/Socket/Client/types.js +10 -0
  74. package/lib/Socket/Client/websocket.d.ts +12 -0
  75. package/lib/Socket/Client/websocket.js +53 -0
  76. package/lib/Socket/business.d.ts +395 -0
  77. package/lib/Socket/business.js +379 -0
  78. package/lib/Socket/chats.d.ts +136 -0
  79. package/lib/Socket/chats.js +1327 -0
  80. package/lib/Socket/communities.d.ts +562 -0
  81. package/lib/Socket/communities.js +439 -0
  82. package/lib/Socket/dugong.d.ts +117 -0
  83. package/lib/Socket/dugong.js +798 -0
  84. package/lib/Socket/groups.d.ts +285 -0
  85. package/lib/Socket/groups.js +354 -0
  86. package/lib/Socket/index.d.ts +585 -0
  87. package/lib/Socket/index.js +52 -0
  88. package/lib/Socket/messages-recv.d.ts +333 -0
  89. package/lib/Socket/messages-recv.js +1781 -0
  90. package/lib/Socket/messages-send.d.ts +353 -0
  91. package/lib/Socket/messages-send.js +1524 -0
  92. package/lib/Socket/mex.d.ts +1 -0
  93. package/lib/Socket/mex.js +41 -0
  94. package/lib/Socket/newsletter.d.ts +286 -0
  95. package/lib/Socket/newsletter.js +364 -0
  96. package/lib/Socket/socket.d.ts +60 -0
  97. package/lib/Socket/socket.js +1012 -0
  98. package/lib/Socket/username.d.ts +82 -0
  99. package/lib/Socket/username.js +159 -0
  100. package/lib/Store/index.d.ts +3 -0
  101. package/lib/Store/index.js +3 -0
  102. package/lib/Store/make-in-memory-store.d.ts +62 -0
  103. package/lib/Store/make-in-memory-store.js +428 -0
  104. package/lib/Store/make-ordered-dictionary.d.ts +12 -0
  105. package/lib/Store/make-ordered-dictionary.js +78 -0
  106. package/lib/Store/object-repository.d.ts +10 -0
  107. package/lib/Store/object-repository.js +23 -0
  108. package/lib/Types/Auth.d.ts +117 -0
  109. package/lib/Types/Auth.js +1 -0
  110. package/lib/Types/Bussines.d.ts +25 -0
  111. package/lib/Types/Call.d.ts +15 -0
  112. package/lib/Types/Call.js +1 -0
  113. package/lib/Types/Chat.d.ts +124 -0
  114. package/lib/Types/Chat.js +7 -0
  115. package/lib/Types/Contact.d.ts +26 -0
  116. package/lib/Types/Contact.js +1 -0
  117. package/lib/Types/Events.d.ts +256 -0
  118. package/lib/Types/Events.js +1 -0
  119. package/lib/Types/GroupMetadata.d.ts +71 -0
  120. package/lib/Types/GroupMetadata.js +1 -0
  121. package/lib/Types/Label.d.ts +5 -0
  122. package/lib/Types/Label.js +24 -0
  123. package/lib/Types/LabelAssociation.d.ts +6 -0
  124. package/lib/Types/LabelAssociation.js +6 -0
  125. package/lib/Types/Message.d.ts +62 -0
  126. package/lib/Types/Message.js +17 -0
  127. package/lib/Types/Mex.d.ts +2 -0
  128. package/lib/Types/Mex.js +38 -0
  129. package/lib/Types/Product.d.ts +79 -0
  130. package/lib/Types/Product.js +1 -0
  131. package/lib/Types/RichType.d.ts +2 -0
  132. package/lib/Types/RichType.js +22 -0
  133. package/lib/Types/Signal.d.ts +87 -0
  134. package/lib/Types/Signal.js +1 -0
  135. package/lib/Types/Socket.d.ts +138 -0
  136. package/lib/Types/Socket.js +1 -0
  137. package/lib/Types/State.d.ts +8 -0
  138. package/lib/Types/State.js +55 -0
  139. package/lib/Types/USync.d.ts +26 -0
  140. package/lib/Types/index.d.ts +68 -0
  141. package/lib/Types/index.js +27 -0
  142. package/lib/Utils/MessageBuilder.d.ts +2 -0
  143. package/lib/Utils/MessageBuilder.js +2 -0
  144. package/lib/Utils/PersistentStore.d.ts +60 -0
  145. package/lib/Utils/PersistentStore.js +592 -0
  146. package/lib/Utils/anti-delete.d.ts +74 -0
  147. package/lib/Utils/anti-delete.js +221 -0
  148. package/lib/Utils/auth-secure.d.ts +86 -0
  149. package/lib/Utils/auth-secure.js +764 -0
  150. package/lib/Utils/auth-utils.d.ts +57 -0
  151. package/lib/Utils/auth-utils.js +306 -0
  152. package/lib/Utils/auto-reply.d.ts +47 -0
  153. package/lib/Utils/auto-reply.js +157 -0
  154. package/lib/Utils/baileys-event-stream.d.ts +8 -0
  155. package/lib/Utils/baileys-event-stream.js +62 -0
  156. package/lib/Utils/browser-utils.d.ts +8 -0
  157. package/lib/Utils/browser-utils.js +27 -0
  158. package/lib/Utils/business.d.ts +49 -0
  159. package/lib/Utils/business.js +239 -0
  160. package/lib/Utils/button-helper-utils.d.ts +53 -0
  161. package/lib/Utils/button-helper-utils.js +312 -0
  162. package/lib/Utils/button-sender.d.ts +54 -0
  163. package/lib/Utils/button-sender.js +822 -0
  164. package/lib/Utils/chat-control.d.ts +159 -0
  165. package/lib/Utils/chat-control.js +230 -0
  166. package/lib/Utils/chat-history-helpers.d.ts +21 -0
  167. package/lib/Utils/chat-history-helpers.js +70 -0
  168. package/lib/Utils/chat-utils.d.ts +407 -0
  169. package/lib/Utils/chat-utils.js +885 -0
  170. package/lib/Utils/companion-reg-client-utils.d.ts +4 -0
  171. package/lib/Utils/companion-reg-client-utils.js +39 -0
  172. package/lib/Utils/crypto.d.ts +41 -0
  173. package/lib/Utils/crypto.js +147 -0
  174. package/lib/Utils/decode-wa-message.d.ts +83 -0
  175. package/lib/Utils/decode-wa-message.js +316 -0
  176. package/lib/Utils/event-buffer.d.ts +12 -0
  177. package/lib/Utils/event-buffer.js +635 -0
  178. package/lib/Utils/generics.d.ts +69 -0
  179. package/lib/Utils/generics.js +438 -0
  180. package/lib/Utils/history-share.d.ts +11 -0
  181. package/lib/Utils/history-share.js +70 -0
  182. package/lib/Utils/history.d.ts +90 -0
  183. package/lib/Utils/history.js +146 -0
  184. package/lib/Utils/humanizer.d.ts +12 -0
  185. package/lib/Utils/humanizer.js +73 -0
  186. package/lib/Utils/identity-change-handler.d.ts +13 -0
  187. package/lib/Utils/identity-change-handler.js +49 -0
  188. package/lib/Utils/index.d.ts +57 -0
  189. package/lib/Utils/index.js +56 -0
  190. package/lib/Utils/jid-tools.d.ts +6 -0
  191. package/lib/Utils/jid-tools.js +77 -0
  192. package/lib/Utils/link-preview.d.ts +12 -0
  193. package/lib/Utils/link-preview.js +84 -0
  194. package/lib/Utils/logger.d.ts +4 -0
  195. package/lib/Utils/logger.js +2 -0
  196. package/lib/Utils/lt-hash.d.ts +12 -0
  197. package/lib/Utils/lt-hash.js +26 -0
  198. package/lib/Utils/make-mutex.d.ts +6 -0
  199. package/lib/Utils/make-mutex.js +32 -0
  200. package/lib/Utils/media-messages.d.ts +18 -0
  201. package/lib/Utils/media-messages.js +70 -0
  202. package/lib/Utils/media-set.d.ts +13 -0
  203. package/lib/Utils/media-set.js +171 -0
  204. package/lib/Utils/message-kind.d.ts +32 -0
  205. package/lib/Utils/message-kind.js +136 -0
  206. package/lib/Utils/message-retry-manager.d.ts +79 -0
  207. package/lib/Utils/message-retry-manager.js +264 -0
  208. package/lib/Utils/message-search.d.ts +44 -0
  209. package/lib/Utils/message-search.js +188 -0
  210. package/lib/Utils/messages-media.d.ts +135 -0
  211. package/lib/Utils/messages-media.js +868 -0
  212. package/lib/Utils/messages.d.ts +44 -0
  213. package/lib/Utils/messages.js +2326 -0
  214. package/lib/Utils/meta-ai.d.ts +13 -0
  215. package/lib/Utils/meta-ai.js +74 -0
  216. package/lib/Utils/mini-app.d.ts +35 -0
  217. package/lib/Utils/mini-app.js +213 -0
  218. package/lib/Utils/noise-handler.d.ts +20 -0
  219. package/lib/Utils/noise-handler.js +200 -0
  220. package/lib/Utils/offline-node-processor.d.ts +9 -0
  221. package/lib/Utils/offline-node-processor.js +39 -0
  222. package/lib/Utils/past-participants.d.ts +14 -0
  223. package/lib/Utils/past-participants.js +40 -0
  224. package/lib/Utils/pre-key-manager.d.ts +25 -0
  225. package/lib/Utils/pre-key-manager.js +105 -0
  226. package/lib/Utils/process-message.d.ts +82 -0
  227. package/lib/Utils/process-message.js +808 -0
  228. package/lib/Utils/qr-render.d.ts +59 -0
  229. package/lib/Utils/qr-render.js +179 -0
  230. package/lib/Utils/qrcodegen.d.ts +79 -0
  231. package/lib/Utils/qrcodegen.js +848 -0
  232. package/lib/Utils/reporting-utils.d.ts +12 -0
  233. package/lib/Utils/reporting-utils.js +257 -0
  234. package/lib/Utils/rich-message-utils.d.ts +48 -0
  235. package/lib/Utils/rich-message-utils.js +444 -0
  236. package/lib/Utils/router.d.ts +37 -0
  237. package/lib/Utils/router.js +165 -0
  238. package/lib/Utils/scheduled-posts.d.ts +30 -0
  239. package/lib/Utils/scheduled-posts.js +110 -0
  240. package/lib/Utils/scheduling.d.ts +42 -0
  241. package/lib/Utils/scheduling.js +139 -0
  242. package/lib/Utils/signal.d.ts +82 -0
  243. package/lib/Utils/signal.js +200 -0
  244. package/lib/Utils/stanza-ack.d.ts +16 -0
  245. package/lib/Utils/stanza-ack.js +37 -0
  246. package/lib/Utils/status.d.ts +50 -0
  247. package/lib/Utils/status.js +107 -0
  248. package/lib/Utils/stickerpack.d.ts +51 -0
  249. package/lib/Utils/stickerpack.js +274 -0
  250. package/lib/Utils/sync-action-utils.d.ts +2 -0
  251. package/lib/Utils/sync-action-utils.js +48 -0
  252. package/lib/Utils/tag.d.ts +12 -0
  253. package/lib/Utils/tag.js +44 -0
  254. package/lib/Utils/tc-token-utils.d.ts +29 -0
  255. package/lib/Utils/tc-token-utils.js +162 -0
  256. package/lib/Utils/templates.d.ts +76 -0
  257. package/lib/Utils/templates.js +150 -0
  258. package/lib/Utils/transcribe.d.ts +12 -0
  259. package/lib/Utils/transcribe.js +107 -0
  260. package/lib/Utils/use-cache-manager-auth-state.d.ts +13 -0
  261. package/lib/Utils/use-cache-manager-auth-state.js +81 -0
  262. package/lib/Utils/use-multi-file-auth-state.d.ts +10 -0
  263. package/lib/Utils/use-multi-file-auth-state.js +166 -0
  264. package/lib/Utils/use-single-file-auth-state.d.ts +10 -0
  265. package/lib/Utils/use-single-file-auth-state.js +113 -0
  266. package/lib/Utils/use-sqlite-auth-state.d.ts +11 -0
  267. package/lib/Utils/use-sqlite-auth-state.js +169 -0
  268. package/lib/Utils/validate-connection.d.ts +42 -0
  269. package/lib/Utils/validate-connection.js +198 -0
  270. package/lib/Utils/vcard.d.ts +58 -0
  271. package/lib/Utils/vcard.js +104 -0
  272. package/lib/Utils/voice-note.d.ts +15 -0
  273. package/lib/Utils/voice-note.js +63 -0
  274. package/lib/VoIP/audio-feeder.d.ts +18 -0
  275. package/lib/VoIP/audio-feeder.js +160 -0
  276. package/lib/VoIP/call-recorder.d.ts +13 -0
  277. package/lib/VoIP/call-recorder.js +73 -0
  278. package/lib/VoIP/index.d.ts +86 -0
  279. package/lib/VoIP/index.js +611 -0
  280. package/lib/VoIP/relay-transport.d.ts +43 -0
  281. package/lib/VoIP/relay-transport.js +563 -0
  282. package/lib/VoIP/signaling.d.ts +26 -0
  283. package/lib/VoIP/signaling.js +662 -0
  284. package/lib/VoIP/types.d.ts +69 -0
  285. package/lib/VoIP/types.js +17 -0
  286. package/lib/VoIP/wasm-engine.d.ts +120 -0
  287. package/lib/VoIP/wasm-engine.js +1358 -0
  288. package/lib/VoIP/worker-bootstrap.d.ts +4 -0
  289. package/lib/VoIP/worker-bootstrap.js +1046 -0
  290. package/lib/WABinary/constants.d.ts +61 -0
  291. package/lib/WABinary/constants.js +1466 -0
  292. package/lib/WABinary/decode.d.ts +9 -0
  293. package/lib/WABinary/decode.js +261 -0
  294. package/lib/WABinary/encode.d.ts +2 -0
  295. package/lib/WABinary/encode.js +219 -0
  296. package/lib/WABinary/generic-utils.d.ts +74 -0
  297. package/lib/WABinary/generic-utils.js +276 -0
  298. package/lib/WABinary/index.d.ts +5 -0
  299. package/lib/WABinary/index.js +5 -0
  300. package/lib/WABinary/jid-utils.d.ts +28 -0
  301. package/lib/WABinary/jid-utils.js +95 -0
  302. package/lib/WABinary/types.d.ts +19 -0
  303. package/lib/WABinary/types.js +1 -0
  304. package/lib/WAM/BinaryInfo.d.ts +7 -0
  305. package/lib/WAM/BinaryInfo.js +9 -0
  306. package/lib/WAM/constants.d.ts +34926 -0
  307. package/lib/WAM/constants.js +22852 -0
  308. package/lib/WAM/encode.d.ts +1 -0
  309. package/lib/WAM/encode.js +149 -0
  310. package/lib/WAM/index.d.ts +3 -0
  311. package/lib/WAM/index.js +3 -0
  312. package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +36 -0
  313. package/lib/WAUSync/Protocols/USyncContactProtocol.js +51 -0
  314. package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +29 -0
  315. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +62 -0
  316. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
  317. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +26 -0
  318. package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
  319. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +37 -0
  320. package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +9 -0
  321. package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +24 -0
  322. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +38 -0
  323. package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -0
  324. package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +14 -0
  325. package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +28 -0
  326. package/lib/WAUSync/Protocols/index.d.ts +7 -0
  327. package/lib/WAUSync/Protocols/index.js +7 -0
  328. package/lib/WAUSync/USyncQuery.d.ts +20 -0
  329. package/lib/WAUSync/USyncQuery.js +121 -0
  330. package/lib/WAUSync/USyncUser.d.ts +16 -0
  331. package/lib/WAUSync/USyncUser.js +30 -0
  332. package/lib/WAUSync/index.d.ts +3 -0
  333. package/lib/WAUSync/index.js +3 -0
  334. package/lib/assets/wasm/loader.d.ts +5 -0
  335. package/lib/assets/wasm/loader.js +5 -0
  336. package/lib/assets/wasm/whatsapp.wasm +0 -0
  337. package/lib/assets/wasm/worker-modules.d.ts +5 -0
  338. package/lib/assets/wasm/worker-modules.js +273 -0
  339. package/lib/index.d.ts +18 -0
  340. package/lib/index.js +23 -0
  341. package/package.json +180 -0
  342. package/postinstall-banner.js +82 -0
@@ -0,0 +1,166 @@
1
+ import { Mutex } from 'async-mutex';
2
+ import { mkdir, readFile, readdir, 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
+ // We need to lock files due to the fact that we are using async functions to read and write files
8
+ // upstream issue #794
9
+ // https://github.com/nodejs/node/issues/26338
10
+ // Use a Map to store mutexes for each file path
11
+ const fileLocks = new Map();
12
+ // Get or create a mutex for a specific file path
13
+ const getFileLock = (path) => {
14
+ let mutex = fileLocks.get(path);
15
+ if (!mutex) {
16
+ mutex = new Mutex();
17
+ fileLocks.set(path, mutex);
18
+ }
19
+ return mutex;
20
+ };
21
+ // JAP@Fix 25-08-26 (ENOSPC guard) --- useMultiFileAuthState writes one small file PER key id
22
+ // (session-*, sender-key-*, sender-key-memory-*, pre-key-*, app-state-sync-key-*, ...) and never
23
+ // prunes any of them on its own. Over months of uptime — especially in busy groups, where a
24
+ // sender-key-memory file is created per (group, participant) pair — this silently accumulates into
25
+ // hundreds of thousands of tiny files. That can hit the filesystem's inode/file-count ceiling and
26
+ // start throwing ENOSPC on writes long before disk *space* usage looks anywhere near full (a
27
+ // classic symptom: panel shows plenty of free MiB/GiB, but writes still fail with ENOSPC). When
28
+ // that happens mid-session, auth writes (including the app-state-sync key from the "App state key
29
+ // not present!" issue) fail silently and never actually persist.
30
+ //
31
+ // `sender-key-memory-*` entries are pure dedup/anti-replay cache — safe to delete anytime; Baileys
32
+ // regenerates them on demand with zero functional loss (worst case: one redundant re-decrypt). They
33
+ // also tend to be the single biggest contributor to file count in active groups, so they're the
34
+ // safest and highest-impact thing to prune automatically. Everything else (creds, real sessions,
35
+ // pre-keys, app-state-sync-keys) is left completely untouched — this never touches those.
36
+ export const pruneStaleAuthFiles = async (folder, { maxAgeDays = 14, categories = ['sender-key-memory'], dryRun = false } = {}) => {
37
+ let entries;
38
+ try {
39
+ entries = await readdir(folder);
40
+ }
41
+ catch {
42
+ return { scanned: 0, removed: 0 };
43
+ }
44
+ const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1000;
45
+ let scanned = 0;
46
+ let removed = 0;
47
+ await Promise.all(entries.map(async (name) => {
48
+ if (!categories.some((cat) => name.startsWith(`${cat}-`) && name.endsWith('.json'))) return;
49
+ scanned++;
50
+ const filePath = join(folder, name);
51
+ try {
52
+ const info = await stat(filePath);
53
+ if (info.mtimeMs < cutoff) {
54
+ if (!dryRun) await unlink(filePath).catch(() => { });
55
+ removed++;
56
+ }
57
+ }
58
+ catch {
59
+ // file vanished between readdir and stat — fine, nothing to prune
60
+ }
61
+ }));
62
+ return { scanned, removed };
63
+ };
64
+ /**
65
+ * stores the full authentication state in a single folder.
66
+ * Far more efficient than singlefileauthstate
67
+ *
68
+ * Again, I wouldn't endorse this for any production level use other than perhaps a bot.
69
+ * Would recommend writing an auth state for use with a proper SQL or No-SQL DB
70
+ * */
71
+ export const useMultiFileAuthState = async (folder) => {
72
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
73
+ const writeData = async (data, file) => {
74
+ const filePath = join(folder, fixFileName(file));
75
+ const mutex = getFileLock(filePath);
76
+ return mutex.acquire().then(async (release) => {
77
+ try {
78
+ await writeFile(filePath, JSON.stringify(data, BufferJSON.replacer));
79
+ }
80
+ finally {
81
+ release();
82
+ }
83
+ });
84
+ };
85
+ const readData = async (file) => {
86
+ try {
87
+ const filePath = join(folder, fixFileName(file));
88
+ const mutex = getFileLock(filePath);
89
+ return await mutex.acquire().then(async (release) => {
90
+ try {
91
+ const data = await readFile(filePath, { encoding: 'utf-8' });
92
+ return JSON.parse(data, BufferJSON.reviver);
93
+ }
94
+ finally {
95
+ release();
96
+ }
97
+ });
98
+ }
99
+ catch (error) {
100
+ return null;
101
+ }
102
+ };
103
+ const removeData = async (file) => {
104
+ try {
105
+ const filePath = join(folder, fixFileName(file));
106
+ const mutex = getFileLock(filePath);
107
+ return mutex.acquire().then(async (release) => {
108
+ try {
109
+ await unlink(filePath);
110
+ }
111
+ catch {
112
+ }
113
+ finally {
114
+ release();
115
+ }
116
+ });
117
+ }
118
+ catch { }
119
+ };
120
+ const folderInfo = await stat(folder).catch(() => { });
121
+ if (folderInfo) {
122
+ if (!folderInfo.isDirectory()) {
123
+ throw new Error(`found something that is not a directory at ${folder}, either delete it or specify a different location`);
124
+ }
125
+ }
126
+ else {
127
+ await mkdir(folder, { recursive: true });
128
+ }
129
+ // JAP@Fix 25-08-26 (ENOSPC guard) --- best-effort prune on every startup. Failures here must
130
+ // never block auth from loading, so this is intentionally fire-and-forget with its own catch.
131
+ pruneStaleAuthFiles(folder).catch(() => { });
132
+ const fixFileName = (file) => file?.replace(/\//g, '__')?.replace(/:/g, '-');
133
+ const creds = (await readData('creds.json')) || initAuthCreds();
134
+ return {
135
+ state: {
136
+ creds,
137
+ keys: {
138
+ get: async (type, ids) => {
139
+ const data = {};
140
+ await Promise.all(ids.map(async (id) => {
141
+ let value = await readData(`${type}-${id}.json`);
142
+ if (type === 'app-state-sync-key' && value) {
143
+ value = proto.Message.AppStateSyncKeyData.fromObject(value);
144
+ }
145
+ data[id] = value;
146
+ }));
147
+ return data;
148
+ },
149
+ set: async (data) => {
150
+ const tasks = [];
151
+ for (const category in data) {
152
+ for (const id in data[category]) {
153
+ const value = data[category][id];
154
+ const file = `${category}-${id}.json`;
155
+ tasks.push(value ? writeData(value, file) : removeData(file));
156
+ }
157
+ }
158
+ await Promise.all(tasks);
159
+ }
160
+ }
161
+ },
162
+ saveCreds: async () => {
163
+ return writeData(creds, 'creds.json');
164
+ }
165
+ };
166
+ };
@@ -0,0 +1,10 @@
1
+ export function useSingleFileAuthState(fileName: any): Promise<{
2
+ state: {
3
+ creds: any;
4
+ keys: {
5
+ get: (type: any, ids: any) => {};
6
+ set: (data: any) => void;
7
+ };
8
+ };
9
+ saveCreds: () => void;
10
+ }>;
@@ -0,0 +1,113 @@
1
+ import { readFile, rename, stat, writeFile } from 'fs/promises';
2
+ import { DEFAULT_CACHE_TTLS } from '../Defaults/index.js';
3
+ import { proto } from '../../WAProto/index.js';
4
+ import { initAuthCreds } from './auth-utils.js';
5
+ import { BufferJSON } from './generics.js';
6
+ import { LRUCache } from 'lru-cache';
7
+ import { Mutex } from 'async-mutex';
8
+ import defaultLogger from './logger.js';
9
+ // JAP@Changes 25-03-26 --- Add useSingleFileAuthState with integrated cache
10
+ const FLUSH_TIMEOUT_MS = 3000;
11
+ // JAP@Changes 22-04-26 --- Enhanced useSingleFileAuthState with LRUCache
12
+ export const useSingleFileAuthState = async (fileName) => {
13
+ const cache = new LRUCache({
14
+ max: 20000,
15
+ ttl: 1000 * DEFAULT_CACHE_TTLS.SIGNAL_STORE,
16
+ updateAgeOnGet: false,
17
+ updateAgeOnHas: false,
18
+ ttlAutopurge: true
19
+ });
20
+ // JAP@Changes 26-04-26 --- Add mutex for prevent race condition
21
+ const mutex = new Mutex();
22
+ let fileData = {};
23
+ let isLoaded = false;
24
+ let flushTimeout = null;
25
+ const loadKey = async () => {
26
+ return await mutex.runExclusive(async () => {
27
+ if (isLoaded)
28
+ return;
29
+ try {
30
+ const data = JSON.parse(await readFile(fileName, 'utf-8'), BufferJSON.reviver);
31
+ fileData = data || {};
32
+ for (const [keyName, value] of Object.entries(fileData)) {
33
+ cache.set(keyName, value);
34
+ }
35
+ }
36
+ catch {
37
+ fileData = {};
38
+ }
39
+ isLoaded = true;
40
+ });
41
+ };
42
+ const flushKey = () => {
43
+ if (flushTimeout)
44
+ return;
45
+ flushTimeout = setTimeout(async () => {
46
+ flushTimeout = null;
47
+ await mutex.runExclusive(async () => {
48
+ try {
49
+ const tempFile = fileName + '.temp';
50
+ await writeFile(tempFile, JSON.stringify(fileData, BufferJSON.replacer));
51
+ await rename(tempFile, fileName);
52
+ }
53
+ catch (err) {
54
+ // JAP@Fix (bug 58): was silently swallowed — auth session could fail
55
+ // to persist (disk full, permission error, etc.) with zero trace.
56
+ defaultLogger.error({ err, fileName }, 'failed to flush auth state to disk');
57
+ }
58
+ });
59
+ }, FLUSH_TIMEOUT_MS);
60
+ };
61
+ const writeKey = (keyName, value) => {
62
+ cache.set(keyName, value);
63
+ fileData[keyName] = value;
64
+ flushKey();
65
+ };
66
+ const removeKey = (keyName) => {
67
+ cache.delete(keyName);
68
+ delete fileData[keyName];
69
+ flushKey();
70
+ };
71
+ const fileInfo = await stat(fileName).catch(() => null);
72
+ if (!fileInfo) {
73
+ await writeFile(fileName, '{}');
74
+ }
75
+ else if (!fileInfo.isFile()) {
76
+ throw new Error(`found something that is not a file at ${fileName}, either delete it or specify a different location`);
77
+ }
78
+ await loadKey();
79
+ const creds = fileData['creds'] || initAuthCreds();
80
+ return {
81
+ state: {
82
+ creds,
83
+ keys: {
84
+ get: (type, ids) => {
85
+ const data = {};
86
+ for (const id of ids) {
87
+ const keyName = type + id;
88
+ let value = cache.get(keyName);
89
+ if (value === undefined && fileData[keyName] !== undefined) {
90
+ value = fileData[keyName];
91
+ cache.set(keyName, value);
92
+ }
93
+ if (type === 'app-state-sync-key' && value) {
94
+ value = proto.Message.AppStateSyncKeyData.fromObject(value);
95
+ }
96
+ data[id] = value;
97
+ }
98
+ return data;
99
+ },
100
+ set: (data) => {
101
+ for (const category in data) {
102
+ for (const id in data[category]) {
103
+ const keyName = category + id;
104
+ const value = data[category][id];
105
+ value ? writeKey(keyName, value) : removeKey(keyName);
106
+ }
107
+ }
108
+ }
109
+ }
110
+ },
111
+ saveCreds: () => writeKey('creds', creds)
112
+ };
113
+ };
@@ -0,0 +1,11 @@
1
+ export function useSqliteAuthState(opts: 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<void>;
10
+ close: () => Promise<void>;
11
+ }>;
@@ -0,0 +1,169 @@
1
+ import { mkdir, readFile, stat, unlink, writeFile } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import { proto } from '../../WAProto/index.js';
4
+ import { initAuthCreds } from './auth-utils.js';
5
+ import { BufferJSON } from './generics.js';
6
+ async function loadBetterSqlite3() {
7
+ try {
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ const mod = (await import('better-sqlite3'));
10
+ return mod.default ?? mod;
11
+ }
12
+ catch (err) {
13
+ const helpful = new Error('`better-sqlite3` is required for `useSqliteAuthState`. Install it as a peer dependency: `npm install better-sqlite3` (or `yarn add better-sqlite3`).');
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ helpful.cause = err;
16
+ throw helpful;
17
+ }
18
+ }
19
+ const CREDS_ROW_KEY = '__creds__';
20
+ const CREATE_SCHEMA_SQL = `
21
+ CREATE TABLE IF NOT EXISTS creds (
22
+ key TEXT PRIMARY KEY,
23
+ value TEXT NOT NULL
24
+ );
25
+ CREATE TABLE IF NOT EXISTS signal_keys (
26
+ type TEXT NOT NULL,
27
+ id TEXT NOT NULL,
28
+ value TEXT NOT NULL,
29
+ PRIMARY KEY (type, id)
30
+ );
31
+ CREATE INDEX IF NOT EXISTS signal_keys_type_idx ON signal_keys(type);
32
+ `;
33
+ // JAP@Add 29-08-26 --- Migration tracking for the auth-state schema,
34
+ // wa_migrations pattern (packages/store-sqlite/src/migrations.ts). Each entry
35
+ // is `{ id, sql }`; applied migrations are recorded by id in `wa_migrations`
36
+ // so `db.exec(...)` schema changes are only ever run once per database file,
37
+ // letting future releases evolve the schema without a manual ALTER step from
38
+ // the user. Kept as an ordered array (not a folder of files) since the schema
39
+ // here is a single flat file with per-domain version keys.
40
+ const MIGRATIONS = [
41
+ { id: '0001_init', sql: CREATE_SCHEMA_SQL }
42
+ ];
43
+ function ensureMigrationsTable(db) {
44
+ db.exec('CREATE TABLE IF NOT EXISTS wa_migrations (id TEXT PRIMARY KEY, applied_at INTEGER NOT NULL)');
45
+ }
46
+ function runMigrations(db) {
47
+ ensureMigrationsTable(db);
48
+ const applied = new Set(db.prepare('SELECT id FROM wa_migrations').all().map((r) => r.id));
49
+ const insertMigration = db.prepare('INSERT INTO wa_migrations (id, applied_at) VALUES (?, ?)');
50
+ for (const migration of MIGRATIONS) {
51
+ if (applied.has(migration.id))
52
+ continue;
53
+ const tx = db.transaction(() => {
54
+ db.exec(migration.sql);
55
+ insertMigration.run(migration.id, Date.now());
56
+ });
57
+ tx();
58
+ }
59
+ }
60
+ export async function useSqliteAuthState(opts) {
61
+ let db;
62
+ if (opts.database) {
63
+ db = opts.database;
64
+ }
65
+ else {
66
+ const Database = await loadBetterSqlite3();
67
+ db = new Database(opts.dbPath);
68
+ }
69
+ // WAL mode allows concurrent reads alongside a single writer; matches
70
+ // what SQLite recommends for read-heavy workloads with sporadic writes.
71
+ db.pragma('journal_mode = WAL');
72
+ db.pragma('synchronous = NORMAL');
73
+ runMigrations(db);
74
+ // JAP@Fix (bug 8): periodic WAL checkpoint + cleanup old signal keys to prevent DB bloat.
75
+ // Runs every 30 minutes. WAL checkpoint reclaims WAL file space; key cleanup removes stale session entries.
76
+ const _walCleanupInterval = setInterval(() => {
77
+ try {
78
+ db.pragma('wal_checkpoint(PASSIVE)');
79
+ // Remove signal keys older than 30 days (pre-keys, session keys that have expired)
80
+ // Only removes types that are safe to prune (not creds or app-state-sync-key)
81
+ const pruneTypes = ['pre-key', 'session'];
82
+ for (const type of pruneTypes) {
83
+ try {
84
+ // Keep last 500 per type to avoid breaking active sessions
85
+ db.prepare(`
86
+ DELETE FROM signal_keys WHERE type = ? AND id NOT IN (
87
+ SELECT id FROM signal_keys WHERE type = ? ORDER BY rowid DESC LIMIT 500
88
+ )
89
+ `).run(type, type);
90
+ } catch { /* ignore per-type errors */ }
91
+ }
92
+ } catch { /* ignore checkpoint errors — non-fatal */ }
93
+ }, 30 * 60 * 1000);
94
+ // Allow Node process to exit even if interval is still running
95
+ if (_walCleanupInterval.unref) _walCleanupInterval.unref();
96
+ const stmts = {
97
+ credsSelect: db.prepare('SELECT value FROM creds WHERE key = ?'),
98
+ credsUpsert: db.prepare('INSERT INTO creds (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value'),
99
+ keySelect: db.prepare('SELECT value FROM signal_keys WHERE type = ? AND id = ?'),
100
+ keyUpsert: db.prepare('INSERT INTO signal_keys (type, id, value) VALUES (?, ?, ?) ON CONFLICT(type, id) DO UPDATE SET value = excluded.value'),
101
+ keyDelete: db.prepare('DELETE FROM signal_keys WHERE type = ? AND id = ?'),
102
+ keyListIds: db.prepare('SELECT id FROM signal_keys WHERE type = ?'),
103
+ keyList: db.prepare('SELECT id, value FROM signal_keys WHERE type = ?'),
104
+ clearKeys: db.prepare('DELETE FROM signal_keys')
105
+ };
106
+ const loadCreds = () => {
107
+ const row = stmts.credsSelect.get(CREDS_ROW_KEY);
108
+ if (!row)
109
+ return initAuthCreds();
110
+ return JSON.parse(row.value, BufferJSON.reviver);
111
+ };
112
+ const persistCreds = (creds) => {
113
+ stmts.credsUpsert.run(CREDS_ROW_KEY, JSON.stringify(creds, BufferJSON.replacer));
114
+ };
115
+ const creds = loadCreds();
116
+ return {
117
+ state: {
118
+ creds,
119
+ keys: {
120
+ get: async (type, ids) => {
121
+ const data = {};
122
+ for (const id of ids) {
123
+ const row = stmts.keySelect.get(type, id);
124
+ if (row) {
125
+ let value = JSON.parse(row.value, BufferJSON.reviver);
126
+ if (type === 'app-state-sync-key' && value) {
127
+ value = proto.Message.AppStateSyncKeyData.fromObject(value);
128
+ }
129
+ data[id] = value;
130
+ }
131
+ }
132
+ return data;
133
+ },
134
+ set: async (data) => {
135
+ const writeTx = db.transaction(() => {
136
+ for (const category in data) {
137
+ for (const id in data[category]) {
138
+ const value = data[category][id];
139
+ if (value) {
140
+ const stringified = JSON.stringify(value, BufferJSON.replacer);
141
+ stmts.keyUpsert.run(category, id, stringified);
142
+ }
143
+ else {
144
+ stmts.keyDelete.run(category, id);
145
+ }
146
+ }
147
+ }
148
+ });
149
+ writeTx();
150
+ }
151
+ }
152
+ },
153
+ saveCreds: async () => {
154
+ persistCreds(creds);
155
+ },
156
+ // JAP@Fix: release the WAL cleanup interval and (if we opened it ourselves)
157
+ // the underlying db handle. Without this, every useSqliteAuthState() call
158
+ // (e.g. re-pairing / rotating sessions) leaked a timer + open sqlite fd forever.
159
+ close: async () => {
160
+ clearInterval(_walCleanupInterval);
161
+ if (!opts.database) {
162
+ try {
163
+ db.close();
164
+ }
165
+ catch { /* already closed */ }
166
+ }
167
+ }
168
+ };
169
+ }
@@ -0,0 +1,42 @@
1
+ export function generateLoginNode(userJid: any, config: any): any;
2
+ export function generateRegistrationNode({ registrationId, signedPreKey, signedIdentityKey }: {
3
+ registrationId: any;
4
+ signedPreKey: any;
5
+ signedIdentityKey: any;
6
+ }, config: any): any;
7
+ export function configureSuccessfulPairing(stanza: any, { advSecretKey, signedIdentityKey, signalIdentities }: {
8
+ advSecretKey: any;
9
+ signedIdentityKey: any;
10
+ signalIdentities: any;
11
+ }): {
12
+ creds: {
13
+ account: any;
14
+ me: {
15
+ id: any;
16
+ name: any;
17
+ lid: any;
18
+ };
19
+ signalIdentities: any[];
20
+ platform: any;
21
+ };
22
+ reply: {
23
+ tag: string;
24
+ attrs: {
25
+ to: string;
26
+ type: string;
27
+ id: any;
28
+ };
29
+ content: {
30
+ tag: string;
31
+ attrs: {};
32
+ content: {
33
+ tag: string;
34
+ attrs: {
35
+ 'key-index': any;
36
+ };
37
+ content: any;
38
+ }[];
39
+ }[];
40
+ };
41
+ };
42
+ export function encodeSignedDeviceIdentity(account: any, includeSignatureKey: any): any;