Executando verificação de segurança...
39

Como criar um bot de Sticker para o Whatsapp 📸

Stickers Whatsapp

Nesse guia vou te mostrar como podemos transformar imagens e link de imagens enviados no Whatsapp em Stickers!

Requisitos

Mão na massa!

Como de costume crie uma pasta para seu projeto onde quiser, abra o terminal dentro da pasta e já roda o npm init para iniciar o processo de criação do projeto. Após finalizar vamos intalar as dependencias que vamos usar.

Instalando dependencias

Use o comando npm i nome-da-lib para instalar todas as dependencias abaixo. Exemplo npm i whatsapp-web.js.

1. whatsapp-web.js

Nesse guia não vou utilizar o venom-bot que usei no Guia completo de como integrar o ChatGPT com Whatsapp 🤖, para ensinar outras dependencias legais que fazem a mesma coisa caso voce tenha problemas com o venom-bot. Dessa vez vamos instalar o whatsapp-web.js, já vai no seu terminal e roda o comando npm i whatsapp-web.js.

3. qrcode-terminal

Vamos precisar dessa lib para transformar o qrcode gerado em base64 do whatsapp-web.js em uma imagem no nosso terminal. Assim facilita a vida e não vamos precisar copiar e colar o base64 em sites de terceiros para gerar nossa imagem.

3. axios

Apenas para facilitar nossa vida com as requisições e ficar menos verboso.

Codando

Vamos começar com o snippet de conexão do whatsapp-web.js utilizando o qrcode-terminal para nos conectar e testar nossa integração. Crie um arquivo index.js na raiz do seu projeto e implemente o código abaixo.

const { Client } = require('whatsapp-web.js');
const qrcode = require('qrcode-terminal')

const client = new Client();

client.on('qr', qr => {
    qrcode.generate(qr, {small: true});
});

client.on('ready', () => {
    console.log('Client is ready!');
});

/**
 * Aqui vem como default 'message', bora trocar para 'message_create', 
 * dessa forma nós também poderemos dar comandos e não apenas seus 
 * contatos.
 */
client.on('message_create', message => {
	if(message.body === 'Hello') {
		message.reply('🤖 world 🌎');
	}
});

client.initialize();

Whatsapp teste

Agora que a gente já viu que está tudo funcionando bora criar uma condicional dentro do nosso listener de mensagens para pegar o comando que o usuário mandou e chamar as funções que a gente criar de acordo com o comando.

client.on('message_create', msg => {
    const command = msg.body.split(' ')[0];
    // Cola seu número onde tem o 84848484, sem o 9
    const sender = msg.from.includes("84848484") ? msg.to : msg.from
    if (command === "/sticker")  generateSticker(msg, sender)
});

Prontinho, bora implementar a função generateSticker(). Nela vamos validar apenas 1 coisa, se a mensagem enviada contém uma imagem ou um link de uma imagem, já que cada caso precisa ser tratado de uma forma diferente. No caso da imagem crua vamos apenas utilizar a função downloadMedia() do próprio objeto msg do whatsapp-web.js, e desestruturando o objeto { data } para pegar a key data que contem nosso base64 para posteriormente criarmos uma instancia da classe MessageMedia que criará um objeto de imagem para nós que possibilitará envia-lo como sticker na função sendMessage(). Já a url de imagem nós precisamos baixá-la usando o axios e como ela chega para gente como um Buffer que contém uma sequencia de bytes, precisaremos transforma-la em base64 para posteriormente repetir o mesmo processo da imagem crua e envia-la usando a função sendMessage().

const generateSticker = async (msg, sender) => {
    if(msg.type === "image") {
        try {
            const { data } = await msg.downloadMedia()
            const image = await new MessageMedia("image/jpeg", data, "image.jpg")
            await client.sendMessage(sender, image, { sendMediaAsSticker: true })
        } catch(e) {
            msg.reply("❌ Erro ao processar imagem")
        }
    } else {
        try {
            const url = msg.body.substring(msg.body.indexOf(" ")).trim()
            const { data } = await axios.get(url, {responseType: 'arraybuffer'})
            const returnedB64 = Buffer.from(data).toString('base64');
            const image = await new MessageMedia("image/jpeg", returnedB64, "image.jpg")
            await client.sendMessage(sender, image, { sendMediaAsSticker: true })
        } catch(e) {
            msg.reply("❌ Não foi possível gerar um sticker com esse link")
        }
    }
}

