Update content-moderation.js
This commit is contained in:
parent
7e822acb45
commit
b6dee67c0e
|
|
@ -96,16 +96,20 @@ class ContentModeration {
|
||||||
|
|
||||||
// Inicializa o modelo NSFW
|
// Inicializa o modelo NSFW
|
||||||
this.nsfwModel = null;
|
this.nsfwModel = null;
|
||||||
this.initNSFWModel();
|
this.nsfwModelLoading = false;
|
||||||
|
this.loadNSFWModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
async initNSFWModel() {
|
async loadNSFWModel() {
|
||||||
|
if (this.nsfwModel || this.nsfwModelLoading) return;
|
||||||
|
this.nsfwModelLoading = true;
|
||||||
try {
|
try {
|
||||||
// Carrega o modelo NSFW do TensorFlow.js
|
this.nsfwModel = await nsfwjs.load();
|
||||||
this.nsfwModel = await tf.loadGraphModel('https://d1zv2aa70wpiur.cloudfront.net/tfjs_models/tfjs_nsfw_mobilenet/model.json');
|
console.log('Modelo NSFW carregado!');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erro ao carregar modelo NSFW:', error);
|
console.error('Erro ao carregar modelo NSFW:', error);
|
||||||
}
|
}
|
||||||
|
this.nsfwModelLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normaliza o texto removendo substituições de caracteres
|
// Normaliza o texto removendo substituições de caracteres
|
||||||
|
|
@ -136,21 +140,16 @@ class ContentModeration {
|
||||||
// Verifica se o conteúdo é NSFW
|
// Verifica se o conteúdo é NSFW
|
||||||
async checkNSFW(file) {
|
async checkNSFW(file) {
|
||||||
if (!this.isMediaFile(file)) return false;
|
if (!this.isMediaFile(file)) return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Verifica primeiro pelo nome do arquivo
|
|
||||||
const fileName = file.name.toLowerCase();
|
const fileName = file.name.toLowerCase();
|
||||||
if (this.blockedWords.some(word => fileName.includes(word.toLowerCase()))) {
|
if (this.blockedWords.some(word => fileName.includes(word.toLowerCase()))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Se for uma imagem ou vídeo, verifica o conteúdo
|
|
||||||
if (file.type.startsWith('image/')) {
|
if (file.type.startsWith('image/')) {
|
||||||
return await this.checkImageNSFW(file);
|
return await this.checkImageNSFW(file);
|
||||||
} else if (file.type.startsWith('video/')) {
|
} else if (file.type.startsWith('video/')) {
|
||||||
return await this.checkVideoNSFW(file);
|
return await this.checkVideoNSFW(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Erro ao verificar NSFW:', error);
|
console.error('Erro ao verificar NSFW:', error);
|
||||||
|
|
@ -159,75 +158,59 @@ class ContentModeration {
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkImageNSFW(file) {
|
async checkImageNSFW(file) {
|
||||||
if (!this.nsfwModel) return false;
|
if (!this.nsfwModel) await this.loadNSFWModel();
|
||||||
|
return new Promise((resolve) => {
|
||||||
try {
|
const img = new window.Image();
|
||||||
const img = await createImageBitmap(file);
|
img.onload = async () => {
|
||||||
const tensor = tf.browser.fromPixels(img)
|
const predictions = await this.nsfwModel.classify(img);
|
||||||
.resizeBilinear([224, 224])
|
const isNSFW = predictions.some(p =>
|
||||||
.expandDims()
|
(p.className === 'Porn' || p.className === 'Hentai' || p.className === 'Sexy') && p.probability > 0.7
|
||||||
.toFloat()
|
);
|
||||||
.div(255.0);
|
resolve(isNSFW);
|
||||||
|
};
|
||||||
const predictions = await this.nsfwModel.predict(tensor).data();
|
img.onerror = () => resolve(false);
|
||||||
tensor.dispose();
|
img.src = URL.createObjectURL(file);
|
||||||
|
});
|
||||||
// Verifica se o conteúdo é NSFW
|
|
||||||
const nsfwScore = predictions[1]; // Índice 1 é para conteúdo NSFW
|
|
||||||
return nsfwScore > 0.5; // Threshold de 50%
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Erro ao verificar imagem NSFW:', error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkVideoNSFW(file) {
|
async checkVideoNSFW(file) {
|
||||||
if (!this.nsfwModel) return false;
|
if (!this.nsfwModel) await this.loadNSFWModel();
|
||||||
|
// Extrai frames do vídeo e analisa cada um
|
||||||
try {
|
return new Promise((resolve) => {
|
||||||
const video = document.createElement('video');
|
const video = document.createElement('video');
|
||||||
|
video.preload = 'auto';
|
||||||
video.src = URL.createObjectURL(file);
|
video.src = URL.createObjectURL(file);
|
||||||
|
video.muted = true;
|
||||||
return new Promise((resolve) => {
|
video.currentTime = 0;
|
||||||
video.onloadeddata = async () => {
|
video.onloadeddata = async () => {
|
||||||
// Captura frames do vídeo para análise
|
const canvas = document.createElement('canvas');
|
||||||
const canvas = document.createElement('canvas');
|
canvas.width = video.videoWidth;
|
||||||
canvas.width = video.videoWidth;
|
canvas.height = video.videoHeight;
|
||||||
canvas.height = video.videoHeight;
|
const ctx = canvas.getContext('2d');
|
||||||
const ctx = canvas.getContext('2d');
|
let nsfwDetected = false;
|
||||||
|
let framesChecked = 0;
|
||||||
// Analisa alguns frames do vídeo
|
const totalFrames = 5;
|
||||||
const frameCount = 5;
|
const duration = video.duration;
|
||||||
const interval = video.duration / frameCount;
|
for (let i = 1; i <= totalFrames; i++) {
|
||||||
let nsfwFrames = 0;
|
video.currentTime = (duration * i) / (totalFrames + 1);
|
||||||
|
await new Promise(r => video.onseeked = r);
|
||||||
for (let i = 0; i < frameCount; i++) {
|
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
||||||
video.currentTime = i * interval;
|
const img = new window.Image();
|
||||||
await new Promise(r => video.onseeked = r);
|
img.src = canvas.toDataURL();
|
||||||
|
await new Promise(r => img.onload = r);
|
||||||
ctx.drawImage(video, 0, 0);
|
const predictions = await this.nsfwModel.classify(img);
|
||||||
const tensor = tf.browser.fromPixels(canvas)
|
if (predictions.some(p =>
|
||||||
.resizeBilinear([224, 224])
|
(p.className === 'Porn' || p.className === 'Hentai' || p.className === 'Sexy') && p.probability > 0.7
|
||||||
.expandDims()
|
)) {
|
||||||
.toFloat()
|
nsfwDetected = true;
|
||||||
.div(255.0);
|
break;
|
||||||
|
|
||||||
const predictions = await this.nsfwModel.predict(tensor).data();
|
|
||||||
tensor.dispose();
|
|
||||||
|
|
||||||
if (predictions[1] > 0.5) {
|
|
||||||
nsfwFrames++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
framesChecked++;
|
||||||
URL.revokeObjectURL(video.src);
|
}
|
||||||
resolve(nsfwFrames > frameCount / 2); // Se mais da metade dos frames for NSFW
|
resolve(nsfwDetected);
|
||||||
};
|
};
|
||||||
});
|
video.onerror = () => resolve(false);
|
||||||
} catch (error) {
|
});
|
||||||
console.error('Erro ao verificar vídeo NSFW:', error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verifica se uma URL contém caracteres cirílicos
|
// Verifica se uma URL contém caracteres cirílicos
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue