Help us understand the problem. What is going on with this article?

[AWS] LINEWORKSでリマインダBOTを作ってみた

Advent Calendar7日目です。

今回は、AWS環境でリマインダBOTを作成してみました。
Cloudformationのテンプレートも掲載しますので、興味がある方はご覧ください。

Lambdaでの実装の記事は こちら

完成したBOT

BOTのやりとりはこんな感じです。
iOS の画像.png

以下の機能があります。

  • イベント登録機能

    • イベントのタイトル、時間を入力することでリマインドしたいイベントを登録できます。
    • 「イベント登録」ボタンを押すことで登録が開始します。
  • イベント参照機能

    • 登録したイベントを参照することができます。
    • 「イベント参照」ボタンを押すことでイベントを参照することができます。
  • イベント通知機能

    • 登録したイベントの日時が近づくとBOTが通知してくれます。

今回は、BOTにトーク固定メニューを用いてボタンを配置しました。

全体構成

overview.png

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関数の実装について紹介したいと思います。
実装編のリンク先

peyryo
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away