Advent Calendar7日目です。
今回は、AWS環境でリマインダBOTを作成してみました。
Cloudformationのテンプレートも掲載しますので、興味がある方はご覧ください。
Lambdaでの実装の記事は こちら
完成したBOT
以下の機能があります。
-
イベント登録機能
- イベントのタイトル、時間を入力することでリマインドしたいイベントを登録できます。
- 「イベント登録」ボタンを押すことで登録が開始します。
-
イベント参照機能
- 登録したイベントを参照することができます。
- 「イベント参照」ボタンを押すことでイベントを参照することができます。
-
イベント通知機能
- 登録したイベントの日時が近づくとBOTが通知してくれます。
今回は、BOTにトーク固定メニューを用いてボタンを配置しました。
全体構成
BOTのバックエンドの構築はAWSを利用しました。
今回はなるべく手軽に作るために、サーバレスで構築してみました。
BOTとのやり取りは API Gateway と Lambda が担い、トークの状態管理に DynamoDB を使用しています。
LINEWORKS -> AWS へのメッセージは、API Gateway経由でlambdaで処理されます。
そのため、LINEWORKSのBOTのcallback URLには、API GatewayのURLを設定してあります。
AWS->LINEWORKS へのメッセージ通知は、SQS を介して送信用のLambdaが行います。
メッセージ送信に必要なアクセストークンおよび認証キーは、S3 で管理してあります。
リマインドの通知は、CloudWatch Event を利用して Lambda を定期的に起動し、
DynamoDB内にあるイベントをポーリングすることで実現しています。
テンプレート
AWSのリソース作成には、 Cloudformation を用いています。
今回は、Lambda と API Gateway を使用しているため、記述が容易な AWS SAM を利用しました。
各種リソースの名称と設定値は適当に設定してありますので、もし使用する場合は適宜変えてください。
template.yaml
AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::Serverless-2016-10-31
# テンプレートのパラメータに LINEWORKS の BOT に必要な認証情報を渡すように設定
Parameters:
BotNo:
Description: LINEWORKS bot number
Type: String
ApiId:
Description: LINEWORKS api id
Type: String
ServerListId:
Description: LINEWORKS server list id
Type: String
ServerApiConsumerKey:
Description: LINEWORKS server api consumer key
Type: String
# 全Lambda関数に適用されるプロパティ
Globals:
Function:
AutoPublishAlias: live
Timeout: 10
# Lambdaの関数に適用されるプロパティ
Environment:
Variables:
BOT_NO: !Ref BotNo
API_ID: !Ref ApiId
SERVER_LIST_ID: !Ref ServerListId
SERVER_API_CONSUMER_KEY: !Ref ServerApiConsumerKey
Resources:
# AWS -> LINEWORKSへの通知を担うLambdaの関数
SendLambda:
Type: AWS::Serverless::Function
Properties:
FunctionName: 'send-lineworks-message'
Handler: index.handler
Runtime: python3.7
CodeUri: lambda/send-message
Role:
Fn::GetAtt:
- LambdaExecutionRole
- Arn
Events:
# SQS のトリガーをここで定義
SQS1:
Type: SQS
Properties:
Queue:
Fn::GetAtt:
- MessageQueue
- Arn
BatchSize: 10
# LINEWORKS -> AWS の受信処理を担うLambdaの関数
RecieveMessage:
Type: AWS::Serverless::Function
Properties:
FunctionName: 'recieve-lineworks-message'
Handler: index.handler
Runtime: python3.7
CodeUri: lambda/recieve-message
Role:
Fn::GetAtt:
- LambdaExecutionRole
- Arn
Events:
PostEvent:
Type: Api
Properties:
Path: /callback
Method: post
# DynamoDBから登録されているEventを取得するLambda関数
GetEvents:
Type: AWS::Serverless::Function
Properties:
FunctionName: 'get-events'
Handler: index.handler
Runtime: python3.7
CodeUri: lambda/get-events
Role:
Fn::GetAtt:
- LambdaExecutionRole
- Arn
Events:
# CloudWatch Eventをここで定義
Schedule:
Type: Schedule
Properties:
# ポーリング間隔は5分
Schedule: rate(5 minutes)
# Lambda関数 の権限(甘め)
# とりあえず、全Lambda関数に適用
LambdaExecutionRole:
Description: Creating service role in IAM for AWS Lambda
Type: AWS::IAM::Role
Properties:
RoleName: !Sub 'LineWorksLambdaExecution'
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [lambda.amazonaws.com]
Action: sts:AssumeRole
Path: /
ManagedPolicyArns:
- !Sub 'arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
Policies:
-
PolicyName: lineworks-lambda-execution-role
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action: "sqs:*"
Resource: "*"
-
Effect: "Allow"
Action: "dynamodb:*"
Resource: "*"
# DynamoDBの定義
LineWorksDB:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
-
AttributeName: "Hash"
AttributeType: "S"
-
AttributeName: "Range"
AttributeType: "S"
KeySchema:
-
AttributeName: "Hash"
KeyType: "HASH"
-
AttributeName: "Range"
KeyType: "RANGE"
ProvisionedThroughput:
ReadCapacityUnits: "1"
WriteCapacityUnits: "1"
TableName: lineworks-sample-table
# 「ExpireTime」をTTLに設定
# TTLを設定することでアイテムの自動削除が可能
TimeToLiveSpecification:
AttributeName: ExpireTime
Enabled: true
Tags:
- Key: key
Value: value
# SQSの定義
MessageQueue:
Type: 'AWS::SQS::Queue'
Properties:
QueueName: lineworks-message-queue
デプロイする際は、以下のスクリプトを用いました。
スタック名も適当です。
build.sh
### ここは適宜それぞれの環境に合わせて変更
BOT_NO="xxx"
API_ID="yyy"
SERVER_LIST_ID="zzz"
SERVER_API_CONSUMER_KEY="aaa"
DEPLOY_S3_BUCKET = "bbb"
###
aws cloudformation package --template template.yml --s3-bucket ${DEPLOY_S3_BUCKET} --output-template template-export.yml
aws cloudformation deploy \
--template-file template-export.yml \
--stack-name lineworks-sample-stack \
--capabilities CAPABILITY_NAMED_IAM \
--parameter-overrides BotNo=${BOT_NO} ApiId=${API_ID} ServerListId=${SERVER_LIST_ID} ServerApiConsumerKey=${SERVER_API_CONSUMER_KEY}
まとめ
AWSでサーバレスな環境でリマインダBOTを作成してみました。
次回は、Lambda関数の実装について紹介したいと思います。
実装編のリンク先