diff options
Diffstat (limited to 'server/lib/notifier/shared/video-publication')
7 files changed, 250 insertions, 0 deletions
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 @@ | |||
1 | import { logger } from '@server/helpers/logger' | ||
2 | import { WEBSERVER } from '@server/initializers/constants' | ||
3 | import { UserModel } from '@server/models/user/user' | ||
4 | import { UserNotificationModel } from '@server/models/user/user-notification' | ||
5 | import { MUserDefault, MUserWithNotificationSetting, MVideoFullLight, UserNotificationModelForApi } from '@server/types/models' | ||
6 | import { UserNotificationType } from '@shared/models' | ||
7 | import { AbstractNotification } from '../common/abstract-notification' | ||
8 | |||
9 | export abstract class AbstractOwnedVideoPublication extends AbstractNotification <MVideoFullLight> { | ||
10 | protected user: MUserDefault | ||
11 | |||
12 | async prepare () { | ||
13 | this.user = await UserModel.loadByVideoId(this.payload.id) | ||
14 | } | ||
15 | |||
16 | log () { | ||
17 | logger.info('Notifying user %s of the publication of its video %s.', this.user.username, this.payload.url) | ||
18 | } | ||
19 | |||
20 | getSetting (user: MUserWithNotificationSetting) { | ||
21 | return user.NotificationSetting.myVideoPublished | ||
22 | } | ||
23 | |||
24 | getTargetUsers () { | ||
25 | if (!this.user) return [] | ||
26 | |||
27 | return [ this.user ] | ||
28 | } | ||
29 | |||
30 | async createNotification (user: MUserWithNotificationSetting) { | ||
31 | const notification = await UserNotificationModel.create<UserNotificationModelForApi>({ | ||
32 | type: UserNotificationType.MY_VIDEO_PUBLISHED, | ||
33 | userId: user.id, | ||
34 | videoId: this.payload.id | ||
35 | }) | ||
36 | notification.Video = this.payload | ||
37 | |||
38 | return notification | ||
39 | } | ||
40 | |||
41 | createEmail (to: string) { | ||
42 | const videoUrl = WEBSERVER.URL + this.payload.getWatchStaticPath() | ||
43 | |||
44 | return { | ||
45 | to, | ||
46 | subject: `Your video ${this.payload.name} has been published`, | ||
47 | text: `Your video "${this.payload.name}" has been published.`, | ||
48 | locals: { | ||
49 | title: 'You video is live', | ||
50 | action: { | ||
51 | text: 'View video', | ||
52 | url: videoUrl | ||
53 | } | ||
54 | } | ||
55 | } | ||
56 | } | ||
57 | } | ||
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 @@ | |||
1 | import { logger } from '@server/helpers/logger' | ||
2 | import { WEBSERVER } from '@server/initializers/constants' | ||
3 | import { UserModel } from '@server/models/user/user' | ||
4 | import { UserNotificationModel } from '@server/models/user/user-notification' | ||
5 | import { MUserDefault, MUserWithNotificationSetting, MVideoImportVideo, UserNotificationModelForApi } from '@server/types/models' | ||
6 | import { UserNotificationType } from '@shared/models' | ||
7 | import { AbstractNotification } from '../common/abstract-notification' | ||
8 | |||
9 | export type ImportFinishedForOwnerPayload = { | ||
10 | videoImport: MVideoImportVideo | ||
11 | success: boolean | ||
12 | } | ||
13 | |||
14 | export class ImportFinishedForOwner extends AbstractNotification <ImportFinishedForOwnerPayload> { | ||
15 | private user: MUserDefault | ||
16 | |||
17 | async prepare () { | ||
18 | this.user = await UserModel.loadByVideoImportId(this.videoImport.id) | ||
19 | } | ||
20 | |||
21 | log () { | ||
22 | logger.info('Notifying user %s its video import %s is finished.', this.user.username, this.videoImport.getTargetIdentifier()) | ||
23 | } | ||
24 | |||
25 | getSetting (user: MUserWithNotificationSetting) { | ||
26 | return user.NotificationSetting.myVideoImportFinished | ||
27 | } | ||
28 | |||
29 | getTargetUsers () { | ||
30 | if (!this.user) return [] | ||
31 | |||
32 | return [ this.user ] | ||
33 | } | ||
34 | |||
35 | async createNotification (user: MUserWithNotificationSetting) { | ||
36 | const notification = await UserNotificationModel.create<UserNotificationModelForApi>({ | ||
37 | type: this.payload.success | ||
38 | ? UserNotificationType.MY_VIDEO_IMPORT_SUCCESS | ||
39 | : UserNotificationType.MY_VIDEO_IMPORT_ERROR, | ||
40 | |||
41 | userId: user.id, | ||
42 | videoImportId: this.videoImport.id | ||
43 | }) | ||
44 | notification.VideoImport = this.videoImport | ||
45 | |||
46 | return notification | ||
47 | } | ||
48 | |||
49 | createEmail (to: string) { | ||
50 | if (this.payload.success) return this.createSuccessEmail(to) | ||
51 | |||
52 | return this.createFailEmail(to) | ||
53 | } | ||
54 | |||
55 | private createSuccessEmail (to: string) { | ||
56 | const videoUrl = WEBSERVER.URL + this.videoImport.Video.getWatchStaticPath() | ||
57 | |||
58 | return { | ||
59 | to, | ||
60 | subject: `Your video import ${this.videoImport.getTargetIdentifier()} is complete`, | ||
61 | text: `Your video "${this.videoImport.getTargetIdentifier()}" just finished importing.`, | ||
62 | locals: { | ||
63 | title: 'Import complete', | ||
64 | action: { | ||
65 | text: 'View video', | ||
66 | url: videoUrl | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | |||
72 | private createFailEmail (to: string) { | ||
73 | const importUrl = WEBSERVER.URL + '/my-library/video-imports' | ||
74 | |||
75 | const text = | ||
76 | `Your video import "${this.videoImport.getTargetIdentifier()}" encountered an error.` + | ||
77 | '\n\n' + | ||
78 | `See your videos import dashboard for more information: <a href="${importUrl}">${importUrl}</a>.` | ||
79 | |||
80 | return { | ||
81 | to, | ||
82 | subject: `Your video import "${this.videoImport.getTargetIdentifier()}" encountered an error`, | ||
83 | text, | ||
84 | locals: { | ||
85 | title: 'Import failed', | ||
86 | action: { | ||
87 | text: 'Review imports', | ||
88 | url: importUrl | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | } | ||
93 | |||
94 | private get videoImport () { | ||
95 | return this.payload.videoImport | ||
96 | } | ||
97 | } | ||
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 @@ | |||
1 | export * from './new-video-for-subscribers' | ||
2 | export * from './import-finished-for-owner' | ||
3 | export * from './owned-publication-after-auto-unblacklist' | ||
4 | export * from './owned-publication-after-schedule-update' | ||
5 | 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 @@ | |||
1 | import { logger } from '@server/helpers/logger' | ||
2 | import { WEBSERVER } from '@server/initializers/constants' | ||
3 | import { UserModel } from '@server/models/user/user' | ||
4 | import { UserNotificationModel } from '@server/models/user/user-notification' | ||
5 | import { MUserWithNotificationSetting, MVideoAccountLight, UserNotificationModelForApi } from '@server/types/models' | ||
6 | import { UserNotificationType, VideoPrivacy, VideoState } from '@shared/models' | ||
7 | import { AbstractNotification } from '../common/abstract-notification' | ||
8 | |||
9 | export class NewVideoForSubscribers extends AbstractNotification <MVideoAccountLight> { | ||
10 | private users: MUserWithNotificationSetting[] | ||
11 | |||
12 | async prepare () { | ||
13 | // List all followers that are users | ||
14 | this.users = await UserModel.listUserSubscribersOf(this.payload.VideoChannel.actorId) | ||
15 | } | ||
16 | |||
17 | log () { | ||
18 | logger.info('Notifying %d users of new video %s.', this.users.length, this.payload.url) | ||
19 | } | ||
20 | |||
21 | isDisabled () { | ||
22 | return this.payload.privacy !== VideoPrivacy.PUBLIC || this.payload.state !== VideoState.PUBLISHED || this.payload.isBlacklisted() | ||
23 | } | ||
24 | |||
25 | getSetting (user: MUserWithNotificationSetting) { | ||
26 | return user.NotificationSetting.newVideoFromSubscription | ||
27 | } | ||
28 | |||
29 | getTargetUsers () { | ||
30 | return this.users | ||
31 | } | ||
32 | |||
33 | async createNotification (user: MUserWithNotificationSetting) { | ||
34 | const notification = await UserNotificationModel.create<UserNotificationModelForApi>({ | ||
35 | type: UserNotificationType.NEW_VIDEO_FROM_SUBSCRIPTION, | ||
36 | userId: user.id, | ||
37 | videoId: this.payload.id | ||
38 | }) | ||
39 | notification.Video = this.payload | ||
40 | |||
41 | return notification | ||
42 | } | ||
43 | |||
44 | createEmail (to: string) { | ||
45 | const channelName = this.payload.VideoChannel.getDisplayName() | ||
46 | const videoUrl = WEBSERVER.URL + this.payload.getWatchStaticPath() | ||
47 | |||
48 | return { | ||
49 | to, | ||
50 | subject: channelName + ' just published a new video', | ||
51 | text: `Your subscription ${channelName} just published a new video: "${this.payload.name}".`, | ||
52 | locals: { | ||
53 | title: 'New content ', | ||
54 | action: { | ||
55 | text: 'View video', | ||
56 | url: videoUrl | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | } | ||
61 | } | ||
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 @@ | |||
1 | |||
2 | import { VideoState } from '@shared/models' | ||
3 | import { AbstractOwnedVideoPublication } from './abstract-owned-video-publication' | ||
4 | |||
5 | export class OwnedPublicationAfterAutoUnblacklist extends AbstractOwnedVideoPublication { | ||
6 | |||
7 | isDisabled () { | ||
8 | // Don't notify if video is still waiting for transcoding or scheduled update | ||
9 | return !!this.payload.ScheduleVideoUpdate || (this.payload.waitTranscoding && this.payload.state !== VideoState.PUBLISHED) | ||
10 | } | ||
11 | } | ||
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 @@ | |||
1 | import { VideoState } from '@shared/models' | ||
2 | import { AbstractOwnedVideoPublication } from './abstract-owned-video-publication' | ||
3 | |||
4 | export class OwnedPublicationAfterScheduleUpdate extends AbstractOwnedVideoPublication { | ||
5 | |||
6 | isDisabled () { | ||
7 | // Don't notify if video is still blacklisted or waiting for transcoding | ||
8 | return !!this.payload.VideoBlacklist || (this.payload.waitTranscoding && this.payload.state !== VideoState.PUBLISHED) | ||
9 | } | ||
10 | } | ||
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 @@ | |||
1 | import { AbstractOwnedVideoPublication } from './abstract-owned-video-publication' | ||
2 | |||
3 | export class OwnedPublicationAfterTranscoding extends AbstractOwnedVideoPublication { | ||
4 | |||
5 | isDisabled () { | ||
6 | // Don't notify if didn't wait for transcoding or video is still blacklisted/waiting for scheduled update | ||
7 | return !this.payload.waitTranscoding || !!this.payload.VideoBlacklist || !!this.payload.ScheduleVideoUpdate | ||
8 | } | ||
9 | } | ||