From d26836cd95e981d636006652927773c7943e77ce Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 30 Jul 2021 16:51:27 +0200 Subject: Refactor notifier --- .../lib/notifier/shared/comment/comment-mention.ts | 111 +++++++++++++++++++++ server/lib/notifier/shared/comment/index.ts | 2 + .../shared/comment/new-comment-for-video-owner.ts | 76 ++++++++++++++ 3 files changed, 189 insertions(+) create mode 100644 server/lib/notifier/shared/comment/comment-mention.ts create mode 100644 server/lib/notifier/shared/comment/index.ts create mode 100644 server/lib/notifier/shared/comment/new-comment-for-video-owner.ts (limited to 'server/lib/notifier/shared/comment') diff --git a/server/lib/notifier/shared/comment/comment-mention.ts b/server/lib/notifier/shared/comment/comment-mention.ts new file mode 100644 index 000000000..4f84d8dea --- /dev/null +++ b/server/lib/notifier/shared/comment/comment-mention.ts @@ -0,0 +1,111 @@ +import { logger } from '@server/helpers/logger' +import { toSafeHtml } from '@server/helpers/markdown' +import { WEBSERVER } from '@server/initializers/constants' +import { AccountBlocklistModel } from '@server/models/account/account-blocklist' +import { getServerActor } from '@server/models/application/application' +import { ServerBlocklistModel } from '@server/models/server/server-blocklist' +import { UserModel } from '@server/models/user/user' +import { UserNotificationModel } from '@server/models/user/user-notification' +import { + MCommentOwnerVideo, + MUserDefault, + MUserNotifSettingAccount, + MUserWithNotificationSetting, + UserNotificationModelForApi +} from '@server/types/models' +import { UserNotificationSettingValue, UserNotificationType } from '@shared/models' +import { AbstractNotification } from '../common' + +export class CommentMention extends AbstractNotification { + private users: MUserDefault[] + + private serverAccountId: number + + private accountMutedHash: { [ id: number ]: boolean } + private instanceMutedHash: { [ id: number ]: boolean } + + async prepare () { + const extractedUsernames = this.payload.extractMentions() + logger.debug( + 'Extracted %d username from comment %s.', extractedUsernames.length, this.payload.url, + { usernames: extractedUsernames, text: this.payload.text } + ) + + this.users = await UserModel.listByUsernames(extractedUsernames) + + if (this.payload.Video.isOwned()) { + const userException = await UserModel.loadByVideoId(this.payload.videoId) + this.users = this.users.filter(u => u.id !== userException.id) + } + + // Don't notify if I mentioned myself + this.users = this.users.filter(u => u.Account.id !== this.payload.accountId) + + if (this.users.length === 0) return + + this.serverAccountId = (await getServerActor()).Account.id + + const sourceAccounts = this.users.map(u => u.Account.id).concat([ this.serverAccountId ]) + + this.accountMutedHash = await AccountBlocklistModel.isAccountMutedByMulti(sourceAccounts, this.payload.accountId) + this.instanceMutedHash = await ServerBlocklistModel.isServerMutedByMulti(sourceAccounts, this.payload.Account.Actor.serverId) + } + + log () { + logger.info('Notifying %d users of new comment %s.', this.users.length, this.payload.url) + } + + getSetting (user: MUserNotifSettingAccount) { + const accountId = user.Account.id + if ( + this.accountMutedHash[accountId] === true || this.instanceMutedHash[accountId] === true || + this.accountMutedHash[this.serverAccountId] === true || this.instanceMutedHash[this.serverAccountId] === true + ) { + return UserNotificationSettingValue.NONE + } + + return user.NotificationSetting.commentMention + } + + getTargetUsers () { + return this.users + } + + async createNotification (user: MUserWithNotificationSetting) { + const notification = await UserNotificationModel.create({ + type: UserNotificationType.COMMENT_MENTION, + userId: user.id, + commentId: this.payload.id + }) + notification.Comment = this.payload + + return notification + } + + createEmail (to: string) { + const comment = this.payload + + const accountName = comment.Account.getDisplayName() + const video = comment.Video + const videoUrl = WEBSERVER.URL + comment.Video.getWatchStaticPath() + const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath() + const commentHtml = toSafeHtml(comment.text) + + return { + template: 'video-comment-mention', + to, + subject: 'Mention on video ' + video.name, + locals: { + comment, + commentHtml, + video, + videoUrl, + accountName, + action: { + text: 'View comment', + url: commentUrl + } + } + } + } +} diff --git a/server/lib/notifier/shared/comment/index.ts b/server/lib/notifier/shared/comment/index.ts new file mode 100644 index 000000000..ae01a9646 --- /dev/null +++ b/server/lib/notifier/shared/comment/index.ts @@ -0,0 +1,2 @@ +export * from './comment-mention' +export * from './new-comment-for-video-owner' diff --git a/server/lib/notifier/shared/comment/new-comment-for-video-owner.ts b/server/lib/notifier/shared/comment/new-comment-for-video-owner.ts new file mode 100644 index 000000000..b76fc15bf --- /dev/null +++ b/server/lib/notifier/shared/comment/new-comment-for-video-owner.ts @@ -0,0 +1,76 @@ +import { logger } from '@server/helpers/logger' +import { toSafeHtml } from '@server/helpers/markdown' +import { WEBSERVER } from '@server/initializers/constants' +import { isBlockedByServerOrAccount } from '@server/lib/blocklist' +import { UserModel } from '@server/models/user/user' +import { UserNotificationModel } from '@server/models/user/user-notification' +import { MCommentOwnerVideo, MUserDefault, MUserWithNotificationSetting, UserNotificationModelForApi } from '@server/types/models' +import { UserNotificationType } from '@shared/models' +import { AbstractNotification } from '../common/abstract-notification' + +export class NewCommentForVideoOwner extends AbstractNotification { + private user: MUserDefault + + async prepare () { + this.user = await UserModel.loadByVideoId(this.payload.videoId) + } + + log () { + logger.info('Notifying owner of a video %s of new comment %s.', this.user.username, this.payload.url) + } + + isDisabled () { + if (this.payload.Video.isOwned() === false) return true + + // Not our user or user comments its own video + if (!this.user || this.payload.Account.userId === this.user.id) return true + + return isBlockedByServerOrAccount(this.payload.Account, this.user.Account) + } + + getSetting (user: MUserWithNotificationSetting) { + return user.NotificationSetting.newCommentOnMyVideo + } + + getTargetUsers () { + if (!this.user) return [] + + return [ this.user ] + } + + async createNotification (user: MUserWithNotificationSetting) { + const notification = await UserNotificationModel.create({ + type: UserNotificationType.NEW_COMMENT_ON_MY_VIDEO, + userId: user.id, + commentId: this.payload.id + }) + notification.Comment = this.payload + + return notification + } + + createEmail (to: string) { + const video = this.payload.Video + const videoUrl = WEBSERVER.URL + this.payload.Video.getWatchStaticPath() + const commentUrl = WEBSERVER.URL + this.payload.getCommentStaticPath() + const commentHtml = toSafeHtml(this.payload.text) + + return { + template: 'video-comment-new', + to, + subject: 'New comment on your video ' + video.name, + locals: { + accountName: this.payload.Account.getDisplayName(), + accountUrl: this.payload.Account.Actor.url, + comment: this.payload, + commentHtml, + video, + videoUrl, + action: { + text: 'View comment', + url: commentUrl + } + } + } + } +} -- cgit v1.2.3