New project time. Today i’m our lead developer for our Ansible collection at work, and we do all our support today in Slack. I want to automate some of this support to help resolve issues quickly for users and free up more time for the dev team to develop.
The plan is to make a smart slack bot that will respond to users who need help, ask for the required information. If there is a known fix give the user the information on the fix. If not, let the dev team know if all the information needs to look into the issue.
I plan to do with slack sending event to AWS Lambda, and have a python script respond to it. The app will listen to the chat in the channel and only respond if the user need help.
Setting up Slack
First we’ll create a new slack app https://api.slack.com/apps
OAuth & Permissions
We’ll need to add some scope so that the bot and read and respond to IM and message in a channel
- Channels:history
- channels:read
- chat:write
- group:history
- im:history
- im:read
- im:write
Setting up Lamdba
In AWS Lambda create a new function.
- Runtime Python 3.8 — though could be any python version
Api Gateway
Once the function is created, you’ll want to click on + Add trigger
Here you want to select Api Gateway
- APi = Create an APi
- API type = http API
- Security = open
Once this is created, the API Gateway will create an API-endpoint url, copy this as we will need this for the next steps in Slack
Back to in Slack
Event Subscription
Enable Events, and in the Request URL add your API-endpoint url from AWS
Next in this same window go down to Subscribe to bot events and add
- Message.channels
- message.group
- message.im
For channels, group, and IM the bot is part of the bot will send an event to AWS Api gateway any time a message is sent.
Basic Information
Now in the Basic Information window in the slack app click on install your app. This will install your app in your workspace
Oauth & Permissions
Copy the Bot user Oauth Token. We will need to add this to the AWS side
Back To AWS
In your lambda function page you want click on Configuration and then Environment Variables. Here you want to add a new environment variable called BOT_TOKEN and the value should be your bot token
Testing if it works
First make sure the bot is added to the channel in slack for this to work).
if you type help in as a message in the channel, the bot will respond with “help is on the way”
import os
from six.moves import urllib
import json
def send_text_response(event, response_text):
# use postMessage if we want visible for everybody
# use postEphemeral if we want just the user to see
SLACK_URL = "https://slack.com/api/chat.postMessage"
channel_id = event["event"]["channel"]
user = event["event"]["user"]
bot_token = os.environ["BOT_TOKEN"]
data = urllib.parse.urlencode({
"token": bot_token,
"channel": channel_id,
"text": response_text,
"user": user,
"link_names": True
})
data = data.encode("ascii")
request = urllib.request.Request(SLACK_URL, data=data, method="POST")
request.add_header("Content-Type", "application/x-www-form-urlencoded")
res = urllib.request.urlopen(request).read()
print('res:', res)
def check_message(text):
if 'help' in text:
return 'help is on the way'
if 'carchi8py' in text:
return 'carchi8py is my maker'
return None
def is_bot(event):
return 'bot_profile' in event['event']
def lambda_handler(event, context):
event = json.loads(event["body"])
print('event', event)
if not is_bot(event):
message = check_message(event["event"]["text"])
if message:
send_text_response(event, message)
return {
'statusCode': 200,
'body': 'OK'
}
How this works
The bot we made in Slack will send an event message to Api gateway which will trigger as Lambda function by calling the lambda_handler function. The Event is the json event that slack sent us. So we do a json.loads so we have a dictionary to work with.
First thing we want to do is check if the message was sent by a bot, (if you don’t know this, your bot will respond to it self and create an infinite loop. We only want to respond to humans
Next we pass the text of the message to the check_message, which check to see if a specific word exists, and if so return a specific message to send back to slack
Last we call the send_text_response to Slack. This set up a message so that we can send it back to slack. This uses the BOT_TOKEN we set up as an environment variable