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