Google HomeにLINEのメッセージを読み上げさせる(LINE BOT+Webhook+Firebase+Node.js)

大晦日にポチったRM mini3が届かない・・・

Firebaseの練習を兼ねて遊んでみました。

 

目標:LINEで入力したメッセージをGoogle Homeに読み上げさせる

今回の実現イメージはこんな感じです。

f:id:megalodonkun:20180110002808p:plain

 用意したもの

・Firebase (Realtime Database)

・LINE Messaging API (Developers Trial)

・node.js環境(Raspberry.pi zero w)

Google Home mini

 

・Firebase

下記を参考に設定しました。

新着メールを知らせてくれるGoogle Home - Qiita

認証必須の設定にしてもnode.jsからの読み書きは問題なさそうですが、

LINEのWebhookから書き込めるのか?未検証です(書き込めない気がする)

今回はプロジェクト直下に"line"の子ノードをぶら下げておきます。

 

・LINE Messaging API

下記を参考に設定しました。

Google Home mini で双方向の音声でのLINE送受信を実現する - Qiita

Webhook送信:利用する

Webhook URL:https://XXXXXXXXXXXXXXX.firebaseio.com/line/receive.json

(receive子ノード作ってませんが、これでOKです。詳しくは後述)

これで、このMessaging APIに話しかけるorAPIが参加するグループやトークで発話すると、そのメッセージがJSON形式でFirebaseのline/receiveの下にPOSTされます。

 

・node.js環境

google-home-notifierとfirebase、superagentを導入します。

google-home-notifierについては過去記事にて詳述。

 

megalodon.hateblo.jp

下記の方法でサービスとして登録しました。

Google Homeで時報を知らせる - Qiita

firebase, superagentは下記を参考に導入。

新着メールを知らせてくれるGoogle Home - Qiita

$ mkdir firebase-listener

$ cd firebase-listener

$ npm init

$ npm install firebase --save

$ npm install superagent --save

listenerのコード(index.js)は下記の通り。

var request = require('superagent');
var firebase = require("firebase");

function sendMessage(message) {

  request.post('http://192.168.XXX.XX:XXXX/google-home-notifier')
    .type('form')
    .send({
      text: message
    })
    .end((err, res) => {
      if (err) {
        console.error(err);
      } else {
        console.log(res.text);
      }
  });
}

var config = {
    apiKey: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    authDomain: "XXXXXXXXXXXXX.firebaseapp.com",
    databaseURL: "https://XXXXXXXXXXXX.firebaseio.com",
    projectId: "XXXXXXXXXXXXX",
    storageBucket: "XXXXXXXXXXXXX.appspot.com",
    messagingSenderId: "XXXXXXXXXXXXX"
  };

firebase.initializeApp( config );

var db = firebase.database();
var receivedlineRef = db.ref( '/line/receive');

receivedlineRef.on("child_added", function(snap) {
  var linemessage = snap.val();
  snap.ref.remove(); //Delete child in firebase
  var textmain = linemessage.events[0].message.text;
  var userid = linemessage.events[0].source.userId;
  if(linemessage.events[0].message.type == 'sticker'){
        sendMessage('スタンプは読めないよ');
        return;
  }
  if(userid == "AAAAAAAAAAAAAAAAAAAAAAA"){
        var message = 'AAさんからのLINEです。' + textmain;
  } else if(userid == "BBBBBBBBBBBBBBBBBBBBBBBB"){
        var message = 'BBさんからのLINEです。' + textmain;
  } else {
        var message = textmain;
  }
  sendMessage( message );
});

・configにはFirebaseの設定の際にメモした情報を入力

・Firebaseのchild_addedイベントは、listener起動時に対象ノードに子ノードが存在すると(この場合、/line/receiveの下にノードが存在すると)起動してしまうようです。そのため、今回はあえてreceiveノードをあらかじめ作成していません。存在しない階層でもWebhookで直接指定してやれば、Firebase側で勝手に作ってくれます。

・今回実験のためとはいえFirebaseの認証不要にしちゃっているので+上記の通りreceiveノードに子ノードを溜めたくないので、snapした子ノードは消去する処理としています。

スタンプ送信された時だけ例外処理していますが、その他の例外処理もいりますね・・・

・useridでメッセージの送信者名を入れ込む処理も書いてみました(あんまりスマートなやり方じゃないかも・・・)。useridはメッセージをテスト送信してFirebaseにPOSTしてあげれば確認できます。

 

あとは、このlistenerもサービスとして登録してやれば、LINE⇒Google Home読み上げの仕掛け完成です。

実験してみたところ、きちんとメッセージ本文を読み上げてくれました!

 

感想:

 Node.jsの書き方にちょっとずつ慣れてきました。FirebaseやJSON構文も勉強できていい練習になりました。スマホからメッセージ送るだけでGoogle Homeちゃんに色んな言葉をしゃべらせられるのが単純に面白かったです。

 

次はGoogle Home入力⇒LINE Messaging API投稿にチャレンジして、双方向のやりとりを実現したいと思います。