const os = require('os'); const fs = require('fs-extra'); // 👈 Usa il modulo promises const xml2js = require('xml2js'); const path = require('path'); const WebSocket = require('ws'); require('../config/config'); require('../models/subscribers'); const ImageDownloader = require('../modules/ImageDownloader'); const printf = require('util').format; const { JSDOM } = require('jsdom'); const axios = require('axios'); const CryptoJS = require('crypto-js'); const Url = require('url-parse'); const { ObjectId } = require('mongodb'); const shared_consts = require('./shared_nodejs'); const mongoose = require('mongoose').set('debug', false); const server_constants = require('./server_constants'); // SETTINGS WebPush Configuration const webpush = require('web-push'); const i18n = require('i18n'); const FILELOG = 'filelog.txt'; const FILEEVENTS = 'logevents.txt'; const FILEMANAGERS = 'logmanagers.txt'; const FILETRANSACTION = 'logtrans.txt'; const FILEERRLOGIN = 'errlogin.txt'; const FILESOSTITUZIONI = 'log_sostituzioni.txt'; const FILEIP_TO_BAN = 'log_iptoban.txt'; const FILENAVE = 'logNave.txt'; const subject = process.env.VAPI_KEY_SUBJECT; const publicVapidKey = process.env.PUBLIC_VAPI_KEY; const privateVapidKey = process.env.PRIVATE_VAPI_KEY; const FIELDS_REGEX = ['username', 'name', 'surname']; const sanitizeHtml = require('sanitize-html'); const { exec } = require('child_process'); const util = require('util'); const execPromise = util.promisify(exec); const { spawn } = require('child_process'); const readline = require('readline'); // Code goes here const keySize = 256; // const ivSize = 128; const iterations = 1000; if (!!process.env.GCM_API_KEY && process.env.GCM_API_KEY !== '') { webpush.setGCMAPIKey(process.env.GCM_API_KEY); webpush.setVapidDetails(subject, publicVapidKey, privateVapidKey); } // console.log('setVapidDetails... config...'); // To Translate! const 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 all'Evento", 'partecipanti a Pranzo': 'partecipanti a Pranzo', 'partecipanti a Cena': 'partecipanti a Cena', 'partecipanti a Cena Condivisa': 'partecipanti a Cena Condivisa', TESTO_ASSISTENZA: '👉 Per entrare nel Sito\n\n' + '👉 Hai dimenticato la password?\n\n', BENVENUTO: 'Benvenut@', TUE_NAVI: 'Ecco le tue Navi programmate', HAI_I_7_REQUISITI: 'PRIMI PASSI OK!\nHai i Primi Requisiti per Entrare nella Lista !', NON_HAI_I_7_REQUISITI: 'Attenzione!\nAncora non hai i 7 Requisiti per Entrare nella Lista !', INFO_LA_MIA_LAVAGNA: '✨ Lista dei Passi: ✨ \n', INFO_LAVAGNA_SITO_COMPLETARE: 'Per completare tutti i requisiti vai sul sito:\n%s\n👉🏻 Entra nella tua Lavagna.\n', INFO_LAVAGNA_SITO: 'Per vedere in dettaglio lo STATO, sul sito \n 👉🏻 Entra nella tua Lavagna.\n', INFO_LINK_DA_CONDIVIDERE: 'Link da condividere ai tuoi invitati per farli registrare al sito:\n\n%s', INFO_LINK_ZOOM: 'Link da condividere per partecipare allo Zoom (Conferenza OnLine):\n%s', ZOOM_CONFERENCE: 'Ecco il programma delle Conferenze (Zoom) aperti a TUTTI:', NON_VERIF: 'Non Verificata', VERIF: 'Verificata', EMAIL: 'Email', BOT: 'BOT', EMAIL_NON_VERIF: 'Email Non Verificata\nleggi la tua casella email e trova **"Confermare la Registrazione"**\ne 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', SCRITTO_SOGNO: 'Hai scritto il tuo Sogno', PAYMENTS: 'Modalità di Pagamento', 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 SUL LINK INDICATO', 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: "Complimenti! 🎊\nSei stato aggiunto alla Lista D'Imbarco !\nNei prossimi giorni riceverai un messaggio qui quando la tua Nave sarà pronta a partire.\nRicorda che per salire di graduatoria, puoi condividere il Movimento con i tuoi amici ❤️.", REGALATO_INVITANTE: 'da fare.... 😍🎊 Hai ricevuto in Regalo un Invitato {invitato} da parte di {mittente} !', 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 della nave {%s} cliccando qui: %s', SEND_LINK_CHAT_SOGNATORE: 'Ciao %s!\nOggi Diventi Sognatore !!! 🎊🎊🎊 Entra nella Gift Chat della nave {%s} cliccando qui: %s', ENTRA_GIFT_CHAT: 'Entra nella Gift Chat', DATA_PART_NAVE: 'data di Partenza della Nave:', SOGNATORE: 'SOGNATORE', INTERMEDIO: 'Intermedio', MEDIATORE: 'MEDIATORE', DONATORI: 'DONATORI', RITESSITURA: 'RITESSITURA', 'NAVE COMPLETATA': 'NAVE COMPLETATA', 'Doni Effettuati': 'Doni Effettuati', 'Facilitatore che affianchèra il Mediatore': 'Facilitatore che affianchèra il Mediatore', APERTURA_CHIUSURA_GIFT_CHAT: "%s: Apertura GIFT CHAT\n%s Chiusura GIFT CHAT\nNota Bene: Hai tempo 3 giorni dall'apertura per entrare in Chat ed effettuare il tuo Dono, dopodichè effettueremo la sostituzione.", 'Giorno di Apertura GIFT CHAT': 'Giorno di Apertura GIFT CHAT', 'Giorno in cui Inviare il DONO': 'Hai 3 giorni di tempo per inviare il tuo dono.\nGiorno di Chiusura', SPOSTATO: 'Sei stato Spostato in una Nuova Nave !', Note: 'Note', TEMPORANEA: 'TEMPORANEA', NAVE: 'NAVE', MSG_SEND_FROM: 'Msg Inviato da', ZOOM_CONFERMATO: 'Sei stato confermato ad aver visto la Video Conferenza di Benvenuto!', RICHIESTA_AMICIZIA: "🌈 Richiesta d'Amicizia da parte di %s", RICHIESTA_HANDSHAKE: '🌈 %s ha comunicato che ti conosce personalmente e ha fiducia in te.', ACCETTATO_SUL_GRUPPO: '✅ Sei stato accettato da %s a far parte del Gruppo %s', CREATO_NUOVO_GRUPPO: '✅ Hai appena creato un nuovo Gruppo chiamato %s', ACCETTATO_NOTIFICA_ADMINS: "✅ l'utente %s è stato accettato a far parte del Gruppo %s (da parte di %s)", GROUP_REQUEST: 'Richiesta di entrare nel Gruppo %s da parte di %s', CLICCA_QUI: 'CLICCA QUI', TELEFONO: 'Tel', }, si: {}, es: { "L'Email è già stata Verificata": 'El correo electrónico ya ha sido verificado', 'Nuova Registrazione': 'Nuevo Registro', 'Effettuata una Nuova Registrazione': 'Se ha realizado un nuevo registro', partecipanti: 'participantes', 'partecipanti a Pranzo': 'partecipanti a Pranzo', 'partecipanti a Cena': 'partecipanti a Cena', TESTO_ASSISTENZA: 'Para entrar en el sitio:\n%s\n\n' + '¿Olvidó su contraseña para acceder al sitio?\nhttps://freeplanet.app/requestresetpwd\n\n', BENVENUTO: 'Bienvenido', TUE_NAVI: 'Aquí están sus naves programadas', HAI_I_7_REQUISITI: '¡LOS PRIMEROS PASOS ESTÁN BIEN!\nTiene los primeros 7 requisitos para entrar en la lista de embarque!', NON_HAI_I_7_REQUISITI: '¡Atención!\nTodavía no tienes los 7 requisitos para entrar en la lista de embarque!', HAI_I_9_REQUISITI: '¡FELICITACIONES!\n¡Has completado los 9 pasos de la Guía! Gracias por ayudar a expandirse!', NON_HAI_I_9_REQUISITI: 'Recuerda que puedes ayudar a que el Movimiento crezca y se expanda compartiendo nuestro viaje con todos.!', INFO_LA_MIA_LAVAGNA: '✨ Lista de pasos: ✨ \n', INFO_LAVAGNA_SITO_COMPLETARE: 'Para completar todos los requisitos vaya al sitio:\n%s\nPara ver el estado de su nave y sus invitados,👉🏻 Pizarra.\n', INFO_LAVAGNA_SITO: 'Para ver en detalle el estado de su nave, en el sitio web, haga clic en las 3 líneas de la parte superior izquierda y vaya a "Pizarra"..\n', INFO_LINK_DA_CONDIVIDERE: 'Enlaces para compartir con sus invitados para que se registren en el sitio web:\n\n%s', INFO_LINK_ZOOM: 'Enlaces para compartir para participar en el Zoom (Conferencia en línea):\n%s', ZOOM_CONFERENCE: 'Aquí puedes encontrar las fechas de programación en el Zoom:', NON_VERIF: 'No verificado', VERIF: 'Verificado', EMAIL: 'Email', BOT: 'BOT', EMAIL_NON_VERIF: 'Correo electrónico no verificado\nlea su buzón y encuentre **"Confirmar Registro "** y haga clic en el botón **"Verificar Registro "**.', TELEGRAM_NOT_CONNECTED: 'Telegram no asociado a su cuenta!', NESSUN_INVITATO: 'No invitaste a nadie', ZOOM_PARTECIPATO: 'Participación en al menos 1 Conferencia (Zoom)', LINEE_GUIDA: 'Directrices aceptadas', VIDEO_INTRO: 'Ver el video', SCRITTO_SOGNO: 'Escribiste tu sueño', PAYMENTS: 'Métodos de pago', INVITATI: 'las personas registradas que usted invitó', INVITATI_ATTIVI: 'Invitado con los 7 requisitos', NONREG: 'Invitados no registrados', CLICCA_PER_ZOOM: 'AL DÍA Y HORA INDICADOS, PARA ENTRAR EN LA VIDEOCONFERENCIA, PULSE AQUÍ', CLICCA_ENTRA: 'HAGA CLIC AQUÍ PARA ENTRAR !', ZOOM_INIZIATO: 'ESTA CONFERENCIA HA COMENZADO!', SCEGLI_VOCE: 'elegir una voz:', INVITATI_LISTA: 'Sus invitados (en verde con al menos los 7 primeros requisitos)', CIAO: 'Hola', ADDED_TOLISTAINGRESSO: 'Has sido añadido a la lista de personas que entrarán en Lista de embarque!', NO_PROG: 'Actualmente no está en la lista de embarque.!', SEND_LINK_CHAT_DONATORI: 'Hola %s!\n¡Tu barco por fin está navegando!\nEntra en el Gift Chat haciendo clic aquí: %s', SEND_LINK_CHAT_SOGNATORE: '¡Hola!\n¡Hoy te conviertes en un soñador! 🎊🎊🎊 Entre en el Chat de Regalos de la nave {%s} haciendo clic aquí: %s', ENTRA_GIFT_CHAT: 'Entre en el Chat de Regalos', DATA_PART_NAVE: 'fecha de salida de la nave:', SOGNATORE: 'SOÑADOR', INTERMEDIO: 'Intermedio', MEDIATORE: 'MEDIATOR', DONATORI: 'DONANTES', RITESSITURA: 'RETEJIDO', 'NAVE COMPLETATA': 'NAVE COMPLETADA', 'Doni Effettuati': 'Regalos Realizados', 'Facilitatore che affianchèra il Mediatore': 'Facilitatore de apoyo al Donante', APERTURA_CHIUSURA_GIFT_CHAT: '%s: Apertura del CHAT DE REGALOS\n%s Cierre del CHAT DE REGALOS\nNota: Tienes 3 días desde la apertura para entrar en el Chat y hacer tu Regalo, después de lo cual haremos el reemplazo', SPOSTATO: 'Has sido trasladado a una nueva nave !', Note: 'Notas', TEMPORANEA: 'TEMPORAL', NAVE: 'NAVE', MSG_SEND_FROM: 'Mensaje enviado por', ZOOM_CONFERMATO: '¡Se ha confirmado que ha visto la Video Conferencia de Bienvenida!', RICHIESTA_AMICIZIA: "Richiesta d'Amicizia da parte di %s", ACCETTATO_SUL_GRUPPO: 'Sei stato accettato da %s a far parte del Gruppo %s', ACCETTATO_NOTIFICA_ADMINS: "l'utente %s è stato accettato a far parte del Gruppo %s (da parte di %s)", RICHIESTA_BLOCCO_GRUPPO: 'Richiesta di bloccare il Gruppo %s da parte di %s', }, enUs: { partecipanti: 'participants', 'partecipanti a Pranzo': 'partecipanti a Pranzo', 'partecipanti a Cena': 'partecipanti a Cena', TESTO_ASSISTENZA: 'To enter the Site:\n%s\n\nForgot your password to access the site?\n' + 'https://freeplanet.app/requestresetpwd\nChat AYNI BOT (this one):\nhttps://t.me/notevoleaynibot\n\n', BENVENUTO: 'Welcome', TUE_NAVI: 'Here are your programmed ships', HAI_I_7_REQUISITI: 'FIRST STEPS OK!\nYou have the First 7 Requirements to Enter the Boarding List!', NON_HAI_I_7_REQUISITI: 'Attention!\nYou still do not have the 7 requirements to enter the boarding list!', INFO_LA_MIA_LAVAGNA: '✨ Step List: ✨ \n', INFO_LAVAGNA_SITO_COMPLETARE: 'To complete all the requirements go to the site:%s\nTo see the status of your Ship and your guests\n👉🏻 Dashboard\n', INFO_LAVAGNA_SITO: 'To see in detail the status of your ship, on the website, click on the 3 lines at the top left and go to "Blackboard".\n', INFO_LINK_DA_CONDIVIDERE: 'Links to share with your guests to have them register on website:\n\n%s', INFO_LINK_ZOOM: 'Links to share to participate in Zoom (Online Conference):\n%s', ZOOM_CONFERENCE: 'Here you can find the Zoom Conference Planning:', NON_VERIF: 'Not Verified', VERIF: 'Verified', EMAIL: 'Email', BOT: 'BOT', EMAIL_NON_VERIF: 'Email Not Verified\nread your mailbox and find **"Confirm Registration "**
and click on the button **"Verify Registration "**.', TELEGRAM_NOT_CONNECTED: 'Telegram not associated with your account!', NESSUN_INVITATO: "You didn't invite anyone", ZOOM_PARTECIPATO: 'Participation in at least 1 Conference (Zoom)', LINEE_GUIDA: 'Guidelines Accepted', VIDEO_INTRO: 'Seen the Video', SCRITTO_SOGNO: 'You wrote your Dream', PAYMENTS: 'Methods of Payment', INVITATI: 'registered people you invited', INVITATI_ATTIVI: 'Guests with the 7 Requirements', NONREG: 'Non-registered Guests', CLICCA_PER_ZOOM: 'TO THE DAY AND TIME INDICATED, TO ENTER THE VIDEO-CONFERENCE, CLICK HERE', CLICCA_ENTRA: 'CLICK HERE TO ENTER !', ZOOM_INIZIATO: 'THIS CONFERENCE HAS BEGUN!', SCEGLI_VOCE: 'choose a menu item:', INVITATI_LISTA: 'Your Guests (in green with at least the first 7 requirements)', CIAO: 'Hi', ADDED_TOLISTAINGRESSO: 'You have been added to the List of people who will enter the Boarding List!', NO_PROG: 'You are not currently on the boarding list.!', SEND_LINK_CHAT_DONATORI: 'Hi %s!\nYour ship is finally sailing!\nEnter the Gift Chat by clicking here: %s', SEND_LINK_CHAT_SOGNATORE: "Hello %s!\nToday you become a Dreamer! 🎊🎊🎊 Enter the ship's Gift Chat {%s} by clicking here: %s", ENTRA_GIFT_CHAT: "Enter the ship's Gift Chat", DATA_PART_NAVE: 'date of departure of the ship:', SOGNATORE: 'DREAMER', INTERMEDIO: 'Intermediate', MEDIATORE: 'MEDIATOR', DONATORI: 'DONOR', RITESSITURA: 'RE-ENTER', 'NAVE COMPLETATA': 'SHIP COMPLETED', 'Doni Effettuati': 'Gifts Made', 'Facilitatore che affianchèra il Mediatore': 'Facilitatore supporting the Mediator', APERTURA_CHIUSURA_GIFT_CHAT: '%s: Opening GIFT CHAT\n%s Closing GIFT CHAT\nNote: You have 3 days from the opening to enter the Chat and make your Gift, after which we will make the replacement.', SPOSTATO: "You've been moved to a New Ship !", Note: 'Note', TEMPORANEA: 'TEMPORARY', NAVE: 'SHIP', MSG_SEND_FROM: 'Msg sent by', ZOOM_CONFERMATO: 'You have been confirmed to have seen the Welcome Video Conference!', RICHIESTA_AMICIZIA: "Richiesta d'Amicizia da parte di %s", ACCETTATO_SUL_GRUPPO: 'Sei stato accettato da %s a far parte del Gruppo %s', ACCETTATO_NOTIFICA_ADMINS: "l'utente %s è stato accettato a far parte del Gruppo %s (da parte di %s)", RICHIESTA_BLOCCO_GRUPPO: 'Richiesta di bloccare il Gruppo %s da parte di %s', }, fr: { "L'Email è già stata Verificata": 'Le courrier électronique a déjà été vérifié', 'Nuova Registrazione': 'Nouvelle inscription', 'Effettuata una Nuova Registrazione': 'Un nouvel enregistrement a été effectué', partecipanti: 'participants', 'partecipanti a Pranzo': 'partecipanti a Pranzo', 'partecipanti a Cena': 'partecipanti a Cena', TESTO_ASSISTENZA: 'Pour entrer sur le site:\n%s\n\n' + 'Vous avez oublié votre mot de passe pour accéder au site ?\nhttps://ayni.gifteconomy.app/requestresetpwd\n\n', BENVENUTO: 'Bienvenue', TUE_NAVI: 'Voici vos navires programmés', HAI_I_7_REQUISITI: "PREMIÈRES ÉTAPES OK!\nvous avez les 7 premiers Requis pour Entrer dans la liste d'embarquement!", NON_HAI_I_7_REQUISITI: "'Attention!\nVous ne remplissez pas encore les 7 conditions pour figurer sur la liste d'embarquement!", HAI_I_9_REQUISITI: "FÉLICITATIONS!\n!Vous avez franchi les 9 étapes de la conduite ! Merci d'avoir aidé à se développer!", NON_HAI_I_9_REQUISITI: "N'oubliez pas que vous pouvez aider le Mouvement à grandir et à se développer en partageant notre voyage avec tout le monde.!", INFO_LA_MIA_LAVAGNA: '✨ Liste des étapes: ✨ \n', INFO_LAVAGNA_SITO_COMPLETARE: 'Pour remplir toutes les conditions, rendez-vous sur le site:\n%s\nPour voir le statut de votre navire et de vos invités\n 👉🏻 Tableau.\n', INFO_LAVAGNA_SITO: 'Pour voir en détail le statut de votre navire, sur le site, cliquez sur les 3 lignes en haut à gauche et allez sur "Tableau".\n', INFO_LINK_DA_CONDIVIDERE: "Liens à partager avec vos invités pour qu'ils s'inscrivent sur le site web:\n\n%s", INFO_LINK_ZOOM: 'Liens à partager pour participer à Zoom (Conférence en ligne):\n%s', ZOOM_CONFERENCE: 'Vous trouverez ici les dates de programmation sur Zoom:', NON_VERIF: 'Non vérifié', VERIF: 'Vérifié', EMAIL: 'Courriel', BOT: 'BOT', EMAIL_NON_VERIF: 'Courriel non vérifié\nlisez votre boîte aux lettres et trouvez **"Confirmer l\'inscription "**
et cliquez sur le bouton **"Vérifier l\'inscription "**.', TELEGRAM_NOT_CONNECTED: 'Télégramme non associé à votre compte!', NESSUN_INVITATO: "Vous n'avez invité personne", ZOOM_PARTECIPATO: 'Participation à au moins 1 conférence (Zoom)', LINEE_GUIDA: 'Lignes directrices acceptées', VIDEO_INTRO: 'Voir la vidéo', SCRITTO_SOGNO: 'Vous avez écrit votre rêve', PAYMENTS: 'Modes de paiement', INVITATI: 'personnes inscrites que vous avez invitées', INVITATI_ATTIVI: 'Invité avec les 7 exigences', NONREG: 'Invités non enregistrés', CLICCA_PER_ZOOM: "AU JOUR ET À L'HEURE INDIQUÉS, POUR ENTRER DANS LA VIDÉOCONFÉRENCE, CLIQUEZ ICI", CLICCA_ENTRA: 'CLIQUEZ ICI POUR ENTRER !', ZOOM_INIZIATO: 'CETTE CONFÉRENCE A COMMENCÉ!', SCEGLI_VOCE: 'choisir une voix:', INVITATI_LISTA: 'Vos invités (en vert avec au moins les 7 premières exigences)', CIAO: 'Salut', ADDED_TOLISTAINGRESSO: "Vous avez été ajouté à la liste d'embarquement !", NO_PROG: "Vous n'êtes pas encore sur la liste d'embarquement.!", SEND_LINK_CHAT_DONATORI: 'Salut %s!\nVotre SHIP prend enfin la mer.!\nEntrez dans le Chat Cadeau en cliquant ici: %s', SEND_LINK_CHAT_SOGNATORE: "Bonjour %s !\nAujourd'hui, vous devenez un Rêveur ! 🎊🎊🎊 Entrez dans le chat des cadeaux du navire {%s} en cliquant ici : %s", ENTRA_GIFT_CHAT: 'Entrez dans le chat des cadeaux', DATA_PART_NAVE: 'la date de départ du navire:', SOGNATORE: 'Rêveur', INTERMEDIO: 'Intermediaire', MEDIATORE: 'Médiateur', DONATORI: 'DONATEUR', RITESSITURA: 'RETESSITURA', 'NAVE COMPLETATA': 'NAVIRE COMPLÉTÉ', 'Doni Effettuati': 'Don effectués', 'Facilitatore che affianchèra il Mediatore': 'Le tuteur qui soutient le Mediateur', APERTURA_CHIUSURA_GIFT_CHAT: "%s : Chat d'ouverture\n%s Clôture du GIFT CHAT\nNote: Vous avez 3 jours à partir de l'ouverture pour entrer dans le Chat et faire votre Cadeau, après quoi nous ferons le remplacement", SPOSTATO: 'Vous avez été transféré sur un nouveau navire !', Note: 'Notes', TEMPORANEA: 'TEMPORAIRE', NAVE: 'NAVIRE', MSG_SEND_FROM: 'Message envoyé par', ZOOM_CONFERMATO: 'Vous avez été confirmé comme ayant vu la vidéoconférence de bienvenue !', RICHIESTA_AMICIZIA: "Richiesta d'Amicizia da parte di %s", ACCETTATO_SUL_GRUPPO: 'Sei stato accettato da %s a far parte del Gruppo %s', ACCETTATO_NOTIFICA_ADMINS: "l'utente %s è stato accettato a far parte del Gruppo %s (da parte di %s)", RICHIESTA_BLOCCO_GRUPPO: 'Richiesta di bloccare il Gruppo %s da parte di %s', }, pt: { "L'Email è già stata Verificata": '', 'Nuova Registrazione': 'Novo Registo', 'Effettuata una Nuova Registrazione': 'Foi efectuado um novo registo', partecipanti: 'participantes', 'partecipanti a Pranzo': 'partecipanti a Pranzo', 'partecipanti a Cena': 'partecipanti a Cena', TESTO_ASSISTENZA: 'Para entrar no site:\n%s\n\n' + 'Esqueceu sua senha para acessar o site?\nhttps://freeplanet.app/requestresetpwd\n\n', BENVENUTO: 'Bem-vindo', TUE_NAVI: 'Aqui estão os seus navios programados', HAI_I_7_REQUISITI: 'PRIMEIROS PASSOS OK!\nVocê tem os 7 primeiros requisitos para entrar na lista de embarque!', NON_HAI_I_7_REQUISITI: 'Atenção!\nVocê ainda não tem os 7 requisitos para entrar na lista de embarque!', INFO_LA_MIA_LAVAGNA: '✨ Lista de etapas: ✨ \n', INFO_LAVAGNA_SITO_COMPLETARE: 'Para completar todos os requisitos ir para o sitio:\n%s\nPara ver o estado do seu navio e dos seus convidados:\n 👉🏻 Entre no seu Tablero.\n', INFO_LAVAGNA_SITO: 'Para ver em detalhe o estado do seu navio, no site, clique nas 3 linhas no canto superior esquerdo e vá para "DashBoard"..\n', INFO_LINK_DA_CONDIVIDERE: 'Links para partilhar com os seus convidados para que se registem no website:\n\n%s', INFO_LINK_ZOOM: 'Links para partilhar para participar na Zoom (Conferência Online):\n%s', ZOOM_CONFERENCE: 'Aqui está o programa das Conferências (Zoom) aberto a TODOS:', NON_VERIF: 'Não verificado', VERIF: 'Verificado', EMAIL: 'Email', BOT: 'BOT', EMAIL_NON_VERIF: 'Email Não verificado\nleia a sua caixa de correio e encontre **"Confirmar o registo"**
e clique no botão **"Verificação do registo"**', TELEGRAM_NOT_CONNECTED: 'Telegrama não associado à sua conta!', NESSUN_INVITATO: 'Você não convidou ninguém', ZOOM_PARTECIPATO: 'Participação em pelo menos 1 Conferência (Zoom)', LINEE_GUIDA: 'Directrizes Aceites', VIDEO_INTRO: 'Ver o vídeo', SCRITTO_SOGNO: 'Você escreveu o seu sonho', PAYMENTS: 'Formas de pagamento', INVITATI: 'pessoas registadas que convidou', INVITATI_ATTIVI: 'Convidado com os 7 Requisitos', NONREG: 'Convidados não registados', CLICCA_PER_ZOOM: 'PARA O DIA E HORA INDICADOS, PARA ENTRAR NA VÍDEO-CONFERÊNCIA, CLIQUE AQUI', CLICCA_ENTRA: 'CLIQUE AQUI PARA ENTRAR !', ZOOM_INIZIATO: 'ESTA CONFERÊNCIA JÁ COMEÇOU!', SCEGLI_VOCE: 'escolha uma voz:', INVITATI_LISTA: 'Os seus convidados (em verde com, pelo menos, os 7 primeiros requisitos)', CIAO: 'Olá', ADDED_TOLISTAINGRESSO: 'Foi acrescentado à Lista de Embarque !', NO_PROG: 'Actualmente, ainda não consta da lista de embarque.!', SEND_LINK_CHAT_DONATORI: 'Olà %s!\nO seu SHIP está finalmente a zarpar.!\nEntre no Gift Chat, clicando aqui: %s', SEND_LINK_CHAT_SOGNATORE: 'Olá %s!\nHoje você se torna um sonhador! 🎊🎊🎊 Entre no Gift Chat do navio {%s} clicando aqui: %s', ENTRA_GIFT_CHAT: 'Entre no Gift Chat do navio', DATA_PART_NAVE: 'data de partida do navio:', SOGNATORE: 'SONHEIROS', INTERMEDIO: 'Intermediar', MEDIATORE: 'MEDIATOR', DONATORI: 'DONATORES', RITESSITURA: 'ENTRE EM', 'NAVE COMPLETATA': 'NAVIO COMPLETADO', 'Doni Effettuati': 'Regalo Feitos', 'Facilitatore che affianchèra il Mediatore': 'Facilitatore que apoia o Mediator', APERTURA_CHIUSURA_GIFT_CHAT: '%s: Abertura do GIFT CHAT\n%s Fechamento GIFT CHAT\nNota: Você tem 3 dias desde a abertura para entrar no Chat e fazer o seu Presente, depois do qual faremos o substituição.', SPOSTATO: 'Você foi transferido para um novo navio !', Note: 'Notas', TEMPORANEA: 'TEMPORÁRIO', NAVE: 'NAVE', MSG_SEND_FROM: 'Mensagem enviada por', ZOOM_CONFERMATO: 'Foi-lhe confirmado que assistiu à Conferência de Vídeo de Boas-vindas!', RICHIESTA_AMICIZIA: "Richiesta d'Amicizia da parte di %s", ACCETTATO_SUL_GRUPPO: 'Sei stato accettato da %s a far parte del Gruppo %s', ACCETTATO_NOTIFICA_ADMINS: "l'utente %s è stato accettato a far parte del Gruppo %s (da parte di %s)", RICHIESTA_BLOCCO_GRUPPO: 'Richiesta di bloccare il Gruppo %s da parte di %s', }, }; module.exports = { MYAPPS: [], INITDB_FIRSTIME: true, ACAPO: '\n', ENABLE_CRONTAB: 'CRONTAB', UPDATE_GRADUATORIA: 'UPDATE_GRAD', LANGADMIN: 'it', FREEPLANET: '1', AYNI: '7', CNM: '10', RISO: '13', FIOREDELLAVITA: '15', PIUCHEBUONO: '17', MACRO: '18', IDAPP_BOTONGROUP: '1000', HELP_CHAT: '', TYPECONF_ZOOM: 'zoom', TYPECONF_JITSI: 'jitsi', APORTADOR_NONE: '------', SEP: '|', TYPE_PROJECT: 1, TYPE_TODO: 2, TipoMsg: { SEND_LINK_CHAT_DONATORI: 1, SEND_MSG: 2, SEND_MSG_SINGOLO: 3, SEND_TO_ALL: 10, SEND_MSG_EFFETTUA_IL_DONO: 1000, SEND_MSG_SOLLECITO_DONATORI_NO_DONO: 1005, SEND_MSG_A_MEDIATORI: 1010, SEND_MSG_A_SOGNATORE: 1020, SEND_MSG_A_UTENTE_SOSTITUITO: 1030, SEND_MSG_DONO_RICEVUTO_CORRETTAMENTE: 1040, SEND_MSG_DONO_NON_RICEVUTO: 1050, }, Perm: { PERM_NONE: 0, PERM_FRIEND: 1, PERM_ALL: 10, }, 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, exact: 2048, image: 3000, image_and_filename: 3100, nationality: 4096, intcode: 5000, multioption: 6000, onlydate: 7000, hours: 8000, crypted: 9000, }, MAX_PHASES: 5, FIRST_PROJ: '__PROJECTS', EXECUTE_CALCPROJ: true, isDirectoryAsync: async function (dir) { try { const stats = await fs.promises.stat(dir); return stats.isDirectory(); } catch (e) { return false; } }, isFileExistsAsync: async function (filename) { try { let fileExists = await fs.promises .stat(filename) .then(() => true) .catch(() => false); // console.log(filename, 'esiste', fileExists) return fileExists; } catch (e) { // console.log(filename, 'esiste', 'FALSE') return false; } }, gettranslate: function (text, lang) { try { return textlang[lang][text]; } catch (e) { return textlang['it'][text]; } }, getlangbyres: function (res) { // ++Todo: res estrarre la lingua let lang = ''; try { lang = res.lang; } catch (e) {} if (!lang) { lang = 'it'; } return lang; }, get__: function (text, lang) { try { return textlang[lang][text]; } catch (e) { return textlang['it'][text]; } }, getres__: function (text, res) { let lang = this.getlangbyres(res); 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', ]; }, allfieldSendNotif: function () { return [ 'type', 'userId', 'sender', 'typedir', 'typeid', 'dest', 'descr', 'title', 'openUrl', 'datenotif', 'date_updated', 'read', 'deleted', 'idapp', 'tablerec', 'extrafield', 'tag', 'options', 'idrec', 'status', ]; }, allfieldTodo: function () { return [ 'userId', 'pos', 'category', 'descr', 'note', 'priority', 'statustodo', 'assignedToUsers', 'created_at', 'groupId', 'modify_at', 'completed_at', 'expiring_at', 'enableExpiring', 'progress', 'modified', 'phase', 'assigned_to_userId', 'assignedToUsers', 'hoursplanned', 'hoursworked', 'start_date', 'themecolor', 'themebgcolor', ]; }, allfieldMyEvent: function () { return ['userId']; }, allfieldTodoWithId: function () { return ['_id', ...this.allfieldTodo()]; }, // #TODO Projects++ Add fields ... allfieldProject: function () { return [ 'idapp', 'userId', 'respUsername', 'viceRespUsername', 'pos', 'typeproj', 'id_main_project', 'id_parent', 'descr', 'longdescr', 'groupId', 'hoursplanned', 'hoursleft', 'themecolor', 'themebgcolor', 'hoursworked', 'priority', 'statusproj', 'created_at', 'modify_at', 'completed_at', 'expiring_at', 'enableExpiring', 'progressCalc', 'modified', 'live_url', 'test_url', 'begin_development', 'begin_test', 'totalphases', 'actualphase', 'hoursweeky_plannedtowork', 'endwork_estimate', 'privacyread', 'privacywrite', 'tipovisu', 'view', ]; }, allfieldBooking: function () { return [ 'idapp', 'userId', 'username', 'id_bookedevent', 'tableType', 'numpeople', 'numpeopleLunch', 'numpeopleDinner', 'numpeopleDinnerShared', 'msgbooking', 'modified', 'infoevent', 'datebooked', 'booked', ]; }, allfieldBookingChange: function () { return [ 'numpeople', 'numpeopleLunch', 'numpeopleDinner', 'numpeopleDinnerShared', 'msgbooking', 'modified', 'infoevent', 'datebooked', 'booked', ]; }, allfieldProjectWithId: function () { return ['_id', ...this.allfieldProject()]; }, jsonCopy(src) { return JSON.parse(JSON.stringify(src)); }, CloneRecordToNew(src, modelTable) { const myrec = Object.assign({}, src); delete myrec._doc['_id']; myrec._id = new ObjectId(); if (modelTable === 'Circuit') { myrec._doc.name = myrec._doc.name + ' copia'; myrec._doc.path = myrec._doc.path + '_copia'; } return myrec._doc; }, sendBackNotif: async function (subscription, payload) { const Subscription = require('../models/subscribers'); // console.log('sendBackNotif:', subscription, payload); const pushOptions = { vapidDetails: { subject: process.env.VAPI_KEY_SUBJECT, privateKey: process.env.PRIVATE_VAPI_KEY, publicKey: process.env.PUBLIC_VAPI_KEY, }, TTL: payload.ttl, headers: {}, }; // Pass object into sendNotification return ( webpush .sendNotification(subscription._doc, JSON.stringify(payload), pushOptions) .catch((err) => { if (err.statusCode === 410) { // Gone: is not valid anymore (Expired probably!), so I have to delete from my db return Subscription.findOneAndDelete({ _id: subscription._id }); } else { console.log('Subscription is no longer valid: ', err); } }) .then((ris) => {}) // console.log('sendNotification', ris); .catch((err) => { console.error(err); }) ); }, sendNotificationToUser: async function (userId, title, content, openUrl, openUrl2, tag, actions, id) { const Subscription = require('../models/subscribers'); content = this.convertHTMLtoText(content); content = this.ConvertHTMLToPlainText(content); let payload = { actions, title: title, content, url: openUrl, url2: openUrl2, tag, id, // ttl: req.body.ttl, // icon: req.body.icon, // image: req.body.image, // badge: req.body.badge, // tag: req.body.tag }; try { let subscriptions = []; try { subscriptions = await Subscription.find({ userId }); } catch (err) { console.error(`Error occurred while getting subscriptions`); // res.status(500).json({ // error: 'Technical error occurred' // }); //++ Rimuovi questo record !? return false; } let conta = 0; if (subscriptions && subscriptions.length > 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.VAPI_KEY_SUBJECT, process.env.PUBLIC_VAPI_KEY, process.env.PRIVATE_VAPI_KEY, 'aes128gcm' ); const pushOptions = { vapidDetails: { subject: process.env.VAPI_KEY_SUBJECT, 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); const pushPayload = JSON.stringify(payload); webpush .sendNotification(pushSubscription, pushPayload, pushOptions) .then((value) => { // console.log('Invio Push', value); resolve({ status: true, endpoint: subscription.endpoint, data: value, }); }) .catch(async (err) => { console.error('err Push', err.body); if (err.body) { // Cancella dal DB la notifica Push, visto che da errore! (sarà scaduto) const ris = await Subscription.deleteOne({ _id: subscription._id }); } reject({ status: false, endpoint: subscription.endpoint, data: err, }); }); }).catch((error) => { console.log('ERROR: sendNotificationToUser', error.data.body ? error.data.body : error); }); }); return true; } // q.allSettled(parallelSubscriptionCalls).then((pushResults) => { // console.info(pushResults); // }); // res.json({ // data: 'Push triggered' // }); } catch (e) { console.error('sendNotificationToUser', e.message); } }, getReqByPar(idapp, usernameOrig, groupOrig) { return { body: { idapp: idapp, }, user: { username: usernameOrig, groupOrig, }, }; }, sendNotificationByUsername: async function (idapp, username, cmd, telegram, usernameOrig, recObjCreator) { var { User } = require('../models/user'); const { SendNotif } = require('../models/sendnotif'); const telegrambot = require('../telegram/telegrambot'); const user = await User.findOne({ idapp, username }, { _id: 1, username: 1, lang: 1 }).lean(); if (!user) return; let userId = user._id; let lang = user.lang; let sendmynotif = true; let title = this.getNomeAppByIdApp(idapp); let descr = ''; let openUrl = '/'; let tag = ''; let actions = []; let domanda = ''; let keyb = null; if (cmd) { if (cmd === shared_consts.FRIENDSCMD.REQFRIEND) { descr = printf(this.get__('RICHIESTA_AMICIZIA', lang), usernameOrig); openUrl = '/my/' + usernameOrig; tag = 'reqfriends'; const userrecDest = await User.getUserShortDataByUsername(idapp, usernameOrig); if (userrecDest) { sendmynotif = false; // non lo rimandare 2 volte ! // SEND TELEGRAM NOTIFICATION telegrambot.askConfirmationUserFriend( idapp, shared_consts.CallFunz.RICHIESTA_AMICIZIA, userrecDest, username, usernameOrig ); } } else if (cmd === shared_consts.FRIENDSCMD.SETHANDSHAKE) { const userrecDest = await User.getUserShortDataByUsername(idapp, usernameOrig); const foundIfAlready = await User.isMyHandShake(idapp, username, usernameOrig); if (!foundIfAlready) { telegrambot.askConfirmationUserFriend( idapp, shared_consts.CallFunz.RICHIESTA_HANDSHAKE, userrecDest, username, usernameOrig ); } } } if (userId) { // SEND PUSH NOTIFICATION await this.sendNotificationToUser(userId, title, descr, openUrl, '', tag, actions); } if (telegram && sendmynotif) { const idtelegram = await User.TelegIdByUsername(idapp, username); await telegrambot.sendMsgTelegramByIdTelegram( idapp, idtelegram, descr + domanda, undefined, undefined, true, keyb ); } }, sendMsgTelegramToAdmin: async function (idapp, msg) { const telegrambot = require('../telegram/telegrambot'); const idtelegram = telegrambot.ADMIN_IDTELEGRAM_SERVER; await telegrambot.sendMsgTelegramByIdTelegram(idapp, idtelegram, msg); }, sendNotifAndMsgTelegram: async function (idapp, userId, objmsg, telegram, msgextrateleg) { if (userId) { await this.sendNotificationToUser( userId, objmsg.title, objmsg.descr, objmsg.openUrl, '', objmsg.tag, objmsg.actions ); } if (telegram) { var { User } = require('../models/user'); const telegrambot = require('../telegram/telegrambot'); const idtelegram = await User.TelegIdById(idapp, userId); const msgteleg = objmsg.descr + (msgextrateleg ? '\n' + msgextrateleg : ''); await telegrambot.sendMsgTelegramByIdTelegram(idapp, idtelegram, msgteleg); } }, sendNotifGroupByUsername: async function ( cmd, idapp, usernameOrig, usernameDest, username_action, groupname, myrecgroup, isAdmin, username_worked ) { const { SendNotif } = require('../models/sendnotif'); const { User } = require('../models/user'); const telegrambot = require('../telegram/telegrambot'); const req = this.getReqByPar(idapp, usernameOrig); const user = await User.findOne({ idapp, username: usernameDest }, { _id: 1, lang: 1 }); if (user) { let lang = user.lang; let paramsObj = { usernameDest, groupnameDest: groupname, username_action: username_action, singleadmin_username: usernameDest, options: 0, lang, isAdmin, username_worked, }; let sendnotif = true; let typedir = shared_consts.TypeNotifs.TYPEDIR_GROUPS; let typeid = 0; let onlysave = false; let numuseringroup = await User.countUsersInGroup(idapp, groupname); if (cmd) { if (cmd === shared_consts.GROUPSCMD.SETGROUP) { if (myrecgroup && myrecgroup.createdBy === usernameDest && numuseringroup <= 1) { typeid = shared_consts.TypeNotifs.ID_GROUP_NEW_REC; } else { typeid = shared_consts.TypeNotifs.ID_GROUP_ACCEPTED; } } else if (cmd === shared_consts.GROUPSCMD.REFUSE_REQ_GROUP) { typeid = shared_consts.TypeNotifs.ID_GROUP_REFUSED; } else if (cmd === shared_consts.GROUPSCMD.REMOVE_FROM_MYGROUP) { typeid = shared_consts.TypeNotifs.ID_GROUP_REMOVED; } else if (cmd === shared_consts.GROUPSCMD.REQGROUP) { typeid = shared_consts.TypeNotifs.ID_GROUP_REQUEST_TO_ENTER; // paramsObj.options = MessageOptions.Notify_OnlyToNotifinApp + MessageOptions.Notify_ByBotTelegram; const myuserdata = await User.getUserShortDataByUsername(idapp, username_action); telegrambot.askConfirmationUser( idapp, shared_consts.CallFunz.RICHIESTA_GRUPPO, myuserdata, usernameDest, groupname, myrecgroup._id ); onlysave = false; } else if (cmd === shared_consts.GROUPSCMD.BLOCK_USER) { typeid = shared_consts.TypeNotifs.ID_GROUP_BLOCK_USER; } else if (cmd === shared_consts.GROUPSCMD.DELETE_GROUP) { typeid = shared_consts.TypeNotifs.ID_GROUP_DELETE_USER; } else if (cmd === shared_consts.GROUPSCMD.ADDADMIN_OFMYGROUP) { typeid = shared_consts.TypeNotifs.ID_GROUP_ADDED_ADMIN_OFMYGROUP; } else if (cmd === shared_consts.GROUPSCMD.REMOVEADMIN_OFMYGROUP) { typeid = shared_consts.TypeNotifs.ID_GROUP_REMOVED_ADMIN_OFMYGROUP; } } if (sendnotif && typeid > 0) { // CREATE NOTIFICATION IN TABLE SENDNOTIF await SendNotif.createNewNotifToSingleUser(req, null, paramsObj, onlysave, typedir, typeid); } } }, sendNotifCircuitByUsername: async function ( cmd, idapp, usernameOrig, groupOrig, usernameDest, groupDest, username_action, circuitname, path, myreccircuit, isAdmin, username_worked, extrarec ) { const { SendNotif } = require('../models/sendnotif'); const { User } = require('../models/user'); const telegrambot = require('../telegram/telegrambot'); const { MyGroup } = require('../models/mygroup'); const { Circuit } = require('../models/circuit'); const req = this.getReqByPar(idapp, usernameOrig, groupOrig); let arrris = []; const userOrig = await User.findOne( { idapp, username: usernameOrig }, { _id: 1, lang: 1, aportador_solidario: 1, name: 1, surname: 1, username: 1 } ); const user = await User.findOne({ idapp, username: usernameDest }, { _id: 1, lang: 1 }); let lang = 'it'; if (user) { lang = user.lang; } let ris = null; try { let paramsObj = { usernameDest, circuitnameDest: circuitname, path, username_action: username_action, singleadmin_username: usernameDest, extrarec, options: 0, lang, isAdmin, username_worked, }; let sendnotif = true; let typedir = shared_consts.TypeNotifs.TYPEDIR_CIRCUITS; let typeid = 0; let onlysave = false; let numuserincircuit = await User.countUsersInCircuit(idapp, circuitname); const mycircuit = await Circuit.findOne({ name: circuitname }).lean(); if (mycircuit && extrarec) { extrarec.fido_scoperto_default = mycircuit.fido_scoperto_default; extrarec.fido_scoperto_default_grp = mycircuit.fido_scoperto_default_grp; } if (cmd) { if (cmd === shared_consts.CIRCUITCMD.SET) { if (myreccircuit && myreccircuit.createdBy === usernameDest && numuserincircuit <= 1) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_NEW_REC; } else { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_ACCEPTED; } } else if (cmd === shared_consts.CIRCUITCMD.REFUSE_REQ) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_REFUSED; } else if (cmd === shared_consts.CIRCUITCMD.REMOVE_FROM_MYLIST) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_REMOVED; } else if (cmd === shared_consts.CIRCUITCMD.REQ) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_REQUEST_TO_ENTER; // paramsObj.options = MessageOptions.Notify_OnlyToNotifinApp + MessageOptions.Notify_ByBotTelegram; const myuserdata = await User.getUserShortDataByUsername(idapp, username_action); let cmdrichiesta = shared_consts.CallFunz.RICHIESTA_FIDO; if (mycircuit && mycircuit.askManagerToEnter) { cmdrichiesta = shared_consts.CallFunz.RICHIESTA_CIRCUIT; } telegrambot.askConfirmationUser( idapp, cmdrichiesta, myuserdata, usernameDest, circuitname, myreccircuit._id, '', extrarec.groupname ); if (mycircuit.sendEmailAfterAskingToEnter) { const { Circuit } = require('../models/circuit'); const path = await Circuit.getPathByCircuitName(idapp, circuitname); let myapp = this.getHostByIdApp(idapp); let linkcirc = myapp + path; let messaggio = ''; let mytitle = i18n.__('CIRCUIT_REQUEST_TO_ENTER_ASKMANAGER_TITLE', usernameOrig); messaggio = i18n.__( 'CIRCUIT_REQUEST_TO_ENTER_ASKMANAGER_SHORT', usernameOrig, '' + circuitname + '', numuserincircuit, userOrig.aportador_solidario ); messaggio += '\n\n'; messaggio += 'Clicca qui per entrare sul Circuito\n'; const sendemail = require('../sendemail'); const email = myuserdata.email; sendemail.sendEmail_ByText(lang, email, myuserdata, idapp, { emailbody: messaggio, emailtitle: mytitle, }); } onlysave = false; } else if (cmd === shared_consts.CIRCUITCMD.ADDADMIN) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_ADDED_ADMIN; } else if (cmd === shared_consts.CIRCUITCMD.SETFIDO) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_SETFIDO; } else if (cmd === shared_consts.CIRCUITCMD.REMOVEADMIN) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_REMOVED_ADMIN; } else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_REQ) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ; } else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_REQ_SENT) { // Crea l'ID di Transazione paramsObj.idTransaction = new ObjectId(); typeid = shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ_SENT; } else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_ACCEPT) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_COINS_ACCEPTED; } else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_ACCEPT_SENT) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_COINS_ACCEPTED_SENT; // } else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_REFUSE) { // typeid = shared_consts.TypeNotifs.ID_CIRCUIT_COINS_REFUSED; //} else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_REFUSE_SENT) { // typeid = shared_consts.TypeNotifs.ID_CIRCUIT_COINS_REFUSED_SENT; } } if (sendnotif && typeid > 0) { const groupDestoContoCom = groupDest ? groupDest : extrarec && extrarec.contoComDest ? extrarec.contoComDest : ''; // Check if is group: if ( groupDestoContoCom && cmd !== shared_consts.CIRCUITCMD.SENDCOINS_ACCEPT_SENT && cmd !== shared_consts.CIRCUITCMD.SENDCOINS_REFUSE_SENT ) { let arrusers = await MyGroup.getListAdminsByGroupName(idapp, groupDestoContoCom); if (arrusers.length <= 0) arrusers = await Circuit.getListAdminsByCircuitPath(idapp, groupDestoContoCom); let notiftoUpdate = ''; let findrecnotif = await SendNotif.findOne({ _id: paramsObj.extrarec.notifId }).lean(); notiftoUpdate = findrecnotif ? findrecnotif.extrarec.notifIdToUpdate : ''; if (findrecnotif) { let arrrec = []; if (notiftoUpdate) arrrec = await SendNotif.find({ 'extrarec.notifIdToUpdate': notiftoUpdate }); for (let rec of arrrec) { paramsObj.usernameDest = rec.dest; paramsObj.sender = rec.sender; if ( cmd === shared_consts.CIRCUITCMD.SENDCOINS_ACCEPT || cmd === shared_consts.CIRCUITCMD.SENDCOINS_REFUSE ) { try { paramsObj.extrarec.notifId = rec._id; } catch (e) {} } ris = await SendNotif.createNewNotifToSingleUser(req, null, paramsObj, onlysave, typedir, typeid); if (!ris) { console.error( 'Errore createNewNotifToSingleUser! ', paramsObj.usernameDest, 'dest ->', groupDestoContoCom ); } else { arrris.push(ris._id); } } } else { for (let i = 0; i < arrusers.length; i++) { paramsObj.usernameDest = arrusers[i].username; ris = await SendNotif.createNewNotifToSingleUser(req, null, paramsObj, onlysave, typedir, typeid); if (!ris) { console.error( 'Errore createNewNotifToSingleUser! ', paramsObj.usernameDest, 'dest ->', groupDestoContoCom ); } else { arrris.push(ris._id); } } } } else { // CREATE NOTIFICATION IN TABLE SENDNOTIF ris = await SendNotif.createNewNotifToSingleUser(req, null, paramsObj, onlysave, typedir, typeid); if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_ACCEPT || cmd === shared_consts.CIRCUITCMD.SENDCOINS_REFUSE) { if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_ACCEPT) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_COINS_ACCEPTED_SENT; } else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_REFUSE) { typeid = shared_consts.TypeNotifs.ID_CIRCUIT_COINS_REFUSED_SENT; } let notiftoUpdate = ''; let findrecnotif = await SendNotif.findOne({ _id: paramsObj.extrarec.notifId }).lean(); notiftoUpdate = findrecnotif ? findrecnotif.extrarec.notifIdToUpdate : ''; arrnotiftoUpdate = findrecnotif ? findrecnotif.extrarec.arrnotifIdToUpdate : ''; if (findrecnotif && notiftoUpdate && arrnotiftoUpdate) { for (let myid of arrnotiftoUpdate) { let rec = await SendNotif.findOne({ _id: myid }).lean(); if (rec && rec.status === 0) { paramsObj.usernameDest = rec.dest; paramsObj.extrarec.idStatusToSent = rec._id; ris = await SendNotif.createNewNotifToSingleUser(req, null, paramsObj, onlysave, typedir, typeid); if (!ris) { console.error( 'Errore createNewNotifToSingleUser! ', paramsObj.usernameDest, 'dest ->', groupDestoContoCom ); } } } } } } } return { recnotif: ris, arrris }; } catch (e) { console.log(e.message); } }, sendNotificationByGroupname: async function (idapp, usernameOrig, groupname, cmd, value, telegram, username_action) { const { MyGroup } = require('../models/mygroup'); const { User } = require('../models/user'); const group = await MyGroup.findOne({ idapp, groupname }, { _id: 1, admins: 1, createdBy: 1 }).lean(); if (!group) return; let giainviato = false; try { // SEND TO THE ADMINS THE NOTIFICATIONS for (const singleadmin of group.admins) { try { if (singleadmin.username) { if (usernameOrig === singleadmin.username) giainviato = true; await this.sendNotifGroupByUsername( cmd, idapp, usernameOrig, singleadmin.username, username_action, groupname, group, true ); } } catch (e) { console.error('sendNotificationByGroupname', e); } } if (!giainviato && cmd !== shared_consts.GROUPSCMD.REQGROUP) { // SEND TO THE USER THE NOTIFICATION await this.sendNotifGroupByUsername( cmd, idapp, usernameOrig, usernameOrig, username_action, groupname, null, false ); } } catch (e) { console.error('e', e); } }, getAdminsByCircuit(circuit) { // return circuit.admins return [...circuit.admins, { username: shared_consts.USER_ADMIN_CIRCUITS }]; }, sendNotificationByCircuit: async function ( idapp, usernameOrig, circuitname, cmd, value, telegram, username_action, extrarec ) { const { Circuit } = require('../models/circuit'); const { SendNotif } = require('../models/sendnotif'); const circuit = await Circuit.findOne( { idapp, name: circuitname }, { _id: 1, admins: 1, createdBy: 1, path: 1 } ).lean(); if (!circuit) return; let giainviato = false; try { // SEND TO THE ADMINS THE NOTIFICATIONS let ris = false; let inviato = false; let arrris = []; if ( cmd === shared_consts.CIRCUITCMD.SENDCOINS_REQ || cmd === shared_consts.CIRCUITCMD.SENDCOINS_ACCEPT || cmd === shared_consts.CIRCUITCMD.SENDCOINS_REFUSE ) { groupOrig = extrarec.grouporig; let recnotif = null; if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_REQ) { // msg al Mittente (o mittenti del 'groupOrig') "Stai inviando X RIS" let res = await this.sendNotifCircuitByUsername( shared_consts.CIRCUITCMD.SENDCOINS_REQ_SENT, idapp, extrarec.dest, extrarec.groupdest, usernameOrig, groupOrig, username_action, circuitname, circuit.path, null, false, '', extrarec ); if (res) { recnotif = res.recnotif; arrris = res.arrris; } } else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_ACCEPT) { // msg ai MITTENTI: "X RIS sono stati accettati da Destinatario" await this.sendNotifCircuitByUsername( shared_consts.CIRCUITCMD.SENDCOINS_ACCEPT_SENT, idapp, extrarec.dest, extrarec.groupdest, usernameOrig, groupOrig, username_action, circuitname, circuit.path, null, false, '', extrarec ); } else if (cmd === shared_consts.CIRCUITCMD.SENDCOINS_REFUSE) { await this.sendNotifCircuitByUsername( shared_consts.CIRCUITCMD.SENDCOINS_REFUSE_SENT, idapp, extrarec.dest, extrarec.groupdest, usernameOrig, groupOrig, username_action, circuitname, circuit.path, null, false, '', extrarec ); } if (recnotif) extrarec.notifIdToUpdate = recnotif._id; if (arrris) extrarec.arrnotifIdToUpdate = arrris; let usernametoOrigUse = usernameOrig; if (extrarec.groupname) { usernametoOrigUse = ''; } ris = await this.sendNotifCircuitByUsername( cmd, idapp, usernametoOrigUse, groupOrig, extrarec.dest, extrarec.groupdest, username_action, circuitname, circuit.path, null, false, '', extrarec ); if (arrris && ris && ris.recnotif) { for (const rec of arrris) { let obj = { 'extrarec.notifIdToUpdate': ris.recnotif._id, }; await SendNotif.findOneAndUpdate({ _id: rec._id }, { $set: obj }, { new: false }); } } extrarec.notifIdToUpdate = ''; if (ris.recnotif) inviato = true; // ++Todo: Inviare anche agli Admin ?! } else { const groupOrig = ''; //++Todo: extrarec.groupOrig for (const singleadmin of this.getAdminsByCircuit(circuit)) { try { if (singleadmin.username) { if (usernameOrig === singleadmin.username) giainviato = true; await this.sendNotifCircuitByUsername( cmd, idapp, usernameOrig, groupOrig, singleadmin.username, '', username_action, circuitname, circuit.path, circuit, true, '', extrarec ); inviato = true; } } catch (e) { console.error('sendNotificationByCircuit', e); } } if (!giainviato && cmd !== shared_consts.CIRCUITCMD.REQ) { // SEND TO THE USER DEST THE NOTIFICATION ris = await this.sendNotifCircuitByUsername( cmd, idapp, usernameOrig, groupOrig, usernameOrig, '', username_action, circuitname, circuit.path, null, false, '', extrarec ); if (ris && ris.recnotif) inviato = true; } } if (inviato) { if (arrris && arrris.length > 0) { for (const notif of arrris) { await SendNotif.updatePendingTransactions(notif); } } else { if (ris) { await SendNotif.updatePendingTransactions(ris.recnotif); } } } return { ris: ris.recnotif, inviato }; } catch (e) { console.error('sendNotificationByCircuit: ', e); return { ris: null, inviato: false }; } }, // ********************** // 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 = item._id.toString(); // console.log('currentId', currentId); sortedList.push(item); } else { map.set(item.id_prev.toString(), 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 = nextItem._id.toString(); } 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; }, */ async sendNotifToCircuitsAdmin(idapp, circuit, alsotelegram, title, msg, tag = '') { const { User } = require('../models/user'); const telegrambot = require('../telegram/telegrambot'); if (!circuit || !this.getAdminsByCircuit(circuit)) { console.error('sendNotifToCircuitsAdmin: missing circuit or circuit.admins', circuit); return; } for (const singleadmin of this.getAdminsByCircuit(circuit)) { try { if (singleadmin && singleadmin.username) { const user = await User.getUserShortDataByUsername(idapp, singleadmin.username); if (user) { if (alsotelegram) { if (!user.profile || !user.profile.teleg_id) { console.error('sendNotifToCircuitsAdmin: missing user.profile.teleg_id', user); } else { telegrambot.local_sendMsgTelegramByIdTelegram(idapp, user.profile.teleg_id, title + ' ' + msg); } } if (!user._id) { console.error('sendNotifToCircuitsAdmin: missing user._id', user); } else { await this.sendNotificationToUser(user._id, title, msg, '/', '', tag, []); } } } } catch (e) { console.error('sendNotifToCircuitsAdmin', e); } } }, sendNotifToAdmin(idapp, alsotelegram, title, msg, tag = '') { try { const { User } = require('../models/user'); const queryadmins = { username: 'paoloar77', idapp }; if (idapp === 0) idapp = '13'; User.find(queryadmins).then(async (arrusers) => { if (arrusers !== null) { for (const user of arrusers) { if (alsotelegram) { this.sendMsgTelegramToAdmin(idapp, title + ' ' + msg); } await this.sendNotificationToUser(user._id, title, msg, '/', '', tag, []).then((ris) => { if (ris) { } else { // already sent the error on calling sendNotificationToUser } }); } } }); } catch (e) { console.error(e); } }, checkUserOk(userpassed, userauth, res) { // this.mylog('checkUserOk', userpassed, userauth); if (String(userpassed) !== String(userauth)) { // I'm trying to write something not mine! this.mylog("I'm trying to write something not mine!: userId = ", userpassed, 'req.user._id', userauth); if (!res) { return { exit: true, ret: false, }; } else { return { exit: true, ret: false, // ret: res.status(404). // send({ code: server_constants.RIS_CODE_TODO_CREATING_NOTMYUSER }), }; } } else { return { exit: false, ret: false }; } }, ConvertHTMLToPlainText(strHTML) { if (strHTML) return strHTML.replace(/<[^>]+>/g, ''); return ''; }, convertSpaces_ToUScore(mystr) { if (mystr) return mystr.replace(/\s+/g, '_'); return ''; }, convertHTMLtoText(myhtml) { let msg = myhtml; if (msg) { msg = msg.replace('"', '"'); msg = msg.replace(//g, ''); msg = msg.replace(/<\/strong>/g, ''); msg = msg.replace(//g, ''); msg = msg.replace(/<\/em>/g, ''); msg = msg.replace('>', '>'); msg = msg.replace('<', '<'); msg = msg.replace('&', '&'); msg = msg.replace('
', '\n'); } return msg; }, htmlToTelegramText(html) { try { const withMarkdown = html .replace(/(.*?)<\/strong>/g, '*$1*') .replace(/(.*?)<\/b>/g, '*$1*') .replace(/(.*?)<\/em>/g, '_$1_') .replace(/(.*?)<\/u>/g, '__$1__'); // Remove other HTML tags const plainText = withMarkdown.replace(/<[^>]*>/g, ''); // Replace HTML entities with their equivalent Markdown or plain text representations const replacements = [ { pattern: /&/g, replacement: '&' }, { pattern: /</g, replacement: '<' }, { pattern: />/g, replacement: '>' }, { pattern: /"/g, replacement: '"' }, { pattern: /'/g, replacement: "'" }, ]; let telegramText = plainText; replacements.forEach((replacement) => { telegramText = telegramText.replace(replacement.pattern, replacement.replacement); }); return telegramText; } catch (e) { console.error(e); } }, htmlToTelegramText(html) { try { const withMarkdown = html .replace(/(.*?)<\/strong>/g, '*$1*') .replace(/(.*?)<\/b>/g, '*$1*') .replace(/(.*?)<\/em>/g, '_$1_') .replace(/(.*?)<\/u>/g, '__$1__'); // Remove other HTML tags const plainText = withMarkdown.replace(/<[^>]*>/g, ''); // Replace HTML entities with their equivalent Markdown or plain text representations const replacements = [ { pattern: /&/g, replacement: '&' }, { pattern: /</g, replacement: '<' }, { pattern: />/g, replacement: '>' }, { pattern: /"/g, replacement: '"' }, { pattern: /'/g, replacement: "'" }, ]; let telegramText = plainText; replacements.forEach((replacement) => { telegramText = telegramText.replace(replacement.pattern, replacement.replacement); }); return telegramText; } catch (e) { console.error(e); } }, convertTexttoHtml(myhtml) { // let msg = myhtml; // msg = msg.replace('\n', '
'); // return msg return myhtml; }, removeSpecialCharForEmail(myhtml) { let msg = myhtml; try { if (msg) msg = msg.replace(/"/g, "'"); } catch (e) { return msg; } return msg; }, getNomeAppByIdApp: function (idapp) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); if (myapp) return (process.env.NODE_ENV === 'test' ? 'Test: ' : '') + myapp.name; else return ''; }, getTimeExpReg: async function (idapp, username) { var { User } = require('../models/user'); return await User.createNewReqRegistrationGetLink(idapp, username); }, getLinkRegByIdAppAndMsgStrutt: function (idapp, msg, rec) { let myapp = this.getHostByIdApp(idapp); if (myapp) { myapp += '/registrati/' + rec.aportador_solidario + '/' + msg.from.username + '/' + msg.from.id + '/' + rec.regexpire; } return myapp; }, getHostByIdApp: function (idapp) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); if (myapp) { let siteport = myapp.portapp && myapp.portapp !== '0' ? ':' + myapp.portapp : ''; if (process.env.NODE_ENV === 'test') return myapp.host_test + siteport; else return myapp.host + siteport; } else return ''; }, getLinkUserProfile: function (idapp, username) { return this.getHostByIdApp(idapp) + '/my/' + username; }, getLinkUserTelegram: async function (idapp, username, myuser) { var { User } = require('../models/user'); let u_tg = ''; if (myuser) u_tg = myuser.profile && myuser.profile.hasOwnProperty('username_telegram') ? myuser.profile.username_telegram : usernametelegram; if (!u_tg) { u_tg = await User.getUsernameTelegram(idapp, username); } if (u_tg) return `https://t.me/${u_tg}`; else return ''; }, getLinkEditUserProfile: function (idapp) { return this.getHostByIdApp(idapp) + '/editprofile'; }, getConfSiteOptionEnabledByIdApp: function (idapp, option) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); if (myapp) { if (myapp.hasOwnProperty('confsite')) { if (myapp.confsite.hasOwnProperty('options')) { return this.isBitActive(myapp.confsite.options, option); } } } return false; }, getEnableTokenExpiredByIdApp: function (idapp) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); if (myapp && myapp.confpages && myapp.confpages.hasOwnProperty('enableTokenExpired')) { return myapp.confpages.enableTokenExpired; } return false; }, getConfParamSiteByIdApp: function (idapp, field) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); if (myapp) { if (myapp.hasOwnProperty('confsite')) { if (myapp.confsite.hasOwnProperty(field)) { return myapp.confsite[field]; } } } return false; }, isAbilitaNave: function (idapp) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); return myapp.abilitanave; }, removeLastSlashFromPath: function (myString) { let regex = /\/$/; let result = myString; try { if (myString) result = myString.replace(regex, ''); } catch (e) { return myString; } return result; }, getdirByIdApp: function (idapp, dirmain = false) { let mypath = ''; const myapp = this.MYAPPS.find((item) => item.idapp === idapp); if (myapp) { if (process.env.NODE_ENV === 'test') mypath = myapp && myapp.dir_test ? myapp.dir_test : ''; else mypath = myapp && myapp.dir ? myapp.dir : ''; if (dirmain) { if (!this.sulServer()) { mypath += 'public'; } } } return this.removeLastSlashFromPath(mypath); }, getAdminEmailByIdApp: function (idapp) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); if (myapp) return myapp.adminemail; else return ''; }, getreplyToEmailByIdApp: function (idapp) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); if (myapp) return myapp.replyTo; else return ''; }, getpathregByIdApp: function (idapp, lang) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); if (myapp) { const addstr = myapp.pathreg_add ? myapp.pathreg_add : ''; return 'registration' + addstr + '/' + lang; } else { return 'registration' + '/' + lang; } }, getparamSiteTableByIdApp: function (idapp, param) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); return myapp && param ? myapp[param] : ''; }, getAskToVerifyReg: function (idapp) { return this.getConfSiteOptionEnabledByIdApp(idapp, shared_consts.ConfSite.Need_Aportador_On_DataReg_To_Verify_Reg); }, getidMyGroupBySite: function (idapp) { return this.getparamSiteTableByIdApp(idapp, 'idMyGroup'); }, isManagAndAdminDifferent(idapp) { const manag = this.getManagerEmailByIdApp(idapp); return manag !== this.getAdminEmailByIdApp(idapp) && manag !== ''; }, getManagerEmailByIdApp: function (idapp) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); if (myapp) return !!myapp.manageremail ? myapp.manageremail : ''; else return ''; }, getEmailByIdApp: function (idapp) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); return myapp ? myapp.email_from : ''; }, getPwdByIdApp: function (idapp) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); return myapp ? this.decryptdata(myapp.email_pwd) : ''; }, getTelegramBotNameByIdApp: function (idapp) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); if (process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'development') return myapp ? myapp.telegram_bot_name_test : ''; else return myapp ? myapp.telegram_bot_name : ''; }, getTelegramSupportChat: function (idapp) { try { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); return myapp && myapp.telegram_support_chat ? myapp.telegram_support_chat : ''; } catch (e) { return ''; } }, getTelegramKeyByIdApp: function (idapp) { const myapp = this.MYAPPS.find((item) => item.idapp === idapp); if (process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'development') return myapp ? myapp.telegram_key_test : ''; else return myapp ? myapp.telegram_key : ''; }, getArrTelegramFromSite: function () { const myapp = this.MYAPPS; let arrteleg = []; for (const site of myapp) { if (site.active) { if (process.env.NODE_ENV === 'test') { if (site.telegram_bot_name_test) arrteleg.push(site.idapp); } else { if (site.telegram_bot_name) arrteleg.push(site.idapp); } } } return arrteleg; }, getLookupPipeLine(params, proj) { let myquery = [ { $lookup: { from: params.lk_tab, let: { username: '$' + params.lk_LF, idapp: params.idapp }, pipeline: [ { $match: { $expr: { $and: [{ $eq: ['$' + params.lk_FF, '$$' + params.lk_FF] }, { $eq: ['$idapp', '$$idapp'] }], }, }, }, ], as: params.lk_as, }, }, { $project: proj }, ]; return myquery; }, getNumTabByTable(table) { const myrec = shared_consts.MYTABS.find((rec) => rec.table === table); return myrec ? myrec.id : -1; }, getTableByNumTab(numtab) { const myrec = shared_consts.MYTABS.find((rec) => rec.id === numtab); return myrec ? myrec.table : ''; }, getGroupnameLookupPipeLine(params, proj) { let myquery = [ { $lookup: { from: params.lk_tab, let: { groupname: '$' + params.lk_LF, idapp: params.idapp }, pipeline: [ { $match: { $expr: { $and: [{ $eq: ['$' + params.lk_FF, '$$' + params.lk_FF] }, { $eq: ['$idapp', '$$idapp'] }], }, }, }, ], as: params.lk_as, }, }, { $project: proj }, ]; return myquery; }, getLookupStandardPipeline: function (params, num) { const query = []; if (!params) return; query.push( { $lookup: { from: params.lk_tab, let: { searchId: { $toObjectId: '$' + params.lk_LF } }, pipeline: [ { $match: { $expr: { $and: [{ $eq: ['$' + params.lk_FF, '$$searchId'] }], }, }, }, { $project: params.lk_proj, }, ], as: params.lk_as + num, }, }, { $replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: ['$' + params.lk_as + num, 0], }, '$$ROOT', ], }, }, } ); return query; }, sanitizzaHtml(html) { try { return sanitizeHtml(html); } catch (e) { return html; } }, sanitizzaLookup: function (str) { return str; }, sanitizzaProjection: function (mioproj) { // mioproj = {valore: '$password'}; const COL_TO_REMOVE = ['$password', '$tokens', '$tokens.token', 'ipaddr']; for (let chiave in mioproj) { // Elimina questa richiesta della password ! if (COL_TO_REMOVE.includes(mioproj[chiave])) { delete mioproj[chiave]; } } return mioproj; }, getLookup: function (params, num, pass_proj, proj_add) { const query = []; if (!params) return; let mylkLF = params.lk_LF; if (params.af_objId_tab) { const myobj = {}; myobj['myId' + num] = { $toObjectId: '$' + params.lk_LF }; if (params.lk_tab === 'users') { myobj.namecomplete = { $concat: [{ $toLower: '$name' }, { $toLower: '$surname' }, { $toLower: '$username' }], }; } query.push({ $addFields: myobj }); mylkLF = 'myId' + num; } else { } if (params.lk_tab) { let proj = params.lk_proj; proj = this.sanitizzaProjection(proj); if (!!pass_proj) { proj = pass_proj; } proj = Object.assign({}, proj, proj_add); query.push({ $lookup: { from: params.lk_tab, localField: mylkLF, // field in my collection foreignField: params.lk_FF, // field in the 'from' collection as: params.lk_as, }, }); if (params.unwind) { query.push({ $unwind: { path: '$' + params.lk_as, preserveNullAndEmptyArrays: true, }, }); } if (!params.noarray) { query.push({ $replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: ['$' + params.lk_as, 0], }, '$$ROOT', ], }, }, }); } query.push({ $project: proj }); } return query; }, getFilterParam: function (filter, fieldsearch) { let myregexp = {}; myregexp = new RegExp(filter.trim().replace(' ', '|'), 'ig'); let query = []; const myfilters = []; for (const rec of fieldsearch) { let data = {}; if (rec.type === this.FieldType.exact) { data[rec.field] = filter.trim(); } else if (rec.type === this.FieldType.string) { data[rec.field] = myregexp; if (rec.field === 'profile.username_telegram') { myregexp = new RegExp(this.rimuoviAtPrimoCarattere(filter).trim().replace(' ', '|'), 'ig'); data[rec.field] = myregexp; } } else if (rec.type === this.FieldType.number || rec.type === this.FieldType.hours) { data[rec.field] = parseFloat(filter.trim()); } if (data) myfilters.push(data); } if (myfilters.length > 0) { query = [{ $match: { $or: myfilters } }]; } return query; }, addQueryIdMatch: function (params) { myquery = {}; if ( shared_consts.TABLES_ID_NUMBER.includes(params.table) || shared_consts.TABLES_ID_STRING.includes(params.table) ) { myquery = { $match: { $expr: { $eq: ['$_id', params.myid], }, }, }; } else if (shared_consts.TABLES_NUM_AS_ID_NUMBER.includes(params.table)) { myquery = { $match: { $expr: { $eq: ['$Num', params.myid], }, }, }; } else { myquery = { $match: { $expr: { $eq: ['$_id', mongoose.Types.ObjectId(params.myid)], }, }, }; } return myquery; }, contieneIdStatusSkill(filtersearch) { for (let i = 0; i < filtersearch.length; i++) { const obj = filtersearch[i]; if (obj.$or) { for (let j = 0; j < obj.$or.length; j++) { const condition = obj.$or[j]; if (condition.idStatusSkill) { return true; } } } } return false; }, addNumFavoriteAndBookmarkToQuery(idapp, numtab) { let query = []; try { /* query = [ { $lookup: { from: "reactions", let: { tab: numtab, id: '$_id', }, pipeline: [ { $match: { $expr: { $and: [ { $eq: ['$idrec', '$$id'] }, { $eq: ['$tab', numtab] }, { $eq: ['$idapp', idapp] }, ], }, }, }, { $group: { _id: "$idrec", numseen: { $sum: { $cond: { if: { $ifNull: ["$seen", false] }, // Check if the field exists and is not null then: 1, // Increment count by 1 if the field exists else: 0, // Otherwise, keep the count unchanged } } }, numfav: { $sum: { $cond: { if: { $ifNull: ["$fav", false] }, // Check if the field exists and is not null then: 1, // Increment count by 1 if the field exists else: 0, // Otherwise, keep the count unchanged } } }, numbook: { $sum: { $cond: { if: { $ifNull: ["$book", false] }, // Check if the field exists and is not null then: 1, // Increment count by 1 if the field exists else: 0, // Otherwise, keep the count unchanged } } } }, }, ], as: 'myreact', }, }, { $unwind: { path: "$myreact", preserveNullAndEmptyArrays: true, }, }, ]; if (true) { // RIMUOVI // query = {}; } if (true) { // RIMUOVI // query = {}; } if (Object.keys(query).length > 0) { const numtabbacheca = this.getNumTabByTable(shared_consts.TABLES_MYBACHECAS); if (numtab === numtabbacheca) { const queryadd = this.getQueryMyBacheca(idapp); query = [...query, ...queryadd]; } } const numtabbacheca = this.getNumTabByTable(shared_consts.TABLES_MYBACHECAS); if (numtab === numtabbacheca) { const queryadd = this.getQueryMyBacheca(idapp); query = [...query, ...queryadd]; } */ proj = { numseen: 1, numfav: 1, numbook: 1, numattend: 1, }; } catch (e) { console.error(e); } return { query, proj }; }, getQueryMyBacheca: function (idapp) { const arrquery = [ { $lookup: { from: 'bookings', let: { id: '$_id', }, pipeline: [ { $match: { $expr: { $and: [{ $eq: ['$id_bookedevent', '$$id'] }, { $eq: ['$idapp', idapp] }], }, }, }, { $project: { id_bookedevent: 1, username: 1, numpeople: 1, numpeopleLunch: 1, numpeopleDinner: 1, numpeopleDinnerShared: 1, infoevent: 1, msgbooking: 1, booked: 1, datebooked: 1, userId: 1, idapp: 1, }, }, ], as: 'mybookings', }, }, /** { $lookup: { from: "users", localField: "myId1", foreignField: "_id", as: "user", }, }, { $lookup: { from: "users", let: { myid: { $toObjectId: "$mybookings.userId" }, }, pipeline: [ { $match: { $expr: { $and: [ { $eq: [ "$_id", "$$myid", ], }, { $eq: [ "$idapp", "13", ], }, ], }, }, }, { $project: { _id: 1, username: 1 }, } ], as: "myuser", }, }**/ ]; return arrquery; }, getQueryTable: async function (idapp, params, user) { try { const { Search } = require('../models/search'); 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 newvers = !!params.newvers; let query = []; if (params.filter && params.fieldsearch) { params.filter = this.sanitizzaHtml(params.filter); params.fieldsearch = this.sanitizzaHtml(params.fieldsearch); const querytemp = this.getFilterParam(params.filter, params.fieldsearch); if (querytemp) { query = [...query, ...querytemp]; } } 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) { params.filterand = this.sanitizzaHtml(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_QUALIFIED)) filtriadded.push({ 'profile.qualified': true }); if (params.filterand.includes(shared_consts.FILTER_USER_NO_ZOOM)) filtriadded.push({ 'profile.saw_zoom_presentation': false }); if (params.filterand.includes(shared_consts.FILTER_ASK_ZOOM_VISTO)) filtriadded.push({ 'profile.ask_zoom_partecipato': 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_SI_TELEGRAM_ID)) filtriadded.push({ 'profile.teleg_id': { $gt: 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_VERIFIED_APORTADOR)) filtriadded.push({ verified_by_aportador: { $exists: false }, }); if (params.filterand.includes(shared_consts.FILTER_USER_WITHOUT_USERNAME_TELEGRAM)) filtriadded.push({ $or: [ { 'profile.username_telegram': { $exists: false } }, { 'profile.username_telegram': { $exists: true, $eq: '' } }, ], }); 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 (params.filterand.includes(shared_consts.FILTER_USER_PROVINCE)) filtriadded.push({ 'profile.resid_province': { $exists: true } }); if (params.filterand.includes(shared_consts.FILTER_USER_SENZA_PROVINCE)) filtriadded.push({ 'profile.resid_province': { $exists: false } }); if (params.filterand.includes(shared_consts.FILTER_ATTIVI)) filtriadded.push({ $or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }], }); // Hours if (params.filterand.includes(shared_consts.FILTER_HOURS_ALL)) filtriadded.push({ idapp, todoId: params.codeId, $or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }], }); else if (params.filterand.includes(shared_consts.FILTER_HOURS_MYLIST)) filtriadded.push({ idapp, userId: params.userId, todoId: params.codeId, $or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }], }); if (params.filterand.includes(shared_consts.FILTER_NASCOSTI)) filtriadded.push({ deleted: { $exists: true, $eq: true }, }); if (params.filterand.includes(shared_consts.FILTER_NAVI_NON_PRESENTI)) filtriadded.push({ navinonpresenti: { $exists: true, $eq: true }, $or: [{ subaccount: { $exists: false } }, { subaccount: { $exists: true, $eq: false } }], }); // Iscritti Conacreis if (params.filterand.includes(shared_consts.FILTER_REPORTED)) filtriadded.push({ reported: { $exists: true, $eq: true } }); if (params.filterand.includes(shared_consts.FILTER_TO_MAKE_MEMBERSHIP_CARD)) filtriadded.push({ $or: [{ codiceConacreis: { $exists: false } }, { codiceConacreis: { $exists: true, $eq: '' } }], }); if (params.filterand.includes(shared_consts.FILTER_MEMBERSHIP_CARD_OK)) filtriadded.push({ codiceConacreis: { $exists: true }, $expr: { $gt: [{ $strLenCP: '$codiceConacreis' }, 0] }, }); } if (params.filtercustom) { params.filtercustom = this.sanitizzaHtml(params.filtercustom); let condition = {}; for (const myfilter of params.filtercustom) { if (myfilter['userId']) { myfilter['userId'] = new ObjectId(myfilter['userId']); } if (myfilter['_idOBJ']) { filtriadded.push({ _id: new ObjectId(myfilter['_idOBJ']) }); } else if (myfilter['dateTimeStart']) { const gte = myfilter['dateTimeStart'].$gte; const lte = myfilter['dateTimeStart'].$lte; condition = { dateTimeStart: { $gte: new Date(gte), $lte: new Date(lte), }, }; filtriadded.push(condition); } else if (myfilter.hasOwnProperty('pub_to_share')) { // non aggiungere niente } else { filtriadded.push(myfilter); } } } if (params.filter_gte) { params.filter_gte = this.sanitizzaHtml(params.filter_gte); for (let ind = 0; ind < params.filter_gte.length; ind++) { for (const [key, value] of Object.entries(params.filter_gte[ind])) { if (value > 0) { let condition = {}; condition[key] = { $gte: value }; filtriadded.push(condition); } } } } if (params.filtersearch) { params.filtersearch = this.sanitizzaHtml(params.filtersearch); filtriadded.push(...params.filtersearch); } if (params.options) { if (this.isBitActive(params.options, shared_consts.OPTIONS_SEARCH_ONLY_FULL_WORDS)) { } } if (params.filterextra) { params.filterextra = this.sanitizzaHtml(params.filterextra); if (params.filterextra.length > 0) query = [...query, ...params.filterextra]; } if (filtriadded) { filtriadded = this.sanitizzaHtml(filtriadded); if (filtriadded.length > 0) query.push({ $match: { $and: filtriadded } }); } let numrowend = params.endRow - params.startRow; if (numrowend < 0) numrowend = 1; let projectEnd = { $slice: ['$results', params.startRow, numrowend] }; let querymatch = {}; if (idapp > 0) { querymatch.idapp = idapp; } if (params.searchByBoundariesMap) { projectEnd = '$results'; querymatch.coordinate_gps = { $geoWithin: { $box: [ [params.searchByBoundariesMap.sw.lng, params.searchByBoundariesMap.sw.lat], [params.searchByBoundariesMap.ne.lng, params.searchByBoundariesMap.ne.lat], ], }, }; } if (Object.keys(querymatch).length > 0) { query.push({ $match: querymatch }); } // console.log('QUERYMATCH', query[0].$match.or); // console.log('filter', params.filter); if ( params.querytype === shared_consts.QUERYTYPE_MYGROUP || params.querytype === shared_consts.QUERYTYPE_CIRCUIT ) { const myq = this.addQueryIdMatch(params); if (myq) query.push(myq); query.push({ $project: { req_users: 1 } }); const qa1 = this.getLookup( { lk_tab: 'users', lk_LF: 'req_users.username', lk_FF: 'username', lk_as: 'user', }, 0, { 'user.idapp': 1, 'user.username': 1, 'user.name': 1, 'user.surname': 1, 'user.profile.img': 1, 'user.profile.qualifica': 1, 'user.profile.note': 1, 'profile.da_contattare': 1, } ); if (qa1) query = [...query, ...qa1]; query.push({ $unwind: '$user' }); query.push({ $match: { $and: [{ 'user.idapp': params.idapp }], }, }); query.push({ $replaceRoot: { newRoot: '$user', }, }); } else if ( params.querytype === shared_consts.QUERYTYPE_REFUSED_USER_GRP || params.querytype === shared_consts.QUERYTYPE_REFUSED_USER_CIRCUIT ) { /* const myq = this.addQueryIdMatch(params); if (myq) query.push(myq); */ const myq = this.addQueryIdMatch(params); if (myq) query.push(myq); query.push({ $project: { refused_users: 1 } }); query.push({ $unwind: '$refused_users' }); const qa1 = this.getLookupPipeLine( { lk_tab: 'users', lk_LF: 'refused_users.username', lk_FF: 'username', lk_as: 'user', idapp, }, { 'user.idapp': 1, 'user.username': 1, 'user.name': 1, 'user.surname': 1, 'user.profile.img': 1, 'user.profile.qualifica': 1, 'user.profile.note': 1, 'profile.da_contattare': 1, } ); if (qa1) query = [...query, ...qa1]; query.push({ $unwind: '$user' }); /* query.push({ $match: { $and: [ {'user.idapp': params.idapp}, ], }, }); */ query.push({ $replaceRoot: { newRoot: '$user', }, }); } else if (params.querytype === shared_consts.QUERYTYPE_GROUP_CIRCUIT) { const myq = this.addQueryIdMatch(params); if (myq) query.push(myq); query.push({ $project: { req_groups: 1 } }); const qa1 = this.getLookup( { lk_tab: 'mygroups', lk_LF: 'req_groups.groupname', lk_FF: 'groupname', lk_as: 'group', }, 0, { 'group.idapp': 1, 'group.groupname': 1, 'group.photos': 1, } ); if (qa1) query = [...query, ...qa1]; query.push({ $unwind: '$group' }); if (true) { query.push({ $match: { $and: [{ 'group.idapp': params.idapp }], coordinate_gps: { $geoWithin: { $box: [ [searchByBoudariesMap.sw.lng, searchByBoudariesMap.sw.lat], [searchByBoudariesMap.ne.lng, searchByBoudariesMap.ne.lat], ], }, }, }, }); } else { query.push({ $match: { $and: [{ 'group.idapp': params.idapp }], }, }); } query.push({ $replaceRoot: { newRoot: '$group', }, }); } else if (params.querytype === shared_consts.QUERYTYPE_REFUSED_GROUP_CIRCUIT) { const myq = this.addQueryIdMatch(params); if (myq) query.push(myq); query.push({ $project: { refused_groups: 1 } }); query.push({ $unwind: '$refused_groups' }); const qa1 = this.getGroupnameLookupPipeLine( { lk_tab: 'mygroups', lk_LF: 'refused_groups.groupname', lk_FF: 'groupname', lk_as: 'group', idapp, }, { 'group.idapp': 1, 'group.groupname': 1, 'group.descr': 1, 'group.photos': 1, } ); if (qa1) query = [...query, ...qa1]; query.push({ $unwind: '$group' }); /* query.push({ $match: { $and: [ {'user.idapp': params.idapp}, ], }, }); */ query.push({ $replaceRoot: { newRoot: '$group', }, }); } else if (params.querytype === shared_consts.QUERYTYPE_LIST_MOVEMENTS) { const { Movement } = require('../models/movement'); const myquery = await Movement.getQueryMovsByCircuitId(params.idapp, params.username, '', '', params.myid); query.push(...myquery); } else if (params.querytype === shared_consts.QUERYTYPE_LIST_MOVEMENTS_GROUPNAME) { const { Movement } = require('../models/movement'); const myquery = await Movement.getQueryMovsByCircuitId(params.idapp, '', params.groupname, '', params.myid); query.push(...myquery); } else if (params.querytype === shared_consts.QUERYTYPE_LIST_MOVEMENTS_CONTOCOM) { const { Movement } = require('../models/movement'); const myquery = await Movement.getQueryMovsByCircuitId(params.idapp, '', '', params.contocom, params.myid); query.push(...myquery); } else if (params.querytype === shared_consts.QUERYTYPE_LIST_ALLMOVEMENTS) { const { Movement } = require('../models/movement'); const myquery = await Movement.getQueryAllUsersMovsByCircuitId(params.idapp, params.myid); query.push(...myquery); } if (params.filterextra2) { if (params.filterextra2.length > 0) query = [...query, ...params.filterextra2]; } if (newvers) { // NUOVA VERSIONE let proj = params.lookup2 ? params.lookup2.lk_proj : null; proj = this.sanitizzaProjection(proj); if (params.proj0) { query.push({ $project: params.proj0 }); } if (params.unwind0) { query.push({ $unwind: params.unwind0 }); } let objadd = { query: [], proj: {} }; let numtab = this.getNumTabByTable(params.table); const q1 = this.getLookup(params.lookup1, 1, proj, objadd.proj); if (q1) query = [...query, ...q1]; if (params.unwind1) { query.push({ $unwind: params.unwind1 }); } if (params.lookupPipeline1) { const q1p = this.getLookupStandardPipeline(params.lookupPipeline1, 1); if (q1p) query = [...query, ...q1p]; } params.lookup2 = this.sanitizzaLookup(params.lookup2); params.lookup3 = this.sanitizzaLookup(params.lookup3); params.lookup4 = this.sanitizzaLookup(params.lookup4); params.lookup5 = this.sanitizzaLookup(params.lookup5); const q2 = this.getLookup(params.lookup2, 2, proj, objadd.proj); if (q2) query = [...query, ...q2]; if (params.lookupPipeline2) { const q2p = this.getLookupStandardPipeline(params.lookupPipeline2, 2); if (q2p) query = [...query, ...q2p]; } const q3 = this.getLookup(params.lookup3, 3, proj, objadd.proj); if (q3) query = [...query, ...q3]; const q4 = this.getLookup(params.lookup4, 4, proj, objadd.proj); if (q4) query = [...query, ...q4]; const q5 = this.getLookup(params.lookup5, 5, proj, objadd.proj); if (q5) query = [...query, ...q5]; if (params.filtersearch2) { if (params.filtersearch2.length > 0) { query.push({ $match: { $and: params.filtersearch2 } }); } } let filteradmin = false; if (params.filtercustom) { let condition = {}; for (const myfilter of params.filtercustom) { if (!!myfilter.admins) { filteradmin = true; } if ( myfilter['pub_to_share'] === shared_consts.PUBTOSHARE.ONLY_TABLE_FOLLOW && params.table === 'mygroups' ) { let arraygroups = []; if (user && user.profile.mygroups) { arraygroups = user.profile.mygroups.map((rec) => rec.groupname); } // prendere i gruppi dell'utente // Cerca tra i gruppi di ogni record, se combaciano almeno 1 condition = { 'profile.mygroups': { $elemMatch: { groupname: { $in: arraygroups }, }, }, }; query.push({ $match: { $and: [condition] } }); } else if ( myfilter['pub_to_share'] === shared_consts.PUBTOSHARE.ONLY_TABLE_FOLLOW && params.table === 'circuits' ) { let arraycircuits = []; if (user && user.profile.mycircuits) { arraycircuits = user.profile.mycircuits.map((rec) => rec.circuitname); } // prendere i gruppi dell'utente // Cerca tra i gruppi di ogni record, se combaciano almeno 1 condition = { 'profile.mycircuits': { $elemMatch: { circuitname: { $in: arraycircuits }, }, }, }; query.push({ $match: { $and: [condition] } }); } else if (shared_consts.TABLES_ENABLE_GETREC_BYID.includes(params.table)) { // Rimuovi dalla query quelli non visibili let arraygroups = []; if (user && user.profile.mygroups) { arraygroups = user.profile.mygroups.map((rec) => rec.groupname); } // prendere i gruppi dell'utente // Cerca tra i gruppi di ogni record, se combaciano almeno 1 condition = { 'profile.mygroups': { $elemMatch: { groupname: { $in: arraygroups }, }, }, }; query.push({ $match: { $or: [ { $and: [condition, { pub_to_share: 1 }], }, { $or: [ { pub_to_share: { $exists: false } }, { pub_to_share: { $exists: true, $eq: shared_consts.PUBTOSHARE.ALL } }, ], }, ], }, }); } } } if (params.table === shared_consts.TABLES_MYBACHECAS) { const myq = this.getQueryMyBacheca(idapp); query.push(myq[0]); } if (params.filtersearch3or) { if (params.filtersearch3or.length > 0) { query.push({ $match: { $or: params.filtersearch3or } }); } } if (params.filtersearch3and) { if (params.filtersearch3and.length > 0) { // Se c'è statusskill allora glielo metto in OR if ( params.table === 'myskills' && params.filtersearch && !this.contieneIdStatusSkill(params.filtersearch) ) { query.push({ $match: { $or: [{ $and: params.filtersearch3and }, { idStatusSkill: { $in: [2] } }], }, }); } else { query.push({ $match: { $and: params.filtersearch3and } }); } } } if (params.filter && params.fieldsearch_last) { const querytemp = this.getFilterParam(params.filter, params.fieldsearch_last); if (querytemp) { query = [...query, ...querytemp]; } // Save the search: if (user._id) { const mysearch = new Search({ idapp, userId: user._id, text: params.filter }); await mysearch.save(); } } if (params.table === 'mygroups' || params.table === 'circuits') { // BINARY CHECK (?): const filter = [{ visibility: { $bitsAnyClear: [1] } }]; // if (!User.isAdmin(req.user.perm)) { // not Visibility_Group.HIDDEN if (!filteradmin) { if (user) { const filter = [ { $or: [ { visibility: { $nin: [shared_consts.Visibility_Group.HIDDEN], }, }, { createdBy: { $eq: user.username, }, }, ], }, ]; query.push({ $match: { $and: filter } }); } else { const filter = [ { visibility: { $nin: [shared_consts.Visibility_Group.HIDDEN], }, }, ]; query.push({ $match: { $and: filter } }); } } // } } if (params.options && this.isBitActive(params.options, shared_consts.OPTIONS_ADD_COUNT_FAVORITE)) { // objadd = this.addNumFavoriteAndBookmarkToQuery(idapp, numtab); // if (Object.keys(objadd.query).length > 0) // query = [...query, ...objadd.query]; } } else { // VECCHIA VERSIONE const q1 = this.getLookup(params, 1); if (q1) query = [...query, ...q1]; } if (params.sortBy && !params.searchByBoundariesMap) { // 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 ); if (projectEnd) { query.push({ $project: { count: 1, rows: projectEnd, }, }); } if (this.testing()) { // console.log('query', query); } //console.log('query', query); return query; } catch (e) { console.error('Err query:', e); } }, startTimeLog(name) { if (this.testing()) { // console.log('inizio', name); try { console.time(name); } catch (e) {} } }, endTimeLog(name) { if (this.testing()) { // console.log(' ... fine', name); console.timeEnd(name); } }, async executeQueryTable(mythistable, idapp, params, user) { let query = await this.getQueryTable(idapp, params, user); try { // console.log('query', query); this.startTimeLog('Query 1'); const [ris] = await mythistable.aggregate(query); if (ris) { if (params.table === 'users') { for (const myrec of ris.rows) { if (myrec.ipaddr) myrec.ipaddr = ''; if (myrec.tokens) myrec.tokens = []; if (myrec.password) myrec.password = ''; } } else if (params.table === 'mygroups') { for (const myrec of ris.rows) { if (myrec.pwd_cryp) myrec.pwd_cryp = ''; } } this.endTimeLog('Query 1'); // console.table(ris.rows); // console.log('ROW ', ris.count); return { count: ris.count, rows: ris.rows }; } else { return { count: 0, rows: [] }; } } catch (e) { console.log('error', e); } }, 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]); newrec._id = new ObjectId(); newrec.idapp = idappdest; try { const rec = await newrec.save(); if (rec) { num++; } } catch (e) { console.error('e', e); } } return num; }); } }, isBitActive(bit, whattofind) { return (bit & whattofind) === whattofind; }, isBitAttivoESelez(bit, whattofind, loSono) { const abil = this.isBitActive(bit, whattofind); return (abil && loSono) || !abil; }, SetBit(myval, bit) { let myvalout = myval; myvalout |= bit; return myvalout; }, 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; }, isdiffSecDateLess(mydatediffstr, secs) { let mydate = new Date(); // console.log('mydate', mydate); let mydata2 = new Date(mydatediffstr); let ris = (mydate.getTime() - mydata2.getTime()) / 1000; return ris < secs; }, AddDate(mydate, days) { let date = new Date(mydate); date.setTime(date.getTime() + days * 86400000); return date; }, isMonToSat() { const dayOfWeek = new Date(new Date()).getDay(); return dayOfWeek >= 1 && dayOfWeek <= 6; }, isMonToFri() { const dayOfWeek = new Date(new Date()).getDay(); return dayOfWeek >= 1 && dayOfWeek <= 5; }, // var startTime = '15:10:10'; // var endTime = '22:30:00'; isBetweenTwoTime(startTime, endTime) { currentDate = new Date(); startDate = new Date(currentDate.getTime()); startDate.setHours(startTime.split(':')[0]); startDate.setMinutes(startTime.split(':')[1]); startDate.setSeconds(startTime.split(':')[2]); endDate = new Date(currentDate.getTime()); endDate.setHours(endTime.split(':')[0]); endDate.setMinutes(endTime.split(':')[1]); endDate.setSeconds(endTime.split(':')[2]); valid = startDate < currentDate && endDate > currentDate; return valid; }, getlimiti(mypos) { if (mypos.col < 0) { mypos.col = 0; } if (mypos.riga < 0) { mypos.riga = 0; mypos.col = 0; } return mypos; }, 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)); } if (mypos.riga < 1) { mypos.riga = 1; } if (mypos.col < 1) { mypos.col = 1; } }, getRigaColGenerica(idapp, riga, col, numup) { mypos = { idapp, riga, col, numup, }; if (idapp === this.AYNI) { this.getRigaColByPosUp(mypos); ris = this.getlimiti(mypos); } return ris; }, getRigaColSognatoreByDonatore(idapp, riga, col) { return this.getRigaColGenerica(idapp, riga, col, 6); }, getRigaColMediatoreByFuoco(idapp, riga, col) { return this.getRigaColGenerica(idapp, riga, col, 3); }, getRigaColSognatoreByMediatore(idapp, riga, col) { return this.getRigaColGenerica(idapp, riga, col, 3); }, appendLeadingZeroes(n) { if (n <= 9) { return '0' + n; } return n; }, getWeekDayByLangByNumCar(date, lang, num) { if (!lang) lang = 'it'; const dayOfWeek = new Date(date).getDay(); const myday = { it: ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'], enUs: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], fr: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'], es: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'iernes', 'Sábado'], pt: ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'], de: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'], si: ['Nedelja', 'Ponedeljek', 'Torek', 'Sreda', 'četrtek', 'Petek', 'Sobota'], }; if (num > 0) { return isNaN(dayOfWeek) ? '' : myday[lang][dayOfWeek].substring(0, num); } else { return isNaN(dayOfWeek) ? '' : myday[lang][dayOfWeek]; } }, isSunday(mydate) { const dayOfWeek = new Date(mydate).getDay(); return dayOfWeek === 0; }, isMonday(mydate) { const dayOfWeek = new Date(mydate).getDay(); return dayOfWeek === 1; }, isSundayDate(mydate) { const dayOfWeek = mydate.getDay(); return dayOfWeek === 0; }, isMondayDate(mydate) { const dayOfWeek = mydate.getDay(); return dayOfWeek === 1; }, getWeekDayByLang(date, lang) { return this.getWeekDayByLangByNumCar(date, lang, 3); }, getWeekDayByLangTot(date, lang) { return this.getWeekDayByLangByNumCar(date, lang, 0); }, 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, lang) { if (mydate) { // console.log('getstrDate', mytimestamp) return ( this.getWeekDayByLang(mydate, lang) + ' ' + this.appendLeadingZeroes(mydate.getDate()) + '/' + this.appendLeadingZeroes(mydate.getMonth() + 1) + ' ORE ' + this.appendLeadingZeroes(mydate.getHours()) + ':' + this.appendLeadingZeroes(mydate.getMinutes()) ); } else { return ''; } }, getstrTime(mytimestamp) { // Create a Date object with your desired date const date = new Date(mytimestamp); // You can replace this with your specific date // Get the hour and minute components from the date const hours = date.getHours(); const minutes = date.getMinutes(); // Format the hour and minute components as HH:MM const formattedTime = `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`; return formattedTime; }, getstrDateShort(mydate, lang) { if (mydate) { // console.log('getstrDate', mytimestamp) return ( this.getWeekDayByLang(mydate, lang).substring(0, 3) + ' ' + this.appendLeadingZeroes(mydate.getDate()) + '/' + this.appendLeadingZeroes(mydate.getMonth() + 1) ); } else { return ''; } }, getstrDate_DD_MM_YYYY(mydate) { if (mydate) { // console.log('getstrDate', mytimestamp) return ( this.appendLeadingZeroes(mydate.getDate()) + '/' + this.appendLeadingZeroes(mydate.getMonth() + 1) + '/' + this.appendLeadingZeroes(mydate.getFullYear()) ); } else { return ''; } }, getstrDateYYYY_MM_DD(mydate) { if (mydate) { // console.log('getstrDate', mytimestamp) return ( mydate.getFullYear() + '-' + this.appendLeadingZeroes(mydate.getMonth() + 1) + '-' + this.appendLeadingZeroes(mydate.getDate()) ); } else { return ''; } }, getstrUTCDateYYYY_MM_DD(mydate) { if (mydate) { // console.log('getstrDate', mytimestamp) return ( mydate.getUTCFullYear() + '-' + this.appendLeadingZeroes(mydate.getUTCMonth() + 1) + '-' + this.appendLeadingZeroes(mydate.getUTCDate()) ); } else { return ''; } }, getstrDateLong(mydate, lang) { if (mydate) { // console.log('getstrDate', mytimestamp) return ( this.getWeekDayByLang(mydate, lang) + ' ' + this.appendLeadingZeroes(mydate.getDate()) + '/' + this.appendLeadingZeroes(mydate.getMonth() + 1) + '/' + mydate.getFullYear() ); } else { return ''; } }, getstrDateLongTot(mydate, lang) { if (mydate) { // console.log('getstrDate', mytimestamp) return ( this.getWeekDayByLangTot(mydate, lang) + ' ' + this.appendLeadingZeroes(mydate.getDate()) + '/' + this.appendLeadingZeroes(mydate.getMonth() + 1) + '/' + mydate.getFullYear() ); } else { return ''; } }, getstrDateLongFile(mydate, lang) { if (mydate) { // console.log('getstrDate', mytimestamp) return ( mydate.getFullYear() + '-' + this.appendLeadingZeroes(mydate.getMonth() + 1) + '-' + this.appendLeadingZeroes(mydate.getDate()) + ' (' + this.getWeekDayByLang(mydate, lang) + ')' ); } else { return ''; } }, getlinkzoom(rec) { if (rec === null) { rec = { typeconf: this.TYPECONF_ZOOM, id_conf_zoom: '', }; } let typeconf = rec.typeconf; if (typeconf === '') typeconf = this.TYPECONF_ZOOM; let mylink = 'https://zoom.us/j/'; if (typeconf === this.TYPECONF_JITSI) mylink = 'https://meet.jit.si/'; if (rec.id_conf_zoom === '') { rec.id_conf_zoom = '6668882000'; } return mylink + rec.id_conf_zoom; }, getmd5(mystr) { return CryptoJS.MD5(mystr ? mystr.toLowerCase() : '').toString(); }, getHash(mystr) { return CryptoJS.SHA512(mystr, { outputLength: 256 }).toString(); }, encrypt(msg, pass) { try { // Genera salt e IV casuali const salt = CryptoJS.lib.WordArray.random(128 / 8); // 16 byte const iv = CryptoJS.lib.WordArray.random(128 / 8); // 16 byte // Deriva la chiave usando PBKDF2 const key = CryptoJS.PBKDF2(pass, salt, { keySize: keySize / 32, iterations: iterations, }); // Critta il messaggio const encrypted = CryptoJS.AES.encrypt(msg, key, { iv: iv, padding: CryptoJS.pad.Pkcs7, mode: CryptoJS.mode.CBC, }); // Concatena salt, IV e ciphertext con un delimitatore const transitmessage = `${salt.toString()}|${iv.toString()}|${encrypted.toString()}`; return transitmessage; } catch (error) { console.error('❌❌❌ Errore durante la crittazione:', error.message); throw error; } }, decrypt(transitmessage, pass) { try { let saltHex, ivHex, encrypted; // Controlla se il messaggio è nel nuovo formato (con delimitatore) if (transitmessage.includes('|')) { const parts = transitmessage.split('|'); if (parts.length !== 3) { throw new Error('❌❌❌ Formato del messaggio non valido.'); } [saltHex, ivHex, encrypted] = parts; } else { // Vecchio formato: salt (32 caratteri), IV (32 caratteri), ciphertext (resto) saltHex = transitmessage.substr(0, 32); ivHex = transitmessage.substr(32, 32); encrypted = transitmessage.substring(64); } // Converte salt e IV da esadecimale const salt = CryptoJS.enc.Hex.parse(saltHex); const iv = CryptoJS.enc.Hex.parse(ivHex); // Deriva la chiave usando PBKDF2 const key = CryptoJS.PBKDF2(pass, salt, { keySize: keySize / 32, iterations: iterations, }); // Decritta il messaggio const decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: iv, padding: CryptoJS.pad.Pkcs7, mode: CryptoJS.mode.CBC, }); // Restituisci il messaggio originale in formato UTF-8 let ris = decrypted.toString(CryptoJS.enc.Utf8); // console.log('RIS', ris); return ris; } catch (error) { console.error('❌❌❌ Errore durante la decrittazione:', error.message); throw error; } }, cryptdata(mydata) { if (mydata === '') return ''; // Encrypt //return CryptoJS.AES.encrypt(JSON.stringify(mydata), process.env.SECRK); return this.encrypt(mydata, process.env.SECRK); }, decryptdata(mydatacrypted) { if (!mydatacrypted) return ''; try { // console.log('SECRK', process.env.SECRK); const decr = this.decrypt(mydatacrypted, process.env.SECRK); // console.log('decr:', mydatacrypted, '->', decr); return decr; } catch (error) { console.error('❌❌❌❌❌ Decryption error:', error); return ''; } }, 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!'); // }); try { mystr = this.getstrDateTimeShort(new Date(), 'it') + ': ' + mystr; const stream = fs.createWriteStream(filename, { flags: 'a' }); stream.write('\n' + mystr); stream.end(); } catch (e) {} }, async readlogfile(idapp, filename) { try { return await fs.readFileSync(idapp + '/' + filename, 'utf8'); } catch (e) { return ''; } }, async readfilecontent(filename) { try { const cont = await fs.readFileSync(filename, 'utf8'); return cont; } catch (e) { return ''; } }, async getVersServer() { return await this.readfilecontent(__dirname + '/../version.txt'); }, writelog(mystr) { this.writelogfile(mystr, FILELOG); }, writeEventsLog(mystr) { this.writelogfile(mystr, FILEEVENTS); }, writeManagersLog(mystr) { this.writelogfile(mystr, FILEMANAGERS); }, writeTransactionLog(mystr) { this.writelogfile(mystr, FILETRANSACTION); }, writeErrorLog(mystr) { this.writelogfile(mystr, FILEERRLOGIN); }, writeSostituzioniLog(mystr) { this.writelogfile(mystr, FILESOSTITUZIONI); }, writeIPToBan(mystr) { this.writelogfile(mystr, FILEIP_TO_BAN); }, writeFlottaLog(idapp, mystr, riga, col) { this.mkdirpath(idapp + '/'); this.writelogfile(mystr, idapp + '/' + riga + '_' + col + '.txt'); }, writeNaveLog(mystr) { this.writelogfile(mystr, FILENAVE); }, async copyFile(src, dest) { return new Promise((resolve, reject) => { const readStream = fs.createReadStream(src); const writeStream = fs.createWriteStream(dest); readStream.on('error', reject); writeStream.on('error', reject); writeStream.on('finish', resolve); readStream.pipe(writeStream); }); }, /** * Sposta un file da oldPath a newPath. * Se rename fallisce con EXDEV (diverso device), fa copia + delete. * Se la cartella di destinazione non esiste, la crea. * @param {string} oldPath * @param {string} newPath * @param {(err?: Error) => void} [callback] - opzionale, se non passato ritorna Promise */ async move(oldPath, newPath, callback) { const moveOp = async () => { // Assicurati che la cartella di destinazione esista const dir = path.dirname(newPath); await fs.promises.mkdir(dir, { recursive: true }); try { const newOldPath = oldPath.replace(/\/$/, ''); const newNewPath = newPath.replace(/\/$/, ''); await fs.promises.rename(newOldPath, newNewPath); console.log(`File spostato: ${oldPath} -> ${newPath}`); } catch (err) { if (err.code === 'EXDEV') { // Spostamento tra device diversi: copia + elimina await copyFile(oldPath, newPath); await fs.promises.unlink(oldPath); console.log(`File copiato e cancellato: ${oldPath} -> ${newPath}`); } else if (err.code === 'ENOENT') { throw new Error(`File non trovato: ${oldPath}`); } else { throw err; } } }; if (callback && typeof callback === 'function') { moveOp() .then(() => callback()) .catch(callback); } else { return moveOp(); } }, copy(oldPath, newPath, callback) { fs.copyFile(oldPath, newPath, (err) => { if (err) throw err; // console.log('source.txt was copied to destination.txt'); }); }, extractFileName: function (filename) { return path.basename(filename); }, extractFilePath: function (filename) { return path.dirname(filename); }, async deleteFile(filePath) { try { await fs.promises.unlink(filePath); // console.log(`File eliminato con successo: ${filePath}`); } catch (err) { console.error(`Errore durante l'eliminazione del file: ${filePath}`, err); throw err; } }, async delete(mypath, alsothumb, callback) { try { if (await this.isFileExistsAsync(mypath)) { await fs.promises.unlink(mypath); // console.log(`deleted file ${mypath}`); if (alsothumb) { let img_small = ''; try { img_small = path.dirname(mypath) + '/' + server_constants.PREFIX_IMG_SMALL + path.basename(mypath); if (await this.isFileExistsAsync(img_small)) { await fs.promises.unlink(img_small); console.log(`deleted file ${img_small}`); } else { // console.warn(`File not found: ${img_small}`); } console.log(`deleted file ${img_small}`); } catch (e) { console.error(`Error deleting file ${img_small}`, e?.message); } } } } catch (e) { console.error(`Error deleting file ${mypath}`, e?.message); callback(e); return; } callback(); }, async mkdirpath(dirPath) { try { if (!(await this.isFileExistsAsync(dirPath))) { fs.mkdirSync(dirPath, { recursive: true }); } } catch (e) { if (dirPath !== path.dirname(dirPath)) { const myname = path.dirname(dirPath); await this.mkdirpath(myname); // this.mkdirpath(dirPath); } } }, getNomeCognomeTelegram(msg) { if (msg && msg.chat) { let nomecognome = msg.chat.first_name ? msg.chat.first_name : ''; nomecognome += msg.chat.last_name ? ' ' + msg.chat.last_name : ''; return nomecognome; } return ''; }, 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, ''); }, async ModificheConsentite(req, table, fieldsvalue, idrec, user) { const { Circuit } = require('../models/circuit'); if (table === 'sharewithus') { return true; } if (table === 'hours') { return true; } if (table === 'users') { if (idrec && req.user._id.toString() === idrec) { if (Object.keys(fieldsvalue).some((key) => key.startsWith('profile.'))) { return true; } if (Object.keys(fieldsvalue).some((key) => server_constants.User_Fields.includes(key))) { return true; } } 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; } } else if (table === 'circuits') { if (idrec) { // Permetti di fare modifiche se è un admin del circuito return await Circuit.isCircuitAdmin(idrec, req.user ? req.user.username : ''); } } else if (table === 'accounts') { if (idrec) { if ('fidoConcesso' in fieldsvalue) { // Permetti di fare modifiche se è un admin del circuito return await Circuit.isCircuitAdmin(idrec, req.user ? req.user.username : ''); } } } if (shared_consts.TABLES_PERM_CHANGE_FOR_USERS.includes(table)) { return true; } if (shared_consts.TABLES_PERM_NEWREC.includes(table)) { return true; } return false; }, NotifyIfDelRecord(table) { if (table === 'users' || table === 'extralist' || table === 'groups' || table === 'graduatorias') { 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 ''; }, getmaxcol(riga) { return Math.pow(2, riga - 1); }, getPrimoFuocoByIndCol(col) { // let ris = Math.ceil(col - (col % 8)) + 1; let ris = (Math.ceil(col / 8) - 1) * 8 + 1; if (ris <= 0) ris = 1; return ris; }, getPrimaColFlotta(col) { // let ris = Math.ceil(col - (col % 8)) + 1; let ris = (Math.ceil(col / 64) - 1) * 64 + 1; if (ris <= 0) ris = 1; return ris; }, getStrMsgByTipoMsg(tipomsg) { let mystr = ''; if (tipomsg === this.TipoMsg.SEND_MSG_EFFETTUA_IL_DONO) mystr = 'Inviato Messaggio per Effettuare il Dono a Tutta la Flotta'; else if (tipomsg === this.TipoMsg.SEND_MSG_SOLLECITO_DONATORI_NO_DONO) mystr = "Inviato Messaggio per RICORDARE di Effettuare il Dono a chi ancora non l'ha fatto"; else if (tipomsg === this.TipoMsg.SEND_MSG_A_MEDIATORI) mystr = 'Inviato Messaggio ai Mediatori'; else if (tipomsg === this.TipoMsg.SEND_MSG_A_SOGNATORE) mystr = 'Inviato Messaggio al Sognatore'; else if (tipomsg === this.TipoMsg.SEND_MSG_A_UTENTE_SOSTITUITO) mystr = "Inviato Messaggio all'utente Sostituito"; else if (tipomsg === this.TipoMsg.SEND_MSG_DONO_RICEVUTO_CORRETTAMENTE) mystr = 'Inviato Messaggio Dono Ricevuto Correttamente'; return mystr; }, getflagtelegrambyLang(lang) { if (lang === 'it') return '🇮🇹'; else if (lang === 'si') return '🇸🇮'; else if (lang === 'es') return '🇪🇸'; else if (lang === 'enUs') return '🇬🇧'; else if (lang === 'uk') return '🇬🇧'; else if (lang === 'fr') return '🇫🇷'; }, blockwords(mystr) { const arrwords = ['http', 'Http', 'Asasfasfas', '://', 'mrbit', 'admin', 'superuser']; try { for (const myword of arrwords) { if (mystr) { if (mystr.includes(myword)) { return true; } } } } catch (e) {} return false; }, isAlphaNumeric(str) { let code, i, len; for (i = 0, len = str.length; i < len; i++) { code = str.charCodeAt(i); if ( !(code > 47 && code < 58) && // numeric (0-9) !(code > 64 && code < 91) && // upper alpha (A-Z) !(code > 96 && code < 123) ) { // lower alpha (a-z) return false; } } return true; }, isAlphaNumericAndSpecialCharacter(str) { let code, i, len; for (i = 0, len = str.length; i < len; i++) { code = str.charCodeAt(i); if ( !(code > 47 && code < 58) && // numeric (0-9) !(code > 63 && code < 91) && // upper alpha (A-Z) // e @ code !== 46 && // . (punto) code !== 95 && // _ code !== 45 && // - !(code > 96 && code < 123) ) { // lower alpha (a-z) return false; } } return true; }, categorizeQueryString(queryObj) { let query = {}; let order = {}; //extract query, order, filter value for (const i in queryObj) { if (queryObj[i]) { // extract order if (i === 'order') { order['sort'] = queryObj[i]; continue; } // extract range if (i === 'range') { let range_arr = []; let query_arr = []; // multi ranges if (queryObj[i].constructor === Array) { for (const r of queryObj[i]) { range_arr = r.split('-'); query_arr.push({ price: { $gt: range_arr[0], $lt: range_arr[1] }, }); } } // one range if (queryObj[i].constructor === String) { range_arr = queryObj[i].split('-'); query_arr.push({ price: { $gt: range_arr[0], $lt: range_arr[1] }, }); } Object.assign(query, { $or: query_arr }); delete query[i]; continue; } query[i] = queryObj[i]; } } return { query, order }; }, dateToEpoch(thedate) { const time = new Date(thedate).getTime(); return time - (time % 86400000); }, dateToEpochStr(thedate) { const time = new Date(thedate).getTime(); return new Date(time - (time % 86400000)); }, async loadApps() { const Site = require('../models/site'); try { this.MYAPPS = await Site.findAll(0); // console.log('this.MYAPPS', this.MYAPPS); } catch (e) { console.error('loadApps', e); } }, async getApps() { if (this.MYAPPS.length <= 0) await this.loadApps(); return this.MYAPPS; }, getPaymentTypesById(idmetodo) { return shared_consts.PaymentTypes[idmetodo]; }, getVersionint(versionstr) { let versionarr = versionstr.split('.'); let version = 0; versionarr = versionarr.reverse(); for (let i = 0; i < versionarr.length; i++) { version += versionarr[i] * Math.pow(10, i * 2); } return parseInt(version); }, convstrToInt(mystr) { try { const parsed = parseInt(mystr, 10); // Specifica la base come 10 return isNaN(parsed) ? 0 : parsed; // Restituisce 0 se il valore è NaN } catch (e) { return 0; // Se c'è un errore, restituisce 0 } }, isValidNumber(value) { // Controlla se il valore è un numero valido return !isNaN(value) && value !== null && value !== ''; }, invertescapeslash(mystr) { return mystr.replace(/Ç/g, '/'); }, isNumber(n) { return typeof n != 'boolean' && !isNaN(n) && n; }, getNumObj(obj) { let count = 0; for (let properties in obj) { count = count + 1; } return count; }, getNomeCognomeEUserNameByUser(user) { let nome = `${user.name} ${user.surname} (${user.username})`; if (!user.name) { nome = user.username; } return nome; }, sulServer() { return process.env.LOCALE !== '1'; }, refreshAllTablesInMem(idapp, table, updatebot, username) { const telegrambot = require('../telegram/telegrambot'); if (table === shared_consts.TAB_BOTS || updatebot) { telegrambot.reloadMenuBot(idapp); } if (table === shared_consts.TAB_USERS) { telegrambot.deleteRecInMemByUsername(idapp, username); } else if (table === shared_consts.TAB_SITES) { telegrambot.reloadSites(); } }, downloadImage(url, filepath) { const download = require('image-downloader'); try { return download.image({ url, dest: filepath, }); } catch (e) { console.error('Err download image', e); return false; } }, async checkStr(msg, mystr, user, cmd) { if (msg.includes(mystr)) { if (cmd === 1) { msg = msg.replace(mystr, await this.getTimeExpReg(user.idapp, user.username)); } } return msg; }, getUnsubsribeUrl(mylocalsconf) { if (mylocalsconf) { const baseurl = this.getHostByIdApp(mylocalsconf.idapp); const urlunsibscribe = baseurl + '/unsubscribe?em=' + mylocalsconf.hashemail + '&mc=' + mylocalsconf.dataemail.mailchimpactive + '&email=' + mylocalsconf.emailto; return urlunsibscribe; } return ''; }, getUnsubsribeUrl_User(user) { if (user && user.email) { const hash = this.getHash(user.email + user.username); return this.getHostByIdApp(user.idapp) + '/unsubscribe_user?em=' + hash + '&email=' + user.email; } return ''; }, async convertSpecialTags(user, msg) { try { if (!msg) return msg; if (!!user) { if (msg.includes('{host}')) { msg = msg.replace('{host}', this.getHostByIdApp(user.idapp)); } if (msg.includes('{appname}')) msg = msg.replace('{appname}', this.getNomeAppByIdApp(user.idapp)); msg = msg.replace('{username}', user.username); // msg = await this.checkStr(msg, '{time_exp_reg}', user, 1); msg = msg.replace('{name}', user.name ? user.name : user.username); msg = msg.replace('{surname}', user.surname ? user.surname : ''); msg = msg.replace('{urlunsubscribe_user}', this.getUnsubsribeUrl_User(user)); msg = msg.replace('{aportador_solidario}', user.aportador_solidario ? user.aportador_solidario : ''); if (!!user.profile.link_payment) msg = msg.replace('{link_paypalme}', user.profile.link_payment); if (!!user.profile.revolut) msg = msg.replace('{revolut}', user.profile.revolut); if (!!user.profile.payeer_id) msg = msg.replace('{payeer_id}', user.profile.payeer_id); if (!!user.profile.advcash_id) msg = msg.replace('{advcash_id}', user.profile.advcash_id); if (!!user.profile.email_paypal) msg = msg.replace('{email_paypal}', user.profile.email_paypal); if (!!user.profile.note_payment) msg = msg.replace('{note_payment}', user.profile.note_payment); } // const cl = getclTelegByidapp(user.idapp); msg = msg.replace('{link_chathelp}', this.HELP_CHAT); } catch (e) { console.log(e); } return msg; }, getUserInfoMsg: function (idapp, myuser, usernametelegram = '', name_telegram = '', surname_telegram = '') { let msg = ''; try { const name = myuser.username + (myuser.name ? ` (${myuser.name} ${myuser.surname})` : ''); const linkuserprof = this.getHostByIdApp(idapp) + '/my/' + myuser.username; msg = `
👉🏻 ${name}
email: ${myuser.email}`; let u_tg = myuser.profile && myuser.profile.hasOwnProperty('username_telegram') ? myuser.profile.username_telegram : usernametelegram; let name_tg = myuser.profile && myuser.profile.hasOwnProperty('firstname_telegram') ? myuser.profile.firstname_telegram : name_telegram; let surname_tg = myuser.profile && myuser.profile.hasOwnProperty('lastname_telegram') ? myuser.profile.lastname_telegram : surname_telegram; let namesurnametg = ''; if (name_tg || surname_tg) namesurnametg = ` [${name_tg} ${surname_tg}]`; if (u_tg) { msg += `

