Building a Slack Bot with Node.js Microservices
This was a fun exercise, I learned a little bit about Slack as well as quite a lot about NLP (Natural-language processing).
Index
The contents are as follows:
- NLP
- Requirements
- Node.js
- Slack
- Wit
- Slack and Wit Secrets
- Time Service
- Weather Service
- Privacy
- To Do
- Credits
NLP
Like a lot of people, I learned a certain amount of programming from the old text-based computer games.
I knew that I had learned some Basic and Fortran there, also some GMAP (an obscure assembly language, or - specifically - GCOS Macro Assembler Program). But I hadn't realized that I also learned about NLP:
A threatening little dwarf bars your way. He throws an axe at you, but misses.
> kill dwarf
I'm sorry, but I don't know how to do that. Perhaps there is a weapon nearby?
> use axe
You don't have an axe!
> take axe
OK
> use axe
I'm sorry, but I don't know how to do that.
> throw axe
You missed!
> take axe
OK
> throw axe
You missed!
[If anyone is interested, this exchange occurred in the text-based game Colossal Cave Adventure.]
Things have changed in the many years that have elapsed since then, but I'm not sure they've changed all that much. The slackbot we will implement here is very reminiscent of Eliza - which was an early natural language processing program.
Requirements
A GitHub account will be needed, as well as a Google Cloud Platform account.
Node.js
The Node.js modules will use the @slack/client, express, superagent and moment frameworks.
Slack
For the Slack portion, we will create a real-time messaging (RTM) client which will use websockets.
We will also create a bot user in Slack. This will create a Slack token.
Wit
We will create and train a natural-language processing (NLP) client with Wit.ai.
In order to do this, it will be necessary to sign in with a GitHub account.
We will need to train our client to recognize Intents (I have been unable to find a good definition but broadly speaking the main concept of a question or statement. Intents will also be important for AWS Alexa).
Once our client has been trained, we will need to create a Wit token.
Time
Some sample questions to train the time intent.
Weather
Some sample questions to train the weather intent.
Slack and Wit Secrets
We will embed our Slack token and our Wit token in a secrets.json file as follows:
{
"slackToken" : "xoxb-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"witToken" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
Time Service
To determine the requested time, we will geolocate the location and then request its time offset.
To do this we will use Google's Geocoding API and Google's Timezone API.
It will be necessary to sign in with a Google Cloud Platform account.
Google's Geocoding documentation:
http://developers.google.com/maps/documentation/geocoding/start
Google's Timezone documentation:
http://developers.google.com/maps/documentation/timezone/start
The tutorial recommends creating two API keys, one for each service however we will use the same key for both.
We will also restrict our GCP project to only these two APIs:
Google Secrets
We will embed our Google token in a secrets.json file as follows:
{
"googleToken" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
This file must be created in the Iris-time directory. Note that this is not a valid token!
Weather Service
To determine the requested weather, we will use the OpenWeatherMap API.
OpenWeatherMap Secrets
We will embed our OpenWeatherMap token in a secrets.json file as follows:
{
"openWeatherMapToken" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
This file must be created in the Iris-weather directory. Note that this is not a valid token!
Privacy
Wit.ai was acquired by Facebook in 2016.
If you are at all concerned about Facebook and their concern for user privacy or the uses to which Facebook puts its data, this might be something to bear in mind.
Wit.ai publishes its privacy policy and also has a BLOG.
Facebook are the creators of React and React native.
To Do
- Add a note about Wit.ai ownership and privacy policy
- Add links for express, superagent and moment frameworks
- Replace console logging [
console.log("listening");
] with either util logging or a package like bunyan or winston. - Check for duplicates from the Google Geocoding (Lat/Long) lookup and if found, request a more specific location.
- Update the Service Registry to allow for proxies (currently assumes all services are directly reachable).
- Update the Service Registry to more randomly return matching services for load-balancing purposes (rather than simply the first one that matches).
- Update the Weather API service call to either use City ID or Lat/Long (from Google) instead of City Name.
Credits
Based upon:
http://www.lynda.com/Node-js-tutorials/Building-Slack-Bot-Node-js-Microservices/509406-2.html
This tutorial is worth viewing for some great insight into how to structure the code in a Node.js project.