@nexustechpro/baileys 2.1.3 → 2.1.6
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/README.md +471 -10
- package/lib/Defaults/index.js +0 -4
- package/lib/Signal/libsignal.js +138 -249
- package/lib/Signal/lid-mapping.js +23 -4
- package/lib/Socket/chats.js +1 -0
- package/lib/Socket/messages-recv.js +28 -17
- package/lib/Socket/messages-send.js +43 -18
- package/lib/Socket/newsletter.js +22 -17
- package/lib/Socket/nexus-handler.js +222 -328
- package/lib/Socket/socket.js +27 -18
- package/lib/Utils/browser-utils.js +12 -3
- package/lib/Utils/key-store.js +1 -20
- package/lib/Utils/messages-media.js +21 -16
- package/lib/Utils/messages.js +4 -2
- package/lib/Utils/tc-token-utils.js +50 -15
- package/lib/Utils/use-multi-file-auth-state.js +211 -63
- package/lib/Utils/validate-connection.js +15 -3
- package/lib/WABinary/constants.js +14 -0
- package/lib/index.js +1 -1
- package/package.json +27 -12
|
@@ -2,17 +2,30 @@ import { Mutex } from 'async-mutex'
|
|
|
2
2
|
import { mkdir, readFile, rename, stat, unlink, writeFile, readdir } from 'fs/promises'
|
|
3
3
|
import { join } from 'path'
|
|
4
4
|
import { createHash } from 'crypto'
|
|
5
|
+
import { Keyv } from 'keyv'
|
|
5
6
|
import { proto } from '../../WAProto/index.js'
|
|
6
7
|
import { initAuthCreds } from './auth-utils.js'
|
|
7
8
|
import { BufferJSON } from './generics.js'
|
|
9
|
+
import { PROTOCOL_ADAPTERS } from '../WABinary/index.js'
|
|
8
10
|
|
|
9
|
-
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
10
11
|
const CURRENT_VERSION = 1
|
|
11
12
|
const DEFAULT_PREKEY_RETENTION = 150
|
|
12
13
|
const DEFAULT_CLEANUP_THRESHOLD = 50
|
|
13
14
|
const CLEANUP_INTERVAL_MS = 10 * 60 * 1000
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
const bootstrapCreds = (raw) => {
|
|
17
|
+
const c = raw ?? initAuthCreds()
|
|
18
|
+
if (!c.__version || c.__version < CURRENT_VERSION) c.__version = CURRENT_VERSION
|
|
19
|
+
return c
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const patchAppStateKey = (type, v) =>
|
|
23
|
+
type === 'app-state-sync-key' && v ? proto.Message.AppStateSyncKeyData.fromObject(v) : v
|
|
24
|
+
|
|
25
|
+
const computeChecksum = (data) => createHash('sha256').update(data).digest('hex')
|
|
26
|
+
|
|
27
|
+
// ─── File-based auth state ────────────────────────────────────────────────────
|
|
28
|
+
|
|
16
29
|
const fileLocks = new Map()
|
|
17
30
|
const getFileLock = (path) => {
|
|
18
31
|
if (!fileLocks.has(path)) fileLocks.set(path, new Mutex())
|
|
@@ -22,31 +35,13 @@ const releaseFileLock = (path) => {
|
|
|
22
35
|
if (fileLocks.has(path) && !fileLocks.get(path).isLocked()) fileLocks.delete(path)
|
|
23
36
|
}
|
|
24
37
|
|
|
25
|
-
// ─── Checksum ─────────────────────────────────────────────────────────────────
|
|
26
|
-
const computeChecksum = (data) => createHash('sha256').update(data).digest('hex')
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Production-grade multi-file auth state for Baileys.
|
|
30
|
-
* Atomic writes, checksum integrity, and smart prekey cleanup.
|
|
31
|
-
* Compatible with standard Baileys auth folder format.
|
|
32
|
-
*
|
|
33
|
-
* @param {string} folder - Directory to store auth files
|
|
34
|
-
* @param {object} [options] - Configuration options
|
|
35
|
-
* @param {number} [options.preKeyRetention=150] - How many recent prekeys to keep
|
|
36
|
-
* @param {number} [options.cleanupThreshold=50] - How many new prekeys trigger a cleanup
|
|
37
|
-
* @param {object} [options.logger] - Optional logger with .info/.warn methods
|
|
38
|
-
*/
|
|
39
38
|
export const useMultiFileAuthState = async (folder, options = {}) => {
|
|
40
|
-
const {
|
|
41
|
-
|
|
42
|
-
cleanupThreshold = DEFAULT_CLEANUP_THRESHOLD,
|
|
43
|
-
logger,
|
|
44
|
-
} = options
|
|
39
|
+
const { preKeyRetention = DEFAULT_PREKEY_RETENTION, cleanupThreshold = DEFAULT_CLEANUP_THRESHOLD, logger } = options
|
|
40
|
+
|
|
45
41
|
const fixFileName = (file) => file?.replace(/\//g, '__')?.replace(/:/g, '-')
|
|
46
42
|
const filePath = (file) => join(folder, fixFileName(file))
|
|
47
43
|
const tmpPath = (file) => filePath(file) + '.tmp'
|
|
48
44
|
|
|
49
|
-
// ─── Folder Bootstrap ───────────────────────────────────────────────────────
|
|
50
45
|
const folderInfo = await stat(folder).catch(() => null)
|
|
51
46
|
if (folderInfo) {
|
|
52
47
|
if (!folderInfo.isDirectory()) throw new Error(`Path exists but is not a directory: ${folder}`)
|
|
@@ -54,16 +49,13 @@ export const useMultiFileAuthState = async (folder, options = {}) => {
|
|
|
54
49
|
await mkdir(folder, { recursive: true })
|
|
55
50
|
}
|
|
56
51
|
|
|
57
|
-
// ─── Atomic Write ────────────────────────────────────────────────────────────
|
|
58
52
|
const writeData = async (data, file) => {
|
|
59
53
|
const fp = filePath(file)
|
|
60
54
|
const tp = tmpPath(file)
|
|
61
|
-
const
|
|
62
|
-
const release = await mutex.acquire()
|
|
55
|
+
const release = await getFileLock(fp).acquire()
|
|
63
56
|
try {
|
|
64
57
|
const serialized = JSON.stringify(data, BufferJSON.replacer)
|
|
65
|
-
const
|
|
66
|
-
const payload = JSON.stringify({ data: JSON.parse(serialized), __checksum: checksum })
|
|
58
|
+
const payload = JSON.stringify({ data: JSON.parse(serialized), __checksum: computeChecksum(serialized) })
|
|
67
59
|
await writeFile(tp, payload)
|
|
68
60
|
try {
|
|
69
61
|
await rename(tp, fp)
|
|
@@ -77,11 +69,9 @@ export const useMultiFileAuthState = async (folder, options = {}) => {
|
|
|
77
69
|
}
|
|
78
70
|
}
|
|
79
71
|
|
|
80
|
-
// ─── Read with Checksum Verification ─────────────────────────────────────────
|
|
81
72
|
const readData = async (file) => {
|
|
82
73
|
const fp = filePath(file)
|
|
83
|
-
const
|
|
84
|
-
const release = await mutex.acquire()
|
|
74
|
+
const release = await getFileLock(fp).acquire()
|
|
85
75
|
try {
|
|
86
76
|
const raw = await readFile(fp, { encoding: 'utf-8' }).catch(() => null)
|
|
87
77
|
if (!raw) return null
|
|
@@ -92,28 +82,26 @@ export const useMultiFileAuthState = async (folder, options = {}) => {
|
|
|
92
82
|
if (expected !== parsed.__checksum) {
|
|
93
83
|
logger?.warn({ file }, 'checksum mismatch — reinitializing file')
|
|
94
84
|
await writeFile(fp, JSON.stringify({ data: parsed.data, __checksum: computeChecksum(JSON.stringify(parsed.data)) })).catch(() => { })
|
|
95
|
-
return JSON.parse(JSON.stringify(parsed.data), BufferJSON.reviver)
|
|
96
85
|
}
|
|
97
86
|
return JSON.parse(JSON.stringify(parsed.data), BufferJSON.reviver)
|
|
98
87
|
}
|
|
99
|
-
// legacy file — rewrite with checksum
|
|
100
88
|
const reserialized = JSON.stringify(JSON.parse(raw, BufferJSON.reviver), BufferJSON.replacer)
|
|
101
|
-
|
|
102
|
-
await writeFile(fp, JSON.stringify({ data: JSON.parse(reserialized), __checksum: checksum })).catch(() => { })
|
|
89
|
+
await writeFile(fp, JSON.stringify({ data: JSON.parse(reserialized), __checksum: computeChecksum(reserialized) })).catch(() => { })
|
|
103
90
|
return JSON.parse(raw, BufferJSON.reviver)
|
|
104
91
|
} catch (err) {
|
|
105
92
|
logger?.warn({ file, err: err.message }, 'failed to read auth file — reinitializing')
|
|
106
93
|
await unlink(fp).catch(() => { })
|
|
107
94
|
return null
|
|
108
95
|
}
|
|
109
|
-
} finally {
|
|
96
|
+
} finally {
|
|
97
|
+
release()
|
|
98
|
+
releaseFileLock(fp)
|
|
99
|
+
}
|
|
110
100
|
}
|
|
111
101
|
|
|
112
|
-
// ─── Remove File ────────────────────────────────────────────────────────────
|
|
113
102
|
const removeData = async (file) => {
|
|
114
103
|
const fp = filePath(file)
|
|
115
|
-
const
|
|
116
|
-
const release = await mutex.acquire()
|
|
104
|
+
const release = await getFileLock(fp).acquire()
|
|
117
105
|
try {
|
|
118
106
|
await unlink(fp).catch(() => { })
|
|
119
107
|
} finally {
|
|
@@ -122,34 +110,23 @@ export const useMultiFileAuthState = async (folder, options = {}) => {
|
|
|
122
110
|
}
|
|
123
111
|
}
|
|
124
112
|
|
|
125
|
-
|
|
126
|
-
let creds = (await readData('creds.json')) || initAuthCreds()
|
|
127
|
-
if (!creds.__version) {
|
|
128
|
-
creds.__version = CURRENT_VERSION
|
|
129
|
-
} else if (creds.__version < CURRENT_VERSION) {
|
|
130
|
-
creds.__version = CURRENT_VERSION
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// ─── Prekey Cleanup ─────────────────────────────────────────────────────────
|
|
113
|
+
let creds = bootstrapCreds(await readData('creds.json'))
|
|
134
114
|
let cleanupRunning = false
|
|
135
115
|
let lastCleanupAt = 0
|
|
136
116
|
let lastCleanedPreKeyId = creds.nextPreKeyId
|
|
137
117
|
|
|
138
118
|
const cleanOldPreKeys = async () => {
|
|
139
119
|
const now = Date.now()
|
|
140
|
-
if (cleanupRunning) return
|
|
141
|
-
if (now - lastCleanupAt < CLEANUP_INTERVAL_MS) return
|
|
120
|
+
if (cleanupRunning || now - lastCleanupAt < CLEANUP_INTERVAL_MS) return
|
|
142
121
|
cleanupRunning = true
|
|
143
122
|
try {
|
|
144
123
|
const minId = creds.nextPreKeyId - preKeyRetention
|
|
145
124
|
if (minId <= 0) return
|
|
146
125
|
const files = await readdir(folder)
|
|
147
|
-
const targets =
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if (parseInt(match[1], 10) < minId) targets.push(join(folder, file))
|
|
152
|
-
}
|
|
126
|
+
const targets = files
|
|
127
|
+
.map(f => f.match(/^pre-key-(\d+)\.json(\.tmp)?$/))
|
|
128
|
+
.filter(m => m && parseInt(m[1], 10) < minId)
|
|
129
|
+
.map(m => join(folder, m[0]))
|
|
153
130
|
if (!targets.length) return
|
|
154
131
|
await Promise.all(targets.map(f => unlink(f).catch(() => { })))
|
|
155
132
|
lastCleanupAt = Date.now()
|
|
@@ -164,7 +141,6 @@ export const useMultiFileAuthState = async (folder, options = {}) => {
|
|
|
164
141
|
|
|
165
142
|
cleanOldPreKeys().catch(() => { })
|
|
166
143
|
|
|
167
|
-
// ─── Stats ──────────────────────────────────────────────────────────────────
|
|
168
144
|
const getStats = async () => {
|
|
169
145
|
const files = await readdir(folder).catch(() => [])
|
|
170
146
|
const preKeyFiles = files.filter(f => /^pre-key-\d+\.json$/.test(f))
|
|
@@ -184,9 +160,7 @@ export const useMultiFileAuthState = async (folder, options = {}) => {
|
|
|
184
160
|
const data = {}
|
|
185
161
|
await Promise.all(ids.map(async (id) => {
|
|
186
162
|
let value = await readData(`${type}-${id}.json`)
|
|
187
|
-
if (type === 'app-state-sync-key' && value)
|
|
188
|
-
value = proto.Message.AppStateSyncKeyData.fromObject(value)
|
|
189
|
-
}
|
|
163
|
+
if (type === 'app-state-sync-key' && value) value = proto.Message.AppStateSyncKeyData.fromObject(value)
|
|
190
164
|
data[id] = value
|
|
191
165
|
}))
|
|
192
166
|
return data
|
|
@@ -204,11 +178,185 @@ export const useMultiFileAuthState = async (folder, options = {}) => {
|
|
|
204
178
|
},
|
|
205
179
|
},
|
|
206
180
|
saveCreds: async () => {
|
|
207
|
-
if (creds.nextPreKeyId - lastCleanedPreKeyId >= cleanupThreshold) {
|
|
208
|
-
cleanOldPreKeys().catch(() => { })
|
|
209
|
-
}
|
|
181
|
+
if (creds.nextPreKeyId - lastCleanedPreKeyId >= cleanupThreshold) cleanOldPreKeys().catch(() => { })
|
|
210
182
|
return writeData(creds, 'creds.json')
|
|
211
183
|
},
|
|
212
184
|
getStats,
|
|
213
185
|
}
|
|
214
|
-
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ─── Keyv-backed auth state ───────────────────────────────────────────────────
|
|
189
|
+
|
|
190
|
+
const ser = (v) => {
|
|
191
|
+
if (v == null) return null
|
|
192
|
+
const serialized = JSON.stringify(v, BufferJSON.replacer)
|
|
193
|
+
return { data: JSON.parse(serialized), __checksum: computeChecksum(serialized) }
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const unwrapNestedValue = (obj) => {
|
|
197
|
+
let cur = obj
|
|
198
|
+
while (cur && typeof cur === 'object' && !Array.isArray(cur) && Object.keys(cur).length === 1 && 'value' in cur) cur = cur.value
|
|
199
|
+
return cur
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const deser = (raw, logger, onRewrite) => {
|
|
203
|
+
if (raw == null) return null
|
|
204
|
+
let parsed
|
|
205
|
+
if (typeof raw === 'string') {
|
|
206
|
+
try { parsed = JSON.parse(raw) } catch (err) {
|
|
207
|
+
logger?.warn?.({ err: err.message }, '[Auth] failed to parse stored value — treating as missing')
|
|
208
|
+
return null
|
|
209
|
+
}
|
|
210
|
+
} else {
|
|
211
|
+
parsed = raw
|
|
212
|
+
}
|
|
213
|
+
parsed = unwrapNestedValue(parsed)
|
|
214
|
+
if (parsed == null) return null
|
|
215
|
+
if (typeof parsed === 'object' && '__checksum' in parsed) {
|
|
216
|
+
const innerData = unwrapNestedValue(parsed.data)
|
|
217
|
+
const serializedInner = JSON.stringify(innerData)
|
|
218
|
+
const expected = computeChecksum(serializedInner)
|
|
219
|
+
if (expected !== parsed.__checksum) {
|
|
220
|
+
logger?.warn?.('[Auth] checksum mismatch or legacy-wrapped value — reinitializing')
|
|
221
|
+
onRewrite?.(JSON.stringify({ data: innerData, __checksum: expected }))
|
|
222
|
+
}
|
|
223
|
+
return JSON.parse(serializedInner, BufferJSON.reviver)
|
|
224
|
+
}
|
|
225
|
+
return JSON.parse(JSON.stringify(parsed), BufferJSON.reviver)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Maps our unified collectionName option to each adapter's actual constructor key
|
|
229
|
+
const COLLECTION_OPTION_KEY = {
|
|
230
|
+
'@keyv/mongo': 'collection',
|
|
231
|
+
'@keyv/postgres': 'table',
|
|
232
|
+
'@keyv/mysql': 'table',
|
|
233
|
+
'@keyv/sqlite': 'table',
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const _adapterCache = new Map()
|
|
237
|
+
export const clearAdapterCache = () => _adapterCache.clear()
|
|
238
|
+
|
|
239
|
+
const resolveAdapter = async (connectionString, collectionName) => {
|
|
240
|
+
const cacheKey = collectionName ? `${connectionString}::${collectionName}` : connectionString
|
|
241
|
+
if (_adapterCache.has(cacheKey)) return _adapterCache.get(cacheKey)
|
|
242
|
+
let protocol
|
|
243
|
+
try { protocol = new URL(connectionString).protocol } catch { throw new Error(`[Auth] Invalid connection string: "${connectionString}"`) }
|
|
244
|
+
const pkg = PROTOCOL_ADAPTERS[protocol]
|
|
245
|
+
if (!pkg) throw new Error(`[Auth] Unsupported protocol "${protocol}" — supported: redis, mongodb, postgresql, mysql, sqlite, etcd, memcache. Pass a pre-built KeyvStoreAdapter instance for anything else.`)
|
|
246
|
+
let mod
|
|
247
|
+
try { mod = await import(pkg) } catch (e) {
|
|
248
|
+
if (e.code === 'ERR_MODULE_NOT_FOUND') throw new Error(`[Auth] "${pkg}" is required for this backend — install it: npm i ${pkg}`)
|
|
249
|
+
throw e
|
|
250
|
+
}
|
|
251
|
+
const Adapter = mod.default ?? mod[Object.keys(mod)[0]]
|
|
252
|
+
const optionKey = COLLECTION_OPTION_KEY[pkg]
|
|
253
|
+
// Pass one merged options object — Postgres/MySQL silently ignore a second positional argument
|
|
254
|
+
const adapter = (collectionName && optionKey)
|
|
255
|
+
? new Adapter({ url: connectionString, uri: connectionString, [optionKey]: collectionName })
|
|
256
|
+
: new Adapter(connectionString)
|
|
257
|
+
adapter.setMaxListeners?.(0)
|
|
258
|
+
_adapterCache.set(cacheKey, adapter)
|
|
259
|
+
return adapter
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const isAdapterLike = (v) => v && typeof v === 'object' && typeof v.get === 'function' && typeof v.set === 'function' && typeof v.delete === 'function' && typeof v.clear === 'function'
|
|
263
|
+
|
|
264
|
+
const resolveStore = async (backend, collectionName) => {
|
|
265
|
+
if (backend == null) return null
|
|
266
|
+
if (typeof backend === 'string') return resolveAdapter(backend, collectionName)
|
|
267
|
+
if (backend instanceof Keyv) return backend.opts?.store ?? backend.store ?? null
|
|
268
|
+
if (isAdapterLike(backend)) return backend
|
|
269
|
+
throw new Error('[Auth] backend must be a connection string, Keyv instance, or KeyvStoreAdapter')
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export const useKeyvAuthState = async (sessionId, backend, opts = {}) => {
|
|
273
|
+
const { preKeyRetention = DEFAULT_PREKEY_RETENTION, cleanupThreshold = DEFAULT_CLEANUP_THRESHOLD, logger, collectionName } = opts
|
|
274
|
+
|
|
275
|
+
const store = await resolveStore(backend, collectionName)
|
|
276
|
+
const keyv = store ? new Keyv({ store, namespace: sessionId }) : new Keyv({ namespace: sessionId })
|
|
277
|
+
keyv.on('error', (err) => logger?.warn?.({ err: err?.message }, '[Auth] store error'))
|
|
278
|
+
|
|
279
|
+
const keyName = (type, id) => `${type}-${id}`
|
|
280
|
+
|
|
281
|
+
let creds = bootstrapCreds(deser(await keyv.get('creds'), logger, (fixed) => keyv.set('creds', fixed)))
|
|
282
|
+
let cleanupRunning = false
|
|
283
|
+
let lastCleanupAt = 0
|
|
284
|
+
let lastCleanedPreKeyId = creds.nextPreKeyId
|
|
285
|
+
|
|
286
|
+
const cleanOldPreKeys = async () => {
|
|
287
|
+
const now = Date.now()
|
|
288
|
+
if (cleanupRunning || now - lastCleanupAt < CLEANUP_INTERVAL_MS) return
|
|
289
|
+
cleanupRunning = true
|
|
290
|
+
try {
|
|
291
|
+
const minId = creds.nextPreKeyId - preKeyRetention
|
|
292
|
+
if (minId <= 0) return
|
|
293
|
+
const ids = []
|
|
294
|
+
for (let id = Math.max(0, lastCleanedPreKeyId - preKeyRetention); id < minId; id++) ids.push(keyName('pre-key', id))
|
|
295
|
+
if (!ids.length) return
|
|
296
|
+
await Promise.all(ids.map((k) => keyv.delete(k).catch(() => { })))
|
|
297
|
+
lastCleanupAt = Date.now()
|
|
298
|
+
lastCleanedPreKeyId = creds.nextPreKeyId
|
|
299
|
+
logger?.info?.({ deleted: ids.length, minId }, '[Auth] prekey cleanup done')
|
|
300
|
+
} catch (e) {
|
|
301
|
+
logger?.warn?.({ err: e.message }, '[Auth] prekey cleanup failed')
|
|
302
|
+
} finally {
|
|
303
|
+
cleanupRunning = false
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
cleanOldPreKeys().catch(() => { })
|
|
308
|
+
|
|
309
|
+
const keys = {
|
|
310
|
+
get: async (type, ids) => {
|
|
311
|
+
const data = {}
|
|
312
|
+
if (!ids.length) return data
|
|
313
|
+
const rawKeys = ids.map((id) => keyName(type, id))
|
|
314
|
+
const rawValues = await keyv.getMany(rawKeys)
|
|
315
|
+
const rewrites = []
|
|
316
|
+
ids.forEach((id, i) => {
|
|
317
|
+
data[id] = patchAppStateKey(type, deser(rawValues[i], logger, (fixed) => rewrites.push(keyv.set(rawKeys[i], fixed))))
|
|
318
|
+
})
|
|
319
|
+
if (rewrites.length) await Promise.all(rewrites).catch(() => { })
|
|
320
|
+
return data
|
|
321
|
+
},
|
|
322
|
+
set: async (data) => {
|
|
323
|
+
const setEntries = []
|
|
324
|
+
const delKeys = []
|
|
325
|
+
for (const type in data) {
|
|
326
|
+
for (const id in data[type]) {
|
|
327
|
+
const value = data[type][id]
|
|
328
|
+
const key = keyName(type, id)
|
|
329
|
+
if (value != null) setEntries.push({ key, value: ser(value) })
|
|
330
|
+
else delKeys.push(key)
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
await Promise.all([
|
|
334
|
+
setEntries.length ? keyv.setMany(setEntries) : null,
|
|
335
|
+
delKeys.length ? keyv.deleteMany(delKeys) : null,
|
|
336
|
+
])
|
|
337
|
+
},
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const saveCreds = async () => {
|
|
341
|
+
if (creds.nextPreKeyId - lastCleanedPreKeyId >= cleanupThreshold) cleanOldPreKeys().catch(() => { })
|
|
342
|
+
await keyv.set('creds', ser(creds))
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const clearSession = async () => {
|
|
346
|
+
const store = keyv.opts?.store ?? keyv.store
|
|
347
|
+
if (store && typeof store.deleteMany === 'function' && typeof store.iterator === 'function') {
|
|
348
|
+
const toDelete = []
|
|
349
|
+
for await (const [key] of store.iterator(sessionId)) toDelete.push(key)
|
|
350
|
+
if (toDelete.length) await store.deleteMany(toDelete)
|
|
351
|
+
} else {
|
|
352
|
+
await keyv.clear()
|
|
353
|
+
}
|
|
354
|
+
await close()
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const close = async () => { keyv.removeAllListeners?.() }
|
|
358
|
+
|
|
359
|
+
return { state: { creds, keys }, saveCreds, clearSession }
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export { Keyv }
|
|
@@ -13,7 +13,9 @@ const getUserAgent = (config) => {
|
|
|
13
13
|
secondary: config.version[1],
|
|
14
14
|
tertiary: config.version[2]
|
|
15
15
|
},
|
|
16
|
-
platform:
|
|
16
|
+
platform: config.browser[1].toLocaleLowerCase().includes('android')
|
|
17
|
+
? proto.ClientPayload.UserAgent.Platform.MACOS
|
|
18
|
+
: proto.ClientPayload.UserAgent.Platform.WEB,
|
|
17
19
|
releaseChannel: proto.ClientPayload.UserAgent.ReleaseChannel.RELEASE,
|
|
18
20
|
osVersion: '0.1',
|
|
19
21
|
device: 'Desktop',
|
|
@@ -43,7 +45,9 @@ const getClientPayload = (config) => {
|
|
|
43
45
|
connectReason: proto.ClientPayload.ConnectReason.USER_ACTIVATED,
|
|
44
46
|
userAgent: getUserAgent(config)
|
|
45
47
|
};
|
|
46
|
-
|
|
48
|
+
if (!config.browser[1].toLowerCase().includes('android')) {
|
|
49
|
+
payload.webInfo = getWebInfo(config)
|
|
50
|
+
}
|
|
47
51
|
return payload;
|
|
48
52
|
};
|
|
49
53
|
export const generateLoginNode = (userJid, config) => {
|
|
@@ -61,6 +65,9 @@ export const generateLoginNode = (userJid, config) => {
|
|
|
61
65
|
};
|
|
62
66
|
const getPlatformType = (platform) => {
|
|
63
67
|
const platformType = platform.toUpperCase();
|
|
68
|
+
if (platformType === 'ANDROID') {
|
|
69
|
+
return proto.DeviceProps.PlatformType.ANDROID_PHONE;
|
|
70
|
+
}
|
|
64
71
|
return (proto.DeviceProps.PlatformType[platformType] ||
|
|
65
72
|
proto.DeviceProps.PlatformType.CHROME);
|
|
66
73
|
};
|
|
@@ -77,6 +84,7 @@ export const generateRegistrationNode = ({ registrationId, signedPreKey, signedI
|
|
|
77
84
|
historySyncConfig: {
|
|
78
85
|
storageQuotaMb: 569150,
|
|
79
86
|
inlineInitialPayloadInE2EeMsg: true,
|
|
87
|
+
recentSyncDaysLimit: undefined,
|
|
80
88
|
supportCallLogHistory: false,
|
|
81
89
|
supportBotUserAgentChatHistory: true,
|
|
82
90
|
supportCagReactionsAndPolls: true,
|
|
@@ -84,7 +92,11 @@ export const generateRegistrationNode = ({ registrationId, signedPreKey, signedI
|
|
|
84
92
|
supportRecentSyncChunkMessageCountTuning: true,
|
|
85
93
|
supportHostedGroupMsg: true,
|
|
86
94
|
supportFbidBotChatHistory: true,
|
|
87
|
-
|
|
95
|
+
supportAddOnHistorySyncMigration: undefined,
|
|
96
|
+
supportMessageAssociation: true,
|
|
97
|
+
supportGroupHistory: false,
|
|
98
|
+
onDemandReady: undefined,
|
|
99
|
+
supportGuestChat: undefined
|
|
88
100
|
},
|
|
89
101
|
version: {
|
|
90
102
|
primary: 10,
|
|
@@ -23,6 +23,20 @@ export const VIOLATION_TYPES = {
|
|
|
23
23
|
'18': 'Terms of Service Violation',
|
|
24
24
|
'20': 'Illegal Content'
|
|
25
25
|
};
|
|
26
|
+
|
|
27
|
+
export const PROTOCOL_ADAPTERS = {
|
|
28
|
+
'redis:': '@keyv/redis',
|
|
29
|
+
'rediss:': '@keyv/redis',
|
|
30
|
+
'mongodb:': '@keyv/mongo',
|
|
31
|
+
'mongodb+srv:': '@keyv/mongo',
|
|
32
|
+
'postgresql:': '@keyv/postgres',
|
|
33
|
+
'postgres:': '@keyv/postgres',
|
|
34
|
+
'mysql:': '@keyv/mysql',
|
|
35
|
+
'sqlite:': '@keyv/sqlite',
|
|
36
|
+
'etcd:': '@keyv/etcd',
|
|
37
|
+
'memcache:': '@keyv/memcache',
|
|
38
|
+
'memcached:': '@keyv/memcache',
|
|
39
|
+
}
|
|
26
40
|
export const DOUBLE_BYTE_TOKENS = [
|
|
27
41
|
[
|
|
28
42
|
'read-self',
|
package/lib/index.js
CHANGED
|
@@ -31,7 +31,7 @@ const banner = `
|
|
|
31
31
|
const info = `
|
|
32
32
|
┌───────────────────────────────────────────────────────────────────────┐
|
|
33
33
|
│ 📦 Package: @nexustechpro/baileys │
|
|
34
|
-
│ 🔖 Version: 2.1.
|
|
34
|
+
│ 🔖 Version: 2.1.6 │
|
|
35
35
|
│ ⚡ Status: Production Ready │
|
|
36
36
|
├───────────────────────────────────────────────────────────────────────┤
|
|
37
37
|
│ 🚀 Advanced WhatsApp Web API Client │
|
package/package.json
CHANGED
|
@@ -2,9 +2,18 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@nexustechpro/baileys",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "2.1.
|
|
5
|
+
"version": "2.1.6",
|
|
6
6
|
"description": "Advanced WhatsApp Web API built on Baileys — interactive messages, buttons, carousels, products, events, payments, polls, albums, sticker packs and more.",
|
|
7
7
|
"keywords": [
|
|
8
|
+
"baileys",
|
|
9
|
+
"baileys-mod",
|
|
10
|
+
"baileys-fork",
|
|
11
|
+
"nexus",
|
|
12
|
+
"nexusbot",
|
|
13
|
+
"nexustech",
|
|
14
|
+
"nexustechpro",
|
|
15
|
+
"baileys-advanced",
|
|
16
|
+
"whiskeysockets",
|
|
8
17
|
"whatsapp",
|
|
9
18
|
"whatsapp-api",
|
|
10
19
|
"whatsapp-web",
|
|
@@ -24,17 +33,9 @@
|
|
|
24
33
|
"whatsapp-channel",
|
|
25
34
|
"whatsapp-status",
|
|
26
35
|
"whatsapp-pairing",
|
|
27
|
-
"baileys",
|
|
28
|
-
"baileys-mod",
|
|
29
|
-
"baileys-fork",
|
|
30
|
-
"baileys-advanced",
|
|
31
|
-
"whiskeysockets",
|
|
32
36
|
"wa-api",
|
|
33
37
|
"wa-bot",
|
|
34
38
|
"wa-web",
|
|
35
|
-
"nexus",
|
|
36
|
-
"nexusbot",
|
|
37
|
-
"nexustechpro",
|
|
38
39
|
"automation",
|
|
39
40
|
"bot",
|
|
40
41
|
"chatbot",
|
|
@@ -101,22 +102,32 @@
|
|
|
101
102
|
"@adiwajshing/keyed-db": "^0.2.4",
|
|
102
103
|
"@cacheable/node-cache": "^1.4.0",
|
|
103
104
|
"@hapi/boom": "^9.1.3",
|
|
105
|
+
"@keyv/etcd": "^2.1.1",
|
|
106
|
+
"@keyv/memcache": "^2.0.2",
|
|
107
|
+
"@keyv/mongo": "^3.1.0",
|
|
108
|
+
"@keyv/mysql": "^2.1.10",
|
|
109
|
+
"@keyv/postgres": "^2.2.3",
|
|
110
|
+
"@keyv/redis": "^5.1.6",
|
|
111
|
+
"@keyv/sqlite": "^4.0.8",
|
|
104
112
|
"@microlink/mql": "^0.16.1",
|
|
105
113
|
"async-mutex": "^0.5.0",
|
|
106
114
|
"axios": "^1.6.0",
|
|
107
115
|
"cache-manager": "latest",
|
|
108
116
|
"chalk": "^4.1.2",
|
|
109
117
|
"fflate": "^0.8.2",
|
|
118
|
+
"ffmpeg-static": "^5.3.0",
|
|
110
119
|
"gradient-string": "^2.0.2",
|
|
120
|
+
"keyv": "^5.6.0",
|
|
111
121
|
"libphonenumber-js": "^1.13.3",
|
|
112
122
|
"link-preview-js": "^4.0.3",
|
|
113
123
|
"lru-cache": "^11.1.0",
|
|
114
124
|
"music-metadata": "^11.7.0",
|
|
125
|
+
"node-cache": "^5.1.2",
|
|
115
126
|
"p-queue": "^9.0.0",
|
|
116
127
|
"pino": "^9.6",
|
|
128
|
+
"prismjs": "^1.30.0",
|
|
117
129
|
"protobufjs": "latest",
|
|
118
130
|
"qrcode-terminal": "^0.12.0",
|
|
119
|
-
"sharp": "^0.32.0",
|
|
120
131
|
"url-regex-safe": "^4.0.0",
|
|
121
132
|
"uuid": "latest",
|
|
122
133
|
"whatsapp-rust-bridge": "latest",
|
|
@@ -157,8 +168,9 @@
|
|
|
157
168
|
},
|
|
158
169
|
"peerDependencies": {
|
|
159
170
|
"audio-decode": "^2.1.3",
|
|
160
|
-
"jimp": "
|
|
161
|
-
"link-preview-js": "^4.0.3"
|
|
171
|
+
"jimp": "*",
|
|
172
|
+
"link-preview-js": "^4.0.3",
|
|
173
|
+
"sharp": "*"
|
|
162
174
|
},
|
|
163
175
|
"peerDependenciesMeta": {
|
|
164
176
|
"audio-decode": {
|
|
@@ -166,6 +178,9 @@
|
|
|
166
178
|
},
|
|
167
179
|
"jimp": {
|
|
168
180
|
"optional": true
|
|
181
|
+
},
|
|
182
|
+
"sharp": {
|
|
183
|
+
"optional": true
|
|
169
184
|
}
|
|
170
185
|
},
|
|
171
186
|
"packageManager": "yarn@4.9.2",
|