Criando um bot do Whatsapp no Node.js. Guia completo

Repositório com fonte de bot

Introdução

Agora, vamos explicar como criar um bot WhatsApp no Node JS usando o gateway da API do WhatsApp.

O bot responderá aos comandos que recebe como mensagens normais do WhatsApp e responderá a elas. No nosso exemplo, tentaremos cobrir as funcionalidades mais usadas e necessárias no desenvolvimento:

  • Capacidade de reação e resposta ao comando
  • Exibe o ID do Chat atual (na mensagem privada ou na conversa)
  • Exibe o nome de quem se comunica com o bot
  • Envio de arquivos de vários formatos (pdf, jpg, doc, mp3, etc)
  • Envio de mensagens de voz (arquivos *.ogg)
  • Envio de geolocalização (coordenadas - latitude e longitude)
  • Criação de uma conferência (grupo) com um bot

Atenção: todo o sistema funciona através do WhatsApp Web, respectivamente, seu telefone sempre deve estar conectado à Internet

1 Passo. Preparação

Um pouco de teoria

Autorização do Whatsapp via QR code

No começo, vamos vincular o whatsapp ao nosso script de uma só vez para verificar seu trabalho enquanto escrevemos o código. Para fazer isso, vamos a uma conta pessoal e obtemos um código QR lá. Em seguida, abra o WhatsApp no seu celular, vá para Configurações -> WhatsApp Web -> Digitalizar código QR.

As capacidades do serviço de Chat-Api nos permitirá instalar um Webhook que transmitirá informações sobre novas mensagens (e não só) para seu servidor web. Para o servidor chamar nosso script em novas mensagens, é necessário especificar o URL do WebHook. O URL do WebHook é um link para o qual será enviado pelo método POST, dados JSON com informações sobre mensagens ou notificações recebidas. Portanto, para o bot funcionar, precisamos de um servidor - que receba e processe esses dados.

Vamos implantar um servidor Web no seu computador/VPS/VDS (a seguir denominado Host), respectivamente, será necessário especificá-lo em sua conta pessoal. Portanto, nas configurações da conta, especificamos o endereço do WebHook'a - no meu caso, é https://subdomain.domain.com/webhook. No seu caso, se você usar um domínio separado, será algo parecido com isto: https://domain.com/webhook.

Clique em "Salvar". Pronto, agora todas as notificações de novas mensagens chegarão ao nosso endereço, basta processá-las.

Obtenha acesso gratuito à API do WhatsApp

2.1 Passo. Implantando um bot no seu dispositivo

Recomendamos começar com a clonagem de nosso repositório Git seguido por uma mudança personalizada.

Portanto, crie a pasta WhatsAppBot, clone o git (ou baixemos) em seu arquivos a partir do repositório. Antes de tudo, instalaremos as dependências necessárias para o nosso bot usando o comando npm install - um conjunto de bibliotecas através dos quais ele vai trabalhar.

Em seguida, vá para a configuração (arquivo config.js) e especifique entre aspas seu endereço de url para solicitações e token (você pode levá-los em sua conta pessoal). Acontece desta maneira:

                        module.exports = {
    // API reference URL
    apiUrl: "https://eu14.chat-api.com/instance12345/",
    // API token from your personal account
    token: "xb1s668fphzmr9m"
}
                    

Salvamos o arquivo e digitamos no terminal node index.js - com este comando, iniciaremos o servidor da Web para processar solicitações. Se você fez tudo certo o bot irá funcionar.

2.2 Passo. Desenvolver um bot a partir do zero

Se você decidir escrever um bot a partir do zero - agora vamos dizer como fazê-lo.

Deixamos a descrição de instalação de Node.JS e NPM (supondo que você já esteja familiarizado com isso, basta ler este guia).

Então, criamos a pasta WhatsAppBot, entre nela e abra o terminal. Inicializamos o projeto com o comando npm init, preenchemos os dados ou apenas pressionamos Enter várias vezes até que apareça Is this OK? (yes).

Em seguida, criamos nosso arquivo principal - index.js. Ele irá conter toda a lógica básica do bot. Também criamos o config.js - lá colocaremos os principais parâmetros, que podem ser dinâmicos (de modo a não entrar no arquivo principal para corrigi-los).

