本文介绍怎样运用 AWS Lambda & AWS API Gateway 搭建一个不须要伺服器的环境,供应 Slack Slash Commands 查询豆瓣电影。
在 Slack 输入 /movie 绝地救济,会显示相关的电影资料。
这篇文章运用到的技术:
Slack Slash Commands
AWS Lambda
AWS API Gateway
豆瓣电影 API
阅读这篇文章须要具备什么才能:
Node.js 的基础才能
Amazon Web Services 的基础操纵
接下来我会逐渐讲解这些东西:
Slack Slash Commands 的运作机制
竖立一个简单的 AWS Lambda function
竖立一个简单的 AWS API Gateway 执行 Lambda function
运用 Lambda 呼唤豆瓣电影 API
测试 AWS API Gateway
将 API Gateway endpoint 到场至 Slack Slash Command
Slack Slash Commands 的运作机制
当你在 Slack channel 输入 /movie 权力的游戏,Slack 会发出一个 content-type Header 设为 application/x-www-form-urlencoded 的 HTTP POST 请求,花样以下:
token=YOUR_SLASH_COMMAND_TOKEN
team_id=YOUR_TEAM_ID
team_domain=YOUR_TEAM_DOMAIN
channel_id=YOUR_CHANNEL_ID
channel_name=YOUR_CHANNEL_NAME
user_id=YOUR_USER_ID
user_name=YOUR_USER_NAME
command=/movie
text=权力的游戏
response_url=YOUR_HOOK_URL
然后 Slack 须要收到的 JSON 回应花样以下(详见 Attachments):
{
"response_type": "in_channel",
"attachments": [
{
"title": "权力的游戏 第五季",
"title_link": "http://movie.douban.com/subject/25826612/",
"text": "Game of Thrones\n2015年",
"fields": [
{
"title": "导演",
"value": "Michael Slovis\n...",
"short": true
}, ...
],
"thumb_url": "https://img1.doubanio.com/view/movie_poster_cover/ipst/public/p2230256732.jpg"
}
]
}
responsetype: inchannel 示意 channel 内的运用者都能够看见,若只想给运用敕令的本人看的话能够改成 ephemeral
Slack Slash Commands 有 3000 ms 的 response timeout 限定
竖立一个简单的 AWS Lambda function
前去 AWS Lambda
点选 Create a Lambda function
填写 Configure function,例:slackFunction
Runtime 选择 Node.js
Code entry type 选择 Edit code inline,输入简单的测试程式码:
exports.handler = function(event, context) {
context.succeed("你好天下!");
};
Role 运用 lambdabasicexecution
点选 Next 完成竖立
点选 Test 测试结果:
你好天下!
竖立一个简单的 AWS API Gateway 执行 Lambda function
前去 AWS API Gateway
点选 New API
填写 API name,例:Slack API
点选 Create API 完成新增
点选 Create Resource
填写 Resource Name & Resource Path,例:movie
点选 /movie
点选 Create Method
选择 POST
Integration type 选择 Lambda Function
11. 选择 Lambda Region
12. 填写 Lambda Function,例:slackFunction
13. 点选 Save 完成竖立
14. 点选 Test 测试结果:
你好天下!
运用 Lambda 呼唤豆瓣电影 API
豆瓣电影搜刮 API 的花样以下:
GET https://api.douban.com/v2/movie/search?q={text}
例:https://api.douban.com/v2/movie/search?q=权力的游戏
{
"count": 20,
"start": 0,
"total": 130,
"subjects": [
{
"rating": {...},
"genres": [...],
"collect_count": 47770,
"casts": [
{...}, ...
],
"title": "权利的游戏 第五季",
"original_title": "Game of Thrones",
"subtype": "tv",
"directors": [
{...}, ...
],
"year": "2015",
"images": {...},
"alt": "http://movie.douban.com/subject/25826612/",
"id": "25826612"
}, ...
],
"title": "搜刮 \"权力的游戏\" 的效果"
}
庖代 Edit code inline,在当地竖立一个 Node.js Lambda project:
$ npm init
到场一个支撑 promise 的 XMLHttpRequest 库:
$ npm install request-promise --save
新增 index.js:
var rp = require('request-promise');
exports.handler = function(event, context) {
// 从传进来的参数当中提取要搜寻的字串
var text = event.text ? event.text.trim() : null;
// 向豆瓣 API 发出 HTTP GET 请求
rp('https://api.douban.com/v2/movie/search?q=' + text)
.then(function(data) {
// 回传胜利的结果
context.succeed(data);
}).catch(function(error) {
// 回传失败的结果
context.fail(error);
});
};
将档案压缩成 lambda.zip:
./index.js
./node_module/request-promise
回到 AWS Lambda
点选之前竖立的 function,例:slackFunction
将 Code entry type 从 Edit code inline 改为 Upload a .ZIP file
上传 lambda.zip
点选 Actions > Configure test event,到场测试用的请求
{
"text": "权力的游戏"
}
点选 Test 测试豆瓣回应的结果:
{
// ...
"subjects": [
{
// ...
"title": "权利的游戏 第五季",
// ...
}, ...
],
"title": "搜刮 \"权力的游戏\" 的效果"
}
测试 AWS API Gateway
回到 AWS API Gateway
点选 /movie 的 POST method
点选 Test,并在 Request Body 到场测试用的请求:
{
"text": "权力的游戏"
}
点选 Test 测试 Lambda 回应的豆瓣结果:
{
// ...
"subjects": [
{
// ...
"title": "权利的游戏 第五季",
// ...
}, ...
],
"title": "搜刮 \"权力的游戏\" 的效果"
}
将 API Gateway endpoint 到场至 Slack Slash Command
因为 Slack 发送的请求 Header 花样是 application/www-form-urlencoded,所以须要在 AWS API Gateway 当中将它转换成为 application/json 花样:
点选 /movie 的 POST method
点选 Method Execution
点选 Integration Request
点选 Mapping Templates
点选 Add mapping template
Content-Type 填写 application/www-form-urlencoded
将 Input passthrough 改成 Mapping template
贴上 Ryan Ray 供应的 template gist
Save
最后,一定要记得把 API Gateway 布置给外部运用:
点选 Deploy API
Deployment stage 选择 New Stage
填写 Stage name,例:development
点选 Deploy 完成发布
然后会获得一个 Invoke URL 花样以下:
https://{hash}.execute-api.{region}.amazonaws.com/{stage}/movie
接下来的步骤,把 AWS API Gateway endpoint 整合进 Slack:
在 Search app directory 搜寻框输入 Slash Commands 并进入
点选 Add Configuration
填写 Choose a Command,例:/movie
点选 Add Slash Command Integration
填写 URL,贴上 AWS API Gateway Invoke URL
Method 选择 POST
点选 Save Integration 完成新增
最后一个步骤,更新 Lambda function,让它能够处理 Slack 的请求与回应:
var rp = require('request-promise');
exports.handler = function(event, context) {
/**
* event 会收到来自 AWS API Gateway 转换过的 Slack POST JOSN
* {
* token=YOUR_SLASH_COMMAND_TOKEN
* team_id=YOUR_TEAM_ID
* team_domain=YOUR_TEAM_DOMAIN
* channel_id=YOUR_CHANNEL_ID
* channel_name=YOUR_CHANNEL_NAME
* user_id=YOUR_USER_ID
* user_name=YOUR_USER_NAME
* command=/movie
* text=权力的游戏
* response_url=YOUR_HOOK_URL
* }
*/
if(event.token !== 'YOUR_SLASH_COMMAND_TOKEN') {
return context.fail('未经授权的请求');
}
var text = event.text ? event.text.trim() : null;
// 向豆瓣 API 发出 HTTP GET 请求
rp('https://api.douban.com/v2/movie/search?q=' + text)
.then(function(data) {
// 提取第一笔电影的结果
var subject = data.subjects[0];
// 将豆瓣 API 返回的结果包装成 Slack 支撑的花样
var result = {
"response_type": "in_channel",
"attachments": [{
"title": subject.title,
"title_link": subject.alt,
"text": subject.original_title+"\n"+subject.year+"年",
"fields": [
{
"title": "导演",
"value": subject.directors[0].name,
"short": true
}
],
"thumb_url": subject.images.small
}]
};
// 回传结果
context.succeed(result);
}).catch(function(error) {
// 回传失败的结果
context.fail(error);
});
};
从新压缩 lambda.zip 然后上传
在 Slack channel 输入 /movie 测试结果
总结
熟习之后,轻微修正一下,把豆瓣 API 换成别的 API,又能够诞生出更多风趣的 Slash Commands!
2015/12/30: 更新范例 GitHub repo Google 大神
因为 Slack 有 3 秒的回应限定,所以 API 不稳的话,经常轻易发生 timeout,解决要领能够参考 Slack 供应的体式格局 Delayed responses and multiple responses,或是进步 Lambda 的 Memory(建议 512 以上),也可运用 AWS SNS 之类的服务处理非同步的 Lambda invoke。
特别感谢 Ryan Ray 写的文章 Serverless Slack Integrations with node.js, AWS Lambda, and AWS API Gateway
本文同步分享于 Medium