More changes

pull/1425/head
tidusjar 8 years ago
parent 8b64c18ace
commit f706b36ae5

@ -212,7 +212,7 @@ namespace Ombi.Api
public PlexEpisodeMetadata GetEpisodeMetaData(string authToken, Uri host, string ratingKey)
{
//192.168.1.69:32400/library/metadata/3662/allLeaves
// 192.168.1.69:32400/library/metadata/3662/allLeaves
// The metadata ratingkey should be in the Cache
// Search for it and then call the above with the Directory.RatingKey
// THEN! We need the episode metadata using result.Vide.Key ("/library/metadata/3664")

@ -10,5 +10,10 @@ namespace Ombi.Api.Plex
Task<PlexStatus> GetStatus(string authToken, string uri);
Task<PlexAuthentication> SignIn(UserRequest user);
Task<PlexServer> GetServer(string authToken);
Task<PlexLibraries> GetLibrarySections(string authToken, string plexFullHost);
Task<PlexLibraries> GetLibrary(string authToken, string plexFullHost, string libraryId);
Task<PlexMetadata> GetEpisodeMetaData(string authToken, string host, string ratingKey);
Task<PlexMetadata> GetMetadata(string authToken, string plexFullHost, string itemId);
Task<PlexMetadata> GetSeasons(string authToken, string plexFullHost, string ratingKey);
}
}

@ -0,0 +1,9 @@
namespace Ombi.Api.Plex.Models
{
public class Director
{
public int id { get; set; }
public string filter { get; set; }
public string tag { get; set; }
}
}

@ -0,0 +1,41 @@
using System.Collections.Generic;
using System.Xml.Serialization;
namespace Ombi.Api.Plex.Models
{
public class Directory
{
public Directory()
{
seasons = new List<Directory>();
}
public bool allowSync { get; set; }
public string art { get; set; }
public string composite { get; set; }
public bool filters { get; set; }
public bool refreshing { get; set; }
public string thumb { get; set; }
public string key { get; set; }
public string type { get; set; }
public string title { get; set; }
public string agent { get; set; }
public string scanner { get; set; }
public string language { get; set; }
public string uuid { get; set; }
public int updatedAt { get; set; }
public int createdAt { get; set; }
public Location[] Location { get; set; }
public string providerId { get; set; }
public string guid { get; set; }
public List<Genre> genre { get; set; }
public List<Role> role { get; set; }
public string librarySectionID { get; set; }
public string librarySectionTitle { get; set; }
public string librarySectionUUID { get; set; }
public string personal { get; set; }
public string sourceTitle { get; set; }
public string ratingKey { get; set; }
public string studio { get; set; }
public List<Directory> seasons { get; set; }
}
}

@ -0,0 +1,7 @@
namespace Ombi.Api.Plex.Models
{
public class Genre
{
public string tag { get; set; }
}
}

@ -0,0 +1,8 @@
namespace Ombi.Api.Plex.Models
{
public class Location
{
public int id { get; set; }
public string path { get; set; }
}
}

@ -0,0 +1,26 @@
using System.Collections.Generic;
namespace Ombi.Api.Plex.Models
{
public class Mediacontainer
{
public int size { get; set; }
public bool allowSync { get; set; }
public string identifier { get; set; }
public string mediaTagPrefix { get; set; }
public int mediaTagVersion { get; set; }
public string title1 { get; set; }
public List<Directory> Directory { get; set; }
public string art { get; set; }
public int librarySectionID { get; set; }
public string librarySectionTitle { get; set; }
public string librarySectionUUID { get; set; }
public bool nocache { get; set; }
public string thumb { get; set; }
public string title2 { get; set; }
public string viewGroup { get; set; }
public int viewMode { get; set; }
public Metadata[] Metadata { get; set; }
}
}

@ -0,0 +1,21 @@
namespace Ombi.Api.Plex.Models
{
public class Medium
{
public string videoResolution { get; set; }
public int id { get; set; }
public int duration { get; set; }
public int bitrate { get; set; }
public int width { get; set; }
public int height { get; set; }
public float aspectRatio { get; set; }
public int audioChannels { get; set; }
public string audioCodec { get; set; }
public string videoCodec { get; set; }
public string container { get; set; }
public string videoFrameRate { get; set; }
public string audioProfile { get; set; }
public string videoProfile { get; set; }
public Part[] Part { get; set; }
}
}

