Mi primer bot en Slack
Tags: node, javascript, slack, netlify
Published: 2020-11-13 19:47:52

---
title: Mi primer bot en Slack
published: true
date: 2020-11-12 00:00:00 UTC
tags: node,javascript,slack,netlify
canonical_url: https://jorge.aguilera.soy/blog/2020/mi-primer-slack-bot.html
---

Slack es una herramienta de comunicación de equipos muy utilizada tanto en proyectos abiertos como en entornos laborales. Aunque las comunidades que conozco lo han ido abandonándolo por otras soluciones más ligeras, creo que la presencia en entornos labores es aún muy importante.

Entre las características típicas de mensajería de uno a uno, en grupo, canales, videollamadas, etc se añade un ecosistema de aplicaciones muy amplio así como formas de integrar procesos propios de la empresa en él de tal forma que podamos crear nuestras propias aplicaciones que actuarán como un miembro más del equipo, reaccionando ante eventos, escribiendo en los canales, etc.

En este post voy a explicar de forma resumida cómo podemos hacer un bot que responda a un comando enviado por los usuarios. En Internet hay tutoriales muy completos y la propia documentación de Slack es bastante extensa con ejemplos y herramientas de testeo, por lo que aquí vamos a ver algo muy sencillo pero que podrás instalar y adaptar en el workspace de vuestro slack (si tenéis permisos para ello)

Por otra parte, como el bot tiene que ejecutarse en algún sitio, voy a contar cómo podemos usar Netlify para alojarlo. Netlify proporciona diferentes tipos de cuenta donde alojar tus proyectos, siendo la gratuita muy interesante:

- ilimitados proyectos de contenido estático

- integración con los principales repositorios (Github, Gitlab,…​)

- despliegues automáticos (o manuales con posibilidad de revisión previa)

- ejecución de funciones Serverless (Lambdas de Amazon) 125.000 al mes

- formularios inteligentes (ni idea, no los he probado todavía)

Así pues para este post vamos a necesitar:

- Una cuenta en Netlify, la gratuita nos sirve de sobra

- Un workspace en Slack (prueba primero en un workspace nuevo y si te mola instalas el bot en el de la empresa)

- Node para desarrollar.

<dl>
<dt>INFO</dt>
<dd>
<p>Como bola extra podríamos enlazar la cuenta de Netlify con nuestra cuenta en Gitlab/Github para desplegar
automáticamente cuando actualicemos el repo. Por ahora lo haremos manualmente)</p>
</dd>
</dl>

