GoogleHomeとIFTTTとFirebaseとラズパイとnode.jsでyoutubeの音を流す

# はじめに
[GoogleHomeとIFTTTとFirebaseとラズパイで指定した数に対応した音を流す（英単語読み上げツールの作成）](https://qiita.com/nakagawa1017/items/78f18b88b2ce49077da7)
これの記事の続きです

もうすこし`google-home-notifier`で遊んでみたくなったので下記を参考に、IFTTTで試してみたバージョンの作業メモ
[Google Home自身でYoutubeの音楽を再生する](https://qiita.com/odetarou/items/0e134ff845826d16170c)

# 環境

```
ラズパイ

$lsb_release -a
No LSB modules are available.
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 9.4 (n/a)
Release:	9.4
Codename:	n/a

$npm -v
5.6.0

$node -v
v9.4.0
```
# Firebaseの設定
Realtime Databaseの中で＋ボタンを押して新しい項目を追加する
`googlehome`とその中に`word`と`""`の項目をつくる
<img width="480" alt="68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3137363437392f36633831333539312d363336392d343863642d643765342d3439303633613638313039332e706e67.png" src="https://qiita-image-store.s3.amazonaws.com/0/176479/c531e8d6-8602-f479-e7bd-7721e3cdbdba.png">


# IFTTTの設定
## Google Assistant
<img width="1242" alt="スクリーンショット 2018-10-23 22.25.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/176479/244317e0-471d-ade4-db51-631580796a70.png">

GoogleHomeに「トリガー ○○」というとその言葉をもとにyoutubeから探してくるようにします
書き方は下記のように`トリガー $`と書くと任意の文字列が$に入ります
<img width="279" alt="スクリーンショット 2018-10-29 0.10.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/176479/0e12c5d7-aea5-d73f-691b-77c6ece0a632.png">

## webhooksの設定
<img width="260" alt="スクリーンショット 2018-10-29 0.14.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/176479/18583099-cc80-aeca-1848-f0fab61f0728.png">
`URL`にはFirebase Realtime Databaseの中で設定した項目にBodyの中身を送られるように下記のように設定する

```
https://{Firebaseで設定したプロジェクトID　例:XXXXXXXXXXX-12345}.firebaseio.com/googlehome/word.json
````

をいれる

`Body`には下記のように入れた


```
"youtube {{TextField}}"
```
`TextField`という白い枠がなければ下の`Add ingredient`を押して出すことができる

#ラズパイ内

[Google Home自身でYoutubeの音楽を再生する](https://qiita.com/odetarou/items/0e134ff845826d16170c)内の手順通り
`youtube-dl`を導入する

```
sudo pip3 install youtube-dl
```

`forever`で永続化させようとした時に何故か`config/local.js`を読み込んでくれず手こずったので、`index.js`ファイル内にすべてのconfigで必要な項目を入れれるように参考資料のコードを少し改造しました

```javascript

'use strict';
const firebase = require("firebase");

const config = {
  apiKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  authDomain: 'xxxxxxxxxxxxxxx.firebaseapp.com',
  databaseURL: 'https://xxxxxxxxxxxxxxxx.firebaseio.com',
  projectId: 'xxxxxxxxxxxxxxxxxxxxx',
  storageBucket: 'xxxxxxxxxxxxx.appspot.com',
  messagingSenderId: 'xxxxxxxxxxx'
};

firebase.initializeApp(config);

const Youtube = require('youtube-node');
const youtube = new Youtube();
youtube.setKey('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');//youtubeのAPIキーを取得しココに入れる

const notifier = require('google-home-notifier');
notifier.ip('xxx.xxx.xxx.xxxxxx');//googlehomeのipアドレスをいれる
notifier.device('xxxxxxxxxx', 'ja');//googlehomeの名前を入れる
notifier.accent('ja');

const  exec = require('child_process').exec;


//database更新時
var db = firebase.database();
db.ref("/googlehome").on("value", function(changedSnapshot) {
  //値取得
  var value = changedSnapshot.child("word").val();
  console.log('valueチェック: %s', value);
  if (value) {

//コマンド生成
    getJsonData(value.split(" ")[0], {
      // youtube
      "youtube": function() {
        let keyword = value.split(" ");
        keyword.shift();
        keyword = keyword.join(' ');
        console.log('keywordチェック: %s', keyword);
        play_youtube(keyword);
      }
    })();

    //firebase clear
    db.ref("/googlehome").set({"word": ""});

  }
});

//jsonからvalueに一致する値取得
function getJsonData(value, json) {
  for (var word in json){
     if (value == word){
         console.log('json[word]チェック: %s', json[word]);
     }
     console.log('json["default"]チェック: %s', json["default"]);
  }
  return json["default"]
}


function play_youtube(keyword) {
  // categoryIdの10はMusic https://stackoverflow.com/questions/17698040/youtube-api-v3-where-can-i-find-a-list-of-each-videocategoryid
  youtube.search(keyword, 1, {'type':'video', 'videoCategoryId':10}  , function(error, result) {
    if (error) {
      console.log(error);
      return ;
    }
    console.log(JSON.stringify(result, null, 2));
    for (const item of result.items) {
      if (item.id.videoId) {
        console.log(item.id.videoId);

            exec('youtube-dl -g -x https://www.youtube.com/watch?v='+item.id.videoId, function(error, stdout, stderr) {
              if (error !== null) {
                console.log('exec error: '+error);
              }
              const soundUrl = stdout;
              console.log(soundUrl);

              notifier.play(soundUrl, function(res) {
                console.log(res);
              });
            });

      }
    }
  });
}
```

#node.jsをラズパイ内で永続化
こちらを参考にしました
[[Node.js] Foreverコマンドでスクリプトをバックグラウンドで動かす](https://www.taneyats.com/entry/raspi-dash-button-forever)

```
vim /etc/rc.local
```

```c
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

# googlehomeがyoutubeで音楽を検索するアプリ
sudo -u {{ユーザー名}} /usr/local/bin/node /usr/local/bin/forever start -p /var/run/forever --pidfile /var/run/node-app.pid -l /home/{{ユーザー名}}/Repository/google-home-play-youtube/google-home-notifier/out.log -a -d /home/{{ユーザー名}}/Repository/google-home-play-youtube/google-home-notifier/index.js

exit 0
```

ラズパイをリブートしてきちんと永続化されているか確認する

```c
$ sudo reboot

再起動後
$ forever list

info:    Forever processes running
data:        uid  command             script                                                                                  forever pid  id logfile                                                                         uptime
~~~~~~省略~~~~~~~
data:    [3] Vf2l /usr/local/bin/node /home/{{ユーザー名}}/Repository/google-home-play-youtube/google-home-notifier/index.js        948     1020    /home/{{ユーザー名}}/Repository/google-home-play-youtube/google-home-notifier/out.log 0:10:32:6.993
```


## 参考資料
[Google Home自身でYoutubeの音楽を再生する](https://qiita.com/odetarou/items/0e134ff845826d16170c)
[[Node.js] Foreverコマンドでスクリプトをバックグラウンドで動かす](https://www.taneyats.com/entry/raspi-dash-button-forever)
先人の皆様に感謝を込めて・・・とても助かりました :pray: 

結局foreverで他のファイルを読み取れない原因がよくわからなかった・・・・