Pyhon line-bot-sdkによるLINE Botの始め方

# Pyhon line-bot-sdkによるLine Botの始め方

## はじめに
LINEとはLINE株式会社(Zホールディングス株式会社傘下)により提供されているモバイルメッセンジャーアプリである。韓国最大のインターネットサービス会社NAVERの創業者で元最高経営責任者の **李海珍**（イ・ヘジン）が、家族や親戚と連絡を取ろうとする**東日本大震災**(2011/3/11)被災者の映像を見て発案し、NHN JAPANで開発されたとされている。そのコミュニケーションは個人-個人だけでなく、個人-法人でも使われており、それは**LINE for Buisiness**として提供されている。今回はLINE for Buisinessで提供されているサービスのうち、**LINE公式アカウント**でのBotの始め方を紹介する。

## LINE Botの事前準備

### LINE Bot応答の流れ
LINEユーザーからのリクエストはLINEサーバーへ送られ、そこから別のBotサーバーへ送りレスポンスを要求する。

 1. LINEユーザーが公式Lineアカウントへメッセージを送り、Messaging APIがそれを受け取る。
 1. Messaging APIに登録しているWebhook URL(Bot server)へHTTPS POSTリクエストを送る。
 1. 受け取ったリクエストの"Header"の著名と"Body"をサーバーに登録している秘密鍵によってエンコードされた著名が一致するかどうか検証する。
 1. 承認されればBotが応答し、その結果をMessaging APIへ返す。Messaging APIから公式LINEアカウントへ返す。

上記のようにLINE Bot作成にはLINE公式アカウントのサービス登録と別のBotサーバーが必要である。

### 事前登録
① **LINE Messaging APIを使うため、LINE Developpersに登録もしくはすでに持っているlineアカウントでログインする。**

https://developers.line.biz/ja/

② **Bot severを使うため、Herokuに登録してアカウントを得る。**

https://dashboard.heroku.com/

③ **Herokuにオリジナルプログラムを連携させるため、git hubに登録してアカウントを得る。**

https://github.com/

### ソースコード

### Herokuに連携したgit hubレポジトリに以下のファイルを置く。

Git内フォルダ構造
Main/
　　┣Main.py #Herokuで実行するLINE Botプログラム
　　┣Procfile #Herokuでの実行コマンドの定義
　　┣requirements.txt #Herokuでの実行環境の指定
　　┣runtime.txt #Herokuでの実行アプリの指定

```python:Main.py
from flask import Flask, request, abort
from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)

app = Flask(__name__)
line_bot_api = LineBotApi('YOUR_CHANNEL_ACCESS_TOKEN')
handler = WebhookHandler('YOUR_CHANNEL_SECRET')

@app.route("/")
def check():
    return "successfully"

@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()

```

```:Procfile
web: python Line_Bot.py
```

```:requirements.txt
# ここに新しく使うようにしたmoduleを追加するのを書き忘れがち
Flask==2.0.2
line-bot-sdk==2.0.1
```

```:runtime.txt
python-3.9.9
```

## LINE Server-Heroku Bot Server-Git hub repositoryを連携する

※2022/4/未明からGithubのトークンが漏れてしまったため、Heroku側からすべてのデプロイを無効にされました。
以下のエラーメッセージがデプロイすると出てくるはずです。
**Item could not be retrieved**
Heroku CLIをinstallして、cloneしたgit repositoryのフォルダで、以下のコマンドを打つと、CUIからデプロイできる。

```
cd youtappdir
git remote -v
heroku git:remote -a herokuappname
git push heroku main
```

### HerokuにGit hubレポジトリを連携し、Deploy Branch(実装確認)をする
正常に**Deploy**された場合は、Viewでweb pageを開くと**Successfully**と表示される。
右上の"more"から"View logs"で実行ログを参照することができる。エラーが出たらここで原因を確認しデバッグする。
![キャプチャ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483556/f40cafbe-5ef1-17de-0a60-7c7e1b753433.png)

### Line DevelopersにWebhookを紐づける
Line DevelopersでWebhook URLに以下を登録し、Webhookを有効にする。

```
https://*****.herokuapp.com/callback
```
※*****はHerokuのアプリ名

## 実行と確認
送ったLineメッセージがオウム返しされたら成功。以下の箇所を修正することで、テキスト・画像・動画・絵文字のそれに応答するかやどのように応答するかなどを変更することができる。今回は受け取ったメッセージテキストをそのまま返す処理が書かれている。

```python
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=event.message.text))
```

## おまけ

自動会話AIを使って、自然な会話をすることもできる。以下は株式会社リクルートのAIを使ったコードである。

https://a3rt.recruit.co.jp/product/talkAPI/

```python
TALKAPI_KEY = 'YOUR_API_KEY'
def talkapi(text):
    url = 'https://api.a3rt.recruit.co.jp/talk/v1/smalltalk'
    req = requests.post(url, {'apikey':TALKAPI_KEY,'query':text}, timeout=5)
    data = req.json()
    if data['status'] != 0:
        return data['message']
    rep = data['results'][0]['reply']
    return rep

@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
   tmp_text = event.message.text
   rep = talkapi(tmp_text)
   line_bot_api.reply_message(
       event.reply_token,
       TextSendMessage(text=rep))
```

### 参考Link

https://github.com/line/line-bot-sdk-python