@areumtecnologia/wasockets 1.1.3 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -543,6 +543,46 @@ await sock.chatModify({ pin: true }, jid)
543
543
 
544
544
  ---
545
545
 
546
+ ## 🏷️ Etiquetas de Negócio (Labels - WhatsApp Business)
547
+
548
+ O **WaSockets** permite que você gerencie etiquetas e organize contatos ou mensagens diretamente pelo aplicativo WhatsApp Business.
549
+
550
+ ### Criando, Editando e Deletando Etiquetas (CRUD de Sistema)
551
+
552
+ Você pode criar, editar e excluir as etiquetas globais da sua conta:
553
+
554
+ ```javascript
555
+ // Criar uma nova etiqueta com cor específica
556
+ // Cores suportadas: de 0 a 19 correspondentes à paleta do WhatsApp Business
557
+ const novaLabel = await sock.createLabel('Lead Qualificado', 5)
558
+
559
+ // Atualizar o nome e a cor de uma etiqueta existente
560
+ await sock.updateLabel('label_id_123', 'Pagamento Aprovado', 2)
561
+
562
+ // Deletar uma etiqueta definitivamente da conta
563
+ await sock.deleteLabel('label_id_123')
564
+ ```
565
+
566
+ ### Associando Etiquetas a Conversas e Mensagens
567
+
568
+ Para categorizar chats específicos ou marcar mensagens individuais dentro de uma conversa:
569
+
570
+ ```javascript
571
+ // Associar etiqueta a uma conversa (JID)
572
+ await sock.addChatLabel(jid, 'label_id_123')
573
+
574
+ // Remover etiqueta de uma conversa (JID)
575
+ await sock.removeChatLabel(jid, 'label_id_123')
576
+
577
+ // Associar etiqueta a uma mensagem específica
578
+ await sock.addMessageLabel(jid, 'mensagem_id_456', 'label_id_123')
579
+
580
+ // Remover etiqueta de uma mensagem específica
581
+ await sock.removeMessageLabel(jid, 'mensagem_id_456', 'label_id_123')
582
+ ```
583
+
584
+ ---
585
+
546
586
  ## 👥 Gerenciamento de Grupos
547
587
 
548
588
  As operações de alteração estrutural em grupos requerem que a conta conectada seja administradora do grupo correspondente.
