@areumtecnologia/wasockets 2.0.0-alpha.1 → 2.2.3
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 +1929 -1649
- package/lib/Defaults/baileys-version.json +1 -1
- package/lib/Defaults/connection.js +14 -1
- package/lib/Socket/index.js +51 -48
- package/lib/Socket/messages-recv.js +74 -13
- package/lib/Socket/messages-send.js +50 -25
- package/lib/Socket/socket.js +13 -0
- package/lib/Socket/voip.js +123 -0
- package/lib/Store/make-cache-manager-store.js +14 -5
- package/lib/Types/index.d.ts +4 -0
- package/lib/Utils/auth-utils.js +16 -1
- package/lib/Utils/browser-utils.js +6 -2
- package/lib/Utils/generics.js +47 -8
- package/lib/Utils/index.d.ts +1 -0
- package/lib/Utils/messages-media.js +44 -21
- package/lib/Utils/pre-key-manager.js +16 -1
- package/lib/Utils/validate-connection.js +10 -11
- package/lib/VoIP/VoIPCrypto.js +150 -0
- package/lib/VoIP/VoIPManager.js +469 -0
- package/lib/VoIP/VoIPMediaEngine.js +224 -0
- package/lib/VoIP/VoIPProtocol.js +354 -0
- package/lib/VoIP/VoIPRelayTransport.js +173 -0
- package/lib/VoIP/VoIPSession.js +314 -0
- package/lib/VoIP/assets/wasm/loader.js +5 -0
- package/lib/VoIP/assets/wasm/whatsapp.wasm +0 -0
- package/lib/VoIP/assets/wasm/worker-modules.js +305 -0
- package/lib/VoIP/engine/audio-feeder.d.mts +15 -0
- package/lib/VoIP/engine/audio-feeder.mjs +243 -0
- package/lib/VoIP/engine/index.d.mts +91 -0
- package/lib/VoIP/engine/index.mjs +1683 -0
- package/lib/VoIP/engine/relay-transport.d.mts +43 -0
- package/lib/VoIP/engine/relay-transport.mjs +607 -0
- package/lib/VoIP/engine/signaling.d.mts +44 -0
- package/lib/VoIP/engine/signaling.mjs +893 -0
- package/lib/VoIP/engine/types.d.mts +183 -0
- package/lib/VoIP/engine/types.mjs +17 -0
- package/lib/VoIP/engine/wasm-engine.d.mts +103 -0
- package/lib/VoIP/engine/wasm-engine.mjs +1397 -0
- package/lib/VoIP/engine/worker-bootstrap.mjs +1049 -0
- package/lib/VoIP/index.js +51 -0
- package/lib/VoIP/utils/audio.d.ts +28 -0
- package/lib/VoIP/utils/audio.js +148 -0
- package/lib/WABinary/generic-utils.js +22 -6
- package/lib/index.d.ts +382 -274
- package/lib/index.js +5 -0
- package/package.json +28 -32
package/README.md
CHANGED
|
@@ -1,1650 +1,1930 @@
|
|
|
1
|
-
# WaSockets - API do WhatsApp Web em TypeScript/JavaScript
|
|
2
|
-
|
|
3
|
-
<div align="center">
|
|
4
|
-
<p><strong>Uma modificação otimizada e de alta performance da API do WhatsApp (baseada no Baileys), mantida e aprimorada pela Áreum Tecnologia.</strong></p>
|
|
5
|
-
</div>
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
|
26
|
-
|
|
|
27
|
-
| **
|
|
28
|
-
| **
|
|
29
|
-
| **
|
|
30
|
-
| **
|
|
31
|
-
| **
|
|
32
|
-
| **
|
|
33
|
-
| **
|
|
34
|
-
| **
|
|
35
|
-
| **
|
|
36
|
-
| **
|
|
37
|
-
| **Recursos Web (v1.1.6)** |
|
|
38
|
-
| **Recursos Web (v1.1.6)** |
|
|
39
|
-
| **
|
|
40
|
-
| **
|
|
41
|
-
| **
|
|
42
|
-
| **
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- [
|
|
56
|
-
- [
|
|
57
|
-
- [
|
|
58
|
-
- [
|
|
59
|
-
- [
|
|
60
|
-
- [
|
|
61
|
-
- [
|
|
62
|
-
- [
|
|
63
|
-
- [
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
- [
|
|
67
|
-
- [
|
|
68
|
-
- [
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
- [
|
|
74
|
-
- [
|
|
75
|
-
- [
|
|
76
|
-
|
|
77
|
-
- [
|
|
78
|
-
- [
|
|
79
|
-
- [
|
|
80
|
-
- [
|
|
81
|
-
- [Mensagens
|
|
82
|
-
- [
|
|
83
|
-
- [
|
|
84
|
-
- [
|
|
85
|
-
- [
|
|
86
|
-
- [
|
|
87
|
-
- [
|
|
88
|
-
- [
|
|
89
|
-
- [
|
|
90
|
-
- [
|
|
91
|
-
- [
|
|
92
|
-
- [
|
|
93
|
-
- [
|
|
94
|
-
- [
|
|
95
|
-
- [
|
|
96
|
-
- [
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
})
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
//
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
//
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
###
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
###
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
})
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
await sock.
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
})
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
//
|
|
603
|
-
await sock.sendMessage(
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
})
|
|
657
|
-
```
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
1
|
+
# WaSockets - API do WhatsApp Web em TypeScript/JavaScript
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<p><strong>Uma modificação otimizada e de alta performance da API do WhatsApp (baseada no Baileys), mantida e aprimorada pela Áreum Tecnologia.</strong></p>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
> 💡 **Nota:** Esta é a documentação padrão da biblioteca (mensagens, mídias, comunidades, canais, grupos, botões e gerenciamento de conta). Para a documentação técnica detalhada de arquitetura e módulos adicionais, consulte o [README_DETALHADO.md](./README_DETALHADO.md).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
### ⚠️ Nota Importante e Licença
|
|
14
|
+
|
|
15
|
+
Esta biblioteca é uma modificação independente e não é de forma alguma afiliada, endossada ou associada ao WhatsApp ou à Meta Inc. O uso desta ferramenta é de sua inteira responsabilidade. Desencorajamos fortemente o uso para spam, envio em massa não solicitado ou qualquer prática que viole os Termos de Serviço do WhatsApp.
|
|
16
|
+
|
|
17
|
+
O projeto é licenciado sob a licença **MIT** e incorpora componentes sob a licença **GPL-3.0** (devido ao uso de criptografia do `libsignal`).
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 🚀 Diferenciais e Correções da Áreum Tecnologia
|
|
22
|
+
|
|
23
|
+
O **WaSockets** foi criado para resolver problemas crônicos de estabilidade e adicionar recursos ausentes na versão original do Baileys. Abaixo estão as principais melhorias implementadas:
|
|
24
|
+
|
|
25
|
+
| Categoria | Recurso / Correção | Descrição |
|
|
26
|
+
| :--- | :--- | :--- |
|
|
27
|
+
| **Criptografia & Sessão** | Correção de descriptografia em grupos (`pn/lid mismatch`) | Corrige a falha crítica que impedia a descriptografia correta de mensagens quando a identidade de um participante alternava entre o número de telefone (PN) e o ID interno (LID). |
|
|
28
|
+
| **Criptografia & Sessão** | Descriptografia robusta de Enquetes/Eventos | Resolve o erro AES-GCM `Unsupported state or unable to authenticate data` garantindo que o autor original seja extraído do objeto de mensagem persistido. |
|
|
29
|
+
| **Estabilidade** | Versão Web Estabilizada | Integração com o protocolo Web `v2.3000.1038819500` e restauração da função `fetchLatestWaWebVersion` para buscar sempre a versão de compatibilidade mais recente e funcional do WhatsApp. |
|
|
30
|
+
| **Eventos** | Buffer de Eventos Corrigido | Adicionada a propriedade `shouldIncrementChatUnread` no buffer de eventos para garantir um controle preciso e confiável de mensagens não lidas no chat. |
|
|
31
|
+
| **Segurança** | Sessões de Autenticação Seguras | Remoção de adaptadores de autenticação inseguros/obsoletos (arquivo único ou MongoDB que causavam corrupção de estado), unificando e otimizando o uso do `useMultiFileAuthState`. |
|
|
32
|
+
| **Comunidades** | Suporte a Comunidades | Implementação nativa para escutar e processar comentários em canais de comunidades (`handle comment message`) e reações em comunidades. |
|
|
33
|
+
| **Eventos do WhatsApp** | Manipulação de Eventos e Respostas | Suporte a reações de edição de eventos (`handle event edit`) e decodificação das respostas de presença em eventos (`getAggregateResponsesInEventMessage`). |
|
|
34
|
+
| **Mídia** | Correções de Miniaturas e Status | Correção de falhas na extração de miniaturas (`extractImageThumb`), na geração de previews de links, no envio de mídias em álbuns/vídeos e na publicação de mídias em status de grupos. |
|
|
35
|
+
| **Newsletters (Canais)** | Consulta de Canais Inscritos | Adicionado o método exclusivo `newsletterSubscribed` que lista todos os canais de transmissão (Newsletters) aos quais o usuário está inscrito. |
|
|
36
|
+
| **Mensagens de Negócios** | Botões Interativos & PIX | Suporte avançado para layouts de botões interativos, botões Cards (com imagem/vídeo), suporte para botões PIX estáticos e fluxos completos de checkout e pagamento (`review_and_pay`). |
|
|
37
|
+
| **Recursos Web (v1.1.6)** | Fixação com Duração | Fixação de mensagens com durações configuráveis (24h, 7d, 30d) usando `pinInChatMessage` e `messageAddOnDurationInSecs`. |
|
|
38
|
+
| **Recursos Web (v1.1.6)** | Reação a Status | Método nativo `reactToStatus` para curtir e reagir diretamente a publicações de Status. |
|
|
39
|
+
| **Recursos Web (v1.1.6)** | Eventos & RSVP | Criação, cancelamento (`cancelEvent`) e confirmação de presença (`sendEventResponse`) em eventos de grupo. |
|
|
40
|
+
| **Recursos Web (v1.1.6)** | Favoritos & Notas de Contato | Sincronização via App State de chats favoritos (`updateFavorite`) e anotações internas de contatos (`updateChatNote`). |
|
|
41
|
+
| **Recursos Web (v1.1.6)** | Resolução Reversa de LID | Consulta reversa USync para obter o número de telefone a partir de um identificador `@lid` (`getPnUser`). |
|
|
42
|
+
| **Transição LID (Pilar 2)** | Store Unificado (LID & PN) | `store.getContact(jid)` e `store.getChat(jid)` com indexação cruzada e resolução automática de apelidos LID/PN. |
|
|
43
|
+
| **Transição LID (Pilar 2)** | Roteamento & Resolução JID | Métodos `sock.toPn()`, `sock.toLid()`, `sock.resolveJid()` e auto-aprendizado de chaves no cache do Signal. |
|
|
44
|
+
| **Multimídia & Canais (Pilar 3)** | Álbum Nativo & Waveforms | Envio de álbuns (`sendAlbumMessage`), ordenação indexada e suporte a waveforms PTT customizadas. |
|
|
45
|
+
| **Multimídia & Canais (Pilar 3)** | Newsletters (Canais) v2 | Consulta de reações (`newsletterFetchReactions`), mensagens individuais (`newsletterFetchMessage`) e lista parseada. |
|
|
46
|
+
| **Conectividade & Histórico** | Plataforma Nativa `WIN_HYBRID` | Substitui o `WIN32` depreciado pelo `WIN_HYBRID` nativo em `Browsers.windows('Desktop')`, eliminando o erro 428 e desbloqueando a sincronização de histórico completo (`syncFullHistory: true`). |
|
|
47
|
+
| **Multimídia & ViewOnce** | Emulação de Browser Android | Introdução do preset `Browsers.android('Chrome')` permitindo à sessão receber mensagens e mídias de visualização única (*View Once*). |
|
|
48
|
+
| **Alta Performance** | Cache WeakMap em Nós Binários | Indexação de tags filhas com `WeakMap` em `getBinaryNodeChildren` e `getBinaryNodeChild` gerando aceleração de até 30x no processamento de pacotes XML sem vazamento de memória. |
|
|
49
|
+
| **Privacidade & Contatos** | TC Token Nesting em Fotos de Perfil | Aninhamento do nó `<tctoken>` diretamente na query `<picture>` para atender ao protocolo `profilePicPrivacyToken`, suportando busca em alta resolução (`image`) e miniatura (`preview`). |
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 📌 Índice
|
|
54
|
+
|
|
55
|
+
- [🌟 Camada de Abstração de Alto Nível (WaClient) — Recomendado](#-camada-de-abstração-de-alto-nível-waclient--recomendado)
|
|
56
|
+
- [Por que usar o WaClient?](#por-que-usar-o-waclient)
|
|
57
|
+
- [Guia Rápido (Quick Start)](#guia-rápido-quick-start)
|
|
58
|
+
- [Eventos Semânticos](#eventos-semânticos)
|
|
59
|
+
- [O Contexto de Mensagem (MessageContext / ctx)](#o-contexto-de-mensagem-messagecontext--ctx)
|
|
60
|
+
- [Builders de Botões Interativos (InteractiveMessage)](#builders-de-botões-interativos-interactivemessage)
|
|
61
|
+
- [Controle de Presença Fluente (Typing / Recording)](#controle-de-presença-fluente-typing--recording)
|
|
62
|
+
- [Os 13 Submódulos Especializados](#os-13-submódulos-especializados)
|
|
63
|
+
- [Opções de Configuração (WaClientOptions)](#opções-de-configuração-waclientoptions)
|
|
64
|
+
- [Instalação](#-instalação)
|
|
65
|
+
- [API de Baixo Nível (makeWASocket Legado)](#-conectando-a-conta)
|
|
66
|
+
- [Conexão via QR Code](#conexão-via-qr-code)
|
|
67
|
+
- [Conexão via Código de Emparelhamento (Pairing Code)](#conexão-via-código-de-emparelhamento-pairing-code)
|
|
68
|
+
- [Recebendo Histórico Completo](#recebendo-histórico-completo)
|
|
69
|
+
- [Salvando e Restaurando Sessões](#-salvando-e-restaurando-sessões)
|
|
70
|
+
- [Configurações Importantes do Socket](#-configurações-importantes-do-socket)
|
|
71
|
+
- [Exemplo Prático Inicial (Bootstrap)](#-exemplo-prático-inicial-bootstrap)
|
|
72
|
+
- [Tratamento de Eventos e Mídia](#-tratamento-de-eventos-e-mídia)
|
|
73
|
+
- [Download de Mídias Recebidas](#download-de-mídias-recebidas)
|
|
74
|
+
- [Decifrar Votos de Enquetes](#decifrar-votos-de-enquetes)
|
|
75
|
+
- [Decifrar Respostas de Eventos](#decifrar-respostas-de-eventos)
|
|
76
|
+
- [Verificação de Contatos e Presença](#-verificação-de-contatos-e-presença)
|
|
77
|
+
- [Verificação de Números no WhatsApp (onWhatsApp)](#verificação-de-números-no-whatsapp-onwhatsapp)
|
|
78
|
+
- [Presença e Digitando / Gravando Áudio](#presença-e-digitando--gravando-áudio)
|
|
79
|
+
- [Enviando Mensagens](#-enviando-mensagens)
|
|
80
|
+
- [Mensagens de Texto, Menções e Links](#mensagens-de-texto-e-menções)
|
|
81
|
+
- [Mensagens de Mídia](#mensagens-de-mídia)
|
|
82
|
+
- [Documentos e Arquivos](#documentos-e-arquivos)
|
|
83
|
+
- [Figurinhas (Stickers)](#figurinhas-stickers)
|
|
84
|
+
- [Localização Fixa e Tempo Real](#localização-fixa-e-em-tempo-real)
|
|
85
|
+
- [Contatos e Cartões vCard](#contatos-e-cartões-vcard)
|
|
86
|
+
- [Reações a Mensagens](#reações-a-mensagens)
|
|
87
|
+
- [Criação de Enquetes](#criação-de-enquetes)
|
|
88
|
+
- [Listas Interativas de Opções](#listas-interativas-de-opções-sections)
|
|
89
|
+
- [Botões Interativos](#botões-interativos)
|
|
90
|
+
- [Botão de Pagamento PIX](#botão-de-pagamento-pix)
|
|
91
|
+
- [Fluxos de Checkout (PAY)](#fluxos-de-checkout-pay)
|
|
92
|
+
- [Encaminhamento de Mensagens](#encaminhamento-de-mensagens)
|
|
93
|
+
- [Menção em Status e Reações](#menção-em-status)
|
|
94
|
+
- [Comentários em Canais e Comunidades](#comentários-em-canais-e-comunidades)
|
|
95
|
+
- [Modificando Mensagens e Chats](#-modificando-mensagens-e-chats)
|
|
96
|
+
- [Confirmação de Leitura (readMessages)](#confirmação-de-leitura-readmessages)
|
|
97
|
+
- [Mensagens com Estrela (star)](#mensagens-com-estrela-star)
|
|
98
|
+
- [Fixação de Mensagens com Duração](#fixação-de-mensagens-com-duração)
|
|
99
|
+
- [Favoritos e Anotações de Contato](#favoritos-e-anotações-de-contato)
|
|
100
|
+
- [Perfil do Usuário e Foto](#-perfil-do-usuário-e-foto)
|
|
101
|
+
- [Eventos em Grupos e RSVP](#-eventos-em-grupos-e-rsvp)
|
|
102
|
+
- [Resolução de Usuários (LID e Telefone)](#-resolução-de-usuários--transição-lid-pilar-2)
|
|
103
|
+
- [Etiquetas e Respostas Rápidas (WhatsApp Business)](#-etiquetas-de-negócio-labels---whatsapp-business)
|
|
104
|
+
- [Gerenciamento de Grupos](#-gerenciamento-de-grupos)
|
|
105
|
+
- [Newsletters (Canais)](#-newsletters--canais-v2-pilar-3)
|
|
106
|
+
- [WhatsApp Business (Catálogo e Produtos)](#-whatsapp-business-catálogo-produtos-e-perfil-comercial)
|
|
107
|
+
- [Grupos e Comunidades v2](#-grupos-comunidades-v2-e-moderação-avançada)
|
|
108
|
+
- [Arquitetura de Plugins e Middlewares](#-arquitetura-de-plugins-e-middlewares)
|
|
109
|
+
- [Alta Performance, Cache e Memória](#-alta-performance-cache-e-controle-de-memória)
|
|
110
|
+
- [Configurações de Privacidade](#-configurações-de-privacidade)
|
|
111
|
+
- [Logs e Protocolo](#-logs-e-protocolo)
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 📦 Instalação
|
|
116
|
+
|
|
117
|
+
Adicione o pacote ao seu projeto via Yarn ou NPM:
|
|
118
|
+
|
|
119
|
+
**Versão Estável (Recomendado):**
|
|
120
|
+
```bash
|
|
121
|
+
yarn add @areumtecnologia/wasockets
|
|
122
|
+
# ou
|
|
123
|
+
npm install @areumtecnologia/wasockets
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Versão de Desenvolvimento (Edge):**
|
|
127
|
+
```bash
|
|
128
|
+
yarn add github:areumtecnologia/WaSockets
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 🌟 Camada de Abstração de Alto Nível (WaClient) — Recomendado
|
|
134
|
+
|
|
135
|
+
> **Novo no WaSockets!** A classe `WaClient` é uma camada de abstração de alto nível que elimina mais de **85% do boilerplate** comum de integrações com WhatsApp. Ela gerencia automaticamente autenticação multi-arquivos, reconexões inteligentes, normalização instantânea de mensagens e mídias, oferece builders fluentes de botões interativos e divide todas as funcionalidades em **13 submódulos especializados**.
|
|
136
|
+
|
|
137
|
+
### Por que usar o WaClient?
|
|
138
|
+
|
|
139
|
+
| Recurso | `makeWASocket` (Baixo Nível) | `WaClient` (Alto Nível) |
|
|
140
|
+
| :--- | :--- | :--- |
|
|
141
|
+
| **Autenticação & Sessão** | Configurar `useMultiFileAuthState`, gerenciar pastas e `creds.update` manualmente. | **Automático:** apenas defina `sessionName` e o cliente gerencia tudo. |
|
|
142
|
+
| **Reconexão** | Analisar códigos do `Boom`, verificar `DisconnectReason` e agendar timeouts. | **Automático:** reconexão inteligente em quedas transitórias sem loopings. |
|
|
143
|
+
| **Tratamento de Mensagens** | Escutar `messages.upsert`, iterar arrays brutos, extrair nós Proto profundamente. | **`ctx` Enriquecido:** objeto limpo com `ctx.reply()`, `ctx.react()`, `ctx.delete()`, etc. |
|
|
144
|
+
| **Download de Mídias** | Importar `downloadContentFromMessage`, gerenciar streams e conversão de Buffers. | **`MediaObject`:** métodos diretos `ctx.media.save()`, `toBase64()`, `toStream()`, `toSharp()`. |
|
|
145
|
+
| **Botões Interativos & PIX** | Montar estruturas JSON aninhadas e complexas de `interactiveMessage`. | **Builders Fluentes:** `new InteractiveMessage().addButton(new PixButton(...))`. |
|
|
146
|
+
| **Presença (Digitando)** | Disparar `sendPresenceUpdate` manual e lembrar de cancelar com timeout. | **Lifecycle Automático:** `const typing = client.startTyping(jid); ... typing.stop()`. |
|
|
147
|
+
| **Validação de Destinatário** | Erros de envio quando número não existe no WhatsApp. | **`isOnWhatsApp` Embutido:** validação prévia transparente sem quebrar sua aplicação. |
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
### Guia Rápido (Quick Start)
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
const { WaClient, Events } = require('@areumtecnologia/wasockets/client');
|
|
155
|
+
|
|
156
|
+
// 1. Inicializa o cliente com configurações simplificadas
|
|
157
|
+
const client = new WaClient({
|
|
158
|
+
sessionName: 'atendimento-sac',
|
|
159
|
+
dataPath: './sessions',
|
|
160
|
+
printQRInTerminal: true,
|
|
161
|
+
restartOnClose: true
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// 2. Eventos Semânticos
|
|
165
|
+
client.on(Events.CONNECTED, ({ user }) => {
|
|
166
|
+
console.log(`✓ Bot online com sucesso como: ${user.name} (${user.id})`);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// 3. Recepção de Mensagens com Contexto Enriquecido
|
|
170
|
+
client.on(Events.MESSAGE_RECEIVED, async (ctx) => {
|
|
171
|
+
// Ignora mensagens do próprio bot
|
|
172
|
+
if (ctx.isFromMe) return;
|
|
173
|
+
|
|
174
|
+
console.log(`[${ctx.senderName}]: ${ctx.body}`);
|
|
175
|
+
|
|
176
|
+
// Resposta automática com citação
|
|
177
|
+
if (ctx.body === '!ping') {
|
|
178
|
+
await ctx.react('🏓');
|
|
179
|
+
return ctx.reply('Pong! 🚀');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Se receber mídia (foto, áudio, vídeo, doc)
|
|
183
|
+
if (ctx.media) {
|
|
184
|
+
console.log(`Mídia recebida: ${ctx.media.mimetype} (${ctx.media.fileLength} bytes)`);
|
|
185
|
+
await ctx.media.save(`./downloads/${ctx.id}.${ctx.media.mimetype.split('/')[1]}`);
|
|
186
|
+
await ctx.reply('Arquivo salvo com sucesso!');
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// 4. Inicia a conexão
|
|
191
|
+
client.connect();
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### Eventos Semânticos
|
|
197
|
+
|
|
198
|
+
A classe `WaClient` emite eventos limpos e intuitivos através do enum `Events`:
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
const { Events } = require('@areumtecnologia/wasockets/client');
|
|
202
|
+
|
|
203
|
+
client.on(Events.CONNECTED, ({ user }) => { /* Conexão estabelecida */ });
|
|
204
|
+
client.on(Events.DISCONNECTED, ({ reason, willReconnect, error }) => { /* Queda de conexão */ });
|
|
205
|
+
client.on(Events.QR_CODE, ({ qr, base64 }) => { /* QR code emitido (terminal ou base64 para frontend) */ });
|
|
206
|
+
client.on(Events.PAIRING_CODE, ({ code }) => { /* Código de emparelhamento por telefone */ });
|
|
207
|
+
client.on(Events.LOGGED_OUT, () => { /* Desconectado/revogado pelo celular */ });
|
|
208
|
+
|
|
209
|
+
client.on(Events.MESSAGE_RECEIVED, async (ctx, rawMsg) => { /* Nova mensagem recebida */ });
|
|
210
|
+
client.on(Events.MESSAGE_SENT, async (ctx, rawMsg) => { /* Mensagem enviada pelo bot */ });
|
|
211
|
+
client.on(Events.MESSAGE_UPDATE, (updates) => { /* Edições de mensagem, apagadas ou confirmações */ });
|
|
212
|
+
|
|
213
|
+
client.on(Events.GROUP_PARTICIPANTS_UPDATE, (update) => { /* Entrada, saída ou promoção em grupo */ });
|
|
214
|
+
client.on(Events.PRESENCE_UPDATE, (presence) => { /* Usuário online, digitando ou offline */ });
|
|
215
|
+
client.on(Events.CONTACTS_UPSERT, (contacts) => { /* Novos contatos sincronizados */ });
|
|
216
|
+
client.on(Events.LABELS_UPDATE, (labels) => { /* Criação ou associação de etiquetas comerciais */ });
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
### O Contexto de Mensagem (`MessageContext` / `ctx`)
|
|
222
|
+
|
|
223
|
+
Ao escutar `Events.MESSAGE_RECEIVED`, você recebe um objeto `ctx` que já contém todos os dados mastigados e métodos de ação vinculados diretamente àquela mensagem:
|
|
224
|
+
|
|
225
|
+
#### Propriedades de `ctx`:
|
|
226
|
+
- `ctx.id`: ID único da mensagem.
|
|
227
|
+
- `ctx.chatId`: JID do chat (usuário, grupo ou canal).
|
|
228
|
+
- `ctx.sender`: JID de quem enviou.
|
|
229
|
+
- `ctx.senderNumber`: Apenas os números de telefone do remetente (sem `@s.whatsapp.net`).
|
|
230
|
+
- `ctx.senderName`: Nome formatado (nome salvo, apelido comercial ou pushName).
|
|
231
|
+
- `ctx.isGroup`: Booleano indicando se é grupo (`@g.us`).
|
|
232
|
+
- `ctx.isChannel`: Booleano indicando se é newsletter/canal (`@newsletter`).
|
|
233
|
+
- `ctx.isFromMe`: Booleano se a mensagem foi enviada pelo próprio bot.
|
|
234
|
+
- `ctx.body`: Texto principal da mensagem (já decodificado de texto, legenda, botão ou lista).
|
|
235
|
+
- `ctx.type`: Tipo normalizado (`text`, `image`, `video`, `audio`, `document`, `sticker`, `poll`, etc.).
|
|
236
|
+
- `ctx.media`: Instância de `MediaObject` (se houver mídia na mensagem).
|
|
237
|
+
- `ctx.quoted`: Instância recursiva de `MessageContext` para a mensagem que foi citada/respondida.
|
|
238
|
+
- `ctx.raw`: O nó bruto original do WhatsApp/Baileys para casos de baixo nível.
|
|
239
|
+
|
|
240
|
+
#### Ações Disponíveis em `ctx`:
|
|
241
|
+
```javascript
|
|
242
|
+
// Responde citando a mensagem automaticamente
|
|
243
|
+
await ctx.reply('Olá! Em que posso ajudar?');
|
|
244
|
+
|
|
245
|
+
// Reage com emoji
|
|
246
|
+
await ctx.react('👍');
|
|
247
|
+
|
|
248
|
+
// Remove reação anterior
|
|
249
|
+
await ctx.removeReaction();
|
|
250
|
+
|
|
251
|
+
// Apaga a mensagem para todos no chat
|
|
252
|
+
await ctx.delete();
|
|
253
|
+
|
|
254
|
+
// Edita o texto da mensagem (quando enviada anteriormente pelo próprio bot)
|
|
255
|
+
await ctx.edit('Texto corrigido');
|
|
256
|
+
|
|
257
|
+
// Encaminha para outro destinatário
|
|
258
|
+
await ctx.forward('5511999999999@s.whatsapp.net');
|
|
259
|
+
|
|
260
|
+
// Marca a mensagem como lida (ticks azuis)
|
|
261
|
+
await ctx.markRead();
|
|
262
|
+
|
|
263
|
+
// Fixa a mensagem no topo da conversa (duração em segundos: 24h, 7d, 30d)
|
|
264
|
+
await ctx.pin(86400);
|
|
265
|
+
|
|
266
|
+
// Desafixa a mensagem
|
|
267
|
+
await ctx.unpin();
|
|
268
|
+
|
|
269
|
+
// Favorita ou desfavorita a mensagem com estrela
|
|
270
|
+
await ctx.star();
|
|
271
|
+
await ctx.unstar();
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
#### Utilitários de Mídia (`MediaObject`):
|
|
275
|
+
Se a mensagem contiver imagem, vídeo, áudio ou documento, `ctx.media` fornece métodos instantâneos:
|
|
276
|
+
|
|
277
|
+
```javascript
|
|
278
|
+
if (ctx.media) {
|
|
279
|
+
// 1. Salva diretamente em disco
|
|
280
|
+
await ctx.media.save('./pasta/comprovante.pdf');
|
|
281
|
+
|
|
282
|
+
// 2. Converte para Base64 (ideal para enviar para APIs de IA ou frontend)
|
|
283
|
+
const base64 = ctx.media.toBase64();
|
|
284
|
+
const dataUri = ctx.media.toDataUri(); // 'data:image/jpeg;base64,...'
|
|
285
|
+
|
|
286
|
+
// 3. Obtém como Stream legível (Node Readable)
|
|
287
|
+
const stream = ctx.media.toStream();
|
|
288
|
+
|
|
289
|
+
// 4. Integração nativa com Sharp (se instalado) para redimensionamento/corte
|
|
290
|
+
const sharpInstance = ctx.media.toSharp();
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
### Builders de Botões Interativos (`InteractiveMessage`)
|
|
297
|
+
|
|
298
|
+
Crie botões nativos de alta conversão para WhatsApp sem precisar montar árvores JSON complexas:
|
|
299
|
+
|
|
300
|
+
```javascript
|
|
301
|
+
const {
|
|
302
|
+
InteractiveMessage,
|
|
303
|
+
QuickReplyButton,
|
|
304
|
+
UrlButton,
|
|
305
|
+
CopyCodeButton,
|
|
306
|
+
PixButton,
|
|
307
|
+
ListButton,
|
|
308
|
+
ListSection,
|
|
309
|
+
ListRow
|
|
310
|
+
} = require('@areumtecnologia/wasockets/client');
|
|
311
|
+
|
|
312
|
+
// 1. Menu com Resposta Rápida, Link, Cupom e Chave PIX Estática
|
|
313
|
+
const interactive = new InteractiveMessage()
|
|
314
|
+
.setTitle('Plano Pro - Áreum Tecnologia')
|
|
315
|
+
.setText('Escolha a forma de prosseguir com a sua assinatura:')
|
|
316
|
+
.setFooter('Pagamento seguro via WhatsApp')
|
|
317
|
+
.addButton(new QuickReplyButton('Ativar Teste Grátis', 'btn_trial'))
|
|
318
|
+
.addButton(new UrlButton('Ver Recursos', 'https://areumtecnologia.com.br'))
|
|
319
|
+
.addButton(new CopyCodeButton('Copiar Cupom 20%', 'DESCONTO20'))
|
|
320
|
+
.addButton(new PixButton('Pagar via PIX', '12345678900', 'CPF', 'Áreum Tecnologia'));
|
|
321
|
+
|
|
322
|
+
await client.sendInteractive('5511999999999@s.whatsapp.net', interactive);
|
|
323
|
+
|
|
324
|
+
// 2. Menu com Lista de Opções (Dropdown / Sections)
|
|
325
|
+
const lista = new InteractiveMessage()
|
|
326
|
+
.setTitle('Cardápio Digital')
|
|
327
|
+
.setText('Selecione uma categoria de produtos:')
|
|
328
|
+
.addButton(new ListButton('Ver Cardápio', [
|
|
329
|
+
new ListSection('Bebidas', [
|
|
330
|
+
new ListRow('Suco de Laranja 500ml', 'R$ 9,90', 'item_suco'),
|
|
331
|
+
new ListRow('Refrigerante Lata', 'R$ 6,50', 'item_refri')
|
|
332
|
+
]),
|
|
333
|
+
new ListSection('Pratos Principais', [
|
|
334
|
+
new ListRow('Hambúrguer Artesanal', 'Pão brioche, 180g blend', 'item_burger'),
|
|
335
|
+
new ListRow('Pizza Individual', 'Mussarela e tomate', 'item_pizza')
|
|
336
|
+
])
|
|
337
|
+
]));
|
|
338
|
+
|
|
339
|
+
await client.sendInteractive('5511999999999@s.whatsapp.net', lista);
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
### Controle de Presença Fluente (Typing / Recording)
|
|
345
|
+
|
|
346
|
+
Indique que o bot está digitando ou gravando áudio de forma segura, com cancelamento automático ao enviar ou via objeto retornado:
|
|
347
|
+
|
|
348
|
+
```javascript
|
|
349
|
+
// Inicia estado digitando ('composing')
|
|
350
|
+
const typing = client.startTyping(jid);
|
|
351
|
+
|
|
352
|
+
// Realiza processamento pesado (ex: consulta LLM / banco de dados)
|
|
353
|
+
await processarRequisicao();
|
|
354
|
+
|
|
355
|
+
// Para a digitação manualmente
|
|
356
|
+
await typing.stop();
|
|
357
|
+
|
|
358
|
+
// Ou para gravação de áudio ('recording')
|
|
359
|
+
const recording = client.startRecording(jid);
|
|
360
|
+
await sintetizarVoz();
|
|
361
|
+
await recording.stop();
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
### Os 13 Submódulos Especializados
|
|
367
|
+
|
|
368
|
+
O `WaClient` divide as operações em 13 módulos focados, acessíveis diretamente na instância:
|
|
369
|
+
|
|
370
|
+
| Submódulo | Acesso | Descrição e Principais Métodos |
|
|
371
|
+
| :--- | :--- | :--- |
|
|
372
|
+
| **Mensagens** | `client.messages` | Envio inteligente com validação `isOnWhatsApp`, textos, mídias, álbuns (`sendAlbum`), enquetes (`sendPoll`), vCards (`sendContacts`), reações e encaminhamento. |
|
|
373
|
+
| **Grupos** | `client.groups` | Criar grupos, adicionar/remover membros, promover/rebaixar admins, convites, permissões de grupo e menção em massa (`mentionAll`). |
|
|
374
|
+
| **Canais / Newsletters** | `client.channels` | Criação e gestão de Newsletters v2, busca por código de convite ou JID, seguir, deixar de seguir, silenciar e buscar reações. |
|
|
375
|
+
| **Privacidade** | `client.privacy` | Bloquear/desbloquear contatos, gerenciar lista de bloqueio (`getBlocklist`) e configurar privacidade de Visto por Último, Online, Foto e Recado. |
|
|
376
|
+
| **Perfil** | `client.profile` | Atualizar nome de exibição (`updateName`), recado/status (`updateStatus`), foto de perfil (`updatePicture`) e obter foto em alta resolução. |
|
|
377
|
+
| **Chats** | `client.chat` | Fixar conversas no topo (`pin`/`unpin`), silenciar (`mute`/`unmute`), arquivar (`archive`/`unarchive`), limpar e excluir histórico. |
|
|
378
|
+
| **Presença** | `client.presence` | `startTyping()`, `startRecording()`, marcar conta como online/offline e assinar atualizações de presença de contatos específicos. |
|
|
379
|
+
| **Status / Stories** | `client.stories` | Publicar Status em texto, imagem, áudio ou vídeo, com suporte a menções direcionadas (`statusJidList`) ou broadcast público. |
|
|
380
|
+
| **WhatsApp Business** | `client.business` | Gestão de catálogo comercial, cadastro de produtos (`createProduct`), coleções, perfil da empresa e detalhes de pedidos (`getOrderDetails`). |
|
|
381
|
+
| **Etiquetas / Labels** | `client.labels` | CRUD completo de etiquetas do WhatsApp Business, associação de etiquetas a chats e mensagens específicas. |
|
|
382
|
+
| **Comunidades** | `client.communities` | Criação de comunidades, vinculação de subgrupos (`addSubgroups`), remoção e gestão do grupo de avisos gerais. |
|
|
383
|
+
| **Usuários** | `client.users` | Verificação de existência no WhatsApp (`isOnWhatsApp`), metadados, busca de perfil comercial e resolução reversa de LID para PN (`getPnForLid`). |
|
|
384
|
+
| **Contatos** | `client.contacts` | Cache unificado de contatos em memória com resolução profunda assíncrona de informações completas (`fetchDeep`). |
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
### Opções de Configuração (`WaClientOptions`)
|
|
389
|
+
|
|
390
|
+
Ao instanciar `new WaClient(options)`, você pode customizar:
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
interface WaClientOptions {
|
|
394
|
+
/** Nome da sessão (cria a pasta em dataPath/sessionName) - Padrão: 'default' */
|
|
395
|
+
sessionName?: string;
|
|
396
|
+
/** Diretório base de armazenamento das credenciais - Padrão: './sessions' */
|
|
397
|
+
dataPath?: string;
|
|
398
|
+
/** Auth state customizado (opcional, se desejar gerenciar externamente) */
|
|
399
|
+
auth?: { state: AuthenticationState; saveCreds: () => Promise<void> };
|
|
400
|
+
/** Número de telefone para iniciar autenticação por Pairing Code ao invés de QR */
|
|
401
|
+
phoneNumber?: string;
|
|
402
|
+
/** Imprimir QR Code formatado no terminal - Padrão: true */
|
|
403
|
+
printQRInTerminal?: boolean;
|
|
404
|
+
/** Reconectar automaticamente em quedas transitórias de rede - Padrão: true */
|
|
405
|
+
restartOnClose?: boolean;
|
|
406
|
+
/** Sincronizar histórico completo de mensagens antigas - Padrão: false */
|
|
407
|
+
syncFullHistory?: boolean;
|
|
408
|
+
/** Marcar a conta como online assim que conectar - Padrão: true */
|
|
409
|
+
markOnlineOnConnect?: boolean;
|
|
410
|
+
/** Sobrescrever ou adicionar opções do makeWASocket subjacente */
|
|
411
|
+
socketOptions?: any;
|
|
412
|
+
/** Logger customizado (compatível com Pino ou Console) */
|
|
413
|
+
logger?: any;
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
## 🔑 Conectando a Conta
|
|
423
|
+
|
|
424
|
+
O WhatsApp fornece uma API multi-dispositivo que permite ao **WaSockets** se autenticar como um segundo cliente web. Isso pode ser feito via **QR Code** ou **Código de Emparelhamento**.
|
|
425
|
+
|
|
426
|
+
### Conexão via QR Code
|
|
427
|
+
|
|
428
|
+
```javascript
|
|
429
|
+
const { default: makeWASocket, Browsers } = require('@areumtecnologia/wasockets')
|
|
430
|
+
|
|
431
|
+
const sock = makeWASocket({
|
|
432
|
+
// Configurações do navegador exibidas no WhatsApp do celular
|
|
433
|
+
browser: Browsers.ubuntu('Chrome'),
|
|
434
|
+
printQRInTerminal: true
|
|
435
|
+
})
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
### Conexão via Código de Emparelhamento (Pairing Code)
|
|
439
|
+
|
|
440
|
+
Ideal para servidores sem interface gráfica ou fluxos onde você não deseja escanear o QR Code, usando apenas o número do telefone. O número deve conter o código do país (ex: `55` para Brasil) e DDD, apenas com números.
|
|
441
|
+
|
|
442
|
+
```javascript
|
|
443
|
+
const { default: makeWASocket } = require('@areumtecnologia/wasockets')
|
|
444
|
+
|
|
445
|
+
const sock = makeWASocket({
|
|
446
|
+
printQRInTerminal: false // Deve ser false
|
|
447
|
+
})
|
|
448
|
+
|
|
449
|
+
if (!sock.authState.creds.registered) {
|
|
450
|
+
const numeroTelefone = '5511999999999' // Insira o número completo
|
|
451
|
+
const codigo = await sock.requestPairingCode(numeroTelefone)
|
|
452
|
+
console.log(`Digite este código no seu WhatsApp: ${codigo}`)
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### Recebendo Histórico Completo
|
|
457
|
+
|
|
458
|
+
Por padrão, a conexão emula um cliente leve. Para receber um histórico maior de mensagens anteriores, configure o navegador para emular um Desktop (macOS ou Windows) e ative a sincronização:
|
|
459
|
+
|
|
460
|
+
```javascript
|
|
461
|
+
const sock = makeWASocket({
|
|
462
|
+
browser: Browsers.macOS('Desktop'),
|
|
463
|
+
syncFullHistory: true
|
|
464
|
+
})
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## 💾 Salvando e Restaurando Sessões
|
|
470
|
+
|
|
471
|
+
Para evitar a necessidade de escanear o QR Code a cada reinicialização, utilize a função `useMultiFileAuthState` para salvar as chaves de criptografia e credenciais em uma pasta local.
|
|
472
|
+
|
|
473
|
+
```javascript
|
|
474
|
+
const { default: makeWASocket, useMultiFileAuthState } = require('@areumtecnologia/wasockets')
|
|
475
|
+
|
|
476
|
+
async function iniciar() {
|
|
477
|
+
// Carrega o estado da pasta especificada
|
|
478
|
+
const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
|
|
479
|
+
|
|
480
|
+
const sock = makeWASocket({
|
|
481
|
+
auth: state
|
|
482
|
+
})
|
|
483
|
+
|
|
484
|
+
// Salva as credenciais sempre que forem atualizadas
|
|
485
|
+
sock.ev.on('creds.update', saveCreds)
|
|
486
|
+
}
|
|
487
|
+
iniciar()
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
> [!IMPORTANT]
|
|
491
|
+
> Quando mensagens são enviadas ou recebidas, as chaves de criptografia são atualizadas para segurança. É crucial que o evento `creds.update` chame a função `saveCreds` para persistir o novo estado. Caso contrário, a sessão será desconectada e as mensagens falharão.
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
## ⚙️ Configurações Importantes do Socket
|
|
496
|
+
|
|
497
|
+
### 1. Cache de Metadados de Grupo (Altamente Recomendado)
|
|
498
|
+
Se a sua aplicação gerencia grupos, buscar metadados diretamente no WhatsApp para cada mensagem recebida causa lentidão e risco de banimento por limite de requisições. Implemente um cache temporário:
|
|
499
|
+
|
|
500
|
+
```javascript
|
|
501
|
+
const NodeCache = require('@cacheable/node-cache') // ou similar
|
|
502
|
+
const groupCache = new NodeCache({ stdTTL: 5 * 60, useClones: false })
|
|
503
|
+
|
|
504
|
+
const sock = makeWASocket({
|
|
505
|
+
cachedGroupMetadata: async (jid) => groupCache.get(jid)
|
|
506
|
+
})
|
|
507
|
+
|
|
508
|
+
sock.ev.on('groups.update', async ([event]) => {
|
|
509
|
+
const metadata = await sock.groupMetadata(event.id)
|
|
510
|
+
groupCache.set(event.id, metadata)
|
|
511
|
+
})
|
|
512
|
+
|
|
513
|
+
sock.ev.on('group-participants.update', async (event) => {
|
|
514
|
+
const metadata = await sock.groupMetadata(event.id)
|
|
515
|
+
groupCache.set(event.id, metadata)
|
|
516
|
+
})
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
### 2. Recuperação de Mensagens e Enquetes
|
|
520
|
+
Para descriptografar respostas de enquetes antigas ou gerenciar tentativas de reenvio automáticas do WhatsApp, configure a função `getMessage`:
|
|
521
|
+
|
|
522
|
+
```javascript
|
|
523
|
+
const sock = makeWASocket({
|
|
524
|
+
getMessage: async (key) => {
|
|
525
|
+
// Busque a mensagem salva no seu banco de dados ou store local
|
|
526
|
+
return await buscarMensagemSalva(key.id)
|
|
527
|
+
}
|
|
528
|
+
})
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### 3. Fila Inteligente de Mensagens Durante Quedas Transitórias
|
|
532
|
+
Quando a conexão com o WhatsApp cai momentaneamente, o **WaSockets** armazena mensagens em buffer de espera e as envia automaticamente assim que a conexão se restabelece:
|
|
533
|
+
|
|
534
|
+
```javascript
|
|
535
|
+
const sock = makeWASocket({
|
|
536
|
+
enableMessageQueue: true, // Ativado por padrão (evita perda de mensagens durante reconexão)
|
|
537
|
+
messageQueueTtlMs: 5 * 60 * 1000 // TTL de expiração na fila (padrão: 5 minutos)
|
|
538
|
+
})
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
### 4. Auto-Reparo de Sessão E2E / Signal (`repairSession`)
|
|
542
|
+
Se uma conversa específica apresentar erros de chave ou falhas de descriptografia (`Bad MAC` ou `Session Corrupted`), não é mais necessário deletar a pasta inteira de autenticação. Use o método `repairSession`:
|
|
543
|
+
|
|
544
|
+
```javascript
|
|
545
|
+
// Remove a sessão danificada e força a renegociação de chaves E2E com o contato
|
|
546
|
+
await sock.repairSession('5511999999999@s.whatsapp.net')
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
---
|
|
550
|
+
|
|
551
|
+
## 🚀 Exemplo Prático Inicial (Bootstrap)
|
|
552
|
+
|
|
553
|
+
Aqui está um arquivo funcional completo em JavaScript (CommonJS) para iniciar a sua integração:
|
|
554
|
+
|
|
555
|
+
```javascript
|
|
556
|
+
const { default: makeWASocket, DisconnectReason, useMultiFileAuthState, makeReconnectManager, shouldReconnect } = require('@areumtecnologia/wasockets')
|
|
557
|
+
const { Boom } = require('@hapi/boom')
|
|
558
|
+
|
|
559
|
+
async function connectToWhatsApp() {
|
|
560
|
+
// 1. Inicializa o estado de autenticação baseado em arquivos
|
|
561
|
+
const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys')
|
|
562
|
+
|
|
563
|
+
// 2. Cria o Socket de Conexão com fila de mensagens inteligente ativada por padrão
|
|
564
|
+
const sock = makeWASocket({
|
|
565
|
+
auth: state,
|
|
566
|
+
printQRInTerminal: true,
|
|
567
|
+
enableMessageQueue: true // Fila de envio automático durante reconexões transitórias
|
|
568
|
+
})
|
|
569
|
+
|
|
570
|
+
// Gerenciador de reconexão adaptativa com Backoff Exponencial e Full Jitter (evita banimentos)
|
|
571
|
+
const reconnectManager = makeReconnectManager({
|
|
572
|
+
onReconnect: async (attempt) => {
|
|
573
|
+
console.log(`Reconectando ao WhatsApp (tentativa #${attempt})...`)
|
|
574
|
+
await connectToWhatsApp()
|
|
575
|
+
}
|
|
576
|
+
})
|
|
577
|
+
|
|
578
|
+
// 3. Monitora o status da conexão
|
|
579
|
+
sock.ev.on('connection.update', async (update) => {
|
|
580
|
+
const { connection, lastDisconnect } = update
|
|
581
|
+
|
|
582
|
+
if (connection === 'close') {
|
|
583
|
+
await reconnectManager.handleDisconnect(lastDisconnect?.error)
|
|
584
|
+
} else if (connection === 'open') {
|
|
585
|
+
reconnectManager.reset()
|
|
586
|
+
console.log('Conexão com o WhatsApp estabelecida com sucesso!')
|
|
587
|
+
}
|
|
588
|
+
})
|
|
589
|
+
|
|
590
|
+
// 4. Salva credenciais atualizadas
|
|
591
|
+
sock.ev.on('creds.update', saveCreds)
|
|
592
|
+
|
|
593
|
+
// 5. Escuta e responde a novas mensagens recebidas
|
|
594
|
+
sock.ev.on('messages.upsert', async (event) => {
|
|
595
|
+
for (const m of event.messages) {
|
|
596
|
+
// Ignora mensagens que não sejam do tipo padrão ou geradas pelo próprio bot
|
|
597
|
+
if (!m.message || m.key.fromMe) continue
|
|
598
|
+
|
|
599
|
+
console.log('Mensagem recebida de:', m.key.remoteJid)
|
|
600
|
+
console.log('Conteúdo:', JSON.stringify(m, null, 2))
|
|
601
|
+
|
|
602
|
+
// Responde à mensagem
|
|
603
|
+
await sock.sendMessage(m.key.remoteJid, { text: 'Olá! Recebi sua mensagem com sucesso.' })
|
|
604
|
+
}
|
|
605
|
+
})
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// Inicia o processo
|
|
609
|
+
connectToWhatsApp()
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
---
|
|
613
|
+
|
|
614
|
+
## 📡 Tratamento de Eventos e Mídia
|
|
615
|
+
|
|
616
|
+
O **WaSockets** utiliza um sistema de eventos tipado baseado no `EventEmitter`.
|
|
617
|
+
|
|
618
|
+
```javascript
|
|
619
|
+
sock.ev.on('messages.upsert', ({ messages, type }) => {
|
|
620
|
+
// type pode ser 'notify' (nova notificação) ou 'append' (carregamento histórico)
|
|
621
|
+
console.log('Novas mensagens recebidas:', messages)
|
|
622
|
+
})
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
### Download de Mídias Recebidas
|
|
626
|
+
|
|
627
|
+
Para baixar mídias (fotos, vídeos, áudios, documentos ou stickers) recebidas no evento `messages.upsert`, utilize a função utilitária `downloadMediaMessage`:
|
|
628
|
+
|
|
629
|
+
```javascript
|
|
630
|
+
const { downloadMediaMessage } = require('@areumtecnologia/wasockets')
|
|
631
|
+
const fs = require('fs')
|
|
632
|
+
|
|
633
|
+
sock.ev.on('messages.upsert', async ({ messages }) => {
|
|
634
|
+
for (const msg of messages) {
|
|
635
|
+
if (!msg.message || msg.key.fromMe) continue
|
|
636
|
+
|
|
637
|
+
const isMedia = msg.message.imageMessage ||
|
|
638
|
+
msg.message.videoMessage ||
|
|
639
|
+
msg.message.audioMessage ||
|
|
640
|
+
msg.message.documentMessage ||
|
|
641
|
+
msg.message.stickerMessage
|
|
642
|
+
|
|
643
|
+
if (isMedia) {
|
|
644
|
+
// Baixa o arquivo diretamente em formato Buffer
|
|
645
|
+
const buffer = await downloadMediaMessage(msg, 'buffer', {})
|
|
646
|
+
|
|
647
|
+
// Exemplo: Salvar no disco
|
|
648
|
+
const ext = msg.message.imageMessage ? 'jpg' : msg.message.audioMessage ? 'ogg' : 'bin'
|
|
649
|
+
fs.writeFileSync(`./download_${msg.key.id}.${ext}`, buffer)
|
|
650
|
+
console.log(`Mídia baixada com sucesso (${buffer.length} bytes)!`)
|
|
651
|
+
|
|
652
|
+
// Ou baixar como stream de leitura para processamento em tempo real:
|
|
653
|
+
// const stream = await downloadMediaMessage(msg, 'stream', {})
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
})
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
### Decifrar Votos de Enquetes
|
|
660
|
+
|
|
661
|
+
Os votos em enquetes chegam como mensagens criptografadas no evento `messages.update`. É preciso usar o helper `getAggregateVotesInPollMessage` passando a mensagem original da enquete.
|
|
662
|
+
|
|
663
|
+
```javascript
|
|
664
|
+
const { getAggregateVotesInPollMessage } = require('@areumtecnologia/wasockets')
|
|
665
|
+
|
|
666
|
+
sock.ev.on('messages.update', async (updates) => {
|
|
667
|
+
for (const { key, update } of updates) {
|
|
668
|
+
if (update.pollUpdates) {
|
|
669
|
+
// 1. Busca a mensagem original da enquete que foi criada anteriormente
|
|
670
|
+
const pollCreationMessage = await obterMensagemSalva(key)
|
|
671
|
+
if (pollCreationMessage) {
|
|
672
|
+
// 2. Agrega os votos
|
|
673
|
+
const pollVotes = await getAggregateVotesInPollMessage({
|
|
674
|
+
message: pollCreationMessage,
|
|
675
|
+
pollUpdates: update.pollUpdates
|
|
676
|
+
})
|
|
677
|
+
|
|
678
|
+
// 3. Exibe as opções votadas e os respectivos eleitores
|
|
679
|
+
console.log('Resultado da Enquete Atualizado:', pollVotes)
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
})
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
### Decifrar Respostas de Eventos
|
|
687
|
+
|
|
688
|
+
A mesma lógica se aplica a eventos criados no chat (como convites de reuniões). O **WaSockets** fornece o helper `getAggregateResponsesInEventMessage` para analisar as presenças.
|
|
689
|
+
|
|
690
|
+
```javascript
|
|
691
|
+
const { getAggregateResponsesInEventMessage } = require('@areumtecnologia/wasockets')
|
|
692
|
+
|
|
693
|
+
sock.ev.on('messages.update', async (updates) => {
|
|
694
|
+
for (const { key, update } of updates) {
|
|
695
|
+
if (update.eventResponses) {
|
|
696
|
+
const eventCreationMessage = await obterMensagemSalva(key)
|
|
697
|
+
if (eventCreationMessage) {
|
|
698
|
+
const responses = await getAggregateResponsesInEventMessage({
|
|
699
|
+
message: eventCreationMessage,
|
|
700
|
+
eventResponses: update.eventResponses
|
|
701
|
+
})
|
|
702
|
+
console.log('Respostas ao evento atualizadas:', responses)
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
})
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
---
|
|
710
|
+
|
|
711
|
+
## 🔍 Verificação de Contatos e Presença
|
|
712
|
+
|
|
713
|
+
### Verificação de Números no WhatsApp (onWhatsApp)
|
|
714
|
+
|
|
715
|
+
Valide se um ou vários números de telefone possuem contas ativas registradas no WhatsApp antes de disparar mensagens:
|
|
716
|
+
|
|
717
|
+
```javascript
|
|
718
|
+
// Aceita um ou vários números (com DDI e DDD)
|
|
719
|
+
const resultados = await sock.onWhatsApp('5511999999999', '5511888888888', '5521977777777')
|
|
720
|
+
|
|
721
|
+
for (const { jid, exists } of resultados) {
|
|
722
|
+
if (exists) {
|
|
723
|
+
console.log(`O número ${jid} está ativo no WhatsApp!`)
|
|
724
|
+
} else {
|
|
725
|
+
console.log(`O número ${jid} NÃO possui conta no WhatsApp.`)
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
### Presença e Digitando / Gravando Áudio
|
|
731
|
+
|
|
732
|
+
Simule atividade humana enviando estados de presença ou monitore o status de contatos:
|
|
733
|
+
|
|
734
|
+
```javascript
|
|
735
|
+
// 1. Indicar que está digitando...
|
|
736
|
+
await sock.sendPresenceUpdate('composing', jid)
|
|
737
|
+
|
|
738
|
+
// 2. Indicar que está gravando áudio...
|
|
739
|
+
await sock.sendPresenceUpdate('recording', jid)
|
|
740
|
+
|
|
741
|
+
// 3. Pausar status de digitação/gravação
|
|
742
|
+
await sock.sendPresenceUpdate('paused', jid)
|
|
743
|
+
|
|
744
|
+
// 4. Alterar presença geral da conta ('available' = Online, 'unavailable' = Offline)
|
|
745
|
+
await sock.sendPresenceUpdate('available')
|
|
746
|
+
|
|
747
|
+
// 5. Inscrever-se para escutar presença de um contato específico
|
|
748
|
+
await sock.presenceSubscribe(jid)
|
|
749
|
+
|
|
750
|
+
// 6. Monitorar atualizações de presença recebidas
|
|
751
|
+
sock.ev.on('presence.update', ({ id, presences }) => {
|
|
752
|
+
console.log(`Atualização de presença de ${id}:`, presences)
|
|
753
|
+
})
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
---
|
|
757
|
+
|
|
758
|
+
## ✉️ Enviando Mensagens
|
|
759
|
+
|
|
760
|
+
### Mensagens de Texto e Menções
|
|
761
|
+
|
|
762
|
+
```javascript
|
|
763
|
+
// Mensagem de texto simples
|
|
764
|
+
await sock.sendMessage(jid, { text: 'Olá Mundo!' })
|
|
765
|
+
|
|
766
|
+
// Mensagem citando (respondendo a) outra mensagem
|
|
767
|
+
await sock.sendMessage(jid, { text: 'Esta é uma resposta.' }, { quoted: mensagemOriginal })
|
|
768
|
+
|
|
769
|
+
// Mensagem mencionando contatos no grupo
|
|
770
|
+
await sock.sendMessage(jid, {
|
|
771
|
+
text: 'Olá @5511999999999 e @5511888888888!',
|
|
772
|
+
mentions: ['5511999999999@s.whatsapp.net', '5511888888888@s.whatsapp.net']
|
|
773
|
+
})
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
### Mensagens de Mídia
|
|
777
|
+
|
|
778
|
+
É possível passar caminhos de arquivos locais (`url`), links da internet (`url`), buffers ou streams de leitura.
|
|
779
|
+
|
|
780
|
+
```javascript
|
|
781
|
+
const fs = require('fs')
|
|
782
|
+
|
|
783
|
+
// Imagem com legenda
|
|
784
|
+
await sock.sendMessage(jid, {
|
|
785
|
+
image: { url: './foto.jpg' }, // ou { url: 'https://example.com/foto.jpg' } ou Buffer
|
|
786
|
+
caption: 'Minha foto legal!'
|
|
787
|
+
})
|
|
788
|
+
|
|
789
|
+
// Álbum de mídias (Múltiplas fotos/vídeos no mesmo bloco)
|
|
790
|
+
await sock.sendMessage(jid, {
|
|
791
|
+
album: [
|
|
792
|
+
{ image: { url: './foto1.jpg' }, caption: 'Foto 1' },
|
|
793
|
+
{ image: { url: './foto2.jpg' }, caption: 'Foto 2' },
|
|
794
|
+
{ video: { url: './video.mp4' }, caption: 'Vídeo do Álbum' }
|
|
795
|
+
]
|
|
796
|
+
})
|
|
797
|
+
|
|
798
|
+
// GIF (vídeo mp4 simulado como reprodução contínua)
|
|
799
|
+
await sock.sendMessage(jid, {
|
|
800
|
+
video: fs.readFileSync('./video-gif.mp4'),
|
|
801
|
+
gifPlayback: true,
|
|
802
|
+
caption: 'Olha esse gif!'
|
|
803
|
+
})
|
|
804
|
+
|
|
805
|
+
// Áudio Gravado (Simula o gravador de voz do WhatsApp - PTT)
|
|
806
|
+
await sock.sendMessage(jid, {
|
|
807
|
+
audio: { url: './audio.ogg' },
|
|
808
|
+
mimetype: 'audio/mp4', // obrigatório
|
|
809
|
+
ptt: true // Define como mensagem de voz
|
|
810
|
+
})
|
|
811
|
+
|
|
812
|
+
// Mensagem de Visualização Única (View Once)
|
|
813
|
+
await sock.sendMessage(jid, {
|
|
814
|
+
image: { url: './foto.jpg' },
|
|
815
|
+
viewOnce: true,
|
|
816
|
+
caption: 'Esta foto desaparecerá após ser aberta!'
|
|
817
|
+
})
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
> [!TIP]
|
|
821
|
+
> Para mensagens de áudio funcionarem perfeitamente em todos os dispositivos móveis e web, converta o áudio original para o formato OGG Opus (codec `libopus`) usando a ferramenta FFMpeg:
|
|
822
|
+
> `ffmpeg -i input.mp3 -c:a libopus -ac 1 -avoid_negative_ts make_zero output.ogg`
|
|
823
|
+
|
|
824
|
+
---
|
|
825
|
+
|
|
826
|
+
### Documentos e Arquivos
|
|
827
|
+
|
|
828
|
+
Envie qualquer formato de arquivo (PDF, planilhas, arquivos compactados) informando o `mimetype` e o `fileName` para exibição correta no aplicativo:
|
|
829
|
+
|
|
830
|
+
```javascript
|
|
831
|
+
await sock.sendMessage(jid, {
|
|
832
|
+
document: { url: './fatura_setembro.pdf' }, // ou Buffer ou { url: 'https://exemplo.com/doc.pdf' }
|
|
833
|
+
mimetype: 'application/pdf',
|
|
834
|
+
fileName: 'Fatura_Setembro_2026.pdf'
|
|
835
|
+
})
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
### Figurinhas (Stickers)
|
|
839
|
+
|
|
840
|
+
Envie figurinhas estáticas ou animadas no formato WebP:
|
|
841
|
+
|
|
842
|
+
```javascript
|
|
843
|
+
await sock.sendMessage(jid, {
|
|
844
|
+
sticker: fs.readFileSync('./minha_figurinha.webp') // aceita Buffer ou { url: './figurinha.webp' }
|
|
845
|
+
})
|
|
846
|
+
```
|
|
847
|
+
|
|
848
|
+
### Localização Fixa e em Tempo Real
|
|
849
|
+
|
|
850
|
+
Envie pontos no mapa ou compartilhe localização em tempo real com latitude e longitude:
|
|
851
|
+
|
|
852
|
+
```javascript
|
|
853
|
+
// Localização Fixa
|
|
854
|
+
await sock.sendMessage(jid, {
|
|
855
|
+
location: {
|
|
856
|
+
degreesLatitude: -23.55052,
|
|
857
|
+
degreesLongitude: -46.633308,
|
|
858
|
+
name: 'Sede da Áreum Tecnologia',
|
|
859
|
+
address: 'Av. Paulista, 1000 - Bela Vista, São Paulo - SP'
|
|
860
|
+
}
|
|
861
|
+
})
|
|
862
|
+
|
|
863
|
+
// Localização em Tempo Real (Live Location)
|
|
864
|
+
await sock.sendMessage(jid, {
|
|
865
|
+
location: {
|
|
866
|
+
degreesLatitude: -23.55052,
|
|
867
|
+
degreesLongitude: -46.633308
|
|
868
|
+
},
|
|
869
|
+
live: true
|
|
870
|
+
})
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
### Contatos e Cartões vCard
|
|
874
|
+
|
|
875
|
+
Envie um ou múltiplos contatos com cartão vCard formatado:
|
|
876
|
+
|
|
877
|
+
```javascript
|
|
878
|
+
const vcard = 'BEGIN:VCARD\n'
|
|
879
|
+
+ 'VERSION:3.0\n'
|
|
880
|
+
+ 'FN:Suporte Técnico Áreum\n'
|
|
881
|
+
+ 'ORG:Áreum Tecnologia;\n'
|
|
882
|
+
+ 'TEL;type=CELL;type=VOICE;waid=5511999999999:+55 11 99999-9999\n'
|
|
883
|
+
+ 'END:VCARD'
|
|
884
|
+
|
|
885
|
+
await sock.sendMessage(jid, {
|
|
886
|
+
contacts: {
|
|
887
|
+
displayName: 'Suporte Técnico Áreum',
|
|
888
|
+
contacts: [{ vcard }]
|
|
889
|
+
}
|
|
890
|
+
})
|
|
891
|
+
```
|
|
892
|
+
|
|
893
|
+
### Reações a Mensagens
|
|
894
|
+
|
|
895
|
+
Reaja com emojis a qualquer mensagem enviada ou recebida (ou remova a reação enviando string vazia `''`):
|
|
896
|
+
|
|
897
|
+
```javascript
|
|
898
|
+
// Reagir à mensagem com um emoji
|
|
899
|
+
await sock.sendMessage(jid, {
|
|
900
|
+
react: {
|
|
901
|
+
text: '🔥', // Emoji da reação
|
|
902
|
+
key: msg.key // Chave da mensagem original que receberá a reação
|
|
903
|
+
}
|
|
904
|
+
})
|
|
905
|
+
|
|
906
|
+
// Remover reação anterior
|
|
907
|
+
await sock.sendMessage(jid, {
|
|
908
|
+
react: {
|
|
909
|
+
text: '',
|
|
910
|
+
key: msg.key
|
|
911
|
+
}
|
|
912
|
+
})
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
### Criação de Enquetes
|
|
916
|
+
|
|
917
|
+
Crie enquetes interativas com contagem configurável de seleção (voto único ou múltiplo):
|
|
918
|
+
|
|
919
|
+
```javascript
|
|
920
|
+
await sock.sendMessage(jid, {
|
|
921
|
+
poll: {
|
|
922
|
+
name: 'Qual o melhor diferencial do WaSockets?',
|
|
923
|
+
values: [
|
|
924
|
+
'Resolução Transparente de LID',
|
|
925
|
+
'Envio Nativo de Álbuns',
|
|
926
|
+
'Newsletters v2 e Canais',
|
|
927
|
+
'Fila Inteligente de Reconexão'
|
|
928
|
+
],
|
|
929
|
+
selectableCount: 1 // 1 para escolha única; > 1 para permitir múltiplas escolhas
|
|
930
|
+
}
|
|
931
|
+
})
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
### Listas Interativas de Opções (Sections)
|
|
935
|
+
|
|
936
|
+
Envie menus organizados por categorias e linhas para navegação intuitiva:
|
|
937
|
+
|
|
938
|
+
```javascript
|
|
939
|
+
await sock.sendMessage(jid, {
|
|
940
|
+
text: 'Selecione o setor desejado para atendimento:',
|
|
941
|
+
footer: 'Áreum Tecnologia • Atendimento Automatizado',
|
|
942
|
+
title: 'Central de Relacionamento',
|
|
943
|
+
buttonText: 'Ver Departamentos',
|
|
944
|
+
sections: [
|
|
945
|
+
{
|
|
946
|
+
title: 'Atendimento Comercial',
|
|
947
|
+
rows: [
|
|
948
|
+
{ title: 'Novas Contratações', rowId: 'row_vendas', description: 'Conheça nossos planos e soluções' },
|
|
949
|
+
{ title: 'Upgrade de Plano', rowId: 'row_upgrade', description: 'Amplie os limites da sua conta' }
|
|
950
|
+
]
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
title: 'Suporte & Operações',
|
|
954
|
+
rows: [
|
|
955
|
+
{ title: 'Suporte Técnico', rowId: 'row_suporte', description: 'Dúvidas de integração e bugs' },
|
|
956
|
+
{ title: 'Financeiro', rowId: 'row_financeiro', description: '2ª via de boleto e notas fiscais' }
|
|
957
|
+
]
|
|
958
|
+
}
|
|
959
|
+
]
|
|
960
|
+
})
|
|
961
|
+
```
|
|
962
|
+
|
|
963
|
+
---
|
|
964
|
+
|
|
965
|
+
### Botões Interativos
|
|
966
|
+
|
|
967
|
+
Os botões nativos do WhatsApp são suportados através da propriedade `interactiveButtons`.
|
|
968
|
+
|
|
969
|
+
```javascript
|
|
970
|
+
await sock.sendMessage(jid, {
|
|
971
|
+
text: 'Olá! Escolha uma das opções abaixo:',
|
|
972
|
+
title: 'Painel Interativo',
|
|
973
|
+
subtitle: 'Selecione com um clique',
|
|
974
|
+
footer: 'Áreum Tecnologia',
|
|
975
|
+
interactiveButtons: [
|
|
976
|
+
{
|
|
977
|
+
name: 'quick_reply',
|
|
978
|
+
buttonParamsJson: JSON.stringify({
|
|
979
|
+
display_text: 'Suporte Técnico',
|
|
980
|
+
id: 'btn_suporte'
|
|
981
|
+
})
|
|
982
|
+
},
|
|
983
|
+
{
|
|
984
|
+
name: 'cta_url',
|
|
985
|
+
buttonParamsJson: JSON.stringify({
|
|
986
|
+
display_text: 'Acessar Site',
|
|
987
|
+
url: 'https://areum.com.br',
|
|
988
|
+
merchant_url: 'https://areum.com.br'
|
|
989
|
+
})
|
|
990
|
+
},
|
|
991
|
+
{
|
|
992
|
+
name: 'cta_copy',
|
|
674
993
|
buttonParamsJson: JSON.stringify({
|
|
675
|
-
display_text: '
|
|
676
|
-
id: '
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
await sock.
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
//
|
|
818
|
-
await sock.sendMessage(jid, {
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
//
|
|
839
|
-
await sock.sendMessage(
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
//
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
//
|
|
927
|
-
await sock.
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
//
|
|
947
|
-
await sock.
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
//
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
//
|
|
975
|
-
await sock.
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
//
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
await sock.
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
//
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
//
|
|
1099
|
-
await sock.
|
|
1100
|
-
```
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
//
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
//
|
|
1126
|
-
await sock.
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
//
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
//
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
//
|
|
1249
|
-
await sock.
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
await sock.
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
// Obter
|
|
1314
|
-
const
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
const
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
await sock.
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
###
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
```javascript
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
//
|
|
1377
|
-
await sock.
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
```
|
|
1382
|
-
|
|
1383
|
-
###
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
})
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
```
|
|
1523
|
-
|
|
1524
|
-
---
|
|
1525
|
-
|
|
1526
|
-
##
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
const sock = makeWASocket({
|
|
1534
|
-
|
|
1535
|
-
})
|
|
1536
|
-
```
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
```javascript
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
// Consultar todas as configurações de privacidade ativas da conta
|
|
1613
|
-
const privacySettings = await sock.fetchPrivacySettings()
|
|
1614
|
-
console.log('Configurações de privacidade atuais:', privacySettings)
|
|
1615
|
-
```
|
|
1616
|
-
|
|
1617
|
-
---
|
|
1618
|
-
|
|
1619
|
-
## 🛡️ Logs e Protocolo
|
|
1620
|
-
|
|
1621
|
-
Para habilitar a depuração detalhada e ver o tráfego bruto do Websocket trocado com o WhatsApp, inicialize o logger no nível `debug` ou `trace`. O **WaSockets** usa a biblioteca estruturada `pino` para logs ultra rápidos:
|
|
1622
|
-
|
|
1623
|
-
```javascript
|
|
1624
|
-
const pino = require('pino')
|
|
1625
|
-
|
|
1626
|
-
const sock = makeWASocket({
|
|
1627
|
-
logger: pino({ level: 'debug' })
|
|
1628
|
-
})
|
|
1629
|
-
```
|
|
1630
|
-
|
|
1631
|
-
### Como o WhatsApp se comunica (BinaryNodes)
|
|
1632
|
-
|
|
1633
|
-
As mensagens são trocadas em formato binário encapsuladas em estruturas chamadas `BinaryNode`. Cada nó possui três atributos:
|
|
1634
|
-
- **`tag`**: Nome da ação (ex: `message`, `ib`, `presence`, `iq`)
|
|
1635
|
-
- **`attrs`**: Objeto contendo propriedades em string/chave-valor (ID, timestamp, remetente, etc.)
|
|
1636
|
-
- **`content`**: O corpo de dados do nó (geralmente outro array de nós ou um buffer criptografado)
|
|
1637
|
-
|
|
1638
|
-
Você pode interagir diretamente com o tráfego do Websocket do WhatsApp registrando callbacks específicos:
|
|
1639
|
-
|
|
1640
|
-
```javascript
|
|
1641
|
-
// Monitora todos os pacotes recebidos que possuem a tag 'edge_routing'
|
|
1642
|
-
sock.ws.on('CB:edge_routing', (node) => {
|
|
1643
|
-
console.log('Recebido nó de roteamento:', node)
|
|
1644
|
-
})
|
|
1645
|
-
|
|
1646
|
-
// Monitora pacotes 'message' específicos
|
|
1647
|
-
sock.ws.on('CB:message', (node) => {
|
|
1648
|
-
console.log('Mensagem de protocolo bruta:', node)
|
|
1649
|
-
})
|
|
1650
|
-
```
|
|
994
|
+
display_text: 'Copiar Cupom',
|
|
995
|
+
id: 'btn_cupom',
|
|
996
|
+
copy_code: 'DESCONTO20'
|
|
997
|
+
})
|
|
998
|
+
}
|
|
999
|
+
]
|
|
1000
|
+
})
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
---
|
|
1004
|
+
|
|
1005
|
+
### Botão de Pagamento PIX
|
|
1006
|
+
|
|
1007
|
+
O **WaSockets** permite o envio de chaves estáticas de PIX diretamente integradas na interface de pagamento nativa do WhatsApp pelo botão `payment_info`.
|
|
1008
|
+
|
|
1009
|
+
```javascript
|
|
1010
|
+
await sock.sendMessage(jid, {
|
|
1011
|
+
text: 'Efetue o pagamento do pedido abaixo clicando em Pagar:',
|
|
1012
|
+
interactiveButtons: [
|
|
1013
|
+
{
|
|
1014
|
+
name: 'payment_info',
|
|
1015
|
+
buttonParamsJson: JSON.stringify({
|
|
1016
|
+
payment_settings: [{
|
|
1017
|
+
type: 'pix_static_code',
|
|
1018
|
+
pix_static_code: {
|
|
1019
|
+
merchant_name: 'Áreum Tecnologia LTDA',
|
|
1020
|
+
key: 'financeiro@areum.com.br', // Chave PIX (E-mail, CPF/CNPJ, Telefone ou EVP)
|
|
1021
|
+
key_type: 'EMAIL' // Tipos suportados: PHONE, EMAIL, CPF, EVP
|
|
1022
|
+
}
|
|
1023
|
+
}]
|
|
1024
|
+
})
|
|
1025
|
+
}
|
|
1026
|
+
]
|
|
1027
|
+
})
|
|
1028
|
+
```
|
|
1029
|
+
|
|
1030
|
+
---
|
|
1031
|
+
|
|
1032
|
+
### Fluxos de Checkout (PAY)
|
|
1033
|
+
|
|
1034
|
+
É possível enviar solicitações de checkout com itens detalhados de faturamento para pagamentos eletrônicos integrados no aplicativo através da ação `review_and_pay`.
|
|
1035
|
+
|
|
1036
|
+
```javascript
|
|
1037
|
+
await sock.sendMessage(jid, {
|
|
1038
|
+
text: 'Fatura gerada com sucesso!',
|
|
1039
|
+
interactiveButtons: [
|
|
1040
|
+
{
|
|
1041
|
+
name: 'review_and_pay',
|
|
1042
|
+
buttonParamsJson: JSON.stringify({
|
|
1043
|
+
currency: 'BRL',
|
|
1044
|
+
payment_type: 'physical-goods',
|
|
1045
|
+
total_amount: {
|
|
1046
|
+
value: '15000', // R$ 150,00 (representado sem decimais, multiplicado pelo offset)
|
|
1047
|
+
offset: '100'
|
|
1048
|
+
},
|
|
1049
|
+
reference_id: 'REF_PEDIDO_12345',
|
|
1050
|
+
payment_method: 'confirm',
|
|
1051
|
+
payment_status: 'captured',
|
|
1052
|
+
payment_timestamp: Math.floor(Date.now() / 1000),
|
|
1053
|
+
order: {
|
|
1054
|
+
status: 'completed',
|
|
1055
|
+
order_type: 'PAYMENT_REQUEST',
|
|
1056
|
+
subtotal: { value: '15000', offset: '100' },
|
|
1057
|
+
items: [{
|
|
1058
|
+
retailer_id: 'item_01',
|
|
1059
|
+
name: 'Licença Anual WaSockets',
|
|
1060
|
+
amount: { value: '15000', offset: '100' },
|
|
1061
|
+
quantity: '1'
|
|
1062
|
+
}]
|
|
1063
|
+
},
|
|
1064
|
+
additional_note: 'Agradecemos a sua preferência!'
|
|
1065
|
+
})
|
|
1066
|
+
}
|
|
1067
|
+
]
|
|
1068
|
+
})
|
|
1069
|
+
```
|
|
1070
|
+
|
|
1071
|
+
---
|
|
1072
|
+
|
|
1073
|
+
### Menção em Status
|
|
1074
|
+
|
|
1075
|
+
Permite publicar status (stories) e marcar diretamente contatos/grupos específicos (máximo de 5 menções por status).
|
|
1076
|
+
|
|
1077
|
+
```javascript
|
|
1078
|
+
const contatosParaMencionar = [
|
|
1079
|
+
'5511999999999@s.whatsapp.net',
|
|
1080
|
+
'5511888888888@s.whatsapp.net'
|
|
1081
|
+
]
|
|
1082
|
+
|
|
1083
|
+
// Envia um status em formato de texto mencionando os contatos acima
|
|
1084
|
+
await sock.sendStatusMentions(
|
|
1085
|
+
{
|
|
1086
|
+
text: 'Novidade incrível para vocês! 🚀',
|
|
1087
|
+
backgroundColor: '#1c1c1c',
|
|
1088
|
+
textColor: '#ffffff'
|
|
1089
|
+
},
|
|
1090
|
+
contatosParaMencionar
|
|
1091
|
+
)
|
|
1092
|
+
|
|
1093
|
+
// Curtir / Reagir diretamente a uma publicação de Status (Stories)
|
|
1094
|
+
await sock.reactToStatus(statusMsgKey, '❤️')
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
### Comentários em Canais e Comunidades
|
|
1098
|
+
|
|
1099
|
+
Envie respostas e comentários estruturados em postagens de canais (Newsletters) ou mensagens de aviso em comunidades:
|
|
1100
|
+
|
|
1101
|
+
```javascript
|
|
1102
|
+
await sock.sendMessage(jid, {
|
|
1103
|
+
comment: {
|
|
1104
|
+
targetMessageKey: mensagemOriginal.key,
|
|
1105
|
+
message: { text: 'Excelente atualização! 👏' }
|
|
1106
|
+
}
|
|
1107
|
+
})
|
|
1108
|
+
```
|
|
1109
|
+
|
|
1110
|
+
### Envio Nativo de Álbuns de Fotos e Vídeos (Pilar 3)
|
|
1111
|
+
|
|
1112
|
+
Envie múltiplos arquivos de imagem e vídeo agrupados nativamente em um container de álbum (layout de grade no WhatsApp Web e Celular) com ordenação indexada e suporte a legendas:
|
|
1113
|
+
|
|
1114
|
+
```javascript
|
|
1115
|
+
// Método direto e simplificado
|
|
1116
|
+
await sock.sendAlbumMessage(jid, [
|
|
1117
|
+
{ image: { url: 'https://exemplo.com/foto1.jpg' }, caption: 'Foto 1 do produto' },
|
|
1118
|
+
{ image: { url: 'https://exemplo.com/foto2.jpg' }, caption: 'Foto 2 em outro ângulo' },
|
|
1119
|
+
{ video: { url: 'https://exemplo.com/demonstracao.mp4' }, caption: 'Vídeo explicativo' }
|
|
1120
|
+
])
|
|
1121
|
+
|
|
1122
|
+
// Ou através de sendMessage com a propriedade album:
|
|
1123
|
+
await sock.sendMessage(jid, {
|
|
1124
|
+
album: [
|
|
1125
|
+
{ image: { url: './local/foto1.jpg' } },
|
|
1126
|
+
{ image: { url: './local/foto2.jpg' } }
|
|
1127
|
+
]
|
|
1128
|
+
})
|
|
1129
|
+
```
|
|
1130
|
+
|
|
1131
|
+
### Mensagens de Áudio PTT com Waveform Customizada (Pilar 3)
|
|
1132
|
+
|
|
1133
|
+
Você pode enviar notas de voz (Push-To-Talk) com geração automática de ondas sonoras ou fornecer uma forma de onda predefinida (array ou Buffer):
|
|
1134
|
+
|
|
1135
|
+
```javascript
|
|
1136
|
+
// Áudio PTT com waveform automática gerada a partir do arquivo
|
|
1137
|
+
await sock.sendMessage(jid, {
|
|
1138
|
+
audio: { url: './audio.mp3' },
|
|
1139
|
+
mimetype: 'audio/ogg; codecs=opus',
|
|
1140
|
+
ptt: true
|
|
1141
|
+
})
|
|
1142
|
+
|
|
1143
|
+
// Áudio PTT com waveform predefinida (evita decodificação intensiva de CPU)
|
|
1144
|
+
await sock.sendMessage(jid, {
|
|
1145
|
+
audio: { url: './audio.mp3' },
|
|
1146
|
+
mimetype: 'audio/ogg; codecs=opus',
|
|
1147
|
+
ptt: true,
|
|
1148
|
+
waveform: [0, 15, 30, 75, 100, 80, 45, 20, 10, 0] // 64 barras de amplitude
|
|
1149
|
+
})
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1152
|
+
### Encaminhamento de Mensagens
|
|
1153
|
+
|
|
1154
|
+
Encaminhe mensagens para outros chats preservando ou forçando o status de encaminhado:
|
|
1155
|
+
|
|
1156
|
+
```javascript
|
|
1157
|
+
// Encaminhar uma mensagem recebida para outro destinatário
|
|
1158
|
+
await sock.sendMessage(outroJid, {
|
|
1159
|
+
forward: mensagemOriginal,
|
|
1160
|
+
force: true // Exibe o selo de mensagem encaminhada
|
|
1161
|
+
})
|
|
1162
|
+
```
|
|
1163
|
+
|
|
1164
|
+
---
|
|
1165
|
+
|
|
1166
|
+
## 📝 Modificando Mensagens e Chats
|
|
1167
|
+
|
|
1168
|
+
```javascript
|
|
1169
|
+
// Apagar uma mensagem para todos
|
|
1170
|
+
const msg = await sock.sendMessage(jid, { text: 'Mensagem enviada com erro!' })
|
|
1171
|
+
await sock.sendMessage(jid, { delete: msg.key })
|
|
1172
|
+
|
|
1173
|
+
// Editar uma mensagem enviada
|
|
1174
|
+
await sock.sendMessage(jid, {
|
|
1175
|
+
text: 'Esta é a mensagem com o texto corrigido.',
|
|
1176
|
+
edit: msg.key
|
|
1177
|
+
})
|
|
1178
|
+
|
|
1179
|
+
// Arquivar um chat
|
|
1180
|
+
await sock.chatModify({ archive: true, lastMessages: [msg] }, jid)
|
|
1181
|
+
|
|
1182
|
+
// Silenciar um chat por 8 horas
|
|
1183
|
+
await sock.chatModify({ mute: 8 * 60 * 60 * 1000 }, jid)
|
|
1184
|
+
|
|
1185
|
+
// Remover silenciamento de um chat
|
|
1186
|
+
await sock.chatModify({ mute: null }, jid)
|
|
1187
|
+
|
|
1188
|
+
// Marcar chat como Não Lido
|
|
1189
|
+
await sock.chatModify({ markRead: false, lastMessages: [msg] }, jid)
|
|
1190
|
+
|
|
1191
|
+
// Fixar chat na lista de conversas
|
|
1192
|
+
await sock.chatModify({ pin: true }, jid)
|
|
1193
|
+
```
|
|
1194
|
+
|
|
1195
|
+
### Confirmação de Leitura (readMessages)
|
|
1196
|
+
|
|
1197
|
+
Envie confirmações de leitura explícitas para exibir os ticks azuis ao remetente:
|
|
1198
|
+
|
|
1199
|
+
```javascript
|
|
1200
|
+
// Marca uma ou mais mensagens recebidas como lidas
|
|
1201
|
+
await sock.readMessages([msg.key])
|
|
1202
|
+
```
|
|
1203
|
+
|
|
1204
|
+
### Mensagens com Estrela (star)
|
|
1205
|
+
|
|
1206
|
+
Marque mensagens importantes com estrela (favoritas) na conversa:
|
|
1207
|
+
|
|
1208
|
+
```javascript
|
|
1209
|
+
// Adicionar estrela à mensagem
|
|
1210
|
+
await sock.star(jid, [{ id: msg.key.id, fromMe: msg.key.fromMe }], true)
|
|
1211
|
+
|
|
1212
|
+
// Remover estrela da mensagem
|
|
1213
|
+
await sock.star(jid, [{ id: msg.key.id, fromMe: msg.key.fromMe }], false)
|
|
1214
|
+
```
|
|
1215
|
+
|
|
1216
|
+
### Fixação de Mensagens com Duração
|
|
1217
|
+
|
|
1218
|
+
Fixe mensagens em conversas individuais ou grupos escolhendo a duração desejada:
|
|
1219
|
+
|
|
1220
|
+
```javascript
|
|
1221
|
+
// Fixar mensagem por 7 dias (604800 segundos)
|
|
1222
|
+
// Durações padrão: 86400 (24h), 604800 (7 dias), 2592000 (30 dias)
|
|
1223
|
+
await sock.sendMessage(jid, {
|
|
1224
|
+
pin: {
|
|
1225
|
+
key: msg.key,
|
|
1226
|
+
type: 1, // 1: Fixar, 2: Desafixar
|
|
1227
|
+
time: 604800
|
|
1228
|
+
}
|
|
1229
|
+
})
|
|
1230
|
+
|
|
1231
|
+
// Desafixar mensagem
|
|
1232
|
+
await sock.sendMessage(jid, {
|
|
1233
|
+
pin: {
|
|
1234
|
+
key: msg.key,
|
|
1235
|
+
type: 2
|
|
1236
|
+
}
|
|
1237
|
+
})
|
|
1238
|
+
```
|
|
1239
|
+
|
|
1240
|
+
### Favoritos e Anotações de Contato
|
|
1241
|
+
|
|
1242
|
+
Organize suas conversas sincronizando com o WhatsApp Web e celular:
|
|
1243
|
+
|
|
1244
|
+
```javascript
|
|
1245
|
+
// Marcar conversa como Favorita
|
|
1246
|
+
await sock.updateFavorite(jid, true)
|
|
1247
|
+
|
|
1248
|
+
// Desmarcar conversa como Favorita
|
|
1249
|
+
await sock.updateFavorite(jid, false)
|
|
1250
|
+
|
|
1251
|
+
// Adicionar ou atualizar nota interna no contato (Chat Note)
|
|
1252
|
+
await sock.updateChatNote(jid, 'Cliente solicitou proposta para 50 atendentes.')
|
|
1253
|
+
|
|
1254
|
+
// Remover nota interna do contato
|
|
1255
|
+
await sock.removeChatNote(jid)
|
|
1256
|
+
```
|
|
1257
|
+
|
|
1258
|
+
---
|
|
1259
|
+
|
|
1260
|
+
## 👤 Perfil do Usuário e Foto
|
|
1261
|
+
|
|
1262
|
+
Gerencie fotos de perfil, recados e nome de exibição (PushName) diretamente pelo socket:
|
|
1263
|
+
|
|
1264
|
+
```javascript
|
|
1265
|
+
// 1. Obter a URL da foto de perfil de um contato ou grupo
|
|
1266
|
+
const pfpUrl = await sock.profilePictureUrl(jid, 'image') // ou 'preview' para miniatura
|
|
1267
|
+
console.log('Foto de Perfil:', pfpUrl)
|
|
1268
|
+
|
|
1269
|
+
// 2. Atualizar a sua própria foto de perfil (ou a foto de um grupo do qual você é admin)
|
|
1270
|
+
await sock.updateProfilePicture(jid, { url: './nova_foto.jpg' }) // Aceita caminho, URL ou Buffer
|
|
1271
|
+
|
|
1272
|
+
// 3. Remover a foto de perfil
|
|
1273
|
+
await sock.removeProfilePicture(jid)
|
|
1274
|
+
|
|
1275
|
+
// 4. Consultar o recado / About (Status) de um contato
|
|
1276
|
+
const statusInfo = await sock.fetchStatus(jid)
|
|
1277
|
+
console.log(`Recado de ${jid}: ${statusInfo?.status} (Definido em: ${statusInfo?.setAt})`)
|
|
1278
|
+
|
|
1279
|
+
// 5. Atualizar o seu próprio recado / About
|
|
1280
|
+
await sock.updateProfileStatus('Disponível apenas para atendimentos prioritários 🚀')
|
|
1281
|
+
|
|
1282
|
+
// 6. Atualizar o seu nome público de exibição (PushName)
|
|
1283
|
+
await sock.updateProfileName('Áreum Tecnologia - Suporte Oficial')
|
|
1284
|
+
```
|
|
1285
|
+
|
|
1286
|
+
---
|
|
1287
|
+
|
|
1288
|
+
## 📅 Eventos em Grupos e RSVP
|
|
1289
|
+
|
|
1290
|
+
Crie eventos colaborativos, responda confirmações de presença e cancele eventos:
|
|
1291
|
+
|
|
1292
|
+
```javascript
|
|
1293
|
+
// 1. Criar um novo evento no grupo
|
|
1294
|
+
const evento = await sock.sendMessage(grupoJid, {
|
|
1295
|
+
event: {
|
|
1296
|
+
name: 'Reunião de Planejamento de Sprints',
|
|
1297
|
+
description: 'Alinhamento estratégico dos projetos da Áreum Tecnologia.',
|
|
1298
|
+
startTime: Math.floor(Date.now() / 1000) + 86400, // Amanhã
|
|
1299
|
+
extraGuestsAllowed: true
|
|
1300
|
+
}
|
|
1301
|
+
})
|
|
1302
|
+
|
|
1303
|
+
// 2. Responder ao Evento (RSVP)
|
|
1304
|
+
// Tipos de resposta: 'GOING' (1), 'NOT_GOING' (2), 'MAYBE' (3)
|
|
1305
|
+
await sock.sendEventResponse(grupoJid, evento.key, 'GOING', 1 /* +1 convidado extra */)
|
|
1306
|
+
|
|
1307
|
+
// 3. Cancelar o Evento
|
|
1308
|
+
await sock.cancelEvent(grupoJid, evento.key)
|
|
1309
|
+
```
|
|
1310
|
+
|
|
1311
|
+
---
|
|
1312
|
+
|
|
1313
|
+
## 🔍 Resolução de Usuários & Transição LID (Pilar 2)
|
|
1314
|
+
|
|
1315
|
+
Com a evolução da privacidade no WhatsApp, participantes de grupos e canais frequentemente utilizam identificadores `@lid`. O **WaSockets** oferece um conjunto completo de ferramentas de alto desempenho com cache automático em memória e no banco de chaves Signal:
|
|
1316
|
+
|
|
1317
|
+
### Métodos de Resolução Transparente no Socket
|
|
1318
|
+
|
|
1319
|
+
```javascript
|
|
1320
|
+
// 1. Converter LID para número de telefone (PN) com busca em cache/DB
|
|
1321
|
+
const pnJid = await sock.toPn('12345678901234@lid')
|
|
1322
|
+
console.log('JID com número real:', pnJid) // '5511999999999@s.whatsapp.net'
|
|
1323
|
+
|
|
1324
|
+
// Caso não esteja em cache local, pode passar true para consultar o servidor via USync:
|
|
1325
|
+
const pnJidFromNetwork = await sock.toPn('12345678901234@lid', true)
|
|
1326
|
+
|
|
1327
|
+
// 2. Converter número de telefone (PN) para LID
|
|
1328
|
+
const lidJid = await sock.toLid('5511999999999@s.whatsapp.net')
|
|
1329
|
+
console.log('LID correspondente:', lidJid) // '12345678901234@lid'
|
|
1330
|
+
|
|
1331
|
+
// 3. Resolução completa e unificada (retorna ambos)
|
|
1332
|
+
const resolved = await sock.resolveJid(authorJid)
|
|
1333
|
+
console.log(resolved) // { pn: '5511999999999@s.whatsapp.net', lid: '12345678901234@lid', jid: ... }
|
|
1334
|
+
|
|
1335
|
+
// 4. Registrar manualmente um mapeamento conhecido
|
|
1336
|
+
await sock.storeLidPnMapping('5511999999999@s.whatsapp.net', '12345678901234@lid')
|
|
1337
|
+
|
|
1338
|
+
// 5. Consultas diretas via protocolo USync (baixo nível)
|
|
1339
|
+
const [lidUser] = await sock.getLidUser('5511999999999@s.whatsapp.net')
|
|
1340
|
+
const [pnUser] = await sock.getPnUser('12345678901234@lid')
|
|
1341
|
+
```
|
|
1342
|
+
|
|
1343
|
+
### Store Unificado de Contatos e Conversas (`makeInMemoryStore`)
|
|
1344
|
+
|
|
1345
|
+
Tradicionalmente, quando o WhatsApp chaveia as mensagens para `@lid`, consultas como `store.contacts[jid]` ou `store.messages[jid]` falhavam por incompatibilidade de identificadores. O **WaSockets** resolve isso unificando o catálogo em tempo de execução:
|
|
1346
|
+
|
|
1347
|
+
```javascript
|
|
1348
|
+
import { makeInMemoryStore } from '@areumtecnologia/wasockets'
|
|
1349
|
+
|
|
1350
|
+
const store = makeInMemoryStore({})
|
|
1351
|
+
store.bind(sock.ev)
|
|
1352
|
+
|
|
1353
|
+
// Busca unificada: localiza o contato quer você passe o número (@s.whatsapp.net), o @lid ou apenas os dígitos
|
|
1354
|
+
const contact = store.getContact('12345678901234@lid')
|
|
1355
|
+
// Retorna o contato completo contendo .id, .lid, .phoneNumber, .name, etc.
|
|
1356
|
+
|
|
1357
|
+
// Busca unificada de chat: localiza a conversa mesmo se foi iniciada com PN ou com LID
|
|
1358
|
+
const chat = store.getChat('12345678901234@lid')
|
|
1359
|
+
|
|
1360
|
+
// Carregamento de mensagens com fallback cruzado automático entre LID e PN
|
|
1361
|
+
const messages = await store.loadMessages('12345678901234@lid', 25)
|
|
1362
|
+
```
|
|
1363
|
+
|
|
1364
|
+
---
|
|
1365
|
+
|
|
1366
|
+
## 🏷️ Etiquetas de Negócio (Labels - WhatsApp Business)
|
|
1367
|
+
|
|
1368
|
+
O **WaSockets** permite que você gerencie etiquetas e organize contatos ou mensagens diretamente pelo aplicativo WhatsApp Business.
|
|
1369
|
+
|
|
1370
|
+
### Criando, Editando e Deletando Etiquetas (CRUD de Sistema)
|
|
1371
|
+
|
|
1372
|
+
Você pode criar, editar e excluir as etiquetas globais da sua conta:
|
|
1373
|
+
|
|
1374
|
+
```javascript
|
|
1375
|
+
// Criar uma nova etiqueta com cor específica
|
|
1376
|
+
// Cores suportadas: de 0 a 19 correspondentes à paleta do WhatsApp Business
|
|
1377
|
+
const novaLabel = await sock.createLabel('Lead Qualificado', 5)
|
|
1378
|
+
|
|
1379
|
+
// Atualizar o nome e a cor de uma etiqueta existente
|
|
1380
|
+
await sock.updateLabel('label_id_123', 'Pagamento Aprovado', 2)
|
|
1381
|
+
|
|
1382
|
+
// Deletar uma etiqueta definitivamente da conta
|
|
1383
|
+
await sock.deleteLabel('label_id_123')
|
|
1384
|
+
```
|
|
1385
|
+
|
|
1386
|
+
### Associando Etiquetas a Conversas e Mensagens
|
|
1387
|
+
|
|
1388
|
+
Para categorizar chats específicos ou marcar mensagens individuais dentro de uma conversa:
|
|
1389
|
+
|
|
1390
|
+
```javascript
|
|
1391
|
+
// Associar etiqueta a uma conversa (JID)
|
|
1392
|
+
await sock.addChatLabel(jid, 'label_id_123')
|
|
1393
|
+
|
|
1394
|
+
// Remover etiqueta de uma conversa (JID)
|
|
1395
|
+
await sock.removeChatLabel(jid, 'label_id_123')
|
|
1396
|
+
|
|
1397
|
+
// Associar etiqueta a uma mensagem específica
|
|
1398
|
+
await sock.addMessageLabel(jid, 'mensagem_id_456', 'label_id_123')
|
|
1399
|
+
|
|
1400
|
+
// Remover etiqueta de uma mensagem específica
|
|
1401
|
+
await sock.removeMessageLabel(jid, 'mensagem_id_456', 'label_id_123')
|
|
1402
|
+
```
|
|
1403
|
+
|
|
1404
|
+
### Respostas Rápidas (Quick Replies)
|
|
1405
|
+
|
|
1406
|
+
Para contas WhatsApp Business, gerencie respostas rápidas acessíveis via atalhos:
|
|
1407
|
+
|
|
1408
|
+
```javascript
|
|
1409
|
+
// Criar ou atualizar resposta rápida
|
|
1410
|
+
await sock.addOrEditQuickReply({
|
|
1411
|
+
id: 'qr_ola',
|
|
1412
|
+
shortcut: '/ola',
|
|
1413
|
+
message: 'Olá! Seja muito bem-vindo à Áreum Tecnologia. Como podemos te ajudar hoje?',
|
|
1414
|
+
keywords: ['ola', 'ajuda', 'suporte', 'inicio']
|
|
1415
|
+
})
|
|
1416
|
+
|
|
1417
|
+
// Remover resposta rápida pelo ID
|
|
1418
|
+
await sock.removeQuickReply('qr_ola')
|
|
1419
|
+
```
|
|
1420
|
+
|
|
1421
|
+
---
|
|
1422
|
+
|
|
1423
|
+
## 👥 Gerenciamento de Grupos
|
|
1424
|
+
|
|
1425
|
+
As operações de alteração estrutural em grupos requerem que a conta conectada seja administradora do grupo correspondente.
|
|
1426
|
+
|
|
1427
|
+
```javascript
|
|
1428
|
+
// Criar um novo grupo
|
|
1429
|
+
const grupo = await sock.groupCreate('Equipe de Suporte Áreum', ['5511999999999@s.whatsapp.net'])
|
|
1430
|
+
console.log('Grupo criado com ID:', grupo.id)
|
|
1431
|
+
|
|
1432
|
+
// Adicionar/Remover/Promover participantes
|
|
1433
|
+
// Parâmetros de ação: 'add' | 'remove' | 'promote' | 'demote'
|
|
1434
|
+
await sock.groupParticipantsUpdate(grupo.id, ['5511888888888@s.whatsapp.net'], 'add')
|
|
1435
|
+
|
|
1436
|
+
// Obter dados/metadados de um grupo ANTES de entrar usando o código de convite
|
|
1437
|
+
const infoConvite = await sock.groupGetInviteInfo('ABcdEFghIJklMnOpQrStUv')
|
|
1438
|
+
console.log(`Nome do grupo no convite: ${infoConvite.subject}`)
|
|
1439
|
+
|
|
1440
|
+
// Obter o código/link de convite do grupo
|
|
1441
|
+
const codigoConvite = await sock.groupInviteCode(grupo.id)
|
|
1442
|
+
console.log(`Link: https://chat.whatsapp.com/${codigoConvite}`)
|
|
1443
|
+
|
|
1444
|
+
// Revogar link de convite anterior e gerar um novo
|
|
1445
|
+
const novoCodigo = await sock.groupRevokeInvite(grupo.id)
|
|
1446
|
+
|
|
1447
|
+
// Entrar em um grupo usando um código de convite (apenas o código, sem o domínio completo)
|
|
1448
|
+
const resposta = await sock.groupAcceptInvite('ABcdEFghIJklMnOpQrStUv')
|
|
1449
|
+
|
|
1450
|
+
// Alterar o assunto (título) do grupo
|
|
1451
|
+
await sock.groupUpdateSubject(grupo.id, 'Novo Nome do Grupo')
|
|
1452
|
+
|
|
1453
|
+
// Alterar a descrição do grupo
|
|
1454
|
+
await sock.groupUpdateDescription(grupo.id, 'Regras do grupo e links importantes.')
|
|
1455
|
+
|
|
1456
|
+
// Sair do grupo
|
|
1457
|
+
await sock.groupLeave(grupo.id)
|
|
1458
|
+
|
|
1459
|
+
// Obter a lista de pessoas aguardando aprovação para entrar no grupo
|
|
1460
|
+
const solicitacoes = await sock.groupRequestParticipantsList(grupo.id)
|
|
1461
|
+
console.log(solicitacoes)
|
|
1462
|
+
|
|
1463
|
+
// Aprovar entrada pendente
|
|
1464
|
+
await sock.groupRequestParticipantsUpdate(grupo.id, ['5511777777777@s.whatsapp.net'], 'approve') // ou 'reject'
|
|
1465
|
+
|
|
1466
|
+
// Obter metadados do grupo (participantes, título, regras, descrição)
|
|
1467
|
+
const metadados = await sock.groupMetadata(grupo.id)
|
|
1468
|
+
console.log(`Título: ${metadados.subject}, Membros: ${metadados.participants.length}`)
|
|
1469
|
+
```
|
|
1470
|
+
|
|
1471
|
+
---
|
|
1472
|
+
|
|
1473
|
+
## 👥 Etiquetas de Membro (Member Tags) em Grupos
|
|
1474
|
+
|
|
1475
|
+
O WhatsApp permite que os participantes de um grupo criem um rótulo ou descrição curta de até 30 caracteres para si mesmos (ex: definir seu papel ou cargo no grupo).
|
|
1476
|
+
|
|
1477
|
+
### Definindo sua própria Etiqueta de Membro no Grupo
|
|
1478
|
+
|
|
1479
|
+
```javascript
|
|
1480
|
+
// Define a sua etiqueta como "Suporte Técnico" no grupo especificado
|
|
1481
|
+
await sock.updateMemberLabel(grupoJid, "Suporte Técnico")
|
|
1482
|
+
```
|
|
1483
|
+
|
|
1484
|
+
### Monitorando Atualizações de Etiquetas de Outros Membros
|
|
1485
|
+
|
|
1486
|
+
Você pode escutar o evento `group.member-tag.update` para monitorar quando qualquer participante alterar a etiqueta de membro dele no grupo:
|
|
1487
|
+
|
|
1488
|
+
```javascript
|
|
1489
|
+
sock.ev.on('group.member-tag.update', (update) => {
|
|
1490
|
+
const { groupId, label, participant } = update
|
|
1491
|
+
console.log(`O usuário ${participant} definiu a etiqueta "${label}" no grupo ${groupId}`)
|
|
1492
|
+
})
|
|
1493
|
+
```
|
|
1494
|
+
|
|
1495
|
+
---
|
|
1496
|
+
|
|
1497
|
+
## 📢 Newsletters / Canais v2 (Pilar 3)
|
|
1498
|
+
|
|
1499
|
+
O **WaSockets** traz suporte avançado para a criação, monitoramento, consumo e interação em Newsletters (Canais de Transmissão públicos do WhatsApp):
|
|
1500
|
+
|
|
1501
|
+
```javascript
|
|
1502
|
+
// 1. Criar uma Newsletter (Canal)
|
|
1503
|
+
const canal = await sock.newsletterCreate('Notícias Tecnológicas Áreum', 'Canal oficial de novidades')
|
|
1504
|
+
console.log('Canal criado com ID:', canal.id)
|
|
1505
|
+
|
|
1506
|
+
// 2. Obter metadados de um Canal público pelo ID ou Invite Code
|
|
1507
|
+
const metadadosCanal = await sock.newsletterMetadata('JID', canal.id)
|
|
1508
|
+
console.log('Nome do Canal:', metadadosCanal.name)
|
|
1509
|
+
|
|
1510
|
+
// 3. Listar todos os Canais inscritos
|
|
1511
|
+
const canaisInscritos = await sock.newsletterSubscribed()
|
|
1512
|
+
console.log('Canais que eu sigo:', canaisInscritos)
|
|
1513
|
+
|
|
1514
|
+
// 4. Buscar e decodificar mensagens do Canal (com contagem de visualizações e reações)
|
|
1515
|
+
const { messages } = await sock.newsletterFetchMessages(canal.id, 20)
|
|
1516
|
+
for (const msg of messages) {
|
|
1517
|
+
console.log(`[ID: ${msg.server_id}] Visualizações: ${msg.views}`)
|
|
1518
|
+
console.log('Conteúdo:', msg.message?.conversation || msg.message?.extendedTextMessage?.text)
|
|
1519
|
+
console.log('Reações:', msg.reactions) // [{ code: '👍', count: 12 }, { code: '❤️', count: 5 }]
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
// 5. Buscar mensagem individual do Canal
|
|
1523
|
+
const singleMsg = await sock.newsletterFetchMessage(canal.id, '12345')
|
|
1524
|
+
|
|
1525
|
+
// 6. Consultar contadores de reações de uma postagem
|
|
1526
|
+
const reacoes = await sock.newsletterFetchReactions(canal.id, '12345')
|
|
1527
|
+
console.log('Reações do post:', reacoes)
|
|
1528
|
+
|
|
1529
|
+
// 7. Reagir a uma postagem do Canal (suporta server_id, id ou chave da mensagem)
|
|
1530
|
+
await sock.newsletterReactMessage(canal.id, '12345', '🔥')
|
|
1531
|
+
|
|
1532
|
+
// 8. Seguir / Deixar de Seguir
|
|
1533
|
+
await sock.newsletterFollow(canal.id)
|
|
1534
|
+
await sock.newsletterUnfollow(canal.id)
|
|
1535
|
+
|
|
1536
|
+
// 9. Silenciar / Ativar notificações
|
|
1537
|
+
await sock.newsletterMute(canal.id)
|
|
1538
|
+
await sock.newsletterUnmute(canal.id)
|
|
1539
|
+
await sock.newsletterToggleMute(canal.id, true) // ou false para desativar
|
|
1540
|
+
|
|
1541
|
+
// 10. Atualizar nome, descrição ou foto do Canal (Admins)
|
|
1542
|
+
await sock.newsletterUpdateName(canal.id, 'Novo Nome do Canal')
|
|
1543
|
+
await sock.newsletterUpdateDescription(canal.id, 'Nova descrição detalhada do canal')
|
|
1544
|
+
await sock.newsletterUpdatePicture(canal.id, './novo_avatar_canal.jpg')
|
|
1545
|
+
await sock.newsletterRemovePicture(canal.id)
|
|
1546
|
+
|
|
1547
|
+
// 11. Consultar inscritos e administradores
|
|
1548
|
+
const inscritos = await sock.newsletterSubscribers(canal.id)
|
|
1549
|
+
const totalAdmins = await sock.newsletterAdminCount(canal.id)
|
|
1550
|
+
|
|
1551
|
+
// 12. Transferir propriedade ou excluir o Canal
|
|
1552
|
+
await sock.newsletterChangeOwner(canal.id, '5511888888888@s.whatsapp.net')
|
|
1553
|
+
await sock.newsletterDelete(canal.id)
|
|
1554
|
+
```
|
|
1555
|
+
|
|
1556
|
+
---
|
|
1557
|
+
|
|
1558
|
+
## 💼 WhatsApp Business (Catálogo, Produtos e Perfil Comercial)
|
|
1559
|
+
|
|
1560
|
+
Caso a conta conectada seja comercial (WhatsApp Business), o **WaSockets** oferece suporte para interagir com o catálogo de produtos, obter detalhes de pedidos e gerenciar o perfil público e as mídias da empresa.
|
|
1561
|
+
|
|
1562
|
+
### Gerenciamento de Perfil e Capa Comercial
|
|
1563
|
+
|
|
1564
|
+
Você pode atualizar dados públicos de endereço, e-mail, descrição, websites, horários de funcionamento e foto de capa:
|
|
1565
|
+
|
|
1566
|
+
```javascript
|
|
1567
|
+
// Atualizar o perfil comercial do usuário
|
|
1568
|
+
await sock.updateBussinesProfile({
|
|
1569
|
+
address: 'Av. Paulista, 1000 - São Paulo, SP',
|
|
1570
|
+
email: 'contato@suaempresa.com.br',
|
|
1571
|
+
description: 'Empresa especializada em soluções de tecnologia.',
|
|
1572
|
+
websites: ['https://suaempresa.com.br', 'https://blog.suaempresa.com.br'],
|
|
1573
|
+
hours: {
|
|
1574
|
+
timezone: 'America/Sao_Paulo',
|
|
1575
|
+
days: [
|
|
1576
|
+
{ day: '1', mode: 'open_24_h' }, // Segunda-feira (1=Segunda, 7=Domingo)
|
|
1577
|
+
{
|
|
1578
|
+
day: '2',
|
|
1579
|
+
mode: 'specific_hours',
|
|
1580
|
+
openTimeInMinutes: 540, // 09:00 (9h * 60)
|
|
1581
|
+
closeTimeInMinutes: 1080 // 18:00 (18h * 60)
|
|
1582
|
+
}
|
|
1583
|
+
]
|
|
1584
|
+
}
|
|
1585
|
+
})
|
|
1586
|
+
|
|
1587
|
+
// Atualizar ou definir a foto de capa comercial
|
|
1588
|
+
const coverPhotoId = await sock.updateCoverPhoto('./capa_empresa.jpg')
|
|
1589
|
+
|
|
1590
|
+
// Remover a foto de capa atual
|
|
1591
|
+
await sock.removeCoverPhoto(coverPhotoId)
|
|
1592
|
+
```
|
|
1593
|
+
|
|
1594
|
+
### Consulta de Catálogo, Coleções e Pedidos
|
|
1595
|
+
|
|
1596
|
+
```javascript
|
|
1597
|
+
// Obter a lista de produtos do catálogo de um contato (ou do seu próprio)
|
|
1598
|
+
const catalogo = await sock.getCatalog({
|
|
1599
|
+
jid: '5511999999999@s.whatsapp.net',
|
|
1600
|
+
limit: 15
|
|
1601
|
+
})
|
|
1602
|
+
console.log('Produtos:', catalogo.products)
|
|
1603
|
+
|
|
1604
|
+
// Obter as coleções de produtos organizadas do catálogo
|
|
1605
|
+
const colecoes = await sock.getCollections('5511999999999@s.whatsapp.net', 10)
|
|
1606
|
+
|
|
1607
|
+
// Obter os detalhes completos de um pedido comercial a partir do ID e do Token da mensagem de carrinho
|
|
1608
|
+
const detalhesPedido = await sock.getOrderDetails('ID_DO_PEDIDO', 'TOKEN_DO_PEDIDO')
|
|
1609
|
+
console.log('Itens do Pedido:', detalhesPedido.items)
|
|
1610
|
+
```
|
|
1611
|
+
|
|
1612
|
+
### Cadastro e Modificação de Produtos no Catálogo
|
|
1613
|
+
|
|
1614
|
+
```javascript
|
|
1615
|
+
// Adicionar um novo produto no catálogo
|
|
1616
|
+
const novoProduto = await sock.productCreate({
|
|
1617
|
+
name: 'Caneca Personalizada WaSockets',
|
|
1618
|
+
description: 'Caneca de cerâmica de alta qualidade.',
|
|
1619
|
+
price: 4990, // R$ 49,90 (valor representado sem decimais, multiplicado por 100)
|
|
1620
|
+
currency: 'BRL',
|
|
1621
|
+
isHidden: false,
|
|
1622
|
+
image: { url: './caneca.jpg' } // Caminho local, buffer ou stream
|
|
1623
|
+
})
|
|
1624
|
+
console.log('Produto Criado com ID:', novoProduto.id)
|
|
1625
|
+
|
|
1626
|
+
// Atualizar dados de um produto existente
|
|
1627
|
+
await sock.productUpdate(novoProduto.id, {
|
|
1628
|
+
name: 'Caneca Personalizada WaSockets (Edição Especial)',
|
|
1629
|
+
price: 5990
|
|
1630
|
+
})
|
|
1631
|
+
|
|
1632
|
+
// Obter detalhes de um único produto
|
|
1633
|
+
const produto = await sock.getProduct(sock.user.id, novoProduto.id)
|
|
1634
|
+
console.log('Detalhes do Produto:', produto)
|
|
1635
|
+
|
|
1636
|
+
// Remover produtos do catálogo (aceita um array de IDs de produtos)
|
|
1637
|
+
await sock.productDelete([novoProduto.id])
|
|
1638
|
+
```
|
|
1639
|
+
|
|
1640
|
+
---
|
|
1641
|
+
|
|
1642
|
+
## 👥 Grupos, Comunidades v2 e Moderação Avançada
|
|
1643
|
+
|
|
1644
|
+
O **WaSockets** oferece um conjunto completo e modernizado para gerenciamento profissional de Grupos e Comunidades no WhatsApp.
|
|
1645
|
+
|
|
1646
|
+
### Gestão e Moderação de Entrada (Approval Mode)
|
|
1647
|
+
|
|
1648
|
+
Controle quem pode entrar no grupo através do fluxo oficial de aprovação de membros:
|
|
1649
|
+
|
|
1650
|
+
```javascript
|
|
1651
|
+
const groupJid = '1234567890-987654@g.us'
|
|
1652
|
+
|
|
1653
|
+
// Ativar modo de aprovação obrigatória de novos membros
|
|
1654
|
+
await sock.groupMembershipApprovalMode(groupJid, 'on') // ou true / 'off'
|
|
1655
|
+
|
|
1656
|
+
// Listar participantes aguardando aprovação
|
|
1657
|
+
const pendentes = await sock.groupRequestParticipantsList(groupJid)
|
|
1658
|
+
console.log('Solicitações pendentes:', pendentes)
|
|
1659
|
+
|
|
1660
|
+
// Aprovar participantes pendentes (aceita string única ou array)
|
|
1661
|
+
await sock.groupApprovePendingParticipants(groupJid, ['5511999999999@s.whatsapp.net'])
|
|
1662
|
+
|
|
1663
|
+
// Rejeitar participantes pendentes
|
|
1664
|
+
await sock.groupRejectPendingParticipants(groupJid, ['5511888888888@s.whatsapp.net'])
|
|
1665
|
+
```
|
|
1666
|
+
|
|
1667
|
+
### Configuração Unificada de Políticas do Grupo
|
|
1668
|
+
|
|
1669
|
+
Altere facilmente todas as diretrizes de segurança e permissões do grupo em uma única operação:
|
|
1670
|
+
|
|
1671
|
+
```javascript
|
|
1672
|
+
await sock.groupUpdatePermissions(groupJid, {
|
|
1673
|
+
announce: true, // true: apenas admins enviam mensagens; false: todos
|
|
1674
|
+
restrict: true, // true: apenas admins editam dados do grupo; false: todos
|
|
1675
|
+
memberAddMode: 'admin_add', // 'admin_add' ou 'all_member_add'
|
|
1676
|
+
approvalMode: true, // Exigir aprovação de admin para novos participantes
|
|
1677
|
+
ephemeral: 86400 // Mensagens temporárias (24h = 86400s, 7 dias = 604800s, false = desativar)
|
|
1678
|
+
})
|
|
1679
|
+
```
|
|
1680
|
+
|
|
1681
|
+
### Menção a Todos os Membros (@everyone / Mention All)
|
|
1682
|
+
|
|
1683
|
+
Notifique ou mencione todos os participantes de um grupo de forma prática e sem boilerplate:
|
|
1684
|
+
|
|
1685
|
+
```javascript
|
|
1686
|
+
// Método direto
|
|
1687
|
+
await sock.groupSendMentionAll(groupJid, '📢 Atenção a todos os membros: reunião às 15h!')
|
|
1688
|
+
|
|
1689
|
+
// Ou apenas para administradores, excluindo a si próprio:
|
|
1690
|
+
await sock.groupSendMentionAll(groupJid, 'Aviso importante aos administradores', {
|
|
1691
|
+
adminsOnly: true,
|
|
1692
|
+
excludeMe: true
|
|
1693
|
+
})
|
|
1694
|
+
|
|
1695
|
+
// Ou diretamente através do sendMessage usando o parâmetro mentionAll:
|
|
1696
|
+
await sock.sendMessage(groupJid, {
|
|
1697
|
+
text: 'Olá a todos!',
|
|
1698
|
+
mentionAll: true
|
|
1699
|
+
})
|
|
1700
|
+
```
|
|
1701
|
+
|
|
1702
|
+
### Extração Rápida de Administradores e Membros
|
|
1703
|
+
|
|
1704
|
+
```javascript
|
|
1705
|
+
// Retorna array de JIDs apenas de administradores e criador
|
|
1706
|
+
const adminJids = await sock.groupGetAdminJids(groupJid)
|
|
1707
|
+
|
|
1708
|
+
// Retorna lista completa normalizada de participantes com status de admin e LID
|
|
1709
|
+
const participantes = await sock.groupGetParticipants(groupJid)
|
|
1710
|
+
```
|
|
1711
|
+
|
|
1712
|
+
### Comunidades v2 (Subgrupos e Anúncios)
|
|
1713
|
+
|
|
1714
|
+
Gerencie Comunidades do WhatsApp com suporte a separação de subgrupos e grupo de avisos geral:
|
|
1715
|
+
|
|
1716
|
+
```javascript
|
|
1717
|
+
// Criar uma comunidade
|
|
1718
|
+
const comunidade = await sock.communityCreate('Minha Comunidade', 'Descrição da comunidade')
|
|
1719
|
+
|
|
1720
|
+
// Vincular um grupo existente como subgrupo da comunidade
|
|
1721
|
+
await sock.communityLinkGroup(groupJid, comunidade.id)
|
|
1722
|
+
|
|
1723
|
+
// Desvincular um subgrupo da comunidade
|
|
1724
|
+
await sock.communityUnlinkGroup(groupJid, comunidade.id)
|
|
1725
|
+
|
|
1726
|
+
// Obter subgrupos organizados (grupo padrão de anúncios vs subgrupos comuns)
|
|
1727
|
+
const { defaultSubGroup, subGroups, allGroups } = await sock.communityFetchSubGroups(comunidade.id)
|
|
1728
|
+
console.log('Grupo Geral de Anúncios:', defaultSubGroup)
|
|
1729
|
+
console.log('Subgrupos de discussão:', subGroups)
|
|
1730
|
+
|
|
1731
|
+
// Gerenciar aprovações de entrada na Comunidade
|
|
1732
|
+
await sock.communityMembershipApprovalMode(comunidade.id, 'on')
|
|
1733
|
+
await sock.communityApprovePendingParticipants(comunidade.id, ['5511999999999@s.whatsapp.net'])
|
|
1734
|
+
```
|
|
1735
|
+
|
|
1736
|
+
### Mensagens de Visualização Única (View Once)
|
|
1737
|
+
|
|
1738
|
+
Envie imagens, vídeos ou mídias efêmeras com a flag `viewOnce: true`:
|
|
1739
|
+
|
|
1740
|
+
```javascript
|
|
1741
|
+
await sock.sendMessage(jid, {
|
|
1742
|
+
image: { url: './comprovante.jpg' },
|
|
1743
|
+
caption: 'Comprovante confidencial',
|
|
1744
|
+
viewOnce: true
|
|
1745
|
+
})
|
|
1746
|
+
```
|
|
1747
|
+
|
|
1748
|
+
---
|
|
1749
|
+
|
|
1750
|
+
## 🧩 Arquitetura de Plugins e Middlewares
|
|
1751
|
+
|
|
1752
|
+
O **WaSockets** introduz uma arquitetura modular de plugins e ciclo de vida de middlewares que permite estender o socket de maneira limpa, sem monkey-patching.
|
|
1753
|
+
|
|
1754
|
+
### Criando e Instalando Plugins
|
|
1755
|
+
|
|
1756
|
+
Um plugin pode ser uma função simples ou um objeto estruturado:
|
|
1757
|
+
|
|
1758
|
+
```javascript
|
|
1759
|
+
// Exemplo de Plugin de Boas-Vindas ou Auto-Resposta
|
|
1760
|
+
const meuPluginBot = {
|
|
1761
|
+
name: 'auto-reply-plugin',
|
|
1762
|
+
version: '1.0.0',
|
|
1763
|
+
description: 'Responde automaticamente a palavras-chave',
|
|
1764
|
+
install(sock, options, manager) {
|
|
1765
|
+
console.log('Plugin instalado com opções:', options)
|
|
1766
|
+
|
|
1767
|
+
// Escuta eventos normais da conexão
|
|
1768
|
+
sock.ev.on('messages.upsert', async ({ messages, type }) => {
|
|
1769
|
+
if (type !== 'notify') return
|
|
1770
|
+
for (const msg of messages) {
|
|
1771
|
+
if (!msg.key.fromMe && msg.message?.conversation === '!ping') {
|
|
1772
|
+
await sock.sendMessage(msg.key.remoteJid, { text: '🏓 Pong via Plugin!' })
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
})
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1779
|
+
// Instalação do plugin no socket
|
|
1780
|
+
sock.use(meuPluginBot, { prefix: '!' })
|
|
1781
|
+
|
|
1782
|
+
// Listar plugins ativos
|
|
1783
|
+
console.log('Plugins ativos:', sock.listPlugins())
|
|
1784
|
+
```
|
|
1785
|
+
|
|
1786
|
+
### Middlewares de Interceptação de Mensagens
|
|
1787
|
+
|
|
1788
|
+
Intercepte ou cancele envios e recebimentos antes que cheguem à rede:
|
|
1789
|
+
|
|
1790
|
+
```javascript
|
|
1791
|
+
// Intercepta qualquer mensagem antes do envio (retornar false cancela o envio)
|
|
1792
|
+
sock.registerMiddleware('beforeSendMessage', async ({ jid, content, options }, socket) => {
|
|
1793
|
+
console.log(`Enviando mensagem para ${jid}...`)
|
|
1794
|
+
|
|
1795
|
+
// Bloquear envio se contiver palavras proibidas
|
|
1796
|
+
if (typeof content?.text === 'string' && content.text.includes('palavra_bloqueada')) {
|
|
1797
|
+
console.warn('Mensagem bloqueada por política de segurança.')
|
|
1798
|
+
return false // Cancela o disparo
|
|
1799
|
+
}
|
|
1800
|
+
})
|
|
1801
|
+
|
|
1802
|
+
// Executa após a mensagem ser enviada com sucesso
|
|
1803
|
+
sock.registerMiddleware('afterSendMessage', async ({ jid, content, fullMsg }, socket) => {
|
|
1804
|
+
console.log(`Mensagem ${fullMsg.key.id} entregue ao servidor com sucesso!`)
|
|
1805
|
+
})
|
|
1806
|
+
```
|
|
1807
|
+
|
|
1808
|
+
---
|
|
1809
|
+
|
|
1810
|
+
## ⚡ Alta Performance, Cache e Controle de Memória
|
|
1811
|
+
|
|
1812
|
+
### Cache Integrado de Metadados de Grupo (TTL LRU)
|
|
1813
|
+
|
|
1814
|
+
Por padrão, o **WaSockets** ativa um cache inteligente com expiração por tempo (TTL de 5 minutos e limite de grupos em memória). Ao enviar mensagens para grupos ou listar participantes, as requisições repetidas ao WhatsApp são evitadas, acelerando disparos em massa em até 10x:
|
|
1815
|
+
|
|
1816
|
+
```javascript
|
|
1817
|
+
const sock = makeWASocket({
|
|
1818
|
+
enableGroupCache: true // Ativado por padrão com TTL de 5 minutos
|
|
1819
|
+
})
|
|
1820
|
+
```
|
|
1821
|
+
|
|
1822
|
+
### Proteção de Memória na Store (`makeInMemoryStore`)
|
|
1823
|
+
|
|
1824
|
+
Evite vazamento de memória em bots de alta demanda com limpeza automática e limite configurável de mensagens por chat:
|
|
1825
|
+
|
|
1826
|
+
```javascript
|
|
1827
|
+
const store = makeInMemoryStore({
|
|
1828
|
+
maxMessagesPerChat: 200 // Limita o histórico a 200 mensagens por chat em RAM (padrão: 500)
|
|
1829
|
+
})
|
|
1830
|
+
|
|
1831
|
+
// Limpeza manual sob demanda
|
|
1832
|
+
store.pruneMessages(groupJid, 50) // Mantém apenas as últimas 50 mensagens do chat especificado
|
|
1833
|
+
store.pruneMessages(undefined, 100) // Trunca todos os chats para no máximo 100 mensagens
|
|
1834
|
+
|
|
1835
|
+
// Obter contagem de mensagens armazenadas
|
|
1836
|
+
const qtdTotal = store.getMessageCount()
|
|
1837
|
+
const qtdChat = store.getMessageCount(groupJid)
|
|
1838
|
+
|
|
1839
|
+
// Limpar mensagens de um chat ou resetar toda a memória
|
|
1840
|
+
store.clear(groupJid)
|
|
1841
|
+
```
|
|
1842
|
+
|
|
1843
|
+
---
|
|
1844
|
+
|
|
1845
|
+
## 🔷 Suporte Completo a TypeScript
|
|
1846
|
+
|
|
1847
|
+
O **WaSockets** inclui definições de tipo completas em `lib/index.d.ts` e exporta a tipagem de todos os métodos dos 5 pilares, interfaces de mensagens, eventos e plugins:
|
|
1848
|
+
|
|
1849
|
+
```typescript
|
|
1850
|
+
import makeWASocket, { WASocket, AnyMessageContent, DisconnectReason, GroupMetadata } from '@areumtecnologia/wasockets'
|
|
1851
|
+
|
|
1852
|
+
const sock: WASocket = makeWASocket({
|
|
1853
|
+
printQRInTerminal: true
|
|
1854
|
+
})
|
|
1855
|
+
```
|
|
1856
|
+
|
|
1857
|
+
---
|
|
1858
|
+
|
|
1859
|
+
## 🔒 Configurações de Privacidade
|
|
1860
|
+
|
|
1861
|
+
```javascript
|
|
1862
|
+
// Bloquear ou desbloquear um usuário
|
|
1863
|
+
await sock.updateBlockStatus('5511999999999@s.whatsapp.net', 'block') // ou 'unblock'
|
|
1864
|
+
|
|
1865
|
+
// Obter lista de usuários bloqueados
|
|
1866
|
+
const listaBloqueados = await sock.fetchBlocklist()
|
|
1867
|
+
|
|
1868
|
+
// Atualizar privacidade do "Visto por Último"
|
|
1869
|
+
// Valores aceitos: 'all' | 'contacts' | 'contact_blacklist' | 'none'
|
|
1870
|
+
await sock.updateLastSeenPrivacy('contacts')
|
|
1871
|
+
|
|
1872
|
+
// Atualizar privacidade do "Visto Online"
|
|
1873
|
+
// Valores aceitos: 'all' | 'match_last_seen'
|
|
1874
|
+
await sock.updateOnlinePrivacy('match_last_seen')
|
|
1875
|
+
|
|
1876
|
+
// Atualizar privacidade das confirmações de leitura (ticks azuis)
|
|
1877
|
+
// Valores aceitos: 'all' | 'none'
|
|
1878
|
+
await sock.updateReadReceiptsPrivacy('none')
|
|
1879
|
+
|
|
1880
|
+
// Atualizar privacidade da Foto de Perfil
|
|
1881
|
+
// Valores aceitos: 'all' | 'contacts' | 'contact_blacklist' | 'none'
|
|
1882
|
+
await sock.updateProfilePicturePrivacy('contacts')
|
|
1883
|
+
|
|
1884
|
+
// Atualizar privacidade do Recado/Status (About)
|
|
1885
|
+
// Valores aceitos: 'all' | 'contacts' | 'contact_blacklist' | 'none'
|
|
1886
|
+
await sock.updateStatusPrivacy('contacts')
|
|
1887
|
+
|
|
1888
|
+
// Atualizar quem pode adicionar você a grupos
|
|
1889
|
+
// Valores aceitos: 'all' | 'contacts' | 'contact_blacklist'
|
|
1890
|
+
await sock.updateGroupsAddPrivacy('contacts')
|
|
1891
|
+
|
|
1892
|
+
// Consultar todas as configurações de privacidade ativas da conta
|
|
1893
|
+
const privacySettings = await sock.fetchPrivacySettings()
|
|
1894
|
+
console.log('Configurações de privacidade atuais:', privacySettings)
|
|
1895
|
+
```
|
|
1896
|
+
|
|
1897
|
+
---
|
|
1898
|
+
|
|
1899
|
+
## 🛡️ Logs e Protocolo
|
|
1900
|
+
|
|
1901
|
+
Para habilitar a depuração detalhada e ver o tráfego bruto do Websocket trocado com o WhatsApp, inicialize o logger no nível `debug` ou `trace`. O **WaSockets** usa a biblioteca estruturada `pino` para logs ultra rápidos:
|
|
1902
|
+
|
|
1903
|
+
```javascript
|
|
1904
|
+
const pino = require('pino')
|
|
1905
|
+
|
|
1906
|
+
const sock = makeWASocket({
|
|
1907
|
+
logger: pino({ level: 'debug' })
|
|
1908
|
+
})
|
|
1909
|
+
```
|
|
1910
|
+
|
|
1911
|
+
### Como o WhatsApp se comunica (BinaryNodes)
|
|
1912
|
+
|
|
1913
|
+
As mensagens são trocadas em formato binário encapsuladas em estruturas denominadas `BinaryNode`. Cada nó possui três atributos:
|
|
1914
|
+
- **`tag`**: Nome da ação (ex: `message`, `ib`, `presence`, `iq`)
|
|
1915
|
+
- **`attrs`**: Objeto contendo propriedades em string/chave-valor (ID, timestamp, remetente, etc.)
|
|
1916
|
+
- **`content`**: O corpo de dados do nó (geralmente outro array de nós ou um buffer criptografado)
|
|
1917
|
+
|
|
1918
|
+
Você pode interagir diretamente com o tráfego do Websocket do WhatsApp registrando callbacks específicos:
|
|
1919
|
+
|
|
1920
|
+
```javascript
|
|
1921
|
+
// Monitora todos os pacotes recebidos que possuem a tag 'edge_routing'
|
|
1922
|
+
sock.ws.on('CB:edge_routing', (node) => {
|
|
1923
|
+
console.log('Recebido nó de roteamento:', node)
|
|
1924
|
+
})
|
|
1925
|
+
|
|
1926
|
+
// Monitora pacotes 'message' específicos
|
|
1927
|
+
sock.ws.on('CB:message', (node) => {
|
|
1928
|
+
console.log('Mensagem de protocolo bruta:', node)
|
|
1929
|
+
})
|
|
1930
|
+
```
|