Spaces:
Sleeping
Sleeping
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}`); | |
}); |