How to Create a Slack Bot using AWS Lambda in < 1 Hour
Learn how to create a Slack Bot with unlimited potential using Slack Events API.
There’s not many resources out there in using AWS Lambda functions in Python so here’s one. Whilst it took me around 2/3 hours, this should sort you out in less than 1 hour!
Prerequisites
- AWS and Slack Account
- Slack Workspace
1. Create an App on Slack
Head on down to https://api.slack.com/ and select the “Your Apps” tab on the site.
Once on the page you will see a list of your apps on your workspace. “Create New App”
You will be presented with a page to name your bot and assign it to the workspace you want the app to belong to.
Upon a successful creation you will be greeted to the “Basic Information” page of your Slack App.
On the sidebar, under the “Features” heading, select “Bot Users” and complete the fields and “Save Changes”
Once this is done lets head to “Event Subscriptions”
Click on the On/Off switch to “Enable Events”
Put this aside, as for now we are done with setting up our App. Now to get crackin’ with some AWS. Let’s accomplish the “challenge” in order to set up the Endpoint in Step 2.
2. Create AWS Lambda function
Log into your AWS Management Console and head on over to “Lambda” in services.
“Create Function” > “Author From Scratch”
Ensure you use Python 3.6 for this tutorial as some libraries may not be supported. Do use what you require for your project :). “Create function”
3. Attach an API Gateway to the function
“Designer” > “+ Add trigger”
Ensure the following is entered:
- API Gateway trigger
- Security: Open
Click on the newly created API Gateway Trigger and a card below should appear with a link. Copy the link (API Endpoint) and let’s test our lambda function works by clicking the link.
4. Take API endpoint and add to events in slack
The link that we copied, take it back to Event Subscription and insert the link. The Slack API will then test the API Gateway and Lambda function. At the moment it is a failure as all we do is return “Hello from Lambda” so we know it works.
The task now is to return the “challenge” value in our lambda function.
To make our life easy and a small debug tip. Insert this line of code:
import jsondef lambda_handler(event, context):
print(f"Received event:\n{event}\nWith context:\n{context}")
# TODO implement
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
This will allow you to view what is passed into the event in the CloudWatch Logs.
To Complete the “challenge” lets add some code in the Lambda function:
import jsondef lambda_handler(event, context):
print(f"Received event:\n{event}\nWith context:\n{context}")
slack_body = event.get("body")
slack_event = json.loads(slack_body)
challenge_answer = slack_event.get("challenge")
return {
'statusCode': 200,
'body': challenge_answer
}
Save this function. Back to the Slack API page and “Retry”. This should then succeed and become Verified!
Next, on the same page select “Subscribe to bot events” and “Add Bot User Event”
Add the “message.im” event. This will allow you to message the bot via a direct message.
Finally, back to “Basic Information” > “Install your app to your workspace” > “Allow”
Once that is successful. Restart your slack app and install the app and start messaging and programming your slack bot!
Direct Message your newly created slack bot.
Full Lambda Function Code for a simple response (Warts and all) :P
import os
import urllibdef send_text_response(event, response_text):
print("Messaging Slack...")
SLACK_URL = "https://slack.com/api/chat.postMessage"
channel_id = event.get("event").get("channel")
data = urllib.parse.urlencode(
(
("token", os.environ["BOT_TOKEN"]),
("channel", channel_id),
("text", response_text)
)
)
data = data.encode("ascii")
request = urllib.request.Request(SLACK_URL, data=data, method="POST")
request.add_header( "Content-Type", "application/x-www-form-urlencoded" )
# Fire off the request!
x = urllib.request.urlopen(request).read()def lambda_handler(event, context):
print(f"Received event:\n{event}\nWith context:\n{context}")
send_text_response(event, "Hello World From Lambda")
return "200 OK"
Here’s one I made earlier
Upon upload of a file to Slack the following will take place:
- Get the file from the
private_url
and authenticates using theBOT_TOKEN
. - The file will then be stored to an S3 Bucket.
- We would then invoke another lambda function which will run the Glasswall Determine File Type test.
- The result is then sent.
There is a bug where Slack will make a request upon a bot’s response.
The way I stop this from happening is by checking the username or user_id of the request. This way it partially stops an infinite amount of requests being made. Instead it passes through 2-3 times.
def check_if_from_bot(event):
message_from = event.get("event").get("username")
if message_from == "gwtf-bot":
return True
if event.get("event").get("subtype") == "bot_message":
return True
Please contact me if you have a solution. :D
My challenge to you…
What can you create with a slack bot?