tailly_back_v2/internal/service/chat_service.go
madipo2611 6f5298d420 v0.0.3
2025-05-03 02:37:08 +03:00

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)
}