From 1286c40f826055d51290a09c9369f0311a0899c9 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 16 Oct 2019 21:41:17 +0100 Subject: [PATCH 01/19] Hopefully provide a fix now for #2998 Theory is that the refresh metadata was using stale data and then overriding the availbility that just happened on that media item. --- src/Ombi.DependencyInjection/IocExtensions.cs | 1 - src/Ombi.Schedule/JobDataKeys.cs | 7 + src/Ombi.Schedule/JobSetup.cs | 117 -- .../Jobs/Emby/EmbyAvaliabilityChecker.cs | 3 + .../Jobs/Emby/EmbyContentSync.cs | 1 - .../Jobs/Lidarr/LidarrAvailabilityChecker.cs | 2 +- .../Jobs/Ombi/Interfaces/IRefreshMetadata.cs | 1 - .../Jobs/Ombi/RefreshMetadata.cs | 97 +- .../Jobs/Plex/PlexAvailabilityChecker.cs | 39 +- .../Jobs/Plex/PlexContentSync.cs | 11 +- src/Ombi.Schedule/OmbiScheduler.cs | 4 +- src/Ombi.Store/Entities/PlexServerContent.cs | 2 + ...6203035_RequestIdOnPlexContent.Designer.cs | 1216 +++++++++++++++++ .../20191016203035_RequestIdOnPlexContent.cs | 22 + .../Migrations/OmbiContextModelSnapshot.cs | 4 +- src/Ombi.Store/Repository/BaseRepository.cs | 4 +- src/Ombi/Startup.cs | 4 +- 17 files changed, 1314 insertions(+), 221 deletions(-) create mode 100644 src/Ombi.Schedule/JobDataKeys.cs delete mode 100644 src/Ombi.Schedule/JobSetup.cs create mode 100644 src/Ombi.Store/Migrations/20191016203035_RequestIdOnPlexContent.Designer.cs create mode 100644 src/Ombi.Store/Migrations/20191016203035_RequestIdOnPlexContent.cs diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index f5705969b..3d54e5a67 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -190,7 +190,6 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/src/Ombi.Schedule/JobDataKeys.cs b/src/Ombi.Schedule/JobDataKeys.cs new file mode 100644 index 000000000..46d2dee2a --- /dev/null +++ b/src/Ombi.Schedule/JobDataKeys.cs @@ -0,0 +1,7 @@ +namespace Ombi.Schedule +{ + public class JobDataKeys + { + public const string RecentlyAddedSearch = "recentlyAddedSearch"; + } +} \ No newline at end of file diff --git a/src/Ombi.Schedule/JobSetup.cs b/src/Ombi.Schedule/JobSetup.cs deleted file mode 100644 index f0f53f128..000000000 --- a/src/Ombi.Schedule/JobSetup.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using Hangfire; -using Ombi.Core.Settings; -using Ombi.Schedule.Jobs; -using Ombi.Schedule.Jobs.Couchpotato; -using Ombi.Schedule.Jobs.Emby; -using Ombi.Schedule.Jobs.Lidarr; -using Ombi.Schedule.Jobs.Ombi; -using Ombi.Schedule.Jobs.Plex; -using Ombi.Schedule.Jobs.Plex.Interfaces; -using Ombi.Schedule.Jobs.Radarr; -using Ombi.Schedule.Jobs.SickRage; -using Ombi.Schedule.Jobs.Sonarr; -using Ombi.Settings.Settings.Models; - -namespace Ombi.Schedule -{ - public class JobSetup : IJobSetup, IDisposable - { - public JobSetup(IPlexContentSync plexContentSync, IRadarrSync radarrSync, - IOmbiAutomaticUpdater updater, IEmbyContentSync embySync, IPlexUserImporter userImporter, - IEmbyUserImporter embyUserImporter, ISonarrSync cache, ICouchPotatoSync cpCache, - ISettingsService jobsettings, ISickRageSync srSync, IRefreshMetadata refresh, - INewsletterJob newsletter, IPlexRecentlyAddedSync recentlyAddedPlex, ILidarrArtistSync artist, - IIssuesPurge purge, IResendFailedRequests resender, IMediaDatabaseRefresh dbRefresh) - { - _plexContentSync = plexContentSync; - _radarrSync = radarrSync; - _updater = updater; - _embyContentSync = embySync; - _plexUserImporter = userImporter; - _embyUserImporter = embyUserImporter; - _sonarrSync = cache; - _cpCache = cpCache; - _jobSettings = jobsettings; - _srSync = srSync; - _refreshMetadata = refresh; - _newsletter = newsletter; - _plexRecentlyAddedSync = recentlyAddedPlex; - _lidarrArtistSync = artist; - _issuesPurge = purge; - _resender = resender; - _mediaDatabaseRefresh = dbRefresh; - } - - private readonly IPlexContentSync _plexContentSync; - private readonly IPlexRecentlyAddedSync _plexRecentlyAddedSync; - private readonly IRadarrSync _radarrSync; - private readonly IOmbiAutomaticUpdater _updater; - private readonly IPlexUserImporter _plexUserImporter; - private readonly IEmbyContentSync _embyContentSync; - private readonly IEmbyUserImporter _embyUserImporter; - private readonly ISonarrSync _sonarrSync; - private readonly ICouchPotatoSync _cpCache; - private readonly ISickRageSync _srSync; - private readonly ISettingsService _jobSettings; - private readonly IRefreshMetadata _refreshMetadata; - private readonly INewsletterJob _newsletter; - private readonly ILidarrArtistSync _lidarrArtistSync; - private readonly IIssuesPurge _issuesPurge; - private readonly IResendFailedRequests _resender; - private readonly IMediaDatabaseRefresh _mediaDatabaseRefresh; - - public void Setup() - { - var s = _jobSettings.GetSettings(); - - // RecurringJob.AddOrUpdate(() => _embyContentSync.Start(), JobSettingsHelper.EmbyContent(s)); - // RecurringJob.AddOrUpdate(() => _sonarrSync.Start(), JobSettingsHelper.Sonarr(s)); - // RecurringJob.AddOrUpdate(() => _radarrSync.CacheContent(), JobSettingsHelper.Radarr(s)); - // //RecurringJob.AddOrUpdate(() => _plexContentSync.Execute(null), JobSettingsHelper.PlexContent(s)); - // //RecurringJob.AddOrUpdate(() => _plexRecentlyAddedSync.Start(), JobSettingsHelper.PlexRecentlyAdded(s)); - // RecurringJob.AddOrUpdate(() => _cpCache.Start(), JobSettingsHelper.CouchPotato(s)); - // RecurringJob.AddOrUpdate(() => _srSync.Start(), JobSettingsHelper.SickRageSync(s)); - // RecurringJob.AddOrUpdate(() => _refreshMetadata.Start(), JobSettingsHelper.RefreshMetadata(s)); - // RecurringJob.AddOrUpdate(() => _lidarrArtistSync.CacheContent(), JobSettingsHelper.LidarrArtistSync(s)); - // RecurringJob.AddOrUpdate(() => _issuesPurge.Start(), JobSettingsHelper.IssuePurge(s)); - - // RecurringJob.AddOrUpdate(() => _updater.Update(null), JobSettingsHelper.Updater(s)); - - // RecurringJob.AddOrUpdate(() => _embyUserImporter.Start(), JobSettingsHelper.UserImporter(s)); - // RecurringJob.AddOrUpdate(() => _plexUserImporter.Start(), JobSettingsHelper.UserImporter(s)); - // RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s)); - //// RecurringJob.AddOrUpdate(() => _resender.Start(), JobSettingsHelper.ResendFailedRequests(s)); - // RecurringJob.AddOrUpdate(() => _mediaDatabaseRefresh.Start(), JobSettingsHelper.MediaDatabaseRefresh(s)); - } - - private bool _disposed; - protected virtual void Dispose(bool disposing) - { - if (_disposed) - return; - - if (disposing) - { - _radarrSync?.Dispose(); - _updater?.Dispose(); - _plexUserImporter?.Dispose(); - _embyContentSync?.Dispose(); - _embyUserImporter?.Dispose(); - _sonarrSync?.Dispose(); - _cpCache?.Dispose(); - _srSync?.Dispose(); - _jobSettings?.Dispose(); - _refreshMetadata?.Dispose(); - _newsletter?.Dispose(); - } - _disposed = true; - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - } -} diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs index 929f8d7b9..9c92bc509 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyAvaliabilityChecker.cs @@ -34,6 +34,7 @@ using Microsoft.Extensions.Logging; using Ombi.Core.Notifications; using Ombi.Helpers; using Ombi.Notifications.Models; +using Ombi.Schedule.Jobs.Ombi; using Ombi.Store.Entities; using Ombi.Store.Repository; using Ombi.Store.Repository.Requests; @@ -63,6 +64,8 @@ namespace Ombi.Schedule.Jobs.Emby { await ProcessMovies(); await ProcessTv(); + + await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System"); } private async Task ProcessMovies() diff --git a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs index bffce3ccc..362840203 100644 --- a/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Emby/EmbyContentSync.cs @@ -56,7 +56,6 @@ namespace Ombi.Schedule.Jobs.Emby // Episodes await OmbiQuartz.TriggerJob(nameof(IEmbyEpisodeSync), "Emby"); - await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System"); } diff --git a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs index 5708dad6c..340164bd5 100644 --- a/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Lidarr/LidarrAvailabilityChecker.cs @@ -43,7 +43,7 @@ namespace Ombi.Schedule.Jobs.Lidarr var cachedAlbum = await _cachedAlbums.FirstOrDefaultAsync(x => x.ForeignAlbumId.Equals(request.ForeignAlbumId)); if (cachedAlbum != null) { - if (cachedAlbum.FullyAvailable) + if (cachedAlbum.FullyAvailable) // ensure we have all tracks { request.Available = true; request.MarkedAsAvailable = DateTime.Now; diff --git a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs index a7e7d5fdc..c29a80994 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/Interfaces/IRefreshMetadata.cs @@ -5,6 +5,5 @@ namespace Ombi.Schedule.Jobs.Ombi { public interface IRefreshMetadata : IBaseJob { - Task ProcessPlexServerContent(IEnumerable contentIds); } } \ No newline at end of file diff --git a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs index 424ef7713..0ccb736dc 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/RefreshMetadata.cs @@ -54,7 +54,7 @@ namespace Ombi.Schedule.Jobs.Ombi { await StartPlex(); } - + var embySettings = await _embySettings.GetSettingsAsync(); if (embySettings.Enable) { @@ -68,44 +68,16 @@ namespace Ombi.Schedule.Jobs.Ombi } } - public async Task ProcessPlexServerContent(IEnumerable contentIds) - { - _log.LogInformation("Starting the Metadata refresh from RecentlyAddedSync"); - var plexSettings = await _plexSettings.GetSettingsAsync(); - try - { - if (plexSettings.Enable) - { - await StartPlexWithKnownContent(contentIds); - } - } - catch (Exception e) - { - _log.LogError(e, "Exception when refreshing the Plex Metadata"); - throw; - } - } - - private async Task StartPlexWithKnownContent(IEnumerable contentids) - { - var everything = _plexRepo.GetAll().Where(x => contentids.Contains(x.Id)); - var allMovies = everything.Where(x => x.Type == PlexMediaTypeEntity.Movie); - await StartPlexMovies(allMovies); - - // Now Tv - var allTv = everything.Where(x => x.Type == PlexMediaTypeEntity.Show); - await StartPlexTv(allTv); - } - private async Task StartPlex() { + // Ensure we check that we have not linked this item to a request var allMovies = _plexRepo.GetAll().Where(x => - x.Type == PlexMediaTypeEntity.Movie && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue())); + x.Type == PlexMediaTypeEntity.Movie && !x.RequestId.HasValue && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue())); await StartPlexMovies(allMovies); // Now Tv var allTv = _plexRepo.GetAll().Where(x => - x.Type == PlexMediaTypeEntity.Show && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue() || !x.TvDbId.HasValue())); + x.Type == PlexMediaTypeEntity.Show && !x.RequestId.HasValue && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue() || !x.TvDbId.HasValue())); await StartPlexTv(allTv); } @@ -117,9 +89,13 @@ namespace Ombi.Schedule.Jobs.Ombi private async Task StartPlexTv(IQueryable allTv) { - var tvCount = 0; foreach (var show in allTv) - { + { + // Just double check there is no associated request id + if (show.RequestId.HasValue) + { + continue; + } var hasImdb = show.ImdbId.HasValue(); var hasTheMovieDb = show.TheMovieDbId.HasValue(); var hasTvDbId = show.TvDbId.HasValue(); @@ -143,21 +119,15 @@ namespace Ombi.Schedule.Jobs.Ombi show.TvDbId = id; _plexRepo.UpdateWithoutSave(show); } - tvCount++; - if (tvCount >= 75) - { - await _plexRepo.SaveChangesAsync(); - tvCount = 0; - } + await _plexRepo.SaveChangesAsync(); } - await _plexRepo.SaveChangesAsync(); } private async Task StartEmbyTv() { var allTv = _embyRepo.GetAll().Where(x => x.Type == EmbyMediaType.Series && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue() || !x.TvDbId.HasValue())); - var tvCount = 0; + foreach (var show in allTv) { var hasImdb = show.ImdbId.HasValue(); @@ -183,21 +153,20 @@ namespace Ombi.Schedule.Jobs.Ombi show.TvDbId = id; _embyRepo.UpdateWithoutSave(show); } - tvCount++; - if (tvCount >= 75) - { - await _embyRepo.SaveChangesAsync(); - tvCount = 0; - } + + await _embyRepo.SaveChangesAsync(); } - await _embyRepo.SaveChangesAsync(); } private async Task StartPlexMovies(IQueryable allMovies) { - int movieCount = 0; foreach (var movie in allMovies) { + // Just double check there is no associated request id + if (movie.RequestId.HasValue) + { + continue; + } var hasImdb = movie.ImdbId.HasValue(); var hasTheMovieDb = movie.TheMovieDbId.HasValue(); // Movies don't really use TheTvDb @@ -214,26 +183,19 @@ namespace Ombi.Schedule.Jobs.Ombi movie.TheMovieDbId = id; _plexRepo.UpdateWithoutSave(movie); } - movieCount++; - if (movieCount >= 75) - { - await _plexRepo.SaveChangesAsync(); - movieCount = 0; - } - } - await _plexRepo.SaveChangesAsync(); + await _plexRepo.SaveChangesAsync(); + } } private async Task StartEmbyMovies(EmbySettings settings) { var allMovies = _embyRepo.GetAll().Where(x => x.Type == EmbyMediaType.Movie && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue())); - int movieCount = 0; foreach (var movie in allMovies) { movie.ImdbId.HasValue(); - movie.TheMovieDbId.HasValue(); + movie.TheMovieDbId.HasValue(); // Movies don't really use TheTvDb // Check if it even has 1 ID @@ -242,6 +204,8 @@ namespace Ombi.Schedule.Jobs.Ombi // Ok this sucks, // The only think I can think that has happened is that we scanned Emby before Emby has got the metadata // So let's recheck emby to see if they have got the metadata now + // + // Yeah your right that does suck - Future Jamie _log.LogInformation($"Movie {movie.Title} does not have a ImdbId or TheMovieDbId, so rechecking emby"); foreach (var server in settings.Servers) { @@ -273,15 +237,10 @@ namespace Ombi.Schedule.Jobs.Ombi movie.TheMovieDbId = id; _embyRepo.UpdateWithoutSave(movie); } - movieCount++; - if (movieCount >= 75) - { - await _embyRepo.SaveChangesAsync(); - movieCount = 0; - } - } - await _embyRepo.SaveChangesAsync(); + await _embyRepo.SaveChangesAsync(); + + } } private async Task GetTheMovieDbId(bool hasTvDbId, bool hasImdb, string tvdbID, string imdbId, string title, bool movie) @@ -364,7 +323,7 @@ namespace Ombi.Schedule.Jobs.Ombi { var result = await _movieApi.GetTvExternals(id); - return result.tvdb_id.ToString(); + return result.tvdb_id.ToString(); } } diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index 9a7a8601a..72d7f5a2c 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -45,7 +45,7 @@ namespace Ombi.Schedule.Jobs.Plex } catch (Exception e) { - _log.LogError(e, "Exception thrown in Plex availbility checker"); + _log.LogError(e, "Exception thrown in Plex availability checker"); } } @@ -72,7 +72,7 @@ namespace Ombi.Schedule.Jobs.Plex { useTvDb = true; } - + var tvDbId = child.ParentRequest.TvDbId; var imdbId = child.ParentRequest.ImdbId; IQueryable seriesEpisodes = null; @@ -80,7 +80,7 @@ namespace Ombi.Schedule.Jobs.Plex { seriesEpisodes = plexEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString()); } - if (useTvDb && (seriesEpisodes == null || !seriesEpisodes.Any()) ) + if (useTvDb && (seriesEpisodes == null || !seriesEpisodes.Any())) { seriesEpisodes = plexEpisodes.Where(x => x.Series.TvDbId == tvDbId.ToString()); } @@ -94,8 +94,8 @@ namespace Ombi.Schedule.Jobs.Plex { // Let's try and match the series by name seriesEpisodes = plexEpisodes.Where(x => - x.Series.Title.Equals(child.Title, StringComparison.CurrentCultureIgnoreCase) && - x.Series.ReleaseYear == child.ParentRequest.ReleaseDate.Year.ToString()); + x.Series.Title.Equals(child.Title, StringComparison.InvariantCultureIgnoreCase) && + x.Series.ReleaseYear.Equals(child.ParentRequest.ReleaseDate.Year.ToString(), StringComparison.InvariantCultureIgnoreCase)); } @@ -122,17 +122,18 @@ namespace Ombi.Schedule.Jobs.Plex var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available)); if (allAvailable) { - // We have fulfulled this request! + _log.LogInformation("[PAC] - Child request {0} is now available, sending notification", $"{child.Title} - {child.Id}"); + // We have ful-fulled this request! child.Available = true; child.MarkedAsAvailable = DateTime.Now; - _backgroundJobClient.Enqueue(() => _notificationService.Publish(new NotificationOptions + await _notificationService.Publish(new NotificationOptions { DateTime = DateTime.Now, NotificationType = NotificationType.RequestAvailable, RequestId = child.Id, RequestType = RequestType.TvShow, Recipient = child.RequestedUser.Email - })); + }); } } @@ -166,20 +167,22 @@ namespace Ombi.Schedule.Jobs.Plex movie.Available = true; movie.MarkedAsAvailable = DateTime.Now; - if (movie.Available) + item.RequestId = movie.Id; + + _log.LogInformation("[PAC] - Movie request {0} is now available, sending notification", $"{movie.Title} - {movie.Id}"); + await _notificationService.Publish(new NotificationOptions { - _backgroundJobClient.Enqueue(() => _notificationService.Publish(new NotificationOptions - { - DateTime = DateTime.Now, - NotificationType = NotificationType.RequestAvailable, - RequestId = movie.Id, - RequestType = RequestType.Movie, - Recipient = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty - })); - } + DateTime = DateTime.Now, + NotificationType = NotificationType.RequestAvailable, + RequestId = movie.Id, + RequestType = RequestType.Movie, + Recipient = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty + }); + } await _movieRepo.Save(); + await _repo.SaveChangesAsync(); } private bool _disposed; diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index 283434f53..a8d77a71b 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -49,14 +49,13 @@ 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) { Plex = plex; PlexApi = plexApi; Logger = logger; Repo = repo; EpisodeSync = epsiodeSync; - Metadata = metadataRefresh; Plex.ClearCache(); } @@ -65,12 +64,11 @@ namespace Ombi.Schedule.Jobs.Plex private ILogger Logger { get; } private IPlexContentRepository Repo { get; } private IPlexEpisodeSync EpisodeSync { get; } - private IRefreshMetadata Metadata { get; } public async Task Execute(IJobExecutionContext context) { JobDataMap dataMap = context.JobDetail.JobDataMap; - var recentlyAddedSearch = dataMap.GetBooleanValueFromString("recentlyAddedSearch"); + var recentlyAddedSearch = dataMap.GetBooleanValueFromString(JobDataKeys.RecentlyAddedSearch); var plexSettings = await Plex.GetSettingsAsync(); if (!plexSettings.Enable) @@ -83,7 +81,9 @@ namespace Ombi.Schedule.Jobs.Plex return; } var processedContent = new ProcessedContent(); - Logger.LogInformation($"Starting Plex Content Cacher {(recentlyAddedSearch ? "Recently Added Scan" : "")}"); + Logger.LogInformation(recentlyAddedSearch + ? "Starting Plex Content Cacher Recently Added Scan" + : "Starting Plex Content Cacher"); try { if (recentlyAddedSearch) @@ -103,7 +103,6 @@ namespace Ombi.Schedule.Jobs.Plex if (!recentlyAddedSearch) { Logger.LogInformation("Starting EP Cacher"); - await OmbiQuartz.TriggerJob(nameof(IPlexEpisodeSync), "Plex"); } diff --git a/src/Ombi.Schedule/OmbiScheduler.cs b/src/Ombi.Schedule/OmbiScheduler.cs index 37240cd52..cfe3bbf27 100644 --- a/src/Ombi.Schedule/OmbiScheduler.cs +++ b/src/Ombi.Schedule/OmbiScheduler.cs @@ -60,7 +60,7 @@ namespace Ombi.Schedule private static async Task AddSystem(JobSettings s) { - await OmbiQuartz.Instance.AddJob(nameof(IRefreshMetadata), "System", JobSettingsHelper.RefreshMetadata(s)); + await OmbiQuartz.Instance.AddJob(nameof(IRefreshMetadata), "System", null); await OmbiQuartz.Instance.AddJob(nameof(IIssuesPurge), "System", JobSettingsHelper.IssuePurge(s)); //OmbiQuartz.Instance.AddJob(nameof(IOmbiAutomaticUpdater), "System", JobSettingsHelper.Updater(s)); await OmbiQuartz.Instance.AddJob(nameof(INewsletterJob), "System", JobSettingsHelper.Newsletter(s)); @@ -80,7 +80,7 @@ namespace Ombi.Schedule private static async Task AddPlex(JobSettings s) { await OmbiQuartz.Instance.AddJob(nameof(IPlexContentSync), "Plex", JobSettingsHelper.PlexContent(s), new Dictionary { { "recentlyAddedSearch", "false" } }); - await OmbiQuartz.Instance.AddJob(nameof(IPlexContentSync) + "RecentlyAdded", "Plex", JobSettingsHelper.PlexRecentlyAdded(s), new Dictionary { { "recentlyAddedSearch", "true" } }); + await OmbiQuartz.Instance.AddJob(nameof(IPlexContentSync) + "RecentlyAdded", "Plex", JobSettingsHelper.PlexRecentlyAdded(s), new Dictionary { { JobDataKeys.RecentlyAddedSearch, "true" } }); await OmbiQuartz.Instance.AddJob(nameof(IPlexUserImporter), "Plex", JobSettingsHelper.UserImporter(s)); await OmbiQuartz.Instance.AddJob(nameof(IPlexEpisodeSync), "Plex", null); await OmbiQuartz.Instance.AddJob(nameof(IPlexAvailabilityChecker), "Plex", null); diff --git a/src/Ombi.Store/Entities/PlexServerContent.cs b/src/Ombi.Store/Entities/PlexServerContent.cs index 17d8ceffb..f8e0e01d4 100644 --- a/src/Ombi.Store/Entities/PlexServerContent.cs +++ b/src/Ombi.Store/Entities/PlexServerContent.cs @@ -53,6 +53,8 @@ namespace Ombi.Store.Entities public DateTime AddedAt { get; set; } public string Quality { get; set; } + public int? RequestId { get; set; } + [NotMapped] public bool HasImdb => !string.IsNullOrEmpty(ImdbId); diff --git a/src/Ombi.Store/Migrations/20191016203035_RequestIdOnPlexContent.Designer.cs b/src/Ombi.Store/Migrations/20191016203035_RequestIdOnPlexContent.Designer.cs new file mode 100644 index 000000000..f0cd74378 --- /dev/null +++ b/src/Ombi.Store/Migrations/20191016203035_RequestIdOnPlexContent.Designer.cs @@ -0,0 +1,1216 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; + +namespace Ombi.Store.Migrations +{ + [DbContext(typeof(OmbiContext))] + [Migration("20191016203035_RequestIdOnPlexContent")] + partial class RequestIdOnPlexContent + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.2-servicing-10034"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider"); + + b.Property("ProviderKey"); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider"); + + b.Property("Name"); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Type"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("ApplicationConfiguration"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuditArea"); + + b.Property("AuditType"); + + b.Property("DateTime"); + + b.Property("Description"); + + b.Property("User"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Content"); + + b.Property("SettingsName"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("Message"); + + b.Property("NotificationType"); + + b.Property("Subject"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("PlayerId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("Alias"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("EmbyConnectUserId"); + + b.Property("EpisodeRequestLimit"); + + b.Property("LastLoggedIn"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("MovieRequestLimit"); + + b.Property("MusicRequestLimit"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("ProviderUserId"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserAccessToken"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("UserType"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("RequestId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("AlbumId"); + + b.Property("ContentId"); + + b.Property("ContentType"); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Completed"); + + b.Property("Dts"); + + b.Property("Error"); + + b.Property("RequestId"); + + b.Property("RetryCount"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("ArtistName"); + + b.Property("Available"); + + b.Property("Cover"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("Disk"); + + b.Property("ForeignAlbumId"); + + b.Property("ForeignArtistId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Rating"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("IssueId"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("ParentRequestId"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("SeriesType"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Value"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Comment"); + + b.Property("Date"); + + b.Property("IssuesId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Description"); + + b.Property("IssueCategoryId"); + + b.Property("IssueId"); + + b.Property("ProviderId"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("ResovledDate"); + + b.Property("Status"); + + b.Property("Subject"); + + b.Property("Title"); + + b.Property("UserReportedId"); + + b.HasKey("Id"); + + b.HasIndex("IssueCategoryId"); + + b.HasIndex("IssueId"); + + b.HasIndex("UserReportedId"); + + b.ToTable("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("Background"); + + b.Property("Denied"); + + b.Property("DeniedReason"); + + b.Property("DigitalReleaseDate"); + + b.Property("ImdbId"); + + b.Property("IssueId"); + + b.Property("LangCode"); + + b.Property("MarkedAsApproved"); + + b.Property("MarkedAsAvailable"); + + b.Property("MarkedAsDenied"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RequestType"); + + b.Property("RequestedByAlias"); + + b.Property("RequestedDate"); + + b.Property("RequestedUserId"); + + b.Property("RootPathOverride"); + + b.Property("Status"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeCount"); + + b.Property("RequestDate"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Background"); + + b.Property("ImdbId"); + + b.Property("Overview"); + + b.Property("PosterPath"); + + b.Property("QualityOverride"); + + b.Property("ReleaseDate"); + + b.Property("RootFolder"); + + b.Property("Status"); + + b.Property("Title"); + + b.Property("TotalSeasons"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Token"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Agent"); + + b.Property("Enabled"); + + b.Property("UserId"); + + b.Property("Value"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("RadarrQualityProfile"); + + b.Property("RadarrRootPath"); + + b.Property("SonarrQualityProfile"); + + b.Property("SonarrQualityProfileAnime"); + + b.Property("SonarrRootPath"); + + b.Property("SonarrRootPathAnime"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Date"); + + b.Property("Deleted"); + + b.Property("RequestId"); + + b.Property("RequestType"); + + b.Property("UserId"); + + b.Property("VoteType"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AirDate"); + + b.Property("Approved"); + + b.Property("Available"); + + b.Property("EpisodeNumber"); + + b.Property("Requested"); + + b.Property("SeasonId"); + + b.Property("Title"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChildRequestId"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues") + .WithMany("Comments") + .HasForeignKey("IssuesId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests") + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/20191016203035_RequestIdOnPlexContent.cs b/src/Ombi.Store/Migrations/20191016203035_RequestIdOnPlexContent.cs new file mode 100644 index 000000000..f197cdcdb --- /dev/null +++ b/src/Ombi.Store/Migrations/20191016203035_RequestIdOnPlexContent.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations +{ + public partial class RequestIdOnPlexContent : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RequestId", + table: "PlexServerContent", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RequestId", + table: "PlexServerContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs index 466011d43..4be5b7a43 100644 --- a/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace Ombi.Store.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.1-servicing-10028"); + .HasAnnotation("ProductVersion", "2.2.2-servicing-10034"); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { @@ -455,6 +455,8 @@ namespace Ombi.Store.Migrations b.Property("ReleaseYear"); + b.Property("RequestId"); + b.Property("TheMovieDbId"); b.Property("Title"); diff --git a/src/Ombi.Store/Repository/BaseRepository.cs b/src/Ombi.Store/Repository/BaseRepository.cs index 82661e0c3..14b871a12 100644 --- a/src/Ombi.Store/Repository/BaseRepository.cs +++ b/src/Ombi.Store/Repository/BaseRepository.cs @@ -90,8 +90,8 @@ namespace Ombi.Store.Repository .WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), - TimeSpan.FromSeconds(2), - TimeSpan.FromSeconds(3) + TimeSpan.FromSeconds(5), + TimeSpan.FromSeconds(10) }); var result = await policy.ExecuteAndCaptureAsync(async () => diff --git a/src/Ombi/Startup.cs b/src/Ombi/Startup.cs index 72b212841..c353bcf6a 100755 --- a/src/Ombi/Startup.cs +++ b/src/Ombi/Startup.cs @@ -27,6 +27,7 @@ using Ombi.Store.Context; using Ombi.Store.Entities; using Ombi.Store.Repository; using Serilog; +using SQLitePCL; using ILogger = Serilog.ILogger; namespace Ombi @@ -97,8 +98,7 @@ namespace Ombi x.UseActivator(new IoCJobActivator(services.BuildServiceProvider())); }); - - SQLitePCL.raw.sqlite3_config(2); + SQLitePCL.raw.sqlite3_config(raw.SQLITE_CONFIG_MULTITHREAD); services.AddCors(o => o.AddPolicy("MyPolicy", builder => { From c547777df7b98a6098c79882d18bb52973bb9d85 Mon Sep 17 00:00:00 2001 From: Jamie Date: Wed, 16 Oct 2019 22:57:25 +0100 Subject: [PATCH 02/19] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae8417bae..a611b5b99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## (unreleased) +## v3.0.4817 (2019-10-15) ### **New Features** From 2c8e50e9ffd48251f3bfeeef1eb2d48c215e6026 Mon Sep 17 00:00:00 2001 From: Jamie Rees Date: Fri, 18 Oct 2019 10:14:08 +0100 Subject: [PATCH 03/19] Add SK lang --- src/Ombi/ClientApp/app/app.component.html | 9 ++++++--- src/Ombi/ClientApp/app/app.component.ts | 4 ++-- src/Ombi/wwwroot/translations/sk.json | 3 +++ 3 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 src/Ombi/wwwroot/translations/sk.json diff --git a/src/Ombi/ClientApp/app/app.component.html b/src/Ombi/ClientApp/app/app.component.html index 08c153f31..d0d4e2a81 100644 --- a/src/Ombi/ClientApp/app/app.component.html +++ b/src/Ombi/ClientApp/app/app.component.html @@ -127,6 +127,9 @@
  • English
  • +
  • + Español +
  • Français
  • @@ -139,9 +142,6 @@
  • Italiano
  • -
  • - Español -
  • Nederlands
  • @@ -157,6 +157,9 @@
  • Svenska
  • +
  • + Slovak +
  • diff --git a/src/Ombi/ClientApp/app/app.component.ts b/src/Ombi/ClientApp/app/app.component.ts index 7005f147c..3c235ba1a 100644 --- a/src/Ombi/ClientApp/app/app.component.ts +++ b/src/Ombi/ClientApp/app/app.component.ts @@ -43,13 +43,13 @@ export class AppComponent implements OnInit { __webpack_public_path__ = base + "/dist/"; } - this.translate.addLangs(["en", "de", "fr", "da", "es", "it", "nl", "sv", "no", "pl", "pt"]); + this.translate.addLangs(["en", "de", "fr", "da", "es", "it", "nl", "sk", "sv", "no", "pl", "pt"]); // this language will be used as a fallback when a translation isn't found in the current language this.translate.setDefaultLang("en"); // See if we can match the supported langs with the current browser lang const browserLang: string = translate.getBrowserLang(); - this.translate.use(browserLang.match(/en|fr|da|de|es|it|nl|sv|no|pl|pt/) ? browserLang : "en"); + this.translate.use(browserLang.match(/en|fr|da|de|es|it|nl|sk|sv|no|pl|pt/) ? browserLang : "en"); } public ngOnInit() { diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json new file mode 100644 index 000000000..544b7b4dd --- /dev/null +++ b/src/Ombi/wwwroot/translations/sk.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file From c1360ca51585757b182b1974c3e63e2c34dbff65 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 10:32:07 +0100 Subject: [PATCH 04/19] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 186 ++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 src/Ombi/wwwroot/translations/sk.json diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json new file mode 100644 index 000000000..7fabf59d9 --- /dev/null +++ b/src/Ombi/wwwroot/translations/sk.json @@ -0,0 +1,186 @@ +{ + "Login": { + "SignInButton": "Sign in", + "UsernamePlaceholder": "Username", + "PasswordPlaceholder": "Password", + "RememberMe": "Remember Me", + "ForgottenPassword": "Forgot your password?", + "Errors": { + "IncorrectCredentials": "Incorrect username or password" + } + }, + "Common": { + "ContinueButton": "Continue", + "Available": "Available", + "PartiallyAvailable": "Partially Available", + "Monitored": "Monitored", + "NotAvailable": "Not Available", + "ProcessingRequest": "Processing Request", + "PendingApproval": "Pending Approval", + "RequestDenied": "Request Denied", + "NotRequested": "Not Requested", + "Requested": "Requested", + "Request": "Request", + "Denied": "Denied", + "Approve": "Approve", + "PartlyAvailable": "Partly Available", + "Errors": { + "Validation": "Please check your entered values" + } + }, + "PasswordReset": { + "EmailAddressPlaceholder": "Email Address", + "ResetPasswordButton": "Reset Password" + }, + "LandingPage": { + "OnlineHeading": "Currently Online", + "OnlineParagraph": "The media server is currently online", + "PartiallyOnlineHeading": "Partially Online", + "PartiallyOnlineParagraph": "The media server is partially online.", + "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", + "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", + "OfflineHeading": "Currently Offline", + "OfflineParagraph": "The media server is currently offline.", + "CheckPageForUpdates": "Check this page for continuous site updates." + }, + "NavigationBar": { + "Search": "Search", + "Requests": "Requests", + "UserManagement": "User Management", + "Issues": "Issues", + "Vote": "Vote", + "Donate": "Donate!", + "DonateLibraryMaintainer": "Donate to Library Maintainer", + "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi ;)", + "UpdateAvailableTooltip": "Update Available!", + "Settings": "Settings", + "Welcome": "Welcome {{username}}", + "UpdateDetails": "Update Details", + "Logout": "Logout", + "OpenMobileApp": "Open Mobile App", + "RecentlyAdded": "Recently Added" + }, + "Search": { + "Title": "Search", + "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", + "MoviesTab": "Movies", + "TvTab": "TV Shows", + "MusicTab": "Music", + "Suggestions": "Suggestions", + "NoResults": "Sorry, we didn't find any results!", + "DigitalDate": "Digital Release: {{date}}", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ViewOnPlex": "View On Plex", + "ViewOnEmby": "View On Emby", + "RequestAdded": "Request for {{title}} has been added successfully", + "Similar": "Similar", + "Refine": "Refine", + "SearchBarPlaceholder": "Type Here to Search", + "Movies": { + "PopularMovies": "Popular Movies", + "UpcomingMovies": "Upcoming Movies", + "TopRatedMovies": "Top Rated Movies", + "NowPlayingMovies": "Now Playing Movies", + "HomePage": "Home Page", + "Trailer": "Trailer" + }, + "TvShows": { + "Popular": "Popular", + "Trending": "Trending", + "MostWatched": "Most Watched", + "MostAnticipated": "Most Anticipated", + "Results": "Results", + "AirDate": "Air Date:", + "AllSeasons": "All Seasons", + "FirstSeason": "First Season", + "LatestSeason": "Latest Season", + "Select": "Select ...", + "SubmitRequest": "Submit Request", + "Season": "Season: {{seasonNumber}}", + "SelectAllInSeason": "Select All in Season {{seasonNumber}}" + } + }, + "Requests": { + "Title": "Requests", + "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", + "MoviesTab": "Movies", + "TvTab": "TV Shows", + "MusicTab": "Music", + "RequestedBy": "Requested By:", + "Status": "Status:", + "RequestStatus": "Request status:", + "Denied": " Denied:", + "TheatricalRelease": "Theatrical Release: {{date}}", + "ReleaseDate": "Released: {{date}}", + "TheatricalReleaseSort": "Theatrical Release", + "DigitalRelease": "Digital Release: {{date}}", + "RequestDate": "Request Date:", + "QualityOverride": "Quality Override:", + "RootFolderOverride": "Root Folder Override:", + "ChangeRootFolder": "Root Folder", + "ChangeQualityProfile": "Quality Profile", + "MarkUnavailable": "Mark Unavailable", + "MarkAvailable": "Mark Available", + "Remove": "Remove", + "Deny": "Deny", + "Season": "Season:", + "GridTitle": "Title", + "AirDate": "AirDate", + "GridStatus": "Status", + "ReportIssue": "Report Issue", + "Filter": "Filter", + "Sort": "Sort", + "SeasonNumberHeading": "Season: {seasonNumber}", + "SortTitleAsc": "Title ▲", + "SortTitleDesc": "Title ▼", + "SortRequestDateAsc": "Request Date ▲", + "SortRequestDateDesc": "Request Date ▼", + "SortStatusAsc": "Status ▲", + "SortStatusDesc": "Status ▼", + "Remaining": { + "Quota": "{{remaining}}/{{total}} requests remaining", + "NextDays": "Another request will be added in {{time}} days", + "NextHours": "Another request will be added in {{time}} hours", + "NextMinutes": "Another request will be added in {{time}} minutes", + "NextMinute": "Another request will be added in {{time}} minute" + } + }, + "Issues": { + "Title": "Issues", + "PendingTitle": "Pending Issues", + "InProgressTitle": "In Progress Issues", + "ResolvedTitle": "Resolved Issues", + "ColumnTitle": "Title", + "Category": "Category", + "Status": "Status", + "Details": "Details", + "Description": "Description", + "NoComments": "No Comments!", + "MarkInProgress": "Mark In Progress", + "MarkResolved": "Mark Resolved", + "SendMessageButton": "Send", + "Subject": "Subject", + "Comments": "Comments", + "WriteMessagePlaceholder": "Write your message here...", + "ReportedBy": "Reported By" + }, + "Filter": { + "ClearFilter": "Clear Filter", + "FilterHeaderAvailability": "Availability", + "FilterHeaderRequestStatus": "Status", + "Approved": "Approved", + "PendingApproval": "Pending Approval" + }, + "UserManagment": { + "TvRemaining": "TV: {{remaining}}/{{total}} remaining", + "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", + "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvDue": "TV: {{date}}", + "MovieDue": "Movie: {{date}}", + "MusicDue": "Music: {{date}}" + }, + "Votes": { + "CompletedVotesTab": "Voted", + "VotesTab": "Votes Needed" + } +} From 65895d541e965c2c6d12fe4545ef99dfea548170 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 10:41:48 +0100 Subject: [PATCH 05/19] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 56 +++++++++++++-------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 7fabf59d9..0304fd926 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -1,43 +1,43 @@ { "Login": { - "SignInButton": "Sign in", - "UsernamePlaceholder": "Username", - "PasswordPlaceholder": "Password", - "RememberMe": "Remember Me", - "ForgottenPassword": "Forgot your password?", + "SignInButton": "Prihláste sa", + "UsernamePlaceholder": "Užívateľské meno", + "PasswordPlaceholder": "Heslo", + "RememberMe": "Zapamätať prihlásenie", + "ForgottenPassword": "Zabudli ste heslo?", "Errors": { - "IncorrectCredentials": "Incorrect username or password" + "IncorrectCredentials": "Nesprávne meno alebo heslo" } }, "Common": { - "ContinueButton": "Continue", - "Available": "Available", - "PartiallyAvailable": "Partially Available", - "Monitored": "Monitored", - "NotAvailable": "Not Available", - "ProcessingRequest": "Processing Request", - "PendingApproval": "Pending Approval", - "RequestDenied": "Request Denied", - "NotRequested": "Not Requested", - "Requested": "Requested", - "Request": "Request", - "Denied": "Denied", - "Approve": "Approve", - "PartlyAvailable": "Partly Available", + "ContinueButton": "Pokračovať", + "Available": "Dostupné", + "PartiallyAvailable": "Čiastočne dostupné", + "Monitored": "Sledované", + "NotAvailable": "Nie je k dispozícii", + "ProcessingRequest": "Spracovávanie požiadavky", + "PendingApproval": "Čaká na schválenie", + "RequestDenied": "Požiadavka zamietnutá", + "NotRequested": "Nepožiadané", + "Requested": "Požiadané", + "Request": "Požiadavka", + "Denied": "Zamietnuté", + "Approve": "Schválené", + "PartlyAvailable": "Čiastočne dostupné", "Errors": { - "Validation": "Please check your entered values" + "Validation": "Skontrolujte zadaný obsah" } }, "PasswordReset": { - "EmailAddressPlaceholder": "Email Address", - "ResetPasswordButton": "Reset Password" + "EmailAddressPlaceholder": "Emailová adresa", + "ResetPasswordButton": "Nastaviť nové heslo" }, "LandingPage": { - "OnlineHeading": "Currently Online", - "OnlineParagraph": "The media server is currently online", - "PartiallyOnlineHeading": "Partially Online", - "PartiallyOnlineParagraph": "The media server is partially online.", - "MultipleServersUnavailable": "There are {{serversUnavailable}} servers offline out of {{totalServers}}.", + "OnlineHeading": "Momentálne online", + "OnlineParagraph": "Mediálny server je momentálne online", + "PartiallyOnlineHeading": "Čiastočne online", + "PartiallyOnlineParagraph": "Mediálny server je momentálne online.", + "MultipleServersUnavailable": "Momntálne je {{serversUnavailable}} server offline z {{totalServers}}.", "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", "OfflineHeading": "Currently Offline", "OfflineParagraph": "The media server is currently offline.", From 22c824e9b05994ad6de913e2ed58eaee10743390 Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 10:55:28 +0100 Subject: [PATCH 06/19] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 104 +++++++++++++------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 0304fd926..37da47913 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -37,33 +37,33 @@ "OnlineParagraph": "Mediálny server je momentálne online", "PartiallyOnlineHeading": "Čiastočne online", "PartiallyOnlineParagraph": "Mediálny server je momentálne online.", - "MultipleServersUnavailable": "Momntálne je {{serversUnavailable}} server offline z {{totalServers}}.", - "SingleServerUnavailable": "There is {{serversUnavailable}} server offline out of {{totalServers}}.", - "OfflineHeading": "Currently Offline", - "OfflineParagraph": "The media server is currently offline.", - "CheckPageForUpdates": "Check this page for continuous site updates." + "MultipleServersUnavailable": "Momntálne je {{serversUnavailable}} serverov offline z {{totalServers}}.", + "SingleServerUnavailable": "Momntálne je {{serversUnavailable}} server offline z {{totalServers}}.", + "OfflineHeading": "Momentálne offline", + "OfflineParagraph": "Mediálny server je momentálne offline.", + "CheckPageForUpdates": "Prezrite túto stránku pre aktualizácie." }, "NavigationBar": { - "Search": "Search", - "Requests": "Requests", - "UserManagement": "User Management", - "Issues": "Issues", - "Vote": "Vote", - "Donate": "Donate!", + "Search": "Hľadať", + "Requests": "Požiadavky", + "UserManagement": "Správa užívateľov", + "Issues": "Problémy", + "Vote": "Hlasovať", + "Donate": "Prispieť!", "DonateLibraryMaintainer": "Donate to Library Maintainer", "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi ;)", - "UpdateAvailableTooltip": "Update Available!", - "Settings": "Settings", - "Welcome": "Welcome {{username}}", - "UpdateDetails": "Update Details", - "Logout": "Logout", - "OpenMobileApp": "Open Mobile App", - "RecentlyAdded": "Recently Added" + "UpdateAvailableTooltip": "K dispozícii je aktualizácia!", + "Settings": "Nastavenie", + "Welcome": "Vitaj {{username}}", + "UpdateDetails": "Aktualizovať údaje", + "Logout": "Odhlásiť sa", + "OpenMobileApp": "Otvoriť mobilnú aplikáciu", + "RecentlyAdded": "Nedávno pridané" }, "Search": { - "Title": "Search", - "Paragraph": "Want to watch something that is not currently available? No problem, just search for it below and request it!", - "MoviesTab": "Movies", + "Title": "Hľadať", + "Paragraph": "Chcete sledovať niečo, čo v súčasnosti nie je k dispozícii? Žiadny problém. Vyhľadajte to nižšie a požiadajte o to!", + "MoviesTab": "Filmy", "TvTab": "TV Shows", "MusicTab": "Music", "Suggestions": "Suggestions", @@ -119,42 +119,42 @@ "RootFolderOverride": "Root Folder Override:", "ChangeRootFolder": "Root Folder", "ChangeQualityProfile": "Quality Profile", - "MarkUnavailable": "Mark Unavailable", - "MarkAvailable": "Mark Available", - "Remove": "Remove", - "Deny": "Deny", - "Season": "Season:", - "GridTitle": "Title", - "AirDate": "AirDate", - "GridStatus": "Status", - "ReportIssue": "Report Issue", + "MarkUnavailable": "Označiť nedostupné", + "MarkAvailable": "Označiť dostupné", + "Remove": "Odstrániť", + "Deny": "Odmietnuť", + "Season": "Séria:", + "GridTitle": "Názov", + "AirDate": "Dátum vysielania", + "GridStatus": "Stav", + "ReportIssue": "Nahlásiť problém", "Filter": "Filter", - "Sort": "Sort", - "SeasonNumberHeading": "Season: {seasonNumber}", - "SortTitleAsc": "Title ▲", - "SortTitleDesc": "Title ▼", - "SortRequestDateAsc": "Request Date ▲", - "SortRequestDateDesc": "Request Date ▼", - "SortStatusAsc": "Status ▲", - "SortStatusDesc": "Status ▼", + "Sort": "Triediť", + "SeasonNumberHeading": "Séria: {seasonNumber}", + "SortTitleAsc": "Názov ▲", + "SortTitleDesc": "Názov ▼", + "SortRequestDateAsc": "Dátum požiadavky ▲", + "SortRequestDateDesc": "Dátum požiadavky ▼", + "SortStatusAsc": "Stav ▲", + "SortStatusDesc": "Stav ▼", "Remaining": { - "Quota": "{{remaining}}/{{total}} requests remaining", - "NextDays": "Another request will be added in {{time}} days", - "NextHours": "Another request will be added in {{time}} hours", - "NextMinutes": "Another request will be added in {{time}} minutes", - "NextMinute": "Another request will be added in {{time}} minute" + "Quota": "{{remaining}}/{{total}} zostávajúce žiadosti", + "NextDays": "Ďalšia žiadosť bude pridaná o {{time}} dní", + "NextHours": "Ďalšia žiadosť bude pridaná o {{time}} hodín", + "NextMinutes": "Ďalšia žiadosť bude pridaná o {{time}} minút", + "NextMinute": "Ďalšia žiadosť bude pridaná o {{time}} minútu" } }, "Issues": { - "Title": "Issues", - "PendingTitle": "Pending Issues", - "InProgressTitle": "In Progress Issues", - "ResolvedTitle": "Resolved Issues", - "ColumnTitle": "Title", - "Category": "Category", - "Status": "Status", - "Details": "Details", - "Description": "Description", + "Title": "Problémy", + "PendingTitle": "Nevyriešené problémy", + "InProgressTitle": "Riešené problémy", + "ResolvedTitle": "Vyiešené problémy", + "ColumnTitle": "Názov", + "Category": "Kategória", + "Status": "Stav", + "Details": "Podrobnosti", + "Description": "Popis", "NoComments": "No Comments!", "MarkInProgress": "Mark In Progress", "MarkResolved": "Mark Resolved", From 9d1a53e1f3bcf00ad270d197cd391e6a4eb7862e Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 11:06:40 +0100 Subject: [PATCH 07/19] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 70 +++++++++++++-------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 37da47913..23fa5dfd4 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -64,28 +64,28 @@ "Title": "Hľadať", "Paragraph": "Chcete sledovať niečo, čo v súčasnosti nie je k dispozícii? Žiadny problém. Vyhľadajte to nižšie a požiadajte o to!", "MoviesTab": "Filmy", - "TvTab": "TV Shows", - "MusicTab": "Music", - "Suggestions": "Suggestions", - "NoResults": "Sorry, we didn't find any results!", - "DigitalDate": "Digital Release: {{date}}", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ViewOnPlex": "View On Plex", - "ViewOnEmby": "View On Emby", - "RequestAdded": "Request for {{title}} has been added successfully", - "Similar": "Similar", - "Refine": "Refine", - "SearchBarPlaceholder": "Type Here to Search", + "TvTab": "Seriály", + "MusicTab": "Hudba", + "Suggestions": "Návrhy", + "NoResults": "Ľutujeme, nenašli sme žiadne výsledky!", + "DigitalDate": "Online vydanie: {{date}}", + "TheatricalRelease": "Kino vydanie: {{date}}", + "ViewOnPlex": "Zobraziť na Plex", + "ViewOnEmby": "Zobraziť na Emby", + "RequestAdded": "Žiadosť o {{title}} bola úspešne pridaná", + "Similar": "Podobné", + "Refine": "Filtrovať", + "SearchBarPlaceholder": "Tu zadajte pre vyhľadávanie", "Movies": { - "PopularMovies": "Popular Movies", - "UpcomingMovies": "Upcoming Movies", - "TopRatedMovies": "Top Rated Movies", - "NowPlayingMovies": "Now Playing Movies", - "HomePage": "Home Page", - "Trailer": "Trailer" + "PopularMovies": "Populárne filmy", + "UpcomingMovies": "Blížiace sa filmy", + "TopRatedMovies": "Najlepšie hodnotené filmy", + "NowPlayingMovies": "Teraz prehrávané filmy", + "HomePage": "Úvodná stránka", + "Trailer": "Upútavka" }, "TvShows": { - "Popular": "Popular", + "Popular": "Populárne", "Trending": "Trending", "MostWatched": "Most Watched", "MostAnticipated": "Most Anticipated", @@ -155,26 +155,26 @@ "Status": "Stav", "Details": "Podrobnosti", "Description": "Popis", - "NoComments": "No Comments!", - "MarkInProgress": "Mark In Progress", - "MarkResolved": "Mark Resolved", - "SendMessageButton": "Send", - "Subject": "Subject", - "Comments": "Comments", - "WriteMessagePlaceholder": "Write your message here...", - "ReportedBy": "Reported By" + "NoComments": "Žiadne komentáre!", + "MarkInProgress": "Označiť ako prebiehajúce", + "MarkResolved": "Označiť ako vyriešené", + "SendMessageButton": "Odoslať", + "Subject": "Predmet", + "Comments": "Komentáre", + "WriteMessagePlaceholder": "Napíšte správu sem...", + "ReportedBy": "Nahlásené od" }, "Filter": { - "ClearFilter": "Clear Filter", - "FilterHeaderAvailability": "Availability", - "FilterHeaderRequestStatus": "Status", - "Approved": "Approved", - "PendingApproval": "Pending Approval" + "ClearFilter": "Vymazať filter", + "FilterHeaderAvailability": "Dostupnosť", + "FilterHeaderRequestStatus": "Stav", + "Approved": "Schválené", + "PendingApproval": "Čaká na schválenie" }, "UserManagment": { - "TvRemaining": "TV: {{remaining}}/{{total}} remaining", - "MovieRemaining": "Movies: {{remaining}}/{{total}} remaining", - "MusicRemaining": "Music: {{remaining}}/{{total}} remaining", + "TvRemaining": "TV: {{remaining}}/{{total}} zostávajúce", + "MovieRemaining": "Filmy: {{remaining}}/{{total}} zostávajúce", + "MusicRemaining": "Hudba: {{remaining}}/{{total}} zostávajúce", "TvDue": "TV: {{date}}", "MovieDue": "Movie: {{date}}", "MusicDue": "Music: {{date}}" From c1dc15c78af0ea418597dc1a486e32c7572371ad Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 11:13:35 +0100 Subject: [PATCH 08/19] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 62 +++++++++++++-------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 23fa5dfd4..42b7a9fd3 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -78,7 +78,7 @@ "SearchBarPlaceholder": "Tu zadajte pre vyhľadávanie", "Movies": { "PopularMovies": "Populárne filmy", - "UpcomingMovies": "Blížiace sa filmy", + "UpcomingMovies": "Očakávané filmy", "TopRatedMovies": "Najlepšie hodnotené filmy", "NowPlayingMovies": "Teraz prehrávané filmy", "HomePage": "Úvodná stránka", @@ -86,39 +86,39 @@ }, "TvShows": { "Popular": "Populárne", - "Trending": "Trending", - "MostWatched": "Most Watched", - "MostAnticipated": "Most Anticipated", - "Results": "Results", - "AirDate": "Air Date:", - "AllSeasons": "All Seasons", - "FirstSeason": "First Season", - "LatestSeason": "Latest Season", - "Select": "Select ...", - "SubmitRequest": "Submit Request", - "Season": "Season: {{seasonNumber}}", - "SelectAllInSeason": "Select All in Season {{seasonNumber}}" + "Trending": "Trendy", + "MostWatched": "Najsledovanejšie", + "MostAnticipated": "Najočakávanejšie", + "Results": "Výsledky", + "AirDate": "Dátum vysielania:", + "AllSeasons": "Všetky série", + "FirstSeason": "Prvá séria", + "LatestSeason": "Posledná séria", + "Select": "Vybrať ...", + "SubmitRequest": "Poslať žiadosť", + "Season": "Séria: {{seasonNumber}}", + "SelectAllInSeason": "Vybrať všetko v danej sérii {{seasonNumber}}" } }, "Requests": { - "Title": "Requests", - "Paragraph": "Below you can see yours and all other requests, as well as their download and approval status.", - "MoviesTab": "Movies", - "TvTab": "TV Shows", - "MusicTab": "Music", - "RequestedBy": "Requested By:", - "Status": "Status:", - "RequestStatus": "Request status:", - "Denied": " Denied:", - "TheatricalRelease": "Theatrical Release: {{date}}", - "ReleaseDate": "Released: {{date}}", - "TheatricalReleaseSort": "Theatrical Release", - "DigitalRelease": "Digital Release: {{date}}", - "RequestDate": "Request Date:", - "QualityOverride": "Quality Override:", - "RootFolderOverride": "Root Folder Override:", - "ChangeRootFolder": "Root Folder", - "ChangeQualityProfile": "Quality Profile", + "Title": "Požiadavky", + "Paragraph": "Nižšie nájdete svoje a všetky ďalšie žiadosti, ako aj stav ich sťahovania a schvaľovania.", + "MoviesTab": "Filmy", + "TvTab": "Seriály", + "MusicTab": "Hudba", + "RequestedBy": "Vyžiadané od:", + "Status": "Stav:", + "RequestStatus": "Stav požiadavky:", + "Denied": " Zamietnuté:", + "TheatricalRelease": "Kino vydanie: {{date}}", + "ReleaseDate": "Vydané: {{date}}", + "TheatricalReleaseSort": "Kino vydanie", + "DigitalRelease": "Online vydanie: {{date}}", + "RequestDate": "Dátum požiadavky:", + "QualityOverride": "Prepísanie kvality:", + "RootFolderOverride": "Prepísanie Root priečinku:", + "ChangeRootFolder": "Koreňový priečinok", + "ChangeQualityProfile": "Profil kvality", "MarkUnavailable": "Označiť nedostupné", "MarkAvailable": "Označiť dostupné", "Remove": "Odstrániť", From 1f9a31f4fef954fa8f6196665e2a7dd68b02b39b Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 11:31:51 +0100 Subject: [PATCH 09/19] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 42b7a9fd3..9b4f1221d 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -50,8 +50,8 @@ "Issues": "Problémy", "Vote": "Hlasovať", "Donate": "Prispieť!", - "DonateLibraryMaintainer": "Donate to Library Maintainer", - "DonateTooltip": "This is how I convince my wife to let me spend my spare time developing Ombi ;)", + "DonateLibraryMaintainer": "Darovať správcovi knižnice", + "DonateTooltip": "Takto som presvedčil svoju manželku, aby mi umožnila tráviť svoj voľný čas vývojom Ombi ;)", "UpdateAvailableTooltip": "K dispozícii je aktualizácia!", "Settings": "Nastavenie", "Welcome": "Vitaj {{username}}", @@ -176,11 +176,11 @@ "MovieRemaining": "Filmy: {{remaining}}/{{total}} zostávajúce", "MusicRemaining": "Hudba: {{remaining}}/{{total}} zostávajúce", "TvDue": "TV: {{date}}", - "MovieDue": "Movie: {{date}}", - "MusicDue": "Music: {{date}}" + "MovieDue": "Film: {{date}}", + "MusicDue": "Hudba: {{date}}" }, "Votes": { - "CompletedVotesTab": "Voted", - "VotesTab": "Votes Needed" + "CompletedVotesTab": "Hlasované", + "VotesTab": "Potrebné hlasovanie" } } From 371a48878c0252cca75a5b8738f8617dfd5c2fbb Mon Sep 17 00:00:00 2001 From: Jamie Date: Fri, 18 Oct 2019 11:53:16 +0100 Subject: [PATCH 10/19] New translations en.json (Slovak) --- src/Ombi/wwwroot/translations/sk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/wwwroot/translations/sk.json b/src/Ombi/wwwroot/translations/sk.json index 9b4f1221d..d7c3e376a 100644 --- a/src/Ombi/wwwroot/translations/sk.json +++ b/src/Ombi/wwwroot/translations/sk.json @@ -20,7 +20,7 @@ "RequestDenied": "Požiadavka zamietnutá", "NotRequested": "Nepožiadané", "Requested": "Požiadané", - "Request": "Požiadavka", + "Request": "Požiadať", "Denied": "Zamietnuté", "Approve": "Schválené", "PartlyAvailable": "Čiastočne dostupné", From 5d73845951778335c587fd36bbb1f76804763d11 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 19 Oct 2019 00:00:13 +0100 Subject: [PATCH 11/19] Add the migration to the correct database... #3214 --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 12 +- .../20191018225833_PlexContentId.Designer.cs | 314 ++++++++++++++++++ .../External/20191018225833_PlexContentId.cs | 22 ++ .../External/ExternalContextModelSnapshot.cs | 4 +- 4 files changed, 347 insertions(+), 5 deletions(-) create mode 100644 src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.Designer.cs create mode 100644 src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.cs diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 710c39595..f6d61b30d 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -714,7 +714,8 @@ namespace Ombi.Schedule.Jobs.Ombi (key, g) => new { SeasonNumber = key, - Episodes = g.ToList() + Episodes = g.ToList(), + EpisodeAirDate = tvInfo.seasons.Where(x => x.season_number == key).Select(x => x.air_date) } ); @@ -724,7 +725,8 @@ namespace Ombi.Schedule.Jobs.Ombi { var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); - finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString}"); + var episodeAirDate = epInformation.EpisodeAirDate; + finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}"); finalsb.Append("
    "); } @@ -837,7 +839,8 @@ namespace Ombi.Schedule.Jobs.Ombi (key, g) => new { SeasonNumber = key, - Episodes = g.ToList() + Episodes = g.ToList(), + EpisodeAirDate = tvInfo.seasons.Where(x => x.season_number == key).Select(x => x.air_date) } ); @@ -847,7 +850,8 @@ namespace Ombi.Schedule.Jobs.Ombi { var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); - finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString}"); + var episodeAirDate = epInformation.EpisodeAirDate; + finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}"); finalsb.Append("
    "); } diff --git a/src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.Designer.cs b/src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.Designer.cs new file mode 100644 index 000000000..cba04a14c --- /dev/null +++ b/src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.Designer.cs @@ -0,0 +1,314 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context; + +namespace Ombi.Store.Migrations.External +{ + [DbContext(typeof(ExternalContext))] + [Migration("20191018225833_PlexContentId")] + partial class PlexContentId + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.2-servicing-10034"); + + modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("CouchPotatoCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId") + .IsRequired(); + + b.Property("ImdbId"); + + b.Property("ProviderId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("EmbyContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("EmbyId"); + + b.Property("EpisodeNumber"); + + b.Property("ImdbId"); + + b.Property("ParentId"); + + b.Property("ProviderId"); + + b.Property("SeasonNumber"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("EmbyEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ArtistId"); + + b.Property("ForeignAlbumId"); + + b.Property("Monitored"); + + b.Property("PercentOfTracks"); + + b.Property("ReleaseDate"); + + b.Property("Title"); + + b.Property("TrackCount"); + + b.HasKey("Id"); + + b.ToTable("LidarrAlbumCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ArtistId"); + + b.Property("ArtistName"); + + b.Property("ForeignArtistId"); + + b.Property("Monitored"); + + b.HasKey("Id"); + + b.ToTable("LidarrArtistCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("GrandparentKey"); + + b.Property("Key"); + + b.Property("ParentKey"); + + b.Property("SeasonNumber"); + + b.Property("Title"); + + b.HasKey("Id"); + + b.HasIndex("GrandparentKey"); + + b.ToTable("PlexEpisode"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ParentKey"); + + b.Property("PlexContentId"); + + b.Property("PlexServerContentId"); + + b.Property("SeasonKey"); + + b.Property("SeasonNumber"); + + b.HasKey("Id"); + + b.HasIndex("PlexServerContentId"); + + b.ToTable("PlexSeasonsContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AddedAt"); + + b.Property("ImdbId"); + + b.Property("Key"); + + b.Property("Quality"); + + b.Property("ReleaseYear"); + + b.Property("RequestId"); + + b.Property("TheMovieDbId"); + + b.Property("Title"); + + b.Property("TvDbId"); + + b.Property("Type"); + + b.Property("Url"); + + b.HasKey("Id"); + + b.ToTable("PlexServerContent"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("HasFile"); + + b.Property("TheMovieDbId"); + + b.HasKey("Id"); + + b.ToTable("RadarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SickRageEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("EpisodeNumber"); + + b.Property("HasFile"); + + b.Property("SeasonNumber"); + + b.Property("TvDbId"); + + b.HasKey("Id"); + + b.ToTable("SonarrEpisodeCache"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b => + { + b.HasOne("Ombi.Store.Entities.EmbyContent", "Series") + .WithMany("Episodes") + .HasForeignKey("ParentId") + .HasPrincipalKey("EmbyId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series") + .WithMany("Episodes") + .HasForeignKey("GrandparentKey") + .HasPrincipalKey("Key") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b => + { + b.HasOne("Ombi.Store.Entities.PlexServerContent") + .WithMany("Seasons") + .HasForeignKey("PlexServerContentId"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.cs b/src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.cs new file mode 100644 index 000000000..5d5e33dce --- /dev/null +++ b/src/Ombi.Store/Migrations/External/20191018225833_PlexContentId.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.External +{ + public partial class PlexContentId : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RequestId", + table: "PlexServerContent", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RequestId", + table: "PlexServerContent"); + } + } +} diff --git a/src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs b/src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs index 4e97b5514..77ef6b080 100644 --- a/src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/External/ExternalContextModelSnapshot.cs @@ -14,7 +14,7 @@ namespace Ombi.Store.Migrations.External { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.1.3-rtm-32065"); + .HasAnnotation("ProductVersion", "2.2.2-servicing-10034"); modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b => { @@ -194,6 +194,8 @@ namespace Ombi.Store.Migrations.External b.Property("ReleaseYear"); + b.Property("RequestId"); + b.Property("TheMovieDbId"); b.Property("Title"); From 3008cd124d8454024d1de6340497fd4f91d3e815 Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Sat, 19 Oct 2019 00:53:27 -0500 Subject: [PATCH 12/19] Add adult movie filtering --- src/Ombi.Api/Request.cs | 19 +-- .../Models/External/TheMovieDbSettings.cs | 9 ++ src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 122 ++++++++++++------ .../ClientApp/app/interfaces/ISettings.ts | 5 + .../app/services/settings.service.ts | 9 ++ .../ClientApp/app/settings/settings.module.ts | 3 + .../app/settings/settingsmenu.component.html | 1 + .../themoviedb/themoviedb.component.html | 29 +++++ .../themoviedb/themoviedb.component.ts | 32 +++++ src/Ombi/Controllers/SettingsController.cs | 19 +++ 10 files changed, 187 insertions(+), 61 deletions(-) create mode 100644 src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs create mode 100644 src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html create mode 100644 src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts diff --git a/src/Ombi.Api/Request.cs b/src/Ombi.Api/Request.cs index fd888d0d2..918e189fe 100644 --- a/src/Ombi.Api/Request.cs +++ b/src/Ombi.Api/Request.cs @@ -93,24 +93,7 @@ namespace Ombi.Api public void AddQueryString(string key, string value) { if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) return; - - var builder = new UriBuilder(FullUri); - var startingTag = string.Empty; - var hasQuery = false; - if (string.IsNullOrEmpty(builder.Query)) - { - startingTag = "?"; - } - else - { - hasQuery = true; - startingTag = builder.Query.Contains("?") ? "&" : "?"; - } - builder.Query = hasQuery - ? $"{builder.Query}{startingTag}{key}={value}" - : $"{startingTag}{key}={value}"; - - _modified = builder.Uri; + _modified = FullUri.AddQueryParameter(key, value); } public void AddJsonBody(object obj) diff --git a/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs new file mode 100644 index 000000000..562d9fc88 --- /dev/null +++ b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs @@ -0,0 +1,9 @@ +namespace Ombi.Core.Settings.Models.External +{ + public sealed class TheMovieDbSettings : Ombi.Settings.Settings.Models.Settings + { + public bool ShowAdultMovies { get; set; } + + public string ExcludedKeywordIds { get; set; } + } +} diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 79ccc5bb7..7c24d4c60 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -1,31 +1,36 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Threading.Tasks; using AutoMapper; +using Nito.AsyncEx; using Ombi.Api.TheMovieDb.Models; -using Ombi.Helpers; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; using Ombi.TheMovieDbApi.Models; namespace Ombi.Api.TheMovieDb { public class TheMovieDbApi : IMovieDbApi { - public TheMovieDbApi(IMapper mapper, IApi api) + public TheMovieDbApi(IMapper mapper, IApi api, ISettingsService settingsService) { Api = api; Mapper = mapper; + Settings = new AsyncLazy(() => settingsService.GetSettingsAsync()); } + private const string ApiToken = "b8eabaf5608b88d0298aa189dd90bf00"; + private const string BaseUri ="http://api.themoviedb.org/3/"; private IMapper Mapper { get; } - private readonly string ApiToken = "b8eabaf5608b88d0298aa189dd90bf00"; - private static readonly string BaseUri ="http://api.themoviedb.org/3/"; private IApi Api { get; } + private AsyncLazy Settings { get; } public async Task GetMovieInformation(int movieId) { var request = new Request($"movie/{movieId}", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.AddQueryString("api_key", ApiToken); AddRetry(request); var result = await Api.Request(request); @@ -35,7 +40,7 @@ namespace Ombi.Api.TheMovieDb public async Task Find(string externalId, ExternalSource source) { var request = new Request($"find/{externalId}", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.AddQueryString("api_key", ApiToken); AddRetry(request); request.AddQueryString("external_source", source.ToString()); @@ -46,9 +51,11 @@ namespace Ombi.Api.TheMovieDb public async Task> SearchByActor(string searchTerm, string langCode) { var request = new Request($"search/person", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("query", searchTerm); - request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("query", searchTerm); + request.AddQueryString("language", langCode); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); var result = await Api.Request>(request); return result; @@ -57,8 +64,8 @@ namespace Ombi.Api.TheMovieDb public async Task GetActorMovieCredits(int actorId, string langCode) { var request = new Request($"person/{actorId}/movie_credits", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); var result = await Api.Request(request); return result; @@ -67,8 +74,8 @@ namespace Ombi.Api.TheMovieDb public async Task> SearchTv(string searchTerm) { var request = new Request($"search/tv", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("query", searchTerm); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("query", searchTerm); AddRetry(request); var result = await Api.Request>(request); @@ -78,7 +85,7 @@ namespace Ombi.Api.TheMovieDb public async Task GetTvExternals(int theMovieDbId) { var request = new Request($"/tv/{theMovieDbId}/external_ids", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.AddQueryString("api_key", ApiToken); AddRetry(request); return await Api.Request(request); @@ -87,9 +94,8 @@ namespace Ombi.Api.TheMovieDb public async Task> SimilarMovies(int movieId, string langCode) { var request = new Request($"movie/{movieId}/similar", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - - request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); AddRetry(request); var result = await Api.Request>(request); @@ -99,65 +105,95 @@ namespace Ombi.Api.TheMovieDb public async Task GetMovieInformationWithExtraInfo(int movieId, string langCode = "en") { var request = new Request($"movie/{movieId}", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("append_to_response", "videos,release_dates"); - request.FullUri = request.FullUri.AddQueryParameter("language", langCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("append_to_response", "videos,release_dates"); + request.AddQueryString("language", langCode); AddRetry(request); var result = await Api.Request(request); return Mapper.Map(result); } - public async Task> SearchMovie(string searchTerm, int? year, string langageCode) + public async Task> SearchMovie(string searchTerm, int? year, string langCode) { var request = new Request($"search/movie", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("query", searchTerm); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("query", searchTerm); + request.AddQueryString("language", langCode); if (year.HasValue && year.Value > 0) { - request.FullUri = request.FullUri.AddQueryParameter("year", year.Value.ToString()); + request.AddQueryString("year", year.Value.ToString()); } + + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> PopularMovies(string langageCode) + public async Task> PopularMovies(string langCode) { - var request = new Request($"movie/popular", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> TopRated(string langageCode) + public async Task> TopRated(string langCode) { - var request = new Request($"movie/top_rated", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + request.AddQueryString("vote_count.gte", "250"); + request.AddQueryString("sort_by", "vote_average.desc"); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> Upcoming(string langageCode) + public async Task> Upcoming(string langCode) { - var request = new Request($"movie/upcoming", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + request.AddQueryString("with_release_type", "2|3"); + var startDate = DateTime.Today.AddDays(7); + request.AddQueryString("release_date.gte", startDate.ToString("yyyy-MM-dd")); + request.AddQueryString("release_date.lte", startDate.AddDays(17).ToString("yyyy-MM-dd")); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); } - public async Task> NowPlaying(string langageCode) + public async Task> NowPlaying(string langCode) { - var request = new Request($"movie/now_playing", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); - request.FullUri = request.FullUri.AddQueryParameter("language", langageCode); + var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + request.AddQueryString("with_release_type", "2|3"); + var today = DateTime.Today; + request.AddQueryString("release_date.gte", today.AddDays(-42).ToString("yyyy-MM-dd")); + request.AddQueryString("release_date.lte", today.AddDays(6).ToString("yyyy-MM-dd")); + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); @@ -166,7 +202,7 @@ namespace Ombi.Api.TheMovieDb public async Task GetTVInfo(string themoviedbid) { var request = new Request($"/tv/{themoviedbid}", BaseUri, HttpMethod.Get); - request.FullUri = request.FullUri.AddQueryParameter("api_key", ApiToken); + request.AddQueryString("api_key", ApiToken); AddRetry(request); return await Api.Request(request); diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 75aaf7605..26892ca6e 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -245,3 +245,8 @@ export interface IVoteSettings extends ISettings { musicVoteMax: number; tvShowVoteMax: number; } + +export interface ITheMovieDbSettings extends ISettings { + showAdultMovies: boolean; + excludedKeywordIds: string; +} diff --git a/src/Ombi/ClientApp/app/services/settings.service.ts b/src/Ombi/ClientApp/app/services/settings.service.ts index a80cfd772..8c7787b6d 100644 --- a/src/Ombi/ClientApp/app/services/settings.service.ts +++ b/src/Ombi/ClientApp/app/services/settings.service.ts @@ -32,6 +32,7 @@ import { ISlackNotificationSettings, ISonarrSettings, ITelegramNotifcationSettings, + ITheMovieDbSettings, IUpdateSettings, IUserManagementSettings, IVoteSettings, @@ -301,6 +302,14 @@ export class SettingsService extends ServiceHelpers { return this.http.post(`${this.url}/vote`, JSON.stringify(settings), {headers: this.headers}); } + public getTheMovieDbSettings(): Observable { + return this.http.get(`${this.url}/themoviedb`, {headers: this.headers}); + } + + public saveTheMovieDbSettings(settings: ITheMovieDbSettings) { + return this.http.post(`${this.url}/themoviedb`, JSON.stringify(settings), {headers: this.headers}); + } + public getNewsletterSettings(): Observable { return this.http.get(`${this.url}/notifications/newsletter`, {headers: this.headers}); } diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 6fb69dc27..4d672d622 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -36,6 +36,7 @@ import { PushbulletComponent } from "./notifications/pushbullet.component"; import { PushoverComponent } from "./notifications/pushover.component"; import { SlackComponent } from "./notifications/slack.component"; import { TelegramComponent } from "./notifications/telegram.component"; +import { TheMovieDbComponent } from "./themoviedb/themoviedb.component"; import { OmbiComponent } from "./ombi/ombi.component"; import { PlexComponent } from "./plex/plex.component"; import { RadarrComponent } from "./radarr/radarr.component"; @@ -80,6 +81,7 @@ const routes: Routes = [ { path: "Newsletter", component: NewsletterComponent, canActivate: [AuthGuard] }, { path: "Lidarr", component: LidarrComponent, canActivate: [AuthGuard] }, { path: "Vote", component: VoteComponent, canActivate: [AuthGuard] }, + { path: "TheMovieDb", component: TheMovieDbComponent, canActivate: [AuthGuard] }, { path: "FailedRequests", component: FailedRequestsComponent, canActivate: [AuthGuard] }, ]; @@ -135,6 +137,7 @@ const routes: Routes = [ NewsletterComponent, LidarrComponent, VoteComponent, + TheMovieDbComponent, FailedRequestsComponent, ], exports: [ diff --git a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html index d58c96e2e..686f4c020 100644 --- a/src/Ombi/ClientApp/app/settings/settingsmenu.component.html +++ b/src/Ombi/ClientApp/app/settings/settingsmenu.component.html @@ -13,6 +13,7 @@
  • User Importer
  • Authentication
  • Vote
  • +
  • The Movie Database
  • diff --git a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html new file mode 100644 index 000000000..afce968c2 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html @@ -0,0 +1,29 @@ + + +
    + The Movie Database +
    +
    +
    + + +
    +
    + +
    + +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    \ No newline at end of file diff --git a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts new file mode 100644 index 000000000..e167d3009 --- /dev/null +++ b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from "@angular/core"; + +import { ITheMovieDbSettings } from "../../interfaces"; +import { NotificationService } from "../../services"; +import { SettingsService } from "../../services"; + +@Component({ + templateUrl: "./themoviedb.component.html", +}) +export class TheMovieDbComponent implements OnInit { + + public settings: ITheMovieDbSettings; + public advanced: boolean; + + constructor(private settingsService: SettingsService, private notificationService: NotificationService) { } + + public ngOnInit() { + this.settingsService.getTheMovieDbSettings().subscribe(x => { + this.settings = x; + }); + } + + public save() { + this.settingsService.saveTheMovieDbSettings(this.settings).subscribe(x => { + if (x) { + this.notificationService.success("Successfully saved The Movie Database settings"); + } else { + this.notificationService.success("There was an error when saving The Movie Database settings"); + } + }); + } +} diff --git a/src/Ombi/Controllers/SettingsController.cs b/src/Ombi/Controllers/SettingsController.cs index ebc2fbe66..6033ae2ca 100644 --- a/src/Ombi/Controllers/SettingsController.cs +++ b/src/Ombi/Controllers/SettingsController.cs @@ -659,6 +659,25 @@ namespace Ombi.Controllers return vote.Enabled; } + /// + /// Save The Movie DB settings. + /// + /// The settings. + [HttpPost("themoviedb")] + public async Task TheMovieDbSettings([FromBody]TheMovieDbSettings settings) + { + return await Save(settings); + } + + /// + /// Get The Movie DB settings. + /// + [HttpGet("themoviedb")] + public async Task TheMovieDbSettings() + { + return await Get(); + } + /// /// Saves the email notification settings. /// From 9154dbbe9b16eddc8422db4c81a231ecc00003c0 Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Sat, 19 Oct 2019 01:28:13 -0500 Subject: [PATCH 13/19] Fix TS import order --- src/Ombi/ClientApp/app/settings/settings.module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 4d672d622..00328c778 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -36,12 +36,12 @@ import { PushbulletComponent } from "./notifications/pushbullet.component"; import { PushoverComponent } from "./notifications/pushover.component"; import { SlackComponent } from "./notifications/slack.component"; import { TelegramComponent } from "./notifications/telegram.component"; -import { TheMovieDbComponent } from "./themoviedb/themoviedb.component"; import { OmbiComponent } from "./ombi/ombi.component"; import { PlexComponent } from "./plex/plex.component"; import { RadarrComponent } from "./radarr/radarr.component"; import { SickRageComponent } from "./sickrage/sickrage.component"; import { SonarrComponent } from "./sonarr/sonarr.component"; +import { TheMovieDbComponent } from "./themoviedb/themoviedb.component"; import { UpdateComponent } from "./update/update.component"; import { UserManagementComponent } from "./usermanagement/usermanagement.component"; import { VoteComponent } from "./vote/vote.component"; From 69c8736a5273bf3abd26be91210d6ce91fea1883 Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Sat, 19 Oct 2019 19:45:44 -0500 Subject: [PATCH 14/19] Fix search bar overlap on mobile --- .../app/search/moviesearch.component.html | 47 +++++++++------- .../app/search/search.component.scss | 2 +- .../app/search/tvsearch.component.html | 53 ++++++++++++------- src/Ombi/ClientApp/styles/base.scss | 21 ++++++++ 4 files changed, 84 insertions(+), 39 deletions(-) diff --git a/src/Ombi/ClientApp/app/search/moviesearch.component.html b/src/Ombi/ClientApp/app/search/moviesearch.component.html index ed669e0f5..30507d004 100644 --- a/src/Ombi/ClientApp/app/search/moviesearch.component.html +++ b/src/Ombi/ClientApp/app/search/moviesearch.component.html @@ -1,30 +1,41 @@ 
    + +
    + + + +
    +
    +
    - +
    -
    - - - +
    +
    -
    + +
    + +
    +
    diff --git a/src/Ombi/ClientApp/app/search/search.component.scss b/src/Ombi/ClientApp/app/search/search.component.scss index b8339bd82..52ff70f0b 100644 --- a/src/Ombi/ClientApp/app/search/search.component.scss +++ b/src/Ombi/ClientApp/app/search/search.component.scss @@ -3,7 +3,7 @@ padding-top: 5% } .form-control-search { - width: 77%; + padding-right: 165px; } } diff --git a/src/Ombi/ClientApp/app/search/tvsearch.component.html b/src/Ombi/ClientApp/app/search/tvsearch.component.html index 5975abb0d..86ee7c24c 100644 --- a/src/Ombi/ClientApp/app/search/tvsearch.component.html +++ b/src/Ombi/ClientApp/app/search/tvsearch.component.html @@ -1,32 +1,44 @@ 
    diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index 9c7756d8f..54d62c3cf 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -389,6 +389,27 @@ $border-radius: 10px; padding-right: 105px; } +.search-button-container { + margin-top: 10px; + text-align: center; +} + +@media (max-width: 450px) { + .form-control-search { + padding-right: 0 !important; + } + + .search-button-container-inline { + display: none; + } +} + +@media (min-width: 450px) { + .search-button-container { + display: none; + } +} + .input-group-addon .btn-group { position: absolute; right: 45px; From 22d47512b692a4cac9d54f752ec445ee7bacd3cd Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Tue, 22 Oct 2019 12:12:20 -0500 Subject: [PATCH 15/19] Add comments to clarify filter decisions --- src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 32 ++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index 7c24d4c60..b5f0a1596 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -133,11 +133,15 @@ namespace Ombi.Api.TheMovieDb return Mapper.Map>(result.results); } + /// + /// Maintains filter parity with /movie/popular. + /// public async Task> PopularMovies(string langCode) { var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); request.AddQueryString("language", langCode); + request.AddQueryString("sort_by", "popularity.desc"); var settings = await Settings; request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); @@ -147,13 +151,21 @@ namespace Ombi.Api.TheMovieDb return Mapper.Map>(result.results); } + /// + /// Maintains filter parity with /movie/top_rated. + /// public async Task> TopRated(string langCode) { var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); request.AddQueryString("language", langCode); - request.AddQueryString("vote_count.gte", "250"); request.AddQueryString("sort_by", "vote_average.desc"); + + // `vote_count` consideration isn't explicitly documented, but using only the `sort_by` filter + // does not provide the same results as `/movie/top_rated`. This appears to be adequate enough + // to filter out extremely high-rated movies due to very little votes + request.AddQueryString("vote_count.gte", "250"); + var settings = await Settings; request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); @@ -163,15 +175,24 @@ namespace Ombi.Api.TheMovieDb return Mapper.Map>(result.results); } + /// + /// Maintains filter parity with /movie/upcoming. + /// public async Task> Upcoming(string langCode) { var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); request.AddQueryString("language", langCode); + + // Release types "2 or 3" explicitly stated as used in docs request.AddQueryString("with_release_type", "2|3"); + + // The date range being used in `/movie/upcoming` isn't documented, but we infer it is + // an offset from today based on the minimum and maximum date they provide in the output var startDate = DateTime.Today.AddDays(7); request.AddQueryString("release_date.gte", startDate.ToString("yyyy-MM-dd")); request.AddQueryString("release_date.lte", startDate.AddDays(17).ToString("yyyy-MM-dd")); + var settings = await Settings; request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); @@ -181,15 +202,24 @@ namespace Ombi.Api.TheMovieDb return Mapper.Map>(result.results); } + /// + /// Maintains filter parity with /movie/now_playing. + /// public async Task> NowPlaying(string langCode) { var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); request.AddQueryString("language", langCode); + + // Release types "2 or 3" explicitly stated as used in docs request.AddQueryString("with_release_type", "2|3"); + + // The date range being used in `/movie/now_playing` isn't documented, but we infer it is + // an offset from today based on the minimum and maximum date they provide in the output var today = DateTime.Today; request.AddQueryString("release_date.gte", today.AddDays(-42).ToString("yyyy-MM-dd")); request.AddQueryString("release_date.lte", today.AddDays(6).ToString("yyyy-MM-dd")); + var settings = await Settings; request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); From 23cceec6f90b04d5572e3e0113cd5029ebb80e46 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Wed, 23 Oct 2019 08:50:46 +0100 Subject: [PATCH 16/19] Fixed potential null ref !wip --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index f6d61b30d..585ed42bb 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -715,7 +715,7 @@ namespace Ombi.Schedule.Jobs.Ombi { SeasonNumber = key, Episodes = g.ToList(), - EpisodeAirDate = tvInfo.seasons.Where(x => x.season_number == key).Select(x => x.air_date) + EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date) ?? new List() } ); @@ -840,7 +840,7 @@ namespace Ombi.Schedule.Jobs.Ombi { SeasonNumber = key, Episodes = g.ToList(), - EpisodeAirDate = tvInfo.seasons.Where(x => x.season_number == key).Select(x => x.air_date) + EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date) ?? new List() } ); From 721ef47bb2a2d6798824fbeba59e58955c9fde3c Mon Sep 17 00:00:00 2001 From: Taylor Buchanan Date: Fri, 25 Oct 2019 01:56:56 -0500 Subject: [PATCH 17/19] Use tags and autocomplete for excluded keywords --- .../Models/External/TheMovieDbSettings.cs | 6 ++- src/Ombi.TheMovieDbApi/IMovieDbApi.cs | 2 + src/Ombi.TheMovieDbApi/Models/Keyword.cs | 13 +++++ src/Ombi.TheMovieDbApi/TheMovieDbApi.cs | 53 +++++++++++++------ src/Ombi/ClientApp/app/interfaces/IMovieDb.ts | 4 ++ .../ClientApp/app/interfaces/ISettings.ts | 2 +- src/Ombi/ClientApp/app/interfaces/index.ts | 1 + .../app/services/applications/index.ts | 1 + .../applications/themoviedb.service.ts | 25 +++++++++ .../ClientApp/app/settings/settings.module.ts | 5 +- .../themoviedb/themoviedb.component.html | 31 +++++++++-- .../themoviedb/themoviedb.component.ts | 47 ++++++++++++++-- src/Ombi/ClientApp/styles/base.scss | 8 +++ .../External/TheMovieDbController.cs | 38 +++++++++++++ src/Ombi/package.json | 1 + src/Ombi/yarn.lock | 15 ++++++ 16 files changed, 223 insertions(+), 29 deletions(-) create mode 100644 src/Ombi.TheMovieDbApi/Models/Keyword.cs create mode 100644 src/Ombi/ClientApp/app/interfaces/IMovieDb.ts create mode 100644 src/Ombi/ClientApp/app/services/applications/themoviedb.service.ts create mode 100644 src/Ombi/Controllers/External/TheMovieDbController.cs diff --git a/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs index 562d9fc88..fe0c238d8 100644 --- a/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs +++ b/src/Ombi.Settings/Settings/Models/External/TheMovieDbSettings.cs @@ -1,9 +1,11 @@ -namespace Ombi.Core.Settings.Models.External +using System.Collections.Generic; + +namespace Ombi.Core.Settings.Models.External { public sealed class TheMovieDbSettings : Ombi.Settings.Settings.Models.Settings { public bool ShowAdultMovies { get; set; } - public string ExcludedKeywordIds { get; set; } + public List ExcludedKeywordIds { get; set; } } } diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs index 43d8b02c1..16ff4ce92 100644 --- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -21,5 +21,7 @@ namespace Ombi.Api.TheMovieDb Task GetTVInfo(string themoviedbid); Task> SearchByActor(string searchTerm, string langCode); Task GetActorMovieCredits(int actorId, string langCode); + Task> SearchKeyword(string searchTerm); + Task GetKeyword(int keywordId); } } \ No newline at end of file diff --git a/src/Ombi.TheMovieDbApi/Models/Keyword.cs b/src/Ombi.TheMovieDbApi/Models/Keyword.cs new file mode 100644 index 000000000..770eebc94 --- /dev/null +++ b/src/Ombi.TheMovieDbApi/Models/Keyword.cs @@ -0,0 +1,13 @@ +using System.Runtime.Serialization; + +namespace Ombi.Api.TheMovieDb.Models +{ + public sealed class Keyword + { + [DataMember(Name = "id")] + public int Id { get; set; } + + [DataMember(Name = "name")] + public string Name { get; set; } + } +} diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index b5f0a1596..a55bdadeb 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; @@ -142,10 +143,7 @@ namespace Ombi.Api.TheMovieDb request.AddQueryString("api_key", ApiToken); request.AddQueryString("language", langCode); request.AddQueryString("sort_by", "popularity.desc"); - var settings = await Settings; - request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); - request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); - + await AddDiscoverMovieSettings(request); AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); @@ -165,11 +163,8 @@ namespace Ombi.Api.TheMovieDb // does not provide the same results as `/movie/top_rated`. This appears to be adequate enough // to filter out extremely high-rated movies due to very little votes request.AddQueryString("vote_count.gte", "250"); - - var settings = await Settings; - request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); - request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); + await AddDiscoverMovieSettings(request); AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); @@ -193,10 +188,7 @@ namespace Ombi.Api.TheMovieDb request.AddQueryString("release_date.gte", startDate.ToString("yyyy-MM-dd")); request.AddQueryString("release_date.lte", startDate.AddDays(17).ToString("yyyy-MM-dd")); - var settings = await Settings; - request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); - request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); - + await AddDiscoverMovieSettings(request); AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); @@ -220,10 +212,7 @@ namespace Ombi.Api.TheMovieDb request.AddQueryString("release_date.gte", today.AddDays(-42).ToString("yyyy-MM-dd")); request.AddQueryString("release_date.lte", today.AddDays(6).ToString("yyyy-MM-dd")); - var settings = await Settings; - request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); - request.AddQueryString("without_keywords", settings.ExcludedKeywordIds); - + await AddDiscoverMovieSettings(request); AddRetry(request); var result = await Api.Request>(request); return Mapper.Map>(result.results); @@ -237,6 +226,38 @@ namespace Ombi.Api.TheMovieDb return await Api.Request(request); } + + public async Task> SearchKeyword(string searchTerm) + { + var request = new Request("search/keyword", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("query", searchTerm); + AddRetry(request); + + var result = await Api.Request>(request); + return result.results ?? new List(); + } + + public async Task GetKeyword(int keywordId) + { + var request = new Request($"keyword/{keywordId}", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + AddRetry(request); + + var keyword = await Api.Request(request); + return keyword == null || keyword.Id == 0 ? null : keyword; + } + + private async Task AddDiscoverMovieSettings(Request request) + { + var settings = await Settings; + request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); + if (settings.ExcludedKeywordIds?.Any() == true) + { + request.AddQueryString("without_keywords", string.Join(",", settings.ExcludedKeywordIds)); + } + } + private static void AddRetry(Request request) { request.Retry = true; diff --git a/src/Ombi/ClientApp/app/interfaces/IMovieDb.ts b/src/Ombi/ClientApp/app/interfaces/IMovieDb.ts new file mode 100644 index 000000000..63443ae4c --- /dev/null +++ b/src/Ombi/ClientApp/app/interfaces/IMovieDb.ts @@ -0,0 +1,4 @@ +export interface IMovieDbKeyword { + id: number; + name: string; +} diff --git a/src/Ombi/ClientApp/app/interfaces/ISettings.ts b/src/Ombi/ClientApp/app/interfaces/ISettings.ts index 26892ca6e..d3dece200 100644 --- a/src/Ombi/ClientApp/app/interfaces/ISettings.ts +++ b/src/Ombi/ClientApp/app/interfaces/ISettings.ts @@ -248,5 +248,5 @@ export interface IVoteSettings extends ISettings { export interface ITheMovieDbSettings extends ISettings { showAdultMovies: boolean; - excludedKeywordIds: string; + excludedKeywordIds: number[]; } diff --git a/src/Ombi/ClientApp/app/interfaces/index.ts b/src/Ombi/ClientApp/app/interfaces/index.ts index e1cf823e8..24eac0093 100644 --- a/src/Ombi/ClientApp/app/interfaces/index.ts +++ b/src/Ombi/ClientApp/app/interfaces/index.ts @@ -3,6 +3,7 @@ export * from "./ICouchPotato"; export * from "./IImages"; export * from "./IMediaServerStatus"; export * from "./INotificationSettings"; +export * from "./IMovieDb"; export * from "./IPlex"; export * from "./IRadarr"; export * from "./IRequestEngineResult"; diff --git a/src/Ombi/ClientApp/app/services/applications/index.ts b/src/Ombi/ClientApp/app/services/applications/index.ts index 295a53415..28edca151 100644 --- a/src/Ombi/ClientApp/app/services/applications/index.ts +++ b/src/Ombi/ClientApp/app/services/applications/index.ts @@ -7,3 +7,4 @@ export * from "./tester.service"; export * from "./plexoauth.service"; export * from "./plextv.service"; export * from "./lidarr.service"; +export * from "./themoviedb.service"; diff --git a/src/Ombi/ClientApp/app/services/applications/themoviedb.service.ts b/src/Ombi/ClientApp/app/services/applications/themoviedb.service.ts new file mode 100644 index 000000000..0b5d83278 --- /dev/null +++ b/src/Ombi/ClientApp/app/services/applications/themoviedb.service.ts @@ -0,0 +1,25 @@ +import { PlatformLocation } from "@angular/common"; +import { HttpClient, HttpErrorResponse, HttpParams } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { empty, Observable, throwError } from "rxjs"; +import { catchError } from "rxjs/operators"; + +import { IMovieDbKeyword } from "../../interfaces"; +import { ServiceHelpers } from "../service.helpers"; + +@Injectable() +export class TheMovieDbService extends ServiceHelpers { + constructor(http: HttpClient, public platformLocation: PlatformLocation) { + super(http, "/api/v1/TheMovieDb", platformLocation); + } + + public getKeywords(searchTerm: string): Observable { + const params = new HttpParams().set("searchTerm", searchTerm); + return this.http.get(`${this.url}/Keywords`, {headers: this.headers, params}); + } + + public getKeyword(keywordId: number): Observable { + return this.http.get(`${this.url}/Keywords/${keywordId}`, { headers: this.headers }) + .pipe(catchError((error: HttpErrorResponse) => error.status === 404 ? empty() : throwError(error))); + } +} diff --git a/src/Ombi/ClientApp/app/settings/settings.module.ts b/src/Ombi/ClientApp/app/settings/settings.module.ts index 00328c778..377756e56 100644 --- a/src/Ombi/ClientApp/app/settings/settings.module.ts +++ b/src/Ombi/ClientApp/app/settings/settings.module.ts @@ -3,13 +3,14 @@ import { NgModule } from "@angular/core"; import { FormsModule, ReactiveFormsModule } from "@angular/forms"; import { RouterModule, Routes } from "@angular/router"; import { NgbAccordionModule, NgbModule } from "@ng-bootstrap/ng-bootstrap"; +import { TagInputModule } from "ngx-chips"; import { ClipboardModule } from "ngx-clipboard"; import { AuthGuard } from "../auth/auth.guard"; import { AuthService } from "../auth/auth.service"; import { CouchPotatoService, EmbyService, IssuesService, JobService, LidarrService, MobileService, NotificationMessageService, PlexService, RadarrService, - RequestRetryService, SonarrService, TesterService, ValidationService, + RequestRetryService, SonarrService, TesterService, TheMovieDbService, ValidationService, } from "../services"; import { PipeModule } from "../pipes/pipe.module"; @@ -99,6 +100,7 @@ const routes: Routes = [ NgbAccordionModule, AutoCompleteModule, CalendarModule, + TagInputModule, ClipboardModule, PipeModule, RadioButtonModule, @@ -159,6 +161,7 @@ const routes: Routes = [ NotificationMessageService, LidarrService, RequestRetryService, + TheMovieDbService, ], }) diff --git a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html index afce968c2..ccadc68ac 100644 --- a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html +++ b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.html @@ -11,13 +11,34 @@
    -
    diff --git a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts index e167d3009..4fc9138a0 100644 --- a/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts +++ b/src/Ombi/ClientApp/app/settings/themoviedb/themoviedb.component.ts @@ -1,8 +1,16 @@ import { Component, OnInit } from "@angular/core"; +import { empty, of } from "rxjs"; import { ITheMovieDbSettings } from "../../interfaces"; import { NotificationService } from "../../services"; import { SettingsService } from "../../services"; +import { TheMovieDbService } from "../../services"; + +interface IKeywordTag { + id: number; + name: string; + initial: boolean; +} @Component({ templateUrl: "./themoviedb.component.html", @@ -10,17 +18,48 @@ import { SettingsService } from "../../services"; export class TheMovieDbComponent implements OnInit { public settings: ITheMovieDbSettings; - public advanced: boolean; + public excludedKeywords: IKeywordTag[]; - constructor(private settingsService: SettingsService, private notificationService: NotificationService) { } + constructor(private settingsService: SettingsService, + private notificationService: NotificationService, + private tmdbService: TheMovieDbService) { } public ngOnInit() { - this.settingsService.getTheMovieDbSettings().subscribe(x => { - this.settings = x; + this.settingsService.getTheMovieDbSettings().subscribe(settings => { + this.settings = settings; + this.excludedKeywords = settings.excludedKeywordIds + ? settings.excludedKeywordIds.map(id => ({ + id, + name: "", + initial: true, + })) + : []; }); } + public autocompleteKeyword = (text: string) => this.tmdbService.getKeywords(text); + + public onAddingKeyword = (tag: string | IKeywordTag) => { + if (typeof tag === "string") { + const id = Number(tag); + return isNaN(id) ? empty() : this.tmdbService.getKeyword(id); + } else { + return of(tag); + } + } + + public onKeywordSelect = (keyword: IKeywordTag) => { + if (keyword.initial) { + this.tmdbService.getKeyword(keyword.id) + .subscribe(k => { + keyword.name = k.name; + keyword.initial = false; + }); + } + } + public save() { + this.settings.excludedKeywordIds = this.excludedKeywords.map(k => k.id); this.settingsService.saveTheMovieDbSettings(this.settings).subscribe(x => { if (x) { this.notificationService.success("Successfully saved The Movie Database settings"); diff --git a/src/Ombi/ClientApp/styles/base.scss b/src/Ombi/ClientApp/styles/base.scss index 9c7756d8f..ce56d0033 100644 --- a/src/Ombi/ClientApp/styles/base.scss +++ b/src/Ombi/ClientApp/styles/base.scss @@ -1010,6 +1010,14 @@ a > h4:hover { width:300px; } +.ng2-tag-input.dark input { + background: transparent; + color: white; +} + +.ng2-tag-input .fa-cloud-download { + margin-right: 5px; +} ::ng-deep ngb-accordion > div.card > div.card-header { padding:0px; diff --git a/src/Ombi/Controllers/External/TheMovieDbController.cs b/src/Ombi/Controllers/External/TheMovieDbController.cs new file mode 100644 index 000000000..714831633 --- /dev/null +++ b/src/Ombi/Controllers/External/TheMovieDbController.cs @@ -0,0 +1,38 @@ +using Microsoft.AspNetCore.Mvc; +using Ombi.Api.TheMovieDb; +using Ombi.Api.TheMovieDb.Models; +using Ombi.Attributes; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Ombi.Controllers.External +{ + [Admin] + [ApiV1] + [Produces("application/json")] + public sealed class TheMovieDbController : Controller + { + public TheMovieDbController(IMovieDbApi tmdbApi) => TmdbApi = tmdbApi; + + private IMovieDbApi TmdbApi { get; } + + /// + /// Searches for keywords matching the specified term. + /// + /// The search term. + [HttpGet("Keywords")] + public async Task> GetKeywords([FromQuery]string searchTerm) => + await TmdbApi.SearchKeyword(searchTerm); + + /// + /// Gets the keyword matching the specified ID. + /// + /// The keyword ID. + [HttpGet("Keywords/{keywordId}")] + public async Task GetKeywords(int keywordId) + { + var keyword = await TmdbApi.GetKeyword(keywordId); + return keyword == null ? NotFound() : (IActionResult)Ok(keyword); + } + } +} diff --git a/src/Ombi/package.json b/src/Ombi/package.json index acd432418..47ddb1fd2 100644 --- a/src/Ombi/package.json +++ b/src/Ombi/package.json @@ -63,6 +63,7 @@ "natives": "1.1.6", "ng2-cookies": "^1.0.12", "ngx-bootstrap": "^3.1.4", + "ngx-chips": "^2.1.0", "ngx-clipboard": "^11.1.1", "ngx-editor": "^4.1.0", "ngx-infinite-scroll": "^6.0.1", diff --git a/src/Ombi/yarn.lock b/src/Ombi/yarn.lock index 3f35f5f50..d68dca944 100644 --- a/src/Ombi/yarn.lock +++ b/src/Ombi/yarn.lock @@ -4183,10 +4183,25 @@ ng2-cookies@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/ng2-cookies/-/ng2-cookies-1.0.12.tgz#3f3e613e0137b0649b705c678074b4bd08149ccc" +ng2-material-dropdown@0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/ng2-material-dropdown/-/ng2-material-dropdown-0.11.0.tgz#27a402ef3cbdcaf6791ef4cfd4b257e31db7546f" + integrity sha512-wptBo09qKecY0QPTProAThrc4A3ajJTcHE9LTpCG5XZZUhXLBzhnGK8OW33TN8A+K/jqcs7OB74ppYJiqs3nhQ== + dependencies: + tslib "^1.9.0" + ngx-bootstrap@^3.1.4: version "3.1.4" resolved "https://registry.yarnpkg.com/ngx-bootstrap/-/ngx-bootstrap-3.1.4.tgz#5105c0227da3b51a1972d04efa1504a79474fd57" +ngx-chips@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ngx-chips/-/ngx-chips-2.1.0.tgz#aa299bcf40dc3e1f6288bf1d29e2fdfe9a132ed3" + integrity sha512-OQV4dTfD3nXm5d2mGKUSgwOtJOaMnZ4F+lwXOtd7DWRSUne0JQWwoZNHdOpuS6saBGhqCPDAwq6KxdR5XSgZUQ== + dependencies: + ng2-material-dropdown "0.11.0" + tslib "^1.9.0" + ngx-clipboard@^11.1.1: version "11.1.9" resolved "https://registry.yarnpkg.com/ngx-clipboard/-/ngx-clipboard-11.1.9.tgz#a391853dc49e436de407260863a2c814d73a9332" From 35199a8b5e61b0b3ae45fbb64b46c1b4e301c960 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Tue, 29 Oct 2019 21:42:53 +0000 Subject: [PATCH 18/19] Fixed #3208 --- src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index a8d77a71b..70ab6878d 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -108,6 +108,8 @@ namespace Ombi.Schedule.Jobs.Plex if ((processedContent?.HasProcessedContent ?? false) && recentlyAddedSearch) { + Logger.LogInformation("Kicking off Plex Availability Checker"); + await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); Logger.LogInformation("Starting Metadata refresh"); // Just check what we send it await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System"); From d13a1865ea45314abb1bd9473d47ae7c5ab30398 Mon Sep 17 00:00:00 2001 From: tidusjar Date: Sat, 2 Nov 2019 21:36:34 +0000 Subject: [PATCH 19/19] Fixed the error in the newsletter --- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 585ed42bb..0443d06c2 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -715,7 +715,7 @@ namespace Ombi.Schedule.Jobs.Ombi { SeasonNumber = key, Episodes = g.ToList(), - EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date) ?? new List() + EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault() } ); @@ -840,7 +840,7 @@ namespace Ombi.Schedule.Jobs.Ombi { SeasonNumber = key, Episodes = g.ToList(), - EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date) ?? new List() + EpisodeAirDate = tvInfo?.seasons?.Where(x => x.season_number == key)?.Select(x => x.air_date).FirstOrDefault() } );