Bunch small things: Notifs for react, subsplash...
This commit is contained in:
103
dbTools/logger.js
Normal file
103
dbTools/logger.js
Normal 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;
|
||||
@@ -216,9 +216,10 @@ userDB = (DB) => {
|
||||
}
|
||||
|
||||
DB.setProfileToken = (profileid, token)=>{
|
||||
if(!token) return false;
|
||||
const _id = DB.ObjectID(profileid);
|
||||
let update = {
|
||||
$set:{
|
||||
$addToSet:{
|
||||
token
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
7
index.js
7
index.js
@@ -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!")
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -15,13 +15,19 @@ const sendPushNotification = async (profileToken, body, data) => {
|
||||
if (!profileToken) return 0;
|
||||
let expo = new Expo();
|
||||
|
||||
|
||||
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 = [];
|
||||
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,
|
||||
@@ -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
716
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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
83
routes/subsplash.js
Normal 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
|
||||
Reference in New Issue
Block a user