From afbd033a997b13e3123f9a848bdf34d43c653b35 Mon Sep 17 00:00:00 2001 From: lainon Date: Tue, 30 Aug 2022 13:23:29 +0300 Subject: [PATCH] refactor(engine, controller, checkers, tests) Add more null checks, getting rid of NullReferenceException, remove repeat code --- src/Ombi.Core.Tests/Engine/VoteEngineTests.cs | 1 - .../Engine/Demo/DemoTvSearchEngine.cs | 16 +-- src/Ombi.Core/Engine/UserDeletionEngine.cs | 7 +- src/Ombi.Core/Engine/UserStatsEngine.cs | 4 +- .../Engine/V2/MovieSearchEngineV2.cs | 2 +- src/Ombi.Core/Rule/RuleEvaluator.cs | 4 +- src/Ombi.Core/Senders/TvSender.cs | 2 +- src/Ombi.Mapping/Profiles/TvProfileV2.cs | 2 +- .../Agents/LegacyMobileNotification.cs | 2 +- .../NotificationMessageCurlys.cs | 2 +- src/Ombi.Notifications/NotificationService.cs | 2 +- .../Jobs/Emby/EmbyAvaliabilityChecker.cs | 97 +++++++++--------- .../Jellyfin/JellyfinAvaliabilityChecker.cs | 99 ++++++++++--------- .../Jobs/Ombi/RefreshMetadata.cs | 2 +- .../Jobs/Plex/PlexContentSync.cs | 4 +- .../Jobs/Plex/PlexWatchlistImport.cs | 2 +- .../Controllers/V1/External/EmbyController.cs | 2 +- .../V1/External/JellyfinController.cs | 2 +- .../Controllers/V1/External/PlexController.cs | 4 +- 19 files changed, 130 insertions(+), 126 deletions(-) diff --git a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs index 4194ae0ea..7cb19d995 100644 --- a/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs +++ b/src/Ombi.Core.Tests/Engine/VoteEngineTests.cs @@ -32,7 +32,6 @@ namespace Ombi.Core.Tests.Engine MusicRequestEngine = new Mock(); TvRequestEngine = new Mock(); MovieRequestEngine = new Mock(); - MovieRequestEngine = new Mock(); User = new Mock(); User.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "abc", NormalizedUserName = "ABC", Id = "abc" }); diff --git a/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs index 706a5337d..0a6138fcf 100644 --- a/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs +++ b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs @@ -40,16 +40,16 @@ namespace Ombi.Core.Engine.Demo { var searchResult = await TvMazeApi.Search(search); - for (var i = 0; i < searchResult.Count; i++) - { - if (!_demoLists.TvShows.Contains(searchResult[i].show?.externals?.thetvdb ?? 0)) - { - searchResult.RemoveAt(i); - } - } - if (searchResult != null) { + for (var i = 0; i < searchResult.Count; i++) + { + if (!_demoLists.TvShows.Contains(searchResult[i].show?.externals?.thetvdb ?? 0)) + { + searchResult.RemoveAt(i); + } + } + var retVal = new List(); foreach (var tvMazeSearch in searchResult) { diff --git a/src/Ombi.Core/Engine/UserDeletionEngine.cs b/src/Ombi.Core/Engine/UserDeletionEngine.cs index 1c8fd63ca..a7aef8196 100644 --- a/src/Ombi.Core/Engine/UserDeletionEngine.cs +++ b/src/Ombi.Core/Engine/UserDeletionEngine.cs @@ -46,16 +46,15 @@ namespace Ombi.Core.Engine { _movieRepository = movieRepository; _userManager = userManager; - _tvRepository = tvRepository; - _musicRepository = musicRepository; _issuesRepository = issueRepo; _issueCommentsRepository = issueCommentsRepo; - _notificationRepository = notificationidsRepo; _requestLogRepository = requestLogRepo; - _requestSubscriptionRepository = requestSubRepository; _notificationRepository = notificationidsRepo; + _requestSubscriptionRepository = requestSubRepository; _userNotificationPreferences = notificationPreferencesRepo; _userQualityProfiles = qualityProfilesRepo; + _tvRepository = tvRepository; + _musicRepository = musicRepository; _voteRepository = voteRepository; _mobileDevicesRepository = mobileDevicesRepository; _watchlistUserError = watchlistUserError; diff --git a/src/Ombi.Core/Engine/UserStatsEngine.cs b/src/Ombi.Core/Engine/UserStatsEngine.cs index f079aa156..fb8d049bc 100644 --- a/src/Ombi.Core/Engine/UserStatsEngine.cs +++ b/src/Ombi.Core/Engine/UserStatsEngine.cs @@ -46,8 +46,8 @@ namespace Ombi.Core.Engine TotalTvRequests = childrenCount, CompletedRequestsTv = availableChildren, CompletedRequestsMovies = availableMovies, - MostRequestedUserMovie = userMovie.FirstOrDefault()?.RequestedUser ?? new OmbiUser(), - MostRequestedUserTv = userTv.FirstOrDefault()?.RequestedUser ?? new OmbiUser(), + MostRequestedUserMovie = userMovie?.FirstOrDefault()?.RequestedUser ?? new OmbiUser(), + MostRequestedUserTv = userTv?.FirstOrDefault()?.RequestedUser ?? new OmbiUser(), }; } } diff --git a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs index 044d79969..e4f74a097 100644 --- a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs @@ -482,7 +482,7 @@ namespace Ombi.Core.Engine.V2 () => MovieApi.Find(imdbId, ExternalSource.imdb_id), DateTimeOffset.Now.AddHours(12)); var movie = findResult.movie_results.FirstOrDefault(); - var movieInfo = await Cache.GetOrAddAsync(nameof(GetMovieInfoByImdbId) + movie.id + langCode, + var movieInfo = await Cache.GetOrAddAsync(nameof(GetMovieInfoByImdbId) + movie?.id + langCode, () => MovieApi.GetFullMovieInfo(movie.id, cancellationToken, langCode), DateTimeOffset.Now.AddHours(12)); return await ProcessSingleMovie(movieInfo); diff --git a/src/Ombi.Core/Rule/RuleEvaluator.cs b/src/Ombi.Core/Rule/RuleEvaluator.cs index 712d6031e..c118a5416 100644 --- a/src/Ombi.Core/Rule/RuleEvaluator.cs +++ b/src/Ombi.Core/Rule/RuleEvaluator.cs @@ -84,7 +84,7 @@ namespace Ombi.Core.Rule var ctor = ctors.FirstOrDefault(); var services = new List(); - foreach (var param in ctor.GetParameters()) + foreach (var param in ctor?.GetParameters()) { services.Add(provider.GetService(param.ParameterType)); } @@ -106,7 +106,7 @@ namespace Ombi.Core.Rule var ctor = ctors.FirstOrDefault(); var services = new List(); - foreach (var param in ctor.GetParameters()) + foreach (var param in ctor?.GetParameters()) { services.Add(provider.GetService(param.ParameterType)); } diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index fd9cda22b..027b08ee3 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -365,7 +365,7 @@ namespace Ombi.Core.Senders // So we need to monitor the series but unmonitor every episode existingSeason.monitored = true; var sea = result.seasons.FirstOrDefault(x => x.seasonNumber == existingSeason.seasonNumber); - sea.monitored = true; + sea?.monitored = true; result = await SonarrApi.UpdateSeries(result, s.ApiKey, s.FullUri); var epToUnmonitored = new List(); diff --git a/src/Ombi.Mapping/Profiles/TvProfileV2.cs b/src/Ombi.Mapping/Profiles/TvProfileV2.cs index ba221582e..09021efb2 100644 --- a/src/Ombi.Mapping/Profiles/TvProfileV2.cs +++ b/src/Ombi.Mapping/Profiles/TvProfileV2.cs @@ -21,7 +21,7 @@ namespace Ombi.Mapping.Profiles .ForMember(dest => dest.ImdbId, opts => opts.MapFrom(src => src.ExternalIds.ImdbId)) .ForMember(dest => dest.TheTvDbId, opts => opts.MapFrom(src => src.ExternalIds.TvDbId)) .ForMember(dest => dest.Network, opts => opts.MapFrom(src => src.networks.FirstOrDefault())) - .ForMember(dest => dest.NetworkId, opts => opts.MapFrom(src => src.networks.FirstOrDefault()?.id)) + .ForMember(dest => dest.NetworkId, opts => opts.MapFrom(src => src.networks.FirstOrDefault().id)) .ForMember(dest => dest.Overview, opts => opts.MapFrom(src => src.overview)) .ForMember(dest => dest.Rating, opts => opts.MapFrom(src => src.vote_average.ToString(CultureInfo.CurrentUICulture))) diff --git a/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs b/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs index 9df7c6a94..19d1f4c44 100644 --- a/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs +++ b/src/Ombi.Notifications/Agents/LegacyMobileNotification.cs @@ -277,7 +277,7 @@ namespace Ombi.Notifications.Agents if (model.UserId.HasValue() && (!notificationIds?.Any() ?? true)) { var user = _userManager.Users.Include(x => x.NotificationUserIds).FirstOrDefault(x => x.Id == model.UserId); - notificationIds = user.NotificationUserIds; + notificationIds = user?.NotificationUserIds; } if (!notificationIds?.Any() ?? true) diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index 3c7857f8c..376b76572 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -25,7 +25,7 @@ namespace Ombi.Notifications { ApplicationName = string.IsNullOrEmpty(s?.ApplicationName) ? "Ombi" : s.ApplicationName; ApplicationUrl = s?.ApplicationUrl.HasValue() ?? false ? s.ApplicationUrl : string.Empty; - RequestedUser = user.UserName; + RequestedUser = user?.UserName; Alias = user.UserAlias; UserName = user.UserName; } diff --git a/src/Ombi.Notifications/NotificationService.cs b/src/Ombi.Notifications/NotificationService.cs index f22800cdc..ec0d3329e 100644 --- a/src/Ombi.Notifications/NotificationService.cs +++ b/src/Ombi.Notifications/NotificationService.cs @@ -70,7 +70,7 @@ namespace Ombi.Notifications var ctor = ctors.FirstOrDefault(); var services = new List(); - foreach (var param in ctor.GetParameters()) + foreach (var param in ctor?.GetParameters()) { services.Add(_provider.GetService(param.ParameterType)); } diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index 67ed8b97a..b95abdb2b 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -62,55 +62,58 @@ namespace Ombi.Schedule.Jobs.Emby foreach (var movie in movies) { - var has4kRequest = movie.Has4KRequest; - EmbyContent embyContent = null; - if (movie?.TheMovieDbId > 0) + if (movie != null) { - embyContent = await _repo.GetByTheMovieDbId(movie.TheMovieDbId.ToString()); - } - else if(movie.ImdbId.HasValue()) - { - embyContent = await _repo.GetByImdbId(movie.ImdbId); - } - - if (embyContent == null) - { - // We don't have this yet - continue; - } - - _log.LogInformation("We have found the request {0} on Emby, sending the notification", movie?.Title ?? string.Empty); - - var notify = false; - - if (has4kRequest && embyContent.Has4K && !movie.Available4K) - { - movie.Available4K = true; - movie.MarkedAsAvailable4K = DateTime.Now; - notify = true; - } - - // If we have a non-4k version or we don't care about versions, then mark as available - if (!movie.Available && ( !feature4kEnabled || embyContent.Quality != null )) - { - movie.Available = true; - movie.MarkedAsAvailable = DateTime.Now; - notify = true; - } - if (notify) - { - var recipient = movie.RequestedUser.Email.HasValue() ? movie.RequestedUser.Email : string.Empty; - - _log.LogDebug("MovieId: {0}, RequestUser: {1}", movie.Id, recipient); - - await _notificationService.Notify(new NotificationOptions + var has4kRequest = movie.Has4KRequest; + EmbyContent embyContent = null; + if (movie?.TheMovieDbId > 0) { - DateTime = DateTime.Now, - NotificationType = NotificationType.RequestAvailable, - RequestId = movie.Id, - RequestType = RequestType.Movie, - Recipient = recipient, - }); + embyContent = await _repo.GetByTheMovieDbId(movie.TheMovieDbId.ToString()); + } + else if (movie.ImdbId.HasValue()) + { + embyContent = await _repo.GetByImdbId(movie.ImdbId); + } + + if (embyContent == null) + { + // We don't have this yet + continue; + } + + _log.LogInformation("We have found the request {0} on Emby, sending the notification", movie?.Title ?? string.Empty); + + var notify = false; + + if (has4kRequest && embyContent.Has4K && !movie.Available4K) + { + movie.Available4K = true; + movie.MarkedAsAvailable4K = DateTime.Now; + notify = true; + } + + // If we have a non-4k version or we don't care about versions, then mark as available + if (!movie.Available && (!feature4kEnabled || embyContent.Quality != null)) + { + movie.Available = true; + movie.MarkedAsAvailable = DateTime.Now; + notify = true; + } + if (notify) + { + var recipient = movie.RequestedUser.Email.HasValue() ? movie.RequestedUser.Email : string.Empty; + + _log.LogDebug("MovieId: {0}, RequestUser: {1}", movie.Id, recipient); + + await _notificationService.Notify(new NotificationOptions + { + DateTime = DateTime.Now, + NotificationType = NotificationType.RequestAvailable, + RequestId = movie.Id, + RequestType = RequestType.Movie, + Recipient = recipient, + }); + } } } await _movieRepo.Save(); diff --git a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs index 7369e699b..e311e21b2 100644 --- a/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Jellyfin/JellyfinAvaliabilityChecker.cs @@ -87,56 +87,59 @@ namespace Ombi.Schedule.Jobs.Jellyfin foreach (var movie in movies) { - var has4kRequest = movie.Has4KRequest; - JellyfinContent jellyfinContent = null; - if (movie?.TheMovieDbId > 0) + if (movie != null) { - jellyfinContent = await _repo.GetByTheMovieDbId(movie.TheMovieDbId.ToString()); - } - else if(movie.ImdbId.HasValue()) - { - jellyfinContent = await _repo.GetByImdbId(movie.ImdbId); - } - - if (jellyfinContent == null) - { - // We don't have this yet - continue; - } - - _log.LogInformation("We have found the request {0} on Jellyfin, sending the notification", movie?.Title ?? string.Empty); - - var notify = false; - - if (has4kRequest && jellyfinContent.Has4K && !movie.Available4K) - { - movie.Available4K = true; - movie.MarkedAsAvailable4K = DateTime.Now; - notify = true; - } - - // If we have a non-4k version or we don't care about versions, then mark as available - if (!movie.Available && ( !feature4kEnabled || jellyfinContent.Quality != null )) - { - movie.Available = true; - movie.MarkedAsAvailable = DateTime.Now; - notify = true; - } - - if (notify) - { - var recipient = movie.RequestedUser.Email.HasValue() ? movie.RequestedUser.Email : string.Empty; - - _log.LogDebug("MovieId: {0}, RequestUser: {1}", movie.Id, recipient); - - await _notificationService.Notify(new NotificationOptions + var has4kRequest = movie.Has4KRequest; + JellyfinContent jellyfinContent = null; + if (movie?.TheMovieDbId > 0) { - DateTime = DateTime.Now, - NotificationType = NotificationType.RequestAvailable, - RequestId = movie.Id, - RequestType = RequestType.Movie, - Recipient = recipient, - }); + jellyfinContent = await _repo.GetByTheMovieDbId(movie.TheMovieDbId.ToString()); + } + else if (movie.ImdbId.HasValue()) + { + jellyfinContent = await _repo.GetByImdbId(movie.ImdbId); + } + + if (jellyfinContent == null) + { + // We don't have this yet + continue; + } + + _log.LogInformation("We have found the request {0} on Jellyfin, sending the notification", movie?.Title ?? string.Empty); + + var notify = false; + + if (has4kRequest && jellyfinContent.Has4K && !movie.Available4K) + { + movie.Available4K = true; + movie.MarkedAsAvailable4K = DateTime.Now; + notify = true; + } + + // If we have a non-4k version or we don't care about versions, then mark as available + if (!movie.Available && (!feature4kEnabled || jellyfinContent.Quality != null)) + { + movie.Available = true; + movie.MarkedAsAvailable = DateTime.Now; + notify = true; + } + + if (notify) + { + var recipient = movie.RequestedUser.Email.HasValue() ? movie.RequestedUser.Email : string.Empty; + + _log.LogDebug("MovieId: {0}, RequestUser: {1}", movie.Id, recipient); + + await _notificationService.Notify(new NotificationOptions + { + DateTime = DateTime.Now, + NotificationType = NotificationType.RequestAvailable, + RequestId = movie.Id, + RequestType = RequestType.Movie, + Recipient = recipient, + }); + } } } await _movieRepo.Save(); diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index 64abb2aac..9122f58e5 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -294,7 +294,7 @@ namespace Ombi.Schedule.Jobs.Ombi var guids = new List(); var meta = metaData.MediaContainer.Metadata.FirstOrDefault(); - guids.Add(meta.guid); + guids.Add(meta?.guid); if (meta.Guid != null) { foreach (var g in meta.Guid) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 9c5a651e2..174371272 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -354,7 +354,7 @@ namespace Ombi.Schedule.Jobs.Plex movie.ratingKey); var meta = metaData.MediaContainer.Metadata.FirstOrDefault(); - guids.Add(meta.guid); + guids.Add(meta?.guid); if (meta.Guid != null) { foreach (var g in meta.Guid) @@ -651,7 +651,7 @@ namespace Ombi.Schedule.Jobs.Plex var metadata = showMetadata.MediaContainer.Metadata.FirstOrDefault(); var guids = new List { - metadata.guid + metadata?.guid }; if (metadata.Guid != null) { diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs index 82b5a6d1a..6492351e2 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexWatchlistImport.cs @@ -205,7 +205,7 @@ namespace Ombi.Schedule.Jobs.Plex var metaData = await _plexApi.GetWatchlistMetadata(movie.ratingKey, authToken, cancellationToken); var meta = metaData.MediaContainer.Metadata.FirstOrDefault(); - guids.Add(meta.guid); + guids.Add(meta?.guid); if (meta.Guid != null) { foreach (var g in meta.Guid) diff --git a/src/Ombi/Controllers/V1/External/EmbyController.cs b/src/Ombi/Controllers/V1/External/EmbyController.cs index 04c06dc12..3d58e379a 100644 --- a/src/Ombi/Controllers/V1/External/EmbyController.cs +++ b/src/Ombi/Controllers/V1/External/EmbyController.cs @@ -46,7 +46,7 @@ namespace Ombi.Controllers.V1.External request.Enable = true; var firstServer = request.Servers.FirstOrDefault(); // Test that we can connect - var result = await client.GetUsers(firstServer.FullUri, firstServer.ApiKey); + var result = await client.GetUsers(firstServer?.FullUri, firstServer?.ApiKey); if (result != null && result.Any()) { diff --git a/src/Ombi/Controllers/V1/External/JellyfinController.cs b/src/Ombi/Controllers/V1/External/JellyfinController.cs index 4e295eac5..ebe3a3ff1 100644 --- a/src/Ombi/Controllers/V1/External/JellyfinController.cs +++ b/src/Ombi/Controllers/V1/External/JellyfinController.cs @@ -47,7 +47,7 @@ namespace Ombi.Controllers.V1.External request.Enable = true; var firstServer = request.Servers.FirstOrDefault(); // Test that we can connect - var result = await client.GetUsers(firstServer.FullUri, firstServer.ApiKey); + var result = await client.GetUsers(firstServer?.FullUri, firstServer?.ApiKey); if (result != null && result.Any()) { diff --git a/src/Ombi/Controllers/V1/External/PlexController.cs b/src/Ombi/Controllers/V1/External/PlexController.cs index 7cc0cc824..a292bc576 100644 --- a/src/Ombi/Controllers/V1/External/PlexController.cs +++ b/src/Ombi/Controllers/V1/External/PlexController.cs @@ -140,7 +140,7 @@ namespace Ombi.Controllers.V1.External { var s = await PlexSettings.GetSettingsAsync(); var settings = s.Servers.FirstOrDefault(x => x.MachineIdentifier == machineId); - var libs = await PlexApi.GetLibrariesForMachineId(settings.PlexAuthToken, machineId); + var libs = await PlexApi.GetLibrariesForMachineId(settings?.PlexAuthToken, machineId); return new PlexLibrariesLiteResponse { @@ -167,7 +167,7 @@ namespace Ombi.Controllers.V1.External { var s = await PlexSettings.GetSettingsAsync(); var server = s.Servers.FirstOrDefault(x => x.MachineIdentifier == user.MachineIdentifier); - var result = await PlexApi.AddUser(user.Username, user.MachineIdentifier, server.PlexAuthToken, + var result = await PlexApi.AddUser(user.Username, user.MachineIdentifier, server?.PlexAuthToken, user.LibsSelected); if (result.HasError) {