【Python】Line APIを使う [第一回 美女Botの作成]


モチベーション

最近女の子とラインをしていない...
すぐに返信してくれてかつ可愛い子はいないものか。
linebotを活用することで実現できるのではないか?

このようなしょうもない理由でlinebotの作成をしようと思う。

環境

・mac Catalina
・Docker version 19.03.13
・Flask 1.1.2
・Python 3.8.3
・docker-compose version 1.27.4
・heroku 7.45.0
・bash

今回作成するもの

まずは環境構築として、dockerからherokuにコンテナを移動し起動するまでをする。
LINEBOTはおはようと言ったらおはようと返してくれる美人のbotを作成する。
あくまで非リアだからこんなことしてるわけでないことに注意!

流れ

第一回の流れを記す。

1.LINE Developersの登録
2.pythonファイルの作成
3.Dockerfileとdocker-compose.ymlの作成
4.herokuへのアップロード

最終的なファイル構成は以下のようになる。

bijobot
├── Dockerfile
├── app.py
├── docker-compose.yml
└── requirements.txt

1.LINE Developersの登録

以下よりサイトに飛ぶ。
LINE Developers

まずはLoginして、Providersよりcreateを選択する。
すでにdisny通知というのがあるのは気にしない。

Create a new providerと出てくるのでdisny通知のようにつけたい名前をつける。
筆者は"自由画像子"という名前をつけた。

次にThis provider doesn't have any channels yetと出てくるのでCreate a Messaging API channelを選択する。

その後以下のような画面に飛ぶのでそれぞれ適当に記入する。
channel iconにはフリー画像でよく使われており個人的にタイプの子を採用した。

規約に同意しAdminを確認すると、以下のように新しくチャンネルが追加されているのが確認できる。

ここで作成したチャンネルに移動し、Basic setting内の

Channnel secret

Messaging API内の

Channel access token

に関しては必要なので控えておくようにする。

2.pythonファイルの作成

Messaging API SDKs
のOfficial SDKsよりflaskを使ってファイルを作成する手順が書かれているのでこれを応用して作成していく。

まずはappを作るための作業ディレクトリを作成する。
bijoとかでいいだろう。

terminal
mkdir bijo
cd bijo

次にpythonファイルを作成する。

作成したpythonファイルは以下のようになる。
必ずapp.pyという名前をつけること。

app.py

from flask import Flask, request, abort

# os内のenvironmentを扱うライブラリ
import os

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)



#環境変数取得

YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]

line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)


app = Flask(__name__)



@app.route("/")
def hello_world():
    return "hello!"

@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):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=event.message.text))


if __name__ == "__main__":
    app.run()

YOUR_CHANNEL_ACCESS_TOKEN
YOUR_CHANNEL_ACCESS_TOKEN
には先程控えた
Channnel secret
Channel access token
を使用する。
osを使ってherokuの環境変数から情報を取り出す。
これは後ほどherokuで設定する。

3.Dockerfileとdocker-compose.ymlの作成

herokuでProcfileなどを作成するのはめんどくさいし、できるならモダンな技術が使いたかったのでdockerを使用する。
Dockerfileとdocker-compose.ymlは以下のようにbijoディレクトリの中に作成する。

※herokuではdocker-compose.ymlは使用されないので注意。

heroku.ymlというdocker-compose.ymlのheroku版を作らなきゃいけないらしいけどなんか面倒そうなので今回はパス。

docker-compose.yml
# ローカル作業用:heroku内では作用しない。

# ローカル作業用:heroku内では作用しない。

version: '3'

services:
  app:
    build: .
    container_name: bijobot
    tty: true
    ports:
      - 5000:5000
    environment:
        FLASK_ENV: 'development'    #デバッグモードON
        FLASK_APP:  "app.py"        #app.pyを起動 
        YOUR_CHANNEL_ACCESS_TOKEN: 控えたaccess token
        YOUR_CHANNEL_SECRET:控えたchannel secret
    volumes:
      - ./:/code/
    command: flask run -h 0.0.0.0
    # command: gunicorn -b 0.0.0.0:$PORT app:app --log-file=-

FLASK_ENV: 'development'としておくことでファイルをsave時に自動でサーバーに反映される。

Dockerfile
FROM python:3.7-alpine

# codeというディレクトリを作成し、そこを作業フォルダとする
WORKDIR /code

#デバッグモードON
ENV FLASK_ENV: 'development'   

# alpineのおまじない
RUN apk add --no-cache gcc musl-dev linux-headers

# requirements.txtをcode内に移動
COPY requirements.txt requirements.txt
# requirements.txtの中のライブラリをinstallする
RUN pip install -r requirements.txt

