diff --git a/.github/labeler.yml b/.github/labeler.yml index 57c72ae71..120b02c56 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,9 +1,5 @@ -# Add 'test' label to any change to *.spec.js files within the source dir -automation: - - tests/**/* +automation: tests/**/* -frontend: -- any: ['src/Ombi/ClientApp/**/*'] +frontend: src/Ombi/ClientApp/**/* -backend: -- any: ['src/**/*.cs'] +backend: src/**/*.cs diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index 4d13fad78..499cd272d 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -2,9 +2,9 @@ name: Automation Tests on: push: - branches: [ feature/ui-automation, develop ] + branches: [ develop, feature/** ] pull_request: - branches: [ feature/ui-automation, develop ] + branches: [ develop ] schedule: - cron: '0 0 * * *' diff --git a/Tools/nuget.exe b/Tools/nuget.exe deleted file mode 100644 index 9f8781de0..000000000 Binary files a/Tools/nuget.exe and /dev/null differ diff --git a/src/Ombi.Api/OmbiHttpClient.cs b/src/Ombi.Api/OmbiHttpClient.cs index 0b00664be..978476cf7 100644 --- a/src/Ombi.Api/OmbiHttpClient.cs +++ b/src/Ombi.Api/OmbiHttpClient.cs @@ -86,12 +86,16 @@ namespace Ombi.Api _handler = await GetHandler(); } _client = new HttpClient(_handler); - _client.DefaultRequestHeaders.Add("User-Agent",$"Ombi/{_runtimeVersion} (https://ombi.io/)"); + _client.DefaultRequestHeaders.Add("User-Agent", $"Ombi/{_runtimeVersion} (https://ombi.io/)"); } } private async Task GetHandler() { + if (_cache == null) + { + return new HttpClientHandler(); + } var settings = await _cache.GetOrAdd(CacheKeys.OmbiSettings, async () => await _settings.GetSettingsAsync(), DateTime.Now.AddHours(1)); if (settings.IgnoreCertificateErrors) { diff --git a/src/Ombi.Core/Engine/BaseMediaEngine.cs b/src/Ombi.Core/Engine/BaseMediaEngine.cs index 66e60767a..d2e18d2b2 100644 --- a/src/Ombi.Core/Engine/BaseMediaEngine.cs +++ b/src/Ombi.Core/Engine/BaseMediaEngine.cs @@ -69,8 +69,8 @@ namespace Ombi.Core.Engine { var allResults = await TvRepository.Get().ToListAsync(); - var distinctResults = allResults.DistinctBy(x => x.TvDbId); - _dbTv = distinctResults.ToDictionary(x => x.TvDbId); + var distinctResults = allResults.DistinctBy(x => x.ExternalProviderId); + _dbTv = distinctResults.ToDictionary(x => x.ExternalProviderId); _cacheTime = now; } return _dbTv; diff --git a/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs index 343fb400a..2c91a458f 100644 --- a/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs +++ b/src/Ombi.Core/Engine/Demo/DemoTvSearchEngine.cs @@ -28,7 +28,7 @@ namespace Ombi.Core.Engine.Demo ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, ISettingsService s, IRepository sub, IOptions lists, IImageService imageService, ISettingsService custom) - : base(identity, service, tvMaze, mapper, trakt, r, um, custom, memCache, s, sub, imageService) + : base(identity, service, tvMaze, mapper, trakt, r, um, custom, memCache, s, sub, imageService, null) { _demoLists = lists.Value; } diff --git a/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs b/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs index 746045ef3..c4bd0aa0e 100644 --- a/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs +++ b/src/Ombi.Core/Engine/Interfaces/IMovieEngineV2.cs @@ -27,5 +27,6 @@ namespace Ombi.Core.Engine.Interfaces Task GetMovieInfoByImdbId(string imdbId, CancellationToken requestAborted); Task> GetStreamInformation(int movieDbId, CancellationToken cancellationToken); + Task> RecentlyRequestedMovies(int currentlyLoaded, int toLoad, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs b/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs index 3a4207d9b..c93403b3e 100644 --- a/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/ITvRequestEngine.cs @@ -13,6 +13,7 @@ namespace Ombi.Core.Engine.Interfaces Task RemoveTvRequest(int requestId); Task GetTvRequest(int requestId); Task RequestTvShow(TvRequestViewModel tv); + Task RequestTvShow(TvRequestViewModelV2 tv); Task DenyChildRequest(int requestId, string reason); Task> GetRequestsLite(int count, int position, OrderFilterModel type); Task> SearchTvRequest(string search); diff --git a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs index b2afb4c6f..ef2373294 100644 --- a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs +++ b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngine.cs @@ -1,5 +1,6 @@ using Ombi.Core.Models.Search; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace Ombi.Core.Engine.Interfaces @@ -7,7 +8,7 @@ namespace Ombi.Core.Engine.Interfaces public interface ITvSearchEngine { Task> Search(string searchTerm); - Task GetShowInformation(int tvdbid); + Task GetShowInformation(string movieDbId, CancellationToken token); Task> Popular(); Task> Popular(int currentlyLoaded, int amountToLoad, bool includeImages = false); Task> Anticipated(); diff --git a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs index d2201825f..c1cf2027a 100644 --- a/src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/Interfaces/ITvSearchEngineV2.cs @@ -7,8 +7,8 @@ namespace Ombi.Core { public interface ITVSearchEngineV2 { - Task GetShowInformation(int tvdbid); - Task GetShowByRequest(int requestId); - Task> GetStreamInformation(int tvDbId, int tvMazeId, CancellationToken cancellationToken); + Task GetShowInformation(string tvdbid, CancellationToken token); + Task GetShowByRequest(int requestId, CancellationToken token); + Task> GetStreamInformation(int movieDbId, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/src/Ombi.Core/Engine/MovieSearchEngine.cs b/src/Ombi.Core/Engine/MovieSearchEngine.cs index cda8676fd..11bcfbfa2 100644 --- a/src/Ombi.Core/Engine/MovieSearchEngine.cs +++ b/src/Ombi.Core/Engine/MovieSearchEngine.cs @@ -189,7 +189,7 @@ namespace Ombi.Core.Engine } protected async Task> TransformMovieResultsToResponse( - IEnumerable movies) + IEnumerable movies) { var viewMovies = new List(); foreach (var movie in movies) @@ -244,7 +244,7 @@ namespace Ombi.Core.Engine } } - private async Task ProcessSingleMovie(MovieSearchResult movie) + private async Task ProcessSingleMovie(MovieDbSearchResult movie) { var viewMovie = Mapper.Map(movie); return await ProcessSingleMovie(viewMovie); diff --git a/src/Ombi.Core/Engine/TvRequestEngine.cs b/src/Ombi.Core/Engine/TvRequestEngine.cs index b06c99d49..30d6c4e79 100644 --- a/src/Ombi.Core/Engine/TvRequestEngine.cs +++ b/src/Ombi.Core/Engine/TvRequestEngine.cs @@ -148,6 +148,106 @@ namespace Ombi.Core.Engine return await AddRequest(newRequest.NewRequest, tv.RequestOnBehalf); } + public async Task RequestTvShow(TvRequestViewModelV2 tv) + { + var user = await GetUser(); + var canRequestOnBehalf = false; + + if (tv.RequestOnBehalf.HasValue()) + { + canRequestOnBehalf = await UserManager.IsInRoleAsync(user, OmbiRoles.PowerUser) || await UserManager.IsInRoleAsync(user, OmbiRoles.Admin); + + if (!canRequestOnBehalf) + { + return new RequestEngineResult + { + Result = false, + Message = "You do not have the correct permissions to request on behalf of users!", + ErrorMessage = $"You do not have the correct permissions to request on behalf of users!" + }; + } + } + + var tvBuilder = new TvShowRequestBuilderV2(MovieDbApi); + (await tvBuilder + .GetShowInfo(tv.TheMovieDbId)) + .CreateTvList(tv) + .CreateChild(tv, canRequestOnBehalf ? tv.RequestOnBehalf : user.Id); + + await tvBuilder.BuildEpisodes(tv); + + var ruleResults = await RunRequestRules(tvBuilder.ChildRequest); + var results = ruleResults as RuleResult[] ?? ruleResults.ToArray(); + if (results.Any(x => !x.Success)) + { + return new RequestEngineResult + { + ErrorMessage = results.FirstOrDefault(x => !string.IsNullOrEmpty(x.Message)).Message + }; + } + + // Check if we have auto approved the request, if we have then mark the episodes as approved + if (tvBuilder.ChildRequest.Approved) + { + foreach (var seasons in tvBuilder.ChildRequest.SeasonRequests) + { + foreach (var ep in seasons.Episodes) + { + ep.Approved = true; + ep.Requested = true; + } + } + } + + var existingRequest = await TvRepository.Get().FirstOrDefaultAsync(x => x.ExternalProviderId == tv.TheMovieDbId); + if (existingRequest != null) + { + // Remove requests we already have, we just want new ones + foreach (var existingSeason in existingRequest.ChildRequests) + foreach (var existing in existingSeason.SeasonRequests) + { + var newChild = tvBuilder.ChildRequest.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == existing.SeasonNumber); + if (newChild != null) + { + // We have some requests in this season... + // Let's find the episodes. + foreach (var existingEp in existing.Episodes) + { + var duplicateEpisode = newChild.Episodes.FirstOrDefault(x => x.EpisodeNumber == existingEp.EpisodeNumber); + if (duplicateEpisode != null) + { + // Remove it. + newChild.Episodes.Remove(duplicateEpisode); + } + } + if (!newChild.Episodes.Any()) + { + // We may have removed all episodes + tvBuilder.ChildRequest.SeasonRequests.Remove(newChild); + } + } + } + + // Remove the ID since this is a new child + // This was a TVDBID for the request rules to run + tvBuilder.ChildRequest.Id = 0; + if (!tvBuilder.ChildRequest.SeasonRequests.Any()) + { + // Looks like we have removed them all! They were all duplicates... + return new RequestEngineResult + { + Result = false, + ErrorMessage = "This has already been requested" + }; + } + return await AddExistingRequest(tvBuilder.ChildRequest, existingRequest, tv.RequestOnBehalf); + } + + // This is a new request + var newRequest = tvBuilder.CreateNewRequest(tv); + return await AddRequest(newRequest.NewRequest, tv.RequestOnBehalf); + } + public async Task> GetRequests(int count, int position, OrderFilterModel type) { var shouldHide = await HideFromOtherUsers(); diff --git a/src/Ombi.Core/Engine/TvSearchEngine.cs b/src/Ombi.Core/Engine/TvSearchEngine.cs index 433cacee0..156c76d6e 100644 --- a/src/Ombi.Core/Engine/TvSearchEngine.cs +++ b/src/Ombi.Core/Engine/TvSearchEngine.cs @@ -6,7 +6,6 @@ using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Settings; -using Ombi.Core.Settings.Models.External; using Ombi.Store.Repository; using System; @@ -16,12 +15,13 @@ using System.Security.Principal; using System.Threading.Tasks; using Ombi.Core.Rule.Interfaces; using Ombi.Store.Repository.Requests; -using Microsoft.Extensions.Caching.Memory; using Ombi.Core.Authentication; using Ombi.Helpers; using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; -using TraktSharp.Entities; +using Ombi.Api.TheMovieDb; +using Ombi.Api.TheMovieDb.Models; +using System.Threading; namespace Ombi.Core.Engine { @@ -29,13 +29,16 @@ namespace Ombi.Core.Engine { private readonly ISettingsService _customizationSettings; private readonly IImageService _imageService; + private readonly IMovieDbApi _theMovieDbApi; public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ISettingsService customizationSettings, - ICacheService memCache, ISettingsService s, IRepository sub, IImageService imageService) + ICacheService memCache, ISettingsService s, IRepository sub, IImageService imageService, + IMovieDbApi theMovieDbApi) : base(identity, service, r, um, memCache, s, sub) { _imageService = imageService; + _theMovieDbApi = theMovieDbApi; TvMazeApi = tvMaze; Mapper = mapper; TraktApi = trakt; @@ -48,18 +51,18 @@ namespace Ombi.Core.Engine public async Task> Search(string searchTerm) { - var searchResult = await TvMazeApi.Search(searchTerm); + var searchResult = await _theMovieDbApi.SearchTv(searchTerm); if (searchResult != null) { var retVal = new List(); - foreach (var tvMazeSearch in searchResult) + foreach (var result in searchResult) { - if (tvMazeSearch.show.externals == null || !(tvMazeSearch.show.externals?.thetvdb.HasValue ?? false)) - { - continue; - } - var mappedResult = await ProcessResult(tvMazeSearch, false); + //if (tvMazeSearch.show.externals == null || !(tvMazeSearch.show.externals?.thetvdb.HasValue ?? false)) + //{ + // continue; + //} + var mappedResult = await ProcessResult(result, false); if (mappedResult == null) { continue; @@ -71,58 +74,64 @@ namespace Ombi.Core.Engine return null; } - public async Task GetShowInformation(int tvdbid) + public async Task GetShowInformation(string theMovieDbId, CancellationToken token) { - var show = await Cache.GetOrAdd(nameof(GetShowInformation) + tvdbid, - async () => await TvMazeApi.ShowLookupByTheTvDbId(tvdbid), DateTime.Now.AddHours(12)); + var show = await Cache.GetOrAdd(nameof(GetShowInformation) + theMovieDbId, + async () => await _theMovieDbApi.GetTVInfo(theMovieDbId), DateTime.Now.AddHours(12)); if (show == null) { // We don't have enough information return null; } - var episodes = await Cache.GetOrAdd("TvMazeEpisodeLookup" + show.id, - async () => await TvMazeApi.EpisodeLookup(show.id), DateTime.Now.AddHours(12)); - if (episodes == null || !episodes.Any()) - { - // We don't have enough information - return null; - } + //var episodes = await Cache.GetOrAdd("TvMazeEpisodeLookup" + show.id, + // async () => await TvMazeApi.EpisodeLookup(show.id), DateTime.Now.AddHours(12)); + //if (episodes == null || !episodes.Any()) + //{ + // // We don't have enough information + // return null; + //} var mapped = Mapper.Map(show); - foreach (var e in episodes) + foreach(var tvSeason in show.seasons) { - var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season); - if (season == null) - { - var newSeason = new SeasonRequests - { - SeasonNumber = e.season, - Episodes = new List() - }; - newSeason.Episodes.Add(new EpisodeRequests - { - Url = e.url.ToHttpsUrl(), - Title = e.name, - AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue, - EpisodeNumber = e.number, + var seasonEpisodes = (await _theMovieDbApi.GetSeasonEpisodes(show.id, tvSeason.season_number, token)); - }); - mapped.SeasonRequests.Add(newSeason); - } - else + foreach (var episode in seasonEpisodes.episodes) { - // We already have the season, so just add the episode - season.Episodes.Add(new EpisodeRequests + var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == episode.season_number); + if (season == null) { - Url = e.url.ToHttpsUrl(), - Title = e.name, - AirDate = e.airstamp.HasValue() ? DateTime.Parse(e.airstamp) : DateTime.MinValue, - EpisodeNumber = e.number, - }); + var newSeason = new SeasonRequests + { + SeasonNumber = episode.season_number, + Episodes = new List() + }; + newSeason.Episodes.Add(new EpisodeRequests + { + //Url = episode...ToHttpsUrl(), + Title = episode.name, + AirDate = episode.air_date.HasValue() ? DateTime.Parse(episode.air_date) : DateTime.MinValue, + EpisodeNumber = episode.episode_number, + + }); + mapped.SeasonRequests.Add(newSeason); + } + else + { + // We already have the season, so just add the episode + season.Episodes.Add(new EpisodeRequests + { + //Url = e.url.ToHttpsUrl(), + Title = episode.name, + AirDate = episode.air_date.HasValue() ? DateTime.Parse(episode.air_date) : DateTime.MinValue, + EpisodeNumber = episode.episode_number, + }); + } } } + return await ProcessResult(mapped, false); } @@ -135,12 +144,14 @@ namespace Ombi.Core.Engine public async Task> Popular(int currentlyLoaded, int amountToLoad, bool includeImages = false) { + var langCode = await DefaultLanguageCode(null); + var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); - var results = new List(); + var results = new List(); foreach (var pagesToLoad in pages) { - var apiResult = await Cache.GetOrAdd(nameof(Popular) + pagesToLoad.Page, - async () => await TraktApi.GetPopularShows(pagesToLoad.Page, ResultLimit), DateTime.Now.AddHours(12)); + var apiResult = await Cache.GetOrAdd(nameof(Popular) + langCode + pagesToLoad.Page, + async () => await _theMovieDbApi.PopularTv(langCode, pagesToLoad.Page), DateTime.Now.AddHours(12)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); } @@ -158,12 +169,14 @@ namespace Ombi.Core.Engine public async Task> Anticipated(int currentlyLoaded, int amountToLoad) { + var langCode = await DefaultLanguageCode(null); + var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); - var results = new List(); + var results = new List(); foreach (var pagesToLoad in pages) { - var apiResult = await Cache.GetOrAdd(nameof(Anticipated) + pagesToLoad.Page, - async () => await TraktApi.GetAnticipatedShows(pagesToLoad.Page, ResultLimit), DateTime.Now.AddHours(12)); + var apiResult = await Cache.GetOrAdd(nameof(Anticipated) + langCode + pagesToLoad.Page, + async () => await _theMovieDbApi.UpcomingTv(langCode, pagesToLoad.Page), DateTime.Now.AddHours(12)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); } var processed = ProcessResults(results); @@ -180,12 +193,14 @@ namespace Ombi.Core.Engine public async Task> Trending(int currentlyLoaded, int amountToLoad) { + var langCode = await DefaultLanguageCode(null); + var pages = PaginationHelper.GetNextPages(currentlyLoaded, amountToLoad, ResultLimit); - var results = new List(); + var results = new List(); foreach (var pagesToLoad in pages) { - var apiResult = await Cache.GetOrAdd(nameof(Trending) + pagesToLoad.Page, - async () => await TraktApi.GetTrendingShows(pagesToLoad.Page, ResultLimit), DateTime.Now.AddHours(12)); + var apiResult = await Cache.GetOrAdd(nameof(Trending) + langCode + pagesToLoad.Page, + async () => await _theMovieDbApi.TopRatedTv(langCode, pagesToLoad.Page), DateTime.Now.AddHours(12)); results.AddRange(apiResult.Skip(pagesToLoad.Skip).Take(pagesToLoad.Take)); } var processed = ProcessResults(results); @@ -220,14 +235,15 @@ namespace Ombi.Core.Engine { return null; } - item.TheTvDbId = item.Id.ToString(); - if (includeImages) - { - if (item.TheTvDbId.HasValue()) - { - item.BackdropPath = await _imageService.GetTvBackground(item.TheTvDbId); - } - } + item.TheMovieDbId = item.Id.ToString(); + //item.TheTvDbId = item.Id.ToString(); + //if (includeImages) + //{ + // if (item.TheTvDbId.HasValue()) + // { + // item.BackdropPath = await _imageService.GetTvBackground(item.TheTvDbId); + // } + //} await RunSearchRules(item); diff --git a/src/Ombi.Core/Engine/V2/CalendarEngine.cs b/src/Ombi.Core/Engine/V2/CalendarEngine.cs index 4a5814e1a..b7ecc8ec6 100644 --- a/src/Ombi.Core/Engine/V2/CalendarEngine.cs +++ b/src/Ombi.Core/Engine/V2/CalendarEngine.cs @@ -47,7 +47,7 @@ namespace Ombi.Core.Engine.V2 new ExtraParams { Overview = e.Season?.ChildRequest?.ParentRequest?.Overview ?? string.Empty, - ProviderId = e.Season?.ChildRequest?.ParentRequest?.TvDbId ?? 0, + ProviderId = e.Season?.ChildRequest?.ParentRequest?.ExternalProviderId ?? 0, Type = RequestType.TvShow, ReleaseDate = e.AirDate, RequestStatus = e.RequestStatus diff --git a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs index dc009371a..3714e58a8 100644 --- a/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/MovieSearchEngineV2.cs @@ -8,11 +8,13 @@ using Ombi.Core.Engine.Interfaces; using Ombi.Core.Models.Requests; using Ombi.Core.Models.Search; using Ombi.Core.Models.Search.V2; +using Ombi.Core.Models.UI; using Ombi.Core.Rule.Interfaces; using Ombi.Core.Settings; using Ombi.Helpers; using Ombi.Settings.Settings.Models; using Ombi.Store.Entities; +using Ombi.Store.Entities.Requests; using Ombi.Store.Repository; using System; using System.Collections.Generic; @@ -27,20 +29,21 @@ namespace Ombi.Core.Engine.V2 { public MovieSearchEngineV2(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, ILogger logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService s, IRepository sub, - ISettingsService customizationSettings) + ISettingsService customizationSettings, IMovieRequestEngine movieRequestEngine) : base(identity, service, r, um, mem, s, sub) { MovieApi = movApi; Mapper = mapper; Logger = logger; _customizationSettings = customizationSettings; + _movieRequestEngine = movieRequestEngine; } private IMovieDbApi MovieApi { get; } private IMapper Mapper { get; } private ILogger Logger { get; } private readonly ISettingsService _customizationSettings; - + private readonly IMovieRequestEngine _movieRequestEngine; public async Task GetFullMovieInformation(int theMovieDbId, CancellationToken cancellationToken, string langCode = null) { @@ -127,7 +130,7 @@ namespace Ombi.Core.Engine.V2 var pages = PaginationHelper.GetNextPages(currentlyLoaded, toLoad, _theMovieDbMaxPageItems); - var results = new List(); + var results = new List(); foreach (var pagesToLoad in pages) { var apiResult = await Cache.GetOrAdd(nameof(PopularMovies) + pagesToLoad.Page + langCode, @@ -161,7 +164,7 @@ namespace Ombi.Core.Engine.V2 var pages = PaginationHelper.GetNextPages(currentPosition, amountToLoad, _theMovieDbMaxPageItems); - var results = new List(); + var results = new List(); foreach (var pagesToLoad in pages) { var apiResult = await Cache.GetOrAdd(nameof(TopRatedMovies) + pagesToLoad.Page + langCode, @@ -177,7 +180,7 @@ namespace Ombi.Core.Engine.V2 var pages = PaginationHelper.GetNextPages(currentPosition, amountToLoad, _theMovieDbMaxPageItems); - var results = new List(); + var results = new List(); foreach (var pagesToLoad in pages) { var apiResult = await Cache.GetOrAdd(nameof(NowPlayingMovies) + pagesToLoad.Page + langCode, @@ -187,6 +190,41 @@ namespace Ombi.Core.Engine.V2 return await TransformMovieResultsToResponse(results); } + /// + /// Gets recently requested movies + /// + /// + public async Task> RecentlyRequestedMovies(int currentlyLoaded, int toLoad, CancellationToken cancellationToken) + { + var langCode = await DefaultLanguageCode(null); + + var results = new List(); + + var requestResult = await Cache.GetOrAdd(nameof(RecentlyRequestedMovies) + "Requests" + toLoad + langCode, + async () => + { + return await _movieRequestEngine.GetRequests(toLoad, currentlyLoaded, new Models.UI.OrderFilterModel + { + OrderType = OrderType.RequestedDateDesc + }); + }, DateTime.Now.AddMinutes(15), cancellationToken); + + var movieDBResults = await Cache.GetOrAdd(nameof(RecentlyRequestedMovies) + toLoad + langCode, + async () => + { + var responses = new List(); + foreach(var movie in requestResult.Collection) + { + responses.Add(await MovieApi.GetMovieInformation(movie.TheMovieDbId)); + } + return responses; + }, DateTime.Now.AddHours(12), cancellationToken); + + results.AddRange(movieDBResults); + + return await TransformMovieResultsToResponse(results); + } + /// /// Gets upcoming movies. @@ -213,7 +251,7 @@ namespace Ombi.Core.Engine.V2 var pages = PaginationHelper.GetNextPages(currentPosition, amountToLoad, _theMovieDbMaxPageItems); - var results = new List(); + var results = new List(); foreach (var pagesToLoad in pages) { var apiResult = await Cache.GetOrAdd(nameof(UpcomingMovies) + pagesToLoad.Page + langCode, @@ -269,8 +307,8 @@ namespace Ombi.Core.Engine.V2 return data; } - protected async Task> TransformMovieResultsToResponse( - IEnumerable movies) + protected async Task> TransformMovieResultsToResponse( + IEnumerable movies) where T: new() { var settings = await _customizationSettings.GetSettingsAsync(); var viewMovies = new List(); @@ -286,7 +324,7 @@ namespace Ombi.Core.Engine.V2 return viewMovies; } - private async Task ProcessSingleMovie(MovieSearchResult movie) + private async Task ProcessSingleMovie(T movie) where T : new() { var viewMovie = Mapper.Map(movie); return await ProcessSingleMovie(viewMovie); diff --git a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs index 60cd6377d..b24f5a42c 100644 --- a/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs +++ b/src/Ombi.Core/Engine/V2/MultiSearchEngine.cs @@ -63,7 +63,8 @@ namespace Ombi.Core.Engine.V2 var result = new MultiSearchResult { MediaType = multiSearch.media_type, - Poster = multiSearch.poster_path + Poster = multiSearch.poster_path, + Overview = multiSearch.overview }; if (multiSearch.media_type.Equals("movie", StringComparison.InvariantCultureIgnoreCase) && filter.Movies) diff --git a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs index 29ea01879..fb71c1eb7 100644 --- a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs @@ -43,89 +43,70 @@ namespace Ombi.Core.Engine.V2 } - public async Task GetShowByRequest(int requestId) + public async Task GetShowByRequest(int requestId, CancellationToken token) { var request = await RequestService.TvRequestService.Get().FirstOrDefaultAsync(x => x.Id == requestId); - return await GetShowInformation(request.TvDbId); + return await GetShowInformation(request.ExternalProviderId.ToString(), token); // TODO } - public async Task GetShowInformation(int tvdbid) + public async Task GetShowInformation(string tvdbid, CancellationToken token) { - var tvdbshow = await Cache.GetOrAdd(nameof(GetShowInformation) + tvdbid, - async () => await _tvMaze.ShowLookupByTheTvDbId(tvdbid), DateTime.Now.AddHours(12)); - if (tvdbshow == null) - { - return null; - } - var show = await Cache.GetOrAdd("GetTvFullInformation" + tvdbshow.id, - async () => await _tvMaze.GetTvFullInformation(tvdbshow.id), DateTime.Now.AddHours(12)); - if (show == null) + var show = await Cache.GetOrAdd(nameof(GetShowInformation) + tvdbid, + async () => await _movieApi.GetTVInfo(tvdbid), DateTime.Now.AddHours(12)); + if (show == null || show.name == null) { // We don't have enough information return null; } - // Setup the task so we can get the data later on if we have a IMDBID - Task traktInfoTask = null; - if (show.externals?.imdb.HasValue() ?? false) - { - traktInfoTask = Cache.GetOrAdd("GetExtendedTvInfoTrakt" + show.externals?.imdb, - () => _traktApi.GetTvExtendedInfo(show.externals?.imdb), DateTime.Now.AddHours(12)); - } - var mapped = _mapper.Map(show); - foreach (var e in show._embedded?.episodes ?? new Api.TvMaze.Models.V2.Episode[0]) - { - var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season); - if (season == null) - { - var newSeason = new SeasonRequests - { - SeasonNumber = e.season, - Episodes = new List() - }; - newSeason.Episodes.Add(new EpisodeRequests - { - Url = e.url.ToHttpsUrl(), - Title = e.name, - AirDate = e.airstamp, - EpisodeNumber = e.number, - }); - mapped.SeasonRequests.Add(newSeason); - } - else + foreach (var tvSeason in show.seasons.Where(x => x.season_number != 0)) // skip the first season + { + var seasonEpisodes = (await _movieApi.GetSeasonEpisodes(show.id, tvSeason.season_number, token)); + + foreach (var episode in seasonEpisodes.episodes) { - // We already have the season, so just add the episode - season.Episodes.Add(new EpisodeRequests + var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == episode.season_number); + if (season == null) { - Url = e.url.ToHttpsUrl(), - Title = e.name, - AirDate = e.airstamp, - EpisodeNumber = e.number, - }); + var newSeason = new SeasonRequests + { + SeasonNumber = episode.season_number, + Overview = tvSeason.overview, + Episodes = new List() + }; + newSeason.Episodes.Add(new EpisodeRequests + { + //Url = episode...ToHttpsUrl(), + Title = episode.name, + AirDate = episode.air_date.HasValue() ? DateTime.Parse(episode.air_date) : DateTime.MinValue, + EpisodeNumber = episode.episode_number, + + }); + mapped.SeasonRequests.Add(newSeason); + } + else + { + // We already have the season, so just add the episode + season.Episodes.Add(new EpisodeRequests + { + //Url = e.url.ToHttpsUrl(), + Title = episode.name, + AirDate = episode.air_date.HasValue() ? DateTime.Parse(episode.air_date) : DateTime.MinValue, + EpisodeNumber = episode.episode_number, + }); + } } } - return await ProcessResult(mapped, traktInfoTask); + + return await ProcessResult(mapped); } - public async Task> GetStreamInformation(int tvDbId, int tvMazeId, CancellationToken cancellationToken) + public async Task> GetStreamInformation(int movieDbId, CancellationToken cancellationToken) { - var tvdbshow = await Cache.GetOrAdd(nameof(GetShowInformation) + tvMazeId, - async () => await _tvMaze.ShowLookupByTheTvDbId(tvMazeId), DateTime.Now.AddHours(12)); - if (tvdbshow == null) - { - return null; - } - - /// this is a best effort guess since TV maze do not provide the TheMovieDbId - var movieDbResults = await _movieApi.SearchTv(tvdbshow.name, tvdbshow.premiered.Substring(0, 4)); - var potential = movieDbResults.FirstOrDefault(); - tvDbId = potential.Id; - // end guess - - var providers = await _movieApi.GetTvWatchProviders(tvDbId, cancellationToken); + var providers = await _movieApi.GetTvWatchProviders(movieDbId, cancellationToken); var results = await GetUserWatchProvider(providers); var data = new List(); @@ -158,9 +139,9 @@ namespace Ombi.Core.Engine.V2 return _mapper.Map(tvMazeSearch); } - private async Task ProcessResult(SearchFullInfoTvShowViewModel item, Task showInfoTask) + private async Task ProcessResult(SearchFullInfoTvShowViewModel item) { - item.TheTvDbId = item.Id.ToString(); + item.TheMovieDbId = item.Id.ToString(); var oldModel = _mapper.Map(item); await RunSearchRules(oldModel); @@ -179,18 +160,9 @@ namespace Ombi.Core.Engine.V2 item.Images.Medium = item.Images.Medium.ToHttpsUrl(); } - if (item.Cast?.Any() ?? false) - { - foreach (var cast in item.Cast) - { - if (!string.IsNullOrEmpty(cast.Character?.Image?.Medium)) - { - cast.Character.Image.Medium = cast.Character?.Image?.Medium.ToHttpsUrl(); - } - } - } - - return await GetExtraInfo(showInfoTask, item); + + return item; + //return await GetExtraInfo(showInfoTask, item); } private async Task GetExtraInfo(Task showInfoTask, SearchFullInfoTvShowViewModel model) diff --git a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs index 8ccbed8fb..39667eaca 100644 --- a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs +++ b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs @@ -35,14 +35,17 @@ namespace Ombi.Core.Helpers public TvRequests NewRequest { get; protected set; } protected TvMazeShow ShowInfo { get; set; } protected List Results { get; set; } + protected TvSearchResult TheMovieDbRecord { get; set; } public async Task GetShowInfo(int id) { ShowInfo = await TvApi.ShowLookupByTheTvDbId(id); Results = await MovieDbApi.SearchTv(ShowInfo.name); - foreach (TvSearchResult result in Results) { + foreach (TvSearchResult result in Results) + { if (result.Name.Equals(ShowInfo.name, StringComparison.InvariantCultureIgnoreCase)) - { + { + TheMovieDbRecord = result; var showIds = await MovieDbApi.GetTvExternals(result.Id); ShowInfo.externals.imdb = showIds.imdb_id; BackdropPath = result.BackdropPath; @@ -59,7 +62,7 @@ namespace Ombi.Core.Helpers return this; } - + public TvShowRequestBuilder CreateChild(TvRequestViewModel model, string userId) { ChildRequest = new ChildRequests @@ -240,6 +243,7 @@ namespace Ombi.Core.Helpers PosterPath = PosterPath, Title = ShowInfo.name, ReleaseDate = FirstAir, + ExternalProviderId = TheMovieDbRecord.Id, Status = ShowInfo.status, ImdbId = ShowInfo.externals?.imdb ?? string.Empty, TvDbId = tv.TvDbId, diff --git a/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs b/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs new file mode 100644 index 000000000..e6724b482 --- /dev/null +++ b/src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs @@ -0,0 +1,247 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Ombi.Api.TheMovieDb; +using Ombi.Api.TheMovieDb.Models; +using Ombi.Core.Models.Requests; +using Ombi.Store.Entities; +using Ombi.Store.Entities.Requests; +using Ombi.Store.Repository.Requests; +using System.Threading; + +namespace Ombi.Core.Helpers +{ + public class TvShowRequestBuilderV2 + { + + public TvShowRequestBuilderV2(IMovieDbApi movApi) + { + MovieDbApi = movApi; + } + + private IMovieDbApi MovieDbApi { get; } + + public ChildRequests ChildRequest { get; set; } + public List TvRequests { get; protected set; } + public string PosterPath { get; protected set; } + public string BackdropPath { get; protected set; } + public DateTime FirstAir { get; protected set; } + public TvRequests NewRequest { get; protected set; } + protected TvInfo TheMovieDbRecord { get; set; } + + public async Task GetShowInfo(int id) + { + TheMovieDbRecord = await MovieDbApi.GetTVInfo(id.ToString()); + BackdropPath = TheMovieDbRecord.Images?.Backdrops?.OrderBy(x => x.VoteCount).ThenBy(x => x.VoteAverage).FirstOrDefault()?.FilePath; ; + + DateTime.TryParse(TheMovieDbRecord.first_air_date, out var dt); + + FirstAir = dt; + + // For some reason the poster path is always http + PosterPath = TheMovieDbRecord.Images?.Posters?.OrderBy(x => x.VoteCount).ThenBy(x => x.VoteAverage).FirstOrDefault()?.FilePath; + + return this; + } + + public TvShowRequestBuilderV2 CreateChild(TvRequestViewModelV2 model, string userId) + { + var animationGenre = TheMovieDbRecord.genres?.Any(s => s.name.Equals("Animation", StringComparison.InvariantCultureIgnoreCase)) ?? false; + var animeKeyword = TheMovieDbRecord.Keywords?.KeywordsValue?.Any(s => s.Name.Equals("Anime", StringComparison.InvariantCultureIgnoreCase)) ?? false; + ChildRequest = new ChildRequests + { + Id = model.TheMovieDbId, // This is set to 0 after the request rules have run, the request rules needs it to identify the request + RequestType = RequestType.TvShow, + RequestedDate = DateTime.UtcNow, + Approved = false, + RequestedUserId = userId, + SeasonRequests = new List(), + Title = TheMovieDbRecord.name, + ReleaseYear = FirstAir, + RequestedByAlias = model.RequestedByAlias, + SeriesType = animationGenre && animeKeyword ? SeriesType.Anime : SeriesType.Standard + }; + + return this; + } + + public TvShowRequestBuilderV2 CreateTvList(TvRequestViewModelV2 tv) + { + TvRequests = new List(); + // Only have the TV requests we actually requested and not everything + foreach (var season in tv.Seasons) + { + if (season.Episodes.Any()) + { + TvRequests.Add(season); + } + } + + return this; + } + + + public async Task BuildEpisodes(TvRequestViewModelV2 tv) + { + var allEpisodes = new List(); + + foreach (var season in TheMovieDbRecord.seasons) + { + var seasonEpisodes = await MovieDbApi.GetSeasonEpisodes(TheMovieDbRecord.id, season.season_number, CancellationToken.None); + allEpisodes.AddRange(seasonEpisodes.episodes); + } + + if (tv.RequestAll) + { + foreach (var ep in allEpisodes) + { + var season = ChildRequest.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == ep.season_number); + if (season == null) + { + ChildRequest.SeasonRequests.Add(new SeasonRequests + { + Episodes = new List{ + new EpisodeRequests + { + EpisodeNumber = ep.episode_number, + AirDate = FormatDate(ep.air_date), + Title = ep.name, + } + }, + SeasonNumber = ep.season_number, + }); + } + else + { + season.Episodes.Add(new EpisodeRequests + { + EpisodeNumber = ep.episode_number, + AirDate = FormatDate(ep.air_date), + Title = ep.name, + }); + } + } + + } + else if (tv.LatestSeason) + { + var latest = allEpisodes.OrderByDescending(x => x.season_number).FirstOrDefault(); + var episodesRequests = new List(); + foreach (var ep in allEpisodes) + { + if (ep.season_number == latest.season_number) + { + episodesRequests.Add(new EpisodeRequests + { + EpisodeNumber = ep.episode_number, + AirDate = FormatDate(ep.air_date), + Title = ep.name, + }); + } + } + ChildRequest.SeasonRequests.Add(new SeasonRequests + { + Episodes = episodesRequests, + SeasonNumber = latest.season_number, + }); + } + else if (tv.FirstSeason) + { + var first = allEpisodes.OrderBy(x => x.season_number).FirstOrDefault(); + var episodesRequests = new List(); + foreach (var ep in allEpisodes) + { + if (ep.season_number == first.season_number) + { + episodesRequests.Add(new EpisodeRequests + { + EpisodeNumber = ep.episode_number, + AirDate = FormatDate(ep.air_date), + Title = ep.name, + }); + } + } + ChildRequest.SeasonRequests.Add(new SeasonRequests + { + Episodes = episodesRequests, + SeasonNumber = first.season_number, + }); + } + else + { + // It's a custom request + var seasonRequests = new List(); + foreach (var ep in allEpisodes) + { + var existingSeasonRequest = seasonRequests.FirstOrDefault(x => x.SeasonNumber == ep.season_number); + if (existingSeasonRequest != null) + { + var requestedSeason = tv.Seasons.FirstOrDefault(x => x.SeasonNumber == ep.season_number); + var requestedEpisode = requestedSeason?.Episodes?.Any(x => x.EpisodeNumber == ep.episode_number) ?? false; + if (requestedSeason != null && requestedEpisode) + { + // We already have this, let's just add the episodes to it + existingSeasonRequest.Episodes.Add(new EpisodeRequests + { + EpisodeNumber = ep.episode_number, + AirDate = FormatDate(ep.air_date), + Title = ep.name, + }); + } + } + else + { + var newRequest = new SeasonRequests { SeasonNumber = ep.season_number }; + var requestedSeason = tv.Seasons.FirstOrDefault(x => x.SeasonNumber == ep.season_number); + var requestedEpisode = requestedSeason?.Episodes?.Any(x => x.EpisodeNumber == ep.episode_number) ?? false; + if (requestedSeason != null && requestedEpisode) + { + newRequest.Episodes.Add(new EpisodeRequests + { + EpisodeNumber = ep.episode_number, + AirDate = FormatDate(ep.air_date), + Title = ep.name, + }); + seasonRequests.Add(newRequest); + } + } + } + + foreach (var s in seasonRequests) + { + ChildRequest.SeasonRequests.Add(s); + } + } + return this; + } + + + public TvShowRequestBuilderV2 CreateNewRequest(TvRequestViewModelV2 tv) + { + int.TryParse(TheMovieDbRecord.ExternalIds?.TvDbId, out var tvdbId); + NewRequest = new TvRequests + { + Overview = TheMovieDbRecord.overview, + PosterPath = PosterPath, + Title = TheMovieDbRecord.name, + ReleaseDate = FirstAir, + ExternalProviderId = TheMovieDbRecord.id, + Status = TheMovieDbRecord.status, + ImdbId = TheMovieDbRecord.ExternalIds?.ImdbId ?? string.Empty, + TvDbId = tvdbId, + ChildRequests = new List(), + TotalSeasons = tv.Seasons.Count(), + Background = BackdropPath + }; + NewRequest.ChildRequests.Add(ChildRequest); + + return this; + } + + private DateTime FormatDate(string date) + { + return string.IsNullOrEmpty(date) ? DateTime.MinValue : DateTime.Parse(date); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Models/Requests/TvRequestViewModel.cs b/src/Ombi.Core/Models/Requests/TvRequestViewModel.cs index 15349462b..95eb77735 100644 --- a/src/Ombi.Core/Models/Requests/TvRequestViewModel.cs +++ b/src/Ombi.Core/Models/Requests/TvRequestViewModel.cs @@ -3,17 +3,9 @@ using Newtonsoft.Json; namespace Ombi.Core.Models.Requests { - public class TvRequestViewModel + public class TvRequestViewModel : TvRequestViewModelBase { - public bool RequestAll { get; set; } - public bool LatestSeason { get; set; } - public bool FirstSeason { get; set; } public int TvDbId { get; set; } - public List Seasons { get; set; } = new List(); - [JsonIgnore] - public string RequestedByAlias { get; set; } - - public string RequestOnBehalf { get; set; } } public class SeasonsViewModel @@ -27,4 +19,16 @@ namespace Ombi.Core.Models.Requests public int EpisodeNumber { get; set; } } + + public class TvRequestViewModelBase + { + public bool RequestAll { get; set; } + public bool LatestSeason { get; set; } + public bool FirstSeason { get; set; } + public List Seasons { get; set; } = new List(); + [JsonIgnore] + public string RequestedByAlias { get; set; } + + public string RequestOnBehalf { get; set; } + } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs b/src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs new file mode 100644 index 000000000..d967993ec --- /dev/null +++ b/src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Ombi.Core.Models.Requests +{ + public class TvRequestViewModelV2 : TvRequestViewModelBase + { + public int TheMovieDbId { get; set; } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Models/Search/V2/MultiSearchResult.cs b/src/Ombi.Core/Models/Search/V2/MultiSearchResult.cs index 8346608b5..64870a97c 100644 --- a/src/Ombi.Core/Models/Search/V2/MultiSearchResult.cs +++ b/src/Ombi.Core/Models/Search/V2/MultiSearchResult.cs @@ -6,5 +6,6 @@ public string MediaType { get; set; } public string Title { get; set; } public string Poster { get; set; } + public string Overview { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Core/Models/Search/V2/SearchFullInfoTvShowViewModel.cs b/src/Ombi.Core/Models/Search/V2/SearchFullInfoTvShowViewModel.cs index 8533bb2d7..0902c1fb1 100644 --- a/src/Ombi.Core/Models/Search/V2/SearchFullInfoTvShowViewModel.cs +++ b/src/Ombi.Core/Models/Search/V2/SearchFullInfoTvShowViewModel.cs @@ -14,7 +14,7 @@ namespace Ombi.Core.Models.Search.V2 public string FirstAired { get; set; } public string NetworkId { get; set; } public string Runtime { get; set; } - public List Genre { get; set; } + public GenreViewModel[] Genres { get; set; } public string Overview { get; set; } public int LastUpdated { get; set; } public string AirsDayOfWeek { get; set; } @@ -24,23 +24,12 @@ namespace Ombi.Core.Models.Search.V2 public NetworkViewModel Network { get; set; } public Images Images { get; set; } public List Cast { get; set; } - public List Crew { get; set; } + public List Crew { get; set; } public string Certification { get; set; } - - /// - /// This is used from the Trakt API - /// - /// - /// The trailer. - /// + public string Tagline { get; set; } + public Keywords Keywords { get; set; } + public ExternalIds ExternalIds { get; set; } public string Trailer { get; set; } - - /// - /// This is used from the Trakt API - /// - /// - /// The trailer. - /// public string Homepage { get; set; } public List SeasonRequests { get; set; } = new List(); @@ -66,7 +55,7 @@ namespace Ombi.Core.Models.Search.V2 { public int Id { get; set; } public string Name { get; set; } - public Country Country { get; set; } + public string Country { get; set; } } public class Country @@ -84,8 +73,10 @@ namespace Ombi.Core.Models.Search.V2 public class CastViewModel { - public PersonViewModel Person { get; set; } - public CharacterViewModel Character { get; set; } + public int Id { get; set; } + public string Person { get; set; } + public string Character { get; set; } + public string Image { get; set; } public bool Self { get; set; } public bool Voice { get; set; } } @@ -95,7 +86,7 @@ namespace Ombi.Core.Models.Search.V2 public int Id { get; set; } public string Url { get; set; } public string Name { get; set; } - public Images Image { get; set; } + public string Image { get; set; } } public class CharacterViewModel @@ -106,9 +97,4 @@ namespace Ombi.Core.Models.Search.V2 public Images Image { get; set; } } - public class CrewViewModel - { - public string Type { get; set; } - public PersonViewModel Person { get; set; } - } } \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs index 9d4ab30ef..927ebf1be 100644 --- a/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/ExistingPlexRequestRule.cs @@ -32,8 +32,8 @@ namespace Ombi.Core.Rule.Rules.Request var tvContent = _plexContent.GetAll().Include(x => x.Episodes).Where(x => x.Type == PlexMediaTypeEntity.Show); // We need to do a check on the TVDBId - var anyTvDbMatches = await tvContent.FirstOrDefaultAsync(x => x.TvDbId.Length > 0 && x.TvDbId == tvRequest.Id.ToString()); // the Id on the child is the tvdbid at this point - if (anyTvDbMatches == null) + var anyMovieDbMatches = await tvContent.FirstOrDefaultAsync(x => x.TheMovieDbId.Length > 0 && x.TheMovieDbId == tvRequest.Id.ToString()); + if (anyMovieDbMatches == null) { // So we do not have a TVDB Id, that really sucks. // Let's try and match on the title and year of the show @@ -50,7 +50,7 @@ namespace Ombi.Core.Rule.Rules.Request return Success(); } // looks like we have a match on the TVDbID - return CheckExistingContent(tvRequest, anyTvDbMatches); + return CheckExistingContent(tvRequest, anyMovieDbMatches); } return Success(); } diff --git a/src/Ombi.Core/Rule/Rules/Request/ExistingTVRequestRule.cs b/src/Ombi.Core/Rule/Rules/Request/ExistingTVRequestRule.cs index 9942ece63..02546d356 100644 --- a/src/Ombi.Core/Rule/Rules/Request/ExistingTVRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/Request/ExistingTVRequestRule.cs @@ -28,7 +28,7 @@ namespace Ombi.Core.Rule.Rules.Request { var tv = (ChildRequests) obj; var tvRequests = Tv.GetChild(); - var currentRequest = await tvRequests.FirstOrDefaultAsync(x => x.ParentRequest.TvDbId == tv.Id); // the Id on the child is the tvdbid at this point + var currentRequest = await tvRequests.FirstOrDefaultAsync(x => x.ParentRequest.ExternalProviderId == tv.Id); // the Id on the child is the TheMovieDb at this point if (currentRequest == null) { return Success(); diff --git a/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs b/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs index ca7ccb6ce..0e4313ac7 100644 --- a/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs +++ b/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Ombi.Core.Models.Search; +using Ombi.Helpers; using Ombi.Store.Context; using Ombi.Store.Entities; using Ombi.Store.Entities.Requests; @@ -22,7 +23,7 @@ namespace Ombi.Core.Rule.Rules if (obj.RequestType == RequestType.TvShow) { var vm = (ChildRequests) obj; - var result = await _ctx.SonarrCache.FirstOrDefaultAsync(x => x.TvDbId == vm.Id); + var result = await _ctx.SonarrCache.FirstOrDefaultAsync(x => x.TvDbId == vm.Id); // TODO lookup the external provider in the sonarr sync to use themoviedb if (result != null) { if (vm.SeasonRequests.Any()) @@ -53,8 +54,13 @@ namespace Ombi.Core.Rule.Rules if (obj.Type == RequestType.TvShow) { var vm = (SearchTvShowViewModel) obj; - // Check if it's in Radarr - var result = await _ctx.SonarrCache.FirstOrDefaultAsync(x => x.TvDbId == vm.Id); + // Check if it's in Sonarr + if (!vm.TheTvDbId.HasValue()) + { + return new RuleResult { Success = true }; + } + var tvdbidint = int.Parse(vm.TheTvDbId); + var result = await _ctx.SonarrCache.FirstOrDefaultAsync(x => x.TvDbId == tvdbidint); if (result != null) { vm.Approved = true; @@ -69,7 +75,7 @@ namespace Ombi.Core.Rule.Rules // Check if we have it var monitoredInSonarr = await sonarrEpisodes.FirstOrDefaultAsync(x => x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == season.SeasonNumber - && x.TvDbId == vm.Id); + && x.TvDbId == tvdbidint); if (monitoredInSonarr != null) { ep.Approved = true; diff --git a/src/Ombi.Core/Senders/TvSender.cs b/src/Ombi.Core/Senders/TvSender.cs index 91c38428a..5d5c48555 100644 --- a/src/Ombi.Core/Senders/TvSender.cs +++ b/src/Ombi.Core/Senders/TvSender.cs @@ -140,7 +140,7 @@ namespace Ombi.Core.Senders private async Task SendToDogNzb(ChildRequests model, DogNzbSettings settings) { - var id = model.ParentRequest.TvDbId; + var id = model.ParentRequest.ExternalProviderId; return await DogNzbApi.AddTvShow(settings.ApiKey, id.ToString()); } diff --git a/src/Ombi.Mapping/Profiles/MovieProfile.cs b/src/Ombi.Mapping/Profiles/MovieProfile.cs index 7027f3aed..161cb1fda 100644 --- a/src/Ombi.Mapping/Profiles/MovieProfile.cs +++ b/src/Ombi.Mapping/Profiles/MovieProfile.cs @@ -4,6 +4,7 @@ using AutoMapper; using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Models.Search; using Ombi.Core.Models.Search.V2; +using Ombi.Store.Entities.Requests; using Ombi.TheMovieDbApi.Models; using Keywords = Ombi.Core.Models.Search.V2.Keywords; using KeywordsValue = Ombi.Api.TheMovieDb.Models.KeywordsValue; @@ -14,7 +15,7 @@ namespace Ombi.Mapping.Profiles { public MovieProfile() { - CreateMap() + CreateMap() .ForMember(dest => dest.Adult, opts => opts.MapFrom(src => src.adult)) .ForMember(dest => dest.BackdropPath, opts => opts.MapFrom(src => src.backdrop_path)) .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id)) @@ -24,7 +25,7 @@ namespace Ombi.Mapping.Profiles .ForMember(dest => dest.Popularity, opts => opts.MapFrom(src => src.popularity)) .ForMember(dest => dest.PosterPath, opts => opts.MapFrom(src => src.poster_path)) .ForMember(dest => dest.ReleaseDate, opts => opts.MapFrom(src => src.release_date)) - .ForMember(dest => dest.Title, opts => opts.MapFrom(src => src.title)) + .ForMember(dest => dest.Title, opts => opts.MapFrom(src => string.IsNullOrEmpty(src.title) ? src.name : src.title)) .ForMember(dest => dest.Video, opts => opts.MapFrom(src => src.video)) .ForMember(dest => dest.VoteAverage, opts => opts.MapFrom(src => src.vote_average)) .ForMember(dest => dest.VoteCount, opts => opts.MapFrom(src => src.vote_count)); @@ -75,7 +76,8 @@ namespace Ombi.Mapping.Profiles CreateMap(); - CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); CreateMap().ReverseMap(); diff --git a/src/Ombi.Mapping/Profiles/TvProfile.cs b/src/Ombi.Mapping/Profiles/TvProfile.cs index 0e1378d95..55f5ccf9e 100644 --- a/src/Ombi.Mapping/Profiles/TvProfile.cs +++ b/src/Ombi.Mapping/Profiles/TvProfile.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using AutoMapper; +using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TvMaze.Models; using Ombi.Core.Models.Search; using Ombi.Helpers; @@ -27,6 +28,15 @@ namespace Ombi.Mapping.Profiles .ForMember(dest => dest.Banner, opts => opts.MapFrom(src => !string.IsNullOrEmpty(src.show.image.medium) ? src.show.image.medium.ToHttpsUrl() : string.Empty)) .ForMember(dest => dest.Status, opts => opts.MapFrom(src => src.show.status)); + CreateMap() + .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.Id)) + .ForMember(dest => dest.TheMovieDbId, opts => opts.MapFrom(src => src.Id.ToString())) + .ForMember(dest => dest.FirstAired, opts => opts.MapFrom(src => src.ReleaseDate)) + .ForMember(dest => dest.Overview, opts => opts.MapFrom(src => src.Overview)) + .ForMember(dest => dest.Rating, opts => opts.MapFrom(src => src.VoteAverage.ToString(CultureInfo.CurrentUICulture))) + .ForMember(dest => dest.Title, opts => opts.MapFrom(src => src.Name)) + .ForMember(dest => dest.Banner, opts => opts.MapFrom(src => !string.IsNullOrEmpty(src.BackdropPath) ? src.BackdropPath.ToHttpsUrl() : src.PosterPath)); + CreateMap() .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.externals.thetvdb)) .ForMember(dest => dest.FirstAired, opts => opts.MapFrom(src => src.premiered)) @@ -56,10 +66,27 @@ namespace Ombi.Mapping.Profiles .ForMember(dest => dest.Runtime, opts => opts.MapFrom(src => src.Runtime.ToString())) .ForMember(dest => dest.Title, opts => opts.MapFrom(src => src.Title)) .ForMember(dest => dest.Status, opts => opts.MapFrom(src => TraktEnumHelper.GetDescription(src.Status))) - .ForMember(dest => dest.Trailer, + .ForMember(dest => dest.Trailer, opts => opts.MapFrom(src => src.Trailer != null ? src.Trailer.ToString().ToHttpsUrl() : string.Empty)) - .ForMember(dest => dest.Homepage, + .ForMember(dest => dest.Homepage, opts => opts.MapFrom(src => src.Homepage != null ? src.Homepage.ToString().ToHttpsUrl() : string.Empty)); + + + CreateMap() + .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.Id)) + .ForMember(dest => dest.FirstAired, opts => opts.MapFrom(src => src.ReleaseDate)) + //.ForMember(dest => dest.ImdbId, opts => opts.MapFrom(src => src.Ids.Imdb)) + //.ForMember(dest => dest.Network, opts => opts.MapFrom(src => src.Network)) + .ForMember(dest => dest.Overview, opts => opts.MapFrom(src => src.Overview)) + .ForMember(dest => dest.Rating, opts => opts.MapFrom(src => src.VoteAverage.ToString())) + .ForMember(dest => dest.BackdropPath, opts => opts.MapFrom(src => src.PosterPath)) + //.ForMember(dest => dest.Runtime, opts => opts.MapFrom(src => src.Runtime.ToString())) + .ForMember(dest => dest.Title, opts => opts.MapFrom(src => src.Title)); + //.ForMember(dest => dest.Status, opts => opts.MapFrom(src => TraktEnumHelper.GetDescription(src.Status))) + //.ForMember(dest => dest.Trailer, + // opts => opts.MapFrom(src => src.Trailer != null ? src.Trailer.ToString().ToHttpsUrl() : string.Empty)) + //.ForMember(dest => dest.Homepage, + // opts => opts.MapFrom(src => src.Homepage != null ? src.Homepage.ToString().ToHttpsUrl() : string.Empty)); } } } \ No newline at end of file diff --git a/src/Ombi.Mapping/Profiles/TvProfileV2.cs b/src/Ombi.Mapping/Profiles/TvProfileV2.cs index 5ee0645fd..d54321d01 100644 --- a/src/Ombi.Mapping/Profiles/TvProfileV2.cs +++ b/src/Ombi.Mapping/Profiles/TvProfileV2.cs @@ -1,5 +1,8 @@ -using System.Globalization; +using System; +using System.Globalization; +using System.Linq; using AutoMapper; +using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TvMaze.Models.V2; using Ombi.Core.Models.Search; using Ombi.Core.Models.Search.V2; @@ -11,72 +14,90 @@ namespace Ombi.Mapping.Profiles { public TvProfileV2() { - CreateMap() - .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.externals.thetvdb)) - .ForMember(dest => dest.FirstAired, opts => opts.MapFrom(src => src.premiered)) - .ForMember(dest => dest.ImdbId, opts => opts.MapFrom(src => src.externals.imdb)) - .ForMember(dest => dest.Network, opts => opts.MapFrom(src => src.network.name)) - .ForMember(dest => dest.NetworkId, opts => opts.MapFrom(src => src.network.id.ToString())) - .ForMember(dest => dest.Overview, opts => opts.MapFrom(src => src.summary.RemoveHtml())) + + CreateMap() + .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id)) + .ForMember(dest => dest.FirstAired, opts => opts.MapFrom(src => src.first_air_date)) + .ForMember(dest => dest.ImdbId, opts => opts.MapFrom(src => src.ExternalIds.ImdbId)) + .ForMember(dest => dest.TheTvDbId, opts => opts.MapFrom(src => src.ExternalIds.TvDbId)) + .ForMember(dest => dest.Network, opts => opts.MapFrom(src => src.networks.FirstOrDefault())) + .ForMember(dest => dest.NetworkId, opts => opts.MapFrom(src => src.networks.FirstOrDefault().id)) + .ForMember(dest => dest.Overview, opts => opts.MapFrom(src => src.overview)) .ForMember(dest => dest.Rating, - opts => opts.MapFrom(src => src.rating.average.ToString(CultureInfo.CurrentUICulture))) - .ForMember(dest => dest.Runtime, opts => opts.MapFrom(src => src.runtime.ToString())) + opts => opts.MapFrom(src => src.vote_average.ToString(CultureInfo.CurrentUICulture))) + //.ForMember(dest => dest.Runtime, opts => opts.MapFrom(src => src.runtime.ToString())) .ForMember(dest => dest.SeriesId, opts => opts.MapFrom(src => src.id)) .ForMember(dest => dest.Title, opts => opts.MapFrom(src => src.name)) - .ForMember(dest => dest.Network, opts => opts.MapFrom(src => src.network)) - .ForMember(dest => dest.Images, opts => opts.MapFrom(src => src.image)) - .ForMember(dest => dest.Cast, opts => opts.MapFrom(src => src._embedded.cast)) - .ForMember(dest => dest.Crew, opts => opts.MapFrom(src => src._embedded.crew)) - .ForMember(dest => dest.Banner, - opts => opts.MapFrom(src => - !string.IsNullOrEmpty(src.image.medium) - ? src.image.medium.ToHttpsUrl() - : string.Empty)) + //.ForMember(dest => dest.Network, opts => opts.MapFrom(src => src.network)) + .ForMember(dest => dest.Images, opts => opts.MapFrom(src => src.Images)) + .ForMember(dest => dest.Cast, opts => opts.MapFrom(src => src.Credits.cast)) + .ForMember(dest => dest.Crew, opts => opts.MapFrom(src => src.Credits.crew)) + .ForMember(dest => dest.Banner, opts => opts.MapFrom(src => GetBanner(src.Images))) + .ForMember(dest => dest.Genres, opts => opts.MapFrom(src => src.genres)) + .ForMember(dest => dest.Keywords, opts => opts.MapFrom(src => src.Keywords)) + .ForMember(dest => dest.Tagline, opts => opts.MapFrom(src => src.tagline)) + .ForMember(dest => dest.ExternalIds, opts => opts.MapFrom(src => src.ExternalIds)) + .ForMember(dest => dest.Trailer, opts => opts.MapFrom(src => GetTrailer(src.Videos))) + .ForMember(dest => dest.Runtime, opts => opts.MapFrom(src => src.episode_run_time.FirstOrDefault())) .ForMember(dest => dest.Status, opts => opts.MapFrom(src => src.status)); - CreateMap() - .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id)) - .ForMember(dest => dest.Country, opts => opts.MapFrom(src => src.country)) - .ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name)); + CreateMap().ReverseMap(); + CreateMap() + .ForMember(dest => dest.Original, opts => opts.MapFrom(src => src.Posters.OrderBy(x => x.VoteCount).ThenBy(x => x.VoteAverage).FirstOrDefault().FilePath)); + + + CreateMap().ReverseMap(); + CreateMap().ReverseMap(); + + + CreateMap() + .ForMember(dest => dest.id, opts => opts.MapFrom(src => src.id)) + .ForMember(dest => dest.name, opts => opts.MapFrom(src => src.name)); + + CreateMap() + .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id)) + .ForMember(dest => dest.Country, opts => opts.MapFrom(src => src.origin_country)) + .ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name)); CreateMap() .ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name)) .ForMember(dest => dest.Code, opts => opts.MapFrom(src => src.code)) .ForMember(dest => dest.Timezone, opts => opts.MapFrom(src => src.timezone)); - CreateMap() - .ForMember(dest => dest.Medium, opts => opts.MapFrom(src => src.medium.ToHttpsUrl())) - .ForMember(dest => dest.Original, opts => opts.MapFrom(src => src.original.ToHttpsUrl())); + CreateMap() + .ForMember(dest => dest.Character, opts => opts.MapFrom(src => src.character)) + .ForMember(dest => dest.Person, opts => opts.MapFrom(src => src.name)) + .ForMember(dest => dest.Image, opts => opts.MapFrom(src => src.profile_path)) + .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id)); - CreateMap() - .ForMember(dest => dest.Character, opts => opts.MapFrom(src => src.character)) - .ForMember(dest => dest.Person, opts => opts.MapFrom(src => src.person)) - .ForMember(dest => dest.Voice, opts => opts.MapFrom(src => src.voice)) - .ForMember(dest => dest.Self, opts => opts.MapFrom(src => src.self)); - - CreateMap() + CreateMap() .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id)) - .ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name)) - .ForMember(dest => dest.Image, opts => opts.MapFrom(src => src.image)) - .ForMember(dest => dest.Url, opts => opts.MapFrom(src => src.url.ToHttpsUrl())); - - CreateMap() - .ForMember(dest => dest.Person, opts => opts.MapFrom(src => src.person)) - .ForMember(dest => dest.Type, opts => opts.MapFrom(src => src.type)); - - CreateMap() - .ForMember(dest => dest.Person, opts => opts.MapFrom(src => src.person)) - .ForMember(dest => dest.Self, opts => opts.MapFrom(src => src.self)) - .ForMember(dest => dest.Voice, opts => opts.MapFrom(src => src.voice)) - .ForMember(dest => dest.Character, opts => opts.MapFrom(src => src.character)); - - CreateMap() - .ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name)) - .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.id)) - .ForMember(dest => dest.Url, opts => opts.MapFrom(src => src.url.ToHttpsUrl())) - .ForMember(dest => dest.Image, opts => opts.MapFrom(src => src.image)); + .ForMember(dest => dest.Image, opts => opts.MapFrom(src => src.profile_path)) + .ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.name)); CreateMap().ReverseMap(); } + + private string GetBanner(Api.TheMovieDb.Models.Images images) + { + var hasBackdrop = images?.Backdrops?.Any(); + if (hasBackdrop ?? false) + { + return images.Backdrops?.OrderBy(x => x.VoteCount).ThenBy(x => x.VoteAverage).Select(x => x.FilePath).FirstOrDefault(); + } + else if (images != null) + { + return images.Posters?.OrderBy(x => x.VoteCount).ThenBy(x => x.VoteAverage).Select(x => x.FilePath).FirstOrDefault(); + } + else + { + return string.Empty; + } + } + + private string GetTrailer(Api.TheMovieDb.Models.Videos trailer) + { + return trailer?.results?.FirstOrDefault(x => x.type.Equals("trailer", StringComparison.InvariantCultureIgnoreCase))?.key ?? null; + } } } \ No newline at end of file diff --git a/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs b/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs index b8d76e10d..15ec9b286 100644 --- a/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs +++ b/src/Ombi.Notifications.Templates/EmailBasicTemplate.cs @@ -13,7 +13,7 @@ namespace Ombi.Notifications.Templates if (string.IsNullOrEmpty(_templateLocation)) { #if DEBUG - _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "netcoreapp3.1", "Templates", + _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net5.0", "Templates", "BasicTemplate.html"); #else _templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates","BasicTemplate.html"); diff --git a/src/Ombi.Notifications/NotificationMessageCurlys.cs b/src/Ombi.Notifications/NotificationMessageCurlys.cs index dcf49138d..54e85080b 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -131,7 +131,7 @@ namespace Ombi.Notifications { LoadIssues(opts); RequestId = req?.Id.ToString(); - ProviderId = req?.ParentRequest?.TvDbId.ToString() ?? string.Empty; + ProviderId = req?.ParentRequest?.ExternalProviderId.ToString() ?? string.Empty; string title; if (req == null) { diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs index f554e428d..8333eed56 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexContentSync.cs @@ -34,6 +34,8 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Ombi.Api.Plex; using Ombi.Api.Plex.Models; +using Ombi.Api.TheMovieDb; +using Ombi.Api.TheMovieDb.Models; using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; @@ -49,8 +51,9 @@ namespace Ombi.Schedule.Jobs.Plex { public class PlexContentSync : IPlexContentSync { + private readonly IMovieDbApi _movieApi; public PlexContentSync(ISettingsService plex, IPlexApi plexApi, ILogger logger, IPlexContentRepository repo, - IPlexEpisodeSync epsiodeSync, IHubContext hub) + IPlexEpisodeSync epsiodeSync, IHubContext hub, IMovieDbApi movieDbApi) { Plex = plex; PlexApi = plexApi; @@ -58,6 +61,7 @@ namespace Ombi.Schedule.Jobs.Plex Repo = repo; EpisodeSync = epsiodeSync; Notification = hub; + _movieApi = movieDbApi; Plex.ClearCache(); } @@ -418,7 +422,7 @@ namespace Ombi.Schedule.Jobs.Plex { var showMetadata = await PlexApi.GetMetadata(servers.PlexAuthToken, servers.FullUri, existingContent.Key); - GetProviderIds(showMetadata, existingContent); + await GetProviderIds(showMetadata, existingContent); await Repo.Update(existingContent); } @@ -531,7 +535,7 @@ namespace Ombi.Schedule.Jobs.Plex Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, show.ratingKey), Seasons = new List() }; - GetProviderIds(showMetadata, item); + await GetProviderIds(showMetadata, item); // Let's just double check to make sure we do not have it now we have some id's var existingImdb = false; @@ -573,7 +577,7 @@ namespace Ombi.Schedule.Jobs.Plex } } - private static void GetProviderIds(PlexMetadata showMetadata, PlexServerContent existingContent) + private async Task GetProviderIds(PlexMetadata showMetadata, PlexServerContent existingContent) { var metadata = showMetadata.MediaContainer.Metadata.FirstOrDefault(); var guids = new List @@ -601,6 +605,13 @@ namespace Ombi.Schedule.Jobs.Plex if (providerIds.TheTvDb.HasValue()) { + // Lookup TheMovieDbId + var findResult = await _movieApi.Find(providerIds.TheTvDb, ExternalSource.tvdb_id); + var tvResult = findResult.tv_results.FirstOrDefault(); + if (tvResult != null) + { + existingContent.TheMovieDbId = tvResult.id.ToString(); + } existingContent.TvDbId = providerIds.TheTvDb; } } @@ -683,6 +694,7 @@ namespace Ombi.Schedule.Jobs.Plex } private bool _disposed; + protected virtual void Dispose(bool disposing) { if (_disposed) diff --git a/src/Ombi.Settings/Settings/Models/OmbiSettings.cs b/src/Ombi.Settings/Settings/Models/OmbiSettings.cs index 11812e439..36b540026 100644 --- a/src/Ombi.Settings/Settings/Models/OmbiSettings.cs +++ b/src/Ombi.Settings/Settings/Models/OmbiSettings.cs @@ -4,7 +4,6 @@ { public string BaseUrl { get; set; } public bool CollectAnalyticData { get; set; } - public bool Set { get; set; } public bool Wizard { get; set; } public string ApiKey { get; set; } public bool IgnoreCertificateErrors { get; set; } @@ -14,5 +13,9 @@ public string DefaultLanguageCode { get; set; } = "en"; public bool AutoDeleteAvailableRequests { get; set; } public int AutoDeleteAfterDays { get; set; } + + //INTERNAL + public bool HasMigratedOldTvDbData { get; set; } + public bool Set { get; set; } } } \ No newline at end of file diff --git a/src/Ombi.Store/Entities/Requests/SeasonRequests.cs b/src/Ombi.Store/Entities/Requests/SeasonRequests.cs index 8a69a4767..8a9fabf08 100644 --- a/src/Ombi.Store/Entities/Requests/SeasonRequests.cs +++ b/src/Ombi.Store/Entities/Requests/SeasonRequests.cs @@ -11,6 +11,7 @@ namespace Ombi.Store.Repository.Requests public class SeasonRequests : Entity { public int SeasonNumber { get; set; } + public string Overview { get; set; } public List Episodes { get; set; } = new List(); public int ChildRequestId { get; set; } diff --git a/src/Ombi.Store/Entities/Requests/TvRequests.cs b/src/Ombi.Store/Entities/Requests/TvRequests.cs index 5e33c016f..9ba54c58f 100644 --- a/src/Ombi.Store/Entities/Requests/TvRequests.cs +++ b/src/Ombi.Store/Entities/Requests/TvRequests.cs @@ -6,7 +6,13 @@ namespace Ombi.Store.Entities.Requests { public class TvRequests : Entity { + /// + /// No longer used since moved away from TvMaze + /// public int TvDbId { get; set; } + + // TheMovieDbId + public int ExternalProviderId { get; set; } public string ImdbId { get; set; } public int? QualityOverride { get; set; } public int? RootFolder { get; set; } diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20210305151743_TvRequestProviderId.Designer.cs b/src/Ombi.Store/Migrations/OmbiMySql/20210305151743_TvRequestProviderId.Designer.cs new file mode 100644 index 000000000..5621af456 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20210305151743_TvRequestProviderId.Designer.cs @@ -0,0 +1,1232 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.MySql; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + [DbContext(typeof(OmbiMySqlContext))] + [Migration("20210305151743_TvRequestProviderId")] + partial class TvRequestProviderId + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 64) + .HasAnnotation("ProductVersion", "5.0.1"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasColumnType("longtext"); + + b.Property("ClaimValue") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasColumnType("longtext"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("RoleId") + .HasColumnType("varchar(255)"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AuditArea") + .HasColumnType("int"); + + b.Property("AuditType") + .HasColumnType("int"); + + b.Property("DateTime") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("User") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .HasColumnType("longtext"); + + b.Property("NotificationType") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("PlayerId") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("varchar(255)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Alias") + .HasColumnType("longtext"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("longtext"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("int"); + + b.Property("Language") + .HasColumnType("longtext"); + + b.Property("LastLoggedIn") + .HasColumnType("datetime(6)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("MovieRequestLimit") + .HasColumnType("int"); + + b.Property("MusicRequestLimit") + .HasColumnType("int"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasColumnType("longtext"); + + b.Property("PhoneNumber") + .HasColumnType("longtext"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("ProviderUserId") + .HasColumnType("longtext"); + + b.Property("SecurityStamp") + .HasColumnType("longtext"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserAccessToken") + .HasColumnType("longtext"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UserType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AddedAt") + .HasColumnType("datetime(6)"); + + b.Property("AlbumId") + .HasColumnType("longtext"); + + b.Property("ContentId") + .HasColumnType("int"); + + b.Property("ContentType") + .HasColumnType("int"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Completed") + .HasColumnType("datetime(6)"); + + b.Property("Dts") + .HasColumnType("datetime(6)"); + + b.Property("Error") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("ArtistName") + .HasColumnType("longtext"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Cover") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("Disk") + .HasColumnType("longtext"); + + b.Property("ForeignAlbumId") + .HasColumnType("longtext"); + + b.Property("ForeignArtistId") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Rating") + .HasColumnType("decimal(65,30)"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("ParentRequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("SeriesType") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Comment") + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("IssuesId") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasColumnType("longtext"); + + b.Property("IssueCategoryId") + .HasColumnType("int"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("longtext"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("ResovledDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Subject") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("UserReportedId") + .HasColumnType("varchar(255)"); + + 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() + .HasColumnType("int"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("Denied") + .HasColumnType("tinyint(1)"); + + b.Property("DeniedReason") + .HasColumnType("longtext"); + + b.Property("DigitalReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("IssueId") + .HasColumnType("int"); + + b.Property("LangCode") + .HasColumnType("longtext"); + + b.Property("MarkedAsApproved") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsAvailable") + .HasColumnType("datetime(6)"); + + b.Property("MarkedAsDenied") + .HasColumnType("datetime(6)"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("RequestedByAlias") + .HasColumnType("longtext"); + + b.Property("RequestedDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestedUserId") + .HasColumnType("varchar(255)"); + + b.Property("RootPathOverride") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("TheMovieDbId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("EpisodeCount") + .HasColumnType("int"); + + b.Property("RequestDate") + .HasColumnType("datetime(6)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Background") + .HasColumnType("longtext"); + + b.Property("ExternalProviderId") + .HasColumnType("int"); + + b.Property("ImdbId") + .HasColumnType("longtext"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("PosterPath") + .HasColumnType("longtext"); + + b.Property("QualityOverride") + .HasColumnType("int"); + + b.Property("ReleaseDate") + .HasColumnType("datetime(6)"); + + b.Property("RootFolder") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("longtext"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("TotalSeasons") + .HasColumnType("int"); + + b.Property("TvDbId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Token") + .HasColumnType("longtext"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Agent") + .HasColumnType("int"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("RadarrQualityProfile") + .HasColumnType("int"); + + b.Property("RadarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrQualityProfile") + .HasColumnType("int"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("int"); + + b.Property("SonarrRootPath") + .HasColumnType("int"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Deleted") + .HasColumnType("tinyint(1)"); + + b.Property("RequestId") + .HasColumnType("int"); + + b.Property("RequestType") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("varchar(255)"); + + b.Property("VoteType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AirDate") + .HasColumnType("datetime(6)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("Available") + .HasColumnType("tinyint(1)"); + + b.Property("EpisodeNumber") + .HasColumnType("int"); + + b.Property("Requested") + .HasColumnType("tinyint(1)"); + + b.Property("SeasonId") + .HasColumnType("int"); + + b.Property("Title") + .HasColumnType("longtext"); + + b.Property("Url") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ChildRequestId") + .HasColumnType("int"); + + b.Property("Overview") + .HasColumnType("longtext"); + + b.Property("SeasonNumber") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + 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"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/20210305151743_TvRequestProviderId.cs b/src/Ombi.Store/Migrations/OmbiMySql/20210305151743_TvRequestProviderId.cs new file mode 100644 index 000000000..a5a0a2b00 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiMySql/20210305151743_TvRequestProviderId.cs @@ -0,0 +1,52 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.OmbiMySql +{ + public partial class TvRequestProviderId : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ExternalProviderId", + table: "TvRequests", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "Overview", + table: "SeasonRequests", + type: "longtext", + nullable: true); + + migrationBuilder.AlterColumn( + name: "StreamingCountry", + table: "AspNetUsers", + type: "longtext", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + oldType: "longtext", + oldNullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ExternalProviderId", + table: "TvRequests"); + + migrationBuilder.DropColumn( + name: "Overview", + table: "SeasonRequests"); + + migrationBuilder.AlterColumn( + name: "StreamingCountry", + table: "AspNetUsers", + type: "longtext", + nullable: true, + oldClrType: typeof(string), + oldType: "longtext"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs index 38487dc9f..f127b6c23 100644 --- a/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiMySql/OmbiMySqlContextModelSnapshot.cs @@ -308,6 +308,7 @@ namespace Ombi.Store.Migrations.OmbiMySql .HasColumnType("longtext"); b.Property("StreamingCountry") + .IsRequired() .HasColumnType("longtext"); b.Property("TwoFactorEnabled") @@ -764,6 +765,9 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("Background") .HasColumnType("longtext"); + b.Property("ExternalProviderId") + .HasColumnType("int"); + b.Property("ImdbId") .HasColumnType("longtext"); @@ -954,6 +958,9 @@ namespace Ombi.Store.Migrations.OmbiMySql b.Property("ChildRequestId") .HasColumnType("int"); + b.Property("Overview") + .HasColumnType("longtext"); + b.Property("SeasonNumber") .HasColumnType("int"); diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20210305151854_TvRequestProviderId.Designer.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20210305151854_TvRequestProviderId.Designer.cs new file mode 100644 index 000000000..20aedc05c --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20210305151854_TvRequestProviderId.Designer.cs @@ -0,0 +1,1231 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Ombi.Store.Context.Sqlite; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + [DbContext(typeof(OmbiSqliteContext))] + [Migration("20210305151854_TvRequestProviderId")] + partial class TvRequestProviderId + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "5.0.1"); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ClaimType") + .HasColumnType("TEXT"); + + b.Property("ClaimValue") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("ProviderKey") + .HasColumnType("TEXT"); + + b.Property("ProviderDisplayName") + .HasColumnType("TEXT"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("LoginProvider") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Audit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuditArea") + .HasColumnType("INTEGER"); + + b.Property("AuditType") + .HasColumnType("INTEGER"); + + b.Property("DateTime") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Audit"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("MobileDevices"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NotificationType") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("NotificationTemplates"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("PlayerId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationUserId"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessFailedCount") + .HasColumnType("INTEGER"); + + b.Property("Alias") + .HasColumnType("TEXT"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailConfirmed") + .HasColumnType("INTEGER"); + + b.Property("EpisodeRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("LastLoggedIn") + .HasColumnType("TEXT"); + + b.Property("LockoutEnabled") + .HasColumnType("INTEGER"); + + b.Property("LockoutEnd") + .HasColumnType("TEXT"); + + b.Property("MovieRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("MusicRequestLimit") + .HasColumnType("INTEGER"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PasswordHash") + .HasColumnType("TEXT"); + + b.Property("PhoneNumber") + .HasColumnType("TEXT"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("INTEGER"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .HasColumnType("TEXT"); + + b.Property("StreamingCountry") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("TwoFactorEnabled") + .HasColumnType("INTEGER"); + + b.Property("UserAccessToken") + .HasColumnType("TEXT"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("UserType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddedAt") + .HasColumnType("TEXT"); + + b.Property("AlbumId") + .HasColumnType("TEXT"); + + b.Property("ContentId") + .HasColumnType("INTEGER"); + + b.Property("ContentType") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RecentlyAddedLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestQueue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Completed") + .HasColumnType("TEXT"); + + b.Property("Dts") + .HasColumnType("TEXT"); + + b.Property("Error") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RetryCount") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RequestQueue"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestSubscription"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("ArtistName") + .HasColumnType("TEXT"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Cover") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("Disk") + .HasColumnType("TEXT"); + + b.Property("ForeignAlbumId") + .HasColumnType("TEXT"); + + b.Property("ForeignArtistId") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Rating") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("AlbumRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("ParentRequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("SeriesType") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ParentRequestId"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("IssueCategory"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Comment") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("IssuesId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("IssuesId"); + + b.HasIndex("UserId"); + + b.ToTable("IssueComments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedDate") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("IssueCategoryId") + .HasColumnType("INTEGER"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("ResovledDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Subject") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("UserReportedId") + .HasColumnType("TEXT"); + + 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() + .HasColumnType("INTEGER"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("Denied") + .HasColumnType("INTEGER"); + + b.Property("DeniedReason") + .HasColumnType("TEXT"); + + b.Property("DigitalReleaseDate") + .HasColumnType("TEXT"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("IssueId") + .HasColumnType("INTEGER"); + + b.Property("LangCode") + .HasColumnType("TEXT"); + + b.Property("MarkedAsApproved") + .HasColumnType("TEXT"); + + b.Property("MarkedAsAvailable") + .HasColumnType("TEXT"); + + b.Property("MarkedAsDenied") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("RequestedByAlias") + .HasColumnType("TEXT"); + + b.Property("RequestedDate") + .HasColumnType("TEXT"); + + b.Property("RequestedUserId") + .HasColumnType("TEXT"); + + b.Property("RootPathOverride") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("TheMovieDbId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("RequestedUserId"); + + b.ToTable("MovieRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeCount") + .HasColumnType("INTEGER"); + + b.Property("RequestDate") + .HasColumnType("TEXT"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("RequestLog"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Background") + .HasColumnType("TEXT"); + + b.Property("ExternalProviderId") + .HasColumnType("INTEGER"); + + b.Property("ImdbId") + .HasColumnType("TEXT"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("PosterPath") + .HasColumnType("TEXT"); + + b.Property("QualityOverride") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("RootFolder") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TotalSeasons") + .HasColumnType("INTEGER"); + + b.Property("TvDbId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TvRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Tokens"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Agent") + .HasColumnType("INTEGER"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("RadarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("RadarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfile") + .HasColumnType("INTEGER"); + + b.Property("SonarrQualityProfileAnime") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPath") + .HasColumnType("INTEGER"); + + b.Property("SonarrRootPathAnime") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserQualityProfiles"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("Deleted") + .HasColumnType("INTEGER"); + + b.Property("RequestId") + .HasColumnType("INTEGER"); + + b.Property("RequestType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.Property("VoteType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AirDate") + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("Available") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("Requested") + .HasColumnType("INTEGER"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Url") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("EpisodeRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChildRequestId") + .HasColumnType("INTEGER"); + + b.Property("Overview") + .HasColumnType("TEXT"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChildRequestId"); + + b.ToTable("SeasonRequests"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Ombi.Store.Entities.MobileDevices", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("NotificationUserIds") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.RequestSubscription", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.AlbumRequest", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest") + .WithMany("ChildRequests") + .HasForeignKey("ParentRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("ParentRequest"); + + b.Navigation("RequestedUser"); + }); + + 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"); + + b.Navigation("Issues"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory") + .WithMany() + .HasForeignKey("IssueCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.Requests.MovieRequests", null) + .WithMany("Issues") + .HasForeignKey("IssueId"); + + b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported") + .WithMany() + .HasForeignKey("UserReportedId"); + + b.Navigation("IssueCategory"); + + b.Navigation("UserReported"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser") + .WithMany() + .HasForeignKey("RequestedUserId"); + + b.Navigation("RequestedUser"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Tokens", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserNotificationPreferences", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany("UserNotificationPreferences") + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.UserQualityProfiles", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Votes", b => + { + b.HasOne("Ombi.Store.Entities.OmbiUser", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b => + { + b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest") + .WithMany("SeasonRequests") + .HasForeignKey("ChildRequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ChildRequest"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b => + { + b.Navigation("NotificationUserIds"); + + b.Navigation("UserNotificationPreferences"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b => + { + b.Navigation("Issues"); + + b.Navigation("SeasonRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b => + { + b.Navigation("Comments"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b => + { + b.Navigation("Issues"); + }); + + modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b => + { + b.Navigation("ChildRequests"); + }); + + modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b => + { + b.Navigation("Episodes"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/20210305151854_TvRequestProviderId.cs b/src/Ombi.Store/Migrations/OmbiSqlite/20210305151854_TvRequestProviderId.cs new file mode 100644 index 000000000..a3185b1a1 --- /dev/null +++ b/src/Ombi.Store/Migrations/OmbiSqlite/20210305151854_TvRequestProviderId.cs @@ -0,0 +1,34 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ombi.Store.Migrations.OmbiSqlite +{ + public partial class TvRequestProviderId : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ExternalProviderId", + table: "TvRequests", + type: "INTEGER", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "Overview", + table: "SeasonRequests", + type: "TEXT", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ExternalProviderId", + table: "TvRequests"); + + migrationBuilder.DropColumn( + name: "Overview", + table: "SeasonRequests"); + } + } +} diff --git a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs index 6a00fe29b..144ca4613 100644 --- a/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs +++ b/src/Ombi.Store/Migrations/OmbiSqlite/OmbiSqliteContextModelSnapshot.cs @@ -764,6 +764,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("Background") .HasColumnType("TEXT"); + b.Property("ExternalProviderId") + .HasColumnType("INTEGER"); + b.Property("ImdbId") .HasColumnType("TEXT"); @@ -954,6 +957,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite b.Property("ChildRequestId") .HasColumnType("INTEGER"); + b.Property("Overview") + .HasColumnType("TEXT"); + b.Property("SeasonNumber") .HasColumnType("INTEGER"); diff --git a/src/Ombi.Store/Repository/Requests/ITvRequestRepository.cs b/src/Ombi.Store/Repository/Requests/ITvRequestRepository.cs index 396ec9dfb..d7106c086 100644 --- a/src/Ombi.Store/Repository/Requests/ITvRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/ITvRequestRepository.cs @@ -16,7 +16,7 @@ namespace Ombi.Store.Repository.Requests IQueryable Get(string userId); IQueryable GetLite(string userId); Task GetRequestAsync(int tvDbId); - TvRequests GetRequest(int tvDbId); + TvRequests GetRequest(int theMovieDbId); Task Update(TvRequests request); Task UpdateChild(ChildRequests request); IQueryable GetChild(); diff --git a/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs index a5a7406ab..0a72b1b32 100644 --- a/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs +++ b/src/Ombi.Store/Repository/Requests/TvRequestRepository.cs @@ -20,7 +20,7 @@ namespace Ombi.Store.Repository.Requests public async Task GetRequestAsync(int tvDbId) { - return await Db.TvRequests.Where(x => x.TvDbId == tvDbId) + return await Db.TvRequests.Where(x => x.ExternalProviderId == tvDbId) .Include(x => x.ChildRequests) .ThenInclude(x => x.RequestedUser) .Include(x => x.ChildRequests) @@ -29,9 +29,9 @@ namespace Ombi.Store.Repository.Requests .FirstOrDefaultAsync(); } - public TvRequests GetRequest(int tvDbId) + public TvRequests GetRequest(int theMovieDbId) { - return Db.TvRequests.Where(x => x.TvDbId == tvDbId).AsSplitQuery() + return Db.TvRequests.Where(x => x.ExternalProviderId == theMovieDbId).AsSplitQuery() .Include(x => x.ChildRequests) .ThenInclude(x => x.RequestedUser) .Include(x => x.ChildRequests) diff --git a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs index 1b35381ad..ea2465c1d 100644 --- a/src/Ombi.TheMovieDbApi/IMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/IMovieDbApi.cs @@ -10,16 +10,20 @@ namespace Ombi.Api.TheMovieDb { Task GetMovieInformation(int movieId); Task GetMovieInformationWithExtraInfo(int movieId, string langCode = "en"); - Task> NowPlaying(string languageCode, int? page = null); - Task> PopularMovies(string languageCode, int? page = null, CancellationToken cancellationToken = default(CancellationToken)); - Task> SearchMovie(string searchTerm, int? year, string languageCode); + Task> NowPlaying(string languageCode, int? page = null); + Task> PopularMovies(string languageCode, int? page = null, CancellationToken cancellationToken = default(CancellationToken)); + Task> PopularTv(string langCode, int? page = null, CancellationToken cancellationToken = default(CancellationToken)); + Task> SearchMovie(string searchTerm, int? year, string languageCode); Task> SearchTv(string searchTerm, string year = default); - Task> TopRated(string languageCode, int? page = null); - Task> Upcoming(string languageCode, int? page = null); - Task> SimilarMovies(int movieId, string langCode); + Task> TopRated(string languageCode, int? page = null); + Task> Upcoming(string languageCode, int? page = null); + Task> TopRatedTv(string languageCode, int? page = null); + Task> UpcomingTv(string languageCode, int? page = null); + Task> SimilarMovies(int movieId, string langCode); Task Find(string externalId, ExternalSource source); - Task GetTvExternals(int theMovieDbId); - Task GetTVInfo(string themoviedbid); + Task GetTvExternals(int theMovieDbId); + Task GetSeasonEpisodes(int theMovieDbId, int seasonNumber, CancellationToken token, string langCode = "en"); + Task GetTVInfo(string themoviedbid, string langCode = "en"); Task> SearchByActor(string searchTerm, string langCode); Task GetActorMovieCredits(int actorId, string langCode); Task> MultiSearch(string searchTerm, string languageCode, CancellationToken cancellationToken); diff --git a/src/Ombi.TheMovieDbApi/Models/FindResult.cs b/src/Ombi.TheMovieDbApi/Models/FindResult.cs index f76fca564..07020d866 100644 --- a/src/Ombi.TheMovieDbApi/Models/FindResult.cs +++ b/src/Ombi.TheMovieDbApi/Models/FindResult.cs @@ -6,7 +6,12 @@ public object[] person_results { get; set; } public TvResults[] tv_results { get; set; } public object[] tv_episode_results { get; set; } - public object[] tv_season_results { get; set; } + public FindSeasonResults[] tv_season_results { get; set; } + } + + public class FindSeasonResults + { + public int show_id { get; set; } } public class Movie_Results diff --git a/src/Ombi.TheMovieDbApi/Models/FullMovieInfo.cs b/src/Ombi.TheMovieDbApi/Models/FullMovieInfo.cs index 3149ed5a1..1dc39299a 100644 --- a/src/Ombi.TheMovieDbApi/Models/FullMovieInfo.cs +++ b/src/Ombi.TheMovieDbApi/Models/FullMovieInfo.cs @@ -87,6 +87,10 @@ namespace Ombi.Api.TheMovieDb.Models { [JsonProperty("file_path")] public string FilePath { get; set; } + [JsonProperty("vote_count")] + public int VoteCount { get; set; } + [JsonProperty("vote_average")] + public double VoteAverage { get; set; } } public class Keywords @@ -128,6 +132,8 @@ namespace Ombi.Api.TheMovieDb.Models public string InstagramId { get; set; } [JsonProperty("twitter_id")] public string TwitterId { get; set; } + [JsonProperty("tvdb_id")] + public string TvDbId { get; set; } } public class Credits diff --git a/src/Ombi.TheMovieDbApi/Models/MovieSearchResult.cs b/src/Ombi.TheMovieDbApi/Models/MovieDbSearchResult.cs similarity index 94% rename from src/Ombi.TheMovieDbApi/Models/MovieSearchResult.cs rename to src/Ombi.TheMovieDbApi/Models/MovieDbSearchResult.cs index 8503cd7f7..0e4a8852f 100644 --- a/src/Ombi.TheMovieDbApi/Models/MovieSearchResult.cs +++ b/src/Ombi.TheMovieDbApi/Models/MovieDbSearchResult.cs @@ -1,6 +1,6 @@ namespace Ombi.Api.TheMovieDb.Models { - public class MovieSearchResult + public class MovieDbSearchResult { public string PosterPath { get; set; } public bool Adult { get; set; } diff --git a/src/Ombi.TheMovieDbApi/Models/SeasonDetails.cs b/src/Ombi.TheMovieDbApi/Models/SeasonDetails.cs new file mode 100644 index 000000000..eb36bdd87 --- /dev/null +++ b/src/Ombi.TheMovieDbApi/Models/SeasonDetails.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Ombi.Api.TheMovieDb.Models +{ + public class SeasonDetails + { + public string _id { get; set; } + public string air_date { get; set; } + public Episode[] episodes { get; set; } + public string name { get; set; } + public string overview { get; set; } + public int id { get; set; } + public string poster_path { get; set; } + public int season_number { get; set; } + } + + public class Episode + { + public string air_date { get; set; } + public int episode_number { get; set; } + public Crew[] crew { get; set; } + public Guest_Stars[] guest_stars { get; set; } + public int id { get; set; } + public string name { get; set; } + public string overview { get; set; } + public string production_code { get; set; } + public int season_number { get; set; } + public string still_path { get; set; } + public float vote_average { get; set; } + public int vote_count { get; set; } + } + + + + public class Guest_Stars + { + public string character { get; set; } + public string credit_id { get; set; } + public int order { get; set; } + public bool adult { get; set; } + public int gender { get; set; } + public int id { get; set; } + public string known_for_department { get; set; } + public string name { get; set; } + public string original_name { get; set; } + public float popularity { get; set; } + public string profile_path { get; set; } + } + +} diff --git a/src/Ombi.TheMovieDbApi/Models/TvInfo.cs b/src/Ombi.TheMovieDbApi/Models/TvInfo.cs index f1070d658..024d6f42b 100644 --- a/src/Ombi.TheMovieDbApi/Models/TvInfo.cs +++ b/src/Ombi.TheMovieDbApi/Models/TvInfo.cs @@ -18,6 +18,7 @@ namespace Ombi.Api.TheMovieDb.Models public Network[] networks { get; set; } public int number_of_episodes { get; set; } public int number_of_seasons { get; set; } + public string tagline { get; set; } public string[] origin_country { get; set; } public string original_language { get; set; } public string original_name { get; set; } @@ -30,7 +31,21 @@ namespace Ombi.Api.TheMovieDb.Models public string type { get; set; } public float vote_average { get; set; } public int vote_count { get; set; } - [JsonProperty("external_ids")] public TvExternalIds TvExternalIds { get; set; } + [JsonProperty("videos")] + public Videos Videos { get; set; } + [JsonProperty("credits")] + public Credits Credits { get; set; } + [JsonProperty("similar")] + public Similar Similar { get; set; } + [JsonProperty("recommendations")] + public Recommendations Recommendations { get; set; } + [JsonProperty("external_ids")] + public ExternalIds ExternalIds { get; set; } + [JsonProperty("keywords")] + public Keywords Keywords { get; set; } + [JsonProperty("images")] + public Images Images { get; set; } + } public class Created_By diff --git a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs index f270ad3b2..74c849d59 100644 --- a/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs +++ b/src/Ombi.TheMovieDbApi/TheMovieDbApi.cs @@ -132,7 +132,7 @@ namespace Ombi.Api.TheMovieDb return await Api.Request(request); } - public async Task> SimilarMovies(int movieId, string langCode) + public async Task> SimilarMovies(int movieId, string langCode) { var request = new Request($"movie/{movieId}/similar", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); @@ -140,7 +140,7 @@ namespace Ombi.Api.TheMovieDb AddRetry(request); var result = await Api.Request>(request); - return Mapper.Map>(result.results); + return Mapper.Map>(result.results); } public async Task GetMovieInformationWithExtraInfo(int movieId, string langCode = "en") @@ -154,7 +154,7 @@ namespace Ombi.Api.TheMovieDb return Mapper.Map(result); } - public async Task> SearchMovie(string searchTerm, int? year, string langCode) + public async Task> SearchMovie(string searchTerm, int? year, string langCode) { var request = new Request($"search/movie", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); @@ -171,15 +171,25 @@ namespace Ombi.Api.TheMovieDb AddRetry(request); var result = await Api.Request>(request); - return Mapper.Map>(result.results); + return Mapper.Map>(result.results); } /// /// Maintains filter parity with /movie/popular. /// - public async Task> PopularMovies(string langCode, int? page = null, CancellationToken cancellationToken = default(CancellationToken)) + public async Task> PopularMovies(string langCode, int? page = null, CancellationToken cancellationToken = default(CancellationToken)) { - var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + return await Popular("movie", langCode, page, cancellationToken); + } + + public async Task> PopularTv(string langCode, int? page = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return await Popular("tv", langCode, page, cancellationToken); + } + + public async Task> Popular(string type, string langCode, int? page = null, CancellationToken cancellationToken = default(CancellationToken)) + { + var request = new Request($"discover/{type}", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); request.AddQueryString("language", langCode); request.AddQueryString("sort_by", "popularity.desc"); @@ -187,18 +197,28 @@ namespace Ombi.Api.TheMovieDb { request.AddQueryString("page", page.ToString()); } - await AddDiscoverMovieSettings(request); + await AddDiscoverSettings(request); AddRetry(request); var result = await Api.Request>(request, cancellationToken); - return Mapper.Map>(result.results); + return Mapper.Map>(result.results); + } + + public Task> TopRated(string langCode, int? page = null) + { + return TopRated("movie", langCode, page); + } + + public Task> TopRatedTv(string langCode, int? page = null) + { + return TopRated("tv", langCode, page); } /// /// Maintains filter parity with /movie/top_rated. /// - public async Task> TopRated(string langCode, int? page = null) + private async Task> TopRated(string type, string langCode, int? page = null) { - var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + var request = new Request($"discover/{type}", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); request.AddQueryString("language", langCode); request.AddQueryString("sort_by", "vote_average.desc"); @@ -212,18 +232,27 @@ namespace Ombi.Api.TheMovieDb // to filter out extremely high-rated movies due to very little votes request.AddQueryString("vote_count.gte", "250"); - await AddDiscoverMovieSettings(request); + await AddDiscoverSettings(request); AddRetry(request); var result = await Api.Request>(request); - return Mapper.Map>(result.results); + return Mapper.Map>(result.results); + } + + public Task> Upcoming(string langCode, int? page = null) + { + return Upcoming("movie", langCode, page); + } + public Task> UpcomingTv(string langCode, int? page = null) + { + return Upcoming("tv", langCode, page); } /// /// Maintains filter parity with /movie/upcoming. /// - public async Task> Upcoming(string langCode, int? page = null) + private async Task> Upcoming(string type, string langCode, int? page = null) { - var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); + var request = new Request($"discover/{type}", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); request.AddQueryString("language", langCode); @@ -239,16 +268,16 @@ namespace Ombi.Api.TheMovieDb { request.AddQueryString("page", page.ToString()); } - await AddDiscoverMovieSettings(request); + await AddDiscoverSettings(request); AddRetry(request); var result = await Api.Request>(request); - return Mapper.Map>(result.results); + return Mapper.Map>(result.results); } /// /// Maintains filter parity with /movie/now_playing. /// - public async Task> NowPlaying(string langCode, int? page = null) + public async Task> NowPlaying(string langCode, int? page = null) { var request = new Request($"discover/movie", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); @@ -267,22 +296,33 @@ namespace Ombi.Api.TheMovieDb request.AddQueryString("page", page.ToString()); } - await AddDiscoverMovieSettings(request); + await AddDiscoverSettings(request); AddRetry(request); var result = await Api.Request>(request); - return Mapper.Map>(result.results); + return Mapper.Map>(result.results); } - public async Task GetTVInfo(string themoviedbid) + public async Task GetTVInfo(string themoviedbid, string langCode = "en") { var request = new Request($"/tv/{themoviedbid}", BaseUri, HttpMethod.Get); request.AddQueryString("api_key", ApiToken); - request.AddQueryString("append_to_response", "external_ids"); + request.AddQueryString("language", langCode); + request.AddQueryString("append_to_response", "videos,credits,similar,recommendations,external_ids,keywords,images"); AddRetry(request); return await Api.Request(request); } + public async Task GetSeasonEpisodes(int theMovieDbId, int seasonNumber, CancellationToken token, string langCode = "en") + { + var request = new Request($"/tv/{theMovieDbId}/season/{seasonNumber}", BaseUri, HttpMethod.Get); + request.AddQueryString("api_key", ApiToken); + request.AddQueryString("language", langCode); + AddRetry(request); + + return await Api.Request(request, token); + } + public async Task> SearchKeyword(string searchTerm) { var request = new Request("search/keyword", BaseUri, HttpMethod.Get); @@ -330,7 +370,7 @@ namespace Ombi.Api.TheMovieDb return Api.Request(request, token); } - private async Task AddDiscoverMovieSettings(Request request) + private async Task AddDiscoverSettings(Request request) { var settings = await Settings; request.AddQueryString("include_adult", settings.ShowAdultMovies.ToString().ToLower()); diff --git a/src/Ombi.sln b/src/Ombi.sln index 70324f967..01bc0643e 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -7,6 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi", "Ombi\Ombi.csproj", EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9D30CCF8-A115-4EB7-A34D-07780D752789}" ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig ..\.azuredevops\pipelines\templates\build-steps.yml = ..\.azuredevops\pipelines\templates\build-steps.yml ..\build.cake = ..\build.cake ..\CHANGELOG.md = ..\CHANGELOG.md @@ -121,7 +122,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Webhook", "Ombi.Ap EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.CloudService", "Ombi.Api.CloudService\Ombi.Api.CloudService.csproj", "{5DE40A66-B369-469E-8626-ECE23D9D8034}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.RottenTomatoes", "Ombi.Api.RottenTomatoes\Ombi.Api.RottenTomatoes.csproj", "{8F19C701-7881-4BC7-8BBA-B068A6B954AD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.RottenTomatoes", "Ombi.Api.RottenTomatoes\Ombi.Api.RottenTomatoes.csproj", "{8F19C701-7881-4BC7-8BBA-B068A6B954AD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/Ombi/ClientApp/angular.json b/src/Ombi/ClientApp/angular.json index 41030a25a..76749756d 100644 --- a/src/Ombi/ClientApp/angular.json +++ b/src/Ombi/ClientApp/angular.json @@ -15,7 +15,6 @@ "options": { "aot": true, "progress": true, - "extractCss": true, "outputPath": "dist", "index": "src/index.html", "main": "src/main.ts", @@ -65,7 +64,6 @@ "optimization": true, "outputHashing": "all", "sourceMap": false, - "extractCss": true, "namedChunks": false, "aot": true, "extractLicenses": true, @@ -99,8 +97,7 @@ }, "hmr": { "hmr": true, - "browserTarget": "ombi:build:hmr", - "hmrWarning": false + "browserTarget": "ombi:build:hmr" } } }, diff --git a/src/Ombi/ClientApp/package.json b/src/Ombi/ClientApp/package.json index 6c1713eff..9d3715eaf 100644 --- a/src/Ombi/ClientApp/package.json +++ b/src/Ombi/ClientApp/package.json @@ -9,22 +9,22 @@ }, "private": true, "dependencies": { - "@angular/animations": "^9.1.7", - "@angular/cdk": "^9.2.3", - "@angular/common": "^9.1.7", - "@angular/compiler": "^9.1.7", - "@angular/core": "^9.1.7", - "@angular/forms": "^9.1.7", - "@angular/localize": "^11.0.2", - "@angular/material": "^9.2.3", - "@angular/platform-browser": "^9.1.7", - "@angular/platform-browser-dynamic": "^9.1.7", - "@angular/platform-server": "^9.1.7", - "@angular/router": "^9.1.7", + "@angular/animations": "^11.2.6", + "@angular/cdk": "^11.2.5", + "@angular/common": "^11.2.6", + "@angular/compiler": "^11.2.6", + "@angular/core": "^11.2.6", + "@angular/forms": "^11.2.6", + "@angular/localize": "^11.2.6", + "@angular/material": "^11.2.5", + "@angular/platform-browser": "^11.2.6", + "@angular/platform-browser-dynamic": "^11.2.6", + "@angular/platform-server": "^11.2.6", + "@angular/router": "^11.2.6", "@angularclass/hmr": "^2.1.3", "@aspnet/signalr": "^1.1.0", "@auth0/angular-jwt": "^2.1.0", - "@fortawesome/fontawesome-free": "^5.15.2", + "@fortawesome/fontawesome-free": "^5.15.3", "@fullcalendar/core": "^4.2.0", "@fullcalendar/daygrid": "^4.4.0", "@fullcalendar/interaction": "^4.2.0", @@ -35,7 +35,7 @@ "@yellowspot/ng-truncate": "^1.4.0", "angular-bootstrap-md": "^7.5.4", "angular-router-loader": "^0.8.5", - "angularx-qrcode": "^2.1.0", + "angularx-qrcode": "^11.0.0", "bootstrap": "^4.2.1", "chart.js": "2.9.4", "core-js": "^2.5.4", @@ -52,26 +52,26 @@ "please-wait": "^0.0.5", "popper.js": "^1.14.3", "primeicons": "^4.0.0", - "primeng": "^11.0.0", - "rxjs": "^6.5.2", + "primeng": "^11.3.1", + "rxjs": "^6.6.6", "sass-recursive-map-merge": "^1.0.1", "spinkit": "^1.2.5", "store": "^2.0.12", "ts-md5": "^1.2.7", "tslib": "^1.10.0", "tslint-angular": "^1.1.2", - "zone.js": "~0.10.2" + "zone.js": "~0.11.4" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.901.6", - "@angular/cli": "~9.1.6", - "@angular/compiler-cli": "^9.1.7", - "@angular/language-service": "^9.1.7", - "@types/jasmine": "~2.8.6", - "@types/jasminewd2": "~2.0.3", - "@types/node": "^12.11.1", - "codelyzer": "^5.1.2", - "typescript": "~3.8.3" + "@angular-devkit/build-angular": "~0.1102.5", + "@angular/cli": "~11.2.5", + "@angular/compiler-cli": "^11.2.6", + "@angular/language-service": "^11.2.6", + "@types/jasmine": "~3.6.7", + "@types/jasminewd2": "~2.0.8", + "@types/node": "^14.14.35", + "codelyzer": "^6.0.1", + "typescript": "~4.1.5" }, "optionalDependencies": { "node-sass": "^4.12.0", diff --git a/src/Ombi/ClientApp/src/app/app.component.ts b/src/Ombi/ClientApp/src/app/app.component.ts index edc20610d..356107039 100644 --- a/src/Ombi/ClientApp/src/app/app.component.ts +++ b/src/Ombi/ClientApp/src/app/app.component.ts @@ -82,7 +82,7 @@ export class AppComponent implements OnInit { } public ngOnInit() { - window["loading_screen"].finish(); + // window["loading_screen"].finish(); this.settingsService.getCustomization().subscribe(x => { this.customizationSettings = x; diff --git a/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.ts b/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.ts index 4a06b22d8..83d4d364c 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/actor/discover-actor.component.ts @@ -15,7 +15,7 @@ export class DiscoverActorComponent implements AfterViewInit { public loadingFlag: boolean; public discoverResults: IDiscoverCardResult[] = []; - + constructor(private searchService: SearchV2Service, private route: ActivatedRoute) { this.route.params.subscribe((params: any) => { diff --git a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts index 1bb4f4359..b22ad1e69 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/card/discover-card.component.ts @@ -29,7 +29,8 @@ export class DiscoverCardComponent implements OnInit { public ngOnInit() { if (this.result.type == RequestType.tvShow) { - this.getExtraTvInfo(); + this.fullyLoaded = true; + // this.getExtraTvInfo(); } if (this.result.type == RequestType.movie) { this.getExtraMovieInfo(); @@ -44,15 +45,15 @@ export class DiscoverCardComponent implements OnInit { } public async getExtraTvInfo() { - if (this.result.tvMovieDb) { + // if (this.result.tvMovieDb) { this.tvSearchResult = await this.searchService.getTvInfoWithMovieDbId(+this.result.id); - } else { - this.tvSearchResult = await this.searchService.getTvInfo(+this.result.id); - } - if (!this.tvSearchResult || this.tvSearchResult?.status.length > 0 && this.tvSearchResult?.status === "404") { - this.hide = true; - return; - } + // } else { + // this.tvSearchResult = await this.searchService.getTvInfo(+this.result.id); + // } + // if (!this.tvSearchResult || this.tvSearchResult?.status.length > 0 && this.tvSearchResult?.status === "404") { + // this.hide = true; + // return; + // } this.setTvDefaults(this.tvSearchResult); this.updateTvItem(this.tvSearchResult); @@ -172,8 +173,8 @@ export class DiscoverCardComponent implements OnInit { private updateTvItem(updated: ISearchTvResultV2) { this.result.title = updated.title; this.result.id = updated.id; - this.result.available = updated.fullyAvailable || updated.partlyAvailable; - this.result.posterPath = updated.banner; + // this.result.available = updated.fullyAvailable || updated.partlyAvailable; + // this.result.posterPath = updated.banner; this.result.requested = updated.requested; this.result.url = updated.imdbId; this.result.overview = updated.overview; diff --git a/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.ts b/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.ts index b32b9e718..1c39f000d 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/carousel-list/carousel-list.component.ts @@ -10,6 +10,7 @@ export enum DiscoverType { Upcoming, Trending, Popular, + RecentlyRequested, } @Component({ @@ -216,6 +217,8 @@ export class CarouselListComponent implements OnInit { case DiscoverType.Upcoming: this.movies = await this.searchService.upcomingMoviesByPage(this.currentlyLoaded, this.amountToLoad); break + case DiscoverType.RecentlyRequested: + this.movies = await this.searchService.recentlyRequestedMoviesByPage(this.currentlyLoaded, this.amountToLoad); } this.currentlyLoaded += this.amountToLoad; } @@ -290,7 +293,7 @@ export class CarouselListComponent implements OnInit { this.tvShows.forEach(m => { tempResults.push({ available: m.available, - posterPath: "../../../images/default_tv_poster.png", + posterPath: m.backdropPath ? `https://image.tmdb.org/t/p/w500/${m.backdropPath}` : "../../../images/default_tv_poster.png", requested: m.requested, title: m.title, type: RequestType.tvShow, diff --git a/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.html b/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.html index 77083a436..fd114128e 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.html @@ -1,8 +1,6 @@
-
-
-

