必要なもの
- Node.js
- Node-RED
- ディスコードのBOTを自分で作る
- 出力先(今回はGoogleHome)
BOT作ってない人はこちらから
注意
これ多分 Node-RED のバグなんですが、Objectをデバッグコンソールに出そうとすると RangeError: Maximum call stack size exceeded
を吐いて死ぬ時があります。すなおに出てくる場合もあるから多分循環参照とかを最初に解決して文字列にしようとしてるんじゃないかなーと。これで結構ハマりました。デバグ機能を使う時には注意しましょう。
手順
Node-Red
今回は適当にローカルで。
インストールして、 http://<対象サーバ>:1880/
にアクセスすれば編集画面が開けます。
必要ライブラリ
右上のハンバーガーメニューから「パレットの管理」>「ノードの追加」とすればライブラリをインストールする事ができます。今回入れたのは
- node-red-contrib-cast (GoogleHome用)
- node-red-new-discord (discord用)
フローの作成
全体構造として
- 起動時のキック
- クライアントオブジェクトの呼び出し
- イベントの設定
- GoogleHomeにキャスト
といった単純な構造です。
クライアントトークンの登録
ベタベタと置いたところで、discodeClient
に赤い三角がついていると思います。
これをダブルクリックすると token
という変数と登録しろと出ている筈なので、画面に従ってBOTのTOKENを入れてあげましょう。
初動のキック - クライアントオブジェクトの呼び出し
最初の二つですが、単純にdiscordClientを引っぱってくるためだけのものです。
node-red-new-discord
にはテキストメッセージをフックにするノードしか用意されておらずその他のイベントに対応したい場合は自分でイベントを登録しなければいけません。
readme を読めばわかりますが、この discordClient
は単純に Discode.js の Client を次のノードに渡してくれるノードです。
右のノード一覧の一番上に「inject」というノードがありますので、そこからキックしてあげましょう。ノードをダブルクリックすると一番下に「Node-RED起動の ** 秒後、以下を行う」というチェックボックスがありますので、それをチェックすれば開始時にキックしてくれます。
どうやら0.1秒のままだとDiscord.jsの初期化が間に合わないみたいなので、2秒ぐらいにするといいかんじです。
イベントの登録
渡ってきたメッセージは msg
という変数で参照でき、 msg.discord
にClientオブジェクトがまるっと入っています。
なのでそこにフックを入れてあげましょう。この方式でどんなイベントフックにも対応できます。というか本来のDiscode.jsの使いかたですね。
const bot = msg.discord;
// ボイスチャンネルに何かあった場合は voiceStateUpdate がトリガーされる。
bot.on('voiceStateUpdate', (oldState, newState) => {
// 今どこかのボイスチャンネルにいる、かつさっきとチャンネルが違う時
if(newState.channelID && oldState.channelID != newState.channelID){
let member = newState.member.displayName
let channel = newState.channel.name
msg.payload = '';
// GoogleHomeの場合はこのプロパティが読み上げられる
msg.message = member + 'が' + channel + 'に入りました';
// 非同期でメッセージの送信を行う場合は node.send を呼んであげる
node.send(msg);
}
});
// 最初にキックされた時の後続処理
// なにか喋ってくれた方がいいので入れてるだけ。
delete msg.discord
msg.payload = '';
msg.message = 'ボイスステータスアップデート登録';
return msg;
GoogleHomeに喋らせる
Castのノードをクリックすると、一番上にIPを入れるところがありますので、そこにGoogleHomeのIPを入れましょう。
上でも触れましたが、メッセージの message
というプロパティが読み上げられます。