mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-11 07:46:05 -07:00
Damn son. So many changes... Fixed alot of stuff around tv episodes with the new DB model #865
This commit is contained in:
parent
1a7f81b16c
commit
0875b5f665
40 changed files with 340 additions and 874 deletions
|
@ -1,110 +1,110 @@
|
||||||
using System.Collections.Generic;
|
//using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
//using System.Threading.Tasks;
|
||||||
using Moq;
|
//using Moq;
|
||||||
using Ombi.Core.Models.Requests;
|
//using Ombi.Core.Models.Requests;
|
||||||
using Ombi.Core.Models.Requests.Movie;
|
//using Ombi.Core.Models.Requests.Movie;
|
||||||
using Ombi.Core.Models.Requests.Tv;
|
//using Ombi.Core.Models.Requests.Tv;
|
||||||
using Ombi.Core.Models.Search;
|
//using Ombi.Core.Models.Search;
|
||||||
using Ombi.Core.Requests.Models;
|
//using Ombi.Core.Requests.Models;
|
||||||
using Ombi.Core.Rule.Rules.Search;
|
//using Ombi.Core.Rule.Rules.Search;
|
||||||
using Xunit;
|
//using Xunit;
|
||||||
|
|
||||||
namespace Ombi.Core.Tests.Rule.Search
|
//namespace Ombi.Core.Tests.Rule.Search
|
||||||
{
|
//{
|
||||||
public class ExistignRequestRuleTests
|
// public class ExistignRequestRuleTests
|
||||||
{
|
// {
|
||||||
public ExistignRequestRuleTests()
|
// public ExistignRequestRuleTests()
|
||||||
{
|
// {
|
||||||
MovieMock = new Mock<IRequestService<MovieRequestModel>>();
|
// MovieMock = new Mock<IRequestService<MovieRequestModel>>();
|
||||||
TvMock = new Mock<IRequestService<TvRequestModel>>();
|
// TvMock = new Mock<IRequestService<TvRequestModel>>();
|
||||||
Rule = new ExistingRequestRule(MovieMock.Object, TvMock.Object);
|
// Rule = new ExistingRequestRule(MovieMock.Object, TvMock.Object);
|
||||||
}
|
// }
|
||||||
|
|
||||||
private ExistingRequestRule Rule { get; }
|
// private ExistingRequestRule Rule { get; }
|
||||||
private Mock<IRequestService<MovieRequestModel>> MovieMock { get; }
|
// private Mock<IRequestService<MovieRequestModel>> MovieMock { get; }
|
||||||
private Mock<IRequestService<TvRequestModel>> TvMock { get; }
|
// private Mock<IRequestService<TvRequestModel>> TvMock { get; }
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
// [Fact]
|
||||||
public async Task ShouldBe_Requested_WhenExisitngMovie()
|
// public async Task ShouldBe_Requested_WhenExisitngMovie()
|
||||||
{
|
// {
|
||||||
var list = new List<MovieRequestModel>{new MovieRequestModel
|
// var list = new List<MovieRequestModel>{new MovieRequestModel
|
||||||
{
|
// {
|
||||||
ProviderId = 123,
|
// ProviderId = 123,
|
||||||
Approved = true
|
// Approved = true
|
||||||
}};
|
// }};
|
||||||
MovieMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list);
|
// MovieMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list);
|
||||||
var search = new SearchMovieViewModel
|
// var search = new SearchMovieViewModel
|
||||||
{
|
// {
|
||||||
Id = 123,
|
// Id = 123,
|
||||||
|
|
||||||
};
|
// };
|
||||||
var result = await Rule.Execute(search);
|
// var result = await Rule.Execute(search);
|
||||||
|
|
||||||
Assert.True(result.Success);
|
// Assert.True(result.Success);
|
||||||
Assert.Equal(search.Approved, true);
|
// Assert.Equal(search.Approved, true);
|
||||||
}
|
// }
|
||||||
|
|
||||||
[Fact]
|
// [Fact]
|
||||||
public async Task ShouldBe_NotRequested_WhenNewMovie()
|
// public async Task ShouldBe_NotRequested_WhenNewMovie()
|
||||||
{
|
// {
|
||||||
var list = new List<MovieRequestModel>{new MovieRequestModel
|
// var list = new List<MovieRequestModel>{new MovieRequestModel
|
||||||
{
|
// {
|
||||||
ProviderId = 123,
|
// ProviderId = 123,
|
||||||
Approved = true
|
// Approved = true
|
||||||
}};
|
// }};
|
||||||
MovieMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list);
|
// MovieMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list);
|
||||||
var search = new SearchMovieViewModel
|
// var search = new SearchMovieViewModel
|
||||||
{
|
// {
|
||||||
Id = 999,
|
// Id = 999,
|
||||||
|
|
||||||
};
|
// };
|
||||||
var result = await Rule.Execute(search);
|
// var result = await Rule.Execute(search);
|
||||||
|
|
||||||
Assert.True(result.Success);
|
// Assert.True(result.Success);
|
||||||
Assert.Equal(search.Approved, false);
|
// Assert.Equal(search.Approved, false);
|
||||||
}
|
// }
|
||||||
|
|
||||||
[Fact]
|
// [Fact]
|
||||||
public async Task ShouldBe_Requested_WhenExisitngTv()
|
// public async Task ShouldBe_Requested_WhenExisitngTv()
|
||||||
{
|
// {
|
||||||
var list = new List<TvRequestModel>{new TvRequestModel
|
// var list = new List<TvRequestModel>{new TvRequestModel
|
||||||
{
|
// {
|
||||||
ProviderId = 123,
|
// ProviderId = 123,
|
||||||
Approved = true
|
// Approved = true
|
||||||
}};
|
// }};
|
||||||
TvMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list);
|
// TvMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list);
|
||||||
var search = new SearchTvShowViewModel
|
// var search = new SearchTvShowViewModel
|
||||||
{
|
// {
|
||||||
Id = 123,
|
// Id = 123,
|
||||||
|
|
||||||
};
|
// };
|
||||||
var result = await Rule.Execute(search);
|
// var result = await Rule.Execute(search);
|
||||||
|
|
||||||
Assert.True(result.Success);
|
// Assert.True(result.Success);
|
||||||
Assert.Equal(search.Approved, true);
|
// Assert.Equal(search.Approved, true);
|
||||||
}
|
// }
|
||||||
|
|
||||||
[Fact]
|
// [Fact]
|
||||||
public async Task ShouldBe_NotRequested_WhenNewTv()
|
// public async Task ShouldBe_NotRequested_WhenNewTv()
|
||||||
{
|
// {
|
||||||
var list = new List<TvRequestModel>{new TvRequestModel
|
// var list = new List<TvRequestModel>{new TvRequestModel
|
||||||
{
|
// {
|
||||||
ProviderId = 123,
|
// ProviderId = 123,
|
||||||
Approved = true
|
// Approved = true
|
||||||
}};
|
// }};
|
||||||
TvMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list);
|
// TvMock.Setup(x => x.GetAllAsync()).ReturnsAsync(list);
|
||||||
var search = new SearchTvShowViewModel()
|
// var search = new SearchTvShowViewModel()
|
||||||
{
|
// {
|
||||||
Id = 999,
|
// Id = 999,
|
||||||
|
|
||||||
};
|
// };
|
||||||
var result = await Rule.Execute(search);
|
// var result = await Rule.Execute(search);
|
||||||
|
|
||||||
Assert.True(result.Success);
|
// Assert.True(result.Success);
|
||||||
Assert.Equal(search.Approved, false);
|
// Assert.Equal(search.Approved, false);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
}
|
// }
|
||||||
}
|
//}
|
|
@ -1,19 +1,11 @@
|
||||||
using System;
|
using Ombi.Core.Claims;
|
||||||
using Ombi.Core.Claims;
|
|
||||||
using Ombi.Core.Models.Requests;
|
|
||||||
using Ombi.Core.Rule;
|
using Ombi.Core.Rule;
|
||||||
using Ombi.Core.Rules;
|
using Ombi.Core.Rules;
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Hangfire;
|
|
||||||
using Ombi.Core.Models.Requests.Movie;
|
|
||||||
using Ombi.Core.Models.Search;
|
using Ombi.Core.Models.Search;
|
||||||
using Ombi.Core.Notifications;
|
|
||||||
using Ombi.Helpers;
|
|
||||||
using Ombi.Notifications.Models;
|
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
|
|
||||||
namespace Ombi.Core.Engine.Interfaces
|
namespace Ombi.Core.Engine.Interfaces
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Core.Models.Requests;
|
|
||||||
using Ombi.Core.Models.Requests.Tv;
|
|
||||||
using Ombi.Core.Models.Search;
|
using Ombi.Core.Models.Search;
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
using Ombi.Api.TheMovieDb;
|
using Ombi.Api.TheMovieDb;
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Core.Models.Requests;
|
||||||
using Ombi.Core.Models.Requests.Movie;
|
|
||||||
using Ombi.Core.Models.Search;
|
using Ombi.Core.Models.Search;
|
||||||
using Ombi.Core.Rules;
|
using Ombi.Core.Rules;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using Ombi.Notifications;
|
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using Hangfire;
|
|
||||||
using Ombi.Api.TvMaze;
|
using Ombi.Api.TvMaze;
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Core.Models.Requests;
|
||||||
using Ombi.Core.Models.Search;
|
using Ombi.Core.Models.Search;
|
||||||
using Ombi.Core.Rules;
|
using Ombi.Core.Rules;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using Ombi.Notifications;
|
|
||||||
using Ombi.Notifications.Models;
|
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.Tracing;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
|
@ -18,7 +14,6 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Ombi.Core.Engine.Interfaces;
|
using Ombi.Core.Engine.Interfaces;
|
||||||
using Ombi.Core.IdentityResolver;
|
using Ombi.Core.IdentityResolver;
|
||||||
using Ombi.Core.Models.Requests.Tv;
|
|
||||||
using Ombi.Core.Rule;
|
using Ombi.Core.Rule;
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
using Ombi.Store.Repository.Requests;
|
using Ombi.Store.Repository.Requests;
|
||||||
|
@ -50,7 +45,7 @@ namespace Ombi.Core.Engine
|
||||||
// For some reason the poster path is always http
|
// For some reason the poster path is always http
|
||||||
var posterPath = showInfo.image?.medium.Replace("http:", "https:");
|
var posterPath = showInfo.image?.medium.Replace("http:", "https:");
|
||||||
|
|
||||||
var tvRequests = new List<SeasonRequestModel>();
|
var tvRequests = new List<SeasonRequests>();
|
||||||
// Only have the TV requests we actually requested and not everything
|
// Only have the TV requests we actually requested and not everything
|
||||||
foreach (var season in tv.SeasonRequests)
|
foreach (var season in tv.SeasonRequests)
|
||||||
{
|
{
|
||||||
|
@ -84,7 +79,44 @@ namespace Ombi.Core.Engine
|
||||||
SeasonRequests = new List<SeasonRequests>()
|
SeasonRequests = new List<SeasonRequests>()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (tv.LatestSeason)
|
if (tv.RequestAll)
|
||||||
|
{
|
||||||
|
var episodes = await TvApi.EpisodeLookup(showInfo.id);
|
||||||
|
var seasonRequests = new List<SeasonRequests>();
|
||||||
|
foreach (var ep in episodes)
|
||||||
|
{
|
||||||
|
var episodesRequests = new List<EpisodeRequests>();
|
||||||
|
var season = childRequest.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == ep.season);
|
||||||
|
if (season == null)
|
||||||
|
{
|
||||||
|
childRequest.SeasonRequests.Add(new SeasonRequests
|
||||||
|
{
|
||||||
|
Episodes = new List<EpisodeRequests>{
|
||||||
|
new EpisodeRequests
|
||||||
|
{
|
||||||
|
EpisodeNumber = ep.number,
|
||||||
|
AirDate = DateTime.Parse(ep.airdate),
|
||||||
|
Title = ep.name,
|
||||||
|
Url = ep.url
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SeasonNumber = ep.season,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
season.Episodes.Add(new EpisodeRequests
|
||||||
|
{
|
||||||
|
EpisodeNumber = ep.number,
|
||||||
|
AirDate = DateTime.Parse(ep.airdate),
|
||||||
|
Title = ep.name,
|
||||||
|
Url = ep.url
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (tv.LatestSeason)
|
||||||
{
|
{
|
||||||
var episodes = await TvApi.EpisodeLookup(showInfo.id);
|
var episodes = await TvApi.EpisodeLookup(showInfo.id);
|
||||||
var latest = episodes.OrderBy(x => x.season).FirstOrDefault();
|
var latest = episodes.OrderBy(x => x.season).FirstOrDefault();
|
||||||
|
@ -105,8 +137,7 @@ namespace Ombi.Core.Engine
|
||||||
SeasonNumber = latest.season,
|
SeasonNumber = latest.season,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else if (tv.FirstSeason)
|
||||||
if (tv.FirstSeason)
|
|
||||||
{
|
{
|
||||||
var episodes = await TvApi.EpisodeLookup(showInfo.id);
|
var episodes = await TvApi.EpisodeLookup(showInfo.id);
|
||||||
var first = episodes.OrderByDescending(x => x.season).FirstOrDefault();
|
var first = episodes.OrderByDescending(x => x.season).FirstOrDefault();
|
||||||
|
@ -130,7 +161,12 @@ namespace Ombi.Core.Engine
|
||||||
SeasonNumber = first.season,
|
SeasonNumber = first.season,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// It's a custom request
|
||||||
|
childRequest.SeasonRequests = tvRequests;
|
||||||
|
}
|
||||||
|
|
||||||
var ruleResults = await RunRequestRules(childRequest);
|
var ruleResults = await RunRequestRules(childRequest);
|
||||||
var results = ruleResults as RuleResult[] ?? ruleResults.ToArray();
|
var results = ruleResults as RuleResult[] ?? ruleResults.ToArray();
|
||||||
if (results.Any(x => !x.Success))
|
if (results.Any(x => !x.Success))
|
||||||
|
@ -144,6 +180,35 @@ namespace Ombi.Core.Engine
|
||||||
var existingRequest = await TvRepository.Get().FirstOrDefaultAsync(x => x.TvDbId == tv.Id);
|
var existingRequest = await TvRepository.Get().FirstOrDefaultAsync(x => x.TvDbId == tv.Id);
|
||||||
if (existingRequest != null)
|
if (existingRequest != null)
|
||||||
{
|
{
|
||||||
|
// Remove requests we already have, we just want new ones
|
||||||
|
var existingSeasons = existingRequest.ChildRequests.Select(x => x.SeasonRequests);
|
||||||
|
foreach (var existingSeason in existingRequest.ChildRequests)
|
||||||
|
foreach (var existing in existingSeason.SeasonRequests)
|
||||||
|
{
|
||||||
|
var newChild = 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
|
||||||
|
childRequest.SeasonRequests.Remove(newChild);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the ID since this is a new child
|
||||||
|
childRequest.Id = 0;
|
||||||
return await AddExistingRequest(childRequest, existingRequest);
|
return await AddExistingRequest(childRequest, existingRequest);
|
||||||
}
|
}
|
||||||
// This is a new request
|
// This is a new request
|
||||||
|
@ -190,7 +255,7 @@ namespace Ombi.Core.Engine
|
||||||
results = Mapper.Map<TvRequests>(request);
|
results = Mapper.Map<TvRequests>(request);
|
||||||
|
|
||||||
// TODO need to check if we need to approve any child requests since they may have updated
|
// TODO need to check if we need to approve any child requests since they may have updated
|
||||||
|
|
||||||
await TvRepository.Update(results);
|
await TvRepository.Update(results);
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
@ -215,47 +280,6 @@ namespace Ombi.Core.Engine
|
||||||
return await AfterRequest(newRequest);
|
return await AfterRequest(newRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<SeasonRequestModel> GetListDifferences(List<SeasonRequestModel> existing,
|
|
||||||
List<SeasonRequestModel> request)
|
|
||||||
{
|
|
||||||
var requestsToRemove = new List<SeasonRequestModel>();
|
|
||||||
foreach (var r in request)
|
|
||||||
{
|
|
||||||
// Do we have an existing season?
|
|
||||||
var existingSeason = existing.FirstOrDefault(x => x.SeasonNumber == r.SeasonNumber);
|
|
||||||
if (existingSeason == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare the episodes
|
|
||||||
for (var i = r.Episodes.Count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
var existingEpisode = existingSeason.Episodes.FirstOrDefault(x => x.EpisodeNumber == r.Episodes[i].EpisodeNumber);
|
|
||||||
if (existingEpisode == null)
|
|
||||||
{
|
|
||||||
// we are fine, we have not yet requested this
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We already have this request
|
|
||||||
r.Episodes.RemoveAt(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!r.Episodes.Any())
|
|
||||||
{
|
|
||||||
requestsToRemove.Add(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var remove in requestsToRemove)
|
|
||||||
{
|
|
||||||
request.Remove(remove);
|
|
||||||
}
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<RequestEngineResult> AddRequest(TvRequests model)
|
private async Task<RequestEngineResult> AddRequest(TvRequests model)
|
||||||
{
|
{
|
||||||
await TvRepository.Add(model);
|
await TvRepository.Add(model);
|
||||||
|
|
|
@ -15,8 +15,8 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Core.Models.Requests.Tv;
|
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
|
using Ombi.Store.Repository.Requests;
|
||||||
|
|
||||||
namespace Ombi.Core.Engine
|
namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
|
@ -64,29 +64,32 @@ namespace Ombi.Core.Engine
|
||||||
var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season);
|
var season = mapped.SeasonRequests.FirstOrDefault(x => x.SeasonNumber == e.season);
|
||||||
if (season == null)
|
if (season == null)
|
||||||
{
|
{
|
||||||
var newSeason = new SeasonRequestModel
|
var newSeason = new SeasonRequests
|
||||||
{
|
{
|
||||||
SeasonNumber = e.season,
|
SeasonNumber = e.season,
|
||||||
|
Episodes = new List<EpisodeRequests>()
|
||||||
};
|
};
|
||||||
newSeason.Episodes.Add(new EpisodesRequested
|
newSeason.Episodes.Add(new EpisodeRequests
|
||||||
|
{
|
||||||
|
Url = e.url,
|
||||||
|
Title = e.name,
|
||||||
|
AirDate = DateTime.Parse(e.airstamp),
|
||||||
|
EpisodeNumber = e.number,
|
||||||
|
|
||||||
|
});
|
||||||
|
mapped.SeasonRequests.Add(newSeason);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We already have the season, so just add the episode
|
||||||
|
season.Episodes.Add(new EpisodeRequests
|
||||||
{
|
{
|
||||||
Url = e.url,
|
Url = e.url,
|
||||||
Title = e.name,
|
Title = e.name,
|
||||||
AirDate = DateTime.Parse(e.airstamp),
|
AirDate = DateTime.Parse(e.airstamp),
|
||||||
EpisodeNumber = e.number,
|
EpisodeNumber = e.number,
|
||||||
});
|
});
|
||||||
mapped.SeasonRequests.Add(newSeason);
|
|
||||||
}
|
}
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// // Find the episode
|
|
||||||
// var ep = episodes.FirstOrDefault(x => x.number == e.number);
|
|
||||||
|
|
||||||
// ep.Url = e.url;
|
|
||||||
// ep.Title = e.name;
|
|
||||||
// ep.AirDate = DateTime.Parse(e.airstamp);
|
|
||||||
// ep.EpisodeNumber = e.number;
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var existingRequests = await GetTvRequests();
|
var existingRequests = await GetTvRequests();
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Core.Models.Requests.Movie;
|
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
|
|
||||||
namespace Ombi.Core
|
namespace Ombi.Core
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Ombi.Store.Entities;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ombi.Core.Models.Requests
|
|
||||||
{
|
|
||||||
public class BaseRequestModel : Entity
|
|
||||||
{
|
|
||||||
public int ProviderId { get; set; }
|
|
||||||
public string Overview { get; set; }
|
|
||||||
public string Title { get; set; }
|
|
||||||
public string PosterPath { get; set; }
|
|
||||||
public DateTime ReleaseDate { get; set; }
|
|
||||||
public RequestType Type { get; set; }
|
|
||||||
public string Status { get; set; }
|
|
||||||
public bool Approved { get; set; }
|
|
||||||
public bool Admin { get; set; }
|
|
||||||
public DateTime RequestedDate { get; set; }
|
|
||||||
public bool Available { get; set; }
|
|
||||||
public IssueState Issues { get; set; }
|
|
||||||
public string OtherMessage { get; set; }
|
|
||||||
public string AdminNote { get; set; }
|
|
||||||
public string RequestedUser { get; set; }
|
|
||||||
public int IssueId { get; set; }
|
|
||||||
public bool Denied { get; set; }
|
|
||||||
public string DeniedReason { get; set; }
|
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public bool Released => DateTime.UtcNow > ReleaseDate;
|
|
||||||
|
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public bool CanApprove => !Approved && !Available;
|
|
||||||
|
|
||||||
public bool UserHasRequested(string username)
|
|
||||||
{
|
|
||||||
return RequestedUser.Equals(username, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
using Ombi.Core.Models.Requests;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Ombi.Core.Requests.Models
|
|
||||||
{
|
|
||||||
public interface IRequestService<T> where T : BaseRequestModel
|
|
||||||
{
|
|
||||||
int AddRequest(T model);
|
|
||||||
|
|
||||||
Task<int> AddRequestAsync(T model);
|
|
||||||
|
|
||||||
void BatchDelete(IEnumerable<T> model);
|
|
||||||
|
|
||||||
void BatchUpdate(IEnumerable<T> model);
|
|
||||||
|
|
||||||
T CheckRequest(int providerId);
|
|
||||||
|
|
||||||
Task<T> CheckRequestAsync(int providerId);
|
|
||||||
|
|
||||||
void DeleteRequest(T request);
|
|
||||||
|
|
||||||
Task DeleteRequestAsync(int request);
|
|
||||||
|
|
||||||
Task DeleteRequestAsync(T request);
|
|
||||||
|
|
||||||
T Get(int id);
|
|
||||||
|
|
||||||
IEnumerable<T> GetAll();
|
|
||||||
|
|
||||||
Task<IEnumerable<T>> GetAllAsync();
|
|
||||||
|
|
||||||
Task<IEnumerable<T>> GetAllAsync(int count, int position);
|
|
||||||
|
|
||||||
Task<T> GetAsync(int id);
|
|
||||||
|
|
||||||
T UpdateRequest(T model);
|
|
||||||
|
|
||||||
IQueryable<T> GetAllQueryable();
|
|
||||||
}
|
|
||||||
}
|
|
12
src/Ombi.Core/Models/Requests/IssueState.cs
Normal file
12
src/Ombi.Core/Models/Requests/IssueState.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace Ombi.Core.Models.Requests
|
||||||
|
{
|
||||||
|
public enum IssueState
|
||||||
|
{
|
||||||
|
None = 99,
|
||||||
|
WrongAudio = 0,
|
||||||
|
NoSubtitles = 1,
|
||||||
|
WrongContent = 2,
|
||||||
|
PlaybackIssues = 3,
|
||||||
|
Other = 4 // Provide a message
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,212 +0,0 @@
|
||||||
using Ombi.Core.Requests.Models;
|
|
||||||
using Ombi.Helpers;
|
|
||||||
using Ombi.Store.Entities;
|
|
||||||
using Ombi.Store.Repository;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Ombi.Core.Models.Requests.Tv;
|
|
||||||
|
|
||||||
namespace Ombi.Core.Models.Requests
|
|
||||||
{
|
|
||||||
public class JsonRequestService<T> : IRequestService<T> where T : BaseRequestModel
|
|
||||||
{
|
|
||||||
public JsonRequestService(IRequestRepository repo)
|
|
||||||
{
|
|
||||||
Repo = repo;
|
|
||||||
RequestType = typeof(T) == typeof(TvRequestModel) ? RequestType.TvShow : RequestType.Movie;
|
|
||||||
}
|
|
||||||
|
|
||||||
private RequestType RequestType { get; }
|
|
||||||
private IRequestRepository Repo { get; }
|
|
||||||
|
|
||||||
public int AddRequest(T model)
|
|
||||||
{
|
|
||||||
var entity = new RequestBlobs
|
|
||||||
{
|
|
||||||
Type = model.Type,
|
|
||||||
Content = ByteConverterHelper.ReturnBytes(model),
|
|
||||||
ProviderId = model.ProviderId
|
|
||||||
};
|
|
||||||
var id = Repo.Insert(entity);
|
|
||||||
|
|
||||||
return id.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<int> AddRequestAsync(T model)
|
|
||||||
{
|
|
||||||
var entity = new RequestBlobs
|
|
||||||
{
|
|
||||||
Type = model.Type,
|
|
||||||
Content = ByteConverterHelper.ReturnBytes(model),
|
|
||||||
ProviderId = model.ProviderId
|
|
||||||
};
|
|
||||||
var id = await Repo.InsertAsync(entity).ConfigureAwait(false);
|
|
||||||
|
|
||||||
return id.Id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T CheckRequest(int providerId)
|
|
||||||
{
|
|
||||||
var blobs = Repo.GetAll();
|
|
||||||
var blob = blobs.FirstOrDefault(x => x.ProviderId == providerId && x.Type == RequestType);
|
|
||||||
|
|
||||||
if (blob == null)
|
|
||||||
return null;
|
|
||||||
var model = ByteConverterHelper.ReturnObject<T>(blob.Content);
|
|
||||||
model.Id = blob.Id;
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<T> CheckRequestAsync(int providerId)
|
|
||||||
{
|
|
||||||
var blobs = await Repo.GetAllAsync().ConfigureAwait(false);
|
|
||||||
var blob = blobs.FirstOrDefault(x => x.ProviderId == providerId && x.Type == RequestType);
|
|
||||||
if (blob == null)
|
|
||||||
return null;
|
|
||||||
var model = ByteConverterHelper.ReturnObject<T>(blob.Content);
|
|
||||||
model.Id = blob.Id;
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DeleteRequest(T request)
|
|
||||||
{
|
|
||||||
var blob = Repo.Get(request.Id);
|
|
||||||
Repo.Delete(blob);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRequestAsync(T request)
|
|
||||||
{
|
|
||||||
var blob = await Repo.GetAsync(request.Id).ConfigureAwait(false);
|
|
||||||
Repo.Delete(blob);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DeleteRequestAsync(int request)
|
|
||||||
{
|
|
||||||
var blob = await Repo.GetAsync(request).ConfigureAwait(false);
|
|
||||||
Repo.Delete(blob);
|
|
||||||
}
|
|
||||||
|
|
||||||
public T UpdateRequest(T model)
|
|
||||||
{
|
|
||||||
var b = Repo.Get(model.Id);
|
|
||||||
b.Content = ByteConverterHelper.ReturnBytes(model);
|
|
||||||
var blob = Repo.Update(b);
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Get(int id)
|
|
||||||
{
|
|
||||||
var blob = Repo.Get(id);
|
|
||||||
if (blob == null)
|
|
||||||
return default(T);
|
|
||||||
var model = ByteConverterHelper.ReturnObject<T>(blob.Content);
|
|
||||||
model.Id =
|
|
||||||
blob
|
|
||||||
.Id; // They should always be the same, but for somereason a user didn't have it in the db https://github.com/tidusjar/Ombi/issues/862#issuecomment-269743847
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<T> GetAsync(int id)
|
|
||||||
{
|
|
||||||
var blob = await Repo.GetAsync(id).ConfigureAwait(false);
|
|
||||||
if (blob == null)
|
|
||||||
return default(T);
|
|
||||||
var model = ByteConverterHelper.ReturnObject<T>(blob.Content);
|
|
||||||
model.Id = blob.Id;
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<T> GetAll()
|
|
||||||
{
|
|
||||||
var blobs = Repo.GetAll().Where(x => x.Type == RequestType).ToList();
|
|
||||||
var retVal = new List<T>();
|
|
||||||
|
|
||||||
foreach (var b in blobs)
|
|
||||||
{
|
|
||||||
if (b == null)
|
|
||||||
continue;
|
|
||||||
var model = ByteConverterHelper.ReturnObject<T>(b.Content);
|
|
||||||
model.Id = b.Id;
|
|
||||||
retVal.Add(model);
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IQueryable<T> GetAllQueryable()
|
|
||||||
{
|
|
||||||
var retVal = new List<T>();
|
|
||||||
var blobs = Repo.GetAllQueryable();
|
|
||||||
foreach (var b in blobs)
|
|
||||||
{
|
|
||||||
if (b == null)
|
|
||||||
continue;
|
|
||||||
var model = ByteConverterHelper.ReturnObject<T>(b.Content);
|
|
||||||
model.Id = b.Id;
|
|
||||||
retVal.Add(model);
|
|
||||||
}
|
|
||||||
return retVal.AsQueryable();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<T>> GetAllAsync()
|
|
||||||
{
|
|
||||||
var blobs = await Repo.GetAllAsync().ConfigureAwait(false);
|
|
||||||
var retVal = new List<T>();
|
|
||||||
|
|
||||||
foreach (var b in blobs.Where(x => x.Type == RequestType))
|
|
||||||
{
|
|
||||||
if (b == null)
|
|
||||||
continue;
|
|
||||||
var model = ByteConverterHelper.ReturnObject<T>(b.Content);
|
|
||||||
model.Id = b.Id;
|
|
||||||
retVal.Add(model);
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<T>> GetAllAsync(int count, int position)
|
|
||||||
{
|
|
||||||
var blobs = await Repo.GetAllAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
var retVal = new List<T>();
|
|
||||||
|
|
||||||
foreach (var b in blobs.Where(x => x.Type == RequestType).Skip(position).Take(count))
|
|
||||||
{
|
|
||||||
if (b == null)
|
|
||||||
continue;
|
|
||||||
var model = ByteConverterHelper.ReturnObject<T>(b.Content);
|
|
||||||
model.Id = b.Id;
|
|
||||||
retVal.Add(model);
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void BatchUpdate(IEnumerable<T> model)
|
|
||||||
{
|
|
||||||
var entities = model
|
|
||||||
.Select(m => new RequestBlobs
|
|
||||||
{
|
|
||||||
Type = m.Type,
|
|
||||||
Content = ByteConverterHelper.ReturnBytes(m),
|
|
||||||
ProviderId = m.ProviderId,
|
|
||||||
Id = m.Id
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
Repo.UpdateAll(entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void BatchDelete(IEnumerable<T> model)
|
|
||||||
{
|
|
||||||
var entities = model
|
|
||||||
.Select(m => new RequestBlobs
|
|
||||||
{
|
|
||||||
Type = m.Type,
|
|
||||||
Content = ByteConverterHelper.ReturnBytes(m),
|
|
||||||
ProviderId = m.ProviderId,
|
|
||||||
Id = m.Id
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
Repo.DeleteAll(entities);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
namespace Ombi.Core.Models.Requests.Movie
|
|
||||||
{
|
|
||||||
public class MovieRequestModel : BaseRequestModel
|
|
||||||
{
|
|
||||||
public string ImdbId { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
using Ombi.Store.Entities;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Ombi.Core.Models.Requests
|
|
||||||
{
|
|
||||||
public enum IssueState
|
|
||||||
{
|
|
||||||
None = 99,
|
|
||||||
WrongAudio = 0,
|
|
||||||
NoSubtitles = 1,
|
|
||||||
WrongContent = 2,
|
|
||||||
PlaybackIssues = 3,
|
|
||||||
Other = 4 // Provide a message
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EpisodesModel : IEquatable<EpisodesModel>
|
|
||||||
{
|
|
||||||
public int SeasonNumber { get; set; }
|
|
||||||
public int EpisodeNumber { get; set; }
|
|
||||||
|
|
||||||
public bool Equals(EpisodesModel other)
|
|
||||||
{
|
|
||||||
// Check whether the compared object is null.
|
|
||||||
if (ReferenceEquals(other, null)) return false;
|
|
||||||
|
|
||||||
//Check whether the compared object references the same data.
|
|
||||||
if (ReferenceEquals(this, other)) return true;
|
|
||||||
|
|
||||||
//Check whether the properties are equal.
|
|
||||||
return SeasonNumber.Equals(other.SeasonNumber) && EpisodeNumber.Equals(other.EpisodeNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
var hashSeason = SeasonNumber.GetHashCode();
|
|
||||||
var hashEp = EpisodeNumber.GetHashCode();
|
|
||||||
|
|
||||||
//Calculate the hash code.
|
|
||||||
return hashSeason + hashEp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SeasonRequestModel
|
|
||||||
{
|
|
||||||
public int SeasonNumber { get; set; }
|
|
||||||
public List<EpisodesRequested> Episodes { get; set; } = new List<EpisodesRequested>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EpisodesRequested
|
|
||||||
{
|
|
||||||
public int EpisodeNumber { get; set; }
|
|
||||||
public string Title { get; set; }
|
|
||||||
public DateTime AirDate { get; set; }
|
|
||||||
public string Url { get; set; }
|
|
||||||
public bool Requested { get; set; }
|
|
||||||
public string Status { get; set; }
|
|
||||||
public bool Available { get; set; }
|
|
||||||
public bool Approved { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
using Ombi.Store.Entities;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ombi.Core.Models.Requests
|
|
||||||
{
|
|
||||||
public class RequestViewModel
|
|
||||||
{
|
|
||||||
public int Id { get; set; }
|
|
||||||
public int ProviderId { get; set; }
|
|
||||||
public string ImdbId { get; set; }
|
|
||||||
public string Overview { get; set; }
|
|
||||||
public string Title { get; set; }
|
|
||||||
public string PosterPath { get; set; }
|
|
||||||
public DateTime ReleaseDate { get; set; }
|
|
||||||
public bool Released { get; set; }
|
|
||||||
public RequestType Type { get; set; }
|
|
||||||
public string Status { get; set; }
|
|
||||||
public bool Approved { get; set; }
|
|
||||||
public string[] RequestedUsers { get; set; }
|
|
||||||
public DateTime RequestedDate { get; set; }
|
|
||||||
public string ReleaseYear { get; set; }
|
|
||||||
public bool Available { get; set; }
|
|
||||||
public bool Admin { get; set; }
|
|
||||||
public int IssueId { get; set; }
|
|
||||||
public QualityModel[] Qualities { get; set; }
|
|
||||||
public EpisodesModel[] Episodes { get; set; }
|
|
||||||
public bool Denied { get; set; }
|
|
||||||
public string DeniedReason { get; set; }
|
|
||||||
public RootFolderModel[] RootFolders { get; set; }
|
|
||||||
public bool HasRootFolders { get; set; }
|
|
||||||
public string CurrentRootPath { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Ombi.Core.Models.Requests.Tv
|
|
||||||
{
|
|
||||||
public class TvRequestModel : BaseRequestModel
|
|
||||||
{
|
|
||||||
public TvRequestModel()
|
|
||||||
{
|
|
||||||
ChildRequests = new List<ChildTvRequest>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string ImdbId { get; set; }
|
|
||||||
public string TvDbId { get; set; }
|
|
||||||
|
|
||||||
public List<ChildTvRequest> ChildRequests { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// For TV Shows with a custom root folder
|
|
||||||
/// </summary>
|
|
||||||
/// <value>
|
|
||||||
/// The root folder selected.
|
|
||||||
/// </value>
|
|
||||||
public int RootFolderSelected { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ChildTvRequest : BaseRequestModel
|
|
||||||
{
|
|
||||||
public bool RequestAll { get; set; }
|
|
||||||
public List<SeasonRequestModel> SeasonRequests { get; set; } = new List<SeasonRequestModel>();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Core.Models.Requests;
|
||||||
|
using Ombi.Store.Repository.Requests;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ombi.Core.Models.Search
|
namespace Ombi.Core.Models.Search
|
||||||
|
@ -39,7 +40,7 @@ namespace Ombi.Core.Models.Search
|
||||||
/// </value>
|
/// </value>
|
||||||
public string Homepage { get; set; }
|
public string Homepage { get; set; }
|
||||||
|
|
||||||
public List<SeasonRequestModel> SeasonRequests { get; set; } = new List<SeasonRequestModel>();
|
public List<SeasonRequests> SeasonRequests { get; set; } = new List<SeasonRequests>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If we are requesting the entire series
|
/// If we are requesting the entire series
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
using Ombi.Core.Models.Requests.Movie;
|
using Ombi.Core.Settings;
|
||||||
using Ombi.Core.Settings;
|
|
||||||
using Ombi.Settings.Settings.Models.External;
|
using Ombi.Settings.Settings.Models.External;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Ombi.Api.Radarr;
|
using Ombi.Api.Radarr;
|
||||||
using Ombi.Core.Models.Requests;
|
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
|
|
||||||
|
|
|
@ -30,4 +30,9 @@
|
||||||
<ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.Api.TheMovieDb.csproj" />
|
<ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.Api.TheMovieDb.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Models\Requests\Movie\" />
|
||||||
|
<Folder Include="Models\Requests\Tv\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
|
@ -1,11 +1,7 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Ombi.Core.Models.Requests;
|
|
||||||
using Ombi.Core.Models.Requests.Movie;
|
|
||||||
using Ombi.Core.Models.Requests.Tv;
|
|
||||||
using Ombi.Core.Models.Search;
|
using Ombi.Core.Models.Search;
|
||||||
using Ombi.Core.Requests.Models;
|
|
||||||
using Ombi.Core.Rule.Interfaces;
|
using Ombi.Core.Rule.Interfaces;
|
||||||
using Ombi.Store.Repository;
|
using Ombi.Store.Repository;
|
||||||
using Ombi.Store.Repository.Requests;
|
using Ombi.Store.Repository.Requests;
|
||||||
|
|
|
@ -17,7 +17,6 @@ using Ombi.Core.Engine.Interfaces;
|
||||||
using Ombi.Core.IdentityResolver;
|
using Ombi.Core.IdentityResolver;
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Core.Models.Requests;
|
||||||
using Ombi.Core.Notifications;
|
using Ombi.Core.Notifications;
|
||||||
using Ombi.Core.Requests.Models;
|
|
||||||
using Ombi.Core.Rule;
|
using Ombi.Core.Rule;
|
||||||
using Ombi.Core.Settings;
|
using Ombi.Core.Settings;
|
||||||
using Ombi.Notifications;
|
using Ombi.Notifications;
|
||||||
|
@ -75,7 +74,6 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddEntityFrameworkSqlite().AddDbContext<OmbiContext>();
|
services.AddEntityFrameworkSqlite().AddDbContext<OmbiContext>();
|
||||||
|
|
||||||
services.AddScoped<IOmbiContext, OmbiContext>();
|
services.AddScoped<IOmbiContext, OmbiContext>();
|
||||||
services.AddTransient<IRequestRepository, RequestJsonRepository>();
|
|
||||||
services.AddTransient<ISettingsRepository, SettingsJsonRepository>();
|
services.AddTransient<ISettingsRepository, SettingsJsonRepository>();
|
||||||
services.AddTransient<IUserRepository, UserRepository>();
|
services.AddTransient<IUserRepository, UserRepository>();
|
||||||
services.AddTransient<ISettingsResolver, SettingsResolver>();
|
services.AddTransient<ISettingsResolver, SettingsResolver>();
|
||||||
|
@ -89,7 +87,6 @@ namespace Ombi.DependencyInjection
|
||||||
public static void RegisterServices(this IServiceCollection services)
|
public static void RegisterServices(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddTransient<IRequestServiceMain, RequestService>();
|
services.AddTransient<IRequestServiceMain, RequestService>();
|
||||||
services.AddTransient(typeof(IRequestService<>), typeof(JsonRequestService<>));
|
|
||||||
services.AddSingleton<INotificationService, NotificationService>();
|
services.AddSingleton<INotificationService, NotificationService>();
|
||||||
services.AddTransient<INotificationHelper, NotificationHelper>();
|
services.AddTransient<INotificationHelper, NotificationHelper>();
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ using Ombi.Core.Models.Search;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using TraktApiSharp.Objects.Get.Shows;
|
using TraktApiSharp.Objects.Get.Shows;
|
||||||
using TraktApiSharp.Objects.Get.Shows.Common;
|
using TraktApiSharp.Objects.Get.Shows.Common;
|
||||||
|
using Ombi.Store.Repository.Requests;
|
||||||
|
|
||||||
//using TraktApiSharp.Objects.Get.Shows;
|
//using TraktApiSharp.Objects.Get.Shows;
|
||||||
//using TraktApiSharp.Objects.Get.Shows.Common;
|
//using TraktApiSharp.Objects.Get.Shows.Common;
|
||||||
|
@ -51,23 +52,22 @@ namespace Ombi.Mapping.Profiles
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CreateMap<TvMazeCustomSeason, SeasonRequestModel>()
|
//CreateMap<TvMazeCustomSeason, SeasonRequests>()
|
||||||
.ConstructUsing(x =>
|
// .ConstructUsing(x =>
|
||||||
{
|
// {
|
||||||
var season = new SeasonRequestModel
|
// var season = new SeasonRequests
|
||||||
{
|
// {
|
||||||
SeasonNumber = x.SeasonNumber
|
// SeasonNumber = x.SeasonNumber
|
||||||
};
|
// };
|
||||||
foreach (var ep in x.EpisodeNumber)
|
// foreach (var ep in x.EpisodeNumber)
|
||||||
{
|
// {
|
||||||
season.Episodes.Add(new EpisodesRequested
|
// season.Episodes.Add(new EpisodeRequests
|
||||||
{
|
// {
|
||||||
EpisodeNumber = ep,
|
// EpisodeNumber = ep,
|
||||||
|
// });
|
||||||
});
|
// }
|
||||||
}
|
// return season;
|
||||||
return season;
|
// });
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ namespace Ombi.Store.Context
|
||||||
{
|
{
|
||||||
int SaveChanges();
|
int SaveChanges();
|
||||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
|
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
|
||||||
DbSet<RequestBlobs> Requests { get; set; }
|
|
||||||
DbSet<GlobalSettings> Settings { get; set; }
|
DbSet<GlobalSettings> Settings { get; set; }
|
||||||
DbSet<PlexContent> PlexContent { get; set; }
|
DbSet<PlexContent> PlexContent { get; set; }
|
||||||
DbSet<RadarrCache> RadarrCache { get; set; }
|
DbSet<RadarrCache> RadarrCache { get; set; }
|
||||||
|
|
|
@ -34,8 +34,7 @@ namespace Ombi.Store.Context
|
||||||
// Add the notifcation templates
|
// Add the notifcation templates
|
||||||
AddAllTemplates();
|
AddAllTemplates();
|
||||||
}
|
}
|
||||||
|
|
||||||
public DbSet<RequestBlobs> Requests { get; set; }
|
|
||||||
public DbSet<GlobalSettings> Settings { get; set; }
|
public DbSet<GlobalSettings> Settings { get; set; }
|
||||||
public DbSet<User> Users { get; set; }
|
public DbSet<User> Users { get; set; }
|
||||||
public DbSet<PlexContent> PlexContent { get; set; }
|
public DbSet<PlexContent> PlexContent { get; set; }
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace Ombi.Store.Entities
|
|
||||||
{
|
|
||||||
[Table("RequestBlobs")]
|
|
||||||
public class RequestBlobs : Entity
|
|
||||||
{
|
|
||||||
public int ProviderId { get; set; }
|
|
||||||
public byte[] Content { get; set; }
|
|
||||||
public RequestType Type { get; set; }
|
|
||||||
|
|
||||||
}
|
|
||||||
public enum RequestType
|
|
||||||
{
|
|
||||||
Movie = 1,
|
|
||||||
TvShow = 2
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Ombi.Store.Entities
|
|
||||||
{
|
|
||||||
public class RequestHistory : Entity
|
|
||||||
{
|
|
||||||
public int UserId { get; set; }
|
|
||||||
public RequestType Type { get; set; }
|
|
||||||
public DateTime RequestedDate { get; set; }
|
|
||||||
public int RequestId { get; set; }
|
|
||||||
|
|
||||||
public virtual RequestBlobs Request { get; set; }
|
|
||||||
public virtual User User { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
12
src/Ombi.Store/Entities/RequestType.cs
Normal file
12
src/Ombi.Store/Entities/RequestType.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Entities
|
||||||
|
{
|
||||||
|
public enum RequestType
|
||||||
|
{
|
||||||
|
TvShow,
|
||||||
|
Movie
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,8 +24,10 @@ namespace Ombi.Store.Repository.Requests
|
||||||
public DateTime AirDate { get; set; }
|
public DateTime AirDate { get; set; }
|
||||||
public string Url { get; set; }
|
public string Url { get; set; }
|
||||||
public bool Available { get; set; }
|
public bool Available { get; set; }
|
||||||
|
public bool Approved { get; set; }
|
||||||
|
public bool Requested { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public int SeasonId { get; set; }
|
public int SeasonId { get; set; }
|
||||||
[ForeignKey(nameof(SeasonId))]
|
[ForeignKey(nameof(SeasonId))]
|
||||||
public SeasonRequests Season { get; set; }
|
public SeasonRequests Season { get; set; }
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Ombi.Store.Entities;
|
|
||||||
|
|
||||||
namespace Ombi.Store.Repository
|
|
||||||
{
|
|
||||||
public interface IRequestRepository
|
|
||||||
{
|
|
||||||
void Delete(RequestBlobs entity);
|
|
||||||
void DeleteAll(IEnumerable<RequestBlobs> entity);
|
|
||||||
RequestBlobs Get(int id);
|
|
||||||
IEnumerable<RequestBlobs> GetAll();
|
|
||||||
Task<IEnumerable<RequestBlobs>> GetAllAsync();
|
|
||||||
Task<RequestBlobs> GetAsync(int id);
|
|
||||||
RequestBlobs Insert(RequestBlobs entity);
|
|
||||||
Task<RequestBlobs> InsertAsync(RequestBlobs entity);
|
|
||||||
RequestBlobs Update(RequestBlobs entity);
|
|
||||||
void UpdateAll(IEnumerable<RequestBlobs> entity);
|
|
||||||
IQueryable<RequestBlobs> GetAllQueryable();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,140 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Ombi.Store.Context;
|
|
||||||
using Ombi.Store.Entities;
|
|
||||||
|
|
||||||
namespace Ombi.Store.Repository
|
|
||||||
{
|
|
||||||
public class RequestJsonRepository : IRequestRepository
|
|
||||||
{
|
|
||||||
//private ICacheProvider Cache { get; }
|
|
||||||
|
|
||||||
public RequestJsonRepository(IOmbiContext ctx)
|
|
||||||
{
|
|
||||||
Db = ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IOmbiContext Db { get; }
|
|
||||||
|
|
||||||
public RequestBlobs Insert(RequestBlobs entity)
|
|
||||||
{
|
|
||||||
|
|
||||||
var id = Db.Requests.Add(entity);
|
|
||||||
Db.SaveChanges();
|
|
||||||
return id.Entity;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<RequestBlobs> InsertAsync(RequestBlobs entity)
|
|
||||||
{
|
|
||||||
|
|
||||||
var id = await Db.Requests.AddAsync(entity).ConfigureAwait(false);
|
|
||||||
await Db.SaveChangesAsync();
|
|
||||||
return id.Entity;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<RequestBlobs> GetAll()
|
|
||||||
{
|
|
||||||
//var key = "GetAll";
|
|
||||||
//var item = Cache.GetOrSet(key, () =>
|
|
||||||
//{
|
|
||||||
|
|
||||||
var page = Db.Requests.ToList();
|
|
||||||
return page;
|
|
||||||
|
|
||||||
//}, 5);
|
|
||||||
//return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<RequestBlobs>> GetAllAsync()
|
|
||||||
{
|
|
||||||
//var key = "GetAll";
|
|
||||||
//var item = await Cache.GetOrSetAsync(key, async () =>
|
|
||||||
//{
|
|
||||||
|
|
||||||
var page = await Db.Requests.ToListAsync().ConfigureAwait(false);
|
|
||||||
return page;
|
|
||||||
|
|
||||||
//}, 5);
|
|
||||||
//return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestBlobs Get(int id)
|
|
||||||
{
|
|
||||||
//var key = "Get" + id;
|
|
||||||
//var item = Cache.GetOrSet(key, () =>
|
|
||||||
//{
|
|
||||||
|
|
||||||
var page = Db.Requests.Find(id);
|
|
||||||
return page;
|
|
||||||
|
|
||||||
//}, 5);
|
|
||||||
//return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<RequestBlobs> GetAsync(int id)
|
|
||||||
{
|
|
||||||
//var key = "Get" + id;
|
|
||||||
//var item = await Cache.GetOrSetAsync(key, async () =>
|
|
||||||
//{
|
|
||||||
|
|
||||||
var page = await Db.Requests.FindAsync(id).ConfigureAwait(false);
|
|
||||||
return page;
|
|
||||||
|
|
||||||
//}, 5);
|
|
||||||
//return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Delete(RequestBlobs entity)
|
|
||||||
{
|
|
||||||
//ResetCache();
|
|
||||||
|
|
||||||
Db.Requests.Remove(entity);
|
|
||||||
Db.SaveChanges();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestBlobs Update(RequestBlobs entity)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Db.SaveChanges();
|
|
||||||
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine(e);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateAll(IEnumerable<RequestBlobs> entity)
|
|
||||||
{
|
|
||||||
|
|
||||||
Db.Requests.UpdateRange(entity);
|
|
||||||
Db.SaveChanges();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void DeleteAll(IEnumerable<RequestBlobs> entity)
|
|
||||||
{
|
|
||||||
|
|
||||||
Db.Requests.RemoveRange(entity);
|
|
||||||
Db.SaveChanges();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public IQueryable<RequestBlobs> GetAllQueryable()
|
|
||||||
{
|
|
||||||
return Db.Requests.AsQueryable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -167,6 +167,8 @@ CREATE TABLE IF NOT EXISTS EpisodeRequests (
|
||||||
Url VARCHAR(100) NOT NULL,
|
Url VARCHAR(100) NOT NULL,
|
||||||
SeasonId INTEGER NOT NULL,
|
SeasonId INTEGER NOT NULL,
|
||||||
Available INTEGER NOT NULL,
|
Available INTEGER NOT NULL,
|
||||||
|
Requested INTEGER NOT NULL,
|
||||||
|
Approved INTEGER NOT NULL,
|
||||||
|
|
||||||
|
|
||||||
FOREIGN KEY (SeasonId) REFERENCES SeasonRequests(Id)
|
FOREIGN KEY (SeasonId) REFERENCES SeasonRequests(Id)
|
||||||
|
|
|
@ -138,5 +138,7 @@ export interface IEpisodesRequests {
|
||||||
airDate: Date,
|
airDate: Date,
|
||||||
url: string,
|
url: string,
|
||||||
available: boolean,
|
available: boolean,
|
||||||
|
requested: boolean,
|
||||||
|
approved: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
userType: UserType,
|
userType: UserType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export enum UserType {
|
export enum UserType {
|
||||||
LocalUser = 1,
|
LocalUser = 1,
|
||||||
PlexUser = 2,
|
PlexUser = 2,
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
|
|
||||||
<img class="img-responsive" src="https://image.tmdb.org/t/p/w150/{{request.posterPath}}" alt="poster">
|
<img class="img-responsive poster" src="https://image.tmdb.org/t/p/w150/{{request.posterPath}}" alt="poster">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
|
|
||||||
<img class="img-responsive" src="{{request.posterPath}}" alt="poster">
|
<img class="img-responsive poster" src="{{request.posterPath}}" alt="poster">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -187,52 +187,85 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<p-dialog *ngIf="showChildDialogue" id="dialogOverride" header="{{selectedSeason?.title}}" [(visible)]="showChildDialogue" [contentStyle]="{'overflow':'auto','max-height':'500px'}" [width]="768">
|
||||||
|
<div class="row" *ngFor="let child of selectedSeason.childRequests">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<!--Child Requests-->
|
||||||
|
<div class="col-md-9">
|
||||||
|
<span class="col-md-12">Requested By: <b>{{child.requestedUser.username}}</b></span>
|
||||||
|
|
||||||
<div class="modal fade in" *ngIf="showChildDialogue" style="display: block;">
|
<!--<span class="col-md-12" *ngIf="child.requestAll">Requested All Seasons</span>-->
|
||||||
<div class="modal-dialog">
|
<!--Seasons-->
|
||||||
<div class="modal-content">
|
<span *ngIf="child.approved && !child.available" class="label label-info">Processing Request</span>
|
||||||
<div class="modal-header">
|
<span *ngIf="child.denied" class="label label-danger">Request Denied</span>
|
||||||
<button type="button" class="close" (click)="showChildDialogue=false">×</button>
|
<span *ngIf="child.deniedReason" title="{{child.deniedReason}}"><i class="fa fa-info-circle"></i></span>
|
||||||
<h4 class="modal-title">{{selectedSeason?.title}}</h4>
|
<span *ngIf="!child.approved && !child.availble && !child.denied" class="label label-warning">Pending Approval</span>
|
||||||
</div>
|
<div class="col-md-12" *ngFor="let seasons of child.seasonRequests">
|
||||||
<div class="modal-body">
|
|
||||||
<div class="row" *ngFor="let child of selectedSeason.childRequests">
|
|
||||||
<div class="col-md-12">
|
|
||||||
<!--Child Requests-->
|
|
||||||
<div class="col-md-9">
|
|
||||||
<span class="col-md-12">Requested By: <b>{{child.requestedUser}}</b></span>
|
|
||||||
|
|
||||||
<!--<span class="col-md-12" *ngIf="child.requestAll">Requested All Seasons</span>-->
|
|
||||||
<!--Seasons-->
|
|
||||||
<span *ngIf="child.approved && !child.available" class="label label-info">Processing Request</span>
|
|
||||||
<span *ngIf="child.denied" class="label label-danger">Request Denied</span>
|
|
||||||
<span *ngIf="child.deniedReason" title="{{child.deniedReason}}"><i class="fa fa-info-circle"></i></span>
|
|
||||||
<span *ngIf="!child.approved && !child.availble && !child.denied" class="label label-warning">Pending Approval</span>
|
|
||||||
<div class="col-md-12" *ngFor="let seasons of child.seasonRequests">
|
|
||||||
|
|
||||||
|
|
||||||
<span>Season: {{seasons.seasonNumber}}</span>
|
<span><b>Season: {{seasons.seasonNumber}}</b></span>
|
||||||
<span>Episodes:</span>
|
<div>
|
||||||
|
<span>Episodes:</span>
|
||||||
|
|
||||||
<div *ngFor="let episode of seasons.episodes">
|
<div *ngFor="let episode of seasons.episodes">
|
||||||
<!--Episodes-->
|
<!--Episodes-->
|
||||||
<span># {{episode.episodeNumber}} | {{episode.title}}</span>
|
<span># {{episode.episodeNumber}} | {{episode.title}}</span>
|
||||||
<span *ngIf="episode.available" class="label label-success">Available</span>
|
<span *ngIf="episode.available" class="label label-success">Available</span>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<button *ngIf="!child.approved" type="button" (click)="approveSeasonRequest(child)" class="btn btn-sm btn-success-outline" style="text-align: right"><i class="fa fa-plus"></i> Approve</button>
|
|
||||||
<button *ngIf="!child.approved && !child.available && !child.denied" type="button" (click)="denySeasonRequest(child)" class="btn btn-sm btn-danger-outline" style="text-align: right"><i class="fa fa-plus"></i> Deny</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="col-md-3">
|
||||||
<button type="button" class="btn btn-danger-outline" (click)="showChildDialogue=false">Close</button>
|
<button *ngIf="!child.approved" type="button" (click)="approveSeasonRequest(child)" class="btn btn-sm btn-success-outline" style="text-align: right"><i class="fa fa-plus"></i> Approve</button>
|
||||||
|
<button *ngIf="child.approved && !child.available" type="button" [disabled]="true" class="btn btn-sm btn-primary-outline" style="text-align: right"><i class="fa fa-plus"></i> Processing</button>
|
||||||
|
<button *ngIf="!child.approved && !child.available && !child.denied" type="button" (click)="denySeasonRequest(child)" class="btn btn-sm btn-danger-outline" style="text-align: right"><i class="fa fa-plus"></i> Deny</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<hr />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</p-dialog>
|
||||||
|
<!--<div class="modal fade in" *ngIf="showChildDialogue" style="display: block;">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" (click)="showChildDialogue=false">×</button>
|
||||||
|
<h4 class="modal-title">{{selectedSeason?.title}}</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="row" *ngFor="let child of selectedSeason.childRequests">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="col-md-9">
|
||||||
|
<span class="col-md-12">Requested By: <b>{{child.requestedUser.username}}</b></span>
|
||||||
|
|
||||||
|
|
||||||
|
<span *ngIf="child.approved && !child.available" class="label label-info">Processing Request</span>
|
||||||
|
<span *ngIf="child.denied" class="label label-danger">Request Denied</span>
|
||||||
|
<span *ngIf="child.deniedReason" title="{{child.deniedReason}}"><i class="fa fa-info-circle"></i></span>
|
||||||
|
<span *ngIf="!child.approved && !child.availble && !child.denied" class="label label-warning">Pending Approval</span>
|
||||||
|
<div class="col-md-12" *ngFor="let seasons of child.seasonRequests">
|
||||||
|
|
||||||
|
|
||||||
|
<span>Season: {{seasons.seasonNumber}}</span>
|
||||||
|
<span>Episodes:</span>
|
||||||
|
|
||||||
|
<div *ngFor="let episode of seasons.episodes">
|
||||||
|
<span># {{episode.episodeNumber}} | {{episode.title}}</span>
|
||||||
|
<span *ngIf="episode.available" class="label label-success">Available</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<button *ngIf="!child.approved" type="button" (click)="approveSeasonRequest(child)" class="btn btn-sm btn-success-outline" style="text-align: right"><i class="fa fa-plus"></i> Approve</button>
|
||||||
|
<button *ngIf="child.approved && !child.available" type="button" [disabled]="true" class="btn btn-sm btn-primary-outline" style="text-align: right"><i class="fa fa-plus"></i> Processing</button>
|
||||||
|
<button *ngIf="!child.approved && !child.available && !child.denied" type="button" (click)="denySeasonRequest(child)" class="btn btn-sm btn-danger-outline" style="text-align: right"><i class="fa fa-plus"></i> Deny</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-danger-outline" (click)="showChildDialogue=false">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>-->
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
<div id="{{id}}imgDiv" class="col-sm-2">
|
<div id="{{id}}imgDiv" class="col-sm-2">
|
||||||
|
|
||||||
|
|
||||||
<img *ngIf="result.posterPath" class="img-responsive" src="https://image.tmdb.org/t/p/w150/{{result.posterPath}}" alt="poster">
|
<img *ngIf="result.posterPath" class="img-responsive poster" src="https://image.tmdb.org/t/p/w150/{{result.posterPath}}" alt="poster">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { NotificationService } from '../services/notification.service';
|
||||||
|
|
||||||
import { ISearchTvResult } from '../interfaces/ISearchTvResult';
|
import { ISearchTvResult } from '../interfaces/ISearchTvResult';
|
||||||
import { IRequestEngineResult } from '../interfaces/IRequestEngineResult';
|
import { IRequestEngineResult } from '../interfaces/IRequestEngineResult';
|
||||||
import { IEpisodesRequested } from "../interfaces/IRequestModel";
|
import { IEpisodesRequests } from "../interfaces/IRequestModel";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './seriesinformation.component.html',
|
templateUrl: './seriesinformation.component.html',
|
||||||
|
@ -33,7 +33,7 @@ export class SeriesInformationComponent implements OnInit, OnDestroy {
|
||||||
private seriesId: number;
|
private seriesId: number;
|
||||||
public series: ISearchTvResult;
|
public series: ISearchTvResult;
|
||||||
|
|
||||||
requestedEpisodes: IEpisodesRequested[] = [];
|
requestedEpisodes: IEpisodesRequests[] = [];
|
||||||
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
@ -61,7 +61,7 @@ export class SeriesInformationComponent implements OnInit, OnDestroy {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public addRequest(episode: IEpisodesRequested) {
|
public addRequest(episode: IEpisodesRequests) {
|
||||||
episode.requested = true;
|
episode.requested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
|
|
||||||
<img *ngIf="result.banner" class="img-responsive" width="150" [src]="result.banner" alt="poster">
|
<img *ngIf="result.banner" class="img-responsive poster" width="150" [src]="result.banner" alt="poster">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
|
|
||||||
namespace Ombi.Models
|
namespace Ombi.Models
|
||||||
{
|
{
|
||||||
public class RequestGridModel<T> where T : BaseRequestModel
|
public class RequestGridModel<T> where T : BaseRequest
|
||||||
{
|
{
|
||||||
public IEnumerable<T> Available { get; set; }
|
public IEnumerable<T> Available { get; set; }
|
||||||
public IEnumerable<T> New { get; set; }
|
public IEnumerable<T> New { get; set; }
|
||||||
|
|
|
@ -14,3 +14,14 @@ $bg-colour-disabled: #252424;
|
||||||
background: $primary-colour !important;
|
background: $primary-colour !important;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#dialogOverride > div > .ui-dialog-content {
|
||||||
|
border: 1px solid $bg-colour-disabled !important;
|
||||||
|
background: $bg-colour !important;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
/*#dialogOverride > div > .ui-dialog-titlebar {
|
||||||
|
background: $primary-colour !important;
|
||||||
|
color: white;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
|
@ -734,4 +734,9 @@ body {
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poster {
|
||||||
|
box-shadow: 5px 5px 30px #000000;
|
||||||
|
border-radius: 30px;
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue