# alphattspro-main/soti.py import os import asyncio import ssl from fastapi import APIRouter, WebSocket, WebSocketDisconnect, Request from fastapi.responses import HTMLResponse, JSONResponse, StreamingResponse, FileResponse import httpx import websockets router = APIRouter() # تعریف آدرسهای مربوط به هر دو اسپیس مستقل هوش مصنوعی صوتی SOTI_PRO_HTTP = "https://ezmarynoori-sotipro.hf.space" SOTI_PRO_WS = "wss://ezmarynoori-sotipro.hf.space/ws" SOTI_FREE_HTTP = "https://ezmarynoori-sotifree.hf.space" SOTI_FREE_WS = "wss://ezmarynoori-sotifree.hf.space/ws" # هدرهای امنیتی جهت اعطای رسمی دسترسی دوربین و میکروفون به مرورگر و وبویو موبایل PERMISSION_HEADERS = { "Permissions-Policy": "camera=*, microphone=*, geolocation=*, autoplay=*", "Feature-Policy": "camera *; microphone *; autoplay *", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, OPTIONS", "Access-Control-Allow-Headers": "*" } # غیرفعال کردن بررسی سختگیرانه SSL برای جلوگیری از خطای تایید گواهینامه در داکر رانفلر ssl_context = ssl.create_default_context() ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE def get_target_urls(request_or_ws) -> tuple[str, str]: """ مسیریابی هوشمند و پویا بر اساس هدر Referer مرورگر کاربر. اگر کاربر در صفحه sotifree باشد به سرور رایگان و در غیر این صورت به سرور پرو متصل میشود. """ referer = request_or_ws.headers.get("referer", "").lower() if "sotifree" in referer: return SOTI_FREE_HTTP, SOTI_FREE_WS else: return SOTI_PRO_HTTP, SOTI_PRO_WS @router.websocket("/ws") async def websocket_proxy(client_ws: WebSocket): """ پروکسی هوشمند وبسوکت با مسیریابی پویا بین پرو و رایگان بر اساس ارجاع دهنده (Referer) """ await client_ws.accept() # تشخیص خودکار مقصد بر اساس آدرس صفحهای که کاربر در آن قرار دارد target_http, target_ws = get_target_urls(client_ws) # هدرهای شبیهسازی شده برای عبور از سد امنیتی هاگینگفیس headers = { "Host": target_http.replace("https://", ""), "Origin": target_http, "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" } # تشخیص پویا و هوشمند نسخه کتابخانه websockets رانفلر جهت ارسال پارامتر صحیح دستتکانی ws_kwargs = {} try: ws_version = getattr(websockets, "__version__", "10.0") try: major_version = int(ws_version.split('.')[0]) except ValueError: major_version = 10 if major_version >= 14: ws_kwargs["additional_headers"] = headers else: ws_kwargs["extra_headers"] = headers except Exception: ws_kwargs["extra_headers"] = headers try: # اتصال امن به وبسوکت هدف با غیرفعال کردن چک کردن SSL جهت تضمین پایداری ارتباط async with websockets.connect( target_ws, ssl=ssl_context, **ws_kwargs ) as server_ws: async def client_to_server(): try: while True: data = await client_ws.receive() if "text" in data and data["text"] is not None: await server_ws.send(data["text"]) elif "bytes" in data and data["bytes"] is not None: await server_ws.send(data["bytes"]) except Exception: pass async def server_to_client(): try: async for message in server_ws: if isinstance(message, str): await client_ws.send_text(message) else: await client_ws.send_bytes(message) except Exception: pass await asyncio.gather(client_to_server(), server_to_client()) except WebSocketDisconnect: pass except Exception as e: print(f"Soti WS Proxy Error: {e}") finally: try: await client_ws.close() except: pass @router.get("/api/instructions") async def proxy_instructions(request: Request): """ دریافت هوشمند و پروکسی دستورالعملهای شخصیتها بر اساس نسخه کاربر (پرو یا رایگان) """ target_http, _ = get_target_urls(request) async with httpx.AsyncClient(verify=False) as client: try: resp = await client.get(f"{target_http}/api/instructions", timeout=10.0) return JSONResponse(content=resp.json(), status_code=resp.status_code, headers=PERMISSION_HEADERS) except Exception as e: return JSONResponse(content={"error": str(e)}, status_code=500, headers=PERMISSION_HEADERS) # --- صفحات اصلی هردو نسخه --- @router.get("/soti") @router.get("/soti/") async def serve_soti_pro_page(): async with httpx.AsyncClient(verify=False) as client: try: resp = await client.get(f"{SOTI_PRO_HTTP}/", timeout=15.0) return HTMLResponse(content=resp.text, status_code=resp.status_code, headers=PERMISSION_HEADERS) except Exception as e: return HTMLResponse(f"