diff --git a/internal/http/graph/message_resolvers.go b/internal/http/graph/message_resolvers.go index 9953c60..f947076 100644 --- a/internal/http/graph/message_resolvers.go +++ b/internal/http/graph/message_resolvers.go @@ -159,17 +159,22 @@ func (r *mutationResolver) SendMessage(ctx context.Context, receiverID int, cont return nil, errors.New("не авторизован") } - // Проверяем, что не отправляем сообщение себе - if senderID == receiverID { - return nil, errors.New("cannot send message to yourself") - } - chat, err := r.Services.Chat.GetOrCreateChat(ctx, senderID, receiverID) if err != nil { return nil, fmt.Errorf("ошибка создания чата: %v", err) } - return r.Services.Chat.SendMessage(ctx, senderID, chat.ID, content) + message, err := r.Services.Chat.SendMessage(ctx, senderID, chat.ID, content) + if err != nil { + return nil, err + } + + // Рассылаем сообщение через WebSocket + if r.Services.ChatHub != nil { + r.Services.ChatHub.Broadcast(message) + } + + return message, nil } // MarkAsRead - помечает сообщение как прочитанное diff --git a/internal/http/handlers/chat.go b/internal/http/handlers/chat.go index 8fd2bbb..d397f9d 100644 --- a/internal/http/handlers/chat.go +++ b/internal/http/handlers/chat.go @@ -9,6 +9,7 @@ import ( "tailly_back_v2/internal/service" "tailly_back_v2/internal/ws" "tailly_back_v2/pkg/auth" + "time" "github.com/gorilla/websocket" ) @@ -105,13 +106,17 @@ func (h *ChatHandler) HandleWebSocket(w http.ResponseWriter, r *http.Request) { } func (h *ChatHandler) readPump(ctx context.Context, conn *websocket.Conn, client *ws.Client, userID int) { - defer func() { - h.hub.UnregisterClient(client) - conn.Close() - }() + ticker := time.NewTicker(30 * time.Second) + defer ticker.Stop() for { select { + case <-ticker.C: + // Отправляем ping + if err := conn.WriteJSON(map[string]string{"type": "ping"}); err != nil { + log.Printf("Ping error: %v", err) + return + } case <-ctx.Done(): return default: @@ -125,11 +130,15 @@ func (h *ChatHandler) readPump(ctx context.Context, conn *websocket.Conn, client if err := conn.ReadJSON(&msg); err != nil { if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) { - log.Printf("WebSocket read error: %v", err) + log.Printf("WebSocket error: %v", err) } return } + if msg.Type == "pong" { + continue + } + // Обработка ping/pong if msg.Type == "ping" { conn.WriteJSON(map[string]string{"type": "pong"}) diff --git a/internal/service/chat_service.go b/internal/service/chat_service.go index 0e1d4e7..03f9268 100644 --- a/internal/service/chat_service.go +++ b/internal/service/chat_service.go @@ -39,30 +39,38 @@ func (s *chatService) SendMessage(ctx context.Context, senderID, chatID int, con return nil, err } + // Проверяем, что отправитель является участником чата if senderID != chat.User1ID && senderID != chat.User2ID { return nil, errors.New("user is not a participant of this chat") } + // Определяем получателя receiverID := chat.User1ID if senderID == chat.User1ID { receiverID = chat.User2ID } + // Создаем сообщение message := &domain.Message{ ChatID: chatID, SenderID: senderID, - ReceiverID: receiverID, + ReceiverID: receiverID, // Гарантируем что receiverID всегда установлен Content: content, Status: "sent", CreatedAt: time.Now(), } + // Сохраняем в БД if err := s.chatRepo.SaveMessage(ctx, message); err != nil { return nil, err } - // Отправляем сообщение через WebSocket + // Отправляем через WebSocket только один раз if s.hub != nil { + // Добавляем проверку перед рассылкой + if message.ReceiverID == 0 { + return nil, errors.New("receiver ID is required") + } s.hub.Broadcast(message) } diff --git a/internal/ws/hub.go b/internal/ws/hub.go index 2eb35ed..b761c52 100644 --- a/internal/ws/hub.go +++ b/internal/ws/hub.go @@ -1,6 +1,7 @@ package ws import ( + "log" "sync" "tailly_back_v2/internal/domain" ) @@ -36,6 +37,16 @@ func (h *Hub) UnregisterClient(client *Client) { } func (h *Hub) Broadcast(message *domain.Message) { + if message == nil || message.SenderID == 0 { + log.Println("Attempt to broadcast invalid message") + return + } + + if message.ReceiverID == 0 { + log.Printf("Message %d has no receiver", message.ID) + return + } + h.broadcast <- message }