@pontalabs/baileys 1.0.10 → 1.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 (119) hide show
  1. package/README.md +96 -85
  2. package/lib/Defaults/connection.js +39 -0
  3. package/lib/Defaults/constants.js +50 -0
  4. package/lib/Defaults/history.js +13 -0
  5. package/lib/Defaults/index.js +36 -151
  6. package/lib/Defaults/media.js +43 -0
  7. package/lib/Defaults/phonenumber-mcc.json +221 -221
  8. package/lib/Defaults/prefix.js +12 -0
  9. package/lib/Defaults/vialeys-version.json +7 -0
  10. package/lib/Signal/Group/ciphertext-message.js +10 -15
  11. package/lib/Signal/Group/group-session-builder.js +34 -60
  12. package/lib/Signal/Group/group_cipher.js +69 -76
  13. package/lib/Signal/Group/index.js +41 -60
  14. package/lib/Signal/Group/keyhelper.js +12 -57
  15. package/lib/Signal/Group/sender-chain-key.js +20 -33
  16. package/lib/Signal/Group/sender-key-distribution-message.js +43 -48
  17. package/lib/Signal/Group/sender-key-message.js +58 -53
  18. package/lib/Signal/Group/sender-key-name.js +21 -31
  19. package/lib/Signal/Group/sender-key-record.js +21 -34
  20. package/lib/Signal/Group/sender-key-state.js +59 -106
  21. package/lib/Signal/Group/sender-message-key.js +16 -21
  22. package/lib/Signal/libsignal.js +282 -203
  23. package/lib/Signal/lid-mapping.js +164 -184
  24. package/lib/Socket/Client/index.js +31 -22
  25. package/lib/Socket/Client/types.js +9 -15
  26. package/lib/Socket/Client/websocket.js +42 -37
  27. package/lib/Socket/business.js +212 -336
  28. package/lib/Socket/chats.js +696 -940
  29. package/lib/Socket/community.js +454 -369
  30. package/lib/Socket/groups.js +278 -280
  31. package/lib/Socket/index.js +9 -21
  32. package/lib/Socket/messages-recv.js +1027 -1570
  33. package/lib/Socket/messages-send.js +1180 -1136
  34. package/lib/Socket/mex.js +59 -0
  35. package/lib/Socket/newsletter.js +193 -251
  36. package/lib/Socket/socket.js +758 -898
  37. package/lib/Store/index.js +35 -24
  38. package/lib/Store/make-cache-manager-store.js +53 -66
  39. package/lib/Store/make-in-memory-store.js +319 -325
  40. package/lib/Store/make-ordered-dictionary.js +49 -57
  41. package/lib/Store/object-repository.js +10 -15
  42. package/lib/Types/Auth.js +2 -3
  43. package/lib/Types/Bussines.js +2 -3
  44. package/lib/Types/Call.js +2 -3
  45. package/lib/Types/Chat.js +10 -9
  46. package/lib/Types/Contact.js +2 -3
  47. package/lib/Types/Events.js +2 -3
  48. package/lib/Types/GroupMetadata.js +2 -3
  49. package/lib/Types/Label.js +6 -12
  50. package/lib/Types/LabelAssociation.js +4 -13
  51. package/lib/Types/Message.js +10 -18
  52. package/lib/Types/MexUpdates.js +15 -18
  53. package/lib/Types/Newsletter.js +26 -34
  54. package/lib/Types/Product.js +2 -3
  55. package/lib/Types/Signal.js +2 -3
  56. package/lib/Types/Socket.js +2 -3
  57. package/lib/Types/State.js +8 -13
  58. package/lib/Types/USync.js +2 -3
  59. package/lib/Types/index.js +49 -40
  60. package/lib/Utils/auth-utils.js +190 -495
  61. package/lib/Utils/browser-utils.js +29 -0
  62. package/lib/Utils/business.js +177 -199
  63. package/lib/Utils/chat-utils.js +711 -624
  64. package/lib/Utils/crypto.js +116 -161
  65. package/lib/Utils/decode-wa-message.js +225 -321
  66. package/lib/Utils/event-buffer.js +363 -405
  67. package/lib/Utils/generics.js +318 -472
  68. package/lib/Utils/history.js +72 -76
  69. package/lib/Utils/index.js +49 -41
  70. package/lib/Utils/link-preview.js +59 -103
  71. package/lib/Utils/logger.js +4 -7
  72. package/lib/Utils/lt-hash.js +29 -42
  73. package/lib/Utils/make-mutex.js +26 -42
  74. package/lib/Utils/message-retry-manager.js +134 -160
  75. package/lib/Utils/messages-media.js +665 -731
  76. package/lib/Utils/messages.js +518 -1
  77. package/lib/Utils/noise-handler.js +127 -125
  78. package/lib/Utils/pre-key-manager.js +86 -0
  79. package/lib/Utils/process-message.js +739 -351
  80. package/lib/Utils/signal.js +146 -129
  81. package/lib/Utils/use-multi-file-auth-state.js +68 -135
  82. package/lib/Utils/validate-connection.js +183 -142
  83. package/lib/Utils/vialeys-event-stream.js +41 -0
  84. package/lib/WABinary/constants.js +1281 -1289
  85. package/lib/WABinary/decode.js +145 -200
  86. package/lib/WABinary/encode.js +149 -202
  87. package/lib/WABinary/generic-utils.js +79 -97
  88. package/lib/WABinary/index.js +36 -25
  89. package/lib/WABinary/jid-utils.js +91 -123
  90. package/lib/WABinary/types.js +2 -3
  91. package/lib/WAM/BinaryInfo.js +8 -13
  92. package/lib/WAM/constants.js +16584 -11464
  93. package/lib/WAM/encode.js +117 -133
  94. package/lib/WAM/index.js +34 -23
  95. package/lib/WAUSync/Protocols/USyncBotProfileProtocol.js +62 -69
  96. package/lib/WAUSync/Protocols/USyncContactProtocol.js +11 -25
  97. package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +32 -44
  98. package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +13 -23
  99. package/lib/WAUSync/Protocols/USyncLIDProtocol.js +24 -38
  100. package/lib/WAUSync/Protocols/USyncStatusProtocol.js +17 -31
  101. package/lib/WAUSync/Protocols/index.js +37 -26
  102. package/lib/WAUSync/USyncQuery.js +66 -66
  103. package/lib/WAUSync/USyncUser.js +13 -18
  104. package/lib/WAUSync/index.js +34 -23
  105. package/lib/index.js +95 -28
  106. package/package.json +4 -3
  107. package/lib/Defaults/baileys-version.json +0 -3
  108. package/lib/Signal/Group/queue-job.d.ts +0 -1
  109. package/lib/Signal/Group/queue-job.js +0 -57
  110. package/lib/Socket/usync.d.ts +0 -37
  111. package/lib/Socket/usync.js +0 -83
  112. package/lib/Utils/baileys-event-stream.d.ts +0 -18
  113. package/lib/Utils/baileys-event-stream.js +0 -70
  114. package/lib/Utils/signal-housekeeping.d.ts +0 -19
  115. package/lib/Utils/signal-housekeeping.js +0 -73
  116. package/lib/Utils/use-mongo-file-auth-state.d.ts +0 -6
  117. package/lib/Utils/use-mongo-file-auth-state.js +0 -84
  118. package/lib/Utils/use-single-file-auth-state.d.ts +0 -13
  119. package/lib/Utils/use-single-file-auth-state.js +0 -80
