]>
Commit | Line | Data |
---|---|---|
d26836cd C |
1 | import { MUser, MUserDefault } from '@server/types/models/user' |
2 | import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist' | |
3 | import { UserNotificationSettingValue } from '../../../shared/models/users' | |
4 | import { logger } from '../../helpers/logger' | |
5 | import { CONFIG } from '../../initializers/config' | |
6 | import { MAbuseFull, MAbuseMessage, MActorFollowFull, MApplication, MPlugin } from '../../types/models' | |
7 | import { MCommentOwnerVideo, MVideoAccountLight, MVideoFullLight } from '../../types/models/video' | |
8 | import { JobQueue } from '../job-queue' | |
9 | import { PeerTubeSocket } from '../peertube-socket' | |
785f1897 | 10 | import { Hooks } from '../plugins/hooks' |
d26836cd C |
11 | import { |
12 | AbstractNotification, | |
13 | AbuseStateChangeForReporter, | |
14 | AutoFollowForInstance, | |
15 | CommentMention, | |
16 | FollowForInstance, | |
17 | FollowForUser, | |
18 | ImportFinishedForOwner, | |
19 | ImportFinishedForOwnerPayload, | |
20 | NewAbuseForModerators, | |
21 | NewAbuseMessageForModerators, | |
22 | NewAbuseMessageForReporter, | |
23 | NewAbusePayload, | |
24 | NewAutoBlacklistForModerators, | |
25 | NewBlacklistForOwner, | |
26 | NewCommentForVideoOwner, | |
27 | NewPeerTubeVersionForAdmins, | |
28 | NewPluginVersionForAdmins, | |
29 | NewVideoForSubscribers, | |
30 | OwnedPublicationAfterAutoUnblacklist, | |
31 | OwnedPublicationAfterScheduleUpdate, | |
32 | OwnedPublicationAfterTranscoding, | |
33 | RegistrationForModerators, | |
785f1897 | 34 | StudioEditionFinishedForOwner, |
d26836cd C |
35 | UnblacklistForOwner |
36 | } from './shared' | |
37 | ||
38 | class Notifier { | |
39 | ||
40 | private readonly notificationModels = { | |
41 | newVideo: [ NewVideoForSubscribers ], | |
42 | publicationAfterTranscoding: [ OwnedPublicationAfterTranscoding ], | |
43 | publicationAfterScheduleUpdate: [ OwnedPublicationAfterScheduleUpdate ], | |
44 | publicationAfterAutoUnblacklist: [ OwnedPublicationAfterAutoUnblacklist ], | |
45 | newComment: [ CommentMention, NewCommentForVideoOwner ], | |
46 | newAbuse: [ NewAbuseForModerators ], | |
47 | newBlacklist: [ NewBlacklistForOwner ], | |
48 | unblacklist: [ UnblacklistForOwner ], | |
49 | importFinished: [ ImportFinishedForOwner ], | |
50 | userRegistration: [ RegistrationForModerators ], | |
51 | userFollow: [ FollowForUser ], | |
52 | instanceFollow: [ FollowForInstance ], | |
53 | autoInstanceFollow: [ AutoFollowForInstance ], | |
54 | newAutoBlacklist: [ NewAutoBlacklistForModerators ], | |
55 | abuseStateChange: [ AbuseStateChangeForReporter ], | |
56 | newAbuseMessage: [ NewAbuseMessageForReporter, NewAbuseMessageForModerators ], | |
57 | newPeertubeVersion: [ NewPeerTubeVersionForAdmins ], | |
1808a1f8 | 58 | newPluginVersion: [ NewPluginVersionForAdmins ], |
92e66e04 | 59 | videoStudioEditionFinished: [ StudioEditionFinishedForOwner ] |
d26836cd C |
60 | } |
61 | ||
62 | private static instance: Notifier | |
63 | ||
64 | private constructor () { | |
65 | } | |
66 | ||
67 | notifyOnNewVideoIfNeeded (video: MVideoAccountLight): void { | |
68 | const models = this.notificationModels.newVideo | |
69 | ||
70 | this.sendNotifications(models, video) | |
71 | .catch(err => logger.error('Cannot notify subscribers of new video %s.', video.url, { err })) | |
72 | } | |
73 | ||
74 | notifyOnVideoPublishedAfterTranscoding (video: MVideoFullLight): void { | |
75 | const models = this.notificationModels.publicationAfterTranscoding | |
76 | ||
77 | this.sendNotifications(models, video) | |
78 | .catch(err => logger.error('Cannot notify owner that its video %s has been published after transcoding.', video.url, { err })) | |
79 | } | |
80 | ||
81 | notifyOnVideoPublishedAfterScheduledUpdate (video: MVideoFullLight): void { | |
82 | const models = this.notificationModels.publicationAfterScheduleUpdate | |
83 | ||
84 | this.sendNotifications(models, video) | |
85 | .catch(err => logger.error('Cannot notify owner that its video %s has been published after scheduled update.', video.url, { err })) | |
86 | } | |
87 | ||
88 | notifyOnVideoPublishedAfterRemovedFromAutoBlacklist (video: MVideoFullLight): void { | |
89 | const models = this.notificationModels.publicationAfterAutoUnblacklist | |
90 | ||
91 | this.sendNotifications(models, video) | |
92 | .catch(err => { | |
93 | logger.error('Cannot notify owner that its video %s has been published after removed from auto-blacklist.', video.url, { err }) | |
94 | }) | |
95 | } | |
96 | ||
97 | notifyOnNewComment (comment: MCommentOwnerVideo): void { | |
98 | const models = this.notificationModels.newComment | |
99 | ||
100 | this.sendNotifications(models, comment) | |
101 | .catch(err => logger.error('Cannot notify of new comment.', comment.url, { err })) | |
102 | } | |
103 | ||
104 | notifyOnNewAbuse (payload: NewAbusePayload): void { | |
105 | const models = this.notificationModels.newAbuse | |
106 | ||
107 | this.sendNotifications(models, payload) | |
108 | .catch(err => logger.error('Cannot notify of new abuse %d.', payload.abuseInstance.id, { err })) | |
109 | } | |
110 | ||
111 | notifyOnVideoAutoBlacklist (videoBlacklist: MVideoBlacklistLightVideo): void { | |
112 | const models = this.notificationModels.newAutoBlacklist | |
113 | ||
114 | this.sendNotifications(models, videoBlacklist) | |
115 | .catch(err => logger.error('Cannot notify of auto-blacklist of video %s.', videoBlacklist.Video.url, { err })) | |
116 | } | |
117 | ||
118 | notifyOnVideoBlacklist (videoBlacklist: MVideoBlacklistVideo): void { | |
119 | const models = this.notificationModels.newBlacklist | |
120 | ||
121 | this.sendNotifications(models, videoBlacklist) | |
122 | .catch(err => logger.error('Cannot notify video owner of new video blacklist of %s.', videoBlacklist.Video.url, { err })) | |
123 | } | |
124 | ||
125 | notifyOnVideoUnblacklist (video: MVideoFullLight): void { | |
126 | const models = this.notificationModels.unblacklist | |
127 | ||
128 | this.sendNotifications(models, video) | |
129 | .catch(err => logger.error('Cannot notify video owner of unblacklist of %s.', video.url, { err })) | |
130 | } | |
131 | ||
132 | notifyOnFinishedVideoImport (payload: ImportFinishedForOwnerPayload): void { | |
133 | const models = this.notificationModels.importFinished | |
134 | ||
135 | this.sendNotifications(models, payload) | |
136 | .catch(err => { | |
137 | logger.error('Cannot notify owner that its video import %s is finished.', payload.videoImport.getTargetIdentifier(), { err }) | |
138 | }) | |
139 | } | |
140 | ||
141 | notifyOnNewUserRegistration (user: MUserDefault): void { | |
142 | const models = this.notificationModels.userRegistration | |
143 | ||
144 | this.sendNotifications(models, user) | |
145 | .catch(err => logger.error('Cannot notify moderators of new user registration (%s).', user.username, { err })) | |
146 | } | |
147 | ||
148 | notifyOfNewUserFollow (actorFollow: MActorFollowFull): void { | |
149 | const models = this.notificationModels.userFollow | |
150 | ||
151 | this.sendNotifications(models, actorFollow) | |
152 | .catch(err => { | |
153 | logger.error( | |
154 | 'Cannot notify owner of channel %s of a new follow by %s.', | |
155 | actorFollow.ActorFollowing.VideoChannel.getDisplayName(), | |
156 | actorFollow.ActorFollower.Account.getDisplayName(), | |
157 | { err } | |
158 | ) | |
159 | }) | |
160 | } | |
161 | ||
162 | notifyOfNewInstanceFollow (actorFollow: MActorFollowFull): void { | |
163 | const models = this.notificationModels.instanceFollow | |
164 | ||
165 | this.sendNotifications(models, actorFollow) | |
166 | .catch(err => logger.error('Cannot notify administrators of new follower %s.', actorFollow.ActorFollower.url, { err })) | |
167 | } | |
168 | ||
169 | notifyOfAutoInstanceFollowing (actorFollow: MActorFollowFull): void { | |
170 | const models = this.notificationModels.autoInstanceFollow | |
171 | ||
172 | this.sendNotifications(models, actorFollow) | |
173 | .catch(err => logger.error('Cannot notify administrators of auto instance following %s.', actorFollow.ActorFollowing.url, { err })) | |
174 | } | |
175 | ||
176 | notifyOnAbuseStateChange (abuse: MAbuseFull): void { | |
177 | const models = this.notificationModels.abuseStateChange | |
178 | ||
179 | this.sendNotifications(models, abuse) | |
180 | .catch(err => logger.error('Cannot notify of abuse %d state change.', abuse.id, { err })) | |
181 | } | |
182 | ||
183 | notifyOnAbuseMessage (abuse: MAbuseFull, message: MAbuseMessage): void { | |
184 | const models = this.notificationModels.newAbuseMessage | |
185 | ||
186 | this.sendNotifications(models, { abuse, message }) | |
187 | .catch(err => logger.error('Cannot notify on new abuse %d message.', abuse.id, { err })) | |
188 | } | |
189 | ||
190 | notifyOfNewPeerTubeVersion (application: MApplication, latestVersion: string) { | |
191 | const models = this.notificationModels.newPeertubeVersion | |
192 | ||
193 | this.sendNotifications(models, { application, latestVersion }) | |
194 | .catch(err => logger.error('Cannot notify on new PeerTubeb version %s.', latestVersion, { err })) | |
195 | } | |
196 | ||
197 | notifyOfNewPluginVersion (plugin: MPlugin) { | |
198 | const models = this.notificationModels.newPluginVersion | |
199 | ||
200 | this.sendNotifications(models, plugin) | |
201 | .catch(err => logger.error('Cannot notify on new plugin version %s.', plugin.name, { err })) | |
202 | } | |
203 | ||
92e66e04 C |
204 | notifyOfFinishedVideoStudioEdition (video: MVideoFullLight) { |
205 | const models = this.notificationModels.videoStudioEditionFinished | |
1808a1f8 C |
206 | |
207 | this.sendNotifications(models, video) | |
92e66e04 | 208 | .catch(err => logger.error('Cannot notify on finished studio edition %s.', video.url, { err })) |
1808a1f8 C |
209 | } |
210 | ||
d26836cd C |
211 | private async notify <T> (object: AbstractNotification<T>) { |
212 | await object.prepare() | |
213 | ||
214 | const users = object.getTargetUsers() | |
215 | ||
216 | if (users.length === 0) return | |
217 | if (await object.isDisabled()) return | |
218 | ||
219 | object.log() | |
220 | ||
221 | const toEmails: string[] = [] | |
222 | ||
223 | for (const user of users) { | |
224 | const setting = object.getSetting(user) | |
225 | ||
785f1897 C |
226 | const webNotificationEnabled = this.isWebNotificationEnabled(setting) |
227 | const emailNotificationEnabled = this.isEmailEnabled(user, setting) | |
228 | const notification = object.createNotification(user) | |
229 | ||
230 | if (webNotificationEnabled) { | |
231 | await notification.save() | |
d26836cd C |
232 | |
233 | PeerTubeSocket.Instance.sendNotification(user.id, notification) | |
234 | } | |
235 | ||
785f1897 | 236 | if (emailNotificationEnabled) { |
d26836cd C |
237 | toEmails.push(user.email) |
238 | } | |
785f1897 C |
239 | |
240 | Hooks.runAction('action:notifier.notification.created', { webNotificationEnabled, emailNotificationEnabled, user, notification }) | |
d26836cd C |
241 | } |
242 | ||
243 | for (const to of toEmails) { | |
244 | const payload = await object.createEmail(to) | |
245 | JobQueue.Instance.createJob({ type: 'email', payload }) | |
246 | } | |
247 | } | |
248 | ||
249 | private isEmailEnabled (user: MUser, value: UserNotificationSettingValue) { | |
250 | if (CONFIG.SIGNUP.REQUIRES_EMAIL_VERIFICATION === true && user.emailVerified === false) return false | |
251 | ||
252 | return value & UserNotificationSettingValue.EMAIL | |
253 | } | |
254 | ||
255 | private isWebNotificationEnabled (value: UserNotificationSettingValue) { | |
256 | return value & UserNotificationSettingValue.WEB | |
257 | } | |
258 | ||
259 | private async sendNotifications <T> (models: (new (payload: T) => AbstractNotification<T>)[], payload: T) { | |
260 | for (const model of models) { | |
261 | // eslint-disable-next-line new-cap | |
262 | await this.notify(new model(payload)) | |
263 | } | |
264 | } | |
265 | ||
266 | static get Instance () { | |
267 | return this.instance || (this.instance = new this()) | |
268 | } | |
269 | } | |
270 | ||
271 | // --------------------------------------------------------------------------- | |
272 | ||
273 | export { | |
274 | Notifier | |
275 | } |