E no fim nosso index.js ficará assim

const { Client, MessageMedia } = require('whatsapp-web.js')
const qrcode = require('qrcode-terminal')
const axios = require('axios')
const client = new Client({})

client.on('qr', qr => {
    qrcode.generate(qr, {small: true})
});

client.on('ready', () => {
    console.log('O Wpp-Sticker está pronto 😋 Não esquece da estrelinha no repo ⭐')
});

/**
 * Aqui vem como default 'message', bora trocar para 'message_create', 
 * dessa forma nós também poderemos dar comandos e não apenas seus 
 * contatos.
 */
client.on('message_create', msg => {
    const command = msg.body.split(' ')[0];
    // Cola seu número onde tem o 84848484, sem o 9
    const sender = msg.from.includes("84848484") ? msg.to : msg.from
    if (command === "/sticker")  generateSticker(msg, sender)
});

client.initialize();

const generateSticker = async (msg, sender) => {
    if(msg.type === "image") {
        try {
            const { data } = await msg.downloadMedia()
            const image = await new MessageMedia("image/jpeg", data, "image.jpg")
            await client.sendMessage(sender, image, { sendMediaAsSticker: true })
        } catch(e) {
            msg.reply("❌ Erro ao processar imagem")
        }
    } else {
        try {

            const url = msg.body.substring(msg.body.indexOf(" ")).trim()
            const { data } = await axios.get(url, {responseType: 'arraybuffer'})
            const returnedB64 = Buffer.from(data).toString('base64');
            const image = await new MessageMedia("image/jpeg", returnedB64, "image.jpg")
            await client.sendMessage(sender, image, { sendMediaAsSticker: true })
        } catch(e) {
            msg.reply("❌ Não foi possível gerar um sticker com esse link")
        }
    }
}

Demo

E bora ver essa belezura rodando com o melhor inicial da Gen 1 do Pokemon e depois o melhor Pokemon de todos os tempos.

Gif Aplicação

Dicas

  1. Caso queira formatar sua imagem antes de enviá-la da uma olhada no jimp. Essa lib vai te ajudar a manipular as imagens da forma que quiser.

  2. Se quiser que o bot mande comandos apenas para um grupo específico faça o seguinte:

client.on('message_create', msg => {
    const command = msg.body.split(' ')[0];
    const sender = msg.from.includes("84374282") ? msg.to : msg.from
    if (command === "/sticker"  && sender === 'ID-DO-SEU-GRUPO')  generateSticker(msg, sender)
});

Sim, eu sei o que voce está pensando "-A mas eu não sei o id do meu grupo Harry", faz o seguinte escreve console.log(msg) dentro do client.on() vai ficar assim:

client.on('message_create', msg => {
    console.log(msg)
    const command = msg.body.split(' ')[0];
    const sender = msg.from.includes("84374282") ? msg.to : msg.from
    if (command === "/sticker"  && sender === 'ID-DO-SEU-GRUPO')  generateSticker(msg, sender)
});

Manda qualquer mensagem no grupo que voce quer que o bot funcione e procure no seu terminal caso voce tenha enviado, a seguinte key to: '[email protected]',(talvez seja um número até maior que esse caso tenha mais gente no grupo) e caso tenha sido outra pessoa que enviou a msg ao invés de to vai ser from. Prontinho, ta aí o seu id do grupo.

Ta com preguiça e quer um plug and play?

Sei que eu deveria colocar isso no início pra evitar da galera descobrir só depois de ler tudo mas você também deveria ler mais 👍

Vai lá no repositório pra dar fork e aproveita e deixa a estrela ⭐ https://github.com/victorharry/wpp-sticker

To pensando em criar uns conteúdos legais com projetinhos do tipo no youtube, se inscreve lá pra dar aquela moral se te ajudei de alguma forma Dev Cansado (:

Toss a tabcoin to your Witcher 🪙🎶

Carregando publicação patrocinada...
3

Incrível! Você me inspirou para futuramente compartilhar também como fazer um bot rodando no terminal para telegram que fiz tempos atrás!
Há tempos também buscava como fazer algum bot que rodava assim para whatsapp e nunca havia achado algo tão bem escrito como o seu. Muito obrigado!

3
2
1
1
1
1
1

E aí, mano blz?

Muito top, fiz uma apai baseada nessa tua para aprender um pouco, e acabei recebendo um alerta sobre a possibilidade de banimento da conta por usar essa a libs (whatsapp-web.js, venom-bot), tu deu uma pesquisada sobre isso?
Queria saber do relato da galera.

Valeu demais!

2

Sim! O maior problema aqui é sobre spam de mensagens, em um periodo de tempo muitoo pequeno, entao provavelmente você fez algo do tipo. Já tenho um bot rodando faz mais de 2 anos e nunca tive esse problema, mas ja vi isso rolar com um amigo proximo quando ele estava spammando muitas mensagens, tipo 1000 mensagens em 1 segundo. Fora isso que eu falei é impossivel tomar ban. Então o problema aqui não são as libs e sim como você as usa.

1
1
1
1
1
1

Muito massa! tava pensando em fazer um com python (unica linguagem que eu sei) mas vou salvar esse post para fazer este projeto quando iniciar JS.

1

obrigado por compartilhar seu conhecimento!
onde eu poderia aprender mais sobre a criação de bots para whatsapp? tenho interesse em criar um que eu mande alguma tarefa e ele já envia automaticamente para o notion ou o lembretes do iphone

1
1

Reparei que quando você utiliza o link (Ninetales) o sticker vem com o fundo transparente e quando você anexa a imagem (Charizard) não é removido o fundo. Os 2 tem fundo branco porque só o via link fica transparente?

Espero que tenha ficado nitido minha dúvida

3

Fala mano, blz?

Quando você envia imagens pelo whatsapp ele converte para jpeg, o que nesse formato acaba perdendo a propriedade de "fundo transparente", já quando ele evnia o link, a api faz o download diretamente de onde está hospedado, no caso ele passou um link de uma imagem png (que esse formato permite ter o "fundo transparente") assim criando a imagem com o fundo transparente.

Resumindo: Quando envia como imagem pelo whatsapp ele converte a imagem e perde o fundo transparente, quando envia via link ele mantém essa propriedade.

1

Exatamente! Não cheguei a testar converter ela pra png, é até algo que vou tentar ver aqui agora, pq de fato seria o ideal. Valeu pelo insight Patrick

edit:

Tentei aqui com o Mimetype image/png e alterar o image.jpg para image.png mas sem sucesso.

2

victorharry algumas coisas que acho que seria legal, poder enviar media como documento e daí ter uma lista de extensões suportadas, porque assim a pessoa pode simplesmente selecionar que quer enviar um documento mas selecionar uma imagem png por exemplo.

Mas com seu tutorial já da uma base legal para fazer várias coisas.

Por exemplo usar o jimp para remover o background caso a pessoa passe um parâmetro, ex:
/sticker --transparent

lá no código verificar

if (msg.body.includes('--transparent')) removeBackground(image)
1

Que top! Obrigado pelo tutorial!

Você sabe onde (se existe) uma hospedagem gratuita para rodar esser bot sem depdender do terminal (e consequentemente sem depender do computador ligado)?

1
1

O que a galera fez com essa Lib foi magia, eu ainda fico de cara com o funcionamento dela, que é basicamente um Google Chrome rodando no fundo. Tem outra Lib que não usa o Puppeteer que é mais leve, a Baileys.

1
1
1
1
1

E a questão de Gifs e videos para figurinhas animada como fica, não consegui pensar em uma possibilidade de implementar isso, alguém tem alguma ideia?

1

Também estava procurando e tentando ter ideias para isso, minha solução está sendo tentar usar o ffmpeg para tentar converter

0