Bunch small things: Notifs for react, subsplash...

This commit is contained in:
aeroreyna
2022-12-28 22:54:19 -05:00
parent 6b6f263821
commit 1f3cc06470
10 changed files with 686 additions and 295 deletions

103
dbTools/logger.js Normal file
View File

@@ -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;

View File

@@ -216,9 +216,10 @@ userDB = (DB) => {
}
DB.setProfileToken = (profileid, token)=>{
if(!token) return false;
const _id = DB.ObjectID(profileid);
let update = {
$set:{
$addToSet:{
token
}
}

View File

@@ -14,6 +14,8 @@ class Post {
// Any reaction or comment updates this ts,
// this will be used as index to query new posts
this.lastUpdated = info.lastUpdated || this.createdAt;
// Add tags to posts
this.tags = info.tags;
}
addComment(comment){
@@ -43,6 +45,7 @@ class Post {
r.contentHistory = this.contentHistory;
r.lastUpdated = this.lastUpdated;
r.toProfile = this.toProfile;
r.tags = this.tags;
return r;
}
}

View File

@@ -18,6 +18,7 @@ var corsOptions = {
origin: ['http://localhost:8080', "https://social.emmint.com"],
credentials: true
};
app.use(cors(corsOptions));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
@@ -47,9 +48,11 @@ const Profile = require("./def/profile.js");
const profileRoute = require('./routes/profile.js');
const postRoute = require('./routes/post.js');
const paymentsRoute = require('./routes/payments.js');
const subsplashRoute = require('./routes/subsplash.js');
DB.getDB.then((DB) => {
app.use(DB.logger)
// middleware function to check for logged-in users
const sessionChecker = async (req, res, next) => {
@@ -249,10 +252,14 @@ DB.getDB.then((DB) => {
return logout(req, res);
});
//Private Routes
app.use('/user', sessionChecker, profileRoute);
app.use('/post', sessionChecker, postRoute);
app.use('/payments', sessionChecker, paymentsRoute);
//Public Routes
app.use('/subsplash', subsplashRoute);
// route for handling 404 requests(unavailable routes)
app.use(function (req, res, next) {
res.status(404).send("Sorry can't find that!")

View File

@@ -5,7 +5,8 @@ const DBName = "EMI_SOCIAL";
const mongoUrl = process.env.MONGO_URL;
const postDB = require("./dbTools/post.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) => {
@@ -114,6 +115,7 @@ const getDB = new Promise((resolve, reject) => {
postDB(DB);
profileDB(DB);
paymentDB(DB);
loggerDB(DB);
resolve(DB);
});

View File

@@ -15,13 +15,19 @@ 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`);
if(!Array.isArray(profileToken)) return 0;
let pushTokens = [];
profileToken.forEach((token) => {
if (!Expo.isExpoPushToken(token)) {
console.error(`Push token ${token} is not a valid Expo push token`);
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/)
messages.push({
to: pushToken,
@@ -348,6 +354,34 @@ const Notifications = {
DB.addNotification(post.profileid, notifBody, postId, post.comments.length - 1, senderProfile._id);
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) {
const DB = await DBGetter.getDB;
let subscribedPromise = Object.keys(groupProfile.subscribed).map((profileid) => {
@@ -384,7 +418,7 @@ const Notifications = {
}
const notifBody = `${senderProfile.profile.firstName} post in your profile`;
sendPushNotification(profile.token, notifBody, {});
sendWebNotification(profile.webSubscription, notifBody, message)
sendWebNotification(profile.webSubscription, notifBody, message);
DB.addNotification(toProfileId, notifBody, post._id, null, senderProfile._id);
return youGotANewPostTemplate(profile, user.username, senderProfile, message);
},
@@ -396,14 +430,22 @@ const Notifications = {
const groupProfile = await DB.getProfileCache(groupId);
const user = await DB.getUserById(groupProfile.userid);
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) {
const DB = await DBGetter.getDB;
const requesterProfile = await DB.getProfileCache(requesterProfileId);
const groupProfile = await DB.getProfileCache(groupId);
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

716
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,8 +10,10 @@
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.1.3",
"bcrypt": "^5.0.0",
"body-parser": "^1.19.0",
"cheerio": "^1.0.0-rc.12",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
@@ -19,6 +21,7 @@
"express": "^4.17.1",
"mongodb": "^3.6.3",
"nodemailer": "^6.6.3",
"object-hash": "^3.0.0",
"stripe": "^8.178.0",
"web-push": "^3.4.5"
}

View File

@@ -142,6 +142,7 @@ DB.getDB.then((DB) => {
createdAt: new Date()
};
r = await DB.newReaction(postid, profileid, reaction);
Notifications.youGotANewReaction(postid, profileid, 'like');
return res.json({
status: "ok"
});

83
routes/subsplash.js Normal file
View File

@@ -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