@ -0,0 +1,50 @@
namespace Ombi.Api.Plex.Models
{
public class Metadata
{
public string ratingKey { get; set; }
public string key { get; set; }
public string studio { get; set; }
public string type { get; set; }
public string title { get; set; }
public string contentRating { get; set; }
public string summary { get; set; }
public int index { get; set; }
public float rating { get; set; }
public int viewCount { get; set; }
public int lastViewedAt { get; set; }
public int year { get; set; }
public string thumb { get; set; }
public string art { get; set; }
public string banner { get; set; }
public string theme { get; set; }
public int duration { get; set; }
public string originallyAvailableAt { get; set; }
public int leafCount { get; set; }
public int viewedLeafCount { get; set; }
public int childCount { get; set; }
public int addedAt { get; set; }
public int updatedAt { get; set; }
public Genre[] Genre { get; set; }
public Role[] Role { get; set; }
public string primaryExtraKey { get; set; }
public string parentRatingKey { get; set; }
public string grandparentRatingKey { get; set; }
public string guid { get; set; }
public int librarySectionID { get; set; }
public string librarySectionKey { get; set; }
public string grandparentKey { get; set; }
public string parentKey { get; set; }
public string grandparentTitle { get; set; }
public string parentTitle { get; set; }
public int parentIndex { get; set; }
public string parentThumb { get; set; }
public string grandparentThumb { get; set; }
public string grandparentArt { get; set; }
public string grandparentTheme { get; set; }
public string chapterSource { get; set; }
public Medium[] Media { get; set; }
public Director[] Director { get; set; }
public Writer[] Writer { get; set; }
}
}

@ -0,0 +1,15 @@
namespace Ombi.Api.Plex.Models
{
public class Part
{
public int id { get; set; }
public string key { get; set; }
public int duration { get; set; }
public string file { get; set; }
public int size { get; set; }
public string audioProfile { get; set; }
public string container { get; set; }
public string videoProfile { get; set; }
public Stream[] Stream { get; set; }
}
}

@ -0,0 +1,33 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: Library.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
namespace Ombi.Api.Plex.Models
{
public class PlexLibraries
{
public Mediacontainer MediaContainer { get; set; }
}
}

@ -0,0 +1,33 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: PlexMetadata.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
namespace Ombi.Api.Plex.Models
{
public class PlexMetadata
{
public Mediacontainer MediaContainer { get; set; }
}
}

@ -0,0 +1,7 @@
namespace Ombi.Api.Plex.Models
{
public class Role
{
public string tag { get; set; }
}
}

@ -0,0 +1,28 @@
namespace Ombi.Api.Plex.Models
{
public class Stream
{
public int id { get; set; }
public int streamType { get; set; }
public bool _default { get; set; }
public string codec { get; set; }
public int index { get; set; }
public int bitrate { get; set; }
public int bitDepth { get; set; }
public string chromaSubsampling { get; set; }
public float frameRate { get; set; }
public bool hasScalingMatrix { get; set; }
public int height { get; set; }
public int level { get; set; }
public string profile { get; set; }
public int refFrames { get; set; }
public string scanType { get; set; }
public int width { get; set; }
public int channels { get; set; }
public string language { get; set; }
public string languageCode { get; set; }
public string audioChannelLayout { get; set; }
public int samplingRate { get; set; }
public bool selected { get; set; }
}
}

@ -0,0 +1,9 @@
namespace Ombi.Api.Plex.Models
{
public class Writer
{
public int id { get; set; }
public string filter { get; set; }
public string tag { get; set; }
}
}