Popular

+

{{'Discovery.PopularTab' | translate}}

@@ -10,7 +8,7 @@
-

Trending

+

{{'Discovery.TrendingTab' | translate}}

@@ -18,10 +16,15 @@
-

Upcoming

+

{{'Discovery.UpcomingTab' | translate}}

-
+
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.ts b/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.ts index 7b4fc291b..f9af8c573 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/discover/discover.component.ts @@ -1,344 +1,15 @@ -import { Component, OnInit, Inject } from "@angular/core"; -import { SearchV2Service } from "../../../services"; -import { ISearchMovieResult, ISearchTvResult, RequestType } from "../../../interfaces"; -import { IDiscoverCardResult, DiscoverOption, DisplayOption } from "../../interfaces"; -import { trigger, transition, style, animate } from "@angular/animations"; -import { StorageService } from "../../../shared/storage/storage-service"; -import { DOCUMENT } from "@angular/common"; -import { ISearchTvResultV2 } from "../../../interfaces/ISearchTvResultV2"; +import { Component } from "@angular/core"; import { DiscoverType } from "../carousel-list/carousel-list.component"; @Component({ templateUrl: "./discover.component.html", styleUrls: ["./discover.component.scss"], - animations: [ - trigger('slideIn', [ - transition(':enter', [ - style({ transform: 'translateX(100%)' }), - animate('200ms ease-in', style({ transform: 'translateY(0%)' })) - ]) - ]) - ], }) -export class DiscoverComponent implements OnInit { - - public upcomingMovies: IDiscoverCardResult[] = []; - public trendingMovies: IDiscoverCardResult[] = []; +export class DiscoverComponent { - public discoverResults: IDiscoverCardResult[] = []; - public movies: ISearchMovieResult[] = []; - public tvShows: ISearchTvResult[] = []; - - public discoverOptions: DiscoverOption = DiscoverOption.Combined; public DiscoverType = DiscoverType; - public DiscoverOption = DiscoverOption; - public displayOption: DisplayOption = DisplayOption.Card; - public DisplayOption = DisplayOption; - public defaultTvPoster: string; + constructor() { } - public popularActive: boolean = true; - public trendingActive: boolean; - public upcomingActive: boolean; - - public loadingFlag: boolean; - public scrollDisabled: boolean; - - private amountToLoad = 14; - - private contentLoaded: number; - private isScrolling: boolean = false; - private mediaTypeStorageKey = "DiscoverOptions"; - private displayOptionsKey = "DiscoverDisplayOptions"; - - - - constructor(private searchService: SearchV2Service, - private storageService: StorageService, - @Inject(DOCUMENT) private container: Document) { } - - - public async ngOnInit() { - this.loading() - // this.upcomingMovies = this.mapTvModel(await this.searchService.popularTvByPage(0, 14)); - // this.trendingMovies = this.mapMovieModel(await this.searchService.popularMoviesByPage(0, 14)); -this.finishLoading(); - // const localDiscoverOptions = +this.storageService.get(this.mediaTypeStorageKey); - // if (localDiscoverOptions) { - // this.discoverOptions = DiscoverOption[DiscoverOption[localDiscoverOptions]]; - // } - // const localDisplayOptions = +this.storageService.get(this.displayOptionsKey); - // if (localDisplayOptions) { - // this.displayOption = DisplayOption[DisplayOption[localDisplayOptions]]; - // } - // this.scrollDisabled = true; - // switch (this.discoverOptions) { - // case DiscoverOption.Combined: - // this.movies = await this.searchService.popularMoviesByPage(0, this.amountToLoad); - // this.tvShows = await this.searchService.popularTvByPage(0, this.amountToLoad); - // break; - // case DiscoverOption.Movie: - // this.movies = await this.searchService.popularMoviesByPage(0, this.amountToLoad); - // break; - // case DiscoverOption.Tv: - // this.tvShows = await this.searchService.popularTvByPage(0, this.amountToLoad); - // break; - // } - - // this.contentLoaded = this.amountToLoad; - - // this.createInitialModel(); - // this.scrollDisabled = false; - // if (!this.containerHasScrollBar()) { - // await this.onScroll(); - // } - } - - public async onScroll() { - console.log("scrolled"); - if (!this.contentLoaded) { - return; - } - if (!this.isScrolling) { - this.isScrolling = true; - this.loading(); - if (this.popularActive) { - switch (this.discoverOptions) { - case DiscoverOption.Combined: - this.movies = await this.searchService.popularMoviesByPage(this.contentLoaded, this.amountToLoad); - this.tvShows = await this.searchService.popularTvByPage(this.contentLoaded, this.amountToLoad); - break; - case DiscoverOption.Movie: - this.movies = await this.searchService.popularMoviesByPage(this.contentLoaded, this.amountToLoad); - break; - case DiscoverOption.Tv: - this.tvShows = await this.searchService.popularTvByPage(this.contentLoaded, this.amountToLoad); - break; - } - } - if (this.trendingActive) { - switch (this.discoverOptions) { - case DiscoverOption.Combined: - this.movies = await this.searchService.nowPlayingMoviesByPage(this.contentLoaded, this.amountToLoad); - this.tvShows = await this.searchService.trendingTvByPage(this.contentLoaded, this.amountToLoad); - break; - case DiscoverOption.Movie: - this.movies = await this.searchService.nowPlayingMoviesByPage(this.contentLoaded, this.amountToLoad); - break; - case DiscoverOption.Tv: - this.tvShows = await this.searchService.trendingTvByPage(this.contentLoaded, this.amountToLoad); - break; - } - } - if (this.upcomingActive) { - switch (this.discoverOptions) { - case DiscoverOption.Combined: - this.movies = await this.searchService.upcomingMoviesByPage(this.contentLoaded, this.amountToLoad); - this.tvShows = await this.searchService.anticipatedTvByPage(this.contentLoaded, this.amountToLoad); - break; - case DiscoverOption.Movie: - this.movies = await this.searchService.upcomingMoviesByPage(this.contentLoaded, this.amountToLoad); - break; - case DiscoverOption.Tv: - this.tvShows = await this.searchService.anticipatedTvByPage(this.contentLoaded, this.amountToLoad); - break; - } - } - this.contentLoaded += 12; - - this.createModel(); - this.isScrolling = false; - } - } - - public async popular() { - this.clear(); - this.scrollDisabled = true; - this.isScrolling = false; - this.contentLoaded = 12; - this.loading() - this.popularActive = true; - this.trendingActive = false; - this.upcomingActive = false; - switch (this.discoverOptions) { - case DiscoverOption.Combined: - this.movies = await this.searchService.popularMoviesByPage(0, this.amountToLoad); - this.tvShows = await this.searchService.popularTvByPage(0, this.amountToLoad); - break; - case DiscoverOption.Movie: - this.movies = await this.searchService.popularMoviesByPage(0, this.amountToLoad); - break; - case DiscoverOption.Tv: - this.tvShows = await this.searchService.popularTvByPage(0, this.amountToLoad); - break; - } - - this.createModel(); - this.scrollDisabled = false; - } - - public async trending() { - this.clear(); - - this.scrollDisabled = true; - this.isScrolling = false; - this.contentLoaded = 12; - this.loading() - this.popularActive = false; - this.trendingActive = true; - this.upcomingActive = false; - switch (this.discoverOptions) { - case DiscoverOption.Combined: - this.movies = await this.searchService.nowPlayingMoviesByPage(0, this.amountToLoad); - this.tvShows = await this.searchService.trendingTvByPage(0, this.amountToLoad); - break; - case DiscoverOption.Movie: - this.movies = await this.searchService.nowPlayingMoviesByPage(0, this.amountToLoad); - break; - case DiscoverOption.Tv: - this.tvShows = await this.searchService.trendingTvByPage(0, this.amountToLoad); - break; - } - - this.createModel(); - this.scrollDisabled = false; - } - - public async upcoming() { - this.clear(); - this.scrollDisabled = true; - this.isScrolling = false; - this.contentLoaded = 12; - this.loading() - this.popularActive = false; - this.trendingActive = false; - this.upcomingActive = true; - switch (this.discoverOptions) { - case DiscoverOption.Combined: - this.movies = await this.searchService.upcomingMoviesByPage(0, this.amountToLoad); - this.tvShows = await this.searchService.anticipatedTvByPage(0, this.amountToLoad); - break; - case DiscoverOption.Movie: - this.movies = await this.searchService.upcomingMoviesByPage(0, this.amountToLoad); - break; - case DiscoverOption.Tv: - this.tvShows = await this.searchService.anticipatedTvByPage(0, this.amountToLoad); - break; - } - - this.createModel(); - this.scrollDisabled = false; - } - - public async switchDiscoverMode(newMode: DiscoverOption) { - this.loading(); - this.clear(); - this.discoverOptions = newMode; - this.storageService.save(this.mediaTypeStorageKey, newMode.toString()); - await this.ngOnInit(); - this.finishLoading(); - } - - public changeView(view: DisplayOption) { - this.displayOption = view; - this.storageService.save(this.displayOptionsKey, view.toString()); - } - - private createModel() { - const tempResults = []; - - // switch (this.discoverOptions) { - // case DiscoverOption.Combined: - // tempResults.push(...this.mapMovieModel()); - // tempResults.push(...this.mapTvModel()); - // break; - // case DiscoverOption.Movie: - // tempResults.push(...this.mapMovieModel()); - // break; - // case DiscoverOption.Tv: - // tempResults.push(...this.mapTvModel()); - // break; - // } - - this.shuffle(tempResults); - this.discoverResults.push(...tempResults); - - this.finishLoading(); - } - - private mapMovieModel(movies: ISearchMovieResult[]): IDiscoverCardResult[] { - const tempResults = []; - movies.forEach(m => { - tempResults.push({ - available: m.available, - posterPath: m.posterPath ? `https://image.tmdb.org/t/p/w500/${m.posterPath}` : "../../../images/default_movie_poster.png", - requested: m.requested, - title: m.title, - type: RequestType.movie, - id: m.id, - url: `http://www.imdb.com/title/${m.imdbId}/`, - rating: m.voteAverage, - overview: m.overview, - approved: m.approved, - imdbid: m.imdbId, - denied: false, - background: m.backdropPath - }); - }); - return tempResults; - } - - private mapTvModel(tv: ISearchTvResult[]): IDiscoverCardResult[] { - const tempResults = []; - tv.forEach(m => { - tempResults.push({ - available: m.available, - posterPath: "../../../images/default_tv_poster.png", - requested: m.requested, - title: m.title, - type: RequestType.tvShow, - id: m.id, - url: undefined, - rating: +m.rating, - overview: m.overview, - approved: m.approved || m.partlyAvailable, - imdbid: m.imdbId, - denied: false, - background: m.background - }); - }); - return tempResults; - } - - private createInitialModel() { - this.clear(); - this.createModel(); - } - - private shuffle(discover: IDiscoverCardResult[]): IDiscoverCardResult[] { - for (let i = discover.length - 1; i > 0; i--) { - const j = Math.floor(Math.random() * (i + 1)); - [discover[i], discover[j]] = [discover[j], discover[i]]; - } - return discover; - } - - private loading() { - this.loadingFlag = true; - } - - private clear() { - this.discoverResults = []; - } - - private finishLoading() { - this.loadingFlag = false; - } - - private containerHasScrollBar(): boolean { - return this.container.documentElement.scrollHeight > this.container.documentElement.clientHeight; - // div.scrollHeight > div.clientHeight; - // this.container.documentElement.scrollHeight > (window.innerHeight + window.pageYOffset); - } } diff --git a/src/Ombi/ClientApp/src/app/discover/components/index.ts b/src/Ombi/ClientApp/src/app/discover/components/index.ts index c0f3a7141..0eb0ca3fb 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/index.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/index.ts @@ -23,11 +23,6 @@ export const components: any[] = [ CarouselListComponent, ]; - -export const entryComponents: any[] = [ - DiscoverCardDetailsComponent -]; - export const providers: any[] = [ SearchService, MatDialog, diff --git a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html index 5a8ad4b42..fb836a105 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html +++ b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.html @@ -2,14 +2,14 @@
-
-
+
+
-
-

{{'Discovery.NoSearch' | translate}}

+
+

{{'Discovery.NoSearch' | translate}}

\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.ts b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.ts index 0b2aa2030..6637b9e07 100644 --- a/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.ts +++ b/src/Ombi/ClientApp/src/app/discover/components/search-results/search-results.component.ts @@ -87,7 +87,7 @@ export class DiscoverSearchResultsComponent implements OnInit { id: m.id, url: "", rating: 0, - overview: "", + overview: m.overview, approved: false, imdbid: "", denied: false, diff --git a/src/Ombi/ClientApp/src/app/discover/discover.module.ts b/src/Ombi/ClientApp/src/app/discover/discover.module.ts index 931a0861b..2514f0636 100644 --- a/src/Ombi/ClientApp/src/app/discover/discover.module.ts +++ b/src/Ombi/ClientApp/src/app/discover/discover.module.ts @@ -24,9 +24,6 @@ import * as fromComponents from './components'; declarations: [ ...fromComponents.components ], - entryComponents: [ - ...fromComponents.entryComponents - ], exports: [ RouterModule, ], diff --git a/src/Ombi/ClientApp/src/app/interfaces/ICommon.ts b/src/Ombi/ClientApp/src/app/interfaces/ICommon.ts index 13a91af6c..76ce43a4b 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ICommon.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ICommon.ts @@ -28,6 +28,7 @@ export interface IUsersModel { } export interface INavBar { + id: string; icon: string; faIcon: string; name: string; diff --git a/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts b/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts index 1499c8b88..495563c36 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/IRequestModel.ts @@ -100,6 +100,7 @@ export interface IBaseRequest { export interface ITvRequests { id: number; imdbId: string; + externalProviderId: number; rootFolder: number; overview: string; title: string; @@ -111,7 +112,8 @@ export interface ITvRequests { qualityOverride: number; background: any; totalSeasons: number; - tvDbId: number; + tvDbId: number; // NO LONGER USED + open: boolean; // THIS IS FOR THE UI // For UI display @@ -146,6 +148,7 @@ export enum OrderType { export interface INewSeasonRequests { id: number; + overview: string; seasonNumber: number; episodes: IEpisodesRequests[]; seasonAvailable: boolean; diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResult.ts b/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResult.ts index 70216896c..ecdbcb80e 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResult.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISearchMovieResult.ts @@ -40,6 +40,7 @@ export interface IMultiSearchResult { mediaType: string; title: string; poster: string; + overview: string; } export interface ILanguageRefine { diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResult.ts b/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResult.ts index 78438a079..2a5b3742e 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResult.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResult.ts @@ -36,16 +36,21 @@ export interface ISearchTvResult { subscribed: boolean; showSubscribe: boolean; fullyAvailable: boolean; + backdropPath: string; partlyAvailable: boolean; background: any; open: boolean; // THIS IS FOR THE UI } -export interface ITvRequestViewModel { +export interface ITvRequestViewModelV2 extends ITvRequestViewModelBase { + theMovieDbId: number; +} + + +export interface ITvRequestViewModelBase { requestAll: boolean; firstSeason: boolean; latestSeason: boolean; - tvDbId: number; seasons: ISeasonsViewModel[]; requestOnBehalf: string | undefined; } diff --git a/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts b/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts index ef48adc21..8ea7bacc5 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResultV2.ts @@ -1,4 +1,5 @@ import { INewSeasonRequests, RequestType } from "./IRequestModel"; +import { IExternalIds, IGenresViewModel, IKeywords } from "./ISearchMovieResultV2"; export interface ISearchTvResultV2 { id: number; @@ -11,7 +12,7 @@ export interface ISearchTvResultV2 { firstAired: string; networkId: string; runtime: string; - genre: string[]; + genres: IGenresViewModel[], overview: string; lastUpdated: number; airsDayOfWeek: string; @@ -21,7 +22,6 @@ export interface ISearchTvResultV2 { siteRating: number; trailer: string; homepage: string; - certification: string; seasonRequests: INewSeasonRequests[]; requestAll: boolean; approved: boolean; @@ -30,6 +30,7 @@ export interface ISearchTvResultV2 { plexUrl: string; embyUrl: string; jellyfinUrl: string; + tagline: string; quality: string; firstSeason: boolean; latestSeason: boolean; @@ -38,8 +39,10 @@ export interface ISearchTvResultV2 { showSubscribe: boolean; fullyAvailable: boolean; partlyAvailable: boolean; + externalIds: IExternalIds; network: INetwork; images: IImagesV2; + keywords: IKeywords; cast: ICast[]; crew: ICrew[]; requestId: number; diff --git a/src/Ombi/ClientApp/src/app/media-details/components/index.ts b/src/Ombi/ClientApp/src/app/media-details/components/index.ts index e8cb89d4a..6799a8f74 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/index.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/index.ts @@ -45,15 +45,6 @@ export const components: any[] = [ TvRequestGridComponent, ]; -export const entryComponents: any[] = [ - YoutubeTrailerComponent, - DenyDialogComponent, - MovieAdvancedOptionsComponent, - TvAdvancedOptionsComponent, - NewIssueComponent, - RequestBehalfComponent, -]; - export const providers: any[] = [ SearchService, RequestService, diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html index f41884170..92eb37af4 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.html @@ -42,31 +42,31 @@
- - {{'Search.ViewOnPlex' | translate}} + + {{'Search.ViewOnPlex' | translate}} - - {{'Search.ViewOnEmby' | translate}} + + {{'Search.ViewOnEmby' | translate}} - - {{'Search.ViewOnJellyfin' | translate}} + + {{'Search.ViewOnJellyfin' | translate}} - - - - - - - -
diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts index 97cc75802..b493edae1 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/movie-details.component.ts @@ -107,10 +107,8 @@ export class MovieDetailsComponent { }); dialogRef.afterClosed().subscribe(result => { - this.movieRequest.denied = result; - if (this.movieRequest.denied) { - this.movie.approved = false; - } + this.movieRequest.denied = result.denied; + this.movieRequest.deniedReason = result.reason; }); } diff --git a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html index b14e2d44a..7af4dd802 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/movie/panels/movie-information-panel.component.html @@ -2,16 +2,16 @@
- {{movie.voteAverage | number:'1.0-1'}}/10 + {{movie.voteAverage | number:'1.0-1'}}/10 + src="{{baseUrl}}images/{{ratings.critics_rating === 'Rotten' ? 'rotten-rotten.svg' : 'rotten-fresh.svg'}}"> {{ratings.critics_score}}% + src="{{baseUrl}}images/{{ratings.audience_rating === 'Upright' ? 'rotten-audience-fresh.svg' : 'rotten-audience-rotten.svg'}}"> {{ratings.audience_score}}%
@@ -53,6 +53,11 @@ {{request.requestedDate | date}}
+
+ {{'Requests.DeniedReason' | translate }}: + {{request.deniedReason}} +
+
{{'MediaDetails.Quality' | translate }}: diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.html index 4a986a684..49875514d 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/cast-carousel/cast-carousel.component.html @@ -5,22 +5,21 @@ diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.html index 6235d5fe6..654f3a4a5 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.html @@ -1,10 +1,10 @@

{{ 'Requests.DenyReason' | translate}}

- +
- - + +
\ No newline at end of file diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts b/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts index 8ead47144..4e6257b3f 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/deny-dialog/deny-dialog.component.ts @@ -1,4 +1,4 @@ -import { Component, Inject, Output, EventEmitter } from "@angular/core"; +import { Component, Inject } from "@angular/core"; import { IDenyDialogData } from "../interfaces/interfaces"; import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; import { RequestService, MessageService } from "../../../../services"; @@ -36,8 +36,8 @@ export class DenyDialogComponent { this.messageService.send(result.errorMessage, "Ok"); this.data.denied = false; } - - this.dialogRef.close(); + + this.dialogRef.close({denied: this.data.denied, reason: this.denyReason}); } onNoClick(): void { diff --git a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html index c49b52e1c..7e2caf4f8 100644 --- a/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html +++ b/src/Ombi/ClientApp/src/app/media-details/components/shared/social-icons/social-icons.component.html @@ -1,8 +1,9 @@