upd
This commit is contained in:
@@ -19,13 +19,15 @@ export class ChatService {
|
||||
) {}
|
||||
|
||||
async createChat(userId: string, dto: CreateChatDto) {
|
||||
await this.assertProfileOwnership(userId, dto.profileId);
|
||||
|
||||
const [foundMatch] = await this.drizzleService.db
|
||||
.select()
|
||||
.from(match)
|
||||
.where(
|
||||
and(
|
||||
eq(match.id, dto.matchId),
|
||||
or(eq(match.user1Id, userId), eq(match.user2Id, userId)),
|
||||
or(eq(match.profile1Id, dto.profileId), eq(match.profile2Id, dto.profileId)),
|
||||
),
|
||||
)
|
||||
.limit(1);
|
||||
@@ -37,50 +39,46 @@ export class ChatService {
|
||||
.from(chat)
|
||||
.where(
|
||||
or(
|
||||
and(
|
||||
eq(chat.profile1Id, foundMatch.user1Id),
|
||||
eq(chat.profile2Id, foundMatch.user2Id),
|
||||
),
|
||||
and(
|
||||
eq(chat.profile1Id, foundMatch.user2Id),
|
||||
eq(chat.profile2Id, foundMatch.user1Id),
|
||||
),
|
||||
and(eq(chat.profile1Id, foundMatch.profile1Id), eq(chat.profile2Id, foundMatch.profile2Id)),
|
||||
and(eq(chat.profile1Id, foundMatch.profile2Id), eq(chat.profile2Id, foundMatch.profile1Id)),
|
||||
),
|
||||
)
|
||||
.limit(1);
|
||||
|
||||
if (existingChat.length > 0) return existingChat[0];
|
||||
|
||||
const currentUser = await this.drizzleService.db
|
||||
.select({ activeChatId: user.activeChatId })
|
||||
.from(user)
|
||||
.where(eq(user.id, userId))
|
||||
const [currentProfile] = await this.drizzleService.db
|
||||
.select({ activeChatId: profile.activeChatId })
|
||||
.from(profile)
|
||||
.where(eq(profile.id, dto.profileId))
|
||||
.limit(1);
|
||||
|
||||
if (currentUser[0]?.activeChatId) {
|
||||
if (currentProfile?.activeChatId) {
|
||||
throw new BadRequestException(
|
||||
'You already have an active chat. Close it before opening a new one.',
|
||||
'Profile already has an active chat. Close it before opening a new one.',
|
||||
);
|
||||
}
|
||||
|
||||
const [newChat] = await this.drizzleService.db
|
||||
.insert(chat)
|
||||
.values({
|
||||
profile1Id: foundMatch.user1Id,
|
||||
profile2Id: foundMatch.user2Id,
|
||||
profile1Id: foundMatch.profile1Id,
|
||||
profile2Id: foundMatch.profile2Id,
|
||||
status: 'active',
|
||||
} as any)
|
||||
.returning();
|
||||
|
||||
await this.drizzleService.db
|
||||
.update(user)
|
||||
.update(profile)
|
||||
.set({ activeChatId: newChat.id } as any)
|
||||
.where(or(eq(user.id, foundMatch.user1Id), eq(user.id, foundMatch.user2Id)));
|
||||
.where(or(eq(profile.id, foundMatch.profile1Id), eq(profile.id, foundMatch.profile2Id)));
|
||||
|
||||
return newChat;
|
||||
}
|
||||
|
||||
async closeChat(userId: string, chatId: string) {
|
||||
async closeChat(userId: string, profileId: string, chatId: string) {
|
||||
await this.assertProfileOwnership(userId, profileId);
|
||||
|
||||
const [foundChat] = await this.drizzleService.db
|
||||
.select()
|
||||
.from(chat)
|
||||
@@ -88,7 +86,7 @@ export class ChatService {
|
||||
.limit(1);
|
||||
|
||||
if (!foundChat) throw new NotFoundException('Chat not found');
|
||||
if (foundChat.profile1Id !== userId && foundChat.profile2Id !== userId) {
|
||||
if (foundChat.profile1Id !== profileId && foundChat.profile2Id !== profileId) {
|
||||
throw new ForbiddenException('Not a chat participant');
|
||||
}
|
||||
|
||||
@@ -98,26 +96,29 @@ export class ChatService {
|
||||
.where(eq(chat.id, chatId));
|
||||
|
||||
await this.drizzleService.db
|
||||
.update(user)
|
||||
.update(profile)
|
||||
.set({ activeChatId: null } as any)
|
||||
.where(or(eq(user.id, foundChat.profile1Id), eq(user.id, foundChat.profile2Id)));
|
||||
.where(or(eq(profile.id, foundChat.profile1Id), eq(profile.id, foundChat.profile2Id)));
|
||||
|
||||
return { message: 'Chat closed' };
|
||||
}
|
||||
|
||||
async getMyChats(userId: string) {
|
||||
async getChatsForProfile(userId: string, profileId: string) {
|
||||
await this.assertProfileOwnership(userId, profileId);
|
||||
return this.drizzleService.db
|
||||
.select()
|
||||
.from(chat)
|
||||
.where(
|
||||
and(
|
||||
or(eq(chat.profile1Id, userId), eq(chat.profile2Id, userId)),
|
||||
or(eq(chat.profile1Id, profileId), eq(chat.profile2Id, profileId)),
|
||||
eq(chat.status, 'active'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
async getChatMessages(userId: string, chatId: string, page = 1, limit = 50) {
|
||||
async getChatMessages(userId: string, profileId: string, chatId: string, page = 1, limit = 50) {
|
||||
await this.assertProfileOwnership(userId, profileId);
|
||||
|
||||
const [foundChat] = await this.drizzleService.db
|
||||
.select()
|
||||
.from(chat)
|
||||
@@ -125,7 +126,7 @@ export class ChatService {
|
||||
.limit(1);
|
||||
|
||||
if (!foundChat) throw new NotFoundException('Chat not found');
|
||||
if (foundChat.profile1Id !== userId && foundChat.profile2Id !== userId) {
|
||||
if (foundChat.profile1Id !== profileId && foundChat.profile2Id !== profileId) {
|
||||
throw new ForbiddenException('Not a chat participant');
|
||||
}
|
||||
|
||||
@@ -139,7 +140,9 @@ export class ChatService {
|
||||
.offset(offset);
|
||||
}
|
||||
|
||||
async sendMessage(userId: string, chatId: string, dto: SendMessageDto) {
|
||||
async sendMessage(userId: string, profileId: string, chatId: string, dto: SendMessageDto) {
|
||||
await this.assertProfileOwnership(userId, profileId);
|
||||
|
||||
const [foundChat] = await this.drizzleService.db
|
||||
.select()
|
||||
.from(chat)
|
||||
@@ -147,7 +150,7 @@ export class ChatService {
|
||||
.limit(1);
|
||||
|
||||
if (!foundChat) throw new NotFoundException('Active chat not found');
|
||||
if (foundChat.profile1Id !== userId && foundChat.profile2Id !== userId) {
|
||||
if (foundChat.profile1Id !== profileId && foundChat.profile2Id !== profileId) {
|
||||
throw new ForbiddenException('Not a chat participant');
|
||||
}
|
||||
|
||||
@@ -159,31 +162,50 @@ export class ChatService {
|
||||
.insert(message)
|
||||
.values({
|
||||
chatId,
|
||||
userId,
|
||||
profileId,
|
||||
text: dto.text || null,
|
||||
mediaUrl: dto.mediaUrl || null,
|
||||
mediaType: dto.mediaType || null,
|
||||
} as any)
|
||||
.returning();
|
||||
|
||||
const recipientId =
|
||||
foundChat.profile1Id === userId ? foundChat.profile2Id : foundChat.profile1Id;
|
||||
const recipientProfileId =
|
||||
foundChat.profile1Id === profileId ? foundChat.profile2Id : foundChat.profile1Id;
|
||||
|
||||
const [recipient] = await this.drizzleService.db
|
||||
.select({ fcmToken: user.fcmToken })
|
||||
.from(user)
|
||||
.where(eq(user.id, recipientId))
|
||||
const [recipientProfile] = await this.drizzleService.db
|
||||
.select({ userId: profile.userId })
|
||||
.from(profile)
|
||||
.where(eq(profile.id, recipientProfileId))
|
||||
.limit(1);
|
||||
|
||||
if (recipient?.fcmToken) {
|
||||
await this.notificationsService.sendPushNotification(
|
||||
recipient.fcmToken,
|
||||
'New message',
|
||||
dto.text?.substring(0, 100) || 'Media message',
|
||||
{ chatId, messageId: newMessage.id, type: 'message' },
|
||||
);
|
||||
if (recipientProfile) {
|
||||
const [recipientUser] = await this.drizzleService.db
|
||||
.select({ fcmToken: user.fcmToken })
|
||||
.from(user)
|
||||
.where(eq(user.id, recipientProfile.userId))
|
||||
.limit(1);
|
||||
|
||||
if (recipientUser?.fcmToken) {
|
||||
await this.notificationsService.sendPushNotification(
|
||||
recipientUser.fcmToken,
|
||||
'New message',
|
||||
dto.text?.substring(0, 100) || 'Media message',
|
||||
{ chatId, messageId: newMessage.id, type: 'message' },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return newMessage;
|
||||
}
|
||||
|
||||
private async assertProfileOwnership(userId: string, profileId: string) {
|
||||
const [found] = await this.drizzleService.db
|
||||
.select({ userId: profile.userId })
|
||||
.from(profile)
|
||||
.where(eq(profile.id, profileId))
|
||||
.limit(1);
|
||||
|
||||
if (!found) throw new NotFoundException('Profile not found');
|
||||
if (found.userId !== userId) throw new ForbiddenException('Profile does not belong to you');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user