@ -1,6 +1,7 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Ombi.Api.Plex.Models;
using Ombi.Api.Plex.Models.Server;
using Ombi.Api.Plex.Models.Status;
@ -61,6 +62,52 @@ namespace Ombi.Api.Plex
return await Api.Request<PlexServer>(request);
}
public async Task<PlexLibraries> GetLibrarySections(string authToken, string plexFullHost)
{
var request = new Request(plexFullHost, "library/sections", HttpMethod.Get);
AddHeaders(request, authToken);
return await Api.Request<PlexLibraries>(request);
}
public async Task<PlexLibraries> GetLibrary(string authToken, string plexFullHost, string libraryId)
{
var request = new Request(plexFullHost, $"library/sections/{libraryId}/all", HttpMethod.Get);
AddHeaders(request, authToken);
return await Api.Request<PlexLibraries>(request);
}
/// <summary>
// 192.168.1.69:32400/library/metadata/3662/allLeaves
// The metadata ratingkey should be in the Cache
// Search for it and then call the above with the Directory.RatingKey
// THEN! We need the episode metadata using result.Vide.Key ("/library/metadata/3664")
// We then have the GUID which contains the TVDB ID plus the season and episode number: guid="com.plexapp.agents.thetvdb://269586/2/8?lang=en"
/// </summary>
/// <param name="authToken"></param>
/// <param name="plexFullHost"></param>
/// <param name="ratingKey"></param>
/// <returns></returns>
public async Task<PlexMetadata> GetEpisodeMetaData(string authToken, string plexFullHost, string ratingKey)
{
var request = new Request(plexFullHost, $"/library/metadata/{ratingKey}", HttpMethod.Get);
AddHeaders(request, authToken);
return await Api.Request<PlexMetadata>(request);
}
public async Task<PlexMetadata> GetMetadata(string authToken, string plexFullHost, string itemId)
{
var request = new Request(plexFullHost, $"library/metadata/{itemId}", HttpMethod.Get);
AddHeaders(request, authToken);
return await Api.Request<PlexMetadata>(request);
}
public async Task<PlexMetadata> GetSeasons(string authToken, string plexFullHost, string ratingKey)
{
var request = new Request(plexFullHost, $"library/metadata/{ratingKey}/children", HttpMethod.Get);
AddHeaders(request, authToken);
return await Api.Request<PlexMetadata>(request);
}
/// <summary>
/// Adds the required headers and also the authorization header
/// </summary>
@ -81,8 +128,8 @@ namespace Ombi.Api.Plex
request.AddHeader("X-Plex-Client-Identifier", $"OmbiV3");
request.AddHeader("X-Plex-Product", "Ombi");
request.AddHeader("X-Plex-Version", "3");
request.AddContentHeader("Content-Type", "application/json" );
request.AddHeader("Accept","application/json");
request.AddContentHeader("Content-Type", request.ContentType == ContentType.Json ? "application/json" : "application/xml");
request.AddHeader("Accept", "application/json");
}
}
}

