ある中卒がWeb系エンジニアになるまでと、それからのこと

うつ病で高校を中退したり、たこ焼き屋のオヤジにホームページとたこ焼きを作らされたり、そのホームページが訴えられそうになったり、弁護士を目指したりした後にエンジニアになった人が書くブログ

vue + skywayアプリでRealtime Databaseを使う

2020/07/07の日報

Hanasot開発の日報、第11日目です。
やったことは

  • vue + skywayでRealtime Databaseを使う

です。
時間は、

  • Hanasot開発 1h26min
  • 日報ブログ 2h52min

です。
運動は

  • アンイーブン・スクワット 左右17repsずつ * 2

です。

vue + skywayでRealtime Databaseを使う

今日は「発言者を1人に限定してみよう(発言者以外はミュートしよう)」のpart1です。そもそもこの機能はHanasotの骨組みである哲学対話のルールに基づいています。哲学対話で重要とされるルールの1つに、「発言中に口を挟ませないために、対話中に発言できるはマイクを持っている人のみ」というものがあるんです。他人との対話を通して自分の心と対話する哲学対話の思想に深く結びつくルールといえるでしょう。

今日から2,3日かけてこの機能を作っていきます。

実装方法

この機能はDBをリアルタイムで反映させることで実現します。具体的には下記のフローです。

1.skywayでルームが作成されたら、同時にfirebaseでもルーム一覧コレクションにドキュメントを作成

2.ドキュメントは入れ子にして

【ルーム一覧コレクションのドキュメント】
・ルームID
・現在の発言者(初期値はルームの作成者。リアルタイムで更新する。)
・作成日時
・参加者一覧(サブコレクション)

【参加者一覧コレクションのドキュメント】
・参加者ID
・マイクはオンかオフか(リアルタイムで更新する。)
・カメラはオンかオフか(リアルタイムで更新する。)
・参加日時

このように保存する。参加者一覧のドキュメントは参加者が入室する度に追加されていく。
(文字だとわかりにくいかと思いますので、下の動作時の画像も合わせてご確認ください。)

3.DBを常に監視して、発言者以外はマイクをオンにできないようにする(発言者がマイクをオフにするのは可能)

4.発言者が発言権を譲ったらDBの発言者を更新して、マイクのオンオフを切り替える

参加者ごとに保存しているカメラのオンオフ・マイクのオンオフのデータは、明日以降UIの部分で使う予定です。

firebaseにコレクションを作成する

firebaseコンソールのdatabaseタブを開き「コレクションを開始」をクリックして作成していきます。

f:id:chusotsuengineer:20200707223842p:plain
コレクション名を入力
f:id:chusotsuengineer:20200707224146p:plain
最初のドキュメントは使用しませんが、DB構成を明確にするために入力しておきます
f:id:chusotsuengineer:20200707224424p:plain
サブコレクションも作っていきます
f:id:chusotsuengineer:20200707224453p:plain
サブコレクションの構成はこんな感じです

これでコレクションの作成と、DBに書き込む項目がわかりました。早速コードを書きましょう。

~~~~略~~~~
  import firebase from 'firebase';
~~~~略~~~~
    methods: {
      makeRoom() {
        const mediaConnection = this.peer.joinRoom(this.roomID, {
          mode: 'sfu',
          stream: this.localStream,
        });

        // ルームを作成
        firebase.firestore().collection('rooms').doc(this.roomID).set({
          createdAt: firebase.firestore.FieldValue.serverTimestamp(),
          right: this.peer.id,
        });
        firebase.firestore().collection('rooms').doc(this.roomID).collection('participants')
          .doc(this.peer.id).set({
            isMuted: false,
            isCameraOff: false,
            joinedAt: firebase.firestore.FieldValue.serverTimestamp(),
          });

        this.setEventListener(mediaConnection);
      },
~~~~略~~~~

firebase.firestore().collection('コレクション名').doc('ドキュメントのID').set(書き込む項目)というように記述します。

サブコレクションがあるならfirebase.firestore().collection('コレクション名').doc('ドキュメントのID').collection('コレクション名').doc('ドキュメントのID').set(書き込む項目)という感じで2回コレクションを指定します。直感的でいいですね。

DBと接続する

ただこのままだとエラーが起きてしまいます。必要な環境変数を設定していないからです。vueのコンストラクタを呼んでいるjsファイルを開きましょう。vue-cliならindex.jsだと思います。その先頭に下のコードを書きます。

import firebase from 'firebase';

const config = {
  apiKey: 'apiキー',
  authDomain: 'ホスティング先のURL',
  databaseURL: 'DBのURL',
  projectId: 'プロジェクト名',
  storageBucket: 'ストレージ(画像とかを保存する)のURL',
  messagingSenderId: 'よくわからん',
}

firebase.initializeApp(config);

configの取得方法はドキュメントに書いてあります。が、既にホスティングしているならこんなことしなくても大丈夫です。
ホスティング先のURL/__/firebase/init.jsにアクセスすればjson形式で表示されます。マジで。セキュリティどうなってんのという気もしますが今回はスルー。

ルールを書き換える

これで万事OKと思いきやこんなエラーが出ました。

f:id:chusotsuengineer:20200707230202p:plain
真っ赤やん
前のプロジェクトで1億回は見たエラーなのでもはや慌てません。これはセキュリティルールに引っかかった時に吐くエラーです。

f:id:chusotsuengineer:20200707230310p:plain
コンソールでルールを確認してみる

前回チラ見したとき、このルールは「どのドキュメントにもアクセスOK」の意味だと思ってましたが、よくみるとif falseになってますね。どのドキュメントもアクセスさせねーよってことでした。ここtrueに書き換えるだけでとりあえずOKです。公開前にちゃんと制定していきます。

コレクション作成完了

あとはこんな感じでルームIDを入力して送信してみると

f:id:chusotsuengineer:20200707230608p:plain
謎の後光が差す猫

f:id:chusotsuengineer:20200707230715p:plain
日本語のidでもOKなのは知らなかった
f:id:chusotsuengineer:20200707230817p:plain
サブコレクションもちゃんとできてます

成功ですね。

所感

参加者一覧のとこサブコレクションにしようかmapにしようか迷ったんですけど、Timestampがmapでは使えなかったのでサブコレクションにしました。そんな違いがあるんですね。

ルールはガチガチに固めないとヤバそうなので早め早めに作っていきます。
あと、ルールをローカルに反映するのも忘れないようにしないとdeployで消えちゃうので気をつけましょう。 そんなところかな。

なんか今日やたら記事を書くのに時間かかってグロッキーです。なんでかなー。