package handlers import ( "context" "net/http" "strconv" "tailly_back_v2/internal/domain" "tailly_back_v2/internal/service" "tailly_back_v2/internal/ws" "github.com/go-chi/chi/v5" "github.com/gorilla/websocket" ) type ChatHandler struct { chatService service.ChatService hub *ws.ChatHub } var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true // В production заменить на проверку origin }, } func (h *ChatHandler) WebSocketConnection(w http.ResponseWriter, r *http.Request) { userID, err := strconv.Atoi(chi.URLParam(r, "userID")) if err != nil { http.Error(w, "Invalid user ID", http.StatusBadRequest) return } conn, err := upgrader.Upgrade(w, r, nil) if err != nil { http.Error(w, "Could not open websocket connection", http.StatusBadRequest) return } client := &ws.Client{ UserID: userID, Send: make(chan *domain.Message, 256), } h.hub.Register(client) // Горутина для чтения сообщений go h.readPump(conn, client) // Горутина для записи сообщений go h.writePump(conn, client) } func (h *ChatHandler) readPump(conn *websocket.Conn, client *ws.Client) { defer func() { h.hub.Unregister(client) conn.Close() }() for { var msg struct { ChatID int `json:"chatId"` Content string `json:"content"` } if err := conn.ReadJSON(&msg); err != nil { break } // Отправляем сообщение через сервис message, err := h.chatService.SendMessage( context.Background(), client.UserID, msg.ChatID, msg.Content, ) if err != nil { // Обработка ошибки (можно отправить ошибку обратно клиенту) continue } // Отправляем сообщение получателю через хаб h.hub.Broadcast(message) } } func (h *ChatHandler) writePump(conn *websocket.Conn, client *ws.Client) { defer conn.Close() for { message, ok := <-client.Send if !ok { conn.WriteMessage(websocket.CloseMessage, []byte{}) return } if err := conn.WriteJSON(message); err != nil { return } } }