@ -13,20 +13,7 @@ namespace Ombi.Api
{
NullValueHandling = NullValueHandling.Ignore
};
public async Task<T> Get<T>(Uri uri)
{
var h = new HttpClient();
//h.DefaultRequestHeaders.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("application/json"));
var response = await h.GetAsync(uri);
if (!response.IsSuccessStatusCode)
{
// Logging
}
var receiveString = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(receiveString, Settings);
}
public async Task<T> Request<T>(Request request)
{
using (var httpClient = new HttpClient())

@ -0,0 +1,114 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: PlexHelper.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;
namespace Ombi.Helpers
{
public class PlexHelper
{
public static string GetProviderIdFromPlexGuid(string guid)
{
if (string.IsNullOrEmpty(guid))
return guid;
var guidSplit = guid.Split(new[] { '/', '?' }, StringSplitOptions.RemoveEmptyEntries);
if (guidSplit.Length > 1)
{
return guidSplit[1];
}
return string.Empty;
}
public static EpisodeModelHelper GetSeasonsAndEpisodesFromPlexGuid(string guid)
{
var ep = new EpisodeModelHelper();
//guid="com.plexapp.agents.thetvdb://269586/2/8?lang=en"
if (string.IsNullOrEmpty(guid))
return null;
try
{
var guidSplit = guid.Split(new[] { '/', '?' }, StringSplitOptions.RemoveEmptyEntries);
if (guidSplit.Length > 2)
{
ep.ProviderId = guidSplit[1];
ep.SeasonNumber = int.Parse(guidSplit[2]);
ep.EpisodeNumber = int.Parse(guidSplit[3]);
}
return ep;
}
catch (Exception e)
{
return ep;
}
}
public static int GetSeasonNumberFromTitle(string title)
{
if (string.IsNullOrEmpty(title))
{
return 0;
}
var split = title.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (split.Length < 2)
{
// Cannot get the season number, it's not in the usual format
return 0;
}
int season;
if (int.TryParse(split[1], out season))
{
return season;
}
return 0;
}
public static string GetPlexMediaUrl(string machineId, string mediaId)
{
var url =
$"https://app.plex.tv/web/app#!/server/{machineId}/details?key=library%2Fmetadata%2F{mediaId}";
return url;
}
public static string FormatGenres(string tags)
{
var split = tags.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
return string.Join(", ", split);
}
}
public class EpisodeModelHelper
{
public string ProviderId { get; set; }
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
}
}

@ -0,0 +1,143 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: PlexContentCacher.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.Linq;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Helpers;
namespace Ombi.Schedule.Jobs
{
public partial class PlexContentCacher
{
public PlexContentCacher(ISettingsService<PlexSettings> plex, IPlexApi plexApi)
{
Plex = plex;
PlexApi = plexApi;
}
private ISettingsService<PlexSettings> Plex { get; }
private IPlexApi PlexApi { get; }
public void CacheContent()
{
var plexSettings = Plex.GetSettings();
if (!plexSettings.Enable)
{
return;
}
if (!ValidateSettings(plexSettings))
{
return;
}
//TODO
//var libraries = CachedLibraries(plexSettings);
//if (libraries == null || !libraries.Any())
//{
// return;
//}
}
//private List<PlexLibraries> CachedLibraries(PlexSettings plexSettings)
//{
// var results = new List<PlexLibraries>();
// results = GetLibraries(plexSettings);
// foreach (PlexLibraries t in results)
// {
// foreach (var t1 in t.MediaContainer.Directory)
// {
// var currentItem = t1;
// var metaData = PlexApi.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri,
// currentItem.ratingKey).Result;
// // Get the seasons for each show
// if (currentItem.type.Equals(PlexMediaType.Show.ToString(), StringComparison.CurrentCultureIgnoreCase))
// {
// var seasons = PlexApi.GetSeasons(plexSettings.PlexAuthToken, plexSettings.FullUri,
// currentItem.ratingKey).Result;
// // We do not want "all episodes" this as a season
// var filtered = seasons.MediaContainer.Directory.Where(x => !x.title.Equals("All episodes", StringComparison.CurrentCultureIgnoreCase));
// t1.seasons.AddRange(filtered);
// }
// var providerId = PlexHelper.GetProviderIdFromPlexGuid(metaData.MediaContainer.);
// t1.providerId = providerId;
// }
// foreach (Video t1 in t.Video)
// {
// var currentItem = t1;
// var metaData = PlexApi.GetMetadata(plexSettings.PlexAuthToken, plexSettings.FullUri,
// currentItem.RatingKey);
// var providerId = PlexHelper.GetProviderIdFromPlexGuid(metaData.Video.Guid);
// t1.ProviderId = providerId;
// }
// }
//}
private List<PlexLibraries> GetLibraries(PlexSettings plexSettings)
{
var sections = PlexApi.GetLibrarySections(plexSettings.PlexAuthToken, plexSettings.FullUri).Result;
var libs = new List<PlexLibraries>();
if (sections != null)
{
foreach (var dir in sections.MediaContainer.Directory ?? new List<Directory>())
{
var lib = PlexApi.GetLibrary(plexSettings.PlexAuthToken, plexSettings.FullUri, dir.key).Result;
if (lib != null)
{
libs.Add(lib);
}
}
}
return libs;
}
private static bool ValidateSettings(PlexSettings plex)
{
if (plex.Enable)
{
if (plex?.Ip == null || plex?.PlexAuthToken == null)
{
return false;
}
}
return plex.Enable;
}
}
}

@ -0,0 +1,40 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: PlexContentCacher.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
namespace Ombi.Schedule.Jobs
{
public partial class PlexContentCacher
{
public enum PlexMediaType
{
Movie,
Show,
Artist
}
}
}

@ -11,4 +11,9 @@
<PackageReference Include="Hangfire.RecurringJobExtensions" Version="1.1.6" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Api.Plex\Ombi.Api.Plex.csproj" />
<ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj" />
</ItemGroup>
</Project>

@ -79,7 +79,7 @@
</div>-->
</div>
<div class="col-sm-3 col-sm-push-3">
<div *ngIf="!request.admin">
<div *ngIf="request.admin">
<div *ngIf="!request.approved">
<form>
<input name="requestId" type="text" value="{{request.requestId}}" hidden="hidden" />

Loading…
Cancel
Save