Exemplo de criação de um bot Whatsapp em Java

O guia completo
Repositório de fontes Bot
Publicado: 5 de novembro de 2020

Mostraremos como escrever um bot WhatsApp simples em Java usando nossa API WhatsApp.

Neste exemplo, o bot responderá aos comandos recebidos na forma de mensagens regulares no WhatsApp e responderá a eles. Não se esqueça de baixar o bot finalizado de nosso repositório e usá-lo em seu trabalho!

Qual é a funcionalidade deste bot?

  1. Ao enviar o comando "chatid", o bot deve enviar uma mensagem com o ID do chat atual
  2. Ao enviar o comando "file [format]", o bot deve enviar os arquivos preparados (pdf, jpg, doc, mp3);
  3. Ao enviar o comando "ogg", o bot deve enviar um arquivo com a extensão "ogg" (mensagem de voz);
  4. Ao enviar o comando "geo", o bot deve enviar geo-coordenadas (localização);
  5. Ao enviar o comando "group", o bot deve criar um grupo consigo mesmo e com o usuário;
  6. Quando você envia qualquer mensagem não-comandada, o bot responde com uma mensagem de boas-vindas descrevendo todos os comandos (como uma espécie de menu);

Preparação

Primeiro, iremos vincular imediatamente o WhatsApp ao nosso script, então, quando escrevermos o código, verificaremos o seu funcionamento. Para fazer isso, vá para sua conta pessoal e obtenha um código QR lá. Em seguida, abra o WhatsApp no seu celular, vá para Configurações -> WhatsApp Web -> Digitalize o código QR.

Atenção!
Para que o bot funcione, o telefone deve estar sempre conectado à Internet e não deve ser usado para o WhatsApp Web.

Para que nosso bot responda aos comandos, é necessário que o bot seja capaz de aceitar e processar os dados recebidos. Para fazer isso, você precisa criar seu próprio servidor - Webhook e inserir o endereço em sua conta pessoal.

Um pouco sobre a função do Webhook

O Webhook resolve o problema de atrasos na resposta às mensagens recebidas. Sem ele, nosso bot teria que perguntar constantemente ao servidor sobre os dados recebidos, fazer solicitações regulares e fixas aos servidores. Portanto, ter alguma latência na resposta, e isso também, contribuiria para a carga no servidor.

Mas, se especificarmos o endereço do servidor Webhook, essa necessidade não será mais relevante. Os próprios servidores enviarão notificações de mudanças recebidas assim que aparecerem. E a tarefa do servidor Webhook é aceitar e processá-los corretamente, implementando a lógica do bot. Você pode especificar um domínio e um endereço ip.

Put webhook in your personal cabinet Configure um webhook em seu perfil pessoal

Criar seu próprio servidor em Java usando o framework Spring Boot

Para simplificar a criação do nosso modelo de inicialização do aplicativo Spring Boot, usaremos o spring initializr: Configure as configurações necessárias, selecione a versão Java desejada e clique em Generate

Em seguida, você precisa baixar o projeto gerado e abri-lo em seu IDE. Usarei o Intellij IDEA. Vamos criar uma pasta "controller"", na qual armazenaremos nosso controlador para processar os dados de entrada em nosso servidor e as classes necessárias para o bot funcionar.

Сhat-api envia dados JSON que precisamos analisar e processar.

Para descobrir o que exatamente chega até nós no json, usaremos a página de teste na conta pessoal e iremos para a guia Webhook Simulator tab.

JSON body dados que chegarão ao nosso servidor (sua estrutura). Para trabalhar confortavelmente com ele em Java, vamos desserializar em um objeto e tratar os dados como se fossem propriedades do objeto.

Para nosso conforto, usaremos o serviço serviço para gerar automaticamente Json to Java class. Copie o JSON body. Clique em Preview e copie as classes Java geradas automaticamente em nosso projeto. Para fazer isso, crie um arquivo jsonserializables.java e cole o código no arquivo.

Depois que nossa classe que descreve o corpo JSON é criada, prosseguimos com a implementação do próprio controlador, que processará os dados de entrada. Para fazer isso, crie um novo arquivo "MessageController" e descreva a classe MessageController nele.

@RestController
@RequestMapping("webhook")
    public class MessageController {
        @PostMapping
        public String AnswerWebhook(@RequestBody RequestWebhook hook) throws IOException {
            return  "ok";
        }

A anotação @RequestMapping("webhook") é responsável pela direção em que nosso controlador será processado. Por exemplo: "localhost:8080/webhook"

A anotação @PostMapping significa que a função AnswerWebhook processará os pedidos POST.

Ao mesmo tempo, o parâmetro RequestWebhook nos parâmetros da função é nossa classe JSON desserializada, cuja desserialização é assumida pelo Spring Boot e imediatamente obtemos um objeto pronto para uso e podemos trabalhar com ele dentro da própria função. Nele, descreveremos a lógica do bot.

Implementando a lógica do controlador

@RestController
    @RequestMapping("webhook")
    public class MessageController {
        @PostMapping
        public String AnswerWebhook(@RequestBody RequestWebhook hook) throws IOException {
            for (var message : hook.getMessages()) {
                if (message.getFromMe())
                    continue;
                String option = message.getBody().split(" ")[0].toLowerCase();
                switch (option)
                {
                    case "chatid":
                        ApiWA.sendChatId(message.getChatId());
                        break;
                    case "file":
                        var texts = message.getBody().split(" ");
                        if (texts.length > 1)
                            ApiWA.sendFile(message.getChatId(), texts[1]);
                        break;
                    case "ogg":
                        ApiWA.sendOgg(message.getChatId());
                        break;
                    case "geo":
                        ApiWA.sendGeo(message.getChatId());
                        break;
                    case "group":
                        ApiWA.createGroup(message.getAuthor());
                        break;
                    default:
                        ApiWA.sendDefault(message.getChatId());
                        break;
                }
            }
            return  "ok";
        }

Em um ciclo, revisamos todas as mensagens recebidas e as processamos no switch. É necessário verificar o início do ciclo para que o bot não fique obcecado consigo mesmo. Se a mensagem vier dela mesma, nós a pulamos e não a processamos.

A seguir, escreveremos o comando recebido na variável option. Para fazer isso, dividimos o corpo da mensagem usando o método split e colocamos o comando em letras minúsculas para que o bot responda aos comandos independentemente do caso. Em switch, dependendo do comando que veio, chamamos o método necessário da classe ApiWA, de cuja implementação falaremos agora.

Classe ApiWA

Esta classe implementará métodos estáticos para chamar a API. Dentro da classe, descreveremos as variáveis que irão armazenar nosso token para que possamos usar a API com sucesso, passando esses dados. Eles podem ser encontrados em sua conta pessoal.

public class ApiWA {
        private static String APIURL = "https://eu115.chat-api.com/instance123456/";
        private static String TOKEN = "1hi0xw1fzaen1234";
    }

Em seguida, precisamos implementar um método que envie uma solicitação POST.

 public static CompletableFuture<Void> postJSON(URI uri,
                                            Map<String,String> map)
            throws IOException
    {
        ObjectMapper objectMapper = new ObjectMapper();
        String requestBody = objectMapper
                .writerWithDefaultPrettyPrinter()
                .writeValueAsString(map);

        HttpRequest request = HttpRequest.newBuilder(uri)
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(requestBody))
                .build();

        return HttpClient.newHttpClient()
                .sendAsync(request, HttpResponse.BodyHandlers.ofString())
                .thenApply(HttpResponse::statusCode)
                .thenAccept(System.out::println);
    }

Este método recebe em parâmetros uma referência de URI para a qual uma solicitação POST deve ser feita, bem como um dicionário, que é serializado em uma string Json e passado para o servidor.

Para implementar cada um dos métodos, examinamos a documentação detalhada e repetimos as solicitações.

Este é o método para enviar chatid:

    public static void sendChatId(String chat_id) throws IOException {
        URI uri = URI.create(APIURL + "sendMessage?token=" + TOKEN);
        Map<String, String> map = new HashMap<String, String>();
        map.put("body", "Your ID: " + chat_id);
        map.put("phone", chat_id);
        ApiWA.postJSON(uri, map);
    }

Formamos um link para o qual você precisa fazer uma solicitação e um dicionário com parâmetros. Depois disso, acessamos o método para enviar uma solicitação POST, que implementamos anteriormente.

Descrevemos a implementação do envio de um arquivo via Whatsapp chatbot no próximo capítulo, e o resto da funcionalidade, como o envio de geolocalização, criação de um grupo e outros comandos, você pode ver no código fonte de nosso bot.

Outros comandos
Outros métodos são implementados de maneira semelhante. O código-fonte pode ser baixado e visualizado no Github.

Falaremos separadamente sobre como aplicar o método de envio do arquivo

 public static void sendFile(String chat_id, String file_format) throws IOException {
        Map<String, String> formats= new HashMap<String, String>();
        formats.put("doc", Base64Help.getDOC());
        formats.put("jpeg", Base64Help.getJPEG());
        formats.put("pdf", Base64Help.getPDFtring());
        formats.put("mp3", Base64Help.getMP3String());

        if (formats.containsKey(file_format))
        {
            Map<String, String> map = new HashMap<String, String>();
            map.put("phone", chat_id);
            map.put("body", formats.get(file_format));
            map.put("filename", "ThisIsFile");
            map.put("caption", "ThisIsCaption");
            URI uri = URI.create(APIURL + "sendFile?token=" + TOKEN);
            ApiWA.postJSON(uri, map);
        }
        else
        {
            Map<String, String> map = new HashMap<String, String>();
            map.put("phone", chat_id);
            map.put("body", "File not found");
            URI uri = URI.create(APIURL + "sendMessage?token=" + TOKEN);
            ApiWA.postJSON(uri, map);
        }
    }

Este método armazena um dicionário no qual as chaves são o formato do arquivo e os valores são uma string no formato Base64. A string Base64 é usada para transferências de arquivos. Para gerar uma string, você pode usar o serviço em nosso site. Se o arquivo com o formato desejado não constar do dicionário, enviamos uma mensagem informando que o arquivo não foi encontrado.

Descrevemos a classe Base64Help e os métodos para obter uma string com um arquivo no formato necessário. A string em si é armazenada em arquivos txt no servidor e do código acabamos de lê-la do arquivo. Isso é necessário porque o Java não permite que você armazene essas strings longas diretamente em seu código. Você pode gerar uma string Base64 automaticamente ou usando serviços.

public class Base64Help {
        static public String getPDFString() throws IOException {
            return new String(Files.readAllBytes(Paths.get("src/main/resources/pdf.txt")));
        }

        static  public String getMP3String() throws IOException {
            return new String(Files.readAllBytes(Paths.get("src/main/resources/mp3.txt")));
        }

        static public String getJPEG() throws IOException {
            return new String(Files.readAllBytes(Paths.get("src/main/resources/jpeg.txt")));
        }

        static public String getDOC() throws IOException {
            return new String(Files.readAllBytes(Paths.get("src/main/resources/doc.txt")));
        }

    }

Portanto, descrevemos o trabalho de um bot Whatsapp simples e postamos o código-fonte com a funcionalidade pronta para uso no Github.

Todo o código e o guia estarão disponíveis no link do Github: https://github.com/chatapi/whatsapp-java-bot-en

tutorial de java chatbot para whatsapp

Você só precisa substituir o token de sua conta pessoal e o número da instância no código.

Tutorial de Java chatbot para Whatsapp

Agora você precisa carregar nosso servidor junto com o bot para a hospedagem e especificar seu domínio como webhook. A cada mensagem recebida, o servidor receberá e processará os dados. Se você tiver alguma dúvida, pode sempre entrar em contato com nosso suporte técnico!