Abrimos o config.js e adicionamos dois parâmetros - apiUrl e token:

                        module.exports = {
    apiUrl: "",
    token: ""
}
                    

Não esqueça a primeira linha - module.exports -, que lhe permitirá trabalhar com esses dados de outro arquivo. Podemos preencher imediatamente os dados para a configuração com os dados de sua conta pessoal. Salvar e fechar.

Usaremos as seguintes dependências (requirements):

Abrimos o index.js e começamos a criar um bot com um requerimento dependências:

                        const config = require("./config.js");
const token = config.token, apiUrl = config.apiUrl;
const app = require('express')();
const bodyParser = require('body-parser');
const fetch = require('node-fetch');
                    

Detalhadamente: node-fetch permite fazer solicitações de API, config carregará nossos dados de outro arquivo, colocaremos imediatamente os dados do config nas variáveis token e apiUrl (para facilitar o acesso a eles). O módulo Express é necessário para implantar o servidor web e а body-parser permite recuperar convenientemente o fluxo de solicitações recebidos.

Em seguida, explicaremos ao nosso parser que iremos trabalhar com dados JSON:

                        app.use(bodyParser.json());
                    

A propósito, para descobrir como será o JSON recebido - você pode ir para uma seção de testes de fácil utilização, que fornecemos na conta pessoal. Aqui você pode testar solicitações e o Webhook.

Por precaução, suspendemos o manipulador de erros completo que pode gerar prequest durante o processo de solicitação:

                        process.on('unhandledRejection', err => {
    console.log(err)
});
                    

E agora vamos começar a escrever o código principal.

Para verificar o domínio estacionado no Host, processaremos a página principal (uma espécie de index.html) com o seguinte bloco:

                        app.get('/', function (req, res) {
    res.send("It's working");
}); 
                    

Simplificando - isso permitirá verificar o desempenho do nosso site - após o lançamento do projeto, quando você mudar para o yoursite.ru - se tudo for feito corretamente - você verá a inscrição “It's working". Agora, escreveremos uma função para se comunicar com nossa API.

                        async function apiChatApi(method, params){
    const options = {};
    options['method'] = "POST";
    options['body'] = JSON.stringify(params);
    options['headers'] = { 'Content-Type': 'application/json' };
    
    const url = `${apiUrl}/${method}?token=${token}`; 
    
    const apiResponse = await fetch(url, options);
    const jsonResponse = await apiResponse.json();
    return jsonResponse;
}
                    

Analisaremos mais detalhadamente: criamos a função assíncrona apiChatApi, que aceita dois parâmetros: o método que queremos acessar e o objeto de parâmetro com os quais nós acessamos a este método. Bem, para ser franco, queremos enviar uma mensagem - acessamos o método message e transferimos o texto da mensagem e destinatário no objeto.

Dentro da função, criamos o objeto options, que reabastecemos imediatamente com duas chaves: json e method. No primeiro, passamos os parâmetros necessários para a API e, no segundo, indicamos o método que acessamos e no qual queremos obter a resposta.

Em seguida, declaramos uma constante - nosso endereço de url para acessar a API. Em suma, ele conterá o próprio url (da configuração), o método e o token transmitidos pela solicitação GET.

Depois disso, enviamos a solicitação e escrevemos a resposta em apiResponse, que retornamos (no bot mais simples, a propósito, o retorno da resposta da função, em princípio, não será necessário, exceto para detectar erros)

A função de comunicação com a API está pronta. É hora de começar a escrever a lógica do bot.

Escolhemos, como será chamado a nossa página para processamento. No meu caso, que seja webhook (ou seja, o webhook enviará solicitações para http://domain.com/webhook). Escrevemos esse manipulador de url:

                        app.post('/webhook', async function (req, res) {

});
                    

Dentro do manipulador, escrevemos na variável data tudo o que obtemos:

                        app.post('/webhook', async function (req, res) {
    const data = req.body;

});
                    

E a executemos através de um loop for para analisar todas as mensagens:

                        app.post('/webhook', async function (req, res) {
    const data = req.body;
    for (var i in data.messages) {

    }
});
                    

Agora, escreveremos as informações sobre a mensagem recebida em variáveis e também isolamos imediatamente as informações sobre as mensagens enviadas:

                        app.post('/webhook', async function (req, res) {
    const data = req.body;
    for (var i in data.messages) {
        const author = data.messages[i].author;
        const body = data.messages[i].body;
        const chatId = data.messages[i].chatId;
        const senderName = data.messages[i].senderName;

        if(data.messages[i].fromMe)return;
    }
});
                    

Portanto, no author, agora temos informações sobre o autor da mensagem, body contém o texto, chatId é o Id do chat atual e senderName recebeu o nome da pessoa que está falando conosco.

Não se esqueça de adicionar o código para iniciar o servidor da web no final do arquivo:

                        app.listen(80, function () {
    console.log('Listening on port 80..');
});
                    

E agora podemos testar o desempenho do bot escrevendo o seguinte código em um loop for após as variáveis declaradas:

                        console.log(senderName, author, chatId, body);
                    

Inicie o bot com o comando node index.js e escreva a mensagem bot: Test. Se tudo estiver correto, no console, veremos: Eugene 79123456789@c.us 79123456789@c.us Test

Se tudo funciona, siga em frente. Removemos (ou comentamos) a linha de depuração com console.log e pensamos em como processar os comandos.

Na verdade, existem várias opções, mas recomendamos a construção if else if em conjunto com expressões regulares: isso permitirá, em primeiro lugar, criar comandos complexos com argumentos e, em segundo lugar, não se preocupar com a repetição de variáveis (como seria no caso do switch-case), e, em terceiro lugar, é muito fácil verificar o comando inserido incorretamente (fechamento else) e emitir a mensagem correspondente.

A seguir, examinaremos o código incorporado no for, não se confundem 😉

Então, vamos começar editando a estrutura de comando:

                        if(/help/.test(body)) {
    // This section will work when the user enters "help"
    } else if(/chatId/.test(body)) {
    // This section will work when the user enters "chatId"
    } else if(/file (pdf|jpg|doc|mp3)/.test(body)) {
    // This section will work when the user enters "file pdf, file jpg, etc"
    } else if(/ptt/.test(body)) {            
    // This section will work when the user enters "ptt"
    } else if(/geo/.test(body)) {
    // This section will work when the user enters "geo"
    } else if(/group/.test(body)) {
    // This section will work when the user enters "group"
}
                    

Bem, agora na verdade, escreveremos manipuladores de comando. Vamos começar com help: aqui tudo é fácil:

                        const text = `${senderName}, this is a demo bot for https://chat-api.com/.
Commands:
1. chatId - view the current chat ID
2. file [pdf/jpg/doc/mp3] - get a file
3. ptt - get a voice message
4. geo - get a location
5. group - create a group with you and the bot`;
await apiChatApi('message', {chatId: chatId, body: text});
                    

Aqui está tudo claro: na variável text, escreveremos um texto pré-preparado, colocaremos nele a variável senderName, contendo o nome do usuário que escreveu o bot.

Bem, a última linha é uma chamada à nossa função para trabalhar com a API, na qual passamos um método - 'message' e um objeto com parâmetros - {chatId: chatId, body: text}.

Podemos executar nosso projeto com o comando node index.js e escrever no bot help.

A propósito, recomendamos que você envie um texto com todos os comandos para qualquer comando não escrito para o bot, por exemplo, se uma pessoa escrever "Olá!" para o bot, embora não tenhamos colocado esse comando. Então, essa mensagem inicial ficará à vista do usuário o tempo todo.

Agora vamos escrever um manipulador para o comando chatId. Em princípio, tudo aqui também é simples:

                        await apiChatApi('message', {chatId: chatId, body: chatId});
                    

Acessamos a API, o método message e solicitamos enviar para o chat chatld texto chatld.

whatsapp api

É muito simples, concordam? Continuamos.

No nosso caminho, a parte mais difícil do código, é a funcionalidade do comando file. Para começar, vamos dar uma olhada mais de perto no texto:

                        /file (pdf|jpg|doc|mp3)/.test(body)
                    

Descreverei brevemente sua lógica: verificamos se body é igual a file + um dos valores entre parênteses. Por exemplo, body é igual ao valor de file pdf ou ao valor de file jpg, e assim por diante.

Se for igual, executamos nosso manipulador, que em primeiro lugar, usando a função match, calcula o tipo do arquivo a ser enviado para a variável fileType:

                        const fileType = body.match(/file (pdf|jpg|doc|mp3)/)[1];
                    

Ou seja, em fileType, agora temos o valor pdf/jpg/doc/mp3. Agora vamos criar o objeto com os dados a serem enviados:

                        const files = {
     doc: "https://domain.com/tra.docx",
     jpg: "https://domain.com/tra.jpg",
     mp3: "https://domain.com/tra.mp3",
     pdf: "https://domain.com/tra.pdf"
};
                    

Respectivamente, nos permitirá obter o url do arquivo acessando-o pelo índice de chaves, por exemplo:

                        files["doc"] // => "https://domain.com/tra.docx"
files["mp3"] // => "https://domain.com/tra.mp3"
                    

Assim, files[fileType] fornecerão o url do arquivo que precisamos.

A única coisa que resta é criar um objeto de parâmetros que precisamos passar para a API:

                        var dataFile = {
     phone: author,
     body: files[fileType],
     filename: `File *.${fileType}`            
};
                    

No phone, transferimos o autor da mensagem, no body um link para o arquivo (ver no API), e no filename colocamos o nome visível do arquivo (como exemplo, eu coloquei a palavra "Arquivo" e sua extensão).

Escrevemos uma pequena construção que agregará a chave "caption" (a linha inferior do texto abaixo da figura) apenas no caso, se a solicitação for para uma imagem:

                        if (fileType == "jpg") dataFile['caption'] = "Photo text";
                    

Em suma, passamos tudo isso para nossa função, indicando que queremos chamar o método sendFile:

                        await apiChatApi('sendFile', dataFile);
                    

Agora, implementamos o manipulador do comando ptt - mensagens de voz.

                        await apiChatApi('sendAudio', {audio: "https://domain.com/tra.ogg", chatId: chatId});
                    

Acessamos nossa função passando o método sendAudio e a chave audio com um link direto para o arquivo no objeto de parâmetro.

Sending audio bot Whatsapp

Neste artigo, os links de arquivo são estáticos (referindo-se à hospedagem). Aconselhamos que você transfira arquivos no formato base64.

O manipulador para o comando geo também é muito simples:

                        await apiChatApi('sendLocation', {lat: 51.178843, lng: -1.826210, address: 'Stonehenge', chatId: chatId});
                    

Em vez de audio, passamos as chaves lat e lng - a latitude e longitude do espaço necessário, respectivamente. Na chave "address", passamos o seu nome. As próprias coordenadas podem ser obtidas, por exemplo, no Google Maps.

Ficou um comando group, criando um grupo de bot com uma pessoa. Seu manipulador é quase o mesmo que vários anteriores:

                        let arrayPhones = [ author.replace("@c.us","") ];

await apiChatApi('group', {groupName: 'Group with a bot', phones: arrayPhones, messageText: 'Welcome to the new group!'});
                    

Criamos uma matriz arrayPhones, na qual colocamos o autor imediatamente, removendo @c.us em sua linha, deixando apenas o número. Podemos colocar vários números ao mesmo tempo.

Construindo o bot do WhatsApp no nó JS

E executamos a solicitação para a função usando o método group, passando as chaves groupName - o nome da conversa, a matriz de usuários em phones e o texto de boas-vindas em messageText.

Na verdade, isso completa o desenvolvimento dos manipuladores.

Tudo o que você precisa fazer é configurar seu token a partir da sua conta pessoal e número da instance.

Obter chave da API


Whatsapp bot no Node.JS

Agora você precisa fazer upload de nosso servidor com o bot na hospedagem e, como webhook, especificar seu domínio. Em cada mensagem recebida, o servidor chegará e processará os dados.

O código estará disponível através de um link para o Github: https://github.com/chatapi/whatsapp-nodejs-bot-en