Slack Bot with Lambda function
If you make the Wikipedia search bot, you use the below code
Setting Lambda
You choose the Lambda
You make the function by the Create a Lambda function
You don't choose the any Bleu Print.
You choose the "Skip"
You remove the Api Gateway Configure triggers. Because it is setting the after part.
You set the functionname.
You choose the Runtime "Python2.7"
Setting the code
You set the elasticsearch endpoint
.
Because it is different situation for each user.
query = "curl -XGET {your elasticsearch endpoint}:9200/_all/_search?pretty -d\'"
You set the below code.
Before run the below code, you have to run the Elasticsearch.
import logging
import subprocess
import json
import random
"""
Reference:
http://www.yamamanx.com/slack-bot-aws-lambda-python-api-gateway/
"""
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def make_query(keyword):
"""
Make a Elasticsearch search query
:param keyword(string): set the search key words
:return (string): elasticsearch search query
"""
# Simple Query
query = "curl -XGET {your elasticsearch endpoint}:9200/_all/_search?pretty -d\'"
make_query_before = '{ "query": { "match" : { "title": { "query": '
query_keyword = "\"" + keyword + "\""
make_query_after = "} } } }\'"
elasticsearch_query = query + make_query_before + query_keyword + make_query_after
return elasticsearch_query
def return_code(text):
"""
Make return code for slack
:param text(string): slack return text
:return (string): json format for slack
"""
payload={'text': text}
return payload
def lambda_handler(event, context):
"""
Get the Slack command (using the outgoing) and return the search result
:param event:
:param context:
:return (json): if the exists the image data in the search key, return the image, if the no exist the image, r
eturn the wiki url link
"""
command_text = event['text'].replace("bot_lambda_out ", "")
elasticsearch_query = make_query(command_text)
try:
sysmte_output = subprocess.Popen(elasticsearch_query, shell=True, stdout=subprocess.PIPE).stdout.read()
except OSError:
print(OSError)
json_data = json.loads(sysmte_output)
if json_data['hits']['hits']:
title = json_data['hits']['hits'][0]['_source']['title']
abstract = json_data['hits']['hits'][0]['_source']['abstract']
url = json_data['hits']['hits'][0]['_source']['url']
return_data = title + "\n" + abstract + "\n" + url + "\n"
else:
return return_code("No match")
image_list = []
for hit_data in json_data['hits']['hits']:
if hit_data['_source']['image']:
image_list.append(hit_data['_source']['image'])
if image_list:
return return_code(return_data + random.choice(image_list))
if json_data['hits']['hits']:
return return_code(return_data)
Setting the Role
You make the new rolw by the "Create new role from templates(s)"
You set the Role name
You choose the create function
Setting the API Gateway
You choose the API Gateway
You choose the Create API
You choose the Create Method
You choose the Post
Mapping the Request by the Integration Request
When you choose Body Mapping Templates
, you can watch the below screen you choose the Add mapping template
You input the [application/x-www-form-urlencoded]
You input the below sentence for the template
## convert HTML POST data or HTTP GET query string to JSON
## get the raw post data from the AWS built-in variable and give it a nicer name
#if ($context.httpMethod == "POST")
#set($rawAPIData = $input.path('$'))
#elseif ($context.httpMethod == "GET")
#set($rawAPIData = $input.params().querystring)
#set($rawAPIData = $rawAPIData.toString())
#set($rawAPIDataLength = $rawAPIData.length() - 1)
#set($rawAPIData = $rawAPIData.substring(1, $rawAPIDataLength))
#set($rawAPIData = $rawAPIData.replace(", ", "&"))
#else
#set($rawAPIData = "")
#end
## first we get the number of "&" in the string, this tells us if there is more than one key value pair
#set($countAmpersands = $rawAPIData.length() - $rawAPIData.replace("&", "").length())
## if there are no "&" at all then we have only one key value pair.
## we append an ampersand to the string so that we can tokenise it the same way as multiple kv pairs.
## the "empty" kv pair to the right of the ampersand will be ignored anyway.
#if ($countAmpersands == 0)
#set($rawPostData = $rawAPIData + "&")
#end
## now we tokenise using the ampersand(s)
#set($tokenisedAmpersand = $rawAPIData.split("&"))
## we set up a variable to hold the valid key value pairs
#set($tokenisedEquals = [])
## now we set up a loop to find the valid key value pairs, which must contain only one "="
#foreach( $kvPair in $tokenisedAmpersand )
#set($countEquals = $kvPair.length() - $kvPair.replace("=", "").length())
#if ($countEquals == 1)
#set($kvTokenised = $kvPair.split("="))
#if ($kvTokenised[0].length() > 0)
## we found a valid key value pair. add it to the list.
#set($devNull = $tokenisedEquals.add($kvPair))
#end
#end
#end
## next we set up our loop inside the output structure "{" and "}"
{
#foreach( $kvPair in $tokenisedEquals )
## finally we output the JSON for this pair and append a comma if this isn't the last pair
#set($kvTokenised = $kvPair.split("="))
"$util.urlDecode($kvTokenised[0])" : #if($kvTokenised[1].length() > 0)"$util.urlDecode($kvTokenised[1])"#{else}""#end#if( $foreach.hasNext ),#end
#end
}
You save it.
Deploy
After mapping, you deploy the code.
After deploy You copy the API Endpoint.
Deploy
End Point
If the stage doesn't exist you have to create the stage.
Setting the Slack
You search the "Outgoing Webhook"
You add the Outgoing Webhook in the Custom Integratations
After that you set the [Add Configuration]
1: You set the channel for slack bot
2: You set the trigger word for slack bot
3: You set the API endpoint URL(It is set the Lambda(API Gateway)) to the URL(s)
4: You set the Customize Name bot
5: You set the Customize Icon bot
You copy the End Point URL for Slack Outgoing Webhooks and save setting
In my case, I set the trigger word is "bot_lambda_out"
And search word is "earch"
You confirm the wikipedia title and abstrat, link , image.