なでしこさんでLINE Botを作りたい！　～なでしこの最新バージョンを答えてくれるLINE Bot～

　結構放置して間が空いちゃいましたケド、前回作ったおうむ返しのボットを改良して、なでしこの最新バージョンを教えてくれるようにする話し。
　あと、プラグインには、プッシュメッセージや、友達全員に一斉にプッシュ(ブロードキャストメッセージ)送信できる機能を追加。
　アドベントカレンダーの記事ではありますが、例によって出来たの出来ないのと騒ぎます；

# おさらい
　前の記事はアドベントカレンダー外なので、一応念のためリンクを貼っておきます。
　なでしこで、日本語でラインボットを作るべく色々頑張る話です。

**①『[LINE Botを作りたい！　～アカウントの作成とボットの設定から、おうむ返しボットを動かすまで～](https://qiita.com/snowdrops89/items/701c54d9c61c2535c6b1)』**
　LINE Developersのアカウントを取得し、各種設定を行い、とりあえずLINEボット作成(node.js)をお試しするまで。

**②『[なでしこさんのプログラムをherokuで動かしたい！](https://qiita.com/snowdrops89/items/b13edde610c476c7c35d)』**
　Herokuのアカウント取得して、なでしこのプログラムをherokuにデプロイして動かすまで。

**③『[なでしこさんでLINE Botを作りたい！　～おうむ返し＋αのボットが日本語で作れたよ～](https://qiita.com/snowdrops89/items/07c507175fcd0692cb6e)』**
　プラグインを作って、なでしこからLINEmessagingAPIを使い、日本語でおうむ返しのLINEボットを作ってHerokuで動かすまで。

# 定型返信部分の改良

　本題の前に。
　[前回](https://qiita.com/snowdrops89/items/07c507175fcd0692cb6e#%E3%81%AA%E3%81%A7%E3%81%97%E3%81%93%E5%81%B4%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0)はとりあえず、おうむ返し以外のキーワードに対する応答を`もし～違えばもし～`と、ひたすら`もし`の条件分岐で並べたのですが、キーワードと返信テキストをcsvファイルにして「返信メッセージリスト」を作成し、それを`反復`することにしました。
　こんなの。

```reply_list.csv
なでしこ,誰でも簡単プログラマー{改行}https://nadesi.com/
なでしこさん,呼んだ？
{ユーザー名},{ユーザー名}さんって、すてきな名前だね☆
```

　忘れかけていましたが、cnako3なのでファイルの入出力が出来るんです。やったね！
　あっ、`plugin_csv`を`取り込む`の忘れず。
　csv(カンマ区切り)、tsv(タブ区切り)のデータを扱うためのプラグインです。

> [なでしこさん マニュアル > plugin_csv](https://nadesi.com/v3/doc/index.php?plugin_csv&show)

　基本プラグインなのでインストールは要りません。プログラム冒頭で取り込んでおけばＯＫ。

```
!『plugin_csv』を取り込む。
返信メッセージリスト＝「reply_list.csv」を開いて、それをCSV取得。
```

　返信メッセージリストを反復して、送られてきた語句がキーワード部分と合致したら、返信テキスト部分をLINE返信するだけだけど、`{ユーザー名}`と`{改行}`だけ、なでしこの変数みたいに書いたら変換できるようにしといた。

```
//（一部）
返信メッセージリストを反復
　　語句＝対象[0]の『{ユーザー名}』をユーザー名に置換。
　　もし、受信メッセージ＝語句ならば、
　　　　返信テキスト＝対象[1]の『{ユーザー名}』をユーザー名に置換。
　　　　返信テキスト＝対象[1]の『{改行}』を改行に置換。
　　　　イベントリスト[No]＝返信テキストのLINEテキストメッセージを返信先へLINE返信。戻る。
　　ここまで。
ここまで。
```

　これで、応答出来る語句を増やすのがカンタンになりました～♪

# なでしこの最新バージョンを答えてくれるようにする

　そして本題。
　おうむ返しと定型の応答だけじゃアレなんで、「バージョン」と送ったら、v1とv3の最新バージョンを教えてくれる機能を追加したい。
　コレで実用的なボットになるね！（？）

## v3の最新バージョンを取得する
　v3の最新バージョンを知る方法は、[ここ](https://n3s.nadesi.com/id.php?553)にあります。
　`https://n3s.nadesi.com/nako_version.json`をAJAXで取得すればいいんですね。簡単なJSONさんですよ♪

```
{
"version": "3.2.30",
"major": 3,
"minor": 2,
"patch": 30
}
```

　この`version`のとこを返せば良さそう。

## v1の最新バージョンを取得する
　v1は・・・？　何か手だてがあるかのう・・・と捜索したところ、RSSはありました。
　`https://download.nadesi.com/v1/History.xml`
　忘れかけてましたが、cnako3なのでxmlでも大丈夫。やったね☆
　htmlパースするやつ入れなきゃダメかも？

### 拡張プラグインのインストール。
　RSSのxmlを解析するために、`nadesiko3-htmlparser`を使います。

> [なでしこさん マニュアル > nadesiko3-htmlparser](https://nadesi.com/v3/doc/index.php?nadesiko3-htmlparser&show)

　`nadesiko3-htmlparser`は、拡張プラグインです。
　拡張プラグインを使うためには別途インストールしなきゃなりません。

> [Node版プラグインを使う方法](https://nadesi.com/doc3/index.php?Node%E7%89%88%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%82%92%E4%BD%BF%E3%81%86)

#### インストール

```
cd desktop/nako3
npm install nadesiko3-htmlparser
```

#### 取り込む

```
!『nadesiko3-htmlparser』を取り込む。
```

### HTMLパース

　`<item>`の`<title>`にバージョンが入っているようなので、一番最初の`<item>`から`<title>`の内容を取得すれば良さそうなんですが、`CDATA`セクションから価を取る術が分からぬ～。
　・・・こんなの。

```
<title><![CDATA[1.582]]></title>
```

　もっと賢い手立てがありそうな気もしますけど、とりあえず`正規表現マッチ`でこんな感じ？

```
# v1のバージョンを取得
ｖ１バージョンURLへGET送信した時には
　　対象をHTMLパース。
　　ITEM＝「item」のDOM要素取得。
　　ITEMをDOM配列変換。
　　タイトルはITEM[0]から「title」をDOM子要素検索。
　　タイトルのHTML取得して、「/\[CDATA\[(.*?)\]\]/」で正規表現マッチ。
　　ｖ１＝抽出文字列[0]
ここまで。
```

　うーん、`1.582`ですって。なでしこのトップページに記載されているバージョン`Windows版 v1.583 (2021/07/11)`と違いますね・・・
　でも、RSS的にはそうなってるんだからしょうがない！（のか？）
　nakopadの「なでしこについて」で見られるバージョンは`バージョン：1.583`、「更新履歴を見る」では`2021/07/10 version 1.582`。
　なんかマイナーチェンジがRSSに反映されてないっぽい？ケド、ま、次バージョンアップしたら直るでしょう（え）

## LINEボットで答える

```
●バージョン取得
　　# v1のバージョンを取得
　　ｖ１バージョンURLへGET送信した時には
　　　　対象をHTMLパース。
　　　　ITEM＝「item」のDOM要素取得。
　　　　ITEMをDOM配列変換。
　　　　タイトルはITEM[0]から「title」をDOM子要素検索。
　　　　タイトルのHTML取得して、「/\[CDATA\[(.*?)\]\]/」で正規表現マッチ。
　　　　ｖ１＝抽出文字列[0]
　　　　バージョン情報[0]＝「なでしこ１の最新バージョンは、{ｖ１}だよ☆」のLINEテキストメッセージ。
　　　　# v3のバージョンを取得
　　　　ｖ３バージョンURLへGET送信した時には
　　　　　　ｖ３＝対象をJSONデコード。
　　　　　　バージョン情報[1]＝「なでしこ３の最新バージョンは、{ｖ３["version"]}だよ☆」のLINEテキストメッセージ。
　　　　　　# 二つ同時に返信
　　　　　　イベントリスト[No]＝バージョン情報を返信先へLINE返信。
　　　　ここまで。
　　ここまで。
ここまで。
```

　メッセージは配列で渡すことで同時に五つまで送信できるようで、そのお試しも兼ねて、二つをそれぞれ別のメッセージオブジェクトとして作成し、同時に送信しています。
![linebot2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561177/12de7ae7-da11-6198-9bab-902c7f30da0d.jpeg)
　できた！

# プラグイン側の機能追加

## メッセージオブジェクト

　スタンプ、画像、動画、音声、位置情報、二択の確認メッセージが作れるようにしました。

### てすと
　スタンプが送られてきたらスタンプを、画像が送られてきたら画像を、位置情報が送られてきたら位置情報を返信するようにしてみたよ☆（動画と音声は試してない；）
　また、「おやつ」と送ったら、「チョコ」か「ポテチ」の二択を出します。
![linebot10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561177/1227591b-5a6e-b431-9caa-bd2e9882dcd2.jpeg)
![linebot11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561177/16a32d99-4870-4be3-5845-fc14eea575b6.jpeg)
　できた！！

## メッセージ
　プッシュ、マルチキャスト、ブロードキャストメッセージが送れるようにしました。
　プッシュはユーザーIDを指定して一人の人に、マルチキャストはユーザーIDの配列で複数の人に、ブロードキャストは友達になってる人全員にメッセージを送信するやつ。
　ブロードキャストは、[リファレンス](https://developers.line.biz/ja/reference/messaging-api/#send-broadcast-message)を見てもShellしかサンプルコードがなくって、ええ～(；Д；)ってなりますが実装はあるようです。
　`client.broadcast(message)`でいけました☆
　（同様にナローキャストもあるようなんですが、お試しできないからよく分からない。まあ、友達ワタシしかいませんから、実際のところマルチキャストもブロードキャストも本当にみんなに送られんのか試せませんがｗ）

## プラグイン置き場

> https://github.com/snowdrops89/nako3_plugin_linebot

　とりあえず、今ワタシがやりたそうなコトと言ったらこんなものかな。

# コード
```linebot.nako3
!『Plugin_linebot.js』を取り込む。
!『nadesiko3-htmlparser』を取り込む。
!『plugin_csv』を取り込む。

＃---宣言----------
イベントリスト＝空配列。C＝0。No＝0。
イベント種別＝空。返信先＝空。ユーザーID＝空。ユーザー名＝空。受信メッセージ＝空。
返信メッセージリスト＝「reply_list.csv」を開いて、それをCSV取得。
返信テキスト＝空。

＃---情報取得----------
定数 ｖ１バージョンURL＝『https://download.nadesi.com/v1/History.xml』
定数 ｖ３バージョンURL＝『https://n3s.nadesi.com/nako_version.json』
バージョン情報＝空配列。

＃---サーバー----------
LINEボット起動した時には
　　「{PORT番号}でサーバ起動しました」と表示。
　　LINEイベント受信時には
　　　　イベント処理。
　　ここまで。
ここまで。

●イベント処理
　　C=0。
　　LINEイベントを反復
　　　No=対象キー。
　　　イベント種別＝LINEイベント[No]["type"]
　　　もし、イベント種別＝「unfollow」ならば、続ける。
　　　返信先＝LINEイベント[No]["replyToken"]
　　　ユーザーID＝LINEイベント[No]["source"]["userId"]。
　　　ユーザーIDのプロフィール取得した時には
　　　　ユーザー名＝対象["displayName"]。
　　　　イベント種別で条件分岐
　　　　　「follow」ならば、フォロー。。。
　　　　　「message」ならば、メッセージ。。。
　　　　ここまで。
　　　　C=C+1。
　　　　もし、C＝(イベントリストの配列要素数)ならば、イベントリストをLINEメッセージ送信。
　　　ここまで。
　　ここまで。
ここまで。

●フォロー
　　返信テキスト＝「{ユーザー名}さん、はじめまして！{改行}お友達になってくれてありがとう☆」
　　イベントリスト[No]＝返信テキストのLINEテキストメッセージを返信先へLINE返信。
ここまで。

●メッセージ
　　メッセージ種別＝LINEイベント[No]["message"]["type"]
　　メッセージ種別で条件分岐
　　　「text」ならば、
　　　　　受信メッセージ＝LINEイベント[No]["message"]["text"]
　　　　　受信メッセージで条件分岐。
　　　　　　「バージョン」ならば、バージョン取得。。。
　　　　　　「おやつ」ならば、イベントリスト[No]＝「チョコ」と「ポテチ」で「どっち？」のLINE二択メッセージを返信先へLINE返信。。。
　　　　　　「ぷっしゅ」ならば、ユーザーIDに「プッシュです」のLINEテキストメッセージをLINEプッシュ。。。
　　　　　　「全員」ならば、「一斉プッシュです！」のLINEテキストメッセージをLINE一斉プッシュ。。。
　　　　　　違えば、
　　　　　　　返信メッセージリストを反復
　　　　　　　　　語句＝対象[0]の『{ユーザー名}』をユーザー名に置換。
　　　　　　　　　もし、受信メッセージ＝語句ならば、
　　　　　　　　　　　返信テキスト＝対象[1]の『{ユーザー名}』をユーザー名に置換。
　　　　　　　　　　　返信テキスト＝返信テキストの『{改行}』を改行に置換。
　　　　　　　　　　　イベントリスト[No]＝返信テキストのLINEテキストメッセージを返信先へLINE返信。戻る。
　　　　　　　　　ここまで。
　　　　　　　ここまで。
　　　　　　　返信テキスト＝受信メッセージ&「？」
　　　　　　　イベントリスト[No]＝返信テキストのLINEテキストメッセージを返信先へLINE返信。
　　　　　　ここまで。
　　　　　ここまで。
　　　ここまで。
　　　「sticker」ならば、
　　　　　返信スタンプ＝空配列。
　　　　　返信スタンプ[0]＝「わーいスタンプだ～」のLINEテキストメッセージ。
　　　　　返信スタンプ[1]＝「8515」から「16581243」のLINEスタンプメッセージ。
　　　　　イベントリスト[No]＝返信スタンプを返信先へLINE返信。
　　　ここまで。
　　　「image」ならば、
　　　　　返信画像＝空配列。
　　　　　画像URL＝「https://n3s.nadesi.com/image.php?f=8.jpg」
　　　　　返信画像[0]＝「画像だ！」のLINEテキストメッセージ
　　　　　返信画像[1]＝画像URLと画像URLのLINE画像メッセージ。
　　　　　イベントリスト[No]＝返信画像を返信先へLINE返信。
　　　ここまで。
　　　「location」ならば、
　　　　　イベントリスト[No]＝「たいとる」と「じゅうしょ」で[35.687574,139.72922]のLINE位置情報メッセージを返信先へLINE返信。
　　　ここまで。
　　ここまで。
ここまで。

●バージョン取得
　　# v1のバージョンを取得
　　ｖ１バージョンURLへGET送信した時には
　　　　対象をHTMLパース。
　　　　ITEM＝「item」のDOM要素取得。
　　　　ITEMをDOM配列変換。
　　　　タイトルはITEM[0]から「title」をDOM子要素検索。
　　　　タイトルのHTML取得して、「/\[CDATA\[(.*?)\]\]/」で正規表現マッチ。
　　　　ｖ１＝抽出文字列[0]
　　　　バージョン情報[0]＝「なでしこ１の最新バージョンは、{ｖ１}だよ☆」のLINEテキストメッセージ。
　　　　# v3のバージョンを取得
　　　　ｖ３バージョンURLへGET送信した時には
　　　　　　ｖ３＝対象をJSONデコード。
　　　　　　バージョン情報[1]＝「なでしこ３の最新バージョンは、{ｖ３["version"]}だよ☆」のLINEテキストメッセージ。
　　　　　　# 二つ同時に返信
　　　　　　イベントリスト[No]＝バージョン情報を返信先へLINE返信。
　　　　ここまで。
　　ここまで。
ここまで。
```

　なでしこ貯蔵庫にも上げてみました。
　cnako3のプログラムなので動かせませんが、Qiitaの記事ではなでしこのコードにシンタックスハイライトが付かなくて見辛いので・・・

> https://n3s.nadesi.com/id.php?845

# 動作確認

　もしよろしければ試してみてください。

## 友達登録
![215ybrvp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561177/6a152326-fc32-d075-509e-98c1105ea081.png)
## キーワード
|キーワード |応答|
|:--------:|:--------|
|なでしこ|誰でも簡単プログラマー|
|なでしこさん|よんだ？|
|（自分のLINEの表示名）|○○さんってすてきな名前だね|
|（スタンプ）|（スタンプ）|
|（画像）|（画像）|
|（位置情報）|（位置情報）|
|おやつ|「チョコ」「ポテチ」の二択|
|バージョン|なでしこ１のバージョン/なでしこ３のバージョン

　それ以外はおうむ返しです。

# 続くかもしれないし続かないかもしれない

　これで、なでしこの最新バージョンを答えてくれる機能が付いて、ボットに実用性が付加されました。やったね☆
　でも・・・
　バージョンを教えてくれるって、LINEボットに本っ当にやって欲しいのってこうじゃないよね。
　バージョンアップしたらプッシュして教えてほしい。
　毎日定時にバージョンをチェックしに行って、アップしてたらお知らせしてくれる的な？

　実は・・・自分のパソコン上でやってみた分には出来たんですけれどね・・・
　Herokuさんでは出来ませんでした。
　どうやらHerokuさんは、プログラムでファイルのデータを書き換えても、定期的にgitで管理されてる元の状態に戻ってしまうラシイ。（ので、一度バージョンアップしたら、毎日お知らせが上がってしまう状態になってしまう）
　これを解決するには、データファイルをどっか別のトコ（S3とか）に置くか、Heroku Postgresなるアドオンを使って、csvとかじゃなくデータベースにするってことになるらしい。むむむ・・・
（なでしこさん側にも、PostgreSQLを使うためのプラグインがあった気がするけどそもそもえすきゅーえるを知らないからね。むむむむむ( ﾟεﾟ；)
　ううっ、そのうちがんばる；；；；；