UNPKG

@tiledesk/tiledesk-server

Version:
303 lines (241 loc) 10.1 kB
var express = require('express'); var router = express.Router(); const uuidv4 = require('uuid/v4'); var { KB, Namespace } = require('../models/kb_setting'); var winston = require('../config/winston'); const JobManager = require('../utils/jobs-worker-queue-manager/JobManagerV2'); const { Scheduler } = require('../services/Scheduler'); const { AiReindexService } = require('../services/aiReindexService'); const { Webhook } = require('../models/webhook'); const httpUtil = require('../utils/httpUtil'); var jwt = require('jsonwebtoken'); const Faq_kb = require('../models/faq_kb'); const webhookService = require('../services/webhookService'); const errorCodes = require('../errorCodes'); var ObjectId = require('mongoose').Types.ObjectId; const port = process.env.PORT || '3000'; let TILEBOT_ENDPOINT = "http://localhost:" + port + "/modules/tilebot/";; if (process.env.TILEBOT_ENDPOINT) { TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/" } winston.debug("TILEBOT_ENDPOINT: " + TILEBOT_ENDPOINT); const KB_WEBHOOK_TOKEN = process.env.KB_WEBHOOK_TOKEN || 'kbcustomtoken'; const AMQP_MANAGER_URL = process.env.AMQP_MANAGER_URL; const JOB_TOPIC_EXCHANGE = process.env.JOB_TOPIC_EXCHANGE_TRAIN || 'tiledesk-trainer'; let jobManager = new JobManager(AMQP_MANAGER_URL, { debug: false, topic: JOB_TOPIC_EXCHANGE, exchange: JOB_TOPIC_EXCHANGE }) jobManager.connectAndStartPublisher((status, error) => { if (error) { winston.error("connectAndStartPublisher error: ", error); } else { winston.info("KbRoute - ConnectPublisher done with status: ", status); } }) let default_engine = { name: "pinecone", type: process.env.PINECONE_TYPE, apikey: "", vector_size: 1536, index_name: process.env.PINECONE_INDEX } router.post('/kb/reindex', async (req, res) => { winston.verbose("/kb/reindex webhook called") winston.debug("(webhook) req.body: ", req.body); if (!req.headers['x-auth-token']) { winston.error("(webhook) Unauthorized: A x-auth-token must be provided") return res.status(401).send({ success: false, error: "Unauthorized", message: "A x-auth-token must be provided" }) } if (req.headers['x-auth-token'] != KB_WEBHOOK_TOKEN) { winston.error("(webhook) Unauthorized: You don't have the authorization to accomplish this operation") return res.status(401).send({ success: false, error: "Unauthorized", message: "You don't have the authorization to accomplish this operation" }); } let content_id = req.body.content_id; let kb = await KB.findById(content_id).catch( async (err) => { winston.error("(webhook) Error getting kb content: ", err); return res.status(500).send({ success: false, error: "Error getting content with id " + content_id }); }) if (!kb) { winston.warn("(webhook) Kb content not found with id " + content_id + ". Deleting scheduler..."); // Assuming the content has been deleted. The scheduler should be stopped and deleted. res.status(200).send({ success: true, message: "Content no longer exists. Deleting scheduler..." }) setTimeout( async () => { let aiReindexService = new AiReindexService(); let deleteResponse = await aiReindexService.delete(content_id).catch((err) => { winston.error("(webhook) Error deleting scheduler ", err); winston.error("(webhook) Error deleting scheduler " + err); return; }); winston.verbose("(webhook) delete response: ", deleteResponse); return; }, 10000); } else { let json = { id: kb._id, type: kb.type, source: kb.source, content: "", namespace: kb.namespace, refresh_rate: kb.refresh_rate, last_refresh: kb.last_refresh } if (kb.scrape_type) { json.scrape_type = kb.scrape_type } if (kb.scrape_options) { json.parameters_scrape_type_4 = { tags_to_extract: kb.scrape_options.tags_to_extract, unwanted_tags: kb.scrape_options.unwanted_tags, unwanted_classnames: kb.scrape_options.unwanted_classnames } } let namespace = await Namespace.findOne({ id: kb.namespace }).catch((err) => { winston.error("(webhook) Error getting namespace ", err) return res.status(500).send({ success: false, error: err }) }) if (!namespace) { winston.warn("(webhook) Namespace not found with id " + kb.namespace); return res.status(500).send({ success: false, error: err }) } json.engine = namespace.engine || default_engine; let resources = []; resources.push(json); if (process.env.NODE_ENV !== 'test') { scheduleScrape(resources); } res.status(200).send({ success: true, message: "Content queued for reindexing" }); } }) router.post('/kb/status', async (req, res) => { winston.info("(webhook) kb status called"); winston.info("(webhook) req.body: ", req.body); winston.info("(webhook) x-auth-token: " + req.headers['x-auth-token']); winston.info("(webhook) KB_WEBHOOK_TOKEN: " + KB_WEBHOOK_TOKEN); if (!req.headers['x-auth-token']) { winston.error("Unauthorized: A x-auth-token must be provided") return res.status(401).send({ success: false, error: "Unauthorized", message: "A x-auth-token must be provided" }) } if (req.headers['x-auth-token'] != KB_WEBHOOK_TOKEN) { winston.error("Unauthorized: You don't have the authorization to accomplish this operation") return res.status(401).send({ success: false, error: "Unauthorized", message: "You don't have the authorization to accomplish this operation" }); } let body = req.body; winston.verbose('/webhook kb status body: ', body); let kb_id = body.id; winston.verbose('/webhook kb status body: ' + kb_id); let update = {}; if (body.status) { update.status = body.status; } KB.findByIdAndUpdate(kb_id, update, { new: true }, (err, kb) => { if (err) { winston.error(err); return res.status(500).send({ success: false, error: err }); } if (!kb) { winston.info("Knwoledge Base content to be updated not found") return res.status(404).send({ success: false, messages: "Knwoledge Base content not found with id " + kb_id }); } winston.info("kb updated succesfully: ", kb); res.status(200).send(kb); }) }) router.all('/:webhook_id', async (req, res) => { let webhook_id = req.params.webhook_id; let payload = req.body; payload.webhook_http_method = req.method; let params = req.query; let dev = params.dev; delete params.dev; if (params) { payload.webhook_query_params = params; } let webhook = await Webhook.findOne({ webhook_id: webhook_id }).catch((err) => { winston.error("Error finding webhook: ", err); return res.status(500).send({ success: false, error: err }); }) if (!webhook) { winston.warn("Webhook not found with id " + webhook_id); return res.status(404).send({ success: false, error: "Webhook not found with id " + webhook_id }); } if (!webhook.enabled) { winston.verbose("Webhook " + webhook_id + " is currently turned off") return res.status(422).send({ success: false, error: "Webhook " + webhook_id + " is currently turned off"}) } payload.request_id = "automation-request-" + webhook.id_project + "-" + new ObjectId() + "-" + webhook_id; // To delete - Start // This endpoint will be used only for production webhooks, so is no longer // necessary to pass dev and redis_client to webhookService.run(). let redis_client = req.app.get('redis_client'); // and substitute currect run with the following one //webhookService.run(webhook, payload) // To delete - End webhookService.run(webhook, payload, dev, redis_client).then((response) => { return res.status(200).send(response); }).catch((err) => { if (err.code === errorCodes.WEBHOOK.ERRORS.NO_PRELOADED_DEV_REQUEST) { return res.status(422).send({ success: false, message: "Development webhook is currently turned off", code: err.code }) } else { let status = err.status || 500; return res.status(status).send(err.data); } }) }) router.all('/:webhook_id/dev', async (req, res) => { let webhook_id = req.params.webhook_id; let payload = req.body; payload.webhook_http_method = req.method; let params = req.query; delete params.dev; if (params) { payload.webhook_query_params = params; } let webhook = await Webhook.findOne({ webhook_id: webhook_id }).catch((err) => { winston.error("Error finding webhook: ", err); return res.status(500).send({ success: false, error: err }); }) if (!webhook) { winston.warn("Webhook not found with id " + webhook_id); return res.status(404).send({ success: false, error: "Webhook not found with id " + webhook_id }); } let redis_client = req.app.get('redis_client'); webhookService.run(webhook, payload, true, redis_client).then((response) => { return res.status(200).send(response); }).catch((err) => { if (err.code === errorCodes.WEBHOOK.ERRORS.NO_PRELOADED_DEV_REQUEST) { return res.status(422).send({ success: false, message: "Development webhook is currently turned off", code: err.code }) } else { let status = err.status || 500; return res.status(status).send(err.data); } }) }) async function scheduleScrape(resources) { let scheduler = new Scheduler({ jobManager: jobManager }); resources.forEach(r => { winston.debug("(Webhook) Schedule job with following data: ", r); scheduler.trainSchedule(r, async (err, result) => { if (err) { winston.error("Scheduling error: ", err); } else { winston.info("Scheduling result: ", result); } }); }) return true; } async function generateChatbotToken(chatbot) { let signOptions = { issuer: 'https://tiledesk.com', subject: 'bot', audience: 'https://tiledesk.com/bots/' + chatbot._id, jwtid: uuidv4() }; let botPayload = chatbot.toObject(); let botSecret = botPayload.secret; var bot_token = jwt.sign(botPayload, botSecret, signOptions); return bot_token; } module.exports = router;