New: Import from Plex Watchlist
This commit is contained in:
parent
5923b4ae0d
commit
f6fbd3cfee
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"MediaContainer": {
|
||||||
|
"librarySectionID": "watchlist",
|
||||||
|
"librarySectionTitle": "Watchlist",
|
||||||
|
"offset": 0,
|
||||||
|
"totalSize": 3,
|
||||||
|
"identifier": "tv.plex.provider.metadata",
|
||||||
|
"size": 3,
|
||||||
|
"Metadata": [
|
||||||
|
{
|
||||||
|
"type": "show",
|
||||||
|
"title": "30 Rock",
|
||||||
|
"year": 2006,
|
||||||
|
"Guid": [
|
||||||
|
{
|
||||||
|
"id": "tvdb://79488"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "show",
|
||||||
|
"title": "Anthony Bourdain: No Reservations",
|
||||||
|
"year": 2005,
|
||||||
|
"Guid": [
|
||||||
|
{
|
||||||
|
"id": "imdb://tt0475900"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "tmdb://4533"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "tvdb://79668"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "show",
|
||||||
|
"title": "Series Title",
|
||||||
|
"year": 2021,
|
||||||
|
"Guid": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
|
using NzbDrone.Core.ImportLists;
|
||||||
|
using NzbDrone.Core.ImportLists.Plex;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.ImportList.Plex
|
||||||
|
{
|
||||||
|
public class PlexTest : CoreTest<PlexParser>
|
||||||
|
{
|
||||||
|
private ImportListResponse CreateResponse(string url, string content)
|
||||||
|
{
|
||||||
|
var httpRequest = new HttpRequest(url);
|
||||||
|
var httpResponse = new HttpResponse(httpRequest, new HttpHeader(), Encoding.UTF8.GetBytes(content));
|
||||||
|
|
||||||
|
return new ImportListResponse(new ImportListRequest(httpRequest), httpResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_parse_plex_watchlist()
|
||||||
|
{
|
||||||
|
var json = ReadAllText("Files/plex_watchlist.json");
|
||||||
|
|
||||||
|
var result = Subject.ParseResponse(CreateResponse("https://metadata.provider.plex.tv/library/sections/watchlist/all", json));
|
||||||
|
|
||||||
|
result.First().Title.Should().Be("30 Rock");
|
||||||
|
result.First().Year.Should().Be(2006);
|
||||||
|
result.First().TvdbId.Should().Be(79488);
|
||||||
|
|
||||||
|
result[1].TmdbId.Should().Be(4533);
|
||||||
|
result[1].ImdbId.Should().Be("tt0475900");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -121,6 +121,8 @@ namespace NzbDrone.Core.ImportLists
|
||||||
seriesToAdd.Add(new Series
|
seriesToAdd.Add(new Series
|
||||||
{
|
{
|
||||||
TvdbId = report.TvdbId,
|
TvdbId = report.TvdbId,
|
||||||
|
Title = report.Title,
|
||||||
|
Year = report.Year,
|
||||||
Monitored = monitored,
|
Monitored = monitored,
|
||||||
RootFolderPath = importList.RootFolderPath,
|
RootFolderPath = importList.RootFolderPath,
|
||||||
QualityProfileId = importList.QualityProfileId,
|
QualityProfileId = importList.QualityProfileId,
|
||||||
|
|
|
@ -3,6 +3,7 @@ namespace NzbDrone.Core.ImportLists
|
||||||
public enum ImportListType
|
public enum ImportListType
|
||||||
{
|
{
|
||||||
Program,
|
Program,
|
||||||
|
Plex,
|
||||||
Trakt,
|
Trakt,
|
||||||
Other
|
Other
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Common.Http;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.Exceptions;
|
||||||
|
using NzbDrone.Core.Notifications.Plex.PlexTv;
|
||||||
|
using NzbDrone.Core.Parser;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.ImportLists.Plex
|
||||||
|
{
|
||||||
|
public class PlexImport : HttpImportListBase<PlexListSettings>
|
||||||
|
{
|
||||||
|
public readonly IPlexTvService _plexTvService;
|
||||||
|
public override ImportListType ListType => ImportListType.Plex;
|
||||||
|
|
||||||
|
public PlexImport(IPlexTvService plexTvService,
|
||||||
|
IHttpClient httpClient,
|
||||||
|
IImportListStatusService importListStatusService,
|
||||||
|
IConfigService configService,
|
||||||
|
IParsingService parsingService,
|
||||||
|
Logger logger)
|
||||||
|
: base(httpClient, importListStatusService, configService, parsingService, logger)
|
||||||
|
{
|
||||||
|
_plexTvService = plexTvService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Name => "Plex Watchlist";
|
||||||
|
|
||||||
|
public override IList<ImportListItemInfo> Fetch()
|
||||||
|
{
|
||||||
|
Settings.Validate().Filter("AccessToken").ThrowOnError();
|
||||||
|
|
||||||
|
// var generator = GetRequestGenerator();
|
||||||
|
|
||||||
|
return FetchItems(g =>g.GetListItems());
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IParseImportListResponse GetParser()
|
||||||
|
{
|
||||||
|
return new PlexParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IImportListRequestGenerator GetRequestGenerator()
|
||||||
|
{
|
||||||
|
return new PlexListRequestGenerator(_plexTvService)
|
||||||
|
{
|
||||||
|
Settings = Settings
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object RequestAction(string action, IDictionary<string, string> query)
|
||||||
|
{
|
||||||
|
if (action == "startOAuth")
|
||||||
|
{
|
||||||
|
Settings.Validate().Filter("ConsumerKey", "ConsumerSecret").ThrowOnError();
|
||||||
|
|
||||||
|
return _plexTvService.GetPinUrl();
|
||||||
|
}
|
||||||
|
else if (action == "continueOAuth")
|
||||||
|
{
|
||||||
|
Settings.Validate().Filter("ConsumerKey", "ConsumerSecret").ThrowOnError();
|
||||||
|
|
||||||
|
if (query["callbackUrl"].IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
throw new BadRequestException("QueryParam callbackUrl invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query["id"].IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
throw new BadRequestException("QueryParam id invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query["code"].IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
throw new BadRequestException("QueryParam code invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return _plexTvService.GetSignInUrl(query["callbackUrl"], Convert.ToInt32(query["id"]), query["code"]);
|
||||||
|
}
|
||||||
|
else if (action == "getOAuthToken")
|
||||||
|
{
|
||||||
|
Settings.Validate().Filter("ConsumerKey", "ConsumerSecret").ThrowOnError();
|
||||||
|
|
||||||
|
if (query["pinId"].IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
throw new BadRequestException("QueryParam pinId invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var accessToken = _plexTvService.GetAuthToken(Convert.ToInt32(query["pinId"]));
|
||||||
|
|
||||||
|
return new
|
||||||
|
{
|
||||||
|
accessToken
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return new { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Core.Notifications.Plex.PlexTv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.ImportLists.Plex
|
||||||
|
{
|
||||||
|
public class PlexListRequestGenerator : IImportListRequestGenerator
|
||||||
|
{
|
||||||
|
private readonly IPlexTvService _plexTvService;
|
||||||
|
public PlexListSettings Settings { get; set; }
|
||||||
|
|
||||||
|
public PlexListRequestGenerator(IPlexTvService plexTvService)
|
||||||
|
{
|
||||||
|
_plexTvService = plexTvService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual ImportListPageableRequestChain GetListItems()
|
||||||
|
{
|
||||||
|
var pageableRequests = new ImportListPageableRequestChain();
|
||||||
|
|
||||||
|
pageableRequests.Add(GetMoviesRequest());
|
||||||
|
|
||||||
|
return pageableRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<ImportListRequest> GetMoviesRequest()
|
||||||
|
{
|
||||||
|
var request = new ImportListRequest(_plexTvService.GetWatchlist(Settings.AccessToken));
|
||||||
|
|
||||||
|
yield return request;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
using FluentValidation;
|
||||||
|
using NzbDrone.Core.Annotations;
|
||||||
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.ImportLists.Plex
|
||||||
|
{
|
||||||
|
public class PlexListSettingsValidator : AbstractValidator<PlexListSettings>
|
||||||
|
{
|
||||||
|
public PlexListSettingsValidator()
|
||||||
|
{
|
||||||
|
RuleFor(c => c.AccessToken).NotEmpty()
|
||||||
|
.OverridePropertyName("SignIn")
|
||||||
|
.WithMessage("Must authenticate with Plex");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PlexListSettings : IImportListSettings
|
||||||
|
{
|
||||||
|
protected virtual PlexListSettingsValidator Validator => new PlexListSettingsValidator();
|
||||||
|
|
||||||
|
public PlexListSettings()
|
||||||
|
{
|
||||||
|
SignIn = "startOAuth";
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual string Scope => "";
|
||||||
|
|
||||||
|
public string BaseUrl { get; set; }
|
||||||
|
|
||||||
|
[FieldDefinition(0, Label = "Access Token", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)]
|
||||||
|
public string AccessToken { get; set; }
|
||||||
|
|
||||||
|
[FieldDefinition(99, Label = "Authenticate with Plex.tv", Type = FieldType.OAuth)]
|
||||||
|
public string SignIn { get; set; }
|
||||||
|
|
||||||
|
public NzbDroneValidationResult Validate()
|
||||||
|
{
|
||||||
|
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
|
using NzbDrone.Core.ImportLists.Exceptions;
|
||||||
|
using NzbDrone.Core.Notifications.Plex.Server;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.ImportLists.Plex
|
||||||
|
{
|
||||||
|
public class PlexParser : IParseImportListResponse
|
||||||
|
{
|
||||||
|
private ImportListResponse _importResponse;
|
||||||
|
|
||||||
|
public virtual IList<ImportListItemInfo> ParseResponse(ImportListResponse importResponse)
|
||||||
|
{
|
||||||
|
List<PlexSectionItem> items;
|
||||||
|
|
||||||
|
_importResponse = importResponse;
|
||||||
|
|
||||||
|
var series = new List<ImportListItemInfo>();
|
||||||
|
|
||||||
|
if (!PreProcess(_importResponse))
|
||||||
|
{
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
|
||||||
|
items = Json.Deserialize<PlexResponse<PlexSectionResponse>>(_importResponse.Content)
|
||||||
|
.MediaContainer
|
||||||
|
.Items;
|
||||||
|
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
var tvdbIdString = FindGuid(item.Guids, "tvdb");
|
||||||
|
var tmdbIdString = FindGuid(item.Guids, "tmdb");
|
||||||
|
var imdbId = FindGuid(item.Guids, "imdb");
|
||||||
|
|
||||||
|
int.TryParse(tvdbIdString, out int tvdbId);
|
||||||
|
int.TryParse(tmdbIdString, out int tmdbId);
|
||||||
|
|
||||||
|
series.Add(new ImportListItemInfo
|
||||||
|
{
|
||||||
|
TvdbId = tvdbId,
|
||||||
|
TmdbId = tmdbId,
|
||||||
|
ImdbId = imdbId,
|
||||||
|
Title = item.Title,
|
||||||
|
Year = item.Year
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual bool PreProcess(ImportListResponse importListResponse)
|
||||||
|
{
|
||||||
|
if (importListResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
|
||||||
|
{
|
||||||
|
throw new ImportListException(importListResponse, "Plex API call resulted in an unexpected StatusCode [{0}]", importListResponse.HttpResponse.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (importListResponse.HttpResponse.Headers.ContentType != null && importListResponse.HttpResponse.Headers.ContentType.Contains("text/json") &&
|
||||||
|
importListResponse.HttpRequest.Headers.Accept != null && !importListResponse.HttpRequest.Headers.Accept.Contains("text/json"))
|
||||||
|
{
|
||||||
|
throw new ImportListException(importListResponse, "Plex API responded with html content. Site is likely blocked or unavailable.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FindGuid(List<PlexSectionItemGuid> guids, string prefix)
|
||||||
|
{
|
||||||
|
var scheme = $"{prefix}://";
|
||||||
|
|
||||||
|
return guids.FirstOrDefault((guid) => guid.Id.StartsWith(scheme))?.Id.Replace(scheme, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace NzbDrone.Core.Notifications.Plex
|
||||||
|
{
|
||||||
|
public enum PlexMediaType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Movie,
|
||||||
|
Show
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,8 @@ namespace NzbDrone.Core.Notifications.Plex.PlexTv
|
||||||
PlexTvPinUrlResponse GetPinUrl();
|
PlexTvPinUrlResponse GetPinUrl();
|
||||||
PlexTvSignInUrlResponse GetSignInUrl(string callbackUrl, int pinId, string pinCode);
|
PlexTvSignInUrlResponse GetSignInUrl(string callbackUrl, int pinId, string pinCode);
|
||||||
string GetAuthToken(int pinId);
|
string GetAuthToken(int pinId);
|
||||||
|
|
||||||
|
HttpRequest GetWatchlist(string authToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PlexTvService : IPlexTvService
|
public class PlexTvService : IPlexTvService
|
||||||
|
@ -80,5 +82,31 @@ namespace NzbDrone.Core.Notifications.Plex.PlexTv
|
||||||
|
|
||||||
return authToken;
|
return authToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HttpRequest GetWatchlist(string authToken)
|
||||||
|
{
|
||||||
|
var clientIdentifier = _configService.PlexClientIdentifier;
|
||||||
|
|
||||||
|
var requestBuilder = new HttpRequestBuilder("https://metadata.provider.plex.tv/library/sections/watchlist/all")
|
||||||
|
.Accept(HttpAccept.Json)
|
||||||
|
.AddQueryParam("clientID", clientIdentifier)
|
||||||
|
.AddQueryParam("context[device][product]", BuildInfo.AppName)
|
||||||
|
.AddQueryParam("context[device][platform]", "Windows")
|
||||||
|
.AddQueryParam("context[device][platformVersion]", "7")
|
||||||
|
.AddQueryParam("context[device][version]", BuildInfo.Version.ToString())
|
||||||
|
.AddQueryParam("includeFields", "title,type,year,ratingKey")
|
||||||
|
.AddQueryParam("includeElements", "Guid")
|
||||||
|
.AddQueryParam("sort", "watchlistedAt:desc")
|
||||||
|
.AddQueryParam("type", (int)PlexMediaType.Show);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(authToken))
|
||||||
|
{
|
||||||
|
requestBuilder.AddQueryParam("X-Plex-Token", authToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = requestBuilder.Build();
|
||||||
|
|
||||||
|
return request;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,27 @@ using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications.Plex.Server
|
namespace NzbDrone.Core.Notifications.Plex.Server
|
||||||
{
|
{
|
||||||
|
public class PlexSectionItemGuid
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class PlexSectionItem
|
public class PlexSectionItem
|
||||||
{
|
{
|
||||||
|
public PlexSectionItem()
|
||||||
|
{
|
||||||
|
Guids = new List<PlexSectionItemGuid>();
|
||||||
|
}
|
||||||
|
|
||||||
[JsonProperty("ratingKey")]
|
[JsonProperty("ratingKey")]
|
||||||
public int Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
public int Year { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("Guid")]
|
||||||
|
public List<PlexSectionItemGuid> Guids { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PlexSectionResponse
|
public class PlexSectionResponse
|
||||||
|
|
|
@ -14,10 +14,10 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
||||||
{
|
{
|
||||||
List<PlexSection> GetTvSections(PlexServerSettings settings);
|
List<PlexSection> GetTvSections(PlexServerSettings settings);
|
||||||
void Update(int sectionId, PlexServerSettings settings);
|
void Update(int sectionId, PlexServerSettings settings);
|
||||||
void UpdateSeries(int metadataId, PlexServerSettings settings);
|
void UpdateSeries(string metadataId, PlexServerSettings settings);
|
||||||
string Version(PlexServerSettings settings);
|
string Version(PlexServerSettings settings);
|
||||||
List<PlexPreference> Preferences(PlexServerSettings settings);
|
List<PlexPreference> Preferences(PlexServerSettings settings);
|
||||||
int? GetMetadataId(int sectionId, int tvdbId, string language, PlexServerSettings settings);
|
string GetMetadataId(int sectionId, int tvdbId, string language, PlexServerSettings settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PlexServerProxy : IPlexServerProxy
|
public class PlexServerProxy : IPlexServerProxy
|
||||||
|
@ -71,7 +71,7 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
||||||
CheckForError(response);
|
CheckForError(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateSeries(int metadataId, PlexServerSettings settings)
|
public void UpdateSeries(string metadataId, PlexServerSettings settings)
|
||||||
{
|
{
|
||||||
var resource = $"library/metadata/{metadataId}/refresh";
|
var resource = $"library/metadata/{metadataId}/refresh";
|
||||||
var request = BuildRequest(resource, HttpMethod.PUT, settings);
|
var request = BuildRequest(resource, HttpMethod.PUT, settings);
|
||||||
|
@ -116,7 +116,7 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
||||||
.Preferences;
|
.Preferences;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int? GetMetadataId(int sectionId, int tvdbId, string language, PlexServerSettings settings)
|
public string GetMetadataId(int sectionId, int tvdbId, string language, PlexServerSettings settings)
|
||||||
{
|
{
|
||||||
var guid = $"com.plexapp.agents.thetvdb://{tvdbId}?lang={language}";
|
var guid = $"com.plexapp.agents.thetvdb://{tvdbId}?lang={language}";
|
||||||
var resource = $"library/sections/{sectionId}/all?guid={System.Web.HttpUtility.UrlEncode(guid)}";
|
var resource = $"library/sections/{sectionId}/all?guid={System.Web.HttpUtility.UrlEncode(guid)}";
|
||||||
|
|
|
@ -159,10 +159,10 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
||||||
{
|
{
|
||||||
var metadataId = GetMetadataId(section.Id, series, section.Language, settings);
|
var metadataId = GetMetadataId(section.Id, series, section.Language, settings);
|
||||||
|
|
||||||
if (metadataId.HasValue)
|
if (metadataId.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
_logger.Debug("Updating Plex host: {0}, Section: {1}, Series: {2}", settings.Host, section.Id, series);
|
_logger.Debug("Updating Plex host: {0}, Section: {1}, Series: {2}", settings.Host, section.Id, series);
|
||||||
_plexServerProxy.UpdateSeries(metadataId.Value, settings);
|
_plexServerProxy.UpdateSeries(metadataId, settings);
|
||||||
|
|
||||||
partiallyUpdated = true;
|
partiallyUpdated = true;
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
||||||
return partiallyUpdated;
|
return partiallyUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int? GetMetadataId(int sectionId, Series series, string language, PlexServerSettings settings)
|
private string GetMetadataId(int sectionId, Series series, string language, PlexServerSettings settings)
|
||||||
{
|
{
|
||||||
_logger.Debug("Getting metadata from Plex host: {0} for series: {1}", settings.Host, series);
|
_logger.Debug("Getting metadata from Plex host: {0} for series: {1}", settings.Host, series);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Parser.Model
|
namespace NzbDrone.Core.Parser.Model
|
||||||
{
|
{
|
||||||
|
@ -8,7 +7,10 @@ namespace NzbDrone.Core.Parser.Model
|
||||||
public int ImportListId { get; set; }
|
public int ImportListId { get; set; }
|
||||||
public string ImportList { get; set; }
|
public string ImportList { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
|
public int Year { get; set; }
|
||||||
public int TvdbId { get; set; }
|
public int TvdbId { get; set; }
|
||||||
|
public int TmdbId { get; set; }
|
||||||
|
public string ImdbId { get; set; }
|
||||||
public DateTime ReleaseDate { get; set; }
|
public DateTime ReleaseDate { get; set; }
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|
|
@ -6,6 +6,7 @@ using FluentValidation;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.EnsureThat;
|
using NzbDrone.Common.EnsureThat;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Exceptions;
|
using NzbDrone.Core.Exceptions;
|
||||||
using NzbDrone.Core.MetadataSource;
|
using NzbDrone.Core.MetadataSource;
|
||||||
using NzbDrone.Core.Organizer;
|
using NzbDrone.Core.Organizer;
|
||||||
|
@ -61,8 +62,15 @@ namespace NzbDrone.Core.Tv
|
||||||
var existingSeries = _seriesService.GetAllSeries();
|
var existingSeries = _seriesService.GetAllSeries();
|
||||||
|
|
||||||
foreach (var s in newSeries)
|
foreach (var s in newSeries)
|
||||||
|
{
|
||||||
|
if (s.Path.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
_logger.Info("Adding Series {0} Root Folder Path: [{1}]", s, s.RootFolderPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
_logger.Info("Adding Series {0} Path: [{1}]", s, s.Path);
|
_logger.Info("Adding Series {0} Path: [{1}]", s, s.Path);
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue