LINEのメッセージをGoogleHomeで読み上げる LINE連携編

こちらの続きです。
[LINEのメッセージをGoogleHomeで読み上げる RaspberryPiセットアップ編](https://qiita.com/f-nak/items/33dfe81799e91fb93583)

## 前回までのあらすじ
- Raspberry Pi3 Model B をセットアップ済み
- MacBook Air OSX Yosemite(10.10.5)
- ラズパイにNode.jsをインストール済み
- google-home-notifierが動くことをごくカンタンに確認済み
- Macとラズパイはssh接続したmacのターミナル、またはVNC接続した画面越しに行う(ラズパイにマウスとキーボードをつないでいないため)

## 今回やりたいこと
LINEのメッセージを読み上げて欲しい！
幸い、ジャストヒットな記事があったのでこちらに沿ってやってみます。
[LINEに送信したメッセージを、Google Homeで読み上げ、家族に通知](https://qiita.com/daaaaaasuke/items/5e95983166667094f42f)
[1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)


# １. LINEのbot(Messaging API)を作成する
IFTTTでLINEをトリガーにできればよかったのですが、どうやらできないようです。代わりにbotに話しかけることをトリガーするとのこと。

具体的な作成手順は参考にした記事の通りなので、割愛します。
ポイントは以下です。

- プラン → Developer Trial
- Webhook送信 → 利用する
- 自動応答メッセージ → 利用しない
- 作ったbotと友達になる

# ２. Node.jsのプロジェクト作成
今回のソースを保存しておく任意のディレクトリを作成します。

- ラズパイに任意のディレクトリを作り、作業ディレクトリとする。
- 作業ディレクトリ内でNode.jsの設定ファイルを作成する npm init
 - いろいろ聞かれるが適当にEnter連打でとりあえずOK
- 作業ディレクトリ内でコマンド実行 

```
npm install google-home-notifier ngrok @line/bot-sdk express
```

今回はgoogle-home-notifierの他にngrok, @line/bot-sdk, expressの3つも利用します。

そして、作業ディレクトリ内に以下のファイルを作製します。

```javascript:server.js
'use strict';

const express = require('express');
const line = require('@line/bot-sdk');
const googlehome = require('google-home-notifier');

// for express
const port = 3000; // ngrokのポートと合わせる
const app = express();

// for LINE
const config = {
  channelSecret: '', // Messaging APIのChannel Secret
  channelAccessToken: '' // Messaging APIのアクセストークン（ロングターム）
};
const replyPrefixText = 'メッセージを受け付けました : ';

// for googlehome
const language = 'ja';
googlehome.device('Google Home', language);
googlehome.ip('192.168.XXX.XXX', language); // google home のIPを設定する
const speakPrefixText = '新しいメッセージです。';


app.post('/webhook', line.middleware(config), (req, res) => {
    console.log(req.body.events);
    Promise
      .all(req.body.events.map(handleEvent))
      .then((result) => res.json(result));
});

const client = new line.Client(config);

function handleEvent(event) {
  if (!checkEvent(event)) {
    return Promise.resolve(null);
  }

  return googlehomeSpeak(event.message.text)
    .then(speakedText => lineReplyMessage(event.replyToken, speakedText));
}

function checkEvent(event){
  if(event.type !== 'message') return false;
  if(event.message.type !== 'text') return false;

  // LINE の Channel基本設定 から「接続確認」をするとreplyTokenが以下の固定値になるらしい
  // 実在しないreplyTokenなので応答しないようにfalseを返す
  if(event.replyToken === '00000000000000000000000000000000') return false;
  if(event.replyToken === 'ffffffffffffffffffffffffffffffff') return false;
 
  return true;
}

function googlehomeSpeak(text) {
  return new Promise((resolve, reject) => {
    googlehome.notify(speakPrefixText + text, (res) => {
      console.log('googlehome response : ' + res + ', speech_text : ' + text);
      resolve(text);
    });
  });
}

function lineReplyMessage(replyToken, text) {
  return client.replyMessage(replyToken, {
    type: 'text',
    text: replyPrefixText + text
  });
}


app.listen(port);
console.log(`Server running at ${port}`);
```
以下の記事を参考にさせていただきました。
[LINEに送信したメッセージを、Google Homeで読み上げ、家族に通知](https://qiita.com/daaaaaasuke/items/5e95983166667094f42f)
[1時間でLINE BOTを作るハンズオン (資料+レポート) in Node学園祭2017 #nodefest](https://qiita.com/n0bisuke/items/ceaa09ef8898bee8369d)

promiseでgoogle homeでしゃべる→LINEに返信するという順番に動作するよう制御したので、LINEで返信が来る=google homeでしゃべっているということになります。

# ３.　Messaging APIのセキュリティ情報をコピーする
上記のserver.jsはLINEのセキュリティ情報を設定する箇所があります。
先程作製したMessaging APIの「Channel基本設定」画面から以下の値をserver.jsにコピーします。

コピー元（LINEのChannel基本設定画面)

- Channel Secret
- アクセストークン（ロングターム）
 ※最初は未設定なのですぐ横のボタンで発行します

<br>
コピー先

```javascript:server.js
// for LINE
const config = {
  channelSecret: '', // Messaging APIのChannel Secret
  channelAccessToken: '' // Messaging APIのアクセストークン（ロングターム）
};
```
これでserver.jsが完成です。

# ４. ngrokに会員登録しauthtokenを登録する

ngrokは会員登録せずに使うと8時間しか起動できません。なので、会員登録し、発行されるauthtokenを登録します。

- https://ngrok.com/ から「Get started for free」ボタンを押して進める
- 登録後に表示される「Setup & Installation」画面の「③Connect your account」にあるauthtokenをメモする。
- 先程作った作業ディレクトリで以下のコマンドを実行する


```
npx ngrok authtoken XXXXXXXX
```

以下のようなログが出ればOK

```
Authtoken saved to configuration file: ~~~~~~~~~
```
XXXXXXXXはメモしたauthtokenです。
今回はngrokを-g(グローバル)ではなくローカルにインストールしているので、npxを使ってngrokコマンドを実行しています。


# ５. Node.jsのサーバーを起動する
作成したserver.jsを起動します。そして、ローカル起動したserver.jsをngrokで外部に公開します。

- ssh接続したターミナルではなく、VNC接続してラズパイ本体でターミナルを2つ起動する。
- 1つ目のターミナルでserver.jsがあるディレクトリに移動し、以下を実行する

```
node server.js
```

以下のようなログが出ればOK

```
*** WARNING *** The program 'node' uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node>
*** WARNING *** The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=node&f=DNSServiceRegister>
Server running at 3000
```

- 2つ目のターミナルでserver.jsがあるディレクトリに移動し、以下を実行する

```
npx ngrok http 3000
```

以下のようなログが出ればOK

```
Session Status                online                                            
Account                       <アカウント名> (Plan: Free)                                
Version                       2.2.8                                             
Region                        United States (us)                                
Web Interface                 http://127.0.0.1:4040                             
Forwarding                    http://XXXXXXXX.ngrok.io -> localhost:3000        
Forwarding                    https://XXXXXXXX.ngrok.io -> localhost:3000  
```

もし、ngrokを会員登録せずに実行した場合、Accountの行の代わりに以下のような表示になります。表示されているとおり8時間しか起動できません。

```
Session Expires               7 hours, 59 minutes             
```

# ６. LINEのMessaging APIにURLを設定
ngrokで設定したURLをLINEのAPIに設定します。

- LINEのChannel基本設定画面のWebhook URLに「XXXXXXXX.ngrok.io/webhook」を設定し、更新ボタンを押す（XXXXはngrokで作製したURL）。
 - 「接続確認」ボタンを押して成功すればOK
 
これで準備完了です！

# ７. botとトークしてみる
友達になったbotとトークしてみます。

```
自分：こんにちは
bot：メッセージを受け付けました：こんにちは
```
おおおおーーー！
そして少し遅れて

```
google home: 新しいメッセージです。こんにちは
```

しゃべったーーー！
嬉しい！！



※2018/05/13
ngrokのフリープランを使い、８時間制約を回避する手順を追加しました。
daaaaaasukeさんありがとうございました！