diff --git a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexAvailabilityChecker.cs index 3de9749d6..2d115ab88 100644 --- a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexAvailabilityChecker.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; namespace Ombi.Schedule.Jobs.Plex { diff --git a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexEpisodeSync.cs index ede393790..7de7c3c0c 100644 --- a/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/Interfaces/IPlexEpisodeSync.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Ombi.Api.Plex.Models; @@ -9,6 +10,6 @@ namespace Ombi.Schedule.Jobs.Plex.Interfaces public interface IPlexEpisodeSync : IBaseJob { Task Start(); - Task ProcessEpsiodes(Metadata[] episodes, IQueryable currentEpisodes); + Task> ProcessEpsiodes(Metadata[] episodes, IQueryable currentEpisodes); } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs b/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs new file mode 100644 index 000000000..be70d0029 --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Plex/Models/ProcessedContent.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Ombi.Schedule.Jobs.Plex.Models +{ + public class ProcessedContent + { + public IEnumerable Content { get; set; } + public IEnumerable Episodes { get; set; } + + public bool HasProcessedContent => Content.Any(); + public bool HasProcessedEpisodes => Episodes.Any(); + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index 343c4256e..9c86a13c4 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -4,10 +4,12 @@ using System.Linq; using System.Threading.Tasks; using Hangfire; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Notifications.Models; using Ombi.Store.Entities; +using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; @@ -16,13 +18,14 @@ namespace Ombi.Schedule.Jobs.Plex public class PlexAvailabilityChecker : IPlexAvailabilityChecker { public PlexAvailabilityChecker(IPlexContentRepository repo, ITvRequestRepository tvRequest, IMovieRequestRepository movies, - INotificationService notification, IBackgroundJobClient background) + INotificationService notification, IBackgroundJobClient background, ILogger log) { _tvRepo = tvRequest; _repo = repo; _movieRepo = movies; _notificationService = notification; _backgroundJobClient = background; + _log = log; } private readonly ITvRequestRepository _tvRepo; @@ -30,16 +33,29 @@ namespace Ombi.Schedule.Jobs.Plex private readonly IPlexContentRepository _repo; private readonly INotificationService _notificationService; private readonly IBackgroundJobClient _backgroundJobClient; + private readonly ILogger _log; public async Task Start() { - await ProcessMovies(); - await ProcessTv(); + try + { + await ProcessMovies(); + await ProcessTv(); + } + catch (Exception e) + { + _log.LogError(e, "Exception thrown in Plex availbility checker"); + } } - private async Task ProcessTv() + private Task ProcessTv() { var tv = _tvRepo.GetChild().Where(x => !x.Available); + return ProcessTv(tv); + } + + private async Task ProcessTv(IQueryable tv) + { var plexEpisodes = _repo.GetAllEpisodes().Include(x => x.Series); foreach (var child in tv) @@ -81,6 +97,10 @@ namespace Ombi.Schedule.Jobs.Plex { foreach (var episode in season.Episodes) { + if (episode.Available) + { + continue; + } var foundEp = await seriesEpisodes.FirstOrDefaultAsync( x => x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == episode.Season.SeasonNumber); diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 7fdb5d19a..fec69bcc3 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -39,6 +39,7 @@ using Ombi.Core.Settings.Models.External; using Ombi.Helpers; using Ombi.Schedule.Jobs.Ombi; using Ombi.Schedule.Jobs.Plex.Interfaces; +using Ombi.Schedule.Jobs.Plex.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -47,7 +48,7 @@ namespace Ombi.Schedule.Jobs.Plex public class PlexContentSync : IPlexContentSync { public PlexContentSync(ISettingsService plex, IPlexApi plexApi, ILogger logger, IPlexContentRepository repo, - IPlexEpisodeSync epsiodeSync, IRefreshMetadata metadataRefresh) + IPlexEpisodeSync epsiodeSync, IRefreshMetadata metadataRefresh, IPlexAvailabilityChecker checker) { Plex = plex; PlexApi = plexApi; @@ -55,6 +56,7 @@ namespace Ombi.Schedule.Jobs.Plex Repo = repo; EpisodeSync = epsiodeSync; Metadata = metadataRefresh; + Checker = checker; plex.ClearCache(); } @@ -64,6 +66,7 @@ namespace Ombi.Schedule.Jobs.Plex private IPlexContentRepository Repo { get; } private IPlexEpisodeSync EpisodeSync { get; } private IRefreshMetadata Metadata { get; } + private IPlexAvailabilityChecker Checker { get; } public async Task CacheContent(bool recentlyAddedSearch = false) { @@ -77,17 +80,13 @@ namespace Ombi.Schedule.Jobs.Plex Logger.LogError("Plex Settings are not valid"); return; } - var processedContent = new HashSet(); + var processedContent = new ProcessedContent(); Logger.LogInformation("Starting Plex Content Cacher"); try { if (recentlyAddedSearch) { - var result = await StartTheCache(plexSettings, true); - foreach (var r in result) - { - processedContent.Add(r); - } + processedContent = await StartTheCache(plexSettings, true); } else { @@ -105,31 +104,32 @@ namespace Ombi.Schedule.Jobs.Plex BackgroundJob.Enqueue(() => EpisodeSync.Start()); } - if (processedContent.Any() && recentlyAddedSearch) + if (processedContent.HasProcessedContent && recentlyAddedSearch) { // Just check what we send it - BackgroundJob.Enqueue(() => Metadata.ProcessPlexServerContent(processedContent)); + BackgroundJob.Enqueue(() => Metadata.ProcessPlexServerContent(processedContent.Content)); + } + + if (processedContent.HasProcessedEpisodes && recentlyAddedSearch) + { + BackgroundJob.Enqueue(() => Checker.Start()); } } - private async Task> StartTheCache(PlexSettings plexSettings, bool recentlyAddedSearch) + private async Task StartTheCache(PlexSettings plexSettings, bool recentlyAddedSearch) { - var processedContent = new HashSet(); + var processedContent = new ProcessedContent(); foreach (var servers in plexSettings.Servers ?? new List()) { try { - Logger.LogInformation("Starting to cache the content on server {0}", servers.Name); - + Logger.LogInformation("Starting to cache the content on server {0}", servers.Name); + if (recentlyAddedSearch) { // If it's recently added search then we want the results to pass to the metadata job // This way the metadata job is smaller in size to process, it only need to look at newly added shit - var result = await ProcessServer(servers, true); - foreach (var plexServerContent in result) - { - processedContent.Add(plexServerContent); - } + return await ProcessServer(servers, true); } else { @@ -145,9 +145,11 @@ namespace Ombi.Schedule.Jobs.Plex return processedContent; } - private async Task> ProcessServer(PlexServers servers, bool recentlyAddedSearch) + private async Task ProcessServer(PlexServers servers, bool recentlyAddedSearch) { - var processedContent = new Dictionary(); + var retVal = new ProcessedContent(); + var contentProcessed = new Dictionary(); + var episodesProcessed = new List(); Logger.LogInformation("Getting all content from server {0}", servers.Name); var allContent = await GetAllContent(servers, recentlyAddedSearch); Logger.LogInformation("We found {0} items", allContent.Count); @@ -170,12 +172,12 @@ namespace Ombi.Schedule.Jobs.Plex // Lookup the rating key var showMetadata = await PlexApi.GetMetadata(servers.PlexAuthToken, servers.FullUri, grandParentKey); var show = showMetadata.MediaContainer.Metadata.FirstOrDefault(); - if(show == null) + if (show == null) { continue; } - await ProcessTvShow(servers, show, contentToAdd, processedContent); + await ProcessTvShow(servers, show, contentToAdd, contentProcessed); if (contentToAdd.Any()) { await Repo.AddRange(contentToAdd, false); @@ -183,7 +185,7 @@ namespace Ombi.Schedule.Jobs.Plex { foreach (var plexServerContent in contentToAdd) { - processedContent.Add(plexServerContent.Id, plexServerContent.Key); + contentProcessed.Add(plexServerContent.Id, plexServerContent.Key); } } contentToAdd.Clear(); @@ -198,7 +200,8 @@ namespace Ombi.Schedule.Jobs.Plex // Save just to make sure we don't leave anything hanging await Repo.SaveChangesAsync(); - await EpisodeSync.ProcessEpsiodes(content.Metadata, allEps); + var episodesAdded = await EpisodeSync.ProcessEpsiodes(content.Metadata, allEps); + episodesProcessed.AddRange(episodesAdded.Select(x => x.Id)); } if (content.viewGroup.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase)) { @@ -208,7 +211,7 @@ namespace Ombi.Schedule.Jobs.Plex foreach (var show in content.Metadata ?? new Metadata[] { }) { count++; - await ProcessTvShow(servers, show, contentToAdd, processedContent); + await ProcessTvShow(servers, show, contentToAdd, contentProcessed); if (contentToAdd.Any()) { @@ -217,7 +220,7 @@ namespace Ombi.Schedule.Jobs.Plex { foreach (var plexServerContent in contentToAdd) { - processedContent.Add(plexServerContent.Id, plexServerContent.Key); + contentProcessed.Add(plexServerContent.Id, plexServerContent.Key); } } contentToAdd.Clear(); @@ -299,7 +302,7 @@ namespace Ombi.Schedule.Jobs.Plex await Repo.AddRange(contentToAdd); foreach (var c in contentToAdd) { - processedContent.Add(c.Id, c.Key); + contentProcessed.Add(c.Id, c.Key); } contentToAdd.Clear(); } @@ -310,7 +313,7 @@ namespace Ombi.Schedule.Jobs.Plex await Repo.AddRange(contentToAdd); foreach (var c in contentToAdd) { - processedContent.Add(c.Id, c.Key); + contentProcessed.Add(c.Id, c.Key); } contentToAdd.Clear(); } @@ -321,14 +324,16 @@ namespace Ombi.Schedule.Jobs.Plex await Repo.AddRange(contentToAdd); foreach (var c in contentToAdd) { - processedContent.Add(c.Id, c.Key); + contentProcessed.Add(c.Id, c.Key); } } - return processedContent.Values; + retVal.Content = contentProcessed.Values; + retVal.Episodes = episodesProcessed; + return retVal; } - private async Task ProcessTvShow(PlexServers servers, Metadata show, HashSet contentToAdd, Dictionary contentProcessed) + private async Task ProcessTvShow(PlexServers servers, Metadata show, HashSet contentToAdd, Dictionary contentProcessed) { var seasonList = await PlexApi.GetSeasons(servers.PlexAuthToken, servers.FullUri, show.ratingKey); @@ -349,7 +354,7 @@ namespace Ombi.Schedule.Jobs.Plex var existingContent = await Repo.GetFirstContentByCustom(x => x.Title == show.title && x.ReleaseYear == show.year.ToString() && x.Type == PlexMediaTypeEntity.Show); - + // Just double check the rating key, since this is our unique constraint var existingKey = await Repo.GetByKey(show.ratingKey); @@ -422,6 +427,26 @@ namespace Ombi.Schedule.Jobs.Plex if (seasonExists != null) { // We already have this season + // check if we have the episode + //if (episode != null) + //{ + // var existing = existingContent.Episodes.Any(x => + // x.SeasonNumber == episode.parentIndex && x.EpisodeNumber == episode.index); + // if (!existing) + // { + // // We don't have this episode, lets add it + // existingContent.Episodes.Add(new PlexEpisode + // { + // EpisodeNumber = episode.index, + // SeasonNumber = episode.parentIndex, + // GrandparentKey = episode.grandparentRatingKey, + // ParentKey = episode.parentRatingKey, + // Key = episode.ratingKey, + // Title = episode.title + // }); + // itemAdded = true; + // } + //} continue; } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs index d98eace4a..5652d126b 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexEpisodeSync.cs @@ -129,7 +129,7 @@ namespace Ombi.Schedule.Jobs.Plex await _repo.SaveChangesAsync(); } - public async Task ProcessEpsiodes(Metadata[] episodes, IQueryable currentEpisodes) + public async Task> ProcessEpsiodes(Metadata[] episodes, IQueryable currentEpisodes) { var ep = new HashSet(); try @@ -179,6 +179,7 @@ namespace Ombi.Schedule.Jobs.Plex } await _repo.AddRange(ep); + return ep; } catch (Exception e) { diff --git a/src/Ombi.Store/Repository/PlexContentRepository.cs b/src/Ombi.Store/Repository/PlexContentRepository.cs index 098466310..e452eeb7d 100644 --- a/src/Ombi.Store/Repository/PlexContentRepository.cs +++ b/src/Ombi.Store/Repository/PlexContentRepository.cs @@ -89,6 +89,7 @@ namespace Ombi.Store.Repository { return await Db.PlexServerContent .Include(x => x.Seasons) + .Include(x => x.Episodes) .FirstOrDefaultAsync(predicate); }