@natyapp/meta 1.6.7 → 1.7.0

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.
Files changed (89) hide show
  1. package/.github/copilot-instructions.md +1540 -0
  2. package/README.md +122 -1
  3. package/dist/index.d.ts +7 -2
  4. package/dist/index.js +11 -2
  5. package/dist/interfaces/IConnection.d.ts +2 -2
  6. package/dist/interfaces/ILog.d.ts +2 -2
  7. package/dist/interfaces/ILogger.d.ts +62 -0
  8. package/dist/interfaces/ILogger.js +2 -0
  9. package/dist/interfaces/ISdk.d.ts +4 -2
  10. package/dist/interfaces/IWebhook.d.ts +2 -2
  11. package/dist/interfaces/index.d.ts +1 -0
  12. package/dist/interfaces/index.js +1 -0
  13. package/dist/queue/messageQueue.d.ts +1 -1
  14. package/dist/queue/messageQueue.js +45 -0
  15. package/dist/routes/webhooks/methods/connection.js +78 -11
  16. package/dist/routes/webhooks/methods/messages.js +18 -3
  17. package/dist/services/axiosInstances.d.ts +14 -5
  18. package/dist/services/axiosInstances.js +111 -23
  19. package/dist/services/middlewares/validations.d.ts +2 -2
  20. package/dist/services/middlewares/validations.js +1 -2
  21. package/dist/services/mutations/connection.js +1 -1
  22. package/dist/services/mutations/logs.js +1 -1
  23. package/dist/services/mutations/messages.js +1 -1
  24. package/dist/services/mutations/validation.d.ts +1 -1
  25. package/dist/services/mutations/validation.js +1 -1
  26. package/dist/services/mutations/webhooks.js +1 -1
  27. package/dist/types/logs.d.ts +1 -1
  28. package/dist/types/requestTypes.d.ts +2 -0
  29. package/dist/useCases/connection/index.d.ts +9 -9
  30. package/dist/useCases/connection/index.js +156 -7
  31. package/dist/useCases/events/NatyEvents.d.ts +4 -2
  32. package/dist/useCases/events/NatyEvents.js +13 -1
  33. package/dist/useCases/log/index.d.ts +5 -5
  34. package/dist/useCases/log/index.js +65 -3
  35. package/dist/useCases/message/whatsappResponse.d.ts +33 -23
  36. package/dist/useCases/message/whatsappResponse.js +655 -109
  37. package/dist/useCases/messages/index.d.ts +5 -5
  38. package/dist/useCases/messages/index.js +66 -3
  39. package/dist/useCases/sdk/index.d.ts +8 -4
  40. package/dist/useCases/sdk/index.js +38 -6
  41. package/dist/useCases/webhook/index.d.ts +9 -9
  42. package/dist/useCases/webhook/index.js +154 -7
  43. package/dist/utils/consoleLogger.d.ts +20 -0
  44. package/dist/utils/consoleLogger.js +51 -0
  45. package/dist/utils/index.d.ts +6 -0
  46. package/dist/utils/index.js +6 -0
  47. package/dist/utils/loggerContext.d.ts +57 -0
  48. package/dist/utils/loggerContext.js +90 -0
  49. package/dist/utils/methodContext.d.ts +34 -0
  50. package/dist/utils/methodContext.js +48 -0
  51. package/dist/utils/parseError.d.ts +12 -0
  52. package/dist/utils/parseError.js +27 -3
  53. package/dist/utils/pinoAdapter.d.ts +30 -0
  54. package/dist/utils/pinoAdapter.js +68 -0
  55. package/dist/utils/sanitize.d.ts +42 -0
  56. package/dist/utils/sanitize.js +120 -0
  57. package/dist/utils/tryCatch.d.ts +10 -1
  58. package/dist/utils/tryCatch.js +40 -5
  59. package/docs/01-visao-geral.md +355 -0
  60. package/docs/02-contexto-negocio.md +596 -0
  61. package/docs/03-arquitetura.md +925 -0
  62. package/docs/04-fluxos-funcionais.md +887 -0
  63. package/docs/05-integracoes.md +960 -0
  64. package/docs/06-entidades.md +849 -0
  65. package/docs/07-guia-pratico.md +1133 -0
  66. package/docs/08-troubleshooting.md +816 -0
  67. package/docs/README.md +125 -0
  68. package/examples/logger-example.ts +279 -0
  69. package/package.json +2 -2
  70. /package/dist/{Entities → entities}/Logs.d.ts +0 -0
  71. /package/dist/{Entities → entities}/Logs.js +0 -0
  72. /package/dist/{Entities → entities}/connection.d.ts +0 -0
  73. /package/dist/{Entities → entities}/connection.js +0 -0
  74. /package/dist/{Entities → entities}/errorLogs.d.ts +0 -0
  75. /package/dist/{Entities → entities}/errorLogs.js +0 -0
  76. /package/dist/{Entities → entities}/index.d.ts +0 -0
  77. /package/dist/{Entities → entities}/index.js +0 -0
  78. /package/dist/{Entities → entities}/messages.d.ts +0 -0
  79. /package/dist/{Entities → entities}/messages.js +0 -0
  80. /package/dist/{Entities → entities}/webhooks.d.ts +0 -0
  81. /package/dist/{Entities → entities}/webhooks.js +0 -0
  82. /package/dist/{Entities → entities}/whatsappMessage.d.ts +0 -0
  83. /package/dist/{Entities → entities}/whatsappMessage.js +0 -0
  84. /package/dist/{Errors → errors}/Either.d.ts +0 -0
  85. /package/dist/{Errors → errors}/Either.js +0 -0
  86. /package/dist/{Errors → errors}/ErrorHandling.d.ts +0 -0
  87. /package/dist/{Errors → errors}/ErrorHandling.js +0 -0
  88. /package/dist/{Errors → errors}/index.d.ts +0 -0
  89. /package/dist/{Errors → errors}/index.js +0 -0
@@ -0,0 +1,1133 @@
1
+ # 07 - Guia Prático de Uso
2
+
3
+ [⬅️ Voltar ao Índice](README.md)
4
+
5
+ ---
6
+
7
+ ## 📋 Sumário
8
+ - [Setup Inicial](#-setup-inicial)
9
+ - [Exemplos de Envio de Mensagens](#-exemplos-de-envio-de-mensagens)
10
+ - [Exemplos de Recebimento de Mensagens](#-exemplos-de-recebimento-de-mensagens)
11
+ - [Trabalhando com Mídia](#-trabalhando-com-mídia)
12
+ - [Gestão de Conexões](#-gestão-de-conexões)
13
+ - [Gestão de Webhooks](#-gestão-de-webhooks)
14
+ - [Implementando um Chatbot Completo](#-implementando-um-chatbot-completo)
15
+ - [Best Practices](#-best-practices)
16
+
17
+ ---
18
+
19
+ ## 🚀 Setup Inicial
20
+
21
+ ### Passo 1: Instalação
22
+
23
+ ```bash
24
+ # Usando npm
25
+ npm install @natyapp/meta
26
+
27
+ # Usando pnpm
28
+ pnpm add @natyapp/meta
29
+
30
+ # Usando yarn
31
+ yarn add @natyapp/meta
32
+ ```
33
+
34
+ ### Passo 2: Configuração de Variáveis de Ambiente
35
+
36
+ Crie um arquivo `.env` na raiz do projeto:
37
+
38
+ ```env
39
+ # Obrigatório
40
+ API_META=https://api.meta.naty.app/v1
41
+ NATY_APP_TOKEN=seu_app_token_aqui
42
+
43
+ # Opcionais
44
+ NODE_ENV=development
45
+ PORT=3000
46
+ ```
47
+
48
+ **Importante:** Adicione `.env` ao `.gitignore`:
49
+
50
+ ```gitignore
51
+ # .gitignore
52
+ .env
53
+ .env.local
54
+ .env.*.local
55
+ node_modules/
56
+ dist/
57
+ ```
58
+
59
+ ### Passo 3: Estrutura de Projeto Recomendada
60
+
61
+ ```
62
+ my-whatsapp-bot/
63
+ ├── src/
64
+ │ ├── index.ts # Ponto de entrada
65
+ │ ├── sdk.ts # Inicialização do SDK
66
+ │ ├── handlers/ # Handlers de eventos
67
+ │ │ ├── messageHandler.ts
68
+ │ │ └── connectionHandler.ts
69
+ │ ├── services/ # Lógica de negócio
70
+ │ │ ├── chatbotService.ts
71
+ │ │ └── databaseService.ts
72
+ │ └── utils/ # Utilitários
73
+ │ └── logger.ts
74
+ ├── .env
75
+ ├── .gitignore
76
+ ├── package.json
77
+ └── tsconfig.json
78
+ ```
79
+
80
+ ### Passo 4: Inicialização Básica
81
+
82
+ **Arquivo: `src/sdk.ts`**
83
+
84
+ ```typescript
85
+ import { NatyMeta } from '@natyapp/meta';
86
+ import express from 'express';
87
+ import dotenv from 'dotenv';
88
+
89
+ dotenv.config();
90
+
91
+ // Criar instância Express
92
+ const app = express();
93
+ app.use(express.json());
94
+
95
+ // Inicializar SDK
96
+ const sdk = new NatyMeta();
97
+
98
+ export async function initializeSDK() {
99
+ const result = await sdk.connect({
100
+ appToken: process.env.NATY_APP_TOKEN!,
101
+ app: app,
102
+ pathname: '/webhooks'
103
+ });
104
+
105
+ if (result.isLeft()) {
106
+ console.error('Erro ao inicializar SDK:', result.value);
107
+ process.exit(1);
108
+ }
109
+
110
+ console.log('✅ SDK inicializado com sucesso!');
111
+ return sdk;
112
+ }
113
+
114
+ export { sdk, app };
115
+ ```
116
+
117
+ **Arquivo: `src/index.ts`**
118
+
119
+ ```typescript
120
+ import { initializeSDK, app } from './sdk';
121
+ import './handlers/messageHandler'; // Registra listeners
122
+ import './handlers/connectionHandler';
123
+
124
+ async function main() {
125
+ // Inicializar SDK
126
+ await initializeSDK();
127
+
128
+ // Iniciar servidor
129
+ const PORT = process.env.PORT || 3000;
130
+ app.listen(PORT, () => {
131
+ console.log(`🚀 Servidor rodando na porta ${PORT}`);
132
+ console.log(`📥 Webhook: http://localhost:${PORT}/webhooks/messages`);
133
+ });
134
+ }
135
+
136
+ main().catch(console.error);
137
+ ```
138
+
139
+ ### Passo 5: Configuração de Logger (Opcional mas Recomendado)
140
+
141
+ O SDK suporta loggers customizados para melhor observabilidade em produção.
142
+
143
+ #### Usando Pino Logger (Recomendado)
144
+
145
+ **Instalar dependências:**
146
+ ```bash
147
+ npm install pino pino-pretty
148
+ ```
149
+
150
+ **Arquivo: `src/utils/logger.ts`**
151
+
152
+ ```typescript
153
+ import pino from 'pino';
154
+ import { createPinoAdapter } from '@natyapp/meta';
155
+
156
+ export const logger = pino({
157
+ level: process.env.LOG_LEVEL || 'info',
158
+ transport: process.env.NODE_ENV === 'development' ? {
159
+ target: 'pino-pretty',
160
+ options: {
161
+ colorize: true,
162
+ translateTime: 'SYS:HH:MM:ss',
163
+ ignore: 'pid,hostname'
164
+ }
165
+ } : undefined
166
+ });
167
+
168
+ export const sdkLogger = createPinoAdapter(logger);
169
+ ```
170
+
171
+ **Atualizar `src/sdk.ts`:**
172
+
173
+ ```typescript
174
+ import { NatyMeta } from '@natyapp/meta';
175
+ import { sdkLogger, logger } from './utils/logger';
176
+
177
+ const sdk = new NatyMeta({
178
+ logger: sdkLogger // Injeta logger customizado
179
+ });
180
+
181
+ export async function initializeSDK() {
182
+ const result = await sdk.connect({
183
+ appToken: process.env.NATY_APP_TOKEN!,
184
+ app: app,
185
+ pathname: '/webhooks'
186
+ });
187
+
188
+ if (result.isError) {
189
+ logger.error({ error: result.isError }, 'Erro ao inicializar SDK');
190
+ process.exit(1);
191
+ }
192
+
193
+ logger.info('✅ SDK inicializado com sucesso!');
194
+ return sdk;
195
+ }
196
+ ```
197
+
198
+ **Logs disponíveis:**
199
+ - ✅ HTTP requests/responses (nível debug)
200
+ - ✅ Token refresh operations (nível info)
201
+ - ✅ Message sending/receiving (nível info)
202
+ - ✅ Webhook processing (nível info)
203
+ - ✅ Errors with context (nível error)
204
+
205
+ ---
206
+
207
+ ## 📤 Exemplos de Envio de Mensagens
208
+
209
+ ### Exemplo 1: Mensagem de Texto Simples
210
+
211
+ ```typescript
212
+ import { sdk } from './sdk';
213
+
214
+ async function sendTextMessage() {
215
+ const whatsapp = sdk.Message.WhatsappResponse({
216
+ companyId: 'abc123',
217
+ phone_number_id: '123456789012345'
218
+ });
219
+
220
+ const result = await whatsapp.send_text({
221
+ to: '5511999999999',
222
+ message: 'Olá! Bem-vindo ao nosso atendimento.'
223
+ predense: true
224
+ });
225
+
226
+ if (result.isRight()) {
227
+ console.log('Mensagem enviada! ID:', result.value.messages[0].id);
228
+ } else {
229
+ console.error('Erro:', result.value);
230
+ }
231
+ }
232
+ ```
233
+
234
+ ### Exemplo 2: Mensagem com Link Preview
235
+
236
+ ```typescript
237
+ async function sendTextWithPreview() {
238
+ const whatsapp = sdk.Message.WhatsappResponse({
239
+ companyId: 'abc123',
240
+ phone_number_id: '123456789012345'
241
+ });
242
+
243
+ const result = await whatsapp.send_text({
244
+ to: '5511999999999',
245
+ message: 'Confira nosso site: https://www.minhaempresa.com.br',
246
+ preview_url: true // Exibe preview do link
247
+ });
248
+
249
+ if (result.isRight()) {
250
+ console.log('Mensagem com preview enviada!');
251
+ }
252
+ }
253
+ ```
254
+
255
+ ### Exemplo 3: Botões Interativos
256
+
257
+ ```typescript
258
+ import { Button } from '@natyapp/meta';
259
+
260
+ async function sendButtonMessage() {
261
+ const whatsapp = sdk.Message.WhatsappResponse({
262
+ companyId: 'abc123',
263
+ phone_number_id: '123456789012345'
264
+ });
265
+
266
+ // Construir mensagem com botões
267
+ const buttonPayload = new Button()
268
+ .setBody('Como podemos ajudar você hoje?')
269
+ .addButton({ id: 'suporte', title: '💬 Suporte' })
270
+ .addButton({ id: 'vendas', title: '🛒 Vendas' })
271
+ .addButton({ id: 'financeiro', title: '💰 Financeiro' })
272
+ .build();
273
+
274
+ const result = await whatsapp.send_buttons({
275
+ to: '5511999999999',
276
+ ...buttonPayload
277
+ });
278
+
279
+ if (result.isRight()) {
280
+ console.log('Botões enviados!');
281
+ }
282
+ }
283
+ ```
284
+
285
+ ### Exemplo 4: Lista de Opções
286
+
287
+ ```typescript
288
+ import { List } from '@natyapp/meta';
289
+
290
+ async function sendListMessage() {
291
+ const whatsapp = sdk.Message.WhatsappResponse({
292
+ companyId: 'abc123',
293
+ phone_number_id: '123456789012345'
294
+ });
295
+
296
+ // Construir lista com múltiplas seções
297
+ const listPayload = new List()
298
+ .setBody('Confira nossos produtos e serviços:')
299
+ .setButtonText('📋 Ver Opções')
300
+ .addSection('Produtos')
301
+ .addItem({
302
+ id: 'prod_smartphone',
303
+ title: '📱 Smartphones',
304
+ description: 'Últimos modelos disponíveis'
305
+ })
306
+ .addItem({
307
+ id: 'prod_notebook',
308
+ title: '💻 Notebooks',
309
+ description: 'Alta performance'
310
+ })
311
+ .addSection('Serviços')
312
+ .addItem({
313
+ id: 'serv_suporte',
314
+ title: '🔧 Suporte Técnico',
315
+ description: 'Atendimento especializado'
316
+ })
317
+ .addItem({
318
+ id: 'serv_garantia',
319
+ title: '🛡️ Garantia Estendida',
320
+ description: 'Proteção completa'
321
+ })
322
+ .build();
323
+
324
+ const result = await whatsapp.send_list({
325
+ to: '5511999999999',
326
+ ...listPayload
327
+ });
328
+
329
+ if (result.isRight()) {
330
+ console.log('Lista enviada!');
331
+ }
332
+ }
333
+ ```
334
+
335
+ ### Exemplo 5: Imagem com Legenda
336
+
337
+ ```typescript
338
+ async function sendImageMessage() {
339
+ const whatsapp = sdk.Message.WhatsappResponse({
340
+ companyId: 'abc123',
341
+ phone_number_id: '123456789012345'
342
+ });
343
+
344
+ const result = await whatsapp.send_image({
345
+ to: '5511999999999',
346
+ url: 'https://exemplo.com/produtos/smartphone.jpg',
347
+ caption: '📱 Novo Smartphone X Pro - Disponível agora!'
348
+ });
349
+
350
+ if (result.isRight()) {
351
+ console.log('Imagem enviada!');
352
+ }
353
+ }
354
+ ```
355
+
356
+ ### Exemplo 6: Vídeo
357
+
358
+ ```typescript
359
+ async function sendVideoMessage() {
360
+ const whatsapp = sdk.Message.WhatsappResponse({
361
+ companyId: 'abc123',
362
+ phone_number_id: '123456789012345'
363
+ });
364
+
365
+ const result = await whatsapp.send_video({
366
+ to: '5511999999999',
367
+ url: 'https://exemplo.com/videos/tutorial.mp4',
368
+ caption: '🎥 Tutorial: Como usar nosso produto'
369
+ });
370
+
371
+ if (result.isRight()) {
372
+ console.log('Vídeo enviado!');
373
+ }
374
+ }
375
+ ```
376
+
377
+ ### Exemplo 7: Documento PDF
378
+
379
+ ```typescript
380
+ async function sendDocumentMessage() {
381
+ const whatsapp = sdk.Message.WhatsappResponse({
382
+ companyId: 'abc123',
383
+ phone_number_id: '123456789012345'
384
+ });
385
+
386
+ const result = await whatsapp.send_document({
387
+ to: '5511999999999',
388
+ url: 'https://exemplo.com/documentos/catalogo.pdf',
389
+ filename: 'Catálogo_2026.pdf',
390
+ caption: '📄 Catálogo completo de produtos'
391
+ });
392
+
393
+ if (result.isRight()) {
394
+ console.log('Documento enviado!');
395
+ }
396
+ }
397
+ ```
398
+
399
+ ### Exemplo 8: Localização
400
+
401
+ ```typescript
402
+ async function sendLocationMessage() {
403
+ const whatsapp = sdk.Message.WhatsappResponse({
404
+ companyId: 'abc123',
405
+ phone_number_id: '123456789012345'
406
+ });
407
+
408
+ const result = await whatsapp.send_location({
409
+ to: '5511999999999',
410
+ latitude: -23.5505199,
411
+ longitude: -46.6333094,
412
+ name: 'Minha Empresa LTDA',
413
+ address: 'Av. Paulista, 1000 - São Paulo, SP'
414
+ });
415
+
416
+ if (result.isRight()) {
417
+ console.log('Localização enviada!');
418
+ }
419
+ }
420
+ ```
421
+
422
+ ### Exemplo 9: Template Aprovado
423
+
424
+ ```typescript
425
+ async function sendTemplateMessage() {
426
+ const whatsapp = sdk.Message.WhatsappResponse({
427
+ companyId: 'abc123',
428
+ phone_number_id: '123456789012345'
429
+ });
430
+
431
+ const result = await whatsapp.send_text_template({
432
+ to: '5511999999999',
433
+ template: {
434
+ name: 'confirmacao_pedido', // Nome do template aprovado pela Meta
435
+ language: 'pt_BR',
436
+ components: [
437
+ {
438
+ type: 'body',
439
+ parameters: [
440
+ { type: 'text', text: 'João Silva' }, // {{1}}
441
+ { type: 'text', text: '#12345' }, // {{2}}
442
+ { type: 'text', text: 'R$ 250,00' } // {{3}}
443
+ ]
444
+ }
445
+ ]
446
+ }
447
+ });
448
+
449
+ if (result.isRight()) {
450
+ console.log('Template enviado!');
451
+ }
452
+ }
453
+ ```
454
+
455
+ ### Exemplo 10: Marcar como Lido
456
+
457
+ ```typescript
458
+ async function markAsRead(messageId: string) {
459
+ const whatsapp = sdk.Message.WhatsappResponse({
460
+ companyId: 'abc123',
461
+ phone_number_id: '123456789012345'
462
+ });
463
+
464
+ const result = await whatsapp.mark_as_read(messageId);
465
+
466
+ if (result.isRight()) {
467
+ console.log('Mensagem marcada como lida!');
468
+ }
469
+ }
470
+ ```
471
+
472
+ ---
473
+
474
+ ## 📥 Exemplos de Recebimento de Mensagens
475
+
476
+ ### Exemplo 1: Handler Básico
477
+
478
+ **Arquivo: `src/handlers/messageHandler.ts`**
479
+
480
+ ```typescript
481
+ import { sdk } from '../sdk';
482
+
483
+ sdk.on('message', async (data) => {
484
+ console.log('=== Nova Mensagem ===');
485
+ console.log('De:', data.sender);
486
+ console.log('Tipo:', data.message.type);
487
+ console.log('Mensagem:', data.message);
488
+
489
+ // Responder automaticamente
490
+ await data.whatsappResponse.send_text({
491
+ to: data.sender,
492
+ message: 'Mensagem recebida! Em breve responderemos.'
493
+ });
494
+ });
495
+ ```
496
+
497
+ ### Exemplo 2: Processamento por Tipo de Mensagem
498
+
499
+ ```typescript
500
+ import { sdk } from '../sdk';
501
+
502
+ sdk.on('message', async (data) => {
503
+ const { message, sender, whatsappResponse } = data;
504
+
505
+ switch (message.type) {
506
+ case 'text':
507
+ await handleTextMessage(message.text.body, sender, whatsappResponse);
508
+ break;
509
+
510
+ case 'image':
511
+ await handleImageMessage(message.image, sender, whatsappResponse);
512
+ break;
513
+
514
+ case 'interactive':
515
+ await handleInteractiveMessage(message.interactive, sender, whatsappResponse);
516
+ break;
517
+
518
+ default:
519
+ console.log(`Tipo não tratado: ${message.type}`);
520
+ }
521
+ });
522
+
523
+ async function handleTextMessage(text: string, sender: string, whatsapp: any) {
524
+ console.log(`Texto recebido: "${text}"`);
525
+
526
+ const lowerText = text.toLowerCase();
527
+
528
+ if (lowerText.includes('oi') || lowerText.includes('olá')) {
529
+ await whatsapp.send_text({
530
+ to: sender,
531
+ message: 'Olá! Bem-vindo. Como posso ajudar?'
532
+ });
533
+ } else if (lowerText.includes('preço') || lowerText.includes('valor')) {
534
+ await whatsapp.send_text({
535
+ to: sender,
536
+ message: 'Para consultar preços, digite CATALOGO.'
537
+ });
538
+ }
539
+ }
540
+
541
+ async function handleImageMessage(image: any, sender: string, whatsapp: any) {
542
+ console.log(`Imagem recebida: ${image.id}`);
543
+
544
+ // Download automático
545
+ const downloadResult = await whatsapp.download_media(image.id);
546
+
547
+ if (downloadResult.isRight()) {
548
+ console.log('Imagem baixada com sucesso!');
549
+ // Processar imagem (ex: análise, OCR, salvar em disco)
550
+ }
551
+
552
+ await whatsapp.send_text({
553
+ to: sender,
554
+ message: 'Imagem recebida! Estamos analisando.'
555
+ });
556
+ }
557
+
558
+ async function handleInteractiveMessage(interactive: any, sender: string, whatsapp: any) {
559
+ const buttonId = interactive.button_reply?.id || interactive.list_reply?.id;
560
+
561
+ console.log(`Botão/Item selecionado: ${buttonId}`);
562
+
563
+ // Processar seleção
564
+ switch (buttonId) {
565
+ case 'suporte':
566
+ await whatsapp.send_text({
567
+ to: sender,
568
+ message: 'Você foi direcionado para o suporte. Aguarde...'
569
+ });
570
+ break;
571
+
572
+ case 'vendas':
573
+ await whatsapp.send_text({
574
+ to: sender,
575
+ message: 'Equipe de vendas: (11) 99999-9999'
576
+ });
577
+ break;
578
+ }
579
+ }
580
+ ```
581
+
582
+ ### Exemplo 3: Sistema de Contextos/Conversação
583
+
584
+ ```typescript
585
+ import { sdk } from '../sdk';
586
+
587
+ // Armazenar contextos de conversação
588
+ const userContexts = new Map<string, ConversationContext>();
589
+
590
+ interface ConversationContext {
591
+ state: string;
592
+ data: Record<string, any>;
593
+ lastInteraction: Date;
594
+ }
595
+
596
+ sdk.on('message', async (data) => {
597
+ const { sender, message, whatsappResponse } = data;
598
+
599
+ // Obter ou criar contexto
600
+ let context = userContexts.get(sender);
601
+ if (!context) {
602
+ context = {
603
+ state: 'initial',
604
+ data: {},
605
+ lastInteraction: new Date()
606
+ };
607
+ userContexts.set(sender, context);
608
+ }
609
+
610
+ // Atualizar last interaction
611
+ context.lastInteraction = new Date();
612
+
613
+ // Processar baseado no estado
614
+ await processConversation(context, message, sender, whatsappResponse);
615
+ });
616
+
617
+ async function processConversation(
618
+ context: ConversationContext,
619
+ message: any,
620
+ sender: string,
621
+ whatsapp: any
622
+ ) {
623
+ const text = message.text?.body.toLowerCase() || '';
624
+
625
+ switch (context.state) {
626
+ case 'initial':
627
+ await whatsapp.send_text({
628
+ to: sender,
629
+ message: 'Olá! Para começar, qual é o seu nome?'
630
+ });
631
+ context.state = 'collecting_name';
632
+ break;
633
+
634
+ case 'collecting_name':
635
+ context.data.name = message.text.body;
636
+ await whatsapp.send_text({
637
+ to: sender,
638
+ message: `Prazer, ${context.data.name}! Qual é o seu email?`
639
+ });
640
+ context.state = 'collecting_email';
641
+ break;
642
+
643
+ case 'collecting_email':
644
+ context.data.email = message.text.body;
645
+ await whatsapp.send_text({
646
+ to: sender,
647
+ message: `Perfeito! Seu cadastro foi completo.\n\nNome: ${context.data.name}\nEmail: ${context.data.email}`
648
+ });
649
+
650
+ // Salvar no banco de dados
651
+ await saveUserToDatabase(context.data);
652
+
653
+ // Resetar contexto
654
+ userContexts.delete(sender);
655
+ break;
656
+ }
657
+ }
658
+
659
+ async function saveUserToDatabase(data: any) {
660
+ console.log('Salvando usuário:', data);
661
+ // Implementar lógica de salvamento
662
+ }
663
+
664
+ // Limpar contextos antigos a cada 30 minutos
665
+ setInterval(() => {
666
+ const now = new Date();
667
+ for (const [sender, context] of userContexts.entries()) {
668
+ const diffMinutes = (now.getTime() - context.lastInteraction.getTime()) / 1000 / 60;
669
+ if (diffMinutes > 30) {
670
+ userContexts.delete(sender);
671
+ console.log(`Contexto expirado para ${sender}`);
672
+ }
673
+ }
674
+ }, 30 * 60 * 1000);
675
+ ```
676
+
677
+ ---
678
+
679
+ ## 🎞 Trabalhando com Mídia
680
+
681
+ ### Upload de Arquivo Local
682
+
683
+ ```typescript
684
+ import fs from 'fs';
685
+ import { sdk } from './sdk';
686
+
687
+ async function uploadLocalFile() {
688
+ const whatsapp = sdk.Message.WhatsappResponse({
689
+ companyId: 'abc123',
690
+ phone_number_id: '123456789012345'
691
+ });
692
+
693
+ // Criar stream de leitura
694
+ const stream = fs.createReadStream('./assets/product.jpg');
695
+
696
+ // Upload
697
+ const uploadResult = await whatsapp.createMedia(stream);
698
+
699
+ if (uploadResult.isRight()) {
700
+ const mediaId = uploadResult.value.id;
701
+ console.log('Upload concluído! Media ID:', mediaId);
702
+
703
+ // Enviar usando media_id
704
+ const sendResult = await whatsapp.send_image({
705
+ to: '5511999999999',
706
+ media_id: mediaId,
707
+ caption: 'Produto em destaque!'
708
+ });
709
+
710
+ if (sendResult.isRight()) {
711
+ console.log('Imagem enviada!');
712
+ }
713
+ }
714
+ }
715
+ ```
716
+
717
+ ### Download de Mídia Recebida
718
+
719
+ ```typescript
720
+ import fs from 'fs';
721
+ import { sdk } from './sdk';
722
+
723
+ sdk.on('message', async (data) => {
724
+ if (data.message.type === 'image') {
725
+ const mediaId = data.message.image.id;
726
+
727
+ // Download como buffer
728
+ const downloadResult = await data.whatsappResponse.download_media(mediaId);
729
+
730
+ if (downloadResult.isRight()) {
731
+ const imageBuffer = downloadResult.value;
732
+
733
+ // Salvar em disco
734
+ const filename = `./downloads/${Date.now()}_${mediaId}.jpg`;
735
+ fs.writeFileSync(filename, imageBuffer);
736
+ console.log(`Imagem salva em: ${filename}`);
737
+
738
+ // Ou processar diretamente
739
+ await processImage(imageBuffer);
740
+ }
741
+ }
742
+ });
743
+
744
+ async function processImage(buffer: Buffer) {
745
+ // Exemplo: Análise com IA, OCR, etc.
746
+ console.log(`Processando imagem de ${buffer.length} bytes`);
747
+ }
748
+ ```
749
+
750
+ ---
751
+
752
+ ## 🔧 Gestão de Conexões
753
+
754
+ ### Criar Nova Conexão
755
+
756
+ ```typescript
757
+ import { sdk } from './sdk';
758
+
759
+ async function createNewConnection() {
760
+ const result = await sdk.Connection.create({
761
+ companyId: 'abc123',
762
+ phoneNumberId: '123456789012345',
763
+ phoneNumber: '+5511999999999',
764
+ accessToken: 'EAAxxxxxxxxxxxxxxxxx',
765
+ appId: '123456789',
766
+ appSecret: 'abcdef1234567890',
767
+ accountId: '987654321',
768
+ businessId: '456789123'
769
+ });
770
+
771
+ if (result.isRight()) {
772
+ console.log('Conexão criada:', result.value);
773
+ } else {
774
+ console.error('Erro ao criar conexão:', result.value);
775
+ }
776
+ }
777
+ ```
778
+
779
+ ### Buscar Conexão
780
+
781
+ ```typescript
782
+ async function getConnectionInfo() {
783
+ const result = await sdk.Connection.get({
784
+ companyId: 'abc123',
785
+ phoneNumberId: '123456789012345'
786
+ });
787
+
788
+ if (result.isRight()) {
789
+ const connection = result.value;
790
+ console.log('Conexão encontrada:');
791
+ console.log('ID:', connection.id);
792
+ console.log('Número:', connection.phoneNumber);
793
+ console.log('Ativa:', connection.isActive);
794
+ }
795
+ }
796
+ ```
797
+
798
+ ### Atualizar Token
799
+
800
+ ```typescript
801
+ async function updateConnectionToken(connectionId: string, newToken: string) {
802
+ const result = await sdk.Connection.update(connectionId, {
803
+ accessToken: newToken
804
+ });
805
+
806
+ if (result.isRight()) {
807
+ console.log('Token atualizado com sucesso!');
808
+ }
809
+ }
810
+ ```
811
+
812
+ ### Listar Todas as Conexões
813
+
814
+ ```typescript
815
+ async function listAllConnections(companyId: string) {
816
+ const result = await sdk.Connection.list({ companyId });
817
+
818
+ if (result.isRight()) {
819
+ const connections = result.value;
820
+ console.log(`Total de conexões: ${connections.length}`);
821
+
822
+ connections.forEach(conn => {
823
+ console.log(`- ${conn.phoneNumber} (${conn.isActive ? 'Ativa' : 'Inativa'})`);
824
+ });
825
+ }
826
+ }
827
+ ```
828
+
829
+ ---
830
+
831
+ ## 🪝 Gestão de Webhooks
832
+
833
+ ### Configurar Webhooks
834
+
835
+ ```typescript
836
+ import { sdk } from './sdk';
837
+
838
+ async function setupWebhooks() {
839
+ const result = await sdk.Webhook.create({
840
+ companyId: 'abc123',
841
+ connection: {
842
+ url: 'https://meuapp.com/webhooks/connections',
843
+ active: true
844
+ },
845
+ messages: {
846
+ url: 'https://meuapp.com/webhooks/messages',
847
+ active: true
848
+ }
849
+ });
850
+
851
+ if (result.isRight()) {
852
+ console.log('Webhooks configurados:', result.value);
853
+ }
854
+ }
855
+ ```
856
+
857
+ ### Desativar Webhook Temporariamente
858
+
859
+ ```typescript
860
+ async function disableMessageWebhook(webhookId: string) {
861
+ const result = await sdk.Webhook.update(webhookId, {
862
+ messages: {
863
+ url: 'https://meuapp.com/webhooks/messages',
864
+ active: false // Desativa
865
+ }
866
+ });
867
+
868
+ if (result.isRight()) {
869
+ console.log('Webhook de mensagens desativado');
870
+ }
871
+ }
872
+ ```
873
+
874
+ ---
875
+
876
+ ## 🤖 Implementando um Chatbot Completo
877
+
878
+ ### Chatbot com IA (Exemplo Completo)
879
+
880
+ ```typescript
881
+ import { sdk } from './sdk';
882
+ import { Button, List } from '@natyapp/meta';
883
+
884
+ // Simulação de serviço de IA
885
+ async function getAIResponse(userMessage: string): Promise<string> {
886
+ // Aqui você integraria com OpenAI, DialogFlow, etc.
887
+ const responses: Record<string, string> = {
888
+ 'horário': 'Atendemos de segunda a sexta, das 9h às 18h.',
889
+ 'preço': 'Nossos produtos variam de R$ 50 a R$ 5.000.',
890
+ 'entrega': 'Entregamos em todo o Brasil em até 7 dias úteis.',
891
+ };
892
+
893
+ for (const [key, response] of Object.entries(responses)) {
894
+ if (userMessage.toLowerCase().includes(key)) {
895
+ return response;
896
+ }
897
+ }
898
+
899
+ return 'Desculpe, não entendi. Digite MENU para ver as opções disponíveis.';
900
+ }
901
+
902
+ // Handler principal
903
+ sdk.on('message', async (data) => {
904
+ const { sender, message, whatsappResponse } = data;
905
+
906
+ // Logs
907
+ console.log(`[${new Date().toISOString()}] Mensagem de ${sender}`);
908
+
909
+ // Processar por tipo
910
+ if (message.type === 'text') {
911
+ const userText = message.text.body.trim();
912
+
913
+ // Comandos especiais
914
+ if (userText.toUpperCase() === 'MENU') {
915
+ await sendMainMenu(sender, whatsappResponse);
916
+ return;
917
+ }
918
+
919
+ if (userText.toUpperCase() === 'CATALOGO') {
920
+ await sendCatalog(sender, whatsappResponse);
921
+ return;
922
+ }
923
+
924
+ // Processar com IA
925
+ const aiResponse = await getAIResponse(userText);
926
+ await whatsappResponse.send_text({
927
+ to: sender,
928
+ message: aiResponse
929
+ });
930
+
931
+ } else if (message.type === 'interactive') {
932
+ await handleInteractiveSelection(message.interactive, sender, whatsappResponse);
933
+ }
934
+
935
+ // Marcar como lido
936
+ await whatsappResponse.mark_as_read(message.id);
937
+ });
938
+
939
+ async function sendMainMenu(to: string, whatsapp: any) {
940
+ const buttons = new Button()
941
+ .setBody('🏠 *Menu Principal*\n\nEscolha uma opção:')
942
+ .addButton({ id: 'products', title: '🛍️ Produtos' })
943
+ .addButton({ id: 'support', title: '💬 Suporte' })
944
+ .addButton({ id: 'about', title: 'ℹ️ Sobre Nós' })
945
+ .build();
946
+
947
+ await whatsapp.send_buttons({ to, ...buttons });
948
+ }
949
+
950
+ async function sendCatalog(to: string, whatsapp: any) {
951
+ const list = new List()
952
+ .setBody('📱 *Catálogo de Produtos*\n\nSelecione uma categoria:')
953
+ .setButtonText('Ver Catálogo')
954
+ .addSection('Eletrônicos')
955
+ .addItem({ id: 'cat_smartphones', title: 'Smartphones', description: 'Últimos modelos' })
956
+ .addItem({ id: 'cat_notebooks', title: 'Notebooks', description: 'Alta performance' })
957
+ .addSection('Acessórios')
958
+ .addItem({ id: 'cat_fones', title: 'Fones de Ouvido', description: 'Som premium' })
959
+ .addItem({ id: 'cat_capas', title: 'Capas e Películas', description: 'Proteção total' })
960
+ .build();
961
+
962
+ await whatsapp.send_list({ to, ...list });
963
+ }
964
+
965
+ async function handleInteractiveSelection(interactive: any, sender: string, whatsapp: any) {
966
+ const selectedId = interactive.button_reply?.id || interactive.list_reply?.id;
967
+
968
+ console.log(`Usuário selecionou: ${selectedId}`);
969
+
970
+ switch (selectedId) {
971
+ case 'products':
972
+ await sendCatalog(sender, whatsapp);
973
+ break;
974
+
975
+ case 'support':
976
+ await whatsapp.send_text({
977
+ to: sender,
978
+ message: '💬 *Suporte*\n\nWhatsApp: (11) 99999-9999\nEmail: suporte@empresa.com\nHorário: Seg-Sex, 9h-18h'
979
+ });
980
+ break;
981
+
982
+ case 'about':
983
+ await whatsapp.send_text({
984
+ to: sender,
985
+ message: 'ℹ️ *Sobre Nós*\n\nSomos uma empresa especializada em tecnologia desde 2020.\n\nMissão: Levar tecnologia de qualidade a todos.'
986
+ });
987
+ break;
988
+
989
+ case 'cat_smartphones':
990
+ await whatsapp.send_text({
991
+ to: sender,
992
+ message: '📱 *Smartphones*\n\n1. iPhone 14 Pro - R$ 7.999\n2. Samsung S23 - R$ 5.499\n3. Xiaomi 13 - R$ 3.999\n\nPara mais info, digite o número do produto.'
993
+ });
994
+ break;
995
+ }
996
+ }
997
+ ```
998
+
999
+ ---
1000
+
1001
+ ## ✅ Best Practices
1002
+
1003
+ ### 1. Tratamento de Erros Robusto
1004
+
1005
+ ```typescript
1006
+ async function sendMessageSafely(to: string, message: string) {
1007
+ try {
1008
+ const whatsapp = sdk.Message.WhatsappResponse({
1009
+ companyId: 'abc123',
1010
+ phone_number_id: '123456789012345'
1011
+ });
1012
+
1013
+ const result = await whatsapp.send_text({ to, message });
1014
+
1015
+ if (result.isLeft()) {
1016
+ // Log estruturado
1017
+ console.error('Erro ao enviar mensagem:', {
1018
+ to,
1019
+ error: result.value,
1020
+ timestamp: new Date().toISOString()
1021
+ });
1022
+
1023
+ // Alertar equipe (ex: Slack, email)
1024
+ await notifyTeam(`Falha no envio para ${to}`);
1025
+
1026
+ return false;
1027
+ }
1028
+
1029
+ return true;
1030
+ } catch (error) {
1031
+ console.error('Exceção não tratada:', error);
1032
+ return false;
1033
+ }
1034
+ }
1035
+ ```
1036
+
1037
+ ### 2. Rate Limiting
1038
+
1039
+ ```typescript
1040
+ import PQueue from 'p-queue';
1041
+
1042
+ // Fila com limite
1043
+ const messageQueue = new PQueue({
1044
+ interval: 1000, // 1 segundo
1045
+ intervalCap: 10 // 10 mensagens por segundo
1046
+ });
1047
+
1048
+ async function sendWithQueue(to: string, message: string) {
1049
+ return messageQueue.add(() =>
1050
+ whatsapp.send_text({ to, message })
1051
+ );
1052
+ }
1053
+ ```
1054
+
1055
+ ### 3. Timeout para Webhooks
1056
+
1057
+ ```typescript
1058
+ sdk.on('message', async (data) => {
1059
+ // Responder imediatamente à Meta (evitar timeout de 15s)
1060
+ setImmediate(async () => {
1061
+ try {
1062
+ await processMessageAsync(data);
1063
+ } catch (error) {
1064
+ console.error('Erro no processamento:', error);
1065
+ }
1066
+ });
1067
+ });
1068
+
1069
+ async function processMessageAsync(data: any) {
1070
+ // Processamento demorado aqui
1071
+ const analysis = await deepAnalysis(data.message);
1072
+ await sendResponse(data.sender, analysis);
1073
+ }
1074
+ ```
1075
+
1076
+ ### 4. Logging Estruturado
1077
+
1078
+ ```typescript
1079
+ import winston from 'winston';
1080
+
1081
+ const logger = winston.createLogger({
1082
+ level: 'info',
1083
+ format: winston.format.json(),
1084
+ transports: [
1085
+ new winston.transports.File({ filename: 'error.log', level: 'error' }),
1086
+ new winston.transports.File({ filename: 'combined.log' })
1087
+ ]
1088
+ });
1089
+
1090
+ sdk.on('message', (data) => {
1091
+ logger.info('message_received', {
1092
+ sender: data.sender,
1093
+ type: data.message.type,
1094
+ timestamp: new Date().toISOString()
1095
+ });
1096
+ });
1097
+ ```
1098
+
1099
+ ### 5. Validação de Números
1100
+
1101
+ ```typescript
1102
+ import { parsePhoneNumber } from 'libphonenumber-js';
1103
+
1104
+ function validateAndFormatPhone(phone: string, countryCode: string = 'BR'): string | null {
1105
+ try {
1106
+ const phoneNumber = parsePhoneNumber(phone, countryCode);
1107
+ if (phoneNumber.isValid()) {
1108
+ return phoneNumber.format('E.164'); // +5511999999999
1109
+ }
1110
+ } catch (error) {
1111
+ console.error('Número inválido:', phone);
1112
+ }
1113
+ return null;
1114
+ }
1115
+
1116
+ // Uso
1117
+ const formattedPhone = validateAndFormatPhone('11999999999', 'BR');
1118
+ if (formattedPhone) {
1119
+ await whatsapp.send_text({ to: formattedPhone, message: 'Olá!' });
1120
+ }
1121
+ ```
1122
+
1123
+ ---
1124
+
1125
+ ## 🔗 Próximos Passos
1126
+
1127
+ - **[Troubleshooting](08-troubleshooting.md)** - Resolva problemas comuns
1128
+ - **[Integrações](05-integracoes.md)** - Aprofunde-se nas APIs
1129
+ - **[Fluxos Funcionais](04-fluxos-funcionais.md)** - Entenda os processos internos
1130
+
1131
+ ---
1132
+
1133
+ [⬅️ Anterior: Entidades](06-entidades.md) | [⬆️ Voltar ao Índice](README.md) | [➡️ Próximo: Troubleshooting](08-troubleshooting.md)