@tiledesk/tiledesk-server 2.5.3 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +1 -1
- package/app.js +7 -1
- package/config/labels/widget.json +257 -252
- package/event/botEvent.js +24 -3
- package/jobs.js +9 -1
- package/jobsManager.js +13 -1
- package/middleware/fetchLabels.js +23 -13
- package/package.json +6 -4
- package/pubmodules/queue/reconnect.js +47 -0
- package/pubmodules/trigger/default.js +2 -2
- package/pubmodules/trigger/rulesTrigger.js +14 -2
- package/routes/kb.js +307 -62
- package/services/QuoteManager.js +26 -20
- package/services/Scheduler.js +33 -0
- package/services/openaiService.js +12 -11
- package/services/requestService.js +96 -92
- package/services/updateLeadQueued.js +149 -0
- package/test/TooManykbUrlsList.txt +304 -0
- package/test/kbRoute.js +331 -20
- package/test/kbUrlsList.txt +4 -0
- package/utils/jobs-worker-queue-manager/JobManagerV2.js +146 -0
- package/utils/jobs-worker-queue-manager/queueManagerClassV2.js +355 -0
    
        package/routes/kb.js
    CHANGED
    
    | @@ -2,8 +2,26 @@ var express = require('express'); | |
| 2 2 | 
             
            var { KB } = require('../models/kb_setting');
         | 
| 3 3 | 
             
            var router = express.Router();
         | 
| 4 4 | 
             
            var winston = require('../config/winston');
         | 
| 5 | 
            +
            var multer = require('multer')
         | 
| 6 | 
            +
            var upload = multer()
         | 
| 5 7 | 
             
            const openaiService = require('../services/openaiService');
         | 
| 8 | 
            +
            const JobManager = require('../utils/jobs-worker-queue-manager/JobManagerV2');
         | 
| 9 | 
            +
            const { Scheduler } = require('../services/Scheduler');
         | 
| 6 10 |  | 
| 11 | 
            +
            const Sitemapper = require('sitemapper');
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            const AMQP_MANAGER_URL = process.env.AMQP_MANAGER_URL;
         | 
| 14 | 
            +
            const JOB_TOPIC_EXCHANGE = process.env.JOB_TOPIC_EXCHANGE_TRAIN || 'tiledesk-trainer';
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            let jobManager = new JobManager(AMQP_MANAGER_URL, {
         | 
| 17 | 
            +
                debug: false,
         | 
| 18 | 
            +
                topic: JOB_TOPIC_EXCHANGE,
         | 
| 19 | 
            +
                exchange: JOB_TOPIC_EXCHANGE
         | 
| 20 | 
            +
            })
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            jobManager.connectAndStartPublisher(() => {
         | 
| 23 | 
            +
                winston.info("ConnectPublisher done");
         | 
| 24 | 
            +
            })
         | 
