クラスLINEを楽しくするBotをつくる

#はじめに
学生の皆さんはクラスのLINEグループに入ってますか？グループトークでの会話が弾めばクラスの雰囲気もよくなるはず。そこで今回はクラスLINEが楽しくなるようなBotをつくってみます。
（というのは建前で,KOSENハッカソンでLINEBotつくってるチームが楽しそうだったので自分もやってみる。）
#開発環境
- macos Mojava 10.14.2
- Python 3.6.4

#つくる
###1.Botアカウントの作成
[LINEdevelopersのサイト](https://developers.line.biz/ja/)に自分のLINEアカウントでログインします。
**「Messaging APIを始める」**を選択します。
<img width="1678" alt="スクリーンショット 2019-01-03 21.47.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/295999/a304263d-c3cd-cf50-2f71-3d3bf58cedc8.png">

**「今すぐはじめよう」**を選択します。
<img width="1433" alt="スクリーンショット 2019-01-03 21.52.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/295999/562110f8-88b1-08af-7e46-dd79411b8187.png">

プロバイダーを登録します。もうある人はそっちを使いましょう。
![スクリーンショット 2019-01-07 14.41.49.png](https://qiita-image-store.s3.amazonaws.com/0/295999/d3794cea-94c6-f7d9-1cdf-fa66ae40746c.png)


Botの情報を入力していきます。
プランを**「Developer Trial」**にするところだけ注意してください。
業種はもちろん学生です。
![スクリーンショット 2019-01-03 22.18.24.png](https://qiita-image-store.s3.amazonaws.com/0/295999/fbecfcb6-7c17-e504-cc3e-be2a661426a0.png)

Botの設定を行います。
以下の設定にしているか確認してください。

- Webhook送信: 利用する
- Botのグループトーク参加: 利用する
- 自動応答メッセージ: 利用しない
- 友達追加時あいさつ: 利用する
![スクリーンショット 2019-01-07 14.42.16.png](https://qiita-image-store.s3.amazonaws.com/0/295999/2c5477a1-ea54-d0bd-e007-20f640b88158.png)


最後にBotを友達追加しましょう。
**「チャネル基本設定」**の下までスクロールするとQRコードがあるのでLINEアプリなどから読み取りましょう。
<img width="375" alt="IMG_1344.png" src="https://qiita-image-store.s3.amazonaws.com/0/295999/ce5cc896-c162-9fac-22f3-0007036a066a.png">
この時点では既読はついても返事はしてくれません。悲しいね。


###2.サンプルの作成
まずは受け取ったテキストをおうむ返しするBotをつくります。

まずは環境構築
Flask・SDK of the LINE Messaging API for Python・ngrokをインストールします。

```
$ pip install flask 
$ pip install line-bot-sdk
$ brew install ngrok
```

[line-bot-sdk-python](https://github.com/line/line-bot-sdk-python)の`README.rst`へ行き,Usageのサンプルプログラムをコピーして`app.py`として保存します。
下記ではデバッグのためにメッセージを返す関数を追加しました。

```python:app.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 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:
        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()
```

####Channel Secretとアクセストークンの確認
先ほどの「LINE developers」の画面で**Channel Secret**と**Channel Access Token**を確認します。

- Channel Secret確認

![スクリーンショット 2019-01-07 16.31.32.png](https://qiita-image-store.s3.amazonaws.com/0/295999/899a6d76-4e5b-c94e-d136-241a99dd5248.png)



- アクセストークン発行

![スクリーンショット 2019-01-07 16.31.57.png](https://qiita-image-store.s3.amazonaws.com/0/295999/4527d26d-ef00-8142-e0af-8cdbe4850a81.png)


`app.py`のソースコードの`YOUR_CHANNEL_ACCESS_TOKEN`と`YOUR_CHANNEL_SECRET`の部分をそれぞれ確認した値に書き換えます。


###3.Flaskの実行とngrokによる公開
####Flaskの実行
app.pyのあるディレクトリに移動して以下のコマンドを実行します。

```
$ export FLASK_APP=app.py
$ export FLASK_DEBUG=1
$ flask run --host=0.0.0.0
```
http://localhost:5000 にアクセスし「**hello world!**」の画面が出れば成功です。

####ngrokによる公開
一時的に外部へ公開するためにngrokを使います。
以下コマンドをFlaskを実行したのと同じ場所で実行してテストします。
今回は5000を指定しましょう。

```
$ ngrok http 5000
```
実行するとこのような画面が出てきます。

```
ngrok by @inconshreveable                                                           (Ctrl+C to quit)

Session Status                online
Session Expires               7 hours, 59 minutes
Version                       2.2.8
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://c7602dfa.ngrok.io -> localhost:5000
Forwarding                    https://c7602dfa.ngrok.io -> localhost:5000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00
```
`https://`で始まるアドレスをコピーします。
この場合は`https://c7602dfa.ngrok.io`です。

####Webhook URLの更新
先ほど取得したURLを登録します。
今回は`https://c7602dfa.ngrok.io/callback`が**Webhook URL**になります。
LINE developers画面の**Webhook URL**を更新しましょう。
<img width="1334" alt="スクリーンショット 2019-01-09 22.14.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/295999/e6e3f599-d113-6d77-aeb4-e8a36ddf1ee3.png">

更新ボタンを押して,もう一度Botに話しかけてみます。
<img width="375" alt="IMG_1366.png" src="https://qiita-image-store.s3.amazonaws.com/0/295999/41aa50aa-7287-a7c0-9c60-5ee14febf9ec.png">
おうむ返ししてくれました！

###4.楽しくする
このままだと特に楽しくもないのでクラスラインで使えそうな機能を追加しましょう。
今回は時間割を教えてくれるBotをつくります。

先ほどの`app.py`を書き換えます。

```python:app.py
from flask import Flask, request, abort

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

app = Flask(__name__)

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

lesson = {
    '月曜日の時間割':'月曜日は\n1:こくご\n2:たいいく\n3:さんすう\nです。',
    '火曜日の時間割':'火曜日は\n1~2:りかじっけん\n3:こくご\nです。',
    '水曜日の時間割':'水曜日は\n1:さんすう\n2:おんがく\n3:せいかつ\nです。',
    '木曜日の時間割':'木曜日は\n1:たいいく\n2:かていか\n3:りか\nです。',
    '金曜日の時間割':'金曜日は\n1:さんすう\n2:こくご\n3:がっかつ\nです。'
}

@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:
        abort(400)

    return 'OK'


@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    if event.message.text =='時間割を教えて':
        day_list = ["月", "火", "水", "木", "金"]
        items = [QuickReplyButton(action=MessageAction(label=f"{day}", text=f"{day}曜日の時間割")) for day in day_list]
        messages = TextSendMessage(text="何曜日の時間割ですか？",quick_reply=QuickReply(items=items))
        line_bot_api.reply_message(event.reply_token, messages=messages)
    elif event.message.text in lesson:
        line_bot_api.reply_message(
            event.reply_token,
            TextMessage(text=lesson[event.message.text])
        )

    '''
    line_bot_api.reply_message(
        event.reply_token,
        TextSendMessage(text=event.message.text))
    '''

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

```

「**時間割を教えて**」というメッセージに対して,クイックリプライの機能で曜日を決めてもらい,その曜日ごとの時間割を返します。
<img width="375" alt="IMG_1368.png" src="https://qiita-image-store.s3.amazonaws.com/0/295999/74bdfbd7-efa1-3b03-58b4-f2f6ca21c269.png">
金曜日を選択
<img width="375" alt="IMG_1369.png" src="https://qiita-image-store.s3.amazonaws.com/0/295999/fee23a7d-c254-ef0e-e8f7-916b06b54699.png">
時間割を聞いたときに全員に既読無視されるようなことが無くなるといいな😊

#終わりに
とりあえず,クラスラインに入れて使ってもらうところまではできたのでよかったです。
LINEBotのいいところは身近の人たちに使ってもらえて直接意見を聞けるところだと思います。
これからもっとクラスラインを盛り上げるBotにできたらいいな。
#参考
[Messaging API - LINE Developers](https://qiita.com/suigin/items/0deb9451f45e351acf92)
[1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)
[FlaskでLINE botを実装し，herokuにdeployするまで](https://qiita.com/suigin/items/0deb9451f45e351acf92)