@areumtecnologia/wasockets 2.2.3 → 2.3.1
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 +98 -25
- package/lib/Client/Builders/Buttons.js +127 -0
- package/lib/Client/Builders/EventBuilder.js +122 -0
- package/lib/Client/Builders/InteractiveMessage.js +150 -0
- package/lib/Client/Builders/Lists.js +78 -0
- package/lib/Client/Builders/PollBuilder.js +84 -0
- package/lib/Client/Builders/index.js +21 -0
- package/lib/Client/Constants.js +54 -0
- package/lib/Client/Context/CallContext.js +96 -0
- package/lib/Client/Context/MediaObject.js +155 -0
- package/lib/Client/Context/MessageContext.js +213 -0
- package/lib/Client/Modules/BusinessManager.js +155 -0
- package/lib/Client/Modules/ChannelManager.js +144 -0
- package/lib/Client/Modules/ChatManager.js +113 -0
- package/lib/Client/Modules/CommunityManager.js +136 -0
- package/lib/Client/Modules/GroupManager.js +194 -0
- package/lib/Client/Modules/LabelManager.js +123 -0
- package/lib/Client/Modules/MessageManager.js +198 -0
- package/lib/Client/Modules/PresenceManager.js +68 -0
- package/lib/Client/Modules/PrivacyManager.js +98 -0
- package/lib/Client/Modules/ProfileManager.js +92 -0
- package/lib/Client/Modules/UserManager.js +92 -0
- package/lib/Client/Modules/VoipManager.js +117 -0
- package/lib/Client/Modules/index.js +29 -0
- package/lib/Client/Normalizers/EventNormalizer.js +99 -0
- package/lib/Client/Normalizers/JidNormalizer.js +96 -0
- package/lib/Client/Normalizers/MessageNormalizer.js +422 -0
- package/lib/Client/WaClient.js +438 -0
- package/lib/Client/index.d.ts +547 -0
- package/lib/Client/index.js +76 -0
- package/package.json +29 -23
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true })
|
|
4
|
+
|
|
5
|
+
class MessageNormalizer {
|
|
6
|
+
/**
|
|
7
|
+
* Recursively unwraps all container wrappers (ephemeral, viewOnce, associatedChild, etc.)
|
|
8
|
+
* @param {Object} rawMessageContent - raw message node from proto
|
|
9
|
+
* @returns {Object} Unwrapped message object
|
|
10
|
+
*/
|
|
11
|
+
static unwrapMessage(rawMessageContent) {
|
|
12
|
+
if (!rawMessageContent) return null
|
|
13
|
+
|
|
14
|
+
let msg = rawMessageContent
|
|
15
|
+
let unwrapped = true
|
|
16
|
+
|
|
17
|
+
// Loop to peel away multiple layers of wrappers if nested
|
|
18
|
+
while (unwrapped && msg) {
|
|
19
|
+
unwrapped = false
|
|
20
|
+
|
|
21
|
+
if (msg.ephemeralMessage?.message) {
|
|
22
|
+
msg = msg.ephemeralMessage.message
|
|
23
|
+
unwrapped = true
|
|
24
|
+
continue
|
|
25
|
+
}
|
|
26
|
+
if (msg.viewOnceMessage?.message) {
|
|
27
|
+
msg = msg.viewOnceMessage.message
|
|
28
|
+
unwrapped = true
|
|
29
|
+
continue
|
|
30
|
+
}
|
|
31
|
+
if (msg.viewOnceMessageV2?.message) {
|
|
32
|
+
msg = msg.viewOnceMessageV2.message
|
|
33
|
+
unwrapped = true
|
|
34
|
+
continue
|
|
35
|
+
}
|
|
36
|
+
if (msg.viewOnceMessageV2Extension?.message) {
|
|
37
|
+
msg = msg.viewOnceMessageV2Extension.message
|
|
38
|
+
unwrapped = true
|
|
39
|
+
continue
|
|
40
|
+
}
|
|
41
|
+
if (msg.documentWithCaptionMessage?.message) {
|
|
42
|
+
msg = msg.documentWithCaptionMessage.message
|
|
43
|
+
unwrapped = true
|
|
44
|
+
continue
|
|
45
|
+
}
|
|
46
|
+
if (msg.associatedChildMessage?.message) {
|
|
47
|
+
msg = msg.associatedChildMessage.message
|
|
48
|
+
unwrapped = true
|
|
49
|
+
continue
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return msg
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Identifies the primary friendly content type of the message (28 distinct types)
|
|
58
|
+
* @param {Object} messageContent - Raw or unwrapped message content
|
|
59
|
+
* @returns {string} Normalized friendly type
|
|
60
|
+
*/
|
|
61
|
+
static extractType(messageContent) {
|
|
62
|
+
const msg = this.unwrapMessage(messageContent)
|
|
63
|
+
if (!msg) return 'unknown'
|
|
64
|
+
|
|
65
|
+
// 1. Text & Media Basics
|
|
66
|
+
if (msg.conversation || msg.extendedTextMessage) return 'text'
|
|
67
|
+
if (msg.imageMessage) return 'image'
|
|
68
|
+
if (msg.albumMessage) return 'album'
|
|
69
|
+
if (msg.videoMessage) return msg.videoMessage.gifPlayback ? 'gif' : 'video'
|
|
70
|
+
if (msg.audioMessage) return msg.audioMessage.ptt ? 'voice' : 'audio'
|
|
71
|
+
if (msg.documentMessage) return 'document'
|
|
72
|
+
if (msg.stickerMessage) return 'sticker'
|
|
73
|
+
if (msg.locationMessage) return 'location'
|
|
74
|
+
if (msg.liveLocationMessage) return 'live_location'
|
|
75
|
+
if (msg.contactMessage || msg.contactsArrayMessage) return 'contact'
|
|
76
|
+
|
|
77
|
+
// 2. Polls & Events
|
|
78
|
+
if (msg.pollCreationMessage || msg.pollCreationMessageV2 || msg.pollCreationMessageV3) return 'poll_creation'
|
|
79
|
+
if (msg.pollUpdateMessage) return 'poll_update'
|
|
80
|
+
if (msg.eventMessage) return 'event'
|
|
81
|
+
if (msg.eventResponseMessage || msg.encEventResponseMessage) return 'event_response'
|
|
82
|
+
|
|
83
|
+
// 3. Reactions & Pins
|
|
84
|
+
if (msg.reactionMessage) return 'reaction'
|
|
85
|
+
if (msg.pinInChatMessage) return 'pin_in_chat'
|
|
86
|
+
if (msg.unpinInChatMessage) return 'unpin_in_chat'
|
|
87
|
+
|
|
88
|
+
// 4. Replies from Buttons, Lists & Questions
|
|
89
|
+
if (msg.buttonsResponseMessage) return 'button_reply'
|
|
90
|
+
if (msg.listResponseMessage) return 'list_reply'
|
|
91
|
+
if (msg.templateButtonReplyMessage) return 'template_button_reply'
|
|
92
|
+
if (msg.questionReplyMessage) return 'question_reply'
|
|
93
|
+
|
|
94
|
+
// 5. Specific Interactive Flow Buttons
|
|
95
|
+
const firstBtnName = msg.interactiveMessage?.interactiveButtons?.[0]?.name
|
|
96
|
+
if (firstBtnName) {
|
|
97
|
+
switch (firstBtnName) {
|
|
98
|
+
case 'review_and_pay': return 'review_and_pay'
|
|
99
|
+
case 'review_order': return 'review_order'
|
|
100
|
+
case 'quick_reply': return 'quick_reply'
|
|
101
|
+
case 'cta_url': return 'cta_url'
|
|
102
|
+
case 'cta_copy': return 'cta_copy'
|
|
103
|
+
case 'cta_call': return 'cta_call'
|
|
104
|
+
case 'voice_call': return 'voice_call'
|
|
105
|
+
case 'payment_info': return 'payment_info'
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// 6. Native Flow Responses
|
|
110
|
+
if (msg.interactiveResponseMessage?.nativeFlowResponseMessage) {
|
|
111
|
+
const flowName = msg.interactiveResponseMessage.nativeFlowResponseMessage.name
|
|
112
|
+
if (flowName === 'menu_options') return 'native_flow_menu_options_response'
|
|
113
|
+
return 'native_flow_response'
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// 7. Interactive Containers
|
|
117
|
+
if (msg.interactiveMessage?.interactiveButtons) return 'interactive_buttons'
|
|
118
|
+
if (msg.interactiveMessage?.interactiveList) return 'interactive_list'
|
|
119
|
+
if (msg.interactiveResponseMessage) return 'interactive_response'
|
|
120
|
+
if (msg.interactiveMessage) return 'interactive_message'
|
|
121
|
+
|
|
122
|
+
// 8. Protocol
|
|
123
|
+
if (msg.protocolMessage) return 'protocol'
|
|
124
|
+
|
|
125
|
+
// Fallback to first non-metadata proto key
|
|
126
|
+
const keys = Object.keys(msg).filter(k => k !== 'messageContextInfo' && k !== 'senderKeyDistributionMessage')
|
|
127
|
+
return keys[0] ? keys[0].replace('Message', '').toLowerCase() : 'unknown'
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Extracts readable text content across diverse message structures
|
|
132
|
+
* @param {Object} messageContent - Raw or unwrapped message content
|
|
133
|
+
* @returns {string} Text body
|
|
134
|
+
*/
|
|
135
|
+
static extractBody(messageContent) {
|
|
136
|
+
const msg = this.unwrapMessage(messageContent)
|
|
137
|
+
if (!msg) return ''
|
|
138
|
+
|
|
139
|
+
// Direct Text
|
|
140
|
+
if (msg.conversation) return msg.conversation
|
|
141
|
+
if (msg.extendedTextMessage?.text) return msg.extendedTextMessage.text
|
|
142
|
+
|
|
143
|
+
// Media Captions
|
|
144
|
+
if (msg.imageMessage?.caption) return msg.imageMessage.caption
|
|
145
|
+
if (msg.videoMessage?.caption) return msg.videoMessage.caption
|
|
146
|
+
if (msg.documentMessage?.caption) return msg.documentMessage.caption
|
|
147
|
+
|
|
148
|
+
// Button / List selections
|
|
149
|
+
if (msg.buttonsResponseMessage?.selectedDisplayText) return msg.buttonsResponseMessage.selectedDisplayText
|
|
150
|
+
if (msg.buttonsResponseMessage?.selectedButtonId) return msg.buttonsResponseMessage.selectedButtonId
|
|
151
|
+
if (msg.listResponseMessage?.title) return msg.listResponseMessage.title
|
|
152
|
+
if (msg.templateButtonReplyMessage?.selectedDisplayText) return msg.templateButtonReplyMessage.selectedDisplayText
|
|
153
|
+
if (msg.templateButtonReplyMessage?.selectedId) return msg.templateButtonReplyMessage.selectedId
|
|
154
|
+
|
|
155
|
+
// Interactive / Native Flows
|
|
156
|
+
if (msg.interactiveResponseMessage?.body?.text) return msg.interactiveResponseMessage.body.text
|
|
157
|
+
if (msg.interactiveResponseMessage?.nativeFlowResponseMessage?.paramsJson) {
|
|
158
|
+
return msg.interactiveResponseMessage.nativeFlowResponseMessage.paramsJson
|
|
159
|
+
}
|
|
160
|
+
if (msg.interactiveMessage?.body?.text) return msg.interactiveMessage.body.text
|
|
161
|
+
|
|
162
|
+
// Polls, Reactions, Questions & Locations
|
|
163
|
+
if (msg.pollCreationMessage?.name) return msg.pollCreationMessage.name
|
|
164
|
+
if (msg.pollCreationMessageV2?.name) return msg.pollCreationMessageV2.name
|
|
165
|
+
if (msg.pollCreationMessageV3?.name) return msg.pollCreationMessageV3.name
|
|
166
|
+
if (msg.reactionMessage?.text) return msg.reactionMessage.text
|
|
167
|
+
if (msg.questionReplyMessage?.message?.extendedTextMessage?.text) return msg.questionReplyMessage.message.extendedTextMessage.text
|
|
168
|
+
if (msg.questionReplyMessage?.answer) return msg.questionReplyMessage.answer
|
|
169
|
+
if (msg.locationMessage?.name || msg.locationMessage?.address) {
|
|
170
|
+
return [msg.locationMessage.name, msg.locationMessage.address].filter(Boolean).join(' - ')
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return ''
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Extracts and safely parses interactive button/list responses
|
|
178
|
+
* @param {Object} messageContent - Unwrapped message content
|
|
179
|
+
* @returns {Object|null} { id, text, params, flowName, type }
|
|
180
|
+
*/
|
|
181
|
+
static extractInteractiveReply(messageContent) {
|
|
182
|
+
const msg = this.unwrapMessage(messageContent)
|
|
183
|
+
if (!msg) return null
|
|
184
|
+
|
|
185
|
+
// 1. Classic Button Response
|
|
186
|
+
if (msg.buttonsResponseMessage) {
|
|
187
|
+
return {
|
|
188
|
+
id: msg.buttonsResponseMessage.selectedButtonId || '',
|
|
189
|
+
text: msg.buttonsResponseMessage.selectedDisplayText || '',
|
|
190
|
+
type: 'button'
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 2. List Dropdown Selection
|
|
195
|
+
if (msg.listResponseMessage) {
|
|
196
|
+
const row = msg.listResponseMessage.singleSelectReply
|
|
197
|
+
return {
|
|
198
|
+
id: row?.selectedRowId || '',
|
|
199
|
+
text: msg.listResponseMessage.title || '',
|
|
200
|
+
description: row?.description || '',
|
|
201
|
+
type: 'list'
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// 3. Native Flow Interactive Response
|
|
206
|
+
if (msg.interactiveResponseMessage?.nativeFlowResponseMessage) {
|
|
207
|
+
const flow = msg.interactiveResponseMessage.nativeFlowResponseMessage
|
|
208
|
+
let params = {}
|
|
209
|
+
if (flow.paramsJson) {
|
|
210
|
+
try {
|
|
211
|
+
params = JSON.parse(flow.paramsJson)
|
|
212
|
+
} catch {
|
|
213
|
+
params = { raw: flow.paramsJson }
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const id = params?.id || params?.selected_id || params?.row_id || flow.name || ''
|
|
218
|
+
return {
|
|
219
|
+
id,
|
|
220
|
+
text: flow.paramsJson || '',
|
|
221
|
+
params,
|
|
222
|
+
flowName: flow.name || '',
|
|
223
|
+
type: 'native_flow'
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// 4. Template Button Reply
|
|
228
|
+
if (msg.templateButtonReplyMessage) {
|
|
229
|
+
return {
|
|
230
|
+
id: msg.templateButtonReplyMessage.selectedId || '',
|
|
231
|
+
text: msg.templateButtonReplyMessage.selectedDisplayText || '',
|
|
232
|
+
type: 'template_button'
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// 5. Question Reply (Channels)
|
|
237
|
+
if (msg.questionReplyMessage) {
|
|
238
|
+
return {
|
|
239
|
+
id: msg.questionReplyMessage.selectedButtonId || '',
|
|
240
|
+
text: msg.questionReplyMessage.selectedDisplayText || msg.questionReplyMessage.answer || '',
|
|
241
|
+
type: 'question_reply'
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return null
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Extracts and parses contacts from vCards
|
|
250
|
+
* @param {Object} messageContent - Unwrapped message content
|
|
251
|
+
* @returns {Array<{ name: string, number: string, org?: string, vcard: string }>}
|
|
252
|
+
*/
|
|
253
|
+
static extractContacts(messageContent) {
|
|
254
|
+
const msg = this.unwrapMessage(messageContent)
|
|
255
|
+
if (!msg) return []
|
|
256
|
+
|
|
257
|
+
const parseVcard = (vcard = '') => {
|
|
258
|
+
const nameMatch = vcard.match(/FN:(.+)/i)
|
|
259
|
+
// Tenta waid= primeiro, se não encontrar pega TEL
|
|
260
|
+
const waidMatch = vcard.match(/waid=(\d+)/i)
|
|
261
|
+
const telMatch = vcard.match(/TEL[^:]*:([+\d\s().-]+)/i)
|
|
262
|
+
const orgMatch = vcard.match(/ORG:([^;\n\r]+)/i)
|
|
263
|
+
|
|
264
|
+
let number = ''
|
|
265
|
+
if (waidMatch) {
|
|
266
|
+
number = waidMatch[1].replace(/\D/g, '')
|
|
267
|
+
} else if (telMatch) {
|
|
268
|
+
number = telMatch[1].replace(/\D/g, '')
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return {
|
|
272
|
+
name: (nameMatch ? nameMatch[1] : '').replace(/\\/g, '').trim(),
|
|
273
|
+
number,
|
|
274
|
+
org: orgMatch ? orgMatch[1].trim() : undefined,
|
|
275
|
+
vcard
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (msg.contactMessage) {
|
|
280
|
+
return [parseVcard(msg.contactMessage.vcard)]
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (msg.contactsArrayMessage?.contacts) {
|
|
284
|
+
return msg.contactsArrayMessage.contacts.map(c => parseVcard(c.vcard))
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return []
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Extracts coordinates and metadata from location messages
|
|
292
|
+
* @param {Object} messageContent - Unwrapped message content
|
|
293
|
+
* @returns {Object|null}
|
|
294
|
+
*/
|
|
295
|
+
static extractLocation(messageContent) {
|
|
296
|
+
const msg = this.unwrapMessage(messageContent)
|
|
297
|
+
if (!msg) return null
|
|
298
|
+
|
|
299
|
+
const loc = msg.locationMessage || msg.liveLocationMessage
|
|
300
|
+
if (!loc) return null
|
|
301
|
+
|
|
302
|
+
return {
|
|
303
|
+
latitude: Number(loc.degreesLatitude || 0),
|
|
304
|
+
longitude: Number(loc.degreesLongitude || 0),
|
|
305
|
+
name: loc.name || '',
|
|
306
|
+
address: loc.address || '',
|
|
307
|
+
url: loc.url || '',
|
|
308
|
+
accuracyInMeters: loc.accuracyInMeters ? Number(loc.accuracyInMeters) : undefined,
|
|
309
|
+
speedInMps: loc.speedInMps ? Number(loc.speedInMps) : undefined,
|
|
310
|
+
isLive: Boolean(msg.liveLocationMessage)
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Extracts reaction details
|
|
316
|
+
* @param {Object} messageContent - Unwrapped message content
|
|
317
|
+
* @returns {Object|null}
|
|
318
|
+
*/
|
|
319
|
+
static extractReaction(messageContent) {
|
|
320
|
+
const msg = this.unwrapMessage(messageContent)
|
|
321
|
+
if (!msg?.reactionMessage) return null
|
|
322
|
+
|
|
323
|
+
const reaction = msg.reactionMessage
|
|
324
|
+
return {
|
|
325
|
+
emoji: reaction.text || '',
|
|
326
|
+
reactedMessageId: reaction.key?.id || '',
|
|
327
|
+
targetKey: reaction.key || null,
|
|
328
|
+
isRemoval: !reaction.text,
|
|
329
|
+
senderTimestamp: reaction.senderTimestampMs ? new Date(Number(reaction.senderTimestampMs)) : new Date()
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Extracts poll creation structure
|
|
335
|
+
* @param {Object} messageContent - Unwrapped message content
|
|
336
|
+
* @param {Object} [rawMessage]
|
|
337
|
+
* @returns {Object|null}
|
|
338
|
+
*/
|
|
339
|
+
static extractPollCreation(messageContent, rawMessage) {
|
|
340
|
+
const msg = this.unwrapMessage(messageContent)
|
|
341
|
+
const poll = msg?.pollCreationMessage || msg?.pollCreationMessageV2 || msg?.pollCreationMessageV3
|
|
342
|
+
if (!poll) return null
|
|
343
|
+
|
|
344
|
+
return {
|
|
345
|
+
id: rawMessage?.key?.id || '',
|
|
346
|
+
name: poll.name || '',
|
|
347
|
+
selectableOptionsCount: Number(poll.selectableOptionsCount || 1),
|
|
348
|
+
allowsMultipleAnswers: Number(poll.selectableOptionsCount || 1) > 1,
|
|
349
|
+
options: (poll.options || []).map(opt => ({
|
|
350
|
+
name: opt.optionName || '',
|
|
351
|
+
hash: opt.optionHash ? Buffer.from(opt.optionHash).toString('hex') : null
|
|
352
|
+
}))
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Extracts media node if present
|
|
358
|
+
* @param {Object} messageContent - Unwrapped message content
|
|
359
|
+
* @returns {Object|null}
|
|
360
|
+
*/
|
|
361
|
+
static extractMediaNode(messageContent) {
|
|
362
|
+
const msg = this.unwrapMessage(messageContent)
|
|
363
|
+
if (!msg) return null
|
|
364
|
+
|
|
365
|
+
return (
|
|
366
|
+
msg.imageMessage ||
|
|
367
|
+
msg.videoMessage ||
|
|
368
|
+
msg.audioMessage ||
|
|
369
|
+
msg.documentMessage ||
|
|
370
|
+
msg.stickerMessage ||
|
|
371
|
+
null
|
|
372
|
+
)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Extracts structured media details
|
|
377
|
+
* @param {Object} messageContent - Unwrapped message content
|
|
378
|
+
* @returns {Object|null}
|
|
379
|
+
*/
|
|
380
|
+
static extractMediaDetails(messageContent) {
|
|
381
|
+
const node = this.extractMediaNode(messageContent)
|
|
382
|
+
if (!node) return null
|
|
383
|
+
|
|
384
|
+
return {
|
|
385
|
+
mimetype: node.mimetype || '',
|
|
386
|
+
fileName: node.fileName || '',
|
|
387
|
+
caption: node.caption || '',
|
|
388
|
+
duration: node.seconds ? Number(node.seconds) : null,
|
|
389
|
+
isPtt: Boolean(node.ptt),
|
|
390
|
+
isGif: Boolean(node.gifPlayback),
|
|
391
|
+
isViewOnce: Boolean(node.viewOnce)
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Extracts quoted message context info
|
|
397
|
+
* @param {Object} messageContent - Unwrapped message content
|
|
398
|
+
* @returns {Object|null}
|
|
399
|
+
*/
|
|
400
|
+
static extractContextInfo(messageContent) {
|
|
401
|
+
const msg = this.unwrapMessage(messageContent)
|
|
402
|
+
if (!msg) return null
|
|
403
|
+
|
|
404
|
+
return (
|
|
405
|
+
msg.extendedTextMessage?.contextInfo ||
|
|
406
|
+
msg.imageMessage?.contextInfo ||
|
|
407
|
+
msg.videoMessage?.contextInfo ||
|
|
408
|
+
msg.audioMessage?.contextInfo ||
|
|
409
|
+
msg.documentMessage?.contextInfo ||
|
|
410
|
+
msg.stickerMessage?.contextInfo ||
|
|
411
|
+
msg.buttonsResponseMessage?.contextInfo ||
|
|
412
|
+
msg.listResponseMessage?.contextInfo ||
|
|
413
|
+
msg.interactiveResponseMessage?.contextInfo ||
|
|
414
|
+
msg.templateButtonReplyMessage?.contextInfo ||
|
|
415
|
+
msg.messageContextInfo ||
|
|
416
|
+
null
|
|
417
|
+
)
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
exports.MessageNormalizer = MessageNormalizer
|
|
422
|
+
exports.default = MessageNormalizer
|