Categorias
Tecnologia

Criando um bot super simples para o Slack

Em uma das reuniões dessa última semana na empresa onde trabalho surgiu uma necessidade simples de comunicação: Precisamos que toda a equipe saiba quando um novo release de algum dos nossos repositórios for criado no Github.

Como usamos o Slack como ferramenta de comunicação interna, na hora já pensei:

“Esta é a minha chance de criar um bot para o Slack!”

Sempre tive vontade de fazer algo para o Slack, mas não tinha conseguido achar um tempo e nem um motivo específico para isso. Eu já imaginava que para esse objetivo, avisar sobre um novo release, não seria algo complicado.

Realmente não foi. Em apenas algumas linhas deu pra criar um bot que conecta os webhooks do Github e do Slack utilizando o Flask como meio-campo.

Abaixo o código final da primeira versão.

# coding: utf-8
import os
import requests
from flask import Flask
from flask import request

app = Flask(__name__)

slack_webhook_url = os.getenv('SLACK_WEBHOOK_URL')

@app.route("/", methods=['POST', ])
def webhook():
 action = request.json['action']
 release = request.json['release']
 repository = request.json['repository']

slack_data = {
 "text": "A new release from *{repo_name}* was {action}!\n"
         "Click <{release_url}|Release {tag_name}> for more details".format(action=action,
           repo_name=repository['name'],
           release_url=release['url'],
           tag_name=release['tag_name'])
}

response = requests.post(slack_webhook_url, json=slack_data)

if response.status_code != 200:
 raise ValueError(
   'Request to slack returned an error {}, the response is:\n{}'.format(response.status_code, 
      response.text)
 )

return ""

Pelo pouco tempo que passei lendo sobre como fazer um bot para o Slack eu entendi que você cadastra um Incoming Webhook e eles geram uma URL a qual você irá executar um request do tipo POST enviando a mensagem que você quer que um canal específico receba.

É realmente muito simples, porque a própria URL já carrega os tokens que são gerados para você.

Existem diversas outras funcionalidades que podem ser criadas em um bot para o Slack e a documentação deles cobre tudo. Mas vou falar apenas desse pequeno release-alert que criei.

Explicando linha por linha

Antes de começar a escrever o código vou precisar do Flask e de alguns outros pacotes. Então começo ainda na linha de comando do shell.

$ pip install Flask
$ pip install requests

Depois eu coloco a URL que gerei no Incoming Webhooks do Slack em uma variável de ambiente que chamo de SLACK_WEBHOOK_URL. Depois basta importá-la para dentro do código.

$ export SLACK_WEBHOOK_URL=<aqui vai a url do webhook do slack>

Agora crio meu arquivo Python chamado bot.py. Como estou usando o Flask, só vou precisar desse arquivo e praticamente nada mais.

Nas primeiras linhas começo importando o que vou utilizar e criando o app do Flask.

import os
import requests
from flask import Flask
from flask import request

app = Flask(__name__)

Trago para dentro do código a variável de ambiente que criei antes.

slack_webhook_url = os.getenv('SLACK_WEBHOOK_URL')

Agora vou começar a montar o meu endpoint. Ele receberá um evento POST enviado pelo webhook do Github. Para que isso aconteça você precisa cadastrar uma URL de webhook no settings do seu projeto no Github.

No meu caso, eu cadastrei a webhook no settings da organização, já que queria que todos os projetos da empresa disparassem o aviso. Mas funciona do mesmo jeito em qualquer um dos casos.

Quando cadastrei o meu webhook no Github especifiquei que gostaria de receber apenas os eventos relacionados ao release dos projetos.

Para testar o código localmente eu utilizei o ngrok. Explico como usar o ngrok em outra publicação.

@app.route("/", methods=['POST', ])
def webhook():

As primeiras linhas do meu endpoint capturam as informações que eu preciso do corpo enviado pelo POST do webhook do Github.

 action = request.json['action']
 release = request.json['release']
 repository = request.json['repository']

O Flask facilita recuperar informações de um corpo de um request JSON com o seu objeto request nativo. Basta chamar request.json e ele retorna um dicionário.

Agora eu vou montar o corpo da mensagem que enviarei para o Slack. O formato pedido é muito simples: um JSON com um campo ‘text’.

slack_data = {
 "text": "A new release from *{repo_name}* was {action}!\n"
         "Click <{release_url}|Release {tag_name}> for more details".format(action=action,
            repo_name=repository['name'],
            release_url=release['url'],
            tag_name=release['tag_name'])
}

Esse dicionário será transformado em um JSON pela próxima linha. O pacote requests já resolve isso para mim através do argumento json.

response = requests.post(slack_webhook_url, json=slack_data)

if response.status_code != 200:
 raise ValueError(
   'Request to slack returned an error {}, the response is:\n{}'.format(response.status_code, 
       response.text)
 )

return ""