@@ -1,166 +1,183 @@
1
- "use strict"
2
-
3
- Object.defineProperty(exports, "__esModule", { value: true })
4
-
5
- const lodash_1 = require("lodash")
6
- const Defaults_1 = require("../Defaults")
7
- const WABinary_1 = require("../WABinary")
8
- const crypto_1 = require("./crypto")
9
- const generics_1 = require("./generics")
10
-
11
- const createSignalIdentity = (wid, accountSignatureKey) => {
12
- return {
13
- identifier: { name: wid, deviceId: 0 },
14
- identifierKey: crypto_1.generateSignalPubKey(accountSignatureKey)
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const { KEY_BUNDLE_TYPE: KEY_BUNDLE_TYPE } = require("../Defaults/constants");
4
+ const {
5
+ S_WHATSAPP_NET: S_WHATSAPP_NET,
6
+ getBinaryNodeChild: getBinaryNodeChild,
7
+ getBinaryNodeChildren: getBinaryNodeChildren,
8
+ getBinaryNodeChildUInt: getBinaryNodeChildUInt,
9
+ getBinaryNodeChildBuffer: getBinaryNodeChildBuffer,
10
+ assertNodeErrorFree: assertNodeErrorFree,
11
+ jidDecode: jidDecode,
12
+ getServerFromDomainType: getServerFromDomainType,
13
+ WAJIDDomains: WAJIDDomains,
14
+ } = require("../WABinary");
15
+ const { Curve: Curve, generateSignalPubKey: generateSignalPubKey } = require("./crypto");
16
+ const { encodeBigEndian: encodeBigEndian } = require("./generics");
17
+ function chunk(array, size) {
18
+ const chunks = [];
19
+ for (let i = 0; i < array.length; i += size) {
20
+ chunks.push(array.slice(i, i + size));
15
21
  }
22
+ return chunks;
16
23
  }
17
-
18
- const getPreKeys = async ({ get }, min, limit) => {
19
- const idList = []
24
+ const createSignalIdentity = (wid, accountSignatureKey) => ({
25
+ identifier: { name: wid, deviceId: 0 },
26
+ identifierKey: generateSignalPubKey(accountSignatureKey),
27
+ });
28
+ const getPreKeys = async ({ get: get }, min, limit) => {
29
+ const idList = [];
20
30
  for (let id = min; id < limit; id++) {
21
- idList.push(id.toString())
31
+ idList.push(id.toString());
22
32
  }
23
- return get('pre-key', idList)
24
- }
25
-
33
+ return get("pre-key", idList);
34
+ };
26
35
  const generateOrGetPreKeys = (creds, range) => {
27
- const avaliable = creds.nextPreKeyId - creds.firstUnuploadedPreKeyId
28
- const remaining = range - avaliable
29
- const lastPreKeyId = creds.nextPreKeyId + remaining - 1
30
- const newPreKeys = {}
36
+ const avaliable = creds.nextPreKeyId - creds.firstUnuploadedPreKeyId;
37
+ const remaining = range - avaliable;
38
+ const lastPreKeyId = creds.nextPreKeyId + remaining - 1;
39
+ const newPreKeys = {};
31
40
  if (remaining > 0) {
32
41
  for (let i = creds.nextPreKeyId; i <= lastPreKeyId; i++) {
33
- newPreKeys[i] = crypto_1.Curve.generateKeyPair()
42
+ newPreKeys[i] = Curve.generateKeyPair();
34
43
  }
35
44
  }
36
45
  return {
37
- newPreKeys,
38
- lastPreKeyId,
46
+ newPreKeys: newPreKeys,
47
+ lastPreKeyId: lastPreKeyId,
39
48
  preKeysRange: [creds.firstUnuploadedPreKeyId, range],
40
- }
41
- }
42
-
49
+ };
50
+ };
43
51
  const xmppSignedPreKey = (key) => ({
44
- tag: 'skey',
52
+ tag: "skey",
45
53
  attrs: {},
46
54
  content: [
47
- { tag: 'id', attrs: {}, content: generics_1.encodeBigEndian(key.keyId, 3) },
48
- { tag: 'value', attrs: {}, content: key.keyPair.public },
49
- { tag: 'signature', attrs: {}, content: key.signature }
50
- ]
51
- })
52
-
55
+ { tag: "id", attrs: {}, content: encodeBigEndian(key.keyId, 3) },
56
+ { tag: "value", attrs: {}, content: key.keyPair.public },
57
+ { tag: "signature", attrs: {}, content: key.signature },
58
+ ],
59
+ });
53
60
  const xmppPreKey = (pair, id) => ({
54
- tag: 'key',
61
+ tag: "key",
55
62
  attrs: {},
56
63
  content: [
57
- { tag: 'id', attrs: {}, content: generics_1.encodeBigEndian(id, 3) },
58
- { tag: 'value', attrs: {}, content: pair.public }
59
- ]
60
- })
61
-
64
+ { tag: "id", attrs: {}, content: encodeBigEndian(id, 3) },
65
+ { tag: "value", attrs: {}, content: pair.public },
66
+ ],
67
+ });
62
68
  const parseAndInjectE2ESessions = async (node, repository) => {
63
- const extractKey = (key) => (key ? ({
64
- keyId: WABinary_1.getBinaryNodeChildUInt(key, 'id', 3),
65
- publicKey: crypto_1.generateSignalPubKey(WABinary_1.getBinaryNodeChildBuffer(key, 'value')),
66
- signature: WABinary_1.getBinaryNodeChildBuffer(key, 'signature')
67
- }) : undefined)
68
- const nodes = WABinary_1.getBinaryNodeChildren(WABinary_1.getBinaryNodeChild(node, 'list'), 'user')
69
+ const extractKey = (key) =>
70
+ key
71
+ ? {
72
+ keyId: getBinaryNodeChildUInt(key, "id", 3),
73
+ publicKey: generateSignalPubKey(getBinaryNodeChildBuffer(key, "value")),
74
+ signature: getBinaryNodeChildBuffer(key, "signature"),
75
+ }
76
+ : undefined;
77
+ const nodes = getBinaryNodeChildren(getBinaryNodeChild(node, "list"), "user");
69
78
  for (const node of nodes) {
70
- WABinary_1.assertNodeErrorFree(node)
79
+ assertNodeErrorFree(node);
71
80
  }
72
- // Most of the work in repository.injectE2ESession is CPU intensive, not IO
73
- // So Promise.all doesn't really help here,
74
- // but blocks even loop if we're using it inside keys.transaction, and it makes it "sync" actually
75
- // This way we chunk it in smaller parts and between those parts we can yield to the event loop
76
- // It's rare case when you need to E2E sessions for so many users, but it's possible
77
- const chunkSize = 100
78
- const chunks = lodash_1.chunk(nodes, chunkSize)
81
+ const chunkSize = 100;
82
+ const chunks = chunk(nodes, chunkSize);
79
83
  for (const nodesChunk of chunks) {
80
- await Promise.all(nodesChunk.map(async (node) => {
81
- const signedKey = WABinary_1.getBinaryNodeChild(node, 'skey')
82
- const key = WABinary_1.getBinaryNodeChild(node, 'key')
83
- const identity = WABinary_1.getBinaryNodeChildBuffer(node, 'identity')
84
- const jid = node.attrs.jid
85
- const registrationId = WABinary_1.getBinaryNodeChildUInt(node, 'registration', 4)
84
+ for (const node of nodesChunk) {
85
+ const signedKey = getBinaryNodeChild(node, "skey");
86
+ const key = getBinaryNodeChild(node, "key");
87
+ const identity = getBinaryNodeChildBuffer(node, "identity");
88
+ const jid = node.attrs.jid;
89
+ const registrationId = getBinaryNodeChildUInt(node, "registration", 4);
86
90
  await repository.injectE2ESession({
87
- jid,
91
+ jid: jid,
88
92
  session: {
89
93
  registrationId: registrationId,
90
- identityKey: crypto_1.generateSignalPubKey(identity),
94
+ identityKey: generateSignalPubKey(identity),
91
95
  signedPreKey: extractKey(signedKey),
92
- preKey: extractKey(key)
93
- }
94
- })
95
- }))
96
+ preKey: extractKey(key),
97
+ },
98
+ });
99
+ }
96
100
  }
