Cloud Functions에서 채팅 메시지 모니터링 및 푸시 알림

하고 싶은 일



앱에서 메시지 보내기→DB(Firestore)에 메시지가 저장됨→이를 모니터링하고 있던 CloudFunctions가 푸시 알림을 보냅니다.

Cloud Functions로 가능한 작업

관심사가 발생할 때 사용자에게 알리기



이것과 유사한 이미지.

Firestore 디자인



chatrooms(컬렉션)
 ∟chatroom1(문서)
  ∟messages (컬렉션)
   ∟message1(문서)
   ∟message2(문서)
   ∟message3(문서)

 ∟chatroom2(문서)
  ∟messages (컬렉션)
   ∟message1(문서)
   ∟message2(문서)
:
:
  • 루트 레벨에 chatrooms 컬렉션이 있습니다
  • chatrooms 문서 아래에 messages 하위 컬렉션이 있습니다

  • 이렇게 설계했습니다.

    앱 디자인



    디자인이라고 할 정도는 아니지만, 다음과 같이 사전에 주제를 구독시킵니다.
    타이밍으로서는 LINE에서 말하는 「그룹 채팅에 참가한다」와 같은 것을 계기로 하면 좋은 것이 아닐까요.

    이 때 주제 이름으로 대화방의 문서 ID를 지정합니다.
    Messaging.messaging().subscribe(toTopic: "/topics/\(chatroomドキュメントのid)")
    

    이렇게 하면 /topics/{chatroomドキュメントのid} 받는 사람에게 FCM 메시지를 보낼 때 푸시 알림을 받을 수 있습니다.

    CloudFunctions 설계



    CLI 도구를 설치하지 않은 경우 설치합니다.$ npm install -g firebase-tools
    적당히 디렉토리를 만들어 거기서 프로젝트를 초기화합니다.$ firebase init functions


    프로젝트를 선택하고 Javascript 또는 Typescript를 선택합니다.
    이번에는 자바 스크립트를 선택한 전제로 이야기를 진행합니다.
    그 후 여러가지 듣습니다만 모두 Enter로 OK입니다.


    이런 파일군이 자동으로 생성될 것입니다.

    index.js에 다음을 추가합니다. (공식의 순서대로입니다만)
    이것으로

    functions/index.js
    // The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
    const functions = require('firebase-functions');
    
    // The Firebase Admin SDK to access the Firebase Realtime Database.
    const admin = require('firebase-admin');
    admin.initializeApp(functions.config().firebase);
    

    이제 Firestore에 액세스할 수 있습니다.
    그런 다음 중요한 푸시 알림을 수행하는 함수를 정의합니다.

    Firestore에 추가를 트리거에 푸시 알림을 보냅니다.
    이쪽을 참고로 했습니다.
    Cloud Functions로 Cloud Firestore 확장

    functions/index.js
    exports.sendNotifications = functions.firestore
        .document('/chatrooms/{chatroomId}/messages/{messageId}')
        .onCreate((event, snapshot) => { // 公式ではeventとなっていたが、そうするとevent.params.chatroomIdのように値を取ってこれなかった。
    
            var topic = snapshot.params.chatroomId; // こうすることで上で指定したドキュメントのパスの{chatroomId}部分が取得できる。
    
            var payload = {
              notification: {
                title: "新着メッセージ", // この辺りを動的に取ってくるケースが多いかな?
                body: "新着メッセージがあります"
              }
            };
    
            var options = {
              priority: "high"
            };
    
            // 指定したtopic宛てにメッセージを送る
            return admin.messaging().sendToTopic(topic, payload, options)
              .then(function(response) {
                return console.log("Successfully sent message:", response);
              })
              .catch(function(error) {
                return console.log("Error sending message:", error);
              });
        });
    

    그리고 배포합니다.
    $ firebase deploy --only functions
    위의 코드라면 에러는 나오지 않는다고 생각합니다만, 당초 자신은 sendToTopic내의 console.log에 return를 붙이지 않았기 때문에 이하와 같이 Lint로 화났습니다.Each then() should return a value or throw promise/always-return
    잘 배포가 끝나면 이렇게 될 것입니다.
    ✔  functions: Finished running predeploy script.
    i  functions: ensuring necessary APIs are enabled...
    ✔  functions: all necessary APIs are enabled
    i  functions: preparing functions directory for uploading...
    i  functions: packaged functions (49.67 KB) for uploading
    ✔  functions: functions folder uploaded successfully
    i  functions: creating function sendNotifications...
    ✔  functions[generateThumbnail]: Successful delete operation. 
    ✔  functions[sendNotifications]: Successful create operation. 
    
    ✔  Deploy complete!
    

    그리고 앱에서 메시지를 보냅니다. (이 기사에서는 메시지 전송 위치에 대해 언급하지 않지만 Firestore message 문서를 생성하는 프로세스를 실행하면 괜찮습니다. 앱에서 그것을 구현하는 것이 귀찮은 경우 Firestore 콘솔에서 직접 messages 문서를 만들어도 동작 확인은 가능합니다.)
    그러면 그 채팅방을 구독하고 있는 단말기에 통지가 간다고 생각합니다.

    Cloud Functions 로그에도 결과가 출력되어야 합니다.



    더 좋은 방법이 있으면 가르쳐 주셨으면합니다.

    좋은 웹페이지 즐겨찾기