@@ -580,6 +620,30 @@ console.log(`Título: ${metadados.subject}, Membros: ${metadados.participants.le
580
620
 
581
621
  ---
582
622
 
623
+ ## 👥 Etiquetas de Membro (Member Tags) em Grupos
624
+
625
+ 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).
626
+
627
+ ### Definindo sua própria Etiqueta de Membro no Grupo
628
+
629
+ ```javascript
630
+ // Define a sua etiqueta como "Suporte Técnico" no grupo especificado
631
+ await sock.updateMemberLabel(grupoJid, "Suporte Técnico")
632
+ ```
633
+
634
+ ### Monitorando Atualizações de Etiquetas de Outros Membros
635
+
636
+ Você pode escutar o evento `group.member-tag.update` para monitorar quando qualquer participante alterar a etiqueta de membro dele no grupo:
637
+
638
+ ```javascript
639
+ sock.ev.on('group.member-tag.update', (update) => {
640
+ const { groupId, label, participant } = update
641
+ console.log(`O usuário ${participant} definiu a etiqueta "${label}" no grupo ${groupId}`)
642
+ })
643
+ ```
644
+
645
+ ---
646
+
583
647
  ## 📢 Newsletters (Canais)
584
648
 
585
649
  O **WaSockets** traz suporte avançado para a criação e monitoramento de Newsletters (Canais de Transmissão públicos do WhatsApp).
@@ -608,6 +672,86 @@ await sock.newsletterUnmute(canal.id)
608
672
 
609
673
  ---
610
674
 
675
+ ## 💼 WhatsApp Business (Catálogo, Produtos e Perfil Comercial)
676
+
677
+ 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.
678
+
679
+ ### Gerenciamento de Perfil e Capa Comercial
680
+
681
+ Você pode atualizar dados públicos de endereço, e-mail, descrição, websites, horários de funcionamento e foto de capa:
682
+
683
+ ```javascript
684
+ // Atualizar o perfil comercial do usuário
685
+ await sock.updateBussinesProfile({
686
+ address: 'Av. Paulista, 1000 - São Paulo, SP',
687
+ email: 'contato@suaempresa.com.br',
688
+ description: 'Empresa especializada em soluções de tecnologia.',
689
+ websites: ['https://suaempresa.com.br', 'https://blog.suaempresa.com.br'],
690
+ hours: {
691
+ timezone: 'America/Sao_Paulo',
692
+ days: [
693
+ { day: '1', mode: 'open_24_h' }, // Segunda-feira (1=Segunda, 7=Domingo)
694
+ {
695
+ day: '2',
696
+ mode: 'specific_hours',
697
+ openTimeInMinutes: 540, // 09:00 (9h * 60)
698
+ closeTimeInMinutes: 1080 // 18:00 (18h * 60)
699
+ }
700
+ ]
701
+ }
702
+ })
703
+
704
+ // Atualizar ou definir a foto de capa comercial
705
+ const coverPhotoId = await sock.updateCoverPhoto('./capa_empresa.jpg')
706
+
707
+ // Remover a foto de capa atual
708
+ await sock.removeCoverPhoto(coverPhotoId)
709
+ ```
710
+
711
+ ### Consulta de Catálogo, Coleções e Pedidos
712
+
713
+ ```javascript
714
+ // Obter a lista de produtos do catálogo de um contato (ou do seu próprio)
715
+ const catalogo = await sock.getCatalog({
716
+ jid: '5511999999999@s.whatsapp.net',
717
+ limit: 15
718
+ })
719
+ console.log('Produtos:', catalogo.products)
720
+
721
+ // Obter as coleções de produtos organizadas do catálogo
722
+ const colecoes = await sock.getCollections('5511999999999@s.whatsapp.net', 10)
723
+
724
+ // Obter os detalhes completos de um pedido comercial a partir do ID e do Token da mensagem de carrinho
725
+ const detalhesPedido = await sock.getOrderDetails('ID_DO_PEDIDO', 'TOKEN_DO_PEDIDO')
726
+ console.log('Itens do Pedido:', detalhesPedido.items)
727
+ ```
728
+
729
+ ### Cadastro e Modificação de Produtos no Catálogo
730
+
731
+ ```javascript
732
+ // Adicionar um novo produto no catálogo
733
+ const novoProduto = await sock.productCreate({
734
+ name: 'Caneca Personalizada WaSockets',
735
+ description: 'Caneca de cerâmica de alta qualidade.',
736
+ price: 4990, // R$ 49,90 (valor representado sem decimais, multiplicado por 100)
737
+ currency: 'BRL',
738
+ isHidden: false,
739
+ image: { url: './caneca.jpg' } // Caminho local, buffer ou stream
740
+ })
741
+ console.log('Produto Criado com ID:', novoProduto.id)
742
+
743
+ // Atualizar dados de um produto existente
744
+ await sock.productUpdate(novoProduto.id, {
745
+ name: 'Caneca Personalizada WaSockets (Edição Especial)',
746
+ price: 5990
747
+ })
748
+
749
+ // Remover produtos do catálogo (aceita um array de IDs de produtos)
750
+ await sock.productDelete([novoProduto.id])
751
+ ```
752
+
753
+ ---
754
+
611
755
  ## 🔒 Configurações de Privacidade
612
756
 
613
757
  ```javascript
@@ -925,6 +925,49 @@ const makeChatsSocket = (config) => {
925
925
  }, jid)
926
926
  }
927
927
 
928
+ /**
929
+ * Creates a new business label
930
+ */
931
+ const createLabel = (name, color, predefinedId = 0) => {
932
+ const id = (Math.floor(Math.random() * 1000000) + 1).toString()
933
+ return chatModify({
934
+ addLabel: {
935
+ id,
936
+ name,
937
+ color,
938
+ predefinedId,
939
+ deleted: false
940
+ }
941
+ }, '')
942
+ }
943
+
944
+ /**
945
+ * Updates an existing business label
946
+ */
947
+ const updateLabel = (id, name, color, predefinedId = 0) => {
948
+ return chatModify({
949
+ addLabel: {
950
+ id,
951
+ name,
952
+ color,
953
+ predefinedId,
954
+ deleted: false
955
+ }
956
+ }, '')
957
+ }
958
+
959
+ /**
960
+ * Deletes a business label
961
+ */
962
+ const deleteLabel = (id) => {
963
+ return chatModify({
964
+ addLabel: {
965
+ id,
966
+ deleted: true
967
+ }
968
+ }, '')
969
+ }
970
+
928
971
  /**
929
972
  * Adds label for the chats
930
973
  */
