Преглед на файлове

feat: send push notification on events

Léo Salé преди 3 години
родител
ревизия
9e5fe602cf

+ 4 - 0
app/lib/friends/services/challenge_location_service.dart

@@ -1,7 +1,10 @@
 import 'package:cloud_firestore/cloud_firestore.dart';
 import 'package:physigo/friends/models/challenge_location_request.dart';
+import 'package:physigo/services/push_notifications_service.dart';
 
 const userId = "tlmysIvwTBaoZKWqBofx";
+const name = "John";
+const surname = "Smith";
 
 class ChallengeLocationService {
   static final _db = FirebaseFirestore.instance;
@@ -37,6 +40,7 @@ class ChallengeLocationService {
     final user = await _users.doc(userId).get();
     final shareLocationRequest = {"user_id": friendId, "requester_id": userId, "location": user['weekly_place']};
     await _shareLocationRequests.add(shareLocationRequest);
+    PushNotificationsService.sendChallengeLocationRequestNotification(userId, name, surname);
   }
 
   static Future<void> acceptChallengeLocationRequest(ChallengeLocationRequest request) async {

+ 5 - 0
app/lib/friends/services/friends_service.dart

@@ -1,9 +1,12 @@
 import 'package:cloud_firestore/cloud_firestore.dart';
 import 'package:physigo/friends/models/friend_request.dart';
+import 'package:physigo/services/push_notifications_service.dart';
 import '../models/friend.dart';
 import '../models/friend_relation.dart';
 
 const userId = "tlmysIvwTBaoZKWqBofx";
+const name = "John";
+const surname = "Smith";
 
 class FriendsService {
   static final _db = FirebaseFirestore.instance;
@@ -41,6 +44,7 @@ class FriendsService {
       await _checkExistingFriendRelation(friend.id);
       final friendRequest = {"user_id": userId, "friend_id": friend.id, "request_status": "pending"};
       await _friends.add(friendRequest);
+      PushNotificationsService.sendFriendRequestNotification(userId, name, surname);
     } catch (error) {
       return Future.error(error);
     }
@@ -49,6 +53,7 @@ class FriendsService {
   static Future<void> acceptFriendRequest(FriendRequest friendRequest) async {
     final newStatus = {"request_status": "accepted"};
     await _friends.doc(friendRequest.requestId).update(newStatus);
+    PushNotificationsService.sendFriendRequestAcceptedNotification(userId, name, surname);
   }
 
   static Future<void> refuseFriendRequest(FriendRequest friendRequest) async {

+ 1 - 1
app/lib/main.dart

@@ -6,7 +6,7 @@ import 'package:physigo/friends/friends_page.dart';
 import 'navigation/navigation_page.dart';
 
 import 'firebase_options.dart';
-import 'services/push_notifications.dart';
+import 'push_notifications_initializer.dart';
 
 void main() async {
   WidgetsFlutterBinding.ensureInitialized();

+ 0 - 0
app/lib/services/push_notifications.dart → app/lib/push_notifications_initializer.dart


+ 35 - 0
app/lib/services/push_notifications_service.dart

@@ -0,0 +1,35 @@
+import 'package:flutter/foundation.dart';
+import 'package:http/http.dart' as http;
+
+class PushNotificationsService {
+  static const _url = 'https://physigo.vercel.app/api/push-notification';
+
+  static void sendFriendRequestNotification(String userId, String name, String surname) {
+    const title = "Friend Request";
+    final body = "$name $surname wants to be your friend";
+    _sendPushNotification(userId, title, body);
+  }
+
+  static void sendChallengeLocationRequestNotification(String userId, String name, String surname) {
+    const title = "Shared Challenge location request";
+    final body = "$name $surname shared their challenge's location with you";
+    _sendPushNotification(userId, title, body);
+  }
+
+  static void sendFriendRequestAcceptedNotification(String userId, String name, String surname) {
+    const title = "New Friend";
+    final body = "$name $surname is now your friend!";
+    _sendPushNotification(userId, title, body);
+  }
+
+  static Future<void> _sendPushNotification(String userId, String title, String body) async {
+    try {
+      await http.post(Uri.parse('$_url?user_id=$userId&title=$title&body=$body'));
+    } catch (error) {
+      // We don't care if sending the notification fails
+      if (kDebugMode) {
+        debugPrint(error.toString());
+      }
+    }
+  }
+}

+ 42 - 0
serverless_functions/api/push-notification.ts

@@ -0,0 +1,42 @@
+import { VercelRequest, VercelResponse } from '@vercel/node';
+import { initializeApp, cert } from 'firebase-admin/app';
+import { getFirestore } from 'firebase-admin/firestore';
+import { getMessaging } from 'firebase-admin/messaging';
+import { Message } from 'firebase-admin/lib/messaging/messaging-api';
+
+const serviceAccountStringified = Buffer.from(process.env.FIREBASE_SERVICE_ACCOUNT!, 'base64').toString('ascii');
+const serviceAccount = JSON.parse(serviceAccountStringified);
+initializeApp({
+  credential: cert(serviceAccount),
+});
+const firestore = getFirestore();
+const messaging = getMessaging();
+export default async function sendPushNotification(req: VercelRequest, res: VercelResponse) {
+  const { user_id, title, body } = req.query as { user_id: string; title: string; body: string };
+
+  const friend = await firestore
+    .collection('Users')
+    .doc(user_id)
+    .get();
+  if (!friend.exists) {
+    return res.status(400).json({ error: "User doesn't exist" });
+  }
+  const token = friend.data()!['token'];
+  const message: Message = {
+    notification: {
+      title,
+      body,
+    },
+    token,
+  };
+  messaging
+    .send(message)
+    .then((response) => {
+      console.log('Successfully sent message:', response);
+      res.status(200);
+    })
+    .catch((error) => {
+      console.log('Error sending message:', error);
+      res.status(500).send(error);
+    });
+}

Файловите разлики са ограничени, защото са твърде много
+ 978 - 0
serverless_functions/package-lock.json


+ 3 - 1
serverless_functions/package.json

@@ -13,6 +13,8 @@
   },
   "dependencies": {
     "@vercel/node": "^1.15.0",
-    "axios": "^0.27.2"
+    "axios": "^0.27.2",
+    "firebase": "^9.8.1",
+    "firebase-admin": "^10.2.0"
   }
 }

Някои файлове не бяха показани, защото твърде много файлове са промени