96 lines
3.8 KiB
TypeScript
96 lines
3.8 KiB
TypeScript
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<Conversation>,
|
||
) {}
|
||
|
||
async create(participants: User[], name?: string, isGroup = false): Promise<Conversation> {
|
||
const conversation = this.conversationsRepository.create({
|
||
participants,
|
||
name,
|
||
isGroup,
|
||
});
|
||
return this.conversationsRepository.save(conversation);
|
||
}
|
||
|
||
async findAllForUser(userId: string): Promise<Conversation[]> {
|
||
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<Conversation> {
|
||
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<Conversation> {
|
||
// Проверяем существующую приватную беседу между двумя пользователями
|
||
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<Conversation> {
|
||
const conversation = await this.findOne(conversationId, userId);
|
||
|
||
if (!conversation.isGroup) {
|
||
throw new ForbiddenException('Нельзя добавлять участников в приватные беседы');
|
||
}
|
||
|
||
// Добавляем участника
|
||
return conversation;
|
||
}
|
||
} |