mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-16 02:02:55 -07:00
Got most of it working!
This commit is contained in:
parent
be50b1eff1
commit
3aa07aa7a6
32 changed files with 577 additions and 75 deletions
|
@ -5,19 +5,19 @@ steps:
|
||||||
packageType: 'sdk'
|
packageType: 'sdk'
|
||||||
version: '5.x'
|
version: '5.x'
|
||||||
|
|
||||||
- task: DotNetCoreInstaller@1
|
# - task: DotNetCoreInstaller@1
|
||||||
displayName: 'Use .NET Core sdk for versioning'
|
# displayName: 'Use .NET Core sdk for versioning'
|
||||||
inputs:
|
# inputs:
|
||||||
packageType: 'sdk'
|
# packageType: 'sdk'
|
||||||
version: '3.1.x'
|
# version: '3.1.x'
|
||||||
|
|
||||||
- task: PowerShell@2
|
# - task: PowerShell@2
|
||||||
displayName: 'Set Version'
|
# displayName: 'Set Version'
|
||||||
inputs:
|
# inputs:
|
||||||
targetType: 'inline'
|
# targetType: 'inline'
|
||||||
script: |
|
# script: |
|
||||||
dotnet tool install -g dotnet-setversion
|
# dotnet tool install -g dotnet-setversion
|
||||||
setversion -r $(BuildVersion)
|
# setversion -r $(BuildVersion)
|
||||||
|
|
||||||
- task: DotNetCoreCLI@2
|
- task: DotNetCoreCLI@2
|
||||||
displayName: 'publish $(runtime)'
|
displayName: 'publish $(runtime)'
|
||||||
|
|
BIN
Tools/nuget.exe
BIN
Tools/nuget.exe
Binary file not shown.
|
@ -86,12 +86,16 @@ namespace Ombi.Api
|
||||||
_handler = await GetHandler();
|
_handler = await GetHandler();
|
||||||
}
|
}
|
||||||
_client = new HttpClient(_handler);
|
_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<HttpMessageHandler> GetHandler()
|
private async Task<HttpMessageHandler> GetHandler()
|
||||||
{
|
{
|
||||||
|
if (_cache == null)
|
||||||
|
{
|
||||||
|
return new HttpClientHandler();
|
||||||
|
}
|
||||||
var settings = await _cache.GetOrAdd(CacheKeys.OmbiSettings, async () => await _settings.GetSettingsAsync(), DateTime.Now.AddHours(1));
|
var settings = await _cache.GetOrAdd(CacheKeys.OmbiSettings, async () => await _settings.GetSettingsAsync(), DateTime.Now.AddHours(1));
|
||||||
if (settings.IgnoreCertificateErrors)
|
if (settings.IgnoreCertificateErrors)
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,8 +69,8 @@ namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
var allResults = await TvRepository.Get().ToListAsync();
|
var allResults = await TvRepository.Get().ToListAsync();
|
||||||
|
|
||||||
var distinctResults = allResults.DistinctBy(x => x.TvDbId);
|
var distinctResults = allResults.DistinctBy(x => x.ExternalProviderId);
|
||||||
_dbTv = distinctResults.ToDictionary(x => x.TvDbId);
|
_dbTv = distinctResults.ToDictionary(x => x.ExternalProviderId);
|
||||||
_cacheTime = now;
|
_cacheTime = now;
|
||||||
}
|
}
|
||||||
return _dbTv;
|
return _dbTv;
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
Task RemoveTvRequest(int requestId);
|
Task RemoveTvRequest(int requestId);
|
||||||
Task<TvRequests> GetTvRequest(int requestId);
|
Task<TvRequests> GetTvRequest(int requestId);
|
||||||
Task<RequestEngineResult> RequestTvShow(TvRequestViewModel tv);
|
Task<RequestEngineResult> RequestTvShow(TvRequestViewModel tv);
|
||||||
|
Task<RequestEngineResult> RequestTvShow(TvRequestViewModelV2 tv);
|
||||||
Task<RequestEngineResult> DenyChildRequest(int requestId, string reason);
|
Task<RequestEngineResult> DenyChildRequest(int requestId, string reason);
|
||||||
Task<RequestsViewModel<TvRequests>> GetRequestsLite(int count, int position, OrderFilterModel type);
|
Task<RequestsViewModel<TvRequests>> GetRequestsLite(int count, int position, OrderFilterModel type);
|
||||||
Task<IEnumerable<TvRequests>> SearchTvRequest(string search);
|
Task<IEnumerable<TvRequests>> SearchTvRequest(string search);
|
||||||
|
|
|
@ -148,6 +148,106 @@ namespace Ombi.Core.Engine
|
||||||
return await AddRequest(newRequest.NewRequest, tv.RequestOnBehalf);
|
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)
|
public async Task<RequestsViewModel<TvRequests>> GetRequests(int count, int position, OrderFilterModel type)
|
||||||
{
|
{
|
||||||
var shouldHide = await HideFromOtherUsers();
|
var shouldHide = await HideFromOtherUsers();
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace Ombi.Core.Engine.V2
|
||||||
new ExtraParams
|
new ExtraParams
|
||||||
{
|
{
|
||||||
Overview = e.Season?.ChildRequest?.ParentRequest?.Overview ?? string.Empty,
|
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,
|
Type = RequestType.TvShow,
|
||||||
ReleaseDate = e.AirDate,
|
ReleaseDate = e.AirDate,
|
||||||
RequestStatus = e.RequestStatus
|
RequestStatus = e.RequestStatus
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace Ombi.Core.Engine.V2
|
||||||
public async Task<SearchFullInfoTvShowViewModel> GetShowByRequest(int requestId, CancellationToken token)
|
public async Task<SearchFullInfoTvShowViewModel> GetShowByRequest(int requestId, CancellationToken token)
|
||||||
{
|
{
|
||||||
var request = await RequestService.TvRequestService.Get().FirstOrDefaultAsync(x => x.Id == requestId);
|
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)
|
public async Task<SearchFullInfoTvShowViewModel> GetShowInformation(string tvdbid, CancellationToken token)
|
||||||
|
|
|
@ -41,7 +41,8 @@ namespace Ombi.Core.Helpers
|
||||||
{
|
{
|
||||||
ShowInfo = await TvApi.ShowLookupByTheTvDbId(id);
|
ShowInfo = await TvApi.ShowLookupByTheTvDbId(id);
|
||||||
Results = await MovieDbApi.SearchTv(ShowInfo.name);
|
Results = await MovieDbApi.SearchTv(ShowInfo.name);
|
||||||
foreach (TvSearchResult result in Results) {
|
foreach (TvSearchResult result in Results)
|
||||||
|
{
|
||||||
if (result.Name.Equals(ShowInfo.name, StringComparison.InvariantCultureIgnoreCase))
|
if (result.Name.Equals(ShowInfo.name, StringComparison.InvariantCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
TheMovieDbRecord = result;
|
TheMovieDbRecord = result;
|
||||||
|
@ -61,7 +62,7 @@ namespace Ombi.Core.Helpers
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TvShowRequestBuilder CreateChild(TvRequestViewModel model, string userId)
|
public TvShowRequestBuilder CreateChild(TvRequestViewModel model, string userId)
|
||||||
{
|
{
|
||||||
ChildRequest = new ChildRequests
|
ChildRequest = new ChildRequests
|
||||||
|
|
247
src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs
Normal file
247
src/Ombi.Core/Helpers/TvShowRequestBuilderV2.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,17 +3,9 @@ using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Ombi.Core.Models.Requests
|
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 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
|
public class SeasonsViewModel
|
||||||
|
@ -27,4 +19,16 @@ namespace Ombi.Core.Models.Requests
|
||||||
public int EpisodeNumber { get; set; }
|
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; }
|
||||||
|
}
|
||||||
}
|
}
|
10
src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs
Normal file
10
src/Ombi.Core/Models/Requests/TvRequestViewModelV2.cs
Normal 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; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,8 +32,8 @@ namespace Ombi.Core.Rule.Rules.Request
|
||||||
|
|
||||||
var tvContent = _plexContent.GetAll().Include(x => x.Episodes).Where(x => x.Type == PlexMediaTypeEntity.Show);
|
var tvContent = _plexContent.GetAll().Include(x => x.Episodes).Where(x => x.Type == PlexMediaTypeEntity.Show);
|
||||||
// We need to do a check on the TVDBId
|
// 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
|
var anyMovieDbMatches = await tvContent.FirstOrDefaultAsync(x => x.TheMovieDbId.Length > 0 && x.TheMovieDbId == tvRequest.Id.ToString());
|
||||||
if (anyTvDbMatches == null)
|
if (anyMovieDbMatches == null)
|
||||||
{
|
{
|
||||||
// So we do not have a TVDB Id, that really sucks.
|
// So we do not have a TVDB Id, that really sucks.
|
||||||
// Let's try and match on the title and year of the show
|
// 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();
|
return Success();
|
||||||
}
|
}
|
||||||
// looks like we have a match on the TVDbID
|
// looks like we have a match on the TVDbID
|
||||||
return CheckExistingContent(tvRequest, anyTvDbMatches);
|
return CheckExistingContent(tvRequest, anyMovieDbMatches);
|
||||||
}
|
}
|
||||||
return Success();
|
return Success();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace Ombi.Core.Rule.Rules.Request
|
||||||
{
|
{
|
||||||
var tv = (ChildRequests) obj;
|
var tv = (ChildRequests) obj;
|
||||||
var tvRequests = Tv.GetChild();
|
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)
|
if (currentRequest == null)
|
||||||
{
|
{
|
||||||
return Success();
|
return Success();
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Ombi.Core.Rule.Rules
|
||||||
if (obj.RequestType == RequestType.TvShow)
|
if (obj.RequestType == RequestType.TvShow)
|
||||||
{
|
{
|
||||||
var vm = (ChildRequests) obj;
|
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 (result != null)
|
||||||
{
|
{
|
||||||
if (vm.SeasonRequests.Any())
|
if (vm.SeasonRequests.Any())
|
||||||
|
|
|
@ -140,7 +140,7 @@ namespace Ombi.Core.Senders
|
||||||
|
|
||||||
private async Task<DogNzbAddResult> SendToDogNzb(ChildRequests model, DogNzbSettings settings)
|
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());
|
return await DogNzbApi.AddTvShow(settings.ApiKey, id.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace Ombi.Notifications.Templates
|
||||||
if (string.IsNullOrEmpty(_templateLocation))
|
if (string.IsNullOrEmpty(_templateLocation))
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "netcoreapp3.1", "Templates",
|
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "bin", "Debug", "net5.0", "Templates",
|
||||||
"BasicTemplate.html");
|
"BasicTemplate.html");
|
||||||
#else
|
#else
|
||||||
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates","BasicTemplate.html");
|
_templateLocation = Path.Combine(Directory.GetCurrentDirectory(), "Templates","BasicTemplate.html");
|
||||||
|
|
|
@ -123,7 +123,7 @@ namespace Ombi.Notifications
|
||||||
{
|
{
|
||||||
LoadIssues(opts);
|
LoadIssues(opts);
|
||||||
RequestId = req?.Id.ToString();
|
RequestId = req?.Id.ToString();
|
||||||
ProviderId = req?.ParentRequest?.TvDbId.ToString() ?? string.Empty;
|
ProviderId = req?.ParentRequest?.ExternalProviderId.ToString() ?? string.Empty;
|
||||||
string title;
|
string title;
|
||||||
if (req == null)
|
if (req == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,6 +34,8 @@ using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Ombi.Api.Plex;
|
using Ombi.Api.Plex;
|
||||||
using Ombi.Api.Plex.Models;
|
using Ombi.Api.Plex.Models;
|
||||||
|
using Ombi.Api.TheMovieDb;
|
||||||
|
using Ombi.Api.TheMovieDb.Models;
|
||||||
using Ombi.Core.Settings;
|
using Ombi.Core.Settings;
|
||||||
using Ombi.Core.Settings.Models.External;
|
using Ombi.Core.Settings.Models.External;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
|
@ -49,8 +51,9 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
{
|
{
|
||||||
public class PlexContentSync : IPlexContentSync
|
public class PlexContentSync : IPlexContentSync
|
||||||
{
|
{
|
||||||
|
private readonly IMovieDbApi _movieApi;
|
||||||
public PlexContentSync(ISettingsService<PlexSettings> plex, IPlexApi plexApi, ILogger<PlexContentSync> logger, IPlexContentRepository repo,
|
public PlexContentSync(ISettingsService<PlexSettings> plex, IPlexApi plexApi, ILogger<PlexContentSync> logger, IPlexContentRepository repo,
|
||||||
IPlexEpisodeSync epsiodeSync, IHubContext<NotificationHub> hub)
|
IPlexEpisodeSync epsiodeSync, IHubContext<NotificationHub> hub, IMovieDbApi movieDbApi)
|
||||||
{
|
{
|
||||||
Plex = plex;
|
Plex = plex;
|
||||||
PlexApi = plexApi;
|
PlexApi = plexApi;
|
||||||
|
@ -58,6 +61,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
Repo = repo;
|
Repo = repo;
|
||||||
EpisodeSync = epsiodeSync;
|
EpisodeSync = epsiodeSync;
|
||||||
Notification = hub;
|
Notification = hub;
|
||||||
|
_movieApi = movieDbApi;
|
||||||
Plex.ClearCache();
|
Plex.ClearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +422,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
{
|
{
|
||||||
var showMetadata = await PlexApi.GetMetadata(servers.PlexAuthToken, servers.FullUri,
|
var showMetadata = await PlexApi.GetMetadata(servers.PlexAuthToken, servers.FullUri,
|
||||||
existingContent.Key);
|
existingContent.Key);
|
||||||
GetProviderIds(showMetadata, existingContent);
|
await GetProviderIds(showMetadata, existingContent);
|
||||||
|
|
||||||
await Repo.Update(existingContent);
|
await Repo.Update(existingContent);
|
||||||
}
|
}
|
||||||
|
@ -531,7 +535,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, show.ratingKey),
|
Url = PlexHelper.GetPlexMediaUrl(servers.MachineIdentifier, show.ratingKey),
|
||||||
Seasons = new List<PlexSeasonsContent>()
|
Seasons = new List<PlexSeasonsContent>()
|
||||||
};
|
};
|
||||||
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
|
// Let's just double check to make sure we do not have it now we have some id's
|
||||||
var existingImdb = false;
|
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 metadata = showMetadata.MediaContainer.Metadata.FirstOrDefault();
|
||||||
var guids = new List<string>
|
var guids = new List<string>
|
||||||
|
@ -601,6 +605,13 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
|
|
||||||
if (providerIds.TheTvDb.HasValue())
|
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;
|
existingContent.TvDbId = providerIds.TheTvDb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -683,6 +694,7 @@ namespace Ombi.Schedule.Jobs.Plex
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (_disposed)
|
if (_disposed)
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
{
|
{
|
||||||
public string BaseUrl { get; set; }
|
public string BaseUrl { get; set; }
|
||||||
public bool CollectAnalyticData { get; set; }
|
public bool CollectAnalyticData { get; set; }
|
||||||
public bool Set { get; set; }
|
|
||||||
public bool Wizard { get; set; }
|
public bool Wizard { get; set; }
|
||||||
public string ApiKey { get; set; }
|
public string ApiKey { get; set; }
|
||||||
public bool IgnoreCertificateErrors { get; set; }
|
public bool IgnoreCertificateErrors { get; set; }
|
||||||
|
@ -14,5 +13,9 @@
|
||||||
public string DefaultLanguageCode { get; set; } = "en";
|
public string DefaultLanguageCode { get; set; } = "en";
|
||||||
public bool AutoDeleteAvailableRequests { get; set; }
|
public bool AutoDeleteAvailableRequests { get; set; }
|
||||||
public int AutoDeleteAfterDays { get; set; }
|
public int AutoDeleteAfterDays { get; set; }
|
||||||
|
|
||||||
|
//INTERNAL
|
||||||
|
public bool HasMigratedOldTvDbData { get; set; }
|
||||||
|
public bool Set { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ namespace Ombi.Store.Repository.Requests
|
||||||
IQueryable<TvRequests> Get(string userId);
|
IQueryable<TvRequests> Get(string userId);
|
||||||
IQueryable<TvRequests> GetLite(string userId);
|
IQueryable<TvRequests> GetLite(string userId);
|
||||||
Task<TvRequests> GetRequestAsync(int tvDbId);
|
Task<TvRequests> GetRequestAsync(int tvDbId);
|
||||||
TvRequests GetRequest(int tvDbId);
|
TvRequests GetRequest(int theMovieDbId);
|
||||||
Task Update(TvRequests request);
|
Task Update(TvRequests request);
|
||||||
Task UpdateChild(ChildRequests request);
|
Task UpdateChild(ChildRequests request);
|
||||||
IQueryable<ChildRequests> GetChild();
|
IQueryable<ChildRequests> GetChild();
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Ombi.Store.Repository.Requests
|
||||||
|
|
||||||
public async Task<TvRequests> GetRequestAsync(int tvDbId)
|
public async Task<TvRequests> 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)
|
.Include(x => x.ChildRequests)
|
||||||
.ThenInclude(x => x.RequestedUser)
|
.ThenInclude(x => x.RequestedUser)
|
||||||
.Include(x => x.ChildRequests)
|
.Include(x => x.ChildRequests)
|
||||||
|
@ -29,9 +29,9 @@ namespace Ombi.Store.Repository.Requests
|
||||||
.FirstOrDefaultAsync();
|
.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)
|
.Include(x => x.ChildRequests)
|
||||||
.ThenInclude(x => x.RequestedUser)
|
.ThenInclude(x => x.RequestedUser)
|
||||||
.Include(x => x.ChildRequests)
|
.Include(x => x.ChildRequests)
|
||||||
|
|
|
@ -6,7 +6,12 @@
|
||||||
public object[] person_results { get; set; }
|
public object[] person_results { get; set; }
|
||||||
public TvResults[] tv_results { get; set; }
|
public TvResults[] tv_results { get; set; }
|
||||||
public object[] tv_episode_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
|
public class Movie_Results
|
||||||
|
|
|
@ -42,11 +42,15 @@ export interface ISearchTvResult {
|
||||||
open: boolean; // THIS IS FOR THE UI
|
open: boolean; // THIS IS FOR THE UI
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITvRequestViewModel {
|
export interface ITvRequestViewModelV2 extends ITvRequestViewModelBase {
|
||||||
|
theMovieDbId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface ITvRequestViewModelBase {
|
||||||
requestAll: boolean;
|
requestAll: boolean;
|
||||||
firstSeason: boolean;
|
firstSeason: boolean;
|
||||||
latestSeason: boolean;
|
latestSeason: boolean;
|
||||||
tvDbId: number;
|
|
||||||
seasons: ISeasonsViewModel[];
|
seasons: ISeasonsViewModel[];
|
||||||
requestOnBehalf: string | undefined;
|
requestOnBehalf: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
<div class="social-icons-container-inner">
|
<div class="social-icons-container-inner">
|
||||||
|
|
||||||
<a *ngIf="homepage" class="media-icons" href="{{homepage}}" target="_blank">
|
<a *ngIf="homepage" class="media-icons" href="{{homepage}}" target="_blank">
|
||||||
<i matTooltip="Homepage" class="sfa-home fa-2x grow-social"></i>
|
<i matTooltip="Homepage" class="sfa-home fa-2x grow-social"></i>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { Component, Input } from "@angular/core";
|
import { Component, Input } from "@angular/core";
|
||||||
import { IChildRequests, IEpisodesRequests, INewSeasonRequests, ISeasonsViewModel, ITvRequestViewModel, RequestType } from "../../../../../interfaces";
|
import { IChildRequests, IEpisodesRequests, INewSeasonRequests, ISeasonsViewModel, ITvRequestViewModelV2, RequestType } from "../../../../../interfaces";
|
||||||
import { RequestService } from "../../../../../services/request.service";
|
import { RequestService } from "../../../../../services/request.service";
|
||||||
import { MessageService } from "../../../../../services";
|
import { MessageService } from "../../../../../services";
|
||||||
import { DenyDialogComponent } from "../../../shared/deny-dialog/deny-dialog.component";
|
import { DenyDialogComponent } from "../../../shared/deny-dialog/deny-dialog.component";
|
||||||
import { ISearchTvResultV2 } from "../../../../../interfaces/ISearchTvResultV2";
|
import { ISearchTvResultV2 } from "../../../../../interfaces/ISearchTvResultV2";
|
||||||
import { MatDialog } from "@angular/material/dialog";
|
import { MatDialog } from "@angular/material/dialog";
|
||||||
import { SelectionModel } from "@angular/cdk/collections";
|
import { SelectionModel } from "@angular/cdk/collections";
|
||||||
|
import { RequestServiceV2 } from "../../../../../services/requestV2.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: "./tv-request-grid.component.html",
|
templateUrl: "./tv-request-grid.component.html",
|
||||||
|
@ -24,7 +25,7 @@ export class TvRequestGridComponent {
|
||||||
|
|
||||||
public displayedColumns: string[] = ['select', 'number', 'title', 'airDate', 'status'];
|
public displayedColumns: string[] = ['select', 'number', 'title', 'airDate', 'status'];
|
||||||
|
|
||||||
constructor(private requestService: RequestService, private notificationService: MessageService,
|
constructor(private requestService: RequestService, private requestServiceV2: RequestServiceV2, private notificationService: MessageService,
|
||||||
private dialog: MatDialog) {
|
private dialog: MatDialog) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -39,8 +40,8 @@ export class TvRequestGridComponent {
|
||||||
|
|
||||||
this.tv.requested = true;
|
this.tv.requested = true;
|
||||||
|
|
||||||
const viewModel = <ITvRequestViewModel>{
|
const viewModel = <ITvRequestViewModelV2>{
|
||||||
firstSeason: this.tv.firstSeason, latestSeason: this.tv.latestSeason, requestAll: this.tv.requestAll, tvDbId: this.tv.id,
|
firstSeason: this.tv.firstSeason, latestSeason: this.tv.latestSeason, requestAll: this.tv.requestAll, theMovieDbId: this.tv.id,
|
||||||
requestOnBehalf: null
|
requestOnBehalf: null
|
||||||
};
|
};
|
||||||
viewModel.seasons = [];
|
viewModel.seasons = [];
|
||||||
|
@ -57,7 +58,7 @@ export class TvRequestGridComponent {
|
||||||
viewModel.seasons.push(seasonsViewModel);
|
viewModel.seasons.push(seasonsViewModel);
|
||||||
});
|
});
|
||||||
|
|
||||||
const requestResult = await this.requestService.requestTv(viewModel).toPromise();
|
const requestResult = await this.requestServiceV2.requestTv(viewModel).toPromise();
|
||||||
|
|
||||||
if (requestResult.result) {
|
if (requestResult.result) {
|
||||||
this.notificationService.send(
|
this.notificationService.send(
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { Observable } from "rxjs";
|
||||||
import { UITreeNode } from "primeng/tree";
|
import { UITreeNode } from "primeng/tree";
|
||||||
import { FilterType, IAlbumRequest, IAlbumRequestModel, IAlbumUpdateModel, IChildRequests, IDenyAlbumModel, IDenyMovieModel, IFilter,
|
import { FilterType, IAlbumRequest, IAlbumRequestModel, IAlbumUpdateModel, IChildRequests, IDenyAlbumModel, IDenyMovieModel, IFilter,
|
||||||
IMovieRequestModel, IMovieRequests, IMovieUpdateModel, IRequestEngineResult, IRequestsViewModel, ITvDenyModel, ITvRequests, ITvUpdateModel, OrderType } from "../interfaces";
|
IMovieRequestModel, IMovieRequests, IMovieUpdateModel, IRequestEngineResult, IRequestsViewModel, ITvDenyModel, ITvRequests, ITvUpdateModel, OrderType } from "../interfaces";
|
||||||
import { ITvRequestViewModel } from "../interfaces";
|
|
||||||
import { ServiceHelpers } from "./service.helpers";
|
import { ServiceHelpers } from "./service.helpers";
|
||||||
|
|
||||||
import { IRemainingRequests } from "../interfaces/IRemainingRequests";
|
import { IRemainingRequests } from "../interfaces/IRemainingRequests";
|
||||||
|
@ -42,10 +41,6 @@ export class RequestService extends ServiceHelpers {
|
||||||
return this.http.get<number>(`${this.url}tv/total`, {headers: this.headers});
|
return this.http.get<number>(`${this.url}tv/total`, {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
||||||
public requestTv(tv: ITvRequestViewModel): Observable<IRequestEngineResult> {
|
|
||||||
return this.http.post<IRequestEngineResult>(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers});
|
|
||||||
}
|
|
||||||
|
|
||||||
public approveMovie(movie: IMovieUpdateModel): Observable<IRequestEngineResult> {
|
public approveMovie(movie: IMovieUpdateModel): Observable<IRequestEngineResult> {
|
||||||
return this.http.post<IRequestEngineResult>(`${this.url}Movie/Approve`, JSON.stringify(movie), {headers: this.headers});
|
return this.http.post<IRequestEngineResult>(`${this.url}Movie/Approve`, JSON.stringify(movie), {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { Injectable, Inject } from "@angular/core";
|
||||||
import { HttpClient } from "@angular/common/http";
|
import { HttpClient } from "@angular/common/http";
|
||||||
import { Observable } from "rxjs";
|
import { Observable } from "rxjs";
|
||||||
import { ServiceHelpers } from "./service.helpers";
|
import { ServiceHelpers } from "./service.helpers";
|
||||||
import { IRequestsViewModel, IMovieRequests, IChildRequests, IMovieAdvancedOptions as IMediaAdvancedOptions, IRequestEngineResult, IAlbumRequest } from "../interfaces";
|
import { IRequestsViewModel, IMovieRequests, IChildRequests, IMovieAdvancedOptions as IMediaAdvancedOptions, IRequestEngineResult, IAlbumRequest, ITvRequestViewModelV2 } from "../interfaces";
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -88,4 +88,8 @@ export class RequestServiceV2 extends ServiceHelpers {
|
||||||
public getAlbumDeniedRequests(count: number, position: number, sortProperty: string , order: string): Observable<IRequestsViewModel<IAlbumRequest>> {
|
public getAlbumDeniedRequests(count: number, position: number, sortProperty: string , order: string): Observable<IRequestsViewModel<IAlbumRequest>> {
|
||||||
return this.http.get<IRequestsViewModel<IAlbumRequest>>(`${this.url}Album/denied/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers});
|
return this.http.get<IRequestsViewModel<IAlbumRequest>>(`${this.url}Album/denied/${count}/${position}/${sortProperty}/${order}`, {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public requestTv(tv: ITvRequestViewModelV2): Observable<IRequestEngineResult> {
|
||||||
|
return this.http.post<IRequestEngineResult>(`${this.url}TV/`, JSON.stringify(tv), {headers: this.headers});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Component, OnInit, Inject } from "@angular/core";
|
import { Component, Inject } from "@angular/core";
|
||||||
import { MatCheckboxChange } from "@angular/material/checkbox";
|
import { MatCheckboxChange } from "@angular/material/checkbox";
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
|
import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog";
|
||||||
import { ISearchTvResultV2 } from "../../interfaces/ISearchTvResultV2";
|
import { ISearchTvResultV2 } from "../../interfaces/ISearchTvResultV2";
|
||||||
import { RequestService, MessageService } from "../../services";
|
import { MessageService } from "../../services";
|
||||||
import { ITvRequestViewModel, ISeasonsViewModel, IEpisodesRequests, INewSeasonRequests } from "../../interfaces";
|
import { ISeasonsViewModel, IEpisodesRequests, INewSeasonRequests, ITvRequestViewModelV2 } from "../../interfaces";
|
||||||
import { ThousandShortPipe } from "../../pipes/ThousandShortPipe";
|
import { RequestServiceV2 } from "../../services/requestV2.service";
|
||||||
|
|
||||||
export interface EpisodeRequestData {
|
export interface EpisodeRequestData {
|
||||||
series: ISearchTvResultV2;
|
series: ISearchTvResultV2;
|
||||||
|
@ -21,7 +21,7 @@ export class EpisodeRequestComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(public dialogRef: MatDialogRef<EpisodeRequestComponent>, @Inject(MAT_DIALOG_DATA) public data: EpisodeRequestData,
|
constructor(public dialogRef: MatDialogRef<EpisodeRequestComponent>, @Inject(MAT_DIALOG_DATA) public data: EpisodeRequestData,
|
||||||
private requestService: RequestService, private notificationService: MessageService) { }
|
private requestService: RequestServiceV2, private notificationService: MessageService) { }
|
||||||
|
|
||||||
|
|
||||||
public async submitRequests() {
|
public async submitRequests() {
|
||||||
|
@ -31,7 +31,7 @@ export class EpisodeRequestComponent {
|
||||||
return ep.selected;
|
return ep.selected;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
debugger;
|
|
||||||
if (!selected && !this.data.series.requestAll && !this.data.series.firstSeason && !this.data.series.latestSeason) {
|
if (!selected && !this.data.series.requestAll && !this.data.series.firstSeason && !this.data.series.latestSeason) {
|
||||||
this.notificationService.send("You need to select some episodes!", "OK");
|
this.notificationService.send("You need to select some episodes!", "OK");
|
||||||
return;
|
return;
|
||||||
|
@ -39,8 +39,8 @@ export class EpisodeRequestComponent {
|
||||||
|
|
||||||
this.data.series.requested = true;
|
this.data.series.requested = true;
|
||||||
|
|
||||||
const viewModel = <ITvRequestViewModel>{
|
const viewModel = <ITvRequestViewModelV2>{
|
||||||
firstSeason: this.data.series.firstSeason, latestSeason: this.data.series.latestSeason, requestAll: this.data.series.requestAll, tvDbId: this.data.series.id,
|
firstSeason: this.data.series.firstSeason, latestSeason: this.data.series.latestSeason, requestAll: this.data.series.requestAll, theMovieDbId: this.data.series.id,
|
||||||
requestOnBehalf: this.data.requestOnBehalf
|
requestOnBehalf: this.data.requestOnBehalf
|
||||||
};
|
};
|
||||||
viewModel.seasons = [];
|
viewModel.seasons = [];
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Ombi.Core;
|
|
||||||
using Ombi.Core.Engine;
|
using Ombi.Core.Engine;
|
||||||
using Ombi.Core.Engine.Interfaces;
|
using Ombi.Core.Engine.Interfaces;
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Core.Models.Requests;
|
||||||
using Ombi.Core.Models.UI;
|
using Ombi.Core.Models.UI;
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
|
using System;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Ombi.Controllers.V2
|
namespace Ombi.Controllers.V2
|
||||||
{
|
{
|
||||||
|
@ -18,12 +20,17 @@ namespace Ombi.Controllers.V2
|
||||||
private readonly IMovieRequestEngine _movieRequestEngine;
|
private readonly IMovieRequestEngine _movieRequestEngine;
|
||||||
private readonly ITvRequestEngine _tvRequestEngine;
|
private readonly ITvRequestEngine _tvRequestEngine;
|
||||||
private readonly IMusicRequestEngine _musicRequestEngine;
|
private readonly IMusicRequestEngine _musicRequestEngine;
|
||||||
|
private readonly IVoteEngine _voteEngine;
|
||||||
|
private readonly ILogger<RequestsController> _logger;
|
||||||
|
|
||||||
public RequestsController(IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, IMusicRequestEngine musicRequestEngine)
|
public RequestsController(IMovieRequestEngine movieRequestEngine, ITvRequestEngine tvRequestEngine, IMusicRequestEngine musicRequestEngine,
|
||||||
|
IVoteEngine voteEngine, ILogger<RequestsController> logger)
|
||||||
{
|
{
|
||||||
_movieRequestEngine = movieRequestEngine;
|
_movieRequestEngine = movieRequestEngine;
|
||||||
_tvRequestEngine = tvRequestEngine;
|
_tvRequestEngine = tvRequestEngine;
|
||||||
_musicRequestEngine = musicRequestEngine;
|
_musicRequestEngine = musicRequestEngine;
|
||||||
|
_voteEngine = voteEngine;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -168,5 +175,41 @@ namespace Ombi.Controllers.V2
|
||||||
{
|
{
|
||||||
return await _musicRequestEngine.GetRequests(count, position, sort, sortOrder);
|
return await _musicRequestEngine.GetRequests(count, position, sort, sortOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Requests a tv show/episode/season.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tv">The tv.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("tv")]
|
||||||
|
public async Task<RequestEngineResult> RequestTv([FromBody] TvRequestViewModelV2 tv)
|
||||||
|
{
|
||||||
|
tv.RequestedByAlias = GetApiAlias();
|
||||||
|
var result = await _tvRequestEngine.RequestTvShow(tv);
|
||||||
|
if (result.Result)
|
||||||
|
{
|
||||||
|
var voteResult = await _voteEngine.UpVote(result.RequestId, RequestType.TvShow);
|
||||||
|
if (voteResult.IsError)
|
||||||
|
{
|
||||||
|
_logger.LogError("Couldn't automatically add the vote for the tv {0} because {1}", tv.TheMovieDbId, voteResult.ErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetApiAlias()
|
||||||
|
{
|
||||||
|
// Make sure this only applies when using the API KEY
|
||||||
|
if (HttpContext.Request.Headers.Keys.Contains("ApiKey", StringComparer.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
if (HttpContext.Request.Headers.TryGetValue("ApiAlias", out var apiAlias))
|
||||||
|
{
|
||||||
|
return apiAlias;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -17,6 +17,10 @@ using Newtonsoft.Json;
|
||||||
using Ombi.Settings.Settings.Models;
|
using Ombi.Settings.Settings.Models;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Ombi.Api.TheMovieDb;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Ombi.Api.TheMovieDb.Models;
|
||||||
|
|
||||||
namespace Ombi
|
namespace Ombi
|
||||||
{
|
{
|
||||||
|
@ -127,6 +131,9 @@ namespace Ombi
|
||||||
}
|
}
|
||||||
|
|
||||||
await SortOutBaseUrl(baseUrl, settingsDb, ombiSettingsContent);
|
await SortOutBaseUrl(baseUrl, settingsDb, ombiSettingsContent);
|
||||||
|
var httpClient = new Ombi.Api.OmbiHttpClient(null, null);
|
||||||
|
var api = new Ombi.Api.Api(new Logger<Api.Api>(NullLoggerFactory.Instance), httpClient);
|
||||||
|
await MigrateOldTvDbIds(ombiDb, ombiSettingsContent, settingsDb, new Ombi.Api.TheMovieDb.TheMovieDbApi(null, (Api.IApi)api, null));
|
||||||
|
|
||||||
Console.WriteLine($"We are running on {urlValue}");
|
Console.WriteLine($"We are running on {urlValue}");
|
||||||
|
|
||||||
|
@ -283,6 +290,70 @@ namespace Ombi
|
||||||
Console.WriteLine($"Wrote new baseurl at {indexPath}");
|
Console.WriteLine($"Wrote new baseurl at {indexPath}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task MigrateOldTvDbIds(OmbiContext ctx, GlobalSettings ombiSettingsContent, SettingsContext settingsContext, Api.TheMovieDb.TheMovieDbApi api)
|
||||||
|
{
|
||||||
|
var ombiSettings = JsonConvert.DeserializeObject<OmbiSettings>(ombiSettingsContent.Content);
|
||||||
|
if (ombiSettings.HasMigratedOldTvDbData)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tvRequests = ctx.TvRequests;
|
||||||
|
Console.WriteLine($"Total Requests to migrate {await tvRequests.CountAsync()}");
|
||||||
|
foreach (var request in tvRequests)
|
||||||
|
{
|
||||||
|
var findResuilt = await api.Find(request.TvDbId.ToString(), ExternalSource.tvdb_id);
|
||||||
|
|
||||||
|
var found = findResuilt.tv_results.FirstOrDefault();
|
||||||
|
|
||||||
|
if (found == null)
|
||||||
|
{
|
||||||
|
var seriesFound = findResuilt.tv_season_results.FirstOrDefault();
|
||||||
|
if (seriesFound == null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Cannot find TheMovieDb Record for request {request.Title}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
request.ExternalProviderId = seriesFound.show_id;
|
||||||
|
Console.WriteLine($"Cannot find TheMovieDb Record for request, found potential match Title: {request.Title}, Match: {seriesFound.show_id}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
request.ExternalProviderId = found.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Console.WriteLine($"Finished Migration");
|
||||||
|
|
||||||
|
var strat = ctx.Database.CreateExecutionStrategy();
|
||||||
|
await strat.ExecuteAsync(async () =>
|
||||||
|
{
|
||||||
|
using (var tran = await ctx.Database.BeginTransactionAsync())
|
||||||
|
{
|
||||||
|
ctx.TvRequests.UpdateRange(tvRequests);
|
||||||
|
await ctx.SaveChangesAsync();
|
||||||
|
await tran.CommitAsync();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var settingsStrat = settingsContext.Database.CreateExecutionStrategy();
|
||||||
|
await settingsStrat.ExecuteAsync(async () =>
|
||||||
|
{
|
||||||
|
using (var tran = await settingsContext.Database.BeginTransactionAsync())
|
||||||
|
{
|
||||||
|
ombiSettings.HasMigratedOldTvDbData = true;
|
||||||
|
|
||||||
|
ombiSettingsContent.Content = JsonConvert.SerializeObject(ombiSettings);
|
||||||
|
settingsContext.Update(ombiSettingsContent);
|
||||||
|
await settingsContext.SaveChangesAsync();
|
||||||
|
await tran.CommitAsync();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Options
|
public class Options
|
||||||
|
|
|
@ -148,7 +148,6 @@ namespace Ombi
|
||||||
// Generate a API Key
|
// Generate a API Key
|
||||||
settings.ApiKey = Guid.NewGuid().ToString("N");
|
settings.ApiKey = Guid.NewGuid().ToString("N");
|
||||||
settings.CollectAnalyticData = true; // Since this is a first setup, enable analytical data collection
|
settings.CollectAnalyticData = true; // Since this is a first setup, enable analytical data collection
|
||||||
settings.Set = true;
|
|
||||||
ombiService.SaveSettings(settings);
|
ombiService.SaveSettings(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,9 +156,6 @@ namespace Ombi
|
||||||
app.UsePathBase(settings.BaseUrl);
|
app.UsePathBase(settings.BaseUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup the scheduler
|
|
||||||
//var jobSetup = app.ApplicationServices.GetService<IJobSetup>();
|
|
||||||
//jobSetup.Setup();
|
|
||||||
ctx.Seed();
|
ctx.Seed();
|
||||||
var settingsctx = serviceProvider.GetService<SettingsContext>();
|
var settingsctx = serviceProvider.GetService<SettingsContext>();
|
||||||
settingsctx.Seed();
|
settingsctx.Seed();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue