【Ruby】HTTPClientとLINE Notifyを使ってターミナルから文字列を送るプログラム

# はじめに
**「プログラムとLINEを連携して通知したい」**って思ったことはないでしょうか。

ググると、すぐに**LINE Notify**がヒットし、そのまま登録、APIドキュメントを読むと、`curl`コマンドでターミナルから通知が出来そうだということまではわかります。

でも、Webアプリに組み込むなら**プログラムを書いて実装したい**のに良く分からない…:sob:

そんな思いを持つあなたに向けて記事を書きました。

今回は**ターミナルで任意の文字列を入力して、自分のLINEに通知するところまでをゴール**としていますが、これを応用すればあとは変数を変えるだけで、**Ruby**を使用したアプリケーションに組み込むための第一ステップがクリアでき、目的の**「プログラムとLINEを連携して通知」**が出来るきっかけになるのではと思います。

# この記事が役に立つ方
- LINE Notifyを使ってみたい
- HTTPクライアントは`HTTPClient`を使いたい
- Ruby初心者

# この記事のメリット
- LINE Notifyを使ったプログラムの書き方が分かる
- `HTTPClient`の使い方が分かる

# 環境
- macOS Catalina version 10.15.1
- シェル：zsh
- Ruby 2.6.3
- HTTPクライアント：`HTTPClient`

# 【事前準備】トークンの取得からHTTPリクエストに必要な情報のメモまで
## 1. LINE Notifyにログイン・マイページに移動
右上から普段使っているLINE IDでログイン可能です。
ログイン後、「マイページ」に移動して下さい。

![スクリーンショット 2019-11-13 19.55.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483292/4496abce-2bf3-f797-29f5-35c9a80b7b17.png)

## 2. トークンを発行する
マイページ下部の「トークンを発行する」をクリックして下さい。
![スクリーンショット 2019-11-13 20.02.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483292/e7b9be02-38c7-f974-a933-96f07d35abab.png)

「トークン名」を任意で入力し、通知するトークンルームを選択します。

今回は試すだけなので、

- トークン名を「test」
- 通知するトークンルームを「1:1でLINE Notifyから通知を受け取る」


として自分だけが受け取るようにします。

![スクリーンショット 2019-11-13 20.07.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483292/2fd0db92-c8fa-c111-4fab-d0d5bb6ee8bf.png)

## 3. トークンをメモする

トークンは発行時にしか確認が出来ないので、必ずコピペでどこかにメモしておきましょう。

**※メモし忘れたらやり直しです。**

![スクリーンショット 2019-11-13 20.24.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483292/f7fef5fe-5663-1035-c2ce-371838e1f22b.png)

以下のように、マイページで「連携中サービス」に**「From:test」**が出ていれば準備はOKです。

![スクリーンショット 2019-11-13 20.03.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483292/de805bda-88c2-f654-51c4-00dbdb99ffc8.png)

## 今回使用する機能

