Code

プログラム概要

主な使用ライブラリ:flask,line-bot-sdk,gspread,oauth2client
やりたかったこと:我が家のオリジナルLine_botを作りたい。でもってgoogle-spreadsheetで返答を簡単に編集したい。

各方面、無課金にて実装できた(これ大事!)。よく見ている「いまにゅのプログラミング塾」の動画を複数参考にさせてもらってます。

こういうやつ

itaru_bot   

作成手順

  

1:Google Cloud Platform設定

GoogleアカウントでGCPに登録。クレジットカードの登録が必要。今回の用途(driveとsheets_API)は 登録すれば制限なく無料にて利用可能のようである(R3.7現在)。
プロジェクトを作成し、「APIとサ-ビス」より「Google Drive API」と「Sheets API」を有効化。
「APIとサ-ビス」の認証情報より、サービスアカウントを適当な名前で新規作成し、jsonファイルをダウンロードする。
スプレッドシートを作成し、「共有」ボタンよりjsonファイル内の「client_email」のアドレスを編集者として共有させる。
※スプレッドシートのURLとSheet名が後々必要になるので控えておく。

↓適当に返してほしい文字列を入れておく

sp_sheet.jpg

2:LINE Developers設定

LINE DevelopersにLineアカウントでサインイン。
messaging-api のページでプロバイダを新規登録する。
ここでは「チャネル基本設定」タブの「チャネルシークレット」と 「Messaging API設定」タブの「チャネルアクセストークン」を控える。

3:line-bot-sdkで実装

いよいよpythonで実装。LINE公式ライブラリの「line-bot-sdk」のpythonのGithubリポジトリより、入力をそのままオウム返し するコードが書いてあるため借用。

    #app.py
    import os 
    import random
    import pandas as pd
    import gspread
    from flask import Flask, request, abort
    from linebot import (
        LineBotApi, WebhookHandler
    )
    from linebot.exceptions import (
        InvalidSignatureError
    )
    from linebot.models import (
        MessageEvent, TextMessage, TextSendMessage,
    )
    from datetime import datetime, timedelta
    from oauth2client.service_account import ServiceAccountCredentials


    app = Flask(__name__)
    #実際は直書きはせず、os.environでherokuの環境変数に入れる。後述。
    YOUR_CHANNEL_ACCESS_TOKEN="手順2のチャネルトークン"
    YOUR_CHANNEL_SECRET="手順2のチャネルシークレット"

    line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
    handler = WebhookHandler(YOUR_CHANNEL_SECRET)
    @app.route('/')
    def hello_world():
        return "hello_world"

    @app.route("/callback", methods=['POST'])
    def callback():
        # get X-Line-Signature header value
        signature = request.headers['X-Line-Signature']

        # get request body as text
        body = request.get_data(as_text=True)
        app.logger.info("Request body: " + body)

        # handle webhook body
        try:
            handler.handle(body, signature)
        except InvalidSignatureError:
            print("Invalid signature. Please check your channel access token/channel secret.")
            abort(400)

        return 'OK'

  #ここまでほぼ公式のまま。ここからちょっと変更して、オウム返しでなく、スプレッドシートから返答を引き出す仕様に。
    @handler.add(MessageEvent, message=TextMessage)
    def handle_message(event):
            reply = get_record(event.message.text)
            line_bot_api.reply_message(
                event.reply_token,
                TextSendMessage(text=reply))
    #GCPの認証して、スプレッドシートの任意のシートを返す関数。
    def auth(): 
        #手順1で用意したjsonファイルを'secret.json'という名前で同一ディレクトリに。
        SP_CREDENTIAL_FILE = 'secret.json'
        # APIを利用する範囲
        SP_SCOPE = [
            'https://spreadsheets.google.com/feeds',
            'https://www.googleapis.com/auth/drive'
        ]
        SP_SHEET_KEY = '手順1で用意したスプレッドシートのURLのd/より後から/editの前まで'
        SP_SHEET = 'シート名'
        credentials = ServiceAccountCredentials.from_json_keyfile_name(SP_CREDENTIAL_FILE, SP_SCOPE)
        gc = gspread.authorize(credentials)
        worksheet = gc.open_by_key(SP_SHEET_KEY).worksheet(SP_SHEET)
        return worksheet

   #auth関数で手に入れたワークシートをデータフレーム化。入力文字列に対応する返しをランダムで出してくれる関数。
    def get_record(key):
        worksheet = auth()
        df = pd.DataFrame(worksheet.get_all_records())
        reply_df = df[["入力", "返し"]].values
        reply = []
        for row in reply_df:
            if row[0] in key:
                reply.append(row[1])
        return (random.choice(reply))
    

4:herokuへデプロイ

無料で使えるPaaSサービス、herokuでデプロイして24時間いつでも返してくれるBotに。上記のapp.pyファイルと同一ディレクトリにsecret.json とあと二つ以下のファイルを作成。
・reqirements.txt

    Flask
    line-bot-sdk
    pandas
    gspread
    oauth2client

・Procfile(テキストファイル。拡張子つけない。)

    web: python app.py

herokuへ登録したのち、ターミナル上でログイン→空アプリ作成→指定してpushという流れ。

    #ログイン
    $ heroku login #ブラウザが立ち上がりログイン画面へ

    #アプリ作成
    $ heroku create 作りたいアプリ名

    #アプリをgit指定
    $ heroku git:remote -a アプリ名

    #アドしてコミット
    $ git add
    $ git commit -m "My first commit"

    #push
    $ git push heroku main

    #環境変数を設定(今回はline_tokenという変数名に)
    $ heroku config:set line_token=アクセストークンの値  

↓デプロイ完了したら、LineのMessaging API設定のWebhook設定に"アプリurl/callback"というURLを登録しWenhookの利用をオンにすれば準備完了。

lineAPI.jpg

↓返事した!最初は結構感動!!

bot_demo.jpg

5:ちょっと改造

スプレッドシート読み込みの復習もかねてちょっと改造。同一スプレッドシートに別のシートを作成。

↓366日分、何の記念日化を登録した「what_day」というシート。調べてみると毎日何かしらの記念日なものだ。

what_day.jpg
    def auth2_whatday():
        #シート名以外、上記のauth()関数と全く同じ
        return worksheet

    #本日日付の「月」と「日」で読み込んだワークシートを紹介。今日は何の日かを返す。
    def get_whatday():
        now = datetime.now() + timedelta(hours=9)
        month = now.month
        day = now.day
        worksheet = auth2_whatday()
        df = pd.DataFrame(worksheet.get_all_records())
        reply_df = df[["月", "日", "内容"]].values
        naiyou = []
        for row in reply_df:
            if row[0] == month and row[1] == day:
                naiyou.append(row[2])
        return (f"今日{month}月{day}日は、{naiyou[0]}ですよ~。")

    #handler.addを書き換え、「何の日」、「なんの日」という文字列を受け取ったら上の関数を発動。
    @handler.add(MessageEvent, message=TextMessage)
    def handle_message(event):
        if "何の日" in event.message.text or "なんの日" in event.message.text:
            reply = get_whatday()
            line_bot_api.reply_message(
                event.reply_token,
                TextSendMessage(text=reply))
        else:
            reply = get_record(event.message.text)
            line_bot_api.reply_message(
                event.reply_token,
                TextSendMessage(text=reply))    

↓日付を計算して今日は何の日か教えてくれる。

whatday_demo.jpg

他にもおみくじ作ったりいろいろ遊べる。

学んだこと

LINE Messaging APIは、調べた感じreplyは制限なく無料で使える(R3.7月現在)。GCPも無料枠でOK。
herokuはクレカ登録なしでも月に550時間までは無料。身内で使う分には全然足りるはず。ただしsleepしてしまうため、 時間が空くと一度返信までに30秒ほどかかる。とはいえ十分遊べる。無料枠バンザイ!
月額700円程払うとスリープもなくなり常時起動出来るので、ちょっとしたお店のBotとか簡単に作れるな~と。 クラウド上のスプレッドシートを簡単にpythonから操作できるのもかなりいろいろ使えそう。