Lambda + CloudWatch + DynamoDB + LINE Notifyでリマインダーを作る


はじめに

DynamoDBのキャッチアップのついでに、リマインダーを作りたかったので作ってみた。
今回は時間があまりなかったので、備忘録みたいな感じ。(まだ完成していない)

構成としては以下のような感じ。

本当は、Androidアプリを作って、プッシュ通知までもって行きたかったが時間がないので後日。
通知の部分は、簡単にできるLineNotifyを使ってLineで通知をするようにした。

DynamoDBを立てる

  1. IAMにて、ユーザーにAmazonDynamoDBFullAccessの権限をつける
  2. DynamoDBのトップページにてテーブル作成を押す
  3. テーブル名とパーティーションキー名(今回はDate)を入力する。
  4. できたDynamoDBの構成は以下の通り
    • テーブル…データのコレクション。
    • 項目 …各テーブルには0以上の項目がある。
    • 属性 …各項目は1つ以上の属性でできている。
  5. 項目の作成ボタンから指定のテーブルの項目とデータが設定できる 今回の構成
    • remainder_id: Number ID
    • color: String 表示カラー(6進数)
    • contents: String 内容
    • Date: String 日付(format: 2019-12-22)
    • time: String 時間(format: 00:00)
    • type: Number カテゴリー

DynamoDB開発者ガイド:https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Introduction.html

Lambdaで関数を作成する

Lambdaには3つ関数を作る予定。
- Regist Remainder: リマインダーを登録する
- Put Remainder: 前日にリマインダーをCloudWatchに登録する
- Push Remainder: リマインダーを通知する

注意点1: 関数内でDynamoDBを接続する際は、roleの設定を忘れない
 参考→ LambdaからDynamoDB見るときの権限:https://qiita.com/hellscare/items/d80c9ff0290966eb0cf8
注意点2: パーティションキーとソートキーの関係を理解しないとデータをうまく取れない。
 参考→ DynamoDBでPythonを使って試してみた:https://qiita.com/estaro/items/b329deafdfef790aa355

RegistRemainder関数

※あとで作る

PutRemainder関数

※これまだうまくできていません。。

import json
import boto3
import datetime
from boto3.dynamodb.conditions import Key


cloudwatch = boto3.resource('cloudwatch')
dynamodb = boto3.resource('dynamodb')
remainder_table = dynamodb.Table('Remainder')


def lambda_handler(event, context):
    # get tomorrow schedule from DB
    response= remainder_table.query(
        KeyConditionExpression=Key('Date').eq(str(datetime.date.today()))
    )
    print('Get Tommorow Data: ', response)

    if len(response['Items']) > 0:
        for data in response['Items']:
            print('GET Items: ', data)
            # リマインド時間取得
            remaind_date = datetime.datetime.strptime(str(data['Date'])+ " " + str(data['time']), '%Y-%m-%d %H:%M')
            print('Set Date: ', remaind_date.datetime)
            print('Set Remaind Id', data['remaind_id'])
            # Put an event
            response = cloudwatch.put_events(
                Entries=[
                    {
                        'Time': remaind_date.datetime,
                        'Resources': [
                            ARNYour AmazonResourceName',
                        ],
                        'Detail': {"remaind_id": data['remaind_id']}
                    }
                ]
            )
            print(response['Entries'])
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

このLambda関数は毎日0時に起動するようにCloudWatchで設定。
起動すると、今日のRemainderの時間をDynamoDBから探し出して、CloudWatchEventに登録する。

PushRemainder関数

import json
import boto3
import datetime
from boto3.dynamodb.conditions import Key
import requests


dynamodb = boto3.resource('dynamodb')


def lambda_handler(event, context):
    print('START lambda_handler: getParam ->', event)
    print('TODAY IS: ', str(datetime.date.today()))
    remainder_table = dynamodb.Table('Remainder')
    table_response= remainder_table.query(
        KeyConditionExpression=Key('Date').eq(str(datetime.date.today())) & Key('remaind_id').eq(event['remaind_id'])
    )

    print('>>>>>>Get Data: ', table_response)

    if len(table_response['Items']) > 0:
        for remaind_data in table_response['Items']:
            header = {'Authorization':'Bearer <access token>'}
            param = {'message': remaind_data['contents']}
            response = requests.post('https://notify-api.line.me/api/notify', headers=header, data=param,)
            print('>>>>>SEND: ', remaind_data['contents'])
            print('>>>>>>POST Response: ', response)

    return {
        'statusCode': 200,
        'body': json.dumps('Remaind Finish!')
    }

CloudWatchEventに登録されて、指定の時間になると引数が渡されて実行される関数。
実行されたら、
今日の日付と、引数で渡されたremaider_idを元にDynamoDBから検索。
取得したリマインダーデータをLineNotifyを使ってLineに通知をする。

<LineNotifyに接続する>
 公式Document: https://notify-bot.line.me/doc/ja/
 ※LineNotifyにリクエストを送る必要があるので、Lambdaにrequestsライブラリ等の外部モジュールを設定する
  注意点: zipをアップロードするとき、lambda_function.pyのデータが消える可能性があるので注意!!!!!!
  →requestsモジュールのインストール:https://qiita.com/SHASE03/items/16fd31d3698f207b42c9

 ※Notifyのアクセストークン取得はPCサイトからしかできないので注意
  →トークンの発行方法:https://qiita.com/iitenkida7/items/576a8226ba6584864d95

結論

こんな感じ。
画像とかも表示できると思うので、おいおい追加していきます。

終わりに

随時、進捗があったら更新します!
年末までには完成させたらいいなと思います!