diff --git a/.azuredevops/pipelines/templates/publish-os-steps.yml b/.azuredevops/pipelines/templates/publish-os-steps.yml index 2f63fa4a4..cfb14e579 100644 --- a/.azuredevops/pipelines/templates/publish-os-steps.yml +++ b/.azuredevops/pipelines/templates/publish-os-steps.yml @@ -5,19 +5,19 @@ steps: packageType: 'sdk' version: '5.x' -- task: DotNetCoreInstaller@1 - displayName: 'Use .NET Core sdk for versioning' - inputs: - packageType: 'sdk' - version: '3.1.x' +# - task: DotNetCoreInstaller@1 +# displayName: 'Use .NET Core sdk for versioning' +# inputs: +# packageType: 'sdk' +# version: '3.1.x' -- task: PowerShell@2 - displayName: 'Set Version' - inputs: - targetType: 'inline' - script: | - dotnet tool install -g dotnet-setversion - setversion -r $(BuildVersion) +# - task: PowerShell@2 +# displayName: 'Set Version' +# inputs: +# targetType: 'inline' +# script: | +# dotnet tool install -g dotnet-setversion +# setversion -r $(BuildVersion) - task: DotNetCoreCLI@2 displayName: 'publish $(runtime)' 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/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/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/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/TvSearchEngineV2.cs b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs index 64ca59fa1..5335fb0b7 100644 --- a/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs +++ b/src/Ombi.Core/Engine/V2/TvSearchEngineV2.cs @@ -46,7 +46,7 @@ namespace Ombi.Core.Engine.V2 public async Task GetShowByRequest(int requestId, CancellationToken token) { var request = await RequestService.TvRequestService.Get().FirstOrDefaultAsync(x => x.Id == requestId); - return await GetShowInformation(request.TvDbId.ToString(), token); // TODO + return await GetShowInformation(request.ExternalProviderId.ToString(), token); // TODO } public async Task GetShowInformation(string tvdbid, CancellationToken token) diff --git a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs index c1afc5112..39667eaca 100644 --- a/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs +++ b/src/Ombi.Core/Helpers/TvShowRequestBuilder.cs @@ -41,7 +41,8 @@ namespace Ombi.Core.Helpers { 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; @@ -61,7 +62,7 @@ namespace Ombi.Core.Helpers return this; } - + public TvShowRequestBuilder CreateChild(TvRequestViewModel model, string userId) { ChildRequest = new ChildRequests 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/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 da2e780e9..ddd8cd983 100644 --- a/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs +++ b/src/Ombi.Core/Rule/Rules/SonarrCacheRule.cs @@ -22,7 +22,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()) 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.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 0aea728a4..9edf9a820 100644 --- a/src/Ombi.Notifications/NotificationMessageCurlys.cs +++ b/src/Ombi.Notifications/NotificationMessageCurlys.cs @@ -123,7 +123,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/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/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/ClientApp/src/app/interfaces/ISearchTvResult.ts b/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResult.ts index eb4cc2e22..2a5b3742e 100644 --- a/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResult.ts +++ b/src/Ombi/ClientApp/src/app/interfaces/ISearchTvResult.ts @@ -42,11 +42,15 @@ export interface ISearchTvResult { 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/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 5613a7bf8..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,4 +1,5 @@