import { Injectable, NotFoundException, ForbiddenException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Conversation } from './entities/conversation.entity'; import { User } from '../users/entities/user.entity'; @Injectable() export class ConversationsService { constructor( @InjectRepository(Conversation) private conversationsRepository: Repository, ) {} async create(participants: User[], name?: string, isGroup = false): Promise { const conversation = this.conversationsRepository.create({ participants, name, isGroup, }); return this.conversationsRepository.save(conversation); } async findAllForUser(userId: string): Promise { return this.conversationsRepository .createQueryBuilder('conversation') .leftJoinAndSelect('conversation.participants', 'participants') .leftJoinAndSelect('conversation.messages', 'messages') .leftJoin('conversation.participants', 'user') .where('user.id = :userId', { userId }) .orderBy('messages.createdAt', 'DESC') .getMany(); } async findOne(id: string, userId: string): Promise { const conversation = await this.conversationsRepository .createQueryBuilder('conversation') .leftJoinAndSelect('conversation.participants', 'participants') .leftJoinAndSelect('conversation.messages', 'messages') .leftJoinAndSelect('messages.sender', 'sender') .where('conversation.id = :id', { id }) .orderBy('messages.createdAt', 'ASC') .getOne(); if (!conversation) { throw new NotFoundException('Беседа не найдена'); } const isParticipant = conversation.participants.some(p => p.id === userId); if (!isParticipant) { throw new ForbiddenException('Вы не являетесь участником этой беседы'); } return conversation; } async findOrCreatePrivate(user1Id: string, user2Id: string): Promise { // Проверяем существующую приватную беседу между двумя пользователями const existingConversation = await this.conversationsRepository .createQueryBuilder('conversation') .leftJoinAndSelect('conversation.participants', 'participants') .where('conversation.isGroup = false') .andWhere((qb) => { const subQuery = qb.subQuery() .select('c.id') .from('conversations', 'c') .leftJoin('conversation_participants', 'cp1', 'cp1.conversationId = c.id') .leftJoin('conversation_participants', 'cp2', 'cp2.conversationId = c.id') .where('c.isGroup = false') .andWhere('cp1.userId = :user1Id', { user1Id }) .andWhere('cp2.userId = :user2Id', { user2Id }) .andWhere('(SELECT COUNT(*) FROM conversation_participants WHERE conversationId = c.id) = 2') .getQuery(); return 'conversation.id IN ' + subQuery; }) .getOne(); if (existingConversation) { return existingConversation; } // Создаем новую приватную беседу с двумя участниками const participants = [{ id: user1Id }, { id: user2Id }] as any; return this.create(participants, undefined, false); } async addParticipant(conversationId: string, userId: string, participantId: string): Promise { const conversation = await this.findOne(conversationId, userId); if (!conversation.isGroup) { throw new ForbiddenException('Нельзя добавлять участников в приватные беседы'); } // Добавляем участника return conversation; } }