const express = require('express'); const path = require('node:path'); const { WebSocketServer, WebSocket } = require('ws'); const http = require('node:http'); require('dotenv').config(); const app = express(); const server = http.createServer(app); const wss = new WebSocketServer({ server }); app.use(express.static(path.join(__dirname, '../build'))); const GEMINI_API_KEY = process.env.GEMINI_API_KEY; if (!GEMINI_API_KEY) { console.error('GEMINI_API_KEY environment variable is not set!'); process.exit(1); } // کلمات ممنوعه (حساس به حروف بزرگ/کوچک با استفاده از Regex) const forbiddenWordsRegex = [/گوگل/gi, /جمینای/gi, /google/gi, /gemini/gi]; // متن جایگزین ثابت const replacementText = "من چت بات صوتی برنامه هوش مصنوعی پیشرفته هستم."; const createGeminiWebSocket = (clientWs, initialSetupData) => { const geminiWs = new WebSocket( `wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1alpha.GenerativeService.BidiGenerateContent?key=${GEMINI_API_KEY}` ); geminiWs.on('open', () => { console.log('Server: Connected to Gemini API'); if (initialSetupData) { console.log('Server: Sending initial setup to Gemini:', initialSetupData); geminiWs.send(JSON.stringify(initialSetupData)); } }); geminiWs.on('message', (data) => { let finalMessageString; try { const messageString = data.toString(); let messageObject = JSON.parse(messageString); let modified = false; // --- 👇 منطق بررسی و جایگزینی متن 👇 --- if (messageObject.serverContent && messageObject.serverContent.modelTurn && messageObject.serverContent.modelTurn.parts) { messageObject.serverContent.modelTurn.parts = messageObject.serverContent.modelTurn.parts.map(part => { if (part.text) { // بررسی وجود کلمات ممنوعه در متن این پارت const containsForbidden = forbiddenWordsRegex.some(regex => { regex.lastIndex = 0; // ریست کردن ایندکس برای تست مجدد return regex.test(part.text); }); if (containsForbidden) { console.log(`Server: Detected forbidden word in part: "${part.text}". Replacing with fixed response.`); // کل متن این پارت را با متن جایگزین عوض می‌کنیم part.text = replacementText; modified = true; } } return part; }); } // --- 👆 پایان منطق بررسی 👆 --- // اگر تغییری ایجاد شده، آبجکت را دوباره به رشته تبدیل کن finalMessageString = modified ? JSON.stringify(messageObject) : messageString; if (modified) { console.log('Server: Sending modified message to client:', finalMessageString); } else { // console.log('Server: Forwarding original message from Gemini:', finalMessageString); // برای دیباگ می‌توانید این لاگ را فعال کنید } } catch (error) { console.error('Server: Error processing/modifying Gemini message:', error); // در صورت خطا، سعی می‌کنیم پیام اصلی را بفرستیم finalMessageString = data.toString(); console.log('Server: Forwarding original message due to error.'); } // ارسال پیام نهایی (اصلی یا ویرایش شده) به کلاینت try { const blob = Buffer.from(finalMessageString); clientWs.send(blob, { binary: true }); } catch (sendError) { console.error('Server: Error sending message to client:', sendError); } }); geminiWs.on('error', (error) => { console.error('Gemini WebSocket error:', error); if (clientWs.readyState === WebSocket.OPEN) clientWs.close(); }); geminiWs.on('close', (code, reason) => { console.log('Gemini WebSocket closed:', code, reason.toString()); if (clientWs.readyState === WebSocket.OPEN) clientWs.close(); }); return geminiWs; }; wss.on('connection', (ws) => { console.log('Client connected'); let geminiWs = null; ws.on('message', async (message) => { try { const data = JSON.parse(message); // console.log('Server: Received from client:', data); // برای دیباگ if (data.setup) { console.log('Server: Received setup from client:', data.setup); if (geminiWs) geminiWs.close(); geminiWs = createGeminiWebSocket(ws, data); return; } if (geminiWs && geminiWs.readyState === WebSocket.OPEN) { // console.log('Server: Forwarding client message to Gemini:', data); // برای دیباگ geminiWs.send(JSON.stringify(data)); } else { console.warn('Server: Gemini connection not ready or non-existent. Message from client ignored.'); } } catch (error) { console.error('Server: Error processing message from client:', error); } }); ws.on('close', () => { console.log('Client disconnected'); if (geminiWs) geminiWs.close(); }); ws.on('error', (error) => { console.error('Client WebSocket error:', error); if (geminiWs) geminiWs.close(); }); }); app.get('*', (req, res) => { res.sendFile(path.join(__dirname, '../build', 'index.html')); }); const PORT = process.env.PORT || 3001; server.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });