Lambda と Aurora Serverless で超実用的な Twitter Bot をつくってみた

はじめまして、川野です。

AWS を勉強するにあたり、実際に手を動かすことはやはり大切ですよね。
builders.flash の連載記事の中に、Twitter Bot を作成するという初心者向けのとても面白いハンズオンがあります。ド文系IT未経験で入社した2年目社員の私も、この連載のおかげで楽しく AWS の勉強ができているわけです。
本記事はその連載記事への敬意と感謝の意を込めた、やってみた +α 記事になります。

builders.flash の記事は現在第4回まで公開されています。(第1回の記事はこちら
私は今回、第3回までの内容を応用し、ハンズオン記事とは異なるサービスを使いながら、最高に実用的な Twitter Bot を作りました。

つくったもの

突然ですが、あなたは毎日の献立づくりに悩んでいませんか?

私は一人暮らしをしているのですが、献立を考えるのが面倒で、だいたいメニューが決まっています。
もし一緒に食事する家族がいたらと思うと、それはもう大変なことだろうなあと思うわけです。

そんなわけで、今回は 1日3食分の献立をつぶやいてくれる Twitter Bot を作成しました。
それではいきましょう!

構成

今回の構成は次のとおりです。

menu365bot_構成図

もととなるハンズオンではツイート文言の取得に Amazon DynamoDB を使用していますが、今回は献立を取得するだけなので NoSQL である必要はないですし、せっかくなので異なるサービスを使ってみよう!ということで Amazon Aurora Serverless を使用しています。

当初、献立はこんな感じで格納することを考えていました。(のちにテーブルが2つに分かれることになります)

menu
ほうれん草のクリームパスタ
豆腐ハンバーグ
海鮮ちらし寿司

Amazon Aurora Serverless について

ここで、Aurora Serverless を使用することでどんなメリットがあるのか、簡単に説明しましょう。

まず、Aurora Serverless は使用頻度の低い用途に適しています。
ニーズに応じて自動的に起動し処理を行うという特徴があり、消費するデータベースリソースに対してのみ料金が発生する ためです。
Twitter Bot は1日3回のみつぶやく予定のため、アクティブなときのみ料金が発生するのはコスト効率が良いですね。

また、DB クラスターのエンドポイントとして機能する Data API を有効化することで、Lambda から簡単に DB クラスターにアクセス し、SQL クエリを実行できるようになります。
さらに、Data API を有効化すると、RDS コンソールからクエリエディタを使用できるのも便利です。(詳細はこちら

気づいてしまったこと&ひらめき

献立をテーブルに格納するのはいいのですが、それなりの数考えないと結局同じ献立のループになってしまうんですよね。

そこでひらめいた。
テーブルを2つに分けて、組み合わせで異なる料理にしよう! と。
実際、同じ材料を使用して異なる料理を作ることも多いわけですから。

先ほど提示したテーブルを分割して組み合わせれば、

ほうれん草のクリームパスタ、豆腐ハンバーグ、海鮮ちらし寿司、ほうれん草のハンバーグ、豆腐ちらし寿司、海鮮クリームパスタ、ほうれん草のちらし寿司、豆腐クリームパスタ、海鮮ハンバーグ
たった3種類の料理が、9種類の料理になりました。
なかなかのアイデア料理も生まれているようですし、一石二鳥とはこのこと。
40ほどの料理を考え、DB を準備しました。

Lambda関数の作成

私が作成したコードは下記のとおりです。

builders.flash の第3回記事で作成した最終的なコードの init メソッド、tweet メソッドはそのまま活用します。

init メソッドは Twitter API Key / Token 情報を Parameter Store から取得する処理を、tweet メソッドは menu(=献立)を受け取りツイートする処理を行っています。詳しくはこちらを参照してください。

ハンズオン記事の DynamoDB 同様、今回も AWS SDK for Python (boto3) を使用して SQL クエリを実行 します。

import json
import os
from requests_oauthlib import OAuth1Session

import boto3

rds_data = boto3.client('rds-data')
ssm_client = boto3.client('ssm')

oauth = None

def lambda_handler(event, context): 
    init()
    
    menu = ''
    table_list = ['menu1', 'menu2']
    
    response = ssm_client.get_parameter(
        Name='/credentials/menu365db',
        WithDecryption=True
    )
    menu365db_parameters = json.loads(response['Parameter']['Value'])
    
    cluster_arn = menu365db_parameters["cluster_arn"]
    secret_arn = menu365db_parameters["secret_arn"]
    
    for table_name in table_list:
        response = rds_data.execute_statement(
            resourceArn = cluster_arn, 
            secretArn = secret_arn, 
            database = 'menu365db', 
            sql = 'SELECT * FROM ' + table_name + ' ORDER BY RANDOM() LIMIT 1'
        )
        menu += response['records'][0][0]['stringValue']
    
    tweet(menu)
    
def init():

# 省略

def tweet(menu):

# 省略

Data API のパラメータに resourceArnsecretArn があることが確認できます。

resourceArn
… DB クラスターの Amazon リソースネーム (ARN)
secretArn
… DB クラスターへのアクセスを有効にするシークレット ARN

これらを使用して DB クラスターへのアクセスを許可しているわけです。

なお、シークレット ARN は AWS Secrets Manager のコンソールから確認できます。
今回、ARN とシークレット ARN はいずれも AWS Systems ManagerParameter Store を使用してパラメータ化しています。
(パラメータ化については第3回記事のここを参照してください)

そして menu1menu2 の2つのテーブルに対して SQL クエリを実行していることがわかるかと思います。
ORDER BY RANDOM() LIMIT 1 で、ランダムに並び替え1レコード取得しています。

実行結果

実行結果はこんな感じです。

さいごに

今回ははじめて Aurora Serverless を使用しました。
自分で情報収集しながら はじめましてのサービスを使うのは初めてだったので、良い経験となりました。

今回作成した Twitter Bot は飽きるまで動かす予定なので、良かったら見守ってあげてください。
何より、あなたの生活をより便利にしてくれるはずです。

まだまだ勉強中で、不十分な内容があったかもしれませんが、最後までお読みいただきありがとうございました。

以上、川野でした!

タイトルとURLをコピーしました