This commit is contained in:
Malik 2026-05-13 07:35:25 +10:00 committed by GitHub
commit 2db156c986
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 131 additions and 3 deletions

View file

@ -677,6 +677,8 @@ namespace Emby.Server.Implementations
_pluginManager.CreatePlugins();
Resolve<ILibraryManager>().AddScanners(GetExports<IScanner>());
Resolve<ILibraryManager>().AddParts(
GetExports<IResolverIgnoreRule>(),
GetExports<IItemResolver>(),

View file

@ -251,6 +251,8 @@ namespace Emby.Server.Implementations.Library
private IMultiItemResolver[] MultiItemResolvers { get; set; } = [];
private IScanner[] Scanners { get; set; } = Array.Empty<IScanner>();
/// <summary>
/// Gets or sets the comparers.
/// </summary>
@ -282,6 +284,16 @@ namespace Emby.Server.Implementations.Library
PostScanTasks = postScanTasks.ToArray();
}
public void AddScanners(IEnumerable<IScanner> scanners)
{
Scanners = scanners.ToArray();
}
public bool SupportsScanner(IScanner scanner)
{
return Scanners.Select(s => s.Enabled && s == scanner).FirstOrDefault(e => false);
}
/// <summary>
/// Records the configuration values.
/// </summary>

View file

@ -825,6 +825,15 @@ public class LibraryController : BaseJellyfinApiController
.OrderBy(i => typesList.IndexOf(i.ItemType))
.ToList();
result.MetadataResolvers = plugins
.SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.MetadataResolver))
.Select(i => new LibraryOptionInfoDto
{
Name = i.Name
})
.DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
.ToArray();
result.MetadataSavers = plugins
.SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.MetadataSaver))
.Select(i => new LibraryOptionInfoDto
@ -884,6 +893,16 @@ public class LibraryController : BaseJellyfinApiController
typeOptions.Add(new LibraryTypeOptionsDto
{
Type = type,
MetadataResolvers = plugins
.Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))
.SelectMany(i => i.Plugins.Where(p => p.Type == MetadataPluginType.MetadataResolver))
.Select(i => new LibraryOptionInfoDto
{
Name = i.Name,
DefaultEnabled = false // TODO(Malik): implement IsDefault check
})
.DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
.ToArray(),
MetadataFetchers = plugins
.Where(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase))

View file

@ -8,6 +8,11 @@ namespace Jellyfin.Api.Models.LibraryDtos;
/// </summary>
public class LibraryOptionsResultDto
{
/// <summary>
/// Gets or sets the metadata readers.
/// </summary>
public IReadOnlyList<LibraryOptionInfoDto> MetadataResolvers { get; set; } = Array.Empty<LibraryOptionInfoDto>();
/// <summary>
/// Gets or sets the metadata savers.
/// </summary>

View file

@ -15,6 +15,11 @@ public class LibraryTypeOptionsDto
/// </summary>
public string? Type { get; set; }
/// <summary>
/// Gets or sets the metadata fetchers.
/// </summary>
public IReadOnlyList<LibraryOptionInfoDto> MetadataResolvers { get; set; } = Array.Empty<LibraryOptionInfoDto>();
/// <summary>
/// Gets or sets the metadata fetchers.
/// </summary>

View file

@ -239,6 +239,8 @@ namespace MediaBrowser.Controller.Library
/// <returns>IEnumerable{System.String}.</returns>
Task<IEnumerable<Video>> GetIntros(BaseItem item, User user);
public bool SupportsScanner(IScanner scanner);
/// <summary>
/// Gets the IDs of local alternate versions for a video.
/// Local alternate versions are alternate quality versions at different file paths.
@ -278,6 +280,8 @@ namespace MediaBrowser.Controller.Library
IEnumerable<IBaseItemComparer> itemComparers,
IEnumerable<ILibraryPostScanTask> postScanTasks);
void AddScanners(IEnumerable<IScanner> scanners);
/// <summary>
/// Sorts the specified items.
/// </summary>

View file

