integrated email is forum posts/comments
This commit is contained in:
@@ -4,6 +4,7 @@ const { ForumPost, ForumComment, PostTag, User } = require('../models');
|
||||
const { authenticateToken } = require('../middleware/auth');
|
||||
const { uploadForumPostImages, uploadForumCommentImages } = require('../middleware/upload');
|
||||
const logger = require('../utils/logger');
|
||||
const emailService = require('../services/emailService');
|
||||
const router = express.Router();
|
||||
|
||||
// Helper function to build nested comment tree
|
||||
@@ -468,6 +469,46 @@ router.patch('/posts/:id/accept-answer', authenticateToken, async (req, res) =>
|
||||
status: commentId ? 'answered' : 'open'
|
||||
});
|
||||
|
||||
// Send email notification if marking an answer (not unmarking)
|
||||
if (commentId) {
|
||||
(async () => {
|
||||
try {
|
||||
const comment = await ForumComment.findByPk(commentId, {
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'author',
|
||||
attributes: ['id', 'username', 'firstName', 'lastName', 'email']
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const postAuthor = await User.findByPk(req.user.id, {
|
||||
attributes: ['id', 'username', 'firstName', 'lastName', 'email']
|
||||
});
|
||||
|
||||
// Only send email if not marking your own comment as answer
|
||||
if (comment && comment.authorId !== req.user.id) {
|
||||
await emailService.sendForumAnswerAcceptedNotification(
|
||||
comment.author,
|
||||
postAuthor,
|
||||
post,
|
||||
comment
|
||||
);
|
||||
}
|
||||
} catch (emailError) {
|
||||
// Email errors don't block answer marking
|
||||
logger.error("Failed to send answer accepted notification email", {
|
||||
error: emailError.message,
|
||||
stack: emailError.stack,
|
||||
commentId: commentId,
|
||||
postId: req.params.id
|
||||
});
|
||||
console.error("Email notification error:", emailError);
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
const updatedPost = await ForumPost.findByPk(post.id, {
|
||||
include: [
|
||||
{
|
||||
@@ -540,11 +581,107 @@ router.post('/posts/:id/comments', authenticateToken, uploadForumCommentImages,
|
||||
{
|
||||
model: User,
|
||||
as: 'author',
|
||||
attributes: ['id', 'username', 'firstName', 'lastName']
|
||||
attributes: ['id', 'username', 'firstName', 'lastName', 'email']
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// Send email notifications (non-blocking)
|
||||
(async () => {
|
||||
try {
|
||||
const commenter = commentWithDetails.author;
|
||||
const notifiedUserIds = new Set();
|
||||
|
||||
// Reload post with author details for email
|
||||
const postWithAuthor = await ForumPost.findByPk(req.params.id, {
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'author',
|
||||
attributes: ['id', 'username', 'firstName', 'lastName', 'email']
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// If this is a reply, send reply notification to parent comment author
|
||||
if (parentCommentId) {
|
||||
const parentComment = await ForumComment.findByPk(parentCommentId, {
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'author',
|
||||
attributes: ['id', 'username', 'firstName', 'lastName', 'email']
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// Send reply notification if not replying to yourself
|
||||
if (parentComment && parentComment.authorId !== req.user.id) {
|
||||
await emailService.sendForumReplyNotification(
|
||||
parentComment.author,
|
||||
commenter,
|
||||
postWithAuthor,
|
||||
commentWithDetails,
|
||||
parentComment
|
||||
);
|
||||
notifiedUserIds.add(parentComment.authorId);
|
||||
}
|
||||
} else {
|
||||
// Send comment notification to post author if not commenting on your own post
|
||||
if (postWithAuthor.authorId !== req.user.id) {
|
||||
await emailService.sendForumCommentNotification(
|
||||
postWithAuthor.author,
|
||||
commenter,
|
||||
postWithAuthor,
|
||||
commentWithDetails
|
||||
);
|
||||
notifiedUserIds.add(postWithAuthor.authorId);
|
||||
}
|
||||
}
|
||||
|
||||
// Get all unique participants who have commented on this post (excluding commenter and already notified)
|
||||
const participants = await ForumComment.findAll({
|
||||
where: {
|
||||
postId: req.params.id,
|
||||
authorId: {
|
||||
[Op.notIn]: [req.user.id, ...Array.from(notifiedUserIds)]
|
||||
},
|
||||
isDeleted: false
|
||||
},
|
||||
attributes: ['authorId'],
|
||||
include: [
|
||||
{
|
||||
model: User,
|
||||
as: 'author',
|
||||
attributes: ['id', 'username', 'firstName', 'lastName', 'email']
|
||||
}
|
||||
],
|
||||
group: ['ForumComment.authorId', 'author.id']
|
||||
});
|
||||
|
||||
// Send thread activity notifications to all unique participants
|
||||
for (const participant of participants) {
|
||||
if (participant.author) {
|
||||
await emailService.sendForumThreadActivityNotification(
|
||||
participant.author,
|
||||
commenter,
|
||||
postWithAuthor,
|
||||
commentWithDetails
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (emailError) {
|
||||
// Email errors don't block comment creation
|
||||
logger.error("Failed to send forum comment notification emails", {
|
||||
error: emailError.message,
|
||||
stack: emailError.stack,
|
||||
commentId: comment.id,
|
||||
postId: req.params.id
|
||||
});
|
||||
console.error("Email notification error:", emailError);
|
||||
}
|
||||
})();
|
||||
|
||||
const reqLogger = logger.withRequestId(req.id);
|
||||
reqLogger.info("Forum comment created", {
|
||||
postId: req.params.id,
|
||||
|
||||
Reference in New Issue
Block a user