From 88a8c1aa596e1113d6da52e5e8cbe443abc6384f Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Tue, 7 Dec 2021 18:56:41 -0500 Subject: [PATCH] feat(notif): 4K media notifications (#2324) --- server/entity/MediaRequest.ts | 12 ++-- server/lib/notifications/agents/email.ts | 25 ++++++-- server/lib/notifications/agents/webpush.ts | 25 ++++++-- server/subscriber/MediaSubscriber.ts | 69 ++++++++++++++++++---- 4 files changed, 101 insertions(+), 30 deletions(-) diff --git a/server/entity/MediaRequest.ts b/server/entity/MediaRequest.ts index 7f1de381..0e97f3d6 100644 --- a/server/entity/MediaRequest.ts +++ b/server/entity/MediaRequest.ts @@ -142,7 +142,7 @@ export class MediaRequest { if (this.type === MediaType.MOVIE) { const movie = await tmdb.getMovie({ movieId: media.tmdbId }); notificationManager.sendNotification(Notification.MEDIA_PENDING, { - event: 'New Movie Request', + event: `New ${this.is4k ? '4K ' : ''}Movie Request`, subject: `${movie.title}${ movie.release_date ? ` (${movie.release_date.slice(0, 4)})` : '' }`, @@ -161,7 +161,7 @@ export class MediaRequest { if (this.type === MediaType.TV) { const tv = await tmdb.getTvShow({ tvId: media.tmdbId }); notificationManager.sendNotification(Notification.MEDIA_PENDING, { - event: 'New Series Request', + event: `New ${this.is4k ? '4K ' : ''}Series Request`, subject: `${tv.name}${ tv.first_air_date ? ` (${tv.first_air_date.slice(0, 4)})` : '' }`, @@ -226,7 +226,7 @@ export class MediaRequest { : Notification.MEDIA_APPROVED : Notification.MEDIA_DECLINED, { - event: `Movie Request ${ + event: `${this.is4k ? '4K ' : ''}Movie Request ${ this.status === MediaRequestStatus.APPROVED ? autoApproved ? 'Automatically Approved' @@ -257,7 +257,7 @@ export class MediaRequest { : Notification.MEDIA_APPROVED : Notification.MEDIA_DECLINED, { - event: `Series Request ${ + event: `${this.is4k ? '4K ' : ''}Series Request ${ this.status === MediaRequestStatus.APPROVED ? autoApproved ? 'Automatically Approved' @@ -528,7 +528,7 @@ export class MediaRequest { ); notificationManager.sendNotification(Notification.MEDIA_FAILED, { - event: `Movie Request Failed`, + event: `${this.is4k ? '4K ' : ''}Movie Request Failed`, subject: `${movie.title}${ movie.release_date ? ` (${movie.release_date.slice(0, 4)})` : '' }`, @@ -744,7 +744,7 @@ export class MediaRequest { ); notificationManager.sendNotification(Notification.MEDIA_FAILED, { - event: `Series Request Failed`, + event: `${this.is4k ? '4K ' : ''}Series Request Failed`, subject: `${series.name}${ series.first_air_date ? ` (${series.first_air_date.slice(0, 4)})` diff --git a/server/lib/notifications/agents/email.ts b/server/lib/notifications/agents/email.ts index c49d5827..4df74d14 100644 --- a/server/lib/notifications/agents/email.ts +++ b/server/lib/notifications/agents/email.ts @@ -72,28 +72,41 @@ class EmailAgent ? 'movie' : 'series' : undefined; + const is4k = payload.request?.is4k; if (payload.request) { let body = ''; switch (type) { case Notification.MEDIA_PENDING: - body = `A new request for the following ${mediaType} is pending approval:`; + body = `A new request for the following ${mediaType} ${ + is4k ? 'in 4K ' : '' + }is pending approval:`; break; case Notification.MEDIA_APPROVED: - body = `Your request for the following ${mediaType} has been approved:`; + body = `Your request for the following ${mediaType} ${ + is4k ? 'in 4K ' : '' + }has been approved:`; break; case Notification.MEDIA_AUTO_APPROVED: - body = `A new request for the following ${mediaType} has been automatically approved:`; + body = `A new request for the following ${mediaType} ${ + is4k ? 'in 4K ' : '' + }has been automatically approved:`; break; case Notification.MEDIA_AVAILABLE: - body = `Your request for the following ${mediaType} is now available:`; + body = `Your request for the following ${mediaType} ${ + is4k ? 'in 4K ' : '' + }is now available:`; break; case Notification.MEDIA_DECLINED: - body = `Your request for the following ${mediaType} was declined:`; + body = `Your request for the following ${mediaType} ${ + is4k ? 'in 4K ' : '' + }was declined:`; break; case Notification.MEDIA_FAILED: - body = `A request for the following ${mediaType} failed to be added to ${ + body = `A request for the following ${mediaType} ${ + is4k ? 'in 4K ' : '' + }failed to be added to ${ payload.media?.mediaType === MediaType.MOVIE ? 'Radarr' : 'Sonarr' }:`; break; diff --git a/server/lib/notifications/agents/webpush.ts b/server/lib/notifications/agents/webpush.ts index e61e86f6..fc4fefbb 100644 --- a/server/lib/notifications/agents/webpush.ts +++ b/server/lib/notifications/agents/webpush.ts @@ -46,6 +46,7 @@ class WebPushAgent ? 'movie' : 'series' : undefined; + const is4k = payload.request?.is4k; const issueType = payload.issue ? payload.issue.issueType !== IssueType.OTHER @@ -59,22 +60,34 @@ class WebPushAgent message = payload.message; break; case Notification.MEDIA_APPROVED: - message = `Your ${mediaType} request has been approved.`; + message = `Your ${ + is4k ? '4K ' : '' + }${mediaType} request has been approved.`; break; case Notification.MEDIA_AUTO_APPROVED: - message = `Automatically approved a new ${mediaType} request from ${payload.request?.requestedBy.displayName}.`; + message = `Automatically approved a new ${ + is4k ? '4K ' : '' + }${mediaType} request from ${ + payload.request?.requestedBy.displayName + }.`; break; case Notification.MEDIA_AVAILABLE: - message = `Your ${mediaType} request is now available!`; + message = `Your ${ + is4k ? '4K ' : '' + }${mediaType} request is now available!`; break; case Notification.MEDIA_DECLINED: - message = `Your ${mediaType} request was declined.`; + message = `Your ${is4k ? '4K ' : ''}${mediaType} request was declined.`; break; case Notification.MEDIA_FAILED: - message = `Failed to process ${mediaType} request.`; + message = `Failed to process ${is4k ? '4K ' : ''}${mediaType} request.`; break; case Notification.MEDIA_PENDING: - message = `Approval required for a new ${mediaType} request from ${payload.request?.requestedBy.displayName}.`; + message = `Approval required for a new ${ + is4k ? '4K ' : '' + }${mediaType} request from ${ + payload.request?.requestedBy.displayName + }.`; break; case Notification.ISSUE_CREATED: message = `A new ${issueType} was reported by ${payload.issue?.createdBy.displayName}.`; diff --git a/server/subscriber/MediaSubscriber.ts b/server/subscriber/MediaSubscriber.ts index fe7043aa..7f391105 100644 --- a/server/subscriber/MediaSubscriber.ts +++ b/server/subscriber/MediaSubscriber.ts @@ -14,15 +14,19 @@ import notificationManager, { Notification } from '../lib/notifications'; @EventSubscriber() export class MediaSubscriber implements EntitySubscriberInterface { - private async notifyAvailableMovie(entity: Media, dbEntity?: Media) { + private async notifyAvailableMovie( + entity: Media, + dbEntity: Media, + is4k: boolean + ) { if ( - entity.status === MediaStatus.AVAILABLE && - dbEntity?.status !== MediaStatus.AVAILABLE + entity[is4k ? 'status4k' : 'status'] === MediaStatus.AVAILABLE && + dbEntity[is4k ? 'status4k' : 'status'] !== MediaStatus.AVAILABLE ) { if (entity.mediaType === MediaType.MOVIE) { const requestRepository = getRepository(MediaRequest); const relatedRequests = await requestRepository.find({ - where: { media: entity, is4k: false }, + where: { media: entity, is4k }, }); if (relatedRequests.length > 0) { @@ -31,7 +35,7 @@ export class MediaSubscriber implements EntitySubscriberInterface { relatedRequests.forEach((request) => { notificationManager.sendNotification(Notification.MEDIA_AVAILABLE, { - event: 'Movie Now Available', + event: `${is4k ? '4K ' : ''}Movie Request Now Available`, notifyAdmin: false, notifyUser: request.requestedBy, subject: `${movie.title}${ @@ -52,15 +56,25 @@ export class MediaSubscriber implements EntitySubscriberInterface { } } - private async notifyAvailableSeries(entity: Media, dbEntity: Media) { + private async notifyAvailableSeries( + entity: Media, + dbEntity: Media, + is4k: boolean + ) { const seasonRepository = getRepository(Season); const newAvailableSeasons = entity.seasons - .filter((season) => season.status === MediaStatus.AVAILABLE) + .filter( + (season) => + season[is4k ? 'status4k' : 'status'] === MediaStatus.AVAILABLE + ) .map((season) => season.seasonNumber); const oldSeasonIds = dbEntity.seasons.map((season) => season.id); const oldSeasons = await seasonRepository.findByIds(oldSeasonIds); const oldAvailableSeasons = oldSeasons - .filter((season) => season.status === MediaStatus.AVAILABLE) + .filter( + (season) => + season[is4k ? 'status4k' : 'status'] === MediaStatus.AVAILABLE + ) .map((season) => season.seasonNumber); const changedSeasons = newAvailableSeasons.filter( @@ -74,7 +88,7 @@ export class MediaSubscriber implements EntitySubscriberInterface { for (const changedSeasonNumber of changedSeasons) { const requests = await requestRepository.find({ - where: { media: entity, is4k: false }, + where: { media: entity, is4k: true }, }); const request = requests.find( (request) => @@ -93,7 +107,7 @@ export class MediaSubscriber implements EntitySubscriberInterface { ); const tv = await tmdb.getTvShow({ tvId: entity.tmdbId }); notificationManager.sendNotification(Notification.MEDIA_AVAILABLE, { - event: 'Series Now Available', + event: `${is4k ? '4K ' : ''}Series Request Now Available`, subject: `${tv.name}${ tv.first_air_date ? ` (${tv.first_air_date.slice(0, 4)})` : '' }`, @@ -148,7 +162,22 @@ export class MediaSubscriber implements EntitySubscriberInterface { event.entity.mediaType === MediaType.MOVIE && event.entity.status === MediaStatus.AVAILABLE ) { - this.notifyAvailableMovie(event.entity as Media, event.databaseEntity); + this.notifyAvailableMovie( + event.entity as Media, + event.databaseEntity, + false + ); + } + + if ( + event.entity.mediaType === MediaType.MOVIE && + event.entity.status4k === MediaStatus.AVAILABLE + ) { + this.notifyAvailableMovie( + event.entity as Media, + event.databaseEntity, + true + ); } if ( @@ -156,7 +185,23 @@ export class MediaSubscriber implements EntitySubscriberInterface { (event.entity.status === MediaStatus.AVAILABLE || event.entity.status === MediaStatus.PARTIALLY_AVAILABLE) ) { - this.notifyAvailableSeries(event.entity as Media, event.databaseEntity); + this.notifyAvailableSeries( + event.entity as Media, + event.databaseEntity, + false + ); + } + + if ( + event.entity.mediaType === MediaType.TV && + (event.entity.status4k === MediaStatus.AVAILABLE || + event.entity.status4k === MediaStatus.PARTIALLY_AVAILABLE) + ) { + this.notifyAvailableSeries( + event.entity as Media, + event.databaseEntity, + true + ); } if (