# すべてのファイルをcode内にマウントする。
COPY . .

# $PORTを指定しないと動かないので注意
CMD gunicorn -b 0.0.0.0:$PORT app:app --log-file=-

さらにrequirements.txtを作成する。

こちらはいかのコマンドを叩くことで解凍可能だが今回は予め作成しておく手順で行く。

terminal
pip freeze > requirements.txt

requirements.txtには以下のように記入する。

certifi==2020.11.8
chardet==3.0.4
click==7.1.2
Flask==1.1.2
future==0.18.2
gunicorn==20.0.4
idna==2.10
itsdangerous==1.1.0
Jinja2==2.11.2
line-bot-sdk==1.17.0
MarkupSafe==1.1.1
requests==2.25.0
urllib3==1.26.2
Werkzeug==1.0.1

requirements.txtはpythonのライブラリを予め書いておきインストールできるようにするもので、本来であれば、

pip install gunicorn flask line-bot-sdk

としなければ行かなかったものを必要なくする。

terminal
touch requirements.txt

次に以下のコマンドを打ってdocker containerを立ち上げる。

terminal
docker-compose build
docker-compose up -d

ここでlocalhost:5000にアクセスし、hello!と表示されることを確認する。

4.herokuでのデプロイ

herokuの登録は予め済んでいるうえですすめる。
まずはherokuにログインする。

terminal
heroku  login
heroku container:login

次にherokuにappを作成する。
heroku create つけたいアプリ名とすることでおk。
今回はbijobijoという適当なapp名をつけた。
ここでエラーが出たら、すでにあるアプリ名なのでつけ直す必要がある。

heroku create bijobijo

次にlocalのgitとremoteのgitを紐付ける必要がある。
以下のコマンドで紐付けは可能。

terminal
heroku git:remote -a アプリ名

次に
heroku config:set つけたい環境変数名="設定する環境変数の文字列" --app 自分のアプリケーション名
とすることでherokuに環境変数がセットできる。

そのため以下をセットする。

heroku config:set YOUR_CHANNEL_SECRET="Channel Secretの文字列" --app 自分のアプリケーション名
heroku config:set YOUR_CHANNEL_ACCESS_TOKEN="アクセストークンの文字列" --app 自分のアプリケーション名

configに関しては以下のようにherokuのサイトで自分のアプリよりsettingのconfig varsより確認することも可能。

セットした環境変数は

heroku config

で確認することもできる。

これで環境変数が設定できたのでuploadしていく。

ここで詰まったとこ

みんな安易に

heroku container:push web

としてたからdocker-compose.ymlの名前のことかと思い

heroku container:push app

としていたがうまく起動しなかった。

どういうことか検索していると、以下の記事に答えが書いてあった。

Container Registry & Runtime (Docker Deploys)

heroku container:push <process-type>

To push multiple images, rename your Dockerfiles using Dockerfile.:

つまり、Dockerfile.webという名前をつけていればこれを起動させることができる。

すぐにDockerfileをDockerfile.webに書き換えて、以下のコマンドを順々に叩く。

terminal
heroku container:push web
heroku container:release web

これでアプリがリリースされた状態になる。

ここで以下のコマンドを叩き、hello!と書いてあるページに遷移すればokである。

terminal
heroku open

実際に動いているコンテナについてはheroku公式より自身のアプリからResourcesより確認することができる。
以下であればwebが起動しているのがわかる。

最後に、LINE Developerより自身のchannelに移動し、Messaging APIより
Webhook settingsを選択し、
https://{自身のアプリ名}.herokuapp.com/callback
をセットしてやれば終わりである。
また、以下のようにUse webhookをonにしないとlinebotが機能しないので注意。

これで毎日美人とメッセージのやり取りができる!!

あれ、なんか固定メッセージが来ているようなので対処します。

Messaging APIよりAuto-replay messagesを選択。

応答設定→詳細設定→応答メッセージ→応答メッセージ設定→オフ
でこれが解消される。

ではでは、

うまく返せていますね。

こころなしか虚しいです。

linebotを使うことで業務の自動化などもできそうなのでこれ以降も挑戦していきたいと思う。

参考記事

全体図

初心者でも簡単!PythonでLINEチャットボットを作成してみよう!

herokuでenvironmentを設定する方法

Python + HerokuでLINE BOTを作ってみた

requirements.txtの取り扱い

Python, pip list / freezeでインストール済みパッケージ一覧を確認

dockerのherokuへのpush

Container Registry & Runtime
↑これがreleaseの際に最も役に立った。

Local Development with Docker Compose
Python初心者がFlaskでLINEbotを作ることになった(Heroku+ClearDB編)