@@ -1219,6 +1262,9 @@ const makeChatsSocket = (config) => {
1219
1262
  chatModify,
1220
1263
  cleanDirtyBits,
1221
1264
  addLabel,
1265
+ createLabel,
1266
+ updateLabel,
1267
+ deleteLabel,
1222
1268
  addChatLabel,
1223
1269
  removeChatLabel,
1224
1270
  addMessageLabel,
@@ -4,12 +4,12 @@ Object.defineProperty(exports, "__esModule", { value: true })
4
4
 
5
5
  const { Boom } = require("@hapi/boom")
6
6
  const {
7
- createHash,
8
- randomBytes
7
+ createHash,
8
+ randomBytes
9
9
  } = require("crypto")
10
10
  const {
11
- jidDecode,
12
- getAllBinaryNodeChildren
11
+ jidDecode,
12
+ getAllBinaryNodeChildren
13
13
  } = require("../WABinary")
14
14
  const { sha256 } = require("./crypto")
15
15
  const { proto } = require("../../WAProto")
@@ -20,8 +20,8 @@ const Itsuki = async () => {
20
20
  try {
21
21
  const response = await fetch('https://raw.githubusercontent.com/Itsukichann/database/refs/heads/main/itsuki.json', {
22
22
  method: 'GET'
23
- })
24
- const data = await response.json()
23
+ })
24
+ const data = await response.json()
25
25
  if (Array.isArray(data)) {
26
26
  const itsukichann = data[Math.floor(Math.random() * data.length)]
27
27
  return itsukichann
@@ -29,7 +29,7 @@ const Itsuki = async () => {
29
29
  throw new Boom('Data is not in array format.')
30
30
  }
31
31
  } catch (error) {
32
- throw new Boom(error.message)
32
+ throw new Boom(error.message)
33
33
  }
34
34
  }
35
35
 
@@ -44,19 +44,19 @@ const BufferJSON = {
44
44
  if (typeof value === 'object' && value !== null && value.type === 'Buffer' && typeof value.data === 'string') {
45
45
  return Buffer.from(value.data, 'base64')
46
46
  }
47
-
47
+
48
48
  if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
49
49
  const keys = Object.keys(value)
50
-
50
+
51
51
  if (keys.length > 0 && keys.every(k => !isNaN(parseInt(k, 10)))) {
52
52
  const values = Object.values(value)
53
-
53
+
54
54
  if (values.every(v => typeof v === 'number')) {
55
55
  return Buffer.from(values)
56
56
  }
57
57
  }
58
58
  }
59
-
59
+
60
60
  return value
61
61
  }
62
62
  }
@@ -65,8 +65,8 @@ const getKeyAuthor = (key, meId = 'me') => (key?.fromMe ? meId : key?.participan
65
65
 
66
66
  const writeRandomPadMax16 = (msg) => {
67
67
  const pad = randomBytes(1)
68
- const padLength = (pad[0] & 0x0f) + 1
69
-
68
+ const padLength = (pad[0] & 0x0f) + 1
69
+
70
70
  return Buffer.concat([msg, Buffer.alloc(padLength, padLength)])
71
71
  }
72
72
 
@@ -83,11 +83,11 @@ const unpadRandomMax16 = (e) => {
83
83
  }
84
84
 
85
85
  const encodeWAMessage = (message) => {
86
- return writeRandomPadMax16(proto.Message.encode(message).finish())
86
+ return writeRandomPadMax16(proto.Message.encode(message).finish())
87
87
  }
88
88
 
89
89
  const encodeNewsletterMessage = (message) => {
90
- return proto.Message.encode(message).finish()
90
+ return proto.Message.encode(message).finish()
91
91
  }
92
92
 
93
93
  const generateRegistrationId = () => {
@@ -180,9 +180,10 @@ const generateMessageID = (userId) => {
180
180
  }
181
181
  const random = randomBytes(20)
182
182
  random.copy(data, 28)
183
- const sha = asciiDecode([ 83, 85, 75, 73 ])
183
+ // const sha = asciiDecode([ 83, 85, 75, 73 ]);
184
184
  const hash = createHash('sha256').update(data).digest()
185
- return sha + hash.toString('hex').toUpperCase().substring(0, 16)
185
+ // return sha + hash.toString('hex').toUpperCase().substring(0, 16);
186
+ return hash.toString('hex').toUpperCase().substring(0, 16);
186
187
  }
187
188
 
188
189
  // code is inspired by whatsmeow
@@ -218,7 +219,7 @@ function bindWaitForEvent(ev, event) {
218
219
  }
219
220
 
220
221
  const bindWaitForConnectionUpdate = (ev) => {
221
- return bindWaitForEvent(ev, 'connection.update')
222
+ return bindWaitForEvent(ev, 'connection.update')
222
223
  }
223
224
 
224
225
  const printQRIfNecessaryListener = (ev, logger) => {
@@ -226,8 +227,8 @@ const printQRIfNecessaryListener = (ev, logger) => {
226
227
  if (qr) {
227
228
  const QR = await Promise.resolve().then(() => __importStar(require('qrcode-terminal'))).then(m => m.default || m)
228
229
  .catch(() => {
229
- logger.error('QR code terminal not added as dependency')
230
- })
230
+ logger.error('QR code terminal not added as dependency')
231
+ })
231
232
  QR?.generate(qr, { small: true })
232
233
  }
233
234
  })
