mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-13 08:42:57 -07:00
Lots of backend work
This commit is contained in:
parent
c360b79f87
commit
9dbe334562
22 changed files with 395 additions and 53 deletions
|
@ -18,7 +18,7 @@ namespace Ombi.Api.Plex.Models
|
||||||
public string art { get; set; }
|
public string art { get; set; }
|
||||||
public string banner { get; set; }
|
public string banner { get; set; }
|
||||||
public string theme { get; set; }
|
public string theme { get; set; }
|
||||||
public int duration { get; set; }
|
public string duration { get; set; }
|
||||||
public string originallyAvailableAt { get; set; }
|
public string originallyAvailableAt { get; set; }
|
||||||
public int leafCount { get; set; }
|
public int leafCount { get; set; }
|
||||||
public int viewedLeafCount { get; set; }
|
public int viewedLeafCount { get; set; }
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
{
|
{
|
||||||
public int id { get; set; }
|
public int id { get; set; }
|
||||||
public string key { get; set; }
|
public string key { get; set; }
|
||||||
public int duration { get; set; }
|
public string duration { get; set; }
|
||||||
public string file { get; set; }
|
public string file { get; set; }
|
||||||
public int size { get; set; }
|
public string size { get; set; }
|
||||||
public string audioProfile { get; set; }
|
public string audioProfile { get; set; }
|
||||||
public string container { get; set; }
|
public string container { get; set; }
|
||||||
public string videoProfile { get; set; }
|
public string videoProfile { get; set; }
|
||||||
|
|
|
@ -64,14 +64,14 @@ namespace Ombi.Api.Plex
|
||||||
|
|
||||||
public async Task<PlexLibraries> GetLibrarySections(string authToken, string plexFullHost)
|
public async Task<PlexLibraries> GetLibrarySections(string authToken, string plexFullHost)
|
||||||
{
|
{
|
||||||
var request = new Request(plexFullHost, "library/sections", HttpMethod.Get);
|
var request = new Request("library/sections", plexFullHost, HttpMethod.Get);
|
||||||
AddHeaders(request, authToken);
|
AddHeaders(request, authToken);
|
||||||
return await Api.Request<PlexLibraries>(request);
|
return await Api.Request<PlexLibraries>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<PlexLibraries> GetLibrary(string authToken, string plexFullHost, string libraryId)
|
public async Task<PlexLibraries> GetLibrary(string authToken, string plexFullHost, string libraryId)
|
||||||
{
|
{
|
||||||
var request = new Request(plexFullHost, $"library/sections/{libraryId}/all", HttpMethod.Get);
|
var request = new Request($"library/sections/{libraryId}/all", plexFullHost, HttpMethod.Get);
|
||||||
AddHeaders(request, authToken);
|
AddHeaders(request, authToken);
|
||||||
return await Api.Request<PlexLibraries>(request);
|
return await Api.Request<PlexLibraries>(request);
|
||||||
}
|
}
|
||||||
|
@ -89,21 +89,21 @@ namespace Ombi.Api.Plex
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public async Task<PlexMetadata> GetEpisodeMetaData(string authToken, string plexFullHost, string ratingKey)
|
public async Task<PlexMetadata> GetEpisodeMetaData(string authToken, string plexFullHost, string ratingKey)
|
||||||
{
|
{
|
||||||
var request = new Request(plexFullHost, $"/library/metadata/{ratingKey}", HttpMethod.Get);
|
var request = new Request($"/library/metadata/{ratingKey}", plexFullHost, HttpMethod.Get);
|
||||||
AddHeaders(request, authToken);
|
AddHeaders(request, authToken);
|
||||||
return await Api.Request<PlexMetadata>(request);
|
return await Api.Request<PlexMetadata>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<PlexMetadata> GetMetadata(string authToken, string plexFullHost, string itemId)
|
public async Task<PlexMetadata> GetMetadata(string authToken, string plexFullHost, string itemId)
|
||||||
{
|
{
|
||||||
var request = new Request(plexFullHost, $"library/metadata/{itemId}", HttpMethod.Get);
|
var request = new Request($"library/metadata/{itemId}", plexFullHost, HttpMethod.Get);
|
||||||
AddHeaders(request, authToken);
|
AddHeaders(request, authToken);
|
||||||
return await Api.Request<PlexMetadata>(request);
|
return await Api.Request<PlexMetadata>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<PlexMetadata> GetSeasons(string authToken, string plexFullHost, string ratingKey)
|
public async Task<PlexMetadata> GetSeasons(string authToken, string plexFullHost, string ratingKey)
|
||||||
{
|
{
|
||||||
var request = new Request(plexFullHost, $"library/metadata/{ratingKey}/children", HttpMethod.Get);
|
var request = new Request($"library/metadata/{ratingKey}/children", plexFullHost, HttpMethod.Get);
|
||||||
AddHeaders(request, authToken);
|
AddHeaders(request, authToken);
|
||||||
return await Api.Request<PlexMetadata>(request);
|
return await Api.Request<PlexMetadata>(request);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,7 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddTransient<ISettingsRepository, SettingsJsonRepository>();
|
services.AddTransient<ISettingsRepository, SettingsJsonRepository>();
|
||||||
services.AddTransient<IUserRepository, UserRepository>();
|
services.AddTransient<IUserRepository, UserRepository>();
|
||||||
services.AddTransient<ISettingsResolver, SettingsResolver>();
|
services.AddTransient<ISettingsResolver, SettingsResolver>();
|
||||||
|
services.AddTransient<IPlexContentRepository, PlexContentRepository>();
|
||||||
services.AddTransient(typeof(ISettingsService<>), typeof(SettingsServiceV2<>));
|
services.AddTransient(typeof(ISettingsService<>), typeof(SettingsServiceV2<>));
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,26 +28,32 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Ombi.Api.Plex;
|
using Ombi.Api.Plex;
|
||||||
using Ombi.Api.Plex.Models;
|
using Ombi.Api.Plex.Models;
|
||||||
using Ombi.Core.Settings;
|
using Ombi.Core.Settings;
|
||||||
using Ombi.Core.Settings.Models.External;
|
using Ombi.Core.Settings.Models.External;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Repository;
|
||||||
|
|
||||||
namespace Ombi.Schedule.Jobs
|
namespace Ombi.Schedule.Jobs
|
||||||
{
|
{
|
||||||
public partial class PlexContentCacher : IPlexContentCacher
|
public partial class PlexContentCacher : IPlexContentCacher
|
||||||
{
|
{
|
||||||
public PlexContentCacher(ISettingsService<PlexSettings> plex, IPlexApi plexApi, ILogger<PlexContentCacher> logger)
|
public PlexContentCacher(ISettingsService<PlexSettings> plex, IPlexApi plexApi, ILogger<PlexContentCacher> logger, IPlexContentRepository repo)
|
||||||
{
|
{
|
||||||
Plex = plex;
|
Plex = plex;
|
||||||
PlexApi = plexApi;
|
PlexApi = plexApi;
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
|
Repo = repo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ISettingsService<PlexSettings> Plex { get; }
|
private ISettingsService<PlexSettings> Plex { get; }
|
||||||
private IPlexApi PlexApi { get; }
|
private IPlexApi PlexApi { get; }
|
||||||
private ILogger<PlexContentCacher> Logger { get; }
|
private ILogger<PlexContentCacher> Logger { get; }
|
||||||
|
private IPlexContentRepository Repo { get; }
|
||||||
|
|
||||||
public void CacheContent()
|
public void CacheContent()
|
||||||
{
|
{
|
||||||
|
@ -63,7 +69,7 @@ namespace Ombi.Schedule.Jobs
|
||||||
|
|
||||||
Logger.LogInformation("Starting Plex Content Cacher");
|
Logger.LogInformation("Starting Plex Content Cacher");
|
||||||
//TODO
|
//TODO
|
||||||
//var libraries = CachedLibraries(plexSettings);
|
StartTheCache(plexSettings).Wait();
|
||||||
|
|
||||||
//if (libraries == null || !libraries.Any())
|
//if (libraries == null || !libraries.Any())
|
||||||
//{
|
//{
|
||||||
|
@ -95,7 +101,7 @@ namespace Ombi.Schedule.Jobs
|
||||||
// t1.seasons.AddRange(filtered);
|
// t1.seasons.AddRange(filtered);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// var providerId = PlexHelper.GetProviderIdFromPlexGuid(metaData.MediaContainer.);
|
// var providerId = PlexHelper.GetProviderIdFromPlexGuid(metaData.MediaContainer);
|
||||||
// t1.providerId = providerId;
|
// t1.providerId = providerId;
|
||||||
// }
|
// }
|
||||||
// foreach (Video t1 in t.Video)
|
// foreach (Video t1 in t.Video)
|
||||||
|
@ -110,19 +116,103 @@ namespace Ombi.Schedule.Jobs
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
private List<PlexLibraries> GetLibraries(PlexSettings plexSettings)
|
private async Task StartTheCache(PlexSettings plexSettings)
|
||||||
|
{
|
||||||
|
var allContent = GetAllContent(plexSettings);
|
||||||
|
|
||||||
|
// Let's now process this.
|
||||||
|
|
||||||
|
foreach (var content in allContent)
|
||||||
|
{
|
||||||
|
var contentToAdd = new List<PlexContent>();
|
||||||
|
if (content.viewGroup.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
// Process Shows
|
||||||
|
foreach (var metadata in content.Metadata)
|
||||||
|
{
|
||||||
|
var seasonList = await PlexApi.GetSeasons(plexSettings.PlexAuthToken, plexSettings.FullUri,
|
||||||
|
metadata.ratingKey);
|
||||||
|
var seasonsContent = new List<SeasonsContent>();
|
||||||
|
foreach (var season in seasonList.MediaContainer.Metadata)
|
||||||
|
{
|
||||||
|
seasonsContent.Add(new SeasonsContent
|
||||||
|
{
|
||||||
|
ParentKey = int.Parse(season.parentRatingKey),
|
||||||
|
SeasonKey = int.Parse(season.ratingKey),
|
||||||
|
SeasonNumber = season.index
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we already have this item?
|
||||||
|
var existingContent = await Repo.GetByKey(metadata.key);
|
||||||
|
if (existingContent != null)
|
||||||
|
{
|
||||||
|
// Ok so we have it, let's check if there are any new seasons
|
||||||
|
var seasonDifference = seasonsContent.Except(existingContent.Seasons).ToList();
|
||||||
|
if (seasonDifference.Any())
|
||||||
|
{
|
||||||
|
// We have new seasons on Plex, let's add them back into the entity
|
||||||
|
existingContent.Seasons.AddRange(seasonDifference);
|
||||||
|
await Repo.Update(existingContent);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No changes, no need to do anything
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the show metadata... This sucks since the `metadata` var contains all information about the show
|
||||||
|
// But it does not contain the `guid` property that we need to pull out thetvdb id...
|
||||||
|
var showMetadata = await PlexApi.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri,
|
||||||
|
metadata.ratingKey);
|
||||||
|
var item = new PlexContent
|
||||||
|
{
|
||||||
|
AddedAt = DateTime.Now,
|
||||||
|
Key = metadata.ratingKey,
|
||||||
|
ProviderId = PlexHelper.GetProviderIdFromPlexGuid(showMetadata.MediaContainer.Metadata
|
||||||
|
.FirstOrDefault()
|
||||||
|
.guid),
|
||||||
|
ReleaseYear = metadata.year.ToString(),
|
||||||
|
Type = PlexMediaTypeEntity.Show,
|
||||||
|
Title = metadata.title,
|
||||||
|
Url = PlexHelper.GetPlexMediaUrl(plexSettings.MachineIdentifier, metadata.ratingKey),
|
||||||
|
Seasons = new List<SeasonsContent>()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
item.Seasons.AddRange(seasonsContent);
|
||||||
|
|
||||||
|
contentToAdd.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Mediacontainer> GetAllContent(PlexSettings plexSettings)
|
||||||
{
|
{
|
||||||
var sections = PlexApi.GetLibrarySections(plexSettings.PlexAuthToken, plexSettings.FullUri).Result;
|
var sections = PlexApi.GetLibrarySections(plexSettings.PlexAuthToken, plexSettings.FullUri).Result;
|
||||||
|
|
||||||
var libs = new List<PlexLibraries>();
|
var libs = new List<Mediacontainer>();
|
||||||
if (sections != null)
|
if (sections != null)
|
||||||
{
|
{
|
||||||
foreach (var dir in sections.MediaContainer.Directory ?? new List<Directory>())
|
foreach (var dir in sections.MediaContainer.Directory ?? new List<Directory>())
|
||||||
{
|
{
|
||||||
|
if (plexSettings.PlexSelectedLibraries.Any())
|
||||||
|
{
|
||||||
|
// Only get the enabled libs
|
||||||
|
var keys = plexSettings.PlexSelectedLibraries.Where(x => x.Enabled).Select(x => x.Key.ToString()).ToList();
|
||||||
|
if (!keys.Contains(dir.key))
|
||||||
|
{
|
||||||
|
// We are not monitoring this lib
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
var lib = PlexApi.GetLibrary(plexSettings.PlexAuthToken, plexSettings.FullUri, dir.key).Result;
|
var lib = PlexApi.GetLibrary(plexSettings.PlexAuthToken, plexSettings.FullUri, dir.key).Result;
|
||||||
if (lib != null)
|
if (lib != null)
|
||||||
{
|
{
|
||||||
libs.Add(lib);
|
libs.Add(lib.MediaContainer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,8 @@ namespace Ombi.Schedule.Jobs
|
||||||
{
|
{
|
||||||
public enum PlexMediaType
|
public enum PlexMediaType
|
||||||
{
|
{
|
||||||
Movie,
|
Movie = 0,
|
||||||
Show,
|
Show = 1
|
||||||
Artist
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
namespace Ombi.Core.Settings.Models.External
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Settings.Models.External
|
||||||
{
|
{
|
||||||
public sealed class PlexSettings : ExternalSettings
|
public sealed class PlexSettings : ExternalSettings
|
||||||
{
|
{
|
||||||
|
@ -8,5 +10,14 @@
|
||||||
|
|
||||||
public string PlexAuthToken { get; set; }
|
public string PlexAuthToken { get; set; }
|
||||||
public string MachineIdentifier { get; set; }
|
public string MachineIdentifier { get; set; }
|
||||||
|
|
||||||
|
public List<PlexSelectedLibraries> PlexSelectedLibraries { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PlexSelectedLibraries
|
||||||
|
{
|
||||||
|
public int Key { get; set; }
|
||||||
|
public string Title { get; set; } // Name is for display purposes
|
||||||
|
public bool Enabled { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,6 +13,7 @@ namespace Ombi.Store.Context
|
||||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
|
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken));
|
||||||
DbSet<RequestBlobs> Requests { get; set; }
|
DbSet<RequestBlobs> Requests { get; set; }
|
||||||
DbSet<GlobalSettings> Settings { get; set; }
|
DbSet<GlobalSettings> Settings { get; set; }
|
||||||
|
DbSet<PlexContent> PlexContent { get; set; }
|
||||||
DbSet<User> Users { get; set; }
|
DbSet<User> Users { get; set; }
|
||||||
EntityEntry<GlobalSettings> Entry(GlobalSettings settings);
|
EntityEntry<GlobalSettings> Entry(GlobalSettings settings);
|
||||||
EntityEntry<TEntity> Attach<TEntity>(TEntity entity) where TEntity : class;
|
EntityEntry<TEntity> Attach<TEntity>(TEntity entity) where TEntity : class;
|
||||||
|
|
|
@ -17,9 +17,13 @@ namespace Ombi.Store.Context
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DbSet<RequestBlobs> Requests { get; set; }
|
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 EntityEntry<GlobalSettings> Entry(GlobalSettings settings)
|
public EntityEntry<GlobalSettings> Entry(GlobalSettings settings)
|
||||||
{
|
{
|
||||||
return Entry(settings);
|
return Entry(settings);
|
||||||
|
|
68
Ombi/Ombi.Store/Entities/PlexContent.cs
Normal file
68
Ombi/Ombi.Store/Entities/PlexContent.cs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2017 Jamie Rees
|
||||||
|
// File: PlexContent.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 System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Entities
|
||||||
|
{
|
||||||
|
[Table("PlexContent")]
|
||||||
|
public class PlexContent : Entity
|
||||||
|
{
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string ReleaseYear { get; set; }
|
||||||
|
public string ProviderId { get; set; }
|
||||||
|
public PlexMediaTypeEntity Type { get; set; }
|
||||||
|
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only used for TV Shows
|
||||||
|
/// </summary>
|
||||||
|
public List<SeasonsContent> Seasons { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Plex's internal ID for this item
|
||||||
|
/// </summary>
|
||||||
|
public string Key { get; set; }
|
||||||
|
public DateTime AddedAt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SeasonsContent : Entity
|
||||||
|
{
|
||||||
|
public int SeasonNumber { get; set; }
|
||||||
|
public int SeasonKey { get; set; }
|
||||||
|
public int ParentKey { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PlexMediaTypeEntity
|
||||||
|
{
|
||||||
|
Movie = 0,
|
||||||
|
Show = 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard1.6</TargetFramework>
|
<TargetFramework>netstandard1.6</TargetFramework>
|
||||||
<!--<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>-->
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.1" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
|
||||||
|
|
16
Ombi/Ombi.Store/Repository/IPlexContentRepository.cs
Normal file
16
Ombi/Ombi.Store/Repository/IPlexContentRepository.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Repository
|
||||||
|
{
|
||||||
|
public interface IPlexContentRepository
|
||||||
|
{
|
||||||
|
Task<PlexContent> Add(PlexContent content);
|
||||||
|
Task<bool> ContentExists(string providerId);
|
||||||
|
Task<IEnumerable<PlexContent>> GetAll();
|
||||||
|
Task<PlexContent> Get(string providerId);
|
||||||
|
Task<PlexContent> GetByKey(string key);
|
||||||
|
Task Update(PlexContent existingContent);
|
||||||
|
}
|
||||||
|
}
|
79
Ombi/Ombi.Store/Repository/PlexContentRepository.cs
Normal file
79
Ombi/Ombi.Store/Repository/PlexContentRepository.cs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2017 Jamie Rees
|
||||||
|
// File: PlexContentRepository.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 System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Ombi.Store.Context;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Repository
|
||||||
|
{
|
||||||
|
public class PlexContentRepository : IPlexContentRepository
|
||||||
|
{
|
||||||
|
|
||||||
|
public PlexContentRepository(IOmbiContext db)
|
||||||
|
{
|
||||||
|
Db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IOmbiContext Db { get; }
|
||||||
|
|
||||||
|
public async Task<IEnumerable<PlexContent>> GetAll()
|
||||||
|
{
|
||||||
|
return await Db.PlexContent.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> ContentExists(string providerId)
|
||||||
|
{
|
||||||
|
return await Db.PlexContent.AnyAsync(x => x.ProviderId == providerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PlexContent> Add(PlexContent content)
|
||||||
|
{
|
||||||
|
await Db.PlexContent.AddAsync(content);
|
||||||
|
await Db.SaveChangesAsync();
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PlexContent> Get(string providerId)
|
||||||
|
{
|
||||||
|
return await Db.PlexContent.FirstOrDefaultAsync(x => x.ProviderId == providerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PlexContent> GetByKey(string key)
|
||||||
|
{
|
||||||
|
return await Db.PlexContent.FirstOrDefaultAsync(x => x.Key == key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Update(PlexContent existingContent)
|
||||||
|
{
|
||||||
|
Db.PlexContent.Update(existingContent);
|
||||||
|
await Db.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
Ombi/Ombi/.gitignore
vendored
1
Ombi/Ombi/.gitignore
vendored
|
@ -18,3 +18,4 @@ npm-debug.log
|
||||||
testem.log
|
testem.log
|
||||||
#/typings
|
#/typings
|
||||||
/systemjs.config.js*
|
/systemjs.config.js*
|
||||||
|
/Logs/**
|
||||||
|
|
|
@ -49,6 +49,14 @@ namespace Ombi.Controllers.External
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("Libraries")]
|
||||||
|
public async Task<PlexLibraries> GetPlexLibraries([FromBody] PlexSettings settings)
|
||||||
|
{
|
||||||
|
var libs = await PlexApi.GetLibrarySections(settings.PlexAuthToken, settings.FullUri);
|
||||||
|
|
||||||
|
return libs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="1.1.0" />
|
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
|
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.1" />
|
||||||
|
|
|
@ -59,10 +59,10 @@ namespace Ombi
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddMvc();
|
services.AddMvc();
|
||||||
services.AddOmbiMappingProfile();
|
services.AddOmbiMappingProfile();
|
||||||
//services.AddAutoMapper(expression =>
|
services.AddAutoMapper(expression =>
|
||||||
//{
|
{
|
||||||
// expression.AddCollectionMappers();
|
expression.AddCollectionMappers();
|
||||||
//});
|
});
|
||||||
services.RegisterDependencies(); // Ioc and EF
|
services.RegisterDependencies(); // Ioc and EF
|
||||||
|
|
||||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
|
|
|
@ -10,3 +10,16 @@ export interface IPlexUser {
|
||||||
title: string,
|
title: string,
|
||||||
authentication_token: string,
|
authentication_token: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IPlexLibraries {
|
||||||
|
mediaContainer:IMediaContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IMediaContainer {
|
||||||
|
directory:IDirectory[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDirectory {
|
||||||
|
key: string,
|
||||||
|
title: string,
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ export interface IExternalSettings extends ISettings {
|
||||||
enable:boolean,
|
enable:boolean,
|
||||||
subDir: string,
|
subDir: string,
|
||||||
ip: string,
|
ip: string,
|
||||||
port:number
|
port:number,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IOmbiSettings extends ISettings {
|
export interface IOmbiSettings extends ISettings {
|
||||||
|
@ -21,13 +21,20 @@ export interface IOmbiSettings extends ISettings {
|
||||||
export interface IEmbySettings extends IExternalSettings {
|
export interface IEmbySettings extends IExternalSettings {
|
||||||
apiKey: string,
|
apiKey: string,
|
||||||
administratorId: string,
|
administratorId: string,
|
||||||
enableEpisodeSearching:boolean
|
enableEpisodeSearching:boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPlexSettings extends IExternalSettings {
|
export interface IPlexSettings extends IExternalSettings {
|
||||||
enableEpisodeSearching: boolean,
|
enableEpisodeSearching: boolean,
|
||||||
plexAuthToken: string,
|
plexAuthToken: string,
|
||||||
machineIdentifier: string
|
machineIdentifier: string,
|
||||||
|
plexSelectedLibraries : IPlexLibraries[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPlexLibraries {
|
||||||
|
key: string,
|
||||||
|
title: string,
|
||||||
|
enabled:boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISonarrSettings extends IExternalSettings {
|
export interface ISonarrSettings extends IExternalSettings {
|
||||||
|
@ -35,7 +42,7 @@ export interface ISonarrSettings extends IExternalSettings {
|
||||||
qualityProfile: string,
|
qualityProfile: string,
|
||||||
seasonFolders: boolean,
|
seasonFolders: boolean,
|
||||||
rootPath: string,
|
rootPath: string,
|
||||||
fullRootPath:string
|
fullRootPath:string,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ILandingPageSettings extends ISettings {
|
export interface ILandingPageSettings extends ISettings {
|
||||||
|
@ -52,5 +59,5 @@ export interface ILandingPageSettings extends ISettings {
|
||||||
|
|
||||||
export interface ICustomizationSettings extends ISettings {
|
export interface ICustomizationSettings extends ISettings {
|
||||||
applicationName: string,
|
applicationName: string,
|
||||||
logo:string
|
logo:string,
|
||||||
}
|
}
|
|
@ -1,20 +1,27 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Http } from '@angular/http';
|
import { Http } from '@angular/http'
|
||||||
|
|
||||||
|
import { AuthHttp } from 'angular2-jwt';;
|
||||||
import { Observable } from 'rxjs/Rx';
|
import { Observable } from 'rxjs/Rx';
|
||||||
|
|
||||||
import { ServiceHelpers } from '../service.helpers';
|
import { ServiceAuthHelpers } from '../service.helpers';
|
||||||
|
|
||||||
import { IPlexAuthentication } from '../../interfaces/IPlex'
|
import { IPlexAuthentication, IPlexLibraries} from '../../interfaces/IPlex';
|
||||||
|
import { IPlexSettings } from '../../interfaces/ISettings';
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PlexService extends ServiceHelpers {
|
export class PlexService extends ServiceAuthHelpers {
|
||||||
constructor(http: Http) {
|
constructor(http: AuthHttp, private regularHttp: Http) {
|
||||||
super(http, '/api/v1/Plex/');
|
super(http, '/api/v1/Plex/');
|
||||||
}
|
}
|
||||||
|
|
||||||
logIn(login: string, password: string): Observable<IPlexAuthentication> {
|
logIn(login: string, password: string): Observable<IPlexAuthentication> {
|
||||||
return this.http.post(`${this.url}/`, JSON.stringify({ login: login, password:password}), { headers: this.headers }).map(this.extractData);
|
return this.regularHttp.post(`${this.url}`, JSON.stringify({ login: login, password:password}), { headers: this.headers }).map(this.extractData);
|
||||||
|
}
|
||||||
|
|
||||||
|
getLibraries(plexSettings: IPlexSettings): Observable<IPlexLibraries> {
|
||||||
|
return this.http.post(`${this.url}Libraries`, JSON.stringify(plexSettings), { headers: this.headers }).map(this.extractData);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -78,6 +78,24 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<label>Please select the libraries you want Ombi to look in for content</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<button (click)="loadLibraries()" class="btn btn-primary-outline">Load Libraries <i class="fa fa-film"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="settings.plexSelectedLibraries">
|
||||||
|
<div *ngFor="let lib of settings.plexSelectedLibraries">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
<input type="checkbox" id="{{lib.title}}" [(ngModel)]="lib.enabled" ng-checked="lib.enabled">
|
||||||
|
<label for="{{lib.title}}">{{lib.title}}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div>
|
<div>
|
||||||
<button id="testPlex" type="submit" (click)="testPlex()" class="btn btn-primary-outline">Test Connectivity <div id="spinner"></div></button>
|
<button id="testPlex" type="submit" (click)="testPlex()" class="btn btn-primary-outline">Test Connectivity <div id="spinner"></div></button>
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
import { IPlexSettings } from '../../interfaces/ISettings'
|
import { IPlexSettings, IPlexLibraries } from '../../interfaces/ISettings'
|
||||||
|
|
||||||
|
|
||||||
import { SettingsService } from '../../services/settings.service';
|
import { SettingsService } from '../../services/settings.service';
|
||||||
|
import { PlexService } from '../../services/applications/plex.service';
|
||||||
import { NotificationService } from "../../services/notification.service";
|
import { NotificationService } from "../../services/notification.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -11,7 +14,7 @@ import { NotificationService } from "../../services/notification.service";
|
||||||
})
|
})
|
||||||
export class PlexComponent implements OnInit {
|
export class PlexComponent implements OnInit {
|
||||||
|
|
||||||
constructor(private settingsService: SettingsService, private notificationService: NotificationService) { }
|
constructor(private settingsService: SettingsService, private notificationService: NotificationService, private plexService: PlexService) { }
|
||||||
|
|
||||||
settings: IPlexSettings;
|
settings: IPlexSettings;
|
||||||
username: string;
|
username: string;
|
||||||
|
@ -29,6 +32,22 @@ export class PlexComponent implements OnInit {
|
||||||
// TODO Plex Service
|
// TODO Plex Service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadLibraries() {
|
||||||
|
this.plexService.getLibraries(this.settings).subscribe(x => {
|
||||||
|
|
||||||
|
this.settings.plexSelectedLibraries = [];
|
||||||
|
x.mediaContainer.directory.forEach((item, index) => {
|
||||||
|
var lib: IPlexLibraries = {
|
||||||
|
key: item.key,
|
||||||
|
title: item.title,
|
||||||
|
enabled: false
|
||||||
|
};
|
||||||
|
this.settings.plexSelectedLibraries.push(lib);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
save() {
|
save() {
|
||||||
this.settingsService.savePlex(this.settings).subscribe(x => {
|
this.settingsService.savePlex(this.settings).subscribe(x => {
|
||||||
if (x) {
|
if (x) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue