Update proxy-server.js
This commit is contained in:
parent
0826cec6d1
commit
472be801d9
|
@ -1,210 +1,137 @@
|
|||
const express = require('express');
|
||||
const { createProxyMiddleware } = require('http-proxy-middleware');
|
||||
const bodyParser = require('body-parser');
|
||||
const multer = require('multer');
|
||||
const tf = require('@tensorflow/tfjs-node');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
import express from 'express';
|
||||
import { createProxyMiddleware } from 'http-proxy-middleware';
|
||||
import multer from 'multer';
|
||||
import bodyParser from 'body-parser';
|
||||
import * as tf from '@tensorflow/tfjs-node';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
class ProxyServer {
|
||||
constructor() {
|
||||
this.app = express();
|
||||
this.port = process.env.PROXY_PORT || 3001;
|
||||
this.nsfwModel = null;
|
||||
this.setupMiddleware();
|
||||
this.setupRoutes();
|
||||
this.initNSFWModel();
|
||||
const app = express();
|
||||
const upload = multer({ storage: multer.memoryStorage() });
|
||||
|
||||
// Configurações do modelo NSFW
|
||||
const NSFW_THRESHOLD = 0.3; // Reduzido para ser mais sensível
|
||||
const NSFW_CATEGORIES = ['porn', 'sexy', 'hentai', 'drawings', 'neutral'];
|
||||
|
||||
// Lista expandida de palavras-chave bloqueadas
|
||||
const BLOCKED_KEYWORDS = [
|
||||
'porn', 'sex', 'xxx', 'adult', 'nude', 'naked', 'nsfw', '18+',
|
||||
'pornografia', 'sexo', 'adulto', 'nu', 'nua', 'nudez', 'erótico',
|
||||
'erotico', 'sensual', 'proibido', 'proibida', 'privado', 'privada',
|
||||
'intimo', 'íntimo', 'intima', 'íntima', 'mulher', 'homem', 'corpo',
|
||||
'peito', 'bunda', 'pernas', 'lingerie', 'biquini', 'calcinha', 'cueca'
|
||||
];
|
||||
|
||||
// Lista expandida de domínios bloqueados
|
||||
const BLOCKED_DOMAINS = [
|
||||
'pornhub.com', 'xvideos.com', 'xnxx.com', 'redtube.com',
|
||||
'youporn.com', 'xhamster.com', 'brazzers.com', 'onlyfans.com',
|
||||
'chaturbate.com', 'myfreecams.com', 'stripchat.com', 'bongacams.com',
|
||||
'cam4.com', 'streamate.com', 'adultfriendfinder.com', 'ashleymadison.com',
|
||||
'fling.com', 'adultmatchmaker.com', 'adultdating.com', 'adultchat.com'
|
||||
];
|
||||
|
||||
// Carrega o modelo NSFW
|
||||
let model;
|
||||
async function loadModel() {
|
||||
try {
|
||||
model = await tf.loadLayersModel('file://./model/model.json');
|
||||
console.log('Modelo NSFW carregado com sucesso');
|
||||
} catch (error) {
|
||||
console.error('Erro ao carregar modelo NSFW:', error);
|
||||
}
|
||||
}
|
||||
loadModel();
|
||||
|
||||
async initNSFWModel() {
|
||||
try {
|
||||
// Carrega o modelo NSFW do TensorFlow.js
|
||||
this.nsfwModel = await tf.loadGraphModel('https://d1zv2aa70wpiur.cloudfront.net/tfjs_models/tfjs_nsfw_mobilenet/model.json');
|
||||
console.log('Modelo NSFW carregado com sucesso');
|
||||
} catch (error) {
|
||||
console.error('Erro ao carregar modelo NSFW:', error);
|
||||
}
|
||||
}
|
||||
|
||||
setupMiddleware() {
|
||||
// Configuração do multer para upload de arquivos
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
const uploadDir = path.join(__dirname, '../uploads');
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true });
|
||||
}
|
||||
cb(null, uploadDir);
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, Date.now() + '-' + file.originalname);
|
||||
// Função melhorada para verificar conteúdo NSFW
|
||||
async function checkNSFW(file) {
|
||||
try {
|
||||
const image = await tf.node.decodeImage(file.buffer);
|
||||
const predictions = await model.classify(image);
|
||||
|
||||
// Verifica todas as categorias NSFW
|
||||
const nsfwScore = predictions.reduce((score, pred) => {
|
||||
if (NSFW_CATEGORIES.includes(pred.className)) {
|
||||
return score + pred.probability;
|
||||
}
|
||||
});
|
||||
return score;
|
||||
}, 0);
|
||||
|
||||
this.upload = multer({ storage: storage });
|
||||
|
||||
// Middleware para análise de conteúdo
|
||||
this.app.use(bodyParser.json());
|
||||
this.app.use(bodyParser.urlencoded({ extended: true }));
|
||||
}
|
||||
|
||||
setupRoutes() {
|
||||
// Rota para verificar conteúdo
|
||||
this.app.post('/check-content', this.upload.single('file'), async (req, res) => {
|
||||
try {
|
||||
if (!req.file) {
|
||||
return res.status(400).json({ error: 'Nenhum arquivo enviado' });
|
||||
}
|
||||
|
||||
const result = await this.checkContent(req.file);
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
console.error('Erro ao verificar conteúdo:', error);
|
||||
res.status(500).json({ error: 'Erro ao processar arquivo' });
|
||||
}
|
||||
});
|
||||
|
||||
// Rota para verificar URL
|
||||
this.app.post('/check-url', async (req, res) => {
|
||||
try {
|
||||
const { url } = req.body;
|
||||
if (!url) {
|
||||
return res.status(400).json({ error: 'URL não fornecida' });
|
||||
}
|
||||
|
||||
const result = await this.checkUrl(url);
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
console.error('Erro ao verificar URL:', error);
|
||||
res.status(500).json({ error: 'Erro ao processar URL' });
|
||||
}
|
||||
});
|
||||
|
||||
// Configuração do proxy
|
||||
this.app.use('/', createProxyMiddleware({
|
||||
target: 'http://localhost:3000',
|
||||
changeOrigin: true,
|
||||
onProxyReq: async (proxyReq, req, res) => {
|
||||
// Verifica URLs suspeitas
|
||||
if (req.url.includes('http')) {
|
||||
const isBlocked = await this.checkUrl(req.url);
|
||||
if (isBlocked) {
|
||||
res.status(403).json({
|
||||
error: 'Conteúdo bloqueado',
|
||||
reason: 'URL suspeita detectada'
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
async checkContent(file) {
|
||||
// Verifica o nome do arquivo
|
||||
const fileName = file.originalname.toLowerCase();
|
||||
const blockedWords = [
|
||||
'porn', 'sex', 'nude', 'nudes', 'onlyfans', 'leaks', 'hentai',
|
||||
'🔞', '🍆', '🍑', '🥒', '🥵', 'PORN', 'Pornografia'
|
||||
];
|
||||
|
||||
if (blockedWords.some(word => fileName.includes(word))) {
|
||||
return {
|
||||
blocked: true,
|
||||
reason: 'Nome do arquivo contém termos impróprios'
|
||||
};
|
||||
}
|
||||
|
||||
// Verifica o conteúdo do arquivo
|
||||
if (file.mimetype.startsWith('image/')) {
|
||||
return await this.checkImageContent(file.path);
|
||||
} else if (file.mimetype.startsWith('video/')) {
|
||||
return await this.checkVideoContent(file.path);
|
||||
}
|
||||
|
||||
return { blocked: false };
|
||||
}
|
||||
|
||||
async checkImageContent(filePath) {
|
||||
if (!this.nsfwModel) return { blocked: false };
|
||||
|
||||
try {
|
||||
const imageBuffer = fs.readFileSync(filePath);
|
||||
const tfImage = tf.node.decodeImage(imageBuffer);
|
||||
const resized = tf.image.resizeBilinear(tfImage, [224, 224]);
|
||||
const expanded = resized.expandDims(0);
|
||||
const normalized = expanded.div(255.0);
|
||||
|
||||
const predictions = await this.nsfwModel.predict(normalized).data();
|
||||
|
||||
tfImage.dispose();
|
||||
resized.dispose();
|
||||
expanded.dispose();
|
||||
normalized.dispose();
|
||||
|
||||
const nsfwScore = predictions[1];
|
||||
return {
|
||||
blocked: nsfwScore > 0.5,
|
||||
reason: nsfwScore > 0.5 ? 'Conteúdo impróprio detectado' : null,
|
||||
score: nsfwScore
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Erro ao verificar imagem:', error);
|
||||
return { blocked: false };
|
||||
}
|
||||
}
|
||||
|
||||
async checkVideoContent(filePath) {
|
||||
if (!this.nsfwModel) return { blocked: false };
|
||||
|
||||
try {
|
||||
// Aqui você pode implementar a verificação de frames do vídeo
|
||||
// Por enquanto, vamos apenas verificar o nome do arquivo
|
||||
return { blocked: false };
|
||||
} catch (error) {
|
||||
console.error('Erro ao verificar vídeo:', error);
|
||||
return { blocked: false };
|
||||
}
|
||||
}
|
||||
|
||||
async checkUrl(url) {
|
||||
const blockedDomains = [
|
||||
'pornhub.com', 'xvideos.com', 'xnxx.com', 'redtube.com',
|
||||
'onlyfans.com', 'xhamster.com', 'brazzers.com'
|
||||
];
|
||||
|
||||
const blockedKeywords = [
|
||||
'porn', 'sex', 'nude', 'nudes', 'onlyfans', 'leaks', 'hentai'
|
||||
];
|
||||
|
||||
// Verifica domínios bloqueados
|
||||
if (blockedDomains.some(domain => url.includes(domain))) {
|
||||
return {
|
||||
blocked: true,
|
||||
reason: 'Domínio bloqueado'
|
||||
};
|
||||
}
|
||||
|
||||
// Verifica palavras-chave bloqueadas
|
||||
if (blockedKeywords.some(keyword => url.toLowerCase().includes(keyword))) {
|
||||
return {
|
||||
blocked: true,
|
||||
reason: 'URL contém termos impróprios'
|
||||
};
|
||||
}
|
||||
|
||||
return { blocked: false };
|
||||
}
|
||||
|
||||
start() {
|
||||
this.app.listen(this.port, () => {
|
||||
console.log(`Servidor proxy rodando na porta ${this.port}`);
|
||||
});
|
||||
// Libera a memória
|
||||
image.dispose();
|
||||
|
||||
return nsfwScore > NSFW_THRESHOLD;
|
||||
} catch (error) {
|
||||
console.error('Erro ao verificar NSFW:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Inicia o servidor
|
||||
const proxyServer = new ProxyServer();
|
||||
proxyServer.start();
|
||||
// Função melhorada para verificar nome do arquivo
|
||||
function isBlockedFilename(filename) {
|
||||
const lowerFilename = filename.toLowerCase();
|
||||
return BLOCKED_KEYWORDS.some(keyword => lowerFilename.includes(keyword));
|
||||
}
|
||||
|
||||
module.exports = ProxyServer;
|
||||
// Função melhorada para verificar URL
|
||||
function isBlockedUrl(url) {
|
||||
try {
|
||||
const urlObj = new URL(url);
|
||||
return BLOCKED_DOMAINS.some(domain => urlObj.hostname.includes(domain));
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Middleware para verificar conteúdo
|
||||
app.use(bodyParser.json());
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
|
||||
// Rota para upload de arquivos
|
||||
app.post('/upload', upload.single('file'), async (req, res) => {
|
||||
try {
|
||||
if (!req.file) {
|
||||
return res.status(400).json({ error: '🚫 CONTEÚDO BLOQUEADO' });
|
||||
}
|
||||
|
||||
// Verifica o nome do arquivo
|
||||
if (isBlockedFilename(req.file.originalname)) {
|
||||
return res.status(403).json({ error: '🚫 CONTEÚDO BLOQUEADO' });
|
||||
}
|
||||
|
||||
// Verifica o conteúdo do arquivo
|
||||
const isNSFW = await checkNSFW(req.file);
|
||||
if (isNSFW) {
|
||||
return res.status(403).json({ error: '🚫 CONTEÚDO BLOQUEADO' });
|
||||
}
|
||||
|
||||
// Processa o arquivo normalmente
|
||||
res.json({ message: 'Arquivo processado com sucesso' });
|
||||
} catch (error) {
|
||||
console.error('Erro no upload:', error);
|
||||
res.status(500).json({ error: '🚫 CONTEÚDO BLOQUEADO' });
|
||||
}
|
||||
});
|
||||
|
||||
// Configuração do proxy
|
||||
const proxy = createProxyMiddleware({
|
||||
target: 'http://localhost:3000',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {
|
||||
'^/api': ''
|
||||
},
|
||||
onProxyReq: (proxyReq, req, res) => {
|
||||
// Verifica URLs bloqueadas
|
||||
if (isBlockedUrl(req.url)) {
|
||||
res.status(403).json({ error: '🚫 CONTEÚDO BLOQUEADO' });
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
app.use('/api', proxy);
|
||||
|
||||
const PORT = process.env.PORT || 3001;
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Servidor proxy rodando na porta ${PORT}`);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue