Atendimento por WhatsApp¶
Em produção. O módulo recebe e envia mensagem por WhatsApp, guarda tudo o que passa, distribui conversa por fila e reconhece frases que disparam ação.
O canal é a Evolution API em servidor próprio, não a API oficial da Meta.
A instância é o número¶
Cada número conectado é uma instância, com URL e token próprios. O KP cria e pareia instâncias pela própria tela de Configurações, sem ninguém abrir o painel do provedor.
Natureza do número¶
| Natureza | O que é | Quem alcança |
|---|---|---|
empresarial |
Número da operação | A supervisão alcança, pela permissão de ver todas |
pessoal |
Número de uma pessoa | Somente quem está vinculado |
Supervisão não alcança número pessoal
Esta separação existe porque em produção quem tinha permissão de ver conversas enxergava conversa privada de terceiro. A natureza do número é o que fecha esse recorte.
Pareamento¶
Pedir o QR code é declarar "vou parear um aparelho agora": o número anterior deixa de valer naquele instante, e owner_jid é limpo. Sem isso, ao reparear um número que já havia pareado, o primeiro sinal de conexão era lido como sincronia e o código desaparecia da tela antes de dar tempo de ler.
A fila¶
A fila é uma consulta, não uma tabela: são as conversas sem dono que o usuário alcança.
| Regra | Como funciona |
|---|---|
| Conversa nova | Entra sem dono e fica visível para todos os atendentes do número |
| Captura | Quem assume vira dono; a disputa é resolvida por corrida no banco |
| Conversa de grupo | Não tem dono |
| Devolução | Conversa parada volta para a fila, por tempo configurável |
| Descadastro | Conversa de quem saiu do número não fica órfã |
Antes da fila, toda conversa nova ia para o dono do número. Na prática ele acumulava tudo e os demais não tinham o que atender.
Prefixo e transferência¶
Mensagem enviada num número compartilhado sai com o prefixo [NOME], para que o contato saiba com quem fala. A transferência de conversa exige destino.
Nota de voz sai sem prefixo
Voz não carrega texto, e a rota de áudio do provedor não aceita legenda. Mandar o nome em mensagem à parte dobraria as mensagens no aparelho do contato. Como a conversa tem um dono só, o prefixo deixa de ser necessário ali.
O que a conversa aceita¶
| Tipo | Receber | Enviar |
|---|---|---|
| Texto | Sim | Sim |
| Imagem | Sim | Sim |
| Documento | Sim | Sim |
| Áudio e nota de voz | Sim | Sim, gravado na tela ou anexado |
| Vídeo e figurinha | Sim | Não |
| Reação | Sim, como linha discreta | Não |
| Contato e localização | Sim | Não |
Todo áudio enviado chega ao contato como nota de voz, inclusive o arquivo anexado.
Anexos¶
PDF, imagem e vídeo abrem em modal de leitura, sem sair da conversa. Word e Excel continuam baixando, porque o navegador não os renderiza.
Todo arquivo com dado pessoal vive em disco privado, servido por rota que verifica permissão. Nunca no disco público. Ver AD-011.
Quem grava não é quem serve
O anexo é gravado pelo worker da fila e entregue pelo PHP-FPM. Se os dois não puderem ler o mesmo arquivo, a rota devolve 404 e a tela cai nas iniciais ou na frase de áudio indisponível, sem dizer o motivo. Foi um defeito real de produção. Detalhe em Ambientes e deploy.
Motor de ações¶
Uma frase numa mensagem recebida pode virar trabalho no sistema. O exemplo que originou o módulo: alguém escreve "Tarefa Eliezer - Ligar para keilla próxima quinta as 14h", e isso vira tarefa sem ninguém recadastrar.
| Peça | Papel |
|---|---|
| Regra | Reconhece a frase num número habilitado |
| Parser | Interpreta data e hora em português, com implementação própria |
| Efeito | Faz o que a ação promete, em classe própria |
| Execução | Persiste e retenta, sem repetir se a mesma mensagem chegar duas vezes |
Um efeito novo nunca é um ramo novo no motor
Cada ação cumpre o contrato ActionEffect e se registra no ActionEffectRegistry. Um switch por tipo dentro do motor transformaria cada ação nova em risco para todas as outras. Ver AD-015.
O gatilho pelo dono do número é opcional, ativado por escolha.
Pendência conhecida¶
As tarefas criadas pelo motor de ações ficam em whatsapp_action_tasks e não aparecem em tela nenhuma. É decisão de produto pendente: onde elas devem ser vistas.