/gifsuggest slash-command

Categories AWS, Docker, Lambda, RealTimeMessaging, Slack

We have all heard of IaaS, SaaS and PaaS offerings. But I recently came across AWS Lambda, which I would like to define as RaaS (Runtime as a Service). So what AWS lambda provides is an execution environment for running NodeJS and Python code in a completely Serverless/Stateless manner. which means all we have to do is write code that conforms to the specs of a lambda function and let AWS handle the scaling and execution of the code. The good news being that it integrates well with many AWS services and you get billed only for the compute time you use. You can trigger a Lambda function in response to many events such as an S3 upload or a change in a Code Commit repository. Since I wanted to play around with this technology I thought of building a slash command that suggests gifs for a given term. The solution architecture for this application would be as follows.

many moving parts
many moving parts

So the sequence of events is as follows.

  1. When we type in /gifsuggest "something" slack makes a POST request to our app, providing us with lots of information such as the user, team, channel etc. They also provide a response_url whos purpose I will explain later.
  2. Using the nginx config on my VPS I redirect the request to a containerized express app.
  3. Slack user experience guidelines enforce a rule which states that a response must be made in 3000ms or else the command is considered a failure. Which is why at this time I just send some placeholder text immediately to slack.
  4. The next step is we POST the search term and the response url to an API Gateway endpoint.
  5. The API Gateway is what triggers the execution of our lambda function.
  6. The lambda function GETs gifs using the giphy api.
  7. Finally using the response_url from earlier we POST the gifs and create a slack message. Slack allows us to use the same response url to create 5 messages in half an hour.

Below is the slash command in action.

Slash command in action

Now let’s get into the code. There are many moving parts in this application so I will show each microservice in the order of which they execute. The first is the express app that quickly replies to slack and then starts the lambda function. I have called this service slack-lb.

This app is run in an alpine Linux docker container with a nodejs environment.
The next microservice is the Lambda function itself.
There are 2 main parts of invoking a lambda function in javascript.

  1. Event: This contains the data that is being passed into the invocation.
  2. Context: This contains the lifecycle information of the lambda function such as execution time remaining and other lifecycle hooks.

Amazon is nice enough to provide a NodeJS library that registers the AWS lambda context as an Express middleware. This makes migrating existing express apps to Lambda very easy. We just need to write a handler as follows.

and then register middleware in our express app.

To deploy the lambda function all we need to do is create a zip file with the node modules, the handler and the express app files and then upload them on AWS.

Benefits of Lamda:

  1. No need to manage any infrastructure.
  2. Automatic scaling.
  3. Easy monitoring using cloudwatch.

Issues with Lambda:

  1. Currently only supports NodeJS 4.3
  2. Only supports stateless applications
  3. No support for sending files

Scope for improving this project:

  1. Right now once gifs are sent the user still has to copy the url and paste it at the destination there should be a way to forward the gifs using message buttons.
  2. The app is using a public api key for giphy which is rate limited and not peak performance. Must get a production key
  3. Migrate the proxy slack-lb app into its own lambda function.

PS: A lot of people make this mistake but GIF stands for Graphical Interchangeable Format. which would mean that it is gif and not jiff.
P.P.S: Like everything I do this is opensource. Feel free to contribute

Pokemon Go Slack-Bot.

Categories NodeJS, RealTimeMessaging, Reverse Engineering, Slack, Webhooks

This is my first controversial post on this blog. This week I developed a slack-bot that could notify a channel whenever a Pokemon was in the vicinity. The library I used has received a cease and desist order which is why I wont be sharing the code in this post. I do not encourage botting/farming in the game. The purpose of this post is to understand Webhooks and the Real Time Messaging Protocol. I do not endorse the library used or have any association with its developers, neither have I assisted in the development of the library in any way. The solution architecture of the app can be found below.

How to catch em all ?
How to catch em all ?

I created a separate Pokemon Trainer Club account for use with the API, and hardcoded a given location for fetching pokemon. Once the API returns the list of pokemon in the vicinity I find the nearest one and compose a slack message object which looks like the following.

channel: "#general",
username: "Pokemon Alert",
text: "There is a " + pokemon.name + " at " + pkmn.distance + " meters",
attachments: [{image_url: pkmn.image}]

All pokemon found are written to mongodb along with their location and time of discovery, which can be used for later. After the 0.13 update to Pokemon Go, Niantic introduced some server side changes by implementing encrypted variables inside valid requests, which completely broke the library I was using. However if the contributors to the library manage to reverse engineer the changes and make it operational again one could continue developing this application. Anyone with academic curiosity about the project can shoot me an email and I will add you to my private git server where this repository is being hosted. Here is what The application looked like when it was running.

Private Slack

I also host my own slack team . I can give out invites if this app gets working again then you guys can see it in action. I would like to end this post on the usual scope for improvement section and also a valuable message.

Scope for improvement:

  • Make the whole project functional.
  • Allow for communication with the slack bot such as asking it to scan a particular location.
  • Perform some sort of Data analysis on the Pokemon found.

Go team Instinct!
Team Instinct