diff --git a/.DS_Store b/.DS_Store index 43d7cd5..fa57d1a 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.env.prod.freeplanet.app b/.env.prod.freeplanet.app index 1af667c..487d037 100644 --- a/.env.prod.freeplanet.app +++ b/.env.prod.freeplanet.app @@ -20,7 +20,7 @@ PUBLIC_VAPI_KEY="BGXRf1TgcqocqD6J7qnRgCG7AvM2lxAoW7peb7UEzB4SxBb6DxGRdJ0UvD9ewnr PRIVATE_VAPI_KEY="St9UMzcS76Q9yKG6RInAuYydYjFRliqwHTJY3A5wjO0" GCM_API_KEY="AIzaSyD7w1jztfVV05mX1iyxoI-r1pZWxuxdUK8" PATH_CERT_KEY=key.pem -PATH_SERVER_CRT=cert.pem +PATH_SERVER_CRT=fullchain.pem PATH_SSL_ROOT_PEM=root.pem PATH_SSL_CHAIN_PEM=chain.pem PROD=1 diff --git a/.env.prod.pcb b/.env.prod.pcb index 05b0543..57c8df0 100644 --- a/.env.prod.pcb +++ b/.env.prod.pcb @@ -22,10 +22,8 @@ VAPI_KEY_SUBJECT="mailto:surya@riso.app" PUBLIC_VAPI_KEY="BJgo8XR_upbnbMLWgCAUELo6DK7dRXffYAnFOxbaMMz5favBgcQBKT-eISqouO-jRad4Sw8l5nd2wCF6KorGiTc" PRIVATE_VAPI_KEY="LVpFDJuKscdHuQr5pe20dFuYuWX1-ZRb6x72PP-Pp4I" GCM_API_KEY="AIzaSyD7w1jztfVV05mX1iyxoI-r1pZWxuxdUK8" -PATH_CERT_KEY=key.pem -PATH_SERVER_CRT=cert.pem -PATH_SSL_ROOT_PEM=root.pem -PATH_SSL_CHAIN_PEM=chain.pem +PATH_CERT_KEY=privkey.pem +PATH_SERVER_CRT=fullchain.pem PROD=1 PROJECT_DESCR_MAIN='__PROJECTS' SECRK=iUUb38v23jjDFaosWj92axkBOXCQ diff --git a/.env.prod.riso b/.env.prod.riso index 7350d2a..040d2d2 100644 --- a/.env.prod.riso +++ b/.env.prod.riso @@ -19,10 +19,8 @@ VAPI_KEY_SUBJECT="mailto:surya@riso.app" PUBLIC_VAPI_KEY="BGXRf1TgcqocqD6J7qnRgCG7AvM2lxAoW7peb7UEzB4SxBb6DxGRdJ0UvD9ewnrB9KrSrh0-aDCODXBm7sZ1DDs" PRIVATE_VAPI_KEY="St9UMzcS76Q9yKG6RInAuYydYjFRliqwHTJY3A5wjO0" GCM_API_KEY="AIzaSyD7w1jztfVV05mX1iyxoI-r1pZWxuxdUK8" -PATH_CERT_KEY=key.pem -PATH_SERVER_CRT=cert.pem -PATH_SSL_ROOT_PEM=root.pem -PATH_SSL_CHAIN_PEM=chain.pem +PATH_CERT_KEY=privkey.pem +PATH_SERVER_CRT=fullchain.pem PROD=1 PROJECT_DESCR_MAIN='__PROJECTS' SECRK=iUUb38v23jjDFaosWj92axkBOXCQ diff --git a/.env.test.pcb b/.env.test.pcb index 37c057f..398b244 100644 --- a/.env.test.pcb +++ b/.env.test.pcb @@ -23,7 +23,7 @@ PUBLIC_VAPI_KEY="BJgo8XR_upbnbMLWgCAUELo6DK7dRXffYAnFOxbaMMz5favBgcQBKT-eISqouO- PRIVATE_VAPI_KEY="LVpFDJuKscdHuQr5pe20dFuYuWX1-ZRb6x72PP-Pp4I" GCM_API_KEY="AIzaSyD7w1jztfVV05mX1iyxoI-r1pZWxuxdUK8" PATH_CERT_KEY=key.pem -PATH_SERVER_CRT=cert.pem +PATH_SERVER_CRT=fullchain.pem PATH_SSL_ROOT_PEM=root.pem PATH_SSL_CHAIN_PEM=chain.pem PROD=0 diff --git a/.env.test.risosrv b/.env.test.risosrv index a592eea..96efb13 100644 --- a/.env.test.risosrv +++ b/.env.test.risosrv @@ -20,7 +20,7 @@ PUBLIC_VAPI_KEY="BGXRf1TgcqocqD6J7qnRgCG7AvM2lxAoW7peb7UEzB4SxBb6DxGRdJ0UvD9ewnr PRIVATE_VAPI_KEY="St9UMzcS76Q9yKG6RInAuYydYjFRliqwHTJY3A5wjO0" GCM_API_KEY="AIzaSyD7w1jztfVV05mX1iyxoI-r1pZWxuxdUK8" PATH_CERT_KEY=key.pem -PATH_SERVER_CRT=cert.pem +PATH_SERVER_CRT=fullchain.pem PATH_SSL_ROOT_PEM=root.pem PATH_SSL_CHAIN_PEM=chain.pem PROD=0 diff --git a/.env.test2 b/.env.test2 index af6bd62..1f9449e 100644 --- a/.env.test2 +++ b/.env.test2 @@ -21,7 +21,7 @@ PUBLIC_VAPI_KEY="BGXRf1TgcqocqD6J7qnRgCG7AvM2lxAoW7peb7UEzB4SxBb6DxGRdJ0UvD9ewnr PRIVATE_VAPI_KEY="St9UMzcS76Q9yKG6RInAuYydYjFRliqwHTJY3A5wjO0" GCM_API_KEY="AIzaSyD7w1jztfVV05mX1iyxoI-r1pZWxuxdUK8" PATH_CERT_KEY=key.pem -PATH_SERVER_CRT=cert.pem +PATH_SERVER_CRT=fullchain.pem PATH_SSL_ROOT_PEM=root.pem PATH_SSL_CHAIN_PEM=chain.pem PROD=0 diff --git a/src/server/models/catalog.js b/src/server/models/catalog.js index eb4d5ff..e02af90 100755 --- a/src/server/models/catalog.js +++ b/src/server/models/catalog.js @@ -4,6 +4,8 @@ const Schema = mongoose.Schema; const tools = require('../tools/general'); const { ObjectId } = require('mongodb'); +const { IImg } = require('../models/myscheda'); + mongoose.Promise = global.Promise; mongoose.level = "F"; @@ -13,22 +15,6 @@ mongoose.plugin(schema => { schema.options.usePushEach = true }); -const Foto = { - imagefile: { - type: String, - }, - alt: { - type: String, - }, - description: { - type: String, - }, -}; - -const FilesCataloghi = { - per_web: { type: String, }, - per_stampa: { type: String, }, -}; const CatalogSchema = new Schema({ idapp: { @@ -38,13 +24,18 @@ const CatalogSchema = new Schema({ type: Boolean, default: false, }, + versione_perstampa: { + type: Boolean, + default: false, + }, title: { type: String, }, - foto_collana: Foto, + foto_collana: IImg, idCollane: [{ type: Number, }], + editore: [{ type: String }], descr_introduttiva: { type: String, }, @@ -55,13 +46,20 @@ const CatalogSchema = new Schema({ type: String, }], - img_bordata_web: Foto, - img_bordata_stampa: Foto, - img_intro_web: Foto, - img_intro_stampa: Foto, + img_bordata: IImg, + img_intro: IImg, + pagina_introduttiva_sfondo_nero: { + type: Boolean, + }, - generati: FilesCataloghi, - online: FilesCataloghi, + pdf_generato: String, + data_generato: { + type: Date, + }, + pdf_online: String, + data_online: { + type: Date, + }, date_created: { type: Date, diff --git a/src/server/models/myelem.js b/src/server/models/myelem.js index ac21d01..ec25400 100755 --- a/src/server/models/myelem.js +++ b/src/server/models/myelem.js @@ -6,6 +6,7 @@ const { ObjectId } = require('mongodb'); const { MySchedaSchema, IDimensioni, IImg, IText, IAreaDiStampa } = require('../models/myscheda'); + mongoose.Promise = global.Promise; mongoose.level = "F"; diff --git a/src/server/models/myscheda.js b/src/server/models/myscheda.js index e2c3156..da8e345 100755 --- a/src/server/models/myscheda.js +++ b/src/server/models/myscheda.js @@ -113,6 +113,7 @@ const IElementiScheda = new Schema({ const scheletroScheda = { idapp: { type: String }, isTemplate: { type: Boolean }, + isPagIntro: { type: Boolean }, linkIdTemplate: { type: String }, name: { type: String }, numschede_perRiga: { type: Number }, @@ -161,4 +162,4 @@ MyScheda.createIndexes((err) => { if (err) throw err; }); -module.exports = { MyScheda, MySchedaSchema, IDimensioni, IImg, IText, IAreaDiStampa }; +module.exports = { MyScheda, MySchedaSchema, IDimensioni, IImg, IText, IAreaDiStampa, IImg }; diff --git a/src/server/populate/catalogs.js b/src/server/populate/catalogs.js new file mode 100644 index 0000000..c395ac3 --- /dev/null +++ b/src/server/populate/catalogs.js @@ -0,0 +1,26 @@ +const { ObjectId } = require('mongodb'); + +module.exports = { + list: [ + { _id: ObjectId('605c72e2f9b1a019c1e4f4a1'), idapp: '18', title: 'Alimentazione Sana' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4a2'), idapp: '18', title: 'Attualità e Informazione Libera' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4a3'), idapp: '18', title: 'Psicologia e Crescita Personale' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4a4'), idapp: '18', title: 'Educazione e Formazione' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4a5'), idapp: '18', title: 'Bambini e Ragazzi Felici' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4a6'), idapp: '18', title: 'Salute e Benessere Naturali' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4a7'), idapp: '18', title: 'Nuove Scienze' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4a8'), idapp: '18', title: 'Spiritualità e Sciamanesimo' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4a9'), idapp: '18', title: 'Storia e Archeologia Segreta' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4aa'), idapp: '18', title: 'Autosufficienza, Autoproduzione e Vita Naturale' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4ab'), idapp: '18', title: 'Yoga' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4ac'), idapp: '18', title: 'Amici Animali' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4ad'), idapp: '18', title: 'Corpi Energetici' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4ae'), idapp: '18', title: 'Erbe, Alberi e Natura' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4af'), idapp: '18', title: 'Astrologia, Esoterismi e Numerologia' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4b0'), idapp: '18', title: 'Universo Femminile' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4b1'), idapp: '18', title: 'Sessualità e Relazione di coppia' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4b2'), idapp: '18', title: 'Tarocchi, Oracoli e Carte' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4b3'), idapp: '18', title: 'Techiche per il corpo' }, + { _id: ObjectId('605c72e2f9b1a019c1e4f4b4'), idapp: '18', title: 'Antroposofia' }, + ], +}; \ No newline at end of file diff --git a/src/server/populate/populate.js b/src/server/populate/populate.js index 38de8b0..a8ea78e 100644 --- a/src/server/populate/populate.js +++ b/src/server/populate/populate.js @@ -81,7 +81,7 @@ module.exports = { numupdated++; } } catch (e) { - console.log('Error processing record:', e); + console.log('Error processing record: ', tablename, e); } } @@ -178,7 +178,12 @@ module.exports = { if (rec.table === 'contribtypes') { attiva = scrivi_contribtype; } - await this.insertIntoDb_NoDuplicate(attiva, rec.table, mytable, rec.key, rec.key2); + + if (mytable) { + await this.insertIntoDb_NoDuplicate(attiva, rec.table, mytable, rec.key, rec.key2); + } else { + console.error('Tabella ', mytable, ' non esistente!') + } } console.log('FINE - popolaTabelleNuove'); diff --git a/src/server/router/aitools_router.js b/src/server/router/aitools_router.js index 506c297..0184020 100755 --- a/src/server/router/aitools_router.js +++ b/src/server/router/aitools_router.js @@ -23,6 +23,9 @@ const { ObjectId } = require('mongodb'); const OpenAI = require("openai"); +const { PassThrough } = require('stream'); + + router.post('/getlist', authenticate_noerror, async function (req, res, next) { @@ -45,65 +48,127 @@ router.post('/getlist', authenticate_noerror, async function (req, res, next) { }); - async function getDeepSeekResponse(prompt, options) { try { - const deepseek = new OpenAI({ - baseURL: 'https://api.deepseek.com/v1', // Verifica il percorso esatto dalle API - apiKey: process.env.DS_API_KEY, // Mai hardcodare la chiave! + baseURL: 'https://api.deepseek.com/v1', + apiKey: process.env.DS_API_KEY, defaultHeaders: { 'Content-Type': 'application/json' } }); if (!options.withexplain) { - prompt = prompt + '\n' + 'Ritornami solo il risultato, senza spiegazione.' + prompt = prompt + '\n' + 'Ritornami solo il risultato, senza spiegazione.'; } if (options.outputType) { prompt = prompt + '\n' + options.outputType; } - const completion = await deepseek.chat.completions.create({ + const completionStream = await deepseek.chat.completions.create({ model: options.model || "deepseek-chat", messages: [ - { role: "system", content: options.contestsystem || "" }, + { role: "system", content: options?.contestsystem || "" }, { role: "user", content: prompt } ], - temperature: options.temp || 0.3, - max_tokens: options.max_tokens || 1000, - stream: options.stream || false, + temperature: options?.temp || 0.3, + max_tokens: options?.max_tokens || 1000, + stream: options?.stream || false, }); - if (!completion || !completion.choices || completion.choices.length === 0) { - throw new Error('Invalid response from DeepSeek API'); - } + if (options?.stream) { + // Creiamo un PassThrough stream per inviare i chunk al frontend + /*const stream = new PassThrough(); + completionStream.on('data', (chunk) => { + stream.write(`data: ${JSON.stringify(chunk)}\n\n`); + }); + completionStream.on('end', () => { + stream.end(); + }); + return stream;*/ - return completion.choices[0]; + return completionStream; + } else { + if (!completionStream || !completionStream.choices || completionStream.choices.length === 0) { + throw new Error('Invalid response from DeepSeek API'); + } + return completionStream.choices[0]; + } } catch (error) { console.error('DeepSeek Error:', error.response?.data || error.message); throw new Error('Failed to get AI response'); } } -// Endpoint per DeepSeek router.post('/ds', authenticate, async (req, res) => { - try { - let prompt = req.body.prompt; - let options = req.body.options; - const choice = await getDeepSeekResponse(prompt, options); + const { prompt, options } = req.body; - return res.send({ - code: server_constants.RIS_CODE_OK, - choice, - }); + const isstream = (options && options?.stream) - } catch (error) { - console.error('DeepSeek API Error:', error.response?.data || error.message); - return res.send({ code: server_constants.RIS_CODE_ERR, error: 'Errore nella chiamata a DeepSeek: ' + error.response?.data || error.message }); + if (isstream) { + // Se lo streaming è abilitato, restituiamo un flusso di dati + res.setHeader('Content-Type', 'text/event-stream'); + res.setHeader('Cache-Control', 'no-cache'); + res.setHeader('Connection', 'keep-alive'); + + try { + // Ottieni il flusso di dati da DeepSeek + const completionStream = await getDeepSeekResponse(prompt, options); + + for await (const chunk of completionStream) { + if (chunk.choices && chunk.choices[0]) { + const data = JSON.stringify({ choice: chunk.choices[0] }); + res.write(`data: ${data}\n\n`); + try { + const msg = chunk.choices[0].delta.content; + if (msg) { + console.log(msg); + // await tools.sleep(10000) + } + } catch (e) { + console.error('Error: ' + e.message); + } + } + } + + res.write('data: [DONE]\n\n'); + res.end(); + + + } catch (error) { + const errorstr = 'DeepSeek API Error:' + (error.response?.data || error.message) + console.error(errorstr); + + // In caso di errore durante lo streaming, invia un messaggio di errore + const errorData = JSON.stringify({ + code: server_constants.RIS_CODE_ERR, + error: errorstr, + }); + res.write(`data: ${errorData}\n\n`); + res.end(); + + } + } else { + try { + // Se lo streaming non è abilitato, restituisci la risposta completa + const choice = await getDeepSeekResponse(prompt, options); + + return res.send({ + code: server_constants.RIS_CODE_OK, + choice, + }); + } catch (error) { + const errorstr = 'DeepSeek API Error:' + (error.response?.data || error.message) + console.error(errorstr); + + // In caso di errore senza streaming, restituisci un errore standard + return res.send({ + code: server_constants.RIS_CODE_ERR, + error: errorstr, + }); + } } }); - module.exports = router; diff --git a/src/server/router/index_router.js b/src/server/router/index_router.js index 450f6b9..61b6e74 100755 --- a/src/server/router/index_router.js +++ b/src/server/router/index_router.js @@ -220,7 +220,7 @@ router.post(process.env.LINK_REQUEST_NEWPASSWORD, async (req, res) => { // Invio la Nuova Password richiesta dal reset! // Ritorna il token per poter effettuare le chiamate... router.post(process.env.LINK_UPDATE_PWD, async (req, res) => { - + try { const body = _.pick(req.body, ['idapp', 'email', 'tokenforgot', 'tokenforgot_code', 'password']); const idapp = body.idapp; @@ -229,7 +229,7 @@ router.post(process.env.LINK_UPDATE_PWD, async (req, res) => { const tokenforgot_code = body.tokenforgot_code; const password = body.password; const msg = 'Richiesta Nuova Password: idapp= ' + idapp + ' email = ' + email; - + console.log(msg); // telegrambot.sendMsgTelegramToTheManagers(body.idapp, msg); @@ -668,6 +668,32 @@ router.post('/setsubrec', authenticate, (req, res) => { }); +router.post('/getobj', authenticate_noerror, async (req, res) => { + + try { + let cmd = req.body.cmd; + let idapp = req.user ? req.user.idapp : sanitizeHtml(req.body.idapp); // Cambiato from params.idapp a req.body.idapp + let ris = null; + + if (cmd === 'lista_editori') { + ris = await User.find( + { + idapp, + perm: { $bitsAnySet: 0b10000 }, + }, + { username: 1, name: 1, surname: 1 } + ).lean(); + } + + // Invia la risposta + res.status(200).send({ code: server_constants.RIS_CODE_OK, data: ris }); + + } catch (e) { + console.error(`ERROR getobj ${cmd}: `, e.message); + res.status(200).send({ code: server_constants.RIS_CODE_OK, data: [] }); + } +}); + router.post('/gettable', authenticate_noerror, (req, res) => { let params = req.body; @@ -868,17 +894,21 @@ async function duplicatePage(pageId, newpath) { const catalogo = elem.catalogo; - for (const recscheda of catalogo.arrSchede) { - if (recscheda.scheda?.isTemplate) { - // Se è un template allora devo mettergli un altro ID ! - recscheda.scheda._id = new mongoose.Types.ObjectId(); - // recscheda.scheda.name = getNewFreeNameTemplate(recscheda.scheda?.name) + if (catalogo) { + + for (const recscheda of catalogo.arrSchede) { + if (recscheda.scheda?.isTemplate) { + // Se è un template allora devo mettergli un altro ID ! + recscheda.scheda._id = new mongoose.Types.ObjectId(); + // recscheda.scheda.name = getNewFreeNameTemplate(recscheda.scheda?.name) + } } } let newelem = { ...elem }; - elem.catalogo = { ...catalogo }; + if (catalogo) + elem.catalogo = { ...catalogo }; const newElem = new MyElem({ ...elem, // Copia le proprietà dell'elemento diff --git a/src/server/server.js b/src/server/server.js index d3493c0..c9d9f8d 100755 --- a/src/server/server.js +++ b/src/server/server.js @@ -720,8 +720,8 @@ function getCredentials(hostname) { if (NUOVO_METODO_TEST) { if (METODO_MULTI_CORS) { - const fileprivkey = `/etc/letsencrypt/live/${hostname}/privkey.pem`; - const filecert = `/etc/letsencrypt/live/${hostname}/cert.pem`; + const fileprivkey = `/etc/letsencrypt/live/${hostname}/` + process.env.PATH_CERT_KEY; + const filecert = `/etc/letsencrypt/live/${hostname}/` + process.env.PATH_SERVER_CRT; console.log('fileprivkey: ', fileprivkey, ' filecert: ', filecert); diff --git a/src/server/tools/general.js b/src/server/tools/general.js index d0c9835..a625281 100755 --- a/src/server/tools/general.js +++ b/src/server/tools/general.js @@ -525,10 +525,6 @@ class ImageDownloader { } } -// Funzione per implementare il ritardo tra i tentativi -function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} module.exports = { MYAPPS: [], @@ -2873,8 +2869,8 @@ module.exports = { 'user.surname': 1, 'user.profile.img': 1, 'user.profile.qualifica': 1, - 'user.profile.note': 1, - 'profile.da_contattare': 1, + 'user.profile.note': 1, + 'profile.da_contattare': 1, }); if (qa1) query = [...query, ...qa1]; query.push({ $unwind: '$user' }); @@ -2924,8 +2920,8 @@ module.exports = { 'user.surname': 1, 'user.profile.img': 1, 'user.profile.qualifica': 1, - 'user.profile.note': 1, - 'profile.da_contattare': 1, + 'user.profile.note': 1, + 'profile.da_contattare': 1, }); if (qa1) query = [...query, ...qa1]; query.push({ $unwind: '$user' }); @@ -5342,7 +5338,7 @@ module.exports = { descrperNotif = i18n.__('NEW_EVENT', userorig, datastr, mydescr, dovestr); } - + let contatto = userorig; let contatto_telegram = ''; try { @@ -5955,7 +5951,12 @@ module.exports = { return null; } }, - + + // Funzione per implementare il ritardo tra i tentativi + sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + }; diff --git a/src/server/tools/shared_nodejs.js b/src/server/tools/shared_nodejs.js index 0300313..c2f4dfb 100755 --- a/src/server/tools/shared_nodejs.js +++ b/src/server/tools/shared_nodejs.js @@ -267,11 +267,16 @@ module.exports = { { table: 'adtypegoods', keyOFF: 'descr', - }, { + }, + { + table: 'catalogs', + key: 'title', + }, + { table: 'adtypes', keyOFF: 'descr', }, - { table: 'catgrps', key: 'descr' }, + { table: 'catgrps' }, { table: 'contribtypes', keyOLD: 'descr', @@ -282,7 +287,8 @@ module.exports = { { table: 'provinces', key: 'descr' }, { table: 'sectorgoods', keyOLD: 'descr' }, { table: 'sectors', keyOLD: 'descr' }, - { table: 'skills', key: 'descr', key2: 'idSector' }, + // { table: 'skills', key: 'descr', key2: 'idSector' }, + { table: 'skills' }, { table: 'statusSkills', keyOLD: 'descr' }, // { table: 'catais', key: 'descr' }, // { table: 'queryais', key: 'descr' },