herokuを定期的に自動deployして、ペットの様子を監視できるLINE botを作った

# はじめに
義姉夫婦が旅行に行く間、ウサギ（そらちゃん）を預かることになった。
旅行中もお義姉さんがそらちゃんを近くに感じられるように、
メッセージを送ったら、そらちゃんの現在の様子を確認できるbotを作った。

# こんな人向け
- LINEmessagingAPIを使って開発したい人
- LINEmessagingAPIとHerokuを連携してみたい人
- line-bot-sdk-pythonを使用して開発をしてみたい人

# 様相技術
- Python
- line-bot-sdk-python
- heroku
- macOS
- Android
- Selenium

# 方法
だいたいこんな感じ
![udsuds.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1124047/6989bbbd-399d-a189-3457-e6293decee9c.png)

1. droidcamで兎を常時撮影
2. 5分毎に映像のスクショを撮影
3. Herokuにdeploy
4. 義姉がメッセージを送った場合に、最新の画像が送信される

# 目次

# LINE チャネルの作成
私が[以前作成した記事](https://qiita.com/nekonisi/items/291d7ba76a0b4cb42f8c)を参照してください
※ フィードバックくれると嬉しいです。
# Herokuアプリの作成
下記よりHeroku CLIをインストール
https://devcenter.heroku.com/ja/articles/heroku-cli

Heroku loginをする（ブラウザが立ち上がります）

```
$heroku login
```

HerokuCLIでアプリを作成する

```zsh
$heroku create {app名}    
Creating ⬢ {app名}... done
https://{app名}.herokuapp.com/ | https://git.heroku.com/{app名}.git
```

ローカルのファイルとHerokuアプリの連携

```zsh
$mkdir {app名}
$cd {app名}
$git init
$heroku git:remote -a {app名}
```

※ これで、```git push heroku master```すれば、deployされる

# カメラの準備
- AndroidのPlayStoreでdroidcamと検索すれば、インストールできます  
[droidcam](https://play.google.com/store/apps/details?id=com.dev47apps.droidcam&hl=ja&gl=US)
- アプリを立ち上げて、記載されているIPアドレスをブラウザに入力すれば映像が確認できるはずです。

# 画像を返却するためのアプリを作成する
```zsh
$cd {app名}
$pip3 install line-bot-sdk
$mkdir static
```

## ファイル作成
下記ファイルを作成する

```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, ImageSendMessage
)
import os

app = Flask(__name__)
#環境変数取得
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]
APP_NAME = os.environ["APP_NAME"]

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

@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,
        ImageSendMessage(
            original_content_url='https://' + APP_NAME + '.herokuapp.com/static/image.png',
            preview_image_url='https://' + APP_NAME + '.herokuapp.com/static/image.png'
        ))


if __name__ == "__main__":
#    app.run()
    port = int(os.getenv("PORT", 5000))
    app.run(host="0.0.0.0", port=port)
```

```txt:requirements.txt  
Flask==0.12.2
line-bot-sdk==1.5.0
```

```txt:Procfile 
web: python main.py
```

```txt:runtine.txt 
python-3.7.3
```

## 環境変数設定

```zsh
$heroku config:set APP_NAME={app名} YOUR_CHANNEL_ACCESS_TOKEN={LINEチャネルのアクセストークン} YOUR_CHANNEL_SECRET={LINEチャネルのシークレット}
```

## 動作確認
staticフォルダに任意のimage.pngを格納。

```zsh
$git add .
$git commit -m "hoge"
$git push heroku master
```

### Webhook設定
作成したLINEチャネル > Messaging API設定 > Webhook URLに
「https://{app名}.herokuapp.com/callback」を指定する。

対象チャネルにメッセージを送ると、画像が返却されるはずです。

# droidcamから画像を作成する
今回はdroidcamの映像をブラウザで開いて、スクショを撮ることで画像を作成した。

↓こんなかんじ
![3207.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1124047/472e2aed-b467-5dd8-d7b0-bc259d1a089d.jpeg)

## chrome webDriverのインストール
Seleniumを使用して、スクショを撮るのでchrome webDriverをインストールする必要がある。
[こちら](https://chromedriver.chromium.org/downloads)からダウンロードされているバージョンのwebDriverをインストールしてください
解凍後、chromedriverを/usr/local/binに移動します。

コンソールでchromedriverを実行した際に下記のようになればOKです。

```
% chromedriver      
Starting ChromeDriver 89.0.4389.23 (61b08ee2c50024bab004e48d2b1b083cdbdac579-refs/branch-heads/4389@{#294}) on port 9515
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
```

## seleniumのインストール

下記でOKです。

```
pip3 install selenium
```

## build用のスクリプトを作成する
main.pyと同じ階層に下記のファイルを追加してください。
※ 設定値は環境によって変更してください

```python:build.py
! /bin/sh
import cv2
import os
import time
import subprocess
from selenium import webdriver

wd= '{main.pyが存在するディレクトリ}'
driver = webdriver.Chrome()
driver.get('{droidcamのURL}')
driver.set_window_size(1250, 1036)
driver.execute_script("document.body.style.zoom='90%'")
time.sleep(2)
driver.save_screenshot(wd + "/static/image.png")
driver.quit()

os.chdir(wd)
cmd = '/usr/local/bin/git add .;/usr/local/bin/git commit -m "hoge";/usr/local/bin/git push heroku master'
subprocess.call(cmd, shell=True)
```

### 動作確認

下記を実行すると、画像が更新されherokuにdeployが行われるはずです。

```zsh
python build.py
```

## 定期実行用にcronを設定

```
crontab -e
```

下記のように設定します。
```
PATH={自分環境のPATHの値}
*/5 * * * * * /usr/bin/python3 {フルパス}/build.py
```

# おわりに
はじめてheroku触れたのでよかった。
誰かの参考になれば幸いです。
雑に書いたので、何でもいいのでフィードバックもらえると嬉しいです。

[この記事](https://www.1915keke.com/entry/2018/12/17/074038)で正解出してそうなので、真似してやってみる。