mirror of
https://github.com/lidarr/lidarr.git
synced 2025-08-14 02:37:08 -07:00
New: Improved Plex library updating
(cherry picked from commit 98308737cfa78a41ec22a2b23a80bf316bd779ea) Closes #3438 Closes #3445 Closes #3465
This commit is contained in:
parent
d43d404931
commit
40c55608ce
2 changed files with 37 additions and 140 deletions
|
@ -14,11 +14,8 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
|||
public interface IPlexServerProxy
|
||||
{
|
||||
List<PlexSection> GetArtistSections(PlexServerSettings settings);
|
||||
void Update(int sectionId, PlexServerSettings settings);
|
||||
void UpdateArtist(int metadataId, PlexServerSettings settings);
|
||||
string Version(PlexServerSettings settings);
|
||||
List<PlexPreference> Preferences(PlexServerSettings settings);
|
||||
int? GetMetadataId(int sectionId, string mbId, string language, PlexServerSettings settings);
|
||||
void Update(int sectionId, string path, PlexServerSettings settings);
|
||||
}
|
||||
|
||||
public class PlexServerProxy : IPlexServerProxy
|
||||
|
@ -63,19 +60,13 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
|||
.ToList();
|
||||
}
|
||||
|
||||
public void Update(int sectionId, PlexServerSettings settings)
|
||||
public void Update(int sectionId, string path, PlexServerSettings settings)
|
||||
{
|
||||
var resource = $"library/sections/{sectionId}/refresh";
|
||||
var request = BuildRequest(resource, HttpMethod.Get, settings);
|
||||
var response = ProcessRequest(request);
|
||||
|
||||
CheckForError(response);
|
||||
}
|
||||
request.AddQueryParam("path", path);
|
||||
|
||||
public void UpdateArtist(int metadataId, PlexServerSettings settings)
|
||||
{
|
||||
var resource = $"library/metadata/{metadataId}/refresh";
|
||||
var request = BuildRequest(resource, HttpMethod.Put, settings);
|
||||
var response = ProcessRequest(request);
|
||||
|
||||
CheckForError(response);
|
||||
|
@ -99,55 +90,6 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
|||
.Version;
|
||||
}
|
||||
|
||||
public List<PlexPreference> Preferences(PlexServerSettings settings)
|
||||
{
|
||||
var request = BuildRequest(":/prefs", HttpMethod.Get, settings);
|
||||
var response = ProcessRequest(request);
|
||||
|
||||
CheckForError(response);
|
||||
|
||||
if (response.Contains("_children"))
|
||||
{
|
||||
return Json.Deserialize<PlexPreferencesLegacy>(response)
|
||||
.Preferences;
|
||||
}
|
||||
|
||||
return Json.Deserialize<PlexResponse<PlexPreferences>>(response)
|
||||
.MediaContainer
|
||||
.Preferences;
|
||||
}
|
||||
|
||||
public int? GetMetadataId(int sectionId, string mbId, string language, PlexServerSettings settings)
|
||||
{
|
||||
var guid = string.Format("com.plexapp.agents.lastfm://{0}?lang={1}", mbId, language); // TODO Plex Route for MB? LastFM?
|
||||
var resource = $"library/sections/{sectionId}/all?guid={System.Web.HttpUtility.UrlEncode(guid)}";
|
||||
var request = BuildRequest(resource, HttpMethod.Get, settings);
|
||||
var response = ProcessRequest(request);
|
||||
|
||||
CheckForError(response);
|
||||
|
||||
List<PlexSectionItem> items;
|
||||
|
||||
if (response.Contains("_children"))
|
||||
{
|
||||
items = Json.Deserialize<PlexSectionResponseLegacy>(response)
|
||||
.Items;
|
||||
}
|
||||
else
|
||||
{
|
||||
items = Json.Deserialize<PlexResponse<PlexSectionResponse>>(response)
|
||||
.MediaContainer
|
||||
.Items;
|
||||
}
|
||||
|
||||
if (items == null || items.Empty())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return items.First().Id;
|
||||
}
|
||||
|
||||
private HttpRequestBuilder BuildRequest(string resource, HttpMethod method, PlexServerSettings settings)
|
||||
{
|
||||
var scheme = settings.UseSsl ? "https" : "http";
|
||||
|
|
|
@ -8,6 +8,7 @@ using NLog;
|
|||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Core.RootFolders;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Plex.Server
|
||||
|
@ -22,15 +23,15 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
|||
public class PlexServerService : IPlexServerService
|
||||
{
|
||||
private readonly ICached<Version> _versionCache;
|
||||
private readonly ICached<bool> _partialUpdateCache;
|
||||
private readonly IPlexServerProxy _plexServerProxy;
|
||||
private readonly IRootFolderService _rootFolderService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public PlexServerService(ICacheManager cacheManager, IPlexServerProxy plexServerProxy, Logger logger)
|
||||
public PlexServerService(ICacheManager cacheManager, IPlexServerProxy plexServerProxy, IRootFolderService rootFolderService, Logger logger)
|
||||
{
|
||||
_versionCache = cacheManager.GetCache<Version>(GetType(), "versionCache");
|
||||
_partialUpdateCache = cacheManager.GetCache<bool>(GetType(), "partialUpdateCache");
|
||||
_plexServerProxy = plexServerProxy;
|
||||
_rootFolderService = rootFolderService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
@ -50,32 +51,10 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
|||
ValidateVersion(version);
|
||||
|
||||
var sections = GetSections(settings);
|
||||
var partialUpdates = _partialUpdateCache.Get(settings.Host, () => PartialUpdatesAllowed(settings, version), TimeSpan.FromHours(2));
|
||||
|
||||
if (partialUpdates)
|
||||
foreach (var artist in multipleArtist)
|
||||
{
|
||||
var partiallyUpdated = true;
|
||||
|
||||
foreach (var artist in multipleArtist)
|
||||
{
|
||||
partiallyUpdated &= UpdatePartialSection(artist, sections, settings);
|
||||
|
||||
if (!partiallyUpdated)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Only update complete sections if all partial updates failed
|
||||
if (!partiallyUpdated)
|
||||
{
|
||||
_logger.Debug("Unable to update partial section, updating all Music sections");
|
||||
sections.ForEach(s => UpdateSection(s.Id, settings));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sections.ForEach(s => UpdateSection(s.Id, settings));
|
||||
UpdateSections(artist, sections, settings);
|
||||
}
|
||||
|
||||
_logger.Debug("Finished sending Update Request to Plex Server (took {0} ms)", watch.ElapsedMilliseconds);
|
||||
|
@ -94,31 +73,6 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
|||
return _plexServerProxy.GetArtistSections(settings).ToList();
|
||||
}
|
||||
|
||||
private bool PartialUpdatesAllowed(PlexServerSettings settings, Version version)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (version >= new Version(0, 9, 12, 0))
|
||||
{
|
||||
var preferences = GetPreferences(settings);
|
||||
var partialScanPreference = preferences.SingleOrDefault(p => p.Id.Equals("FSEventLibraryPartialScanEnabled"));
|
||||
|
||||
if (partialScanPreference == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return Convert.ToBoolean(partialScanPreference.Value);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn(ex, "Unable to check if partial updates are allowed");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ValidateVersion(Version version)
|
||||
{
|
||||
if (version >= new Version(1, 3, 0) && version < new Version(1, 3, 1))
|
||||
|
@ -137,45 +91,47 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
|||
return version;
|
||||
}
|
||||
|
||||
private List<PlexPreference> GetPreferences(PlexServerSettings settings)
|
||||
private void UpdateSections(Artist artist, List<PlexSection> sections, PlexServerSettings settings)
|
||||
{
|
||||
_logger.Debug("Getting preferences from Plex host: {0}", settings.Host);
|
||||
|
||||
return _plexServerProxy.Preferences(settings);
|
||||
}
|
||||
|
||||
private void UpdateSection(int sectionId, PlexServerSettings settings)
|
||||
{
|
||||
_logger.Debug("Updating Plex host: {0}, Section: {1}", settings.Host, sectionId);
|
||||
|
||||
_plexServerProxy.Update(sectionId, settings);
|
||||
}
|
||||
|
||||
private bool UpdatePartialSection(Artist artist, List<PlexSection> sections, PlexServerSettings settings)
|
||||
{
|
||||
var partiallyUpdated = false;
|
||||
var rootFolderPath = _rootFolderService.GetBestRootFolderPath(artist.Path);
|
||||
var artistRelativePath = rootFolderPath.GetRelativePath(artist.Path);
|
||||
|
||||
// Try to update a matching section location before falling back to updating all section locations.
|
||||
foreach (var section in sections)
|
||||
{
|
||||
var metadataId = GetMetadataId(section.Id, artist, section.Language, settings);
|
||||
|
||||
if (metadataId.HasValue)
|
||||
foreach (var location in section.Locations)
|
||||
{
|
||||
_logger.Debug("Updating Plex host: {0}, Section: {1}, Artist: {2}", settings.Host, section.Id, artist);
|
||||
_plexServerProxy.UpdateArtist(metadataId.Value, settings);
|
||||
if (location.Path.PathEquals(rootFolderPath))
|
||||
{
|
||||
_logger.Debug("Updating matching section location, {0}", location.Path);
|
||||
UpdateSectionPath(artistRelativePath, section, location, settings);
|
||||
|
||||
partiallyUpdated = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return partiallyUpdated;
|
||||
_logger.Debug("Unable to find matching section location, updating all Music sections");
|
||||
|
||||
foreach (var section in sections)
|
||||
{
|
||||
foreach (var location in section.Locations)
|
||||
{
|
||||
UpdateSectionPath(artistRelativePath, section, location, settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int? GetMetadataId(int sectionId, Artist artist, string language, PlexServerSettings settings)
|
||||
private void UpdateSectionPath(string artistRelativePath, PlexSection section, PlexSectionLocation location, PlexServerSettings settings)
|
||||
{
|
||||
_logger.Debug("Getting metadata from Plex host: {0} for artist: {1}", settings.Host, artist);
|
||||
var separator = location.Path.Contains('\\') ? "\\" : "/";
|
||||
var locationRelativePath = artistRelativePath.Replace("\\", separator).Replace("/", separator);
|
||||
|
||||
return _plexServerProxy.GetMetadataId(sectionId, artist.Metadata.Value.ForeignArtistId, language, settings);
|
||||
// Plex location paths trim trailing extraneous separator characters, so it doesn't need to be trimmed
|
||||
var pathToUpdate = $"{location.Path}{separator}{locationRelativePath}";
|
||||
|
||||
_logger.Debug("Updating section location, {0}", location.Path);
|
||||
_plexServerProxy.Update(section.Id, pathToUpdate, settings);
|
||||
}
|
||||
|
||||
public ValidationFailure Test(PlexServerSettings settings)
|
||||
|
@ -183,7 +139,6 @@ namespace NzbDrone.Core.Notifications.Plex.Server
|
|||
try
|
||||
{
|
||||
_versionCache.Remove(settings.Host);
|
||||
_partialUpdateCache.Remove(settings.Host);
|
||||
var sections = GetSections(settings);
|
||||
|
||||
if (sections.Empty())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue