feat: add notification system for comments and likes
- Notify post authors when their content receives a new comment. - Notify parent comment authors when their comment receives a reply. - Send notifications to comment authors when their comments are liked. - Handle notification errors gracefully with error
This commit is contained in:
@@ -1,8 +1,11 @@
|
|||||||
import {
|
import {
|
||||||
ForbiddenException,
|
ForbiddenException,
|
||||||
|
Inject,
|
||||||
Injectable,
|
Injectable,
|
||||||
NotFoundException,
|
NotFoundException,
|
||||||
|
forwardRef,
|
||||||
} from "@nestjs/common";
|
} from "@nestjs/common";
|
||||||
|
import { ContentsRepository } from "../contents/repositories/contents.repository";
|
||||||
import { EventsGateway } from "../realtime/events.gateway";
|
import { EventsGateway } from "../realtime/events.gateway";
|
||||||
import { S3Service } from "../s3/s3.service";
|
import { S3Service } from "../s3/s3.service";
|
||||||
import type { CreateCommentDto } from "./dto/create-comment.dto";
|
import type { CreateCommentDto } from "./dto/create-comment.dto";
|
||||||
@@ -14,6 +17,8 @@ export class CommentsService {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly commentsRepository: CommentsRepository,
|
private readonly commentsRepository: CommentsRepository,
|
||||||
private readonly commentLikesRepository: CommentLikesRepository,
|
private readonly commentLikesRepository: CommentLikesRepository,
|
||||||
|
@Inject(forwardRef(() => ContentsRepository))
|
||||||
|
private readonly contentsRepository: ContentsRepository,
|
||||||
private readonly s3Service: S3Service,
|
private readonly s3Service: S3Service,
|
||||||
private readonly eventsGateway: EventsGateway,
|
private readonly eventsGateway: EventsGateway,
|
||||||
) {}
|
) {}
|
||||||
@@ -29,9 +34,48 @@ export class CommentsService {
|
|||||||
// Récupérer le commentaire avec les infos utilisateur pour le WebSocket
|
// Récupérer le commentaire avec les infos utilisateur pour le WebSocket
|
||||||
const enrichedComment = await this.findOneEnriched(comment.id, userId);
|
const enrichedComment = await this.findOneEnriched(comment.id, userId);
|
||||||
|
|
||||||
// Notifier les autres utilisateurs sur ce contenu
|
// Notifier les autres utilisateurs sur ce contenu (room de contenu)
|
||||||
this.eventsGateway.sendToContent(contentId, "new_comment", enrichedComment);
|
this.eventsGateway.sendToContent(contentId, "new_comment", enrichedComment);
|
||||||
|
|
||||||
|
// Notifications ciblées
|
||||||
|
try {
|
||||||
|
// 1. Notifier l'auteur du post
|
||||||
|
const content = await this.contentsRepository.findOne(contentId);
|
||||||
|
if (content && content.userId !== userId) {
|
||||||
|
this.eventsGateway.sendToUser(content.userId, "notification", {
|
||||||
|
type: "comment",
|
||||||
|
userId: userId,
|
||||||
|
username: enrichedComment.user.username,
|
||||||
|
contentId: contentId,
|
||||||
|
commentId: comment.id,
|
||||||
|
text: `a commenté votre post : "${dto.text.substring(0, 30)}${dto.text.length > 30 ? "..." : ""}"`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Si c'est une réponse, notifier l'auteur du commentaire parent
|
||||||
|
if (dto.parentId) {
|
||||||
|
const parentComment = await this.commentsRepository.findOne(
|
||||||
|
dto.parentId,
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
parentComment &&
|
||||||
|
parentComment.userId !== userId &&
|
||||||
|
(!content || parentComment.userId !== content.userId)
|
||||||
|
) {
|
||||||
|
this.eventsGateway.sendToUser(parentComment.userId, "notification", {
|
||||||
|
type: "reply",
|
||||||
|
userId: userId,
|
||||||
|
username: enrichedComment.user.username,
|
||||||
|
contentId: contentId,
|
||||||
|
commentId: comment.id,
|
||||||
|
text: `a répondu à votre commentaire : "${dto.text.substring(0, 30)}${dto.text.length > 30 ? "..." : ""}"`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to send notification:", error);
|
||||||
|
}
|
||||||
|
|
||||||
return enrichedComment;
|
return enrichedComment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,6 +149,23 @@ export class CommentsService {
|
|||||||
throw new NotFoundException("Comment not found");
|
throw new NotFoundException("Comment not found");
|
||||||
}
|
}
|
||||||
await this.commentLikesRepository.addLike(commentId, userId);
|
await this.commentLikesRepository.addLike(commentId, userId);
|
||||||
|
|
||||||
|
// Notifier l'auteur du commentaire
|
||||||
|
if (comment.userId !== userId) {
|
||||||
|
try {
|
||||||
|
const liker = await this.findOneEnriched(commentId, userId);
|
||||||
|
this.eventsGateway.sendToUser(comment.userId, "notification", {
|
||||||
|
type: "like_comment",
|
||||||
|
userId: userId,
|
||||||
|
username: liker?.user.username,
|
||||||
|
contentId: comment.contentId,
|
||||||
|
commentId: commentId,
|
||||||
|
text: "a aimé votre commentaire",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to send like notification:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async unlike(userId: string, commentId: string) {
|
async unlike(userId: string, commentId: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user