-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
274 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
![slack-lambda-google](https://cloud.githubusercontent.com/assets/559351/12033086/4eb38aba-ae5a-11e5-8dbf-50e82f94424d.png) | ||
|
||
# Google God | ||
|
||
A serverless [Slack Slash Commands](https://api.slack.com/slash-commands) to integrate [Google Knowledge Graph API](https://developers.google.com/knowledge-graph/) using [AWS Lambda](https://aws.amazon.com/lambda/) and [AWS API Gateway](https://aws.amazon.com/api-gateway/). | ||
|
||
![screenshot](https://cloud.githubusercontent.com/assets/559351/12034616/835b2ad4-ae6e-11e5-8b89-fc7b486fd47e.gif) | ||
|
||
## Getting Started | ||
|
||
This project was built with Ryan Ray's repo [slack-lambda-weather](https://github.com/ryanray/slack-lambda-weather) and his [post](http://www.ryanray.me/serverless-slack-integrations). | ||
|
||
### Prerequisites | ||
|
||
* Install [AWS CLI](https://aws.amazon.com/cli/) | ||
* Execution Role ARN for your AWS Lambda | ||
* Create a `config.json` based on `config.sample.json`. This file is gitignored by default because this is where you would put any API key's and other secret info that your lambda may need. | ||
* [Google Knowledge Graph Search API](https://developers.google.com/knowledge-graph/) API key, and paste it to `config.json`. | ||
|
||
### AWS Lambda | ||
|
||
> Lambda is based on EC2 and allows you to deploy and execute your code (Node.js, Java, Python) without having to provision servers. | ||
First build and create your Lambda function on AWS: | ||
|
||
```sh | ||
npm run create LAMBDA_FUNCTION_NAME EXECUTION_ROLE_ARN | ||
``` | ||
|
||
> Before you can create your Lambda you need to create an execution role. If you did any of the Lambda hello world tutorials in the AWS console you should already have a role created. Either way you need to goto the [IAM Management Console - Roles](https://console.aws.amazon.com/iam/home#roles). Get the ARN of `lambda_basic_execution` or create a new role based on `role.example.json` and get the ARN from that. The full ARN looks something like `arn:aws:iam::YOUR_ACCOUNT_ID:role/lambda_basic_execution`. | ||
Build and deploy to update your Lambda code: | ||
|
||
```sh | ||
npm run deploy LAMBDA_FUNCTION_NAME | ||
``` | ||
|
||
### AWS API Gateway | ||
|
||
> Lambda responds to events, which can come from a variety of sources. By default Lambda isn't accessable from a URL, but API Gateway allows you to map a URL and an HTTP method to trigger your Lambda code. You can setup GET, POST, PUT, etc... and map the parameters/body into a JSON payload that Lambda understands. | ||
1. Goto [AWS API Gateway](https://aws.amazon.com/api-gateway/) and Create new API - name it whatever you want - we'll do LambdaTest for now | ||
2. Create a new resource, name it whatever | ||
3. Create a POST method under your resource | ||
4. Select Integration type with Lambda Function, and select your Lambda region, and enter your Lambda function name | ||
5. Save and give API Gateway permission to invoke your Lambda function | ||
6. Click on Integration Request > Mapping Templates | ||
7. Add mapping Template for `application/x-www-form-urlencoded` and click checkmark | ||
8. Change input passthrough to mapping template and paste this template [gist](https://gist.github.com/ryanray/668022ad2432e38493df) that can help you to convert `application/x-www-form-urlencoded` POST from Slack to Lambda's `application/json` format | ||
9. Save and click Deploy API with a new stage, then you can see a public invoke URL | ||
|
||
### Slack | ||
|
||
1. Goto Slack App `https://YOUR_TEAN_DOMAIN.slack.com/apps/manage` | ||
2. Search `Slash Commands` and add a new configuration | ||
3. Choose a command, for this example enter `/google` in the command name input, click Add Slash Command Integration button. | ||
4. Now you should be on the settings page, scroll down and copy the token to your `config.json` (NOTE: you don't want to expose the token to the public!). | ||
5. Copy and paste your API Gateway invoke URL to URL field. | ||
|
||
## Contributing | ||
|
||
Improvements are welcome! Just fork, push your changes to a new branch, and create a pull request! | ||
|
||
![slack-lambda-google-ex](https://cloud.githubusercontent.com/assets/559351/12034120/721ea5a4-ae67-11e5-8d7a-297cbaa1a51d.png) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"GOOGLE_API_KEY": "YOUR_GOOGLE_API_KEY", | ||
"SLASH_COMMANDS_TOKEN": "YOUR_SLACK_SLASH_COMMAND" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
var config = require('./config.json'); | ||
var messages = require('./messages.json'); | ||
var google = require('./lib/google.js'); | ||
|
||
/** | ||
* Entrypoint for AWS Lambda | ||
* @param event is the JSON payload that API Gateway transformed from slack's application/x-www-form-urlencoded request | ||
* @param context has methods to let Lambda know when we're done - similar to http/express modules `response.send()` | ||
*/ | ||
exports.handler = function (event, context) { | ||
console.log(event); | ||
|
||
// Verify request came from slack | ||
if (event.token !== config.SLASH_COMMANDS_TOKEN) { | ||
return context.fail(messages.UNAUTHORIZED_TOKEN); | ||
} | ||
|
||
google(event.text) | ||
.then(function (response) { | ||
context.succeed(response); | ||
}) | ||
.catch(function (error) { | ||
console.error(error); | ||
context.succeed({ | ||
'response_type': 'in_channel', | ||
'attachments': [ | ||
{ | ||
'fallback': messages.ERROR_FALLBACK, | ||
'text': messages.ERROR_TEXT, | ||
'color': 'danger' | ||
} | ||
] | ||
}); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
var _ = require('lodash'); | ||
var request = require('request-promise'); | ||
|
||
var config = require('../config.json'); | ||
var messages = require('../messages.json'); | ||
|
||
// Language priority for search result | ||
var languages = [ | ||
'zh-TW', | ||
'zh', | ||
'en', | ||
'ja' | ||
]; | ||
// Google API params | ||
var params = { | ||
'limit': 1, | ||
'languages': 'zh,en,ja' | ||
}; | ||
|
||
module.exports = function (text) { | ||
return request('https://kgsearch.googleapis.com/v1/entities:search?' + | ||
'query=' + text.trim() + '&' + | ||
'key=' + config.GOOGLE_API_KEY + '&' + | ||
'limit=' + params.limit + '&' + | ||
'languages=' + params.languages) | ||
.then(function (response) { | ||
var data = JSON.parse(response); | ||
|
||
var result = _.get(data, ['itemListElement', 0, 'result']); | ||
if (!result) { | ||
return { | ||
'response_type': 'in_channel', | ||
'attachments': [ | ||
{ | ||
'fallback': messages.RESULT_NOT_FOUND, | ||
'text': messages.RESULT_NOT_FOUND_TEXT, | ||
'color': 'danger' | ||
} | ||
] | ||
}; | ||
} | ||
|
||
var name = item(result, 'name', '@language'); | ||
var title = _.get(name, '@value'); | ||
|
||
var detailedDescription = item(result, 'detailedDescription' ,'inLanguage'); | ||
|
||
return { | ||
'response_type': 'in_channel', | ||
'attachments': [ | ||
{ | ||
'fallback': title, | ||
'title': title, | ||
'title_link': _.get(detailedDescription, 'url'), | ||
'text': _.get(detailedDescription, 'articleBody'), | ||
'thumb_url': _.get(result, ['image', 'contentUrl']) | ||
} | ||
] | ||
}; | ||
}); | ||
}; | ||
|
||
/** | ||
* Get only one item from search result by language priority list | ||
* @param {Object} result search result | ||
* @param {string} children item name | ||
* @param {string} key item language property name | ||
* @return {Object} filter object | ||
*/ | ||
function item (result, children, key) { | ||
var items = _.chain(result).get(children).value(); | ||
var language = _.chain(languages).filter(function (lang) { | ||
return _.find(items, _.matchesProperty(key, lang)); | ||
}).first().value(); | ||
|
||
return _.find(items, _.matchesProperty(key, language)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"UNAUTHORIZED_TOKEN": "Unauthorized Request. Check Your Slash Commands Token.", | ||
"ERROR_FALLBACK": "告訴你一件很恐怖的事⋯⋯", | ||
"ERROR_TEXT": "◢▆▅▄▃崩╰(〒皿〒)╯潰▃▄▅▇◣", | ||
"RESULT_NOT_FOUND_FALLBACK": "告訴你一件很恐怖的事⋯⋯", | ||
"RESULT_NOT_FOUND_TEXT": "幹!我找不到⋯ಥ_ಥ" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"name": "slack-lambda-google", | ||
"version": "0.1.0", | ||
"description": "A serverless Slack Slash Commands to integrate Google Knowledge Graph API using AWS Lambda and AWS API Gateway", | ||
"main": "lambda.js", | ||
"scripts": { | ||
"build": "./scripts/build.sh", | ||
"create": "./scripts/create.sh", | ||
"deploy": "./scripts/deploy.sh" | ||
}, | ||
"author": "Amo Wu <amo260@gmail.com>", | ||
"license": "Apache-2.0", | ||
"dependencies": { | ||
"lodash": "^3.10.1", | ||
"request-promise": "^0.4.3" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/amowu/slack-lambda-google.git" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"Version": "2012-10-17", | ||
"Statement": [ | ||
{ | ||
"Effect": "Allow", | ||
"Action": [ | ||
"logs:CreateLogGroup", | ||
"logs:CreateLogStream", | ||
"logs:PutLogEvents" | ||
], | ||
"Resource": "arn:aws:logs:*:*:*" | ||
}, | ||
{ | ||
"Action": [ | ||
"lambda:InvokeFunction" | ||
], | ||
"Effect": "Allow", | ||
"Resource": "arn:aws:lambda:YOUR_REGION:YOUR_ACCOUNT_ID:function:*" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#!/bin/sh -e | ||
|
||
if [ ! -f ./config.json ]; then | ||
echo "Unable to build Lambda.zip, \"config.json\" is required!" | ||
exit 1 | ||
fi | ||
|
||
npm install | ||
|
||
rm -rf ./dist | ||
mkdir -p dist | ||
|
||
zip -r -q dist/lambda.zip . -i "lib/*" "node_modules/*" "config.json" "messages.json" "lambda.js" "package.json" -x "*/.DS_Store" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#!/bin/sh -e | ||
|
||
[[ -z "$1" ]] && echo "Lambda function name must be provided, example: npm run create myLambdaFunction \"arn:aws:iam::YOUR_AWS_ACCOUNT_ID:role/lambda_basic_execution\"" && exit 1; | ||
[[ -z "$2" ]] && echo "IAM Role ARN must be provided, example: npm run create myLambdaFunction \"arn:aws:iam::YOUR_AWS_ACCOUNT_ID:role/lambda_basic_execution\"" && exit 1; | ||
|
||
echo "build..." | ||
|
||
./scripts/build.sh | ||
|
||
echo "create..." | ||
|
||
aws lambda create-function \ | ||
--function-name "$1" \ | ||
--runtime nodejs \ | ||
--role "$2" \ | ||
--handler lambda.handler \ | ||
--timeout 6 \ | ||
--memory-size 512 \ | ||
--zip-file fileb://$(pwd)/dist/lambda.zip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#!/bin/sh -e | ||
|
||
[[ -z "$1" ]] && echo "Lambda function name must be provided, example: npm run deploy myLambdaFunction" && exit 1; | ||
|
||
echo "build..." | ||
|
||
./scripts/build.sh | ||
|
||
echo "deploy..." | ||
|
||
aws lambda update-function-code \ | ||
--function-name "$1" \ | ||
--zip-file fileb://$(pwd)/dist/lambda.zip |