@badzz88/baileys 8.5.2 → 8.5.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 +1 -1
- package/WAProto/WAProto.proto +1256 -75
- package/WAProto/index.d.ts +36042 -19649
- package/WAProto/index.js +181990 -135645
- package/engine-requirements.js +7 -15
- package/lib/Defaults/index.js +22 -17
- package/lib/Signal/Group/group_cipher.js +5 -5
- package/lib/Signal/Group/keyhelper.js +4 -4
- package/lib/Signal/Group/sender-chain-key.js +2 -2
- package/lib/Signal/Group/sender-key-distribution-message.js +1 -1
- package/lib/Signal/Group/sender-key-message.js +3 -3
- package/lib/Signal/Group/sender-key-record.js +1 -1
- package/lib/Signal/Group/sender-message-key.js +5 -5
- package/lib/Signal/libsignal.js +39 -59
- package/lib/Signal/lid-mapping.js +28 -10
- package/lib/Socket/aigroups.js +5 -5
- package/lib/Socket/business.js +3 -11
- package/lib/Socket/chats.js +668 -319
- package/lib/Socket/communities.js +85 -89
- package/lib/Socket/graphql.js +435 -228
- package/lib/Socket/groups.js +132 -211
- package/lib/Socket/index.js +9 -7
- package/lib/Socket/interactive-handler.js +117 -60
- package/lib/Socket/interop.js +56 -175
- package/lib/Socket/managed-account.js +79 -48
- package/lib/Socket/messages-recv.js +898 -340
- package/lib/Socket/messages-send.js +462 -160
- package/lib/Socket/mex.js +40 -53
- package/lib/Socket/newsletter.js +291 -291
- package/lib/Socket/privacy.js +77 -265
- package/lib/Socket/registration.js +164 -157
- package/lib/Socket/socket.js +181 -199
- package/lib/Socket/username.js +144 -227
- package/lib/Store/make-cache-manager-store.js +2 -2
- package/lib/Store/make-in-memory-store.js +25 -141
- package/lib/Types/Auth.js +3 -3
- package/lib/Types/Label.js +1 -1
- package/lib/Types/LabelAssociation.js +1 -1
- package/lib/Types/Newsletter.js +96 -65
- package/lib/Types/State.js +4 -4
- package/lib/Types/index.js +1 -1
- package/lib/Utils/auth-utils.js +52 -57
- package/lib/Utils/browser-utils.js +1 -1
- package/lib/Utils/business.js +2 -6
- package/lib/Utils/chat-utils.js +102 -38
- package/lib/Utils/crypto.js +54 -84
- package/lib/Utils/decode-wa-message.js +316 -83
- package/lib/Utils/event-buffer.js +37 -61
- package/lib/Utils/generics.js +157 -103
- package/lib/Utils/group-history.js +3 -12
- package/lib/Utils/history.js +15 -15
- package/lib/Utils/index.js +1 -5
- package/lib/Utils/link-preview.js +3 -8
- package/lib/Utils/lt-hash.js +2 -35
- package/lib/Utils/make-mutex.js +1 -1
- package/lib/Utils/message-inspect.js +393 -0
- package/lib/Utils/message-retry-manager.js +27 -92
- package/lib/Utils/messages-media.js +159 -130
- package/lib/Utils/messages.js +144 -566
- package/lib/Utils/meta-ai-msmsg.js +62 -202
- package/lib/Utils/noise-handler.js +19 -21
- package/lib/Utils/offline-node-processor.js +3 -8
- package/lib/Utils/pre-key-manager.js +13 -23
- package/lib/Utils/process-message.js +197 -106
- package/lib/Utils/reporting-utils.js +2 -2
- package/lib/Utils/signal.js +28 -63
- package/lib/Utils/stanza-ack.js +39 -12
- package/lib/Utils/sync-action-utils.js +4 -7
- package/lib/Utils/tc-token-utils.js +20 -25
- package/lib/Utils/use-multi-file-auth-state.js +30 -14
- package/lib/Utils/validate-connection.js +59 -19
- package/lib/WABinary/decode.js +50 -16
- package/lib/WABinary/encode.js +54 -224
- package/lib/WABinary/generic-utils.js +7 -97
- package/lib/WABinary/jid-utils.js +27 -14
- package/lib/WAM/encode.js +7 -7
- package/lib/WAUSync/Protocols/USyncBusinessProtocol.js +58 -1
- package/lib/WAUSync/Protocols/USyncContactProtocol.js +7 -1
- package/lib/WAUSync/Protocols/USyncDeviceProtocol.js +13 -5
- package/lib/WAUSync/Protocols/USyncDisappearingModeProtocol.js +1 -4
- package/lib/WAUSync/Protocols/USyncFeatureProtocol.js +20 -7
- package/lib/WAUSync/Protocols/USyncNewsletterProtocol.js +865 -0
- package/lib/WAUSync/Protocols/USyncPictureProtocol.js +1 -1
- package/lib/WAUSync/Protocols/USyncSidelistProtocol.js +2 -2
- package/lib/WAUSync/Protocols/USyncStatusProtocol.js +7 -2
- package/lib/WAUSync/Protocols/USyncTextStatusProtocol.js +1 -1
- package/lib/WAUSync/Protocols/USyncUsernameProtocol.js +2 -1
- package/lib/WAUSync/Protocols/index.js +1 -0
- package/lib/WAUSync/USyncBackoff.js +26 -0
- package/lib/WAUSync/USyncQuery.js +77 -6
- package/lib/WAUSync/USyncUser.js +16 -8
- package/lib/WAUSync/index.js +1 -0
- package/lib/antiban.js +608 -854
- package/lib/index.js +3 -3
- package/package.json +16 -19
- package/lib/Socket/luxu.js +0 -387
- package/lib/Socket/text-router.js +0 -83
- package/lib/Store/keyed-db.js +0 -108
- package/lib/Types/Mex.js +0 -112
- package/lib/Utils/command-loader.d.ts +0 -31
- package/lib/Utils/command-loader.js +0 -100
- package/lib/Utils/companion-reg-client-utils.js +0 -42
- package/lib/Utils/curve25519-js.js +0 -275
- package/lib/Utils/native-bridge.js +0 -82
- package/lib/Utils/session-pool.d.ts +0 -16
- package/lib/Utils/session-pool.js +0 -94
- package/lib/Utils/sticker.d.ts +0 -17
- package/lib/Utils/sticker.js +0 -145
- package/lib/Utils/view-once-cache.d.ts +0 -9
- package/lib/Utils/view-once-cache.js +0 -79
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
Object.defineProperty(exports, '__esModule', { value: true })
|
|
3
|
-
exports.createSessionPool = void 0
|
|
4
|
-
|
|
5
|
-
const DISCONNECT_REASON_LOGGED_OUT = 401
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Manages multiple Baileys socket instances (one per account/session), automatically
|
|
9
|
-
* restarting any session that disconnects -- except when it was logged out -- using
|
|
10
|
-
* exponential backoff with jitter, instead of every project re-implementing its own
|
|
11
|
-
* reconnect loop.
|
|
12
|
-
*
|
|
13
|
-
* @param {{
|
|
14
|
-
* makeSocket: (sessionId: string) => Promise<any> | any,
|
|
15
|
-
* logger?: any,
|
|
16
|
-
* maxBackoffMs?: number,
|
|
17
|
-
* onSessionUpdate?: (sessionId: string, sock: any) => void,
|
|
18
|
-
* onLoggedOut?: (sessionId: string) => void
|
|
19
|
-
* }} options
|
|
20
|
-
* @returns {{
|
|
21
|
-
* add: (sessionId: string) => Promise<void>,
|
|
22
|
-
* remove: (sessionId: string) => void,
|
|
23
|
-
* get: (sessionId: string) => any,
|
|
24
|
-
* list: () => string[]
|
|
25
|
-
* }}
|
|
26
|
-
*/
|
|
27
|
-
const createSessionPool = options => {
|
|
28
|
-
const logger = options.logger
|
|
29
|
-
const maxBackoffMs = options.maxBackoffMs ?? 60000
|
|
30
|
-
const sessions = new Map() // sessionId -> { sock, attempts, stopped }
|
|
31
|
-
|
|
32
|
-
const computeBackoffMs = attempts => {
|
|
33
|
-
const base = Math.min(1000 * 2 ** attempts, maxBackoffMs)
|
|
34
|
-
return base + Math.floor(Math.random() * (base * 0.2))
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const start = async sessionId => {
|
|
38
|
-
const entry = sessions.get(sessionId) || { attempts: 0, stopped: false }
|
|
39
|
-
sessions.set(sessionId, entry)
|
|
40
|
-
if (entry.stopped) return
|
|
41
|
-
try {
|
|
42
|
-
const sock = await options.makeSocket(sessionId)
|
|
43
|
-
entry.sock = sock
|
|
44
|
-
options.onSessionUpdate?.(sessionId, sock)
|
|
45
|
-
sock.ev.on('connection.update', update => {
|
|
46
|
-
if (update.connection === 'open') {
|
|
47
|
-
entry.attempts = 0
|
|
48
|
-
}
|
|
49
|
-
if (update.connection === 'close') {
|
|
50
|
-
const statusCode = update.lastDisconnect?.error?.output?.statusCode
|
|
51
|
-
if (statusCode === DISCONNECT_REASON_LOGGED_OUT) {
|
|
52
|
-
logger?.info?.({ sessionId }, 'session logged out, removing from pool')
|
|
53
|
-
sessions.delete(sessionId)
|
|
54
|
-
options.onLoggedOut?.(sessionId)
|
|
55
|
-
return
|
|
56
|
-
}
|
|
57
|
-
if (entry.stopped) return
|
|
58
|
-
entry.attempts += 1
|
|
59
|
-
const backoffMs = computeBackoffMs(entry.attempts)
|
|
60
|
-
logger?.warn?.(
|
|
61
|
-
{ sessionId, attempt: entry.attempts, backoffMs },
|
|
62
|
-
'session disconnected, reconnecting with backoff'
|
|
63
|
-
)
|
|
64
|
-
setTimeout(() => start(sessionId), backoffMs)
|
|
65
|
-
}
|
|
66
|
-
})
|
|
67
|
-
} catch (error) {
|
|
68
|
-
entry.attempts += 1
|
|
69
|
-
const backoffMs = computeBackoffMs(entry.attempts)
|
|
70
|
-
logger?.error?.({ error, sessionId, backoffMs }, 'failed to start session, retrying with backoff')
|
|
71
|
-
if (!entry.stopped) {
|
|
72
|
-
setTimeout(() => start(sessionId), backoffMs)
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const add = sessionId => start(sessionId)
|
|
78
|
-
const remove = sessionId => {
|
|
79
|
-
const entry = sessions.get(sessionId)
|
|
80
|
-
if (!entry) return
|
|
81
|
-
entry.stopped = true
|
|
82
|
-
if (entry.sock?.end) {
|
|
83
|
-
try {
|
|
84
|
-
entry.sock.end(undefined)
|
|
85
|
-
} catch {}
|
|
86
|
-
}
|
|
87
|
-
sessions.delete(sessionId)
|
|
88
|
-
}
|
|
89
|
-
const get = sessionId => sessions.get(sessionId)?.sock
|
|
90
|
-
const list = () => [...sessions.keys()]
|
|
91
|
-
|
|
92
|
-
return { add, remove, get, list }
|
|
93
|
-
}
|
|
94
|
-
exports.createSessionPool = createSessionPool
|
package/lib/Utils/sticker.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export interface StickerMetaOptions {
|
|
2
|
-
packName?: string
|
|
3
|
-
packPublisher?: string
|
|
4
|
-
categories?: string[]
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function addExifToWebp(webpBuffer: Buffer, options?: StickerMetaOptions): Promise<Buffer>
|
|
8
|
-
|
|
9
|
-
export function imageToWebpSticker(
|
|
10
|
-
imageBuffer: Buffer,
|
|
11
|
-
options?: StickerMetaOptions & { quality?: number }
|
|
12
|
-
): Promise<Buffer>
|
|
13
|
-
|
|
14
|
-
export function videoToWebpSticker(
|
|
15
|
-
videoBuffer: Buffer,
|
|
16
|
-
options?: StickerMetaOptions & { fps?: number; seconds?: number }
|
|
17
|
-
): Promise<Buffer>
|
package/lib/Utils/sticker.js
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
Object.defineProperty(exports, '__esModule', { value: true })
|
|
3
|
-
exports.imageToWebpSticker = exports.videoToWebpSticker = exports.addExifToWebp = void 0
|
|
4
|
-
const os = require('os')
|
|
5
|
-
const path = require('path')
|
|
6
|
-
const fs = require('fs')
|
|
7
|
-
const crypto = require('crypto')
|
|
8
|
-
const { exec } = require('child_process')
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Builds and writes the EXIF metadata WhatsApp expects on sticker webp files
|
|
12
|
-
* (pack name / author, shown when a user long-presses a sticker).
|
|
13
|
-
* Converts the file to the "extended" (VP8X) WebP container if it isn't already,
|
|
14
|
-
* since that's the container format that actually carries an EXIF chunk.
|
|
15
|
-
* Returns the new buffer with EXIF attached.
|
|
16
|
-
*/
|
|
17
|
-
const addExifToWebp = async (webpBuffer, { packName = '', packPublisher = '', categories = [] } = {}) => {
|
|
18
|
-
const json = {
|
|
19
|
-
'sticker-pack-id': crypto.randomBytes(16).toString('hex'),
|
|
20
|
-
'sticker-pack-name': packName,
|
|
21
|
-
'sticker-pack-publisher': packPublisher,
|
|
22
|
-
emojis: categories.length ? categories : ['😀']
|
|
23
|
-
}
|
|
24
|
-
const jsonBuffer = Buffer.from(JSON.stringify(json), 'utf-8')
|
|
25
|
-
// TIFF header + IFD entry pointing at a single custom tag (0x5741 "AW") holding
|
|
26
|
-
// the JSON payload -- this is the exact structure WhatsApp's client parses.
|
|
27
|
-
const exifAttr = Buffer.from([
|
|
28
|
-
0x49, 0x49, 0x2a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0x57, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
|
|
29
|
-
0x00, 0x00, 0x00
|
|
30
|
-
])
|
|
31
|
-
exifAttr.writeUIntLE(jsonBuffer.length, 14, 4)
|
|
32
|
-
const exifPayload = Buffer.concat([exifAttr, jsonBuffer])
|
|
33
|
-
const pad = buf => (buf.length % 2 === 1 ? Buffer.concat([buf, Buffer.from([0x00])]) : buf)
|
|
34
|
-
const makeChunk = (tag, data) => {
|
|
35
|
-
const sizeField = Buffer.alloc(4)
|
|
36
|
-
sizeField.writeUInt32LE(data.length, 0)
|
|
37
|
-
return Buffer.concat([Buffer.from(tag, 'ascii'), sizeField, pad(data)])
|
|
38
|
-
}
|
|
39
|
-
const exifChunk = makeChunk('EXIF', exifPayload)
|
|
40
|
-
if (webpBuffer.slice(0, 4).toString('ascii') !== 'RIFF' || webpBuffer.slice(8, 12).toString('ascii') !== 'WEBP') {
|
|
41
|
-
throw new Error('addExifToWebp expects a valid WebP buffer')
|
|
42
|
-
}
|
|
43
|
-
let offset = 12
|
|
44
|
-
let vp8xChunk = null
|
|
45
|
-
let vp8xOffset = -1
|
|
46
|
-
const otherChunks = []
|
|
47
|
-
while (offset < webpBuffer.length) {
|
|
48
|
-
const tag = webpBuffer.slice(offset, offset + 4).toString('ascii')
|
|
49
|
-
const size = webpBuffer.readUInt32LE(offset + 4)
|
|
50
|
-
const dataStart = offset + 8
|
|
51
|
-
const dataEnd = dataStart + size
|
|
52
|
-
const chunkTotal = 8 + size + (size % 2)
|
|
53
|
-
if (tag === 'VP8X') {
|
|
54
|
-
vp8xChunk = webpBuffer.slice(offset, offset + chunkTotal)
|
|
55
|
-
vp8xOffset = offset
|
|
56
|
-
} else if (tag !== 'EXIF') {
|
|
57
|
-
// drop any pre-existing EXIF chunk, keep everything else (VP8/VP8L/ANIM/ANMF/ICCP/...)
|
|
58
|
-
otherChunks.push(webpBuffer.slice(offset, offset + chunkTotal))
|
|
59
|
-
}
|
|
60
|
-
offset += chunkTotal
|
|
61
|
-
}
|
|
62
|
-
let flags
|
|
63
|
-
let canvasWidth
|
|
64
|
-
let canvasHeight
|
|
65
|
-
if (vp8xChunk) {
|
|
66
|
-
flags = vp8xChunk.readUInt8(8)
|
|
67
|
-
canvasWidth = vp8xChunk.readUIntLE(12, 3) + 1
|
|
68
|
-
canvasHeight = vp8xChunk.readUIntLE(15, 3) + 1
|
|
69
|
-
} else {
|
|
70
|
-
flags = 0
|
|
71
|
-
let sharp
|
|
72
|
-
try {
|
|
73
|
-
sharp = require('sharp')
|
|
74
|
-
} catch (error) {
|
|
75
|
-
throw new Error('addExifToWebp needs the optional "sharp" dependency to read image dimensions')
|
|
76
|
-
}
|
|
77
|
-
const meta = await sharp(webpBuffer).metadata()
|
|
78
|
-
canvasWidth = meta.width
|
|
79
|
-
canvasHeight = meta.height
|
|
80
|
-
}
|
|
81
|
-
flags |= 0x08 // set the "has EXIF metadata" bit
|
|
82
|
-
const vp8xData = Buffer.alloc(10)
|
|
83
|
-
vp8xData.writeUInt8(flags, 0)
|
|
84
|
-
vp8xData.writeUIntLE(canvasWidth - 1, 4, 3)
|
|
85
|
-
vp8xData.writeUIntLE(canvasHeight - 1, 7, 3)
|
|
86
|
-
const newVp8xChunk = makeChunk('VP8X', vp8xData)
|
|
87
|
-
const body = Buffer.concat([newVp8xChunk, ...otherChunks, exifChunk])
|
|
88
|
-
const fileSize = Buffer.alloc(4)
|
|
89
|
-
fileSize.writeUInt32LE(4 + body.length, 0) // 4 = 'WEBP'
|
|
90
|
-
return Buffer.concat([Buffer.from('RIFF', 'ascii'), fileSize, Buffer.from('WEBP', 'ascii'), body])
|
|
91
|
-
}
|
|
92
|
-
exports.addExifToWebp = addExifToWebp
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Converts a static image buffer to a WhatsApp sticker-ready webp buffer using `sharp`.
|
|
96
|
-
* @param {Buffer} imageBuffer
|
|
97
|
-
* @param {{ packName?: string, packPublisher?: string, categories?: string[], quality?: number }} [options]
|
|
98
|
-
* @returns {Promise<Buffer>}
|
|
99
|
-
*/
|
|
100
|
-
const imageToWebpSticker = async (imageBuffer, options = {}) => {
|
|
101
|
-
let sharp
|
|
102
|
-
try {
|
|
103
|
-
sharp = require('sharp')
|
|
104
|
-
} catch (error) {
|
|
105
|
-
throw new Error('imageToWebpSticker requires the optional "sharp" dependency to be installed')
|
|
106
|
-
}
|
|
107
|
-
const webp = await sharp(imageBuffer)
|
|
108
|
-
.resize(512, 512, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } })
|
|
109
|
-
.webp({ quality: options.quality ?? 80 })
|
|
110
|
-
.toBuffer()
|
|
111
|
-
return addExifToWebp(webp, options)
|
|
112
|
-
}
|
|
113
|
-
exports.imageToWebpSticker = imageToWebpSticker
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Converts a video buffer to an animated WhatsApp sticker-ready webp buffer.
|
|
117
|
-
* Requires the `ffmpeg` binary to be available on PATH.
|
|
118
|
-
* @param {Buffer} videoBuffer
|
|
119
|
-
* @param {{ packName?: string, packPublisher?: string, categories?: string[], fps?: number, seconds?: number }} [options]
|
|
120
|
-
* @returns {Promise<Buffer>}
|
|
121
|
-
*/
|
|
122
|
-
const videoToWebpSticker = async (videoBuffer, options = {}) => {
|
|
123
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'xazbails-sticker-'))
|
|
124
|
-
const inputPath = path.join(tmpDir, 'input.mp4')
|
|
125
|
-
const outputPath = path.join(tmpDir, 'output.webp')
|
|
126
|
-
fs.writeFileSync(inputPath, videoBuffer)
|
|
127
|
-
const fps = options.fps ?? 10
|
|
128
|
-
const seconds = options.seconds ?? 5
|
|
129
|
-
const cmd =
|
|
130
|
-
`ffmpeg -y -i ${inputPath} -t ${seconds} -vf ` +
|
|
131
|
-
`"fps=${fps},scale=512:512:force_original_aspect_ratio=decrease,` +
|
|
132
|
-
`pad=512:512:(ow-iw)/2:(oh-ih)/2:color=0x00000000,split[a][b];` +
|
|
133
|
-
`[a]palettegen=reserve_transparent=1[p];[b][p]paletteuse" ` +
|
|
134
|
-
`-loop 0 -preset default -an -vsync 0 ${outputPath}`
|
|
135
|
-
try {
|
|
136
|
-
await new Promise((resolve, reject) => {
|
|
137
|
-
exec(cmd, err => (err ? reject(err) : resolve()))
|
|
138
|
-
})
|
|
139
|
-
const webp = fs.readFileSync(outputPath)
|
|
140
|
-
return await addExifToWebp(webp, options)
|
|
141
|
-
} finally {
|
|
142
|
-
fs.rmSync(tmpDir, { recursive: true, force: true })
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
exports.videoToWebpSticker = videoToWebpSticker
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export interface AutoCacheViewOnceOptions {
|
|
2
|
-
cacheDir?: string
|
|
3
|
-
logger?: any
|
|
4
|
-
onCached?: (info: { id: string; jid: string; filePath: string; type: string }) => void
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function getViewOnceContent(message: any): Record<string, any> | null
|
|
8
|
-
|
|
9
|
-
export function autoCacheViewOnceMedia(sock: any, options?: AutoCacheViewOnceOptions): () => void
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
Object.defineProperty(exports, '__esModule', { value: true })
|
|
3
|
-
exports.autoCacheViewOnceMedia = void 0
|
|
4
|
-
const path = require('path')
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
const Messages_1 = require('./messages')
|
|
7
|
-
const MessagesMedia_1 = require('./messages-media')
|
|
8
|
-
|
|
9
|
-
const VIEW_ONCE_WRAPPER_KEYS = ['viewOnceMessage', 'viewOnceMessageV2', 'viewOnceMessageV2Extension']
|
|
10
|
-
const VIEW_ONCE_INNER_KEYS = ['imageMessage', 'videoMessage', 'audioMessage']
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Unwraps a message and returns the inner view-once media content if present, otherwise null.
|
|
14
|
-
* Handles both the wrapper style (viewOnceMessage[V2/V2Extension] -> message -> ...)
|
|
15
|
-
* and the inline style (imageMessage/videoMessage with viewOnce: true set directly).
|
|
16
|
-
*/
|
|
17
|
-
const getViewOnceContent = message => {
|
|
18
|
-
if (!message) return null
|
|
19
|
-
const content = (0, Messages_1.extractMessageContent)(message)
|
|
20
|
-
if (!content) return null
|
|
21
|
-
for (const wrapperKey of VIEW_ONCE_WRAPPER_KEYS) {
|
|
22
|
-
const wrapper = content[wrapperKey]
|
|
23
|
-
if (wrapper?.message) {
|
|
24
|
-
const inner = (0, Messages_1.extractMessageContent)(wrapper.message)
|
|
25
|
-
if (inner) return inner
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
for (const key of VIEW_ONCE_INNER_KEYS) {
|
|
29
|
-
if (content[key]?.viewOnce) {
|
|
30
|
-
return { [key]: content[key] }
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return null
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Registers a `messages.upsert` listener on the given socket that automatically
|
|
38
|
-
* downloads and saves view-once media (image/video/audio) to `cacheDir` as soon
|
|
39
|
-
* as it arrives, before the sender's app can mark it as opened/consumed.
|
|
40
|
-
*
|
|
41
|
-
* @param {ReturnType<typeof import('../Socket').default>} sock - an active Baileys socket
|
|
42
|
-
* @param {{ cacheDir?: string, logger?: any, onCached?: (info: { id: string, jid: string, filePath: string, type: string }) => void }} [options]
|
|
43
|
-
* @returns {() => void} a function that removes the listener
|
|
44
|
-
*/
|
|
45
|
-
const autoCacheViewOnceMedia = (sock, options = {}) => {
|
|
46
|
-
const cacheDir = options.cacheDir || './viewonce-cache'
|
|
47
|
-
const logger = options.logger || sock.logger
|
|
48
|
-
if (!fs.existsSync(cacheDir)) {
|
|
49
|
-
fs.mkdirSync(cacheDir, { recursive: true })
|
|
50
|
-
}
|
|
51
|
-
const handler = async ({ messages, type }) => {
|
|
52
|
-
if (type !== 'notify' && type !== 'append') return
|
|
53
|
-
for (const msg of messages) {
|
|
54
|
-
try {
|
|
55
|
-
const viewOnceContent = getViewOnceContent(msg.message)
|
|
56
|
-
if (!viewOnceContent) continue
|
|
57
|
-
const mediaType = Object.keys(viewOnceContent)[0]
|
|
58
|
-
const buffer = await (0, Messages_1.downloadMediaMessage)(
|
|
59
|
-
msg,
|
|
60
|
-
'buffer',
|
|
61
|
-
{},
|
|
62
|
-
{ logger, reuploadRequest: sock.updateMediaMessage }
|
|
63
|
-
)
|
|
64
|
-
const extension = (0, MessagesMedia_1.extensionForMediaMessage)(viewOnceContent) || 'bin'
|
|
65
|
-
const fileName = `${msg.key.id}.${extension}`
|
|
66
|
-
const filePath = path.join(cacheDir, fileName)
|
|
67
|
-
fs.writeFileSync(filePath, buffer)
|
|
68
|
-
logger?.debug?.({ id: msg.key.id, filePath, mediaType }, 'cached view-once media')
|
|
69
|
-
options.onCached?.({ id: msg.key.id, jid: msg.key.remoteJid, filePath, type: mediaType })
|
|
70
|
-
} catch (error) {
|
|
71
|
-
logger?.warn?.({ error, id: msg.key?.id }, 'failed to cache view-once media')
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
sock.ev.on('messages.upsert', handler)
|
|
76
|
-
return () => sock.ev.off('messages.upsert', handler)
|
|
77
|
-
}
|
|
78
|
-
exports.autoCacheViewOnceMedia = autoCacheViewOnceMedia
|
|
79
|
-
exports.getViewOnceContent = getViewOnceContent
|