notifications
This commit is contained in:
@@ -8,6 +8,13 @@ exports.refList = {
|
||||
projects: admin.firestore().collection("projects"),
|
||||
playlists: admin.firestore().collection("playlists"),
|
||||
tasks: admin.firestore().collection("tasks"),
|
||||
notifications: admin.firestore().collection("notifications"),
|
||||
};
|
||||
|
||||
exports.ALERT_TYPE = {
|
||||
NEW_LIKE: "NEW_LIKE",
|
||||
NEW_COMMENT: "NEW_COMMENT",
|
||||
NEW_FOLLOWER: "NEW_FOLLOWER",
|
||||
};
|
||||
|
||||
// Exporter toutes les fonctions
|
||||
@@ -19,3 +26,4 @@ exports.projects = require("./src/project");
|
||||
exports.thumbnail = require("./src/thumbnail");
|
||||
exports.upload = require("./src/upload");
|
||||
exports.algolia = require("./src/algolia");
|
||||
exports.notifications = require("./src/notifications");
|
||||
|
||||
Generated
+69
@@ -10,6 +10,7 @@
|
||||
"@genkit-ai/googleai": "^1.18.0",
|
||||
"@google-cloud/storage": "^7.17.1",
|
||||
"axios": "^1.11.0",
|
||||
"expo-server-sdk": "^4.0.0",
|
||||
"ffmpeg-static": "^5.2.0",
|
||||
"firebase-admin": "^12.7.0",
|
||||
"firebase-functions": "^6.4.0",
|
||||
@@ -3416,6 +3417,12 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz",
|
||||
@@ -3703,6 +3710,40 @@
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-server-sdk": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/expo-server-sdk/-/expo-server-sdk-4.0.0.tgz",
|
||||
"integrity": "sha512-zi83XtG2pqyP3gyn1JIRYkydo2i6HU3CYaWo/VvhZG/F29U+QIDv6LBEUsWf4ddZlVE7c9WN1N8Be49rHgO8OQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.0",
|
||||
"promise-limit": "^2.7.0",
|
||||
"promise-retry": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-server-sdk/node_modules/node-fetch": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.21.2",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz",
|
||||
@@ -5707,6 +5748,34 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"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/proto3-json-serializer": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"@genkit-ai/googleai": "^1.18.0",
|
||||
"@google-cloud/storage": "^7.17.1",
|
||||
"axios": "^1.11.0",
|
||||
"expo-server-sdk": "^4.0.0",
|
||||
"ffmpeg-static": "^5.2.0",
|
||||
"firebase-admin": "^12.7.0",
|
||||
"firebase-functions": "^6.4.0",
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
const { onDocumentCreated } = require("firebase-functions/v2/firestore");
|
||||
const admin = require("firebase-admin");
|
||||
const { refList, ALERT_TYPE } = require("../index");
|
||||
const { Expo } = require("expo-server-sdk");
|
||||
|
||||
// Initialisation de Expo SDK
|
||||
let expo = new Expo();
|
||||
const db = admin.firestore();
|
||||
|
||||
exports.sendNotificationWhenDocIsCreated = onDocumentCreated(
|
||||
{ region: "europe-west1", document: "notifications/{notificationId}" },
|
||||
async (event) => {
|
||||
try {
|
||||
const {
|
||||
receiver = null,
|
||||
title = "MusicLand",
|
||||
receiverCollection = "users",
|
||||
message = "",
|
||||
data: notifData = {},
|
||||
} = event.data.data();
|
||||
|
||||
const { pushToken = null } =
|
||||
(await db.collection(receiverCollection).doc(receiver).get())?.data() ||
|
||||
{};
|
||||
|
||||
if (!receiver || !message) {
|
||||
throw new Error("Receiver and message are required");
|
||||
}
|
||||
|
||||
if (pushToken) {
|
||||
await sendExpoNotification(pushToken, {
|
||||
title: title || "MusicLand",
|
||||
message: message,
|
||||
data: notifData || {},
|
||||
});
|
||||
} else {
|
||||
console.warn("User push token not found");
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Fonction pour envoyer la notification via Expo SDK
|
||||
async function sendExpoNotification(
|
||||
pushToken,
|
||||
{ title = "", message = "", data = {} }
|
||||
) {
|
||||
try {
|
||||
if (!Expo.isExpoPushToken(pushToken)) {
|
||||
throw new Error(`Invalid push token: ${pushToken}`);
|
||||
} else {
|
||||
console.log("Valid push token:", pushToken);
|
||||
}
|
||||
|
||||
const receipts = await expo.sendPushNotificationsAsync([
|
||||
{
|
||||
to: pushToken,
|
||||
sound: "default",
|
||||
title: title,
|
||||
body: message,
|
||||
data: data || {},
|
||||
priority: "high",
|
||||
badge: 1,
|
||||
channelId: "default",
|
||||
},
|
||||
]);
|
||||
console.log("Sent push notifications:", receipts);
|
||||
|
||||
return { sent: true };
|
||||
} catch (e) {
|
||||
console.log("Error sending notification:", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// Fonction pour ajouter une notification à la base de données
|
||||
const sendNotification = async ({
|
||||
sender = "SYSTEM",
|
||||
receiver = null,
|
||||
receiverCollection = "users",
|
||||
title = "",
|
||||
message = null,
|
||||
data = {},
|
||||
}) => {
|
||||
try {
|
||||
if (!receiver || !message) {
|
||||
throw new Error("Receiver and message are required");
|
||||
}
|
||||
const { id } = await refList.notifications.add({
|
||||
sender,
|
||||
receiver,
|
||||
receiverCollection,
|
||||
title,
|
||||
message,
|
||||
time: new Date(),
|
||||
data,
|
||||
});
|
||||
console.log(`Notification ${id} created`);
|
||||
|
||||
return id;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
exports.sendNotification = sendNotification;
|
||||
|
||||
exports.createProjectCommentNotification = onDocumentCreated(
|
||||
{
|
||||
region: "europe-west1",
|
||||
document: "projects/{projectId}/comments/{commentId}",
|
||||
},
|
||||
async (event) => {
|
||||
try {
|
||||
console.log(
|
||||
"[createProjectCommentNotification] Trigger received",
|
||||
JSON.stringify(event.params || {}, null, 2)
|
||||
);
|
||||
const { data: snap } = event;
|
||||
const { projectId, commentId } = event.params || {};
|
||||
const comment = snap?.data();
|
||||
|
||||
if (!projectId || !comment) {
|
||||
console.log(
|
||||
"[createProjectCommentNotification] Missing project/comment data",
|
||||
{ hasProjectId: !!projectId, hasComment: !!comment }
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log(
|
||||
"[createProjectCommentNotification] Comment payload",
|
||||
JSON.stringify(comment, null, 2)
|
||||
);
|
||||
|
||||
const projectSnap = await refList.projects.doc(projectId).get();
|
||||
if (!projectSnap.exists) {
|
||||
console.log(
|
||||
"[createProjectCommentNotification] Project not found",
|
||||
projectId
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const project = projectSnap.data() || {};
|
||||
const receiver = project.userId || null;
|
||||
|
||||
if (!receiver || receiver === comment.userId) {
|
||||
console.log(
|
||||
"[createProjectCommentNotification] Invalid receiver",
|
||||
JSON.stringify({ receiver, commentUserId: comment.userId })
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
const commenterName =
|
||||
typeof comment?.userName === "string" && comment.userName.trim()
|
||||
? comment.userName.trim()
|
||||
: "Un utilisateur";
|
||||
const projectTitle =
|
||||
typeof project.title === "string" && project.title.trim()
|
||||
? project.title.trim()
|
||||
: "ton projet";
|
||||
const message = `${commenterName} a commenté ton projet "${projectTitle}"`;
|
||||
|
||||
console.log(
|
||||
"[createProjectCommentNotification] Creating notification",
|
||||
JSON.stringify(
|
||||
{
|
||||
receiver,
|
||||
message,
|
||||
commentId,
|
||||
projectId,
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
|
||||
await sendNotification({
|
||||
sender: comment.userId || "SYSTEM",
|
||||
receiver,
|
||||
receiverCollection: "users",
|
||||
title: "Nouveau commentaire",
|
||||
message,
|
||||
data: {
|
||||
type: ALERT_TYPE?.NEW_COMMENT,
|
||||
projectId,
|
||||
commentId,
|
||||
commenterId: comment.userId || null,
|
||||
commenterName: commenterName,
|
||||
commenterProfilePicture: comment?.profilePicture || "",
|
||||
text:
|
||||
typeof comment?.text === "string" && comment.text.trim()
|
||||
? comment.text.trim()
|
||||
: "",
|
||||
},
|
||||
});
|
||||
|
||||
console.log(
|
||||
"[createProjectCommentNotification] Notification creation complete"
|
||||
);
|
||||
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.log("createProjectCommentNotification error:", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
);
|
||||
Reference in New Issue
Block a user