diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 3e49d4bca..c02c65295 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -14,6 +14,14 @@ V 1.XX.XX Stable/Early Access Preview/development +#### Media Sever: + +Plex/Emby + +#### Media Server Version: + + + #### Operating System: (Place text here) diff --git a/Ombi.Api/RadarrApi.cs b/Ombi.Api/RadarrApi.cs index 206023f8e..1840f40a0 100644 --- a/Ombi.Api/RadarrApi.cs +++ b/Ombi.Api/RadarrApi.cs @@ -108,7 +108,6 @@ namespace Ombi.Api request.AddHeader("X-Api-Key", apiKey); request.AddJsonBody(options); - RadarrAddMovie result; try { var policy = RetryHandler.RetryAndWaitPolicy((exception, timespan) => Log.Error(exception, "Exception when calling AddSeries for Sonarr, Retrying {0}", timespan), new TimeSpan[] { diff --git a/Ombi.Api/TheMovieDbApi.cs b/Ombi.Api/TheMovieDbApi.cs index ad3f01251..89e6835b2 100644 --- a/Ombi.Api/TheMovieDbApi.cs +++ b/Ombi.Api/TheMovieDbApi.cs @@ -37,6 +37,8 @@ using TMDbLib.Objects.General; using TMDbLib.Objects.Movies; using TMDbLib.Objects.Search; using Movie = TMDbLib.Objects.Movies.Movie; +using TMDbLib.Objects.People; +using System.Linq; namespace Ombi.Api { @@ -69,6 +71,11 @@ namespace Ombi.Api return movies?.Results ?? new List(); } + private async Task GetMovie(int id) + { + return await Client.GetMovie(id); + } + public TmdbMovieDetails GetMovieInformationWithVideos(int tmdbId) { var request = new RestRequest { Resource = "movie/{movieId}", Method = Method.GET }; @@ -100,5 +107,49 @@ namespace Ombi.Api var movies = await Client.GetMovie(imdbId); return movies ?? new Movie(); } + + public async Task> SearchPerson(string searchTerm) + { + return await SearchPerson(searchTerm, null); + } + + public async Task> SearchPerson(string searchTerm, Func> alreadyAvailable) + { + SearchContainer result = await Client.SearchPerson(searchTerm); + + var people = result?.Results ?? new List(); + var person = (people.Count != 0 ? people[0] : null); + var movies = new List(); + var counter = 0; + try + { + if (person != null) + { + var credits = await Client.GetPersonMovieCredits(person.Id); + + // grab results from both cast and crew, prefer items in cast. we can handle directors like this. + List movieResults = (from MovieRole role in credits.Cast select new Movie() { Id = role.Id, Title = role.Title, ReleaseDate = role.ReleaseDate }).ToList(); + movieResults.AddRange((from MovieJob job in credits.Crew select new Movie() { Id = job.Id, Title = job.Title, ReleaseDate = job.ReleaseDate }).ToList()); + + //only get the first 10 movies and delay a bit between each request so we don't overload the API + foreach (var m in movieResults) + { + if (counter == 10) + break; + if (alreadyAvailable == null || !(await alreadyAvailable(m.Id, m.Title, m.ReleaseDate.Value.Year.ToString()))) + { + movies.Add(await GetMovie(m.Id)); + counter++; + } + await Task.Delay(50); + } + } + } + catch (Exception e) + { + Log.Log(LogLevel.Error, e); + } + return movies; + } } } diff --git a/Ombi.Core/SettingModels/PlexRequestSettings.cs b/Ombi.Core/SettingModels/PlexRequestSettings.cs index 6c77ba727..026c84c24 100644 --- a/Ombi.Core/SettingModels/PlexRequestSettings.cs +++ b/Ombi.Core/SettingModels/PlexRequestSettings.cs @@ -41,6 +41,7 @@ namespace Ombi.Core.SettingModels public int Port { get; set; } public string BaseUrl { get; set; } public bool SearchForMovies { get; set; } + public bool SearchForActors { get; set; } public bool SearchForTvShows { get; set; } public bool SearchForMusic { get; set; } [Obsolete("Use the user management settings")] diff --git a/Ombi.Core/Setup.cs b/Ombi.Core/Setup.cs index 1eb05837b..1d21e33b9 100644 --- a/Ombi.Core/Setup.cs +++ b/Ombi.Core/Setup.cs @@ -77,6 +77,7 @@ namespace Ombi.Core { SearchForMovies = true, SearchForTvShows = true, + SearchForActors = true, BaseUrl = baseUrl ?? string.Empty, CollectAnalyticData = true, }; diff --git a/Ombi.Core/StatusChecker/StatusChecker.cs b/Ombi.Core/StatusChecker/StatusChecker.cs index d83e7189c..11710f21b 100644 --- a/Ombi.Core/StatusChecker/StatusChecker.cs +++ b/Ombi.Core/StatusChecker/StatusChecker.cs @@ -202,6 +202,7 @@ namespace Ombi.Core.StatusChecker public async Task OAuth(string url, ISession session) { + await Task.Yield(); var csrf = StringCipher.Encrypt(Guid.NewGuid().ToString("N"), "CSRF"); session[SessionKeys.CSRF] = csrf; diff --git a/Ombi.Services/Interfaces/IAvailabilityChecker.cs b/Ombi.Services/Interfaces/IAvailabilityChecker.cs index f2915faa0..cf602e531 100644 --- a/Ombi.Services/Interfaces/IAvailabilityChecker.cs +++ b/Ombi.Services/Interfaces/IAvailabilityChecker.cs @@ -37,15 +37,15 @@ namespace Ombi.Services.Interfaces void Start(); void CheckAndUpdateAll(); IEnumerable GetPlexMovies(IEnumerable content); - bool IsMovieAvailable(PlexContent[] plexMovies, string title, string year, string providerId = null); + bool IsMovieAvailable(IEnumerable plexMovies, string title, string year, string providerId = null); IEnumerable GetPlexTvShows(IEnumerable content); - bool IsTvShowAvailable(PlexContent[] plexShows, string title, string year, string providerId = null, int[] seasons = null); + bool IsTvShowAvailable(IEnumerable plexShows, string title, string year, string providerId = null, int[] seasons = null); IEnumerable GetPlexAlbums(IEnumerable content); - bool IsAlbumAvailable(PlexContent[] plexAlbums, string title, string year, string artist); + bool IsAlbumAvailable(IEnumerable plexAlbums, string title, string year, string artist); bool IsEpisodeAvailable(string theTvDbId, int season, int episode); - PlexContent GetAlbum(PlexContent[] plexAlbums, string title, string year, string artist); - PlexContent GetMovie(PlexContent[] plexMovies, string title, string year, string providerId = null); - PlexContent GetTvShow(PlexContent[] plexShows, string title, string year, string providerId = null, int[] seasons = null); + PlexContent GetAlbum(IEnumerable plexAlbums, string title, string year, string artist); + PlexContent GetMovie(IEnumerable plexMovies, string title, string year, string providerId = null); + PlexContent GetTvShow(IEnumerable plexShows, string title, string year, string providerId = null, int[] seasons = null); /// /// Gets the episode's stored in the cache. /// diff --git a/Ombi.Services/Jobs/EmbyAvailabilityChecker.cs b/Ombi.Services/Jobs/EmbyAvailabilityChecker.cs index 166ed987a..da4a79212 100644 --- a/Ombi.Services/Jobs/EmbyAvailabilityChecker.cs +++ b/Ombi.Services/Jobs/EmbyAvailabilityChecker.cs @@ -161,15 +161,15 @@ namespace Ombi.Services.Jobs return content.Where(x => x.Type == EmbyMediaType.Movie); } - public bool IsMovieAvailable(EmbyContent[] embyMovies, string title, string year, string providerId) + public bool IsMovieAvailable(IEnumerable embyMovies, string title, string year, string providerId) { var movie = GetMovie(embyMovies, title, year, providerId); return movie != null; } - public EmbyContent GetMovie(EmbyContent[] embyMovies, string title, string year, string providerId) + public EmbyContent GetMovie(IEnumerable embyMovies, string title, string year, string providerId) { - if (embyMovies.Length == 0) + if (embyMovies.Count() == 0) { return null; } @@ -200,14 +200,14 @@ namespace Ombi.Services.Jobs return content.Where(x => x.Type == EmbyMediaType.Series); } - public bool IsTvShowAvailable(EmbyContent[] embyShows, string title, string year, string providerId, int[] seasons = null) + public bool IsTvShowAvailable(IEnumerable embyShows, string title, string year, string providerId, int[] seasons = null) { var show = GetTvShow(embyShows, title, year, providerId, seasons); return show != null; } - public EmbyContent GetTvShow(EmbyContent[] embyShows, string title, string year, string providerId, + public EmbyContent GetTvShow(IEnumerable embyShows, string title, string year, string providerId, int[] seasons = null) { foreach (var show in embyShows) diff --git a/Ombi.Services/Jobs/Interfaces/IEmbyAvailabilityChecker.cs b/Ombi.Services/Jobs/Interfaces/IEmbyAvailabilityChecker.cs index a954064e7..52e620118 100644 --- a/Ombi.Services/Jobs/Interfaces/IEmbyAvailabilityChecker.cs +++ b/Ombi.Services/Jobs/Interfaces/IEmbyAvailabilityChecker.cs @@ -14,11 +14,11 @@ namespace Ombi.Services.Jobs IEnumerable GetEmbyTvShows(IEnumerable content); Task> GetEpisodes(); Task> GetEpisodes(int theTvDbId); - EmbyContent GetMovie(EmbyContent[] embyMovies, string title, string year, string providerId); - EmbyContent GetTvShow(EmbyContent[] embyShows, string title, string year, string providerId, int[] seasons = null); + EmbyContent GetMovie(IEnumerable embyMovies, string title, string year, string providerId); + EmbyContent GetTvShow(IEnumerable embyShows, string title, string year, string providerId, int[] seasons = null); bool IsEpisodeAvailable(string theTvDbId, int season, int episode); - bool IsMovieAvailable(EmbyContent[] embyMovies, string title, string year, string providerId); - bool IsTvShowAvailable(EmbyContent[] embyShows, string title, string year, string providerId, int[] seasons = null); + bool IsMovieAvailable(IEnumerable embyMovies, string title, string year, string providerId); + bool IsTvShowAvailable(IEnumerable embyShows, string title, string year, string providerId, int[] seasons = null); void Start(); } } \ No newline at end of file diff --git a/Ombi.Services/Jobs/PlexAvailabilityChecker.cs b/Ombi.Services/Jobs/PlexAvailabilityChecker.cs index e9da44eb5..e6da24b14 100644 --- a/Ombi.Services/Jobs/PlexAvailabilityChecker.cs +++ b/Ombi.Services/Jobs/PlexAvailabilityChecker.cs @@ -194,15 +194,15 @@ namespace Ombi.Services.Jobs return content.Where(x => x.Type == Store.Models.Plex.PlexMediaType.Movie); } - public bool IsMovieAvailable(PlexContent[] plexMovies, string title, string year, string providerId = null) + public bool IsMovieAvailable(IEnumerable plexMovies, string title, string year, string providerId = null) { var movie = GetMovie(plexMovies, title, year, providerId); return movie != null; } - public PlexContent GetMovie(PlexContent[] plexMovies, string title, string year, string providerId = null) + public PlexContent GetMovie(IEnumerable plexMovies, string title, string year, string providerId = null) { - if (plexMovies.Length == 0) + if (plexMovies.Count() == 0) { return null; } @@ -236,14 +236,14 @@ namespace Ombi.Services.Jobs return content.Where(x => x.Type == Store.Models.Plex.PlexMediaType.Show); } - public bool IsTvShowAvailable(PlexContent[] plexShows, string title, string year, string providerId = null, int[] seasons = null) + public bool IsTvShowAvailable(IEnumerable plexShows, string title, string year, string providerId = null, int[] seasons = null) { var show = GetTvShow(plexShows, title, year, providerId, seasons); return show != null; } - public PlexContent GetTvShow(PlexContent[] plexShows, string title, string year, string providerId = null, + public PlexContent GetTvShow(IEnumerable plexShows, string title, string year, string providerId = null, int[] seasons = null) { var advanced = !string.IsNullOrEmpty(providerId); @@ -345,14 +345,14 @@ namespace Ombi.Services.Jobs return content.Where(x => x.Type == Store.Models.Plex.PlexMediaType.Artist); } - public bool IsAlbumAvailable(PlexContent[] plexAlbums, string title, string year, string artist) + public bool IsAlbumAvailable(IEnumerable plexAlbums, string title, string year, string artist) { return plexAlbums.Any(x => x.Title.Contains(title) && x.Artist.Equals(artist, StringComparison.CurrentCultureIgnoreCase)); } - public PlexContent GetAlbum(PlexContent[] plexAlbums, string title, string year, string artist) + public PlexContent GetAlbum(IEnumerable plexAlbums, string title, string year, string artist) { return plexAlbums.FirstOrDefault(x => x.Title.Contains(title) && diff --git a/Ombi.UI/Content/requests.js b/Ombi.UI/Content/requests.js index 1d2ad987d..132bb7232 100644 --- a/Ombi.UI/Content/requests.js +++ b/Ombi.UI/Content/requests.js @@ -95,7 +95,10 @@ $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { //if ($tvl.mixItUp('isLoaded')) $tvl.mixItUp('destroy'); //$tvl.mixItUp(mixItUpConfig(activeState)); // init or reinit } - if (target === "#MoviesTab") { + if (target === "#MoviesTab" || target === "#ActorsTab") { + if (target === "#ActorsTab") { + actorLoad(); + } $('#approveMovies,#deleteMovies').show(); if ($tvl.mixItUp('isLoaded')) { activeState = $tvl.mixItUp('getState'); @@ -733,6 +736,37 @@ function initLoad() { } + +function actorLoad() { + var $ml = $('#actorMovieList'); + if ($ml.mixItUp('isLoaded')) { + activeState = $ml.mixItUp('getState'); + $ml.mixItUp('destroy'); + } + $ml.html(""); + + var $newOnly = $('#searchNewOnly').val(); + var url = createBaseUrl(base, '/requests/actor' + (!!$newOnly ? '/new' : '')); + $.ajax(url).success(function (results) { + if (results.length > 0) { + results.forEach(function (result) { + var context = buildRequestContext(result, "movie"); + var html = searchTemplate(context); + $ml.append(html); + }); + + + $('.customTooltip').tooltipster({ + contentCloning: true + }); + } + else { + $ml.html(noResultsHtml.format("movie")); + } + $ml.mixItUp(mixItUpConfig()); + }); +}; + function movieLoad() { var $ml = $('#movieList'); if ($ml.mixItUp('isLoaded')) { diff --git a/Ombi.UI/Content/search.js b/Ombi.UI/Content/search.js index bd7690329..ec215b159 100644 --- a/Ombi.UI/Content/search.js +++ b/Ombi.UI/Content/search.js @@ -63,6 +63,26 @@ $(function () { }); + // Type in actor search + $("#actorSearchContent").on("input", function () { + triggerActorSearch(); + }); + + // if they toggle the checkbox, we want to refresh our search + $("#actorsSearchNew").click(function () { + triggerActorSearch(); + }); + + function triggerActorSearch() + { + if (searchTimer) { + clearTimeout(searchTimer); + } + searchTimer = setTimeout(function () { + moviesFromActor(); + }.bind(this), 800); + } + $('#moviesComingSoon').on('click', function (e) { e.preventDefault(); moviesComingSoon(); @@ -300,7 +320,7 @@ $(function () { function movieSearch() { var query = $("#movieSearchContent").val(); var url = createBaseUrl(base, '/search/movie/'); - query ? getMovies(url + query) : resetMovies(); + query ? getMovies(url + query) : resetMovies("#movieList"); } function moviesComingSoon() { @@ -313,6 +333,13 @@ $(function () { getMovies(url); } + function moviesFromActor() { + var query = $("#actorSearchContent").val(); + var $newOnly = $('#actorsSearchNew')[0].checked; + var url = createBaseUrl(base, '/search/actor/' + (!!$newOnly ? 'new/' : '')); + query ? getMovies(url + query, "#actorMovieList", "#actorSearchButton") : resetMovies("#actorMovieList"); + } + function popularShows() { var url = createBaseUrl(base, '/search/tv/popular'); getTvShows(url, true); @@ -330,30 +357,31 @@ $(function () { getTvShows(url, true); } - function getMovies(url) { - resetMovies(); - - $('#movieSearchButton').attr("class", "fa fa-spinner fa-spin"); + function getMovies(url, target, button) { + target = target || "#movieList"; + button = button || "#movieSearchButton"; + resetMovies(target); + $(button).attr("class", "fa fa-spinner fa-spin"); $.ajax(url).success(function (results) { if (results.length > 0) { results.forEach(function (result) { var context = buildMovieContext(result); var html = searchTemplate(context); - $("#movieList").append(html); + $(target).append(html); checkNetflix(context.title, context.id); }); } else { - $("#movieList").html(noResultsHtml); + $(target).html(noResultsHtml); } - $('#movieSearchButton').attr("class", "fa fa-search"); + $(button).attr("class", "fa fa-search"); }); }; - function resetMovies() { - $("#movieList").html(""); + function resetMovies(target) { + $(target).html(""); } function tvSearch() { diff --git a/Ombi.UI/Modules/Admin/ScheduledJobsRunnerModule.cs b/Ombi.UI/Modules/Admin/ScheduledJobsRunnerModule.cs index 2fbe77eb0..083eb57d9 100644 --- a/Ombi.UI/Modules/Admin/ScheduledJobsRunnerModule.cs +++ b/Ombi.UI/Modules/Admin/ScheduledJobsRunnerModule.cs @@ -94,6 +94,8 @@ namespace Ombi.UI.Modules.Admin private async Task ScheduleRun(string key) { + await Task.Yield(); + if (key.Equals(JobNames.PlexCacher, StringComparison.CurrentCultureIgnoreCase)) { PlexContentCacher.CacheContent(); diff --git a/Ombi.UI/Modules/SearchExtensionModule.cs b/Ombi.UI/Modules/SearchExtensionModule.cs index 4c0ee4a6f..d9b34c290 100644 --- a/Ombi.UI/Modules/SearchExtensionModule.cs +++ b/Ombi.UI/Modules/SearchExtensionModule.cs @@ -47,6 +47,8 @@ namespace Ombi.UI.Modules public async Task Netflix(string title) { + await Task.Yield(); + var result = NetflixApi.CheckNetflix(title); if (!string.IsNullOrEmpty(result.Message)) diff --git a/Ombi.UI/Modules/SearchModule.cs b/Ombi.UI/Modules/SearchModule.cs index 76fc5fb62..6e675b959 100644 --- a/Ombi.UI/Modules/SearchModule.cs +++ b/Ombi.UI/Modules/SearchModule.cs @@ -121,6 +121,8 @@ namespace Ombi.UI.Modules Get["SearchIndex", "/", true] = async (x, ct) => await RequestLoad(); + Get["actor/{searchTerm}", true] = async (x, ct) => await SearchPerson((string)x.searchTerm); + Get["actor/new/{searchTerm}", true] = async (x, ct) => await SearchPerson((string)x.searchTerm, true); Get["movie/{searchTerm}", true] = async (x, ct) => await SearchMovie((string)x.searchTerm); Get["tv/{searchTerm}", true] = async (x, ct) => await SearchTvShow((string)x.searchTerm); Get["music/{searchTerm}", true] = async (x, ct) => await SearchAlbum((string)x.searchTerm); @@ -182,9 +184,18 @@ namespace Ombi.UI.Modules private ISettingsService CustomizationSettings { get; } private static Logger Log = LogManager.GetCurrentClassLogger(); + private long _plexMovieCacheTime = 0; + private IEnumerable _plexMovies = null; + + private long _embyMovieCacheTime = 0; + private IEnumerable _embyMovies = null; + + + private long _dbMovieCacheTime = 0; + private Dictionary _dbMovies = null; + private async Task RequestLoad() { - var settings = await PrService.GetSettingsAsync(); var custom = await CustomizationSettings.GetSettingsAsync(); var emby = await EmbySettings.GetSettingsAsync(); @@ -222,6 +233,53 @@ namespace Ombi.UI.Modules return await ProcessMovies(MovieSearchType.Search, searchTerm); } + private async Task SearchPerson(string searchTerm) + { + var movies = TransformMovieListToMovieResultList(await MovieApi.SearchPerson(searchTerm)); + return await TransformMovieResultsToResponse(movies); + } + + private async Task SearchPerson(string searchTerm, bool filterExisting) + { + var movies = TransformMovieListToMovieResultList(await MovieApi.SearchPerson(searchTerm, AlreadyAvailable)); + return await TransformMovieResultsToResponse(movies); + } + + private async Task AlreadyAvailable(int id, string title, string year) + { + var plexSettings = await PlexService.GetSettingsAsync(); + var embySettings = await EmbySettings.GetSettingsAsync(); + + return IsMovieInCache(id, String.Empty) || + (plexSettings.Enable && PlexChecker.IsMovieAvailable(PlexMovies(), title, year)) || + (embySettings.Enable && EmbyChecker.IsMovieAvailable(EmbyMovies(), title, year, String.Empty)); + } + + private IEnumerable PlexMovies() + { long now = DateTime.Now.Ticks; + if(_plexMovies == null || (now - _plexMovieCacheTime) > 10000) + { + var content = PlexContentRepository.GetAll(); + _plexMovies = PlexChecker.GetPlexMovies(content); + _plexMovieCacheTime = now; + } + + return _plexMovies; + } + + private IEnumerable EmbyMovies() + { + long now = DateTime.Now.Ticks; + if (_embyMovies == null || (now - _embyMovieCacheTime) > 10000) + { + var content = EmbyContentRepository.GetAll(); + _embyMovies = EmbyChecker.GetEmbyMovies(content); + _embyMovieCacheTime = now; + } + + return _embyMovies; + } + private Response GetTvPoster(int theTvDbId) { var result = TvApi.ShowLookupByTheTvDbId(theTvDbId); @@ -233,15 +291,10 @@ namespace Ombi.UI.Modules } return banner; } - private async Task ProcessMovies(MovieSearchType searchType, string searchTerm) - { - List apiMovies; - switch (searchType) - { - case MovieSearchType.Search: - var movies = await MovieApi.SearchMovie(searchTerm).ConfigureAwait(false); - apiMovies = movies.Select(x => + private List TransformSearchMovieListToMovieResultList(List searchMovies) + { + return searchMovies.Select(x => new MovieResult { Adult = x.Adult, @@ -260,6 +313,39 @@ namespace Ombi.UI.Modules VoteCount = x.VoteCount }) .ToList(); + } + + private List TransformMovieListToMovieResultList(List movies) + { + return movies.Select(x => + new MovieResult + { + Adult = x.Adult, + BackdropPath = x.BackdropPath, + GenreIds = x.Genres.Select(y => y.Id).ToList(), + Id = x.Id, + OriginalLanguage = x.OriginalLanguage, + OriginalTitle = x.OriginalTitle, + Overview = x.Overview, + Popularity = x.Popularity, + PosterPath = x.PosterPath, + ReleaseDate = x.ReleaseDate, + Title = x.Title, + Video = x.Video, + VoteAverage = x.VoteAverage, + VoteCount = x.VoteCount + }) + .ToList(); + } + private async Task ProcessMovies(MovieSearchType searchType, string searchTerm) + { + List apiMovies; + + switch (searchType) + { + case MovieSearchType.Search: + var movies = await MovieApi.SearchMovie(searchTerm).ConfigureAwait(false); + apiMovies = TransformSearchMovieListToMovieResultList(movies); break; case MovieSearchType.CurrentlyPlaying: apiMovies = await MovieApi.GetCurrentPlayingMovies(); @@ -272,20 +358,31 @@ namespace Ombi.UI.Modules break; } - var allResults = await RequestService.GetAllAsync(); - allResults = allResults.Where(x => x.Type == RequestType.Movie); + return await TransformMovieResultsToResponse(apiMovies); + } - var distinctResults = allResults.DistinctBy(x => x.ProviderId); - var dbMovies = distinctResults.ToDictionary(x => x.ProviderId); + private async Task> RequestedMovies() + { + long now = DateTime.Now.Ticks; + if (_dbMovies == null || (now - _dbMovieCacheTime) > 10000) + { + var allResults = await RequestService.GetAllAsync(); + allResults = allResults.Where(x => x.Type == RequestType.Movie); + var distinctResults = allResults.DistinctBy(x => x.ProviderId); + _dbMovies = distinctResults.ToDictionary(x => x.ProviderId); + _dbMovieCacheTime = now; + } + return _dbMovies; + } - var cpCached = CpCacher.QueuedIds(); - var watcherCached = WatcherCacher.QueuedIds(); - var radarrCached = RadarrCacher.QueuedIds(); - + private async Task TransformMovieResultsToResponse(List movies) + { + await Task.Yield(); var viewMovies = new List(); var counter = 0; - foreach (var movie in apiMovies) + Dictionary dbMovies = await RequestedMovies(); + foreach (var movie in movies) { var viewMovie = new SearchMovieViewModel { @@ -362,20 +459,11 @@ namespace Ombi.UI.Modules viewMovie.Approved = dbm.Approved; viewMovie.Available = dbm.Available; } - if (cpCached.Contains(movie.Id) && canSee) // compare to the couchpotato db + else if (canSee) { - viewMovie.Approved = true; - viewMovie.Requested = true; - } - if (watcherCached.Contains(viewMovie.ImdbId) && canSee) // compare to the watcher db - { - viewMovie.Approved = true; - viewMovie.Requested = true; - } - if (radarrCached.Contains(movie.Id) && canSee) - { - viewMovie.Approved = true; - viewMovie.Requested = true; + bool exists = IsMovieInCache(movie, viewMovie.ImdbId); + viewMovie.Approved = exists; + viewMovie.Requested = exists; } viewMovies.Add(viewMovie); } @@ -383,6 +471,19 @@ namespace Ombi.UI.Modules return Response.AsJson(viewMovies); } + private bool IsMovieInCache(MovieResult movie, string imdbId) + { int id = movie.Id; + return IsMovieInCache(id, imdbId); + } + + private bool IsMovieInCache(int id, string imdbId) + { var cpCached = CpCacher.QueuedIds(); + var watcherCached = WatcherCacher.QueuedIds(); + var radarrCached = RadarrCacher.QueuedIds(); + + return cpCached.Contains(id) || watcherCached.Contains(imdbId) || radarrCached.Contains(id); + } + private bool CanUserSeeThisRequest(int movieId, bool usersCanViewOnlyOwnRequests, Dictionary moviesInDb) { diff --git a/Ombi.UI/Resources/UI.resx b/Ombi.UI/Resources/UI.resx index a9f63e0e8..24519826e 100644 --- a/Ombi.UI/Resources/UI.resx +++ b/Ombi.UI/Resources/UI.resx @@ -1,76 +1,96 @@  + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + + + + + + + + + + + + + + + + + + - + + @@ -89,13 +109,13 @@ text/microsoft-resx - 1.3 + 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Login @@ -191,6 +211,9 @@ Albums + + Don't include titles that are already requested/available + Want to watch something that is not currently on {0}?! No problem! Just search for it below and request it! @@ -473,4 +496,7 @@ If you are an administrator, please use the other login page + + Actors + \ No newline at end of file diff --git a/Ombi.UI/Resources/UI1.Designer.cs b/Ombi.UI/Resources/UI1.Designer.cs index 4920f2e7f..338720039 100644 --- a/Ombi.UI/Resources/UI1.Designer.cs +++ b/Ombi.UI/Resources/UI1.Designer.cs @@ -717,6 +717,15 @@ namespace Ombi.UI.Resources { } } + /// + /// Looks up a localized string similar to Actors. + /// + public static string Search_Actors { + get { + return ResourceManager.GetString("Search_Actors", resourceCulture); + } + } + /// /// Looks up a localized string similar to Albums. /// @@ -879,6 +888,15 @@ namespace Ombi.UI.Resources { } } + /// + /// Looks up a localized string similar to Don't include titles that are already requested/available. + /// + public static string Search_NewOnly { + get { + return ResourceManager.GetString("Search_NewOnly", resourceCulture); + } + } + /// /// Looks up a localized string similar to Not Requested yet. /// diff --git a/Ombi.UI/Views/Admin/Settings.cshtml b/Ombi.UI/Views/Admin/Settings.cshtml index 54e588c20..9a6010964 100644 --- a/Ombi.UI/Views/Admin/Settings.cshtml +++ b/Ombi.UI/Views/Admin/Settings.cshtml @@ -60,6 +60,7 @@ @Html.Checkbox(Model.SearchForMovies,"SearchForMovies","Search for Movies") + @Html.Checkbox(Model.SearchForActors,"SearchForActors","Search for Movies by Actor")
diff --git a/Ombi.UI/Views/Search/Index.cshtml b/Ombi.UI/Views/Search/Index.cshtml index a177fc721..4e0c6df50 100644 --- a/Ombi.UI/Views/Search/Index.cshtml +++ b/Ombi.UI/Views/Search/Index.cshtml @@ -27,6 +27,13 @@ @UI.Search_Movies + @if (Model.Settings.SearchForActors) + { +
  • + @UI.Search_Actors + +
  • + } } @if (Model.Settings.SearchForTvShows) { @@ -72,8 +79,28 @@
    - } + @if (Model.Settings.SearchForActors) + { + +
    +
    + +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + } + } @if (Model.Settings.SearchForTvShows) { @@ -123,7 +150,7 @@ } - -