Bunch small things: Notifs for react, subsplash...
This commit is contained in:
@@ -0,0 +1,103 @@
|
|||||||
|
const hash = require('object-hash');
|
||||||
|
const DBName = "EMI_SOCIAL";
|
||||||
|
|
||||||
|
postDB = (DB) => {
|
||||||
|
DB.pathLogs = DB.db.db(DBName).collection("pathLogs");
|
||||||
|
DB.profileLogs = DB.db.db(DBName).collection("profileLogs");
|
||||||
|
|
||||||
|
let loggerPathData = {};
|
||||||
|
let loggerProfileData = {};
|
||||||
|
DB.logger = async (req, res, next) => {
|
||||||
|
// hash should not include query parameters
|
||||||
|
let hashIndx = hash(req.url.split('/'));
|
||||||
|
// Log url based
|
||||||
|
if (!loggerPathData[hashIndx]) {
|
||||||
|
loggerPathData[hashIndx] = {
|
||||||
|
url: req.url,
|
||||||
|
urlParts: req.url.split('/'),
|
||||||
|
count: 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loggerPathData[hashIndx].count++;
|
||||||
|
}
|
||||||
|
// Log user based
|
||||||
|
let profile_id = req.cookies?.profile_id;
|
||||||
|
if (!profile_id) return next();
|
||||||
|
if (!loggerProfileData[profile_id]) {
|
||||||
|
loggerProfileData[profile_id] = {}
|
||||||
|
}
|
||||||
|
if (!loggerProfileData[profile_id][hashIndx]) {
|
||||||
|
loggerProfileData[profile_id][hashIndx] = {
|
||||||
|
url: req.url,
|
||||||
|
urlParts: req.url.split('/'),
|
||||||
|
count: 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loggerProfileData[profile_id][hashIndx].count++;
|
||||||
|
}
|
||||||
|
//console.log(loggerData);
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Update counters in DB
|
||||||
|
setInterval(async () => {
|
||||||
|
// Restart global counters
|
||||||
|
let localPathData = loggerPathData;
|
||||||
|
loggerPathData = {};
|
||||||
|
let localProfileData = loggerProfileData;
|
||||||
|
loggerProfileData = {};
|
||||||
|
return 0;
|
||||||
|
console.log('updating', localPathData);
|
||||||
|
Object.keys(localPathData).forEach(key => {
|
||||||
|
DB.pathLogs.findOne({ hash: key }).then(async (doc) => {
|
||||||
|
if (doc) {
|
||||||
|
//Update
|
||||||
|
const update = {
|
||||||
|
$inc: {
|
||||||
|
count: localPathData[key].count
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log('updating one ' + key)
|
||||||
|
await DB.pathLogs.updateOne({ hash: key }, update);
|
||||||
|
} else {
|
||||||
|
//Insert
|
||||||
|
const update = localPathData[key];
|
||||||
|
update.hash = key;
|
||||||
|
console.log('inserting one ' + key)
|
||||||
|
await DB.pathLogs.insertOne(update);
|
||||||
|
}
|
||||||
|
}).catch(console.error);
|
||||||
|
});
|
||||||
|
//DB.pathLogs.
|
||||||
|
Object.keys(localProfileData).forEach(key => {
|
||||||
|
DB.profileLogs.findOne({profile_id: key}).then(async (doc) => {
|
||||||
|
if (doc) {
|
||||||
|
//Update for user log
|
||||||
|
const update = {
|
||||||
|
$inc: {
|
||||||
|
//count: localPathData[key].count
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loggerProfileData[key].forEach((hashIndx)=>{
|
||||||
|
//each hash has its counter.
|
||||||
|
update.$inc['hashIndx'] = {
|
||||||
|
count: loggerProfileData[key]['hashIndx'].count
|
||||||
|
};
|
||||||
|
});
|
||||||
|
console.log('updating one user' + key)
|
||||||
|
await DB.profileLogs.updateOne({ profile_id: key }, update);
|
||||||
|
} else {
|
||||||
|
//Insert
|
||||||
|
const update = loggerProfileData[key];
|
||||||
|
update.profile_id = key;
|
||||||
|
console.log('inserting one user' + key)
|
||||||
|
await DB.profileLogs.insertOne(update);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}, 1000 * 60 * 1); //Each 10 mins
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = postDB;
|
||||||
+2
-1
@@ -216,9 +216,10 @@ userDB = (DB) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DB.setProfileToken = (profileid, token)=>{
|
DB.setProfileToken = (profileid, token)=>{
|
||||||
|
if(!token) return false;
|
||||||
const _id = DB.ObjectID(profileid);
|
const _id = DB.ObjectID(profileid);
|
||||||
let update = {
|
let update = {
|
||||||
$set:{
|
$addToSet:{
|
||||||
token
|
token
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ class Post {
|
|||||||
// Any reaction or comment updates this ts,
|
// Any reaction or comment updates this ts,
|
||||||
// this will be used as index to query new posts
|
// this will be used as index to query new posts
|
||||||
this.lastUpdated = info.lastUpdated || this.createdAt;
|
this.lastUpdated = info.lastUpdated || this.createdAt;
|
||||||
|
// Add tags to posts
|
||||||
|
this.tags = info.tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
addComment(comment){
|
addComment(comment){
|
||||||
@@ -43,6 +45,7 @@ class Post {
|
|||||||
r.contentHistory = this.contentHistory;
|
r.contentHistory = this.contentHistory;
|
||||||
r.lastUpdated = this.lastUpdated;
|
r.lastUpdated = this.lastUpdated;
|
||||||
r.toProfile = this.toProfile;
|
r.toProfile = this.toProfile;
|
||||||
|
r.tags = this.tags;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ var corsOptions = {
|
|||||||
origin: ['http://localhost:8080', "https://social.emmint.com"],
|
origin: ['http://localhost:8080', "https://social.emmint.com"],
|
||||||
credentials: true
|
credentials: true
|
||||||
};
|
};
|
||||||
|
|
||||||
app.use(cors(corsOptions));
|
app.use(cors(corsOptions));
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.urlencoded({ extended: true }));
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
@@ -47,9 +48,11 @@ const Profile = require("./def/profile.js");
|
|||||||
const profileRoute = require('./routes/profile.js');
|
const profileRoute = require('./routes/profile.js');
|
||||||
const postRoute = require('./routes/post.js');
|
const postRoute = require('./routes/post.js');
|
||||||
const paymentsRoute = require('./routes/payments.js');
|
const paymentsRoute = require('./routes/payments.js');
|
||||||
|
const subsplashRoute = require('./routes/subsplash.js');
|
||||||
|
|
||||||
|
|
||||||
DB.getDB.then((DB) => {
|
DB.getDB.then((DB) => {
|
||||||
|
app.use(DB.logger)
|
||||||
|
|
||||||
// middleware function to check for logged-in users
|
// middleware function to check for logged-in users
|
||||||
const sessionChecker = async (req, res, next) => {
|
const sessionChecker = async (req, res, next) => {
|
||||||
@@ -249,10 +252,14 @@ DB.getDB.then((DB) => {
|
|||||||
return logout(req, res);
|
return logout(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Private Routes
|
||||||
app.use('/user', sessionChecker, profileRoute);
|
app.use('/user', sessionChecker, profileRoute);
|
||||||
app.use('/post', sessionChecker, postRoute);
|
app.use('/post', sessionChecker, postRoute);
|
||||||
app.use('/payments', sessionChecker, paymentsRoute);
|
app.use('/payments', sessionChecker, paymentsRoute);
|
||||||
|
|
||||||
|
//Public Routes
|
||||||
|
app.use('/subsplash', subsplashRoute);
|
||||||
|
|
||||||
// route for handling 404 requests(unavailable routes)
|
// route for handling 404 requests(unavailable routes)
|
||||||
app.use(function (req, res, next) {
|
app.use(function (req, res, next) {
|
||||||
res.status(404).send("Sorry can't find that!")
|
res.status(404).send("Sorry can't find that!")
|
||||||
|
|||||||
+3
-1
@@ -5,7 +5,8 @@ const DBName = "EMI_SOCIAL";
|
|||||||
const mongoUrl = process.env.MONGO_URL;
|
const mongoUrl = process.env.MONGO_URL;
|
||||||
const postDB = require("./dbTools/post.js");
|
const postDB = require("./dbTools/post.js");
|
||||||
const profileDB = require("./dbTools/profile.js");
|
const profileDB = require("./dbTools/profile.js");
|
||||||
const paymentDB = require("./dbTools/payments.js")
|
const paymentDB = require("./dbTools/payments.js");
|
||||||
|
const loggerDB = require("./dbTools/logger.js");
|
||||||
|
|
||||||
|
|
||||||
const getDB = new Promise((resolve, reject) => {
|
const getDB = new Promise((resolve, reject) => {
|
||||||
@@ -114,6 +115,7 @@ const getDB = new Promise((resolve, reject) => {
|
|||||||
postDB(DB);
|
postDB(DB);
|
||||||
profileDB(DB);
|
profileDB(DB);
|
||||||
paymentDB(DB);
|
paymentDB(DB);
|
||||||
|
loggerDB(DB);
|
||||||
|
|
||||||
resolve(DB);
|
resolve(DB);
|
||||||
});
|
});
|
||||||
|
|||||||
+50
-8
@@ -15,13 +15,19 @@ const sendPushNotification = async (profileToken, body, data) => {
|
|||||||
if (!profileToken) return 0;
|
if (!profileToken) return 0;
|
||||||
let expo = new Expo();
|
let expo = new Expo();
|
||||||
|
|
||||||
// Create the messages that you want to send to clients
|
|
||||||
let messages = [];
|
if(!Array.isArray(profileToken)) return 0;
|
||||||
let pushToken = profileToken;
|
let pushTokens = [];
|
||||||
if (!Expo.isExpoPushToken(pushToken)) {
|
profileToken.forEach((token) => {
|
||||||
console.error(`Push token ${pushToken} is not a valid Expo push token`);
|
if (!Expo.isExpoPushToken(token)) {
|
||||||
|
console.error(`Push token ${token} is not a valid Expo push token`);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
pushTokens.push(token);
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create the messages that you want to send to clients
|
||||||
|
let messages = [];
|
||||||
// Construct a message (see https://docs.expo.io/push-notifications/sending-notifications/)
|
// Construct a message (see https://docs.expo.io/push-notifications/sending-notifications/)
|
||||||
messages.push({
|
messages.push({
|
||||||
to: pushToken,
|
to: pushToken,
|
||||||
@@ -348,6 +354,34 @@ const Notifications = {
|
|||||||
DB.addNotification(post.profileid, notifBody, postId, post.comments.length - 1, senderProfile._id);
|
DB.addNotification(post.profileid, notifBody, postId, post.comments.length - 1, senderProfile._id);
|
||||||
return youGotANewPostCommentTemplate(post, userEmail, postProfile, senderProfile, message);
|
return youGotANewPostCommentTemplate(post, userEmail, postProfile, senderProfile, message);
|
||||||
},
|
},
|
||||||
|
async yourBookmarkedPostGotAReactiom(post, postProfile, senderProfile) {
|
||||||
|
const DB = await DBGetter.getDB;
|
||||||
|
const subscribedPromise = post.bookmarks.map((profileid) => {
|
||||||
|
return DB.getProfileCache(profileid);
|
||||||
|
});
|
||||||
|
const subscribed = await Promise.all(subscribedPromise);
|
||||||
|
subscribed.forEach((bookedProfile) => {
|
||||||
|
if (bookedProfile._id == senderProfile._id) return 0;
|
||||||
|
const notifBody = `${senderProfile.profile.firstName} liked a post you follow`;
|
||||||
|
sendPushNotification(bookedProfile.token, notifBody, {});
|
||||||
|
DB.addNotification(bookedProfile._id, notifBody, post._id, null, senderProfile._id);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
async youGotANewReaction(postId, whoReactedId, reactionType){
|
||||||
|
const DB = await DBGetter.getDB;
|
||||||
|
const post = await DB.getPost(postId);
|
||||||
|
const postProfile = await DB.getProfileCache(post.profileid);
|
||||||
|
const senderProfile = await DB.getProfileCache(whoReactedId);
|
||||||
|
const userEmail = await DB.getUsernameByIdCache(postProfile.userid);
|
||||||
|
if (post.bookmarks) {
|
||||||
|
this.yourBookmarkedPostGotAReactiom(post, postProfile, senderProfile)
|
||||||
|
}
|
||||||
|
if (postProfile.isCourse || senderProfile._id == postProfile._id) return 0; //Course owners do not need to receive notifs
|
||||||
|
const notifBody = `${senderProfile.profile.firstName} liked your post`;
|
||||||
|
sendPushNotification(postProfile.token, notifBody, {});
|
||||||
|
DB.addNotification(post.profileid, notifBody, postId, null, senderProfile._id);
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
async yourGroupGotANewPost(groupProfile, senderProfile, message, post) {
|
async yourGroupGotANewPost(groupProfile, senderProfile, message, post) {
|
||||||
const DB = await DBGetter.getDB;
|
const DB = await DBGetter.getDB;
|
||||||
let subscribedPromise = Object.keys(groupProfile.subscribed).map((profileid) => {
|
let subscribedPromise = Object.keys(groupProfile.subscribed).map((profileid) => {
|
||||||
@@ -384,7 +418,7 @@ const Notifications = {
|
|||||||
}
|
}
|
||||||
const notifBody = `${senderProfile.profile.firstName} post in your profile`;
|
const notifBody = `${senderProfile.profile.firstName} post in your profile`;
|
||||||
sendPushNotification(profile.token, notifBody, {});
|
sendPushNotification(profile.token, notifBody, {});
|
||||||
sendWebNotification(profile.webSubscription, notifBody, message)
|
sendWebNotification(profile.webSubscription, notifBody, message);
|
||||||
DB.addNotification(toProfileId, notifBody, post._id, null, senderProfile._id);
|
DB.addNotification(toProfileId, notifBody, post._id, null, senderProfile._id);
|
||||||
return youGotANewPostTemplate(profile, user.username, senderProfile, message);
|
return youGotANewPostTemplate(profile, user.username, senderProfile, message);
|
||||||
},
|
},
|
||||||
@@ -396,14 +430,22 @@ const Notifications = {
|
|||||||
const groupProfile = await DB.getProfileCache(groupId);
|
const groupProfile = await DB.getProfileCache(groupId);
|
||||||
const user = await DB.getUserById(groupProfile.userid);
|
const user = await DB.getUserById(groupProfile.userid);
|
||||||
yourGroupHasARequestTemplate(groupProfile, user.username, requesterProfile)
|
yourGroupHasARequestTemplate(groupProfile, user.username, requesterProfile)
|
||||||
|
const notifBody = `${requesterProfile.profile.firstName} wants to join your group ${groupProfile.profile.firstName} ${groupProfile.profile.lastName}`;
|
||||||
|
//sendPushNotification(profile.token, notifBody, {});
|
||||||
|
//sendWebNotification(profile.webSubscription, notifBody, message);
|
||||||
},
|
},
|
||||||
async yourGroupRequestAccepted(requesterProfileId, groupId) {
|
async yourGroupRequestAccepted(requesterProfileId, groupId) {
|
||||||
const DB = await DBGetter.getDB;
|
const DB = await DBGetter.getDB;
|
||||||
const requesterProfile = await DB.getProfileCache(requesterProfileId);
|
const requesterProfile = await DB.getProfileCache(requesterProfileId);
|
||||||
const groupProfile = await DB.getProfileCache(groupId);
|
const groupProfile = await DB.getProfileCache(groupId);
|
||||||
const user = await DB.getUserById(requesterProfile.userid);
|
const user = await DB.getUserById(requesterProfile.userid);
|
||||||
yourGroupRequestAcceptedTemplate(groupProfile, user.username, requesterProfile)
|
yourGroupRequestAcceptedTemplate(groupProfile, user.username, requesterProfile);
|
||||||
}
|
const notifBody = `You were added to the group ${groupProfile.profile.firstName} ${groupProfile.profile.lastName}`;
|
||||||
|
sendPushNotification(requesterProfile.token, notifBody, {});
|
||||||
|
sendWebNotification(requesterProfile.webSubscription, notifBody);
|
||||||
|
DB.addNotification(requesterProfile, notifBody, null, null, groupProfile._id);
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Notifications
|
module.exports = Notifications
|
||||||
Generated
+431
-285
File diff suppressed because it is too large
Load Diff
@@ -10,8 +10,10 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"axios": "^1.1.3",
|
||||||
"bcrypt": "^5.0.0",
|
"bcrypt": "^5.0.0",
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
|
"cheerio": "^1.0.0-rc.12",
|
||||||
"cookie-parser": "^1.4.5",
|
"cookie-parser": "^1.4.5",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
@@ -19,6 +21,7 @@
|
|||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"mongodb": "^3.6.3",
|
"mongodb": "^3.6.3",
|
||||||
"nodemailer": "^6.6.3",
|
"nodemailer": "^6.6.3",
|
||||||
|
"object-hash": "^3.0.0",
|
||||||
"stripe": "^8.178.0",
|
"stripe": "^8.178.0",
|
||||||
"web-push": "^3.4.5"
|
"web-push": "^3.4.5"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ DB.getDB.then((DB) => {
|
|||||||
createdAt: new Date()
|
createdAt: new Date()
|
||||||
};
|
};
|
||||||
r = await DB.newReaction(postid, profileid, reaction);
|
r = await DB.newReaction(postid, profileid, reaction);
|
||||||
|
Notifications.youGotANewReaction(postid, profileid, 'like');
|
||||||
return res.json({
|
return res.json({
|
||||||
status: "ok"
|
status: "ok"
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
const axios = require('axios');
|
||||||
|
const cheerio = require('cheerio');
|
||||||
|
var express = require('express')
|
||||||
|
var router = express.Router()
|
||||||
|
const DB = require("./../mongoDB.js");
|
||||||
|
|
||||||
|
const fetchAndParse = async (url) => {
|
||||||
|
let detailHtml = await axios.get(url);
|
||||||
|
return cheerio.load(detailHtml.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getDetails = async (event) => {
|
||||||
|
const $ = await fetchAndParse(event.detailPage);
|
||||||
|
let detailsObj = {
|
||||||
|
content: $(".kit-expanding-text-block__text-content").text(),
|
||||||
|
subtitle: $(".route-event__basic-info h3").text(),
|
||||||
|
image: $($('.kit-image__image')[0]).attr('src'),
|
||||||
|
}
|
||||||
|
return detailsObj;
|
||||||
|
};
|
||||||
|
|
||||||
|
//g2cc4gr Florida
|
||||||
|
//vwkqc93 Global
|
||||||
|
const getEvents = async (eventId) => {
|
||||||
|
const $ = await fetchAndParse('https://subsplash.com/+p4y7/lb/ca/+' + eventId + '?embed');
|
||||||
|
let events = $('.kit-list-item');
|
||||||
|
let eventsArr = [];
|
||||||
|
let promises = [];
|
||||||
|
for (let index = 0; index < events.length; index++) {
|
||||||
|
const element = events[index];
|
||||||
|
let event = {}
|
||||||
|
event.title = $(element).find(".kit-list-item__title").text();
|
||||||
|
event.date = $(element).find(".kit-list-item__subtitle").text();
|
||||||
|
event.summary = $(element).find(".kit-list-item__summary").text();
|
||||||
|
event.detailPage = 'https://subsplash.com' + $(element).parent().attr('href');
|
||||||
|
promises.push(getDetails(event).then((r) => {
|
||||||
|
event.details = r;
|
||||||
|
eventsArr.push(event);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
let r = await Promise.all(promises);
|
||||||
|
return eventsArr;
|
||||||
|
};
|
||||||
|
|
||||||
|
//https://subsplash.com/+p4y7/lb/ms/+y42zyf3?embed&1665854077751
|
||||||
|
//https://subsplash.com/+p4y7/embed/mi/+b2zqkyb?audio&video&info&logoWatermark&shareable&embeddable"frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||||
|
//kit-list-item
|
||||||
|
const getMedia = async (eventId) => {
|
||||||
|
const $ = await fetchAndParse('https://subsplash.com/+p4y7/lb/ms/+' + eventId + '?embed&1665854077751');
|
||||||
|
let events = $('.kit-list-item');
|
||||||
|
let eventsArr = [];
|
||||||
|
let promises = [];
|
||||||
|
for (let index = 0; index < events.length; index++) {
|
||||||
|
const element = events[index];
|
||||||
|
let event = {}
|
||||||
|
event.title = $(element).find(".kit-list-item__title").text();
|
||||||
|
event.date = $(element).find(".kit-list-item__subtitle").text();
|
||||||
|
event.summary = $(element).find(".kit-list-item__summary").text();
|
||||||
|
event.detailPage = 'https://subsplash.com' + $(element).find('a').attr('href');
|
||||||
|
promises.push(getDetails(event).then((r) => {
|
||||||
|
event.details = r;
|
||||||
|
eventsArr.push(event);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
let r = await Promise.all(promises);
|
||||||
|
return eventsArr;
|
||||||
|
};
|
||||||
|
|
||||||
|
//getMedia('y42zyf3').then(console.log)
|
||||||
|
DB.getDB.then((DB) => {
|
||||||
|
router.get("/events/:calendarId", async (req, res) => {
|
||||||
|
const events = await getEvents(req.params.calendarId)
|
||||||
|
return res.json(events);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/media/:seriesId", async (req, res) => {
|
||||||
|
const events = await getMedia(req.params.seriesId)
|
||||||
|
return res.json(events);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router
|
||||||
Reference in New Issue
Block a user