From d26836cd95e981d636006652927773c7943e77ce Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 30 Jul 2021 16:51:27 +0200 Subject: Refactor notifier --- .../abstract-owned-video-publication.ts | 57 +++++++++++++ .../video-publication/import-finished-for-owner.ts | 97 ++++++++++++++++++++++ .../lib/notifier/shared/video-publication/index.ts | 5 ++ .../video-publication/new-video-for-subscribers.ts | 61 ++++++++++++++ .../owned-publication-after-auto-unblacklist.ts | 11 +++ .../owned-publication-after-schedule-update.ts | 10 +++ .../owned-publication-after-transcoding.ts | 9 ++ 7 files changed, 250 insertions(+) create mode 100644 server/lib/notifier/shared/video-publication/abstract-owned-video-publication.ts create mode 100644 server/lib/notifier/shared/video-publication/import-finished-for-owner.ts create mode 100644 server/lib/notifier/shared/video-publication/index.ts create mode 100644 server/lib/notifier/shared/video-publication/new-video-for-subscribers.ts create mode 100644 server/lib/notifier/shared/video-publication/owned-publication-after-auto-unblacklist.ts create mode 100644 server/lib/notifier/shared/video-publication/owned-publication-after-schedule-update.ts create mode 100644 server/lib/notifier/shared/video-publication/owned-publication-after-transcoding.ts (limited to 'server/lib/notifier/shared/video-publication') diff --git a/server/lib/notifier/shared/video-publication/abstract-owned-video-publication.ts b/server/lib/notifier/shared/video-publication/abstract-owned-video-publication.ts new file mode 100644 index 000000000..fd06e080d --- /dev/null +++ b/server/lib/notifier/shared/video-publication/abstract-owned-video-publication.ts @@ -0,0 +1,57 @@ +import { logger } from '@server/helpers/logger' +import { WEBSERVER } from '@server/initializers/constants' +import { UserModel } from '@server/models/user/user' +import { UserNotificationModel } from '@server/models/user/user-notification' +import { MUserDefault, MUserWithNotificationSetting, MVideoFullLight, UserNotificationModelForApi } from '@server/types/models' +import { UserNotificationType } from '@shared/models' +import { AbstractNotification } from '../common/abstract-notification' + +export abstract class AbstractOwnedVideoPublication extends AbstractNotification { + protected user: MUserDefault + + async prepare () { + this.user = await UserModel.loadByVideoId(this.payload.id) + } + + log () { + logger.info('Notifying user %s of the publication of its video %s.', this.user.username, this.payload.url) + } + + getSetting (user: MUserWithNotificationSetting) { + return user.NotificationSetting.myVideoPublished + } + + getTargetUsers () { + if (!this.user) return [] + + return [ this.user ] + } + + async createNotification (user: MUserWithNotificationSetting) { + const notification = await UserNotificationModel.create({ + type: UserNotificationType.MY_VIDEO_PUBLISHED, + userId: user.id, + videoId: this.payload.id + }) + notification.Video = this.payload + + return notification + } + + createEmail (to: string) { + const videoUrl = WEBSERVER.URL + this.payload.getWatchStaticPath() + + return { + to, + subject: `Your video ${this.payload.name} has been published`, + text: `Your video "${this.payload.name}" has been published.`, + locals: { + title: 'You video is live', + action: { + text: 'View video', + url: videoUrl + } + } + } + } +} diff --git a/server/lib/notifier/shared/video-publication/import-finished-for-owner.ts b/server/lib/notifier/shared/video-publication/import-finished-for-owner.ts new file mode 100644 index 000000000..9f374b6f9 --- /dev/null +++ b/server/lib/notifier/shared/video-publication/import-finished-for-owner.ts @@ -0,0 +1,97 @@ +import { logger } from '@server/helpers/logger' +import { WEBSERVER } from '@server/initializers/constants' +import { UserModel } from '@server/models/user/user' +import { UserNotificationModel } from '@server/models/user/user-notification' +import { MUserDefault, MUserWithNotificationSetting, MVideoImportVideo, UserNotificationModelForApi } from '@server/types/models' +import { UserNotificationType } from '@shared/models' +import { AbstractNotification } from '../common/abstract-notification' + +export type ImportFinishedForOwnerPayload = { + videoImport: MVideoImportVideo + success: boolean +} + +export class ImportFinishedForOwner extends AbstractNotification { + private user: MUserDefault + + async prepare () { + this.user = await UserModel.loadByVideoImportId(this.videoImport.id) + } + + log () { + logger.info('Notifying user %s its video import %s is finished.', this.user.username, this.videoImport.getTargetIdentifier()) + } + + getSetting (user: MUserWithNotificationSetting) { + return user.NotificationSetting.myVideoImportFinished + } + + getTargetUsers () { + if (!this.user) return [] + + return [ this.user ] + } + + async createNotification (user: MUserWithNotificationSetting) { + const notification = await UserNotificationModel.create({ + type: this.payload.success + ? UserNotificationType.MY_VIDEO_IMPORT_SUCCESS + : UserNotificationType.MY_VIDEO_IMPORT_ERROR, + + userId: user.id, + videoImportId: this.videoImport.id + }) + notification.VideoImport = this.videoImport + + return notification + } + + createEmail (to: string) { + if (this.payload.success) return this.createSuccessEmail(to) + + return this.createFailEmail(to) + } + + private createSuccessEmail (to: string) { + const videoUrl = WEBSERVER.URL + this.videoImport.Video.getWatchStaticPath() + + return { + to, + subject: `Your video import ${this.videoImport.getTargetIdentifier()} is complete`, + text: `Your video "${this.videoImport.getTargetIdentifier()}" just finished importing.`, + locals: { + title: 'Import complete', + action: { + text: 'View video', + url: videoUrl + } + } + } + } + + private createFailEmail (to: string) { + const importUrl = WEBSERVER.URL + '/my-library/video-imports' + + const text = + `Your video import "${this.videoImport.getTargetIdentifier()}" encountered an error.` + + '\n\n' + + `See your videos import dashboard for more information: ${importUrl}.` + + return { + to, + subject: `Your video import "${this.videoImport.getTargetIdentifier()}" encountered an error`, + text, + locals: { + title: 'Import failed', + action: { + text: 'Review imports', + url: importUrl + } + } + } + } + + private get videoImport () { + return this.payload.videoImport + } +} diff --git a/server/lib/notifier/shared/video-publication/index.ts b/server/lib/notifier/shared/video-publication/index.ts new file mode 100644 index 000000000..940774504 --- /dev/null +++ b/server/lib/notifier/shared/video-publication/index.ts @@ -0,0 +1,5 @@ +export * from './new-video-for-subscribers' +export * from './import-finished-for-owner' +export * from './owned-publication-after-auto-unblacklist' +export * from './owned-publication-after-schedule-update' +export * from './owned-publication-after-transcoding' diff --git a/server/lib/notifier/shared/video-publication/new-video-for-subscribers.ts b/server/lib/notifier/shared/video-publication/new-video-for-subscribers.ts new file mode 100644 index 000000000..4253a0930 --- /dev/null +++ b/server/lib/notifier/shared/video-publication/new-video-for-subscribers.ts @@ -0,0 +1,61 @@ +import { logger } from '@server/helpers/logger' +import { WEBSERVER } from '@server/initializers/constants' +import { UserModel } from '@server/models/user/user' +import { UserNotificationModel } from '@server/models/user/user-notification' +import { MUserWithNotificationSetting, MVideoAccountLight, UserNotificationModelForApi } from '@server/types/models' +import { UserNotificationType, VideoPrivacy, VideoState } from '@shared/models' +import { AbstractNotification } from '../common/abstract-notification' + +export class NewVideoForSubscribers extends AbstractNotification { + private users: MUserWithNotificationSetting[] + + async prepare () { + // List all followers that are users + this.users = await UserModel.listUserSubscribersOf(this.payload.VideoChannel.actorId) + } + + log () { + logger.info('Notifying %d users of new video %s.', this.users.length, this.payload.url) + } + + isDisabled () { + return this.payload.privacy !== VideoPrivacy.PUBLIC || this.payload.state !== VideoState.PUBLISHED || this.payload.isBlacklisted() + } + + getSetting (user: MUserWithNotificationSetting) { + return user.NotificationSetting.newVideoFromSubscription + } + + getTargetUsers () { + return this.users + } + + async createNotification (user: MUserWithNotificationSetting) { + const notification = await UserNotificationModel.create({ + type: UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION, + userId: user.id, + videoId: this.payload.id + }) + notification.Video = this.payload + + return notification + } + + createEmail (to: string) { + const channelName = this.payload.VideoChannel.getDisplayName() + const videoUrl = WEBSERVER.URL + this.payload.getWatchStaticPath() + + return { + to, + subject: channelName + ' just published a new video', + text: `Your subscription ${channelName} just published a new video: "${this.payload.name}".`, + locals: { + title: 'New content ', + action: { + text: 'View video', + url: videoUrl + } + } + } + } +} diff --git a/server/lib/notifier/shared/video-publication/owned-publication-after-auto-unblacklist.ts b/server/lib/notifier/shared/video-publication/owned-publication-after-auto-unblacklist.ts new file mode 100644 index 000000000..27d89a5c7 --- /dev/null +++ b/server/lib/notifier/shared/video-publication/owned-publication-after-auto-unblacklist.ts @@ -0,0 +1,11 @@ + +import { VideoState } from '@shared/models' +import { AbstractOwnedVideoPublication } from './abstract-owned-video-publication' + +export class OwnedPublicationAfterAutoUnblacklist extends AbstractOwnedVideoPublication { + + isDisabled () { + // Don't notify if video is still waiting for transcoding or scheduled update + return !!this.payload.ScheduleVideoUpdate || (this.payload.waitTranscoding && this.payload.state !== VideoState.PUBLISHED) + } +} diff --git a/server/lib/notifier/shared/video-publication/owned-publication-after-schedule-update.ts b/server/lib/notifier/shared/video-publication/owned-publication-after-schedule-update.ts new file mode 100644 index 000000000..2e253b358 --- /dev/null +++ b/server/lib/notifier/shared/video-publication/owned-publication-after-schedule-update.ts @@ -0,0 +1,10 @@ +import { VideoState } from '@shared/models' +import { AbstractOwnedVideoPublication } from './abstract-owned-video-publication' + +export class OwnedPublicationAfterScheduleUpdate extends AbstractOwnedVideoPublication { + + isDisabled () { + // Don't notify if video is still blacklisted or waiting for transcoding + return !!this.payload.VideoBlacklist || (this.payload.waitTranscoding && this.payload.state !== VideoState.PUBLISHED) + } +} diff --git a/server/lib/notifier/shared/video-publication/owned-publication-after-transcoding.ts b/server/lib/notifier/shared/video-publication/owned-publication-after-transcoding.ts new file mode 100644 index 000000000..4fab1090f --- /dev/null +++ b/server/lib/notifier/shared/video-publication/owned-publication-after-transcoding.ts @@ -0,0 +1,9 @@ +import { AbstractOwnedVideoPublication } from './abstract-owned-video-publication' + +export class OwnedPublicationAfterTranscoding extends AbstractOwnedVideoPublication { + + isDisabled () { + // Don't notify if didn't wait for transcoding or video is still blacklisted/waiting for scheduled update + return !this.payload.waitTranscoding || !!this.payload.VideoBlacklist || !!this.payload.ScheduleVideoUpdate + } +} -- cgit v1.2.3