@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.
- package/NOTICE.md +111 -0
- package/README.md +1254 -0
- package/WAProto/index.d.ts +9 -0
- package/WAProto/index.js +142276 -0
- package/engine-requirements.js +13 -0
- package/lib/Builders/A2UI.d.ts +242 -0
- package/lib/Builders/A2UI.js +308 -0
- package/lib/Builders/AIRich.d.ts +105 -0
- package/lib/Builders/AIRich.js +2286 -0
- package/lib/Builders/Button.d.ts +103 -0
- package/lib/Builders/Button.js +883 -0
- package/lib/Builders/ButtonV2.d.ts +28 -0
- package/lib/Builders/ButtonV2.js +144 -0
- package/lib/Builders/ButtonV3.d.ts +25 -0
- package/lib/Builders/ButtonV3.js +184 -0
- package/lib/Builders/Carousel.d.ts +22 -0
- package/lib/Builders/Carousel.js +111 -0
- package/lib/Builders/JapBaileys.d.ts +34 -0
- package/lib/Builders/JapBaileys.js +108 -0
- package/lib/Builders/Poll.d.ts +25 -0
- package/lib/Builders/Poll.js +128 -0
- package/lib/Builders/index.d.ts +17 -0
- package/lib/Builders/index.js +11 -0
- package/lib/Builders/shared.d.ts +67 -0
- package/lib/Builders/shared.js +652 -0
- package/lib/Defaults/index.d.ts +154 -0
- package/lib/Defaults/index.js +178 -0
- package/lib/Framework/Bot.d.ts +61 -0
- package/lib/Framework/Bot.js +248 -0
- package/lib/Framework/Context.d.ts +21 -0
- package/lib/Framework/Context.js +89 -0
- package/lib/Framework/MediaManager.d.ts +17 -0
- package/lib/Framework/MediaManager.js +151 -0
- package/lib/Framework/SessionManager.d.ts +13 -0
- package/lib/Framework/SessionManager.js +33 -0
- package/lib/Framework/StatsManager.d.ts +26 -0
- package/lib/Framework/StatsManager.js +119 -0
- package/lib/Framework/Store/SQLiteStore.d.ts +11 -0
- package/lib/Framework/Store/SQLiteStore.js +73 -0
- package/lib/Framework/index.d.ts +9 -0
- package/lib/Framework/index.js +10 -0
- package/lib/Signal/Group/ciphertext-message.d.ts +9 -0
- package/lib/Signal/Group/ciphertext-message.js +11 -0
- package/lib/Signal/Group/group-session-builder.d.ts +7 -0
- package/lib/Signal/Group/group-session-builder.js +29 -0
- package/lib/Signal/Group/group_cipher.d.ts +10 -0
- package/lib/Signal/Group/group_cipher.js +81 -0
- package/lib/Signal/Group/index.d.ts +11 -0
- package/lib/Signal/Group/index.js +11 -0
- package/lib/Signal/Group/keyhelper.d.ts +6 -0
- package/lib/Signal/Group/keyhelper.js +17 -0
- package/lib/Signal/Group/sender-chain-key.d.ts +13 -0
- package/lib/Signal/Group/sender-chain-key.js +25 -0
- package/lib/Signal/Group/sender-key-distribution-message.d.ts +16 -0
- package/lib/Signal/Group/sender-key-distribution-message.js +62 -0
- package/lib/Signal/Group/sender-key-message.d.ts +18 -0
- package/lib/Signal/Group/sender-key-message.js +65 -0
- package/lib/Signal/Group/sender-key-name.d.ts +11 -0
- package/lib/Signal/Group/sender-key-name.js +47 -0
- package/lib/Signal/Group/sender-key-record.d.ts +12 -0
- package/lib/Signal/Group/sender-key-record.js +40 -0
- package/lib/Signal/Group/sender-key-state.d.ts +16 -0
- package/lib/Signal/Group/sender-key-state.js +83 -0
- package/lib/Signal/Group/sender-message-key.d.ts +11 -0
- package/lib/Signal/Group/sender-message-key.js +25 -0
- package/lib/Signal/libsignal.d.ts +54 -0
- package/lib/Signal/libsignal.js +430 -0
- package/lib/Signal/lid-mapping.d.ts +20 -0
- package/lib/Signal/lid-mapping.js +276 -0
- package/lib/Socket/Client/index.d.ts +2 -0
- package/lib/Socket/Client/index.js +2 -0
- package/lib/Socket/Client/types.d.ts +5 -0
- package/lib/Socket/Client/types.js +10 -0
- package/lib/Socket/Client/websocket.d.ts +12 -0
- package/lib/Socket/Client/websocket.js +53 -0
- package/lib/Socket/business.d.ts +395 -0
- package/lib/Socket/business.js +379 -0
- package/lib/Socket/chats.d.ts +136 -0
- package/lib/Socket/chats.js +1327 -0
- package/lib/Socket/communities.d.ts +562 -0
- package/lib/Socket/communities.js +439 -0
- package/lib/Socket/dugong.d.ts +117 -0
- package/lib/Socket/dugong.js +798 -0
- package/lib/Socket/groups.d.ts +285 -0
- package/lib/Socket/groups.js +354 -0
- package/lib/Socket/index.d.ts +585 -0
- package/lib/Socket/index.js +52 -0
- package/lib/Socket/messages-recv.d.ts +333 -0
- package/lib/Socket/messages-recv.js +1781 -0
- package/lib/Socket/messages-send.d.ts +353 -0
- package/lib/Socket/messages-send.js +1524 -0
- package/lib/Socket/mex.d.ts +1 -0
- package/lib/Socket/mex.js +41 -0
- package/lib/Socket/newsletter.d.ts +286 -0
- package/lib/Socket/newsletter.js +364 -0
- package/lib/Socket/socket.d.ts +60 -0
- package/lib/Socket/socket.js +1012 -0
- package/lib/Socket/username.d.ts +82 -0
- package/lib/Socket/username.js +159 -0
- package/lib/Store/index.d.ts +3 -0
- package/lib/Store/index.js +3 -0
- package/lib/Store/make-in-memory-store.d.ts +62 -0
- package/lib/Store/make-in-memory-store.js +428 -0
- package/lib/Store/make-ordered-dictionary.d.ts +12 -0
- package/lib/Store/make-ordered-dictionary.js +78 -0
- package/lib/Store/object-repository.d.ts +10 -0
- package/lib/Store/object-repository.js +23 -0
- package/lib/Types/Auth.d.ts +117 -0
- package/lib/Types/Auth.js +1 -0
- package/lib/Types/Bussines.d.ts +25 -0
- package/lib/Types/Call.d.ts +15 -0
- package/lib/Types/Call.js +1 -0
- package/lib/Types/Chat.d.ts +124 -0
- package/lib/Types/Chat.js +7 -0
- package/lib/Types/Contact.d.ts +26 -0
- package/lib/Types/Contact.js +1 -0
- package/lib/Types/Events.d.ts +256 -0
- package/lib/Types/Events.js +1 -0
- package/lib/Types/GroupMetadata.d.ts +71 -0
- package/lib/Types/GroupMetadata.js +1 -0
- package/lib/Types/Label.d.ts +5 -0
- package/lib/Types/Label.js +24 -0
- package/lib/Types/LabelAssociation.d.ts +6 -0
- package/lib/Types/LabelAssociation.js +6 -0
- package/lib/Types/Message.d.ts +62 -0
- package/lib/Types/Message.js +17 -0
- package/lib/Types/Mex.d.ts +2 -0
- package/lib/Types/Mex.js +38 -0
- package/lib/Types/Product.d.ts +79 -0
- package/lib/Types/Product.js +1 -0
- package/lib/Types/RichType.d.ts +2 -0
- package/lib/Types/RichType.js +22 -0
- package/lib/Types/Signal.d.ts +87 -0
- package/lib/Types/Signal.js +1 -0
- package/lib/Types/Socket.d.ts +138 -0
- package/lib/Types/Socket.js +1 -0
- package/lib/Types/State.d.ts +8 -0
- package/lib/Types/State.js +55 -0
- package/lib/Types/USync.d.ts +26 -0
- package/lib/Types/index.d.ts +68 -0
- package/lib/Types/index.js +27 -0
- package/lib/Utils/MessageBuilder.d.ts +2 -0
- package/lib/Utils/MessageBuilder.js +2 -0
- package/lib/Utils/PersistentStore.d.ts +60 -0
- package/lib/Utils/PersistentStore.js +592 -0
- package/lib/Utils/anti-delete.d.ts +74 -0
- package/lib/Utils/anti-delete.js +221 -0
- package/lib/Utils/auth-secure.d.ts +86 -0
- package/lib/Utils/auth-secure.js +764 -0
- package/lib/Utils/auth-utils.d.ts +57 -0
- package/lib/Utils/auth-utils.js +306 -0
- package/lib/Utils/auto-reply.d.ts +47 -0
- package/lib/Utils/auto-reply.js +157 -0
- package/lib/Utils/baileys-event-stream.d.ts +8 -0
- package/lib/Utils/baileys-event-stream.js +62 -0
- package/lib/Utils/browser-utils.d.ts +8 -0
- package/lib/Utils/browser-utils.js +27 -0
- package/lib/Utils/business.d.ts +49 -0
- package/lib/Utils/business.js +239 -0
- package/lib/Utils/button-helper-utils.d.ts +53 -0
- package/lib/Utils/button-helper-utils.js +312 -0
- package/lib/Utils/button-sender.d.ts +54 -0
- package/lib/Utils/button-sender.js +822 -0
- package/lib/Utils/chat-control.d.ts +159 -0
- package/lib/Utils/chat-control.js +230 -0
- package/lib/Utils/chat-history-helpers.d.ts +21 -0
- package/lib/Utils/chat-history-helpers.js +70 -0
- package/lib/Utils/chat-utils.d.ts +407 -0
- package/lib/Utils/chat-utils.js +885 -0
- package/lib/Utils/companion-reg-client-utils.d.ts +4 -0
- package/lib/Utils/companion-reg-client-utils.js +39 -0
- package/lib/Utils/crypto.d.ts +41 -0
- package/lib/Utils/crypto.js +147 -0
- package/lib/Utils/decode-wa-message.d.ts +83 -0
- package/lib/Utils/decode-wa-message.js +316 -0
- package/lib/Utils/event-buffer.d.ts +12 -0
- package/lib/Utils/event-buffer.js +635 -0
- package/lib/Utils/generics.d.ts +69 -0
- package/lib/Utils/generics.js +438 -0
- package/lib/Utils/history-share.d.ts +11 -0
- package/lib/Utils/history-share.js +70 -0
- package/lib/Utils/history.d.ts +90 -0
- package/lib/Utils/history.js +146 -0
- package/lib/Utils/humanizer.d.ts +12 -0
- package/lib/Utils/humanizer.js +73 -0
- package/lib/Utils/identity-change-handler.d.ts +13 -0
- package/lib/Utils/identity-change-handler.js +49 -0
- package/lib/Utils/index.d.ts +57 -0
- package/lib/Utils/index.js +56 -0
- package/lib/Utils/jid-tools.d.ts +6 -0
- package/lib/Utils/jid-tools.js +77 -0
- package/lib/Utils/link-preview.d.ts +12 -0
- package/lib/Utils/link-preview.js +84 -0
- package/lib/Utils/logger.d.ts +4 -0
- package/lib/Utils/logger.js +2 -0
- package/lib/Utils/lt-hash.d.ts +12 -0
- package/lib/Utils/lt-hash.js +26 -0
- package/lib/Utils/make-mutex.d.ts +6 -0
- package/lib/Utils/make-mutex.js +32 -0
- package/lib/Utils/media-messages.d.ts +18 -0
- package/lib/Utils/media-messages.js +70 -0
- package/lib/Utils/media-set.d.ts +13 -0
- package/lib/Utils/media-set.js +171 -0
- package/lib/Utils/message-kind.d.ts +32 -0
- package/lib/Utils/message-kind.js +136 -0
- package/lib/Utils/message-retry-manager.d.ts +79 -0
- package/lib/Utils/message-retry-manager.js +264 -0
- package/lib/Utils/message-search.d.ts +44 -0
- package/lib/Utils/message-search.js +188 -0
- package/lib/Utils/messages-media.d.ts +135 -0
- package/lib/Utils/messages-media.js +868 -0
- package/lib/Utils/messages.d.ts +44 -0
- package/lib/Utils/messages.js +2326 -0
- package/lib/Utils/meta-ai.d.ts +13 -0
- package/lib/Utils/meta-ai.js +74 -0
- package/lib/Utils/mini-app.d.ts +35 -0
- package/lib/Utils/mini-app.js +213 -0
- package/lib/Utils/noise-handler.d.ts +20 -0
- package/lib/Utils/noise-handler.js +200 -0
- package/lib/Utils/offline-node-processor.d.ts +9 -0
- package/lib/Utils/offline-node-processor.js +39 -0
- package/lib/Utils/past-participants.d.ts +14 -0
- package/lib/Utils/past-participants.js +40 -0
- package/lib/Utils/pre-key-manager.d.ts +25 -0
- package/lib/Utils/pre-key-manager.js +105 -0
- package/lib/Utils/process-message.d.ts +82 -0
- package/lib/Utils/process-message.js +808 -0
- package/lib/Utils/qr-render.d.ts +59 -0
- package/lib/Utils/qr-render.js +179 -0
- package/lib/Utils/qrcodegen.d.ts +79 -0
- package/lib/Utils/qrcodegen.js +848 -0
- package/lib/Utils/reporting-utils.d.ts +12 -0
- package/lib/Utils/reporting-utils.js +257 -0
- package/lib/Utils/rich-message-utils.d.ts +48 -0
- package/lib/Utils/rich-message-utils.js +444 -0
- package/lib/Utils/router.d.ts +37 -0
- package/lib/Utils/router.js +165 -0
- package/lib/Utils/scheduled-posts.d.ts +30 -0
- package/lib/Utils/scheduled-posts.js +110 -0
- package/lib/Utils/scheduling.d.ts +42 -0
- package/lib/Utils/scheduling.js +139 -0
- package/lib/Utils/signal.d.ts +82 -0
- package/lib/Utils/signal.js +200 -0
- package/lib/Utils/stanza-ack.d.ts +16 -0
- package/lib/Utils/stanza-ack.js +37 -0
- package/lib/Utils/status.d.ts +50 -0
- package/lib/Utils/status.js +107 -0
- package/lib/Utils/stickerpack.d.ts +51 -0
- package/lib/Utils/stickerpack.js +274 -0
- package/lib/Utils/sync-action-utils.d.ts +2 -0
- package/lib/Utils/sync-action-utils.js +48 -0
- package/lib/Utils/tag.d.ts +12 -0
- package/lib/Utils/tag.js +44 -0
- package/lib/Utils/tc-token-utils.d.ts +29 -0
- package/lib/Utils/tc-token-utils.js +162 -0
- package/lib/Utils/templates.d.ts +76 -0
- package/lib/Utils/templates.js +150 -0
- package/lib/Utils/transcribe.d.ts +12 -0
- package/lib/Utils/transcribe.js +107 -0
- package/lib/Utils/use-cache-manager-auth-state.d.ts +13 -0
- package/lib/Utils/use-cache-manager-auth-state.js +81 -0
- package/lib/Utils/use-multi-file-auth-state.d.ts +10 -0
- package/lib/Utils/use-multi-file-auth-state.js +166 -0
- package/lib/Utils/use-single-file-auth-state.d.ts +10 -0
- package/lib/Utils/use-single-file-auth-state.js +113 -0
- package/lib/Utils/use-sqlite-auth-state.d.ts +11 -0
- package/lib/Utils/use-sqlite-auth-state.js +169 -0
- package/lib/Utils/validate-connection.d.ts +42 -0
- package/lib/Utils/validate-connection.js +198 -0
- package/lib/Utils/vcard.d.ts +58 -0
- package/lib/Utils/vcard.js +104 -0
- package/lib/Utils/voice-note.d.ts +15 -0
- package/lib/Utils/voice-note.js +63 -0
- package/lib/VoIP/audio-feeder.d.ts +18 -0
- package/lib/VoIP/audio-feeder.js +160 -0
- package/lib/VoIP/call-recorder.d.ts +13 -0
- package/lib/VoIP/call-recorder.js +73 -0
- package/lib/VoIP/index.d.ts +86 -0
- package/lib/VoIP/index.js +611 -0
- package/lib/VoIP/relay-transport.d.ts +43 -0
- package/lib/VoIP/relay-transport.js +563 -0
- package/lib/VoIP/signaling.d.ts +26 -0
- package/lib/VoIP/signaling.js +662 -0
- package/lib/VoIP/types.d.ts +69 -0
- package/lib/VoIP/types.js +17 -0
- package/lib/VoIP/wasm-engine.d.ts +120 -0
- package/lib/VoIP/wasm-engine.js +1358 -0
- package/lib/VoIP/worker-bootstrap.d.ts +4 -0
- package/lib/VoIP/worker-bootstrap.js +1046 -0
- package/lib/WABinary/constants.d.ts +61 -0
- package/lib/WABinary/constants.js +1466 -0
- package/lib/WABinary/decode.d.ts +9 -0
- package/lib/WABinary/decode.js +261 -0
- package/lib/WABinary/encode.d.ts +2 -0
- package/lib/WABinary/encode.js +219 -0
- package/lib/WABinary/generic-utils.d.ts +74 -0
- package/lib/WABinary/generic-utils.js +276 -0
- package/lib/WABinary/index.d.ts +5 -0
- package/lib/WABinary/index.js +5 -0
- package/lib/WABinary/jid-utils.d.ts +28 -0
- package/lib/WABinary/jid-utils.js +95 -0
- package/lib/WABinary/types.d.ts +19 -0
- package/lib/WABinary/types.js +1 -0
- package/lib/WAM/BinaryInfo.d.ts +7 -0
- package/lib/WAM/BinaryInfo.js +9 -0
- package/lib/WAM/constants.d.ts +34926 -0
- package/lib/WAM/constants.js +22852 -0
- package/lib/WAM/encode.d.ts +1 -0
- package/lib/WAM/encode.js +149 -0
- package/lib/WAM/index.d.ts +3 -0
- package/lib/WAM/index.js +3 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.d.ts +36 -0
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +51 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.d.ts +29 -0
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +62 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +26 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.d.ts +12 -0
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +37 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.d.ts +9 -0
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +24 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.d.ts +38 -0
- package/lib/WAUSync/Protocols/UsyncBotProfileProtocol.js +50 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.d.ts +14 -0
- package/lib/WAUSync/Protocols/UsyncLIDProtocol.js +28 -0
- package/lib/WAUSync/Protocols/index.d.ts +7 -0
- package/lib/WAUSync/Protocols/index.js +7 -0
- package/lib/WAUSync/USyncQuery.d.ts +20 -0
- package/lib/WAUSync/USyncQuery.js +121 -0
- package/lib/WAUSync/USyncUser.d.ts +16 -0
- package/lib/WAUSync/USyncUser.js +30 -0
- package/lib/WAUSync/index.d.ts +3 -0
- package/lib/WAUSync/index.js +3 -0
- package/lib/assets/wasm/loader.d.ts +5 -0
- package/lib/assets/wasm/loader.js +5 -0
- package/lib/assets/wasm/whatsapp.wasm +0 -0
- package/lib/assets/wasm/worker-modules.d.ts +5 -0
- package/lib/assets/wasm/worker-modules.js +273 -0
- package/lib/index.d.ts +18 -0
- package/lib/index.js +23 -0
- package/package.json +180 -0
- 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,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,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;
|