Implement shared-number detection in reserveOutreachSend: reject manual WhatsApp sends with HTTP 409 when the destination number is shared across 2+ leads and hasn't been explicitly released via override. - Add test: reserveOutreachSend bloqueia numero compartilhado sem override e libera com override - Add check in reserveOutreachSend right after isOptedOut check - Uses isNumberSharedAcrossLeads and isSharedNumberOverridden from Task 1 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Máquina Comercial Pessoal
Aplicação local para uma pessoa capturar, qualificar, tratar, exportar e contatar leads. Os dados ficam em SQLite no próprio computador e o WhatsApp funciona por uma sessão de dispositivo vinculado.
Instalação e acesso
Requisitos: Node.js 24 ou superior e npm.
npm install
npm start
Abra http://127.0.0.1:3910. O acesso inicial é admin / admin; abra Configurações > Alterar minha senha, informe admin como senha atual e defina uma nova senha com ao menos 8 caracteres. Essa opção está disponível para qualquer usuário autenticado. No Windows também é possível executar INICIAR-MAQUINA-PESSOAL.bat ou gerar o launcher com npm run build:launcher.
Variáveis opcionais ficam em .env. Consulte .env.example. A porta padrão é 3910 e pode ser alterada com APP_PORT.
Fluxo operacional
- Em Capturar Leads, escolha UF, cidades, nichos e fontes.
- Execute a captura e acompanhe o progresso.
- Em Tratar Leads, filtre e priorize a base.
- Use a ação de WhatsApp na primeira coluna para abrir o envio manual já preenchido com o lead real.
- Exporte o filtro atual em CSV e XLS quando precisar trabalhar fora da aplicação.
Conexão WhatsApp
- Abra Configurações como administrador.
- Clique em Conectar / gerar QR.
- No celular, abra WhatsApp > Dispositivos conectados > Conectar dispositivo.
- Leia o QR exibido na aplicação e aguarde o estado Conectado.
Os estados da conexão incluem parado, iniciando, QR necessário, autenticando, conectado, reconectando, desconectado e erro. Desconectar interrompe a conexão preservando a sessão. Sair e esquecer sessão remove o vínculo local e exigirá um novo QR.
O envio manual exige número com DDI e DDD, cadastro ativo desse número no WhatsApp, mensagem revisada e conexão pronta. O histórico distingue aceite local, confirmação do servidor, entrega e leitura; "aceito" ainda não significa que a mensagem foi entregue.
Automação e segurança comercial
- A automação inicia desligada e deve ser ativada conscientemente pelo administrador.
- Configure um limite diário baixo e mantenha os intervalos de envio.
- Faça contato apenas em horários adequados e com uma finalidade legítima.
- Adicione imediatamente à lista de bloqueio quem pedir para não receber mensagens.
- Não faça spam, disparos indiscriminados nem compre listas de contatos.
- A conexão usa integração não oficial por dispositivo vinculado. Mudanças no WhatsApp podem interromper o funcionamento e uso abusivo pode causar bloqueio da conta.
Templates automáticos são simples: serviço, mensagem e estado ativo. O catálogo inicial usa o serviço neutro Meu serviço; adapte sua oferta no mecanismo de configuração de serviços antes de ativar automações.
Dados locais
O banco, exportações, logs e autenticação do WhatsApp ficam em data/. A sessão vinculada fica em data/runtime/whatsapp-auth. Toda essa pasta é ignorada pelo Git.
Faça backup do banco indicado por APP_DB_PATH antes de manutenção ou migração. Nunca compartilhe .env, banco, logs ou a pasta de autenticação.
Comandos
npm start # servidor local
npm test # suíte automatizada
npm run capture # captura por linha de comando
npm run download-rfb # baixa/retoma os 21 ZIPs necessarios (~6 GB)
npm run extract -- --uf=BA # baixa o que faltar e extrai a base CNPJ da UF
npm run recalc-scores # recalcula os scores
npm run outreach # executa automação, quando habilitada
npm run build:launcher # gera o launcher Windows
O botão Baixar e extrair base faz o mesmo fluxo em um clique. O downloader escolhe o snapshot público mais recente, mantém arquivos .part para retomada e valida tamanho e estrutura EOCD/diretório central dos ZIPs antes da extração. Um snapshot novo exige por padrão 8 GiB livres; ao retomar o mesmo snapshot, ZIPs finais confirmados e .part com metadata reduzem esse requisito, preservando uma margem mínima de 2 GiB para extração. O conjunto completo anterior fica em .rfb-backup até o novo snapshot ser validado. Se o índice ficar offline com o conjunto atual incompleto, o backup é validado e restaurado; finals e manifesto incompletos são movidos para .rfb-incomplete*, e .part permanece disponível quando a restauração não troca de snapshot. Para extrair somente com os arquivos locais já completos, use npm run extract -- --uf=BA --no-download.
Estrutura
public/ interface web
prospeccao/config.json nichos e serviço neutro inicial
scripts/ comandos operacionais e build do launcher
src/capture/ captura de leads
src/treatment/ consultas e dashboard
src/outreach/ templates, limites e automação
src/whatsapp/ sessão local e envio
src/server/ servidor, autenticação e rotas
launcher/ launcher Windows
data/ banco e estado local ignorados
Solução de problemas
- A tela não abre: confirme
npm install, rodenpm starte acessehttp://127.0.0.1:3910. - Porta ocupada: defina outra
APP_PORTno.enve reinicie. - QR não aparece: clique em Conectar / gerar QR. Se o QR expirou ou a tentativa ficou presa, Atualizar QR reinicia o pareamento e solicita um QR novo.
- WhatsApp desconectado: tente conectar novamente. Se a sessão estiver inválida, use Sair e esquecer sessão e vincule de novo.
- Mensagem recusada: confira conexão, número com DDI/DDD, limite diário e lista de bloqueio.
- Captura sem resultados: confirme a base CNPJ da UF, as fontes escolhidas e
GOOGLE_PLACES_API_KEYcaso use Google Places. - Launcher não compila: instale o .NET SDK ou execute a aplicação diretamente com
npm start.
Boas práticas
Mantenha o servidor em 127.0.0.1, use senhas individuais, preserve a automação desligada até revisar templates e limites, e respeite privacidade, consentimento e pedidos de opt-out.