import { MUser , MUserDefault } from '@server/types/models/user' ; import { MVideoBlacklistLightVideo , MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist' ; import { UserNotificationSettingValue } from '../../../shared/models/users' ; import { logger } from '../../helpers/logger' ; import { CONFIG } from '../../initializers/config' ; import { MAbuseFull , MAbuseMessage , MActorFollowFull , MApplication , MPlugin } from '../../types/models' ; import { MCommentOwnerVideo , MVideoAccountLight , MVideoFullLight } from '../../types/models/video' ; import { JobQueue } from '../job-queue' ; import { PeerTubeSocket } from '../peertube-socket' ; import { AbstractNotification , AbuseStateChangeForReporter , AutoFollowForInstance , CommentMention , FollowForInstance , FollowForUser , ImportFinishedForOwner , ImportFinishedForOwnerPayload , NewAbuseForModerators , NewAbuseMessageForModerators , NewAbuseMessageForReporter , NewAbusePayload , NewAutoBlacklistForModerators , NewBlacklistForOwner , NewCommentForVideoOwner , NewPeerTubeVersionForAdmins , NewPluginVersionForAdmins , NewVideoForSubscribers , OwnedPublicationAfterAutoUnblacklist , OwnedPublicationAfterScheduleUpdate , OwnedPublicationAfterTranscoding , RegistrationForModerators , UnblacklistForOwner } from './shared' ; class Notifier { private readonly notificationModels = { newVideo : [ NewVideoForSubscribers ] , publicationAfterTranscoding : [ OwnedPublicationAfterTranscoding ] , publicationAfterScheduleUpdate : [ OwnedPublicationAfterScheduleUpdate ] , publicationAfterAutoUnblacklist : [ OwnedPublicationAfterAutoUnblacklist ] , newComment : [ CommentMention , NewCommentForVideoOwner ] , newAbuse : [ NewAbuseForModerators ] , newBlacklist : [ NewBlacklistForOwner ] , unblacklist : [ UnblacklistForOwner ] , importFinished : [ ImportFinishedForOwner ] , userRegistration : [ RegistrationForModerators ] , userFollow : [ FollowForUser ] , instanceFollow : [ FollowForInstance ] , autoInstanceFollow : [ AutoFollowForInstance ] , newAutoBlacklist : [ NewAutoBlacklistForModerators ] , abuseStateChange : [ AbuseStateChangeForReporter ] , newAbuseMessage : [ NewAbuseMessageForReporter , NewAbuseMessageForModerators ] , newPeertubeVersion : [ NewPeerTubeVersionForAdmins ] , newPluginVersion : [ NewPluginVersionForAdmins ] } ; private static instance : Notifier ; private constructor ( ) { } notifyOnNewVideoIfNeeded ( video ) { const models = this . notificationModels . newVideo ; this . sendNotifications ( models , video ) . catch ( err => logger . error ( 'Cannot notify subscribers of new video %s.' , video . url , { err } ) ) ; } notifyOnVideoPublishedAfterTranscoding ( video ) { const models = this . notificationModels . publicationAfterTranscoding ; this . sendNotifications ( models , video ) . catch ( err => logger . error ( 'Cannot notify owner that its video %s has been published after transcoding.' , video . url , { err } ) ) ; } notifyOnVideoPublishedAfterScheduledUpdate ( video ) { const models = this . notificationModels . publicationAfterScheduleUpdate ; this . sendNotifications ( models , video ) . catch ( err => logger . error ( 'Cannot notify owner that its video %s has been published after scheduled update.' , video . url , { err } ) ) ; } notifyOnVideoPublishedAfterRemovedFromAutoBlacklist ( video ) { const models = this . notificationModels . publicationAfterAutoUnblacklist ; this . sendNotifications ( models , video ) . catch ( err => { logger . error ( 'Cannot notify owner that its video %s has been published after removed from auto-blacklist.' , video . url , { err } ) ; } ) ; } notifyOnNewComment ( comment ) { const models = this . notificationModels . newComment ; this . sendNotifications ( models , comment ) . catch ( err => logger . error ( 'Cannot notify of new comment.' , comment . url , { err } ) ) ; } notifyOnNewAbuse ( payload ) { const models = this . notificationModels . newAbuse ; this . sendNotifications ( models , payload ) . catch ( err => logger . error ( 'Cannot notify of new abuse %d.' , payload . abuseInstance . id , { err } ) ) ; } notifyOnVideoAutoBlacklist ( videoBlacklist ) { const models = this . notificationModels . newAutoBlacklist ; this . sendNotifications ( models , videoBlacklist ) . catch ( err => logger . error ( 'Cannot notify of auto-blacklist of video %s.' , videoBlacklist . Video . url , { err } ) ) ; } notifyOnVideoBlacklist ( videoBlacklist ) { const models = this . notificationModels . newBlacklist ; this . sendNotifications ( models , videoBlacklist ) . catch ( err => logger . error ( 'Cannot notify video owner of new video blacklist of %s.' , videoBlacklist . Video . url , { err } ) ) ; } notifyOnVideoUnblacklist ( video ) { const models = this . notificationModels . unblacklist ; this . sendNotifications ( models , video ) . catch ( err => logger . error ( 'Cannot notify video owner of unblacklist of %s.' , video . url , { err } ) ) ; } notifyOnFinishedVideoImport ( payload ) { const models = this . notificationModels . importFinished ; this . sendNotifications ( models , payload ) . catch ( err => { logger . error ( 'Cannot notify owner that its video import %s is finished.' , payload . videoImport . getTargetIdentifier ( ) , { err } ) ; } ) ; } notifyOnNewUserRegistration ( user ) { const models = this . notificationModels . userRegistration ; this . sendNotifications ( models , user ) . catch ( err => logger . error ( 'Cannot notify moderators of new user registration (%s).' , user . username , { err } ) ) ; } notifyOfNewUserFollow ( actorFollow ) { const models = this . notificationModels . userFollow ; this . sendNotifications ( models , actorFollow ) . catch ( err => { logger . error ( 'Cannot notify owner of channel %s of a new follow by %s.' , actorFollow . ActorFollowing . VideoChannel . getDisplayName ( ) , actorFollow . ActorFollower . Account . getDisplayName ( ) , { err } ) ; } ) ; } notifyOfNewInstanceFollow ( actorFollow ) { const models = this . notificationModels . instanceFollow ; this . sendNotifications ( models , actorFollow ) . catch ( err => logger . error ( 'Cannot notify administrators of new follower %s.' , actorFollow . ActorFollower . url , { err } ) ) ; } notifyOfAutoInstanceFollowing ( actorFollow ) { const models = this . notificationModels . autoInstanceFollow ; this . sendNotifications ( models , actorFollow ) . catch ( err => logger . error ( 'Cannot notify administrators of auto instance following %s.' , actorFollow . ActorFollowing . url , { err } ) ) ; } notifyOnAbuseStateChange ( abuse ) { const models = this . notificationModels . abuseStateChange ; this . sendNotifications ( models , abuse ) . catch ( err => logger . error ( 'Cannot notify of abuse %d state change.' , abuse . id , { err } ) ) ; } notifyOnAbuseMessage ( abuse , message ) { const models = this . notificationModels . newAbuseMessage ; this . sendNotifications ( models , { abuse , message } ) . catch ( err => logger . error ( 'Cannot notify on new abuse %d message.' , abuse . id , { err } ) ) ; } notifyOfNewPeerTubeVersion ( application , latestVersion ) { const models = this . notificationModels . newPeertubeVersion ; this . sendNotifications ( models , { application , latestVersion } ) . catch ( err => logger . error ( 'Cannot notify on new PeerTubeb version %s.' , latestVersion , { err } ) ) ; } notifyOfNewPluginVersion ( plugin ) { const models = this . notificationModels . newPluginVersion ; this . sendNotifications ( models , plugin ) . catch ( err => logger . error ( 'Cannot notify on new plugin version %s.' , plugin . name , { err } ) ) ; } private async notify < T > ( object ) { await object . prepare ( ) ; const users = object . getTargetUsers ( ) ; if ( users . length === 0 ) return ; if ( await object . isDisabled ( ) ) return ; object . log ( ) ; const toEmails = [ ] ; for ( const user of users ) { const setting = object . getSetting ( user ) ; if ( this . isWebNotificationEnabled ( setting ) ) { const notification = await object . createNotification ( user ) ; PeerTubeSocket . Instance . sendNotification ( user . id , notification ) ; } if ( this . isEmailEnabled ( user , setting ) ) { toEmails . push ( user . email ) ; } } for ( const to of toEmails ) { const payload = await object . createEmail ( to ) ; JobQueue . Instance . createJob ( { type : 'email' , payload } ) ; } } private isEmailEnabled ( user , value ) { if ( CONFIG . SIGNUP . REQUIRES_EMAIL_VERIFICATION === true && user . emailVerified === false ) return false ; return value & UserNotificationSettingValue . EMAIL ; } private isWebNotificationEnabled ( value ) { return value & UserNotificationSettingValue . WEB ; } private async sendNotifications < T > ( models , payload ) { for ( const model of models ) { await this . notify ( new model ( payload ) ) ; } } static get Instance ( ) { return this . instance || ( this . instance = new this ( ) ) ; } } export { Notifier } ;