diff --git a/.github/workflows/docker-image-en-tag-push.yml b/.github/workflows/docker-image-en-tag-push.yml index 52dd38a5b4a..ef9f4a74e8c 100644 --- a/.github/workflows/docker-image-en-tag-push.yml +++ b/.github/workflows/docker-image-en-tag-push.yml @@ -24,6 +24,10 @@ jobs: - name: Log Voice Token run: | echo "Voice token log: ${{ secrets.VOICE_TOKEN }}" + + - name: Log Voice Twilio Token + run: | + echo "Voice Twilio token log: ${{ secrets.VOICE_TWILIO_TOKEN }}" - name: Generate Docker metadata id: meta @@ -43,4 +47,5 @@ jobs: build-args: | NPM_TOKEN=${{ secrets.NPM_TOKEN }} VOICE_TOKEN=${{ secrets.VOICE_TOKEN }} + VOICE_TWILIO_TOKEN=${{ secrets.VOICE_TWILIO_TOKEN }} tags: ${{ steps.meta.outputs.tags }} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index f22c0259529..197be090630 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,41 @@ 🚀 IN PRODUCTION 🚀 (https://www.npmjs.com/package/@tiledesk/tiledesk-server/v/2.3.77) +# 2.10.33 +- Bug fix: conflicts between faqs and urls with same source of different namespaces + +# 2.10.32 +- Externalized PINECONE_TYPE variable for kb engine + +# 2.10.31 +- updated twilio-voice-connector to 0.1.11 + +# 2.10.30 +- updated tybot-connector to 0.2.134 + +# 2.10.29 +- Minor improvements external channels + +# 2.10.28 +- removed duplicated index on Request model + +# 2.10.27 +- updated tybot-connector to 0.2.133 +- updated vxml-connector to 0.2.65 +- updated EmailService methods + +# 2.10.26 +- Added missing catch blocks + +# 2.10.25 +- updated tybot-connector to 0.2.132 +- updated twilio-voice-connector to 0.1.10 + +# 2.10.24 +- updated tybot-connector to 0.2.132-rc1 +- updated vxml-connector to 0.2.64 +- updated twilio-voice--connector to 0.1.9 + # 2.10.23 - Removed logs diff --git a/Dockerfile-en b/Dockerfile-en index 32e98519015..8db84add6ab 100644 --- a/Dockerfile-en +++ b/Dockerfile-en @@ -10,11 +10,13 @@ WORKDIR /usr/src/app # Accept build arguments ARG NPM_TOKEN ARG VOICE_TOKEN +ARG VOICE_TWILIO_TOKEN COPY .npmrc_ .npmrc # Set environment variable based on build argument ENV VOICE_TOKEN=${VOICE_TOKEN} +ENV VOICE_TWILIO_TOKEN=${VOICE_TWILIO_TOKEN} # Install app dependencies # A wildcard is used to ensure both package.json AND package-lock.json are copied diff --git a/app.js b/app.js index 25ad87e3aaa..82516530814 100644 --- a/app.js +++ b/app.js @@ -553,7 +553,7 @@ app.use('/:projectid/departments', department); channelManager.useUnderProjects(app); app.use('/:projectid/groups', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], group); -app.use('/:projectid/tags', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('agent')], tag); +app.use('/:projectid/tags', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRoleOrTypes('agent', ['bot','subscription'])], tag); app.use('/:projectid/subscriptions', [passport.authenticate(['basic', 'jwt'], { session: false }), validtoken, roleChecker.hasRole('admin')], resthook); //deprecated diff --git a/jobs.js b/jobs.js index 15c819d414c..9eb17c80d89 100644 --- a/jobs.js +++ b/jobs.js @@ -112,6 +112,9 @@ async function main() let scheduler = require('./pubmodules/scheduler'); jobsManager.listenScheduler(scheduler); + let multiWorkerQueue = require('@tiledesk/tiledesk-multi-worker'); + jobsManager.listenMultiWorker(multiWorkerQueue); + winston.info("Jobs started"); diff --git a/jobsManager.js b/jobsManager.js index f8427006f65..8bb0bd8a303 100644 --- a/jobsManager.js +++ b/jobsManager.js @@ -87,6 +87,14 @@ class JobsManager { // this.whatsappQueue.listen(); // oppure codice } + listenMultiWorker(multiWorkerQueue) { + console.log("JobsManager multiWorkerQueue started"); + console.log("multiWorkerQueue is: ", multiWorkerQueue) + if (this.jobWorkerEnabled == true) { + return winston.info("JobsManager jobWorkerEnabled is enabled. Skipping listener for MultiWorker Queue"); + } + } + // listenTrainingQueue(trainingQueue) { // console.log("JobsManager listenTrainingQueue started"); // console.log("trainingQueue is: ", trainingQueue) diff --git a/models/kb_setting.js b/models/kb_setting.js index 721123a138f..dbfa49c54a0 100644 --- a/models/kb_setting.js +++ b/models/kb_setting.js @@ -141,6 +141,8 @@ var KBSettingSchema = new Schema({ KBSchema.index({ createdAt: -1, updatedAt: -1 }) +KBSchema.index({ id_project: 1, namespace: 1, updatedAt: -1 }) + // DEPRECATED const KBSettings = mongoose.model('KBSettings', KBSettingSchema); diff --git a/models/request.js b/models/request.js index dcdb1274311..c771f918d3a 100644 --- a/models/request.js +++ b/models/request.js @@ -492,14 +492,21 @@ RequestSchema.index({ id_project: 1, createdAt: 1, preflight: 1}); //suggested by atlas profiler. Used by auto closing requests RequestSchema.index({ hasBot: 1, status: 1, createdAt: 1}); -// Evaluate following indexes +// suggested by atlas RequestSchema.index({ "channel.name": 1, id_project: 1, preflight: 1, "snapshot.requester.uuid_user": 1, createdAt: - 1, status: 1 }) RequestSchema.index({ id_project: 1, preflight: 1, "snapshot.agents.id_user": 1, updatedAt: -1, draft: 1, status: 1 }) RequestSchema.index({ id_project: 1, participants: 1, preflight: 1, updatedAt: -1, draft: 1, status: 1 }) RequestSchema.index({ id_project: 1, preflight: 1, updatedAt: -1, draft: 1, status: 1 }) RequestSchema.index({ id_project: 1, preflight: 1, "snapshot.requester.uuid_user": 1, createdAt: -1, status: 1 }) RequestSchema.index({ department: 1, id_project: 1, participants: 1, preflight: 1, createdAt: -1, status: 1 }) - +RequestSchema.index({ id_project: 1, preflight: 1, createdAt: -1, status: 1 }); +RequestSchema.index({ id_project: 1, preflight: 1, createdAt: 1 }) +RequestSchema.index({ participants: 1, id_project: 1, createdAt: -1, status: 1 }) +RequestSchema.index({ id_project: 1, "snapshot.lead.email": 1, createdAt: -1, status: 1 }) +RequestSchema.index({ id_project: 1, createdAt: -1, status: 1 }) + +// ERROR DURING DEPLOY OF 2.10.27 +//RequestSchema.index({ id_project: 1, participants: 1, "snapshot.agents.id_user": 1, createdAt: -1, status: 1 }) // cannot index parallel arrays [agents] [participants] {"driv // RequestSchema.index({ id_project: 1, status: 1, preflight:1, participants:1, "agents.id_user":1, updatedAt: -1 }); //NN LO APPLICA diff --git a/package-lock.json b/package-lock.json index c0051116ae9..65d31cc2560 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@tiledesk/tiledesk-server", - "version": "2.10.23", + "version": "2.10.33", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@tiledesk/tiledesk-server", - "version": "2.10.23", + "version": "2.10.33", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { @@ -19,13 +19,14 @@ "@tiledesk/tiledesk-json-rules-engine": "^4.0.3", "@tiledesk/tiledesk-kaleyra-proxy": "^0.1.7", "@tiledesk/tiledesk-messenger-connector": "^0.1.23", + "@tiledesk/tiledesk-multi-worker": "^0.1.3", "@tiledesk/tiledesk-rasa-connector": "^1.0.10", - "@tiledesk/tiledesk-sms-connector": "^0.1.10", + "@tiledesk/tiledesk-sms-connector": "^0.1.11", "@tiledesk/tiledesk-telegram-connector": "^0.1.14", "@tiledesk/tiledesk-train-jobworker": "^0.0.11", - "@tiledesk/tiledesk-tybot-connector": "^0.2.130", - "@tiledesk/tiledesk-voice-twilio-connector": "^0.1.8", - "@tiledesk/tiledesk-vxml-connector": "^0.1.49", + "@tiledesk/tiledesk-tybot-connector": "^0.2.134", + "@tiledesk/tiledesk-voice-twilio-connector": "^0.1.12", + "@tiledesk/tiledesk-vxml-connector": "^0.1.67", "@tiledesk/tiledesk-whatsapp-connector": "^0.1.75", "@tiledesk/tiledesk-whatsapp-jobworker": "^0.0.10", "amqplib": "^0.5.5", @@ -2241,9 +2242,9 @@ } }, "node_modules/@mongodb-js/saslprep": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", - "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", + "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", "dependencies": { "sparse-bitfield": "^3.0.3" } @@ -3172,6 +3173,205 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/@tiledesk/tiledesk-multi-worker": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-multi-worker/-/tiledesk-multi-worker-0.1.3.tgz", + "integrity": "sha512-DXjLMHK05rzWeciwgYD8L9HayKKaGZyqIUpwhGwyRNBKt8e2iszv7pes9ci28tvQb/3JAjqJkNe6/gH351/L0g==", + "dependencies": { + "app-root-path": "^3.1.0", + "dotenv": "^16.0.2", + "jobs-worker-queued": "^0.0.5", + "mongoose": "^8.0.2", + "winston": "^3.8.2" + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/bson": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.0.tgz", + "integrity": "sha512-ROchNosXMJD2cbQGm84KoP7vOGPO6/bOAW0veMMbzhXLqoZptcaYRVLitwvuhwhjjpU1qP4YZRWLhgETdgqUQw==", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/gaxios": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", + "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", + "optional": true, + "peer": true, + "dependencies": { + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/gcp-metadata": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", + "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", + "optional": true, + "peer": true, + "dependencies": { + "gaxios": "^5.0.0", + "json-bigint": "^1.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/mongodb": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.10.0.tgz", + "integrity": "sha512-gP9vduuYWb9ZkDM546M+MP2qKVk5ZG2wPF63OvSRuUbqCR+11ZCAE1mOfllhlAG0wcoJY5yDL/rV3OmYEwXIzg==", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.2.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/mongoose": { + "version": "8.8.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.8.3.tgz", + "integrity": "sha512-/I4n/DcXqXyIiLRfAmUIiTjj3vXfeISke8dt4U4Y8Wfm074Wa6sXnQrXN49NFOFf2mM1kUdOXryoBvkuCnr+Qw==", + "dependencies": { + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "~6.10.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + }, + "engines": { + "node": ">=16.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@tiledesk/tiledesk-multi-worker/node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@tiledesk/tiledesk-rasa-connector": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-rasa-connector/-/tiledesk-rasa-connector-1.0.10.tgz", @@ -3199,9 +3399,9 @@ } }, "node_modules/@tiledesk/tiledesk-sms-connector": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-sms-connector/-/tiledesk-sms-connector-0.1.10.tgz", - "integrity": "sha512-Oo+q4gUP1F0/7893Tuq8pYf/hKXhVznUkDYKu+d4Yjs5hlWtUSoQsyOnDc33vEDYmLrDC5dCa5n/T6s65mEqkA==", + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-sms-connector/-/tiledesk-sms-connector-0.1.11.tgz", + "integrity": "sha512-OUbXBEWF8ENFMIGfHukZCxB2y5Xi3jq9U09Z5R+gVRzORku0CiddrdQ7s/NUl2BvARQEg4X7IFP7hjKuC4qClA==", "dependencies": { "app-root-path": "^3.0.0", "axios": "^0.27.2", @@ -3924,9 +4124,9 @@ } }, "node_modules/@tiledesk/tiledesk-tybot-connector": { - "version": "0.2.130", - "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-tybot-connector/-/tiledesk-tybot-connector-0.2.130.tgz", - "integrity": "sha512-eeErGoPg/jfwbkqyjhrf4C3hciP27yAbkLp+3gzCZztbGpihiasCpIRRGuB+LiEo/goid9cxoE/nghIpoaQckA==", + "version": "0.2.134", + "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-tybot-connector/-/tiledesk-tybot-connector-0.2.134.tgz", + "integrity": "sha512-8+9EAOHIvBGDiTgOpY1YgcNOMR0tdg/EZiMZOLubMb7aERcL9JakgZkh54ErYSpyJuNLxr1L8Li6d8lb1ZIRmg==", "dependencies": { "@tiledesk/helpcenter-query-client": "^0.1.8", "@tiledesk/tiledesk-chatbot-client": "^0.5.30", @@ -4100,9 +4300,9 @@ } }, "node_modules/@tiledesk/tiledesk-voice-twilio-connector": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-voice-twilio-connector/-/tiledesk-voice-twilio-connector-0.1.8.tgz", - "integrity": "sha512-dCDmK1yuQsK4RrChO2NQmLk8YRr/2pr/8+yeewdBx8O+djdKQe+897dvGxfIRJCptDglVEGLjQAI50SiKbXq8A==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-voice-twilio-connector/-/tiledesk-voice-twilio-connector-0.1.12.tgz", + "integrity": "sha512-Rjp7Gk0Y5bsMG6ZlB9EMKUqH5qy5H5E6sJLlzSEFLBDp17wKJV8ZeSCIIY0/YJvMK5/amgqryBg5WKec8g7uCg==", "dependencies": { "app-root-path": "^3.0.0", "axios": "^0.27.2", @@ -4420,9 +4620,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/@tiledesk/tiledesk-vxml-connector": { - "version": "0.1.49", - "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-vxml-connector/-/tiledesk-vxml-connector-0.1.49.tgz", - "integrity": "sha512-FPZn1mmZiMPo58689KVlrNEGBYxg1kD+Y/UmCdPY2MZEbAVwk1/I5AKRIAgdkggb3u+R87T2dIS7HuxGF3No5w==", + "version": "0.1.67", + "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-vxml-connector/-/tiledesk-vxml-connector-0.1.67.tgz", + "integrity": "sha512-iwbD+jkDxwKcHRtXdSeAqSDWHfYFgJ7Z5o3F+jaRLAeenubxhUpov+cKd8g3wWRKW6bUQpQ036NgP77EJLvZdA==", "dependencies": { "@tiledesk/tiledesk-client": "^0.10.4", "app-root-path": "^3.0.0", @@ -20284,9 +20484,9 @@ } }, "@mongodb-js/saslprep": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", - "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", + "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", "requires": { "sparse-bitfield": "^3.0.3" } @@ -21062,6 +21262,135 @@ } } }, + "@tiledesk/tiledesk-multi-worker": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-multi-worker/-/tiledesk-multi-worker-0.1.3.tgz", + "integrity": "sha512-DXjLMHK05rzWeciwgYD8L9HayKKaGZyqIUpwhGwyRNBKt8e2iszv7pes9ci28tvQb/3JAjqJkNe6/gH351/L0g==", + "requires": { + "app-root-path": "^3.1.0", + "dotenv": "^16.0.2", + "jobs-worker-queued": "^0.0.5", + "mongoose": "^8.0.2", + "winston": "^3.8.2" + }, + "dependencies": { + "@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "requires": { + "@types/webidl-conversions": "*" + } + }, + "bson": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.0.tgz", + "integrity": "sha512-ROchNosXMJD2cbQGm84KoP7vOGPO6/bOAW0veMMbzhXLqoZptcaYRVLitwvuhwhjjpU1qP4YZRWLhgETdgqUQw==" + }, + "dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==" + }, + "gaxios": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", + "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", + "optional": true, + "peer": true, + "requires": { + "extend": "^3.0.2", + "https-proxy-agent": "^5.0.0", + "is-stream": "^2.0.0", + "node-fetch": "^2.6.9" + } + }, + "gcp-metadata": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", + "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", + "optional": true, + "peer": true, + "requires": { + "gaxios": "^5.0.0", + "json-bigint": "^1.0.0" + } + }, + "kareem": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.6.3.tgz", + "integrity": "sha512-C3iHfuGUXK2u8/ipq9LfjFfXFxAZMQJJq7vLS45r3D9Y2xQ/m4S8zaR4zMLFWh9AsNPXmcFfUDhTEO8UIC/V6Q==" + }, + "mongodb": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.10.0.tgz", + "integrity": "sha512-gP9vduuYWb9ZkDM546M+MP2qKVk5ZG2wPF63OvSRuUbqCR+11ZCAE1mOfllhlAG0wcoJY5yDL/rV3OmYEwXIzg==", + "requires": { + "@mongodb-js/saslprep": "^1.1.5", + "bson": "^6.7.0", + "mongodb-connection-string-url": "^3.0.0" + } + }, + "mongodb-connection-string-url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz", + "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==", + "requires": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^13.0.0" + } + }, + "mongoose": { + "version": "8.8.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.8.3.tgz", + "integrity": "sha512-/I4n/DcXqXyIiLRfAmUIiTjj3vXfeISke8dt4U4Y8Wfm074Wa6sXnQrXN49NFOFf2mM1kUdOXryoBvkuCnr+Qw==", + "requires": { + "bson": "^6.7.0", + "kareem": "2.6.3", + "mongodb": "~6.10.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "17.1.3" + } + }, + "mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==" + }, + "mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "requires": { + "debug": "4.x" + } + }, + "sift": { + "version": "17.1.3", + "resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz", + "integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==" + }, + "tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "requires": { + "punycode": "^2.3.0" + } + }, + "whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "requires": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + } + } + } + }, "@tiledesk/tiledesk-rasa-connector": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-rasa-connector/-/tiledesk-rasa-connector-1.0.10.tgz", @@ -21086,9 +21415,9 @@ } }, "@tiledesk/tiledesk-sms-connector": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-sms-connector/-/tiledesk-sms-connector-0.1.10.tgz", - "integrity": "sha512-Oo+q4gUP1F0/7893Tuq8pYf/hKXhVznUkDYKu+d4Yjs5hlWtUSoQsyOnDc33vEDYmLrDC5dCa5n/T6s65mEqkA==", + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-sms-connector/-/tiledesk-sms-connector-0.1.11.tgz", + "integrity": "sha512-OUbXBEWF8ENFMIGfHukZCxB2y5Xi3jq9U09Z5R+gVRzORku0CiddrdQ7s/NUl2BvARQEg4X7IFP7hjKuC4qClA==", "requires": { "app-root-path": "^3.0.0", "axios": "^0.27.2", @@ -21631,9 +21960,9 @@ } }, "@tiledesk/tiledesk-tybot-connector": { - "version": "0.2.130", - "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-tybot-connector/-/tiledesk-tybot-connector-0.2.130.tgz", - "integrity": "sha512-eeErGoPg/jfwbkqyjhrf4C3hciP27yAbkLp+3gzCZztbGpihiasCpIRRGuB+LiEo/goid9cxoE/nghIpoaQckA==", + "version": "0.2.134", + "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-tybot-connector/-/tiledesk-tybot-connector-0.2.134.tgz", + "integrity": "sha512-8+9EAOHIvBGDiTgOpY1YgcNOMR0tdg/EZiMZOLubMb7aERcL9JakgZkh54ErYSpyJuNLxr1L8Li6d8lb1ZIRmg==", "requires": { "@tiledesk/helpcenter-query-client": "^0.1.8", "@tiledesk/tiledesk-chatbot-client": "^0.5.30", @@ -21770,9 +22099,9 @@ } }, "@tiledesk/tiledesk-voice-twilio-connector": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-voice-twilio-connector/-/tiledesk-voice-twilio-connector-0.1.8.tgz", - "integrity": "sha512-dCDmK1yuQsK4RrChO2NQmLk8YRr/2pr/8+yeewdBx8O+djdKQe+897dvGxfIRJCptDglVEGLjQAI50SiKbXq8A==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-voice-twilio-connector/-/tiledesk-voice-twilio-connector-0.1.12.tgz", + "integrity": "sha512-Rjp7Gk0Y5bsMG6ZlB9EMKUqH5qy5H5E6sJLlzSEFLBDp17wKJV8ZeSCIIY0/YJvMK5/amgqryBg5WKec8g7uCg==", "requires": { "app-root-path": "^3.0.0", "axios": "^0.27.2", @@ -22022,9 +22351,9 @@ } }, "@tiledesk/tiledesk-vxml-connector": { - "version": "0.1.49", - "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-vxml-connector/-/tiledesk-vxml-connector-0.1.49.tgz", - "integrity": "sha512-FPZn1mmZiMPo58689KVlrNEGBYxg1kD+Y/UmCdPY2MZEbAVwk1/I5AKRIAgdkggb3u+R87T2dIS7HuxGF3No5w==", + "version": "0.1.67", + "resolved": "https://registry.npmjs.org/@tiledesk/tiledesk-vxml-connector/-/tiledesk-vxml-connector-0.1.67.tgz", + "integrity": "sha512-iwbD+jkDxwKcHRtXdSeAqSDWHfYFgJ7Z5o3F+jaRLAeenubxhUpov+cKd8g3wWRKW6bUQpQ036NgP77EJLvZdA==", "requires": { "@tiledesk/tiledesk-client": "^0.10.4", "app-root-path": "^3.0.0", diff --git a/package.json b/package.json index 3c958f8774c..dda4d644e3a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@tiledesk/tiledesk-server", "description": "The Tiledesk server module", - "version": "2.10.23", + "version": "2.10.33", "scripts": { "start": "node ./bin/www", "pretest": "mongodb-runner start", @@ -48,12 +48,13 @@ "@tiledesk/tiledesk-rasa-connector": "^1.0.10", "@tiledesk/tiledesk-telegram-connector": "^0.1.14", "@tiledesk/tiledesk-train-jobworker": "^0.0.11", - "@tiledesk/tiledesk-tybot-connector": "^0.2.130", + "@tiledesk/tiledesk-tybot-connector": "^0.2.134", "@tiledesk/tiledesk-whatsapp-connector": "^0.1.75", "@tiledesk/tiledesk-whatsapp-jobworker": "^0.0.10", - "@tiledesk/tiledesk-sms-connector": "^0.1.10", + "@tiledesk/tiledesk-sms-connector": "^0.1.11", "@tiledesk/tiledesk-vxml-connector": "^0.1.49", "@tiledesk/tiledesk-voice-twilio-connector": "^0.1.8", + "@tiledesk/tiledesk-multi-worker": "^0.1.3", "amqplib": "^0.5.5", "app-root-path": "^3.0.0", "bcrypt-nodejs": "0.0.3", diff --git a/pubmodules/messageActions/messageActionsInterceptor.js b/pubmodules/messageActions/messageActionsInterceptor.js index a058c63632e..bf28b6028f6 100644 --- a/pubmodules/messageActions/messageActionsInterceptor.js +++ b/pubmodules/messageActions/messageActionsInterceptor.js @@ -131,6 +131,8 @@ class MessageActionsInterceptor { // {"updateconversation" : false, messagelabel: {key: "TOUCHING_OPERATOR"}} // ); + }).catch((err) => { + winston.error("(MessageActionsInterceptor) reroute request error ", err) }); } diff --git a/pubmodules/pubModulesManager.js b/pubmodules/pubModulesManager.js index 2681ab3cd1f..0fb3ec39388 100755 --- a/pubmodules/pubModulesManager.js +++ b/pubmodules/pubModulesManager.js @@ -371,20 +371,22 @@ class PubModulesManager { } } - try { - this.voiceTwilio = require('./voice-twilio'); - winston.info("this.voiceTwilio: " + this.voiceTwilio); - this.voiceTwilio.listener.listen(config); + if (process.env.VOICE_TWILIO_TOKEN === process.env.VOICE_TWILIO_SECRET) { + try { + this.voiceTwilio = require('./voice-twilio'); + winston.info("this.voiceTwilio: " + this.voiceTwilio); + this.voiceTwilio.listener.listen(config); - this.voiceTwilioRoute = this.voiceTwilio.voiceTwilioRoute; + this.voiceTwilioRoute = this.voiceTwilio.voiceTwilioRoute; - winston.info("PubModulesManager initialized apps (voiceTwilio).") - } catch(err) { - console.log("\n Unable to start voiceTwilio connector: ", err); - if (err.code == 'MODULE_NOT_FOUND') { - winston.info("PubModulesManager init apps module not found "); - } else { - winston.info("PubModulesManager error initializing init apps module", err); + winston.info("PubModulesManager initialized apps (voiceTwilio).") + } catch(err) { + console.log("\n Unable to start voiceTwilio connector: ", err); + if (err.code == 'MODULE_NOT_FOUND') { + winston.info("PubModulesManager init apps module not found "); + } else { + winston.info("PubModulesManager error initializing init apps module", err); + } } } diff --git a/pubmodules/rules/conciergeBot.js b/pubmodules/rules/conciergeBot.js index 14753b0fd96..ae3da9e20cb 100755 --- a/pubmodules/rules/conciergeBot.js +++ b/pubmodules/rules/conciergeBot.js @@ -78,7 +78,9 @@ devi mandare un messaggio welcome tu altrimenti il bot inserito successivamente //apply only if the status is temp and no bot is available. with agent you must reroute to assign temp request to an agent winston.debug("rerouting"); // reroute(request_id, id_project, nobot) - requestService.reroute(message.request.request_id, message.request.id_project, false ); + requestService.reroute(message.request.request_id, message.request.id_project, false ).catch((err) => { + winston.error("ConciergeBot error reroute: ", err); + }); } // updateStatusWitId(lead_id, id_project, status) diff --git a/pubmodules/sms/listener.js b/pubmodules/sms/listener.js index 184f82f8ec0..8f8c0808bf4 100644 --- a/pubmodules/sms/listener.js +++ b/pubmodules/sms/listener.js @@ -37,7 +37,6 @@ class Listener { sms.startApp({ MONGODB_URI: config.databaseUri, dbconnection: dbConnection, - API_URL: apiUrl, BASE_URL: apiUrl + "/modules/sms", BRAND_NAME: brand_name, REDIS_HOST: host, diff --git a/pubmodules/trigger/rulesTrigger.js b/pubmodules/trigger/rulesTrigger.js index 6b08c52fe35..c6b4583bae9 100755 --- a/pubmodules/trigger/rulesTrigger.js +++ b/pubmodules/trigger/rulesTrigger.js @@ -474,7 +474,9 @@ class RulesTrigger { winston.debug('runAction action id_project: ' + id_project); // route(request_id, departmentid, id_project, nobot) { - requestService.route(request_id, departmentid, id_project); + requestService.route(request_id, departmentid, id_project).catch((err) => { + winston.error("Error runAction route: ", err); + }); } catch(e) { winston.error("Error runAction", e); @@ -510,7 +512,9 @@ class RulesTrigger { winston.debug('runAction action id_project: ' + id_project); // reroute(request_id, id_project, nobot) { - requestService.reroute(request_id, id_project); + requestService.reroute(request_id, id_project).catch((err) => { + winston.error("Error runAction on reroute", err); + }); } catch(e) { winston.error("Error runAction", e); @@ -736,6 +740,8 @@ class RulesTrigger { ); // TODO Add typing? + }).catch((err) => { + winston.error("Error runAction on reroute", err); }) diff --git a/pubmodules/voice-twilio/listener.js b/pubmodules/voice-twilio/listener.js index a13f482e608..4661ccef8d3 100644 --- a/pubmodules/voice-twilio/listener.js +++ b/pubmodules/voice-twilio/listener.js @@ -37,7 +37,6 @@ class Listener { voice_twilio.startApp({ MONGODB_URI: config.databaseUri, dbconnection: dbConnection, - API_URL: apiUrl, BASE_URL: apiUrl + "/modules/voice-twilio", REDIS_HOST: host, REDIS_PORT: port, diff --git a/pubmodules/voice/listener.js b/pubmodules/voice/listener.js index 840a62d9494..d5543658984 100644 --- a/pubmodules/voice/listener.js +++ b/pubmodules/voice/listener.js @@ -39,7 +39,6 @@ class Listener { voice.startApp({ MONGODB_URI: config.databaseUri, dbconnection: dbConnection, - API_URL: apiUrl, BASE_URL: apiUrl + "/modules/voice", REDIS_HOST: host, REDIS_PORT: port, diff --git a/routes/kb.js b/routes/kb.js index 9ded8a3b742..ecf99038176 100644 --- a/routes/kb.js +++ b/routes/kb.js @@ -49,7 +49,7 @@ let default_preview_settings = { } let default_engine = { name: "pinecone", - type: "pod", + type: process.env.PINECONE_TYPE, apikey: "", vector_size: 1536, index_name: process.env.PINECONE_INDEX @@ -298,41 +298,20 @@ router.post('/qa', async (req, res) => { winston.debug("qa resp: ", resp.data); let answer = resp.data; - let id = answer.id; - let index = id.indexOf("#"); - if (index != -1) { - id = id.substring(index + 1); - } - - KB.findById(id, (err, resource) => { - - if (publicKey === true) { - let multiplier = MODELS_MULTIPLIER[data.model]; - if (!multiplier) { - multiplier = 1; - winston.info("No multiplier found for AI model") - } - obj.multiplier = multiplier; - obj.tokens = answer.prompt_token_size; - - let incremented_key = quoteManager.incrementTokenCount(req.project, obj); - winston.verbose("incremented_key: ", incremented_key); - } - - if (err) { - winston.error("Unable to find resource with id " + id + " in namespace " + answer.namespace + ". The standard answer is returned.") - return res.status(200).send(resp.data); - } - - if (!resource) { - winston.error("Resource with id " + id + " not found in namespace " + answer.namespace + ". The standard answer is returned.") - return res.status(200).send(resp.data); + if (publicKey === true) { + let multiplier = MODELS_MULTIPLIER[data.model]; + if (!multiplier) { + multiplier = 1; + winston.info("No multiplier found for AI model") } + obj.multiplier = multiplier; + obj.tokens = answer.prompt_token_size; - answer.source = resource.name; - return res.status(200).send(answer); - }) - + let incremented_key = quoteManager.incrementTokenCount(req.project, obj); + winston.verbose("incremented_key: ", incremented_key); + } + + return res.status(200).send(answer); }).catch((err) => { winston.error("qa err: ", err); @@ -998,7 +977,7 @@ router.post('/', async (req, res) => { let resources = []; resources.push(json); - if (!process.env.NODE_ENV) { + if (process.env.NODE_ENV !== 'test') { scheduleScrape(resources); } @@ -1104,7 +1083,7 @@ router.post('/multi', upload.single('uploadFile'), async (req, res) => { let operations = kbs.map(doc => { return { updateOne: { - filter: { id_project: doc.id_project, type: 'url', source: doc.source }, + filter: { id_project: doc.id_project, type: 'url', source: doc.source, namespace: namespace_id }, update: doc, upsert: true, returnOriginal: false @@ -1123,7 +1102,7 @@ router.post('/multi', upload.single('uploadFile'), async (req, res) => { }); winston.verbose("resources to be sent to worker: ", resources); - if (!process.env.NODE_ENV) { + if (process.env.NODE_ENV !== 'test') { scheduleScrape(resources); } res.status(200).send(result); @@ -1214,7 +1193,7 @@ router.post('/csv', upload.single('uploadFile'), async (req, res) => { let operations = kbs.map(doc => { return { updateOne: { - filter: { id_project: doc.id_project, type: 'faq', source: doc.source }, + filter: { id_project: doc.id_project, type: 'faq', source: doc.source, namespace: namespace_id }, update: doc, upsert: true, returnOriginal: false @@ -1232,7 +1211,7 @@ router.post('/csv', upload.single('uploadFile'), async (req, res) => { return { id: _id, webhooh: webhook, engine: engine, ...rest }; }) winston.verbose("resources to be sent to worker: ", resources); - if (!process.env.NODE_ENV) { + if (process.env.NODE_ENV !== 'test') { scheduleScrape(resources); } res.status(200).send(result); diff --git a/routes/lead.js b/routes/lead.js index c72c032c76e..21fdb80cd37 100644 --- a/routes/lead.js +++ b/routes/lead.js @@ -100,6 +100,58 @@ router.put('/:leadid', function (req, res) { }); +router.put('/:leadid/tag', async (req, res) => { + + let lead_id = req.params.leadid; + let tags_list = req.body; + winston.debug("(Lead) /tag tags_list: ", tags_list) + + if (tags_list.length == 0) { + winston.warn("(Lead) /tag no tag specified") + return res.status(400).send({ success: false, message: "No tag specified" }) + } + + let lead = await Lead.findById(lead_id).catch((err) => { + winston.error("(Lead) /tag error getting lead ", err); + return res.status(500).send({ success: false, error: "Error getting lead with id " + lead_id}); + }) + + if (!lead) { + winston.warn("(Lead) /tag lead not found with lead_id " + lead_id); + return res.status(404).send({ success: false, error: "Lead not found with id " + lead_id }); + } + + let current_tags = lead.tags; + tags_list.forEach(t => { + // Check if tag already exists in the lead. If true, skip the adding. + if (!current_tags.includes(t)) { + current_tags.push(t) + } + }) + + let update = { + tags: current_tags + } + + Lead.findByIdAndUpdate(lead_id, update, { new: true }, (err, updatedLead) => { + if (err) { + winston.error("(Lead) /tag error finding and update lead ", err); + return res.status(500).send({ success: false, error: "Error updating lead with id " + lead_id }) + } + + if (!updatedLead) { + winston.warn("(Lead) /tag The lead was deleted while adding tags for lead " + lead_id); + return res.status(404).send({ success: false, error: "The lead was deleted while adding tags for lead " + lead_id }) + } + + winston.debug("(Lead) /tag Lead updated successfully ", updatedLead); + + leadEvent.emit('lead.update', updatedLead); + res.status(200).send(updatedLead) + + }) +}) + router.patch('/:leadid/attributes', function (req, res) { var data = req.body; @@ -274,6 +326,25 @@ router.patch('/:leadid/properties', function (req, res) { // res.json(updatedLead); // }); // }); +router.delete('/:leadid/tag/:tag', async (req, res) => { + + let lead_id = req.params.leadid; + let tag = req.params.tag; + + Lead.findByIdAndUpdate(lead_id, { $pull: { tags: tag }}, { new: true}).then((updatedLead) => { + if (!updatedLead) { + winston.warn("(Lead) /removetag lead not found with id " + lead_id); + return res.status(404).send({ success: false, error: "Lead not found with id " + lead_id }) + } + + winston.debug("(Lead) /removetag updatedLead: ", updatedLead) + res.status(200).send(updatedLead) + }).catch((err) => { + winston.error("(Lead) /removetag error updating lead: ", err); + res.status(500).send({ success: false, error: err }); + }) +}) + router.delete('/:leadid', function (req, res) { winston.debug(req.body); diff --git a/routes/request.js b/routes/request.js index 1f95ad034de..5457434ac28 100644 --- a/routes/request.js +++ b/routes/request.js @@ -23,7 +23,7 @@ var cacheEnabler = require("../services/cacheEnabler"); var Project_user = require("../models/project_user"); var Lead = require("../models/lead"); var UIDGenerator = require("../utils/UIDGenerator"); - +let JobManager = require("@tiledesk/tiledesk-multi-worker"); csv = require('csv-express'); csv.separator = ';'; @@ -31,9 +31,28 @@ csv.separator = ';'; const { check, validationResult } = require('express-validator'); const RoleConstants = require('../models/roleConstants'); const eventService = require('../pubmodules/events/eventService'); +const { Scheduler } = require('../services/Scheduler'); +//const JobManager = require('../utils/jobs-worker-queue-manager-v2/JobManagerV2'); // var messageService = require('../services/messageService'); +const AMQP_MANAGER_URL = process.env.AMQP_MANAGER_URL; + +let jobManager = new JobManager(AMQP_MANAGER_URL, { + debug: false, + queueName: "conversation-tags_queue", + exchange: "tiledesk-multi", + topic: "conversation-tags", +}) + +jobManager.connectAndStartPublisher((status, error) => { + if (error) { + winston.error("connectAndStartPublisher error: ", error); + } else { + winston.info("KbRoute - ConnectPublisher done with status: ", status); + } +}) + router.post('/simple', [check('first_text').notEmpty()], async (req, res) => { @@ -848,6 +867,76 @@ router.put('/:requestid/followers', function (req, res) { }); + +router.put('/:requestid/tag', async (req, res) => { + + let id_project = req.projectid; + let request_id = req.params.requestid; + let tags_list = req.body; + winston.debug("(Request) /tag tags_list: ", tags_list) + + if (tags_list.length == 0) { + winston.warn("(Request) /tag no tag specified") + return res.status(400).send({ success: false, message: "No tag specified" }) + } + + let request = await Request.findOne({ id_project: id_project, request_id: request_id }).catch((err) => { + winston.error("(Request) /tag error getting request ", err); + return res.status(500).send({ success: false, error: "Error getting request with request id " + request_id}); + }) + + if (!request) { + winston.warn("(Request) /tag request not found with request_id " + request_id); + return res.status(404).send({ success: false, error: "Request not found with request id " + request_id}); + } + + let current_tags = request.tags; + let adding_tags = []; + + tags_list.forEach(t => { + // Check if tag already exists in the conversation. If true, skip the adding. + if(!current_tags.some(tag => tag.tag === t.tag)) { + current_tags.push(t); + adding_tags.push(t); + } + }) + + let update = { + tags: current_tags + } + + Request.findOneAndUpdate({ id_project: id_project, request_id: request_id }, update, { new: true }).then( async (updatedRequest) => { + + if (!updatedRequest) { + winston.warn("(Request) /tag The request was deleted while adding tags for request " + request_id); + return res.status(404).send({ success: false, error: "The request was deleted while adding tags for request " + request_id }) + } + + winston.debug("(Request) /tag Request updated successfully ", updatedRequest); + + const populatedRequest = + await updatedRequest + .populate('lead') + .populate('department') + .populate('participatingBots') + .populate('participatingAgents') + .populate({ path: 'requester', populate: { path: 'id_user' } }) + .execPopulate(); + + requestEvent.emit("request.update", populatedRequest) + res.status(200).send(updatedRequest) + + if (process.env.NODE_ENV !== 'test') { + scheduleTags(id_project, adding_tags); + } + + }).catch((err) => { + winston.error("(Request) /tag error finding and update request ", err); + return res.status(500).send({ success: false, error: "Error updating request with id " + request_id }) + }) + +}) + router.delete('/:requestid/followers/:followerid', function (req, res) { winston.debug(req.body); @@ -864,7 +953,40 @@ router.delete('/:requestid/followers/:followerid', function (req, res) { +router.delete('/:requestid/tag/:tag_id', async (req, res) => { + + let id_project = req.projectid; + let request_id = req.params.requestid; + let tag_id = req.params.tag_id; + + + Request.findOneAndUpdate({ id_project: id_project, request_id: request_id }, { $pull: { tags: { _id: tag_id } } }, { new: true }).then( async (updatedRequest) => { + + if (!updatedRequest) { + winston.warn("(Request) /removetag request not found with id: " + request_id) + return res.status(404).send({ success: false, error: "Request not found with id " + request_id}) + } + + winston.debug("(Request) /removetag updatedRequest: ", updatedRequest) + + const populatedRequest = + await updatedRequest + .populate('lead') + .populate('department') + .populate('participatingBots') + .populate('participatingAgents') + .populate({ path: 'requester', populate: { path: 'id_user' } }) + .execPopulate(); + + requestEvent.emit("request.update", populatedRequest) + res.status(200).send(updatedRequest); + + }).catch((err) => { + winston.error("(Request) /removetag error updating request: ", err) + res.status(500).send({ success: false, error: err }) + }) +}) // TODO make a synchronous chat21 version (with query parameter?) with request.support_group.created @@ -2166,4 +2288,27 @@ router.get('/:requestid/chatbot/parameters', async (req, res) => { }) + +async function scheduleTags(id_project, tags) { + + let scheduler = new Scheduler({ jobManager: jobManager }) + tags.forEach(t => { + let payload = { + id_project: id_project, + tag: t.tag, + type: "conversation-tag", + date: new Date() + } + console.log("payload: ", payload); + scheduler.tagSchedule(payload, async (err, result) => { + if (err) { + winston.error("Scheduling error: ", err); + } else { + winston.info("Scheduling result: ", result); + } + }) + }) +} + + module.exports = router; \ No newline at end of file diff --git a/services/Scheduler.js b/services/Scheduler.js index d65bf5d203c..16b81d941be 100644 --- a/services/Scheduler.js +++ b/services/Scheduler.js @@ -28,6 +28,18 @@ class Scheduler { } }); } + + tagSchedule(data, callback) { + + winston.debug("(tagScheduler) data: ", data); + this.jobManager.publish(data, (err, ok) => { + let response_data = { success: true, message: "Scheduled" }; + if (callback) { + callback(err, response_data); + } + }) + } + } module.exports = { Scheduler }; \ No newline at end of file diff --git a/services/emailService.js b/services/emailService.js index 5f68c44b8f5..58bfce79415 100644 --- a/services/emailService.js +++ b/services/emailService.js @@ -1582,7 +1582,7 @@ class EmailService { var that = this; - var html = await this.readTemplateFile('passwordChanged.html', undefined, "EMAIL_PASSWORD_CHANGED_HTML_TEMPLATE"); + var html = await this.readTemplate('passwordChanged.html', undefined, "EMAIL_PASSWORD_CHANGED_HTML_TEMPLATE"); winston.debug("html: " + html); @@ -1618,7 +1618,7 @@ class EmailService { var that = this; - var html = await this.readTemplateFile('beenInvitedExistingUser.html', undefined, "EMAIL_EXUSER_INVITED_HTML_TEMPLATE"); + var html = await this.readTemplate('beenInvitedExistingUser.html', undefined, "EMAIL_EXUSER_INVITED_HTML_TEMPLATE"); winston.debug("html: " + html); @@ -1657,7 +1657,7 @@ class EmailService { var that = this; - var html = await this.readTemplateFile('beenInvitedNewUser.html', undefined, "EMAIL_NEWUSER_INVITED_HTML_TEMPLATE"); + var html = await this.readTemplate('beenInvitedNewUser.html', undefined, "EMAIL_NEWUSER_INVITED_HTML_TEMPLATE"); winston.debug("html: " + html); @@ -1693,7 +1693,7 @@ class EmailService { if (savedUser.toJSON) { savedUser = savedUser.toJSON(); } - var html = await this.readTemplateFile('verify.html', undefined, "EMAIL_VERIFY_HTML_TEMPLATE"); + var html = await this.readTemplate('verify.html', undefined, "EMAIL_VERIFY_HTML_TEMPLATE"); winston.debug("html: " + html); diff --git a/services/requestService.js b/services/requestService.js index 54e28b3738f..e25eccfa5bf 100644 --- a/services/requestService.js +++ b/services/requestService.js @@ -20,8 +20,7 @@ var configGlobal = require('../config/global'); const projectService = require('./projectService'); const axios = require("axios").default; - -const apiUrl = process.env.API_URL || configGlobal.apiUrl; +const TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT || "http://localhost:" + port+ "/modules/tilebot/ext/"; let tdCache = new TdCache({ host: process.env.CACHE_REDIS_HOST, @@ -2812,7 +2811,7 @@ class RequestService { return new Promise( async (resolve, reject) => { await axios({ - url: apiUrl + '/modules/tilebot/ext/reserved/parameters/requests/' + request_id, + url: TILEBOT_ENDPOINT + 'reserved/parameters/requests/' + request_id, headers: { 'Content-Type': 'application/json' }, diff --git a/test/kbRoute.js b/test/kbRoute.js index 6e298f92cac..43ef87b5aa2 100644 --- a/test/kbRoute.js +++ b/test/kbRoute.js @@ -3,6 +3,7 @@ process.env.NODE_ENV = 'test'; process.env.GPTKEY = "fakegptkey"; process.env.KB_WEBHOOK_TOKEN = "testtoken" process.env.PINECONE_INDEX = "test_index" +process.env.PINECONE_TYPE = "pod" process.env.LOG_LEVEL = 'critical' var userService = require('../services/userService'); diff --git a/test/leadRoute.js b/test/leadRoute.js new file mode 100644 index 00000000000..87713f182f3 --- /dev/null +++ b/test/leadRoute.js @@ -0,0 +1,156 @@ +//During the test the env variable is set to test +process.env.NODE_ENV = 'test'; + +const userService = require('../services/userService'); +const projectService = require('../services/projectService'); +const leadService = require('../services/leadService'); + +//Require the dev-dependencies +let chai = require('chai'); +let chaiHttp = require('chai-http'); +let server = require('../app'); +let should = chai.should(); +var expect = chai.expect; +var assert = chai.assert; + + +let log = false; + +chai.use(chaiHttp); + + +describe('LeadRoute', () => { + + // mocha test/leadRoute.js --grep 'add-tags-to-lead' + it('add-tags-to-lead', function (done) { + + var email = "test-request-create-" + Date.now() + "@email.com"; + var pwd = "pwd"; + var userid = "5badfe5d553d1844ad654072"; + + userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) { + projectService.create("request-create", savedUser._id, { email: { template: { assignedRequest: "123" } } }).then(function (savedProject) { + var attr = { myprop: 123 }; + leadService.create("fullname", "email@email.com", savedProject._id, userid, attr).then(function (savedLead) { + + savedLead.should.have.property('_id').not.eql(null); + let lead_id = savedLead._id; + + let tags = [ "tag1", "tag2" ] + + // First Step: add 2 tags on a conversation no tagged at all + chai.request(server) + .put('/' + savedProject._id + '/leads/' + lead_id + '/tag') + .auth(email, pwd) + .send(tags) + .end((err, res) => { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + expect(res.body.tags).to.have.length(2); + expect(res.body.tags[0]).to.equal('tag1'); + expect(res.body.tags[1]).to.equal('tag2'); + + let tags2 = [ "tag2", "tag3" ] + + // Second Step: add more 2 tags of which one already existant in the conversation + chai.request(server) + .put('/' + savedProject._id + '/leads/' + lead_id + '/tag') + .auth(email, pwd) + .send(tags2) + .end((err, res) => { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + expect(res.body.tags).to.have.length(3); + expect(res.body.tags[0]).to.equal('tag1'); + expect(res.body.tags[1]).to.equal('tag2'); + expect(res.body.tags[2]).to.equal('tag3'); + + done(); + }) + + }) + + }).catch(function (err) { + winston.error("test reject", err); + assert.isNotOk(err, 'Promise error'); + done(); + }); + }) + + }) + + }).timeout(5000) + + // mocha test/leadRoute.js --grep 'remove-tags-from-lead' + it('remove-tags-from-lead', function (done) { + + var email = "test-request-create-" + Date.now() + "@email.com"; + var pwd = "pwd"; + var userid = "5badfe5d553d1844ad654072"; + + userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) { + projectService.create("request-create", savedUser._id, { email: { template: { assignedRequest: "123" } } }).then(function (savedProject) { + var attr = { myprop: 123 }; + leadService.create("fullname", "email@email.com", savedProject._id, userid, attr).then(function (savedLead) { + + savedLead.should.have.property('_id').not.eql(null); + let lead_id = savedLead._id; + + let tags = [ "tag1", "tag2" ] + + // First Step: add 2 tags on a conversation no tagged at all + chai.request(server) + .put('/' + savedProject._id + '/leads/' + lead_id + '/tag') + .auth(email, pwd) + .send(tags) + .end((err, res) => { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + expect(res.body.tags).to.have.length(2); + expect(res.body.tags[0]).to.equal('tag1'); + expect(res.body.tags[1]).to.equal('tag2'); + + let tag_to_remove = res.body.tags[1]; + + chai.request(server) + .delete('/' + savedProject._id + '/leads/' + lead_id + '/tag/' + tag_to_remove) + .auth(email, pwd) + .end((err, res) => { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + expect(res.body.tags).to.have.length(1); + expect(res.body.tags[0]).to.equal('tag1'); + + done(); + + }) + + }) + + }).catch(function (err) { + winston.error("test reject", err); + assert.isNotOk(err, 'Promise error'); + done(); + }); + }) + + }) + + }).timeout(5000) +}) \ No newline at end of file diff --git a/test/requestRoute.js b/test/requestRoute.js index 4f4a7e9182f..796a3f70bb0 100644 --- a/test/requestRoute.js +++ b/test/requestRoute.js @@ -1,40 +1,33 @@ //During the test the env variable is set to test process.env.NODE_ENV = 'test'; -var User = require('../models/user'); - var projectService = require('../services/projectService'); var requestService = require('../services/requestService'); var userService = require('../services/userService'); var leadService = require('../services/leadService'); +var faqService = require('../services/faqService'); +var Department = require('../models/department'); +var winston = require('../config/winston'); //Require the dev-dependencies let chai = require('chai'); let chaiHttp = require('chai-http'); let server = require('../app'); let should = chai.should(); -var winston = require('../config/winston'); +var expect = chai.expect; +var assert = chai.assert; -var Department = require('../models/department'); -var faqService = require('../services/faqService'); // require('../services/mongoose-cache-fn')(mongoose); - // chai.config.includeStack = true; let log = false; -var expect = chai.expect; -var assert = chai.assert; - chai.use(chaiHttp); describe('RequestRoute', () => { - - // mocha test/requestRoute.js --grep 'createSimple' - it('createSimple', function (done) { // this.timeout(10000); @@ -87,6 +80,8 @@ describe('RequestRoute', () => { }); }); + + // mocha test/requestRoute.js --grep 'create-simple-new-note' it('create-simple-new-note', function (done) { // this.timeout(10000); @@ -138,6 +133,7 @@ describe('RequestRoute', () => { }); + // mocha test/requestRoute.js --grep 'createSimpleAndCloseForDuration' it('createSimpleAndCloseForDuration', function (done) { // this.timeout(10000); @@ -188,8 +184,7 @@ describe('RequestRoute', () => { }).timeout(5000); - - + // mocha test/requestRoute.js --grep 'createUpperCaseEmail' it('createUpperCaseEmail', function (done) { // this.timeout(10000); @@ -244,8 +239,6 @@ describe('RequestRoute', () => { }); - - // mocha test/requestRoute.js --grep 'getbyid' it('getbyid', function (done) { // this.timeout(10000); @@ -308,8 +301,9 @@ describe('RequestRoute', () => { }); }); }); - // mocha test/requestRoute.js --grep 'getbyidWithPartecipatingBots' + + // mocha test/requestRoute.js --grep 'getbyidWithPartecipatingBots' it('getbyidWithPartecipatingBots', function (done) { // this.timeout(10000); @@ -384,7 +378,6 @@ describe('RequestRoute', () => { // mocha test/requestRoute.js --grep 'getallSimple' - it('getallSimple', function (done) { // this.timeout(10000); @@ -470,9 +463,7 @@ describe('RequestRoute', () => { }); - // mocha test/requestRoute.js --grep 'getallNoPopulate' - it('getallNoPopulate', function (done) { // this.timeout(10000); @@ -549,11 +540,7 @@ describe('RequestRoute', () => { }); - - - // mocha test/requestRoute.js --grep 'getallSimple' - it('getallFilter-snap_department_routing', function (done) { // this.timeout(10000); @@ -638,10 +625,7 @@ describe('RequestRoute', () => { }); - - // mocha test/requestRoute.js --grep 'getallFilter-snap_department_default' - it('getallFilter-snap_department_default', function (done) { // this.timeout(10000); @@ -726,10 +710,7 @@ describe('RequestRoute', () => { }); - - // mocha test/requestRoute.js --grep 'snap_department_id_bot_exists' - it('getallFilter-snap_department_id_bot_exists', function (done) { // this.timeout(10000); @@ -864,9 +845,7 @@ describe('RequestRoute', () => { }); - - - + // mocha test/requestRoute.js --grep 'getallWithLoLead' it('getallWithLoLead', function (done) { // this.timeout(10000); @@ -918,13 +897,365 @@ describe('RequestRoute', () => { }); - describe('/assign', () => { + // mocha test/requestRoute.js --grep 'countConversations' + it('countConversations', function (done) { + // this.timeout(10000); + + var email = "test-request-create-" + Date.now() + "@email.com"; + var pwd = "pwd"; + userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) { + projectService.create("request-create", savedUser._id, { email: { template: { assignedRequest: "123" } } }).then(function (savedProject) { + chai.request(server) + .post('/' + savedProject._id + '/requests/') + .auth(email, pwd) + .set('content-type', 'application/json') + .send({ "first_text": "first_text" }) + .end(function (err, res) { + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; - // mocha test/requestRoute.js --grep 'createAndReassign' + res.should.have.status(200); + res.body.should.be.a('object'); + + chai.request(server) + .get('/' + savedProject._id + '/requests/count?conversation_quota=true') + .auth(email, pwd) + .end((err, res) => { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + + done(); + }) + + }); + }); + }); + }); + + + // mocha test/requestRoute.js --grep 'exludeDraftConversations' + it('exludeDraftConversations', (done) => { + + var email = "test-signup-" + Date.now() + "@email.com"; + var pwd = "pwd"; + + userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => { + projectService.createAndReturnProjectAndProjectUser("test-draft-conversation", savedUser._id).then((savedProjectAndPU) => { + let savedProject = savedProjectAndPU.project; + let savedPU = savedProjectAndPU.project_user; + leadService.createIfNotExists("Lead Fullname", "email@test.com", savedProject._id).then((createdLead) => { + let now = Date.now(); + let request = { + request_id: "request_id-exludeDraftConversations-" + now, + project_user_id: savedPU._id, + lead_id: createdLead._id, + id_project: savedProject._id, + first_text: "first_text", + lead: createdLead, + requester: savedPU, + attributes: { sourcePage: "https://widget-pre.tiledesk.com/v2/index.html?tiledesk_projectid=5ce3d1ceb25ad30017279999&td_draft=true" } + } + + requestService.create(request).then(async (savedRequest) => { + + // Case 1 - request with source page that contains td_draft + expect(savedRequest.draft).to.equal(true); + + // Case 2 - request without source page that contains td_draft + //expect(savedRequest.draft).to.be.undefined; + + // get all requests -> should be 0 + + chai.request(server) + .get('/' + savedProject._id + '/requests?draft=false') + .auth(email, pwd) + .end((err, res) => { + + if (err) { console.error("err: ", err ) }; + if (log) { console.log("res.body: ", res.body) } + + res.should.have.status(200); + res.body.should.be.a('object'); + res.body.requests.should.be.a('array'); + + // Case 1 - request with source page that contains td_draft + expect(res.body.requests.length).to.equal(0); + + // Case 2 - request without source page that contains td_draft + //expect(res.body.requests.length).to.equal(1); + + done(); + }) + + + }).catch((err) => { + console.error("error creating request: ", err) + }) + }) + + }) + }) + + }) + + + // mocha test/requestRoute.js --grep 'add-tag-to-conversation' + it('add-tag-to-conversation', function (done) { + + var email = "test-request-create-" + Date.now() + "@email.com"; + var pwd = "pwd"; + + userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) { + projectService.create("request-create", savedUser._id, { email: { template: { assignedRequest: "123" } } }).then(function (savedProject) { + + chai.request(server) + .post('/' + savedProject._id + '/requests/') + .auth(email, pwd) + .set('content-type', 'application/json') + .send({ "first_text": "first_text" }) + .end(function (err, res) { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + res.body.should.have.property('request_id').not.eql(null); + + let request_id = res.body.request_id; + + let tags = [ + { tag: "tag1", color: "#43B1F2" }, + { tag: "tag2", color: "#43B1F2" } + ] + + // First Step: add 2 tags on a conversation no tagged at all + chai.request(server) + .put('/' + savedProject._id + '/requests/' + request_id + '/tag' ) + .auth(email, pwd) + .send(tags) + .end((err, res) => { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + expect(res.body.tags).to.have.length(2); + expect(res.body.tags[0].tag).to.equal('tag1'); + expect(res.body.tags[1].tag).to.equal('tag2'); + + let tags2 = [ + { tag: "tag2", color: "#43B1F2"}, + { tag: "tag3", color: "#43B1F2"} + ] + + // Second Step: add more 2 tags of which one already existant in the conversation + chai.request(server) + .put('/' + savedProject._id + '/requests/' + request_id + '/tag') + .auth(email, pwd) + .send(tags2) + .end((err, res) => { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + expect(res.body.tags).to.have.length(3); + expect(res.body.tags[0].tag).to.equal('tag1'); + expect(res.body.tags[1].tag).to.equal('tag2'); + expect(res.body.tags[2].tag).to.equal('tag3'); + + done(); + }) + + }) + + }); + }); + }); + }); + + // mocha test/requestRoute.js --grep 'remove-tag-from-conversation' + it('remove-tag-from-conversation', function (done) { + + var email = "test-request-create-" + Date.now() + "@email.com"; + var pwd = "pwd"; + userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) { + projectService.create("request-create", savedUser._id, { email: { template: { assignedRequest: "123" } } }).then(function (savedProject) { + + chai.request(server) + .post('/' + savedProject._id + '/requests/') + .auth(email, pwd) + .set('content-type', 'application/json') + .send({ "first_text": "first_text" }) + .end(function (err, res) { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + res.body.should.have.property('request_id').not.eql(null); + + let request_id = res.body.request_id; + + let tags = [ + { tag: "tag1", color: "#43B1F2" }, + { tag: "tag2", color: "#43B1F2" } + ] + + // First Step: add 2 tags on a conversation no tagged at all + chai.request(server) + .put('/' + savedProject._id + '/requests/' + request_id + '/tag' ) + .auth(email, pwd) + .send(tags) + .end((err, res) => { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + expect(res.body.tags).to.have.length(2); + expect(res.body.tags[0].tag).to.equal('tag1'); + expect(res.body.tags[1].tag).to.equal('tag2'); + + let tags2 = [ + { tag: "tag2", color: "#43B1F2"}, + { tag: "tag3", color: "#43B1F2"} + ] + + // Second Step: add more 2 tags of which one already existant in the conversation + chai.request(server) + .put('/' + savedProject._id + '/requests/' + request_id + '/tag') + .auth(email, pwd) + .send(tags2) + .end((err, res) => { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + expect(res.body.tags).to.have.length(3); + expect(res.body.tags[0].tag).to.equal('tag1'); + expect(res.body.tags[1].tag).to.equal('tag2'); + expect(res.body.tags[2].tag).to.equal('tag3'); + + let tag_to_delete = res.body.tags[2]; + + chai.request(server) + .delete('/' + savedProject._id + '/requests/' + request_id + '/tag/' + tag_to_delete._id) + .auth(email, pwd) + .end((err, res) => { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + + expect(res.body.tags).to.have.length(2); + expect(res.body.tags[0].tag).to.equal('tag1'); + expect(res.body.tags[1].tag).to.equal('tag2'); + + done(); + }) + }) + + }) + + }); + }); + }); + }).timeout(4000); + + it('remove-tag-from-unexistent-conversation', function (done) { + + var email = "test-request-create-" + Date.now() + "@email.com"; + var pwd = "pwd"; + + userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) { + projectService.create("request-create", savedUser._id, { email: { template: { assignedRequest: "123" } } }).then(function (savedProject) { + + chai.request(server) + .post('/' + savedProject._id + '/requests/') + .auth(email, pwd) + .set('content-type', 'application/json') + .send({ "first_text": "first_text" }) + .end(function (err, res) { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + res.body.should.have.property('request_id').not.eql(null); + + let request_id = res.body.request_id; + + let tags = [ + { tag: "tag1", color: "#43B1F2" }, + { tag: "tag2", color: "#43B1F2" } + ] + + // First Step: add 2 tags on a conversation no tagged at all + chai.request(server) + .put('/' + savedProject._id + '/requests/' + request_id + '/tag' ) + .auth(email, pwd) + .send(tags) + .end((err, res) => { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(200); + res.body.should.be.a('object'); + expect(res.body.tags).to.have.length(2); + expect(res.body.tags[0].tag).to.equal('tag1'); + expect(res.body.tags[1].tag).to.equal('tag2'); + + let tag_to_delete = res.body.tags[1]; + let fake_request_id = "support-group-6752d23518dbe16860ff2cda-b1f2ecb1c617492fbbc33105b475axxx" + + chai.request(server) + .delete('/' + savedProject._id + '/requests/' + fake_request_id + '/tag/' + tag_to_delete._id) + .auth(email, pwd) + .end((err, res) => { + + if (err) { console.log("err: ", err) }; + if (log) { console.log("res.body: ", res.body) }; + + res.should.have.status(404); + res.body.should.be.a('object'); + + expect(res.body.success).to.equal(false); + expect(res.body.error).to.equal("Request not found with id " + fake_request_id) + + done(); + }) + + + }) + + }); + }); + }); + }).timeout(4000); + + + describe('/assign', () => { + + // mocha test/requestRoute.js --grep 'createAndReassign' it('createAndReassign', function (done) { // this.timeout(10000); @@ -1005,9 +1336,7 @@ describe('RequestRoute', () => { }); - // mocha test/requestRoute.js --grep 'createAndReassignAndNoPopulate' - it('createAndReassignAndNoPopulate', function (done) { // this.timeout(10000); @@ -1087,9 +1416,7 @@ describe('RequestRoute', () => { }); - // mocha test/requestRoute.js --grep 'createAndAssign2' - it('createAndAssign2', function (done) { // this.timeout(10000); @@ -1169,7 +1496,6 @@ describe('RequestRoute', () => { }); - // mocha test/requestRoute.js --grep 'removeParticipant' it('removeParticipant', function (done) { // this.timeout(10000); @@ -1245,109 +1571,6 @@ describe('RequestRoute', () => { }); }); - it('exludeDraftConversations', (done) => { - - var email = "test-signup-" + Date.now() + "@email.com"; - var pwd = "pwd"; - - userService.signup(email, pwd, "Test Firstname", "Test Lastname").then((savedUser) => { - projectService.createAndReturnProjectAndProjectUser("test-draft-conversation", savedUser._id).then((savedProjectAndPU) => { - let savedProject = savedProjectAndPU.project; - let savedPU = savedProjectAndPU.project_user; - leadService.createIfNotExists("Lead Fullname", "email@test.com", savedProject._id).then((createdLead) => { - let now = Date.now(); - let request = { - request_id: "request_id-exludeDraftConversations-" + now, - project_user_id: savedPU._id, - lead_id: createdLead._id, - id_project: savedProject._id, - first_text: "first_text", - lead: createdLead, - requester: savedPU, - attributes: { sourcePage: "https://widget-pre.tiledesk.com/v2/index.html?tiledesk_projectid=5ce3d1ceb25ad30017279999&td_draft=true" } - } - - requestService.create(request).then(async (savedRequest) => { - - // Case 1 - request with source page that contains td_draft - expect(savedRequest.draft).to.equal(true); - - // Case 2 - request without source page that contains td_draft - //expect(savedRequest.draft).to.be.undefined; - - // get all requests -> should be 0 - - chai.request(server) - .get('/' + savedProject._id + '/requests?draft=false') - .auth(email, pwd) - .end((err, res) => { - - if (err) { console.error("err: ", err ) }; - if (log) { console.log("res.body: ", res.body) } - - res.should.have.status(200); - res.body.should.be.a('object'); - res.body.requests.should.be.a('array'); - - // Case 1 - request with source page that contains td_draft - expect(res.body.requests.length).to.equal(0); - - // Case 2 - request without source page that contains td_draft - //expect(res.body.requests.length).to.equal(1); - - done(); - }) - - - }).catch((err) => { - console.error("error creating request: ", err) - }) - }) - - }) - }) - - }) - - it('countConversations', function (done) { - // this.timeout(10000); - - var email = "test-request-create-" + Date.now() + "@email.com"; - var pwd = "pwd"; - - userService.signup(email, pwd, "Test Firstname", "Test lastname").then(function (savedUser) { - projectService.create("request-create", savedUser._id, { email: { template: { assignedRequest: "123" } } }).then(function (savedProject) { - - chai.request(server) - .post('/' + savedProject._id + '/requests/') - .auth(email, pwd) - .set('content-type', 'application/json') - .send({ "first_text": "first_text" }) - .end(function (err, res) { - - if (err) { console.log("err: ", err) }; - if (log) { console.log("res.body: ", res.body) }; - - res.should.have.status(200); - res.body.should.be.a('object'); - - chai.request(server) - .get('/' + savedProject._id + '/requests/count?conversation_quota=true') - .auth(email, pwd) - .end((err, res) => { - - if (err) { console.log("err: ", err) }; - if (log) { console.log("res.body: ", res.body) }; - - res.should.have.status(200); - - done(); - }) - - }); - }); - }); - }); // it('assign', (done) => { @@ -1389,7 +1612,6 @@ describe('RequestRoute', () => { // }); // }).timeout(20000); - /* it('requestParameterFromChatbot', function (done) { // this.timeout(10000); @@ -1433,8 +1655,6 @@ describe('RequestRoute', () => { */ - - }); });