[PYTHON] [AWS] I made a reminder BOT with LINE WORKS

It's the 7th day of Advent Calendar.

This time, I created a reminder BOT in the AWS environment. Cloudformation templates will also be posted, so please have a look if you are interested.

Click here for an article on implementation in Lambda (https://qiita.com/peyryo/items/ff5a2a693d47ce13fa18)

Completed BOT

The exchange of BOT is like this. iOS の画像.png

It has the following functions.

--Event registration function --You can register the event you want to remind by entering the event title and time. --Registration will start by pressing the "Event Registration" button.

--Event reference function --You can refer to the registered event. --You can refer to the event by clicking the "Browse for event" button.

--Event notification function --BOT will notify you when the date and time of the registered event is approaching.

This time, I placed a button on the BOT using a fixed talk menu.

overall structure

overview.png

AWS was used to build the BOT backend. This time, I tried to build it without a server in order to make it as easy as possible.

API Gateway and Lambda are responsible for interacting with the BOT, and DynamoDB is used for talk state management.

Messages to LINEWORKS-> AWS are processed by lambda via API Gateway. Therefore, the URL of API Gateway is set in the callback URL of BOT of LINE WORKS.

Message notification to AWS-> LINEWORKS is done by Lambda for sending via SQS. The access token and authentication key required to send a message are managed by S3.

Remind notifications take advantage of CloudWatch Events to launch Lambda on a regular basis. This is achieved by polling the events in DynamoDB.

template

Cloudformation is used to create AWS resources. This time, I used AWS SAM, which is easy to write because I am using Lambda and API Gateway.

The names and setting values of various resources are set appropriately, so if you want to use them, change them accordingly.

template.yaml

AWSTemplateFormatVersion: 2010-09-09
Transform:
- AWS::Serverless-2016-10-31

#Set template parameters to pass the required credentials to the 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

#Properties that apply to all Lambda functions
Globals:
  Function:
    AutoPublishAlias: live
    Timeout: 10
    #Properties applied to Lambda functions
    Environment:
      Variables:
        BOT_NO: !Ref BotNo
        API_ID: !Ref ApiId
        SERVER_LIST_ID: !Ref ServerListId 
        SERVER_API_CONSUMER_KEY: !Ref ServerApiConsumerKey

Resources:

  # AWS ->Lambda function responsible for notifying LINE WORKS
  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:
        #Define SQS triggers here
        SQS1:
          Type: SQS
          Properties:
            Queue:
              Fn::GetAtt:
                - MessageQueue
                - Arn
            BatchSize: 10

  # LINEWORKS ->Lambda function responsible for AWS reception processing
  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

  #Lambda function to get the event registered from DynamoDB
  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:
        #Define CloudWatch Event here
        Schedule:
          Type: Schedule
          Properties:
            #Polling interval is 5 minutes
            Schedule: rate(5 minutes)

  #Lambda function permissions (sweet)
  #For now, apply to all Lambda functions
  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 definition
  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
      #Set "Expire Time" to TTL
      #Items can be deleted automatically by setting TTL
      TimeToLiveSpecification:
        AttributeName: ExpireTime
        Enabled: true
      Tags:
        - Key: key
          Value: value

  #Definition of SQS
  MessageQueue:
    Type: 'AWS::SQS::Queue'
    Properties:
      QueueName: lineworks-message-queue

When deploying, I used the following script. The stack name is also appropriate.

build.sh

###Change here according to each environment
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}

Summary

I tried to create a reminder BOT in a serverless environment on AWS.

Next time, I'd like to introduce you to the implementation of Lambda functions. Implementation link

Recommended Posts

[AWS] I made a reminder BOT with LINE WORKS
[AWS] I made a reminder BOT with LINE WORKS (implementation)
I made a stamp substitute bot with line
I made a LINE Bot with Serverless Framework!
I made a household account book bot with LINE Bot
I made a LINE BOT with Python and Heroku
I made a LINE BOT that returns parrots with Go
Make a LINE WORKS bot with Amazon Lex
I made a Mattermost bot with Python (+ Flask)
I made a discord bot
I made a Twitter BOT with GAE (python) (with a reference)
I made a wikipedia gacha bot
I made a fortune with Python.
I made a daemon with Python
Until I return something with a line bot in Django!
I made a rigid Pomodoro timer that works with CUI
[Python] I made a Line bot that randomly asks English words.
I made a new AWS S3 bucket
I made a character counter with Python
I made a Twitter Bot with Go x Qiita API x Lambda
I made a Hex map with Python
I made a life game with Numpy
I made a stamp generator with GAN
I made a roguelike game with Python
I made a simple blackjack with Python
I made a configuration file with Python
I made a WEB application with Django
I made a neuron simulator with Python
I tried to make "Sakurai-san" a LINE BOT with API Gateway + Lambda
I wrote a Slack bot that notifies delay information with AWS Lambda
I made a competitive programming glossary with Python
I made a weather forecast bot-like with Python.
I made a GUI application with Python + PyQt5
I made my dog "Monaka Bot" with LineBot
Create a LINE BOT with Minette for Python
I made a Twitter fujoshi blocker with Python ①
[Python] I made a Youtube Downloader with Tkinter.
LINE BOT with Python + AWS Lambda + API Gateway
I made a simple Bitcoin wallet with pycoin
Serverless LINE bot made with IBM Cloud Functions
I made a random number graph with Numpy
I made a bin picking game with Python
I made a QR code image with CuteR
〇✕ I made a game
I made a bot to post on twitter by web scraping a dynamic site with AWS Lambda (continued)
I made a LINE BOT that returns a terrorist image using the Flickr API
I made a Line Bot that uses Python to retrieve unread Gmail emails!
I made a LINE Bot that sends recommended images every day on time
[Python] I made a LINE Bot that detects faces and performs mosaic processing.
[For beginners] I made a motion sensor with Raspberry Pi and notified LINE!
In Python, I made a LINE Bot that sends pollen information from location information.
Make a morphological analysis bot loosely with LINE + Flask
I made a ready-to-use syslog server with Play with Docker
I made a Christmas tree lighting game with Python
I made a vim learning game "PacVim" with Go
I made a window for Log output with Tkinter
I made a net news notification app with Python
Make a parrot return LINE Bot on AWS Cloud9
I made a Python3 environment on Ubuntu with direnv.
[Valentine special project] I made a LINE compatibility diagnosis!
Procedure for creating a Line Bot on AWS Lambda