| 7 25 |  | 
| 8 26 | 
             
            router.get('/', async (req, res) => {
         | 
| 9 27 |  | 
| @@ -27,7 +45,7 @@ router.get('/', async (req, res) => { | |
| 27 45 | 
             
                    limit = parseInt(req.query.limit);
         | 
| 28 46 | 
             
                    winston.debug("Get kb limit: " + limit)
         | 
| 29 47 | 
             
                }
         | 
| 30 | 
            -
             | 
| 48 | 
            +
             | 
| 31 49 | 
             
                if (req.query.page) {
         | 
| 32 50 | 
             
                    page = parseInt(req.query.page);
         | 
| 33 51 | 
             
                    winston.debug("Get kb page: " + page)
         | 
| @@ -55,54 +73,54 @@ router.get('/', async (req, res) => { | |
| 55 73 | 
             
                let sortQuery = {};
         | 
| 56 74 | 
             
                sortQuery[sortField] = direction;
         | 
| 57 75 | 
             
                winston.debug("Get kb sortQuery: " + sortQuery);
         | 
| 58 | 
            -
             | 
| 76 | 
            +
             | 
| 59 77 | 
             
                KB.countDocuments(query, (err, kbs_count) => {
         | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
                        
         | 
| 65 | 
            -
                        KB.find(query)
         | 
| 66 | 
            -
                            .skip(skip)
         | 
| 67 | 
            -
                            .limit(limit)
         | 
| 68 | 
            -
                            .sort(sortQuery)
         | 
| 69 | 
            -
                            .exec((err, kbs) => {
         | 
| 70 | 
            -
                                if (err) {
         | 
| 71 | 
            -
                                    winston.error("Find all kbs error: ", err);
         | 
| 72 | 
            -
                                    return res.status(500).send({ success: false, error: err });
         | 
| 73 | 
            -
                                }
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                                winston.debug("KBs found: ", kbs);
         | 
| 76 | 
            -
             | 
| 77 | 
            -
                                let response = {
         | 
| 78 | 
            -
                                    count: kbs_count,
         | 
| 79 | 
            -
                                    query: {},
         | 
| 80 | 
            -
                                    kbs: kbs
         | 
| 81 | 
            -
                                }
         | 
| 82 | 
            -
                                if (status) {
         | 
| 83 | 
            -
                                    response.query.status = status;
         | 
| 84 | 
            -
                                }
         | 
| 85 | 
            -
                                if (limit) {
         | 
| 86 | 
            -
                                    response.query.limit = limit;
         | 
| 87 | 
            -
                                }
         | 
| 88 | 
            -
                                if (status) {
         | 
| 89 | 
            -
                                    response.query.page = page;
         | 
| 90 | 
            -
                                }
         | 
| 91 | 
            -
                                if (sortField) {
         | 
| 92 | 
            -
                                    response.query.sortField = sortField;
         | 
| 93 | 
            -
                                }
         | 
| 94 | 
            -
                                if (direction) {
         | 
| 95 | 
            -
                                    response.query.direction = direction;
         | 
| 96 | 
            -
                                }
         | 
| 97 | 
            -
                                if (text) {
         | 
| 98 | 
            -
                                    response.query.search = text;
         | 
| 99 | 
            -
                                }
         | 
| 100 | 
            -
             | 
| 101 | 
            -
             | 
| 102 | 
            -
                                return res.status(200).send(response);
         | 
| 103 | 
            -
                            })
         | 
| 78 | 
            +
                    if (err) {
         | 
| 79 | 
            +
                        winston.error("Find all kbs error: ", err);
         | 
| 80 | 
            +
                    }
         | 
| 81 | 
            +
                    winston.debug("KBs count: ", kbs_count);
         | 
| 104 82 |  | 
| 105 | 
            -
                     | 
| 83 | 
            +
                    KB.find(query)
         | 
| 84 | 
            +
                        .skip(skip)
         | 
| 85 | 
            +
                        .limit(limit)
         | 
| 86 | 
            +
                        .sort(sortQuery)
         | 
| 87 | 
            +
                        .exec((err, kbs) => {
         | 
| 88 | 
            +
                            if (err) {
         | 
| 89 | 
            +
                                winston.error("Find all kbs error: ", err);
         | 
| 90 | 
            +
                                return res.status(500).send({ success: false, error: err });
         | 
| 91 | 
            +
                            }
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                            winston.debug("KBs found: ", kbs);
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                            let response = {
         | 
| 96 | 
            +
                                count: kbs_count,
         | 
| 97 | 
            +
                                query: {},
         | 
| 98 | 
            +
                                kbs: kbs
         | 
| 99 | 
            +
                            }
         | 
| 100 | 
            +
                            if (status) {
         | 
| 101 | 
            +
                                response.query.status = status;
         | 
| 102 | 
            +
                            }
         | 
| 103 | 
            +
                            if (limit) {
         | 
| 104 | 
            +
                                response.query.limit = limit;
         | 
| 105 | 
            +
                            }
         | 
| 106 | 
            +
                            if (status) {
         | 
| 107 | 
            +
                                response.query.page = page;
         | 
| 108 | 
            +
                            }
         | 
| 109 | 
            +
                            if (sortField) {
         | 
| 110 | 
            +
                                response.query.sortField = sortField;
         | 
| 111 | 
            +
                            }
         | 
| 112 | 
            +
                            if (direction) {
         | 
| 113 | 
            +
                                response.query.direction = direction;
         | 
| 114 | 
            +
                            }
         | 
| 115 | 
            +
                            if (text) {
         | 
| 116 | 
            +
                                response.query.search = text;
         | 
| 117 | 
            +
                            }
         | 
| 118 | 
            +
             | 
| 119 | 
            +
             | 
| 120 | 
            +
                            return res.status(200).send(response);
         | 
| 121 | 
            +
                        })
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                })
         | 
| 106 124 |  | 
| 107 125 |  | 
| 108 126 | 
             
            })
         | 
| @@ -127,6 +145,31 @@ router.post('/', async (req, res) => { | |
| 127 145 | 
             
                let project_id = req.projectid;
         | 
| 128 146 | 
             
                let body = req.body;
         | 
| 129 147 |  | 
| 148 | 
            +
                // add or override namespace value if it is passed for security reason
         | 
| 149 | 
            +
                body.namespace = project_id;
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                // if (req.body.namespace) {
         | 
| 152 | 
            +
                //     if (req.body.namespace != req.projectid) {
         | 
| 153 | 
            +
                //         return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project."})
         | 
| 154 | 
            +
                //     }
         | 
| 155 | 
            +
                // }
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                let quoteManager = req.app.get('quote_manager');
         | 
| 158 | 
            +
                let limits = await quoteManager.getPlanLimits(req.project);
         | 
| 159 | 
            +
                let kbs_limit = limits.kbs;
         | 
| 160 | 
            +
                winston.verbose("Limit of kbs for current plan: " + kbs_limit);
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                let kbs_count = await KB.countDocuments({ id_project: project_id }).exec();
         | 
| 163 | 
            +
                winston.verbose("Kbs count: " + kbs_count);
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                if (kbs_count >= kbs_limit) {
         | 
| 166 | 
            +
                    return res.status(403).send({ success: false, error: "Maximum number of resources reached for the current plan", plan_limit: kbs_limit })
         | 
| 167 | 
            +
                }
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                let total_count = kbs_count + 1;
         | 
| 170 | 
            +
                if (total_count > kbs_limit) {
         | 
| 171 | 
            +
                    return res.status(403).send({ success: false, error: "Cannot exceed the number of resources in the current plan", plan_limit: kbs_limit })
         | 
| 172 | 
            +
                }
         | 
| 130 173 | 
             
                let new_kb = {
         | 
| 131 174 | 
             
                    id_project: project_id,
         | 
| 132 175 | 
             
                    name: body.name,
         | 
| @@ -141,7 +184,6 @@ router.post('/', async (req, res) => { | |
| 141 184 | 
             
                }
         | 
| 142 185 | 
             
                winston.debug("adding kb: ", new_kb);
         | 
| 143 186 |  | 
| 144 | 
            -
             | 
| 145 187 | 
             
                KB.findOneAndUpdate({ id_project: project_id, type: 'url', source: new_kb.source }, new_kb, { upsert: true, new: true, rawResult: true }, async (err, raw) => {
         | 
| 146 188 | 
             
                    if (err) {
         | 
| 147 189 | 
             
                        winston.error("findOneAndUpdate with upsert error: ", err);
         | 
| @@ -163,17 +205,118 @@ router.post('/', async (req, res) => { | |
| 163 205 | 
             
                            json.content = raw.value.content;
         | 
| 164 206 | 
             
                        }
         | 
| 165 207 |  | 
| 166 | 
            -
                         | 
| 167 | 
            -
             | 
| 168 | 
            -
                         | 
| 169 | 
            -
             | 
| 170 | 
            -
             | 
| 208 | 
            +
                        let resources = [];
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                        resources.push(json);
         | 
| 211 | 
            +
                        scheduleScrape(resources);
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                        // startScrape(json).then((response) => {
         | 
| 214 | 
            +
                        //     winston.verbose("startScrape response: ", response);
         | 
| 215 | 
            +
                        // }).catch((err) => {
         | 
| 216 | 
            +
                        //     winston.error("startScrape err: ", err);
         | 
| 217 | 
            +
                        // })
         | 
| 218 | 
            +
             | 
| 219 | 
            +
                    }
         | 
| 220 | 
            +
                })
         | 
| 221 | 
            +
             | 
| 222 | 
            +
            })
         | 
| 223 | 
            +
             | 
| 224 | 
            +
             | 
| 225 | 
            +
            router.post('/multi', upload.single('uploadFile'), async (req, res) => {
         | 
| 226 | 
            +
             | 
| 227 | 
            +
                let list;
         | 
| 228 | 
            +
                if (req.file) {
         | 
| 229 | 
            +
                    file_string = req.file.buffer.toString('utf-8');
         | 
| 230 | 
            +
                    list = file_string.trim().split('\n');
         | 
| 231 | 
            +
                } else {
         | 
| 232 | 
            +
                    list = req.body.list;
         | 
| 233 | 
            +
                }
         | 
| 234 | 
            +
             | 
| 235 | 
            +
                let project_id = req.projectid;
         | 
| 236 | 
            +
             | 
| 237 | 
            +
                let quoteManager = req.app.get('quote_manager');
         | 
| 238 | 
            +
                let limits = await quoteManager.getPlanLimits(req.project);
         | 
| 239 | 
            +
                let kbs_limit = limits.kbs;
         | 
| 240 | 
            +
                winston.verbose("Limit of kbs for current plan: " + kbs_limit);
         | 
| 241 | 
            +
             | 
| 242 | 
            +
                let kbs_count = await KB.countDocuments({ id_project: project_id }).exec();
         | 
| 243 | 
            +
                winston.verbose("Kbs count: " + kbs_count);
         | 
| 244 | 
            +
             | 
| 245 | 
            +
                if (kbs_count >= kbs_limit) {
         | 
| 246 | 
            +
                    return res.status(403).send({ success: false, error: "Maximum number of resources reached for the current plan", plan_limit: kbs_limit })
         | 
| 247 | 
            +
                }
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                let total_count = kbs_count + list.length;
         | 
| 250 | 
            +
                if (total_count > kbs_limit) {
         | 
| 251 | 
            +
                    return res.status(403).send({ success: false, error: "Cannot exceed the number of resources in the current plan", plan_limit: kbs_limit })
         | 
| 252 | 
            +
                }
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                if (list.length > 300) {
         | 
| 255 | 
            +
                    winston.error("Too many urls. Can't index more than 300 urls at a time.");
         | 
| 256 | 
            +
                    return res.status(403).send({ success: false, error: "Too many urls. Can't index more than 300 urls at a time."})
         | 
| 257 | 
            +
                }
         | 
| 171 258 |  | 
| 259 | 
            +
                let kbs = [];
         | 
| 260 | 
            +
                list.forEach(url => {
         | 
| 261 | 
            +
                    kbs.push({
         | 
| 262 | 
            +
                        id_project: project_id,
         | 
| 263 | 
            +
                        name: url,
         | 
| 264 | 
            +
                        source: url,
         | 
| 265 | 
            +
                        type: 'url',
         | 
| 266 | 
            +
                        content: "",
         | 
| 267 | 
            +
                        namespace: project_id,
         | 
| 268 | 
            +
                        status: -1
         | 
| 269 | 
            +
                    })
         | 
| 270 | 
            +
                })
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                let operations = kbs.map(doc => {
         | 
| 273 | 
            +
                    return {
         | 
| 274 | 
            +
                        updateOne: {
         | 
| 275 | 
            +
                            filter: { id_project: doc.id_project, type: 'url', source: doc.source },
         | 
| 276 | 
            +
                            update: doc,
         | 
| 277 | 
            +
                            upsert: true,
         | 
| 278 | 
            +
                            returnOriginal: false
         | 
| 279 | 
            +
                        }
         | 
| 172 280 | 
             
                    }
         | 
| 173 281 | 
             
                })
         | 
| 174 282 |  | 
| 283 | 
            +
                saveBulk(operations, kbs, project_id).then((result) => {
         | 
| 284 | 
            +
             | 
| 285 | 
            +
                    let resources = result.map(({ name, status, __v, createdAt, updatedAt, id_project, ...keepAttrs }) => keepAttrs)
         | 
| 286 | 
            +
                    resources = resources.map(({ _id, ...rest }) => {
         | 
| 287 | 
            +
                        return { id: _id, ...rest };
         | 
| 288 | 
            +
                    });
         | 
| 289 | 
            +
                    winston.verbose("resources to be sent to worker: ", resources)        
         | 
| 290 | 
            +
                    scheduleScrape(resources);
         | 
| 291 | 
            +
                    res.status(200).send(result);
         | 
| 292 | 
            +
             | 
| 293 | 
            +
                }).catch((err) => {
         | 
| 294 | 
            +
                    winston.error("Unable to save kbs in bulk ", err)
         | 
| 295 | 
            +
                    res.status(500).send(err);
         | 
| 296 | 
            +
                })
         | 
| 297 | 
            +
             | 
| 298 | 
            +
            })
         | 
| 299 | 
            +
             | 
| 300 | 
            +
            router.post('/sitemap', async (req, res) => {
         | 
| 301 | 
            +
             | 
| 302 | 
            +
                let sitemap_url = req.body.sitemap;
         | 
| 303 | 
            +
                
         | 
| 304 | 
            +
                const sitemap = new Sitemapper({
         | 
| 305 | 
            +
                    url: sitemap_url,
         | 
| 306 | 
            +
                    timeout: 15000
         | 
| 307 | 
            +
                });
         | 
| 308 | 
            +
             | 
| 309 | 
            +
                sitemap.fetch().then((data) => {
         | 
| 310 | 
            +
                    winston.debug("data: ", data);
         | 
| 311 | 
            +
                    res.status(200).send(data);
         | 
| 312 | 
            +
                }).catch((err) => {
         | 
| 313 | 
            +
                    console.error("err ", err)
         | 
| 314 | 
            +
                    res.status(500).send({ success: false, error: err });
         | 
| 315 | 
            +
                })
         | 
| 316 | 
            +
             | 
| 175 317 | 
             
            })
         | 
| 176 318 |  | 
| 319 | 
            +
             | 
| 177 320 | 
             
            router.put('/:kb_id', async (req, res) => {
         | 
| 178 321 |  | 
| 179 322 | 
             
                let kb_id = req.params.kb_id;
         | 
| @@ -230,10 +373,14 @@ router.post('/scrape/single', async (req, res) => { | |
| 230 373 | 
             
                            id: kb._id,
         | 
| 231 374 | 
             
                            type: kb.type,
         | 
| 232 375 | 
             
                            source: kb.source,
         | 
| 233 | 
            -
                            content:  | 
| 376 | 
            +
                            content: "",
         | 
| 234 377 | 
             
                            namespace: kb.namespace
         | 
| 235 378 | 
             
                        }
         | 
| 236 379 |  | 
| 380 | 
            +
                        if (kb.content) {
         | 
| 381 | 
            +
                            json.content = kb.content;
         | 
| 382 | 
            +
                        }
         | 
| 383 | 
            +
             | 
| 237 384 | 
             
                        startScrape(json).then((response) => {
         | 
| 238 385 | 
             
                            winston.verbose("startScrape response: ", response);
         | 
| 239 386 | 
             
                            res.status(200).send(response);
         | 
| @@ -256,24 +403,27 @@ router.post('/scrape/status', async (req, res) => { | |
| 256 403 |  | 
| 257 404 | 
             
                if (req.query &&
         | 
| 258 405 | 
             
                    req.query.returnObject &&
         | 
| 259 | 
            -
                    (req.query.returnObject === true || req.query.returnObject === true)) {
         | 
| 406 | 
            +
                    (req.query.returnObject === true || req.query.returnObject === 'true')) {
         | 
| 260 407 | 
             
                    returnObject = true;
         | 
| 261 408 | 
             
                }
         | 
| 262 409 |  | 
| 263 | 
            -
                openaiService.scrapeStatus(data).then((response) => {
         | 
| 410 | 
            +
                openaiService.scrapeStatus(data).then( async (response) => {
         | 
| 264 411 |  | 
| 265 412 | 
             
                    winston.debug("scrapeStatus response.data: ", response.data);
         | 
| 266 413 |  | 
| 267 414 | 
             
                    let update = {};
         | 
| 268 415 |  | 
| 269 416 | 
             
                    if (response.data.status_code) {
         | 
| 270 | 
            -
                        update.status = response.data.status_code;
         | 
| 417 | 
            +
                        // update.status = response.data.status_code;
         | 
| 418 | 
            +
                        update.status = await statusConverter(response.data.status_code)
         | 
| 419 | 
            +
                            
         | 
| 271 420 | 
             
                    }
         | 
| 272 421 |  | 
| 273 422 | 
             
                    KB.findByIdAndUpdate(data.id, update, { new: true }, (err, savedKb) => {
         | 
| 274 423 |  | 
| 275 424 | 
             
                        if (err) {
         | 
| 276 425 | 
             
                            winston.verbose("Status was successfully recovered, but the update on the db failed");
         | 
| 426 | 
            +
                            winston.error("find kb by id and updated error: ", err);
         | 
| 277 427 |  | 
| 278 428 | 
             
                            if (returnObject) {
         | 
| 279 429 | 
             
                                return res.status(206).send({ warning: "Unable to udpate content on db", message: "The original reply was forwarded", data: response.data });
         | 
| @@ -298,8 +448,14 @@ router.post('/scrape/status', async (req, res) => { | |
| 298 448 |  | 
| 299 449 | 
             
            router.post('/qa', async (req, res) => {
         | 
| 300 450 | 
             
                let data = req.body;
         | 
| 451 | 
            +
                // add or override namespace value if it is passed for security reason
         | 
| 452 | 
            +
                data.namespace = req.projectid;
         | 
| 301 453 | 
             
                winston.debug("/qa data: ", data);
         | 
| 302 454 |  | 
| 455 | 
            +
                // if (req.body.namespace != req.projectid) {
         | 
| 456 | 
            +
                //     return res.status(403).send({ success: false, error: "Not allowed. The namespace does not belong to the current project."})
         | 
| 457 | 
            +
                // }
         | 
| 458 | 
            +
             | 
| 303 459 | 
             
                if (!data.gptkey) {
         | 
| 304 460 | 
             
                    let gptkey = process.env.GPTKEY;
         | 
| 305 461 | 
             
                    if (!gptkey) {
         | 
| @@ -310,11 +466,38 @@ router.post('/qa', async (req, res) => { | |
| 310 466 |  | 
| 311 467 | 
             
                openaiService.askNamespace(data).then((resp) => {
         | 
| 312 468 | 
             
                    winston.debug("qa resp: ", resp.data);
         | 
| 313 | 
            -
                     | 
| 469 | 
            +
                    let answer = resp.data;
         | 
| 470 | 
            +
             | 
| 471 | 
            +
                    let id = answer.id;
         | 
| 472 | 
            +
                    let index = id.indexOf("#");
         | 
| 473 | 
            +
                    if (index != -1) {
         | 
| 474 | 
            +
                        id = id.substring(index + 1);
         | 
| 475 | 
            +
                    }
         | 
| 476 | 
            +
             | 
| 477 | 
            +
                    KB.findById(id, (err, resource) => {
         | 
| 478 | 
            +
             | 
| 479 | 
            +
                        if (err) {
         | 
| 480 | 
            +
                            winston.error("Unable to find resource with id " + id + " in namespace " + answer.namespace + ". The standard answer is returned.")
         | 
| 481 | 
            +
                            return res.status(200).send(resp.data);
         | 
| 482 | 
            +
                        }
         | 
| 483 | 
            +
             | 
| 484 | 
            +
                        answer.source = resource.name;
         | 
| 485 | 
            +
                        return res.status(200).send(answer);
         | 
| 486 | 
            +
                    })
         | 
| 487 | 
            +
                
         | 
| 488 | 
            +
             | 
| 314 489 | 
             
                }).catch((err) => {
         | 
| 315 490 | 
             
                    winston.error("qa err: ", err);
         | 
| 316 | 
            -
                     | 
| 317 | 
            -
                     | 
| 491 | 
            +
                    console.log(err.response)
         | 
| 492 | 
            +
                    if (err.response 
         | 
| 493 | 
            +
                        && err.response.status) {
         | 
| 494 | 
            +
                            let status = err.response.status;
         | 
| 495 | 
            +
                            res.status(status).send({ success: false, statusText: err.response.statusText, error: err.response.data.detail });
         | 
| 496 | 
            +
                    }
         | 
| 497 | 
            +
                    else {
         | 
| 498 | 
            +
                        res.status(500).send({ success: false, error: err });
         | 
| 499 | 
            +
                    }
         | 
| 500 | 
            +
                    
         | 
| 318 501 | 
             
                })
         | 
| 319 502 | 
             
            })
         | 
| 320 503 |  | 
| @@ -375,7 +558,7 @@ router.delete('/:kb_id', async (req, res) => { | |
| 375 558 | 
             
                        })
         | 
| 376 559 |  | 
| 377 560 | 
             
                    } else {
         | 
| 378 | 
            -
                        winston. | 
| 561 | 
            +
                        winston.verbose("resp.data: ", resp.data);
         | 
| 379 562 |  | 
| 380 563 | 
             
                        KB.findOneAndDelete({ _id: kb_id, status: { $in: [-1, 3, 4] } }, (err, deletedKb) => {
         | 
| 381 564 | 
             
                            if (err) {
         | 
| @@ -398,6 +581,51 @@ router.delete('/:kb_id', async (req, res) => { | |
| 398 581 |  | 
| 399 582 | 
             
            })
         | 
| 400 583 |  | 
| 584 | 
            +
            async function saveBulk(operations, kbs, project_id) {
         | 
| 585 | 
            +
             | 
| 586 | 
            +
                return new Promise((resolve, reject) => {
         | 
| 587 | 
            +
                    KB.bulkWrite(operations, { ordered: false }).then((result) => {
         | 
| 588 | 
            +
                        winston.verbose("bulkWrite operations result: ", result);
         | 
| 589 | 
            +
             | 
| 590 | 
            +
                        KB.find({ id_project: project_id, source: { $in: kbs.map(kb => kb.source) } }).lean().then((documents) => {
         | 
| 591 | 
            +
                            winston.debug("documents: ", documents);
         | 
| 592 | 
            +
                            resolve(documents)
         | 
| 593 | 
            +
                        }).catch((err) => {
         | 
| 594 | 
            +
                            winston.error("Error finding documents ", err)
         | 
| 595 | 
            +
                            reject(err);
         | 
| 596 | 
            +
                        })
         | 
| 597 | 
            +
             | 
| 598 | 
            +
                    }).catch((err) => {
         | 
| 599 | 
            +
                        reject(err);
         | 
| 600 | 
            +
                    })
         | 
| 601 | 
            +
                })
         | 
| 602 | 
            +
             | 
| 603 | 
            +
            }
         | 
| 604 | 
            +
             | 
| 605 | 
            +
            async function statusConverter(status) {
         | 
| 606 | 
            +
                return new Promise((resolve) => {
         | 
| 607 | 
            +
             | 
| 608 | 
            +
                    let td_status;
         | 
| 609 | 
            +
                    switch(status) {
         | 
| 610 | 
            +
                        case 0:
         | 
| 611 | 
            +
                            td_status = -1;
         | 
| 612 | 
            +
                            break;
         | 
| 613 | 
            +
                        case 2:
         | 
| 614 | 
            +
                            td_status = 200;
         | 
| 615 | 
            +
                            break;    
         | 
| 616 | 
            +
                        case 3:
         | 
| 617 | 
            +
                            td_status = 300;
         | 
| 618 | 
            +
                            break;
         | 
| 619 | 
            +
                        case 4:
         | 
| 620 | 
            +
                            td_status = 400;
         | 
| 621 | 
            +
                            break;
         | 
| 622 | 
            +
                        default:
         | 
| 623 | 
            +
                            td_status = -1
         | 
| 624 | 
            +
                    }
         | 
| 625 | 
            +
                    resolve(td_status);
         | 
| 626 | 
            +
                })
         | 
| 627 | 
            +
            }
         | 
| 628 | 
            +
             | 
| 401 629 | 
             
            async function updateStatus(id, status) {
         | 
| 402 630 | 
             
                return new Promise((resolve) => {
         | 
| 403 631 |  | 
| @@ -412,6 +640,23 @@ async function updateStatus(id, status) { | |
| 412 640 | 
             
                })
         | 
| 413 641 | 
             
            }
         | 
| 414 642 |  | 
| 643 | 
            +
            async function scheduleScrape(resources) {
         | 
| 644 | 
            +
             | 
| 645 | 
            +
                let data = {
         | 
| 646 | 
            +
                    resources: resources
         | 
| 647 | 
            +
                }
         | 
| 648 | 
            +
                winston.info("Schedule job with following data: ", data);
         | 
| 649 | 
            +
                let scheduler = new Scheduler({ jobManager: jobManager });
         | 
| 650 | 
            +
                scheduler.trainSchedule(data, (err, result) => {
         | 
| 651 | 
            +
                    if (err) {
         | 
| 652 | 
            +
                        winston.error("Scheduling error: ", err);
         | 
| 653 | 
            +
                    }
         | 
| 654 | 
            +
                    winston.info("Scheduling result: ", result);
         | 
| 655 | 
            +
                });
         | 
| 656 | 
            +
             | 
| 657 | 
            +
                return true;
         | 
| 658 | 
            +
            }
         | 
| 659 | 
            +
             | 
| 415 660 | 
             
            async function startScrape(data) {
         | 
| 416 661 |  | 
| 417 662 | 
             
                if (!data.gptkey) {
         | 
| @@ -425,7 +670,7 @@ async function startScrape(data) { | |
| 425 670 | 
             
                return new Promise((resolve, reject) => {
         | 
| 426 671 | 
             
                    openaiService.singleScrape(data).then(async (resp) => {
         | 
| 427 672 | 
             
                        winston.debug("singleScrape resp: ", resp.data);
         | 
| 428 | 
            -
                        let status_updated = await updateStatus(data.id,  | 
| 673 | 
            +
                        let status_updated = await updateStatus(data.id, 100);
         | 
| 429 674 | 
             
                        winston.verbose("status of kb " + data.id + " updated: " + status_updated);
         | 
| 430 675 | 
             
                        resolve(resp.data);
         | 
| 431 676 | 
             
                    }).catch((err) => {
         | 
    
        package/services/QuoteManager.js
    CHANGED
    
    | @@ -5,11 +5,11 @@ const messageEvent = require('../event/messageEvent'); | |
| 5 5 | 
             
            const emailEvent = require('../event/emailEvent');
         | 
| 6 6 |  | 
| 7 7 | 
             
            const PLANS_LIST = {
         | 
| 8 | 
            -
                FREE_TRIAL: { requests: 3000,   messages: 0,    tokens: 250000,     email: 200 }, // same as PREMIUM
         | 
| 9 | 
            -
                SANDBOX:    { requests: 200,    messages: 0,    tokens: 10000,      email: 200 },
         | 
| 10 | 
            -
                BASIC:      { requests: 800,    messages: 0,    tokens: 50000,      email: 200 },
         | 
| 11 | 
            -
                PREMIUM:    { requests: 3000,   messages: 0,    tokens: 250000,     email: 200 },
         | 
| 12 | 
            -
                CUSTOM:     { requests: 3000,   messages: 0,    tokens: 250000,     email: 200 }
         | 
| 8 | 
            +
                FREE_TRIAL: { requests: 3000,   messages: 0,    tokens: 250000,     email: 200,     kbs: 50 }, // same as PREMIUM
         | 
| 9 | 
            +
                SANDBOX:    { requests: 200,    messages: 0,    tokens: 10000,      email: 200,     kbs: 50 },
         | 
| 10 | 
            +
                BASIC:      { requests: 800,    messages: 0,    tokens: 50000,      email: 200,     kbs: 150},
         | 
| 11 | 
            +
                PREMIUM:    { requests: 3000,   messages: 0,    tokens: 250000,     email: 200,     kbs: 300},
         | 
| 12 | 
            +
                CUSTOM:     { requests: 3000,   messages: 0,    tokens: 250000,     email: 200,     kbs: 300}
         | 
| 13 13 | 
             
            }
         | 
| 14 14 |  | 
| 15 15 | 
             
            const typesList = ['requests', 'messages', 'email', 'tokens']
         | 
| @@ -58,7 +58,7 @@ class QuoteManager { | |
| 58 58 |  | 
| 59 59 | 
             
                    this.project = project;
         | 
| 60 60 | 
             
                    let key = await this.generateKey(email, 'email');
         | 
| 61 | 
            -
                    winston. | 
| 61 | 
            +
                    winston.verbose("[QuoteManager] incrementEmailCount key: " + key);
         | 
| 62 62 |  | 
| 63 63 | 
             
                    await this.tdCache.incr(key)
         | 
| 64 64 | 
             
                    return key;
         | 
| @@ -68,7 +68,7 @@ class QuoteManager { | |
| 68 68 |  | 
| 69 69 | 
             
                    this.project = project;
         | 
| 70 70 | 
             
                    let key = await this.generateKey(data, 'tokens');
         | 
| 71 | 
            -
                    winston. | 
| 71 | 
            +
                    winston.verbose("[QuoteManager] incrementTokenCount key: " + key);
         | 
| 72 72 |  | 
| 73 73 | 
             
                    if (quotes_enabled === false) {
         | 
| 74 74 | 
             
                        winston.debug("QUOTES DISABLED - incrementTokenCount")
         | 
| @@ -83,8 +83,8 @@ class QuoteManager { | |
| 83 83 |  | 
| 84 84 | 
             
                async generateKey(object, type) {
         | 
| 85 85 |  | 
| 86 | 
            -
                    winston. | 
| 87 | 
            -
                    winston. | 
| 86 | 
            +
                    winston.debug("generateKey object ", object)
         | 
| 87 | 
            +
                    winston.debug("generateKey type " + type)
         | 
| 88 88 | 
             
                    let subscriptionDate;
         | 
| 89 89 | 
             
                    if (this.project.profile.subStart) {
         | 
| 90 90 | 
             
                        subscriptionDate = this.project.profile.subStart;
         | 
| @@ -92,7 +92,7 @@ class QuoteManager { | |
| 92 92 | 
             
                        subscriptionDate = this.project.createdAt;
         | 
| 93 93 | 
             
                    }
         | 
| 94 94 | 
             
                    let objectDate = object.createdAt;
         | 
| 95 | 
            -
                    winston. | 
| 95 | 
            +
                    winston.debug("objectDate " + objectDate);
         | 
| 96 96 |  | 
| 97 97 | 
             
                    // converts date in timestamps and transform from ms to s
         | 
| 98 98 | 
             
                    const objectDateTimestamp = ceil(objectDate.getTime() / 1000);
         | 
| @@ -114,7 +114,7 @@ class QuoteManager { | |
| 114 114 |  | 
| 115 115 | 
             
                    this.project = project;
         | 
| 116 116 | 
             
                    let key = await this.generateKey(object, type);
         | 
| 117 | 
            -
                    winston. | 
| 117 | 
            +
                    winston.verbose("[QuoteManager] getCurrentQuote key: " + key);
         | 
| 118 118 |  | 
| 119 119 | 
             
                    let quote = await this.tdCache.get(key);
         | 
| 120 120 | 
             
                    return Number(quote);
         | 
| @@ -147,17 +147,17 @@ class QuoteManager { | |
| 147 147 | 
             
                 */
         | 
| 148 148 | 
             
                async checkQuote(project, object, type) {
         | 
| 149 149 |  | 
| 150 | 
            -
                    winston. | 
| 150 | 
            +
                    winston.verbose("checkQuote type " + type);
         | 
| 151 151 | 
             
                    if (quotes_enabled === false) {
         | 
| 152 | 
            -
                        winston. | 
| 152 | 
            +
                        winston.verbose("QUOTES DISABLED - checkQuote for type " + type);
         | 
| 153 153 | 
             
                        return true;
         | 
| 154 154 | 
             
                    }
         | 
| 155 155 |  | 
| 156 156 | 
             
                    this.project = project;
         | 
| 157 157 | 
             
                    let limits = await this.getPlanLimits();
         | 
| 158 | 
            -
                    winston. | 
| 158 | 
            +
                    winston.verbose("limits for current plan: ", limits)
         | 
| 159 159 | 
             
                    let quote = await this.getCurrentQuote(project, object, type);
         | 
| 160 | 
            -
                    winston. | 
| 160 | 
            +
                    winston.verbose("getCurrentQuote resp: ", quote)
         | 
| 161 161 |  | 
| 162 162 | 
             
                    if (quote == null) {
         | 
| 163 163 | 
             
                        return true;
         | 
| @@ -171,7 +171,11 @@ class QuoteManager { | |
| 171 171 | 
             
                }
         | 
| 172 172 |  | 
| 173 173 |  | 
| 174 | 
            -
                async getPlanLimits() {
         | 
| 174 | 
            +
                async getPlanLimits(project) {
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                    if (project) {
         | 
| 177 | 
            +
                        this.project = project
         | 
| 178 | 
            +
                    };
         | 
| 175 179 |  | 
| 176 180 | 
             
                    let limits;
         | 
| 177 181 | 
             
                    if (this.project.profile.type === 'payment') {
         | 
| @@ -222,6 +226,8 @@ class QuoteManager { | |
| 222 226 | 
             
                        }
         | 
| 223 227 | 
             
                    }
         | 
| 224 228 |  | 
| 229 | 
            +
                    winston.info("QUOTES ENABLED ? ", quotes_enabled);
         | 
| 230 | 
            +
             | 
| 225 231 | 
             
                    // TODO - Try to generalize to avoid repetition
         | 
| 226 232 | 
             
                    let incrementEventHandler = (object) => { }
         | 
| 227 233 | 
             
                    let checkEventHandler = (object) => { }
         | 
| @@ -244,7 +250,7 @@ class QuoteManager { | |
| 244 250 | 
             
                            let result = await this.incrementRequestsCount(payload.project, payload.request);
         | 
| 245 251 | 
             
                            return result;
         | 
| 246 252 | 
             
                        } else {
         | 
| 247 | 
            -
                            winston. | 
| 253 | 
            +
                            winston.verbose("QUOTES DISABLED - request.create.quote event")
         | 
| 248 254 | 
             
                        }
         | 
| 249 255 | 
             
                    })
         | 
| 250 256 | 
             
                    // REQUESTS EVENTS - END
         | 
| @@ -267,7 +273,7 @@ class QuoteManager { | |
| 267 273 | 
             
                            let result = await this.incrementMessagesCount(payload.project, payload.message);
         | 
| 268 274 | 
             
                            return result;
         | 
| 269 275 | 
             
                        } else {
         | 
| 270 | 
            -
                            winston. | 
| 276 | 
            +
                            winston.verbose("QUOTES DISABLED - message.create.quote event")
         | 
| 271 277 | 
             
                        }
         | 
| 272 278 | 
             
                    })
         | 
| 273 279 | 
             
                    // MESSAGES EVENTS - END
         | 
| @@ -286,11 +292,11 @@ class QuoteManager { | |
| 286 292 |  | 
| 287 293 | 
             
                    emailEvent.on('email.send.quote', async (payload) => {
         | 
| 288 294 | 
             
                        if (quotes_enabled === true) {
         | 
| 289 | 
            -
                            winston. | 
| 295 | 
            +
                            winston.verbose("email.send event catched");
         | 
| 290 296 | 
             
                            let result = await this.incrementEmailCount(payload.project, payload.email);
         | 
| 291 297 | 
             
                            return result;
         | 
| 292 298 | 
             
                        } else {
         | 
| 293 | 
            -
                            winston. | 
| 299 | 
            +
                            winston.verbose("QUOTES DISABLED - email.send event")
         | 
| 294 300 | 
             
                        }
         | 
| 295 301 | 
             
                    })
         | 
| 296 302 | 
             
                    // EMAIL EVENTS - END
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            let JobManager = require("jobs-worker-queued");
         | 
| 2 | 
            +
            let winston = require('../config/winston');
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            let jobManager;
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            class Scheduler {
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                constructor(config) {
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    if (!config) {
         | 
| 11 | 
            +
                        throw new Error('(Scheduler) config is mandatory');
         | 
| 12 | 
            +
                    }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    if (!config.jobManager) {
         | 
| 15 | 
            +
                        throw new Error('(Scheduler) config.jobManager is mandatory');
         | 
| 16 | 
            +
                    }
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    this.jobManager = config.jobManager;
         | 
| 19 | 
            +
                }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                trainSchedule(data, callback) {
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    winston.debug("(trainScheduler) data: ", data);
         | 
| 24 | 
            +
                    this.jobManager.publish(data, (err, ok) => {
         | 
| 25 | 
            +
                        let response_data = { success: true, message: "Scheduled" };
         | 
| 26 | 
            +
                        if (callback) {
         | 
| 27 | 
            +
                            callback(err, response_data);
         | 
| 28 | 
            +
                        }
         | 
| 29 | 
            +
                    });
         | 
| 30 | 
            +
                }
         | 
| 31 | 
            +
            }
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            module.exports = { Scheduler };
         |