Además para desarrollar en nuestro local vamos a tener instalado `npm` y el cli de Netlify `netlify-cli`([https://docs.netlify.com/cli/get-started/](https://docs.netlify.com/cli/get-started/))

Por último `ngrok` es una herramienta muy útil para probar en local nuestro bot antes de subirlo a producción. La cuenta gratuita es suficiente, con el único inconveniente de que cada vez que mates el proceso `ngrok` te cambia la url y tienes que reconfigurar en slack donde está tu bot.

## Politicamente Correcto Bot

El bot a desarrollar es realmente sencillo y servirá para que ante solicitudes por parte de algún compañero para realizar alguna tarea podamos soltar un exabrupto y que el bot nos lo cambie por una frase políticamente correcta.

Básicamente cuando escribamos el comando `/hastalapolla` (o el que quieras implementar) el bot se activará y en lugar de este comando se mandará al canal una frase más adecuada seleccionada aleatoriamente de una lista de candidatas.

La utilidad del bot es más bien poca salvo para servir como punto de partida de algunas funcionalidades más complejas que se te puedan ocurrir

Así mismo debido a la simplicidad del bot no requeriremos de ninguna librería ni framework extra de las existentes.

## Arquitectura

 ![](https://jorge.aguilera.soy/images/1605291701474.svg)

## Entorno

Debemos asegurarnos que tenemos npm instalado:

`npm -v`

así como que hemos instalado el cliente de Netlify:

`netlify -v`

y hemos hecho login a nuestra cuenta con él

`netlify login`

## Creando proyecto

En un directorio limpio inicializaremos el proyecto:

`npm init`

proporcionando un nombre, version, etc por defecto (si vas publicar el código tal vez sí te interese rellenar esta parte más detenidamente)

con lo que tendremos un fichero `package.json` parecido a:

package.json

```
{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
```

así mismo crearemos un subdirectorio `public` donde crearemos un fichero `index.html` con el contenido que quieras (si quieres hacer un landing page para tu bot, este es tu directorio)

```
<html><body>HastaLaPolla Slack bot</body></html>
```

Y por último crearemos un fichero `netlify.toml` para configurar a netlify:

netlify.toml

```
[build]
  functions = "functions"
  publish = "public"
```

Ejecutaremos `netlify` para comprobar que tenemos la infra preparada

`netlify dev`

lo cual nos abrirá la página `index.html` en un navegador

Paramos el proceso y procedemos a crear la función para nuestro bot

## Function

Crearemos nuestra primera función

`netlify function:create`

- seleccionamos hello-world (total, luego lo vamos a cambiar por nuestro código)

- como nombre especificaremos `hastalapolla`

lo cual nos creará un subdirectorio y un fichero JS en él

y procedemos a probar de nuevo que vamos bien

`netlify dev`

y desde el navegador accederemos a `http://localhost:8888/.netlify/functions/hastalapolla`

## Ngrok

Una vez que te hayas creado una cuenta en ngrok y descargado el ejecutable podemos crear un tunel entre el `netlify` que está corriendo en tu máquina con el mundo exterior:

`ngrok http PUERTO_NETLIFY_FUNCTION`

<dl>
<dt>WARNING</dt>
<dd>
<p>Como no estoy seguro que Netlify siempre escuche en el mismo puerto para ejecutar las
funciones te toca revisar el que te muestre a tí. En mi caso es el 37947</p>
</dd>
</dl>

`ngrok` te muestra dos URLs (http y https) que son diferentes cada vez que lo ejecutes. Copia la direccion https y prueba a cambiarla por localhot:8888 en la prueba anterior, por ejempo[https://a9123123xxxxx.ngrok.io/.netlify/functions/hastalapolla](https://a9123123xxxxx.ngrok.io/.netlify/functions/hastalapolla)

## Slack

Ahora avanzaremos un poco por el lado de Slack.

<dl>
<dt>INFO</dt>
<dd>
<p>Lo mejor es crearse un workspace en blanco donde poder instalar y depurar el bot antes de intentarlo en el
de la empresa.</p>
</dd>
</dl>

### App

Lo primero que haremos será crear una App desde [https://api.slack.com/apps](https://api.slack.com/apps) donde deberemos indicar el nombre y workspace donde queremos crearla.

<dl>
<dt>WARNING</dt>
<dd>
<p>Desconozco todas las funcionalidades que ofrece una App de Slack (espero irlas descubriendo) pero para este
bot vamos a necesitar lo mínimo</p>
</dd>
</dl>

### Command

Nuestro bot es tan simple que lo único que va a hacer (por ahora) es reaccionar a un comando `/hastalapolla` por lo que lo daremos de alta en la seccion `Slash Commands` y rellenaremos los campos que nos pide:

 ![hastalapolla1](https://jorge.aguilera.soy/images/2020/slack/hastalapolla1.png)

Figure 1. formulario.png

En Request URL prestaremos especial atención para poner la URL que nos generó ngrok ( **la https** )

## Workspace

Una vez configurado el comando podemos proceder a probarlo desde el workspace donde lo hemos instalado, por ejemplo ejecutando el comando en el canal #random

`/hastalapolla`

Si todo está bien configurado, Slack nos debería ir completando el comando según lo escribes y se enviaría al canal tal cual

## Hastalapolla

Es hora de añadir un poco de código a nuestra function

<dl>
<dt>WARNING</dt>
<dd>
<p>No cortes <code>ngrok</code> o te tocará volver a lanzarlo y reconfigurar la URL en Slack</p>
</dd>
</dl>

Sustituiermos la funcion `hastalapolla.js` por esta:

```
const querystring = require("querystring"); (1)
const axios = require("axios");

const { SLACK_BOT_TOKEN } = process.env; (2)

const list = [
  ':thumbsup: no te preocupes, ahora mismo me pongo con ello',
  'vale, termino una cosa :watch: y me pongo con ello asap',
  'uff, bueno, lo miro y te digo algo',
  'ahora mismo me pillas un poco ocupado, pero en cuanto pueda te cuento',
  'Genial, no te preocupes, ya te cuento luego',
]

const handler = async (event) => {

  if (event.httpMethod !== "POST") {
    return { statusCode: 405, body: "Method Not Allowed" };
  }

  const params = querystring.parse(event.body);

  const selected = list[Math.floor(Math.random() * list.length)]; (3)

  const data = {
    text: selected,
    channel: params.channel_id,
    as_user: true
  };

  const result = await axios.post('https://slack.com/api/chat.postMessage', data, { (4)
    headers:{
      'Authorization': `Bearer ${SLACK_BOT_TOKEN}`,
      'X-Slack-User': params.user_id
    }
  })

  return {
    statusCode: 200 (5)
  }
}

module.exports = { handler }
```

| **1** | Las únicas dependencias que usaremos |
| **2** | No hemos visto todavia el token ni para que sirve, lo haremos a continuación |
| **3** | La frase aleatoria a enviar |
| **4** | Con un "simple" post enviaremos la frase políticamente correcta al canal en nombre del usuario |
| **5** | con un 200 le decimos a Slack que hemos ejecutado su comando. Si añades texto lo leerá el sólo el usuario |

Como puedes ver son 15 líneas excasas de Javascript donde lo más interesante es que utilizamos un paquete de node muy popular para enviar el post (podíamos haberlo hecho usando puro node)

Simplemente instalaremos las dependencias indicadas:

`npm install --save axios`

`npm install --save querystring`

lo cual nos modifica nuestro `package.json` tal que:

```
{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^0.21.0",
    "querystring": "^0.2.0"
  }
}
```

Y podremos probar de nuevo a enviar el comando desde nuestro workspace de Slack. Si todo va bien NO veremos NADA en el canal mientras que en la consola donde está corriendo Netlify veremos que ha llegado la petición.

Simplemente es que estamos intentando enviar un mensaje a un canal sin estar autentificados.

## Token

Para que el bot pueda escribir en un canal hay que darle permisos. Para ello iremos a "OAuth&Permissions" y añadiremos los scopes que muestra la imagen (como bot los scopes `chat:write` y `commands` y como user `chat:write`)

 ![hastalapolla2](https://jorge.aguilera.soy/images/2020/slack/hastalapolla2.png)

Figure 2. scopes.png

Así mismo copiaremos el token de bot que se nos muestra al principio `xoxb-XXXXXXXXXXXXXXXXXXXXXx`

Vamos a proceder a ejecutar de nuevo la consola de `netlify` pero ahora proporcionandole el token copiado para que el bot pueda escribir en el canal. (Desconozco cómo se hace en Window$)

`SLACK_BOT_TOKEN=xoxb-XXXXXXXXXXX netlify dev`

| | Seguramente tendrás que reconfigurar de nuevo `ngrok` y la consola de la app con la nueva url generada. Ten en cuenta que esto es así porque vamos paso a paso incrementando la aplicación, una vez lo tengamos todo no sería necesario más que una vez. |

Y probamos de nuevo a enviar el comando /hastalapolla

Si todo ha ido bien ahora tendremos un mensaje políticamente correcto en el canal.

## Deploy

Es hora de subir nuestra aplicación a Netlify y dejar que se ejecute en la capa gratuita (recuerda, tienes hasta 125K llamadas al mes)

`netlify deploy`

y crearemos un nuevo site donde desplegar la aplicacion. Netlify elegirá un nombre aleatorio lo cual es bueno para nuestro bot, aunque si lo prefieres luego lo puedes cambiar por otro que este libre.

Simplemente resta configurar el nuevo site creado con la variable SLACK\_BOT\_TOKEN para lo que desde la consola de Netlify iremos a build, environment y crearemos la variable con el valor del token (de la misma forma que hicimos por consola en el paso anterior)

Una vez configurado deberemos realizar un nuevo deploy para que tome la variable creada. Simplemente desde la consola de Netlify iremos a build y seleccionamos redeploy.

Por ultimo sólo resta decirle a Slack dónde encontrar ahora el bot para el comando tal como hacíamos con 'ngrok'

<dl>
<dt>TIP</dt>
<dd>
<p>Yo lo que hago es tener un comando "test" que apunta al entorno local con <code>ngrok</code> y el "oficial" que apunte a Netlify</p>
</dd>
</dl>

Si todo ha ido bien, una vez configurado, cada vez que ejecutes el comando /hastalapolla estarás invocando a la función alojada en Netlify por lo que no necesitas ya tu entorno de desarrollo levantado.

## Bola extra

Puedes alojar tu proyecto en un repot git en Gitlab o Github y "enlazarlo" con Netlify de tal forma que cada vez que hagas un push se despliegue automáticamente, pero eso es para otro post (Si estás interesado simplemente comentamelo y lo vemos)