Merge branch 'DotNetCore' of https://github.com/tidusjar/PlexRequests.Net into DotNetCore
Before Width: | Height: | Size: 361 KiB After Width: | Height: | Size: 125 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 5 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 577 B |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 3 KiB |
Before Width: | Height: | Size: 22 KiB |
BIN
Old/Ombi.UI/Content/images/emby-logo-dark.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 11 KiB |
|
@ -471,7 +471,7 @@
|
||||||
<Content Include="Content\helpers\bootbox.min.js">
|
<Content Include="Content\helpers\bootbox.min.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="Content\images\emby-logo-dark.jpg">
|
<Content Include="Content\images\emby-logo-dark.png">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="Content\images\emby-logo.png">
|
<Content Include="Content\images\emby-logo.png">
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<a href="#" id="embyImg">
|
<a href="#" id="embyImg">
|
||||||
<img class="wizard-img" src="@formAction/Content/images/emby-logo-dark.jpg" />
|
<img class="wizard-img" src="@formAction/Content/images/emby-logo-dark.png" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -15,5 +15,6 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
Task RemoveMovieRequest(int requestId);
|
Task RemoveMovieRequest(int requestId);
|
||||||
|
|
||||||
Task<MovieRequests> UpdateMovieRequest(MovieRequests request);
|
Task<MovieRequests> UpdateMovieRequest(MovieRequests request);
|
||||||
|
Task<RequestEngineResult> ApproveMovie(MovieRequests request);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,10 +13,13 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
Task<RequestEngineResult> RequestTvShow(SearchTvShowViewModel tv);
|
Task<RequestEngineResult> RequestTvShow(SearchTvShowViewModel tv);
|
||||||
|
|
||||||
Task<IEnumerable<TvRequests>> SearchTvRequest(string search);
|
Task<IEnumerable<TvRequests>> SearchTvRequest(string search);
|
||||||
|
Task<IEnumerable<TreeNode<TvRequests, List<ChildRequests>>>> SearchTvRequestTree(string search);
|
||||||
|
|
||||||
Task<TvRequests> UpdateTvRequest(TvRequests request);
|
Task<TvRequests> UpdateTvRequest(TvRequests request);
|
||||||
|
Task<IEnumerable<TreeNode<TvRequests, List<ChildRequests>>>> GetRequestsTreeNode(int count, int position);
|
||||||
Task<IEnumerable<ChildRequests>> GetAllChldren(int tvId);
|
Task<IEnumerable<ChildRequests>> GetAllChldren(int tvId);
|
||||||
Task<ChildRequests> UpdateChildRequest(ChildRequests request);
|
Task<ChildRequests> UpdateChildRequest(ChildRequests request);
|
||||||
Task RemoveTvChild(int requestId);
|
Task RemoveTvChild(int requestId);
|
||||||
|
Task<RequestEngineResult> ApproveChildRequest(ChildRequests request);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -141,6 +141,42 @@ namespace Ombi.Core.Engine
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is the method that is triggered by pressing Approve on the requests page
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task<RequestEngineResult> ApproveMovie(MovieRequests request)
|
||||||
|
{
|
||||||
|
if (request.Approved)
|
||||||
|
{
|
||||||
|
var result = await Sender.Send(request);
|
||||||
|
if (result.Success && result.MovieSent)
|
||||||
|
{
|
||||||
|
return new RequestEngineResult
|
||||||
|
{
|
||||||
|
RequestAdded = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!result.Success)
|
||||||
|
{
|
||||||
|
Logger.LogWarning("Tried auto sending movie but failed. Message: {0}", result.Message);
|
||||||
|
return new RequestEngineResult
|
||||||
|
{
|
||||||
|
Message = result.Message,
|
||||||
|
ErrorMessage = result.Message,
|
||||||
|
RequestAdded = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// If there are no providers then it's successful but movie has not been sent
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RequestEngineResult
|
||||||
|
{
|
||||||
|
RequestAdded = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the movie request.
|
/// Updates the movie request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -11,4 +11,13 @@ namespace Ombi.Core.Engine
|
||||||
public bool Leaf { get; set; }
|
public bool Leaf { get; set; }
|
||||||
public bool Expanded { get; set; }
|
public bool Expanded { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class TreeNode<T,U>
|
||||||
|
{
|
||||||
|
public string Label { get; set; }
|
||||||
|
public T Data { get; set; }
|
||||||
|
public List<TreeNode<U>> Children { get; set; }
|
||||||
|
public bool Leaf { get; set; }
|
||||||
|
public bool Expanded { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -37,7 +37,7 @@ namespace Ombi.Core.Engine
|
||||||
private INotificationHelper NotificationHelper { get; }
|
private INotificationHelper NotificationHelper { get; }
|
||||||
private ITvMazeApi TvApi { get; }
|
private ITvMazeApi TvApi { get; }
|
||||||
private IMapper Mapper { get; }
|
private IMapper Mapper { get; }
|
||||||
private ITvSender TvSender {get;}
|
private ITvSender TvSender { get; }
|
||||||
private IAuditRepository Audit { get; }
|
private IAuditRepository Audit { get; }
|
||||||
|
|
||||||
public async Task<RequestEngineResult> RequestTvShow(SearchTvShowViewModel tv)
|
public async Task<RequestEngineResult> RequestTvShow(SearchTvShowViewModel tv)
|
||||||
|
@ -51,7 +51,7 @@ namespace Ombi.Core.Engine
|
||||||
.CreateChild(tv, user.Id);
|
.CreateChild(tv, user.Id);
|
||||||
|
|
||||||
await tvBuilder.BuildEpisodes(tv);
|
await tvBuilder.BuildEpisodes(tv);
|
||||||
|
|
||||||
var ruleResults = await RunRequestRules(tvBuilder.ChildRequest);
|
var ruleResults = await RunRequestRules(tvBuilder.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))
|
||||||
|
@ -122,6 +122,12 @@ namespace Ombi.Core.Engine
|
||||||
return allRequests;
|
return allRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TreeNode<TvRequests, List<ChildRequests>>>> GetRequestsTreeNode(int count, int position)
|
||||||
|
{
|
||||||
|
var allRequests = await TvRepository.Get().Skip(position).Take(count).ToListAsync();
|
||||||
|
return ParseIntoTreeNode(allRequests);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<TvRequests>> GetRequests()
|
public async Task<IEnumerable<TvRequests>> GetRequests()
|
||||||
{
|
{
|
||||||
var allRequests = TvRepository.Get();
|
var allRequests = TvRepository.Get();
|
||||||
|
@ -132,7 +138,7 @@ namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
return await TvRepository.GetChild().Where(x => x.ParentRequestId == tvId).ToListAsync();
|
return await TvRepository.GetChild().Where(x => x.ParentRequestId == tvId).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<TvRequests>> SearchTvRequest(string search)
|
public async Task<IEnumerable<TvRequests>> SearchTvRequest(string search)
|
||||||
{
|
{
|
||||||
var allRequests = TvRepository.Get();
|
var allRequests = TvRepository.Get();
|
||||||
|
@ -140,21 +146,42 @@ namespace Ombi.Core.Engine
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<TreeNode<TvRequests, List<ChildRequests>>>> SearchTvRequestTree(string search)
|
||||||
|
{
|
||||||
|
var allRequests = TvRepository.Get();
|
||||||
|
var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync();
|
||||||
|
return ParseIntoTreeNode(results);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<TvRequests> UpdateTvRequest(TvRequests request)
|
public async Task<TvRequests> UpdateTvRequest(TvRequests request)
|
||||||
{
|
{
|
||||||
await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username);
|
await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username);
|
||||||
var allRequests = TvRepository.Get();
|
var allRequests = TvRepository.Get();
|
||||||
var results = await allRequests.FirstOrDefaultAsync(x => x.Id == request.Id);
|
var results = await allRequests.FirstOrDefaultAsync(x => x.Id == request.Id);
|
||||||
|
|
||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<RequestEngineResult> ApproveChildRequest(ChildRequests request)
|
||||||
|
{
|
||||||
|
if (request.Approved)
|
||||||
|
{
|
||||||
|
await Audit.Record(AuditType.Approved, AuditArea.TvRequest, $"Approved Request {request.Title}", Username);
|
||||||
|
// Autosend
|
||||||
|
await TvSender.SendToSonarr(request);
|
||||||
|
}
|
||||||
|
await TvRepository.UpdateChild(request);
|
||||||
|
return new RequestEngineResult
|
||||||
|
{
|
||||||
|
RequestAdded = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<ChildRequests> UpdateChildRequest(ChildRequests request)
|
public async Task<ChildRequests> UpdateChildRequest(ChildRequests request)
|
||||||
{
|
{
|
||||||
await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username);
|
await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username);
|
||||||
|
|
||||||
await TvRepository.UpdateChild(request);
|
await TvRepository.UpdateChild(request);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
@ -164,7 +191,7 @@ namespace Ombi.Core.Engine
|
||||||
var request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId);
|
var request = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId);
|
||||||
var all = TvRepository.Db.TvRequests.Include(x => x.ChildRequests);
|
var all = TvRepository.Db.TvRequests.Include(x => x.ChildRequests);
|
||||||
var parent = all.FirstOrDefault(x => x.Id == request.ParentRequestId);
|
var parent = all.FirstOrDefault(x => x.Id == request.ParentRequestId);
|
||||||
|
|
||||||
// Is this the only child? If so delete the parent
|
// Is this the only child? If so delete the parent
|
||||||
if (parent.ChildRequests.Count <= 1)
|
if (parent.ChildRequests.Count <= 1)
|
||||||
{
|
{
|
||||||
|
@ -201,6 +228,41 @@ namespace Ombi.Core.Engine
|
||||||
return await AfterRequest(model.ChildRequests.FirstOrDefault());
|
return await AfterRequest(model.ChildRequests.FirstOrDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<TreeNode<TvRequests, List<ChildRequests>>> ParseIntoTreeNode(IEnumerable<TvRequests> result)
|
||||||
|
{
|
||||||
|
var node = new List<TreeNode<TvRequests, List<ChildRequests>>>();
|
||||||
|
|
||||||
|
foreach (var value in result)
|
||||||
|
{
|
||||||
|
node.Add(new TreeNode<TvRequests, List<ChildRequests>>
|
||||||
|
{
|
||||||
|
Data = value,
|
||||||
|
Children = new List<TreeNode<List<ChildRequests>>>
|
||||||
|
{
|
||||||
|
new TreeNode<List<ChildRequests>>
|
||||||
|
{
|
||||||
|
Data = SortEpisodes(value.ChildRequests),
|
||||||
|
Leaf = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<ChildRequests> SortEpisodes(List<ChildRequests> items)
|
||||||
|
{
|
||||||
|
foreach (var value in items)
|
||||||
|
{
|
||||||
|
foreach (var requests in value.SeasonRequests)
|
||||||
|
{
|
||||||
|
requests.Episodes.OrderBy(x => x.EpisodeNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task<RequestEngineResult> AfterRequest(ChildRequests model)
|
private async Task<RequestEngineResult> AfterRequest(ChildRequests model)
|
||||||
{
|
{
|
||||||
var sendRuleResult = await RunSpecificRule(model, SpecificRules.CanSendNotification);
|
var sendRuleResult = await RunSpecificRule(model, SpecificRules.CanSendNotification);
|
||||||
|
@ -209,7 +271,7 @@ namespace Ombi.Core.Engine
|
||||||
NotificationHelper.NewRequest(model);
|
NotificationHelper.NewRequest(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(model.Approved)
|
if (model.Approved)
|
||||||
{
|
{
|
||||||
// Autosend
|
// Autosend
|
||||||
await TvSender.SendToSonarr(model);
|
await TvSender.SendToSonarr(model);
|
||||||
|
@ -221,8 +283,8 @@ namespace Ombi.Core.Engine
|
||||||
//public async Task<IEnumerable<TvRequests>> GetApprovedRequests()
|
//public async Task<IEnumerable<TvRequests>> GetApprovedRequests()
|
||||||
//{
|
//{
|
||||||
// var allRequests = TvRepository.Get();
|
// var allRequests = TvRepository.Get();
|
||||||
|
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//public async Task<IEnumerable<TvRequests>> GetNewRequests()
|
//public async Task<IEnumerable<TvRequests>> GetNewRequests()
|
||||||
|
|
|
@ -19,13 +19,14 @@ using Ombi.Store.Entities.Requests;
|
||||||
using Ombi.Store.Repository.Requests;
|
using Ombi.Store.Repository.Requests;
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Ombi.Core.Engine
|
namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
public class TvSearchEngine : BaseMediaEngine, ITvSearchEngine
|
public class TvSearchEngine : BaseMediaEngine, ITvSearchEngine
|
||||||
{
|
{
|
||||||
public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ISettingsService<PlexSettings> plexSettings,
|
public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, ISettingsService<PlexSettings> plexSettings,
|
||||||
ISettingsService<EmbySettings> embySettings, IPlexContentRepository repo, ITraktApi trakt, IRuleEvaluator r, UserManager<OmbiUser> um)
|
ISettingsService<EmbySettings> embySettings, IPlexContentRepository repo, IEmbyContentRepository embyRepo, ITraktApi trakt, IRuleEvaluator r, UserManager<OmbiUser> um)
|
||||||
: base(identity, service, r, um)
|
: base(identity, service, r, um)
|
||||||
{
|
{
|
||||||
TvMazeApi = tvMaze;
|
TvMazeApi = tvMaze;
|
||||||
|
@ -34,6 +35,7 @@ namespace Ombi.Core.Engine
|
||||||
EmbySettings = embySettings;
|
EmbySettings = embySettings;
|
||||||
PlexContentRepo = repo;
|
PlexContentRepo = repo;
|
||||||
TraktApi = trakt;
|
TraktApi = trakt;
|
||||||
|
EmbyContentRepo = embyRepo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ITvMazeApi TvMazeApi { get; }
|
private ITvMazeApi TvMazeApi { get; }
|
||||||
|
@ -41,6 +43,7 @@ namespace Ombi.Core.Engine
|
||||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||||
private ISettingsService<EmbySettings> EmbySettings { get; }
|
private ISettingsService<EmbySettings> EmbySettings { get; }
|
||||||
private IPlexContentRepository PlexContentRepo { get; }
|
private IPlexContentRepository PlexContentRepo { get; }
|
||||||
|
private IEmbyContentRepository EmbyContentRepo { get; }
|
||||||
private ITraktApi TraktApi { get; }
|
private ITraktApi TraktApi { get; }
|
||||||
|
|
||||||
public async Task<IEnumerable<SearchTvShowViewModel>> Search(string searchTerm)
|
public async Task<IEnumerable<SearchTvShowViewModel>> Search(string searchTerm)
|
||||||
|
@ -175,11 +178,31 @@ namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
if (embySettings.Enable)
|
if (embySettings.Enable)
|
||||||
{
|
{
|
||||||
//var embyShow = EmbyChecker.GetTvShow(embyCached.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4), providerId);
|
var content = await EmbyContentRepo.Get(item.Id.ToString());
|
||||||
//if (embyShow != null)
|
|
||||||
//{
|
if (content != null)
|
||||||
// viewT.Available = true;
|
{
|
||||||
//}
|
item.Available = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's go through the episodes now
|
||||||
|
if (item.SeasonRequests.Any())
|
||||||
|
{
|
||||||
|
var allEpisodes = EmbyContentRepo.GetAllEpisodes().Include(x => x.Series);
|
||||||
|
foreach (var season in item.SeasonRequests)
|
||||||
|
{
|
||||||
|
foreach (var episode in season.Episodes)
|
||||||
|
{
|
||||||
|
var epExists = await allEpisodes.FirstOrDefaultAsync(x =>
|
||||||
|
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber && item.Id.ToString() == x.Series.ProviderId);
|
||||||
|
if (epExists != null)
|
||||||
|
{
|
||||||
|
episode.Available = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (plexSettings.Enable)
|
if (plexSettings.Enable)
|
||||||
{
|
{
|
||||||
|
@ -190,6 +213,24 @@ namespace Ombi.Core.Engine
|
||||||
item.Available = true;
|
item.Available = true;
|
||||||
item.PlexUrl = content.Url;
|
item.PlexUrl = content.Url;
|
||||||
}
|
}
|
||||||
|
// Let's go through the episodes now
|
||||||
|
if (item.SeasonRequests.Any())
|
||||||
|
{
|
||||||
|
var allEpisodes = PlexContentRepo.GetAllEpisodes();
|
||||||
|
foreach (var season in item.SeasonRequests)
|
||||||
|
{
|
||||||
|
foreach (var episode in season.Episodes)
|
||||||
|
{
|
||||||
|
var epExists = await allEpisodes.FirstOrDefaultAsync(x =>
|
||||||
|
x.EpisodeNumber == episode.EpisodeNumber && x.SeasonNumber == season.SeasonNumber);
|
||||||
|
if (epExists != null)
|
||||||
|
{
|
||||||
|
episode.Available = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.Id > 0)
|
if (item.Id > 0)
|
||||||
|
|
|
@ -77,6 +77,12 @@ namespace Ombi.Schedule.Jobs.Emby
|
||||||
|
|
||||||
foreach (var ep in allEpisodes.Items)
|
foreach (var ep in allEpisodes.Items)
|
||||||
{
|
{
|
||||||
|
if (ep.LocationType.Equals("Virtual", StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
// This means that we don't actully have the file, it's just Emby being nice and showing future stuff
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var epInfo = await _api.GetEpisodeInformation(ep.Id, server.ApiKey, server.AdministratorId, server.FullUri);
|
var epInfo = await _api.GetEpisodeInformation(ep.Id, server.ApiKey, server.AdministratorId, server.FullUri);
|
||||||
if (epInfo?.ProviderIds?.Tvdb == null)
|
if (epInfo?.ProviderIds?.Tvdb == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -108,31 +108,8 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Linux
|
Logger.LogInformation(LoggingEvents.Updater, "We are linux");
|
||||||
if (desc.Contains("ubuntu", CompareOptions.IgnoreCase))
|
download = updates.Downloads.FirstOrDefault(x => x.Name.Contains("linux", CompareOptions.IgnoreCase));
|
||||||
{
|
|
||||||
// Ubuntu
|
|
||||||
Logger.LogInformation(LoggingEvents.Updater, "We are ubuntu");
|
|
||||||
download = updates.Downloads.FirstOrDefault(x => x.Name.Contains("ubuntu", CompareOptions.IgnoreCase));
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (desc.Contains("debian", CompareOptions.IgnoreCase))
|
|
||||||
{
|
|
||||||
// Debian
|
|
||||||
Logger.LogInformation(LoggingEvents.Updater, "We are debian");
|
|
||||||
download = updates.Downloads.FirstOrDefault(x => x.Name.Contains("debian", CompareOptions.IgnoreCase));
|
|
||||||
}
|
|
||||||
else if (desc.Contains("centos", CompareOptions.IgnoreCase))
|
|
||||||
{
|
|
||||||
// Centos
|
|
||||||
Logger.LogInformation(LoggingEvents.Updater, "We are centos");
|
|
||||||
download = updates.Downloads.FirstOrDefault(x => x.Name.Contains("centos",
|
|
||||||
CompareOptions.IgnoreCase));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (download == null)
|
if (download == null)
|
||||||
{
|
{
|
||||||
|
@ -201,7 +178,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
{
|
{
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
CreateNoWindow = true,
|
CreateNoWindow = true,
|
||||||
FileName = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location),"TempUpdate",$"Ombi.Updater{updaterExtension}"),
|
FileName = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "TempUpdate", $"Ombi.Updater{updaterExtension}"),
|
||||||
Arguments = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + " " + extension
|
Arguments = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + " " + extension
|
||||||
};
|
};
|
||||||
using (var proc = new Process { StartInfo = start })
|
using (var proc = new Process { StartInfo = start })
|
||||||
|
@ -212,7 +189,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Ctx.WriteLine(e);
|
Ctx.WriteLine(e);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace Ombi.Store.Entities
|
||||||
Url,
|
Url,
|
||||||
Port,
|
Port,
|
||||||
FanartTv,
|
FanartTv,
|
||||||
TheMovieDb
|
TheMovieDb,
|
||||||
|
StoragePath
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,6 +27,9 @@
|
||||||
<ul *ngIf="hasRole('Admin') || hasRole('PowerUser')" class="nav navbar-nav">
|
<ul *ngIf="hasRole('Admin') || hasRole('PowerUser')" class="nav navbar-nav">
|
||||||
<li id="UserManagement" [routerLinkActive]="['active']"><a [routerLink]="['/usermanagement']"><i class="fa fa-user"></i> User Management</a></li>
|
<li id="UserManagement" [routerLinkActive]="['active']"><a [routerLink]="['/usermanagement']"><i class="fa fa-user"></i> User Management</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li><a href="https://www.paypal.me/PlexRequestsNet" target="_blank"><i class="fa fa-heart" style="color:red"></i> Donate!</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
|
|
@ -14,6 +14,12 @@ export interface IPlexLibraries {
|
||||||
mediaContainer: IMediaContainer;
|
mediaContainer: IMediaContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IPlexLibResponse {
|
||||||
|
successful: boolean;
|
||||||
|
message: string;
|
||||||
|
data: IPlexLibraries;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IMediaContainer {
|
export interface IMediaContainer {
|
||||||
directory: IDirectory[];
|
directory: IDirectory[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,4 +137,5 @@ export interface IEpisodesRequests {
|
||||||
available: boolean;
|
available: boolean;
|
||||||
requested: boolean;
|
requested: boolean;
|
||||||
approved: boolean;
|
approved: boolean;
|
||||||
|
selected: boolean; // This is for the UI only
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<h3><i class="fa fa-bell-o"></i> <b>Notice</b></h3>
|
<h3><i class="fa fa-bell-o"></i> <b>Notice</b></h3>
|
||||||
<span [innerHtml]="landingPageSettings.noticeText"></span>
|
<span [innerHtml]="landingPageSettings.noticeText"></span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div *ngIf="mediaServerStatus">
|
||||||
<div *ngIf="mediaServerStatus.fullyAvailable">
|
<div *ngIf="mediaServerStatus.fullyAvailable">
|
||||||
<h3 class="online"><i class="fa fa-check-circle "></i> Currently Online</h3>
|
<h3 class="online"><i class="fa fa-check-circle "></i> Currently Online</h3>
|
||||||
<span>The media server is currently online</span>
|
<span>The media server is currently online</span>
|
||||||
|
|
|
@ -29,6 +29,8 @@ export class LandingPageComponent implements OnInit {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.landingPageService.getServerStatus().subscribe(x => this.mediaServerStatus = x);
|
this.landingPageService.getServerStatus().subscribe(x => {
|
||||||
|
this.mediaServerStatus = x;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ include the remember me checkbox
|
||||||
<div class="card card-container">
|
<div class="card card-container">
|
||||||
<!-- <img class="profile-img-card" src="//lh3.googleusercontent.com/-6V8xOA6M7BA/AAAAAAAAAAI/AAAAAAAAAAA/rzlHcD0KYwo/photo.jpg?sz=120" alt="" /> -->
|
<!-- <img class="profile-img-card" src="//lh3.googleusercontent.com/-6V8xOA6M7BA/AAAAAAAAAAI/AAAAAAAAAAA/rzlHcD0KYwo/photo.jpg?sz=120" alt="" /> -->
|
||||||
<div *ngIf="!customizationSettings.logo"><img id="profile-img" class="profile-img-card" src="/images/ms-icon-150x150.png" /></div>
|
<div *ngIf="!customizationSettings.logo"><img id="profile-img" class="profile-img-card" src="/images/ms-icon-150x150.png" /></div>
|
||||||
<div *ngIf="customizationSettings.logo"><img id="profile-img" class="profile-img-card" [src]="customizationSettings.logo" /></div>
|
<div *ngIf="customizationSettings.logo"><img id="profile-img" class="profile-img-custom" [src]="customizationSettings.logo" /></div>
|
||||||
<p id="profile-name" class="profile-name-card"></p>
|
<p id="profile-name" class="profile-name-card"></p>
|
||||||
|
|
||||||
<form class="form-signin" novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
|
<form class="form-signin" novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
|
||||||
|
|
|
@ -14,7 +14,6 @@ body, html {
|
||||||
height: 100% !important;
|
height: 100% !important;
|
||||||
background-repeat: no-repeat !important;
|
background-repeat: no-repeat !important;
|
||||||
background-image: linear-gradient(rgb(104, 145, 162), rgb(12, 97, 33)) !important;
|
background-image: linear-gradient(rgb(104, 145, 162), rgb(12, 97, 33)) !important;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
landingDiv {
|
landingDiv {
|
||||||
|
@ -52,138 +51,147 @@ img.bg {
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%,-50%);
|
transform: translate(-50%,-50%);
|
||||||
width:100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Card component
|
* Card component
|
||||||
*/
|
*/
|
||||||
.card {
|
.card {
|
||||||
/*background-image: linear-gradient(rgb(104, 145, 162), rgb(12, 97, 33)) !important;*/
|
/*background-image: linear-gradient(rgb(104, 145, 162), rgb(12, 97, 33)) !important;*/
|
||||||
background-color: $bg-colour;
|
background-color: $bg-colour;
|
||||||
/* just in case there no content*/
|
/* just in case there no content*/
|
||||||
padding: 20px 25px 30px;
|
padding: 20px 25px 30px;
|
||||||
margin: 0 auto 25px;
|
margin: 0 auto 25px;
|
||||||
margin-top: 50px;
|
margin-top: 50px;
|
||||||
/* shadows and rounded borders */
|
/* shadows and rounded borders */
|
||||||
-moz-border-radius: 2px;
|
-moz-border-radius: 2px;
|
||||||
-webkit-border-radius: 2px;
|
-webkit-border-radius: 2px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
/*-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
|
/*-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
|
||||||
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
|
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
|
||||||
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);*/
|
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-img-card {
|
.profile-img-custom {
|
||||||
width: 96px;
|
width: 100%;
|
||||||
height: 96px;
|
margin: 0 auto 10px;
|
||||||
margin: 0 auto 10px;
|
display: block;
|
||||||
display: block;
|
-moz-border-radius: 50%;
|
||||||
-moz-border-radius: 50%;
|
-webkit-border-radius: 50%;
|
||||||
-webkit-border-radius: 50%;
|
border-radius: 50%;
|
||||||
border-radius: 50%;
|
}
|
||||||
}
|
|
||||||
/*
|
.profile-img-card {
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
margin: 0 auto 10px;
|
||||||
|
display: block;
|
||||||
|
-moz-border-radius: 50%;
|
||||||
|
-webkit-border-radius: 50%;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
/*
|
||||||
* Form styles
|
* Form styles
|
||||||
*/
|
*/
|
||||||
.profile-name-card {
|
.profile-name-card {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 10px 0 0;
|
margin: 10px 0 0;
|
||||||
min-height: 1em;
|
min-height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-control {
|
.form-control {
|
||||||
color: black;
|
color: black;
|
||||||
background-color: white !important;
|
background-color: white !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reauth-email {
|
.reauth-email {
|
||||||
display: block;
|
display: block;
|
||||||
color: white;
|
color: white;
|
||||||
line-height: 2;
|
line-height: 2;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-signin #inputEmail,
|
.form-signin #inputEmail,
|
||||||
.form-signin #inputPassword {
|
.form-signin #inputPassword {
|
||||||
direction: ltr;
|
direction: ltr;
|
||||||
height: 44px;
|
height: 44px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-signin input[type=email],
|
.form-signin input[type=email],
|
||||||
.form-signin input[type=password],
|
.form-signin input[type=password],
|
||||||
.form-signin input[type=text],
|
.form-signin input[type=text],
|
||||||
.form-signin button {
|
.form-signin button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.btn.btn-signin {
|
.btn.btn-signin {
|
||||||
/*background-color: #4d90fe; */
|
/*background-color: #4d90fe; */
|
||||||
background-color: rgb(104, 145, 162);
|
background-color: rgb(104, 145, 162);
|
||||||
/* background-color: linear-gradient(rgb(104, 145, 162), rgb(12, 97, 33));*/
|
/* background-color: linear-gradient(rgb(104, 145, 162), rgb(12, 97, 33));*/
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
-moz-border-radius: 3px;
|
-moz-border-radius: 3px;
|
||||||
-webkit-border-radius: 3px;
|
-webkit-border-radius: 3px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border: none;
|
border: none;
|
||||||
-o-transition: all 0.218s;
|
-o-transition: all 0.218s;
|
||||||
-moz-transition: all 0.218s;
|
-moz-transition: all 0.218s;
|
||||||
-webkit-transition: all 0.218s;
|
-webkit-transition: all 0.218s;
|
||||||
transition: all 0.218s;
|
transition: all 0.218s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn.btn-signin:hover,
|
.btn.btn-signin:hover,
|
||||||
.btn.btn-signin:active,
|
.btn.btn-signin:active,
|
||||||
.btn.btn-signin:focus {
|
.btn.btn-signin:focus {
|
||||||
background-color: rgb(12, 97, 33);
|
background-color: rgb(12, 97, 33);
|
||||||
}
|
}
|
||||||
|
|
||||||
.forgot-password {
|
.forgot-password {
|
||||||
color: rgb(104, 145, 162);
|
color: rgb(104, 145, 162);
|
||||||
text-align:center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.forgot-password:hover,
|
.forgot-password:hover,
|
||||||
.forgot-password:active,
|
.forgot-password:active,
|
||||||
.forgot-password:focus {
|
.forgot-password:focus {
|
||||||
color: rgb(12, 97, 33);
|
color: rgb(12, 97, 33);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Placeholders
|
// Placeholders
|
||||||
|
|
||||||
::-webkit-input-placeholder { /* WebKit, Blink, Edge */
|
::-webkit-input-placeholder { /* WebKit, Blink, Edge */
|
||||||
color: $placeholder-colour;
|
color: $placeholder-colour;
|
||||||
|
@ -205,4 +213,4 @@ img.bg {
|
||||||
|
|
||||||
::-ms-input-placeholder { /* Microsoft Edge */
|
::-ms-input-placeholder { /* Microsoft Edge */
|
||||||
color: $placeholder-colour;
|
color: $placeholder-colour;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import "rxjs/add/operator/debounceTime";
|
import "rxjs/add/operator/debounceTime";
|
||||||
import "rxjs/add/operator/distinctUntilChanged";
|
import "rxjs/add/operator/distinctUntilChanged";
|
||||||
import "rxjs/add/operator/map";
|
import "rxjs/add/operator/map";
|
||||||
import "rxjs/add/operator/takeUntil";
|
|
||||||
import { Subject } from "rxjs/Subject";
|
import { Subject } from "rxjs/Subject";
|
||||||
|
|
||||||
import "rxjs/add/operator/debounceTime";
|
|
||||||
import "rxjs/add/operator/distinctUntilChanged";
|
|
||||||
import "rxjs/add/operator/map";
|
|
||||||
|
|
||||||
import { AuthService } from "../auth/auth.service";
|
import { AuthService } from "../auth/auth.service";
|
||||||
import { RequestService } from "../services";
|
import { NotificationService, RequestService } from "../services";
|
||||||
|
|
||||||
import { IMovieRequests } from "../interfaces";
|
import { IMovieRequests } from "../interfaces";
|
||||||
|
|
||||||
|
@ -18,7 +13,7 @@ import { IMovieRequests } from "../interfaces";
|
||||||
selector: "movie-requests",
|
selector: "movie-requests",
|
||||||
templateUrl: "./movierequests.component.html",
|
templateUrl: "./movierequests.component.html",
|
||||||
})
|
})
|
||||||
export class MovieRequestsComponent implements OnInit, OnDestroy {
|
export class MovieRequestsComponent implements OnInit {
|
||||||
public movieRequests: IMovieRequests[];
|
public movieRequests: IMovieRequests[];
|
||||||
|
|
||||||
public searchChanged: Subject<string> = new Subject<string>();
|
public searchChanged: Subject<string> = new Subject<string>();
|
||||||
|
@ -29,14 +24,12 @@ export class MovieRequestsComponent implements OnInit, OnDestroy {
|
||||||
private currentlyLoaded: number;
|
private currentlyLoaded: number;
|
||||||
private amountToLoad: number;
|
private amountToLoad: number;
|
||||||
|
|
||||||
private subscriptions = new Subject<void>();
|
|
||||||
|
|
||||||
constructor(private requestService: RequestService,
|
constructor(private requestService: RequestService,
|
||||||
private auth: AuthService) {
|
private auth: AuthService,
|
||||||
|
private notificationService: NotificationService) {
|
||||||
this.searchChanged
|
this.searchChanged
|
||||||
.debounceTime(600) // Wait Xms afterthe last event before emitting last event
|
.debounceTime(600) // Wait Xms after the last event before emitting last event
|
||||||
.distinctUntilChanged() // only emit if value is different from previous value
|
.distinctUntilChanged() // only emit if value is different from previous value
|
||||||
.takeUntil(this.subscriptions)
|
|
||||||
.subscribe(x => {
|
.subscribe(x => {
|
||||||
this.searchText = x as string;
|
this.searchText = x as string;
|
||||||
if (this.searchText === "") {
|
if (this.searchText === "") {
|
||||||
|
@ -44,7 +37,6 @@ export class MovieRequestsComponent implements OnInit, OnDestroy {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.requestService.searchMovieRequests(this.searchText)
|
this.requestService.searchMovieRequests(this.searchText)
|
||||||
.takeUntil(this.subscriptions)
|
|
||||||
.subscribe(m => this.movieRequests = m);
|
.subscribe(m => this.movieRequests = m);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -79,7 +71,7 @@ export class MovieRequestsComponent implements OnInit, OnDestroy {
|
||||||
public approve(request: IMovieRequests) {
|
public approve(request: IMovieRequests) {
|
||||||
request.approved = true;
|
request.approved = true;
|
||||||
request.denied = false;
|
request.denied = false;
|
||||||
this.updateRequest(request);
|
this.approveRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public deny(request: IMovieRequests) {
|
public deny(request: IMovieRequests) {
|
||||||
|
@ -88,14 +80,8 @@ export class MovieRequestsComponent implements OnInit, OnDestroy {
|
||||||
this.updateRequest(request);
|
this.updateRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnDestroy() {
|
|
||||||
this.subscriptions.next();
|
|
||||||
this.subscriptions.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
private loadRequests(amountToLoad: number, currentlyLoaded: number) {
|
private loadRequests(amountToLoad: number, currentlyLoaded: number) {
|
||||||
this.requestService.getMovieRequests(amountToLoad, currentlyLoaded + 1)
|
this.requestService.getMovieRequests(amountToLoad, currentlyLoaded + 1)
|
||||||
.takeUntil(this.subscriptions)
|
|
||||||
.subscribe(x => {
|
.subscribe(x => {
|
||||||
this.movieRequests.push.apply(this.movieRequests, x);
|
this.movieRequests.push.apply(this.movieRequests, x);
|
||||||
this.currentlyLoaded = currentlyLoaded + amountToLoad;
|
this.currentlyLoaded = currentlyLoaded + amountToLoad;
|
||||||
|
@ -104,13 +90,25 @@ export class MovieRequestsComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
private updateRequest(request: IMovieRequests) {
|
private updateRequest(request: IMovieRequests) {
|
||||||
this.requestService.updateMovieRequest(request)
|
this.requestService.updateMovieRequest(request)
|
||||||
.takeUntil(this.subscriptions)
|
|
||||||
.subscribe(x => request = x);
|
.subscribe(x => request = x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private approveRequest(request: IMovieRequests) {
|
||||||
|
this.requestService.approveMovie(request)
|
||||||
|
.subscribe(x => {
|
||||||
|
|
||||||
|
if (x.requestAdded) {
|
||||||
|
this.notificationService.success("Request Approved",
|
||||||
|
`Request for ${request.title} has been approved successfully`);
|
||||||
|
} else {
|
||||||
|
this.notificationService.warning("Request Approved", x.message ? x.message : x.errorMessage);
|
||||||
|
request.approved = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private loadInit() {
|
private loadInit() {
|
||||||
this.requestService.getMovieRequests(this.amountToLoad, 0)
|
this.requestService.getMovieRequests(this.amountToLoad, 0)
|
||||||
.takeUntil(this.subscriptions)
|
|
||||||
.subscribe(x => this.movieRequests = x);
|
.subscribe(x => this.movieRequests = x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,13 @@
|
||||||
|
|
||||||
<div class="col-md-1 col-md-push-9" *ngIf="isAdmin">
|
<div class="col-md-1 col-md-push-9" *ngIf="isAdmin">
|
||||||
<form>
|
<form>
|
||||||
<button style="text-align: right" *ngIf="child.CanApprove" (click)="approve(child)" class="btn btn-sm btn-success-outline" type="submit"><i class="fa fa-plus"></i> Approve</button>
|
<button style="text-align: right" *ngIf="child.canApprove && !child.approved" (click)="approve(child)" class="btn btn-sm btn-success-outline" type="submit"><i class="fa fa-plus"></i> Approve</button>
|
||||||
</form>
|
</form>
|
||||||
<form>
|
<form>
|
||||||
<button type="button" (click)="deny(child)" class="btn btn-sm btn-danger-outline deny"><i class="fa fa-times"></i> Deny</button>
|
<button type="button" (click)="deny(child)" class="btn btn-sm btn-danger-outline deny"><i class="fa fa-times"></i> Deny</button>
|
||||||
</form>
|
</form>
|
||||||
<form>
|
<form>
|
||||||
<button type="button" (click)="deny(child)" class="btn btn-sm btn-danger-outline deny"><i class="fa fa-times"></i> Remove</button>
|
<button type="button" (click)="removeRequest(child)" class="btn btn-sm btn-danger-outline deny"><i class="fa fa-times"></i> Remove</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
<span *ngIf="ep.available" class="label label-success">Available</span>
|
<span *ngIf="ep.available" class="label label-success">Available</span>
|
||||||
<span *ngIf="ep.approved && !ep.available" class="label label-info">Processing Request</span>
|
<span *ngIf="ep.approved && !ep.available" class="label label-info">Processing Request</span>
|
||||||
<div *ngIf="!ep.approved">
|
<div *ngIf="!ep.approved">
|
||||||
<div *ngIf="!ep.available"><span class="label label-warning">Pending Approval</span></div>
|
<div *ngIf="!ep.available"><span class="label label-warning">Pending Approval</span></div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Component, Input } from "@angular/core";
|
import { Component, Input } from "@angular/core";
|
||||||
import { IChildRequests, IEpisodesRequests } from "../interfaces";
|
import { IChildRequests, IEpisodesRequests } from "../interfaces";
|
||||||
import { RequestService } from "../services";
|
import { NotificationService, RequestService } from "../services";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector:"tvrequests-children",
|
selector:"tvrequests-children",
|
||||||
|
@ -9,7 +9,9 @@ import { RequestService } from "../services";
|
||||||
export class TvRequestChildrenComponent {
|
export class TvRequestChildrenComponent {
|
||||||
@Input() public childRequests: IChildRequests[];
|
@Input() public childRequests: IChildRequests[];
|
||||||
@Input() public isAdmin: boolean;
|
@Input() public isAdmin: boolean;
|
||||||
constructor(private requestService: RequestService ) { }
|
constructor(private requestService: RequestService,
|
||||||
|
private notificationService: NotificationService) { }
|
||||||
|
|
||||||
public removeRequest(request: IChildRequests) {
|
public removeRequest(request: IChildRequests) {
|
||||||
this.requestService.deleteChild(request)
|
this.requestService.deleteChild(request)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
@ -36,8 +38,21 @@ export class TvRequestChildrenComponent {
|
||||||
public approve(request: IChildRequests) {
|
public approve(request: IChildRequests) {
|
||||||
request.approved = true;
|
request.approved = true;
|
||||||
request.denied = false;
|
request.denied = false;
|
||||||
this.requestService.updateChild(request)
|
request.seasonRequests.forEach((season) => {
|
||||||
.subscribe();
|
season.episodes.forEach((ep) => {
|
||||||
|
ep.approved = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.requestService.approveChild(request)
|
||||||
|
.subscribe(x => {
|
||||||
|
if (x.requestAdded) {
|
||||||
|
this.notificationService.success("Request Approved",
|
||||||
|
`Request has been approved successfully`);
|
||||||
|
} else {
|
||||||
|
this.notificationService.warning("Request Approved", x.message ? x.message : x.errorMessage);
|
||||||
|
request.approved = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public denySeasonRequest(request: IChildRequests) {
|
public denySeasonRequest(request: IChildRequests) {
|
||||||
|
|
|
@ -19,11 +19,6 @@
|
||||||
(scrolled)="loadMore()">-->
|
(scrolled)="loadMore()">-->
|
||||||
<div>
|
<div>
|
||||||
<p-treeTable [value]="tvRequests">
|
<p-treeTable [value]="tvRequests">
|
||||||
<!--<p-column>
|
|
||||||
<ng-template let-col let-node="rowData" pTemplate="body">
|
|
||||||
<img src="{{node.data.data.banner}}" class="img-responsive poster" width="150" />
|
|
||||||
</ng-template>
|
|
||||||
</p-column>-->
|
|
||||||
|
|
||||||
<p-column>
|
<p-column>
|
||||||
<ng-template let-col let-node="rowData" pTemplate="header">
|
<ng-template let-col let-node="rowData" pTemplate="header">
|
||||||
|
@ -63,7 +58,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!--This is the section that holds the child seasons if they want to specify specific episodes-->
|
<!--This is the section that holds the child seasons if they want to specify specific episodes-->
|
||||||
<div *ngIf="node.leaf">
|
<div *ngIf="node.leaf">
|
||||||
<tvrequests-children [childRequests]="node.data" [isAdmin] ="isAdmin"></tvrequests-children>
|
<tvrequests-children [childRequests]="node.data" [isAdmin] ="isAdmin" ></tvrequests-children>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</p-column>
|
</p-column>
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { Component, OnDestroy, OnInit, ViewEncapsulation } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import "rxjs/add/operator/debounceTime";
|
import "rxjs/add/operator/debounceTime";
|
||||||
import "rxjs/add/operator/distinctUntilChanged";
|
import "rxjs/add/operator/distinctUntilChanged";
|
||||||
import "rxjs/add/operator/map";
|
import "rxjs/add/operator/map";
|
||||||
import "rxjs/add/operator/takeUntil";
|
|
||||||
import { Subject } from "rxjs/Subject";
|
import { Subject } from "rxjs/Subject";
|
||||||
|
|
||||||
import "rxjs/add/operator/debounceTime";
|
import "rxjs/add/operator/debounceTime";
|
||||||
|
@ -13,18 +12,14 @@ import { AuthService } from "../auth/auth.service";
|
||||||
import { RequestService } from "../services";
|
import { RequestService } from "../services";
|
||||||
|
|
||||||
import { TreeNode } from "primeng/primeng";
|
import { TreeNode } from "primeng/primeng";
|
||||||
import { IChildRequests, IEpisodesRequests, INewSeasonRequests, ITvRequests } from "../interfaces";
|
import { ITvRequests } from "../interfaces";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "tv-requests",
|
selector: "tv-requests",
|
||||||
templateUrl: "./tvrequests.component.html",
|
templateUrl: "./tvrequests.component.html",
|
||||||
styleUrls: ["./tvrequests.component.scss"],
|
styleUrls: ["./tvrequests.component.scss"],
|
||||||
//Was required to turn off encapsulation since CSS only should be overridden for this component
|
|
||||||
//However when encapsulation is on angular injects prefixes to all classes so css selectors
|
|
||||||
//Stop working
|
|
||||||
encapsulation: ViewEncapsulation.None,
|
|
||||||
})
|
})
|
||||||
export class TvRequestsComponent implements OnInit, OnDestroy {
|
export class TvRequestsComponent implements OnInit {
|
||||||
|
|
||||||
public tvRequests: TreeNode[];
|
public tvRequests: TreeNode[];
|
||||||
public searchChanged = new Subject<string>();
|
public searchChanged = new Subject<string>();
|
||||||
|
@ -35,23 +30,20 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
private currentlyLoaded: number;
|
private currentlyLoaded: number;
|
||||||
private amountToLoad: number;
|
private amountToLoad: number;
|
||||||
private subscriptions = new Subject<void>();
|
|
||||||
|
|
||||||
constructor(private requestService: RequestService,
|
constructor(private requestService: RequestService,
|
||||||
private auth: AuthService) {
|
private auth: AuthService) {
|
||||||
this.searchChanged
|
this.searchChanged
|
||||||
.debounceTime(600) // Wait Xms afterthe last event before emitting last event
|
.debounceTime(600) // Wait Xms afterthe last event before emitting last event
|
||||||
.distinctUntilChanged() // only emit if value is different from previous value
|
.distinctUntilChanged() // only emit if value is different from previous value
|
||||||
.takeUntil(this.subscriptions)
|
|
||||||
.subscribe(x => {
|
.subscribe(x => {
|
||||||
this.searchText = x as string;
|
this.searchText = x as string;
|
||||||
if (this.searchText === "") {
|
if (this.searchText === "") {
|
||||||
this.resetSearch();
|
this.resetSearch();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.requestService.searchTvRequests(this.searchText)
|
this.requestService.searchTvRequestsTree(this.searchText)
|
||||||
.takeUntil(this.subscriptions)
|
.subscribe(m => this.tvRequests = m);
|
||||||
.subscribe(m => this.tvRequests = this.transformData(m));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public openClosestTab(el: any) {
|
public openClosestTab(el: any) {
|
||||||
|
@ -78,30 +70,7 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public transformData(data: ITvRequests[]): TreeNode[] {
|
|
||||||
const temp: TreeNode[] = [];
|
|
||||||
data.forEach((value) => {
|
|
||||||
temp.push({
|
|
||||||
data: value,
|
|
||||||
children: [{
|
|
||||||
data: this.fixEpisodeSort(value.childRequests), leaf: true,
|
|
||||||
}],
|
|
||||||
leaf: false,
|
|
||||||
});
|
|
||||||
}, this);
|
|
||||||
return <TreeNode[]>temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public fixEpisodeSort(items: IChildRequests[]) {
|
|
||||||
items.forEach((value) => {
|
|
||||||
value.seasonRequests.forEach((requests: INewSeasonRequests) => {
|
|
||||||
requests.episodes.sort((a: IEpisodesRequests, b: IEpisodesRequests) => {
|
|
||||||
return a.episodeNumber - b.episodeNumber;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
this.amountToLoad = 1000;
|
this.amountToLoad = 1000;
|
||||||
this.currentlyLoaded = 5;
|
this.currentlyLoaded = 5;
|
||||||
|
@ -116,10 +85,9 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
|
||||||
//if you scroll really quickly then you start getting duplicates of movies
|
//if you scroll really quickly then you start getting duplicates of movies
|
||||||
//since it's async and some subsequent results return first and then incrementer
|
//since it's async and some subsequent results return first and then incrementer
|
||||||
//is increased so you see movies which had already been gotten show up...
|
//is increased so you see movies which had already been gotten show up...
|
||||||
this.requestService.getTvRequests(this.amountToLoad, this.currentlyLoaded + 1)
|
this.requestService.getTvRequestsTree(this.amountToLoad, this.currentlyLoaded + 1)
|
||||||
.takeUntil(this.subscriptions)
|
|
||||||
.subscribe(x => {
|
.subscribe(x => {
|
||||||
this.tvRequests.push.apply(this.tvRequests, this.transformData(x));
|
this.tvRequests = x;
|
||||||
this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad;
|
this.currentlyLoaded = this.currentlyLoaded + this.amountToLoad;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -128,87 +96,15 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
|
||||||
this.searchChanged.next(text.target.value);
|
this.searchChanged.next(text.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeRequest(request: ITvRequests) {
|
|
||||||
this.requestService.removeTvRequest(request);
|
|
||||||
this.removeRequestFromUi(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public changeAvailability(request: IChildRequests, available: boolean) {
|
|
||||||
request.available = available;
|
|
||||||
|
|
||||||
//this.updateRequest(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Was already here but not sure what's using it...'
|
|
||||||
//public approve(request: IChildRequests) {
|
|
||||||
// request.approved = true;
|
|
||||||
// request.denied = false;
|
|
||||||
// //this.updateRequest(request);
|
|
||||||
//}
|
|
||||||
public approve(request: IChildRequests) {
|
|
||||||
request.approved = true;
|
|
||||||
request.denied = false;
|
|
||||||
this.requestService.updateChild(request)
|
|
||||||
.subscribe();
|
|
||||||
}
|
|
||||||
//Was already here but not sure what's using it...'
|
|
||||||
//public deny(request: IChildRequests) {
|
|
||||||
// request.approved = false;
|
|
||||||
// request.denied = true;
|
|
||||||
// //this.updateRequest(request);
|
|
||||||
//}
|
|
||||||
public deny(request: IChildRequests) {
|
|
||||||
request.approved = false;
|
|
||||||
request.denied = true;
|
|
||||||
this.requestService.updateChild(request)
|
|
||||||
.subscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
public approveSeasonRequest(request: IChildRequests) {
|
|
||||||
request.approved = true;
|
|
||||||
request.denied = false;
|
|
||||||
this.requestService.updateTvRequest(this.selectedSeason)
|
|
||||||
.subscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
public denySeasonRequest(request: IChildRequests) {
|
|
||||||
request.approved = false;
|
|
||||||
request.denied = true;
|
|
||||||
this.requestService.updateTvRequest(this.selectedSeason)
|
|
||||||
.subscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
public showChildren(request: ITvRequests) {
|
public showChildren(request: ITvRequests) {
|
||||||
this.selectedSeason = request;
|
this.selectedSeason = request;
|
||||||
this.showChildDialogue = true;
|
this.showChildDialogue = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getColour(ep: IEpisodesRequests): string {
|
|
||||||
if (ep.available) {
|
|
||||||
return "lime";
|
|
||||||
}
|
|
||||||
if (ep.approved) {
|
|
||||||
return "#00c0ff";
|
|
||||||
}
|
|
||||||
return "white";
|
|
||||||
}
|
|
||||||
|
|
||||||
public ngOnDestroy() {
|
|
||||||
this.subscriptions.next();
|
|
||||||
this.subscriptions.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
//private updateRequest(request: ITvRequests) {
|
|
||||||
// this.requestService.updateTvRequest(request)
|
|
||||||
// .takeUntil(this.subscriptions)
|
|
||||||
// .subscribe(x => request = x);
|
|
||||||
//}
|
|
||||||
|
|
||||||
private loadInit() {
|
private loadInit() {
|
||||||
this.requestService.getTvRequests(this.amountToLoad, 0)
|
this.requestService.getTvRequestsTree(this.amountToLoad, 0)
|
||||||
.takeUntil(this.subscriptions)
|
|
||||||
.subscribe(x => {
|
.subscribe(x => {
|
||||||
this.tvRequests = this.transformData(x);
|
this.tvRequests = x;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,11 +112,4 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
|
||||||
this.currentlyLoaded = 5;
|
this.currentlyLoaded = 5;
|
||||||
this.loadInit();
|
this.loadInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeRequestFromUi(key: ITvRequests) {
|
|
||||||
const index = this.tvRequests.findIndex(x => x.data === key);
|
|
||||||
if (index > -1) {
|
|
||||||
this.tvRequests.splice(index, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,14 +55,15 @@
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ng-template [ngIf]="ep.available"><span class="label label-success">Available</span></ng-template>
|
<ng-template [ngIf]="ep.available"><span class="label label-success">Available</span></ng-template>
|
||||||
<ng-template [ngIf]="ep.approved && !ep.available"><span class="label label-info">Processing Request</span></ng-template>
|
<ng-template [ngIf]="ep.approved && !ep.available "><span class="label label-info">Processing Request</span></ng-template>
|
||||||
<ng-template [ngIf]="ep.requested && !ep.approved && !ep.available"><span class="label label-warning">Pending Approval</span></ng-template>
|
<ng-template [ngIf]="ep.selected"><span class="label label-info">Selected</span></ng-template>
|
||||||
|
<ng-template [ngIf]="ep.requested && !ep.approved && !ep.available && !ep.selected"><span class="label label-warning">Pending Approval</span></ng-template>
|
||||||
<ng-template [ngIf]="!ep.requested && !ep.available"><span class="label label-danger">Not Requested</span></ng-template>
|
<ng-template [ngIf]="!ep.requested && !ep.available"><span class="label label-danger">Not Requested</span></ng-template>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
<button *ngIf="!ep.selected" (click)="addRequest(ep)" [disabled]="ep.available || ep.requested || ep.approved" class="btn btn-sm btn-primary-outline">Select</button>
|
||||||
<button (click)="addRequest(ep)" [disabled]="ep.available || ep.requested || ep.approved" class="btn btn-sm btn-primary-outline">Add Request</button>
|
<button *ngIf="ep.selected" (click)="removeRequest(ep)" class="btn btn-sm btn-primary-outline">Unselect</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -54,10 +54,12 @@ export class SeriesInformationComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
public addRequest(episode: IEpisodesRequests) {
|
public addRequest(episode: IEpisodesRequests) {
|
||||||
episode.requested = true;
|
episode.requested = true;
|
||||||
|
episode.selected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeRequest(episode: IEpisodesRequests) {
|
public removeRequest(episode: IEpisodesRequests) {
|
||||||
episode.requested = false;
|
episode.requested = false;
|
||||||
|
episode.selected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnDestroy() {
|
public ngOnDestroy() {
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
<span *ngIf="node.data.firstAired" class="label label-info" target="_blank">Air Date: {{node.data.firstAired | date: 'dd/MM/yyyy'}}</span>
|
<span *ngIf="node.data.firstAired" class="label label-info" target="_blank">Air Date: {{node.data.firstAired | date: 'dd/MM/yyyy'}}</span>
|
||||||
|
|
||||||
|
|
||||||
<ng-template [ngIf]="result.available"><span class="label label-success">Available</span></ng-template>
|
<ng-template [ngIf]="node.data.available"><span class="label label-success">Available</span></ng-template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { Observable } from "rxjs/Rx";
|
||||||
|
|
||||||
import { ServiceAuthHelpers } from "../service.helpers";
|
import { ServiceAuthHelpers } from "../service.helpers";
|
||||||
|
|
||||||
import { IPlexAuthentication, IPlexLibraries, IPlexServerViewModel } from "../../interfaces";
|
import { IPlexAuthentication, IPlexLibResponse, IPlexServerViewModel } from "../../interfaces";
|
||||||
import { IPlexServer } from "../../interfaces";
|
import { IPlexServer } from "../../interfaces";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -23,7 +23,7 @@ export class PlexService extends ServiceAuthHelpers {
|
||||||
return this.http.post(`${this.url}servers`, JSON.stringify({ login, password }), { headers: this.headers }).map(this.extractData);
|
return this.http.post(`${this.url}servers`, JSON.stringify({ login, password }), { headers: this.headers }).map(this.extractData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getLibraries(plexSettings: IPlexServer): Observable<IPlexLibraries> {
|
public getLibraries(plexSettings: IPlexServer): Observable<IPlexLibResponse> {
|
||||||
return this.http.post(`${this.url}Libraries`, JSON.stringify(plexSettings), { headers: this.headers }).map(this.extractData).catch(this.handleError);
|
return this.http.post(`${this.url}Libraries`, JSON.stringify(plexSettings), { headers: this.headers }).map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { Http } from "@angular/http";
|
||||||
import { AuthHttp } from "angular2-jwt";
|
import { AuthHttp } from "angular2-jwt";
|
||||||
import { Observable } from "rxjs/Rx";
|
import { Observable } from "rxjs/Rx";
|
||||||
|
|
||||||
|
import { TreeNode } from "primeng/primeng";
|
||||||
import { IRequestEngineResult } from "../interfaces";
|
import { IRequestEngineResult } from "../interfaces";
|
||||||
import { IChildRequests, IMovieRequests, IRequestCountModel, IRequestGrid, ITvRequests } from "../interfaces";
|
import { IChildRequests, IMovieRequests, IRequestCountModel, IRequestGrid, ITvRequests } from "../interfaces";
|
||||||
import { ISearchMovieResult } from "../interfaces";
|
import { ISearchMovieResult } from "../interfaces";
|
||||||
|
@ -23,6 +24,10 @@ export class RequestService extends ServiceAuthHelpers {
|
||||||
return this.http.post(`${this.url}TV/`, JSON.stringify(tv), { headers: this.headers }).map(this.extractData);
|
return this.http.post(`${this.url}TV/`, JSON.stringify(tv), { headers: this.headers }).map(this.extractData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public approveMovie(movie: IMovieRequests): Observable<IRequestEngineResult> {
|
||||||
|
return this.http.post(`${this.url}Movie/Approve`, JSON.stringify(movie), { headers: this.headers }).map(this.extractData);
|
||||||
|
}
|
||||||
|
|
||||||
public getMovieRequests(count: number, position: number): Observable<IMovieRequests[]> {
|
public getMovieRequests(count: number, position: number): Observable<IMovieRequests[]> {
|
||||||
return this.http.get(`${this.url}movie/${count}/${position}`).map(this.extractData);
|
return this.http.get(`${this.url}movie/${count}/${position}`).map(this.extractData);
|
||||||
}
|
}
|
||||||
|
@ -44,6 +49,11 @@ export class RequestService extends ServiceAuthHelpers {
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getTvRequestsTree(count: number, position: number): Observable<TreeNode[]> {
|
||||||
|
return this.http.get(`${this.url}tv/${count}/${position}/tree`).map(this.extractData)
|
||||||
|
.catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
public getChildRequests(requestId: number): Observable<IChildRequests[]> {
|
public getChildRequests(requestId: number): Observable<IChildRequests[]> {
|
||||||
return this.http.get(`${this.url}tv/${requestId}/child`).map(this.extractData)
|
return this.http.get(`${this.url}tv/${requestId}/child`).map(this.extractData)
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
|
@ -51,6 +61,10 @@ export class RequestService extends ServiceAuthHelpers {
|
||||||
|
|
||||||
public searchTvRequests(search: string): Observable<ITvRequests[]> {
|
public searchTvRequests(search: string): Observable<ITvRequests[]> {
|
||||||
return this.http.get(`${this.url}tv/search/${search}`).map(this.extractData);
|
return this.http.get(`${this.url}tv/search/${search}`).map(this.extractData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public searchTvRequestsTree(search: string): Observable<TreeNode[]> {
|
||||||
|
return this.http.get(`${this.url}tv/search/${search}/tree`).map(this.extractData);
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeTvRequest(request: ITvRequests) {
|
public removeTvRequest(request: ITvRequests) {
|
||||||
|
@ -62,6 +76,9 @@ export class RequestService extends ServiceAuthHelpers {
|
||||||
}
|
}
|
||||||
public updateChild(child: IChildRequests): Observable<IChildRequests> {
|
public updateChild(child: IChildRequests): Observable<IChildRequests> {
|
||||||
return this.http.put(`${this.url}tv/child`, JSON.stringify(child), { headers: this.headers }).map(this.extractData);
|
return this.http.put(`${this.url}tv/child`, JSON.stringify(child), { headers: this.headers }).map(this.extractData);
|
||||||
|
}
|
||||||
|
public approveChild(child: IChildRequests): Observable<IRequestEngineResult> {
|
||||||
|
return this.http.post(`${this.url}tv/child/approve`, JSON.stringify(child), { headers: this.headers }).map(this.extractData);
|
||||||
}
|
}
|
||||||
public deleteChild(child: IChildRequests): Observable<IChildRequests> {
|
public deleteChild(child: IChildRequests): Observable<IChildRequests> {
|
||||||
return this.http.delete(`${this.url}tv/child/${child.id}`, { headers: this.headers }).map(this.extractData);
|
return this.http.delete(`${this.url}tv/child/${child.id}`, { headers: this.headers }).map(this.extractData);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Headers, Http, Response } from "@angular/http";
|
import { Headers, Http, Response } from "@angular/http";
|
||||||
|
import "rxjs/add/observable/throw";
|
||||||
import { Observable } from "rxjs/Observable";
|
import { Observable } from "rxjs/Observable";
|
||||||
|
|
||||||
import { AuthHttp } from "angular2-jwt";
|
import { AuthHttp } from "angular2-jwt";
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
<ng-template ngbTabContent>
|
<ng-template ngbTabContent>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<div class="col-md-2 " style="float: right;">
|
<div class="col-md-2" style="float: right;">
|
||||||
<button type="submit" (click)="removeServer(server)" class="btn btn-danger-outline">Remove Server</button>
|
<button type="submit" (click)="removeServer(server)" class="btn btn-danger-outline">Remove Server</button>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
|
@ -76,23 +76,20 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div>
|
<div>
|
||||||
<button id="testPlex" type="submit" (click)="test()" class="btn btn-primary-outline">Test Connectivity <div id="spinner"></div></button>
|
<button id="testEmby" type="submit" (click)="test()" class="btn btn-primary-outline">Test Connectivity <div id="spinner"></div></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ngb-tab>
|
</ngb-tab>
|
||||||
</div>
|
</div>
|
||||||
</ngb-tabset>
|
</ngb-tabset>
|
||||||
<div class="row">
|
<div class="col-md-12">
|
||||||
<div class="col-md-1 col-md-push-5">
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div>
|
<div>
|
||||||
<button (click)="save()" type="submit" id="save" class="btn btn-primary-outline">Submit</button>
|
<button (click)="save()" type="submit" id="save" class="btn btn-primary-outline">Submit</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
|
@ -39,7 +39,7 @@ export class EmbyComponent implements OnInit {
|
||||||
|
|
||||||
public test(server: IEmbyServer) {
|
public test(server: IEmbyServer) {
|
||||||
this.testerService.embyTest(server).subscribe(x => {
|
this.testerService.embyTest(server).subscribe(x => {
|
||||||
if (x) {
|
if (x === true) {
|
||||||
this.notificationService.success("Connected", `Successfully connected to the Emby server ${server.name}!`);
|
this.notificationService.success("Connected", `Successfully connected to the Emby server ${server.name}!`);
|
||||||
} else {
|
} else {
|
||||||
this.notificationService.error("Connected", `We could not connect to the Emby server ${server.name}!`);
|
this.notificationService.error("Connected", `We could not connect to the Emby server ${server.name}!`);
|
||||||
|
|
|
@ -58,11 +58,10 @@ export class PushoverComponent implements OnInit {
|
||||||
|
|
||||||
this.testerService.pushoverTest(form.value).subscribe(x => {
|
this.testerService.pushoverTest(form.value).subscribe(x => {
|
||||||
if (x) {
|
if (x) {
|
||||||
this.notificationService.success("Successful", "Successfully sent a Pushbullet message, please check the discord channel");
|
this.notificationService.success("Successful", "Successfully sent a Pushover message");
|
||||||
} else {
|
} else {
|
||||||
this.notificationService.success("Error", "There was an error when sending the Pushbullet message. Please check your settings");
|
this.notificationService.success("Error", "There was an error when sending the Pushover message. Please check your settings");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ export class PlexComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
public testPlex(server: IPlexServer) {
|
public testPlex(server: IPlexServer) {
|
||||||
this.testerService.plexTest(server).subscribe(x => {
|
this.testerService.plexTest(server).subscribe(x => {
|
||||||
if (x) {
|
if (x === true) {
|
||||||
this.notificationService.success("Connected", `Successfully connected to the Plex server ${server.name}!`);
|
this.notificationService.success("Connected", `Successfully connected to the Plex server ${server.name}!`);
|
||||||
} else {
|
} else {
|
||||||
this.notificationService.error("Connected", `We could not connect to the Plex server ${server.name}!`);
|
this.notificationService.error("Connected", `We could not connect to the Plex server ${server.name}!`);
|
||||||
|
@ -90,15 +90,19 @@ export class PlexComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
this.plexService.getLibraries(server).subscribe(x => {
|
this.plexService.getLibraries(server).subscribe(x => {
|
||||||
server.plexSelectedLibraries = [];
|
server.plexSelectedLibraries = [];
|
||||||
x.mediaContainer.directory.forEach((item, index) => {
|
if (x.successful) {
|
||||||
const lib: IPlexLibrariesSettings = {
|
x.data.mediaContainer.directory.forEach((item) => {
|
||||||
key: item.key,
|
const lib: IPlexLibrariesSettings = {
|
||||||
title: item.title,
|
key: item.key,
|
||||||
enabled: false,
|
title: item.title,
|
||||||
};
|
enabled: false,
|
||||||
server.plexSelectedLibraries.push(lib);
|
};
|
||||||
});
|
server.plexSelectedLibraries.push(lib);
|
||||||
},
|
});
|
||||||
|
} else {
|
||||||
|
this.notificationService.error("Error", x.message);
|
||||||
|
}
|
||||||
|
},
|
||||||
err => { this.notificationService.error("Error", err); });
|
err => { this.notificationService.error("Error", err); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<a (click)="emby()" id="embyImg">
|
<a (click)="emby()" id="embyImg">
|
||||||
<img class="wizard-img" src="/images/emby-logo-dark.jpg" />
|
<img class="wizard-img" src="/images/emby-logo-dark.png" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
30
src/Ombi/Controllers/External/PlexController.cs
vendored
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Ombi.Api.Plex;
|
using Ombi.Api.Plex;
|
||||||
using Ombi.Api.Plex.Models;
|
using Ombi.Api.Plex.Models;
|
||||||
using Ombi.Attributes;
|
using Ombi.Attributes;
|
||||||
|
@ -18,14 +19,17 @@ namespace Ombi.Controllers.External
|
||||||
[Produces("application/json")]
|
[Produces("application/json")]
|
||||||
public class PlexController : Controller
|
public class PlexController : Controller
|
||||||
{
|
{
|
||||||
public PlexController(IPlexApi plexApi, ISettingsService<PlexSettings> plexSettings)
|
public PlexController(IPlexApi plexApi, ISettingsService<PlexSettings> plexSettings,
|
||||||
|
ILogger<PlexController> logger)
|
||||||
{
|
{
|
||||||
PlexApi = plexApi;
|
PlexApi = plexApi;
|
||||||
PlexSettings = plexSettings;
|
PlexSettings = plexSettings;
|
||||||
|
_log = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IPlexApi PlexApi { get; }
|
private IPlexApi PlexApi { get; }
|
||||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||||
|
private readonly ILogger<PlexController> _log;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signs into the Plex API.
|
/// Signs into the Plex API.
|
||||||
|
@ -88,11 +92,29 @@ namespace Ombi.Controllers.External
|
||||||
/// <param name="settings">The settings.</param>
|
/// <param name="settings">The settings.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost("Libraries")]
|
[HttpPost("Libraries")]
|
||||||
public async Task<PlexContainer> GetPlexLibraries([FromBody] PlexServers settings)
|
public async Task<PlexLibrariesResponse> GetPlexLibraries([FromBody] PlexServers settings)
|
||||||
{
|
{
|
||||||
var libs = await PlexApi.GetLibrarySections(settings.PlexAuthToken, settings.FullUri);
|
try
|
||||||
|
{
|
||||||
|
var libs = await PlexApi.GetLibrarySections(settings.PlexAuthToken, settings.FullUri);
|
||||||
|
|
||||||
return libs;
|
return new PlexLibrariesResponse
|
||||||
|
{
|
||||||
|
Successful = true,
|
||||||
|
Data = libs
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_log.LogWarning(e,"Error thrown when attempting to obtain the plex libs");
|
||||||
|
|
||||||
|
var message = e.InnerException != null ? $"{e.Message} - {e.InnerException.Message}" : e.Message;
|
||||||
|
return new PlexLibrariesResponse
|
||||||
|
{
|
||||||
|
Successful = false,
|
||||||
|
Message = message
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -36,58 +36,55 @@ namespace Ombi.Controllers
|
||||||
{
|
{
|
||||||
var model = new MediaSeverAvailibilityViewModel();
|
var model = new MediaSeverAvailibilityViewModel();
|
||||||
|
|
||||||
model.ServersAvailable = 3;
|
var plex = await _plexSettings.GetSettingsAsync();
|
||||||
model.ServersUnavailable = 1;
|
if (plex.Enable)
|
||||||
return model;
|
{
|
||||||
//var plex = await _plexSettings.GetSettingsAsync();
|
|
||||||
//if (plex.Enable)
|
|
||||||
//{
|
|
||||||
|
|
||||||
// foreach (var s in plex.Servers)
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var result = await _plexApi.GetStatus(s.PlexAuthToken, s.FullUri);
|
|
||||||
// if (!string.IsNullOrEmpty(result.MediaContainer?.version))
|
|
||||||
// {
|
|
||||||
// model.ServersAvailable++;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// model.ServersUnavailable++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (Exception)
|
|
||||||
// {
|
|
||||||
// model.ServersUnavailable++;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//var emby = await _embySettings.GetSettingsAsync();
|
foreach (var s in plex.Servers)
|
||||||
//if (emby.Enable)
|
{
|
||||||
//{
|
try
|
||||||
// foreach (var server in emby.Servers)
|
{
|
||||||
// {
|
var result = await _plexApi.GetStatus(s.PlexAuthToken, s.FullUri);
|
||||||
// try
|
if (!string.IsNullOrEmpty(result.MediaContainer?.version))
|
||||||
// {
|
{
|
||||||
// var result = await _embyApi.GetUsers(server.FullUri, server.ApiKey);
|
model.ServersAvailable++;
|
||||||
// if (result.Any())
|
}
|
||||||
// {
|
else
|
||||||
// model.ServersAvailable++;
|
{
|
||||||
// }
|
model.ServersUnavailable++;
|
||||||
// else
|
}
|
||||||
// {
|
}
|
||||||
// model.ServersUnavailable++;
|
catch (Exception)
|
||||||
// }
|
{
|
||||||
// }
|
model.ServersUnavailable++;
|
||||||
// catch (Exception)
|
}
|
||||||
// {
|
}
|
||||||
// model.ServersUnavailable++;
|
}
|
||||||
// }
|
|
||||||
// }
|
var emby = await _embySettings.GetSettingsAsync();
|
||||||
//}
|
if (emby.Enable)
|
||||||
//return model;
|
{
|
||||||
|
foreach (var server in emby.Servers)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await _embyApi.GetUsers(server.FullUri, server.ApiKey);
|
||||||
|
if (result.Any())
|
||||||
|
{
|
||||||
|
model.ServersAvailable++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
model.ServersUnavailable++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
model.ServersUnavailable++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return model;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -89,6 +89,29 @@ namespace Ombi.Controllers
|
||||||
return await MovieRequestEngine.UpdateMovieRequest(model);
|
return await MovieRequestEngine.UpdateMovieRequest(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the specified movie request.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="model">The model.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("movie/approve")]
|
||||||
|
public async Task<RequestEngineResult> ApproveMovie([FromBody] MovieRequests model)
|
||||||
|
{
|
||||||
|
return await MovieRequestEngine.ApproveMovie(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tv requests.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="count">The count of items you want to return.</param>
|
||||||
|
/// <param name="position">The position.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("tv/{count:int}/{position:int}/tree")]
|
||||||
|
public async Task<IEnumerable<TreeNode<TvRequests, List<ChildRequests>>>> GetTvRequestsTree(int count, int position)
|
||||||
|
{
|
||||||
|
return await TvRequestEngine.GetRequestsTreeNode(count, position);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the tv requests.
|
/// Gets the tv requests.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -98,16 +121,7 @@ namespace Ombi.Controllers
|
||||||
[HttpGet("tv/{count:int}/{position:int}")]
|
[HttpGet("tv/{count:int}/{position:int}")]
|
||||||
public async Task<IEnumerable<TvRequests>> GetTvRequests(int count, int position)
|
public async Task<IEnumerable<TvRequests>> GetTvRequests(int count, int position)
|
||||||
{
|
{
|
||||||
try
|
return await TvRequestEngine.GetRequests(count, position);
|
||||||
{
|
|
||||||
|
|
||||||
return await TvRequestEngine.GetRequests(count, position);
|
|
||||||
}
|
|
||||||
catch (System.Exception e)
|
|
||||||
{
|
|
||||||
Debug.WriteLine(e.Message);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -142,6 +156,17 @@ namespace Ombi.Controllers
|
||||||
return await TvRequestEngine.SearchTvRequest(searchTerm);
|
return await TvRequestEngine.SearchTvRequest(searchTerm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Searches for a specific tv request
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="searchTerm">The search term.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("tv/search/{searchTerm}/tree")]
|
||||||
|
public async Task<IEnumerable<TreeNode<TvRequests, List<ChildRequests>>>> SearchTvTree(string searchTerm)
|
||||||
|
{
|
||||||
|
return await TvRequestEngine.SearchTvRequestTree(searchTerm);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes the a specific tv request
|
/// Deletes the a specific tv request
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -175,6 +200,17 @@ namespace Ombi.Controllers
|
||||||
return await TvRequestEngine.UpdateChildRequest(child);
|
return await TvRequestEngine.UpdateChildRequest(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the a specific child request
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="child">The model.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("tv/child/approve")]
|
||||||
|
public async Task<RequestEngineResult> ApproveChild([FromBody] ChildRequests child)
|
||||||
|
{
|
||||||
|
return await TvRequestEngine.ApproveChildRequest(child);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes the a specific tv request
|
/// Deletes the a specific tv request
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -141,7 +141,7 @@ namespace Ombi.Controllers
|
||||||
public async Task<bool> PlexSettings([FromBody]PlexSettings plex)
|
public async Task<bool> PlexSettings([FromBody]PlexSettings plex)
|
||||||
{
|
{
|
||||||
var result = await Save(plex);
|
var result = await Save(plex);
|
||||||
if (result)
|
if (result && plex.Enable)
|
||||||
{
|
{
|
||||||
BackgroundJob.Enqueue(() => _plexContentCacher.CacheContent());
|
BackgroundJob.Enqueue(() => _plexContentCacher.CacheContent());
|
||||||
}
|
}
|
||||||
|
@ -166,14 +166,17 @@ namespace Ombi.Controllers
|
||||||
[HttpPost("emby")]
|
[HttpPost("emby")]
|
||||||
public async Task<bool> EmbySettings([FromBody]EmbySettings emby)
|
public async Task<bool> EmbySettings([FromBody]EmbySettings emby)
|
||||||
{
|
{
|
||||||
foreach (var server in emby.Servers)
|
if (emby.Enable)
|
||||||
{
|
{
|
||||||
var users = await _embyApi.GetUsers(server.FullUri, server.ApiKey);
|
foreach (var server in emby.Servers)
|
||||||
var admin = users.FirstOrDefault(x => x.Policy.IsAdministrator);
|
{
|
||||||
server.AdministratorId = admin?.Id;
|
var users = await _embyApi.GetUsers(server.FullUri, server.ApiKey);
|
||||||
|
var admin = users.FirstOrDefault(x => x.Policy.IsAdministrator);
|
||||||
|
server.AdministratorId = admin?.Id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var result = await Save(emby);
|
var result = await Save(emby);
|
||||||
if (result)
|
if (result && emby.Enable)
|
||||||
{
|
{
|
||||||
BackgroundJob.Enqueue(() => _embyContentCacher.Start());
|
BackgroundJob.Enqueue(() => _embyContentCacher.Start());
|
||||||
}
|
}
|
||||||
|
|
38
src/Ombi/Models/External/PlexLibrariesResponse.cs
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2017 Jamie Rees
|
||||||
|
// File: PlexLibrariesResponse.cs
|
||||||
|
// Created By: Jamie Rees
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
// a copy of this software and associated documentation files (the
|
||||||
|
// "Software"), to deal in the Software without restriction, including
|
||||||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
// the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
// ************************************************************************/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using Ombi.Api.Plex.Models;
|
||||||
|
|
||||||
|
namespace Ombi.Models.External
|
||||||
|
{
|
||||||
|
public class PlexLibrariesResponse
|
||||||
|
{
|
||||||
|
public PlexContainer Data { get; set; }
|
||||||
|
public bool Successful { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,12 +24,16 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<!-- Files not to show in IDE -->
|
<!-- Files not to show in IDE -->
|
||||||
|
<Compile Remove="Styles\**" />
|
||||||
<Compile Remove="wwwroot\dist\**" />
|
<Compile Remove="wwwroot\dist\**" />
|
||||||
|
|
||||||
<!-- Files not to publish (note that the 'dist' subfolders are re-added below) -->
|
<!-- Files not to publish (note that the 'dist' subfolders are re-added below) -->
|
||||||
<Content Remove="ClientApp\**" />
|
<Content Remove="ClientApp\**" />
|
||||||
|
<Content Remove="Styles\**" />
|
||||||
<Content Remove="wwwroot\dist\**" />
|
<Content Remove="wwwroot\dist\**" />
|
||||||
|
<EmbeddedResource Remove="Styles\**" />
|
||||||
<EmbeddedResource Remove="wwwroot\dist\**" />
|
<EmbeddedResource Remove="wwwroot\dist\**" />
|
||||||
|
<None Remove="Styles\**" />
|
||||||
<None Remove="wwwroot\dist\**" />
|
<None Remove="wwwroot\dist\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -77,11 +81,6 @@
|
||||||
<ProjectReference Include="..\Ombi.Updater\Ombi.Updater.csproj" />
|
<ProjectReference Include="..\Ombi.Updater\Ombi.Updater.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Styles\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="wwwroot\loading.css" />
|
<None Include="wwwroot\loading.css" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -19,11 +19,13 @@ namespace Ombi
|
||||||
|
|
||||||
int port = 0;
|
int port = 0;
|
||||||
string host = string.Empty;
|
string host = string.Empty;
|
||||||
|
string storagePath = string.Empty;
|
||||||
Parser.Default.ParseArguments<Options>(args)
|
Parser.Default.ParseArguments<Options>(args)
|
||||||
.WithParsed(o =>
|
.WithParsed(o =>
|
||||||
{
|
{
|
||||||
port = o.Port;
|
port = o.Port;
|
||||||
host = o.Host;
|
host = o.Host;
|
||||||
|
storagePath = o.StoragePath;
|
||||||
});
|
});
|
||||||
|
|
||||||
UrlArgs = $"{host}:{port}";
|
UrlArgs = $"{host}:{port}";
|
||||||
|
@ -46,7 +48,7 @@ namespace Ombi
|
||||||
Type = ConfigurationTypes.Port,
|
Type = ConfigurationTypes.Port,
|
||||||
Value = "5000"
|
Value = "5000"
|
||||||
};
|
};
|
||||||
|
|
||||||
ctx.ApplicationConfigurations.Add(url);
|
ctx.ApplicationConfigurations.Add(url);
|
||||||
ctx.ApplicationConfigurations.Add(dbPort);
|
ctx.ApplicationConfigurations.Add(dbPort);
|
||||||
ctx.SaveChanges();
|
ctx.SaveChanges();
|
||||||
|
@ -87,5 +89,10 @@ namespace Ombi
|
||||||
|
|
||||||
[Option('p', "port", Required = false, HelpText = "The port, default is 5000", Default = 5000)]
|
[Option('p', "port", Required = false, HelpText = "The port, default is 5000", Default = 5000)]
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[Option('s', "storage", Required = false, HelpText = "Storage path, where we save the logs and database")]
|
||||||
|
public string StoragePath { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,12 @@ namespace Ombi
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
|
|
||||||
//ApiKeyMiddlewear(app, serviceProvider);
|
//ApiKeyMiddlewear(app, serviceProvider);
|
||||||
|
app.UseSwaggerUI(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
||||||
|
c.ShowJsonEditor();
|
||||||
|
});
|
||||||
|
|
||||||
app.UseMvc(routes =>
|
app.UseMvc(routes =>
|
||||||
{
|
{
|
||||||
routes.MapRoute(
|
routes.MapRoute(
|
||||||
|
@ -179,11 +184,6 @@ namespace Ombi
|
||||||
name: "spa-fallback",
|
name: "spa-fallback",
|
||||||
defaults: new { controller = "Home", action = "Index" });
|
defaults: new { controller = "Home", action = "Index" });
|
||||||
});
|
});
|
||||||
app.UseSwaggerUI(c =>
|
|
||||||
{
|
|
||||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
|
||||||
c.ShowJsonEditor();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ApiKeyMiddlewear(IApplicationBuilder app, IServiceProvider serviceProvider)
|
private static void ApiKeyMiddlewear(IApplicationBuilder app, IServiceProvider serviceProvider)
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
true,
|
true,
|
||||||
"allow-new"
|
"allow-new"
|
||||||
],
|
],
|
||||||
|
"no-trailing-whitespace": [
|
||||||
|
false
|
||||||
|
],
|
||||||
"max-classes-per-file": [
|
"max-classes-per-file": [
|
||||||
false
|
false
|
||||||
],
|
],
|
||||||
|
|
Before Width: | Height: | Size: 22 KiB |
BIN
src/Ombi/wwwroot/images/emby-logo-dark.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1,022 B |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 180 B After Width: | Height: | Size: 86 B |
Before Width: | Height: | Size: 178 B After Width: | Height: | Size: 74 B |
Before Width: | Height: | Size: 120 B After Width: | Height: | Size: 111 B |
Before Width: | Height: | Size: 105 B After Width: | Height: | Size: 81 B |
Before Width: | Height: | Size: 111 B After Width: | Height: | Size: 88 B |
Before Width: | Height: | Size: 110 B After Width: | Height: | Size: 88 B |
Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 110 B |
Before Width: | Height: | Size: 101 B After Width: | Height: | Size: 86 B |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 3.6 KiB |