aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/notifier.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/notifier.ts')
-rw-r--r--server/lib/notifier.ts154
1 files changed, 149 insertions, 5 deletions
diff --git a/server/lib/notifier.ts b/server/lib/notifier.ts
index 11b0937e9..2c51d7101 100644
--- a/server/lib/notifier.ts
+++ b/server/lib/notifier.ts
@@ -13,6 +13,8 @@ import { VideoBlacklistModel } from '../models/video/video-blacklist'
13import * as Bluebird from 'bluebird' 13import * as Bluebird from 'bluebird'
14import { VideoImportModel } from '../models/video/video-import' 14import { VideoImportModel } from '../models/video/video-import'
15import { AccountBlocklistModel } from '../models/account/account-blocklist' 15import { AccountBlocklistModel } from '../models/account/account-blocklist'
16import { ActorFollowModel } from '../models/activitypub/actor-follow'
17import { AccountModel } from '../models/account/account'
16 18
17class Notifier { 19class Notifier {
18 20
@@ -38,7 +40,10 @@ class Notifier {
38 40
39 notifyOnNewComment (comment: VideoCommentModel): void { 41 notifyOnNewComment (comment: VideoCommentModel): void {
40 this.notifyVideoOwnerOfNewComment(comment) 42 this.notifyVideoOwnerOfNewComment(comment)
41 .catch(err => logger.error('Cannot notify of new comment %s.', comment.url, { err })) 43 .catch(err => logger.error('Cannot notify video owner of new comment %s.', comment.url, { err }))
44
45 this.notifyOfCommentMention(comment)
46 .catch(err => logger.error('Cannot notify mentions of comment %s.', comment.url, { err }))
42 } 47 }
43 48
44 notifyOnNewVideoAbuse (videoAbuse: VideoAbuseModel): void { 49 notifyOnNewVideoAbuse (videoAbuse: VideoAbuseModel): void {
@@ -61,6 +66,23 @@ class Notifier {
61 .catch(err => logger.error('Cannot notify owner that its video import %s is finished.', videoImport.getTargetIdentifier(), { err })) 66 .catch(err => logger.error('Cannot notify owner that its video import %s is finished.', videoImport.getTargetIdentifier(), { err }))
62 } 67 }
63 68
69 notifyOnNewUserRegistration (user: UserModel): void {
70 this.notifyModeratorsOfNewUserRegistration(user)
71 .catch(err => logger.error('Cannot notify moderators of new user registration (%s).', user.username, { err }))
72 }
73
74 notifyOfNewFollow (actorFollow: ActorFollowModel): void {
75 this.notifyUserOfNewActorFollow(actorFollow)
76 .catch(err => {
77 logger.error(
78 'Cannot notify owner of channel %s of a new follow by %s.',
79 actorFollow.ActorFollowing.VideoChannel.getDisplayName(),
80 actorFollow.ActorFollower.Account.getDisplayName(),
81 err
82 )
83 })
84 }
85
64 private async notifySubscribersOfNewVideo (video: VideoModel) { 86 private async notifySubscribersOfNewVideo (video: VideoModel) {
65 // List all followers that are users 87 // List all followers that are users
66 const users = await UserModel.listUserSubscribersOf(video.VideoChannel.actorId) 88 const users = await UserModel.listUserSubscribersOf(video.VideoChannel.actorId)
@@ -90,6 +112,8 @@ class Notifier {
90 } 112 }
91 113
92 private async notifyVideoOwnerOfNewComment (comment: VideoCommentModel) { 114 private async notifyVideoOwnerOfNewComment (comment: VideoCommentModel) {
115 if (comment.Video.isOwned() === false) return
116
93 const user = await UserModel.loadByVideoId(comment.videoId) 117 const user = await UserModel.loadByVideoId(comment.videoId)
94 118
95 // Not our user or user comments its own video 119 // Not our user or user comments its own video
@@ -122,11 +146,100 @@ class Notifier {
122 return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender }) 146 return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender })
123 } 147 }
124 148
125 private async notifyModeratorsOfNewVideoAbuse (videoAbuse: VideoAbuseModel) { 149 private async notifyOfCommentMention (comment: VideoCommentModel) {
126 const users = await UserModel.listWithRight(UserRight.MANAGE_VIDEO_ABUSES) 150 const usernames = comment.extractMentions()
151 let users = await UserModel.listByUsernames(usernames)
152
153 if (comment.Video.isOwned()) {
154 const userException = await UserModel.loadByVideoId(comment.videoId)
155 users = users.filter(u => u.id !== userException.id)
156 }
157
158 // Don't notify if I mentioned myself
159 users = users.filter(u => u.Account.id !== comment.accountId)
160
127 if (users.length === 0) return 161 if (users.length === 0) return
128 162
129 logger.info('Notifying %s user/moderators of new video abuse %s.', users.length, videoAbuse.Video.url) 163 const accountMutedHash = await AccountBlocklistModel.isAccountMutedByMulti(users.map(u => u.Account.id), comment.accountId)
164
165 logger.info('Notifying %d users of new comment %s.', users.length, comment.url)
166
167 function settingGetter (user: UserModel) {
168 if (accountMutedHash[user.Account.id] === true) return UserNotificationSettingValue.NONE
169
170 return user.NotificationSetting.commentMention
171 }
172
173 async function notificationCreator (user: UserModel) {
174 const notification = await UserNotificationModel.create({
175 type: UserNotificationType.COMMENT_MENTION,
176 userId: user.id,
177 commentId: comment.id
178 })
179 notification.Comment = comment
180
181 return notification
182 }
183
184 function emailSender (emails: string[]) {
185 return Emailer.Instance.addNewCommentMentionNotification(emails, comment)
186 }
187
188 return this.notify({ users, settingGetter, notificationCreator, emailSender })
189 }
190
191 private async notifyUserOfNewActorFollow (actorFollow: ActorFollowModel) {
192 if (actorFollow.ActorFollowing.isOwned() === false) return
193
194 // Account follows one of our account?
195 let followType: 'account' | 'channel' = 'channel'
196 let user = await UserModel.loadByChannelActorId(actorFollow.ActorFollowing.id)
197
198 // Account follows one of our channel?
199 if (!user) {
200 user = await UserModel.loadByAccountActorId(actorFollow.ActorFollowing.id)
201 followType = 'account'
202 }
203
204 if (!user) return
205
206 if (!actorFollow.ActorFollower.Account || !actorFollow.ActorFollower.Account.name) {
207 actorFollow.ActorFollower.Account = await actorFollow.ActorFollower.$get('Account') as AccountModel
208 }
209 const followerAccount = actorFollow.ActorFollower.Account
210
211 const accountMuted = await AccountBlocklistModel.isAccountMutedBy(user.Account.id, followerAccount.id)
212 if (accountMuted) return
213
214 logger.info('Notifying user %s of new follower: %s.', user.username, followerAccount.getDisplayName())
215
216 function settingGetter (user: UserModel) {
217 return user.NotificationSetting.newFollow
218 }
219
220 async function notificationCreator (user: UserModel) {
221 const notification = await UserNotificationModel.create({
222 type: UserNotificationType.NEW_FOLLOW,
223 userId: user.id,
224 actorFollowId: actorFollow.id
225 })
226 notification.ActorFollow = actorFollow
227
228 return notification
229 }
230
231 function emailSender (emails: string[]) {
232 return Emailer.Instance.addNewFollowNotification(emails, actorFollow, followType)
233 }
234
235 return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender })
236 }
237
238 private async notifyModeratorsOfNewVideoAbuse (videoAbuse: VideoAbuseModel) {
239 const moderators = await UserModel.listWithRight(UserRight.MANAGE_VIDEO_ABUSES)
240 if (moderators.length === 0) return
241
242 logger.info('Notifying %s user/moderators of new video abuse %s.', moderators.length, videoAbuse.Video.url)
130 243
131 function settingGetter (user: UserModel) { 244 function settingGetter (user: UserModel) {
132 return user.NotificationSetting.videoAbuseAsModerator 245 return user.NotificationSetting.videoAbuseAsModerator
@@ -147,7 +260,7 @@ class Notifier {
147 return Emailer.Instance.addVideoAbuseModeratorsNotification(emails, videoAbuse) 260 return Emailer.Instance.addVideoAbuseModeratorsNotification(emails, videoAbuse)
148 } 261 }
149 262
150 return this.notify({ users, settingGetter, notificationCreator, emailSender }) 263 return this.notify({ users: moderators, settingGetter, notificationCreator, emailSender })
151 } 264 }
152 265
153 private async notifyVideoOwnerOfBlacklist (videoBlacklist: VideoBlacklistModel) { 266 private async notifyVideoOwnerOfBlacklist (videoBlacklist: VideoBlacklistModel) {
@@ -264,6 +377,37 @@ class Notifier {
264 return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender }) 377 return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender })
265 } 378 }
266 379
380 private async notifyModeratorsOfNewUserRegistration (registeredUser: UserModel) {
381 const moderators = await UserModel.listWithRight(UserRight.MANAGE_USERS)
382 if (moderators.length === 0) return
383
384 logger.info(
385 'Notifying %s moderators of new user registration of %s.',
386 moderators.length, registeredUser.Account.Actor.preferredUsername
387 )
388
389 function settingGetter (user: UserModel) {
390 return user.NotificationSetting.newUserRegistration
391 }
392
393 async function notificationCreator (user: UserModel) {
394 const notification = await UserNotificationModel.create({
395 type: UserNotificationType.NEW_USER_REGISTRATION,
396 userId: user.id,
397 accountId: registeredUser.Account.id
398 })
399 notification.Account = registeredUser.Account
400
401 return notification
402 }
403
404 function emailSender (emails: string[]) {
405 return Emailer.Instance.addNewUserRegistrationNotification(emails, registeredUser)
406 }
407
408 return this.notify({ users: moderators, settingGetter, notificationCreator, emailSender })
409 }
410
267 private async notify (options: { 411 private async notify (options: {
268 users: UserModel[], 412 users: UserModel[],
269 notificationCreator: (user: UserModel) => Promise<UserNotificationModel>, 413 notificationCreator: (user: UserModel) => Promise<UserNotificationModel>,