133 lines
3.8 KiB
Go
133 lines
3.8 KiB
Go
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)
|
||
}
|