There has been an awakening. Bots, slack bots have taken over and they are everywhere.
Build a slack bot and deploy on heroku
Bot: Why would you want to be something more than a machine?
Me: Because I choose to
Bot: Why do you choose to exist?
Me: Because I can
If you use slack you know what I am talking about. Automation, integrations and bots, these are the things which MAKE slack. And recently I was in need of one. I named it jared(silicon valley). I tell jared who is supposed to do what along with the deadlines, and it does the rest. Jared will message you after every 4 days if the task is still pending, he will post on channel your task status, and will ask you “Why do you choose to exist?”. Its a pretty basic bot which does what it’s told but while making it I learned about
- node library of Slack
- Use mongodb on heroku without shelling out anything
- A few heroku specific hacks for bots
- Do a
git init
beforeheroku create
Get the token
The first thing I did was to just start right away. To build a bot you have to have an
access token. So just go here and choose ‘Make a custom integration’.
Choose ‘Bots’ on the next screen and after that you know the drill.
Get the library
Once I acquired the token, I ran straight for a reliable node library for slack bots.
And found this. This library is I guess
the de facto for making bots and in case its not then it should be. The lack of documentation
worried me a little but just looking around and reading the source as well as the sample
code in ‘examples’ made things quite clear.
My notes on using the library
slack = new Slack(token, true, true)
The slack variable is your window to the slack world of yours. It has three main events
- open
- message
- error
message
being the most important one. This event will be fired whenever your bot receives a message.
Your bot receives a message when people directly contact it or when people post to a channel/group the bot
is part of.
slack.on 'message', (message) ->
The message object tells you important details such as the source channel and the user who sent it.
slack.getDMByName ($name)
returns an instance of channel. And you can use this channel to send a message
like this channel.send "Hi"
. Same is the case with slack.getChannelByName ($name)
, slack.getGroupByName ($name)
.
This will make it more clear. Actually just use this as a template.
Start with heroku deployment
Next problem I faced was with heroku create
(actually it was my fault). I didn’t initialize my project with
git. So git push heroku master
was pretty useless. Bottom line, do a git init first and then start working on
your app.
Signup on heroku if you have’t and read their ‘getting-started-with-nodejs’. Their notes are perfect and cover everything that is needed.
Heroku slack bot problems
The first time deployed the app, it crashed after a minute. The error was “Web process failed to bind to $PORT within 60 seconds of launch”. Quick google search revealed that heroku assigns a dynamic port to your app and tries to bind to it. Since all I had was a slack bot so there was no server in my code. I wasn’t listening to any connections.
Lets say if I had been listening, then there is this dyno sleeping rule they have, that would have made my bot pretty much useless(I have a free plan and I hardly pay for anything, except Apple Music. I’d pay for that).
If an app has a web dyno, and that web dyno receives no traffic in a 30 minute period, the web dyno will sleep. In addition to the web dyno sleeping, the worker dyno (if present) will also sleep.
If a sleeping web dyno receives web traffic, it will become active again after a very short delay. If the app has a worker dyno that was scaled up before sleeping, it will be scaled up again too.
And interacting with the bot or sending it messages doesn’t count as traffic. So no matter what, your bot will go
down after 30 minutes.
Killing 3 agents with one Matrix style punch.
Agent 1: “Web process failed to bind to $PORT within 60 seconds of launch”
Agent 2: Bot dies after 30 minutes
Agent 3: I need a clock in my code. I need to check pending tasks regularly and check their status.
Matrix style punch: Get a server in your code and ping it after every 25 minutes.
Killing Agent 1: Since you have a server running on process.env.PORT
(the port heroku assingned to your app),
heroku is able to bind to it. Agent killed.
Killing Agent 2: The strobe
function is called every 25 minutes because of setInterval strobe, 25*60*1000
.
And strobe
in turn requests your app through its url. So your app can never be idle for 30 minutes, it will always receive some traffic(one request at least) before the timer runs out.
Killing Agent 3: Added my task checking stuff in the strobe function. So everything is checked every 25 minutes.
Edit: One might say that simply use a worker dyno, that would prevent this ‘unable to bind error’. Yes that would prevent that from happening but when you use a worker dyno then the time your script/code is running is counted as active time. And on a free dyno, your code can run for only 18 hours. So, if you use a worker dyno for the bot, it will be put to sleep for at least 6 hours per day, as that code would be running continuously. But when you use a web dyno, the time your code serves requests is counted as active time. Since it’s just every 25 minutes, you will never reach your quota limit. Which would mean that your bot would never sleep.
MongoDB on heroku
MongoDB addon by MongoLab needs you to provide card details, just to verify. And in case you don’t want
to do that, just go to monogolab’s site. MongoLab is MongoDB as a Service. Signup for the
free plan and you get 500MB storage. Make a database there and you’ll get a URI which you can use for
remote access. It looks like this
mongodb://<dbuser>:<dbpassword>@ds<x>.mongolab.com:<x>/your-db
To use mongo in my app I chose mongojs. It’s a really good library and emulates the standard MongoDB API. For example:
So that was that. The bot is on heroku 24/7 doing stuff for me. It was fun and I learned coffeescript too while making it. It’s a cool flavor of node, and coming from a scala background, I could relate. I hope these tips come handy on your next slack bot adventure.