PythonでLINEにメッセージを送る

## はじめに

何番煎じかわかりませんが，Python x LINE NotifyでLINEにメッセージを送れるボットを作ったので，その備忘録です。

深層学習モデルの学習など，時間がかかる処理を回しているときに，その場を離れても進捗状況を知りたい！というときに重宝しています。



## できること

LINEのグループや自分自身にメッセージ・画像・スタンプを送ります

※こちらからのメッセージには反応できません

<div align="center">
<kbd><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426750/e54b48c0-02f6-ec54-3f7d-84ce9777318e.png" width=50%></kbd>
</div>


## LINE Notifyについて

[LINE Notify公式](https://notify-bot.line.me/ja/)

> Webサービスからの通知をLINEで受信

> Webサービスと連携すると、LINEが提供する公式アカウント"LINE Notify"から通知が届きます。

> 複数のサービスと連携でき、グループでも通知を受信することが可能です。



## 動作環境

僕の環境は下の通りです。
が，Pythonで`import requests`できれば動くと思います。

* Windows10 (64bit)
* Python3.6



## 準備

### LINE Notifyと友達になる

まずはLINE Notifyを友達に追加します。
自分に送るだけならこれで大丈夫です。
グループに送りたいときは，そのグループにLINE Notifyを招待しておきます。
このLINE Notifyからメッセージが送られてきます。


### アクセストークンの発行

次に，アクセストークンを発行します。

#### 1. マイページにアクセス

① [LINE Notify公式](https://notify-bot.line.me/ja/)にアクセス
② 右上からログイン
③ ログインと同じところをクリックし，マイページへ

<div align="center">
<kbd><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426750/11d400cc-09bf-9b58-f55e-03f4ec01d220.png" width=80%/></kbd>
</div>


#### 2. トークンの発行

① ページ下部の「トークンを発行」をクリック

<div align="center">
</kbd><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426750/4ad9e978-bb91-7690-de05-08fe39d41e48.png" width=80%/></kbd>
</div>

② トークン名を指定し，グループを選択して発行

<div align="center">
<kbd><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426750/283d4c0a-08b6-12a4-0e9b-bdaa8416322c.png" width=80%/></kbd>
</div>

③ 発行されたトークンをコピーしてどこかに保存

<div align="center">
</kbd><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426750/8a61ed05-e374-893a-1d1c-d7319485c97e.png" width=50%/></kbd>
</div>

④ ページ上部でちゃんと連携されているか確認

<div align="center">
<kbd><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426750/b930c352-18cf-97d7-2cb9-76f84433cc72.png" width=80%/></kbd>
</div>


連携を解除したいときは「解除」をクリックすればOKです。

トークンを保存し忘れたときなどは，一旦解除してもう一度発行すればOKです。


## 実装

### ライブラリ

必要なのは `requests` だけなので，

```python
import requests
```


### 準備

LINE NotifyのAPIのURLと，アクセストークンを含んだヘッダが必要になります。

```python
url = "https://notify-api.line.me/api/notify"
access_token = 'Your Access Token'
headers = {'Authorization': 'Bearer ' + access_token}
```


### メッセージを送る

3行でメッセージを送ることができます。
なお，空文字は送れません。

```python
message = 'Write Your Message'
payload = {'message': message}
r = requests.post(url, headers=headers, params=payload,)
```


### 画像を送る

画像を送るときは， `requests.post` に `files` も渡します。
なお，空文字でないメッセージと一緒でないと送れません。
空文字と一緒に送ろうとすると，エラーは出さずに何も送らないという挙動をするので注意が必要です。

```python
message = 'Write Your Message'
image = 'test.png'  # png or jpg
payload = {'message': message}
files = {'imageFile': open(image, 'rb')}
r = requests.post(url, headers=headers, params=payload, files=files,)
```


### スタンプを送る

スタンプを送るときは，`payload`に`stickerPackageId`と`stickerId`を追加します。
これらのIDは [ここ](https://developers.line.biz/ja/docs/messaging-api/sticker-list/) から探してきて指定します。
こちらも画像と同様，空文字でないメッセージと一緒じゃないと送れず，空文字と一緒に送ろうとしてもエラーは出ません。
また，存在しないIDを指定した場合はメッセージも送られないので，注意が必要です。

```python
message = 'Write Your Message'
payload = {
    'message': message,
    'stickerPackageId': 1,
    'stickerId': 13,
}
r = requests.post(url, headers=headers, params=payload,)
```


### まとめる

以上をまとめてクラスにしてしまうと，次のようになります。

```python:line_notify_bot.py
import requests

class LINENotifyBot(object):
    API_URL = 'https://notify-api.line.me/api/notify'
    def __init__(self, access_token):
        self.__headers = {'Authorization': 'Bearer ' + access_token}

    def send(
        self,
        message,
        image=None,
        sticker_package_id=None,
        sticker_id=None,
    ):
        payload = {
            'message': message,
            'stickerPackageId': sticker_package_id,
            'stickerId': sticker_id,
        }
        files = {}
        if image != None:
            files = {'imageFile': open(image, 'rb')}
        r = requests.post(
            LINENotifyBot.API_URL,
            headers=self.__headers,
            data=payload,
            files=files,
        )
```

実行は次のようになります。

```python
from line_notify_bot import LINENotifyBot

bot = LINENotifyBot(access_token='Your Access Token')

bot.send(
    message='Write Your Message',
    image='test.png',  # png or jpg
    sticker_package_id=1,
    sticker_id=13,
)
```

こちらは [GitHubに公開](https://github.com/moritagit/LINENotifyBot) しているので，使えればOKという方はcloneして頂ければすぐ使えます。
[test/test.ipynb](https://github.com/moritagit/LINENotifyBot/blob/main/tests/test.ipynb) にこれらの実行例をまとめてあるので，そちらを見て頂いた方がわかりやすいかもしれません。

```console
git clone https://github.com/moritagit/LINENotifyBot.git
```



### まとめ

自分が使いやすいように作ってみましたが，かなり簡単に使える割になかなか便利です。
とりあえず深層学習モデルの学習中にlossの値や学習曲線を送ったりしてみてます（tensorboardを使いましょう）。
スタンプを自動で送りたい場面にはまだ出会ってないので，早く出会いたいところ。