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.ts235
1 files changed, 235 insertions, 0 deletions
diff --git a/server/lib/notifier.ts b/server/lib/notifier.ts
new file mode 100644
index 000000000..a21b50b2d
--- /dev/null
+++ b/server/lib/notifier.ts
@@ -0,0 +1,235 @@
1import { UserNotificationSettingValue, UserNotificationType, UserRight } from '../../shared/models/users'
2import { logger } from '../helpers/logger'
3import { VideoModel } from '../models/video/video'
4import { Emailer } from './emailer'
5import { UserNotificationModel } from '../models/account/user-notification'
6import { VideoCommentModel } from '../models/video/video-comment'
7import { UserModel } from '../models/account/user'
8import { PeerTubeSocket } from './peertube-socket'
9import { CONFIG } from '../initializers/constants'
10import { VideoPrivacy, VideoState } from '../../shared/models/videos'
11import { VideoAbuseModel } from '../models/video/video-abuse'
12import { VideoBlacklistModel } from '../models/video/video-blacklist'
13import * as Bluebird from 'bluebird'
14
15class Notifier {
16
17 private static instance: Notifier
18
19 private constructor () {}
20
21 notifyOnNewVideo (video: VideoModel): void {
22 // Only notify on public and published videos
23 if (video.privacy !== VideoPrivacy.PUBLIC || video.state !== VideoState.PUBLISHED) return
24
25 this.notifySubscribersOfNewVideo(video)
26 .catch(err => logger.error('Cannot notify subscribers of new video %s.', video.url, { err }))
27 }
28
29 notifyOnNewComment (comment: VideoCommentModel): void {
30 this.notifyVideoOwnerOfNewComment(comment)
31 .catch(err => logger.error('Cannot notify of new comment %s.', comment.url, { err }))
32 }
33
34 notifyOnNewVideoAbuse (videoAbuse: VideoAbuseModel): void {
35 this.notifyModeratorsOfNewVideoAbuse(videoAbuse)
36 .catch(err => logger.error('Cannot notify of new video abuse of video %s.', videoAbuse.Video.url, { err }))
37 }
38
39 notifyOnVideoBlacklist (videoBlacklist: VideoBlacklistModel): void {
40 this.notifyVideoOwnerOfBlacklist(videoBlacklist)
41 .catch(err => logger.error('Cannot notify video owner of new video blacklist of %s.', videoBlacklist.Video.url, { err }))
42 }
43
44 notifyOnVideoUnblacklist (video: VideoModel): void {
45 this.notifyVideoOwnerOfUnblacklist(video)
46 .catch(err => logger.error('Cannot notify video owner of new video blacklist of %s.', video.url, { err }))
47 }
48
49 private async notifySubscribersOfNewVideo (video: VideoModel) {
50 // List all followers that are users
51 const users = await UserModel.listUserSubscribersOf(video.VideoChannel.actorId)
52
53 logger.info('Notifying %d users of new video %s.', users.length, video.url)
54
55 function settingGetter (user: UserModel) {
56 return user.NotificationSetting.newVideoFromSubscription
57 }
58
59 async function notificationCreator (user: UserModel) {
60 const notification = await UserNotificationModel.create({
61 type: UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION,
62 userId: user.id,
63 videoId: video.id
64 })
65 notification.Video = video
66
67 return notification
68 }
69
70 function emailSender (emails: string[]) {
71 return Emailer.Instance.addNewVideoFromSubscriberNotification(emails, video)
72 }
73
74 return this.notify({ users, settingGetter, notificationCreator, emailSender })
75 }
76
77 private async notifyVideoOwnerOfNewComment (comment: VideoCommentModel) {
78 const user = await UserModel.loadByVideoId(comment.videoId)
79
80 // Not our user or user comments its own video
81 if (!user || comment.Account.userId === user.id) return
82
83 logger.info('Notifying user %s of new comment %s.', user.username, comment.url)
84
85 function settingGetter (user: UserModel) {
86 return user.NotificationSetting.newCommentOnMyVideo
87 }
88
89 async function notificationCreator (user: UserModel) {
90 const notification = await UserNotificationModel.create({
91 type: UserNotificationType.NEW_COMMENT_ON_MY_VIDEO,
92 userId: user.id,
93 commentId: comment.id
94 })
95 notification.Comment = comment
96
97 return notification
98 }
99
100 function emailSender (emails: string[]) {
101 return Emailer.Instance.addNewCommentOnMyVideoNotification(emails, comment)
102 }
103
104 return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender })
105 }
106
107 private async notifyModeratorsOfNewVideoAbuse (videoAbuse: VideoAbuseModel) {
108 const users = await UserModel.listWithRight(UserRight.MANAGE_VIDEO_ABUSES)
109 if (users.length === 0) return
110
111 logger.info('Notifying %s user/moderators of new video abuse %s.', users.length, videoAbuse.Video.url)
112
113 function settingGetter (user: UserModel) {
114 return user.NotificationSetting.videoAbuseAsModerator
115 }
116
117 async function notificationCreator (user: UserModel) {
118 const notification = await UserNotificationModel.create({
119 type: UserNotificationType.NEW_VIDEO_ABUSE_FOR_MODERATORS,
120 userId: user.id,
121 videoAbuseId: videoAbuse.id
122 })
123 notification.VideoAbuse = videoAbuse
124
125 return notification
126 }
127
128 function emailSender (emails: string[]) {
129 return Emailer.Instance.addVideoAbuseModeratorsNotification(emails, videoAbuse)
130 }
131
132 return this.notify({ users, settingGetter, notificationCreator, emailSender })
133 }
134
135 private async notifyVideoOwnerOfBlacklist (videoBlacklist: VideoBlacklistModel) {
136 const user = await UserModel.loadByVideoId(videoBlacklist.videoId)
137 if (!user) return
138
139 logger.info('Notifying user %s that its video %s has been blacklisted.', user.username, videoBlacklist.Video.url)
140
141 function settingGetter (user: UserModel) {
142 return user.NotificationSetting.blacklistOnMyVideo
143 }
144
145 async function notificationCreator (user: UserModel) {
146 const notification = await UserNotificationModel.create({
147 type: UserNotificationType.BLACKLIST_ON_MY_VIDEO,
148 userId: user.id,
149 videoBlacklistId: videoBlacklist.id
150 })
151 notification.VideoBlacklist = videoBlacklist
152
153 return notification
154 }
155
156 function emailSender (emails: string[]) {
157 return Emailer.Instance.addVideoBlacklistNotification(emails, videoBlacklist)
158 }
159
160 return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender })
161 }
162
163 private async notifyVideoOwnerOfUnblacklist (video: VideoModel) {
164 const user = await UserModel.loadByVideoId(video.id)
165 if (!user) return
166
167 logger.info('Notifying user %s that its video %s has been unblacklisted.', user.username, video.url)
168
169 function settingGetter (user: UserModel) {
170 return user.NotificationSetting.blacklistOnMyVideo
171 }
172
173 async function notificationCreator (user: UserModel) {
174 const notification = await UserNotificationModel.create({
175 type: UserNotificationType.UNBLACKLIST_ON_MY_VIDEO,
176 userId: user.id,
177 videoId: video.id
178 })
179 notification.Video = video
180
181 return notification
182 }
183
184 function emailSender (emails: string[]) {
185 return Emailer.Instance.addVideoUnblacklistNotification(emails, video)
186 }
187
188 return this.notify({ users: [ user ], settingGetter, notificationCreator, emailSender })
189 }
190
191 private async notify (options: {
192 users: UserModel[],
193 notificationCreator: (user: UserModel) => Promise<UserNotificationModel>,
194 emailSender: (emails: string[]) => Promise<any> | Bluebird<any>,
195 settingGetter: (user: UserModel) => UserNotificationSettingValue
196 }) {
197 const emails: string[] = []
198
199 for (const user of options.users) {
200 if (this.isWebNotificationEnabled(options.settingGetter(user))) {
201 const notification = await options.notificationCreator(user)
202
203 PeerTubeSocket.Instance.sendNotification(user.id, notification)
204 }
205
206 if (this.isEmailEnabled(user, options.settingGetter(user))) {
207 emails.push(user.email)
208 }
209 }
210
211 if (emails.length !== 0) {
212 await options.emailSender(emails)
213 }
214 }
215
216 private isEmailEnabled (user: UserModel, value: UserNotificationSettingValue) {
217 if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION === true && user.emailVerified !== true) return false
218
219 return value === UserNotificationSettingValue.EMAIL || value === UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL
220 }
221
222 private isWebNotificationEnabled (value: UserNotificationSettingValue) {
223 return value === UserNotificationSettingValue.WEB_NOTIFICATION || value === UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL
224 }
225
226 static get Instance () {
227 return this.instance || (this.instance = new this())
228 }
229}
230
231// ---------------------------------------------------------------------------
232
233export {
234 Notifier
235}