aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2019-01-04 08:56:20 +0100
committerChocobozzz <chocobozzz@cpy.re>2019-01-09 11:15:15 +0100
commitf7cc67b455a12ccae9b0ea16876d166720364357 (patch)
treeeac2cdbf2e92a16b3eda5d74371c82bd79ae22cb /server/lib
parentdc13348070d808d0ba3feb56a435b835c2e7e791 (diff)
downloadPeerTube-f7cc67b455a12ccae9b0ea16876d166720364357.tar.gz
PeerTube-f7cc67b455a12ccae9b0ea16876d166720364357.tar.zst
PeerTube-f7cc67b455a12ccae9b0ea16876d166720364357.zip
Add new follow, mention and user registered notifs
Diffstat (limited to 'server/lib')
-rw-r--r--server/lib/activitypub/process/process-accept.ts2
-rw-r--r--server/lib/activitypub/process/process-follow.ts11
-rw-r--r--server/lib/emailer.ts63
-rw-r--r--server/lib/job-queue/handlers/activitypub-follow.ts9
-rw-r--r--server/lib/notifier.ts154
-rw-r--r--server/lib/user.ts13
6 files changed, 235 insertions, 17 deletions
diff --git a/server/lib/activitypub/process/process-accept.ts b/server/lib/activitypub/process/process-accept.ts
index 89bda9c32..605705ad3 100644
--- a/server/lib/activitypub/process/process-accept.ts
+++ b/server/lib/activitypub/process/process-accept.ts
@@ -2,6 +2,7 @@ import { ActivityAccept } from '../../../../shared/models/activitypub'
2import { ActorModel } from '../../../models/activitypub/actor' 2import { ActorModel } from '../../../models/activitypub/actor'
3import { ActorFollowModel } from '../../../models/activitypub/actor-follow' 3import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
4import { addFetchOutboxJob } from '../actor' 4import { addFetchOutboxJob } from '../actor'
5import { Notifier } from '../../notifier'
5 6
6async function processAcceptActivity (activity: ActivityAccept, targetActor: ActorModel, inboxActor?: ActorModel) { 7async function processAcceptActivity (activity: ActivityAccept, targetActor: ActorModel, inboxActor?: ActorModel) {
7 if (inboxActor === undefined) throw new Error('Need to accept on explicit inbox.') 8 if (inboxActor === undefined) throw new Error('Need to accept on explicit inbox.')
@@ -24,6 +25,7 @@ async function processAccept (actor: ActorModel, targetActor: ActorModel) {
24 if (follow.state !== 'accepted') { 25 if (follow.state !== 'accepted') {
25 follow.set('state', 'accepted') 26 follow.set('state', 'accepted')
26 await follow.save() 27 await follow.save()
28
27 await addFetchOutboxJob(targetActor) 29 await addFetchOutboxJob(targetActor)
28 } 30 }
29} 31}
diff --git a/server/lib/activitypub/process/process-follow.ts b/server/lib/activitypub/process/process-follow.ts
index 24c9085f7..a67892440 100644
--- a/server/lib/activitypub/process/process-follow.ts
+++ b/server/lib/activitypub/process/process-follow.ts
@@ -5,6 +5,7 @@ import { sequelizeTypescript } from '../../../initializers'
5import { ActorModel } from '../../../models/activitypub/actor' 5import { ActorModel } from '../../../models/activitypub/actor'
6import { ActorFollowModel } from '../../../models/activitypub/actor-follow' 6import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
7import { sendAccept } from '../send' 7import { sendAccept } from '../send'
8import { Notifier } from '../../notifier'
8 9
9async function processFollowActivity (activity: ActivityFollow, byActor: ActorModel) { 10async function processFollowActivity (activity: ActivityFollow, byActor: ActorModel) {
10 const activityObject = activity.object 11 const activityObject = activity.object
@@ -21,13 +22,13 @@ export {
21// --------------------------------------------------------------------------- 22// ---------------------------------------------------------------------------
22 23
23async function processFollow (actor: ActorModel, targetActorURL: string) { 24async function processFollow (actor: ActorModel, targetActorURL: string) {
24 await sequelizeTypescript.transaction(async t => { 25 const { actorFollow, created } = await sequelizeTypescript.transaction(async t => {
25 const targetActor = await ActorModel.loadByUrlAndPopulateAccountAndChannel(targetActorURL, t) 26 const targetActor = await ActorModel.loadByUrlAndPopulateAccountAndChannel(targetActorURL, t)
26 27
27 if (!targetActor) throw new Error('Unknown actor') 28 if (!targetActor) throw new Error('Unknown actor')
28 if (targetActor.isOwned() === false) throw new Error('This is not a local actor.') 29 if (targetActor.isOwned() === false) throw new Error('This is not a local actor.')
29 30
30 const [ actorFollow ] = await ActorFollowModel.findOrCreate({ 31 const [ actorFollow, created ] = await ActorFollowModel.findOrCreate({
31 where: { 32 where: {
32 actorId: actor.id, 33 actorId: actor.id,
33 targetActorId: targetActor.id 34 targetActorId: targetActor.id
@@ -52,8 +53,12 @@ async function processFollow (actor: ActorModel, targetActorURL: string) {
52 actorFollow.ActorFollowing = targetActor 53 actorFollow.ActorFollowing = targetActor
53 54
54 // Target sends to actor he accepted the follow request 55 // Target sends to actor he accepted the follow request
55 return sendAccept(actorFollow) 56 await sendAccept(actorFollow)
57
58 return { actorFollow, created }
56 }) 59 })
57 60
61 if (created) Notifier.Instance.notifyOfNewFollow(actorFollow)
62
58 logger.info('Actor %s is followed by actor %s.', targetActorURL, actor.url) 63 logger.info('Actor %s is followed by actor %s.', targetActorURL, actor.url)
59} 64}
diff --git a/server/lib/emailer.ts b/server/lib/emailer.ts
index 6dc8f2adf..3429498e7 100644
--- a/server/lib/emailer.ts
+++ b/server/lib/emailer.ts
@@ -11,6 +11,7 @@ import { VideoCommentModel } from '../models/video/video-comment'
11import { VideoAbuseModel } from '../models/video/video-abuse' 11import { VideoAbuseModel } from '../models/video/video-abuse'
12import { VideoBlacklistModel } from '../models/video/video-blacklist' 12import { VideoBlacklistModel } from '../models/video/video-blacklist'
13import { VideoImportModel } from '../models/video/video-import' 13import { VideoImportModel } from '../models/video/video-import'
14import { ActorFollowModel } from '../models/activitypub/actor-follow'
14 15
15class Emailer { 16class Emailer {
16 17
@@ -103,6 +104,25 @@ class Emailer {
103 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload }) 104 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
104 } 105 }
105 106
107 addNewFollowNotification (to: string[], actorFollow: ActorFollowModel, followType: 'account' | 'channel') {
108 const followerName = actorFollow.ActorFollower.Account.getDisplayName()
109 const followingName = (actorFollow.ActorFollowing.VideoChannel || actorFollow.ActorFollowing.Account).getDisplayName()
110
111 const text = `Hi dear user,\n\n` +
112 `Your ${followType} ${followingName} has a new subscriber: ${followerName}` +
113 `\n\n` +
114 `Cheers,\n` +
115 `PeerTube.`
116
117 const emailPayload: EmailPayload = {
118 to,
119 subject: 'New follower on your channel ' + followingName,
120 text
121 }
122
123 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
124 }
125
106 myVideoPublishedNotification (to: string[], video: VideoModel) { 126 myVideoPublishedNotification (to: string[], video: VideoModel) {
107 const videoUrl = CONFIG.WEBSERVER.URL + video.getWatchStaticPath() 127 const videoUrl = CONFIG.WEBSERVER.URL + video.getWatchStaticPath()
108 128
@@ -185,7 +205,29 @@ class Emailer {
185 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload }) 205 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
186 } 206 }
187 207
188 async addVideoAbuseModeratorsNotification (to: string[], videoAbuse: VideoAbuseModel) { 208 addNewCommentMentionNotification (to: string[], comment: VideoCommentModel) {
209 const accountName = comment.Account.getDisplayName()
210 const video = comment.Video
211 const commentUrl = CONFIG.WEBSERVER.URL + comment.getCommentStaticPath()
212
213 const text = `Hi dear user,\n\n` +
214 `${accountName} mentioned you on video ${video.name}` +
215 `\n\n` +
216 `You can view the comment on ${commentUrl} ` +
217 `\n\n` +
218 `Cheers,\n` +
219 `PeerTube.`
220
221 const emailPayload: EmailPayload = {
222 to,
223 subject: 'Mention on video ' + video.name,
224 text
225 }
226
227 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
228 }
229
230 addVideoAbuseModeratorsNotification (to: string[], videoAbuse: VideoAbuseModel) {
189 const videoUrl = CONFIG.WEBSERVER.URL + videoAbuse.Video.getWatchStaticPath() 231 const videoUrl = CONFIG.WEBSERVER.URL + videoAbuse.Video.getWatchStaticPath()
190 232
191 const text = `Hi,\n\n` + 233 const text = `Hi,\n\n` +
@@ -202,7 +244,22 @@ class Emailer {
202 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload }) 244 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
203 } 245 }
204 246
205 async addVideoBlacklistNotification (to: string[], videoBlacklist: VideoBlacklistModel) { 247 addNewUserRegistrationNotification (to: string[], user: UserModel) {
248 const text = `Hi,\n\n` +
249 `User ${user.username} just registered on ${CONFIG.WEBSERVER.HOST} PeerTube instance.\n\n` +
250 `Cheers,\n` +
251 `PeerTube.`
252
253 const emailPayload: EmailPayload = {
254 to,
255 subject: '[PeerTube] New user registration on ' + CONFIG.WEBSERVER.HOST,
256 text
257 }
258
259 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
260 }
261
262 addVideoBlacklistNotification (to: string[], videoBlacklist: VideoBlacklistModel) {
206 const videoName = videoBlacklist.Video.name 263 const videoName = videoBlacklist.Video.name
207 const videoUrl = CONFIG.WEBSERVER.URL + videoBlacklist.Video.getWatchStaticPath() 264 const videoUrl = CONFIG.WEBSERVER.URL + videoBlacklist.Video.getWatchStaticPath()
208 265
@@ -224,7 +281,7 @@ class Emailer {
224 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload }) 281 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
225 } 282 }
226 283
227 async addVideoUnblacklistNotification (to: string[], video: VideoModel) { 284 addVideoUnblacklistNotification (to: string[], video: VideoModel) {
228 const videoUrl = CONFIG.WEBSERVER.URL + video.getWatchStaticPath() 285 const videoUrl = CONFIG.WEBSERVER.URL + video.getWatchStaticPath()
229 286
230 const text = 'Hi,\n\n' + 287 const text = 'Hi,\n\n' +
diff --git a/server/lib/job-queue/handlers/activitypub-follow.ts b/server/lib/job-queue/handlers/activitypub-follow.ts
index 36d0f237b..b4d381062 100644
--- a/server/lib/job-queue/handlers/activitypub-follow.ts
+++ b/server/lib/job-queue/handlers/activitypub-follow.ts
@@ -8,6 +8,7 @@ import { getOrCreateActorAndServerAndModel } from '../../activitypub/actor'
8import { retryTransactionWrapper } from '../../../helpers/database-utils' 8import { retryTransactionWrapper } from '../../../helpers/database-utils'
9import { ActorFollowModel } from '../../../models/activitypub/actor-follow' 9import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
10import { ActorModel } from '../../../models/activitypub/actor' 10import { ActorModel } from '../../../models/activitypub/actor'
11import { Notifier } from '../../notifier'
11 12
12export type ActivitypubFollowPayload = { 13export type ActivitypubFollowPayload = {
13 followerActorId: number 14 followerActorId: number
@@ -42,7 +43,7 @@ export {
42 43
43// --------------------------------------------------------------------------- 44// ---------------------------------------------------------------------------
44 45
45function follow (fromActor: ActorModel, targetActor: ActorModel) { 46async function follow (fromActor: ActorModel, targetActor: ActorModel) {
46 if (fromActor.id === targetActor.id) { 47 if (fromActor.id === targetActor.id) {
47 throw new Error('Follower is the same than target actor.') 48 throw new Error('Follower is the same than target actor.')
48 } 49 }
@@ -50,7 +51,7 @@ function follow (fromActor: ActorModel, targetActor: ActorModel) {
50 // Same server, direct accept 51 // Same server, direct accept
51 const state = !fromActor.serverId && !targetActor.serverId ? 'accepted' : 'pending' 52 const state = !fromActor.serverId && !targetActor.serverId ? 'accepted' : 'pending'
52 53
53 return sequelizeTypescript.transaction(async t => { 54 const actorFollow = await sequelizeTypescript.transaction(async t => {
54 const [ actorFollow ] = await ActorFollowModel.findOrCreate({ 55 const [ actorFollow ] = await ActorFollowModel.findOrCreate({
55 where: { 56 where: {
56 actorId: fromActor.id, 57 actorId: fromActor.id,
@@ -68,5 +69,9 @@ function follow (fromActor: ActorModel, targetActor: ActorModel) {
68 69
69 // Send a notification to remote server if our follow is not already accepted 70 // Send a notification to remote server if our follow is not already accepted
70 if (actorFollow.state !== 'accepted') await sendFollow(actorFollow) 71 if (actorFollow.state !== 'accepted') await sendFollow(actorFollow)
72
73 return actorFollow
71 }) 74 })
75
76 if (actorFollow.state === 'accepted') Notifier.Instance.notifyOfNewFollow(actorFollow)
72} 77}
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>,
diff --git a/server/lib/user.ts b/server/lib/user.ts
index 481571828..9e24e85a0 100644
--- a/server/lib/user.ts
+++ b/server/lib/user.ts
@@ -10,7 +10,7 @@ import { VideoChannelModel } from '../models/video/video-channel'
10import { FilteredModelAttributes } from 'sequelize-typescript/lib/models/Model' 10import { FilteredModelAttributes } from 'sequelize-typescript/lib/models/Model'
11import { ActorModel } from '../models/activitypub/actor' 11import { ActorModel } from '../models/activitypub/actor'
12import { UserNotificationSettingModel } from '../models/account/user-notification-setting' 12import { UserNotificationSettingModel } from '../models/account/user-notification-setting'
13import { UserNotificationSettingValue } from '../../shared/models/users' 13import { UserNotificationSetting, UserNotificationSettingValue } from '../../shared/models/users'
14 14
15async function createUserAccountAndChannel (userToCreate: UserModel, validateUser = true) { 15async function createUserAccountAndChannel (userToCreate: UserModel, validateUser = true) {
16 const { user, account, videoChannel } = await sequelizeTypescript.transaction(async t => { 16 const { user, account, videoChannel } = await sequelizeTypescript.transaction(async t => {
@@ -96,13 +96,18 @@ export {
96// --------------------------------------------------------------------------- 96// ---------------------------------------------------------------------------
97 97
98function createDefaultUserNotificationSettings (user: UserModel, t: Sequelize.Transaction | undefined) { 98function createDefaultUserNotificationSettings (user: UserModel, t: Sequelize.Transaction | undefined) {
99 return UserNotificationSettingModel.create({ 99 const values: UserNotificationSetting & { userId: number } = {
100 userId: user.id, 100 userId: user.id,
101 newVideoFromSubscription: UserNotificationSettingValue.WEB_NOTIFICATION, 101 newVideoFromSubscription: UserNotificationSettingValue.WEB_NOTIFICATION,
102 newCommentOnMyVideo: UserNotificationSettingValue.WEB_NOTIFICATION, 102 newCommentOnMyVideo: UserNotificationSettingValue.WEB_NOTIFICATION,
103 myVideoImportFinished: UserNotificationSettingValue.WEB_NOTIFICATION, 103 myVideoImportFinished: UserNotificationSettingValue.WEB_NOTIFICATION,
104 myVideoPublished: UserNotificationSettingValue.WEB_NOTIFICATION, 104 myVideoPublished: UserNotificationSettingValue.WEB_NOTIFICATION,
105 videoAbuseAsModerator: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL, 105 videoAbuseAsModerator: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL,
106 blacklistOnMyVideo: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL 106 blacklistOnMyVideo: UserNotificationSettingValue.WEB_NOTIFICATION_AND_EMAIL,
107 }, { transaction: t }) 107 newUserRegistration: UserNotificationSettingValue.WEB_NOTIFICATION,
108 commentMention: UserNotificationSettingValue.WEB_NOTIFICATION,
109 newFollow: UserNotificationSettingValue.WEB_NOTIFICATION
110 }
111
112 return UserNotificationSettingModel.create(values, { transaction: t })
108} 113}