Files
rentall-app/backend/services/email/domain/ForumEmailService.js
2025-11-14 17:36:35 -05:00

319 lines
10 KiB
JavaScript

const EmailClient = require("../core/EmailClient");
const TemplateManager = require("../core/TemplateManager");
/**
* ForumEmailService handles all forum-related email notifications
* This service is responsible for:
* - Sending comment notifications to post authors
* - Sending reply notifications to comment authors
* - Sending answer accepted notifications
* - Sending thread activity notifications to participants
*/
class ForumEmailService {
constructor() {
this.emailClient = new EmailClient();
this.templateManager = new TemplateManager();
this.initialized = false;
}
/**
* Initialize the forum email service
* @returns {Promise<void>}
*/
async initialize() {
if (this.initialized) return;
await Promise.all([
this.emailClient.initialize(),
this.templateManager.initialize(),
]);
this.initialized = true;
console.log("Forum Email Service initialized successfully");
}
/**
* Send notification when someone comments on a post
* @param {Object} postAuthor - Post author user object
* @param {string} postAuthor.firstName - Post author's first name
* @param {string} postAuthor.email - Post author's email
* @param {Object} commenter - Commenter user object
* @param {string} commenter.firstName - Commenter's first name
* @param {string} commenter.lastName - Commenter's last name
* @param {Object} post - Forum post object
* @param {number} post.id - Post ID
* @param {string} post.title - Post title
* @param {Object} comment - Comment object
* @param {string} comment.content - Comment content
* @param {Date} comment.createdAt - Comment creation timestamp
* @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
*/
async sendForumCommentNotification(postAuthor, commenter, post, comment) {
if (!this.initialized) {
await this.initialize();
}
try {
const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
const postUrl = `${frontendUrl}/forum/posts/${post.id}`;
const timestamp = new Date(comment.createdAt).toLocaleString("en-US", {
dateStyle: "medium",
timeStyle: "short",
});
const variables = {
postAuthorName: postAuthor.firstName || "there",
commenterName:
`${commenter.firstName} ${commenter.lastName}`.trim() || "Someone",
postTitle: post.title,
commentContent: comment.content,
postUrl: postUrl,
timestamp: timestamp,
};
const htmlContent = await this.templateManager.renderTemplate(
"forumCommentToPostAuthor",
variables
);
const subject = `${commenter.firstName} ${commenter.lastName} commented on your post`;
const result = await this.emailClient.sendEmail(
postAuthor.email,
subject,
htmlContent
);
if (result.success) {
console.log(
`Forum comment notification email sent to ${postAuthor.email}`
);
}
return result;
} catch (error) {
console.error("Failed to send forum comment notification email:", error);
return { success: false, error: error.message };
}
}
/**
* Send notification when someone replies to a comment
* @param {Object} commentAuthor - Original comment author user object
* @param {string} commentAuthor.firstName - Comment author's first name
* @param {string} commentAuthor.email - Comment author's email
* @param {Object} replier - Replier user object
* @param {string} replier.firstName - Replier's first name
* @param {string} replier.lastName - Replier's last name
* @param {Object} post - Forum post object
* @param {number} post.id - Post ID
* @param {string} post.title - Post title
* @param {Object} reply - Reply comment object
* @param {string} reply.content - Reply content
* @param {Date} reply.createdAt - Reply creation timestamp
* @param {Object} parentComment - Parent comment being replied to
* @param {string} parentComment.content - Parent comment content
* @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
*/
async sendForumReplyNotification(
commentAuthor,
replier,
post,
reply,
parentComment
) {
if (!this.initialized) {
await this.initialize();
}
try {
const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
const postUrl = `${frontendUrl}/forum/posts/${post.id}`;
const timestamp = new Date(reply.createdAt).toLocaleString("en-US", {
dateStyle: "medium",
timeStyle: "short",
});
const variables = {
commentAuthorName: commentAuthor.firstName || "there",
replierName:
`${replier.firstName} ${replier.lastName}`.trim() || "Someone",
postTitle: post.title,
parentCommentContent: parentComment.content,
replyContent: reply.content,
postUrl: postUrl,
timestamp: timestamp,
};
const htmlContent = await this.templateManager.renderTemplate(
"forumReplyToCommentAuthor",
variables
);
const subject = `${replier.firstName} ${replier.lastName} replied to your comment`;
const result = await this.emailClient.sendEmail(
commentAuthor.email,
subject,
htmlContent
);
if (result.success) {
console.log(
`Forum reply notification email sent to ${commentAuthor.email}`
);
}
return result;
} catch (error) {
console.error("Failed to send forum reply notification email:", error);
return { success: false, error: error.message };
}
}
/**
* Send notification when a comment is marked as the accepted answer
* @param {Object} commentAuthor - Comment author user object
* @param {string} commentAuthor.firstName - Comment author's first name
* @param {string} commentAuthor.email - Comment author's email
* @param {Object} postAuthor - Post author user object who accepted the answer
* @param {string} postAuthor.firstName - Post author's first name
* @param {string} postAuthor.lastName - Post author's last name
* @param {Object} post - Forum post object
* @param {number} post.id - Post ID
* @param {string} post.title - Post title
* @param {Object} comment - Comment that was accepted as answer
* @param {string} comment.content - Comment content
* @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
*/
async sendForumAnswerAcceptedNotification(
commentAuthor,
postAuthor,
post,
comment
) {
if (!this.initialized) {
await this.initialize();
}
try {
const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
const postUrl = `${frontendUrl}/forum/posts/${post.id}`;
const variables = {
commentAuthorName: commentAuthor.firstName || "there",
postAuthorName:
`${postAuthor.firstName} ${postAuthor.lastName}`.trim() || "Someone",
postTitle: post.title,
commentContent: comment.content,
postUrl: postUrl,
};
const htmlContent = await this.templateManager.renderTemplate(
"forumAnswerAcceptedToCommentAuthor",
variables
);
const subject = `Your comment was marked as the accepted answer!`;
const result = await this.emailClient.sendEmail(
commentAuthor.email,
subject,
htmlContent
);
if (result.success) {
console.log(
`Forum answer accepted notification email sent to ${commentAuthor.email}`
);
}
return result;
} catch (error) {
console.error(
"Failed to send forum answer accepted notification email:",
error
);
return { success: false, error: error.message };
}
}
/**
* Send notification to thread participants about new activity
* @param {Object} participant - Participant user object
* @param {string} participant.firstName - Participant's first name
* @param {string} participant.email - Participant's email
* @param {Object} commenter - User who posted new comment
* @param {string} commenter.firstName - Commenter's first name
* @param {string} commenter.lastName - Commenter's last name
* @param {Object} post - Forum post object
* @param {number} post.id - Post ID
* @param {string} post.title - Post title
* @param {Object} comment - New comment/activity
* @param {string} comment.content - Comment content
* @param {Date} comment.createdAt - Comment creation timestamp
* @returns {Promise<{success: boolean, messageId?: string, error?: string}>}
*/
async sendForumThreadActivityNotification(
participant,
commenter,
post,
comment
) {
if (!this.initialized) {
await this.initialize();
}
try {
const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
const postUrl = `${frontendUrl}/forum/posts/${post.id}`;
const timestamp = new Date(comment.createdAt).toLocaleString("en-US", {
dateStyle: "medium",
timeStyle: "short",
});
const variables = {
participantName: participant.firstName || "there",
commenterName:
`${commenter.firstName} ${commenter.lastName}`.trim() || "Someone",
postTitle: post.title,
commentContent: comment.content,
postUrl: postUrl,
timestamp: timestamp,
};
const htmlContent = await this.templateManager.renderTemplate(
"forumThreadActivityToParticipant",
variables
);
const subject = `New activity on a post you're following`;
const result = await this.emailClient.sendEmail(
participant.email,
subject,
htmlContent
);
if (result.success) {
console.log(
`Forum thread activity notification email sent to ${participant.email}`
);
}
return result;
} catch (error) {
console.error(
"Failed to send forum thread activity notification email:",
error
);
return { success: false, error: error.message };
}
}
}
module.exports = ForumEmailService;