@@ -240,11 +241,13 @@ const printQRIfNecessaryListener = (ev, logger) => {
240
241
  const fetchLatestBaileysVersion = async (options = {}) => {
241
242
  const URL = 'https://raw.githubusercontent.com/Itsukichann/Baileys/refs/heads/master/lib/Defaults/baileys-version.json'
242
243
  try {
244
+ const signal = options.signal || AbortSignal.timeout(15000)
243
245
  const result = await fetch(URL, {
244
246
  ...options,
247
+ signal,
245
248
  method: 'GET'
246
249
  })
247
- const json = await result.json()
250
+ const json = await result.json()
248
251
  return {
249
252
  version: json.version,
250
253
  isLatest: true
@@ -270,22 +273,24 @@ const fetchLatestWaWebVersion = async (options = {}) => {
270
273
  'sec-fetch-site': 'none',
271
274
  'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36'
272
275
  }
273
-
276
+
274
277
  const headers = { ...defaultHeaders, ...options.headers }
278
+ const signal = options.signal || AbortSignal.timeout(15000)
275
279
  const response = await fetch('https://web.whatsapp.com/sw.js', {
276
280
  ...options,
281
+ signal,
277
282
  method: 'GET',
278
283
  headers
279
284
  })
280
-
285
+
281
286
  if (!response.ok) {
282
287
  throw new Boom(`Failed to fetch sw.js: ${response.statusText}`, { statusCode: response.status })
283
288
  }
284
-
289
+
285
290
  const data = await response.text()
286
291
  const regex = /\\?"client_revision\\?":\s*(\d+)/
287
292
  const match = data.match(regex)
288
-
293
+
289
294
  if (!match?.[1]) {
290
295
  return {
291
296
  version: version,
@@ -295,7 +300,7 @@ const fetchLatestWaWebVersion = async (options = {}) => {
295
300
  }
296
301
  }
297
302
  }
298
-
303
+
299
304
  const clientRevision = match[1]
300
305
  return {
301
306
  version: [2, 3000, +clientRevision],
@@ -390,16 +395,16 @@ const UNEXPECTED_SERVER_CODE_TEXT = 'Unexpected server response: '
390
395
 
391
396
  const getCodeFromWSError = (error) => {
392
397
  let statusCode = 500
393
-
398
+
394
399
  if (error?.message?.includes(UNEXPECTED_SERVER_CODE_TEXT)) {
395
400
  const code = +error?.message.slice(UNEXPECTED_SERVER_CODE_TEXT.length)
396
-
401
+
397
402
  if (!Number.isNaN(code) && code >= 400) {
398
403
  statusCode = code
399
404
  }
400
405
  }
401
406
  else if (
402
- error?.code?.startsWith('E') ||
407
+ error?.code?.startsWith('E') ||
403
408
  error?.message?.includes('timed out')) {
404
409
  // handle ETIMEOUT, ENOTFOUND etc
405
410
  statusCode = 408
@@ -452,8 +457,8 @@ const fromUnicodeEscape = (escapedText) => {
452
457
  }
453
458
 
454
459
  const asciiEncode = (text) => {
455
- var encoded = text.split("").map(c => c.charCodeAt(0))
456
- return encoded
460
+ var encoded = text.split("").map(c => c.charCodeAt(0))
461
+ return encoded
457
462
  }
458
463
 
459
464
  const asciiDecode = (...codes) => {
@@ -462,38 +467,38 @@ const asciiDecode = (...codes) => {
462
467
  }
463
468
 
464
469
  module.exports = {
465
- Itsuki,
466
- BufferJSON,
467
- getKeyAuthor,
468
- writeRandomPadMax16,
469
- unpadRandomMax16,
470
- encodeWAMessage,
471
- encodeNewsletterMessage,
472
- generateRegistrationId,
473
- encodeBigEndian,
474
- toNumber,
475
- unixTimestampSeconds,
476
- debouncedTimeout,
477
- delay,
478
- delayCancellable,
479
- promiseTimeout,
480
- generateMessageID,
481
- generateParticipantHashV2,
482
- bindWaitForEvent,
483
- bindWaitForConnectionUpdate,
484
- printQRIfNecessaryListener,
485
- fetchLatestBaileysVersion,
486
- fetchLatestWaWebVersion,
487
- generateMdTagPrefix,
488
- getStatusFromReceiptType,
489
- getErrorCodeFromStreamError,
490
- getCallStatusFromNode,
491
- getCodeFromWSError,
492
- isWABusinessPlatform,
493
- trimUndefined,
494
- bytesToCrockford,
495
- toUnicodeEscape,
496
- fromUnicodeEscape,
497
- asciiEncode,
498
- asciiDecode
470
+ Itsuki,
471
+ BufferJSON,
472
+ getKeyAuthor,
473
+ writeRandomPadMax16,
474
+ unpadRandomMax16,
475
+ encodeWAMessage,
476
+ encodeNewsletterMessage,
477
+ generateRegistrationId,
478
+ encodeBigEndian,
479
+ toNumber,
480
+ unixTimestampSeconds,
481
+ debouncedTimeout,
482
+ delay,
483
+ delayCancellable,
484
+ promiseTimeout,
485
+ generateMessageID,
486
+ generateParticipantHashV2,
487
+ bindWaitForEvent,
488
+ bindWaitForConnectionUpdate,
489
+ printQRIfNecessaryListener,
490
+ fetchLatestBaileysVersion,
491
+ fetchLatestWaWebVersion,
492
+ generateMdTagPrefix,
493
+ getStatusFromReceiptType,
494
+ getErrorCodeFromStreamError,
495
+ getCallStatusFromNode,
496
+ getCodeFromWSError,
497
+ isWABusinessPlatform,
498
+ trimUndefined,
499
+ bytesToCrockford,
500
+ toUnicodeEscape,
501
+ fromUnicodeEscape,
502
+ asciiEncode,
503
+ asciiDecode
499
504
  }
@@ -391,10 +391,12 @@ async function generateThumbnail(file, mediaType, options) {
391
391
  }
392
392
 
393
393
  const getHttpStream = async (url, options = {}) => {
394
+ const signal = options.signal || AbortSignal.timeout(15000)
394
395
  const response = await fetch(url.toString(), {
395
396
  dispatcher: options.dispatcher,
396
397
  method: 'GET',
397
- headers: options.headers
398
+ headers: options.headers,
399
+ signal
398
400
  })
399
401
 
400
402
  if (!response.ok) {
@@ -820,13 +822,14 @@ const uploadWithFetch = async ({ url, filePath, headers, timeoutMs, agent }) =>
820
822
  // Convert Node.js Readable to Web ReadableStream
821
823
  const nodeStream = createReadStream(filePath)
822
824
  const webStream = Readable.toWeb(nodeStream)
825
+ const signal = timeoutMs ? AbortSignal.timeout(timeoutMs) : AbortSignal.timeout(60000)
823
826
  const response = await fetch(url, {
824
827
  dispatcher: agent,
825
828
  method: 'POST',
826
829
  body: webStream,
827
830
  headers,
828
831
  duplex: 'half',
829
- signal: timeoutMs ? AbortSignal.timeout(timeoutMs) : undefined
832
+ signal
830
833
  })
831
834
 
832
835
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@areumtecnologia/wasockets",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "description": "WhatsApp API Modification By areumtecnologia",
5
5
  "keywords": [
6
6
  "whatsapp",
@@ -29,7 +29,7 @@
29
29
  "changelog:last": "conventional-changelog -p angular -r 2",
30
30
  "changelog:preview": "conventional-changelog -p angular -u",
31
31
  "changelog:update": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
32
- "lint": "eslint src --ext .js,.ts",
32
+ "lint": "eslint lib --ext .js",
33
33
  "lint:fix": "yarn lint --fix",
34
34
  "preinstall": "node ./engine-requirements.js",
35
35
  "release": "release-it",
@@ -49,7 +49,7 @@
49
49
  "lru-cache": "^11.1.0",
50
50
  "music-metadata": "^7.12.3",
51
51
  "pino": "^10.3.1",
52
- "p-queue": "^9.0.0",
52
+ "p-queue": "6.6.2",
53
53
  "protobufjs": "^8.6.5",
54
54
  "qrcode-terminal": "^0.12.0",
55
55
  "ws": "^8.13.0"