Merge pull request #3334 from crobibero/warning-local-metadata
Remove warnings from MediaBrowser.LocalMetadata
This commit is contained in:
commit
fbefddbb81
|
@ -7,12 +7,43 @@ using MediaBrowser.Model.IO;
|
||||||
|
|
||||||
namespace MediaBrowser.LocalMetadata
|
namespace MediaBrowser.LocalMetadata
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The BaseXmlProvider.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of provider.</typeparam>
|
||||||
public abstract class BaseXmlProvider<T> : ILocalMetadataProvider<T>, IHasItemChangeMonitor, IHasOrder
|
public abstract class BaseXmlProvider<T> : ILocalMetadataProvider<T>, IHasItemChangeMonitor, IHasOrder
|
||||||
where T : BaseItem, new()
|
where T : BaseItem, new()
|
||||||
{
|
{
|
||||||
protected IFileSystem FileSystem;
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="BaseXmlProvider{T}"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
|
||||||
|
protected BaseXmlProvider(IFileSystem fileSystem)
|
||||||
|
{
|
||||||
|
this.FileSystem = fileSystem;
|
||||||
|
}
|
||||||
|
|
||||||
public Task<MetadataResult<T>> GetMetadata(ItemInfo info,
|
/// <inheritdoc />
|
||||||
|
public string Name => XmlProviderUtils.Name;
|
||||||
|
|
||||||
|
/// After Nfo
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual int Order => 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the IFileSystem.
|
||||||
|
/// </summary>
|
||||||
|
protected IFileSystem FileSystem { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets metadata for item.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="info">The item info.</param>
|
||||||
|
/// <param name="directoryService">Instance of the <see cref="IDirectoryService"/> interface.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
|
/// <returns>The metadata for item.</returns>
|
||||||
|
public Task<MetadataResult<T>> GetMetadata(
|
||||||
|
ItemInfo info,
|
||||||
IDirectoryService directoryService,
|
IDirectoryService directoryService,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
@ -46,15 +77,23 @@ namespace MediaBrowser.LocalMetadata
|
||||||
return Task.FromResult(result);
|
return Task.FromResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get metadata from path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="result">Resulting metadata.</param>
|
||||||
|
/// <param name="path">The path.</param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
protected abstract void Fetch(MetadataResult<T> result, string path, CancellationToken cancellationToken);
|
protected abstract void Fetch(MetadataResult<T> result, string path, CancellationToken cancellationToken);
|
||||||
|
|
||||||
protected BaseXmlProvider(IFileSystem fileSystem)
|
/// <summary>
|
||||||
{
|
/// Get metadata from xml file.
|
||||||
FileSystem = fileSystem;
|
/// </summary>
|
||||||
}
|
/// <param name="info">Item inf.</param>
|
||||||
|
/// <param name="directoryService">Instance of the <see cref="IDirectoryService"/> interface.</param>
|
||||||
|
/// <returns>The file system metadata.</returns>
|
||||||
protected abstract FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService);
|
protected abstract FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool HasChanged(BaseItem item, IDirectoryService directoryService)
|
public bool HasChanged(BaseItem item, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
var file = GetXmlFile(new ItemInfo(item), directoryService);
|
var file = GetXmlFile(new ItemInfo(item), directoryService);
|
||||||
|
@ -66,15 +105,5 @@ namespace MediaBrowser.LocalMetadata
|
||||||
|
|
||||||
return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > item.DateLastSaved;
|
return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > item.DateLastSaved;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name => XmlProviderUtils.Name;
|
|
||||||
|
|
||||||
// After Nfo
|
|
||||||
public virtual int Order => 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class XmlProviderUtils
|
|
||||||
{
|
|
||||||
public static string Name => "Emby Xml";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,30 +5,41 @@ using MediaBrowser.Model.IO;
|
||||||
|
|
||||||
namespace MediaBrowser.LocalMetadata.Images
|
namespace MediaBrowser.LocalMetadata.Images
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Collection folder local image provider.
|
||||||
|
/// </summary>
|
||||||
public class CollectionFolderLocalImageProvider : ILocalImageProvider, IHasOrder
|
public class CollectionFolderLocalImageProvider : ILocalImageProvider, IHasOrder
|
||||||
{
|
{
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CollectionFolderLocalImageProvider"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
|
||||||
public CollectionFolderLocalImageProvider(IFileSystem fileSystem)
|
public CollectionFolderLocalImageProvider(IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Name => "Collection Folder Images";
|
public string Name => "Collection Folder Images";
|
||||||
|
|
||||||
|
/// Run after LocalImageProvider
|
||||||
|
/// <inheritdoc />
|
||||||
|
public int Order => 1;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool Supports(BaseItem item)
|
public bool Supports(BaseItem item)
|
||||||
{
|
{
|
||||||
return item is CollectionFolder && item.SupportsLocalMetadata;
|
return item is CollectionFolder && item.SupportsLocalMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run after LocalImageProvider
|
/// <inheritdoc />
|
||||||
public int Order => 1;
|
|
||||||
|
|
||||||
public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService)
|
public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
var collectionFolder = (CollectionFolder)item;
|
var collectionFolder = (CollectionFolder)item;
|
||||||
|
|
||||||
return new LocalImageProvider(_fileSystem).GetImages(item, collectionFolder.PhysicalLocations, true, directoryService);
|
return new LocalImageProvider(_fileSystem).GetImages(item, collectionFolder.PhysicalLocations, directoryService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,24 +10,35 @@ using MediaBrowser.Model.IO;
|
||||||
|
|
||||||
namespace MediaBrowser.LocalMetadata.Images
|
namespace MediaBrowser.LocalMetadata.Images
|
||||||
{
|
{
|
||||||
public class EpisodeLocalLocalImageProvider : ILocalImageProvider, IHasOrder
|
/// <summary>
|
||||||
|
/// Episode local image provider.
|
||||||
|
/// </summary>
|
||||||
|
public class EpisodeLocalImageProvider : ILocalImageProvider, IHasOrder
|
||||||
{
|
{
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
public EpisodeLocalLocalImageProvider(IFileSystem fileSystem)
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="EpisodeLocalImageProvider"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
|
||||||
|
public EpisodeLocalImageProvider(IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Name => "Local Images";
|
public string Name => "Local Images";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public int Order => 0;
|
public int Order => 0;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool Supports(BaseItem item)
|
public bool Supports(BaseItem item)
|
||||||
{
|
{
|
||||||
return item is Episode && item.SupportsLocalMetadata;
|
return item is Episode && item.SupportsLocalMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService)
|
public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
var parentPath = Path.GetDirectoryName(item.Path);
|
var parentPath = Path.GetDirectoryName(item.Path);
|
||||||
|
@ -58,20 +69,11 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
|
|
||||||
if (string.Equals(filenameWithoutExtension, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(filenameWithoutExtension, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
list.Add(new LocalImageInfo
|
list.Add(new LocalImageInfo { FileInfo = i, Type = ImageType.Primary });
|
||||||
{
|
|
||||||
FileInfo = i,
|
|
||||||
Type = ImageType.Primary
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (string.Equals(thumbName, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
|
else if (string.Equals(thumbName, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
list.Add(new LocalImageInfo
|
list.Add(new LocalImageInfo { FileInfo = i, Type = ImageType.Primary });
|
||||||
{
|
|
||||||
FileInfo = i,
|
|
||||||
Type = ImageType.Primary
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,21 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.LocalMetadata.Images
|
namespace MediaBrowser.LocalMetadata.Images
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Internal metadata folder image provider.
|
||||||
|
/// </summary>
|
||||||
public class InternalMetadataFolderImageProvider : ILocalImageProvider, IHasOrder
|
public class InternalMetadataFolderImageProvider : ILocalImageProvider, IHasOrder
|
||||||
{
|
{
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
private readonly ILogger<InternalMetadataFolderImageProvider> _logger;
|
private readonly ILogger<InternalMetadataFolderImageProvider> _logger;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="InternalMetadataFolderImageProvider"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="config">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
|
||||||
|
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
|
||||||
|
/// <param name="logger">Instance of the <see cref="ILogger{InternalMetadataFolderImageProvider}"/> interface.</param>
|
||||||
public InternalMetadataFolderImageProvider(
|
public InternalMetadataFolderImageProvider(
|
||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
|
@ -25,8 +34,14 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Make sure this is last so that all other locations are scanned first
|
||||||
|
/// <inheritdoc />
|
||||||
|
public int Order => 1000;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Name => "Internal Images";
|
public string Name => "Internal Images";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool Supports(BaseItem item)
|
public bool Supports(BaseItem item)
|
||||||
{
|
{
|
||||||
if (item is Photo)
|
if (item is Photo)
|
||||||
|
@ -52,9 +67,8 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Make sure this is last so that all other locations are scanned first
|
|
||||||
public int Order => 1000;
|
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService)
|
public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
var path = item.GetInternalMetadataPath();
|
var path = item.GetInternalMetadataPath();
|
||||||
|
@ -66,7 +80,7 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return new LocalImageProvider(_fileSystem).GetImages(item, path, false, directoryService);
|
return new LocalImageProvider(_fileSystem).GetImages(item, path, directoryService);
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,19 +13,71 @@ using MediaBrowser.Model.IO;
|
||||||
|
|
||||||
namespace MediaBrowser.LocalMetadata.Images
|
namespace MediaBrowser.LocalMetadata.Images
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Local image provider.
|
||||||
|
/// </summary>
|
||||||
public class LocalImageProvider : ILocalImageProvider, IHasOrder
|
public class LocalImageProvider : ILocalImageProvider, IHasOrder
|
||||||
{
|
{
|
||||||
|
private static readonly string[] _commonImageFileNames =
|
||||||
|
{
|
||||||
|
"poster",
|
||||||
|
"folder",
|
||||||
|
"cover",
|
||||||
|
"default"
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly string[] _musicImageFileNames =
|
||||||
|
{
|
||||||
|
"folder",
|
||||||
|
"poster",
|
||||||
|
"cover",
|
||||||
|
"default"
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly string[] _personImageFileNames =
|
||||||
|
{
|
||||||
|
"folder",
|
||||||
|
"poster"
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly string[] _seriesImageFileNames =
|
||||||
|
{
|
||||||
|
"poster",
|
||||||
|
"folder",
|
||||||
|
"cover",
|
||||||
|
"default",
|
||||||
|
"show"
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly string[] _videoImageFileNames =
|
||||||
|
{
|
||||||
|
"poster",
|
||||||
|
"folder",
|
||||||
|
"cover",
|
||||||
|
"default",
|
||||||
|
"movie"
|
||||||
|
};
|
||||||
|
|
||||||
private readonly IFileSystem _fileSystem;
|
private readonly IFileSystem _fileSystem;
|
||||||
|
|
||||||
|
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="LocalImageProvider"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
|
||||||
public LocalImageProvider(IFileSystem fileSystem)
|
public LocalImageProvider(IFileSystem fileSystem)
|
||||||
{
|
{
|
||||||
_fileSystem = fileSystem;
|
_fileSystem = fileSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Name => "Local Images";
|
public string Name => "Local Images";
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public int Order => 0;
|
public int Order => 0;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public bool Supports(BaseItem item)
|
public bool Supports(BaseItem item)
|
||||||
{
|
{
|
||||||
if (item.SupportsLocalMetadata)
|
if (item.SupportsLocalMetadata)
|
||||||
|
@ -42,15 +94,10 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
if (item.LocationType == LocationType.Virtual)
|
if (item.LocationType == LocationType.Virtual)
|
||||||
{
|
{
|
||||||
var season = item as Season;
|
var season = item as Season;
|
||||||
|
var series = season?.Series;
|
||||||
if (season != null)
|
if (series != null && series.IsFileProtocol)
|
||||||
{
|
{
|
||||||
var series = season.Series;
|
return true;
|
||||||
|
|
||||||
if (series != null && series.IsFileProtocol)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +132,7 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
.OrderBy(i => Array.IndexOf(BaseItem.SupportedImageExtensions, i.Extension ?? string.Empty));
|
.OrderBy(i => Array.IndexOf(BaseItem.SupportedImageExtensions, i.Extension ?? string.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService)
|
public List<LocalImageInfo> GetImages(BaseItem item, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
var files = GetFiles(item, true, directoryService).ToList();
|
var files = GetFiles(item, true, directoryService).ToList();
|
||||||
|
@ -96,12 +144,26 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LocalImageInfo> GetImages(BaseItem item, string path, bool isPathInMediaFolder, IDirectoryService directoryService)
|
/// <summary>
|
||||||
|
/// Get images for item.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The item.</param>
|
||||||
|
/// <param name="path">The images path.</param>
|
||||||
|
/// <param name="directoryService">Instance of the <see cref="IDirectoryService"/> interface.</param>
|
||||||
|
/// <returns>The local image info.</returns>
|
||||||
|
public List<LocalImageInfo> GetImages(BaseItem item, string path, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
return GetImages(item, new[] { path }, isPathInMediaFolder, directoryService);
|
return GetImages(item, new[] { path }, directoryService);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<LocalImageInfo> GetImages(BaseItem item, IEnumerable<string> paths, bool arePathsInMediaFolders, IDirectoryService directoryService)
|
/// <summary>
|
||||||
|
/// Get images for item from multiple paths.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The item.</param>
|
||||||
|
/// <param name="paths">The image paths.</param>
|
||||||
|
/// <param name="directoryService">Instance of the <see cref="IDirectoryService"/> interface.</param>
|
||||||
|
/// <returns>The local image info.</returns>
|
||||||
|
public List<LocalImageInfo> GetImages(BaseItem item, IEnumerable<string> paths, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
IEnumerable<FileSystemMetadata> files = paths.SelectMany(i => _fileSystem.GetFiles(i, BaseItem.SupportedImageExtensions, true, false));
|
IEnumerable<FileSystemMetadata> files = paths.SelectMany(i => _fileSystem.GetFiles(i, BaseItem.SupportedImageExtensions, true, false));
|
||||||
|
|
||||||
|
@ -196,7 +258,7 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
|
|
||||||
if (!isEpisode && !isSong && !isPerson)
|
if (!isEpisode && !isSong && !isPerson)
|
||||||
{
|
{
|
||||||
PopulateBackdrops(item, images, files, imagePrefix, isInMixedFolder, directoryService);
|
PopulateBackdrops(item, images, files, imagePrefix, isInMixedFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item is IHasScreenshots)
|
if (item is IHasScreenshots)
|
||||||
|
@ -205,46 +267,6 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly string[] CommonImageFileNames = new[]
|
|
||||||
{
|
|
||||||
"poster",
|
|
||||||
"folder",
|
|
||||||
"cover",
|
|
||||||
"default"
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly string[] MusicImageFileNames = new[]
|
|
||||||
{
|
|
||||||
"folder",
|
|
||||||
"poster",
|
|
||||||
"cover",
|
|
||||||
"default"
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly string[] PersonImageFileNames = new[]
|
|
||||||
{
|
|
||||||
"folder",
|
|
||||||
"poster"
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly string[] SeriesImageFileNames = new[]
|
|
||||||
{
|
|
||||||
"poster",
|
|
||||||
"folder",
|
|
||||||
"cover",
|
|
||||||
"default",
|
|
||||||
"show"
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly string[] VideoImageFileNames = new[]
|
|
||||||
{
|
|
||||||
"poster",
|
|
||||||
"folder",
|
|
||||||
"cover",
|
|
||||||
"default",
|
|
||||||
"movie"
|
|
||||||
};
|
|
||||||
|
|
||||||
private void PopulatePrimaryImages(BaseItem item, List<LocalImageInfo> images, List<FileSystemMetadata> files, string imagePrefix, bool isInMixedFolder)
|
private void PopulatePrimaryImages(BaseItem item, List<LocalImageInfo> images, List<FileSystemMetadata> files, string imagePrefix, bool isInMixedFolder)
|
||||||
{
|
{
|
||||||
string[] imageFileNames;
|
string[] imageFileNames;
|
||||||
|
@ -252,24 +274,24 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
if (item is MusicAlbum || item is MusicArtist || item is PhotoAlbum)
|
if (item is MusicAlbum || item is MusicArtist || item is PhotoAlbum)
|
||||||
{
|
{
|
||||||
// these prefer folder
|
// these prefer folder
|
||||||
imageFileNames = MusicImageFileNames;
|
imageFileNames = _musicImageFileNames;
|
||||||
}
|
}
|
||||||
else if (item is Person)
|
else if (item is Person)
|
||||||
{
|
{
|
||||||
// these prefer folder
|
// these prefer folder
|
||||||
imageFileNames = PersonImageFileNames;
|
imageFileNames = _personImageFileNames;
|
||||||
}
|
}
|
||||||
else if (item is Series)
|
else if (item is Series)
|
||||||
{
|
{
|
||||||
imageFileNames = SeriesImageFileNames;
|
imageFileNames = _seriesImageFileNames;
|
||||||
}
|
}
|
||||||
else if (item is Video && !(item is Episode))
|
else if (item is Video && !(item is Episode))
|
||||||
{
|
{
|
||||||
imageFileNames = VideoImageFileNames;
|
imageFileNames = _videoImageFileNames;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
imageFileNames = CommonImageFileNames;
|
imageFileNames = _commonImageFileNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileNameWithoutExtension = item.FileNameWithoutExtension;
|
var fileNameWithoutExtension = item.FileNameWithoutExtension;
|
||||||
|
@ -301,7 +323,7 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PopulateBackdrops(BaseItem item, List<LocalImageInfo> images, List<FileSystemMetadata> files, string imagePrefix, bool isInMixedFolder, IDirectoryService directoryService)
|
private void PopulateBackdrops(BaseItem item, List<LocalImageInfo> images, List<FileSystemMetadata> files, string imagePrefix, bool isInMixedFolder)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(item.Path))
|
if (!string.IsNullOrEmpty(item.Path))
|
||||||
{
|
{
|
||||||
|
@ -328,13 +350,13 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
|
|
||||||
if (extraFanartFolder != null)
|
if (extraFanartFolder != null)
|
||||||
{
|
{
|
||||||
PopulateBackdropsFromExtraFanart(extraFanartFolder.FullName, images, directoryService);
|
PopulateBackdropsFromExtraFanart(extraFanartFolder.FullName, images);
|
||||||
}
|
}
|
||||||
|
|
||||||
PopulateBackdrops(images, files, imagePrefix, "backdrop", "backdrop", isInMixedFolder, ImageType.Backdrop);
|
PopulateBackdrops(images, files, imagePrefix, "backdrop", "backdrop", isInMixedFolder, ImageType.Backdrop);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PopulateBackdropsFromExtraFanart(string path, List<LocalImageInfo> images, IDirectoryService directoryService)
|
private void PopulateBackdropsFromExtraFanart(string path, List<LocalImageInfo> images)
|
||||||
{
|
{
|
||||||
var imageFiles = _fileSystem.GetFiles(path, BaseItem.SupportedImageExtensions, false, false);
|
var imageFiles = _fileSystem.GetFiles(path, BaseItem.SupportedImageExtensions, false, false);
|
||||||
|
|
||||||
|
@ -395,8 +417,6 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
|
||||||
|
|
||||||
private void PopulateSeasonImagesFromSeriesFolder(Season season, List<LocalImageInfo> images, IDirectoryService directoryService)
|
private void PopulateSeasonImagesFromSeriesFolder(Season season, List<LocalImageInfo> images, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
var seasonNumber = season.IndexNumber;
|
var seasonNumber = season.IndexNumber;
|
||||||
|
@ -410,7 +430,7 @@ namespace MediaBrowser.LocalMetadata.Images
|
||||||
var seriesFiles = GetFiles(series, false, directoryService).ToList();
|
var seriesFiles = GetFiles(series, false, directoryService).ToList();
|
||||||
|
|
||||||
// Try using the season name
|
// Try using the season name
|
||||||
var prefix = season.Name.ToLowerInvariant().Replace(" ", string.Empty);
|
var prefix = season.Name.Replace(" ", string.Empty, StringComparison.Ordinal).ToLowerInvariant();
|
||||||
|
|
||||||
var filenamePrefixes = new List<string> { prefix };
|
var filenamePrefixes = new List<string> { prefix };
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,28 @@
|
||||||
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
|
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="..\SharedVersion.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.1</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\SharedVersion.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Code Analyzers-->
|
||||||
|
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
<CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,8 +7,22 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.LocalMetadata.Parsers
|
namespace MediaBrowser.LocalMetadata.Parsers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The box set xml parser.
|
||||||
|
/// </summary>
|
||||||
public class BoxSetXmlParser : BaseItemXmlParser<BoxSet>
|
public class BoxSetXmlParser : BaseItemXmlParser<BoxSet>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="BoxSetXmlParser"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">Instance of the <see cref="ILogger{BoxSetXmlParset}"/> interface.</param>
|
||||||
|
/// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
|
||||||
|
public BoxSetXmlParser(ILogger<BoxSetXmlParser> logger, IProviderManager providerManager)
|
||||||
|
: base(logger, providerManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<BoxSet> item)
|
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<BoxSet> item)
|
||||||
{
|
{
|
||||||
switch (reader.Name)
|
switch (reader.Name)
|
||||||
|
@ -50,32 +64,32 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||||
switch (reader.Name)
|
switch (reader.Name)
|
||||||
{
|
{
|
||||||
case "CollectionItem":
|
case "CollectionItem":
|
||||||
|
{
|
||||||
|
if (!reader.IsEmptyElement)
|
||||||
{
|
{
|
||||||
if (!reader.IsEmptyElement)
|
using (var subReader = reader.ReadSubtree())
|
||||||
{
|
{
|
||||||
using (var subReader = reader.ReadSubtree())
|
var child = GetLinkedChild(subReader);
|
||||||
{
|
|
||||||
var child = GetLinkedChild(subReader);
|
|
||||||
|
|
||||||
if (child != null)
|
if (child != null)
|
||||||
{
|
{
|
||||||
list.Add(child);
|
list.Add(child);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
reader.Read();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
reader.Skip();
|
reader.Skip();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -86,10 +100,5 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||||
|
|
||||||
item.Item.LinkedChildren = list.ToArray();
|
item.Item.LinkedChildren = list.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoxSetXmlParser(ILogger<BoxSetXmlParser> logger, IProviderManager providerManager)
|
|
||||||
: base(logger, providerManager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,22 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.LocalMetadata.Parsers
|
namespace MediaBrowser.LocalMetadata.Parsers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Playlist xml parser.
|
||||||
|
/// </summary>
|
||||||
public class PlaylistXmlParser : BaseItemXmlParser<Playlist>
|
public class PlaylistXmlParser : BaseItemXmlParser<Playlist>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PlaylistXmlParser"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger">Instance of the <see cref="ILogger{PlaylistXmlParser}"/> interface.</param>
|
||||||
|
/// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
|
||||||
|
public PlaylistXmlParser(ILogger<PlaylistXmlParser> logger, IProviderManager providerManager)
|
||||||
|
: base(logger, providerManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<Playlist> result)
|
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<Playlist> result)
|
||||||
{
|
{
|
||||||
var item = result.Item;
|
var item = result.Item;
|
||||||
|
@ -16,11 +30,11 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||||
switch (reader.Name)
|
switch (reader.Name)
|
||||||
{
|
{
|
||||||
case "PlaylistMediaType":
|
case "PlaylistMediaType":
|
||||||
{
|
{
|
||||||
item.PlaylistMediaType = reader.ReadElementContentAsString();
|
item.PlaylistMediaType = reader.ReadElementContentAsString();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "PlaylistItems":
|
case "PlaylistItems":
|
||||||
|
|
||||||
|
@ -59,31 +73,31 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||||
switch (reader.Name)
|
switch (reader.Name)
|
||||||
{
|
{
|
||||||
case "PlaylistItem":
|
case "PlaylistItem":
|
||||||
|
{
|
||||||
|
if (reader.IsEmptyElement)
|
||||||
{
|
{
|
||||||
if (reader.IsEmptyElement)
|
reader.Read();
|
||||||
{
|
continue;
|
||||||
reader.Read();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var subReader = reader.ReadSubtree())
|
|
||||||
{
|
|
||||||
var child = GetLinkedChild(subReader);
|
|
||||||
|
|
||||||
if (child != null)
|
|
||||||
{
|
|
||||||
list.Add(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using (var subReader = reader.ReadSubtree())
|
||||||
|
{
|
||||||
|
var child = GetLinkedChild(subReader);
|
||||||
|
|
||||||
|
if (child != null)
|
||||||
|
{
|
||||||
|
list.Add(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
reader.Skip();
|
reader.Skip();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -94,10 +108,5 @@ namespace MediaBrowser.LocalMetadata.Parsers
|
||||||
|
|
||||||
item.LinkedChildren = list.ToArray();
|
item.LinkedChildren = list.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlaylistXmlParser(ILogger<PlaylistXmlParser> logger, IProviderManager providerManager)
|
|
||||||
: base(logger, providerManager)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,12 @@ namespace MediaBrowser.LocalMetadata.Providers
|
||||||
private readonly ILogger<BoxSetXmlParser> _logger;
|
private readonly ILogger<BoxSetXmlParser> _logger;
|
||||||
private readonly IProviderManager _providerManager;
|
private readonly IProviderManager _providerManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="BoxSetXmlProvider"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
|
||||||
|
/// <param name="logger">Instance of the <see cref="ILogger{BoxSetXmlParser}"/> interface.</param>
|
||||||
|
/// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
|
||||||
public BoxSetXmlProvider(IFileSystem fileSystem, ILogger<BoxSetXmlParser> logger, IProviderManager providerManager)
|
public BoxSetXmlProvider(IFileSystem fileSystem, ILogger<BoxSetXmlParser> logger, IProviderManager providerManager)
|
||||||
: base(fileSystem)
|
: base(fileSystem)
|
||||||
{
|
{
|
||||||
|
@ -23,11 +29,13 @@ namespace MediaBrowser.LocalMetadata.Providers
|
||||||
_providerManager = providerManager;
|
_providerManager = providerManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void Fetch(MetadataResult<BoxSet> result, string path, CancellationToken cancellationToken)
|
protected override void Fetch(MetadataResult<BoxSet> result, string path, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
new BoxSetXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
|
new BoxSetXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
|
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
return directoryService.GetFile(Path.Combine(info.Path, "collection.xml"));
|
return directoryService.GetFile(Path.Combine(info.Path, "collection.xml"));
|
||||||
|
|
|
@ -8,11 +8,20 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.LocalMetadata.Providers
|
namespace MediaBrowser.LocalMetadata.Providers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Playlist xml provider.
|
||||||
|
/// </summary>
|
||||||
public class PlaylistXmlProvider : BaseXmlProvider<Playlist>
|
public class PlaylistXmlProvider : BaseXmlProvider<Playlist>
|
||||||
{
|
{
|
||||||
private readonly ILogger<PlaylistXmlParser> _logger;
|
private readonly ILogger<PlaylistXmlParser> _logger;
|
||||||
private readonly IProviderManager _providerManager;
|
private readonly IProviderManager _providerManager;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PlaylistXmlProvider"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
|
||||||
|
/// <param name="logger">Instance of the <see cref="ILogger{PlaylistXmlParser}"/> interface.</param>
|
||||||
|
/// <param name="providerManager">Instance of the <see cref="IProviderManager"/> interface.</param>
|
||||||
public PlaylistXmlProvider(
|
public PlaylistXmlProvider(
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
ILogger<PlaylistXmlParser> logger,
|
ILogger<PlaylistXmlParser> logger,
|
||||||
|
@ -23,14 +32,16 @@ namespace MediaBrowser.LocalMetadata.Providers
|
||||||
_providerManager = providerManager;
|
_providerManager = providerManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void Fetch(MetadataResult<Playlist> result, string path, CancellationToken cancellationToken)
|
protected override void Fetch(MetadataResult<Playlist> result, string path, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
new PlaylistXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
|
new PlaylistXmlParser(_logger, _providerManager).Fetch(result, path, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
|
protected override FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService)
|
||||||
{
|
{
|
||||||
return directoryService.GetFile(PlaylistXmlSaver.GetSavePath(info.Path, FileSystem));
|
return directoryService.GetFile(PlaylistXmlSaver.GetSavePath(info.Path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,25 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.LocalMetadata.Savers
|
namespace MediaBrowser.LocalMetadata.Savers
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
public abstract class BaseXmlSaver : IMetadataFileSaver
|
public abstract class BaseXmlSaver : IMetadataFileSaver
|
||||||
{
|
{
|
||||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
/// <summary>
|
||||||
|
/// Gets the date added format.
|
||||||
|
/// </summary>
|
||||||
|
public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
|
private static readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="BaseXmlSaver"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
|
||||||
|
/// <param name="configurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
|
||||||
|
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
|
||||||
|
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
|
||||||
|
/// <param name="userDataManager">Instance of the <see cref="IUserDataManager"/> interface.</param>
|
||||||
|
/// <param name="logger">Instance of the <see cref="ILogger{BaseXmlSaver}"/> interface.</param>
|
||||||
public BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<BaseXmlSaver> logger)
|
public BaseXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<BaseXmlSaver> logger)
|
||||||
{
|
{
|
||||||
FileSystem = fileSystem;
|
FileSystem = fileSystem;
|
||||||
|
@ -31,20 +46,40 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the file system.
|
||||||
|
/// </summary>
|
||||||
protected IFileSystem FileSystem { get; private set; }
|
protected IFileSystem FileSystem { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the configuration manager.
|
||||||
|
/// </summary>
|
||||||
protected IServerConfigurationManager ConfigurationManager { get; private set; }
|
protected IServerConfigurationManager ConfigurationManager { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the library manager.
|
||||||
|
/// </summary>
|
||||||
protected ILibraryManager LibraryManager { get; private set; }
|
protected ILibraryManager LibraryManager { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the user manager.
|
||||||
|
/// </summary>
|
||||||
protected IUserManager UserManager { get; private set; }
|
protected IUserManager UserManager { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the user data manager.
|
||||||
|
/// </summary>
|
||||||
protected IUserDataManager UserDataManager { get; private set; }
|
protected IUserDataManager UserDataManager { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the logger.
|
||||||
|
/// </summary>
|
||||||
protected ILogger<BaseXmlSaver> Logger { get; private set; }
|
protected ILogger<BaseXmlSaver> Logger { get; private set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Name => XmlProviderUtils.Name;
|
public string Name => XmlProviderUtils.Name;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string GetSavePath(BaseItem item)
|
public string GetSavePath(BaseItem item)
|
||||||
{
|
{
|
||||||
return GetLocalSavePath(item);
|
return GetLocalSavePath(item);
|
||||||
|
@ -75,20 +110,19 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
|
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
|
||||||
public abstract bool IsEnabledFor(BaseItem item, ItemUpdateType updateType);
|
public abstract bool IsEnabledFor(BaseItem item, ItemUpdateType updateType);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public void Save(BaseItem item, CancellationToken cancellationToken)
|
public void Save(BaseItem item, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var path = GetSavePath(item);
|
var path = GetSavePath(item);
|
||||||
|
|
||||||
using (var memoryStream = new MemoryStream())
|
using var memoryStream = new MemoryStream();
|
||||||
{
|
Save(item, memoryStream);
|
||||||
Save(item, memoryStream, path);
|
|
||||||
|
|
||||||
memoryStream.Position = 0;
|
memoryStream.Position = 0;
|
||||||
|
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
SaveToFile(memoryStream, path);
|
SaveToFile(memoryStream, path);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveToFile(Stream stream, string path)
|
private void SaveToFile(Stream stream, string path)
|
||||||
|
@ -120,7 +154,7 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Save(BaseItem item, Stream stream, string xmlPath)
|
private void Save(BaseItem item, Stream stream)
|
||||||
{
|
{
|
||||||
var settings = new XmlWriterSettings
|
var settings = new XmlWriterSettings
|
||||||
{
|
{
|
||||||
|
@ -141,7 +175,7 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
|
|
||||||
if (baseItem != null)
|
if (baseItem != null)
|
||||||
{
|
{
|
||||||
AddCommonNodes(baseItem, writer, LibraryManager, UserManager, UserDataManager, FileSystem, ConfigurationManager);
|
AddCommonNodes(baseItem, writer, LibraryManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteCustomElements(item, writer);
|
WriteCustomElements(item, writer);
|
||||||
|
@ -152,22 +186,27 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Write custom elements.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The item.</param>
|
||||||
|
/// <param name="writer">The xml writer.</param>
|
||||||
protected abstract void WriteCustomElements(BaseItem item, XmlWriter writer);
|
protected abstract void WriteCustomElements(BaseItem item, XmlWriter writer);
|
||||||
|
|
||||||
public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss";
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the common nodes.
|
/// Adds the common nodes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Task.</returns>
|
/// <param name="item">The item.</param>
|
||||||
public static void AddCommonNodes(BaseItem item, XmlWriter writer, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config)
|
/// <param name="writer">The xml writer.</param>
|
||||||
|
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
|
||||||
|
public static void AddCommonNodes(BaseItem item, XmlWriter writer, ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(item.OfficialRating))
|
if (!string.IsNullOrEmpty(item.OfficialRating))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("ContentRating", item.OfficialRating);
|
writer.WriteElementString("ContentRating", item.OfficialRating);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteElementString("Added", item.DateCreated.ToLocalTime().ToString("G"));
|
writer.WriteElementString("Added", item.DateCreated.ToLocalTime().ToString("G", CultureInfo.InvariantCulture));
|
||||||
|
|
||||||
writer.WriteElementString("LockData", item.IsLocked.ToString(CultureInfo.InvariantCulture).ToLowerInvariant());
|
writer.WriteElementString("LockData", item.IsLocked.ToString(CultureInfo.InvariantCulture).ToLowerInvariant());
|
||||||
|
|
||||||
|
@ -178,7 +217,7 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
|
|
||||||
if (item.CriticRating.HasValue)
|
if (item.CriticRating.HasValue)
|
||||||
{
|
{
|
||||||
writer.WriteElementString("CriticRating", item.CriticRating.Value.ToString(UsCulture));
|
writer.WriteElementString("CriticRating", item.CriticRating.Value.ToString(_usCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(item.Overview))
|
if (!string.IsNullOrEmpty(item.Overview))
|
||||||
|
@ -211,11 +250,11 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
{
|
{
|
||||||
if (item is Person)
|
if (item is Person)
|
||||||
{
|
{
|
||||||
writer.WriteElementString("BirthDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd"));
|
writer.WriteElementString("BirthDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
else if (!(item is Episode))
|
else if (!(item is Episode))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("PremiereDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd"));
|
writer.WriteElementString("PremiereDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,11 +262,11 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
{
|
{
|
||||||
if (item is Person)
|
if (item is Person)
|
||||||
{
|
{
|
||||||
writer.WriteElementString("DeathDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd"));
|
writer.WriteElementString("DeathDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
else if (!(item is Episode))
|
else if (!(item is Episode))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("EndDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd"));
|
writer.WriteElementString("EndDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,12 +302,12 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
|
|
||||||
if (item.CommunityRating.HasValue)
|
if (item.CommunityRating.HasValue)
|
||||||
{
|
{
|
||||||
writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(UsCulture));
|
writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(_usCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.ProductionYear.HasValue && !(item is Person))
|
if (item.ProductionYear.HasValue && !(item is Person))
|
||||||
{
|
{
|
||||||
writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(UsCulture));
|
writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(_usCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasAspectRatio = item as IHasAspectRatio;
|
var hasAspectRatio = item as IHasAspectRatio;
|
||||||
|
@ -295,9 +334,9 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
|
|
||||||
if (runTimeTicks.HasValue)
|
if (runTimeTicks.HasValue)
|
||||||
{
|
{
|
||||||
var timespan = TimeSpan.FromTicks(runTimeTicks.Value);
|
var timespan = TimeSpan.FromTicks(runTimeTicks!.Value);
|
||||||
|
|
||||||
writer.WriteElementString("RunningTime", Math.Floor(timespan.TotalMinutes).ToString(UsCulture));
|
writer.WriteElementString("RunningTime", Math.Floor(timespan.TotalMinutes).ToString(_usCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.ProviderIds != null)
|
if (item.ProviderIds != null)
|
||||||
|
@ -370,7 +409,7 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
|
|
||||||
if (person.SortOrder.HasValue)
|
if (person.SortOrder.HasValue)
|
||||||
{
|
{
|
||||||
writer.WriteElementString("SortOrder", person.SortOrder.Value.ToString(UsCulture));
|
writer.WriteElementString("SortOrder", person.SortOrder.Value.ToString(_usCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteEndElement();
|
writer.WriteEndElement();
|
||||||
|
@ -400,6 +439,11 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
AddMediaInfo(item, writer);
|
AddMediaInfo(item, writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add shares.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The item.</param>
|
||||||
|
/// <param name="writer">The xml writer.</param>
|
||||||
public static void AddShares(IHasShares item, XmlWriter writer)
|
public static void AddShares(IHasShares item, XmlWriter writer)
|
||||||
{
|
{
|
||||||
writer.WriteStartElement("Shares");
|
writer.WriteStartElement("Shares");
|
||||||
|
@ -422,13 +466,13 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Appends the media info.
|
/// Appends the media info.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <param name="item">The item.</param>
|
||||||
|
/// <param name="writer">The xml writer.</param>
|
||||||
|
/// <typeparam name="T">Type of item.</typeparam>
|
||||||
public static void AddMediaInfo<T>(T item, XmlWriter writer)
|
public static void AddMediaInfo<T>(T item, XmlWriter writer)
|
||||||
where T : BaseItem
|
where T : BaseItem
|
||||||
{
|
{
|
||||||
var video = item as Video;
|
if (item is Video video)
|
||||||
|
|
||||||
if (video != null)
|
|
||||||
{
|
{
|
||||||
if (video.Video3DFormat.HasValue)
|
if (video.Video3DFormat.HasValue)
|
||||||
{
|
{
|
||||||
|
@ -454,6 +498,13 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ADd linked children.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">The item.</param>
|
||||||
|
/// <param name="writer">The xml writer.</param>
|
||||||
|
/// <param name="pluralNodeName">The plural node name.</param>
|
||||||
|
/// <param name="singularNodeName">The singular node name.</param>
|
||||||
public static void AddLinkedChildren(Folder item, XmlWriter writer, string pluralNodeName, string singularNodeName)
|
public static void AddLinkedChildren(Folder item, XmlWriter writer, string pluralNodeName, string singularNodeName)
|
||||||
{
|
{
|
||||||
var items = item.LinkedChildren
|
var items = item.LinkedChildren
|
||||||
|
|
|
@ -9,8 +9,26 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.LocalMetadata.Savers
|
namespace MediaBrowser.LocalMetadata.Savers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Box set xml saver.
|
||||||
|
/// </summary>
|
||||||
public class BoxSetXmlSaver : BaseXmlSaver
|
public class BoxSetXmlSaver : BaseXmlSaver
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="BoxSetXmlSaver"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
|
||||||
|
/// <param name="configurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
|
||||||
|
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
|
||||||
|
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
|
||||||
|
/// <param name="userDataManager">Instance of the <see cref="IUserDataManager"/> interface.</param>
|
||||||
|
/// <param name="logger">Instance of the <see cref="ILogger{BoxSetXmlSaver}"/> interface.</param>
|
||||||
|
public BoxSetXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<BoxSetXmlSaver> logger)
|
||||||
|
: base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType)
|
public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType)
|
||||||
{
|
{
|
||||||
if (!item.SupportsLocalMetadata)
|
if (!item.SupportsLocalMetadata)
|
||||||
|
@ -21,18 +39,15 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
return item is BoxSet && updateType >= ItemUpdateType.MetadataDownload;
|
return item is BoxSet && updateType >= ItemUpdateType.MetadataDownload;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void WriteCustomElements(BaseItem item, XmlWriter writer)
|
protected override void WriteCustomElements(BaseItem item, XmlWriter writer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override string GetLocalSavePath(BaseItem item)
|
protected override string GetLocalSavePath(BaseItem item)
|
||||||
{
|
{
|
||||||
return Path.Combine(item.Path, "collection.xml");
|
return Path.Combine(item.Path, "collection.xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoxSetXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<BoxSetXmlSaver> logger)
|
|
||||||
: base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,9 @@ using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.LocalMetadata.Savers
|
namespace MediaBrowser.LocalMetadata.Savers
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Playlist xml saver.
|
||||||
|
/// </summary>
|
||||||
public class PlaylistXmlSaver : BaseXmlSaver
|
public class PlaylistXmlSaver : BaseXmlSaver
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -16,6 +19,21 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string DefaultPlaylistFilename = "playlist.xml";
|
public const string DefaultPlaylistFilename = "playlist.xml";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="PlaylistXmlSaver"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
|
||||||
|
/// <param name="configurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
|
||||||
|
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
|
||||||
|
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
|
||||||
|
/// <param name="userDataManager">Instance of the <see cref="IUserDataManager"/> interface.</param>
|
||||||
|
/// <param name="logger">Instance of the <see cref="ILogger{PlaylistXmlSaver}"/> interface.</param>
|
||||||
|
public PlaylistXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<PlaylistXmlSaver> logger)
|
||||||
|
: base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType)
|
public override bool IsEnabledFor(BaseItem item, ItemUpdateType updateType)
|
||||||
{
|
{
|
||||||
if (!item.SupportsLocalMetadata)
|
if (!item.SupportsLocalMetadata)
|
||||||
|
@ -26,6 +44,7 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
return item is Playlist && updateType >= ItemUpdateType.MetadataImport;
|
return item is Playlist && updateType >= ItemUpdateType.MetadataImport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override void WriteCustomElements(BaseItem item, XmlWriter writer)
|
protected override void WriteCustomElements(BaseItem item, XmlWriter writer)
|
||||||
{
|
{
|
||||||
var game = (Playlist)item;
|
var game = (Playlist)item;
|
||||||
|
@ -36,12 +55,18 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
protected override string GetLocalSavePath(BaseItem item)
|
protected override string GetLocalSavePath(BaseItem item)
|
||||||
{
|
{
|
||||||
return GetSavePath(item.Path, FileSystem);
|
return GetSavePath(item.Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetSavePath(string itemPath, IFileSystem fileSystem)
|
/// <summary>
|
||||||
|
/// Get the save path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemPath">The item path.</param>
|
||||||
|
/// <returns>The save path.</returns>
|
||||||
|
public static string GetSavePath(string itemPath)
|
||||||
{
|
{
|
||||||
var path = itemPath;
|
var path = itemPath;
|
||||||
|
|
||||||
|
@ -52,10 +77,5 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||||
|
|
||||||
return Path.Combine(path, DefaultPlaylistFilename);
|
return Path.Combine(path, DefaultPlaylistFilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlaylistXmlSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger<PlaylistXmlSaver> logger)
|
|
||||||
: base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
MediaBrowser.LocalMetadata/XmlProviderUtils.cs
Normal file
13
MediaBrowser.LocalMetadata/XmlProviderUtils.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
namespace MediaBrowser.LocalMetadata
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The xml provider utils.
|
||||||
|
/// </summary>
|
||||||
|
public static class XmlProviderUtils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name.
|
||||||
|
/// </summary>
|
||||||
|
public static string Name => "Emby Xml";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user