chat.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. from fastapi import APIRouter, WebSocket, WebSocketDisconnect, Depends, Query
  2. from services.chat_manager import manager
  3. import db
  4. import auth_utils
  5. import datetime
  6. router = APIRouter(tags=["chat"])
  7. @router.get("/orders/{order_id}/messages")
  8. async def get_order_messages(order_id: int, token: str = Depends(auth_utils.oauth2_scheme)):
  9. payload = auth_utils.decode_token(token)
  10. if not payload: raise HTTPException(status_code=401, detail="Invalid token")
  11. role = payload.get("role")
  12. user_id = payload.get("id")
  13. order = db.execute_query("SELECT user_id FROM orders WHERE id = %s", (order_id,))
  14. if not order: raise HTTPException(status_code=404, detail="Order not found")
  15. if role != 'admin' and order[0]['user_id'] != user_id: raise HTTPException(status_code=403, detail="Not authorized")
  16. messages = db.execute_query("SELECT id, is_from_admin, message, created_at FROM order_messages WHERE order_id = %s ORDER BY created_at ASC", (order_id,))
  17. for msg in messages:
  18. if msg.get('created_at'): msg['created_at'] = msg['created_at'].isoformat()
  19. return messages
  20. @router.post("/orders/{order_id}/messages")
  21. async def post_order_message(order_id: int, request: Request, token: str = Depends(auth_utils.oauth2_scheme)):
  22. payload = auth_utils.decode_token(token)
  23. if not payload: raise HTTPException(status_code=401, detail="Invalid token")
  24. data = await request.json()
  25. message = data.get("message", "").strip()
  26. if not message: raise HTTPException(status_code=400, detail="Empty message")
  27. role = payload.get("role")
  28. user_id = payload.get("id")
  29. is_admin = (role == 'admin')
  30. order = db.execute_query("SELECT user_id FROM orders WHERE id = %s", (order_id,))
  31. if not order: raise HTTPException(status_code=404, detail="Order not found")
  32. if not is_admin and order[0]['user_id'] != user_id: raise HTTPException(status_code=403, detail="Not authorized")
  33. query = "INSERT INTO order_messages (order_id, user_id, is_from_admin, message) VALUES (%s, %s, %s, %s)"
  34. msg_id = db.execute_commit(query, (order_id, user_id, is_admin, message))
  35. now = datetime.datetime.utcnow().isoformat()
  36. await manager.broadcast_to_order(order_id, {"id": msg_id, "is_from_admin": is_admin, "message": message, "created_at": now})
  37. return {"id": msg_id, "status": "sent"}
  38. @router.websocket("/ws/chat/{order_id}")
  39. async def ws_chat(websocket: WebSocket, order_id: int, token: str = Query(...)):
  40. payload = auth_utils.decode_token(token)
  41. if not payload:
  42. await websocket.close(code=4001)
  43. return
  44. role = payload.get("role")
  45. user_id = payload.get("id")
  46. order = db.execute_query("SELECT user_id FROM orders WHERE id = %s", (order_id,))
  47. if not order:
  48. await websocket.close(code=4004)
  49. return
  50. if role != 'admin' and order[0]['user_id'] != user_id:
  51. await websocket.close(code=4003)
  52. return
  53. await manager.connect(websocket, order_id)
  54. try:
  55. while True:
  56. await websocket.receive_text()
  57. except WebSocketDisconnect:
  58. manager.disconnect(websocket, order_id)