mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-02 13:58:29 +01:00
sync fixes
This commit is contained in:
@@ -68,6 +68,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
/// </summary>
|
||||
/// <value>The entity resolvers enumerable.</value>
|
||||
private IItemResolver[] EntityResolvers { get; set; }
|
||||
private IMultiItemResolver[] MultiItemResolvers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the comparers.
|
||||
@@ -196,9 +197,10 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
EntityResolutionIgnoreRules = rules.ToArray();
|
||||
PluginFolderCreators = pluginFolders.ToArray();
|
||||
EntityResolvers = resolvers.OrderBy(i => i.Priority).ToArray();
|
||||
MultiItemResolvers = EntityResolvers.OfType<IMultiItemResolver>().ToArray();
|
||||
IntroProviders = introProviders.ToArray();
|
||||
Comparers = itemComparers.ToArray();
|
||||
|
||||
|
||||
PostscanTasks = postscanTasks.OrderBy(i =>
|
||||
{
|
||||
var hasOrder = i as IHasOrder;
|
||||
@@ -344,7 +346,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
|
||||
try
|
||||
{
|
||||
await UpdateItem(season, ItemUpdateType.MetadataDownload, cancellationToken).ConfigureAwait(false);
|
||||
await UpdateItem(season, ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -658,9 +660,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
|
||||
if (parent != null)
|
||||
{
|
||||
var multiItemResolvers = EntityResolvers.OfType<IMultiItemResolver>();
|
||||
|
||||
foreach (var resolver in multiItemResolvers)
|
||||
foreach (var resolver in MultiItemResolvers)
|
||||
{
|
||||
var result = resolver.ResolveMultiple(parent, fileList, collectionType, directoryService);
|
||||
|
||||
|
||||
@@ -121,14 +121,28 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
|
||||
ILibraryManager libraryManager)
|
||||
{
|
||||
var discSubfolderCount = 0;
|
||||
var notMultiDisc = false;
|
||||
|
||||
foreach (var fileSystemInfo in list)
|
||||
{
|
||||
if ((fileSystemInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
|
||||
{
|
||||
if (allowSubfolders && IsAlbumSubfolder(fileSystemInfo, directoryService, logger, fileSystem, libraryManager))
|
||||
if (allowSubfolders)
|
||||
{
|
||||
discSubfolderCount++;
|
||||
var path = fileSystemInfo.FullName;
|
||||
var isMultiDisc = IsMultiDiscFolder(path);
|
||||
var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager);
|
||||
|
||||
if (isMultiDisc && hasMusic)
|
||||
{
|
||||
logger.Debug("Found multi-disc folder: " + path);
|
||||
discSubfolderCount++;
|
||||
}
|
||||
else if (hasMusic)
|
||||
{
|
||||
// If there are folders underneath with music that are not multidisc, then this can't be a multi-disc album
|
||||
notMultiDisc = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,34 +154,15 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
|
||||
}
|
||||
}
|
||||
|
||||
return discSubfolderCount > 0;
|
||||
}
|
||||
|
||||
private static bool IsAlbumSubfolder(FileSystemInfo directory, IDirectoryService directoryService, ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager)
|
||||
{
|
||||
var path = directory.FullName;
|
||||
|
||||
if (IsMultiDiscFolder(path))
|
||||
if (notMultiDisc)
|
||||
{
|
||||
logger.Debug("Found multi-disc folder: " + path);
|
||||
|
||||
return ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return discSubfolderCount > 0 && discSubfolderCount > 10;
|
||||
}
|
||||
|
||||
public static bool IsMultiDiscFolder(string path)
|
||||
{
|
||||
return IsMultiDiscAlbumFolder(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is multi disc album folder] [the specified path].
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns><c>true</c> if [is multi disc album folder] [the specified path]; otherwise, <c>false</c>.</returns>
|
||||
private static bool IsMultiDiscAlbumFolder(string path)
|
||||
private static bool IsMultiDiscFolder(string path)
|
||||
{
|
||||
var parser = new AlbumParser(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
|
||||
var result = parser.ParseMultiPart(path);
|
||||
|
||||
@@ -4,6 +4,7 @@ using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||
{
|
||||
@@ -24,6 +25,11 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||
// Contains [boxset] in the path
|
||||
if (args.IsDirectory)
|
||||
{
|
||||
if (IsInvalid(args.GetCollectionType()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var filename = Path.GetFileName(args.Path);
|
||||
|
||||
if (string.IsNullOrEmpty(filename))
|
||||
@@ -45,6 +51,17 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||
return null;
|
||||
}
|
||||
|
||||
private bool IsInvalid(string collectionType)
|
||||
{
|
||||
var validCollectionTypes = new[]
|
||||
{
|
||||
CollectionType.Movies,
|
||||
CollectionType.BoxSets
|
||||
};
|
||||
|
||||
return !validCollectionTypes.Contains(collectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the initial item values.
|
||||
/// </summary>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Controller.Resolvers;
|
||||
@@ -183,7 +182,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||
return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
||||
}
|
||||
|
||||
return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
||||
return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
|
||||
}
|
||||
|
||||
if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
|
||||
@@ -346,6 +345,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||
{
|
||||
var movie = (T)result.Items[0];
|
||||
movie.IsInMixedFolder = false;
|
||||
movie.Name = Path.GetFileName(movie.ContainingFolderPath);
|
||||
return movie;
|
||||
}
|
||||
|
||||
@@ -446,21 +446,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||
}
|
||||
}
|
||||
|
||||
// Don't do any resolving within a series structure
|
||||
if (string.IsNullOrEmpty(collectionType))
|
||||
{
|
||||
if (HasParent<Series>(parent) || HasParent<Season>(parent))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Since the looping is expensive, this is an optimization to help us avoid it
|
||||
if (files.Select(i => i.Name).Contains("series.xml", StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var validCollectionTypes = new[]
|
||||
{
|
||||
string.Empty,
|
||||
@@ -472,25 +457,5 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
|
||||
|
||||
return !validCollectionTypes.Contains(collectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private bool HasParent<T>(Folder parent)
|
||||
where T : Folder
|
||||
{
|
||||
if (parent != null)
|
||||
{
|
||||
var item = parent as T;
|
||||
|
||||
// Just in case the user decided to nest episodes.
|
||||
// Not officially supported but in some cases we can handle it.
|
||||
if (item == null)
|
||||
{
|
||||
item = parent.Parents.OfType<T>().FirstOrDefault();
|
||||
}
|
||||
|
||||
return item != null;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
|
||||
protected override Photo Resolve(ItemResolveArgs args)
|
||||
{
|
||||
// Must be an image file within a photo collection
|
||||
if (!args.IsDirectory &&
|
||||
string.Equals(args.GetCollectionType(), CollectionType.Photos, StringComparison.OrdinalIgnoreCase) &&
|
||||
if (string.Equals(args.GetCollectionType(), CollectionType.Photos, StringComparison.OrdinalIgnoreCase) &&
|
||||
!args.IsDirectory &&
|
||||
IsImageFile(args.Path))
|
||||
{
|
||||
return new Photo
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Controller.Resolvers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using MediaBrowser.Naming.Common;
|
||||
using MediaBrowser.Naming.TV;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
|
||||
@@ -18,17 +12,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
|
||||
/// </summary>
|
||||
public class SeriesResolver : FolderResolver<Series>
|
||||
{
|
||||
private readonly IFileSystem _fileSystem;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public SeriesResolver(IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager)
|
||||
{
|
||||
_fileSystem = fileSystem;
|
||||
_logger = logger;
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the priority.
|
||||
/// </summary>
|
||||
@@ -50,27 +33,16 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
|
||||
{
|
||||
if (args.IsDirectory)
|
||||
{
|
||||
// Avoid expensive tests against VF's and all their children by not allowing this
|
||||
if (args.Parent.IsRoot)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var collectionType = args.GetCollectionType();
|
||||
|
||||
// If there's a collection type and it's not tv, it can't be a series
|
||||
if (!string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (args.HasParent<Series>() || args.HasParent<Season>())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager))
|
||||
if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (args.HasParent<Series>())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Series
|
||||
{
|
||||
Path = args.Path,
|
||||
@@ -82,88 +54,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is series folder] [the specified path].
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <param name="fileSystemChildren">The file system children.</param>
|
||||
/// <param name="directoryService">The directory service.</param>
|
||||
/// <param name="fileSystem">The file system.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="libraryManager">The library manager.</param>
|
||||
/// <returns><c>true</c> if [is series folder] [the specified path]; otherwise, <c>false</c>.</returns>
|
||||
public static bool IsSeriesFolder(string path, IEnumerable<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService, IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager)
|
||||
{
|
||||
foreach (var child in fileSystemChildren)
|
||||
{
|
||||
var attributes = child.Attributes;
|
||||
|
||||
if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
|
||||
{
|
||||
//logger.Debug("Igoring series file or folder marked hidden: {0}", child.FullName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Can't enforce this because files saved by Bitcasa are always marked System
|
||||
//if ((attributes & FileAttributes.System) == FileAttributes.System)
|
||||
//{
|
||||
// logger.Debug("Igoring series subfolder marked system: {0}", child.FullName);
|
||||
// continue;
|
||||
//}
|
||||
|
||||
if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
|
||||
{
|
||||
if (IsSeasonFolder(child.FullName))
|
||||
{
|
||||
//logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var fullName = child.FullName;
|
||||
|
||||
if (libraryManager.IsVideoFile(fullName) || IsVideoPlaceHolder(fullName))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.Debug("{0} is not a series folder.", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is place holder] [the specified path].
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns><c>true</c> if [is place holder] [the specified path]; otherwise, <c>false</c>.</returns>
|
||||
/// <exception cref="System.ArgumentNullException">path</exception>
|
||||
private static bool IsVideoPlaceHolder(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
throw new ArgumentNullException("path");
|
||||
}
|
||||
|
||||
var extension = Path.GetExtension(path);
|
||||
|
||||
return string.Equals(extension, ".disc", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether [is season folder] [the specified path].
|
||||
/// </summary>
|
||||
/// <param name="path">The path.</param>
|
||||
/// <returns><c>true</c> if [is season folder] [the specified path]; otherwise, <c>false</c>.</returns>
|
||||
private static bool IsSeasonFolder(string path)
|
||||
{
|
||||
var seasonNumber = new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(path, true).SeasonNumber;
|
||||
|
||||
return seasonNumber.HasValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the initial item values.
|
||||
/// </summary>
|
||||
|
||||
@@ -860,6 +860,13 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
|
||||
private async Task UpdateUserPolicy(User user, UserPolicy userPolicy, bool fireEvent)
|
||||
{
|
||||
// The xml serializer will output differently if the type is not exact
|
||||
if (userPolicy.GetType() != typeof(UserPolicy))
|
||||
{
|
||||
var json = _jsonSerializer.SerializeToString(userPolicy);
|
||||
userPolicy = _jsonSerializer.DeserializeFromString<UserPolicy>(json);
|
||||
}
|
||||
|
||||
var updateConfig = user.Policy.IsAdministrator != userPolicy.IsAdministrator ||
|
||||
user.Policy.EnableLiveTvManagement != userPolicy.EnableLiveTvManagement ||
|
||||
user.Policy.EnableLiveTvAccess != userPolicy.EnableLiveTvAccess ||
|
||||
|
||||
Reference in New Issue
Block a user