/infobot learnor your bot can constantly poll slack though the slack api for specific events, such as a new user joining or a specific word used. Keeping cost in mind I went with the first option, because the application only has run when it's called. So what are our options as far as hosting goes? Well we could set up out own physical server to host this application and build a rest API on top of it, or use something like an amazon EC2 instance to avoid using physical hardware. Now this would work, but it goes two of our goals: being lightweight and being cost effective. For a simple slash command that is just going to return a generated link or list of learning resources, an entire dedicated server is quite overkill and the cost of hosting that server will add up. This is where AWS Lambda comes in. Lambda will only run your code when it is triggered by a defined event, so you don't pay for the time your code isn't run. More importantly, you get your first 1,000,000 requests free, which far exceeds what nearly any slack command will use. You can use a number of different events, but for this project we use Amazon's API gateway. We will get more into configuring lambda later in this post, but lets just get an overview of what will happen when a slack command is called:
/letmegooglethatforyoucommand that will generate a link like this: http://lmgtfy.com/?q=Jacob+Shodd. After choosing the name for your command you need to provide a url to slack, this is the invoke url of our api gateway. After this there are various other configurations you can make such as a description, autocomplete, etc.
Handlefunction as described below, without this, your Lambda will throw an error. You can think of this as your main function for this project.
evtthat is passed into your function is the entire request sent from Slack, including all headers and information about the request as well as the information from Slack. The second parameter
ctxcontains some useful information about Lambda, such as how much longer your application has to run (Lambda limits your application to 5 Minutes of uptime). For this example we won't be needing
ctx, but we will be using
evtto extract more information about the command that was passed. It is quite ugly, but this is an example of what is contained in
evtinto this object. like so:
request.Bodywe can get going right? Well, not quite yet. Even though the body is sent as a string, it actually holds a lot of information, and thus I gave it it's own struct, and a function to parse the url encoded string that is sent by slack.
info := toInfo(request.Body). So now that we have the request data structured in a way that it is all easily accessible, we will need to do the same for the response data. This is where most of my issues came from. Slack expects a json object with three fields:
text. the response type field lets you choose if everybody in the slack will see the message or only the one who calls the command. This is decided by using
in_channelfor a public message or
ephemeralfor a private message. The
textfield will contain your message to be displayed, which can also use any of slack's formatting tools. This is all quite easy to understand, but for some reason it also expects the body to be a string, with the
textfield in the body using escaped double quotes, or text formatting in slack don't work. This was a massive pain in the neck to figure out, but I ultimately used the following structs and function to make returning data to slack easy for me:
Handlefunction would look like for this application:
http://lmgtfy.com/?q=to create our url. This is then used to create or response and it is sent back to slack! Notice that we did not marshal our request into a json object, this is one feature of the shim is that it will automatically marshal whatever struct that you return. So now for the easy part, getting the code on Lambda. As of now Go isn't officially supported, so we will be using the tools that we downloaded earlier, but sometime in early 2018 these last steps will not be needed, as Amazon announced official support for Go on Lambda. All that is needed is to run
makein our project directory and the shim takes care of everything and outputs a zip file.
/letmegooglethatforyou test searchin you slack channel. After saving this, click the test button next to the drop down and you will be given your test feedback including what was returned by your function:
/letmegooglethatforyou A Tour Of Go?