const os = require("os"); const fs = require('fs'); require('../config/config'); require('../models/subscribers'); const CryptoJS = require('crypto-js'); const Url = require('url-parse'); const { ObjectID } = require('mongodb'); const shared_consts = require('./shared_nodejs'); const mongoose = require('mongoose'); const Subscription = mongoose.model('subscribers'); const server_constants = require('./server_constants'); // SETTINGS WebPush Configuration const webpush = require('web-push'); const FILELOG = 'filelog.txt'; const FILEEVENTS = 'logevents.txt'; const FILEMANAGERS = 'logmanagers.txt'; const FILENAVE = 'logNave.txt'; const subject = process.env.URLBASE_APP1; const publicVapidKey = process.env.PUBLIC_VAPI_KEY; const privateVapidKey = process.env.PRIVATE_VAPI_KEY; const FIELDS_REGEX = ['username', 'name', 'surname']; // Code goes here const keySize = 256; const ivSize = 128; const iterations = 100; if (process.env.GCM_API_KEY !== "") webpush.setGCMAPIKey(process.env.GCM_API_KEY); webpush.setVapidDetails(subject, publicVapidKey, privateVapidKey); // console.log('setVapidDetails... config...'); // To Translate! textlang = { it: { "L'Email è già stata Verificata": "L'Email è già stata Verificata", "Nuova Registrazione": "Nuova Registrazione", "Effettuata una Nuova Registrazione": "Effettuata una Nuova Registrazione", "partecipanti": "partecipanti", 'TESTO_ASSISTENZA': "Per entrare nel Sito AYNI:\nhttps://ayni.gifteconomy.app\n\nHai dimenticato la Password per accedere al sito?\nhttps://ayni.gifteconomy.app/requestresetpwd\n\nChat AYNI BOT (questa):\nhttps://t.me/notevoleaynibot\n\nChat AYNI - EMPOWER: Entra ⛩ nella nostra Community chat:\n https://t.me/joinchat/C741mkx5QYXu-kyYCYvA8g\n\nChat AYNI-BIBLIO: https://t.me/joinchat/AL2qKExZKvenLgpVhOyefQ \n\nChat di Aiuto e Supporto: 'AYNI - HELP'\nhttps://t.me/joinchat/C741mlVmB_RMcOUpNqWC8w\n1 - Fai la tua domanda e chiedi assistenza.\n2 - Dopo aver ricevuto aiuto esci dalla chat.\nPotrai rientrare ogni qualvolta ne avrai la necessità.", 'BENVENUTO': "Benvenuto", 'TUE_NAVI': "Ecco le tue Navi programmate", 'HAI_I_7_REQUISITI': 'PRIMI PASSI OK!\nHai i Primi 7 Requisiti per Entrare nella Lista d\'Imbarco!', 'NON_HAI_I_7_REQUISITI': 'Attenzione!\nAncora non hai i 7 Requisiti per Entrare nella Lista d\'Imbarco!', 'HAI_I_9_REQUISITI': 'COMPLIMENTI!\nHai Completato TUTTI i 9 Passi della Guida! Grazie per Aiutare AYNI ad Espandersi!', 'NON_HAI_I_9_REQUISITI': 'Ricorda che puoi Aiutare a far Crescere ed Espandere il Movimento, Condividendo con chiunque questo nostro viaggio!', 'INFO_LA_MIA_LAVAGNA': '✨ Lista dei Passi: ✨ \n', 'INFO_LAVAGNA_SITO_COMPLETARE': 'Per completare tutti i requisiti vai sul sito:\n%s\nPer vedere lo stato della tua Nave e dei tuoi invitati, clicca sulle 3 linee in alto a sinistra ed accedi alla voce "Lavagna".\n', 'INFO_LAVAGNA_SITO': 'Per vedere in dettaglio lo stato della tua Nave, sul sito AYNI, clicca sulle 3 linee in alto a sinistra ed accedi alla voce "Lavagna".\n', 'INFO_LINK_DA_CONDIVIDERE': 'Link da condividere ai tuoi invitati per farli registrare al sito di Ayni:\n%s\n\nLink da condividere per partecipare allo Zoom (Conferenza OnLine):\n%s', 'ZOOM_CONFERENCE': 'Qui trovi le date di programmazione agli Zoom:', "NON_VERIF": "Non Verificata", "VERIF": "Verificata", 'EMAIL': "Email", 'BOT': "AYNI BOT", 'EMAIL_NON_VERIF': "Email Non Verificata\nleggi la tua casella email e trova **\"Confermare la Registrazione a Ayni\"**
e clicca sul bottone **\"Verifica Registrazione\"**", 'TELEGRAM_NOT_CONNECTED': "Telegram non associato al tuo account!", 'NESSUN_INVITATO': 'Non hai invitato nessuno', 'ZOOM_PARTECIPATO': 'Partecipazione ad almeno 1 Conferenza (Zoom)', 'LINEE_GUIDA': 'Accettato le Linee Guida', 'VIDEO_INTRO': 'Visto il Video di AYNI', 'SCRITTO_SOGNO': 'Hai scritto il tuo Sogno', 'PAYMENTS': 'Modalità di Pagamento (Obbligatorio Paypal)', 'INVITATI': 'persone registrate che hai invitato', 'INVITATI_ATTIVI': 'Invitati con i 7 Requisiti', 'NONREG': 'Invitati non Registrati', 'CLICCA_PER_ZOOM': 'AL GIORNO E ORA INDICATA, PER ENTRARE NELLA VIDEO-CONFERENZA, CLICCA QUI', 'CLICCA_ENTRA': 'CLICCA QUI PER ENTRARE !', 'ZOOM_INIZIATO': 'QUESTA CONFERENZA E\' INIZIATA!', 'SCEGLI_VOCE': 'scegli una voce:', 'INVITATI_LISTA': 'I Tuoi Invitati (in verde con almeno i primi 7 Requisiti)', 'CIAO': 'Ciao', 'ADDED_TOLISTAINGRESSO': 'Sei stato aggiunto alla Lista delle persone che entreranno nella Lista D\'Imbarco !', 'NO_PROG': 'Attualmente non sei ancora dentro alla Lista d\'Imbarco!', 'SEND_LINK_CHAT_DONATORI': 'Ciao %s!\nLa tua NAVE sta finalmente Salpando!\nEntra nella Gift Chat cliccando qui: %s' }, es: { "L'Email è già stata Verificata": "L'Email è già stata Verificata", "Nuova Registrazione": "Nuevo Registro", "Effettuata una Nuova Registrazione": "Se ha realizado un nuevo registro", "partecipanti": "participantes", 'TESTO_ASSISTENZA': "Per entrare nel Sito AYNI:\nhttps://ayni.gifteconomy.app\n\nHai dimenticato la Password per accedere al sito?\nhttps://ayni.gifteconomy.app/requestresetpwd\n\nChat AYNI BOT (questa):\nhttps://t.me/notevoleaynibot\n\nChat AYNI - EMPOWER: Entra ⛩ nella nostra Community chat:\n https://t.me/joinchat/C741mkx5QYXu-kyYCYvA8g\n\nChat AYNI-BIBLIO: https://t.me/joinchat/AL2qKExZKvenLgpVhOyefQ \n\nChat di Aiuto e Supporto: 'AYNI - HELP'\nhttps://t.me/joinchat/C741mlVmB_RMcOUpNqWC8w\n1 - Fai la tua domanda e chiedi assistenza.\n2 - Dopo aver ricevuto aiuto esci dalla chat.\nPotrai rientrare ogni qualvolta ne avrai la necessità.", 'BENVENUTO': "Benvenuto", 'TUE_NAVI': "Ecco le tue Navi programmate", 'HAI_I_7_REQUISITI': 'PRIMI PASSI OK!\nHai i Primi 7 Requisiti per Entrare nella Lista d\'Imbarco!', 'NON_HAI_I_7_REQUISITI': 'Attenzione!\nAncora non hai i 7 Requisiti per Entrare nella Lista d\'Imbarco!', 'HAI_I_9_REQUISITI': 'COMPLIMENTI!\nHai Completato TUTTI i 9 Passi della Guida! Grazie per Aiutare AYNI ad Espandersi!', 'NON_HAI_I_9_REQUISITI': 'Ricorda che puoi Aiutare a far Crescere ed Espandere il Movimento, Condividendo con chiunque questo nostro viaggio!', 'INFO_LA_MIA_LAVAGNA': '✨ Lista dei Passi: ✨ \n', 'INFO_LAVAGNA_SITO_COMPLETARE': 'Per completare tutti i requisiti vai sul sito:\n%s\nPer vedere lo stato della tua Nave e dei tuoi invitati, clicca sulle 3 linee in alto a sinistra ed accedi alla voce "Lavagna".\n', 'INFO_LAVAGNA_SITO': 'Per vedere in dettaglio lo stato della tua Nave, sul sito AYNI, clicca sulle 3 linee in alto a sinistra ed accedi alla voce "Lavagna".\n', 'INFO_LINK_DA_CONDIVIDERE': 'Link da condividere ai tuoi invitati per farli registrare al sito di Ayni:\n%s\n\nLink da condividere per partecipare allo Zoom (Conferenza OnLine):\n%s', 'ZOOM_CONFERENCE': 'Qui trovi le date di programmazione agli Zoom:', "NON_VERIF": "Non Verificata", "VERIF": "Verificata", 'EMAIL': "Email", 'BOT': "AYNI BOT", 'EMAIL_NON_VERIF': "Email Non Verificata\nleggi la tua casella email e trova **\"Confermare la Registrazione a Ayni\"**
e clicca sul bottone **\"Verifica Registrazione\"**", 'TELEGRAM_NOT_CONNECTED': "Telegram non associato al tuo account!", 'NESSUN_INVITATO': 'Non hai invitato nessuno', 'ZOOM_PARTECIPATO': 'Partecipazione ad almeno 1 Conferenza (Zoom)', 'LINEE_GUIDA': 'Accettato le Linee Guida', 'VIDEO_INTRO': 'Visto il Video di AYNI', 'SCRITTO_SOGNO': 'Hai scritto il tuo Sogno', 'PAYMENTS': 'Modalità di Pagamento (Obbligatorio Paypal)', 'INVITATI': 'persone registrate che hai invitato', 'INVITATI_ATTIVI': 'Invitati con i 7 Requisiti', 'NONREG': 'Invitati non Registrati', 'CLICCA_PER_ZOOM': 'AL GIORNO E ORA INDICATA, PER ENTRARE NELLA VIDEO-CONFERENZA, CLICCA QUI', 'CLICCA_ENTRA': 'CLICCA QUI PER ENTRARE !', 'ZOOM_INIZIATO': 'QUESTA CONFERENZA E\' INIZIATA!', 'SCEGLI_VOCE': 'scegli una voce:', 'INVITATI_LISTA': 'I Tuoi Invitati (in verde con almeno i primi 7 Requisiti)', 'CIAO': 'Hola', 'ADDED_TOLISTAINGRESSO': 'Has sido añadido a la lista de personas que entrarán en Lista de embarque!', 'NO_PROG': 'Attualmente non sei ancora dentro alla Lista d\'Imbarco!', 'SEND_LINK_CHAT_DONATORI': 'Ciao %s!\nLa tua NAVE sta finalmente Salpando!\nEntra nella Gift Chat cliccando qui: %s' }, us: { "partecipanti": "participants", 'TESTO_ASSISTENZA': "Per entrare nel Sito AYNI:\nhttps://ayni.gifteconomy.app\n\nHai dimenticato la Password per accedere al sito?\nhttps://ayni.gifteconomy.app/requestresetpwd\n\nChat AYNI BOT (questa):\nhttps://t.me/notevoleaynibot\n\nChat AYNI - EMPOWER: Entra ⛩ nella nostra Community chat:\n https://t.me/joinchat/C741mkx5QYXu-kyYCYvA8g\n\nChat AYNI-BIBLIO: https://t.me/joinchat/AL2qKExZKvenLgpVhOyefQ \n\nChat di Aiuto e Supporto: 'AYNI - HELP'\nhttps://t.me/joinchat/C741mlVmB_RMcOUpNqWC8w\n1 - Fai la tua domanda e chiedi assistenza.\n2 - Dopo aver ricevuto aiuto esci dalla chat.\nPotrai rientrare ogni qualvolta ne avrai la necessità.", 'BENVENUTO': "Benvenuto", 'TUE_NAVI': "Ecco le tue Navi programmate", 'HAI_I_7_REQUISITI': 'PRIMI PASSI OK!\nHai i Primi 7 Requisiti per Entrare nella Lista d\'Imbarco!', 'NON_HAI_I_7_REQUISITI': 'Attenzione!\nAncora non hai i 7 Requisiti per Entrare nella Lista d\'Imbarco!', 'HAI_I_9_REQUISITI': 'COMPLIMENTI!\nHai Completato TUTTI i 9 Passi della Guida! Grazie per Aiutare AYNI ad Espandersi!', 'NON_HAI_I_9_REQUISITI': 'Ricorda che puoi Aiutare a far Crescere ed Espandere il Movimento, Condividendo con chiunque questo nostro viaggio!', 'INFO_LA_MIA_LAVAGNA': '✨ Lista dei Passi: ✨ \n', 'INFO_LAVAGNA_SITO_COMPLETARE': 'Per completare tutti i requisiti vai sul sito:\n%s\nPer vedere lo stato della tua Nave e dei tuoi invitati, clicca sulle 3 linee in alto a sinistra ed accedi alla voce "Lavagna".\n', 'INFO_LAVAGNA_SITO': 'Per vedere in dettaglio lo stato della tua Nave, sul sito AYNI, clicca sulle 3 linee in alto a sinistra ed accedi alla voce "Lavagna".\n', 'INFO_LINK_DA_CONDIVIDERE': 'Link da condividere ai tuoi invitati per farli registrare al sito di Ayni:\n%s\n\nLink da condividere per partecipare allo Zoom (Conferenza OnLine):\n%s', 'ZOOM_CONFERENCE': 'Qui trovi le date di programmazione agli Zoom:', "NON_VERIF": "Non Verificata", "VERIF": "Verificata", 'EMAIL': "Email", 'BOT': "AYNI BOT", 'EMAIL_NON_VERIF': "Email Non Verificata\nleggi la tua casella email e trova **\"Confermare la Registrazione a Ayni\"**
e clicca sul bottone **\"Verifica Registrazione\"**", 'TELEGRAM_NOT_CONNECTED': "Telegram non associato al tuo account!", 'NESSUN_INVITATO': 'Non hai invitato nessuno', 'ZOOM_PARTECIPATO': 'Partecipazione ad almeno 1 Conferenza (Zoom)', 'LINEE_GUIDA': 'Accettato le Linee Guida', 'VIDEO_INTRO': 'Visto il Video di AYNI', 'SCRITTO_SOGNO': 'Hai scritto il tuo Sogno', 'PAYMENTS': 'Modalità di Pagamento (Obbligatorio Paypal)', 'INVITATI': 'persone registrate che hai invitato', 'INVITATI_ATTIVI': 'Invitati con i 7 Requisiti', 'NONREG': 'Invitati non Registrati', 'CLICCA_PER_ZOOM': 'AL GIORNO E ORA INDICATA, PER ENTRARE NELLA VIDEO-CONFERENZA, CLICCA QUI', 'CLICCA_ENTRA': 'CLICCA QUI PER ENTRARE !', 'ZOOM_INIZIATO': 'QUESTA CONFERENZA E\' INIZIATA!', 'SCEGLI_VOCE': 'scegli una voce:', 'INVITATI_LISTA': 'I Tuoi Invitati (in verde con almeno i primi 7 Requisiti)', 'CIAO': 'Hi', 'ADDED_TOLISTAINGRESSO': 'You have been added to the List of people who will enter the Boarding List!', 'NO_PROG': 'Attualmente non sei ancora dentro alla Lista d\'Imbarco!', 'SEND_LINK_CHAT_DONATORI': 'Ciao %s!\nLa tua NAVE sta finalmente Salpando!\nEntra nella Gift Chat cliccando qui: %s' } }; module.exports = { INITDB_FIRSTIME: true, ACAPO: '\n', LANGADMIN: 'it', AYNI: '7', APORTADOR_NONE: '------', TYPE_PROJECT: 1, TYPE_TODO: 2, TipoMsg: { SEND_LINK_CHAT_DONATORI: 1, SEND_MSG: 2, SEND_MSG_SINGOLO: 3, }, Placca: { DONATORI: 1, TUTTI: 2, STR_SOGNATORE: 'Sognatore', STR_MEDIATORE: 'Mediatore', STR_MEDIATORI: 'Mediatori', STR_DONATORI: 'Donatori', SOGNATORE: 'E1 🌈 ', MEDIATORE: 'A1 💦 ', SONOFUOCO: 0, SONOACQUA: 3, SONOTERRA: 2, SONOARIA: 1, }, FieldType: { boolean: 1, date: 2, string: 4, binary: 8, html: 16, select: 32, number: 64, typeinrec: 128, multiselect: 256, password: 512, listimages: 1024, }, MAX_PHASES: 5, FIRST_PROJ: '__PROJECTS', EXECUTE_CALCPROJ: true, gettranslate(text, lang) { try { return textlang[lang][text] } catch (e) { return textlang['it'][text] } }, get__(text, msg) { let lang = 'it'; if (msg) lang = msg.from.language_code; try { return textlang[lang][text] } catch (e) { return textlang['it'][text] } }, getres__(text, res) { // ++Todo: res estrarre la lingua let lang = 'it'; try { return textlang[lang][text] } catch (e) { return textlang['it'][text] } }, 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, res) { this.mylog('checkUserOk', userpassed, userauth); if (String(userpassed) !== String(userauth)) { // I'm trying to write something not mine! this.mylog('userId = ', userpassed, '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 }, convertTexttoHtml(myhtml) { // let msg = myhtml; // msg = msg.replace('\n', '
'); // return msg return myhtml; }, 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 ''; }, isAbilitaNave: function (idapp) { const myapp = MYAPPS.find(item => item.idapp === idapp); return myapp.abilitanave; }, getdirByIdApp: function (idapp) { const myapp = MYAPPS.find(item => item.idapp === idapp); if (myapp) { return myapp.dir; } 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 ''; }, getpathregByIdApp: function (idapp, lang) { const myapp = MYAPPS.find((item) => item.idapp === idapp); if (myapp) return 'registration' + myapp.pathreg_add + '/' + lang; 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 ''; }, getEmailByIdApp: function (idapp) { const myapp = MYAPPS.find((item) => item.idapp === idapp); return (myapp) ? myapp.email_from : '' }, getPwdByIdApp: function (idapp) { const myapp = MYAPPS.find((item) => item.idapp === idapp); return (myapp) ? this.decryptdata(myapp.email_pwd) : '' }, getTelegramBotNameByIdApp: function (idapp) { const myapp = MYAPPS.find((item) => item.idapp === idapp); return (myapp) ? myapp.telegram_bot_name : '' }, getTelegramKeyByIdApp: function (idapp) { const myapp = MYAPPS.find((item) => item.idapp === idapp); return (myapp) ? myapp.telegram_key : '' }, 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') } let query = []; if (params.filter && params.fieldsearch) { let myregexp = {}; myregexp = new RegExp(params.filter.trim().replace(' ', '|'), "ig"); const myfilters = []; params.fieldsearch.forEach((rec) => { const data = {}; if (rec.type === this.FieldType.string) { data[rec.field] = myregexp; } else if (rec.type === this.FieldType.number) { data[rec.field] = parseInt(params.filter.trim()); } myfilters.push(data); }); query = [ { $match: { $or: myfilters } }, ] } let filtriadded = []; // if (params.table === 'extralist') { // if (params.filterand.includes(shared_consts.FILTER_EXTRALIST_DELETED)) // filtriadded.push({ deleted: true }); // else // filtriadded.push({ deleted: { $exists: false } }); // } if (params.filterand) { if (params.filterand.includes(shared_consts.FILTER_EXTRALIST_NOT_REGISTERED)) filtriadded.push({ registered: false }); if (params.filterand.includes(shared_consts.FILTER_EXTRALIST_NOT_CONTACTED)) { filtriadded.push({ contacted: { $exists: false } }); } if (params.filterand.includes(shared_consts.FILTER_EXTRALIST_WITH_NOTE)) filtriadded.push({ 'note': { $exists: true }, "$expr": { "$gt": [{ "$strLenCP": "$note" }, 1] } }); if (params.filterand.includes(shared_consts.FILTER_USER_NO_ZOOM)) filtriadded.push({ 'profile.saw_zoom_presentation': false }); if (params.filterand.includes(shared_consts.FILTER_USER_NO_INVITANTE)) filtriadded.push({ aportador_solidario: { $exists: false } }); if (params.filterand.includes(shared_consts.FILTER_USER_NO_TELEGRAM_ID)) filtriadded.push({ 'profile.teleg_id': { $lt: 1 } }); if (params.filterand.includes(shared_consts.FILTER_USER_CODICE_AUTH_TELEGRAM)) filtriadded.push({ 'profile.teleg_checkcode': { $gt: 1 } }); if (params.filterand.includes(shared_consts.FILTER_USER_NO_EMAIL_VERIFICATA)) filtriadded.push({ verified_email: false }); if (params.filterand.includes(shared_consts.FILTER_USER_NO_DREAM)) filtriadded.push({ 'profile.my_dream': { $exists: false } }); if (params.filterand.includes(shared_consts.FILTER_USER_TELEGRAM_BLOCKED)) filtriadded.push({ 'profile.teleg_id_old': { $gt: 1 } }); } if (filtriadded.length > 0) query.push({ $match: { $and: filtriadded } }); if (idapp > 0) { query.push({ $match: { idapp } }); } // console.log('QUERYMATCH', query[0].$match.or); // console.log('filter', 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) } let numrowend = params.endRow - params.startRow; if (numrowend < 0) numrowend = 1; 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, numrowend] } } } ); // console.log('query', query); return query; }, executeQueryTable(mythistable, idapp, params) { let query = this.getQueryTable(idapp, params); return mythistable .aggregate(query) .then(([ris]) => { if (ris) { // console.table(ris.rows); // console.log('ROW ', ris.count); return ({ count: ris.count, rows: ris.rows }) } else { return ({ count: 0, rows: [] }) } }) .catch(err => { console.error(err); return { count: 0, rows: [] } }); }, async DuplicateAllRecords(mythistable, idapporig, idappdest) { console.log(mythistable.name); const numrec = await mythistable.findAllIdApp(idappdest).then((arrrec) => { if (arrrec && arrrec.length > 1) { return arrrec.length; // Has Already set } else { return 0; } }); // Before check if exist more than 1 record in the destination, // if Yes don't copy if (numrec <= 0) { return await mythistable.findAllIdApp(idapporig).then(async (arrrec) => { let num = 0; for (let ind = 0; ind < arrrec.length; ind++) { let newrec = new mythistable(arrrec[ind]._doc); newrec._id = new ObjectID(); newrec.idapp = idappdest; await newrec.save((err, rec) => { if (rec) { num++; } }); } return num; }); } }, isBitActive(bit, whattofind) { return ((bit & whattofind) === whattofind) }, SetBit(myval, bit) { myval = myval & bit; return myval }, async snooze(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }, IncDateNow(secs) { let mydate = new Date(new Date().getTime() + secs); // console.log('mydate', mydate); return mydate }, AddDate(mydate, days) { let date = new Date(mydate); date.setTime(date.getTime() + days * 86400000); return date; }, getRigaColByPosUp(mypos) { if (mypos.numup > 0) { mypos.riga = mypos.riga - mypos.numup; mypos.col = Math.ceil(mypos.col / (Math.pow(2, mypos.numup))); } if (mypos.numup < 0) { mypos.riga = mypos.riga - mypos.numup; mypos.col = Math.ceil(mypos.col * (Math.pow(2, -mypos.numup))); } }, appendLeadingZeroes(n) { if (n <= 9) { return "0" + n; } return n }, getWeekDay(date) { //Create an array containing each day, starting with Sunday. const weekdays = [ "Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedí", "Venerdì", "Sabato" ]; //Use the getDay() method to get the day. const day = date.getDay(); //Return the element that corresponds to that index. return weekdays[day]; }, getstrDateTimeShort(mydate) { if (mydate) { // console.log('getstrDate', mytimestamp) return this.getWeekDay(mydate) + ' ' + this.appendLeadingZeroes(mydate.getDate()) + '/' + this.appendLeadingZeroes(mydate.getMonth() + 1) + ' ORE ' + this.appendLeadingZeroes(mydate.getHours()) + ':' + this.appendLeadingZeroes(mydate.getMinutes()); } else { return ''; } }, getstrDateShort(mydate) { if (mydate) { // console.log('getstrDate', mytimestamp) return this.getWeekDay(mydate).substring(0, 3) + ' ' + this.appendLeadingZeroes(mydate.getDate()) + '/' + this.appendLeadingZeroes(mydate.getMonth() + 1); } else { return ''; } }, getstrDateLong(mydate) { if (mydate) { // console.log('getstrDate', mytimestamp) return this.getWeekDay(mydate) + ' ' + this.appendLeadingZeroes(mydate.getDate()) + '/' + this.appendLeadingZeroes(mydate.getMonth() + 1) + '/' + mydate.getFullYear(); } else { return ''; } }, getlinkzoom(idconf) { if (idconf === '') idconf = '6668882000'; return 'https://zoom.us/j/' + idconf }, getmd5(mystr) { return CryptoJS.MD5(mystr.toLowerCase()).toString(); }, getHash(mystr) { return CryptoJS.SHA512(mystr, { outputLength: 256 }).toString(); }, encrypt(msg, pass) { var salt = CryptoJS.lib.WordArray.random(128 / 8); var key = CryptoJS.PBKDF2(pass, salt, { keySize: keySize / 32, iterations: iterations }); var iv = CryptoJS.lib.WordArray.random(128 / 8); var encrypted = CryptoJS.AES.encrypt(msg, key, { iv: iv, padding: CryptoJS.pad.Pkcs7, mode: CryptoJS.mode.CBC }); // salt, iv will be hex 32 in length // append them to the ciphertext for use in decryption var transitmessage = salt.toString() + iv.toString() + encrypted.toString(); return transitmessage; }, decrypt(transitmessage, pass) { var salt = CryptoJS.enc.Hex.parse(transitmessage.substr(0, 32)); var iv = CryptoJS.enc.Hex.parse(transitmessage.substr(32, 32)) var encrypted = transitmessage.substring(64); var key = CryptoJS.PBKDF2(pass, salt, { keySize: keySize / 32, iterations: iterations }); var decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: iv, padding: CryptoJS.pad.Pkcs7, mode: CryptoJS.mode.CBC }); return decrypted; }, cryptdata(mydata) { // Encrypt //return CryptoJS.AES.encrypt(JSON.stringify(mydata), process.env.SECRK); return this.encrypt(mydata, process.env.SECRK); }, decryptdata(mydatacrypted) { // Decrypt // const bytes = CryptoJS.AES.decrypt(mydatacrypted.toString(), process.env.SECRK); // return JSON.parse(bytes.toString(CryptoJS.enc.Utf8)); return this.decrypt(mydatacrypted, process.env.SECRK).toString(CryptoJS.enc.Utf8); }, BoolToInt(mybool) { return (mybool) ? -1 : 0 }, StrToBool(mystr) { return (mystr === '-1') ? true : false }, writelogfile(mystr, filename) { // fs.appendFile(FILELOG, mystr, function (err) { // if (err) throw err; // console.log('Saved!'); // }); // mystr = this.getstrDateTimeShort(Date.now()) + ' ' + mystr; const stream = fs.createWriteStream(filename, { flags: 'a' }); stream.write('\n' + mystr); stream.end(); }, writelog(mystr) { this.writelogfile(mystr, FILELOG); }, writeEventsLog(mystr) { this.writelogfile(mystr, FILEEVENTS); }, writeManagersLog(mystr) { this.writelogfile(mystr, FILEMANAGERS); }, writeNaveLog(mystr) { this.writelogfile(mystr, FILENAVE); }, move(oldPath, newPath, callback) { fs.rename(oldPath, newPath, function (err) { if (err) { if (err.code === 'EXDEV') { copy(); } else { callback(err); } return; } callback(); }); function copy() { const readStream = fs.createReadStream(oldPath); const writeStream = fs.createWriteStream(newPath); readStream.on('error', callback); writeStream.on('error', callback); readStream.on('close', function () { fs.unlink(oldPath, callback); }); readStream.pipe(writeStream); } }, delete(path, callback) { fs.unlink(path, function (err) { if (err) { console.error(err); callback(err); return } callback(); }); }, mkdirpath(dirPath) { // if (!fs.accessSync(dirPath, fs.constants.R_OK | fs.constants.W_OK)) { if (!fs.existsSync(dirPath)) { try { fs.mkdirSync(dirPath, { recursive: true }); } catch (e) { mkdirpath(path.dirname(dirPath)); mkdirpath(dirPath); } } }, extractNameAndSurnameByComplete(name_complete) { const suffissoCognome = ['Del', 'La', 'De', 'Lo']; let campi = name_complete.split(" "); let namesurname = { name: '', surname: '', }; if (campi.length === 2) { namesurname.name = campi[0]; namesurname.surname = campi[1]; } else if (campi.length === 3) { if (suffissoCognome.includes(campi[1])) { namesurname.name = campi[0]; namesurname.surname = campi[1] + " " + campi[2]; } else { namesurname.name = campi[0] + " " + campi[1]; namesurname.surname = campi[2]; } } else if (campi.length === 4) { namesurname.name = campi[0] + " " + campi[1]; namesurname.surname = campi[2] + " " + campi[3]; } else if (campi.length > 4) { namesurname.name = campi[0] + " " + campi[1]; namesurname.surname = " " + campi[2]; for (let ind = 3; ind < campi.length; ind++) { namesurname.surname += " " + campi[ind]; } } return namesurname }, getiPAddressUser(req) { try { const striniziale = '::ffff:'; if (req.ip.indexOf(striniziale) >= 0) { return req.ip.substring(striniziale.length) } else { return req.ip; // Express } } catch (e) { return '' } }, removespaces(mystr) { return mystr.replace(/\s+/g, '') }, ModificheConsentite(table, fieldsvalue, idrec, user) { if (table === 'users') { if ('aportador_solidario' in fieldsvalue) { return true; } if ('ALL' in fieldsvalue) { //++Todo: Cancellalo solo se sono io il creatore dell'utente ... o se posso! return true } } if (table === 'navi') { if ('date_made_gift' in fieldsvalue) { return true; } if ('made_gift' in fieldsvalue) { return true; } } if (table === 'navepersistente') { if ('link_chat' in fieldsvalue) { return true; } } return false; }, NotifyIfDelRecord(table) { if ((table === 'users') || (table === 'extralist')) { return true; } return false; }, getFirstWord(mystr) { const myarr = mystr.split(" "); if (myarr.length > 0) return myarr[0]; else return mystr }, getFirst2Car(mystr) { if (!!mystr) return mystr.substring(0, 2) + '.'; else return '' }, };