var os = require("os"); require('../config/config'); require('../models/subscribers'); var Url = require('url-parse'); const { ObjectID } = require('mongodb'); const mongoose = require('mongoose'); const Subscription = mongoose.model('subscribers'); const server_constants = require('../tools/server_constants'); // SETTINGS WebPush Configuration const webpush = require('web-push'); const subject = process.env.URLBASE_APP1; //'mailto:' + process.env.EMAIL_FROM const publicVapidKey = process.env.PUBLIC_VAPI_KEY; const privateVapidKey = process.env.PRIVATE_VAPI_KEY; if (process.env.GCM_API_KEY !== "") webpush.setGCMAPIKey(process.env.GCM_API_KEY); webpush.setVapidDetails(subject, publicVapidKey, privateVapidKey); // console.log('setVapidDetails... config...'); module.exports = { TYPE_PROJECT: 1, TYPE_TODO: 2, MAX_PHASES: 5, FIRST_PROJ: '__PROJECTS', EXECUTE_CALCPROJ: true, getHostname: function () { return os.hostname() }, testing: function () { return (process.env.TESTING_ON === '1') }, mylog: function (...args) { if (!this.testing()) console.log(args) }, mylogoff: function (...args) { // doing nothing }, mylogshow: function (...args) { console.log(args) }, mylogserr: function (...args) { console.error(args) }, allfieldSendMsg: function () { return ['userId', 'source', 'dest', 'message', 'datemsg', 'read', 'deleted', 'origin', 'idapp', 'status', 'options'] }, allfieldTodo: function () { return ['userId', 'pos', 'category', 'descr', 'priority', 'statustodo', 'created_at', 'modify_at', 'completed_at', 'expiring_at', 'enableExpiring', 'id_prev', 'progress', 'modified', 'phase', 'assigned_to_userId', 'hoursplanned', 'hoursworked', 'start_date', 'themecolor', 'themebgcolor'] }, allfieldMyEvent: function () { return ['userId',] }, allfieldTodoWithId: function () { return ['_id', ...this.allfieldTodo()] }, // #TODO Projects++ Add fields ... allfieldProject: function () { return ['userId', 'pos', 'typeproj', 'id_main_project', 'id_parent', 'descr', 'longdescr', 'hoursplanned', 'hoursleft', 'themecolor', 'themebgcolor', 'hoursworked', 'priority', 'statusproj', 'created_at', 'modify_at', 'completed_at', 'expiring_at', 'enableExpiring', 'id_prev', 'progressCalc', 'modified', 'live_url', 'test_url', 'begin_development', 'begin_test', 'totalphases', 'actualphase', 'hoursweeky_plannedtowork', 'endwork_estimate' , 'privacyread', 'privacywrite'] }, allfieldBooking: function () { return ['idapp', 'userId', 'id_bookedevent', 'numpeople', 'msgbooking', 'modified', 'infoevent', 'datebooked', 'booked'] }, allfieldBookingChange: function () { return ['numpeople', 'msgbooking', 'modified', 'infoevent', 'datebooked', 'booked'] }, allfieldProjectWithId: function () { return ['_id', ...this.allfieldProject()] }, jsonCopy(src) { return JSON.parse(JSON.stringify(src)) }, CloneRecordToNew(src) { const myrec = Object.assign({}, src); delete myrec._doc['_id']; myrec._id = new ObjectID(); return myrec._doc }, sendBackNotif: function (subscription, payload) { console.log('sendBackNotif:', subscription, payload); // Pass object into sendNotification webpush.sendNotification(subscription, JSON.stringify(payload)).catch(err => console.error(err)) .catch(err => { if (err.statusCode === 410) { // Gone: is not valid anymore (Expired probably!), so I have to delete from my db return Subscription.findOneAndRemove({ _id: subscription._id }) } else { console.log('Subscription is no longer valid: ', err); } }) }, sendNotificationToUser: function (userId, title, content, openUrl, tag) { let payload = { title: title, message: content, url: openUrl, tag, // ttl: req.body.ttl, // icon: req.body.icon, // image: req.body.image, // badge: req.body.badge, // tag: req.body.tag }; return Subscription.find({ userId }, (err, subscriptions) => { if (err) { console.error(`Error occurred while getting subscriptions`); res.status(500).json({ error: 'Technical error occurred' }); return false; } else { let conta = 0 let parallelSubscriptionCalls = subscriptions.map((subscription) => { const trovati = subscriptions.length return new Promise((resolve, reject) => { const pushSubscription = { endpoint: subscription.endpoint, keys: { p256dh: subscription.keys.p256dh, auth: subscription.keys.auth } }; conta++; const parse = require('url-parse'); const parsedUrl = parse(subscription.endpoint); const audience = parsedUrl.protocol + '//' + parsedUrl.hostname; const vapidHeaders = webpush.getVapidHeaders( audience, process.env.URLBASE_APP1, process.env.PUBLIC_VAPI_KEY, process.env.PRIVATE_VAPI_KEY, 'aes128gcm' ); const pushOptions = { vapidDetails: { subject: process.env.URLBASE_APP1, privateKey: process.env.PRIVATE_VAPI_KEY, publicKey: process.env.PUBLIC_VAPI_KEY, }, TTL: payload.ttl, headers: vapidHeaders }; console.log('************ INVIO WEBPUSH.SENDNOTIFICATION N° ', conta, '/', trovati, 'A', subscription.browser); // console.log('vapidDetails', pushOptions.vapidDetails); payload.title = process.env.URLBASE_APP1 + ' Msg n° ' + conta + '/' + trovati; // payload.message += subscription.browser ; const pushPayload = JSON.stringify(payload); // console.log('A1) SUBS: pushSubscription', pushSubscription); // console.log('A2) OPZIONI: pushOptions', pushOptions); // console.log('A3) MSG_TO_SEND: pushPayload', pushPayload); webpush.sendNotification( pushSubscription, pushPayload, // pushOptions ).then((value) => { resolve({ status: true, endpoint: subscription.endpoint, data: value }); }).catch((err) => { reject({ status: false, endpoint: subscription.endpoint, data: err }); }); }).catch(error => { console.log('ERROR: sendNotificationToUser', error.data.body) }); }); // q.allSettled(parallelSubscriptionCalls).then((pushResults) => { // console.info(pushResults); // }); // res.json({ // data: 'Push triggered' // }); return true; } }); }, // ********************** // SORT WITH PREV_ID // ********************** mapSort: function (linkedList) { let sortedList = []; let remainingList = []; var map = new Map(); var currentId = null; // console.log('linkedList', linkedList); // index the linked list by previous_item_id for (var i = 0; i < linkedList.length; i++) { var item = linkedList[i]; if (item.id_prev === server_constants.LIST_START) { // first item currentId = String(item._id); // console.log('currentId', currentId); sortedList.push(item); } else { map.set(String(item.id_prev), i); } } let conta = 0; while (conta < linkedList.length) { // get the item with a previous item ID referencing the current item var nextItem = linkedList[map.get(currentId)]; if (nextItem === undefined) { } else { sortedList.push(nextItem); currentId = String(nextItem._id); } conta++; } if (linkedList.length > sortedList.length) { // If are not in the list, I'll put at the bottom of the list // console.log('ATTENZIONE !!! ', sortedList.length, linkedList.length); for (const itemlinked of linkedList) { const elemtrov = sortedList.find((item) => item._id === itemlinked._id); if (elemtrov === undefined) { sortedList.push(itemlinked); } } } // console.log('DOPO sortedList', sortedList); return sortedList; }, checkUserOk(userpassed, userauth) { this.mylog('checkUserOk', userpassed, userauth); if (String(userpassed) !== String(userauth)) { // I'm trying to write something not mine! this.mylog('userId = ', userpassed.userId, 'req.user._id', userauth); return { exit: true, ret: res.status(404).send({ code: server_constants.RIS_CODE_TODO_CREATING_NOTMYUSER }) } } else { return { exit: false, ret: false } } }, convertHTMLtoText(myhtml) { let msg = myhtml; msg = msg.replace('"', '"'); msg = msg.replace('>', '>'); msg = msg.replace('<', '<'); msg = msg.replace('&', '&'); msg = msg.replace('
', '\n'); return msg }, removeSpecialCharForEmail(myhtml) { let msg = myhtml; msg = msg.replace(/"/g, '\''); return msg }, getNomeAppByIdApp: function (idapp) { const myapp = MYAPPS.find(item => item.idapp === idapp); if (myapp) return myapp.name; else return ''; }, getHostByIdApp: function (idapp) { const myapp = MYAPPS.find(item => item.idapp === idapp); if (myapp) { let siteport = (myapp.portapp !== "0") ? (':' + myapp.portapp) : ""; return myapp.host + siteport; } else return ''; }, getAdminEmailByIdApp: function (idapp) { const myapp = MYAPPS.find((item) => item.idapp === idapp); if (myapp) return myapp.adminemail; else return ''; }, getreplyToEmailByIdApp: function (idapp) { const myapp = MYAPPS.find((item) => item.idapp === idapp); if (myapp) return myapp.replyTo; else return ''; }, isManagAndAdminDifferent(idapp) { const manag = this.getManagerEmailByIdApp(idapp); return (manag !== this.getAdminEmailByIdApp(idapp)) && (manag !== ''); }, getManagerEmailByIdApp: function (idapp) { const myapp = MYAPPS.find((item) => item.idapp === idapp); if (myapp) return myapp.manageremail; else return ''; }, getQueryTable(idapp, params) { // console.log('idapp', idapp); // console.table(params); if (typeof params.startRow !== 'number') { throw new Error('startRow must be number') } else if (typeof params.endRow !== 'number') { throw new Error('endRow must be number') } const query = [ { $match: Object.assign({ idapp }, params.filter) } ]; if (params.sortBy) { // maybe we want to sort by blog title or something const mysort = { $sort: params.sortBy }; // console.log('sortBy', params.sortBy); // console.table(mysort); query.push(mysort) } query.push( { $group: { _id: null, // get a count of every result that matches until now count: { $sum: 1 }, // keep our results for the next operation results: { $push: '$$ROOT' } } }, // and finally trim the results to within the range given by start/endRow { $project: { count: 1, rows: { $slice: ['$results', params.startRow, params.endRow] } } } ); return query }, executeQueryTable(mythistable, idapp, params) { let query = this.getQueryTable(idapp, params); return mythistable .aggregate(query) .then(([{ count, rows }]) => { return ({ count, rows }) }) .catch(err => { return { count: 0, rows: [] } }); }, isBitActive(bit, whattofind) { return ((bit & whattofind) === whattofind) }, SetBit(myval, bit) { myval = myval & bit; return myval } };