97
- }
98
-
99
- const extractDeviceJids = (result, myJid, excludeZeroDevices) => {
100
- const { user: myUser, device: myDevice } = WABinary_1.jidDecode(myJid)
101
- const extracted = []
101
+ };
102
+ const extractDeviceJids = (result, myJid, myLid, excludeZeroDevices) => {
103
+ const { user: myUser, device: myDevice } = jidDecode(myJid);
104
+ const extracted = [];
102
105
  for (const userResult of result) {
103
- const { devices, id } = userResult
104
- const { user } = WABinary_1.jidDecode(id)
105
- const deviceList = devices?.deviceList
106
- if (Array.isArray(deviceList)) {
107
- for (const { id: device, keyIndex } of deviceList) {
108
- if ((!excludeZeroDevices || device !== 0) && // if zero devices are not-excluded, or device is non zero
109
- (myUser !== user || myDevice !== device) && // either different user or if me user, not this device
110
- (device === 0 || !!keyIndex) // ensure that "key-index" is specified for "non-zero" devices, produces a bad req otherwise
111
- ) {
112
- extracted.push({ user, device })
106
+ const { devices: devices, id: id } = userResult;
107
+ const decoded = jidDecode(id),
108
+ { user: user, server: server } = decoded;
109
+ let { domainType: domainType } = decoded;
110
+ const deviceList = devices?.deviceList;
111
+ if (!Array.isArray(deviceList)) continue;
112
+ for (const { id: device, keyIndex: keyIndex, isHosted: isHosted } of deviceList) {
113
+ if (
114
+ (!excludeZeroDevices || device !== 0) &&
115
+ ((myUser !== user && myLid !== user) || myDevice !== device) &&
116
+ (device === 0 || !!keyIndex)
117
+ ) {
118
+ if (isHosted) {
119
+ domainType =
120
+ domainType === WAJIDDomains.LID
121
+ ? WAJIDDomains.HOSTED_LID
122
+ : WAJIDDomains.HOSTED;
113
123
  }
124
+ extracted.push({
125
+ user: user,
126
+ device: device,
127
+ domainType: domainType,
128
+ server: getServerFromDomainType(server, domainType),
129
+ });
114
130
  }
115
131
  }
116
132
  }
117
- return extracted
118
- }
119
-
120
- /**
121
- * get the next N keys for upload or processing
122
- * @param count number of pre-keys to get or generate
123
- */
124
- const getNextPreKeys = async ({ creds, keys }, count) => {
125
- const { newPreKeys, lastPreKeyId, preKeysRange } = generateOrGetPreKeys(creds, count)
133
+ return extracted;
134
+ };
135
+ const getNextPreKeys = async ({ creds: creds, keys: keys }, count) => {
136
+ const {
137
+ newPreKeys: newPreKeys,
138
+ lastPreKeyId: lastPreKeyId,
139
+ preKeysRange: preKeysRange,
140
+ } = generateOrGetPreKeys(creds, count);
126
141
  const update = {
127
142
  nextPreKeyId: Math.max(lastPreKeyId + 1, creds.nextPreKeyId),
128
- firstUnuploadedPreKeyId: Math.max(creds.firstUnuploadedPreKeyId, lastPreKeyId + 1)
129
- }
130
- await keys.set({ 'pre-key': newPreKeys })
131
- const preKeys = await getPreKeys(keys, preKeysRange[0], preKeysRange[0] + preKeysRange[1])
132
- return { update, preKeys }
133
- }
134
-
143
+ firstUnuploadedPreKeyId: Math.max(creds.firstUnuploadedPreKeyId, lastPreKeyId + 1),
144
+ };
145
+ await keys.set({ "pre-key": newPreKeys });
146
+ const preKeys = await getPreKeys(keys, preKeysRange[0], preKeysRange[0] + preKeysRange[1]);
147
+ return { update: update, preKeys: preKeys };
148
+ };
135
149
  const getNextPreKeysNode = async (state, count) => {
136
- const { creds } = state
137
- const { update, preKeys } = await getNextPreKeys(state, count)
150
+ const { creds: creds } = state;
151
+ const { update: update, preKeys: preKeys } = await getNextPreKeys(state, count);
138
152
  const node = {
139
- tag: 'iq',
140
- attrs: {
141
- xmlns: 'encrypt',
142
- type: 'set',
143
- to: WABinary_1.S_WHATSAPP_NET,
144
- },
153
+ tag: "iq",
154
+ attrs: { xmlns: "encrypt", type: "set", to: S_WHATSAPP_NET },
145
155
  content: [
146
- { tag: 'registration', attrs: {}, content: generics_1.encodeBigEndian(creds.registrationId) },
147
- { tag: 'type', attrs: {}, content: Defaults_1.KEY_BUNDLE_TYPE },
148
- { tag: 'identity', attrs: {}, content: creds.signedIdentityKey.public },
149
- { tag: 'list', attrs: {}, content: Object.keys(preKeys).map(k => xmppPreKey(preKeys[+k], +k)) },
150
- xmppSignedPreKey(creds.signedPreKey)
151
- ]
152
- }
153
- return { update, node }
154
- }
155
-
156
+ {
157
+ tag: "registration",
158
+ attrs: {},
159
+ content: encodeBigEndian(creds.registrationId),
160
+ },
161
+ { tag: "type", attrs: {}, content: KEY_BUNDLE_TYPE },
162
+ { tag: "identity", attrs: {}, content: creds.signedIdentityKey.public },
163
+ {
164
+ tag: "list",
165
+ attrs: {},
166
+ content: Object.keys(preKeys).map((k) => xmppPreKey(preKeys[+k], +k)),
167
+ },
168
+ xmppSignedPreKey(creds.signedPreKey),
169
+ ],
170
+ };
171
+ return { update: update, node: node };
172
+ };
156
173
  module.exports = {
157
- createSignalIdentity,
158
- getPreKeys,
159
- generateOrGetPreKeys,
160
- xmppSignedPreKey,
161
- xmppPreKey,
162
- parseAndInjectE2ESessions,
163
- extractDeviceJids,
164
- getNextPreKeys,
165
- getNextPreKeysNode
166
- }
174
+ createSignalIdentity: createSignalIdentity,
175
+ getPreKeys: getPreKeys,
176
+ generateOrGetPreKeys: generateOrGetPreKeys,
177
+ xmppSignedPreKey: xmppSignedPreKey,
178
+ xmppPreKey: xmppPreKey,
179
+ parseAndInjectE2ESessions: parseAndInjectE2ESessions,
180
+ extractDeviceJids: extractDeviceJids,
181
+ getNextPreKeys: getNextPreKeys,
182
+ getNextPreKeysNode: getNextPreKeysNode,
183
+ };
@@ -1,171 +1,104 @@
1
- "use strict"
2
-
3
- var __importDefault = (this && this.__importDefault) || function (mod) {
4
- return (mod && mod.__esModule) ? mod : { "default": mod }
5
- }
6
-
7
- Object.defineProperty(exports, "__esModule", { value: true })
8
-
9
- const async_mutex_1 = __importDefault(require("async-mutex"))
10
- const promises_1 = require("fs/promises")
11
- const { rename: fsRename } = promises_1
12
- const path_1 = require("path")
13
- const WAProto_1 = require("../../WAProto")
14
- const auth_utils_1 = require("./auth-utils")
15
- const generics_1 = require("./generics")
16
- // We need to lock files due to the fact that we are using async functions to read and write files
17
- // https://github.com/WhiskeySockets/Baileys/issues/794
18
- // https://github.com/nodejs/node/issues/26338
19
- // Use a Map to store mutexes for each file path
20
- const fileLocks = new Map()
21
-
22
- // Get or create a mutex for a specific file path
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const { Mutex: Mutex } = require("async-mutex");
4
+ const { promises: promises } = require("fs");
5
+ const { join: join } = require("path");
6
+ const { proto: proto } = require("../../WAProto");
7
+ const { initAuthCreds: initAuthCreds } = require("./auth-utils");
8
+ const { BufferJSON: BufferJSON } = require("./generics");
9
+ const fileLocks = new Map();
23
10
  const getFileLock = (path) => {
24
- let mutex = fileLocks.get(path)
25
- if (!mutex) {
26
- mutex = new async_mutex_1.Mutex()
27
- fileLocks.set(path, mutex)
28
- }
29
-
30
- return mutex
31
- }
32
-
33
- // Lepas mutex dari Map begitu tidak dipakai lagi supaya tidak numpuk terus (memory leak)
34
- // selama proses hidup lama (bot jalan berbulan-bulan dengan ribuan file sesi berbeda).
35
- const releaseFileLock = (path) => {
36
- fileLocks.delete(path)
37
- }
38
-
39
- /**
40
- * stores the full authentication state in a single folder.
41
- * Far more efficient than singlefileauthstate
42
- *
43
- * Again, I wouldn't endorse this for any production level use other than perhaps a bot.
44
- * Would recommend writing an auth state for use with a proper SQL or No-SQL DB
45
- * */
11
+ let mutex = fileLocks.get(path);
12
+ if (!mutex) {
13
+ mutex = new Mutex();
14
+ fileLocks.set(path, mutex);
15
+ }
16
+ return mutex;
17
+ };
46
18
  const useMultiFileAuthState = async (folder) => {
47
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
48
19
  const writeData = async (data, file) => {
49
- const filePath = path_1.join(folder, fixFileName(file))
50
- const mutex = getFileLock(filePath)
20
+ const filePath = join(folder, fixFileName(file));
21
+ const mutex = getFileLock(filePath);
51
22
  return mutex.acquire().then(async (release) => {
52
23
  try {
53
- // Atomic write: write to temp file then rename, agar file tidak pernah
54
- // kebaca dalam kondisi setengah tertulis kalau proses mati di tengah jalan.
55
- const tmpPath = filePath + '.tmp'
56
- await promises_1.writeFile(tmpPath, JSON.stringify(data, generics_1.BufferJSON.replacer))
57
- await fsRename(tmpPath, filePath)
24
+ await promises.writeFile(filePath, JSON.stringify(data, BufferJSON.replacer));
58
25
  } finally {
59
- release()
60
- releaseFileLock(filePath)
26
+ release();
61
27
  }
62
- })
63
- }
28
+ });
29
+ };
64
30
  const readData = async (file) => {
65
- const filePath = path_1.join(folder, fixFileName(file))
66
31
  try {
67
- const mutex = getFileLock(filePath)
32
+ const filePath = join(folder, fixFileName(file));
33
+ const mutex = getFileLock(filePath);
68
34
  const data = await mutex.acquire().then(async (release) => {
69
35
  try {
70
- return await promises_1.readFile(filePath, { encoding: 'utf-8' })
36
+ return await promises.readFile(filePath, { encoding: "utf-8" });
71
37
  } finally {
72
- release()
73
- releaseFileLock(filePath)
38
+ release();
74
39
  }
75
- })
76
-
77
- return JSON.parse(data, generics_1.BufferJSON.reviver)
40
+ });
41
+ return JSON.parse(data, BufferJSON.reviver);
78
42
  } catch (error) {
79
- // ENOENT (file belum ada) itu normal, tapi kalau isinya rusak/corrupt (JSON parse
80
- // gagal) itu wajib kelihatan di log, bukan diam-diam dianggap "null"/hilang.
81
- if (error?.code !== 'ENOENT') {
82
- console.warn(`[useMultiFileAuthState] Gagal membaca/parse ${filePath}:`, error?.message || error)
83
- }
84
- return null
43
+ return null;
85
44
  }
