LINE Notify を利用して UIFlow のプログラムで LINE に通知を送る（日本語テキストも送信） #M5Stack

[先日参加したオンラインハッカソン](https://protoout.connpass.com/event/172136/)で「[UIFlow](https://m5stack.github.io/UIFlow_doc/ja/) のプログラムで LINE に通知を送る（[LINE Notify](https://notify-bot.line.me/ja/) を利用）」ということをやろうとした際に、その場で初めて試そうとして、すぐにはうまくいかなかった件を、あらためて時間をとって確認してみました。

最終的に成功して、↓このような結果を得られました。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">M5GO から LINEアプリに日本語の通知を送るテスト。<br><br>プログラムは UIFlow で作り、 <a href="https://twitter.com/hashtag/LINE?src=hash&amp;ref_src=twsrc%5Etfw">#LINE</a> Notify で通知を送ってます。<br>IFTTTを使うやり方も試しましたが、この動画ではIFTTTを使わないやり方で実現しています。<br><br>（ <a href="https://twitter.com/gaomar?ref_src=twsrc%5Etfw">@gaomar</a> さん、UIFlow でのやり方を見つけました！）<a href="https://twitter.com/hashtag/M5Stack?src=hash&amp;ref_src=twsrc%5Etfw">#M5Stack</a> <a href="https://t.co/6bDhrHH8xZ">pic.twitter.com/6bDhrHH8xZ</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1252588326004985856?ref_src=twsrc%5Etfw">April 21, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## やってみた内容
### node.js や IFTTT で LINE Notify を使った際の HTTPリクエストの中身を見てみる
以前、[IFTTT経由で LINE Notify を使った記事（MESH から LINE に通知を送るという内容）](https://qiita.com/youtoy/items/55265567c8f892594bc8)を書いたり、[JavaScript祭りというイベントの IoTセッションに登壇した際のネタ](https://www.slideshare.net/yo-to/20190621-iotlt-151647638)で、node.js ＋ LINE Notify で通知を送る、というものを作っていました。

それらの既に動作しているものと、UIFlow のプログラムで送られる HTTPリクエストが同じになれば問題なく動くはず、と考えて、その中身の比較をやってみました。
本来は、[LINE Notify の公式ドキュメント](https://notify-bot.line.me/doc/ja/)を読んで、というやり方をするべきかなと思いつつも、HTTPリクエストのデバッグも試してみたかったという背景もあってこのような流れに。

#### あまり詳細に触れない部分
今回の記事では、LINE Notify の使い方については、詳しくは触れません。
[「LINE Notify 使い方」などというキーワードでググると、その辺りを説明した記事がたくさんでてくる](https://www.google.com/search?q=LINE+Notify+%E4%BD%BF%E3%81%84%E6%96%B9)ので、それらをご参照ください。
また、以下で [IFTTT](https://ifttt.com/) の話も少し出てきますが、IFTTT の使い方についても同様です。

#### HTTPリクエストのデバッグ①（利用する Beeceptor について）

上記の node.js 等で送った HTTPリクエストの内容を受け取った側で見てみようと、以前見かけて気になっていた「[Beeceptor](https://beeceptor.com/)」を使ってみました。
　●Beeceptor - Zero Coding Rest API Mocking - Rest API Mock Server
　　https://beeceptor.com/
<img width="589" alt="Beeceptor.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/e8fbaa9e-3119-8c89-15fa-12add6d8a352.jpeg">
Beeceptor については、下記からの引用で補足します。
　●Webhookのデバッグに便利なツール「Beeceptor」の紹介 | SendGridブログ
　　https://sendgrid.kke.co.jp/blog/?p=11260
> Beeceptorには主に次のような機能があります。
> 　1. HTTPのエンドポイントを作成して受信結果を表示する機能
> 　2. 応答コードとレスポンスを自由に変更できるモックAPI機能
> 　3. HTTPリクエストを中継するプロキシ機能

また、[Beeceptor の FAQ](https://beeceptor.com/faq)を見ると、「How Beeceptor is different from [RequestBin](https://requestbin.com/) or [Mocky.io](https://www.mocky.io/)?」という項目があり、他の似た機能を持つものとの違いも書いてあります。
記載を読んでみると「RequestBin と Mocky.io がそれぞれ持つ異なる機能を両方とも包含していて、さらにプロキシ機能を持ったものが Beeceptor」ということのようです（上記 1〜3 の機能を全て持っているのが特長、となるようです）。

#### HTTPリクエストのデバッグ②（Beeceptor を試してみる）

以前作ったものを動かす前に、まずは公式でも案内されている curl を使ったやり方で試してみます。
LINE Notify を使って通知を送る際のコマンドは、通常は下記です。

```bash
curl -X POST -H 'Authorization: Bearer 【LINE Notify のキー】' -F 'message=【送りたいテキストの内容】' https://notify-api.line.me/api/notify
```

ここでコマンドの最後の部分を、Beeceptor で設定したエンドポイントの URL に置き換えてみます。

```bash
curl -X POST -H 'Authorization: Bearer 【LINE Notify のキー】' -F 'message=【送りたいテキストの内容】' 【Beeceptor で設定した URL】
```
上記を実行して Beeceptor で受信したリクエストの内容を見てみました。
Beeceptor で受信したリクエストのヘッダとボディは以下となり、「Content-type は multipart/form-data」となるようでした。

【ヘッダ】
> {
  "content-length": "169",
  "user-agent": "curl/7.54.0",
  "accept": "*/*",
  "authorization": "Bearer 【LINE Notify のキー】",
  "content-type": "multipart/form-data; boundary=------------------------【文字列】"
}

【ボディ】
> --------------------------【文字列】
> Content-Disposition: form-data; name="message"
> 
> 【送りたいテキストの内容】
> --------------------------【文字列】--

それでは、次に「IFTTT（受ける側は Webhook） ⇒ LINE Notify」の IFTTT の受け側を、といきたいところですが、この前に UIFlow と IFTTT の組み合わせはあっさり成功してしまっていたため、次のお試しへと進みました。

最後は、「node.js ⇒ LINE Notify」という流れのものです。
以前作っていたものは、下記の記事にあるようなシンプルにメッセージを送るだけのものでした。
 ●LINE NotifyをNode.jsで使う - BinDle29’s blog
 　http://bindle29.hatenablog.com/entry/2018/02/25/205915

JavaScript のプログラムで設定した宛先を、Beeceptor で設定したエンドポイントの URL に置き換えて実行した結果、得られたのは以下となりました。
curl で試した時と違って、「Content-type は application/x-www-form-urlencoded」で、HTTPリクエストのボディもシンプルな構成でした。

【ヘッダ】
> {
>   "content-length": "71",
>   "content-type": "application/x-www-form-urlencoded",
>   "authorization": "Bearer 【LINE Notify のキー】",
>   "accept": "application/json"
}

【ボディ】
> message=【URLエンコードされた文字列】

試すなら、こちらを踏襲するのが簡単そうです。

#### LINE Notify の公式ドキュメントを確認
ここにきて、[公式ドキュメント](https://notify-bot.line.me/doc/ja/)で仕様の情報を確認しました。
ドキュメント内の項目「**POST https://notify-api.line.me/api/notify**」の直下を見ていくと、「`Content-Type` で指定できるものは `application/x-www-form-urlencoded` または `multipart/form-data`」と書いてあったり、リクエストパラメータについての記載がありました。
<img width="589" alt="LINE_Notify_仕様.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/a1bbab7c-3780-640c-b245-c17f23cb2820.jpeg">
リクエストパラメータの必須の部分は、上記の HTTPリクエストで送られていた「message（String型で、最大 1000文字）」のみとなっています。
ここで省略可能となっている他のリクエストパラメータは、簡単化のために以下では利用せず進めていきます。

### UIFlow でプログラムを組んでみる

#### IFTTTを使った例
ここで使った IFTTT のアプレットは、下記のように Webhook と LINE Notify を組み合わせたものです。
<img width="669" alt="IFTTT_wl.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/188d0f38-782d-a2a8-f1ed-424b23b55d4f.jpeg">
UIFlow のプログラムに関し、IFTTT を使った場合、以下のようにシンプルな構成で作ることができます。
<img width="518" alt="M5Flow_aa.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/672e18c1-77ca-f035-7761-4714485b283c.jpeg">
HTTPリクエストのブロックを利用して設定する箇所は以下のとおりです。

- Method で POST を指定
- URL に IFTTT の Webhook の宛先となる URL を指定
- Data の部分で始めからついている「マップを作成」のブロックに「key・value」を指定（key は value1 を設定、value が IFTTT に受け渡されるテキストになる）

上記の Headers で Content-type の 指定をしていないですが、UIFlow から POST すると Content-type が application/json になるようで、指定なしでも問題なく動作していました。
また、IFTTT で Webhook を使って HTTPリクエスト を受け取る際は、value1〜value3 の 3つのパラメータを受け取ることができますが、上記では value1 のみ使っています（from UIFlow というテキストを送るようにしています）。

1点、これを作る途中で軽く迷ったのが、Data の指定部分に key と value の値をセットするところでした。やり方としては、以下で示した「＋」のマークを押せば大丈夫でした（以下の画像で示しているのは、Headers のところですが、Data のところも同様です）。
最初、JSONブロックの中とか、メニューから該当しそうなブロックを探すということをしてしまいました・・・。
<img width="303" alt="M5Flow_key_value.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/367b0583-d681-e58e-5810-2c91f0a2364c.jpeg">
ボタンを押したら、以下のようになるので、あとは文字列のブロックを加えてやるだけです。
<img width="321" alt="M5Flow_key_value2.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/42296fda-f344-24fa-2a61-8160ef43c7dc.jpeg">

上記のプログラムから、LINEアプリに通知された内容は以下のとおりです。
UIFlow から IFTTT 送ったテキストは「from UIFlow」でしたが、IFTTT のアプレット内で LINE に通知するテキストを追加しているため、以下では「お知らせだよ：」という文字列も通知に含まれています。
![IFTTTからの通知.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/1d909114-1029-5b14-53bc-b85181b8137b.jpeg)

#### IFTTTを使わない実装の例

それでは、IFTTT を使わない方法での実装を試してみます。
上記の Beeceptor を使って見てみた HTTPリクエストの内容と同じ感じになるように、以下のようにプログラムを組みました。
![M5Flow_LINE.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/ed34713a-5643-cee0-6355-c205eb0b40c4.jpeg)

プログラムの中で、HTTPリクエストのブロックを利用して設定する箇所は以下のとおりです。

- Method で POST を指定
- URL に LINE Notify の宛先となる URL を指定
- Headers の部分に 2つの key・value のペアを設定
  - LINE Notify のキーの設定（記事の上で書いた "authorization": "Bearer 【LINE Notify のキー】" にあたる部分）
  - Content-type の application/x-www-form-urlencoded
- Data の部分で始めからついている「マップを作成」を削除し、テキストのブロックに置き換える（内容を「message=」と、それに続く LINE に通知したい文字列を設定する）

HTTPリクエストのブロックで Data の部分に、デフォルトでくっついていた「マップを作成」は不要っぽいので削除し、直接「文字」のブロックをくっつけました。
そして、文字のブロックを1個置いて「message=【通知したい文字列】」としても良かったのですが、後で通知する文字列を動的に書きかえることも出るかな、と思って「message=」の部分と後続の文字列の部分は分けて、文字を連結するブロックでつなげました。

上記の「message=」の後にくる部分について、UIFlow の テキストブロックで日本語のテキストを直接入力しても意図通りの動作とならないのですが、日本語のテキストを URLエンコードした内容で書いてやると、冒頭にも掲載していた以下の動画のように、日本語テキストでの通知を行えました。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">M5GO から LINEアプリに日本語の通知を送るテスト。<br><br>プログラムは UIFlow で作り、 <a href="https://twitter.com/hashtag/LINE?src=hash&amp;ref_src=twsrc%5Etfw">#LINE</a> Notify で通知を送ってます。<br>IFTTTを使うやり方も試しましたが、この動画ではIFTTTを使わないやり方で実現しています。<br><br>（ <a href="https://twitter.com/gaomar?ref_src=twsrc%5Etfw">@gaomar</a> さん、UIFlow でのやり方を見つけました！）<a href="https://twitter.com/hashtag/M5Stack?src=hash&amp;ref_src=twsrc%5Etfw">#M5Stack</a> <a href="https://t.co/6bDhrHH8xZ">pic.twitter.com/6bDhrHH8xZ</a></p>&mdash; you (@youtoy) <a href="https://twitter.com/youtoy/status/1252588326004985856?ref_src=twsrc%5Etfw">April 21, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

上記のプログラムで、LINEアプリに通知された内容は以下のとおりです。
UIFlow から IFTTT 送ったテキストがデコードされて表示されているのが分かります。
（UIFlow で設定していたテキストは`UIFlow%E3%81%8B%E3%82%89%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AE%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%82%92%E9%80%81%E3%82%8B` で、それがデコードされて「UIFlowから日本語のテキストを送る」という文字列になっています）
![UIFlowからの通知.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/4a42d365-7742-bb35-49c5-99e37696050b.jpeg)

## まとめなど
とりあえず、UIFlow から LINEアプリに通知する方法を試すことができました。
今度は、HTTPリクエストで通知ができる他のサービス・アプリとも組み合わせてみたり、通知のトリガーをボタン押下意外にしてみたりと、別のパターンを試してみたいと思います。