File size: 11,293 Bytes
b44f9a1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | # 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"<h1>خطا در بارگذاری نرمافزار صوتی پرو: {e}</h1>", status_code=500, headers=PERMISSION_HEADERS)
@router.get("/sotifree")
@router.get("/sotifree/")
async def serve_soti_free_page():
async with httpx.AsyncClient(verify=False) as client:
try:
resp = await client.get(f"{SOTI_FREE_HTTP}/", timeout=15.0)
return HTMLResponse(content=resp.text, status_code=resp.status_code, headers=PERMISSION_HEADERS)
except Exception as e:
return HTMLResponse(f"<h1>خطا در بارگذاری نرمافزار صوتی رایگان: {e}</h1>", status_code=500, headers=PERMISSION_HEADERS)
@router.get("/static/{file_path:path}")
async def proxy_static_files(request: Request, file_path: str):
"""
انتقال زنده استاتیک ریاکت با تفکیک هوشمند مسیرها بین پرو، رایگان و دیسک رانفلر
"""
if file_path.startswith("images/"):
# 🟢 بهینهسازی بسیار مهم: لود مستقیم تصویر و ویدیوهای گالریها از هارد دیسک داخلی رانفلر بدون تاخیر شبکه
filename = file_path.replace("images/", "")
local_path = os.path.join("static/images", filename)
if os.path.exists(local_path):
media_type = "application/octet-stream"
if filename.endswith(".mp4"): media_type = "video/mp4"
elif filename.endswith(".png"): media_type = "image/png"
elif filename.endswith(".webp"): media_type = "image/webp"
elif filename.endswith(".jpg") or filename.endswith(".jpeg"): media_type = "image/jpeg"
elif filename.endswith(".txt"): media_type = "text/plain"
return FileResponse(local_path, media_type=media_type, headers=PERMISSION_HEADERS)
return HTMLResponse("File not found", status_code=404)
else:
# تشخیص هوشمند مبدا فایل استاتیک ریاکت صوتی (پرو یا رایگان) بر اساس Referer
target_http, _ = get_target_urls(request)
url = f"{target_http}/static/{file_path}"
async def stream_file():
async with httpx.AsyncClient(verify=False) as client:
try:
async with client.stream("GET", url, timeout=20.0) as resp:
async for chunk in resp.aiter_bytes():
yield chunk
except Exception:
yield b""
media_type = "application/octet-stream"
if file_path.endswith(".js"):
media_type = "application/javascript"
elif file_path.endswith(".css"):
media_type = "text/css"
elif file_path.endswith(".png"):
media_type = "image/png"
elif file_path.endswith(".jpg") or file_path.endswith(".jpeg"):
media_type = "image/jpeg"
elif file_path.endswith(".svg"):
media_type = "image/svg+xml"
elif file_path.endswith(".mp4"):
media_type = "video/mp4"
elif file_path.endswith(".webp"):
media_type = "image/webp"
return StreamingResponse(stream_file(), media_type=media_type, headers=PERMISSION_HEADERS)
@router.get("/manifest.json")
async def proxy_manifest(request: Request):
target_http, _ = get_target_urls(request)
async with httpx.AsyncClient(verify=False) as client:
try:
resp = await client.get(f"{target_http}/manifest.json", timeout=10.0)
return JSONResponse(content=resp.json(), status_code=resp.status_code, headers=PERMISSION_HEADERS)
except Exception:
return JSONResponse(content={}, status_code=404, headers=PERMISSION_HEADERS)
@router.get("/favicon.ico")
async def proxy_favicon(request: Request):
target_http, _ = get_target_urls(request)
async def stream_fav():
async with httpx.AsyncClient(verify=False) as client:
try:
async with client.stream("GET", f"{target_http}/favicon.ico", timeout=10.0) as r:
async for chunk in r.aiter_bytes():
yield chunk
except Exception:
yield b""
return StreamingResponse(stream_fav(), media_type="image/x-icon", headers=PERMISSION_HEADERS)
@router.get("/logo192.png")
async def proxy_logo192(request: Request):
target_http, _ = get_target_urls(request)
async def stream_logo():
async with httpx.AsyncClient(verify=False) as client:
try:
async with client.stream("GET", f"{target_http}/logo192.png", timeout=10.0) as r:
async for chunk in r.aiter_bytes():
yield chunk
except Exception:
yield b""
return StreamingResponse(stream_logo(), media_type="image/png", headers=PERMISSION_HEADERS)
@router.get("/logo512.png")
async def proxy_logo512(request: Request):
target_http, _ = get_target_urls(request)
async def stream_logo():
async with httpx.AsyncClient(verify=False) as client:
try:
async with client.stream("GET", f"{target_http}/logo512.png", timeout=10.0) as r:
async for chunk in r.aiter_bytes():
yield chunk
except Exception:
yield b""
return StreamingResponse(stream_logo(), media_type="image/png", headers=PERMISSION_HEADERS) |