feat: skip trailers/pre-rolls inaccessible to the current user (v1.0.0.9)
All checks were successful
Publish Release / release (push) Successful in 12s

Filters trailer pool items and pre-roll/feature pre-roll bumpers using
BaseItem.IsVisibleStandalone(user), so users without access to the
relevant library are never handed an item they can't actually play —
some Cinema Mode clients hang indefinitely in that case.
This commit is contained in:
Martin
2026-06-10 13:07:11 -04:00
parent 5f7a76feb5
commit 6bb23dc9c4
3 changed files with 16 additions and 13 deletions

View File

@@ -3,8 +3,8 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<RootNamespace>Jellyfin.Plugin.CinemaTrailers4Jellyfins</RootNamespace> <RootNamespace>Jellyfin.Plugin.CinemaTrailers4Jellyfins</RootNamespace>
<AssemblyVersion>1.0.0.8</AssemblyVersion> <AssemblyVersion>1.0.0.9</AssemblyVersion>
<FileVersion>1.0.0.8</FileVersion> <FileVersion>1.0.0.9</FileVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<GenerateDocumentationFile>false</GenerateDocumentationFile> <GenerateDocumentationFile>false</GenerateDocumentationFile>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> <TreatWarningsAsErrors>false</TreatWarningsAsErrors>

View File

@@ -111,7 +111,7 @@ namespace Jellyfin.Plugin.CinemaTrailers4Jellyfins.Services
if (preRollEnabled) if (preRollEnabled)
{ {
var preRoll = GetRandomLibraryMovieIntro("Trailer Pre-Roll", config.TrailerPreRollLibraryId, item.Id); var preRoll = GetRandomLibraryMovieIntro("Trailer Pre-Roll", config.TrailerPreRollLibraryId, item.Id, user);
if (preRoll != null) if (preRoll != null)
intros.Add(preRoll); intros.Add(preRoll);
} }
@@ -129,6 +129,9 @@ namespace Jellyfin.Plugin.CinemaTrailers4Jellyfins.Services
.Where(m => .Where(m =>
m.Path?.StartsWith(outputFolder, StringComparison.OrdinalIgnoreCase) == true m.Path?.StartsWith(outputFolder, StringComparison.OrdinalIgnoreCase) == true
&& m.LocalTrailers.Count > 0 && m.LocalTrailers.Count > 0
// Skip items the user can't actually play (e.g. library not in their access list) —
// some clients hang indefinitely trying to play an inaccessible item.
&& m.IsVisibleStandalone(user)
// Keep TV show trailers for episodes and movie trailers for movies separate. // Keep TV show trailers for episodes and movie trailers for movies separate.
&& m.Tags.Contains(TrailerTags.TvShow, StringComparer.OrdinalIgnoreCase) == isEpisode) && m.Tags.Contains(TrailerTags.TvShow, StringComparer.OrdinalIgnoreCase) == isEpisode)
.SelectMany(m => m.LocalTrailers.Select(t => (Movie: m, Trailer: t))) .SelectMany(m => m.LocalTrailers.Select(t => (Movie: m, Trailer: t)))
@@ -165,7 +168,7 @@ namespace Jellyfin.Plugin.CinemaTrailers4Jellyfins.Services
if (featurePreRollEnabled) if (featurePreRollEnabled)
{ {
var featureRoll = GetRandomLibraryMovieIntro("Feature Pre-Roll", config.FeaturePreRollLibraryId, item.Id); var featureRoll = GetRandomLibraryMovieIntro("Feature Pre-Roll", config.FeaturePreRollLibraryId, item.Id, user);
if (featureRoll != null) if (featureRoll != null)
intros.Add(featureRoll); intros.Add(featureRoll);
} }
@@ -182,7 +185,7 @@ namespace Jellyfin.Plugin.CinemaTrailers4Jellyfins.Services
/// Picks a random Movie from the given Jellyfin library (VirtualFolder ItemId) to use as a /// Picks a random Movie from the given Jellyfin library (VirtualFolder ItemId) to use as a
/// pre-roll/post-roll bumper, excluding the item currently being played. /// pre-roll/post-roll bumper, excluding the item currently being played.
/// </summary> /// </summary>
private IntroInfo? GetRandomLibraryMovieIntro(string label, string libraryId, Guid excludeId) private IntroInfo? GetRandomLibraryMovieIntro(string label, string libraryId, Guid excludeId, User user)
{ {
if (!Guid.TryParse(libraryId, out var parsedId)) if (!Guid.TryParse(libraryId, out var parsedId))
{ {
@@ -204,14 +207,14 @@ namespace Jellyfin.Plugin.CinemaTrailers4Jellyfins.Services
var movies = folder.GetRecursiveChildren() var movies = folder.GetRecursiveChildren()
.OfType<Movie>() .OfType<Movie>()
.Where(m => m.Id != excludeId) .Where(m => m.Id != excludeId && m.IsVisibleStandalone(user))
.ToList(); .ToList();
if (movies.Count == 0) if (movies.Count == 0)
{ {
_logger.LogInformation( _logger.LogInformation(
"|CinemaTrailers4Jellyfins| {Label} library {LibraryId} has no eligible Movie items. " "|CinemaTrailers4Jellyfins| {Label} library {LibraryId} has no eligible Movie items visible to this user. "
+ "Ensure the library has been scanned and contains at least one other Movie.", + "Ensure the library has been scanned, contains at least one other Movie, and is in this user's library access list.",
label, label,
parsedId); parsedId);
return null; return null;

View File

@@ -1,5 +1,5 @@
--- ---
version: 1.0.0.8 version: 1.0.0.9
name: CinemaTrailers4Jellyfins name: CinemaTrailers4Jellyfins
guid: b581493e-1046-40ed-b6dc-cb8027624984 guid: b581493e-1046-40ed-b6dc-cb8027624984
description: > description: >
@@ -12,10 +12,10 @@ category: General
owner: 514mart owner: 514mart
targetAbi: 10.11.0.0 targetAbi: 10.11.0.0
changelog: changelog:
- Fix Trailer Pre-Roll / Feature Pre-Roll bumpers not being found — the - Skip trailers and pre-roll/feature pre-roll bumpers the current user
library lookup now walks the configured library folder's children can't actually access (e.g. a library not in their library access list)
directly instead of relying on TopParentIds matching, which could fail — some Cinema Mode clients hang indefinitely trying to play an
to match movies even when they appear correctly in the library inaccessible item, so these are now filtered out per-user instead
dotnetProjects: dotnetProjects:
- name: Jellyfin.Plugin.CinemaTrailers4Jellyfins - name: Jellyfin.Plugin.CinemaTrailers4Jellyfins