From b9ed1a3e28d5aa72d3c9a370349b0b2e8ef9eeb7 Mon Sep 17 00:00:00 2001 From: Nathan Miller Date: Tue, 28 Jul 2020 15:43:43 -0500 Subject: [PATCH 1/5] fixed requested typo --- src/Ombi.Notifications/Agents/DiscordNotification.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi.Notifications/Agents/DiscordNotification.cs b/src/Ombi.Notifications/Agents/DiscordNotification.cs index a85ddff48..7c49dc7d5 100644 --- a/src/Ombi.Notifications/Agents/DiscordNotification.cs +++ b/src/Ombi.Notifications/Agents/DiscordNotification.cs @@ -111,7 +111,7 @@ namespace Ombi.Notifications.Agents { if (requestedUser.HasValue()) { - fields.Add(new DiscordField { name = "Requsted By", value = requestedUser, inline = true }); + fields.Add(new DiscordField { name = "Requested By", value = requestedUser, inline = true }); } } if (model.Data.TryGetValue("DenyReason", out var denyReason)) From 29f7403919849787d1b63818a0e243147213d119 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 29 Jul 2020 08:56:36 +0100 Subject: [PATCH 2/5] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7f8de2f56..2ed6275a3 100644 --- a/README.md +++ b/README.md @@ -102,12 +102,12 @@ We are planning to bring back these features in V3 but for now you can find a li | Lidarr | Yes | No | # Feature Requests -Feature requests are handled on FeatHub. +Feature requests are handled on Feature Upvote. Search the existing requests to see if your suggestion has already been submitted. -(If a similar request exists, give it a thumbs up (+1), or add additional comments to the request) +(If a similar request exists, please vote, or add additional comments to the request) -#### [![Feature Requests](https://cloud.githubusercontent.com/assets/390379/10127973/045b3a96-6560-11e5-9b20-31a2032956b2.png)](http://feathub.com/tidusjar/Ombi) +#### [![Feature Requests](https://cloud.githubusercontent.com/assets/390379/10127973/045b3a96-6560-11e5-9b20-31a2032956b2.png)](https://features.ombi.io) # Preview From 19a993ba51e433d248c5042fb63c9cc1e3ea9b54 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 30 Jul 2020 08:30:21 +0100 Subject: [PATCH 3/5] Added the new feature suggestion to the navbar --- .../ClientApp/src/app/interfaces/ICommon.ts | 3 ++- .../src/app/my-nav/my-nav.component.html | 11 +++++------ .../src/app/my-nav/my-nav.component.ts | 17 +++++++++-------- src/Ombi/wwwroot/translations/en.json | 4 +++- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Ombi/ClientApp/src/app/interfaces/ICommon.ts b/src/Ombi/ClientApp/src/app/interfaces/ICommon.ts index f0bcd8983..13a91af6c 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ICommon.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ICommon.ts @@ -29,6 +29,7 @@ export interface IUsersModel { export interface INavBar { icon: string; + faIcon: string; name: string; link: string; requiresAdmin: boolean; @@ -36,5 +37,5 @@ export interface INavBar { toolTip?: boolean; toolTipMessage?: string; style?: string; - donation?: boolean; + externalLink?: boolean; } \ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html index c849d80e8..93c689741 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html +++ b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.html @@ -5,20 +5,19 @@
- - + - {{nav.icon}} + {{nav.icon}} +  {{nav.name | translate}} - + {{nav.icon}}  {{nav.name | translate}} - - +
diff --git a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts index 465cae4e1..5b142dd58 100644 --- a/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts +++ b/src/Ombi/ClientApp/src/app/my-nav/my-nav.component.ts @@ -34,7 +34,7 @@ export class MyNavComponent implements OnInit { } public async ngOnInit() { - + this.issuesEnabled = await this.settingsService.issueEnabled().toPromise(); console.log("issues enabled: " + this.issuesEnabled); this.theme = this.store.get("theme"); @@ -42,14 +42,15 @@ export class MyNavComponent implements OnInit { this.store.save("theme","dark"); } this.navItems = [ - { name: "NavigationBar.Discover", icon: "find_replace", link: "/discover", requiresAdmin: false, enabled: true }, - { name: "NavigationBar.Requests", icon: "list", link: "/requests-list", requiresAdmin: false, enabled: true }, - { name: "NavigationBar.Issues", icon: "notification_important", link: "/issues", requiresAdmin: false, enabled: this.issuesEnabled }, - { name: "NavigationBar.UserManagement", icon: "account_circle", link: "/usermanagement", requiresAdmin: true, enabled: true }, + { name: "NavigationBar.Discover", icon: "find_replace", link: "/discover", requiresAdmin: false, enabled: true, faIcon: null }, + { name: "NavigationBar.Requests", icon: "list", link: "/requests-list", requiresAdmin: false, enabled: true, faIcon: null }, + { name: "NavigationBar.Issues", icon: "notification_important", link: "/issues", requiresAdmin: false, enabled: this.issuesEnabled, faIcon: null }, + { name: "NavigationBar.UserManagement", icon: "account_circle", link: "/usermanagement", requiresAdmin: true, enabled: true, faIcon: null }, // { name: "NavigationBar.Calendar", icon: "calendar_today", link: "/calendar", requiresAdmin: false, enabled: true }, - { name: "NavigationBar.Donate", icon: "attach_money", link: "https://www.paypal.me/PlexRequestsNet", donation: true, requiresAdmin: true, enabled: true, toolTip: true, style: "color:red;", toolTipMessage: 'NavigationBar.DonateTooltip' }, - { name: "NavigationBar.Settings", icon: "settings", link: "/Settings/About", requiresAdmin: true, enabled: true }, - { name: "NavigationBar.UserPreferences", icon: "person", link: "/user-preferences", requiresAdmin: false, enabled: true }, + { name: "NavigationBar.Donate", icon: "attach_money", link: "https://www.paypal.me/PlexRequestsNet", externalLink: true, requiresAdmin: true, enabled: true, toolTip: true, style: "color:red;", toolTipMessage: 'NavigationBar.DonateTooltip', faIcon: null }, + { name: "NavigationBar.FeatureSuggestion", icon: null, link: "https://features.ombi.io/", externalLink: true, requiresAdmin: false, enabled: true, toolTip: true, toolTipMessage: 'NavigationBar.FeatureSuggestionTooltip', faIcon: "fa-lightbulb-o" }, + { name: "NavigationBar.Settings", icon: "settings", link: "/Settings/About", requiresAdmin: true, enabled: true, faIcon: null }, + { name: "NavigationBar.UserPreferences", icon: "person", link: "/user-preferences", requiresAdmin: false, enabled: true, faIcon: null }, ]; } diff --git a/src/Ombi/wwwroot/translations/en.json b/src/Ombi/wwwroot/translations/en.json index 7549a7b61..4b198982a 100644 --- a/src/Ombi/wwwroot/translations/en.json +++ b/src/Ombi/wwwroot/translations/en.json @@ -67,7 +67,9 @@ "RecentlyAdded": "Recently Added", "ChangeTheme": "Change Theme", "Calendar": "Calendar", - "UserPreferences": "Preferences" + "UserPreferences": "Preferences", + "FeatureSuggestion":"Feature Suggestion", + "FeatureSuggestionTooltip":"Have a great new idea? Suggest it here!" }, "Search": { "Title": "Search", From 63fd43b1d8dd28d39d0c865f7ed4e7163f05c9d0 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Thu, 30 Jul 2020 09:03:36 +0100 Subject: [PATCH 4/5] wip --- .../Jobs/ArrAvailabilityChecker.cs | 103 ++++++++++++++++++ src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs | 26 ++--- src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs | 53 +++++++-- 3 files changed, 159 insertions(+), 23 deletions(-) create mode 100644 src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs diff --git a/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs new file mode 100644 index 000000000..2294fde9e --- /dev/null +++ b/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; +using Ombi.Core; +using Ombi.Helpers; +using Ombi.Hubs; +using Ombi.Notifications.Models; +using Ombi.Schedule.Jobs.Plex.Models; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; +using Quartz; + +namespace Ombi.Schedule.Jobs.Radarr +{ + public class ArrAvailabilityChecker + { + public ArrAvailabilityChecker( + IExternalRepository radarrRepo, + IExternalRepository sonarrRepo, + IExternalRepository sonarrEpisodeRepo, + INotificationHelper notification, IHubContext hub, + ITvRequestRepository tvRequest, IMovieRequestRepository movies, + ILogger log) + { + _radarrRepo = radarrRepo; + _sonarrRepo = sonarrRepo; + _sonarrEpisodeRepo = sonarrEpisodeRepo; + _notification = notification; + _hub = hub; + _tvRequest = tvRequest; + _movies = movies; + _logger = log; + } + + private readonly IExternalRepository _radarrRepo; + private readonly IExternalRepository _sonarrRepo; + private readonly ILogger _logger; + private readonly IExternalRepository _sonarrEpisodeRepo; + private readonly INotificationHelper _notification; + private readonly IHubContext _hub; + private readonly ITvRequestRepository _tvRequest; + private readonly IMovieRequestRepository _movies; + + public async Task Execute(IJobExecutionContext job) + { + + await ProcessMovies(); + await ProcessTvShows(); + + } + + private async Task ProcessMovies() + { + var availableRadarrMovies = _radarrRepo.GetAll().Where(x => x.HasFile).ToImmutableHashSet(); + var unavailableMovieRequests = _movies.GetAll().Where(x => !x.Available).ToImmutableHashSet(); + + var itemsForAvailability = new List(); + foreach (var movieRequest in unavailableMovieRequests) + { + // Do we have an item in the radarr list + var available = availableRadarrMovies.Any(x => x.TheMovieDbId == movieRequest.TheMovieDbId); + if (available) + { + movieRequest.Available = true; + movieRequest.MarkedAsAvailable = DateTime.UtcNow; + itemsForAvailability.Add(new AvailabilityModel + { + Id = movieRequest.Id, + RequestedUser = movieRequest.RequestedUser != null ? movieRequest.RequestedUser.Email : string.Empty + }); + } + } + + if (itemsForAvailability.Any()) + { + await _movies.SaveChangesAsync(); + } + foreach (var item in itemsForAvailability) + { + await _notification.Notify(new NotificationOptions + { + DateTime = DateTime.Now, + NotificationType = NotificationType.RequestAvailable, + RequestId = item.Id, + RequestType = RequestType.Movie, + Recipient = item.RequestedUser + }); + } + + } + + public async Task ProcessTvShows() + { + + } + + } +} diff --git a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs index 3a8aca3d7..54f77e253 100644 --- a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs @@ -49,29 +49,29 @@ namespace Ombi.Schedule.Jobs.Radarr // Let's remove the old cached data using (var tran = await _ctx.Database.BeginTransactionAsync()) { - await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM RadarrCache"); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM RadarrCache"); tran.Commit(); } var movieIds = new List(); foreach (var m in movies) { - if(m.monitored) - { - if (m.tmdbId > 0) + if (m.monitored || m.hasFile) { - movieIds.Add(new RadarrCache + if (m.tmdbId > 0) { - TheMovieDbId = m.tmdbId, - HasFile = m.hasFile - }); - } - else - { - Logger.LogError("TMDBId is not > 0 for movie {0}", m.title); + movieIds.Add(new RadarrCache + { + TheMovieDbId = m.tmdbId, + HasFile = m.hasFile + }); + } + else + { + Logger.LogError("TMDBId is not > 0 for movie {0}", m.title); + } } } - } using (var tran = await _ctx.Database.BeginTransactionAsync()) { diff --git a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs index cb431d1d5..2668c283f 100644 --- a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs @@ -33,7 +33,7 @@ namespace Ombi.Schedule.Jobs.Sonarr private readonly ISonarrApi _api; private readonly ILogger _log; private readonly ExternalContext _ctx; - + public async Task Execute(IJobExecutionContext job) { try @@ -50,48 +50,81 @@ namespace Ombi.Schedule.Jobs.Sonarr var ids = sonarrSeries.Select(x => x.tvdbId); using (var tran = await _ctx.Database.BeginTransactionAsync()) { - await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM SonarrCache"); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM SonarrCache"); tran.Commit(); } + var existingSeries = await _ctx.SonarrCache.Select(x => x.TvDbId).ToListAsync(); + + //var entites = ids.Except(existingSeries).Select(id => new SonarrCache { TvDbId = id }).ToImmutableHashSet(); var entites = ids.Select(id => new SonarrCache { TvDbId = id }).ToImmutableHashSet(); await _ctx.SonarrCache.AddRangeAsync(entites); entites.Clear(); using (var tran = await _ctx.Database.BeginTransactionAsync()) { - await _ctx.Database.ExecuteSqlCommandAsync("DELETE FROM SonarrEpisodeCache"); + await _ctx.Database.ExecuteSqlRawAsync("DELETE FROM SonarrEpisodeCache"); tran.Commit(); } foreach (var s in sonarrSeries) { - if (!s.monitored) + if (!s.monitored || s.episodeFileCount > 0) // We have files { continue; } + _log.LogDebug("Syncing series: {0}", s.title); var episodes = await _api.GetEpisodes(s.id, settings.ApiKey, settings.FullUri); var monitoredEpisodes = episodes.Where(x => x.monitored || x.hasFile); - + + var allExistingEpisodes = await _ctx.SonarrEpisodeCache.Where(x => x.TvDbId == s.tvdbId).ToListAsync(); // Add to DB _log.LogDebug("We have the episodes, adding to db transaction"); - using (var tran = await _ctx.Database.BeginTransactionAsync()) - { - await _ctx.SonarrEpisodeCache.AddRangeAsync(monitoredEpisodes.Select(episode => + var episodesToAdd = monitoredEpisodes.Select(episode => new SonarrEpisodeCache { EpisodeNumber = episode.episodeNumber, SeasonNumber = episode.seasonNumber, TvDbId = s.tvdbId, HasFile = episode.hasFile - })); + }); + //var episodesToAdd = new List(); + + //foreach (var monitored in monitoredEpisodes) + //{ + // var existing = allExistingEpisodes.FirstOrDefault(x => x.SeasonNumber == monitored.seasonNumber && x.EpisodeNumber == monitored.episodeNumber); + // if (existing == null) + // { + // // Just add a new one + // episodesToAdd.Add(new SonarrEpisodeCache + // { + // EpisodeNumber = monitored.episodeNumber, + // SeasonNumber = monitored.seasonNumber, + // TvDbId = s.tvdbId, + // HasFile = monitored.hasFile + // }); + // } + // else + // { + // // Do we need to update the availability? + // if (monitored.hasFile != existing.HasFile) + // { + // existing.HasFile = monitored.hasFile; + // } + // } + + //} + + using (var tran = await _ctx.Database.BeginTransactionAsync()) + { + await _ctx.SonarrEpisodeCache.AddRangeAsync(episodesToAdd); _log.LogDebug("Commiting the transaction"); await _ctx.SaveChangesAsync(); tran.Commit(); } } - + } } catch (Exception e) From dc00a87da8bed4d8d354cca62019c8e9765b181a Mon Sep 17 00:00:00 2001 From: tidusjar Date: Thu, 30 Jul 2020 09:57:09 +0100 Subject: [PATCH 5/5] Added the availability checker for Radarr/Sonarr --- src/Ombi.DependencyInjection/IocExtensions.cs | 1 + .../Jobs/ArrAvailabilityChecker.cs | 104 +++++++++++++++++- .../Jobs/IArrAvailabilityChecker.cs | 6 + src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs | 2 + src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs | 7 +- src/Ombi.Schedule/OmbiScheduler.cs | 1 + .../ClientApp/src/app/interfaces/ISettings.ts | 1 + .../ClientApp/src/app/services/job.service.ts | 4 + .../src/app/settings/jobs/jobs.component.html | 14 ++- .../src/app/settings/jobs/jobs.component.ts | 26 +++-- src/Ombi/Controllers/V1/JobController.cs | 12 ++ 11 files changed, 160 insertions(+), 18 deletions(-) create mode 100644 src/Ombi.Schedule/Jobs/IArrAvailabilityChecker.cs diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index 76f2f42bc..feb3c55be 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -230,6 +230,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); } } } diff --git a/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs index 2294fde9e..55bb350ff 100644 --- a/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/ArrAvailabilityChecker.cs @@ -4,6 +4,7 @@ using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Core; using Ombi.Helpers; @@ -17,7 +18,7 @@ using Quartz; namespace Ombi.Schedule.Jobs.Radarr { - public class ArrAvailabilityChecker + public class ArrAvailabilityChecker : IArrAvailabilityChecker { public ArrAvailabilityChecker( IExternalRepository radarrRepo, @@ -48,10 +49,8 @@ namespace Ombi.Schedule.Jobs.Radarr public async Task Execute(IJobExecutionContext job) { - await ProcessMovies(); await ProcessTvShows(); - } private async Task ProcessMovies() @@ -66,6 +65,7 @@ namespace Ombi.Schedule.Jobs.Radarr var available = availableRadarrMovies.Any(x => x.TheMovieDbId == movieRequest.TheMovieDbId); if (available) { + _logger.LogInformation($"Found move '{movieRequest.Title}' available in Radarr"); movieRequest.Available = true; movieRequest.MarkedAsAvailable = DateTime.UtcNow; itemsForAvailability.Add(new AvailabilityModel @@ -78,6 +78,8 @@ namespace Ombi.Schedule.Jobs.Radarr if (itemsForAvailability.Any()) { + await _hub.Clients.Clients(NotificationHub.AdminConnectionIds) + .SendAsync(NotificationHub.NotificationEvent, "Radarr Availability Checker found some new available movies!"); await _movies.SaveChangesAsync(); } foreach (var item in itemsForAvailability) @@ -96,8 +98,104 @@ namespace Ombi.Schedule.Jobs.Radarr public async Task ProcessTvShows() { + var tv = await _tvRequest.GetChild().Where(x => !x.Available).ToListAsync(); + var sonarrEpisodes = _sonarrEpisodeRepo.GetAll().Where(x => x.HasFile); + + foreach (var child in tv) + { + var tvDbId = child.ParentRequest.TvDbId; + IQueryable seriesEpisodes = sonarrEpisodes.Where(x => x.TvDbId == tvDbId); + + if (seriesEpisodes == null || !seriesEpisodes.Any()) + { + continue; + } + + //if (!seriesEpisodes.Any()) + //{ + // // Let's try and match the series by name + // seriesEpisodes = sonarrEpisodes.Where(x => + // x.EpisodeNumber == child.Title && + // x.Series.ReleaseYear == child.ParentRequest.ReleaseDate.Year.ToString()); + + //} + var availableEpisode = new List(); + foreach (var season in child.SeasonRequests) + { + foreach (var episode in season.Episodes) + { + if (episode.Available) + { + continue; + } + var foundEp = await seriesEpisodes.AnyAsync( + x => x.EpisodeNumber == episode.EpisodeNumber && + x.SeasonNumber == episode.Season.SeasonNumber); + + if (foundEp) + { + availableEpisode.Add(new AvailabilityModel + { + Id = episode.Id + }); + episode.Available = true; + } + } + } + + //TODO Partial avilability notifications here + if (availableEpisode.Any()) + { + //await _hub.Clients.Clients(NotificationHub.AdminConnectionIds) + // .SendAsync(NotificationHub.NotificationEvent, "Sonarr Availability Checker found some new available episodes!"); + await _tvRequest.Save(); + } + //foreach(var c in availableEpisode) + //{ + // await _tvRepo.MarkEpisodeAsAvailable(c.Id); + //} + + // Check to see if all of the episodes in all seasons are available for this request + var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available)); + if (allAvailable) + { + await _hub.Clients.Clients(NotificationHub.AdminConnectionIds) + .SendAsync(NotificationHub.NotificationEvent, "Sonarr Availability Checker found some new available Shows!"); + child.Available = true; + child.MarkedAsAvailable = DateTime.UtcNow; + _logger.LogInformation("[ARR_AC] - Child request {0} is now available, sending notification", $"{child.Title} - {child.Id}"); + // We have ful-fulled this request! + await _tvRequest.Save(); + await _notification.Notify(new NotificationOptions + { + DateTime = DateTime.Now, + NotificationType = NotificationType.RequestAvailable, + RequestId = child.Id, + RequestType = RequestType.TvShow, + Recipient = child.RequestedUser.Email + }); + } + } + + await _tvRequest.Save(); } + private bool _disposed; + protected virtual void Dispose(bool disposing) + { + if (_disposed) + return; + + if (disposing) + { + } + _disposed = true; + } + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } } } diff --git a/src/Ombi.Schedule/Jobs/IArrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/IArrAvailabilityChecker.cs new file mode 100644 index 000000000..f2a2df601 --- /dev/null +++ b/src/Ombi.Schedule/Jobs/IArrAvailabilityChecker.cs @@ -0,0 +1,6 @@ +namespace Ombi.Schedule.Jobs.Radarr +{ + public interface IArrAvailabilityChecker : IBaseJob + { + } +} diff --git a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs index 54f77e253..3657fba61 100644 --- a/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Radarr/RadarrSync.cs @@ -81,6 +81,8 @@ namespace Ombi.Schedule.Jobs.Radarr tran.Commit(); } } + + await OmbiQuartz.TriggerJob(nameof(IArrAvailabilityChecker), "DVR"); } catch (System.Exception ex) { diff --git a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs index 2668c283f..bf3ee8406 100644 --- a/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs +++ b/src/Ombi.Schedule/Jobs/Sonarr/SonarrSync.cs @@ -11,6 +11,7 @@ using Ombi.Api.Sonarr; using Ombi.Api.Sonarr.Models; using Ombi.Core.Settings; using Ombi.Helpers; +using Ombi.Schedule.Jobs.Radarr; using Ombi.Settings.Settings.Models.External; using Ombi.Store.Context; using Ombi.Store.Entities; @@ -69,7 +70,7 @@ namespace Ombi.Schedule.Jobs.Sonarr foreach (var s in sonarrSeries) { - if (!s.monitored || s.episodeFileCount > 0) // We have files + if (!s.monitored || s.episodeFileCount == 0) // We have files { continue; } @@ -78,7 +79,7 @@ namespace Ombi.Schedule.Jobs.Sonarr var episodes = await _api.GetEpisodes(s.id, settings.ApiKey, settings.FullUri); var monitoredEpisodes = episodes.Where(x => x.monitored || x.hasFile); - var allExistingEpisodes = await _ctx.SonarrEpisodeCache.Where(x => x.TvDbId == s.tvdbId).ToListAsync(); + //var allExistingEpisodes = await _ctx.SonarrEpisodeCache.Where(x => x.TvDbId == s.tvdbId).ToListAsync(); // Add to DB _log.LogDebug("We have the episodes, adding to db transaction"); var episodesToAdd = monitoredEpisodes.Select(episode => @@ -126,6 +127,8 @@ namespace Ombi.Schedule.Jobs.Sonarr } } + + await OmbiQuartz.TriggerJob(nameof(IArrAvailabilityChecker), "DVR"); } catch (Exception e) { diff --git a/src/Ombi.Schedule/OmbiScheduler.cs b/src/Ombi.Schedule/OmbiScheduler.cs index 6ccdecb45..d3c8db860 100644 --- a/src/Ombi.Schedule/OmbiScheduler.cs +++ b/src/Ombi.Schedule/OmbiScheduler.cs @@ -73,6 +73,7 @@ namespace Ombi.Schedule { await OmbiQuartz.Instance.AddJob(nameof(ISonarrSync), "DVR", JobSettingsHelper.Sonarr(s)); await OmbiQuartz.Instance.AddJob(nameof(IRadarrSync), "DVR", JobSettingsHelper.Radarr(s)); + await OmbiQuartz.Instance.AddJob(nameof(IArrAvailabilityChecker), "DVR", null); await OmbiQuartz.Instance.AddJob(nameof(ICouchPotatoSync), "DVR", JobSettingsHelper.CouchPotato(s)); await OmbiQuartz.Instance.AddJob(nameof(ISickRageSync), "DVR", JobSettingsHelper.SickRageSync(s)); await OmbiQuartz.Instance.AddJob(nameof(ILidarrArtistSync), "DVR", JobSettingsHelper.LidarrArtistSync(s)); diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts index 731cb28bf..c5a1b6f8b 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISettings.ts @@ -146,6 +146,7 @@ export interface IJobSettings { issuesPurge: string; retryRequests: string; mediaDatabaseRefresh: string; + arrAvailabilityChecker: string; } export interface IIssueSettings extends ISettings { diff --git a/src/Ombi/ClientApp/src/app/services/job.service.ts b/src/Ombi/ClientApp/src/app/services/job.service.ts index c855b354b..2e991d941 100644 --- a/src/Ombi/ClientApp/src/app/services/job.service.ts +++ b/src/Ombi/ClientApp/src/app/services/job.service.ts @@ -46,4 +46,8 @@ export class JobService extends ServiceHelpers { public runNewsletter(): Observable { return this.http.post(`${this.url}newsletter/`, {headers: this.headers}); } + + public runArrAvailabilityChecker(): Observable { + return this.http.post(`${this.url}arrAvailability/`, {headers: this.headers}); + } } diff --git a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html index 849230bcd..d31129de7 100644 --- a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html +++ b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.html @@ -72,19 +72,19 @@
- + The Emby Sync is required
- + The User Importer is required
- +
@@ -105,6 +105,14 @@ The Media Database Refresh is required
+ +
+ + + The Radarr/Sonarr Availability Checker is required + + +
diff --git a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts index 2850d9441..fca037136 100644 --- a/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts +++ b/src/Ombi/ClientApp/src/app/settings/jobs/jobs.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from "@angular/core"; import { FormBuilder, FormGroup, Validators } from "@angular/forms"; -import { NotificationService, SettingsService } from "../../services"; +import { NotificationService, SettingsService, JobService } from "../../services"; @Component({ templateUrl: "./jobs.component.html", @@ -10,13 +10,14 @@ import { NotificationService, SettingsService } from "../../services"; export class JobsComponent implements OnInit { public form: FormGroup; - + public profilesRunning: boolean; - + constructor(private readonly settingsService: SettingsService, private readonly fb: FormBuilder, - private readonly notificationService: NotificationService) { } - + private readonly notificationService: NotificationService, + private readonly jobsService: JobService) { } + public ngOnInit() { this.settingsService.getJobSettings().subscribe(x => { this.form = this.fb.group({ @@ -27,27 +28,28 @@ export class JobsComponent implements OnInit { userImporter: [x.userImporter, Validators.required], sonarrSync: [x.sonarrSync, Validators.required], radarrSync: [x.radarrSync, Validators.required], - sickRageSync: [x.sickRageSync, Validators.required], + sickRageSync: [x.sickRageSync, Validators.required], newsletter: [x.newsletter, Validators.required], plexRecentlyAddedSync: [x.plexRecentlyAddedSync, Validators.required], lidarrArtistSync: [x.lidarrArtistSync, Validators.required], issuesPurge: [x.issuesPurge, Validators.required], retryRequests: [x.retryRequests, Validators.required], mediaDatabaseRefresh: [x.mediaDatabaseRefresh, Validators.required], - }); + arrAvailabilityChecker: [x.arrAvailabilityChecker, Validators.required], + }); }); } public testCron(expression: string) { this.settingsService.testCron({ expression }).subscribe(x => { - if(x.success) { - this.notificationService.success("Cron is Valid"); + if(x.success) { + this.notificationService.success("Cron is Valid"); } else { this.notificationService.error(x.message); } }); } - + public onSubmit(form: FormGroup) { if (form.invalid) { this.notificationService.error("Please check your entered values"); @@ -62,4 +64,8 @@ export class JobsComponent implements OnInit { } }); } + + public runArrAvailabilityChecker() { + this.jobsService.runArrAvailabilityChecker().subscribe(); + } } diff --git a/src/Ombi/Controllers/V1/JobController.cs b/src/Ombi/Controllers/V1/JobController.cs index 668a4ccf4..b9f029194 100644 --- a/src/Ombi/Controllers/V1/JobController.cs +++ b/src/Ombi/Controllers/V1/JobController.cs @@ -8,6 +8,7 @@ using Ombi.Schedule.Jobs; using Ombi.Schedule.Jobs.Emby; using Ombi.Schedule.Jobs.Ombi; using Ombi.Schedule.Jobs.Plex; +using Ombi.Schedule.Jobs.Radarr; using Quartz; namespace Ombi.Controllers.V1 @@ -134,6 +135,17 @@ namespace Ombi.Controllers.V1 return true; } + /// + /// Runs the Arr Availability Checker + /// + /// + [HttpPost("arrAvailability")] + public async Task StartArrAvailabiltityChecker() + { + await OmbiQuartz.TriggerJob(nameof(IArrAvailabilityChecker), "DVR"); + return true; + } + /// /// Runs the newsletter ///