タスクマネージャーをアップデートした!


前回の記事

作成したタスクマネージャーbot

追加した機能

・WebViewでタスクの登録
・通知機能
・リッチメニュー

使用した技術

フロントエンド
・LINE

バックエンド
・Node.js(Express)
・firebase(cloud functions, firestore)
・Messaging API
・dayJs

WebView
・LIFF(LINE SDK)
・ReactHooks
・Material-UI
・firebase(Hosting, firestore)

システム構成

Cloud Functions + LIFF

1.main関数 : チャットボットとのやりとりを行う
2.register関数 : タスクが登録できたことを知らせる
3.reminder関数 : 指定された時間に通知をする

4.LIFF : タスクの登録を行う

それぞれの関数について

main関数

main関数の主な役割は登録したタスクの表示です。
下記シーケンス図はタスク一覧表示の処理の流れです。

main関数はwebhookURL1として設定しています。
つまりユーザーがメッセージを送信すると、main関数にpost(webhookイベントオブジェクト)が送られます。
webhookイベントオブジェクトの中身はこちら

1.webhookイベントオブジェクトを受け取ったmain関数は、メッセージ内容を確認します。
   メッセージ内容が「@show」であれば2へ
2.ユーザIDとfirebaseに登録してあるIDと照合し一致するタスク取り出します。
3.取り出したタスクをボタンテンプレート形式でユーザに送信するよう処理を行なっています。

ざっくり説明するとmain関数は1~3の処理を行なっています。

1webhookとはユーザーがメッセージを送信したり、友達追加したりなどイベントが発生すると、指定したURLにpostを投げる仕組み・技術のことです

register関数


register関数はタスクが登録された時に登録できたことを通知するプログラムです。
トリガーをonCreateにすることでfirestoreにタスクが登録された時に、処理が走るようになっています。

Node.js
exports.register = functions.region("asia-northeast1")
    .firestore
    .document('todos/{todoId}')
    .onCreate((snap, context) => {
      const userId = snap.data().userId;
      const todoName = snap.data().name;
     return Handle.registerMessage(userId, todoName);
});

firestoreにタスクが登録されるとそのタスクからユーザIDとタスク名を取得し、ユーザID宛にpushメッセージを送る処理をHandle.registerMessage()で書いています。

remider関数

reminder関数は通知設定されたタスクを時間通りに通知するプログラムです。
トリガーは1分毎に実行されるように書いていて、現在時刻と通知時間が一致するタスクがあるかどうかを毎分照合しています。
一致するタスクがあればそのタスクデータを取り出し、登録したユーザーにpushメッセージを送るコードをHandle.reminder()で書いています。

Node.js
exports.reminder = functions.region('asia-northeast1')
.pubsub.schedule('every 1 minutes')
.timeZone('Asia/Tokyo')
.onRun((context) => {
  return Handle.reminder();
})

LIFF

タスクの登録はwebアプリケーションで行なっています。
LIFFとはwebアプリケーションをLINEの中で起動させる仕組みのことで、LINEから離れずに操作することができます。
こんな感じ↓↓↓↓

React.js
  useEffect(() => {
    liff.init({liffId: LIFF_ID})
    .then(() => {
      getProfile();
    })
    .catch((err) => {
      console.log(err.code, err.message);
    })
  }, [])

  const getProfile = () => {
    liff.ready.then( async() => {
        const context = await liff.getContext()
        setUid(context.userId);
    })
  }

webアプリケーションの中でLINESDKを用いて、liff.init()→liff.getContext()することで
ユーザー情報を取得できます。公式ドキュメント
本アプリではタスクにユーザIDをタグ付けすることで、誰のタスクかを管理しています。

まとめ

コードによるプログラム解説ではなく、設計段階の解説をしてみました。
こちらのLINEBotはまだまだ改良していくつもりなので、追加機能の案やバグがあればドシドシコメントお願いします!!
また、今回の記事で分かりにくいことがあればコメント頂ければ幸いです!

実装予定機能

毎週リマインド機能
スヌーズ機能

参考文献

https://developers.line.biz/ja/docs/messaging-api/
https://dev.classmethod.jp/articles/try-cloud-functions-scheduler-pubsub/
https://qiita.com/hirothings/items/37430b2408a5a7a85972
https://ginpen.com/2019/06/01/firestore-indexes-json/
https://github.com/iamkun/dayjs/blob/dev/docs/en/API-reference.md#list-of-all-available-formats