Notifications
This commit is contained in:
125
notifications.js
125
notifications.js
@@ -1,5 +1,84 @@
|
||||
const nodemailer = require("nodemailer");
|
||||
const DBGetter = require("./mongoDB.js");
|
||||
const { Expo } = require('expo-server-sdk');
|
||||
|
||||
|
||||
const sendPushNotification = async (profileToken, body, data) => {
|
||||
if(!profileToken) return 0;
|
||||
let expo = new Expo();
|
||||
|
||||
// Create the messages that you want to send to clients
|
||||
let messages = [];
|
||||
let pushToken = profileToken;
|
||||
if (!Expo.isExpoPushToken(pushToken)) {
|
||||
console.error(`Push token ${pushToken} is not a valid Expo push token`);
|
||||
return 0;
|
||||
}
|
||||
// Construct a message (see https://docs.expo.io/push-notifications/sending-notifications/)
|
||||
messages.push({
|
||||
to: pushToken,
|
||||
sound: 'default',
|
||||
body: body,
|
||||
data: data,
|
||||
})
|
||||
let chunks = expo.chunkPushNotifications(messages);
|
||||
let tickets = [];
|
||||
(async () => {
|
||||
for (let chunk of chunks) {
|
||||
try {
|
||||
let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
|
||||
console.log(ticketChunk);
|
||||
tickets.push(...ticketChunk);
|
||||
// NOTE: If a ticket contains an error code in ticket.details.error, you
|
||||
// must handle it appropriately. The error codes are listed in the Expo
|
||||
// documentation:
|
||||
// https://docs.expo.io/push-notifications/sending-notifications/#individual-errors
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
let receiptIds = [];
|
||||
for (let ticket of tickets) {
|
||||
// NOTE: Not all tickets have IDs; for example, tickets for notifications
|
||||
// that could not be enqueued will have error information and no receipt ID.
|
||||
if (ticket.id) {
|
||||
receiptIds.push(ticket.id);
|
||||
}
|
||||
}
|
||||
|
||||
let receiptIdChunks = expo.chunkPushNotificationReceiptIds(receiptIds);
|
||||
(async () => {
|
||||
for (let chunk of receiptIdChunks) {
|
||||
try {
|
||||
let receipts = await expo.getPushNotificationReceiptsAsync(chunk);
|
||||
console.log(receipts);
|
||||
|
||||
// The receipts specify whether Apple or Google successfully received the
|
||||
// notification and information about an error, if one occurred.
|
||||
for (let receiptId in receipts) {
|
||||
let { status, message, details } = receipts[receiptId];
|
||||
if (status === 'ok') {
|
||||
continue;
|
||||
} else if (status === 'error') {
|
||||
console.error(
|
||||
`There was an error sending a notification: ${message}`
|
||||
);
|
||||
if (details && details.error) {
|
||||
// The error codes are listed in the Expo documentation:
|
||||
// https://docs.expo.io/push-notifications/sending-notifications/#individual-errors
|
||||
// You must handle the errors appropriately.
|
||||
console.error(`The error code is ${details.error}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
const sendEmail = async (to, subject, html) => {
|
||||
let transporter = nodemailer.createTransport({
|
||||
@@ -18,7 +97,7 @@ const sendEmail = async (to, subject, html) => {
|
||||
subject,
|
||||
html,
|
||||
}).catch(console.error);
|
||||
if(info && info.messageId) console.log("Email sent: %s", info.messageId);
|
||||
if (info && info.messageId) console.log("Email sent: %s", info.messageId);
|
||||
};
|
||||
|
||||
const yourBookmarkedPostGotACommentTemplate = (post, userEmail, postProfile, senderProfile, bookedProfile, message) => {
|
||||
@@ -151,32 +230,32 @@ const yourGroupHasARequestTemplate = (groupProfile, ownerEmail, senderProfile) =
|
||||
sendEmail(ownerEmail, subject, html)
|
||||
}
|
||||
|
||||
const convertLinks = ( input ) => {
|
||||
const convertLinks = (input) => {
|
||||
|
||||
let text = input;
|
||||
const linksFound = text.match( /(?:www|https?)[^\s]+/g );
|
||||
const linksFound = text.match(/(?:www|https?)[^\s]+/g);
|
||||
const aLink = [];
|
||||
|
||||
if ( linksFound != null ) {
|
||||
if (linksFound != null) {
|
||||
|
||||
for ( let i=0; i<linksFound.length; i++ ) {
|
||||
for (let i = 0; i < linksFound.length; i++) {
|
||||
let replace = linksFound[i];
|
||||
if ( !( linksFound[i].match( /(http(s?)):\/\// ) ) ) { replace = 'http://' + linksFound[i] }
|
||||
let linkText = replace.split( '/' )[2];
|
||||
if ( linkText.substring( 0, 3 ) == 'www' ) { linkText = linkText.replace( 'www.', '' ) }
|
||||
if ( linkText.match( /youtu/ ) ) {
|
||||
if (!(linksFound[i].match(/(http(s?)):\/\//))) { replace = 'http://' + linksFound[i] }
|
||||
let linkText = replace.split('/')[2];
|
||||
if (linkText.substring(0, 3) == 'www') { linkText = linkText.replace('www.', '') }
|
||||
if (linkText.match(/youtu/)) {
|
||||
|
||||
let youtubeID = replace.split( '/' ).slice(-1)[0];
|
||||
aLink.push( '<div class="video-wrapper"><iframe src="https://www.youtube.com/embed/' + youtubeID + '" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>' )
|
||||
let youtubeID = replace.split('/').slice(-1)[0];
|
||||
aLink.push('<div class="video-wrapper"><iframe src="https://www.youtube.com/embed/' + youtubeID + '" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></div>')
|
||||
}
|
||||
else if ( linkText.match( /vimeo/ ) ) {
|
||||
let vimeoID = replace.split( '/' ).slice(-1)[0];
|
||||
aLink.push( '<div class="video-wrapper"><iframe src="https://player.vimeo.com/video/' + vimeoID + '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>' )
|
||||
else if (linkText.match(/vimeo/)) {
|
||||
let vimeoID = replace.split('/').slice(-1)[0];
|
||||
aLink.push('<div class="video-wrapper"><iframe src="https://player.vimeo.com/video/' + vimeoID + '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>')
|
||||
}
|
||||
else {
|
||||
aLink.push( '<a href="' + replace + '" target="_blank">' + linkText + '</a>' );
|
||||
aLink.push('<a href="' + replace + '" target="_blank">' + linkText + '</a>');
|
||||
}
|
||||
text = text.split( linksFound[i] ).map(item => { return aLink[i].includes('iframe') ? item.trim() : item } ).join( aLink[i] );
|
||||
text = text.split(linksFound[i]).map(item => { return aLink[i].includes('iframe') ? item.trim() : item }).join(aLink[i]);
|
||||
}
|
||||
return text;
|
||||
|
||||
@@ -203,7 +282,7 @@ const broadcastNews = async (post, users) => {
|
||||
|
||||
<p>Blessings</p>
|
||||
`;
|
||||
|
||||
|
||||
for (const user of users) {
|
||||
console.log(user, 'Sending news')
|
||||
await sendEmail(user.username, subject, html);
|
||||
@@ -226,6 +305,7 @@ const Notifications = {
|
||||
const bookedProfile = subscribed[index];
|
||||
if (bookedProfile._id == senderProfile._id) return 0;
|
||||
const notifBody = `${senderProfile.profile.firstName} commented in a post you follow`;
|
||||
sendPushNotification(bookedProfile.token, notifBody, {});
|
||||
DB.addNotification(bookedProfile._id, notifBody, post._id, post.comments.length - 1);
|
||||
yourBookmarkedPostGotACommentTemplate(post, userEmail, postProfile, senderProfile, bookedProfile, message);
|
||||
});
|
||||
@@ -241,6 +321,7 @@ const Notifications = {
|
||||
}
|
||||
if (postProfile.isCourse || senderProfile._id == postProfile._id) return 0; //Course owners do not need to receive notifs
|
||||
const notifBody = `${senderProfile.profile.firstName} commented in your post`;
|
||||
sendPushNotification(postProfile.token, notifBody, {});
|
||||
DB.addNotification(post.profileid, notifBody, postId, post.comments.length - 1);
|
||||
return youGotANewPostCommentTemplate(post, userEmail, postProfile, senderProfile, message);
|
||||
},
|
||||
@@ -258,32 +339,34 @@ const Notifications = {
|
||||
let userProfile = subscribed[index]; //who is this email sending to
|
||||
if (userProfile._id == senderProfile._id) return 0; //avoid sending self notifications
|
||||
const notifBody = `${senderProfile.profile.firstName} post in the group ${groupProfile.profile.firstName} ${groupProfile.profile.lastName}`;
|
||||
sendPushNotification(userProfile.token, notifBody, {});
|
||||
DB.addNotification(userProfile._id, notifBody, post._id);
|
||||
yourGroupGotANewPostTemplate(groupProfile, userEmail, userProfile, senderProfile, message);
|
||||
});
|
||||
},
|
||||
async youGotANewPost(post) {
|
||||
const toProfileId = post.toProfile;
|
||||
const toProfileId = post.toProfile;
|
||||
const whoPostedId = post.profileid;
|
||||
const message = post.content;
|
||||
const DB = await DBGetter.getDB;
|
||||
const profile = await DB.getProfileCache(toProfileId);
|
||||
const user = await DB.getUserById(profile.userid);
|
||||
const senderProfile = await DB.getProfileCache(whoPostedId);
|
||||
if(profile.isGroup) {
|
||||
if (profile.isGroup) {
|
||||
return this.yourGroupGotANewPost(profile, senderProfile, message, post);
|
||||
}
|
||||
if(post.nonOrganicType == 'News'){
|
||||
if (post.nonOrganicType == 'News') {
|
||||
const emails = await DB.getAllEmails();
|
||||
return this.broadcastNews(post, emails);
|
||||
}
|
||||
const notifBody = `${senderProfile.profile.firstName} post in your profile`;
|
||||
sendPushNotification(profile.token, notifBody, {});
|
||||
DB.addNotification(toProfileId, notifBody, post._id);
|
||||
return youGotANewPostTemplate(profile, user.username, senderProfile, message);
|
||||
},
|
||||
youHaveAnInvitation,
|
||||
broadcastNews,
|
||||
async yourGroupHasARequest(requesterProfileId, groupId){
|
||||
async yourGroupHasARequest(requesterProfileId, groupId) {
|
||||
const DB = await DBGetter.getDB;
|
||||
const requesterProfile = await DB.getProfileCache(requesterProfileId);
|
||||
const groupProfile = await DB.getProfileCache(groupId);
|
||||
|
||||
29
package-lock.json
generated
29
package-lock.json
generated
@@ -14,6 +14,7 @@
|
||||
"cookie-parser": "^1.4.5",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^8.2.0",
|
||||
"expo-server-sdk": "^3.6.0",
|
||||
"express": "^4.17.1",
|
||||
"mongodb": "^3.6.3",
|
||||
"nodemailer": "^6.6.3",
|
||||
@@ -378,6 +379,15 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-server-sdk": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/expo-server-sdk/-/expo-server-sdk-3.6.0.tgz",
|
||||
"integrity": "sha512-GyA0BTcFBKk/5gTEO4WOScP9hEttR+GitrcOIl7XwXwE1FHFvbluKiUc9yEjsfEYMgyd78+XhSpGVGQnutGOdA==",
|
||||
"dependencies": {
|
||||
"node-fetch": "^2.6.0",
|
||||
"promise-limit": "^2.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
|
||||
@@ -973,6 +983,11 @@
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||
},
|
||||
"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=="
|
||||
},
|
||||
"node_modules/proper-lockfile": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-2.0.1.tgz",
|
||||
@@ -1627,6 +1642,15 @@
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
|
||||
},
|
||||
"expo-server-sdk": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/expo-server-sdk/-/expo-server-sdk-3.6.0.tgz",
|
||||
"integrity": "sha512-GyA0BTcFBKk/5gTEO4WOScP9hEttR+GitrcOIl7XwXwE1FHFvbluKiUc9yEjsfEYMgyd78+XhSpGVGQnutGOdA==",
|
||||
"requires": {
|
||||
"node-fetch": "^2.6.0",
|
||||
"promise-limit": "^2.7.0"
|
||||
}
|
||||
},
|
||||
"express": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
|
||||
@@ -2079,6 +2103,11 @@
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||
},
|
||||
"promise-limit": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/promise-limit/-/promise-limit-2.7.0.tgz",
|
||||
"integrity": "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="
|
||||
},
|
||||
"proper-lockfile": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-2.0.1.tgz",
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"cookie-parser": "^1.4.5",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^8.2.0",
|
||||
"expo-server-sdk": "^3.6.0",
|
||||
"express": "^4.17.1",
|
||||
"mongodb": "^3.6.3",
|
||||
"nodemailer": "^6.6.3",
|
||||
|
||||
Reference in New Issue
Block a user