diff options
author | Chocobozzz <me@florianbigard.com> | 2020-07-27 16:26:25 +0200 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2020-07-31 11:35:19 +0200 |
commit | 594d3e48d8a887bbf48ce4cc594c1c36c9640fb1 (patch) | |
tree | bae28fa6215a3a3c6ccd78aea6ea7e75c500a96f /server/lib/notifier.ts | |
parent | 94148c9028829b5576a5dcbfba2c7fb9cf6443d3 (diff) | |
download | PeerTube-594d3e48d8a887bbf48ce4cc594c1c36c9640fb1.tar.gz PeerTube-594d3e48d8a887bbf48ce4cc594c1c36c9640fb1.tar.zst PeerTube-594d3e48d8a887bbf48ce4cc594c1c36c9640fb1.zip |
Add abuse messages/states notifications
Diffstat (limited to 'server/lib/notifier.ts')
-rw-r--r-- | server/lib/notifier.ts | 118 |
1 files changed, 114 insertions, 4 deletions
diff --git a/server/lib/notifier.ts b/server/lib/notifier.ts index 8f165d2fd..5c50fcf01 100644 --- a/server/lib/notifier.ts +++ b/server/lib/notifier.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | import { AbuseMessageModel } from '@server/models/abuse/abuse-message' | ||
1 | import { getServerActor } from '@server/models/application/application' | 2 | import { getServerActor } from '@server/models/application/application' |
2 | import { ServerBlocklistModel } from '@server/models/server/server-blocklist' | 3 | import { ServerBlocklistModel } from '@server/models/server/server-blocklist' |
3 | import { | 4 | import { |
@@ -18,7 +19,7 @@ import { CONFIG } from '../initializers/config' | |||
18 | import { AccountBlocklistModel } from '../models/account/account-blocklist' | 19 | import { AccountBlocklistModel } from '../models/account/account-blocklist' |
19 | import { UserModel } from '../models/account/user' | 20 | import { UserModel } from '../models/account/user' |
20 | import { UserNotificationModel } from '../models/account/user-notification' | 21 | import { UserNotificationModel } from '../models/account/user-notification' |
21 | import { MAbuseFull, MAccountServer, MActorFollowFull } from '../types/models' | 22 | import { MAbuseFull, MAbuseMessage, MAccountServer, MActorFollowFull } from '../types/models' |
22 | import { MCommentOwnerVideo, MVideoAccountLight, MVideoFullLight } from '../types/models/video' | 23 | import { MCommentOwnerVideo, MVideoAccountLight, MVideoFullLight } from '../types/models/video' |
23 | import { isBlockedByServerOrAccount } from './blocklist' | 24 | import { isBlockedByServerOrAccount } from './blocklist' |
24 | import { Emailer } from './emailer' | 25 | import { Emailer } from './emailer' |
@@ -129,6 +130,20 @@ class Notifier { | |||
129 | }) | 130 | }) |
130 | } | 131 | } |
131 | 132 | ||
133 | notifyOnAbuseStateChange (abuse: MAbuseFull): void { | ||
134 | this.notifyReporterOfAbuseStateChange(abuse) | ||
135 | .catch(err => { | ||
136 | logger.error('Cannot notify reporter of abuse %d state change.', abuse.id, { err }) | ||
137 | }) | ||
138 | } | ||
139 | |||
140 | notifyOnAbuseMessage (abuse: MAbuseFull, message: AbuseMessageModel): void { | ||
141 | this.notifyOfNewAbuseMessage(abuse, message) | ||
142 | .catch(err => { | ||
143 | logger.error('Cannot notify on new abuse %d message.', abuse.id, { err }) | ||
144 | }) | ||
145 | } | ||
146 | |||
132 | private async notifySubscribersOfNewVideo (video: MVideoAccountLight) { | 147 | private async notifySubscribersOfNewVideo (video: MVideoAccountLight) { |
133 | // List all followers that are users | 148 | // List all followers that are users |
134 | const users = await UserModel.listUserSubscribersOf(video.VideoChannel.actorId) | 149 | const users = await UserModel.listUserSubscribersOf(video.VideoChannel.actorId) |
@@ -359,9 +374,7 @@ class Notifier { | |||
359 | const moderators = await UserModel.listWithRight(UserRight.MANAGE_ABUSES) | 374 | const moderators = await UserModel.listWithRight(UserRight.MANAGE_ABUSES) |
360 | if (moderators.length === 0) return | 375 | if (moderators.length === 0) return |
361 | 376 | ||
362 | const url = abuseInstance.VideoAbuse?.Video?.url || | 377 | const url = this.getAbuseUrl(abuseInstance) |
363 | abuseInstance.VideoCommentAbuse?.VideoComment?.url || | ||
364 | abuseInstance.FlaggedAccount.Actor.url | ||
365 | 378 | ||
366 | logger.info('Notifying %s user/moderators of new abuse %s.', moderators.length, url) | 379 | logger.info('Notifying %s user/moderators of new abuse %s.', moderators.length, url) |
367 | 380 | ||
@@ -387,6 +400,97 @@ class Notifier { | |||
387 | return this.notify({ users: moderators, settingGetter, notificationCreator, emailSender }) | 400 | return this.notify({ users: moderators, settingGetter, notificationCreator, emailSender }) |
388 | } | 401 | } |
389 | 402 | ||
403 | private async notifyReporterOfAbuseStateChange (abuse: MAbuseFull) { | ||
404 | // Only notify our users | ||
405 | if (abuse.ReporterAccount.isOwned() !== true) return | ||
406 | |||
407 | const url = this.getAbuseUrl(abuse) | ||
408 | |||
409 | logger.info('Notifying reporter of abuse % of state change.', url) | ||
410 | |||
411 | const reporter = await UserModel.loadByAccountActorId(abuse.ReporterAccount.actorId) | ||
412 | |||
413 | function settingGetter (user: MUserWithNotificationSetting) { | ||
414 | return user.NotificationSetting.abuseStateChange | ||
415 | } | ||
416 | |||
417 | async function notificationCreator (user: MUserWithNotificationSetting) { | ||
418 | const notification = await UserNotificationModel.create<UserNotificationModelForApi>({ | ||
419 | type: UserNotificationType.ABUSE_STATE_CHANGE, | ||
420 | userId: user.id, | ||
421 | abuseId: abuse.id | ||
422 | }) | ||
423 | notification.Abuse = abuse | ||
424 | |||
425 | return notification | ||
426 | } | ||
427 | |||
428 | function emailSender (emails: string[]) { | ||
429 | return Emailer.Instance.addAbuseStateChangeNotification(emails, abuse) | ||
430 | } | ||
431 | |||
432 | return this.notify({ users: [ reporter ], settingGetter, notificationCreator, emailSender }) | ||
433 | } | ||
434 | |||
435 | private async notifyOfNewAbuseMessage (abuse: MAbuseFull, message: MAbuseMessage) { | ||
436 | const url = this.getAbuseUrl(abuse) | ||
437 | logger.info('Notifying reporter and moderators of new abuse message on %s.', url) | ||
438 | |||
439 | function settingGetter (user: MUserWithNotificationSetting) { | ||
440 | return user.NotificationSetting.abuseNewMessage | ||
441 | } | ||
442 | |||
443 | async function notificationCreator (user: MUserWithNotificationSetting) { | ||
444 | const notification = await UserNotificationModel.create<UserNotificationModelForApi>({ | ||
445 | type: UserNotificationType.ABUSE_NEW_MESSAGE, | ||
446 | userId: user.id, | ||
447 | abuseId: abuse.id | ||
448 | }) | ||
449 | notification.Abuse = abuse | ||
450 | |||
451 | return notification | ||
452 | } | ||
453 | |||
454 | function emailSenderReporter (emails: string[]) { | ||
455 | return Emailer.Instance.addAbuseNewMessageNotification(emails, { target: 'reporter', abuse, message }) | ||
456 | } | ||
457 | |||
458 | function emailSenderModerators (emails: string[]) { | ||
459 | return Emailer.Instance.addAbuseNewMessageNotification(emails, { target: 'moderator', abuse, message }) | ||
460 | } | ||
461 | |||
462 | async function buildReporterOptions () { | ||
463 | // Only notify our users | ||
464 | if (abuse.ReporterAccount.isOwned() !== true) return | ||
465 | |||
466 | const reporter = await UserModel.loadByAccountActorId(abuse.ReporterAccount.actorId) | ||
467 | // Don't notify my own message | ||
468 | if (reporter.Account.id === message.accountId) return | ||
469 | |||
470 | return { users: [ reporter ], settingGetter, notificationCreator, emailSender: emailSenderReporter } | ||
471 | } | ||
472 | |||
473 | async function buildModeratorsOptions () { | ||
474 | let moderators = await UserModel.listWithRight(UserRight.MANAGE_ABUSES) | ||
475 | // Don't notify my own message | ||
476 | moderators = moderators.filter(m => m.Account.id !== message.accountId) | ||
477 | |||
478 | if (moderators.length === 0) return | ||
479 | |||
480 | return { users: moderators, settingGetter, notificationCreator, emailSender: emailSenderModerators } | ||
481 | } | ||
482 | |||
483 | const [ reporterOptions, moderatorsOptions ] = await Promise.all([ | ||
484 | buildReporterOptions(), | ||
485 | buildModeratorsOptions() | ||
486 | ]) | ||
487 | |||
488 | return Promise.all([ | ||
489 | this.notify(reporterOptions), | ||
490 | this.notify(moderatorsOptions) | ||
491 | ]) | ||
492 | } | ||
493 | |||
390 | private async notifyModeratorsOfVideoAutoBlacklist (videoBlacklist: MVideoBlacklistLightVideo) { | 494 | private async notifyModeratorsOfVideoAutoBlacklist (videoBlacklist: MVideoBlacklistLightVideo) { |
391 | const moderators = await UserModel.listWithRight(UserRight.MANAGE_VIDEO_BLACKLIST) | 495 | const moderators = await UserModel.listWithRight(UserRight.MANAGE_VIDEO_BLACKLIST) |
392 | if (moderators.length === 0) return | 496 | if (moderators.length === 0) return |
@@ -599,6 +703,12 @@ class Notifier { | |||
599 | return isBlockedByServerOrAccount(targetAccount, user?.Account) | 703 | return isBlockedByServerOrAccount(targetAccount, user?.Account) |
600 | } | 704 | } |
601 | 705 | ||
706 | private getAbuseUrl (abuse: MAbuseFull) { | ||
707 | return abuse.VideoAbuse?.Video?.url || | ||
708 | abuse.VideoCommentAbuse?.VideoComment?.url || | ||
709 | abuse.FlaggedAccount.Actor.url | ||
710 | } | ||
711 | |||
602 | static get Instance () { | 712 | static get Instance () { |
603 | return this.instance || (this.instance = new this()) | 713 | return this.instance || (this.instance = new this()) |
604 | } | 714 | } |