- Added `GET /messages/unread-count` endpoint to retrieve the count of unread messages for a user. - Implemented `getUnreadCount` method in `MessagesService` and `MessagesRepository`. - Updated frontend service to support fetching unread message count via API.
168 lines
4.5 KiB
TypeScript
168 lines
4.5 KiB
TypeScript
import { Injectable } from "@nestjs/common";
|
|
import { and, desc, eq, inArray, sql } from "drizzle-orm";
|
|
import { DatabaseService } from "../../database/database.service";
|
|
import {
|
|
conversationParticipants,
|
|
conversations,
|
|
messages,
|
|
users,
|
|
} from "../../database/schemas";
|
|
|
|
@Injectable()
|
|
export class MessagesRepository {
|
|
constructor(private readonly databaseService: DatabaseService) {}
|
|
|
|
async findConversationBetweenUsers(userId1: string, userId2: string) {
|
|
const results = await this.databaseService.db
|
|
.select({ id: conversations.id })
|
|
.from(conversations)
|
|
.innerJoin(
|
|
conversationParticipants,
|
|
eq(conversations.id, conversationParticipants.conversationId),
|
|
)
|
|
.where(inArray(conversationParticipants.userId, [userId1, userId2]))
|
|
.groupBy(conversations.id)
|
|
.having(sql`count(${conversations.id}) = 2`);
|
|
|
|
return results[0];
|
|
}
|
|
|
|
async createConversation() {
|
|
const [conv] = await this.databaseService.db
|
|
.insert(conversations)
|
|
.values({})
|
|
.returning();
|
|
return conv;
|
|
}
|
|
|
|
async addParticipant(conversationId: string, userId: string) {
|
|
await this.databaseService.db
|
|
.insert(conversationParticipants)
|
|
.values({ conversationId, userId });
|
|
}
|
|
|
|
async createMessage(data: {
|
|
conversationId: string;
|
|
senderId: string;
|
|
text: string;
|
|
}) {
|
|
const [msg] = await this.databaseService.db
|
|
.insert(messages)
|
|
.values(data)
|
|
.returning();
|
|
|
|
// Update conversation updatedAt
|
|
await this.databaseService.db
|
|
.update(conversations)
|
|
.set({ updatedAt: new Date() })
|
|
.where(eq(conversations.id, data.conversationId));
|
|
|
|
return msg;
|
|
}
|
|
|
|
async findAllConversations(userId: string) {
|
|
// Sous-requête pour trouver les IDs des conversations de l'utilisateur
|
|
const userConvs = this.databaseService.db
|
|
.select({ id: conversationParticipants.conversationId })
|
|
.from(conversationParticipants)
|
|
.where(eq(conversationParticipants.userId, userId));
|
|
|
|
return this.databaseService.db
|
|
.select({
|
|
id: conversations.id,
|
|
updatedAt: conversations.updatedAt,
|
|
lastMessage: {
|
|
text: messages.text,
|
|
createdAt: messages.createdAt,
|
|
},
|
|
recipient: {
|
|
uuid: users.uuid,
|
|
username: users.username,
|
|
displayName: users.displayName,
|
|
avatarUrl: users.avatarUrl,
|
|
},
|
|
})
|
|
.from(conversations)
|
|
.innerJoin(
|
|
conversationParticipants,
|
|
eq(conversations.id, conversationParticipants.conversationId),
|
|
)
|
|
.innerJoin(users, eq(conversationParticipants.userId, users.uuid))
|
|
.leftJoin(messages, eq(conversations.id, messages.conversationId))
|
|
.where(
|
|
and(
|
|
inArray(conversations.id, userConvs),
|
|
eq(conversationParticipants.userId, users.uuid),
|
|
sql`${users.uuid} != ${userId}`,
|
|
),
|
|
)
|
|
.orderBy(desc(conversations.updatedAt));
|
|
}
|
|
|
|
async findMessagesByConversationId(conversationId: string, limit = 50) {
|
|
return this.databaseService.db
|
|
.select({
|
|
id: messages.id,
|
|
text: messages.text,
|
|
createdAt: messages.createdAt,
|
|
senderId: messages.senderId,
|
|
readAt: messages.readAt,
|
|
})
|
|
.from(messages)
|
|
.where(eq(messages.conversationId, conversationId))
|
|
.orderBy(desc(messages.createdAt))
|
|
.limit(limit);
|
|
}
|
|
|
|
async isParticipant(conversationId: string, userId: string) {
|
|
const [participant] = await this.databaseService.db
|
|
.select()
|
|
.from(conversationParticipants)
|
|
.where(
|
|
and(
|
|
eq(conversationParticipants.conversationId, conversationId),
|
|
eq(conversationParticipants.userId, userId),
|
|
),
|
|
);
|
|
return !!participant;
|
|
}
|
|
|
|
async getParticipants(conversationId: string) {
|
|
return this.databaseService.db
|
|
.select({ userId: conversationParticipants.userId })
|
|
.from(conversationParticipants)
|
|
.where(eq(conversationParticipants.conversationId, conversationId));
|
|
}
|
|
|
|
async markAsRead(conversationId: string, userId: string) {
|
|
await this.databaseService.db
|
|
.update(messages)
|
|
.set({ readAt: new Date() })
|
|
.where(
|
|
and(
|
|
eq(messages.conversationId, conversationId),
|
|
sql`${messages.senderId} != ${userId}`,
|
|
sql`${messages.readAt} IS NULL`,
|
|
),
|
|
);
|
|
}
|
|
|
|
async countUnreadMessages(userId: string) {
|
|
const result = await this.databaseService.db
|
|
.select({ count: sql<number>`count(*)` })
|
|
.from(messages)
|
|
.innerJoin(
|
|
conversationParticipants,
|
|
eq(messages.conversationId, conversationParticipants.conversationId),
|
|
)
|
|
.where(
|
|
and(
|
|
eq(conversationParticipants.userId, userId),
|
|
sql`${messages.senderId} != ${userId}`,
|
|
sql`${messages.readAt} IS NULL`,
|
|
),
|
|
);
|
|
return Number(result[0]?.count || 0);
|
|
}
|
|
}
|