mirror of
https://github.com/outline/outline.git
synced 2026-06-13 11:25:03 +03:00
42959d66db
* wip * Implementation complete * tidying * test * Address feedback * Remove duplicative retry logic from UpdateDocumentsPopularityScoreTask. Now that we're split across many runs this is not neccessary * Refactor to subclass, config to instance * Refactor BaseTask to named export * fix: Missing partition * tsc * Feedback
96 lines
2.5 KiB
TypeScript
96 lines
2.5 KiB
TypeScript
import { NotificationEventType } from "@shared/types";
|
|
import { Comment, Document, Notification, User } from "@server/models";
|
|
import { CommentReactionEvent } from "@server/types";
|
|
import { canUserAccessDocument } from "@server/utils/permissions";
|
|
import { BaseTask, TaskPriority } from "./base/BaseTask";
|
|
|
|
export default class ReactionCreatedNotificationsTask extends BaseTask<CommentReactionEvent> {
|
|
public async perform(event: CommentReactionEvent) {
|
|
const { emoji } = event.data;
|
|
|
|
// Only handle add_reaction events, not remove_reaction
|
|
if (event.name !== "comments.add_reaction") {
|
|
return;
|
|
}
|
|
|
|
const [document, comment] = await Promise.all([
|
|
Document.scope("withCollection").findOne({
|
|
where: {
|
|
id: event.documentId,
|
|
},
|
|
}),
|
|
Comment.findByPk(event.modelId),
|
|
]);
|
|
|
|
if (!document || !comment) {
|
|
return;
|
|
}
|
|
|
|
// Get the user who reacted (the actor)
|
|
const actor = await User.findByPk(event.actorId);
|
|
if (!actor) {
|
|
return;
|
|
}
|
|
|
|
// Get the comment author (the recipient of the notification)
|
|
const recipient = await User.findByPk(comment.createdById);
|
|
if (!recipient) {
|
|
return;
|
|
}
|
|
|
|
// Don't notify if the user reacted to their own comment
|
|
if (actor.id === recipient.id) {
|
|
return;
|
|
}
|
|
|
|
// Check if the comment author has this notification type enabled
|
|
if (
|
|
!recipient.subscribedToEventType(NotificationEventType.ReactionsCreate)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
// Check if the comment author can access the document
|
|
if (!(await canUserAccessDocument(recipient, document.id))) {
|
|
return;
|
|
}
|
|
|
|
const existing = await Notification.findOne({
|
|
where: {
|
|
event: NotificationEventType.ReactionsCreate,
|
|
userId: recipient.id,
|
|
commentId: comment.id,
|
|
},
|
|
});
|
|
|
|
if (existing) {
|
|
// If a notification already exists for this reaction, update it
|
|
// as we have a unique constraint on userId, commentId, and event.
|
|
await existing.update({
|
|
viewedAt: null,
|
|
archivedAt: null,
|
|
actorId: actor.id,
|
|
data: { emoji },
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Create the notification
|
|
await Notification.create({
|
|
event: NotificationEventType.ReactionsCreate,
|
|
userId: recipient.id,
|
|
actorId: actor.id,
|
|
teamId: document.teamId,
|
|
commentId: comment.id,
|
|
documentId: document.id,
|
|
data: { emoji },
|
|
});
|
|
}
|
|
|
|
public get options() {
|
|
return {
|
|
priority: TaskPriority.Background,
|
|
};
|
|
}
|
|
}
|