Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 81 additions & 34 deletions functions/upcomingRoom-Message-Notification/src/main.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,108 @@
const sdk = require("node-appwrite");

const admin = require('firebase-admin');
const { getMessaging } = require('firebase-admin/messaging');
const serviceAccount = require("./resonate-service-account.json");

const app = admin.initializeApp({
credential: admin.credential.cert(serviceAccount)
});

module.exports = async function ({ req, res, log, error }) {
var subscribersTokens = [];
const subscribersTokens = [];
const client = new sdk.Client();
const database = new sdk.Databases(client);
const query = sdk.Query;
const { roomId, payload } = JSON.parse(req.body);

client.setEndpoint(
process.env.APPWRITE_ENDPOINT ?? 'https://cloud.appwrite.io/v1'
)
.setProject(process.env.APPWRITE_FUNCTION_PROJECT_ID)
.setKey(process.env.APPWRITE_API_KEY);
log(process.env.APPWRITE_FUNCTION_PROJECT_ID);

log("Send Notification");
log(roomId);
log(payload);
let subscriberList = await database.listDocuments(process.env.UpcomingRoomsDataBaseID, process.env.SubscriberCollectionID, [query.equal('upcomingRoomId', [roomId])]);
log("here as well")
subscriberList.documents.forEach(subscriber => {
for (const token of subscriber["registrationTokens"]) {
subscribersTokens.push(token);

try {
const body = typeof req.body === 'string' ? JSON.parse(req.body) : req.body;
if (!roomId || typeof roomId !== 'string') {
log('Invalid roomId: must be a non-empty string');
return res.json({ message: 'Invalid roomId' }, 400);
}
});
let document = await database.getDocument(process.env.UpcomingRoomsDataBaseID, process.env.UpcomingRoomsCollectionID, roomId);
for (const creator_token of document["creator_fcm_tokens"]) {
subscribersTokens.push(creator_token);
}
log(subscribersTokens);
const message = {
notification: payload,
tokens: subscribersTokens,
priority: "high",
android: {
priority: "high"

if (!payload || typeof payload !== 'object' || !payload.title || !payload.body) {
log('Invalid payload: must be an object with title and body');
return res.json({ message: 'Invalid payload' }, 400);
}

if (!roomId || !payload) {
return res.json({
message: 'Missing required fields',
error: 'roomId and payload are required'
}, 400);
}
};
getMessaging(app).sendEachForMulticast(message)
.then((response) => {

log(`Sending notification for room: ${roomId}`);

const subscriberList = await database.listDocuments(
process.env.UpcomingRoomsDataBaseID,
process.env.SubscriberCollectionID,
[query.equal('upcomingRoomId', [roomId])]
);

subscriberList.documents.forEach(subscriber => {
if (subscriber["registrationTokens"] && Array.isArray(subscriber["registrationTokens"])) {
subscribersTokens.push(...subscriber["registrationTokens"]);
}
});

const roomDocument = await database.getDocument(
process.env.UpcomingRoomsDataBaseID,
process.env.UpcomingRoomsCollectionID,
roomId
);

if (roomDocument["creator_fcm_tokens"] && Array.isArray(roomDocument["creator_fcm_tokens"])) {
subscribersTokens.push(...roomDocument["creator_fcm_tokens"]);
}

// Deduplicate and validate tokens (must be non-empty strings)
const uniqueTokens = [...new Set(subscribersTokens)].filter(token => typeof token === 'string' && token.trim().length > 0);

if (uniqueTokens.length > 0) {
const message = {
notification: payload,
tokens: uniqueTokens,
android: {
priority: "high"
},
apns: {
headers: {
"apns-priority": "10"
}
}
};
Comment thread
coderabbitai[bot] marked this conversation as resolved.

const response = await getMessaging(app).sendEachForMulticast(message);
if (response.failureCount > 0) {
log('Failed');
log(`Failed to send ${response.failureCount} notifications`);
response.responses.forEach((resp, idx) => {
if (!resp.success) {
log(`Failure for token ${uniqueTokens[idx]}: ${resp.error}`);
}
});
} else {
log('Notifications were sent successfully');
}
} else {
log('No valid tokens found to send notifications.');
}

return res.json({
message: 'Notification process completed'
});

return res.json({
message: 'Notification sent'
});
} catch (err) {
error(`Error in upcomingRoom-Message-Notification: ${err.message}`);
return res.json({
message: 'Error occurred',
error: err.message
}, 500);
}
}


131 changes: 62 additions & 69 deletions functions/upcomingRoom-isTime-checker/src/main.js
Original file line number Diff line number Diff line change
@@ -1,88 +1,81 @@
const sdk = require("node-appwrite");
// const admin = require('firebase-admin');

const admin = require('firebase-admin');
// const { getMessaging } = require('firebase-admin/messaging');
// const serviceAccount = require("./resonate-service-account.json");
// const app = admin.initializeApp({
// credential: admin.credential.cert(serviceAccount)
// });

module.exports = async function ({ req, res, log }) {
var subscribersTokens = [];
module.exports = async function ({ req, res, log, error }) {
const client = new sdk.Client();
const database = new sdk.Databases(client);
const query = sdk.Query;
log("here");

client.setEndpoint(
process.env.APPWRITE_ENDPOINT ?? 'https://cloud.appwrite.io/v1'
)
.setProject(process.env.APPWRITE_FUNCTION_PROJECT_ID)
.setKey(process.env.APPWRITE_API_KEY);
log(process.env.APPWRITE_FUNCTION_PROJECT_ID);
log("here also");
let upcomingRoomsList = await database.listDocuments(process.env.UpcomingRoomsDataBaseID, process.env.UpcomingRoomsCollectionID);
log("here as well");
for (const document of upcomingRoomsList.documents) {
log("now here");
var scheduledDateTime = document["scheduledDateTime"];
log(scheduledDateTime);
var splittedDateTime = scheduledDateTime.split('T');
var extractedDate = splittedDateTime[0];
var extractedTime = splittedDateTime[1];
var SplittingDate = extractedDate.split("-");
const year = Number(SplittingDate[0]);
const month = Number(SplittingDate[1]);
const day = Number(SplittingDate[2]);
var SplittingTime = extractedTime.split(":");
const hour = Number(SplittingTime[0]);
const minutes = Number(SplittingTime[1]);
const upcomingRoomDate = Date.UTC(year, month - 1, day, hour, minutes);
log(upcomingRoomDate);
const now = new Date();
const nowTime = now.getTime();
log(nowTime);

var timeLeft = upcomingRoomDate - nowTime;
var timeLeftInMinutes = timeLeft / (1000 * 60);
log(timeLeftInMinutes);
if (timeLeftInMinutes <= 5 && timeLeftInMinutes >= -5 && document["isTime"] == false) {
await database.updateDocument(process.env.UpcomingRoomsDataBaseID, process.env.UpcomingRoomsCollectionID, document.$id, {
"isTime": true
})
// log("Send Notification");
// let subscriberList = await database.listDocuments(process.env.UpcomingRoomsDataBaseID, process.env.SubscriberCollectionID, [query.equal('upcomingRoomId', [document.$id])]);
// log("here as well")
// subscriberList.documents.forEach(subscriber => {
// for (const token of subscriber["registrationTokens"]) {
// subscribersTokens.push(token);
// }
// });
// for (const creator_token of document["creator_fcm_tokens"]) {
// subscribersTokens.push(creator_token);
// }
// log(subscribersTokens);
// const message = {
// notification: {
// title: 'Room Reminder',
// body: `The room ${document["name"]} will Start Soon`
// },
// tokens: subscribersTokens,
// priority: "high",
// android: {
// priority: "high"
// }
// };
// getMessaging(app).sendEachForMulticast(message)
// .then((response) => {
// if (response.failureCount > 0) {
// log('Failed');
// } else {
// log('Notifications were sent successfully');
// }
// });
try {
const upcomingRoomsList = await database.listDocuments(
process.env.UpcomingRoomsDataBaseID,
process.env.UpcomingRoomsCollectionID
);

for (const document of upcomingRoomsList.documents) {
const scheduledDateTime = document["scheduledDateTime"];

if (!scheduledDateTime) {
log(`Skipping document ${document.$id}: missing scheduledDateTime`);
continue;
}

// Use standard Date parsing (handles ISO 8601 correctly)
const upcomingRoomDate = new Date(scheduledDateTime).getTime();

if (isNaN(upcomingRoomDate)) {
log(`Skipping document ${document.$id}: invalid date format "${scheduledDateTime}"`);
continue;
}

const nowTime = new Date().getTime();
Comment thread
coderabbitai[bot] marked this conversation as resolved.

const timeLeft = upcomingRoomDate - nowTime;
const timeLeftInMinutes = timeLeft / (1000 * 60);

// Check if time is within +/- 5 minutes and not yet marked
if (timeLeftInMinutes <= 5 && timeLeftInMinutes >= -5 && document["isTime"] === false) {
await database.updateDocument(
process.env.UpcomingRoomsDataBaseID,
process.env.UpcomingRoomsCollectionID,
document.$id,
{
"isTime": true
}
);

// Log explicitly when an action is taken
log(`Activated room: ${document.$id}`);

/*
// Notification logic (legacy)
var subscribersTokens = [];
// ... (rest of the commented notification logic kept if needed for reference,
// essentially user logic seems to be to keep it commented for now as they didn't ask to implement it)
*/
}
}

return res.json({
message: 'Time check completed successfully'
});

} catch (err) {
error(`Error in upcomingRoom-isTime-checker: ${err.message}`);
return res.json({
message: 'Error occurred during time check',
error: err.message
}, 500);
}
return res.json({
message: 'set verified'
});
};