# Hubot + ES6 + Promises

**Date:** 2018-01-19  
**Author:** Kees C. Bakker  
**Categories:** Chatops, Node.js  
**Tags:** Hubot, Slack  
**Original:** https://keestalkstech.com/hubot-es6-promises/

![Hubot + ES6 + Promises](https://keestalkstech.com/wp-content/uploads/2020/06/2018-01-18_18371.png)

---

Lately we've been playing around with ChatOps at wehkamp. We added a [Hubot](https://hubot.github.com/) to our Slack channels to automate some operational jobs. It makes work more fun and way easier. As it is hosted in our own infrastructure, it can interact with our micro-services.

Consuming an API-endpoint is easy with Hubot. In this article I'll explore how by responding to the word "Norris" with a quote from the [Internet Chuck Norris Database](http://www.icndb.com/).

I will demonstrate how to:

- use JavaScript instead of CoffeeScript
- consume a simple JSON webservice endpoint
- leverage the ES6-style Promise to build a nice chain.

Building stuff for Hubot is really easy!!

![](https://keestalkstech.com/wp-content/uploads/2018/01/hubot1.jpg)
*GitHub created Hubot back in 2011 to automate many of their tasks.*

## I like to drink my coffee, instead of scripting it

I'm sure CoffeeScript has its uses, but it's not for me. I like to do my programming in standard ES6 JavaScript (or TypeScript nowadays). Fortunately Hubot understands `.js` scripts just as well as `.coffee` scripts.

Hubot provides its own HTTP client to talk web-services. Let's wrap a `GET` request with an [ES6 **Promise**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) using [function arrow expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#Arrow_functions) and convert the result to a JSON object:

```js
const norrisUrl = 'https://api.icndb.com/jokes/random';

// wrap with promise
new Promise((resolve, reject) => 
    robot.http(norrisUrl).get()((err, response, body) =>
        err ? reject(err) : resolve(body)
    )
)

// parse to js object
.then(body => JSON.parse(body))
```

Promises can make asynchronous programming easier. When chained together they create a neat pipeline. Another advantage is error handling. We can add a `.catch(err => { })` at the end of the chain to catch any errors that might occur during the processing of the endpoint data.

## Let Hubot listen in

Hubot uses a regular expression to "hear" commands. We want to respond to phrases that contain the word *Norris*. The following regular expression will do so: `/Norris/i`. This expression will respond to "norris", "Norris" and even "noRRis" (due to the `/i`).

The response (`res`) object can echo a `reply` to the channel. Here is the code:

```js
const
    norrisUrl = 'https://api.icndb.com/jokes/random',
    decode = require('decode-html');

//the export is used to init the bot
module.exports = (robot) => {

    //listen to phrases that contain "Norris"
    robot.hear(/Norris/i, (res) => {

        //wrap the HTTP get call as a Promise
        new Promise((resolve, reject) => 
            robot.http(norrisUrl).get()((err, response, body) =>
                err ? reject(err) : resolve(body)
            )
        )
        
        //parse to js object
        .then(body => JSON.parse(body))

        //get joke - jokes may have stuff like "
        .then(json => decode(json.value.joke))

        //reply joke
        .then(joke => res.reply(joke))

        //problems? Annoy the user with the problem
        .catch(err => res.reply('Not even Chuck Norris can deal with this one: ' + err));
    });
};
```

The promise allows us to build a nice chain of pluggable operations. It feels a bit like overkill for this example as the JSON parsing, decoding and replying can be done in 1 `then`. Yet it has a nice "ring" of separation of concern to it.

## And action!

When I run the bot, it responds to my chats:

![](https://keestalkstech.com/wp-content/uploads/2018/01/2018-01-19_1520.jpg)
*Hubot reacts to mentions of Chuck Norris.*

Super fun. Super simple.

### PS. Be careful with hearing too much

When you have 2 bots using `hear` on the same topic and respond with a hear keyword, you might get into trouble. I had to kick these 2 bots discussing Chuck Norris facts out of the channel:

![When 2 bots discuss Chuck Norris.](https://keestalkstech.com/wp-content/uploads/2018/01/botsing.gif)
*2 versions of Hubot reaction to each other... this can go on for while...*

We've mitigated this by checking if the sender of a certain message is a bot or not.

Do you want to know more about our Hubot? Read [Jump-starting Slack bot projects: bot-zero](https://keestalkstech.com/2018/08/jump-starting-slack-bot-projects-bot-zero/).

## Changelog

2022-08-18 😳 Many typos.
