Got most of it working!

This commit is contained in:
tidusjar 2021-03-06 23:13:44 +00:00
parent be50b1eff1
commit 3aa07aa7a6
32 changed files with 577 additions and 75 deletions

View file

@ -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;

View file

@ -13,6 +13,7 @@ namespace Ombi.Core.Engine.Interfaces
Task RemoveTvRequest(int requestId);
Task<TvRequests> GetTvRequest(int requestId);
Task<RequestEngineResult> RequestTvShow(TvRequestViewModel tv);
Task<RequestEngineResult> RequestTvShow(TvRequestViewModelV2 tv);
Task<RequestEngineResult> DenyChildRequest(int requestId, string reason);
Task<RequestsViewModel<TvRequests>> GetRequestsLite(int count, int position, OrderFilterModel type);
Task<IEnumerable<TvRequests>> SearchTvRequest(string search);

View file

@ -148,6 +148,106 @@ namespace Ombi.Core.Engine
return await AddRequest(newRequest.NewRequest, tv.RequestOnBehalf);
}
public async Task<RequestEngineResult> 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<RequestsViewModel<TvRequests>> GetRequests(int count, int position, OrderFilterModel type)
{
var shouldHide = await HideFromOtherUsers();

View file

@ -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

View file

@ -46,7 +46,7 @@ namespace Ombi.Core.Engine.V2
public async Task<SearchFullInfoTvShowViewModel> 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<SearchFullInfoTvShowViewModel> GetShowInformation(string tvdbid, CancellationToken token)

View file

@ -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

View file

@ -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<SeasonsViewModel> 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<TvShowRequestBuilderV2> 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<SeasonRequests>(),
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<SeasonsViewModel>();
// 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<TvShowRequestBuilderV2> BuildEpisodes(TvRequestViewModelV2 tv)
{
var allEpisodes = new List<Episode>();
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<EpisodeRequests>{
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<EpisodeRequests>();
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<EpisodeRequests>();
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<SeasonRequests>();
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<ChildRequests>(),
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);
}
}
}

View file

@ -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<SeasonsViewModel> Seasons { get; set; } = new List<SeasonsViewModel>();
[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<SeasonsViewModel> Seasons { get; set; } = new List<SeasonsViewModel>();
[JsonIgnore]
public string RequestedByAlias { get; set; }
public string RequestOnBehalf { get; set; }
}
}

View file

@ -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; }
}
}

View file

@ -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();
}

View file

@ -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();

View file

@ -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())

View file

@ -140,7 +140,7 @@ namespace Ombi.Core.Senders
private async Task<DogNzbAddResult> SendToDogNzb(ChildRequests model, DogNzbSettings settings)
{
var id = model.ParentRequest.TvDbId;
var id = model.ParentRequest.ExternalProviderId;
return await DogNzbApi.AddTvShow(settings.ApiKey, id.ToString());
}