|
@@ -8,6 +8,7 @@ import os
|
|
|
import auth_utils
|
|
import auth_utils
|
|
|
import session_utils
|
|
import session_utils
|
|
|
from services.global_manager import global_manager
|
|
from services.global_manager import global_manager
|
|
|
|
|
+from services.chat_manager import manager
|
|
|
|
|
|
|
|
import locales
|
|
import locales
|
|
|
import config
|
|
import config
|
|
@@ -74,8 +75,7 @@ app.include_router(blog.router)
|
|
|
app.include_router(admin.router)
|
|
app.include_router(admin.router)
|
|
|
|
|
|
|
|
# WebSocket Global Handler (Centralized to handle various proxy prefixes)
|
|
# WebSocket Global Handler (Centralized to handle various proxy prefixes)
|
|
|
-@app.websocket("/ws/auth/ws/global")
|
|
|
|
|
-@app.websocket("/auth/ws/global")
|
|
|
|
|
|
|
+@app.websocket("/global")
|
|
|
async def ws_global(websocket: WebSocket, token: str = Query(...)):
|
|
async def ws_global(websocket: WebSocket, token: str = Query(...)):
|
|
|
print(f"DEBUG: WS Connection attempt with token: {token[:10]}...")
|
|
print(f"DEBUG: WS Connection attempt with token: {token[:10]}...")
|
|
|
payload = auth_utils.decode_token(token)
|
|
payload = auth_utils.decode_token(token)
|
|
@@ -112,6 +112,53 @@ async def ws_global(websocket: WebSocket, token: str = Query(...)):
|
|
|
print(f"DEBUG: WS Error: {e}")
|
|
print(f"DEBUG: WS Error: {e}")
|
|
|
global_manager.disconnect(websocket, user_id)
|
|
global_manager.disconnect(websocket, user_id)
|
|
|
|
|
|
|
|
|
|
+@app.websocket("/chat")
|
|
|
|
|
+async def ws_chat(websocket: WebSocket, token: str = Query(...), order_id: int = Query(...)):
|
|
|
|
|
+ print(f"DEBUG: Chat WS attempt: order_id={order_id}")
|
|
|
|
|
+ payload = auth_utils.decode_token(token)
|
|
|
|
|
+ if not payload:
|
|
|
|
|
+ await websocket.close(code=4001)
|
|
|
|
|
+ return
|
|
|
|
|
+ role = payload.get("role")
|
|
|
|
|
+ user_id = payload.get("id")
|
|
|
|
|
+ if role != 'admin':
|
|
|
|
|
+ user_info = db.execute_query("SELECT can_chat FROM users WHERE id = %s", (user_id,))
|
|
|
|
|
+ if not user_info or not user_info[0]['can_chat']:
|
|
|
|
|
+ await websocket.close(code=4003)
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
|
|
+ order = db.execute_query("SELECT user_id FROM orders WHERE id = %s", (order_id,))
|
|
|
|
|
+ if not order:
|
|
|
|
|
+ await websocket.close(code=4004)
|
|
|
|
|
+ return
|
|
|
|
|
+ if role != 'admin' and order[0]['user_id'] != user_id:
|
|
|
|
|
+ await websocket.close(code=4003)
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
|
|
+ print(f"DEBUG: Chat WS connected: order_id={order_id}, user_id={user_id}")
|
|
|
|
|
+ await manager.connect(websocket, order_id, role)
|
|
|
|
|
+ try:
|
|
|
|
|
+ while True:
|
|
|
|
|
+ data = await websocket.receive_text()
|
|
|
|
|
+ if data == "typing":
|
|
|
|
|
+ await manager.broadcast_to_order(order_id, {"type": "typing", "is_admin": role == 'admin'})
|
|
|
|
|
+ elif data == "stop_typing":
|
|
|
|
|
+ await manager.broadcast_to_order(order_id, {"type": "stop_typing", "is_admin": role == 'admin'})
|
|
|
|
|
+ elif data == "read":
|
|
|
|
|
+ if role == 'admin':
|
|
|
|
|
+ db.execute_commit("UPDATE order_messages SET is_read = TRUE WHERE order_id = %s AND is_from_admin = FALSE AND is_read = FALSE", (order_id,))
|
|
|
|
|
+ await global_manager.notify_admins()
|
|
|
|
|
+ await global_manager.notify_order_read(order_id)
|
|
|
|
|
+ else:
|
|
|
|
|
+ db.execute_commit("UPDATE order_messages SET is_read = TRUE WHERE order_id = %s AND is_from_admin = TRUE AND is_read = FALSE", (order_id,))
|
|
|
|
|
+ await global_manager.notify_user(user_id)
|
|
|
|
|
+ except WebSocketDisconnect:
|
|
|
|
|
+ print(f"DEBUG: Chat WS disconnected: order_id={order_id}")
|
|
|
|
|
+ manager.disconnect(websocket, order_id)
|
|
|
|
|
+ except Exception as e:
|
|
|
|
|
+ print(f"DEBUG: Chat WS error: {e}")
|
|
|
|
|
+ manager.disconnect(websocket, order_id)
|
|
|
|
|
+
|
|
|
# Mount Static Files
|
|
# Mount Static Files
|
|
|
if not os.path.exists("uploads"):
|
|
if not os.path.exists("uploads"):
|
|
|
os.makedirs("uploads")
|
|
os.makedirs("uploads")
|