// bridge.js — پل ارتباطی افزونه با سرور لوکال پایتون (MVP) // این فایل داخل service worker اجرا می‌شود (importScripts از login.js). // content script هر caption را با پیام {type:"TRANSCRIPT_UPDATE"} می‌فرستد، // و این‌جا روی WebSocket به سرور پایتون (ws://127.0.0.1:8765) forward می‌شود. // // چرا از service worker و نه content script؟ چون content script تابعِ CSP سختگیر // google meet است و connect-src اتصال ws را بلاک می‌کند؛ service worker این محدودیت را ندارد. const BRIDGE_URL = "ws://127.0.0.1:8765"; let ws = null; const pending = []; // پیام‌هایی که موقع وصل‌نبودن سوکت صف می‌شوند (MVP: کوتاه) function connect() { if (ws && (ws.readyState === WebSocket.OPEN || ws.readyState === WebSocket.CONNECTING)) { return; } ws = new WebSocket(BRIDGE_URL); ws.onopen = () => { console.log("[bridge] connected to", BRIDGE_URL); while (pending.length && ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify(pending.shift())); } }; ws.onmessage = (event) => { // پاسخ سرور پایتون (ACK / PONG) — فعلاً فقط لاگ console.log("[bridge] <-", event.data); }; ws.onclose = () => { console.log("[bridge] disconnected, retry in 3s"); ws = null; setTimeout(connect, 3000); }; ws.onerror = () => { try { ws && ws.close(); } catch (e) {} }; } function sendToBridge(payload) { connect(); if (ws && ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify(payload)); } else { pending.push(payload); if (pending.length > 500) pending.splice(0, pending.length - 500); } } // heartbeat: از Chrome 116+ تبادل پیامِ کمتر از ۳۰ ثانیه، service worker را زنده نگه می‌دارد setInterval(() => { if (ws && ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ type: "PING", ts: Date.now() })); } }, 20000); // دریافت caption از content script و forward به سرور پایتون chrome.runtime.onMessage.addListener((message) => { if (message && message.type === "TRANSCRIPT_UPDATE") { sendToBridge(message); } }); connect();