const axios = require('axios'); const Logger = console; require('dotenv').config(); const loadCRM = require('../utils/loadCRM') const lookupContactByPhone = require('../utils/lookupCRMContactByPhone') const createContact = require('../utils/createContact') /** * Serviço para integração com a API do HubSpot. */ class HubspotService { /** * Inicializa o serviço HubspotService com configuração da API. */ constructor() { this.logger = Logger; this.baseUrl = 'https://api.hubapi.com'; this.apiKey = process.env.HUBSPOT_API_KEY; this.client = axios.create({ baseURL: this.baseUrl, headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json' } }); } /** * Cria uma nota de chamada no HubSpot e associa ao contato e opcionalmente a um ticket. * * @param {string} contactId - ID do contato no HubSpot. * @param {Object} callData - Dados da chamada. * @param {string} callData.transcription - Transcrição completa da chamada. * @param {string} callData.summary - Resumo da chamada. * @param {string} callData.recordingUrl - URL da gravação da chamada. * @param {string} callData.callerId - Número do chamador. * @param {string} callData.uniqueId - Identificador único da chamada. * @param {string} [callData.ticketId] - (Opcional) ID do ticket no HubSpot. * @returns {Promise} - Dados da nota criada. */ async createCallNote(contactId, callData) { try { const { transcription, summary, recordingUrl, callerId, uniqueId, ticketId } = callData; const noteContent = ` Chamada Recebida ------------------ Número: ${callerId} ID da Chamada: ${uniqueId} Data/Hora: ${new Date().toLocaleString('pt-BR', { timeZone: 'America/Sao_Paulo' })} Resumo: ${summary} Transcrição Completa: ${transcription} Link da Gravação: ${recordingUrl} `.trim(); // 1. Cria a nota const response = await this.client.post('/crm/v3/objects/notes', { properties: { hs_timestamp: new Date().toISOString(), hs_note_body: noteContent } }); const noteId = response.data.id; // 2. Associa a nota ao contato await this.client.put(`/crm/v3/objects/notes/${noteId}/associations/contact/${contactId}/note_to_contact`); // 3. (Opcional) Associa a nota ao ticket, se houver if (ticketId) { await this.client.put(`/crm/v3/objects/notes/${noteId}/associations/ticket/${ticketId}/note_to_ticket`); this.logger.log(`Nota associada ao ticket ${ticketId}`); } this.logger.log(`Nota ${noteId} criada com sucesso.`); return response.data; } catch (error) { this.logger.error('Erro ao criar nota:', error?.response?.data || error.message); throw error; } } /** * Busca um contato no HubSpot pelo número de telefone. * * @param {string} phoneNumber - Número de telefone para buscar. * @returns {Promise} - Contato encontrado ou null. */ async findContactByPhone(phoneNumber) { try { const response = await this.client.post('/crm/v3/objects/contacts/search', { filterGroups: [{ filters: [{ propertyName: 'phone', operator: 'EQ', value: phoneNumber }] }] }); return response.data.results[0] || null; } catch (error) { this.logger.error('Erro ao buscar contato:', error?.response?.data || error.message); throw error; } } /** * Cria um contato com o número informado caso não exista. * * @param {string} crmPhone - Número de telefone do contato. * @returns {Promise} - Contato existente ou novo contato criado. */ async createContactIfNotExists(companyId, crmPhone) { const crmFiles = await loadCRM(companyId) if (crmFiles.length > 0) { const { crmRest: rest, authentication } = crmFiles[0].crm let contact = await lookupContactByPhone(rest, authentication, crmPhone, companyId) if (!contact.exist) { contact = await createContact(companyId, rest, authentication, crmPhone) } return contact } } } module.exports = HubspotService;