@nexustechpro/baileys 2.0.5 → 2.0.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/WAProto/index.js +22 -18
- package/lib/Defaults/baileys-version.json +1 -1
- package/lib/Defaults/index.js +7 -6
- package/lib/Signal/libsignal.js +65 -50
- package/lib/Socket/chats.js +64 -57
- package/lib/Socket/index.js +2 -3
- package/lib/Socket/messages-recv.js +227 -41
- package/lib/Socket/messages-send.js +79 -117
- package/lib/Socket/nexus-handler.js +325 -90
- package/lib/Socket/registration.js +50 -33
- package/lib/Socket/socket.js +232 -69
- package/lib/Types/Newsletter.js +37 -29
- package/lib/Types/State.js +43 -0
- package/lib/Utils/auth-utils.js +2 -2
- package/lib/Utils/chat-utils.js +48 -16
- package/lib/Utils/companion-reg-client-utils.js +34 -0
- package/lib/Utils/decode-wa-message.js +40 -8
- package/lib/Utils/generics.js +5 -7
- package/lib/Utils/index.js +4 -0
- package/lib/Utils/link-preview.js +10 -0
- package/lib/Utils/messages-media.js +426 -382
- package/lib/Utils/messages.js +602 -487
- package/lib/Utils/process-message.js +53 -35
- package/lib/Utils/reporting-utils.js +155 -0
- package/lib/Utils/signal.js +134 -104
- package/lib/Utils/sync-action-utils.js +33 -0
- package/lib/Utils/tc-token-utils.js +162 -0
- package/lib/WABinary/constants.js +6 -0
- package/lib/WABinary/index.js +1 -0
- package/lib/index.js +2 -3
- package/package.json +6 -4
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { proto } from '../../WAProto/index.js'
|
|
1
2
|
import axios from 'axios'
|
|
2
3
|
import crypto from 'crypto'
|
|
3
4
|
|
|
@@ -27,23 +28,24 @@ class NexusHandler {
|
|
|
27
28
|
// ─── TYPE DETECTION ───────────────────────────────────────────────────────
|
|
28
29
|
detectType(content) {
|
|
29
30
|
if (content.carouselMessage || content.carousel) return 'CAROUSEL'
|
|
30
|
-
|
|
31
|
+
if (content.carouselProto) return 'CAROUSEL_PROTO'
|
|
32
|
+
const map = {
|
|
31
33
|
requestPaymentMessage: 'PAYMENT', productMessage: 'PRODUCT',
|
|
32
34
|
interactiveMessage: 'INTERACTIVE', interactive: 'INTERACTIVE',
|
|
33
|
-
albumMessage: 'ALBUM', eventMessage: 'EVENT',
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
albumMessage: 'ALBUM', eventMessage: 'EVENT',
|
|
36
|
+
pollResultMessage: 'POLL_RESULT', statusMentionMessage: 'STATUS_MENTION',
|
|
37
|
+
orderMessage: 'ORDER', stickerPack: 'STICKER_PACK', groupStatus: 'GROUP_STATUS'
|
|
36
38
|
}
|
|
37
|
-
return
|
|
39
|
+
return map[Object.keys(map).find(k => content[k])] || null
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
// ─── UNIFIED PROCESSOR ────────────────────────────────────────────────────
|
|
41
43
|
async processMessage(content, jid, quoted) {
|
|
42
|
-
const
|
|
43
|
-
if (!
|
|
44
|
-
const handler = this.handlers[
|
|
45
|
-
if (!handler) throw new Error(`No handler for: ${
|
|
46
|
-
return
|
|
44
|
+
const type = this.detectType(content)
|
|
45
|
+
if (!type) throw new Error('Unknown message type')
|
|
46
|
+
const handler = this.handlers[type]
|
|
47
|
+
if (!handler) throw new Error(`No handler for: ${type}`)
|
|
48
|
+
return await handler(content, jid, quoted)
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
// ─── HELPERS ──────────────────────────────────────────────────────────────
|
|
@@ -53,7 +55,7 @@ class NexusHandler {
|
|
|
53
55
|
return await this.utils.prepareWAMessageMedia(payload, { upload: this.upload })
|
|
54
56
|
}
|
|
55
57
|
|
|
56
|
-
async
|
|
58
|
+
async genMsg(jid, content, opts = {}) {
|
|
57
59
|
return await this.utils.generateWAMessage(jid, content, {
|
|
58
60
|
...opts,
|
|
59
61
|
upload: this.upload,
|
|
@@ -63,37 +65,72 @@ class NexusHandler {
|
|
|
63
65
|
})
|
|
64
66
|
}
|
|
65
67
|
|
|
68
|
+
async genFromContent(jid, content, opts = {}) {
|
|
69
|
+
return await this.utils.generateWAMessageFromContent(jid, content, {
|
|
70
|
+
...opts,
|
|
71
|
+
userJid: opts.userJid || this.user?.id
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
|
|
66
75
|
async sendMsg(jid, message, opts = {}) {
|
|
67
76
|
return await this.relay(jid, message, opts)
|
|
68
77
|
}
|
|
69
78
|
|
|
70
79
|
buildCtx(quoted, sender) {
|
|
71
|
-
return {
|
|
80
|
+
return {
|
|
81
|
+
stanzaId: quoted?.key?.id,
|
|
82
|
+
participant: quoted?.key?.participant || sender,
|
|
83
|
+
quotedMessage: quoted?.message
|
|
84
|
+
}
|
|
72
85
|
}
|
|
73
86
|
|
|
74
87
|
buildFullCtx(ctx, adReply) {
|
|
88
|
+
const allowed = ['title', 'body', 'mediaType', 'thumbnailUrl', 'mediaUrl', 'sourceUrl', 'showAdAttribution', 'renderLargerThumbnail', 'thumbnail']
|
|
75
89
|
const final = ctx ? { mentionedJid: ctx.mentionedJid || [], forwardingScore: ctx.forwardingScore || 0, isForwarded: ctx.isForwarded || false, ...ctx } : {}
|
|
76
|
-
if (adReply)
|
|
90
|
+
if (adReply) {
|
|
91
|
+
final.externalAdReply = {}
|
|
92
|
+
for (const k of allowed) if (adReply[k] !== undefined) final.externalAdReply[k] = adReply[k]
|
|
93
|
+
final.externalAdReply = { mediaType: 1, showAdAttribution: false, renderLargerThumbnail: false, ...final.externalAdReply }
|
|
94
|
+
}
|
|
77
95
|
return final
|
|
78
96
|
}
|
|
79
97
|
|
|
80
|
-
genJid() {
|
|
81
|
-
|
|
82
|
-
|
|
98
|
+
genJid() {
|
|
99
|
+
const id = this.utils.generateMessageIDV2?.() || this.utils.generateMessageID?.() || crypto.randomBytes(10).toString('hex')
|
|
100
|
+
return id.includes('@') ? id : `${id}@s.whatsapp.net`
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
parseTime(val, def) { return typeof val === 'string' ? parseInt(val) : (val || def) }
|
|
104
|
+
delay(ms) { return new Promise(r => setTimeout(r, ms)) }
|
|
105
|
+
|
|
106
|
+
async downloadBuffer(urlOrBuffer) {
|
|
107
|
+
if (Buffer.isBuffer(urlOrBuffer)) return urlOrBuffer
|
|
108
|
+
if (typeof urlOrBuffer === 'string') {
|
|
109
|
+
try {
|
|
110
|
+
const res = await axios.get(urlOrBuffer, { responseType: 'arraybuffer' })
|
|
111
|
+
return Buffer.from(res.data)
|
|
112
|
+
} catch { this.opts.logger?.warn('Failed to download buffer from URL') }
|
|
113
|
+
}
|
|
114
|
+
return null
|
|
115
|
+
}
|
|
83
116
|
|
|
84
117
|
// ─── PAYMENT ──────────────────────────────────────────────────────────────
|
|
85
118
|
async handlePayment(content, jid, quoted) {
|
|
86
119
|
const d = content.requestPaymentMessage
|
|
120
|
+
const ctx = this.buildCtx(quoted, content.sender)
|
|
87
121
|
const notes = d.sticker?.stickerMessage
|
|
88
|
-
? { stickerMessage: { ...d.sticker.stickerMessage, contextInfo:
|
|
89
|
-
: d.note ? { extendedTextMessage: { text: d.note, contextInfo:
|
|
122
|
+
? { stickerMessage: { ...d.sticker.stickerMessage, contextInfo: ctx } }
|
|
123
|
+
: d.note ? { extendedTextMessage: { text: d.note, contextInfo: ctx } } : {}
|
|
90
124
|
const targetJid = jid || content.jid
|
|
91
|
-
const msg = await this.
|
|
92
|
-
requestPaymentMessage: {
|
|
93
|
-
expiryTimestamp: d.expiry || 0,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
125
|
+
const msg = await this.genFromContent(targetJid, {
|
|
126
|
+
requestPaymentMessage: proto.Message.RequestPaymentMessage.fromObject({
|
|
127
|
+
expiryTimestamp: d.expiry || 0,
|
|
128
|
+
amount1000: d.amount || 0,
|
|
129
|
+
currencyCodeIso4217: d.currency || 'IDR',
|
|
130
|
+
requestFrom: d.from || '0@s.whatsapp.net',
|
|
131
|
+
noteMessage: notes,
|
|
132
|
+
background: d.background ?? { id: 'DEFAULT', placeholderArgb: 0xfff0f0f0 }
|
|
133
|
+
})
|
|
97
134
|
}, { quoted })
|
|
98
135
|
await this.sendMsg(targetJid, msg.message, { messageId: msg.key.id })
|
|
99
136
|
return msg
|
|
@@ -104,13 +141,36 @@ class NexusHandler {
|
|
|
104
141
|
const p = content.productMessage || {}
|
|
105
142
|
let prodImg = null
|
|
106
143
|
if (p.thumbnail) {
|
|
107
|
-
const
|
|
108
|
-
const res = await this.utils.generateWAMessageContent(
|
|
144
|
+
const src = Buffer.isBuffer(p.thumbnail) ? { image: p.thumbnail } : { image: { url: p.thumbnail.url || p.thumbnail } }
|
|
145
|
+
const res = await this.utils.generateWAMessageContent(src, { upload: this.upload })
|
|
109
146
|
prodImg = res?.imageMessage || res?.message?.imageMessage
|
|
110
147
|
}
|
|
111
|
-
const product =
|
|
112
|
-
|
|
113
|
-
|
|
148
|
+
const product = proto.Message.ProductMessage.Product.create({
|
|
149
|
+
productId: p.productId,
|
|
150
|
+
title: p.title || '',
|
|
151
|
+
description: p.description || '',
|
|
152
|
+
currencyCode: p.currencyCode || 'IDR',
|
|
153
|
+
priceAmount1000: p.priceAmount1000,
|
|
154
|
+
retailerId: p.retailerId,
|
|
155
|
+
url: p.url,
|
|
156
|
+
productImageCount: prodImg ? 1 : 0,
|
|
157
|
+
...(prodImg && { productImage: prodImg })
|
|
158
|
+
})
|
|
159
|
+
const msg = await this.genFromContent(jid, {
|
|
160
|
+
viewOnceMessage: {
|
|
161
|
+
message: {
|
|
162
|
+
interactiveMessage: proto.Message.InteractiveMessage.create({
|
|
163
|
+
body: proto.Message.InteractiveMessage.Body.create({ text: p.body || '' }),
|
|
164
|
+
footer: proto.Message.InteractiveMessage.Footer.create({ text: p.footer || '' }),
|
|
165
|
+
header: proto.Message.InteractiveMessage.Header.create({
|
|
166
|
+
title: p.title || '',
|
|
167
|
+
hasMediaAttachment: !!prodImg,
|
|
168
|
+
productMessage: proto.Message.ProductMessage.create({ product, businessOwnerJid: '0@s.whatsapp.net' })
|
|
169
|
+
}),
|
|
170
|
+
nativeFlowMessage: proto.Message.InteractiveMessage.NativeFlowMessage.create({ buttons: p.buttons || [] })
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
}
|
|
114
174
|
}, { quoted })
|
|
115
175
|
await this.sendMsg(jid, msg.message, { messageId: msg.key.id })
|
|
116
176
|
return msg
|
|
@@ -130,26 +190,29 @@ class NexusHandler {
|
|
|
130
190
|
if (i.mimetype) media.documentMessage.mimetype = i.mimetype
|
|
131
191
|
}
|
|
132
192
|
const bodyText = i.body?.text || i.title || ''
|
|
133
|
-
const footerText = i.footer?.text || i.footer || ''
|
|
134
|
-
const
|
|
193
|
+
const footerText = i.footer?.text || (typeof i.footer === 'string' ? i.footer : '') || ''
|
|
194
|
+
const headerTitle = typeof i.header === 'string' ? i.header : i.header?.title || ''
|
|
195
|
+
let nativeFlow = null
|
|
135
196
|
if (i.buttons?.length || i.nativeFlowMessage) {
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (media.imageMessage) headerMedia.imageMessage = media.imageMessage
|
|
142
|
-
if (media.videoMessage) headerMedia.videoMessage = media.videoMessage
|
|
143
|
-
if (media.documentMessage) headerMedia.documentMessage = media.documentMessage
|
|
144
|
-
const headerTitle = typeof i.header === 'string' ? i.header : i.header?.title || ''
|
|
145
|
-
interactive.header = { title: headerTitle, hasMediaAttachment: true, ...headerMedia }
|
|
146
|
-
} else {
|
|
147
|
-
const headerTitle = typeof i.header === 'string' ? i.header : i.header?.title || ''
|
|
148
|
-
interactive.header = { title: headerTitle, hasMediaAttachment: false }
|
|
197
|
+
const nfm = i.nativeFlowMessage || {}
|
|
198
|
+
nativeFlow = proto.Message.InteractiveMessage.NativeFlowMessage.create({
|
|
199
|
+
buttons: i.buttons || nfm.buttons || [],
|
|
200
|
+
messageParamsJson: nfm.messageParamsJson || ''
|
|
201
|
+
})
|
|
149
202
|
}
|
|
203
|
+
const headerMedia = {}
|
|
204
|
+
if (media?.imageMessage) headerMedia.imageMessage = media.imageMessage
|
|
205
|
+
if (media?.videoMessage) headerMedia.videoMessage = media.videoMessage
|
|
206
|
+
if (media?.documentMessage) headerMedia.documentMessage = media.documentMessage
|
|
207
|
+
const interactive = proto.Message.InteractiveMessage.create({
|
|
208
|
+
body: proto.Message.InteractiveMessage.Body.create({ text: bodyText }),
|
|
209
|
+
footer: proto.Message.InteractiveMessage.Footer.create({ text: footerText }),
|
|
210
|
+
header: proto.Message.InteractiveMessage.Header.create({ title: headerTitle, hasMediaAttachment: !!media, ...headerMedia }),
|
|
211
|
+
...(nativeFlow && { nativeFlowMessage: nativeFlow })
|
|
212
|
+
})
|
|
150
213
|
const ctx = this.buildFullCtx(i.contextInfo, i.externalAdReply)
|
|
151
214
|
if (Object.keys(ctx).length) interactive.contextInfo = ctx
|
|
152
|
-
const msg = await this.
|
|
215
|
+
const msg = await this.genFromContent(jid, { interactiveMessage: interactive }, { quoted })
|
|
153
216
|
await this.sendMsg(jid, msg.message, { messageId: msg.key.id })
|
|
154
217
|
return msg
|
|
155
218
|
}
|
|
@@ -158,17 +221,51 @@ class NexusHandler {
|
|
|
158
221
|
async handleAlbum(content, jid, quoted) {
|
|
159
222
|
const arr = Array.isArray(content.albumMessage) ? content.albumMessage : []
|
|
160
223
|
if (!arr.length) throw new Error('albumMessage must contain media items')
|
|
161
|
-
const album = await this.
|
|
162
|
-
messageContextInfo: { messageSecret: crypto.randomBytes(32) },
|
|
163
|
-
albumMessage:
|
|
224
|
+
const album = await this.genFromContent(jid, {
|
|
225
|
+
messageContextInfo: proto.MessageContextInfo.create({ messageSecret: crypto.randomBytes(32) }),
|
|
226
|
+
albumMessage: proto.Message.AlbumMessage.create({
|
|
227
|
+
expectedImageCount: arr.filter(a => a.image).length,
|
|
228
|
+
expectedVideoCount: arr.filter(a => a.video).length
|
|
229
|
+
})
|
|
164
230
|
}, { userJid: this.genJid(), quoted })
|
|
165
231
|
await this.sendMsg(jid, album.message, { messageId: album.key.id })
|
|
166
232
|
for (const item of arr) {
|
|
167
|
-
const img = await this.
|
|
168
|
-
img.message.messageContextInfo =
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
233
|
+
const img = await this.genMsg(jid, item, {})
|
|
234
|
+
img.message.messageContextInfo = proto.MessageContextInfo.create({
|
|
235
|
+
messageSecret: crypto.randomBytes(32),
|
|
236
|
+
messageAssociation: proto.MessageAssociation.create({ associationType: 1, parentMessageKey: album.key }),
|
|
237
|
+
participant: '0@s.whatsapp.net',
|
|
238
|
+
remoteJid: 'status@broadcast',
|
|
239
|
+
forwardingScore: 99999,
|
|
240
|
+
isForwarded: true,
|
|
241
|
+
mentionedJid: [jid],
|
|
242
|
+
starred: true,
|
|
243
|
+
labels: ['Y', 'Important'],
|
|
244
|
+
isHighlighted: true,
|
|
245
|
+
businessMessageForwardInfo: proto.BusinessMessageForwardInfo.create({ businessOwnerJid: jid }),
|
|
246
|
+
dataSharingContext: proto.DataSharingContext.create({ showMmDisclosure: true })
|
|
247
|
+
})
|
|
248
|
+
img.message.forwardedNewsletterMessageInfo = proto.ForwardedNewsletterMessageInfo.create({
|
|
249
|
+
newsletterJid: '0@newsletter',
|
|
250
|
+
serverMessageId: 1,
|
|
251
|
+
newsletterName: 'WhatsApp',
|
|
252
|
+
contentType: 'UPDATE_CARD',
|
|
253
|
+
timestamp: new Date().toISOString(),
|
|
254
|
+
senderName: 'Nexus',
|
|
255
|
+
priority: 'high',
|
|
256
|
+
status: 'sent'
|
|
257
|
+
})
|
|
258
|
+
img.message.disappearingMode = proto.DisappearingMode.create({
|
|
259
|
+
initiator: 3, trigger: 4, initiatorDeviceJid: jid,
|
|
260
|
+
initiatedByExternalService: true, initiatedByUserDevice: true,
|
|
261
|
+
initiatedBySystem: true, initiatedByServer: true,
|
|
262
|
+
initiatedByAdmin: true, initiatedByUser: true,
|
|
263
|
+
initiatedByApp: true, initiatedByBot: true, initiatedByMe: true
|
|
264
|
+
})
|
|
265
|
+
await this.sendMsg(jid, img.message, {
|
|
266
|
+
messageId: img.key.id,
|
|
267
|
+
quoted: { key: { ...album.key, fromMe: true, participant: this.genJid() }, message: album.message }
|
|
268
|
+
})
|
|
172
269
|
}
|
|
173
270
|
return album
|
|
174
271
|
}
|
|
@@ -176,8 +273,37 @@ class NexusHandler {
|
|
|
176
273
|
// ─── EVENT ────────────────────────────────────────────────────────────────
|
|
177
274
|
async handleEvent(content, jid, quoted) {
|
|
178
275
|
const e = content.eventMessage
|
|
179
|
-
const msg = await this.
|
|
180
|
-
viewOnceMessage: {
|
|
276
|
+
const msg = await this.genFromContent(jid, {
|
|
277
|
+
viewOnceMessage: {
|
|
278
|
+
message: {
|
|
279
|
+
messageContextInfo: proto.MessageContextInfo.create({
|
|
280
|
+
deviceListMetadata: {},
|
|
281
|
+
deviceListMetadataVersion: 2,
|
|
282
|
+
messageSecret: crypto.randomBytes(32),
|
|
283
|
+
supportPayload: JSON.stringify({ version: 2, is_ai_message: true, should_show_system_message: true, ticket_id: crypto.randomBytes(16).toString('hex') })
|
|
284
|
+
}),
|
|
285
|
+
eventMessage: proto.Message.EventMessage.create({
|
|
286
|
+
contextInfo: proto.ContextInfo.create({
|
|
287
|
+
mentionedJid: [jid],
|
|
288
|
+
participant: jid,
|
|
289
|
+
remoteJid: 'status@broadcast',
|
|
290
|
+
forwardedNewsletterMessageInfo: proto.ForwardedNewsletterMessageInfo.create({
|
|
291
|
+
newsletterName: 'Nexus Events',
|
|
292
|
+
newsletterJid: '120363422827915475@newsletter',
|
|
293
|
+
serverMessageId: 1
|
|
294
|
+
})
|
|
295
|
+
}),
|
|
296
|
+
isCanceled: e.isCanceled || false,
|
|
297
|
+
name: e.name,
|
|
298
|
+
description: e.description,
|
|
299
|
+
location: e.location || { degreesLatitude: 0, degreesLongitude: 0, name: 'Location' },
|
|
300
|
+
joinLink: e.joinLink || '',
|
|
301
|
+
startTime: this.parseTime(e.startTime, Date.now()),
|
|
302
|
+
endTime: this.parseTime(e.endTime, Date.now() + 3600000),
|
|
303
|
+
extraGuestsAllowed: e.extraGuestsAllowed !== false
|
|
304
|
+
})
|
|
305
|
+
}
|
|
306
|
+
}
|
|
181
307
|
}, { quoted })
|
|
182
308
|
await this.sendMsg(jid, msg.message, { messageId: msg.key.id })
|
|
183
309
|
return msg
|
|
@@ -186,8 +312,24 @@ class NexusHandler {
|
|
|
186
312
|
// ─── POLL RESULT ──────────────────────────────────────────────────────────
|
|
187
313
|
async handlePollResult(content, jid, quoted) {
|
|
188
314
|
const p = content.pollResultMessage
|
|
189
|
-
const msg = await this.
|
|
190
|
-
pollResultSnapshotMessage:
|
|
315
|
+
const msg = await this.genFromContent(jid, {
|
|
316
|
+
pollResultSnapshotMessage: proto.Message.PollResultSnapshotMessage.create({
|
|
317
|
+
name: p.name,
|
|
318
|
+
pollVotes: (p.pollVotes || []).map(v => proto.Message.PollResultSnapshotMessage.PollVote.create({
|
|
319
|
+
optionName: v.optionName,
|
|
320
|
+
optionVoteCount: typeof v.optionVoteCount === 'number' ? v.optionVoteCount.toString() : v.optionVoteCount
|
|
321
|
+
})),
|
|
322
|
+
contextInfo: proto.ContextInfo.create({
|
|
323
|
+
isForwarded: true,
|
|
324
|
+
forwardingScore: 1,
|
|
325
|
+
forwardedNewsletterMessageInfo: proto.ForwardedNewsletterMessageInfo.create({
|
|
326
|
+
newsletterName: p.newsletter?.newsletterName || 'Newsletter',
|
|
327
|
+
newsletterJid: p.newsletter?.newsletterJid || '120363399602691477@newsletter',
|
|
328
|
+
serverMessageId: 1000,
|
|
329
|
+
contentType: 'UPDATE'
|
|
330
|
+
})
|
|
331
|
+
})
|
|
332
|
+
})
|
|
191
333
|
}, { userJid: this.genJid(), quoted })
|
|
192
334
|
await this.sendMsg(jid, msg.message, { messageId: msg.key.id })
|
|
193
335
|
return msg
|
|
@@ -196,30 +338,48 @@ class NexusHandler {
|
|
|
196
338
|
// ─── STATUS MENTION ───────────────────────────────────────────────────────
|
|
197
339
|
async handleStMention(content, jid, quoted) {
|
|
198
340
|
const d = content.statusMentionMessage
|
|
199
|
-
const
|
|
200
|
-
await this.
|
|
341
|
+
const mediaType = d.image ? 'image' : 'video'
|
|
342
|
+
const media = await this.prepMedia(d.image || d.video, mediaType)
|
|
343
|
+
const statusMsg = await this.relay('status@broadcast', { ...media }, {
|
|
201
344
|
statusJidList: [d.mentions, this.user?.id].filter(Boolean),
|
|
202
|
-
additionalNodes: [{
|
|
345
|
+
additionalNodes: [{
|
|
346
|
+
tag: 'meta', attrs: {},
|
|
347
|
+
content: [{ tag: 'mentioned_users', attrs: {}, content: [{ tag: 'to', attrs: { jid: d.mentions }, content: undefined }] }]
|
|
348
|
+
}]
|
|
203
349
|
})
|
|
204
|
-
const
|
|
205
|
-
statusMentionMessage: {
|
|
350
|
+
const mentionMsg = await this.genFromContent(jid, {
|
|
351
|
+
statusMentionMessage: proto.Message.StatusMentionMessage.create({
|
|
352
|
+
message: {
|
|
353
|
+
protocolMessage: proto.Message.ProtocolMessage.create({
|
|
354
|
+
messageId: statusMsg?.key?.id || d.mentions,
|
|
355
|
+
type: proto.Message.ProtocolMessage.Type.STATUS_MENTION_MESSAGE
|
|
356
|
+
})
|
|
357
|
+
}
|
|
358
|
+
})
|
|
206
359
|
}, { additionalNodes: [{ tag: 'meta', attrs: { is_status_mention: 'true' }, content: undefined }] })
|
|
207
|
-
await this.sendMsg(jid,
|
|
208
|
-
return
|
|
360
|
+
await this.sendMsg(jid, mentionMsg.message, { messageId: mentionMsg.key.id })
|
|
361
|
+
return mentionMsg
|
|
209
362
|
}
|
|
210
363
|
|
|
211
364
|
// ─── ORDER ────────────────────────────────────────────────────────────────
|
|
212
365
|
async handleOrderMessage(content, jid, quoted) {
|
|
213
366
|
const o = content.orderMessage
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
367
|
+
const thumb = await this.downloadBuffer(o.thumbnail)
|
|
368
|
+
const msg = await this.genFromContent(jid, {
|
|
369
|
+
orderMessage: proto.Message.OrderMessage.create({
|
|
370
|
+
orderId: '7NEXUS25022008',
|
|
371
|
+
thumbnail: thumb,
|
|
372
|
+
itemCount: o.itemCount || 0,
|
|
373
|
+
status: proto.Message.OrderMessage.OrderStatus.ACCEPTED,
|
|
374
|
+
surface: proto.Message.OrderMessage.OrderSurface.CATALOG,
|
|
375
|
+
message: o.message,
|
|
376
|
+
orderTitle: o.orderTitle,
|
|
377
|
+
sellerJid: '0@whatsapp.net',
|
|
378
|
+
token: 'NEXUS_EXAMPLE_TOKEN',
|
|
379
|
+
totalAmount1000: o.totalAmount1000 || 0,
|
|
380
|
+
totalCurrencyCode: o.totalCurrencyCode || 'IDR',
|
|
381
|
+
messageVersion: 2
|
|
382
|
+
})
|
|
223
383
|
}, { quoted })
|
|
224
384
|
await this.sendMsg(jid, msg.message, { messageId: msg.key.id })
|
|
225
385
|
return msg
|
|
@@ -228,62 +388,137 @@ class NexusHandler {
|
|
|
228
388
|
// ─── GROUP STATUS ─────────────────────────────────────────────────────────
|
|
229
389
|
async handleGroupStory(content, jid, quoted) {
|
|
230
390
|
const s = content.groupStatus
|
|
231
|
-
const mediaContent = await this.utils.generateWAMessageContent(s, {
|
|
232
|
-
|
|
233
|
-
|
|
391
|
+
const mediaContent = await this.utils.generateWAMessageContent(s, {
|
|
392
|
+
upload: this.upload,
|
|
393
|
+
getUrlInfo: this.opts.getUrlInfo,
|
|
394
|
+
logger: this.opts.logger
|
|
395
|
+
})
|
|
396
|
+
const msg = await this.genFromContent(jid, {
|
|
397
|
+
groupStatusMessageV2: proto.Message.GroupStatusMessageV2.create({ message: mediaContent })
|
|
398
|
+
}, { userJid: jid })
|
|
399
|
+
return await this.sendMsg(jid, msg.message, {
|
|
400
|
+
messageId: msg.key.id,
|
|
401
|
+
additionalNodes: [{ tag: 'meta', attrs: { is_group_status: 'true' }, content: undefined }]
|
|
402
|
+
})
|
|
234
403
|
}
|
|
235
404
|
|
|
236
405
|
// ─── CAROUSEL ─────────────────────────────────────────────────────────────
|
|
237
406
|
async handleCarousel(content, jid, quoted) {
|
|
238
407
|
const c = content.carouselMessage || content.carousel || {}
|
|
239
408
|
const cards = await Promise.all((c.cards || []).map(card => this.buildCard(card)))
|
|
240
|
-
const msg = await this.
|
|
241
|
-
viewOnceMessage: {
|
|
409
|
+
const msg = await this.genFromContent(jid, {
|
|
410
|
+
viewOnceMessage: {
|
|
411
|
+
message: {
|
|
412
|
+
interactiveMessage: proto.Message.InteractiveMessage.create({
|
|
413
|
+
body: proto.Message.InteractiveMessage.Body.create({ text: c.caption || c.body || '' }),
|
|
414
|
+
footer: proto.Message.InteractiveMessage.Footer.create({ text: c.footer || '' }),
|
|
415
|
+
carouselMessage: proto.Message.InteractiveMessage.CarouselMessage.create({ cards, messageVersion: 1 })
|
|
416
|
+
})
|
|
417
|
+
}
|
|
418
|
+
}
|
|
242
419
|
}, { quoted })
|
|
243
420
|
await this.sendMsg(jid, msg.message, { messageId: msg.key.id })
|
|
244
421
|
return msg
|
|
245
422
|
}
|
|
246
423
|
|
|
247
424
|
async buildCard(card) {
|
|
425
|
+
const buttons = (card.buttons || []).map(btn => ({
|
|
426
|
+
name: btn.name,
|
|
427
|
+
buttonParamsJson: JSON.stringify(btn.params || {})
|
|
428
|
+
}))
|
|
248
429
|
if (card.productTitle) {
|
|
249
|
-
|
|
430
|
+
const imgMedia = await this.prepMedia({ url: card.imageUrl }, 'image')
|
|
431
|
+
return {
|
|
432
|
+
header: proto.Message.InteractiveMessage.Header.create({
|
|
433
|
+
title: card.headerTitle || '',
|
|
434
|
+
subtitle: card.headerSubtitle || '',
|
|
435
|
+
hasMediaAttachment: false,
|
|
436
|
+
productMessage: proto.Message.ProductMessage.create({
|
|
437
|
+
product: proto.Message.ProductMessage.Product.create({
|
|
438
|
+
productImage: imgMedia?.imageMessage,
|
|
439
|
+
productId: card.productId || '123456',
|
|
440
|
+
title: card.productTitle,
|
|
441
|
+
description: card.productDescription || '',
|
|
442
|
+
currencyCode: card.currencyCode || 'IDR',
|
|
443
|
+
priceAmount1000: card.priceAmount1000 || '100000',
|
|
444
|
+
retailerId: card.retailerId || 'Retailer',
|
|
445
|
+
url: card.url || '',
|
|
446
|
+
productImageCount: 1
|
|
447
|
+
}),
|
|
448
|
+
businessOwnerJid: card.businessOwnerJid || '0@s.whatsapp.net'
|
|
449
|
+
})
|
|
450
|
+
}),
|
|
451
|
+
body: proto.Message.InteractiveMessage.Body.create({ text: card.bodyText || '' }),
|
|
452
|
+
footer: proto.Message.InteractiveMessage.Footer.create({ text: card.footerText || '' }),
|
|
453
|
+
nativeFlowMessage: proto.Message.InteractiveMessage.NativeFlowMessage.create({ buttons })
|
|
454
|
+
}
|
|
250
455
|
}
|
|
251
456
|
const imgMedia = card.imageUrl ? await this.prepMedia({ url: card.imageUrl }, 'image') : {}
|
|
252
|
-
return {
|
|
457
|
+
return {
|
|
458
|
+
header: proto.Message.InteractiveMessage.Header.create({
|
|
459
|
+
title: card.headerTitle || '',
|
|
460
|
+
subtitle: card.headerSubtitle || '',
|
|
461
|
+
hasMediaAttachment: !!card.imageUrl,
|
|
462
|
+
...imgMedia
|
|
463
|
+
}),
|
|
464
|
+
body: proto.Message.InteractiveMessage.Body.create({ text: card.bodyText || '' }),
|
|
465
|
+
footer: proto.Message.InteractiveMessage.Footer.create({ text: card.footerText || '' }),
|
|
466
|
+
nativeFlowMessage: proto.Message.InteractiveMessage.NativeFlowMessage.create({ buttons })
|
|
467
|
+
}
|
|
253
468
|
}
|
|
254
469
|
|
|
255
470
|
// ─── CAROUSEL PROTO ───────────────────────────────────────────────────────
|
|
256
471
|
async handleCarouselProto(content, jid, quoted) {
|
|
257
472
|
const c = content.carouselProto
|
|
258
|
-
const proto = this.utils.WAProto?.proto
|
|
259
|
-
if (!proto) throw new Error('WAProto not available')
|
|
260
473
|
const cards = await Promise.all((c.cards || []).map(async card => ({
|
|
261
|
-
header: proto.Message.InteractiveMessage.Header.create({
|
|
474
|
+
header: proto.Message.InteractiveMessage.Header.create({
|
|
475
|
+
title: card.title?.substring(0, 60) || '',
|
|
476
|
+
subtitle: card.subtitle || '',
|
|
477
|
+
hasMediaAttachment: false
|
|
478
|
+
}),
|
|
262
479
|
body: proto.Message.InteractiveMessage.Body.create({ text: card.bodyText || '' }),
|
|
263
480
|
footer: proto.Message.InteractiveMessage.Footer.create({ text: card.footerText || '' }),
|
|
264
|
-
nativeFlowMessage: proto.Message.InteractiveMessage.NativeFlowMessage.create({
|
|
481
|
+
nativeFlowMessage: proto.Message.InteractiveMessage.NativeFlowMessage.create({
|
|
482
|
+
buttons: (card.buttons || []).map(btn => ({ name: btn.name, buttonParamsJson: JSON.stringify(btn.params || {}) }))
|
|
483
|
+
})
|
|
265
484
|
})))
|
|
266
|
-
const msg = await this.
|
|
267
|
-
viewOnceMessage: {
|
|
485
|
+
const msg = await this.genFromContent(jid, {
|
|
486
|
+
viewOnceMessage: {
|
|
487
|
+
message: {
|
|
488
|
+
messageContextInfo: proto.MessageContextInfo.create({ deviceListMetadata: {}, deviceListMetadataVersion: 2 }),
|
|
489
|
+
interactiveMessage: proto.Message.InteractiveMessage.create({
|
|
490
|
+
body: proto.Message.InteractiveMessage.Body.create({ text: c.body || '' }),
|
|
491
|
+
footer: proto.Message.InteractiveMessage.Footer.create({ text: c.footer || '' }),
|
|
492
|
+
carouselMessage: proto.Message.InteractiveMessage.CarouselMessage.create({ cards })
|
|
493
|
+
})
|
|
494
|
+
}
|
|
495
|
+
}
|
|
268
496
|
}, { quoted })
|
|
269
497
|
await this.sendMsg(jid, msg.message, { messageId: msg.key.id })
|
|
270
498
|
return msg
|
|
271
499
|
}
|
|
272
500
|
|
|
273
501
|
// ─── STICKER PACK ─────────────────────────────────────────────────────────
|
|
274
|
-
async handleStickerPack(
|
|
275
|
-
const
|
|
502
|
+
async handleStickerPack(content, jid, quoted) {
|
|
503
|
+
const stickerPack = content.stickerPack
|
|
504
|
+
const result = await this.utils.prepareStickerPackMessage(stickerPack, {
|
|
505
|
+
logger: this.opts?.logger,
|
|
506
|
+
upload: this.upload,
|
|
507
|
+
mediaCache: this.opts?.mediaCache,
|
|
508
|
+
options: this.opts,
|
|
509
|
+
mediaUploadTimeoutMs: this.opts?.mediaUploadTimeoutMs
|
|
510
|
+
})
|
|
276
511
|
if (result.isBatched) {
|
|
277
512
|
const sent = []
|
|
278
513
|
for (let i = 0; i < result.stickerPackMessage.length; i++) {
|
|
279
|
-
const msg = await this.
|
|
514
|
+
const msg = await this.genFromContent(jid, { stickerPackMessage: result.stickerPackMessage[i] }, { quoted })
|
|
280
515
|
await this.sendMsg(jid, msg.message, { messageId: msg.key.id })
|
|
281
516
|
sent.push(msg)
|
|
282
517
|
if (i < result.stickerPackMessage.length - 1) await this.delay(2000)
|
|
283
518
|
}
|
|
284
519
|
return sent[sent.length - 1]
|
|
285
520
|
}
|
|
286
|
-
const msg = await this.
|
|
521
|
+
const msg = await this.genFromContent(jid, { stickerPackMessage: result.stickerPackMessage }, { quoted })
|
|
287
522
|
await this.sendMsg(jid, msg.message, { messageId: msg.key.id })
|
|
288
523
|
return msg
|
|
289
524
|
}
|