薬を飲むまで飲んだか聞いてくるLINE botアプリを作ってみた[中編]

2021.04.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、リサリサです。以下の続きです。

①Push機能を作る

作るもの

①Push機能:この機能のスタートになる機能です。

構成はこんな感じです。

①EventBrigeから起動

②メッセージを送る対象のユーザーをSSMのパラメーターストアから取得

③対象がまだ今日薬を飲んでいないか、DynamoDBを見て確認

④飲んでいなければメッセージをプッシュ

という機能を作ります。

Lambdaの枠を作成

line-bot-medical-pushを作成します。

さっき作ったレイヤーを追加。

環境変数に、以下を追加。前編で控えた「チャンネルアクセストークン」を設定します。

メッセージプッシュのサンプルコードを試してみる

line-bot-sdkを使ったサンプルコードのテストをしてみます。

リファレンスはここにあります。

TEXTメッセージ

LINEへのメッセージのpushは以下のようにするみたいです。

line_bot_api = LineBotApi(channel_access_token=チャンネルアクセストークン)
line_bot_api.push_message(あなたのユーザーID, TextSendMessage(text='Hello World!'))
試しに書いてみる
import json
import os
from linebot import (LineBotApi, WebhookHandler)
from linebot.models import (MessageEvent, TextMessage, TextSendMessage)
from linebot.exceptions import (LineBotApiError, InvalidSignatureError)


def lambda_handler(event, context):
    
    user_id = 'U20985f92f155b8d6211c4ce99c6c59dd'

    line_bot_api = LineBotApi(channel_access_token=チャンネルアクセストークン)
    line_bot_api.push_message(あなたのユーザーID, TextSendMessage(text='Hello World!'))

    return {
        'statusCode': 200,
        'body': json.dumps('ok', ensure_ascii=False)
    }
テスト

ボタン付きのメッセージ

今回は、ボタン付きのメッセージを送信したいので、以下のようになるみたいです。

line_bot_api = LineBotApi(channel_access_token=チャンネルアクセストークン)
buttons_template_message = TemplateSendMessage(
    alt_text='Buttons template',
    template=ButtonsTemplate(
        title='Menu',
        text='Please select',
        actions=[
            PostbackAction(
                label='postback',
                display_text='postback text',
                data='action=buy&itemid=1'
            )
        ]
    )
)    
line_bot_api.push_message(あなたのユーザーID, buttons_template_message)
試しに書いてみる
line_bot_api = LineBotApi(channel_access_token=チャンネルアクセストークン)
buttons_template_message = TemplateSendMessage(
    alt_text='Buttons template',
    template=ButtonsTemplate(
        title='Menu',
        text='Please select',
        actions=[
            PostbackAction(
                label='postback',
                display_text='postback text',
                data='action=buy&itemid=1'
            )
        ]
    )
)    
line_bot_api.push_message(あなたのユーザーID, buttons_template_message)
テスト

Lambdaのコードを作成

本編のコードを書きます。

import json
import datetime
import os
import traceback
import boto3
from linebot import (LineBotApi, WebhookHandler)
from linebot.models import (MessageEvent, TextMessage, TextSendMessage,TemplateSendMessage,PostbackAction,ButtonsTemplate)
from linebot.exceptions import (LineBotApiError, InvalidSignatureError)


def getDynamoKey(user_id,date):
    """
    DynamoDBからデータを取得
    """
    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table('line-bot-medical')
    
    get_item = table.get_item(
                Key={
                     "user_id": user_id
                     ,"date": date
                }
            )
    if 'Item' not in get_item:
        item = ''
    else:
        item = get_item['Item']
    print(item)
    return item
    

def get_parameters(param_key):
    """
    パラメーターストアから値を取得
    """
    ssm = boto3.client('ssm', region_name='ap-northeast-1')
    response = ssm.get_parameters(
        Names=[
            param_key,
        ],
        WithDecryption=True
    )
    return response['Parameters'][0]['Value']
    
    
def lambda_handler(event, context):
    
    try:
        print(event)
        today = (datetime.datetime.utcnow() + datetime.timedelta(hours=9)).strftime('%Y/%m/%d') 

        #送信先のユーザーを取得
        if 'user_id' in event:
            # テスト時はeventから送信先のユーザーを取得
            users = [event['user_id']]
        else:
            # メッセージをを送る対象のユーザーをSSMのパラメーターストアから取得
            users = json.loads(get_parameters('line-bot-medical-push-users'))

        for user in users:
            
            # 対象がまだ今日薬を飲んでいないか、DynamoDBを見て確認
            status_data = getDynamoKey(user,today)
            if 'status' in status_data:  
                status = status_data['status']
            else:
                status = ''
            if status != 'ok':
                # 飲んでいなければメッセージをプッシュ
                buttons_template_message = TemplateSendMessage(
                    alt_text='お薬飲んだ?',
                    template=ButtonsTemplate(
                        title=today,
                        text='お薬飲んだ?',
                        actions=[
                            PostbackAction(
                                label='飲んだよ',
                                display_text='飲んだよ',
                                data=f"date={today}&status=ok"
                            ),
                            PostbackAction(
                                label='後で飲むよ',
                                display_text='後で飲むよ',
                                data=f"date={today}&status=ng"
                            )
                        ]
                    )
                )    
                #メッセージ送信
                line_bot_api = LineBotApi(channel_access_token=os.environ['ACCESS_TOKEN'])
                line_bot_api.push_message(user, buttons_template_message)

        return {
            'statusCode': 200,
            'body': json.dumps('ok', ensure_ascii=False)
        }

    except:
        traceback.print_exc()
        return {
            'statusCode': 500,
            'body': json.dumps('err', ensure_ascii=False)
        }

トリガーを設定

夜にだけ飲むお薬なので、19時から23時の間1時間置きに動かします。

テスト

いい感じです。

次はこの後のリアクションに対する応答機能を作ります。

後編へ続く

すみません…続きは後編へ…