hubxglpi/src/shared/utils/commentSanitizer.js

107 lines
4.1 KiB
JavaScript
Raw Normal View History

const { logInfo, logWarning } = require('./logger');
const stripHTML = (html) => {
if (!html) return '';
let cleaned = html
.replace(/&#60;/g, '<') // &#60; para <
.replace(/&#62;/g, '>') // &#62; para >
.replace(/&#38;/g, '&') // &#38; para &
.replace(/&nbsp;/g, ' ') // &nbsp; para espaço
.replace(/&lt;/g, '<') // &lt; para <
.replace(/&gt;/g, '>') // &gt; para >
.replace(/&amp;/g, '&') // &amp; para &
.replace(/&quot;/g, '"'); // &quot; para "
cleaned = cleaned
.replace(/<br\s*\/?>/gi, '\n') // <br> para quebra de linha
.replace(/<p>/gi, '') // Remove <p>
.replace(/<\/p>/gi, '\n\n') // </p> para duas quebras
.replace(/<strong>/gi, '**') // <strong> para **
.replace(/<\/strong>/gi, '**') // </strong> para **
.replace(/<em>/gi, '*') // <em> para *
.replace(/<\/em>/gi, '*') // </em> para *
.replace(/<blockquote>/gi, '> ') // <blockquote> para citação
.replace(/<\/blockquote>/gi, '') // </blockquote>
.replace(/<div[^>]*>/gi, '') // Remove <div> com qualquer atributo
.replace(/<\/div>/gi, '\n') // </div> para quebra
.replace(/<[^>]*>/g, '') // Remove todas outras tags HTML
.replace(/\n\s*\n\s*\n/g, '\n\n') // Remove múltiplas quebras
.replace(/^\s+|\s+$/g, '') // Remove espaços no início/fim
.trim();
return cleaned;
};
const handleImages = (content) => {
const imgRegex = /<img[^>]+src="([^"]+)"[^>]*>/gi;
const hasImages = imgRegex.test(content);
if (hasImages) {
logWarning('📷 Imagem detectada no comentário GLPI');
return content.replace(/<a[^>]*>.*?<img[^>]*>.*?<\/a>/gi, '[IMAGEM ANEXA NO GLPI]');
}
return content;
};
const cleanJSONMetadata = (content) => {
if (typeof content === 'string' && content.includes('{id=') && content.includes('content=')) {
try {
const contentMatch = content.match(/content=([^,]+),/);
if (contentMatch && contentMatch[1]) {
let extracted = contentMatch[1].trim();
extracted = extracted.replace(/^['"]|['"]$/g, '');
return extracted;
}
} catch (error) {
logWarning('Não foi possível extrair conteúdo do metadado GLPI', { content });
}
}
return content;
};
const sanitizeGLPIComment = (commentObj) => {
if (!commentObj || typeof commentObj !== 'object') {
logWarning('Comentário inválido recebido', { comment: commentObj });
return '';
}
let content = commentObj.content || '';
if (!content) return '';
content = cleanJSONMetadata(content.toString());
content = handleImages(content);
content = stripHTML(content);
if (content !== commentObj.content) {
logInfo('🔧 Comentário sanitizado', {
original: commentObj.content.substring(0, 100) + '...',
cleaned: content.substring(0, 100) + '...'
});
}
return content;
};
/**
* @module commentSanitizer
* @description Este módulo utilitário é especializado em limpar e formatar o conteúdo dos comentários (follow-ups) vindos do GLPI.
* O GLPI armazena comentários em formato HTML, muitas vezes com metadados e formatações que não são desejáveis no ServiceNow.
* O objetivo é converter esse conteúdo em texto puro e legível.
*
* Funções:
* - `sanitizeGLPIComment(commentObj)`: A função principal que orquestra o processo de limpeza.
* - `stripHTML(html)`: Remove a maioria das tags HTML, convertendo algumas (como `<br>`, `<p>`, `<strong>`) em marcações de texto simples (quebras de linha, asteriscos).
* - `handleImages(content)`: Detecta a presença de imagens nos comentários do GLPI e as substitui por um texto placeholder, como "[IMAGEM ANEXA NO GLPI]", que as imagens não podem ser transferidas diretamente.
* - `cleanJSONMetadata(content)`: Remove metadados em formato de string JSON que o GLPI às vezes insere no campo de conteúdo, extraindo apenas o texto real do comentário.
*/
module.exports = {
sanitizeGLPIComment,
stripHTML,
handleImages,
cleanJSONMetadata
};