[LINE Notify API Document](https://notify-bot.line.me/doc/ja/)の真ん中あたりにある「通知系」
`POST https://notify-api.line.me/api/notify`
が今回使用する機能です。
![スクリーンショット 2019-11-13 20.45.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483292/b0190238-7a08-7201-5853-a2d52e4c3acd.png)

では、次はこのAPIドキュメントに記載の`curl`コマンドを確認します。

## `curl`コマンドで送る場合
もしプログラムを書く必要がなくて、ターミナルから送れるだけで満足！という方は**ここでおしまい**です！

`POST https://notify-api.line.me/api/notify`の最下部に以下`curl`コマンドがサンプルとして記載されています。

メモしたトークンが合致するかの確認も含め、無事に通知が来るかどうか、一度試してみるといいと思います。

```zsh
curl -X POST -H "Authorization: Bearer 取得したトークン" -F "message=送りたい文章" https://notify-api.line.me/api/notify
```

この`curl`コマンドを`HTTPClient`を使って実装したものが本題のRubyプログラムです。

自分は**HTTPメッセージの構造について理解**が不十分だったので、ここから苦労しました。:sweat_smile:

以下、自分が理解するために活用したサイトです。

[HTTP メッセージ - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Messages)

また、英語ですがこちらの動画も１分半でコンパクトにまとまっていて、わかりやすかったです。
[Parts of an HTTP Request - YouTube](https://www.youtube.com/watch?v=pHFWGN-upGM)

ちなみに、Ruby標準搭載のHTTPクライアント`net/http`を使用して実装する場合は、以下サイトにコピペすると一瞬でRubyプログラムが仕上がります。**便利！**

[curl-to-ruby: Convert curl commands to ruby’s net/http](https://jhawthorn.github.io/curl-to-ruby/)

## LINE Notify API Documentからメモしておく情報

HTTPリクエストを作成・送信するため、
リクエストメソッド・ヘッダ・パラメータが必要です。

[LINE Notify API Document](https://notify-bot.line.me/doc/ja/)で必要な部分を以下にキャプチャしておきました。

![スクリーンショット 2019-11-13 20.46.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483292/764dd440-b70c-653a-3290-efe39d026d0d.png)

![スクリーンショット 2019-11-13 20.47.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483292/43e61cb8-c73e-e355-daf5-74b3555f092b.png)

まとめると、今回のLINE通知に必要な情報は以下の通りです。
これらをプログラム上で反映させる必要があります。

|項目|要素 |値|
|:------------:|:------------:|:-:|
|リクエストメソッド  | - |POST|
|リクエストヘッダ |Content-type | multipart/form-data|
|リクエストヘッダ | Authorization |Bearer 取得したトークン |
|リクエストパラメータ |　message |`gets`（標準入力）|

HTTPClientの使用方法についての理解には以下サイトを使用しました。（英語です）
[Ruby HTTPClient tutorial](http://zetcode.com/web/rubyhttpclient/)

# プログラム
では、実際のプログラムに移ります。
各行の意味はコメントをご参照下さい。

```ruby
require 'httpclient'
# 定数を定義し、freezeで変更不可とする
URL = "https://notify-api.line.me/api/notify".freeze
TOKEN = "自分で取得したトークン".freeze

# httpclientを使ってリクエストの雛形を作成する
client = HTTPClient.new

# URIを指定
uri = URI.parse(URL)

# LINE Notify指定のリクエストヘッダを指定
header = {
  "Content-type" => "multipart/form-data",
  "Authorization" => "Bearer #{TOKEN}"
}

# 標準入力（ターミナル上でキーボードからの入力）を促す
puts "LINEで送信したい文章を入力してEnterを押して下さい"

# 表示するメッセージをクエリとして代入。その他画像等もここで入れることが出来る。
query = {
  "message" => gets # `gets`で標準入力を受け取る
}

# POSTリクエストを作成し、レスポンスを`res`に代入
res = client.post(uri, query, header) 
# リクエストだからといって、`res = client.request`とするとダメ。シンプルにpost。
# 引数を(uri, header, query)と順番を間違えてもエラーになる。


# レスポンスステータスコードを確認する
puts res.body
```

## 実行結果
無事動作するか確認してみましょう。
`”status”:200`が出て、自分のLINEに通知が来れば大成功！

```zsh
$ ruby line-notify.rb
LINEで送信したい文章を入力してEnterを押して下さい
お疲れ様でした！ # 任意の文字列を入力
{"status":200,"message":"ok"}
```



# おわりに
自分用に学習時間を記録するWebアプリを作成中で、**一日の終わりにLINEで学習時間を通知**する機能を実装したかったので、**LINE Notify**を使ってみることにしたんですが...

**HTTPの理解が全然出来ていなかった**ことでずっと`400`や`401`エラーと格闘してました。:sweat_smile:

書いたおかげで思考整理が出来てスッキリ！理解も深まりました！

ちなみに、`HTTPClient`って人気ないんでしょうか？
ネット上では`net/http`を使用した記事が多く、基本的に英語のドキュメントばかりだったので、ひと苦労でした。:tired_face:

# 参考にさせて頂いたサイト（いつもありがとうございます）
[LINE Notify](https://notify-bot.line.me/doc/ja/)
[Ruby HTTPClient tutorial](http://zetcode.com/web/rubyhttpclient/)
[curl-to-ruby: Convert curl commands to ruby’s net/http](https://jhawthorn.github.io/curl-to-ruby/)
[HTTP メッセージ - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/Messages)
[Parts of an HTTP Request - YouTube](https://www.youtube.com/watch?v=pHFWGN-upGM)
[module function Kernel.#gets (Ruby 2.6.0)](https://docs.ruby-lang.org/ja/latest/method/Kernel/m/gets.html)
[超簡単LINE notify を使ってみる - Qiita](https://qiita.com/iitenkida7/items/576a8226ba6584864d95)