@zervonex/baileys 3.0.3 → 3.0.4
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 +31 -0
- package/WAProto/WAProtoCompile.js +1 -0
- package/WAProto/fetcher.js +17 -33
- package/WAProto/index.js +34 -26
- package/WAProto/parser.js +333 -312
- package/lib/Builders/AIRich.js +14 -14
- package/lib/Builders/base.js +3 -3
- package/lib/Builders/builders.js +460 -448
- package/lib/Socket/messages-recv.js +1 -1
- package/lib/Socket/messages-send.js +1 -1
- package/lib/Socket/socket.js +4 -3
- package/lib/Socket/zervonex-handler.js +1 -1
- package/lib/Utils/browser-utils.js +8 -4
- package/lib/Utils/chat-utils.js +1 -1
- package/lib/Utils/messages.js +91 -40
- package/lib/Utils/use-multi-file-auth-state.js +50 -157
- package/lib/Utils/validate-connection.js +19 -28
- package/lib/WABinary/generic-utils.js +43 -19
- package/lib/index.js +1 -1
- package/package.json +55 -90
package/README.md
CHANGED
|
@@ -73,6 +73,7 @@
|
|
|
73
73
|
- [AI Rich Messages](#ai-rich-messages)
|
|
74
74
|
- [Status & Stories](#personal-status--story-statusbroadcast)
|
|
75
75
|
- [Sticker Pack](#sticker-pack)
|
|
76
|
+
- [Premium Stickers](#premium-stickers)
|
|
76
77
|
- [Shorthand Wrappers](#shorthand-wrappers)
|
|
77
78
|
- [Message Modifications](#️-message-modifications)
|
|
78
79
|
- [Media Download](#-media-download)
|
|
@@ -442,6 +443,18 @@ await clearSession()
|
|
|
442
443
|
|
|
443
444
|
`clearSession()` wipes every key belonging to that `sessionId` — creds, prekeys, sessions, sender keys, everything — using each backend's native namespace-scoped bulk delete (a real `deleteMany`/`DELETE WHERE`/`SCAN`+delete under the hood, not a per-key loop). It only affects this session; other sessions sharing the same backend are untouched. There's no equivalent method on `useMultiFileAuthState` — delete the session folder instead.
|
|
444
445
|
|
|
446
|
+
#### Checking auth without loading full state
|
|
447
|
+
|
|
448
|
+
```javascript
|
|
449
|
+
import { hasKeyvAuth } from '@zervonex/baileys'
|
|
450
|
+
|
|
451
|
+
// Check if a session has valid auth (lightweight — no full state load)
|
|
452
|
+
const valid = await hasKeyvAuth('bot1', backend)
|
|
453
|
+
// true if creds exist and contain noiseKey + signedIdentityKey
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
`hasKeyvAuth()` queries the backend using the correct Keyv namespace — the same way `useKeyvAuthState` does internally — so it always returns the right answer regardless of your backend. Useful for checking session ownership before deciding whether to restore a connection, without the overhead of initializing a full auth state.
|
|
457
|
+
|
|
445
458
|
#### Options
|
|
446
459
|
|
|
447
460
|
| Option | Type | Default | Description |
|
|
@@ -1363,6 +1376,23 @@ await sock.stickerPackMessage(jid, {
|
|
|
1363
1376
|
}, { quoted: message })
|
|
1364
1377
|
```
|
|
1365
1378
|
|
|
1379
|
+
### Premium Stickers
|
|
1380
|
+
|
|
1381
|
+
Pass `premium` on a single sticker:
|
|
1382
|
+
```js
|
|
1383
|
+
await sock.sendMessage(jid, { sticker: buffer, premium: 1 })
|
|
1384
|
+
```
|
|
1385
|
+
|
|
1386
|
+
Per-sticker in a pack:
|
|
1387
|
+
```js
|
|
1388
|
+
await sock.sendMessage(jid, { stickerPack: { stickers: [{ data: buffer, emojis: ['🔥'], premium: 1 }] } })
|
|
1389
|
+
```
|
|
1390
|
+
|
|
1391
|
+
Whole pack as premium:
|
|
1392
|
+
```js
|
|
1393
|
+
await sock.sendMessage(jid, { stickerPack: { premium: 1, stickers: [...] } })
|
|
1394
|
+
```
|
|
1395
|
+
|
|
1366
1396
|
**Per-sticker options:**
|
|
1367
1397
|
|
|
1368
1398
|
| Field | Type | Default | Description |
|
|
@@ -2961,6 +2991,7 @@ import {
|
|
|
2961
2991
|
makeWASocket,
|
|
2962
2992
|
useMultiFileAuthState,
|
|
2963
2993
|
useKeyvAuthState,
|
|
2994
|
+
hasKeyvAuth,
|
|
2964
2995
|
makeCacheableSignalKeyStore,
|
|
2965
2996
|
Browsers,
|
|
2966
2997
|
DisconnectReason,
|
|
@@ -255,6 +255,7 @@ function makeProto(tablePath) {
|
|
|
255
255
|
node.toObject = o => o ?? {}
|
|
256
256
|
node.verify = () => null
|
|
257
257
|
node.name = full.split('.').pop()
|
|
258
|
+
node.fields = Object.fromEntries(TABLE[full].order.map(f => [f.name, { type: f.s ?? f.k, id: f.id, repeated: f.rep ?? false }]))
|
|
258
259
|
}
|
|
259
260
|
for (const [full, values] of Object.entries(e)) {
|
|
260
261
|
const node = nodeFor(full.replace(/^proto\./, '').split('.'))
|
package/WAProto/fetcher.js
CHANGED
|
@@ -1,69 +1,53 @@
|
|
|
1
1
|
import { fetch, Agent } from 'undici'
|
|
2
2
|
import { createHash } from 'crypto'
|
|
3
|
-
import { readFileSync, writeFileSync, existsSync } from 'fs'
|
|
3
|
+
import { readFileSync, writeFileSync, existsSync, createWriteStream, unlinkSync } from 'fs'
|
|
4
|
+
import { pipeline } from 'stream/promises'
|
|
4
5
|
import { join, dirname } from 'path'
|
|
5
6
|
import { fileURLToPath } from 'url'
|
|
6
7
|
|
|
7
8
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
8
9
|
const CACHE_FILE = join(__dirname, '.cache.json')
|
|
9
10
|
const PROTO_FILE = join(__dirname, 'WAProto.proto')
|
|
10
|
-
|
|
11
|
+
const BUNDLE_TMP = join(__dirname, 'WAProto.bundle.tmp')
|
|
11
12
|
const GITHUB_RAW = 'https://raw.githubusercontent.com/nexustechpro2/baileys/wa-cache'
|
|
12
13
|
const CACHE_TTL = 24 * 60 * 60 * 1000
|
|
13
|
-
|
|
14
|
-
const agent = new Agent({ connect: { family: 4 } })
|
|
14
|
+
const agent = new Agent({ connect: { family: 4, timeout: 60000 } })
|
|
15
15
|
|
|
16
16
|
const isCacheValid = (cache) => cache.version && cache.timestamp && (Date.now() - cache.timestamp) < CACHE_TTL
|
|
17
17
|
const readCache = () => { try { return existsSync(CACHE_FILE) ? JSON.parse(readFileSync(CACHE_FILE, 'utf8')) : {} } catch { return {} } }
|
|
18
18
|
const writeCache = (data) => writeFileSync(CACHE_FILE, JSON.stringify({ ...data, timestamp: Date.now() }, null, 2), 'utf8')
|
|
19
|
+
const removeTmp = () => { try { if (existsSync(BUNDLE_TMP)) unlinkSync(BUNDLE_TMP) } catch { } }
|
|
19
20
|
|
|
20
21
|
async function fetchFromGitHub(file) {
|
|
21
22
|
const res = await fetch(`${GITHUB_RAW}/${file}`, { method: 'GET', dispatcher: agent })
|
|
22
23
|
if (!res.ok) throw new Error(`[WAProto] GitHub fetch failed: ${res.status} for ${file}`)
|
|
23
|
-
|
|
24
|
+
if (file.endsWith('.json')) return res.json()
|
|
25
|
+
const hash = createHash('sha256')
|
|
26
|
+
const writer = createWriteStream(BUNDLE_TMP)
|
|
27
|
+
await pipeline(res.body, async function* (source) { for await (const chunk of source) { hash.update(chunk); yield chunk } }, writer)
|
|
28
|
+
return hash.digest('hex')
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
async function fetchClientRevision() {
|
|
27
32
|
const data = await fetchFromGitHub('wa-version.json')
|
|
28
|
-
if (!data?.version) throw new Error('[WAProto]
|
|
33
|
+
if (!data?.version) throw new Error('[WAProto] wa-version.json missing version field')
|
|
29
34
|
return String(data.version)
|
|
30
35
|
}
|
|
31
36
|
|
|
32
|
-
async function fetchCombinedBundle() {
|
|
33
|
-
return fetchFromGitHub('WAProto.bundle.js')
|
|
34
|
-
}
|
|
35
|
-
|
|
36
37
|
export async function fetchProtoBundle() {
|
|
37
38
|
const cache = readCache()
|
|
38
39
|
if (isCacheValid(cache) && existsSync(PROTO_FILE)) return { changed: false, bundle: null, version: cache.version }
|
|
39
|
-
|
|
40
40
|
const version = await fetchClientRevision()
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return { changed: false, bundle: null, version }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
let bundle = await fetchCombinedBundle()
|
|
48
|
-
const hash = createHash('sha256').update(bundle).digest('hex')
|
|
49
|
-
|
|
50
|
-
if (cache.hash === hash) {
|
|
51
|
-
writeCache({ version, hash })
|
|
52
|
-
return { changed: false, bundle: null, version }
|
|
53
|
-
}
|
|
54
|
-
|
|
41
|
+
if (cache.version === version && existsSync(PROTO_FILE)) { writeCache({ ...cache, version }); return { changed: false, bundle: null, version } }
|
|
42
|
+
const hash = await fetchFromGitHub('WAProto.bundle.js')
|
|
43
|
+
if (cache.hash === hash) { writeCache({ version, hash }); removeTmp(); return { changed: false, bundle: null, version } }
|
|
55
44
|
writeCache({ version, hash })
|
|
56
|
-
|
|
57
|
-
bundle = null
|
|
58
|
-
return result
|
|
45
|
+
return { changed: true, bundlePath: BUNDLE_TMP, version }
|
|
59
46
|
}
|
|
60
47
|
|
|
61
48
|
export async function getWAVersion() {
|
|
62
49
|
const cache = readCache()
|
|
63
50
|
if (isCacheValid(cache) && cache.version) return [2, 3000, parseInt(cache.version)]
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (!data?.version) throw new Error('[WAProto] GitHub wa-version.json missing version field')
|
|
67
|
-
|
|
68
|
-
return [2, 3000, parseInt(data.version)]
|
|
51
|
+
const version = await fetchClientRevision()
|
|
52
|
+
return [2, 3000, parseInt(version)]
|
|
69
53
|
}
|
package/WAProto/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, unlinkSync, readFileSync } from 'fs'
|
|
2
2
|
import { join, dirname } from 'path'
|
|
3
3
|
import { fileURLToPath } from 'url'
|
|
4
|
+
import { Worker, isMainThread, workerData, parentPort } from 'worker_threads'
|
|
4
5
|
import logger from '../lib/Utils/logger.js'
|
|
5
6
|
import { fetchProtoBundle } from './fetcher.js'
|
|
6
7
|
import { generateTable, _reloadProto } from './WAProtoCompile.js'
|
|
@@ -9,37 +10,33 @@ import { parseBundle } from './parser.js'
|
|
|
9
10
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
10
11
|
const PROTO_FILE = join(__dirname, 'WAProto.proto')
|
|
11
12
|
const TABLE_FILE = join(__dirname, 'WAProto.json')
|
|
13
|
+
const SELF = new URL(import.meta.url)
|
|
12
14
|
|
|
13
15
|
const log = msg => logger.info(msg)
|
|
14
16
|
const err = msg => logger.error(msg)
|
|
17
|
+
const del = (...files) => { for (const f of files) { try { if (existsSync(f)) unlinkSync(f) } catch { } } }
|
|
18
|
+
const isJsonValid = () => { try { const { m, t } = JSON.parse(readFileSync(TABLE_FILE, 'utf8')); return Array.isArray(m) && m.length > 0 && typeof t === 'object' && Object.keys(t).length > 0 } catch { return false } }
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
function runInWorker(data) {
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
const w = new Worker(SELF, { workerData: data })
|
|
23
|
+
w.once('message', msg => { w.terminate(); msg.ok ? resolve() : reject(new Error(msg.error)) })
|
|
24
|
+
w.once('error', reject)
|
|
25
|
+
})
|
|
21
26
|
}
|
|
22
27
|
|
|
23
|
-
const del = (...files) => { for (const f of files) { try { if (existsSync(f)) unlinkSync(f) } catch { } } }
|
|
24
|
-
|
|
25
28
|
async function regenerateFromProto() {
|
|
26
29
|
log('Regenerating WAProto.json from existing WAProto.proto...')
|
|
27
|
-
await
|
|
30
|
+
await runInWorker({ bundlePath: null, version: null, protoPath: PROTO_FILE, tablePath: TABLE_FILE })
|
|
28
31
|
_reloadProto()
|
|
29
32
|
log('Regenerated successfully')
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
async function refetch() {
|
|
33
36
|
log('Fetching proto bundle from GitHub...')
|
|
34
|
-
const { bundle, version } = await fetchProtoBundle()
|
|
35
|
-
if (!bundle) throw new Error('fetchProtoBundle returned no bundle')
|
|
36
|
-
|
|
37
|
-
const { writeFileSync } = await import('fs')
|
|
38
|
-
const tmp = PROTO_FILE + '.tmp'
|
|
39
|
-
writeFileSync(tmp, protoText, 'utf8')
|
|
40
|
-
const { renameSync } = await import('fs')
|
|
41
|
-
renameSync(tmp, PROTO_FILE)
|
|
42
|
-
await generateTable(PROTO_FILE, TABLE_FILE)
|
|
37
|
+
const { bundle, bundlePath, version } = await fetchProtoBundle()
|
|
38
|
+
if (!bundle && !bundlePath) throw new Error('fetchProtoBundle returned no bundle')
|
|
39
|
+
await runInWorker({ bundlePath: bundlePath ?? null, bundle: bundle ?? null, version, protoPath: PROTO_FILE, tablePath: TABLE_FILE })
|
|
43
40
|
_reloadProto()
|
|
44
41
|
log(`Fetched and compiled — WA version ${version}`)
|
|
45
42
|
}
|
|
@@ -59,7 +56,6 @@ async function boot() {
|
|
|
59
56
|
}
|
|
60
57
|
return
|
|
61
58
|
}
|
|
62
|
-
|
|
63
59
|
if (hasProto && !hasJson) {
|
|
64
60
|
log('WAProto.json missing — generating from existing proto...')
|
|
65
61
|
try { await regenerateFromProto(); return } catch (e) {
|
|
@@ -69,19 +65,31 @@ async function boot() {
|
|
|
69
65
|
}
|
|
70
66
|
return
|
|
71
67
|
}
|
|
72
|
-
|
|
73
|
-
if (hasJson && !hasProto) {
|
|
74
|
-
err('WAProto.proto missing but WAProto.json exists — cannot trust JSON, refetching...')
|
|
75
|
-
del(TABLE_FILE)
|
|
76
|
-
await refetch()
|
|
77
|
-
return
|
|
78
|
-
}
|
|
68
|
+
if (hasJson && !hasProto) { err('WAProto.proto missing but WAProto.json exists — cannot trust JSON, refetching...'); del(TABLE_FILE); await refetch(); return }
|
|
79
69
|
|
|
80
70
|
log('No proto files found — fetching from GitHub...')
|
|
81
71
|
await refetch()
|
|
82
72
|
}
|
|
83
73
|
|
|
84
|
-
|
|
74
|
+
if (!isMainThread) {
|
|
75
|
+
const { bundlePath, bundle, version, protoPath, tablePath } = workerData
|
|
76
|
+
try {
|
|
77
|
+
if (bundlePath || bundle) {
|
|
78
|
+
const src = bundlePath ? readFileSync(bundlePath, 'utf8') : bundle
|
|
79
|
+
if (bundlePath) unlinkSync(bundlePath)
|
|
80
|
+
const { writeFileSync, renameSync } = await import('fs')
|
|
81
|
+
const tmp = protoPath + '.tmp'
|
|
82
|
+
writeFileSync(tmp, parseBundle(src, version), 'utf8')
|
|
83
|
+
renameSync(tmp, protoPath)
|
|
84
|
+
}
|
|
85
|
+
await generateTable(protoPath, tablePath)
|
|
86
|
+
parentPort.postMessage({ ok: true })
|
|
87
|
+
} catch (e) {
|
|
88
|
+
parentPort.postMessage({ ok: false, error: e.message })
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
await boot()
|
|
92
|
+
}
|
|
85
93
|
|
|
86
94
|
export { proto, codec, generateTable, _reloadProto } from './WAProtoCompile.js'
|
|
87
95
|
export { getWAVersion, fetchProtoBundle } from './fetcher.js'
|