mirror of
https://github.com/urosran/cally.git
synced 2025-11-26 00:24:53 +00:00
Notifications
This commit is contained in:
@ -1,14 +1,107 @@
|
||||
const {onRequest} = require("firebase-functions/v2/https");
|
||||
const {getAuth} = require("firebase-admin/auth");
|
||||
const {getFirestore} = require("firebase-admin/firestore");
|
||||
const admin = require("firebase-admin");
|
||||
const logger = require("firebase-functions/logger");
|
||||
const functions = require('firebase-functions');
|
||||
const admin = require('firebase-admin');
|
||||
const {Expo} = require('expo-server-sdk');
|
||||
|
||||
try {
|
||||
admin.initializeApp();
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
admin.initializeApp();
|
||||
const db = admin.firestore();
|
||||
|
||||
let expo = new Expo({accessToken: process.env.EXPO_ACCESS_TOKEN});
|
||||
|
||||
// Firestore trigger that listens for new events in the 'Events' collection
|
||||
exports.sendNotificationOnEventCreation = functions.firestore
|
||||
.document('Events/{eventId}')
|
||||
.onCreate(async (snapshot, context) => {
|
||||
const eventData = snapshot.data();
|
||||
|
||||
const pushTokens = await getPushTokensForEvent(eventData);
|
||||
|
||||
if (!pushTokens.length) {
|
||||
console.log('No push tokens available for the event.');
|
||||
return;
|
||||
}
|
||||
|
||||
let messages = [];
|
||||
for (let pushToken of pushTokens) {
|
||||
if (!Expo.isExpoPushToken(pushToken)) {
|
||||
console.error(`Push token ${pushToken} is not a valid Expo push token`);
|
||||
continue;
|
||||
}
|
||||
|
||||
messages.push({
|
||||
to: pushToken,
|
||||
sound: 'default',
|
||||
title: 'New Event Added!',
|
||||
body: `An event "${eventData.title}" has been added. Check it out!`,
|
||||
data: {eventId: context.params.eventId},
|
||||
});
|
||||
}
|
||||
|
||||
let chunks = expo.chunkPushNotifications(messages);
|
||||
let tickets = [];
|
||||
for (let chunk of chunks) {
|
||||
try {
|
||||
let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
|
||||
|
||||
tickets.push(...ticketChunk);
|
||||
|
||||
for (let ticket of ticketChunk) {
|
||||
if (ticket.status === 'ok') {
|
||||
console.log('Notification successfully sent:', ticket.id);
|
||||
} else if (ticket.status === 'error') {
|
||||
console.error(`Notification error: ${ticket.message}`);
|
||||
|
||||
if (ticket.details && ticket.details.error) {
|
||||
console.error('Error details:', ticket.details.error);
|
||||
if (ticket.details.error === 'DeviceNotRegistered') {
|
||||
console.log(`Removing invalid push token: ${ticket.to}`);
|
||||
await removeInvalidPushToken(ticket.to);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error sending notification:', error);
|
||||
}
|
||||
}
|
||||
|
||||
let receiptIds = [];
|
||||
for (let ticket of tickets) {
|
||||
if (ticket.id) {
|
||||
receiptIds.push(ticket.id);
|
||||
}
|
||||
}
|
||||
|
||||
let receiptIdChunks = expo.chunkPushNotificationReceiptIds(receiptIds);
|
||||
for (let chunk of receiptIdChunks) {
|
||||
try {
|
||||
let receipts = await expo.getPushNotificationReceiptsAsync(chunk);
|
||||
console.log('Receipts:', receipts);
|
||||
|
||||
for (let receiptId in receipts) {
|
||||
let { status, message, details } = receipts[receiptId];
|
||||
|
||||
if (status === 'ok') {
|
||||
console.log(`Notification with receipt ID ${receiptId} was delivered successfully`);
|
||||
} else if (status === 'error') {
|
||||
console.error(`Notification error: ${message}`);
|
||||
if (details && details.error) {
|
||||
console.error(`Error details: ${details.error}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error retrieving receipts:', error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
exports.createSubUser = onRequest(async (request, response) => {
|
||||
const authHeader = request.get('Authorization');
|
||||
@ -97,3 +190,20 @@ exports.generateCustomToken = onRequest(async (request, response) => {
|
||||
response.status(500).json({error: "Failed to generate custom token"});
|
||||
}
|
||||
});
|
||||
|
||||
async function getPushTokensForEvent() {
|
||||
const usersRef = db.collection('Profiles');
|
||||
const snapshot = await usersRef.get();
|
||||
let pushTokens = [];
|
||||
|
||||
snapshot.forEach(doc => {
|
||||
const data = doc.data();
|
||||
if (data.pushToken) {
|
||||
pushTokens.push(data.pushToken);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Push Tokens:', pushTokens);
|
||||
return pushTokens;
|
||||
}
|
||||
|
||||
|
||||
53
firebase/functions/package-lock.json
generated
53
firebase/functions/package-lock.json
generated
@ -6,6 +6,7 @@
|
||||
"": {
|
||||
"name": "functions",
|
||||
"dependencies": {
|
||||
"expo-server-sdk": "^3.11.0",
|
||||
"firebase-admin": "^12.1.0",
|
||||
"firebase-functions": "^5.0.0"
|
||||
},
|
||||
@ -3115,6 +3116,12 @@
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/err-code": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
|
||||
"integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
@ -3425,6 +3432,16 @@
|
||||
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-server-sdk": {
|
||||
"version": "3.11.0",
|
||||
"resolved": "https://registry.npmjs.org/expo-server-sdk/-/expo-server-sdk-3.11.0.tgz",
|
||||
"integrity": "sha512-EGH82ZcdAFjKq+6daDE8Xj7BjaSeP1VDvZ3Hmtn/KzEQ3ffqHkauMsgXL2wLEPlvatLq3EsYNcejXRBV54WnFQ==",
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.0",
|
||||
"promise-limit": "^2.7.0",
|
||||
"promise-retry": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.19.2",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
|
||||
@ -5754,7 +5771,6 @@
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
@ -6183,6 +6199,34 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/promise-limit": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/promise-limit/-/promise-limit-2.7.0.tgz",
|
||||
"integrity": "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/promise-retry": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
|
||||
"integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"err-code": "^2.0.2",
|
||||
"retry": "^0.12.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/promise-retry/node_modules/retry": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
|
||||
"integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/prompts": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
|
||||
@ -7048,8 +7092,7 @@
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ts-api-utils": {
|
||||
"version": "1.3.0",
|
||||
@ -7268,8 +7311,7 @@
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
|
||||
"license": "BSD-2-Clause",
|
||||
"optional": true
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/websocket-driver": {
|
||||
"version": "0.7.4",
|
||||
@ -7299,7 +7341,6 @@
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
},
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"expo-server-sdk": "^3.11.0",
|
||||
"firebase-admin": "^12.1.0",
|
||||
"firebase-functions": "^5.0.0"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user