86
- }
45
+ };
87
46
  const removeData = async (file) => {
88
- const filePath = path_1.join(folder, fixFileName(file))
89
47
  try {
90
- const mutex = getFileLock(filePath)
48
+ const filePath = join(folder, fixFileName(file));
49
+ const mutex = getFileLock(filePath);
91
50
  await mutex.acquire().then(async (release) => {
92
- try {
93
- await promises_1.unlink(filePath)
51
+ try {
52
+ await promises.unlink(filePath);
94
53
  } finally {
95
- release()
96
- releaseFileLock(filePath)
54
+ release();
97
55
  }
98
- })
56
+ });
99
57
  } catch {}
100
- }
101
- const folderInfo = await promises_1.stat(folder).catch(() => { })
58
+ };
59
+ const folderInfo = await promises.stat(folder).catch(() => {});
102
60
  if (folderInfo) {
103
61
  if (!folderInfo.isDirectory()) {
104
- throw new Error(`found something that is not a directory at ${folder}, either delete it or specify a different location`)
62
+ throw new Error(
63
+ `found something that is not a directory at ${folder}, either delete it or specify a different location`
64
+ );
105
65
  }
66
+ } else {
67
+ await promises.mkdir(folder, { recursive: true });
106
68
  }
107
- else {
108
- await promises_1.mkdir(folder, { recursive: true })
109
- }
110
- const fixFileName = (file) => {
111
- return file?.replace(/\//g, '__')?.replace(/:/g, '-')
112
- }
113
-
114
- // Bersihkan file .tmp "yatim" yang tertinggal dari proses sebelumnya yang mati
115
- // di tengah proses rename (atomic write). File-file ini tidak berguna dan kalau
116
- // dibiarkan menumpuk, cuma buang-buang disk.
117
- try {
118
- const entries = await promises_1.readdir(folder)
119
- await Promise.all(
120
- entries
121
- .filter((name) => name.endsWith('.tmp'))
122
- .map((name) => promises_1.unlink(path_1.join(folder, name)).catch(() => {}))
123
- )
124
- } catch {}
125
-
126
- const creds = await readData('creds.json') || auth_utils_1.initAuthCreds()
69
+ const fixFileName = (file) => file?.replace(/\//g, "__")?.replace(/:/g, "-");
70
+ const creds = (await readData("creds.json")) || initAuthCreds();
127
71
  return {
128
72
  state: {
129
- creds,
73
+ creds: creds,
130
74
  keys: {
131
75
  get: async (type, ids) => {
132
- const data = {}
133
- await Promise.all(ids.map(async (id) => {
134
- let value = await readData(`${type}-${id}.json`)
135
- if (type === 'app-state-sync-key' && value) {
136
- value = WAProto_1.proto.Message.AppStateSyncKeyData.fromObject(value)
137
- }
138
- data[id] = value
139
- }))
140
- return data
76
+ const data = {};
77
+ await Promise.all(
78
+ ids.map(async (id) => {
79
+ let value = await readData(`${type}-${id}.json`);
80
+ if (type === "app-state-sync-key" && value) {
81
+ value = proto.Message.AppStateSyncKeyData.fromObject(value);
82
+ }
83
+ data[id] = value;
84
+ })
85
+ );
86
+ return data;
141
87
  },
142
88
  set: async (data) => {
143
- const tasks = []
89
+ const tasks = [];
144
90
  for (const category in data) {
145
91
  for (const id in data[category]) {
146
- const value = data[category][id]
147
- const file = `${category}-${id}.json`
148
- tasks.push(value ? writeData(value, file) : removeData(file))
92
+ const value = data[category][id];
93
+ const file = `${category}-${id}.json`;
94
+ tasks.push(value ? writeData(value, file) : removeData(file));
149
95
  }
150
96
  }
151
- await Promise.all(tasks)
152
- }
153
- }
154
- },
155
- // saveCreds sekarang selalu langsung menulis (tidak didebounce). creds.json adalah
156
- // file paling kritis — kalau proses mati tepat di jendela debounce, sesi bisa hilang
157
- // atau balik ke state lama sehingga semua pesan gagal didekripsi setelah reconnect.
158
- saveCreds: async () => {
159
- return writeData(creds, 'creds.json')
97
+ await Promise.all(tasks);
98
+ },
99
+ },
160
100
  },
161
- // Tetap disediakan sebagai alias untuk kompatibilitas kode lama yang memanggil
162
- // saveCredsNow() secara eksplisit (misal di handler disconnect/cleanup).
163
- saveCredsNow: async () => {
164
- return writeData(creds, 'creds.json')
165
- }
166
- }
167
- }
168
-
169
- module.exports = {
170
- useMultiFileAuthState
171
- }
101
+ saveCreds: async () => writeData(creds, "creds.json"),
102
+ };
103
+ };
104
+ module.exports = { useMultiFileAuthState: useMultiFileAuthState };