Apri chat 👉🏻 https://t.me/${u_tg}`; } } catch (e) { console.error('getUserInfoMsg', e); } return msg; }, getUserShortInfoMsg: function (idapp, myuser, usernametelegram = '', name_telegram = '', surname_telegram = '') { let msg = ''; try { const name = myuser.username + (myuser.name ? ` (${myuser.name} ${myuser.surname})` : ''); const linkuserprof = this.getLinkUserProfile(idapp, myuser.username); let u_tg = myuser.profile && myuser.profile.hasOwnProperty('username_telegram') ? myuser.profile.username_telegram : usernametelegram; msg = `
Vedi Profilo sulla APP di ${name}`; msg += `
Telegram: @${u_tg}`; } catch (e) { console.error('getUserInfoMsg', e); } return msg; }, getlinkRelativeRequestNewPassword: function (idapp, email, tokenforgot) { const strlinkreg = process.env.LINK_UPDATE_PASSWORD + `?idapp=${idapp}&email=${email}&tokenforgot=${tokenforgot}`; return strlinkreg; }, getlinkRequestNewPassword: function (idapp, email, tokenforgot) { const strlinkreg = this.getHostByIdApp(idapp) + this.getlinkRelativeRequestNewPassword(idapp, email, tokenforgot); return strlinkreg; }, execScriptOnServer: async function (idapp, script, dir, listafiles, extfiles) { return new Promise(async (resolve, reject) => { exec(script, async (error, stdout, stderr) => { // Aggiunto async qui if (error) { console.error(`error: ${error}`); return reject(`Execution failed: ${error}`); } if (stderr) { console.error(`stderr: ${stderr}`); } // Se vuoi mantenere questa parte, puoi decommentarla // if (stdout) { // console.log(`OUT: ${stdout}`); // } let arrout = []; let arrscripts = stdout .split('\n') .filter((script) => script.trim() !== '') .map((script) => script.replace(/\//g, '')); for (let i = 0; i < arrscripts.length; i++) { let label = arrscripts[i]; let sock = false; let description = ''; if (listafiles) { if (arrscripts[i].endsWith('.sh')) { let labelFilePath = path.join(__dirname, '..', '..', '..', dir, `${arrscripts[i]}`); // Verifica se il file esiste try { // console.log(__dirname); // console.log(labelFilePath); // Leggi il contenuto del file .label const labelContent = await fs.readFileSync(labelFilePath, 'utf-8'); const lines = labelContent.split('\n'); for (let i = 0; i < lines.length; i++) { let linea = lines[i]; // se la linea inizia con #DATA if (linea.indexOf('#DATA') !== -1) { // estrai la linea separata da | let arrparams = linea.split('|'); if (arrparams && arrparams.length > 0) { let paramstr = arrparams[1].trim(); let value = arrparams[2].trim(); if (paramstr === 'TITLE') { label = value; } else if (paramstr === 'DESCRIZ') { description = value; } else if (paramstr === 'SOCK') { sock = value ? value.toLowerCase() === 'true' : false; } } } } } catch (error) { // Se desideri, puoi tenere un avviso o un log qui } } } else { label = ''; } if (label && (!extfiles || (extfiles && arrscripts[i].endsWith('.' + extfiles)))) { arrout.push({ label, value: arrscripts[i], description, sock }); } } resolve({ error, stdout, stderr, arrout }); }); }); }, execScriptNoOutput: function (script) { return new Promise((resolve, reject) => { console.log('execScriptNoOutput:', script); exec(script, (error, stdout, stderr) => { if (error) { console.error(`Exec error: ${error.message}`); return reject(error); } if (stderr) { console.warn(`Stderr (non bloccante): ${stderr}`); } resolve(true); }); }); }, execScriptWithInputOnServer: async function (idapp, script) { return new Promise((resolve, reject) => { const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); // Esegui il processo const child = spawn('bash', [script]); let outputData = ''; let errorData = ''; // Gestisci l'output standard child.stdout.on('data', (data) => { outputData += data.toString(); // Accumulate output data console.log(`Output: ${data}`); // Chiedi l'input dell'utente rl.question('Your input: ', (answer) => { child.stdin.write(`${answer}\n`); // Invia la risposta allo script }); }); // Gestisci l'output di errore child.stderr.on('data', (data) => { errorData += data.toString(); // Accumulate error data console.error(`Error: ${data}`); }); // Gestisci la chiusura del processo child.on('close', (code) => { console.log(`Process exited with code ${code}`); rl.close(); // Chiusura dell'interfaccia readline // Risolvi la promessa con i dati raccolti if (code !== 0) { reject(new Error(`Process exited with code ${code}: ${errorData}`)); // Rifiuta in caso di errore } else { resolve({ stdout: outputData, stderr: errorData }); } }); // Gestisci errori nel processo child.on('error', (error) => { reject(new Error(`Failed to start process: ${error.message}`)); }); }); }, execScriptByTelegram: function (idapp, msg, script, testo) { const { exec } = require('child_process'); const telegrambot = require('../telegram/telegrambot'); const idchat = msg.chat.id; console.log(testo + ' (' + script + ')'); telegrambot.local_sendMsgTelegramByIdTelegram(idapp, idchat, testo); exec(script, (error, stdout, stderr) => { if (error) { telegrambot.local_sendMsgTelegramByIdTelegram(idapp, idchat, 'ERROR: ' + error.message); console.log(`error: ${error.message}`); return; } if (stderr) { telegrambot.local_sendMsgTelegramByIdTelegram(idapp, idchat, 'ERROR: ' + stderr); console.log(`stderr: ${stderr}`); return; } // console.log(` ... stdout: ${stdout}`); telegrambot.local_sendMsgTelegramByIdTelegram(idapp, idchat, stdout); }); }, capitalize(value) { if (!value) { return ''; } const myval = value.toString(); return myval.charAt(0).toUpperCase() + myval.slice(1); }, truncateString(str, maxLength) { if (str.length > maxLength) { return str.slice(0, maxLength) + '...'; } else { return str; } }, removeFileExtension(filename) { // Trova l'ultima occorrenza del punto nel nome del file const lastDotIndex = filename.lastIndexOf('.'); // Se non c'è un punto o il punto è all'inizio del nome file, // restituisci il nome file originale if (lastDotIndex === -1 || lastDotIndex === 0) { return filename; } // Altrimenti, restituisci la parte del nome file prima dell'ultimo punto return filename.substring(0, lastDotIndex); }, removeSpanAndDivTags(text) { // Rimozione dei tag e dalla stringa di testo const spanRegex = /]*>|<\/span>/gi; const cleanedText = text.replace(spanRegex, ''); // Rimozione dei tag
e
dalla stringa di testo const divRegex = /]*>|<\/div>/gi; const finalText = cleanedText.replace(divRegex, ''); return finalText; }, firstchars(value, numchars = 200, continua, link) { if (!value) { return ''; } try { value = this.convertHTMLTagsForTelegram(value); value = this.removeSpanAndDivTags(value); truncatedValue = this.truncateString(value, numchars); if (str.length < maxLength) { continua = false; } // Aggiungi il testo aggiuntivo per indicare il troncamento if (continua) { if (link) { truncatedValue += ` (... continua sulla App)`; } else { truncatedValue += ` (... continua sulla App)`; } } else { truncatedValue += ' ...'; } return truncatedValue; } catch (e) { return value; } }, removeFontTags(text) { // Rimozione dei tag e dalla stringa di testo const regex = /]*>|<\/font>/gi; const cleanedText = text.replace(regex, ''); return cleanedText; }, removeAtChar(mystr) { if (mystr && mystr[0] === '@') { return (mystr = mystr.substring(1)); } return mystr; }, updateQueryStringParameter(uri, key, value) { if (uri === '' || !uri) return ''; var re = new RegExp('([?&])' + key + '=.*?(&|$)', 'i'); var separator = uri.indexOf('?') !== -1 ? '&' : '?'; if (uri.match(re)) { return uri.replace(re, '$1' + key + '=' + value + '$2'); } else { return uri + separator + key + '=' + value; } }, isArray(val) { return Array.isArray(val); }, getContentByTypeMsg(typemsg) {}, getContentNotifByParams(params, content, typesend) { if (typesend === shared_consts.TypeSend.TELEGRAM) { let myhost = this.getHostByIdApp(params.idapp); if (params.textaddTelegram) { content = content + '\n' + params.textaddTelegram; } if (params.linkaddTelegram) { if (params.openUrl) content = content + '\n' + '' + params.linkaddTelegram + ''; } /*if (params.openUrl) content = content + '\n' + '' + i18n.__('OPEN PAGE') + ''; */ } return content; }, getAhref(username, link) { return `${username}`; }, replaceStringAtEnd(inputString, searchString, replacement) { // Create a regular expression that matches the searchString at the end of the inputString const regex = new RegExp(searchString + '$'); // Use the replace method with the regular expression to replace the string const result = inputString.replace(regex, replacement); return result; }, getstrDateTimeEvent(myevent) { let mystr = ''; // is same day? if (this.getstrDateShort(myevent.dateTimeStart) === this.getstrDateShort(myevent.dateTimeEnd)) { mystr = i18n.__( 'DATEDAYONLY', this.getstrDateLong(myevent.dateTimeStart), this.getstrTime(myevent.dateTimeStart), this.getstrTime(myevent.dateTimeEnd) ); } else { mystr = i18n.__( 'DATE_2DAYS', this.getstrDateLong(myevent.dateTimeStart), this.getstrTime(myevent.dateTimeStart), this.getstrDateLong(myevent.dateTimeEnd), this.getstrTime(myevent.dateTimeEnd) ); } return '🗓 ' + mystr; }, getDoveStrByAnnuncio(myrec) { let dove = '🏠 '; if (myrec.mycities && myrec.mycities.length > 0) { dove += myrec.mycities .map((city) => { return `${city.comune} (${city.prov})`; }) .join(', '); } return dove; }, async getDescrEstesaStrByEvent(myrec) { let mystr = ''; mystr = await this.firstchars(this.replaceStringAtEnd(myrec.note, '', ''), 800); if (mystr) mystr = 'ℹ️ ' + mystr; return mystr; }, async getEventForTelegram(myrec, mydescr, userorig) { try { let datastr = this.getstrDateTimeEvent(myrec); let dovestr = this.getDoveStrByAnnuncio(myrec); let descrestesa = await this.getDescrEstesaStrByEvent(myrec); let organizedby = myrec.organisedBy; let contributo = myrec.contribstr; let newdescr = i18n.__('NEW_EVENT', userorig, datastr, mydescr, dovestr); let newdescrtelegram = i18n.__('NEW_EVENT_TELEGRAM', datastr, mydescr, dovestr, descrestesa, userorig); if (organizedby) { newdescrtelegram += i18n.__('ORGANIZED_BY', organizedby); } if (contributo) { newdescrtelegram += i18n.__('CONTRIB', contributo); } newdescrtelegram += i18n.__('EVENT_ADDED_FROM', userorig); return { newdescr, newdescrtelegram }; } catch (e) { console.error('Error', e); } }, addRowTelegram(icon, title, content, acapo, acapofine, islink) { let mystr = ''; let descrcontent = content; if (islink) { title = `${title}`; descrcontent = ''; } if (title) { if (icon) mystr += `${icon} `; mystr += `${title}`; if (acapo) { mystr += `\n`; } else { mystr += `: `; } } if (descrcontent) { mystr += `${descrcontent}\n`; if (acapofine) { mystr += `\n`; } } return mystr; }, async getInCambioDiByRec(myrec) { const { Contribtype } = require('../models/contribtype'); try { const idapp = myrec.idapp; if (!idapp) return ''; const contribtype = await Contribtype.findAllIdApp(idapp); let mystr = ''; for (const contribId of myrec.idContribType) { const reccontr = contribtype.find((rec) => rec._id.toString() === contribId); if (reccontr) { if (mystr) { mystr += ', '; } mystr += reccontr.label; } } return mystr; } catch (e) {} }, async getStatusSkillByRec(myrec, onlyifNoDiPersona) { const { StatusSkill } = require('../models/statusSkill'); try { const idapp = myrec.idapp; if (!idapp) return ''; const statusskill = await StatusSkill.findAllIdApp(idapp); let mystr = ''; if (onlyifNoDiPersona) { if (myrec.idStatusSkill.length === 1 && myrec.idStatusSkill[0] === shared_consts.STATUSSKILL_DI_PERSONA) return ''; } for (const status of myrec.idStatusSkill) { const reccontr = statusskill.find((rec) => rec._id === status); if (reccontr) { if (mystr) { mystr += ' e '; } mystr += reccontr.descr; } } return mystr; } catch (e) {} }, getIconByAdType(adType) { if (adType === shared_consts.AdType.OFFRO) return '🟢'; else if (adType === shared_consts.AdType.CERCO) return '🔴'; return ''; }, async getCategoriaSkillByRec(myrec) { const { Skill } = require('../models/skill'); const { Sector } = require('../models/sector'); try { // console.log('myrec', myrec); const idapp = myrec.idapp; if (!idapp) return ''; const skillrec = await Skill.findAllIdApp(idapp); const sectorrec = await Sector.findAllIdApp(idapp); let mystr = ''; const recsec = sectorrec.find((rec) => rec._id === myrec.idSector); if (recsec) { mystr += recsec.descr; } const rec = skillrec.find((rec) => rec._id === myrec.idSkill); if (rec) { mystr += ' 👉🏻 ' + rec.descr; } return mystr; } catch (e) {} }, async getCategoriaGoodByRec(myrec) { const { SectorGood } = require('../models/sectorgood'); // const { Good } = require('../models/good'); // const goodrec = await Good.findAllIdApp(idapp); try { const idapp = myrec.idapp; if (!idapp) return ''; const secgoodrec = await SectorGood.findAllIdApp(idapp); let mystr = ''; const rec = secgoodrec.find((rec) => rec._id === myrec.idSectorGood); // const rec = goodrec.find((rec) => rec._id === myrec.idSectorGood); if (rec) { mystr += rec.descr; } return mystr; } catch (e) {} }, getComuniEProvinceByRec(myrec) { try { let mystr = ''; if (myrec.hasOwnProperty('mycities')) { let ind = 0; for (const city of myrec.mycities) { if (ind > 0) mystr += ', '; mystr += city.comune + ' (' + city.prov + ')'; ind++; } } return mystr; } catch (e) {} }, convertAndTruncateHTMLForTelegram(text, maxLength = 200, link = '') { const tagMap = { '
    ': '', '
      ': '', '
    1. ': '\n• ', '
': '', '': '', '': '', '
': '\n', '
': '', '
': '\n', }; // Rimuoviamo specificamente \n text = text.replace(/\n<\/b>/g, ''); Object.keys(tagMap).forEach((tag) => { const replacement = tagMap[tag]; text = text.replaceAll(tag, replacement); }); text = text .split('\n') .map((line) => line.trim()) .join('\n'); text = text .replace(/\n{3,}/g, '\n\n') .replace(/\n+$/, '') .trim(); if (text.length <= maxLength) { return text; } // Tronchiamo il testo let truncated = text.slice(0, maxLength); let openTags = []; // Troviamo tutti i tag aperti const regex = /<(\w+)[^>]*>/g; let match; while ((match = regex.exec(truncated)) !== null) { if (!truncated.includes(``, match.index)) { openTags.push(match[1]); } } // Rimuoviamo l'ultima parola parziale truncated = truncated.replace(/\S+$/, ''); let strcontinua = ''; if (link) { strcontinua = ` (... continua sulla App)`; } else { strcontinua = ` (... continua sulla App)`; } // Aggiungiamo '...' e chiudiamo i tag aperti truncated += strcontinua; while (openTags.length > 0) { truncated += ``; } return truncated; }, convertHTMLTagsForTelegram(text) { const tagMap = { '
    ': '', '
      ': '', '
    1. ': '\n• ', '
': '', '': '', '': '', '
': '\n', '
': '', '
': '\n', }; // Rimuoviamo i tag vuoti o contenenti solo spazi bianchi o newline text = text.replace(/<(b|i|strong|em)>(\s|\n)*<\/\1>/g, ''); Object.keys(tagMap).forEach((tag) => { const replacement = tagMap[tag]; text = text.replaceAll(tag, replacement); }); // Rimuoviamo gli spazi bianchi all'inizio e alla fine di ogni riga text = text .split('\n') .map((line) => line.trim()) .join('\n'); // Rimuoviamo le righe vuote consecutive, lasciandone solo una text = text.replace(/\n{3,}/g, '\n\n'); // Rimuoviamo le righe vuote alla fine del testo text = text.replace(/\n+$/, ''); text = text.replace(/\n<\/b>/g, ''); return text.trim(); }, async getAnnuncioForTelegram(myrec, tablerec, mydescr, userorig, nuovo) { try { let newdescr = ''; let out = ''; let tiposcambio = ''; let iconascambio = '🟢'; let lang = 'it'; let datastr = ''; let dovestr = ''; let organizedby = ''; let contributo = ''; let img = ''; let descrperNotif = ''; if (tablerec === shared_consts.TABLES_MYGOODS || tablerec === shared_consts.TABLES_MYSKILLS) { iconascambio = this.getIconByAdType(myrec.adType); if (myrec.adType === shared_consts.AdType.OFFRO) tiposcambio = 'Offro'; else if (myrec.adType === shared_consts.AdType.CERCO) tiposcambio = 'Cerco'; } else if (tablerec === shared_consts.TABLES_MYHOSPS) { iconascambio = this.getIconByAdType(myrec.adType); if (myrec.adType === shared_consts.AdType.CERCO) tiposcambio = 'Cerco'; else tiposcambio = 'Offro'; if (myrec.typeHosp === shared_consts.TYPEHOSP_OSPITALITA) tiposcambio += ' Ospitalità'; else if (myrec.typeHosp === shared_consts.TYPEHOSP_SCAMBIOCASA) tiposcambio += ' Scambio Casa'; } else if (tablerec === shared_consts.TABLES_MYBACHECAS) { datastr = this.getstrDateTimeEvent(myrec); organizedby = myrec.organisedBy; contributo = myrec.contribstr; } if (tablerec === shared_consts.TABLES_MYGOODS) { newdescr = i18n.__('Good', userorig, mydescr); descrperNotif = i18n.__('Good: %', mydescr); } else if (tablerec === shared_consts.TABLES_MYSKILLS) { newdescr = i18n.__('Service', userorig, mydescr); descrperNotif = i18n.__('Service: %', mydescr); } else if (tablerec === shared_consts.TABLES_MYHOSPS) { newdescr = i18n.__('Hosp', userorig, mydescr); descrperNotif = i18n.__('Hosp %s', userorig, mydescr); } else if (tablerec === shared_consts.TABLES_MYBACHECAS) { newdescr = i18n.__('Event', userorig, mydescr); let dovestr = this.getDoveStrByAnnuncio(myrec); descrperNotif = i18n.__('NEW_EVENT', userorig, datastr, mydescr, dovestr); } let contatto = userorig; let contatto_telegram = ''; try { let username_telegram = myrec.profile.username_telegram; if (username_telegram) { contatto_telegram = `@${username_telegram}`; contatto = contatto_telegram; } else { contatto = myrec.email; } } catch (e) {} let organizedBy = ''; let cat = ''; let status = ''; let online = false; let solo_online = false; let writtenby = myrec.profile.username_telegram; let sitoweb = ''; let contact_phone = ''; let contact_email = ''; if (tablerec === shared_consts.TABLES_MYGOODS) { cat = await this.getCategoriaGoodByRec(myrec); } else if (tablerec === shared_consts.TABLES_MYSKILLS) { cat = await this.getCategoriaSkillByRec(myrec); online = myrec.idStatusSkill.findIndex((id) => id === shared_consts.STATUSSKILL_ONLINE) >= 0; solo_online = online && myrec.idStatusSkill.length === 1; status = await this.getStatusSkillByRec(myrec, true); if (status) { status = ' ' + status; } } else if (tablerec === shared_consts.TABLES_MYHOSPS) { cat = ''; } else if (tablerec === shared_consts.TABLES_MYBACHECAS) { if (myrec.website) { sitoweb = myrec.website; } contact_phone = myrec.contact_phone || ''; contact_email = myrec.contact_email || ''; if (myrec.organisedBy) { organizedBy = myrec.organisedBy; contatto = ''; } else { if (myrec.mygrp && myrec.mygrp.title) { organizedBy = myrec.mygrp.title; contatto = ''; } } if ( (myrec.contact_telegram && myrec.contact_telegram?.toLowerCase() !== contatto_telegram?.toLowerCase()) || !contatto ) { contatto += '\n' + myrec.contact_telegram; } /*if (myrec.contact_phone) { contatto += ' 📞 ' + myrec.contact_phone; }*/ } // let out = i18n.__('NEW_ANNUNCIO_TELEGRAM', mydescr, dovestr, descrestesa, userorig); if (tiposcambio) out += this.addRowTelegram(iconascambio, tiposcambio + status, '', true, false); const url = this.getHostByIdApp(myrec.idapp) + shared_consts.getDirectoryByTable(tablerec, true) + myrec._id; out += `${myrec.descr}\n\n`; if (datastr) out += this.addRowTelegram('', '', datastr, true, true); if (cat) out += this.addRowTelegram('⭐️', 'Categoria', cat, true, true); let descrcontent = this.convertAndTruncateHTMLForTelegram(myrec.note, 500, url); // let descrcontent = this.firstchars(this.removeLastSpaceAndACapo(note), 200, true, url); descrcontent = this.cleanHtmlForTelegram(descrcontent); // descrcontent = 'Prova Pao Ciaooo'; if (descrcontent) out += this.addRowTelegram('', '', '📝 ' + descrcontent, true, true); const localita = this.getComuniEProvinceByRec(myrec); if (!solo_online) out += this.addRowTelegram('🏠', 'Località', localita, false, true); const incambiodi = await this.getInCambioDiByRec(myrec); if (incambiodi) out += this.addRowTelegram('⚖️', 'In cambio di', incambiodi, false, true); if (organizedBy) { out += this.addRowTelegram('🏠', 'Organizzato da', organizedBy, false, true); } else { out += this.addRowTelegram('👤', 'Contatto', contatto, false, true); } if (contributo) out += this.addRowTelegram('💰', 'Contributo Richiesto', contributo, false, true); if (contact_phone || contact_email || sitoweb) { out += this.addRowTelegram( 'ℹ️', 'Per Info:', (contact_phone ? '📞 ' + contact_phone + ' ' : '') + (contact_email ? ' 📨 ' + contact_email + ' ' : '') + (sitoweb ? ' 🌐 ' + sitoweb + ' ' : ''), true, true ); } if (writtenby && organizedBy) { out += this.addRowTelegram('✍️', 'Redatto da', '@' + writtenby, false, true); } let cosastr = 'Annuncio'; if (tablerec === shared_consts.TABLES_MYBACHECAS) { cosastr = 'Evento'; } out += this.addRowTelegram('', `👉🏻 Vedi ${cosastr} completo su RISO`, url, true, true, true); if (myrec.photos && myrec.photos.length > 0) { // prende la prima foto ! ; if (myrec.photos[0].imagefile) img = this.getURLImg(myrec.idapp, tablerec, myrec.username, myrec.photos[0].imagefile, false); } console.log('out', out); // out += i18n.__('ADDED_FROM', ); return { newdescr, newdescrtelegram: out, img, descrperNotif }; } catch (e) { console.error('Error', e); } }, generateVapiKey() { const webpush = require('web-push'); const vapidKeys = webpush.generateVAPIDKeys(); const msg1 = 'VAPID Public Key:' + vapidKeys.publicKey; const msg2 = 'VAPID Private Key:' + vapidKeys.privateKey; console.log(msg1); console.log(msg2); return { msg: msg1 + ' ' + msg2 }; }, differentObjects(obj1, obj2) { try { const fieldsUpdated = []; const obj1Fields = obj1 ? Object.keys(obj1) : []; const obj2Fields = obj2 ? Object.keys(obj2) : []; const commonFields = obj1Fields.filter((field) => obj2Fields.includes(field)); commonFields.forEach((field) => { if (obj1 && obj2 && (obj1[field] && obj1[field].toString()) !== (obj2[field] && obj2[field].toString())) { if (obj1[field] !== undefined && obj2[field] !== undefined) fieldsUpdated.push(field); } }); return fieldsUpdated; } catch (e) { console.error('Err:', e); } }, isObjectEmpty(obj) { return Object.keys(obj).length === 0; }, getUnitsMeasure(unit, short) { const unitrec = shared_consts.Units_Of_Measure_ListBox.find((rec) => rec.value === unit); return unitrec ? (short ? unitrec.short : unitrec.label) : ''; }, getIdUnitsByText(unitstr) { const unitrec = shared_consts.Units_Of_Measure_ListBox.find((rec) => rec.short === unitstr); return unitrec ? unitrec.value : 0; }, getWeightAndUnitByText(text) { const result = []; text = text.replace(',', '.'); const regex = /^(\d+\.?\d*)\s*(ml|gr|g|l|kg|uova)\s*$/; // Aggiunto un punto dopo \d+ per accettare anche i numeri con la virgola const match = regex.exec(text); if (match) { let peso = parseFloat(match[1]); // Cambiato da parseInt a parseFloat per gestire i numeri con la virgola let unita = match[2]; if (unita === 'gr') unita = 'g'; const unit = this.getIdUnitsByText(unita); return { weight: peso, unit }; } return { weight: 0, unit: 0 }; }, async isManagerByReq(req) { try { var { User } = require('../models/user'); const idapp = req.body.idapp; let userId = ''; if (req.body) userId = req.body.userId; const myuser = await User.getUserById(idapp, userId); let ismanager = false; if (myuser && myuser.perm) { ismanager = User.isManager(myuser.perm); } return ismanager; } catch (e) { return false; } }, addslashes(str) { return (str + '').replace(/[\\"']/g, '\\$&').replace(/\u0000/g, '\\0'); }, removeescape(inputString) { // return inputString.replace(/\\/g, '').replace(/"/g, ''); if (inputString) return inputString.replace(/\\/g, '').replace(/"/g, ''); else return ''; }, escapeQuotes(stringa) { if (stringa) return stringa.replace(/"/g, '\\"'); else return ''; }, replaceQuotesWithSingleQuotes(jsonString) { if (jsonString) return jsonString.replace(/"/g, "'"); else return ''; }, ripulisciCampo(stringa) { let mystr = this.replaceQuotesWithSingleQuotes(stringa); return mystr; }, convertToNumeroVirgola(valstr) { if (valstr === '' || valstr === undefined) valstr = '0'; valstr = valstr + ''; valstr = valstr.replace(',', '.'); return parseFloat(valstr); }, convertPriceEurToValue(inputString) { inputString = this.removeescape(this.addslashes(inputString)); if (inputString === '') return '0'; // Rimuovi il simbolo della valuta (€) e sostituisci la virgola con un punto return inputString.replace(/[^\d.,]/g, '').replace(',', '.'); }, removeLastSpaceAndACapo(miastr) { miastr = miastr.trimRight().replace(/[\n\r]+$/, ''); // Rimuove eventuali '
' in fondo alla stringa // Rimuove eventuali '

' in fondo alla stringa miastr = miastr.replace(/<\/div>$/, ''); miastr = miastr.replace(/<\/div>$/, ''); miastr = miastr.replace(/
$/, ''); miastr = miastr.replace(/

<\/div>$/, ''); miastr = miastr.replace(/
$/, ''); miastr = miastr.trimRight().replace(/[\n\r]+$/, ''); miastr = miastr.replace(/

<\/div>$/, ''); miastr = miastr.replace(/
$/, ''); miastr = miastr.replace(/
$/, ''); miastr = miastr.replace(/
$/, ''); return miastr; }, rimuoviAtPrimoCarattere(stringa) { if (stringa.charAt(0) === '@') { return stringa.slice(1); } else { return stringa; } }, // Funzione per ottenere le coordinate di una singola città async getCityCoordinates(city) { try { const response = await axios.get( `https://nominatim.openstreetmap.org/search?format=json&q=${city.descr},${city.prov},Italia` ); if (response.data.length > 0) { city.lat = parseFloat(response.data[0].lat); city.long = parseFloat(response.data[0].lon); // console.log(`${city.descr}: Lat ${city.lat}, Long ${city.long}`); return city; } else { console.error(`Coordinate non trovate per ${city.descr}, ${city.prov}`); } return null; } catch (error) { console.error(`Errore durante il recupero delle coordinate per ${city.descr}, ${city.prov}:`, error.message); } }, /** * Funzione per scaricare dati GeoJSON dei comuni d'Italia e salvarli localmente. * @param {string} url - L'URL dal quale scaricare i dati GeoJSON. * @param {string} outputPath - Il percorso del file in cui salvare i dati GeoJSON. */ async downloadGeoJSON(url, outputPath) { try { // Effettua una richiesta GET all'URL specificato per scaricare i dati. const response = await axios.get(url); const data = response.data; // Salva i dati GeoJSON in un file locale. await fs.writeFile(outputPath, JSON.stringify(data, null, 2)); console.log(`Dati GeoJSON salvati in ${outputPath}`); } catch (error) { console.error('Errore durante il download o il salvataggio dei dati GeoJSON:', error); } }, arrotondaA2Decimali(valore) { try { return parseFloat(valore).toFixed(2); } catch (error) { return valore; } }, cleanHtmlForTelegram(htmlContent) { try { // Assicurati che l'HTML abbia un elemento body const dom = new JSDOM(`${htmlContent}`); const document = dom.window.document; // Definisci i tag permessi su Telegram const allowedTags = ['b', 'strong', 'i', 'em', 'u', 's', 'strike', 'del', 'a', 'code']; // Seleziona tutti gli elementi all'interno del body const allElements = document.body.querySelectorAll('*'); allElements.forEach((element) => { const tagName = element.tagName?.toLowerCase(); if (!allowedTags.includes(tagName)) { // Crea un nodo di testo e sostituisci l'elemento con quel nodo di testo const textNode = document.createTextNode(element.textContent || ''); element.replaceWith(textNode); } else { // Se il tag è permesso, rimuovi tutti gli attributi ad eccezione di 'href' per i link if (tagName === 'a') { const href = element.getAttribute('href'); while (element.attributes.length > 0) { element.removeAttribute(element.attributes[0].name); } if (href) { element.setAttribute('href', href); } } else { while (element.attributes.length > 0) { element.removeAttribute(element.attributes[0].name); } } } }); // Ritorna l'HTML pulito return document.body.innerHTML; } catch (error) { console.error("Errore durante la pulizia dell'HTML:", error); throw error; // Oppure, gestisci l'errore come preferisci } }, getHostWithNoHttporHttps(url) { try { const parsedUrl = new URL(url); return parsedUrl.host; } catch (error) { console.error("Errore durante la pulizia dell'HTML:", error); throw error; // Oppure, gestisci l'errore come preferisci } }, // Crea un file con all'interno il nome del dominio per ogni app: createFileWithDomainName() { const arrapps = getApps(); const filename = server_constants.FILECONFIG_SERVER; for (const app of arrapps) { fs.writeFile(filename, this.getHostWithNoHttporHttps(app.host), function (err) { if (err) { console.log(err); } }); if (app.host_test) { fs.writeFile(filename, this.getHostWithNoHttporHttps(app.host_test), function (err) { if (err) { console.log(err); } }); } } }, async listCollectionsBySize() { let output = ''; // Variabile per memorizzare l'output try { const conn = mongoose.connection; // Ottieni le collezioni e calcola la dimensione const collections = await conn.db.listCollections().toArray(); // Calcola la dimensione per ciascuna collezione const collectionSizes = await Promise.all( collections.map(async (collection) => { const stats = await conn.db.collection(collection.name).stats(); return { name: collection.name, size: stats.size }; }) ); // Ordina le collezioni per dimensione collectionSizes.sort((a, b) => b.size - a.size); // Ordine decrescente output += 'Collezioni ordinate per dimensione:\n'; // Inizio dell'output collectionSizes.forEach((collection) => { const sizeInMB = (collection.size / (1024 * 1024)).toFixed(2); // Converti in MB output += `Collezione: ${collection.name}, Dimensione: ${sizeInMB} MB\n`; // Aggiungi all'output }); return output; // Restituisci l'output alla fine } catch (error) { console.error('Errore:', error); return `Errore: ${error.message}`; // Restituisci l'errore come stringa } }, getStringaConto(mov) { let mystr = ''; let userfrom = ''; let userto = ''; let profilefrom = null; let profileto = null; let tipocontofrom = shared_consts.AccountType.USER; let tipocontoto = shared_consts.AccountType.USER; if (mov.contocomfrom && mov.contocomfrom.name) { userfrom += mov.contocomfrom.name; tipocontofrom = shared_consts.AccountType.COMMUNITY_ACCOUNT; } if (mov.groupfrom) { userfrom += mov.groupfrom.groupname; tipocontofrom = shared_consts.AccountType.CONTO_DI_GRUPPO; } if (mov.userfrom) { userfrom += mov.userfrom.username; profilefrom = mov.userfrom.profile; } if (mov.contocomto && mov.contocomto.name) { userto += mov.contocomto.name; tipocontoto = shared_consts.AccountType.COMMUNITY_ACCOUNT; } if (mov.groupto) { userto += mov.groupto.groupname; tipocontoto = shared_consts.AccountType.CONTO_DI_GRUPPO; } if (mov.userto) { userto += mov.userto.username; profileto = mov.userto.profile; } // mystr = t('movement.from') + userfrom + ' ' + t('movement.to') + userto return { userfrom: { profile: profilefrom, username: userfrom }, userto: { profile: profileto, username: userto }, tipocontofrom, tipocontoto, }; }, getDirUpload() { return 'upload/'; }, getDirByTable(idapp, table) { let mydir = this.getdirByIdApp(idapp) + '/'; if (table === 'catalog') { mydir = 'upload/cataloghi/'; } return mydir; }, getURLImg(idapp, table, username, img, checkifExist) { let dirmain = ''; try { // let dir = this.getdirByIdApp(idapp) + dirmain + '/' + this.getDirUpload(); let dir = this.getdirByIdApp(idapp); '/' + this.getDirUpload() + shared_consts.getDirectoryImgByTable(table, username) + dirmain; img = dir + img; /*if (checkifExist) { if (!this.isFileExistsAsync(img)) { return ''; } }*/ if (!this.sulServer()) { // Finta Immagine img = 'https://riso.app/upload/profile/SoniaVioletFlame/myskills/1000133092.jpg'; } return img; } catch (e) { console.error('Err GetURLImg', e); return ''; } }, getLangByUsername(idapp, username) { //++Todo LANG: Estrarre il Lang dall'username (user, group) return 'it'; }, getFieldsForAnnunci() { let annunciFields = { idMyGroup: { type: String, }, expiryDateAdv: { type: Date, }, enableExpiringAdv: { type: Boolean, }, // **ADDFIELD_ANNUNCI }; return annunciFields; }, // Funzione per pulire il nome del file cleanFileName(filePath) { // Ottieni solo il nome del file dall'intero percorso // const fileName = filePath.split('/').pop(); // Rimuovi apostrofi e sostituisci gli spazi con underscore const cleanedName = fileName.replace(/'/g, '').replace(/\s+/g, '_'); // Restituisci il percorso chiaro; puoi decidere di mantenere il resto del percorso return cleanedName; }, fixUrl(myurl, idapp) { if (!myurl.startsWith('http')) { return this.getHostByIdApp(idapp) + myurl; } if (myurl.startsWith('http://127.0.0.1')) { //myurl = myurl.replace('http://127.0.0.1:8084/', 'https://riso.app/') // Se è in locale allora metti una foto finta... myurl = 'https://images.unsplash.com/photo-1464047736614-af63643285bf?q=80&w=2874&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'; //myurl = myurl.replace('http://127.0.0.1', 'http://localhost') } return myurl; }, // Funzione per convertire XML in JSON convertXMLToJSON(xml) { const parser = new xml2js.Parser(); parser.parseString(xml, (err, result) => { if (err) { console.error('Error parsing XML:', err); } else { console.log(JSON.stringify(result, null, 2)); // Stampa il risultato in formato JSON } }); }, async getFreeDiskSpace(path = '/') { try { const { stdout } = await execPromise(`df -k ${path} | tail -1 | awk '{print $4}'`); const freeSpaceKB = parseInt(stdout.trim()); const freeSpaceGB = (freeSpaceKB / 1024 / 1024).toFixed(2); return `${freeSpaceGB} GB`; } catch (error) { console.error('Errore nel recupero dello spazio libero su disco:', error); return null; } }, async findAllQueryIdApp(model, myfind, sort) { try { if (sort) { return await model.find(myfind).sort(sort).lean(); } else { return await model.find(myfind).lean(); } } catch (err) { console.error('Errore in findAllQueryIdApp:', err, model); return null; } }, // Funzione per implementare il ritardo tra i tentativi sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }, /** * Converte una data in formato italiano GG/MM/YYYY in un oggetto Date e restituisce il timestamp. * @param {string} dateString - La data in formato GG/MM/YYYY. * @returns {Object} - Un oggetto contenente la data (Date) e il timestamp (number). * Restituisce null se la data non è valida. */ convertiDataItaliana(dateString) { // Verifica che la data sia una stringa valida if (!dateString || typeof dateString !== 'string') { console.error('Input non valido: la data deve essere una stringa.'); return null; } // Rimuovi eventuali spazi bianchi e dividi la data in GG, MM, YYYY const [giorno, mese, anno] = dateString.trim().split('/').map(Number); // Controlla che i valori siano stati estratti correttamente if (isNaN(giorno) || isNaN(mese) || isNaN(anno)) { console.error('Formato data non valido:', dateString); return null; } // Crea un oggetto Date (mese parte da 0 in JavaScript) const dateObj = new Date(anno, mese - 1, giorno); // Verifica che la data sia valida if (isNaN(dateObj.getTime())) { console.error('Data non valida:', dateString); return null; } // Restituisci l'oggetto con la data e il timestamp return { date: dateObj, timestamp: dateObj.getTime(), }; }, getDateFromISOString(mydate) { const mydate2 = new Date(mydate); return mydate2; }, async downloadImgIfMissing(productInfo) { const ProductInfo = require('../models/productInfo'); const Product = require('../models/product'); try { if (this.sulServer()) { dirmain = ''; } else { dirmain = server_constants.DIR_PUBLIC_LOCALE; } /*if (true) { const prova = await this.isFileExistsAsync('prova'); console.log('PROVA:', prova); }*/ const vecchiomodo = false; if (productInfo.image_link && vecchiomodo) { const relativeimg = productInfo.image_link.split('/').pop(); const img = this.getdirByIdApp(productInfo.idapp) + dirmain + server_constants.DIR_UPLOAD + '/products/' + productInfo.image_link.split('/').pop(); const savePath = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine let scaricaimg = !productInfo.imagefile || !(await this.isFileExistsAsync(savePath)); if (!productInfo.imagefile && (await this.isFileExistsAsync(savePath))) { // esiste il file, ma sul DB non è corretto const stats = fs.statSync(savePath); // Ottieni informazioni sul file if (stats.size > 0) { // Controlla se la dimensione del file è maggiore di zero // Esiste il file ed è non vuoto, ma sul DB non è corretto productInfo.imagefile = relativeimg; return { prodInfo: productInfo, aggiornatoimg: true }; } else { scaricaimg = true; } } if (productInfo.imagefile && (await this.isFileExistsAsync(savePath))) { // esiste il file, ma sul DB non è corretto const stats = fs.statSync(savePath); // Ottieni informazioni sul file if (stats.size <= 0) { // Controlla se la dimensione del file è maggiore di zero scaricaimg = true; } } if (scaricaimg && vecchiomodo) { // Download image from the URL productInfo.image_link productInfo.imagefile = relativeimg; const downloader = new ImageDownloader(); const aggiornatoimg = await downloader .downloadImage(productInfo.image_link, savePath, { maxRetries: 1, initialDelay: 300, timeout: 15000, }) .then((result) => { if (result) { // console.log('Download completato con successo!'); } else { console.log('Download non riuscito.'); } return result; }); return { prodInfo: productInfo, aggiornatoimg: aggiornatoimg.ris }; } } let fileesistente = false; if (productInfo.imagefile && productInfo.imagefile !== 'noimg.jpg') { // controlla se esiste il file const img = this.getdirByIdApp(productInfo.idapp) + dirmain + server_constants.DIR_UPLOAD + '/products/' + productInfo.imagefile.split('/').pop(); const filecompleto = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine // Se non esiste lo scarico ! fileesistente = await this.isFileExistsAsync(filecompleto); } if (!vecchiomodo && (!productInfo.image_link || !fileesistente)) { let scarica_da_sito = !productInfo.imagefile || productInfo.imagefile === 'noimg.jpg'; if (!scarica_da_sito && productInfo.imagefile) { scarica_da_sito = !fileesistente; // Se non esiste lo scarico ! } if (scarica_da_sito && !productInfo.image_not_found) { // date and time productInfo.imagefile = 'img_' + new Date().toISOString().replace(/T/, ' ').replace(/\..+/, ''); const img = this.getdirByIdApp(productInfo.idapp) + dirmain + server_constants.DIR_UPLOAD + '/products/' + productInfo.imagefile.split('/').pop(); let savePath = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine let link = 'https://www.gruppomacro.com/copertine.php?id_gm=' + productInfo.sku; const downloader = new ImageDownloader(); let aggiornatoimg; try { aggiornatoimg = await downloader.downloadImage(link, savePath, { maxRetries: 3, initialDelay: 300, timeout: 15000, nomefileoriginale: true, }); } catch (e) { aggiornatoimg = { ris: false }; } if ( aggiornatoimg?.code === 404 || (aggiornatoimg?.filepath && aggiornatoimg.filepath.includes('noimg.jpg')) ) { // non trovato quindi la prossima volta non richiederlo await ProductInfo.setImgNotFound(productInfo._id); } if (aggiornatoimg?.filepath.includes('noimg.jpg')) { // nascondi il prodotto se non trovo l'immagine ! await Product.updateOne({ idProductInfo: productInfo._id }, { $set: { deleted: true } }); aggiornatoimg = { ris: false, deleted: true }; } if (aggiornatoimg?.filepath) { const filenamebase = path.basename(aggiornatoimg.filepath); // const img = '/upload/products/' + filenamebase; productInfo.imagefile = filenamebase; } return { prodInfo: productInfo, aggiornatoimg: aggiornatoimg.ris }; } else { return { prodInfo: null, aggiornatoimg: false }; } } } catch (e) { console.error('downloadImgIfMissing', e.message); } return { prodInfo: null, aggiornatoimg: false }; }, removeAccents(mystr) { if (!mystr) return mystr; const accentsMap = new Map([ ['á', 'a'], ['à', 'a'], ['ã', 'a'], ['ä', 'a'], ['â', 'a'], ['é', 'e'], ['è', 'e'], ['ë', 'e'], ['ê', 'e'], ['í', 'i'], ['ì', 'i'], ['ï', 'i'], ['î', 'i'], ['ó', 'o'], ['ò', 'o'], ['ö', 'o'], ['ô', 'o'], ['õ', 'o'], ['ú', 'u'], ['ù', 'u'], ['ü', 'u'], ['û', 'u'], ['ç', 'c'], ['ñ', 'n'], ]); return Array.from(mystr) .map((char) => accentsMap.get(char) || char) .join(''); }, getDateYYYYMMDD_Today() { // Ottieni la data attuale nel formato YYYY-MM-DD const today = new Date(); const formattedDate = today.toISOString().split('T')[0]; // Format YYYY-MM-DD return formattedDate; }, convertFullFileNameToURL(idapp, fullfilename) { const mydir = this.getdirByIdApp(idapp); const myhost = this.getHostByIdApp(idapp); // ++ remove mydir from fullfilename and add myhost to generate a URL const url = fullfilename.replace(mydir, '').replace(/\\/g, '/'); // Replace backslashes with slashes const myurl = myhost + '/' + url; console.log('myurl', myurl); return myurl; }, removePathDirByFileName(idapp, fullfilename) { const mydir = this.getdirByIdApp(idapp); let filename = fullfilename.replace(mydir, '').replace(/\\/g, '/'); // Sostituisce backslash con slash // Rimuove la barra iniziale se presente if (filename.startsWith('/')) { filename = filename.substring(1); } return filename; }, isDateValid(mydate) { try { return ( mydate instanceof Date && isFinite(mydate.getTime()) && mydate.toISOString().split('T')[0] !== '1970-01-01' ); } catch { return false; } }, async getSizeFile(filename) { try { if (await this.isFileExistsAsync(filename)) { const stats = fs.statSync ? fs.statSync(filename) : null; const fileSizeInBytes = stats.size; const fileSizeInMB = fileSizeInBytes / (1024 * 1024); return fileSizeInMB.toFixed(2); // Returns size in MB with 2 decimal places } else { return 0; } } catch (e) { console.error('Error getting file size:', e); return '0.00'; } }, aggiungiSuffissoAlNomeFile(filePath, suffisso) { const dir = path.dirname(filePath); const estensione = path.extname(filePath); const nomeFile = path.basename(filePath, estensione); const nuovoNomeFile = nomeFile + suffisso + estensione; return path.join(dir, nuovoNomeFile); }, async attendiNSecondi(numsec) { await new Promise((resolve) => setTimeout(resolve, numsec * 1000)); }, async copyDirectory(sourceDir, destinationDir) { try { await fs.copy(sourceDir, destinationDir); console.log('Directory copiata con successo!'); } catch (err) { console.error('Errore durante la copia della directory:', err); } }, fixFilePath(myfilepath) { return myfilepath.replace(/\\/g, '/'); }, getDateNow() { const mydate = new Date(); return mydate; }, };