const path = require('path') const { StatusCodes } = require("http-status-codes") const { createCRMContact, sendMessageSocket, mustContainProperties, journaling, ticketCRM, findProperty, journalingRequest, createContact, lookupContactByPhone, templateValidator } = require('../utils') const fs = require("fs") const { URL } = require('url') const { oauth2 } = require('../utils') const { exchangeForTokens } = oauth2 const Company = require('../models/Company') const CRM = require('../models/CRM') const CustomError = require('../errors') const contactCreate = async (req, res) => { const { companyId, crmFirstName, crmLastName, crmPhone, crmEmail } = req.body mustContainProperties(req, ['companyId', 'crmPhone',]) await createCRMContact(companyId, crmFirstName, crmPhone, crmEmail, crmLastName) res.status(StatusCodes.OK).send() } const deleteCrm = async (req, res) => { let { companyId, crmBaseURL } = req.body mustContainProperties(req, ['companyId', 'crmBaseURL',]) if (!crmBaseURL.startsWith('http://') && !crmBaseURL.startsWith('https://')) { crmBaseURL = `https://${crmBaseURL.trim()}` } const crm = await CRM.findOne({ companyId, crmBaseURL: new URL(crmBaseURL.trim()).hostname }) if (crm) await crm.deleteOne() res.status(StatusCodes.OK).send() } const deleteCompany = async (req, res) => { const { companyId } = req.body mustContainProperties(req, ['companyId',]) const company = await Company.findOne({ companyId, }) if (company) await company.deleteOne() res.status(StatusCodes.OK).send() } const callJournaling = async (req, res) => { let { companyId, operation, crmPhone, crmAgent, crmCallDuration, crmFirstName, operationStatus } = req.body console.log('REQ.BODY CRM TESTe: ', JSON.stringify(req.body, null, 6)) // return res.status(StatusCodes.OK).send() crmPhone = '55' + crmPhone console.log('========> CRMPHONE: ', crmPhone) console.log('========> COMPANY ID before: ', companyId) companyId = '40' console.log('========> COMPANY ID after: ', companyId) mustContainProperties(req, ['companyId', 'operation', 'crmPhone', 'crmAgent',]) // if (operation == 'inboundAnsweredCall' && !crmCallDuration) // throw new CustomError.BadRequestError(`The crmCallDuration property must be provided when operation is inboundAnsweredCall`) // if (operation == 'outboundAsweredCall' && !crmCallDuration) // throw new CustomError.BadRequestError(`The crmCallDuration property must be provided when operation is outboundAsweredCall`) if (!crmCallDuration || crmCallDuration.trim() == "") crmCallDuration = "300" if (operationStatus == "hangup") await journaling(companyId, operation, crmPhone, crmAgent, crmCallDuration, crmFirstName) else if (operationStatus == "update-answer") { console.log('update-answer') await ticketCRM(companyId, crmPhone, crmAgent, crmFirstName) } res.status(StatusCodes.OK).send() } const install = async (req, res) => { const { authUrl, companyId } = req.query console.log('--------> authUrl: ', authUrl) // Store the authUrl in the session req.session.authUrl = authUrl res.redirect(authUrl) } const oauthCallBack = async (req, res) => { const { code } = req.query // Retrieve the stored authUrl from the session const storedAuthUrl = req.session.authUrl console.log('xxxxxxxxxx storedAuthUrl: ', storedAuthUrl) const parsedUrl = new URL(storedAuthUrl) const clientId = parsedUrl.searchParams.get('client_id') if (code) { let crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': clientId }) crmOauth = crmOauth.toObject() let authCodeProof = { grant_type: 'authorization_code', client_id: crmOauth.crm.authentication.crmClientId, client_secret: crmOauth.crm.authentication.crmClientSecret, redirect_uri: process.env.URL_OAUTH_CALLBACK, //remove this // refactor this. To salesforce only when using oauth2 code_verifier: `gwkPueV2GSzkFvGFiHbNjpRuq_XBEGBsihM59pMaiFalZrOQ_7J4hgtBR8GIbLHutcuUwba2k0xeKhD8ELjWEswE3xv-H2e6Jh8EOwOccj2i_rYPUlMGdPDqpuRs8D3w`, code: `${code.split('%')[0]}` // //enable this // code } // Exchange the authorization code for an access token and refresh token await exchangeForTokens(crmOauth, authCodeProof) const url = `${process.env.URL_OAUTH_FRONTEND_SUCCESS_REDIRECT}?clientId=${encodeURIComponent(clientId)}` return res.redirect(url) // return res.redirect(process.env.URL_OAUTH_FRONTEND_SUCCESS_REDIRECT) } res.status(StatusCodes.OK).send() } const testTemplate = async (req, res) => { const { clientId, companyId } = req.body let crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': clientId, testing: true }) if (!crmOauth) return res.status(StatusCodes.OK).send() crmOauth = crmOauth.toObject() const { crmPhoneTest } = crmOauth.crm.authentication await templateValidator(crmPhoneTest, crmOauth.crm, companyId) crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': clientId }) crmOauth.testing = false await crmOauth.save() res.status(StatusCodes.OK).send() } const uploadCrmConfig = async (req, res) => { const { companyId, } = req.body mustContainProperties(req, ['companyId',]) if (!req?.file) throw new CustomError.BadRequestError(`The crm property file must be provided`) const file = req.file let newCrm = fs.readFileSync(file.path, "utf8") newCrm = JSON.parse(newCrm) const index = newCrm.crmRest.findIndex(rest => rest?.createContactRecord) const crmBaseURL = new URL(newCrm.crmRest[index].createContactRecord.request.url.trim()).hostname let company = await Company.findOne({ companyId }) if (!company) { company = await Company.create({ companyId }) } let crm = await CRM.findOne({ companyId, crmBaseURL }) if (crm) { crm.testing = true crm.crm = newCrm await crm.save() } else { crm = await CRM.create({ crmBaseURL, companyId: company.companyId, company, testing: true, crm: newCrm }) } fs.unlinkSync(file.path) const { type, crmClientId, crmClientSecret, crmScopes, crmPhoneTest } = crm.crm.authentication if (type == 'oauth2') { const { request, body, response } = findProperty(crm.crm.crmRest, 'authorizationEndpoint') let { url } = request url = url.replace('crmClientId', crmClientId) .replace('crmClientSecret', crmClientSecret) .replace('crmScopes', crmScopes) .replace('crmRedirectURI', process.env.URL_OAUTH_CALLBACK) const authUrl = `https://api-integracao-crm.hitmanager.app.br/api/v1/crm/install?authUrl=${encodeURIComponent(url)}&companyId=${encodeURIComponent(companyId)}` console.log('--------> authUrl: ', authUrl) return res.status(StatusCodes.OK).json({ url: authUrl }) } else { await templateValidator(crmPhoneTest, newCrm, companyId) crm.testing = false await crm.save() } res.status(StatusCodes.OK).send() } const getCrms = async (req, res) => { const { companyId, } = req.params if (!companyId) throw new CustomError.BadRequestError(`The companyId must be provided in the URL`) const crms = await CRM.find({ companyId }, { _id: 1, crmBaseURL: 1, createdAt: 1, companyId: 1, enabled: 1 }) res.status(StatusCodes.OK).send(crms) } module.exports = { contactCreate, uploadCrmConfig, callJournaling, oauthCallBack, install, deleteCrm, deleteCompany, testTemplate, getCrms }