const mongoose = require('mongoose').set('debug', false); const Schema = mongoose.Schema; mongoose.Promise = global.Promise; mongoose.level = 'F'; const i18n = require('i18n'); const {ObjectID} = require('mongodb'); const shared_consts = require('../tools/shared_nodejs'); const globalTables = require('../tools/globalTables'); const tools = require('../tools/general'); // Resolving error Unknown modifier: $pushAll mongoose.plugin(schema => { schema.options.usePushEach = true; }); const sendNotifSchema = new Schema({ idapp: { type: String, }, typedir: { type: Number, default: 0, }, typeid: { type: Number, default: 0, }, sender: { // mittente type: String, default: '', }, dest: { type: String, default: '', }, title: { type: String, }, descr: { type: String, }, openUrl: { type: String, }, datenotif: { type: Date, }, status: { type: Number, default: 0, }, typesend: { type: Number, }, read: { type: Boolean, default: false, }, tablerec: { type: String, }, idrec: { type: String, }, deleted: { type: Boolean, default: false, }, extrafield: { type: String, }, tag: { type: String, }, options: { type: Array, }, }); sendNotifSchema.statics.setNotifAsRead = function(idapp, username, idnotif) { const SendNotif = this; try { if (idnotif) { return SendNotif.findOneAndUpdate({ $and: [ {idapp}, {dest: username}, {'_id': idnotif}, ], $or: [ {deleted: {$exists: false}}, {deleted: {$exists: true, $eq: false}}], }, {$set: {read: true}}, {new: false}).then((ret) => { return !!ret; }).catch((err) => { console.error('err', err); }); } } catch (e) { return false; } }; sendNotifSchema.statics.findAllNotifByUsernameIdAndIdApp = function(username, lastdataread, idapp) { const SendNotif = this; return SendNotif.find({ $and: [ {idapp}, {'dest': username}, {'datenotif': {$gt: new Date(lastdataread)}}, ], }).lean().sort({datenotif: -1}).then(async (arrnotif) => { // console.log('arrnotif', arrnotif.length); return this.compileOtherFields(arrnotif); }).catch((err) => { console.error('err', err); }); }; sendNotifSchema.statics.getDescrAndLinkByRecNotif = function(recnotif) { const numchars = 80; let newdescr = ''; let mydescr = ''; let myidrec = ''; let userorig = recnotif.sender; let tag = ''; try { if (recnotif.myrectableorig) { myidrec = recnotif.myrectableorig._id; mydescr = recnotif.myrectableorig.descr ? tools.firstchars(recnotif.myrectableorig.descr, numchars) : ''; } if (recnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_BACHECA) { if (recnotif.typeid === shared_consts.TypeNotifs.ID_BACHECA_NEW_GOOD) { newdescr = i18n.__('%s new Good: %s', userorig, mydescr); recnotif.openUrl = '/mygood/' + myidrec; tag = 'newgood'; } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_BACHECA_NEW_SERVICE) { newdescr = i18n.__('%s new Service: %s', userorig, mydescr); recnotif.openUrl = '/myservice/' + myidrec; tag = 'newservice'; } } else if (recnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_FRIENDS) { recnotif.openUrl = '/my/' + userorig; if (recnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_NEW_REC) { newdescr = i18n.__('%s asked you for Friendship', userorig, mydescr); tag = 'newfriend'; } else if ((recnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_ACCEPTED) || (recnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_ACCEPTED_MY_REQUEST)) { newdescr = i18n.__('%s accepted your Friendship', userorig, mydescr); tag = 'acceptedfriend'; } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_REFUSED) { newdescr = i18n.__('%s refused your Friendship', userorig, mydescr); tag = 'refusedfriend'; } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_REPORTED) { tag = 'reportuser'; if (recnotif.paramsObj.usernameDest === recnotif.paramsObj.username_action) { newdescr = i18n.__('FRIEND_REPORTED_YOU', recnotif.paramsObj.username_worked); } else if (recnotif.paramsObj.isAdmin) { newdescr = i18n.__('FRIEND_REPORTED', recnotif.paramsObj.usernameDest, userorig); } else { newdescr = i18n.__('FRIEND_REPORTED_TO_ME', recnotif.paramsObj.username_action, recnotif.paramsObj.username_action); } } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_UNBLOCKED) { tag = 'unblockeduser'; if (recnotif.paramsObj.usernameDest === recnotif.paramsObj.username_action) { newdescr = i18n.__('FRIEND_UNBLOCKED_YOU', recnotif.paramsObj.username_worked); } else if (recnotif.paramsObj.isAdmin) { newdescr = i18n.__('FRIEND_UNBLOCKED', recnotif.paramsObj.usernameDest, userorig); } else { newdescr = i18n.__('FRIEND_UNBLOCKED_TO_ME', recnotif.paramsObj.username_action, recnotif.paramsObj.username_action); } } } else if (recnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_GROUPS) { tag = 'group'; recnotif.openUrl = '/grp/' + recnotif.paramsObj.groupnameDest; if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_NEW_REC) { newdescr = i18n.__('GROUP_CREATED', userorig, recnotif.paramsObj.groupnameDest); } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_ACCEPTED) { if (recnotif.paramsObj.isAdmin) { newdescr = i18n.__('ACCETTATO_NOTIFICA_ADMINS', userorig, recnotif.paramsObj.groupnameDest, recnotif.paramsObj.username_action); } else newdescr = i18n.__('GROUPS_ACCEPTED', userorig, recnotif.paramsObj.groupnameDest, recnotif.paramsObj.username_action); tag = 'addgroup'; } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_REMOVED) { if (recnotif.paramsObj.username_action === recnotif.paramsObj.usernameDest && userorig === recnotif.paramsObj.usernameDest) newdescr = i18n.__('GROUPS_EXIT_USER_TO_ME', recnotif.paramsObj.groupnameDest, recnotif.paramsObj.username_action); else if (userorig === recnotif.paramsObj.usernameDest) newdescr = i18n.__('GROUPS_REMOVED_TO_ME', recnotif.paramsObj.groupnameDest, recnotif.paramsObj.username_action); else if (userorig === recnotif.paramsObj.username_action) newdescr = i18n.__('GROUPS_EXIT_USER', userorig, recnotif.paramsObj.groupnameDest); else newdescr = i18n.__('GROUPS_REMOVED', userorig, recnotif.paramsObj.groupnameDest, recnotif.paramsObj.username_action); tag = 'remgroup'; } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_REFUSED) { newdescr = i18n.__('GROUPS_REFUSED', userorig, recnotif.paramsObj.groupnameDest, recnotif.paramsObj.username_action); tag = 'addgroup'; } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_REQUEST_TO_ENTER) { newdescr = i18n.__('GROUP_REQUEST_TO_ENTER', userorig, recnotif.paramsObj.groupnameDest, recnotif.paramsObj.singleadmin_username); tag = 'reqgroups'; // sendnotifPush = false; // non lo rimandare 2 volte ! // telegrambot.askConfirmationUser(idapp, shared_consts.CallFunz.RICHIESTA_GRUPPO, myuser, singleadmin.username, groupname, group._id); } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_BLOCK_USER) { newdescr = i18n.__('RICHIESTA_BLOCCO_GRUPPO', userorig, recnotif.paramsObj.groupnameDest, recnotif.paramsObj.singleadmin_username); tag = 'blockgroups'; } else if (recnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_DELETE_USER) { newdescr = i18n.__('GRUPPO_ELIMINATO', userorig, recnotif.paramsObj.username_action); tag = 'deletegroup'; } if (recnotif.paramsObj.isAdmin) { // If is a Admin, then click to see the user's profile recnotif.openUrl = '/my/' + userorig; } } recnotif.tag = recnotif.tag ? recnotif.tag : tag; if (!recnotif.descr) { recnotif.descr = newdescr; } return recnotif; } catch (e) { console.error(e); return null; } }; sendNotifSchema.statics.compileOtherFields = async function(arrnotif) { const {User} = require('../models/user'); try { // Fill in the image profile of the semyinders ! for (const notif of arrnotif) { let myimgprofile = await User.findOne({idapp: notif.idapp, username: notif.sender}, {'profile.img': 1}).lean(); if (myimgprofile && myimgprofile.profile.img) notif.myimgsender = 'upload/profile/' + notif.sender + '/' + myimgprofile.profile.img; } return arrnotif; } catch (e) { console.error(e); return arrnotif; } }; sendNotifSchema.statics.findLastNotifsByUserIdAndIdApp = function(username, idapp, limit) { const SendNotif = this; return SendNotif.aggregate([ { $match: { idapp, dest: username, }, }, {$limit: limit}, { $sort: {datenotif: -1}, }, ]).then(async (arrnotif) => { return this.compileOtherFields(arrnotif); }).catch((err) => { console.error(err); }); }; sendNotifSchema.statics.saveAndSendNotif = async function(myrecnotif, req, res, user) { const SendNotif = this; let idapp = req.body.idapp; const check = tools.checkUserOk(myrecnotif.sender, user ? myrecnotif.sender : req.user.username, res); if (check.exit) return check.ret; const {myrecout, save} = await SendNotif.updateStatusAndDescr(myrecnotif, false); if (!myrecout) return null; // console.log('myrecout._id', myrecout._id.toString()); if (save) { let res = null; try { res = await myrecout.save(); if (res) { const idobj = res._id; const myrecread = await SendNotif.findById(idobj).lean(); // console.log('myrecread._id', myrecread._id.toString()); return await globalTables.sendNotif(myrecread.typedir, myrecread.typeid, res, idapp, user ? user : req.user, myrecread); } } catch(e) { console.log(e.message); return null; } } else { return await globalTables.sendNotif(myrecout.typedir, myrecout.typeid, res, idapp, user ? user : req.user, myrecout); } }; sendNotifSchema.statics.updateStatusAndDescr = async function(myrecnotif, onlysave) { const SendNotif = this; try { if (!myrecnotif.openUrl) { // If not exist, then I set openUrl and description myrecnotif = this.getDescrAndLinkByRecNotif(myrecnotif); } let newstatus = 0; let typeidsearch = 0; let dest = ''; // Controllare se devo modificare un Notif già esistente ! if (myrecnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_FRIENDS) { typeidsearch = shared_consts.TypeNotifs.ID_FRIENDS_NEW_REC; if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_ACCEPTED) { newstatus = shared_consts.StatusNotifs.STATUS_FRIENDS_ACCEPTED; dest = myrecnotif.sender; } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_FRIENDS_REFUSED) { newstatus = shared_consts.StatusNotifs.STATUS_FRIENDS_REFUSED; dest = myrecnotif.sender; } } else if (myrecnotif.typedir === shared_consts.TypeNotifs.TYPEDIR_GROUPS) { typeidsearch = shared_consts.TypeNotifs.ID_GROUP_NEW_REC; if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_ACCEPTED) { typeidsearch = shared_consts.TypeNotifs.ID_GROUP_REQUEST_TO_ENTER; newstatus = shared_consts.GroupsNotifs.STATUS_GROUPS_ACCEPTED; dest = myrecnotif.dest; } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_REFUSED) { typeidsearch = shared_consts.TypeNotifs.ID_GROUP_REQUEST_TO_ENTER; newstatus = shared_consts.GroupsNotifs.STATUS_GROUPS_REFUSED; dest = myrecnotif.dest; } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_REMOVED) { typeidsearch = shared_consts.TypeNotifs.ID_GROUP_REQUEST_TO_ENTER; newstatus = shared_consts.GroupsNotifs.STATUS_GROUPS_REMOVED; dest = myrecnotif.dest; } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_BLOCK_USER) { typeidsearch = shared_consts.TypeNotifs.ID_GROUP_REQUEST_TO_ENTER; newstatus = shared_consts.GroupsNotifs.STATUS_GROUPS_BLOCKED; dest = myrecnotif.dest; } else if (myrecnotif.typeid === shared_consts.TypeNotifs.ID_GROUP_DELETE_USER) { typeidsearch = shared_consts.TypeNotifs.ID_GROUP_REQUEST_TO_ENTER; newstatus = shared_consts.GroupsNotifs.STATUS_GROUPS_DELETED; dest = myrecnotif.dest; } } if (newstatus) { const fields_to_update = { status: newstatus, read: true, descr: myrecnotif.descr, }; const query = { idapp: myrecnotif.idapp, typedir: myrecnotif.typedir, typeid: typeidsearch, dest, deleted: false, status: 0, }; // Cerca il record e se lo trova lo aggiorna const myrec = await SendNotif.findOneAndUpdate(query, {$set: fields_to_update}, { new: true, returnNewDocument: true, }); if (myrec) { return {myrecout: myrec, save: false}; } } // myrecnotif._id = new ObjectID(); if (newstatus > 0) { myrecnotif.status = newstatus; } return {myrecout: myrecnotif, save: true}; } catch (e) { console.error(e); return {myrecout: null, save: false}; } }; sendNotifSchema.statics.saveNotif = async function(myrecnotif) { const SendNotif = this; const {myrecout, save} = await SendNotif.updateStatusAndDescr(myrecnotif, true); if (!myrecout) return null; return myrecout.save().then((writeresult) => { let idobj = writeresult._id; return SendNotif.findById(idobj).lean().then(async (recnotif) => { return recnotif; }); }).catch((e) => { console.log(e.message); return null; }); }; sendNotifSchema.statics.getDefaultRec = function(req) { return { idapp: req.body.idapp, typedir: '', typeid: '', sender: req.user ? req.user.username : '', dest: '', descr: '', openUrl: '', datenotif: new Date(), status: 0, read: false, tablerec: '', idrec: 0, }; }; sendNotifSchema.statics.getExtraParam = function(myrecnotif, paramsObj) { let out = myrecnotif; //if (myrecnotif._doc) { //out = myrecnotif._doc //} out.paramsObj = paramsObj; out.options = paramsObj.options ? paramsObj.options : []; out.typesend = paramsObj.typesend ? paramsObj.typesend : 0; out.extrafield = paramsObj.groupnameDest ? paramsObj.groupnameDest : ''; return myrecnotif; }; sendNotifSchema.statics.createNewNotification = async function(req, res, paramsObj, table, rec, typedir, typeid) { const SendNotif = this; try { let myrecnotif = new SendNotif(this.getDefaultRec(req)); myrecnotif = this.getExtraParam(myrecnotif, paramsObj); myrecnotif.tablerec = table; if (rec && table) { myrecnotif.idrec = rec._id; } myrecnotif.typedir = typedir; myrecnotif.typeid = typeid; await SendNotif.sendToTheDestinations(myrecnotif, req, res); return true; } catch (e) { console.error('createNewNotification', e); return false; } }; sendNotifSchema.statics.createNewNotifToSingleUser = async function(req, res, paramsObj, onlysave, typedir, typeid) { const SendNotif = this; try { let myrecnotif = new SendNotif(this.getDefaultRec(req)); myrecnotif = this.getExtraParam(myrecnotif, paramsObj); myrecnotif.typedir = typedir; myrecnotif.typeid = typeid; await SendNotif.sendToSingleUserDest(myrecnotif, req, res, onlysave); return true; } catch (e) { console.error('createNewNotification', e); return false; } }; sendNotifSchema.statics.sendToTheDestinations = async function(myrecnotifpass, req, res) { const SendNotif = this; const {User} = require('../models/user'); const {City} = require('../models/city'); const {Province} = require('../models/province'); try { // Send only to the destination to reach: const userlist = await User.find({ idapp: myrecnotifpass.idapp, $or: [ {deleted: {$exists: false}}, {deleted: {$exists: true, $eq: false}}], }, { name: 1, surname: 1, lang: 1, username: 1, 'profile.notifs': 1, 'profile.notif_idCities': 1, 'profile.notif_provinces': 1, 'profile.notif_regions': 1, 'profile.notif_sectors': 1, 'profile.notif_sector_goods': 1, }).lean(); let arrprovinces = []; let arrregions = []; let idSector = 0; const mytable = globalTables.getTableByTableName(myrecnotifpass.tablerec); if (shared_consts.TABLES_ADV_NOTIFICATION.includes(myrecnotifpass.tablerec) || shared_consts.TABLES_EVENTS_NOTIFICATION.includes(myrecnotifpass.tablerec)) { const myrectableorig = await mytable.findOne({_id: myrecnotifpass.idrec}).lean(); if (myrectableorig) { for (const city of myrectableorig.idCity) { arrprovinces.push(await City.getProvinceByIdCity(city)); arrregions.push(await City.getRegionByIdCity(city)); } if (myrecnotifpass.tablerec === shared_consts.TABLES_MYGOODS) { idSector = myrectableorig.idSectorGood; } else { idSector = myrectableorig.idSector; } } myrecnotifpass.myrectableorig = myrectableorig; } myrecnotifpass = this.getDescrAndLinkByRecNotif(myrecnotifpass); delete myrecnotifpass._doc['_id']; for (const user of userlist) { if (user.profile && user.profile.notifs) { const usernotifprofile = user.profile.notifs.find((notif) => notif.dir === myrecnotifpass.typedir); let send = false; if (shared_consts.TABLES_ADV_NOTIFICATION.includes(myrecnotifpass.tablerec) || shared_consts.TABLES_EVENTS_NOTIFICATION.includes(myrecnotifpass.tablerec)) { // Estrai la Città, la Provincia e la regione. if (usernotifprofile && tools.isBitActive(usernotifprofile.value, shared_consts.UsersNotif.NEW_ADV_PROVINCE) && user.profile.notif_provinces && user.profile.notif_provinces.some(r => arrprovinces.indexOf(r) >= 0)) { send = true; } if (usernotifprofile && tools.isBitActive(usernotifprofile.value, shared_consts.UsersNotif.NEW_ADV_REGION) && user.profile.notif_regions && user.profile.notif_regions.some(r => arrregions.indexOf(r) >= 0)) { send = true; } if (idSector && usernotifprofile && tools.isBitActive(usernotifprofile.value, shared_consts.UsersNotif.NEW_ADV_SECTOR)) { // Controlla se è del settore selezionato if (myrecnotifpass.tablerec === shared_consts.TABLES_MYGOODS) { if (user.profile.notif_sector_goods) { send = send && (user.profile.notif_sector_goods.includes(idSector)); } } else if (user.profile.notif_sectors) { send = send && (user.profile.notif_sectors.includes(idSector)); } } } if (shared_consts.TABLES_GROUPS_NOTIFICATION.includes(myrecnotifpass.tablerec)) { if (usernotifprofile && tools.isBitActive(usernotifprofile.value, shared_consts.GroupsNotifs.STATUS_GROUPS_NEW)) { send = true; } } if (send) { let myrecnotif = new SendNotif(myrecnotifpass); myrecnotif.dest = user.username; await SendNotif.saveAndSendNotif(myrecnotif, req, res, user); } } } } catch (e) { console.error('sendToTheDestinations', e); return false; } }; sendNotifSchema.statics.sendToSingleUserDest = async function(myrecnotif, req, res, onlysave) { const SendNotif = this; try { myrecnotif.dest = myrecnotif.paramsObj && myrecnotif.paramsObj.usernameDest ? myrecnotif.paramsObj.usernameDest : ''; myrecnotif.username_worked = myrecnotif.paramsObj && myrecnotif.paramsObj.username_worked ? myrecnotif.paramsObj.username_worked : myrecnotif.dest; if (onlysave) { await SendNotif.saveNotif(myrecnotif); } else { await SendNotif.saveAndSendNotif(myrecnotif, req, res, null); } } catch (e) { console.error('sendToSingleUserDest', e); return false; } }; const SendNotif = mongoose.model('SendNotif', sendNotifSchema); module.exports = {SendNotif: SendNotif};