parent
aee8579d18
commit
ad0dc01cf7
|
@ -0,0 +1,32 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Notifications.Emby
|
||||||
|
{
|
||||||
|
public class MediaBrowserItems
|
||||||
|
{
|
||||||
|
public List<MediaBrowserItem> Items { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MediaBrowserItem
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Path { get; set; }
|
||||||
|
|
||||||
|
public MediaBrowserProviderIds ProviderIds { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MediaBrowserProviderIds
|
||||||
|
{
|
||||||
|
public string Imdb { get; set; }
|
||||||
|
public int Tvdb { get; set; }
|
||||||
|
public int TvMaze { get; set; }
|
||||||
|
public int TvRage { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MediaBrowserMatchQuality
|
||||||
|
{
|
||||||
|
Id = 0,
|
||||||
|
Name = 1,
|
||||||
|
None = 2
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,10 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Emby
|
namespace NzbDrone.Core.Notifications.Emby
|
||||||
{
|
{
|
||||||
|
@ -31,6 +35,71 @@ namespace NzbDrone.Core.Notifications.Emby
|
||||||
ProcessRequest(request, settings);
|
ProcessRequest(request, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HashSet<string> GetPaths(MediaBrowserSettings settings, Series series)
|
||||||
|
{
|
||||||
|
var path = "/Items";
|
||||||
|
var url = GetUrl(settings);
|
||||||
|
|
||||||
|
// NameStartsWith uses the sort title, which is not the series title
|
||||||
|
var request = new HttpRequestBuilder(url)
|
||||||
|
.Resource(path)
|
||||||
|
.AddQueryParam("recursive", "true")
|
||||||
|
.AddQueryParam("includeItemTypes", "Series")
|
||||||
|
.AddQueryParam("fields", "Path,ProviderIds")
|
||||||
|
.AddQueryParam("years", series.Year)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var paths = ProcessGetRequest<MediaBrowserItems>(request, settings).Items.GroupBy(item =>
|
||||||
|
{
|
||||||
|
if (item is { ProviderIds.Tvdb: int tvdbid } && tvdbid != 0 && tvdbid == series.TvdbId)
|
||||||
|
{
|
||||||
|
return MediaBrowserMatchQuality.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is { ProviderIds.Imdb: string imdbid } && imdbid == series.ImdbId)
|
||||||
|
{
|
||||||
|
return MediaBrowserMatchQuality.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is { ProviderIds.TvMaze: int tvmazeid } && tvmazeid != 0 && tvmazeid == series.TvMazeId)
|
||||||
|
{
|
||||||
|
return MediaBrowserMatchQuality.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is { ProviderIds.TvRage: int tvrageid } && tvrageid != 0 && tvrageid == series.TvRageId)
|
||||||
|
{
|
||||||
|
return MediaBrowserMatchQuality.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is { Name: var name } && name == series.Title)
|
||||||
|
{
|
||||||
|
return MediaBrowserMatchQuality.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MediaBrowserMatchQuality.None;
|
||||||
|
}, item => item.Path).OrderBy(group => (int)group.Key).First();
|
||||||
|
|
||||||
|
if (paths.Key == MediaBrowserMatchQuality.None)
|
||||||
|
{
|
||||||
|
_logger.Trace("Could not find series by name");
|
||||||
|
|
||||||
|
return new HashSet<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Trace("Found series by name/id: {0}", string.Join(" ", paths));
|
||||||
|
|
||||||
|
return paths.ToHashSet();
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
_logger.Trace("Could not find series by name.");
|
||||||
|
|
||||||
|
return new HashSet<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Update(MediaBrowserSettings settings, string seriesPath, string updateType)
|
public void Update(MediaBrowserSettings settings, string seriesPath, string updateType)
|
||||||
{
|
{
|
||||||
var path = "/Library/Media/Updated";
|
var path = "/Library/Media/Updated";
|
||||||
|
@ -52,6 +121,19 @@ namespace NzbDrone.Core.Notifications.Emby
|
||||||
ProcessRequest(request, settings);
|
ProcessRequest(request, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private T ProcessGetRequest<T>(HttpRequest request, MediaBrowserSettings settings)
|
||||||
|
where T : new()
|
||||||
|
{
|
||||||
|
request.Headers.Add("X-MediaBrowser-Token", settings.ApiKey);
|
||||||
|
|
||||||
|
var response = _httpClient.Get<T>(request);
|
||||||
|
_logger.Trace("Response: {0}", response.Content);
|
||||||
|
|
||||||
|
CheckForError(response);
|
||||||
|
|
||||||
|
return response.Resource;
|
||||||
|
}
|
||||||
|
|
||||||
private string ProcessRequest(HttpRequest request, MediaBrowserSettings settings)
|
private string ProcessRequest(HttpRequest request, MediaBrowserSettings settings)
|
||||||
{
|
{
|
||||||
request.Headers.Add("X-MediaBrowser-Token", settings.ApiKey);
|
request.Headers.Add("X-MediaBrowser-Token", settings.ApiKey);
|
||||||
|
@ -64,10 +146,15 @@ namespace NzbDrone.Core.Notifications.Emby
|
||||||
return response.Content;
|
return response.Content;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpRequest BuildRequest(string path, MediaBrowserSettings settings)
|
private string GetUrl(MediaBrowserSettings settings)
|
||||||
{
|
{
|
||||||
var scheme = settings.UseSsl ? "https" : "http";
|
var scheme = settings.UseSsl ? "https" : "http";
|
||||||
var url = $@"{scheme}://{settings.Address}/mediabrowser";
|
return $@"{scheme}://{settings.Address}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpRequest BuildRequest(string path, MediaBrowserSettings settings)
|
||||||
|
{
|
||||||
|
var url = GetUrl(settings);
|
||||||
|
|
||||||
return new HttpRequestBuilder(url).Resource(path).Build();
|
return new HttpRequestBuilder(url).Resource(path).Build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
@ -32,7 +35,23 @@ namespace NzbDrone.Core.Notifications.Emby
|
||||||
|
|
||||||
public void Update(MediaBrowserSettings settings, Series series, string updateType)
|
public void Update(MediaBrowserSettings settings, Series series, string updateType)
|
||||||
{
|
{
|
||||||
_proxy.Update(settings, series.Path, updateType);
|
HashSet<string> paths;
|
||||||
|
|
||||||
|
paths = _proxy.GetPaths(settings, series);
|
||||||
|
|
||||||
|
var mappedPath = new OsPath(series.Path);
|
||||||
|
|
||||||
|
if (settings.MapTo.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
mappedPath = new OsPath(settings.MapTo) + (mappedPath - new OsPath(settings.MapFrom));
|
||||||
|
}
|
||||||
|
|
||||||
|
paths.Add(mappedPath.ToString());
|
||||||
|
|
||||||
|
foreach (var path in paths)
|
||||||
|
{
|
||||||
|
_proxy.Update(settings, path, updateType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValidationFailure Test(MediaBrowserSettings settings)
|
public ValidationFailure Test(MediaBrowserSettings settings)
|
||||||
|
|
|
@ -13,6 +13,8 @@ namespace NzbDrone.Core.Notifications.Emby
|
||||||
{
|
{
|
||||||
RuleFor(c => c.Host).ValidHost();
|
RuleFor(c => c.Host).ValidHost();
|
||||||
RuleFor(c => c.ApiKey).NotEmpty();
|
RuleFor(c => c.ApiKey).NotEmpty();
|
||||||
|
RuleFor(c => c.MapFrom).NotEmpty().Unless(c => c.MapTo.IsNullOrWhiteSpace());
|
||||||
|
RuleFor(c => c.MapTo).NotEmpty().Unless(c => c.MapFrom.IsNullOrWhiteSpace());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +33,7 @@ namespace NzbDrone.Core.Notifications.Emby
|
||||||
[FieldDefinition(1, Label = "Port")]
|
[FieldDefinition(1, Label = "Port")]
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(2, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Connect to Emby over HTTPS instead of HTTP")]
|
[FieldDefinition(2, Label = "Use SSL", Type = FieldType.Checkbox, HelpText = "Connect to Emby/Jellyfin over HTTPS instead of HTTP")]
|
||||||
public bool UseSsl { get; set; }
|
public bool UseSsl { get; set; }
|
||||||
|
|
||||||
[FieldDefinition(3, Label = "API Key", Privacy = PrivacyLevel.ApiKey)]
|
[FieldDefinition(3, Label = "API Key", Privacy = PrivacyLevel.ApiKey)]
|
||||||
|
@ -43,6 +45,12 @@ namespace NzbDrone.Core.Notifications.Emby
|
||||||
[FieldDefinition(5, Label = "Update Library", HelpText = "Update Library on Import, Rename, or Delete?", Type = FieldType.Checkbox)]
|
[FieldDefinition(5, Label = "Update Library", HelpText = "Update Library on Import, Rename, or Delete?", Type = FieldType.Checkbox)]
|
||||||
public bool UpdateLibrary { get; set; }
|
public bool UpdateLibrary { get; set; }
|
||||||
|
|
||||||
|
[FieldDefinition(6, Label = "Map Paths From", HelpText = "Sonarr path, used to modify series paths when Emby/Jellyfin sees library path location differently from Sonarr(Requires 'UpdateLibrary')", Type = FieldType.Textbox, Advanced = true)]
|
||||||
|
public string MapFrom { get; set; }
|
||||||
|
|
||||||
|
[FieldDefinition(7, Label = "Map Paths To", HelpText = "Emby/Jellyfin path, used to modify series paths when Emby/Jellyfin sees library path location differently from Sonarr(Requires 'UpdateLibrary')", Type = FieldType.Textbox, Advanced = true)]
|
||||||
|
public string MapTo { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string Address => $"{Host.ToUrlHost()}:{Port}";
|
public string Address => $"{Host.ToUrlHost()}:{Port}";
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue