fix(mediarequests): changed lidarr notification and request to match new architecture
This was using an older architecture for the notifications and request, this change updates the system to match how movies and tv are done
This commit is contained in:
@@ -66,7 +66,7 @@ class MusicBrainz extends ExternalAPI {
|
||||
public async getAlbum({
|
||||
albumId,
|
||||
}: {
|
||||
albumId: string;
|
||||
albumId?: string;
|
||||
}): Promise<MbAlbumDetails> {
|
||||
try {
|
||||
const data = await this.get<MbAlbumDetails>(
|
||||
|
||||
@@ -47,7 +47,9 @@ class WebPushAgent
|
||||
const mediaType = payload.media
|
||||
? payload.media.mediaType === MediaType.MOVIE
|
||||
? 'movie'
|
||||
: 'series'
|
||||
: payload.media.mediaType === MediaType.TV
|
||||
? 'series'
|
||||
: 'album'
|
||||
: undefined;
|
||||
const is4k = payload.request?.is4k;
|
||||
|
||||
@@ -119,7 +121,9 @@ class WebPushAgent
|
||||
const actionUrl = payload.issue
|
||||
? `/issues/${payload.issue.id}`
|
||||
: payload.media
|
||||
? `/${payload.media.mediaType}/${payload.media.tmdbId}`
|
||||
? payload.media.mediaType === MediaType.MUSIC
|
||||
? `/music/${payload.media.mbId}`
|
||||
: `/${payload.media.mediaType}/${payload.media.tmdbId}`
|
||||
: undefined;
|
||||
|
||||
const actionUrlTitle = actionUrl
|
||||
|
||||
@@ -4,6 +4,8 @@ import type {
|
||||
AddSeriesOptions,
|
||||
SonarrSeries,
|
||||
} from '@server/api/servarr/sonarr';
|
||||
import LidarrAPI from '@server/api/servarr/lidarr';
|
||||
import MusicBrainz from '@server/api/musicbrainz'
|
||||
import SonarrAPI from '@server/api/servarr/sonarr';
|
||||
import TheMovieDb from '@server/api/themoviedb';
|
||||
import { ANIME_KEYWORD_ID } from '@server/api/themoviedb/constants';
|
||||
@@ -26,6 +28,7 @@ import type {
|
||||
InsertEvent,
|
||||
RemoveEvent,
|
||||
UpdateEvent,
|
||||
Not
|
||||
} from 'typeorm';
|
||||
import { EventSubscriber } from 'typeorm';
|
||||
|
||||
@@ -171,6 +174,65 @@ export class MediaRequestSubscriber
|
||||
}
|
||||
}
|
||||
|
||||
private async notifyAvailableMusic(
|
||||
entity: MediaRequest,
|
||||
event?: UpdateEvent<MediaRequest>
|
||||
) {
|
||||
|
||||
// Get fresh media state using event manager
|
||||
let latestMedia: Media | null = null;
|
||||
if (event?.manager) {
|
||||
latestMedia = await event.manager.findOne(Media, {
|
||||
where: { id: entity.media.id },
|
||||
});
|
||||
}
|
||||
if (!latestMedia) {
|
||||
const mediaRepository = getRepository(Media);
|
||||
latestMedia = await mediaRepository.findOne({
|
||||
where: { id: entity.media.id },
|
||||
});
|
||||
|
||||
if(!latestMedia
|
||||
|| latestMedia.mediaType !== MediaType.MUSIC
|
||||
|| latestMedia['status'] != MediaStatus.AVAILABLE)
|
||||
{
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const musicbrainz = new MusicBrainz();
|
||||
const albumDetails = await musicbrainz.getAlbum({
|
||||
albumId: latestMedia.mbId,
|
||||
});
|
||||
|
||||
const coverImage = albumDetails.images?.find(
|
||||
(img) => img.CoverType.toLowerCase() === 'cover'
|
||||
)?.Url;
|
||||
|
||||
notificationManager.sendNotification(
|
||||
Notification.MEDIA_AVAILABLE,
|
||||
{
|
||||
event: `Album Request Now Available`,
|
||||
notifyAdmin: false,
|
||||
notifySystem: true,
|
||||
notifyUser: entity.requestedBy,
|
||||
subject: albumDetails.title ?? latestMedia.mbId ?? 'Unknown Album',
|
||||
message: albumDetails.overview || 'Album is now available.',
|
||||
media: latestMedia,
|
||||
request: entity,
|
||||
image: coverImage,
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
logger.error('Something went wrong sending media notification(s)', {
|
||||
label: 'Notifications',
|
||||
errorMessage: e.message,
|
||||
mediaId: entity.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async sendToRadarr(entity: MediaRequest): Promise<void> {
|
||||
if (
|
||||
entity.status === MediaRequestStatus.APPROVED &&
|
||||
@@ -738,10 +800,10 @@ export class MediaRequestSubscriber
|
||||
}
|
||||
}
|
||||
|
||||
public async sendToLidarr(): Promise<void> {
|
||||
public async sendToLidarr(entity: MediaRequest): Promise<void> {
|
||||
if (
|
||||
this.status !== MediaRequestStatus.APPROVED ||
|
||||
this.type !== MediaType.MUSIC
|
||||
entity.status !== MediaRequestStatus.APPROVED ||
|
||||
entity.type !== MediaType.MUSIC
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -750,7 +812,7 @@ export class MediaRequestSubscriber
|
||||
const mediaRepository = getRepository(Media);
|
||||
const settings = getSettings();
|
||||
const media = await mediaRepository.findOne({
|
||||
where: { id: this.media.id },
|
||||
where: { id: entity.media.id },
|
||||
relations: { requests: true },
|
||||
});
|
||||
|
||||
@@ -759,21 +821,21 @@ export class MediaRequestSubscriber
|
||||
}
|
||||
|
||||
const lidarrSettings =
|
||||
this.serverId !== null && this.serverId >= 0
|
||||
? settings.lidarr.find((l) => l.id === this.serverId)
|
||||
entity.serverId !== null && entity.serverId >= 0
|
||||
? settings.lidarr.find((l) => l.id === entity.serverId)
|
||||
: settings.lidarr.find((l) => l.isDefault);
|
||||
|
||||
if (!lidarrSettings) {
|
||||
logger.warn('No valid Lidarr server configured', {
|
||||
label: 'Media Request',
|
||||
requestId: this.id,
|
||||
mediaId: this.media.id,
|
||||
requestId: entity.id,
|
||||
mediaId: entity.media.id,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const rootFolder = this.rootFolder || lidarrSettings.activeDirectory;
|
||||
const qualityProfile = this.profileId || lidarrSettings.activeProfileId;
|
||||
const rootFolder = entity.rootFolder || lidarrSettings.activeDirectory;
|
||||
const qualityProfile = entity.profileId || lidarrSettings.activeProfileId;
|
||||
const tags = lidarrSettings.tags?.map((t) => t.toString()) || [];
|
||||
|
||||
const lidarr = new LidarrAPI({
|
||||
@@ -881,26 +943,26 @@ export class MediaRequestSubscriber
|
||||
logger.error('Failed final album monitoring check', {
|
||||
label: 'Media Request',
|
||||
error: err.message,
|
||||
requestId: this.id,
|
||||
mediaId: this.media.id,
|
||||
albumId: album.id,
|
||||
requestId: entity.id,
|
||||
mediaId: entity.media.id,
|
||||
albumId: entity.id,
|
||||
});
|
||||
}
|
||||
}, 20000);
|
||||
|
||||
logger.info('Completed album monitoring setup', {
|
||||
label: 'Media Request',
|
||||
requestId: this.id,
|
||||
mediaId: this.media.id,
|
||||
albumId: album.id,
|
||||
requestId: entity.id,
|
||||
mediaId: entity.media.id,
|
||||
albumId: entity.id,
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error('Failed to process album monitoring', {
|
||||
label: 'Media Request',
|
||||
error: err.message,
|
||||
requestId: this.id,
|
||||
mediaId: this.media.id,
|
||||
albumId: album.id,
|
||||
requestId: entity.id,
|
||||
mediaId: entity.media.id,
|
||||
albumId: entity.id,
|
||||
});
|
||||
}
|
||||
}, 60000);
|
||||
@@ -934,8 +996,8 @@ export class MediaRequestSubscriber
|
||||
logger.error('Failed to process existing album', {
|
||||
label: 'Media Request',
|
||||
error: err.message,
|
||||
requestId: this.id,
|
||||
mediaId: this.media.id,
|
||||
requestId: entity.id,
|
||||
mediaId: entity.media.id,
|
||||
albumId: existingAlbum.id,
|
||||
});
|
||||
}
|
||||
@@ -943,9 +1005,9 @@ export class MediaRequestSubscriber
|
||||
}
|
||||
} else {
|
||||
const requestRepository = getRepository(MediaRequest);
|
||||
this.status = MediaRequestStatus.FAILED;
|
||||
entity.status = MediaRequestStatus.FAILED;
|
||||
await requestRepository.save(this);
|
||||
this.sendNotification(media, Notification.MEDIA_FAILED);
|
||||
MediaRequest.sendNotification(entity, media, Notification.MEDIA_FAILED);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -953,8 +1015,8 @@ export class MediaRequestSubscriber
|
||||
logger.error('Failed to process Lidarr request', {
|
||||
label: 'Media Request',
|
||||
error: e.message,
|
||||
requestId: this.id,
|
||||
mediaId: this.media.id,
|
||||
requestId: entity.id,
|
||||
mediaId: entity.media.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1060,6 +1122,7 @@ export class MediaRequestSubscriber
|
||||
|
||||
this.sendToRadarr(event.entity as MediaRequest);
|
||||
this.sendToSonarr(event.entity as MediaRequest);
|
||||
this.sendToLidarr(event.entity as MediaRequest);
|
||||
|
||||
this.updateParentStatus(event.entity as MediaRequest);
|
||||
|
||||
@@ -1070,6 +1133,9 @@ export class MediaRequestSubscriber
|
||||
if (event.entity.media.mediaType === MediaType.TV) {
|
||||
this.notifyAvailableSeries(event.entity as MediaRequest, event);
|
||||
}
|
||||
if (event.entity.media.mediaType === MediaType.MUSIC) {
|
||||
this.notifyAvailableMusic(event.entity as MediaRequest, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1080,6 +1146,7 @@ export class MediaRequestSubscriber
|
||||
|
||||
this.sendToRadarr(event.entity as MediaRequest);
|
||||
this.sendToSonarr(event.entity as MediaRequest);
|
||||
this.sendToLidarr(event.entity as MediaRequest);
|
||||
|
||||
this.updateParentStatus(event.entity as MediaRequest);
|
||||
}
|
||||
|
||||
@@ -109,6 +109,11 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
|
||||
|
||||
const allSeasonsReady = allSeasonResults.every((result) => result);
|
||||
shouldComplete = allSeasonsReady;
|
||||
} else if (event.mediaType === MediaType.MUSIC)
|
||||
{
|
||||
if(event['status'] == MediaStatus.AVAILABLE || event['status'] === MediaStatus.DELETED) {
|
||||
shouldComplete = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldComplete) {
|
||||
|
||||
Reference in New Issue
Block a user