tailly_back_v2/internal/service/chat_service.go
madipo2611 6ad760a85b
All checks were successful
continuous-integration/drone/push Build is passing
v0.0.16 Исправление работы мессенджера
2025-08-09 13:30:49 +03:00

133 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"context"
"errors"
"tailly_back_v2/internal/domain"
"tailly_back_v2/internal/repository"
"tailly_back_v2/internal/ws"
"time"
)
type ChatService interface {
SendMessage(ctx context.Context, senderID, chatID int, content string) (*domain.Message, error)
GetChatMessages(ctx context.Context, chatID, userID int, limit, offset int) ([]*domain.Message, error)
MarkAsRead(ctx context.Context, messageID int) error
DeleteMessage(ctx context.Context, messageID, userID int) error
GetUserChats(ctx context.Context, userID int) ([]*domain.Chat, error)
GetOrCreateChat(ctx context.Context, user1ID, user2ID int) (*domain.Chat, error)
GetUnreadCount(ctx context.Context, chatID, userID int) (int, error)
}
type chatService struct {
chatRepo repository.ChatRepository
userRepo repository.UserRepository
hub *ws.ChatHub
}
func NewChatService(
chatRepo repository.ChatRepository,
userRepo repository.UserRepository,
) ChatService {
hub := ws.NewChatHub()
go hub.Run() // Запускаем хаб в отдельной горутине
return &chatService{
chatRepo: chatRepo,
userRepo: userRepo,
hub: hub,
}
}
func (s *chatService) SendMessage(ctx context.Context, senderID, chatID int, content string) (*domain.Message, error) {
// Проверяем существование чата
chat, err := s.chatRepo.GetChatByID(ctx, chatID)
if err != nil {
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, // Явно устанавливаем получателя
Content: content,
Status: "sent",
CreatedAt: time.Now(),
}
if err := s.chatRepo.SaveMessage(ctx, message); err != nil {
return nil, err
}
// Отправляем через WebSocket
if s.hub != nil {
s.hub.Broadcast(message)
}
return message, nil
}
func (s *chatService) GetChatMessages(ctx context.Context, chatID, userID int, limit, offset int) ([]*domain.Message, error) {
// Проверяем доступ пользователя к чату
chat, err := s.chatRepo.GetChatByID(ctx, chatID)
if err != nil {
return nil, err
}
if userID != chat.User1ID && userID != chat.User2ID {
return nil, errors.New("access denied")
}
return s.chatRepo.GetMessagesByChat(ctx, chatID, limit, offset)
}
func (s *chatService) MarkAsRead(ctx context.Context, messageID int) error {
return s.chatRepo.UpdateMessageStatus(ctx, messageID, "read")
}
func (s *chatService) DeleteMessage(ctx context.Context, messageID, userID int) error {
message, err := s.chatRepo.GetMessageByID(ctx, messageID)
if err != nil {
return err
}
if message.SenderID != userID {
return errors.New("only sender can delete the message")
}
return s.chatRepo.DeleteMessage(ctx, messageID)
}
func (s *chatService) GetUserChats(ctx context.Context, userID int) ([]*domain.Chat, error) {
return s.chatRepo.GetUserChats(ctx, userID)
}
func (s *chatService) GetOrCreateChat(ctx context.Context, user1ID, user2ID int) (*domain.Chat, error) {
// Проверяем существование чата
chat, err := s.chatRepo.GetChatByParticipants(ctx, user1ID, user2ID)
if err == nil {
return chat, nil
}
if !errors.Is(err, repository.ErrChatNotFound) {
return nil, err
}
// Создаем новый чат
return s.chatRepo.CreateChat(ctx, user1ID, user2ID)
}
func (s *chatService) GetUnreadCount(ctx context.Context, chatID, userID int) (int, error) {
return s.chatRepo.GetUnreadCount(ctx, chatID, userID)
}