131 lines
3.5 KiB
Go
131 lines
3.5 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)
|
|
}
|
|
|
|
type chatService struct {
|
|
chatRepo repository.ChatRepository
|
|
userRepo repository.UserRepository
|
|
hub *ws.ChatHub
|
|
}
|
|
|
|
func NewChatService(
|
|
chatRepo repository.ChatRepository,
|
|
userRepo repository.UserRepository,
|
|
hub *ws.ChatHub,
|
|
) ChatService {
|
|
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")
|
|
}
|
|
|
|
message := &domain.Message{
|
|
ChatID: chatID,
|
|
SenderID: senderID,
|
|
Content: content,
|
|
Status: "sent",
|
|
CreatedAt: time.Now(),
|
|
}
|
|
|
|
if err := s.chatRepo.SaveMessage(ctx, message); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Отправляем через WebSocket
|
|
recipientID := chat.User1ID
|
|
if senderID == chat.User1ID {
|
|
recipientID = chat.User2ID
|
|
}
|
|
|
|
s.hub.Broadcast(&domain.Message{
|
|
ID: message.ID,
|
|
ChatID: chatID,
|
|
SenderID: senderID,
|
|
ReceiverID: recipientID,
|
|
Content: content,
|
|
Status: "sent",
|
|
CreatedAt: message.CreatedAt,
|
|
})
|
|
|
|
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)
|
|
}
|