@ -0,0 +1,22 @@
#pragma warning disable CS1591
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Controller.Resolvers
{
public interface IScanner
{
bool Enabled { get; set; }
bool Default { get; set; }
public ICollection<BaseItem> ApplyMetadata(ICollection<BaseItem> ts);
}
}

View file

@ -0,0 +1,38 @@
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.IO;
namespace MediaBrowser.Controller.Resolvers
{
public abstract class Scanner : IScanner
{
public bool Enabled { get; set; } = false;
public bool Default { get; set; } = false;
public ResolverPriority Priority => ResolverPriority.Plugin;
protected BaseItem ApplyMetadata(BaseItem t)
{
protected abstract BaseItem ApplyMetadata(BaseItem t);
}
public ICollection<BaseItem> ApplyMetadata(ICollection<BaseItem> ts)
{
foreach (var t in ts)
{
ApplyMetadata(t);
}
return ts;
}
}
}

View file

@ -18,6 +18,8 @@ namespace MediaBrowser.Model.Configuration
MetadataFetcherOrder = Array.Empty<string>();
DisabledImageFetchers = Array.Empty<string>();
ImageFetcherOrder = Array.Empty<string>();
MetadataResolvers = Array.Empty<string>();
DisabledMetadataResolvers = Array.Empty<string>();
}
public string ItemType { get; set; }
@ -33,5 +35,9 @@ namespace MediaBrowser.Model.Configuration
public string[] DisabledImageFetchers { get; set; }
public string[] ImageFetcherOrder { get; set; }
public string[] MetadataResolvers { get; set; }
public string[] DisabledMetadataResolvers { get; set; }
}
}

View file

@ -15,6 +15,7 @@ namespace MediaBrowser.Model.Configuration
MetadataSaver,
SubtitleFetcher,
LyricFetcher,
MediaSegmentProvider
MediaSegmentProvider,
MetadataResolver
}
}

View file

@ -309,6 +309,8 @@ namespace MediaBrowser.Model.Configuration
ImageFetchers = Array.Empty<string>();
ImageFetcherOrder = Array.Empty<string>();
ImageOptions = Array.Empty<ImageOption>();
MetadataResolvers = Array.Empty<string>();
MetadataResolverOrder = Array.Empty<string>();
}
public string Type { get; set; }
@ -321,6 +323,10 @@ namespace MediaBrowser.Model.Configuration
public string[] ImageFetcherOrder { get; set; }
public string[] MetadataResolvers { get; set; }
public string[] MetadataResolverOrder { get; set; }
public ImageOption[] ImageOptions { get; set; }
public ImageOption GetImageOptions(ImageType type)

View file

@ -687,6 +687,14 @@ namespace MediaBrowser.Providers.Manager
Type = MetadataPluginType.MediaSegmentProvider
}));
// Filesystem to metadata resolvers
var metadataResolverProviders = summary.Plugins.Select(p => p.Type == MetadataPluginType.MetadataResolver && p.Name != null ? p : null);
pluginList.AddRange(metadataResolverProviders.Select(i => new MetadataPlugin
{
Name = i?.Name,
Type = MetadataPluginType.MetadataResolver
}));
summary.Plugins = pluginList.ToArray();
var supportedImageTypes = imageProviders.OfType<IRemoteImageProvider>()
@ -708,10 +716,10 @@ namespace MediaBrowser.Providers.Manager
var providers = GetMetadataProvidersInternal<T>(item, libraryOptions, options, true, true, libraryPath).ToList();
// Locals
list.AddRange(providers.Where(i => i is ILocalMetadataProvider).Select(i => new MetadataPlugin
list.AddRange(providers.Where(i => i is IMetadataProvider && i is not IRemoteMetadataProvider && i is not ILocalMetadataProvider && i is not ICustomMetadataProvider).Select(i => new MetadataPlugin
{
Name = i.Name,
Type = MetadataPluginType.LocalMetadataProvider
Type = MetadataPluginType.MetadataResolver
}));
// Fetchers