Browse Source

fix plex other video library detection (#2679)

pull/2680/head
Jason Dove 1 month ago committed by GitHub
parent
commit
1f31beab5b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 3
      CHANGELOG.md
  2. 33
      ErsatzTV.Infrastructure/Data/Repositories/MediaSourceRepository.cs
  3. 34
      ErsatzTV.Infrastructure/Plex/PlexServerApiClient.cs

3
CHANGELOG.md

@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
### Fixed
- Fix startup on systems unsupported by NvEncSharp
- Fix detection of Plex Other Video libraries using `Plex Personal Media` agent
- If the library is already detected as a Movies library in ETV, synchronization must be disabled for the library to change it to an Other Videos library
- A warning will be logged when this scenario is detected
## [25.9.0] - 2025-11-29
### Added

33
ErsatzTV.Infrastructure/Data/Repositories/MediaSourceRepository.cs

@ -6,10 +6,12 @@ using ErsatzTV.Core.Interfaces.Repositories; @@ -6,10 +6,12 @@ using ErsatzTV.Core.Interfaces.Repositories;
using ErsatzTV.Core.Jellyfin;
using ErsatzTV.Infrastructure.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace ErsatzTV.Infrastructure.Data.Repositories;
public class MediaSourceRepository(IDbContextFactory<TvContext> dbContextFactory) : IMediaSourceRepository
public class MediaSourceRepository(IDbContextFactory<TvContext> dbContextFactory, ILogger<MediaSourceRepository> logger)
: IMediaSourceRepository
{
public async Task<PlexMediaSource> Add(PlexMediaSource plexMediaSource)
{
@ -166,23 +168,42 @@ public class MediaSourceRepository(IDbContextFactory<TvContext> dbContextFactory @@ -166,23 +168,42 @@ public class MediaSourceRepository(IDbContextFactory<TvContext> dbContextFactory
dbContext.PlexLibraries.Remove(delete);
}
// update library path (for other video metadata)
foreach (PlexLibrary incoming in toUpdate)
{
Option<PlexLibrary> maybeExisting = await dbContext.PlexLibraries
.Include(l => l.Paths)
.SelectOneAsync(l => l.Key, l => l.Key == incoming.Key, cancellationToken);
foreach (LibraryPath existing in maybeExisting.Map(l => l.Paths.HeadOrNone()))
foreach (PlexLibrary existingLibrary in maybeExisting)
{
foreach (LibraryPath path in incoming.Paths.HeadOrNone())
// update library type, but only if not synchronized
if (incoming.MediaKind != existingLibrary.MediaKind)
{
existing.Path = path.Path;
if (existingLibrary.ShouldSyncItems)
{
logger.LogWarning(
"Plex library \"{Name}\" should be type {NewType} (currently {OldType}) but cannot be updated while synchronization is enabled for this library.",
incoming.Name,
incoming.MediaKind,
existingLibrary.MediaKind);
}
else
{
existingLibrary.MediaKind = incoming.MediaKind;
}
}
// update library path (for other video metadata)
foreach (LibraryPath existing in existingLibrary.Paths.HeadOrNone())
{
foreach (LibraryPath path in incoming.Paths.HeadOrNone())
{
existing.Path = path.Path;
}
}
}
}
await dbContext.SaveChangesAsync(cancellationToken);
return deletedMediaIds;

34
ErsatzTV.Infrastructure/Plex/PlexServerApiClient.cs

@ -14,16 +14,10 @@ using Refit; @@ -14,16 +14,10 @@ using Refit;
namespace ErsatzTV.Infrastructure.Plex;
public class PlexServerApiClient : IPlexServerApiClient
public class PlexServerApiClient(PlexEtag plexEtag, ILogger<PlexServerApiClient> logger) : IPlexServerApiClient
{
private readonly ILogger<PlexServerApiClient> _logger;
private readonly PlexEtag _plexEtag;
public PlexServerApiClient(PlexEtag plexEtag, ILogger<PlexServerApiClient> logger)
{
_plexEtag = plexEtag;
_logger = logger;
}
private const string PersonalMediaAgent = "com.plexapp.agents.none";
private const string PlexPersonalMediaAgent = "tv.plex.agents.none";
public async Task<bool> Ping(
PlexConnection connection,
@ -537,7 +531,7 @@ public class PlexServerApiClient : IPlexServerApiClient @@ -537,7 +531,7 @@ public class PlexServerApiClient : IPlexServerApiClient
{
Key = response.Key,
Name = response.Title,
MediaKind = response.Agent == "com.plexapp.agents.none" && response.Language == "xn"
MediaKind = response.Agent is PersonalMediaAgent or PlexPersonalMediaAgent
? LibraryMediaKind.OtherVideos
: LibraryMediaKind.Movies,
ShouldSyncItems = false,
@ -565,13 +559,13 @@ public class PlexServerApiClient : IPlexServerApiClient @@ -565,13 +559,13 @@ public class PlexServerApiClient : IPlexServerApiClient
return new PlexCollection
{
Key = item.RatingKey,
Etag = _plexEtag.ForCollection(item),
Etag = plexEtag.ForCollection(item),
Name = item.Title
};
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error projecting Plex collection");
logger.LogWarning(ex, "Error projecting Plex collection");
return None;
}
}
@ -591,7 +585,7 @@ public class PlexServerApiClient : IPlexServerApiClient @@ -591,7 +585,7 @@ public class PlexServerApiClient : IPlexServerApiClient
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error projecting Plex collection media item");
logger.LogWarning(ex, "Error projecting Plex collection media item");
return None;
}
}
@ -610,7 +604,7 @@ public class PlexServerApiClient : IPlexServerApiClient @@ -610,7 +604,7 @@ public class PlexServerApiClient : IPlexServerApiClient
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error projecting Plex tag");
logger.LogWarning(ex, "Error projecting Plex tag");
return None;
}
}
@ -651,7 +645,7 @@ public class PlexServerApiClient : IPlexServerApiClient @@ -651,7 +645,7 @@ public class PlexServerApiClient : IPlexServerApiClient
var movie = new PlexMovie
{
Etag = _plexEtag.ForMovie(response),
Etag = plexEtag.ForMovie(response),
Key = response.Key,
MovieMetadata = [metadata],
MediaVersions = [version],
@ -884,7 +878,7 @@ public class PlexServerApiClient : IPlexServerApiClient @@ -884,7 +878,7 @@ public class PlexServerApiClient : IPlexServerApiClient
var show = new PlexShow
{
Key = response.Key,
Etag = _plexEtag.ForShow(response),
Etag = plexEtag.ForShow(response),
ShowMetadata = new List<ShowMetadata> { metadata },
TraktListItems = new List<TraktListItem>()
};
@ -1046,7 +1040,7 @@ public class PlexServerApiClient : IPlexServerApiClient @@ -1046,7 +1040,7 @@ public class PlexServerApiClient : IPlexServerApiClient
var season = new PlexSeason
{
Key = response.Key,
Etag = _plexEtag.ForSeason(response),
Etag = plexEtag.ForSeason(response),
SeasonNumber = response.Index,
SeasonMetadata = new List<SeasonMetadata> { metadata },
TraktListItems = new List<TraktListItem>()
@ -1092,7 +1086,7 @@ public class PlexServerApiClient : IPlexServerApiClient @@ -1092,7 +1086,7 @@ public class PlexServerApiClient : IPlexServerApiClient
var episode = new PlexEpisode
{
Key = response.Key,
Etag = _plexEtag.ForEpisode(response),
Etag = plexEtag.ForEpisode(response),
EpisodeMetadata = [metadata],
MediaVersions = [version],
TraktListItems = []
@ -1238,7 +1232,7 @@ public class PlexServerApiClient : IPlexServerApiClient @@ -1238,7 +1232,7 @@ public class PlexServerApiClient : IPlexServerApiClient
var otherVideo = new PlexOtherVideo
{
Etag = _plexEtag.ForMovie(response),
Etag = plexEtag.ForMovie(response),
Key = response.Key,
OtherVideoMetadata = [metadata],
MediaVersions = [version],
@ -1431,7 +1425,7 @@ public class PlexServerApiClient : IPlexServerApiClient @@ -1431,7 +1425,7 @@ public class PlexServerApiClient : IPlexServerApiClient
}
else
{
_logger.LogWarning("Unsupported guid format from Plex; ignoring: {Guid}", guid);
logger.LogWarning("Unsupported guid format from Plex; ignoring: {Guid}", guid);
}
return None;

Loading…
Cancel
Save