af1152b001
Refactored all C# test files to use explicit namespace declarations and moved all using directives inside the namespace block for consistency. Updated assembly info and cache files to reflect the new build. Adjusted MvcTestingAppManifest.json to use fully qualified assembly names. No functional changes; all updates are related to code style, organization, and project metadata.
109 lines
4.9 KiB
C#
109 lines
4.9 KiB
C#
// <copyright file="ExtraResolver.cs" company="PlaceholderCompany">
|
|
// Copyright (c) PlaceholderCompany. All rights reserved.
|
|
// </copyright>
|
|
|
|
namespace Emby.Server.Implementations.Library.Resolvers
|
|
{
|
|
using System;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.IO;
|
|
using Emby.Naming.Common;
|
|
using Emby.Naming.Video;
|
|
using MediaBrowser.Controller.Entities;
|
|
using MediaBrowser.Controller.Library;
|
|
using MediaBrowser.Controller.Providers;
|
|
using MediaBrowser.Controller.Resolvers;
|
|
using MediaBrowser.Model.Entities;
|
|
using Microsoft.Extensions.Logging;
|
|
using static Emby.Naming.Video.ExtraRuleResolver;
|
|
|
|
/// <summary>
|
|
/// Resolves a Path into a Video or Video subclass.
|
|
/// </summary>
|
|
internal class ExtraResolver : BaseVideoResolver<Video>
|
|
{
|
|
private readonly NamingOptions _namingOptions;
|
|
private readonly IItemResolver[] _trailerResolvers;
|
|
private readonly IItemResolver[] _videoResolvers;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="ExtraResolver"/> class.
|
|
/// </summary>
|
|
/// <param name="logger">The logger.</param>
|
|
/// <param name="namingOptions">An instance of <see cref="NamingOptions"/>.</param>
|
|
/// <param name="directoryService">The directory service.</param>
|
|
public ExtraResolver(ILogger<ExtraResolver> logger, NamingOptions namingOptions, IDirectoryService directoryService)
|
|
: base(logger, namingOptions, directoryService)
|
|
{
|
|
_namingOptions = namingOptions;
|
|
_trailerResolvers = new IItemResolver[] { new GenericVideoResolver<Trailer>(logger, namingOptions, directoryService) };
|
|
_videoResolvers = new IItemResolver[] { this };
|
|
}
|
|
|
|
protected override Video Resolve(ItemResolveArgs args)
|
|
{
|
|
return ResolveVideo<Video>(args, true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the resolvers for the extra type.
|
|
/// </summary>
|
|
/// <param name="extraType">The extra type.</param>
|
|
/// <returns>The resolvers for the extra type.</returns>
|
|
public IItemResolver[]? GetResolversForExtraType(ExtraType extraType) => extraType switch
|
|
{
|
|
ExtraType.Trailer => _trailerResolvers,
|
|
// For audio we'll have to rely on the AudioResolver, which is a "built-in"
|
|
ExtraType.ThemeSong => null,
|
|
_ => _videoResolvers
|
|
};
|
|
|
|
public bool TryGetExtraTypeForOwner(string path, VideoFileInfo ownerVideoFileInfo, [NotNullWhen(true)] out ExtraType? extraType, string? libraryRoot = "")
|
|
{
|
|
var extraResult = GetExtraInfo(path, _namingOptions, libraryRoot);
|
|
if (extraResult.ExtraType is null)
|
|
{
|
|
extraType = null;
|
|
return false;
|
|
}
|
|
|
|
var cleanDateTimeResult = CleanDateTimeParser.Clean(Path.GetFileNameWithoutExtension(path), _namingOptions.CleanDateTimeRegexes);
|
|
var name = cleanDateTimeResult.Name;
|
|
var year = cleanDateTimeResult.Year;
|
|
|
|
var parentDir = ownerVideoFileInfo.IsDirectory ? ownerVideoFileInfo.Path : Path.GetDirectoryName(ownerVideoFileInfo.Path.AsSpan());
|
|
|
|
var trimmedFileNameWithoutExtension = TrimFilenameDelimiters(ownerVideoFileInfo.FileNameWithoutExtension, _namingOptions.VideoFlagDelimiters);
|
|
var trimmedVideoInfoName = TrimFilenameDelimiters(ownerVideoFileInfo.Name, _namingOptions.VideoFlagDelimiters);
|
|
var trimmedExtraFileName = TrimFilenameDelimiters(name, _namingOptions.VideoFlagDelimiters);
|
|
|
|
// first check filenames
|
|
bool isValid = StartsWith(trimmedExtraFileName, trimmedFileNameWithoutExtension)
|
|
|| (StartsWith(trimmedExtraFileName, trimmedVideoInfoName) && year == ownerVideoFileInfo.Year);
|
|
|
|
if (!isValid)
|
|
{
|
|
// When the extra rule type is DirectoryName we must go one level higher to get the "real" dir name
|
|
var currentParentDir = extraResult.Rule?.RuleType == ExtraRuleType.DirectoryName
|
|
? Path.GetDirectoryName(Path.GetDirectoryName(path.AsSpan()))
|
|
: Path.GetDirectoryName(path.AsSpan());
|
|
|
|
isValid = !currentParentDir.IsEmpty && !parentDir.IsEmpty && currentParentDir.Equals(parentDir, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
extraType = extraResult.ExtraType;
|
|
return isValid;
|
|
}
|
|
|
|
private static ReadOnlySpan<char> TrimFilenameDelimiters(ReadOnlySpan<char> name, ReadOnlySpan<char> videoFlagDelimiters)
|
|
{
|
|
return name.IsEmpty ? name : name.TrimEnd().TrimEnd(videoFlagDelimiters).TrimEnd();
|
|
}
|
|
|
|
private static bool StartsWith(ReadOnlySpan<char> fileName, ReadOnlySpan<char> baseName)
|
|
{
|
|
return !baseName.IsEmpty && fileName.StartsWith(baseName, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
}
|
|
}
|