No final do arquivo estou apenas tratando algum possível erro. Caso o requests retorne um status_code diferente de 200 eu levanto uma exceção.

No final retorno uma string vazia, porque cada endpoint do Flask precisa retornar alguma coisa para não levantar erros.

Para que meu bot fique disponível o tempo todo, fiz um deploy na minha conta gratuita do Heroku. E voilá!

Categorias
Tecnologia

Como fazer tunelamento de localhost de forma segura

Veja como expor seu servidor local para a internet e para que serve isso

O tunelamento do localhost é uma maneira de ter um “link externo” que aponte para alguma aplicação que você esteja rodando localmente. Dessa forma podemos “expor” nosso servidor local de forma segura.

Mas por que eu iria querer isso? Podemos usar essa solução para diversas situações, principalmente no desenvolvimento web. Vou mostrar alguns exemplos de uso nessa publicação.

Para os exemplos a seguir eu estou usando o ngrok, um software que facilita muito isso e ainda mantém essa exposição totalmente segura.

Mostrar um desenvolvimento em andamento para o cliente

Digamos que você esteja desenvolvendo um site ou um sistema web para um cliente e quer mostrar o que você desenvolveu até o momento. O mais comum seria fazer o deploy do trabalho em andamento em um servidor web e disponibilizar o link para seu cliente.

Mas existe uma outra opção, podemos deixar o site rodando localmente e tunelar com o ngrok.

Você pode iniciar um servidor local com o SimpleHTTPServer do Python, por exemplo, e rodar o ngrok na linha de comando, como no exemplo abaixo.

$ python -m SimpleHTTPServer 8000
Serving HTTP on 0.0.0.0 port 8000 ...

Em outra aba do terminal você inicia o tunelamento.

./ngrok http 8000

Agora ele irá exibir o endereço que ficará disponível para seu cliente pela internet. Será algo como http://36096fff.ngrok.io.

Ao rodar, o ngrok vai aparecer assim no seu terminal…

Estamos iniciando um servidor HTTP local na porta 8000. Perceba que o comando de tunelamento recebeu os parâmetros http e 8000, indicando que é um servidor http e que está usando a porta 8000.

Testar um chatbot durante o desenvolvimento

Durante o desenvolvimento de um chatbot para o Facebook Messenger, por exemplo, não é possível testar sem um “endereço web”. É preciso que seja registrada uma URL nas configurações do seu chatbot do Messenger para que ele receba os eventos de mensagem.

Para entender melhor sobre isso, veja este artigo.

Para que você não precise fazer deploy de cada pequena alteração em um servidor web para testar no seu chatbot, crie um tunelamento, como no exemplo anterior, e registre o endereço gerado na seção webhook nas configurações do chatbot no Messenger.

Obs: Nem todos os aplicativos de mensagem se utilizam de webhooks para receber os eventos. No caso do Telegram, como neste link, não é necessário utilizar o tunelamento.

Testar endpoints de webhooks

Eu falei em webhooks no item anterior. Pra quem não sabe o que é, segue uma tradução livre de uma parte do artigo da Wikipedia:

Webhooks são “retornos de chamada HTTP definidos pelo usuário”. Normalmente eles são ativados por algum evento, como o push de código para um repositório ou um novo comentário postado em um blog. Quando ele acontece, o site origem faz uma requisição HTTP para a URI configurada para o webhook, enviando os dados do evento.

Existem diversos serviços que utilizam esse formato para enviar dados de eventos. Um bom exemplo é o Sendgrid ou o Mandrill, que usam webhooks para enviar os eventos de email (lido, marcado como spam, link clicado, etc.) para um sistema de terceiros que esteja usando sua API.

Outro bom exemplo são integrações com gateways de pagamento, como Iugu, PagSeguro ou PayPal, onde, mesmo durante o desenvolvimento, você precisa de um “endereço web aberto” para receber os eventos relacionados aos pagamentos, alterando o status de uma compra, por exemplo.

Para isso, abra um tunelamento com o ngrok e registre o novo endereço gerado por ele com o seu endpoint para receber os eventos webhook do serviço que você está utilizando.

Painel do ngrok

Uma funcionalidade interessante do ngrok é o seu painel, ou interface web.

Screenshot da interface web

Com ela você vê todas as requisições que foram feitas ao seu endereço web aberto. Com isso você pode verificar os dados que estão vindo com as requisições e ainda dar um “replay” na mesma, para testar novamente.

Para acessar, veja o endereço listado no terminal do ngrok como Web Interface e abra no seu navegador. Vai ser algo como http://127.0.0.1:4040.

Concluindo

Esses são alguns casos de uso para o tunelamento de localhost. Alguns deles eu já utilizei, como o teste de webhooks e a demonstração de desenvolvimento em andamento para cliente. Mas eu descobri mesmo que isso era possível ao ler um tutorial de criação de chatbot para o Facebook Messenger, então resolvi dar esse exemplo também.

Publicado originalmente no Medium.