diff --git a/src/Ombi.Core/Engine/VoteEngine.cs b/src/Ombi.Core/Engine/VoteEngine.cs index 7c4d48a6f..5c73e03d9 100644 --- a/src/Ombi.Core/Engine/VoteEngine.cs +++ b/src/Ombi.Core/Engine/VoteEngine.cs @@ -11,7 +11,7 @@ using Ombi.Core.Models; using Ombi.Core.Models.UI; using Ombi.Core.Rule.Interfaces; using Ombi.Core.Settings; -using Ombi.Schedule.Jobs.Ombi; +using Ombi.Helpers; using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; using Ombi.Store.Repository; @@ -114,7 +114,7 @@ namespace Ombi.Core.Engine foreach (var epInformation in childRequests.SeasonRequests.OrderBy(x => x.SeasonNumber)) { var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); - var episodeString = NewsletterJob.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); + var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString}"); finalsb.Append("
"); } diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index 10e07822a..644c02515 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -20,16 +20,17 @@ + + - diff --git a/src/Ombi.Core/Senders/MovieSender.cs b/src/Ombi.Core/Senders/MovieSender.cs index 844caced3..49a6c9efa 100644 --- a/src/Ombi.Core/Senders/MovieSender.cs +++ b/src/Ombi.Core/Senders/MovieSender.cs @@ -76,16 +76,28 @@ namespace Ombi.Core.Senders } catch (Exception e) { - Log.LogError(e, "Error when seing movie to DVR app, added to the request queue"S); - await _requestQueuRepository.Add(new RequestQueue + Log.LogError(e, "Error when seing movie to DVR app, added to the request queue"); + + // Check if already in request quee + var existingQueue = await _requestQueuRepository.FirstOrDefaultAsync(x => x.RequestId == model.Id); + if (existingQueue != null) + { + existingQueue.RetryCount++; + existingQueue.Error = e.Message; + await _requestQueuRepository.SaveChangesAsync(); + } + else { - Dts = DateTime.UtcNow, - Error = e.Message, - RequestId = model.Id, - Type = RequestType.Movie, - RetryCount = 0 - }); - _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); + await _requestQueuRepository.Add(new RequestQueue + { + Dts = DateTime.UtcNow, + Error = e.Message, + RequestId = model.Id, + Type = RequestType.Movie, + RetryCount = 0 + }); + _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); + } } return new SenderResult diff --git a/src/Ombi.Core/Senders/MusicSender.cs b/src/Ombi.Core/Senders/MusicSender.cs index 235ea3db8..b016e76b5 100644 --- a/src/Ombi.Core/Senders/MusicSender.cs +++ b/src/Ombi.Core/Senders/MusicSender.cs @@ -49,15 +49,25 @@ namespace Ombi.Core.Senders catch (Exception e) { _log.LogError(e, "Exception thrown when sending a music to DVR app, added to the request queue"); - await _requestQueueRepository.Add(new RequestQueue + var existingQueue = await _requestQueueRepository.FirstOrDefaultAsync(x => x.RequestId == model.Id); + if (existingQueue != null) { - Dts = DateTime.UtcNow, - Error = e.Message, - RequestId = model.Id, - Type = RequestType.Album, - RetryCount = 0 - }); - _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); + existingQueue.RetryCount++; + existingQueue.Error = e.Message; + await _requestQueueRepository.SaveChangesAsync(); + } + else + { + await _requestQueueRepository.Add(new RequestQueue + { + Dts = DateTime.UtcNow, + Error = e.Message, + RequestId = model.Id, + Type = RequestType.Album, + RetryCount = 0 + }); + _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); + } } diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index c590e52ca..cc686aa38 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -52,72 +52,81 @@ namespace Ombi.Core.Senders { try { - - - var sonarr = await SonarrSettings.GetSettingsAsync(); - if (sonarr.Enabled) - { - var result = await SendToSonarr(model); - if (result != null) + var sonarr = await SonarrSettings.GetSettingsAsync(); + if (sonarr.Enabled) { - return new SenderResult + var result = await SendToSonarr(model); + if (result != null) { - Sent = true, - Success = true - }; + return new SenderResult + { + Sent = true, + Success = true + }; + } } - } - var dog = await DogNzbSettings.GetSettingsAsync(); - if (dog.Enabled) - { - var result = await SendToDogNzb(model, dog); - if (!result.Failure) + var dog = await DogNzbSettings.GetSettingsAsync(); + if (dog.Enabled) { + var result = await SendToDogNzb(model, dog); + if (!result.Failure) + { + return new SenderResult + { + Sent = true, + Success = true + }; + } return new SenderResult { - Sent = true, - Success = true + Message = result.ErrorMessage }; } - return new SenderResult - { - Message = result.ErrorMessage - }; - } - var sr = await SickRageSettings.GetSettingsAsync(); - if (sr.Enabled) - { - var result = await SendToSickRage(model, sr); - if (result) + var sr = await SickRageSettings.GetSettingsAsync(); + if (sr.Enabled) { + var result = await SendToSickRage(model, sr); + if (result) + { + return new SenderResult + { + Sent = true, + Success = true + }; + } return new SenderResult { - Sent = true, - Success = true + Message = "Could not send to SickRage!" }; } return new SenderResult { - Message = "Could not send to SickRage!" + Success = true }; } - return new SenderResult - { - Success = true - }; - } catch (Exception e) { Logger.LogError(e, "Exception thrown when sending a movie to DVR app, added to the request queue"); - await _requestQueueRepository.Add(new RequestQueue + // Check if already in request quee + var existingQueue = await _requestQueueRepository.FirstOrDefaultAsync(x => x.RequestId == model.Id); + if (existingQueue != null) { - Dts = DateTime.UtcNow, - Error = e.Message, - RequestId = model.Id, - Type = RequestType.TvShow, - RetryCount = 0 - }); - _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); + existingQueue.RetryCount++; + existingQueue.Error = e.Message; + await _requestQueueRepository.SaveChangesAsync(); + } + else + { + await _requestQueueRepository.Add(new RequestQueue + { + Dts = DateTime.UtcNow, + Error = e.Message, + RequestId = model.Id, + Type = RequestType.TvShow, + RetryCount = 0 + }); + _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); + } } return new SenderResult @@ -171,7 +180,7 @@ namespace Ombi.Core.Senders } if (profiles.SonarrQualityProfileAnime > 0) { - qualityToUse = profiles.SonarrQualityProfileAnime; + qualityToUse = profiles.SonarrQualityProfileAnime; } } seriesType = "anime"; @@ -191,7 +200,7 @@ namespace Ombi.Core.Senders } if (profiles.SonarrQualityProfile > 0) { - qualityToUse = profiles.SonarrQualityProfile; + qualityToUse = profiles.SonarrQualityProfile; } } seriesType = "standard"; @@ -202,7 +211,7 @@ namespace Ombi.Core.Senders { qualityToUse = model.ParentRequest.QualityOverride.Value; } - + try { // Does the series actually exist? @@ -296,7 +305,7 @@ namespace Ombi.Core.Senders } } var seriesChanges = false; - + foreach (var season in model.SeasonRequests) { var sonarrSeason = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber); diff --git a/src/Ombi.Helpers/StringHelper.cs b/src/Ombi.Helpers/StringHelper.cs index c198301fc..68a29e848 100644 --- a/src/Ombi.Helpers/StringHelper.cs +++ b/src/Ombi.Helpers/StringHelper.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Security; @@ -76,6 +77,49 @@ namespace Ombi.Helpers return -1; } + public static string BuildEpisodeList(IEnumerable orderedEpisodes) + { + var epSb = new StringBuilder(); + var previousEpisodes = new List(); + var previousEpisode = -1; + foreach (var ep in orderedEpisodes) + { + if (ep - 1 == previousEpisode) + { + // This is the next one + previousEpisodes.Add(ep); + } + else + { + if (previousEpisodes.Count > 1) + { + // End it + epSb.Append($"{previousEpisodes.First()}-{previousEpisodes.Last()}, "); + } + else if (previousEpisodes.Count == 1) + { + epSb.Append($"{previousEpisodes.FirstOrDefault()}, "); + } + // New one + previousEpisodes.Clear(); + previousEpisodes.Add(ep); + } + previousEpisode = ep; + } + + if (previousEpisodes.Count > 1) + { + // Got some left over + epSb.Append($"{previousEpisodes.First()}-{previousEpisodes.Last()}"); + } + else if (previousEpisodes.Count == 1) + { + epSb.Append(previousEpisodes.FirstOrDefault()); + } + + return epSb.ToString(); + } + public static string RemoveSpaces(this string str) { return str.Replace(" ", ""); diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs index 7ce32de04..fa111d5f4 100644 --- a/src/Ombi.Schedule/JobSetup.cs +++ b/src/Ombi.Schedule/JobSetup.cs @@ -21,7 +21,7 @@ namespace Ombi.Schedule IEmbyUserImporter embyUserImporter, ISonarrSync cache, ICouchPotatoSync cpCache, ISettingsService jobsettings, ISickRageSync srSync, IRefreshMetadata refresh, INewsletterJob newsletter, IPlexRecentlyAddedSync recentlyAddedPlex, ILidarrArtistSync artist, - IIssuesPurge purge) + IIssuesPurge purge, IResendFailedRequests resender) { _plexContentSync = plexContentSync; _radarrSync = radarrSync; @@ -38,6 +38,7 @@ namespace Ombi.Schedule _plexRecentlyAddedSync = recentlyAddedPlex; _lidarrArtistSync = artist; _issuesPurge = purge; + _resender = resender; } private readonly IPlexContentSync _plexContentSync; @@ -55,6 +56,7 @@ namespace Ombi.Schedule private readonly INewsletterJob _newsletter; private readonly ILidarrArtistSync _lidarrArtistSync; private readonly IIssuesPurge _issuesPurge; + private readonly IResendFailedRequests _resender; public void Setup() { @@ -76,6 +78,8 @@ namespace Ombi.Schedule RecurringJob.AddOrUpdate(() => _embyUserImporter.Start(), JobSettingsHelper.UserImporter(s)); RecurringJob.AddOrUpdate(() => _plexUserImporter.Start(), JobSettingsHelper.UserImporter(s)); RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s)); + RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s)); + RecurringJob.AddOrUpdate(() => _resender.Start(), JobSettingsHelper.ResendFailedRequests(s)); } diff --git a/src/Ombi.Schedule/Jobs/Ombi/IResendFailedRequests.cs b/src/Ombi.Schedule/Jobs/Ombi/IResendFailedRequests.cs new file mode 100644 index 000000000..b55c0f69b --- /dev/null +++ b/src/Ombi.Schedule/Jobs/Ombi/IResendFailedRequests.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Ombi.Schedule.Jobs.Ombi +{ + public interface IResendFailedRequests + { + Task Start(); + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 472cd325b..ab0ef9578 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -677,7 +677,7 @@ namespace Ombi.Schedule.Jobs.Ombi foreach (var epInformation in results.OrderBy(x => x.SeasonNumber)) { var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); - var episodeString = BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); + var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString}"); finalsb.Append("
"); } @@ -715,48 +715,7 @@ namespace Ombi.Schedule.Jobs.Ombi } } - public static string BuildEpisodeList(IEnumerable orderedEpisodes) - { - var epSb = new StringBuilder(); - var previousEpisodes = new List(); - var previousEpisode = -1; - foreach (var ep in orderedEpisodes) - { - if (ep - 1 == previousEpisode) - { - // This is the next one - previousEpisodes.Add(ep); - } - else - { - if (previousEpisodes.Count > 1) - { - // End it - epSb.Append($"{previousEpisodes.First()}-{previousEpisodes.Last()}, "); - } - else if (previousEpisodes.Count == 1) - { - epSb.Append($"{previousEpisodes.FirstOrDefault()}, "); - } - // New one - previousEpisodes.Clear(); - previousEpisodes.Add(ep); - } - previousEpisode = ep; - } - - if (previousEpisodes.Count > 1) - { - // Got some left over - epSb.Append($"{previousEpisodes.First()}-{previousEpisodes.Last()}"); - } - else if(previousEpisodes.Count == 1) - { - epSb.Append(previousEpisodes.FirstOrDefault()); - } - - return epSb.ToString(); - } + private async Task ProcessEmbyTv(HashSet embyContent, StringBuilder sb) { @@ -841,7 +800,7 @@ namespace Ombi.Schedule.Jobs.Ombi foreach (var epInformation in results.OrderBy(x => x.SeasonNumber)) { var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); - var episodeString = BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); + var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString}"); finalsb.Append("
"); } diff --git a/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs b/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs index 1e7b8d760..bc8f93a97 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/ResendFailedRequests.cs @@ -1,19 +1,75 @@ -using System.Threading.Tasks; +using System; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Ombi.Core; +using Ombi.Core.Senders; using Ombi.Store.Entities; using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; namespace Ombi.Schedule.Jobs.Ombi { - public class ResendFailedRequests + public class ResendFailedRequests : IResendFailedRequests { - public ResendFailedRequests(IRepository queue, IMovieSender movieSender) + public ResendFailedRequests(IRepository queue, IMovieSender movieSender, ITvSender tvSender, IMusicSender musicSender, + IMovieRequestRepository movieRepo, ITvRequestRepository tvRepo, IMusicRequestRepository music) { - + _requestQueue = queue; + _movieSender = movieSender; + _tvSender = tvSender; + _musicSender = musicSender; + _movieRequestRepository = movieRepo; + _tvRequestRepository = tvRepo; + _musicRequestRepository = music; } + private readonly IRepository _requestQueue; + private readonly IMovieSender _movieSender; + private readonly ITvSender _tvSender; + private readonly IMusicSender _musicSender; + private readonly IMovieRequestRepository _movieRequestRepository; + private readonly ITvRequestRepository _tvRequestRepository; + private readonly IMusicRequestRepository _musicRequestRepository; + public async Task Start() { + // Get all the failed ones! + var failedRequests = _requestQueue.GetAll().Where(x => !x.Completed.HasValue); + foreach (var request in failedRequests) + { + if (request.Type == RequestType.Movie) + { + var movieRequest = await _movieRequestRepository.GetAll().FirstOrDefaultAsync(x => x.Id == request.RequestId); + var result = await _movieSender.Send(movieRequest); + if (result.Success) + { + request.Completed = DateTime.UtcNow; + await _requestQueue.SaveChangesAsync(); + } + } + if (request.Type == RequestType.TvShow) + { + var tvRequest = await _tvRequestRepository.GetChild().FirstOrDefaultAsync(x => x.Id == request.RequestId); + var result = await _tvSender.Send(tvRequest); + if (result.Success) + { + request.Completed = DateTime.UtcNow; + await _requestQueue.SaveChangesAsync(); + } + } + if (request.Type == RequestType.Album) + { + var musicRequest = await _musicRequestRepository.GetAll().FirstOrDefaultAsync(x => x.Id == request.RequestId); + var result = await _musicSender.Send(musicRequest); + if (result.Success) + { + request.Completed = DateTime.UtcNow; + await _requestQueue.SaveChangesAsync(); + } + } + } } } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Ombi.Schedule.csproj b/src/Ombi.Schedule/Ombi.Schedule.csproj index 06cc2bb49..94657e922 100644 --- a/src/Ombi.Schedule/Ombi.Schedule.csproj +++ b/src/Ombi.Schedule/Ombi.Schedule.csproj @@ -34,6 +34,7 @@ + diff --git a/src/Ombi.Settings/Settings/Models/JobSettings.cs b/src/Ombi.Settings/Settings/Models/JobSettings.cs index 8b283cdf7..46a950185 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettings.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettings.cs @@ -15,5 +15,6 @@ public string Newsletter { get; set; } public string LidarrArtistSync { get; set; } public string IssuesPurge { get; set; } + public string RetryRequests { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs index 4491ca27a..1aca72344 100644 --- a/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs +++ b/src/Ombi.Settings/Settings/Models/JobSettingsHelper.cs @@ -61,6 +61,10 @@ namespace Ombi.Settings.Settings.Models { return Get(s.IssuesPurge, Cron.Daily()); } + public static string ResendFailedRequests(JobSettings s) + { + return Get(s.RetryRequests, Cron.Daily(6)); + } private static string Get(string settings, string defaultCron) { diff --git a/src/Ombi.Store/Entities/RequestQueue.cs b/src/Ombi.Store/Entities/RequestQueue.cs index e561f9ec7..85f73e04b 100644 --- a/src/Ombi.Store/Entities/RequestQueue.cs +++ b/src/Ombi.Store/Entities/RequestQueue.cs @@ -10,7 +10,7 @@ namespace Ombi.Store.Entities public RequestType Type { get; set; } public DateTime Dts { get; set; } public string Error { get; set; } - public DateTime Completed { get; set; } + public DateTime? Completed { get; set; } public int RetryCount { get; set; } } } \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index f1934a994..7e57c0e64 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -145,6 +145,7 @@ export interface IJobSettings { plexRecentlyAddedSync: string; lidarrArtistSync: string; issuesPurge: string; + retryRequests: string; } export interface IIssueSettings extends ISettings { diff --git a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html index 1365710f0..e889c0fca 100644 --- a/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/app/settings/jobs/jobs.component.html @@ -48,6 +48,13 @@ The Automatic Update is required + +
+ + + The Retry Requests is required + +
diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index b523250a6..338b55f21 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -520,6 +520,7 @@ namespace Ombi.Controllers j.Newsletter = j.Newsletter.HasValue() ? j.Newsletter : JobSettingsHelper.Newsletter(j); j.LidarrArtistSync = j.LidarrArtistSync.HasValue() ? j.LidarrArtistSync : JobSettingsHelper.LidarrArtistSync(j); j.IssuesPurge = j.IssuesPurge.HasValue() ? j.IssuesPurge : JobSettingsHelper.IssuePurge(j); + j.RetryRequests = j.RetryRequests.HasValue() ? j.RetryRequests : JobSettingsHelper.ResendFailedRequests(j); return j; }