From a37dc3da96a5445178de01c43a683230bc14882f Mon Sep 17 00:00:00 2001 From: Stepan Goremykin Date: Sun, 8 Oct 2023 00:17:48 +0200 Subject: Use async overload --- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations/Library') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index b0a4a4151..9de36d73c 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2858,7 +2858,7 @@ namespace Emby.Server.Implementations.Library { var path = Path.Combine(virtualFolderPath, collectionType.ToString().ToLowerInvariant() + ".collection"); - File.WriteAllBytes(path, Array.Empty()); + await File.WriteAllBytesAsync(path, Array.Empty()).ConfigureAwait(false); } CollectionFolder.SaveLibraryOptions(virtualFolderPath, options); -- cgit v1.2.3 From 8ea812b65d5287dad9c599d03dba8ad2994b244a Mon Sep 17 00:00:00 2001 From: Stepan Goremykin Date: Sun, 8 Oct 2023 00:26:12 +0200 Subject: Reduce string literal length by using verbatim string --- Emby.Naming/Common/NamingOptions.cs | 2 +- .../IO/ManagedFileSystem.cs | 2 +- .../Library/Resolvers/TV/SeasonResolver.cs | 2 +- .../Users/UserManager.cs | 2 +- .../MediaEncoding/EncodingHelper.cs | 14 ++++++------- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 10 ++++----- .../MediaInfo/AudioFileProber.cs | 2 +- .../TV/EpisodePathParserTest.cs | 8 ++++---- .../Library/PathExtensionsTests.cs | 24 +++++++++++----------- .../Plugins/PluginManagerTests.cs | 4 ++-- .../Parsers/MovieNfoParserTests.cs | 2 +- 11 files changed, 36 insertions(+), 36 deletions(-) (limited to 'Emby.Server.Implementations/Library') diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 692edae4a..b63c8f10e 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -376,7 +376,7 @@ namespace Emby.Naming.Common IsNamed = true, SupportsAbsoluteEpisodeNumbers = false }, - new EpisodeExpression("[\\/._ -]p(?:ar)?t[_. -]()([ivx]+|[0-9]+)([._ -][^\\/]*)$") + new EpisodeExpression(@"[\/._ -]p(?:ar)?t[_. -]()([ivx]+|[0-9]+)([._ -][^\/]*)$") { SupportsAbsoluteEpisodeNumbers = true }, diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 18b00ce0b..79eca4022 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -91,7 +91,7 @@ namespace Emby.Server.Implementations.IO } // unc path - if (filePath.StartsWith("\\\\", StringComparison.Ordinal)) + if (filePath.StartsWith(@"\\", StringComparison.Ordinal)) { return filePath; } diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index e9538a5c9..858c5b281 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -62,7 +62,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV var resolver = new Naming.TV.EpisodeResolver(namingOptions); var folderName = System.IO.Path.GetFileName(path); - var testPath = "\\\\test\\" + folderName; + var testPath = @"\\test\" + folderName; var episodeInfo = resolver.Resolve(testPath, true); diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 94ac4798c..22bfd7e6f 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -103,7 +103,7 @@ namespace Jellyfin.Server.Implementations.Users // This is some regex that matches only on unicode "word" characters, as well as -, _ and @ // In theory this will cut out most if not all 'control' characters which should help minimize any weirdness // Usernames can contain letters (a-z + whatever else unicode is cool with), numbers (0-9), at-signs (@), dashes (-), underscores (_), apostrophes ('), periods (.) and spaces ( ) - [GeneratedRegex("^[\\w\\ \\-'._@]+$")] + [GeneratedRegex(@"^[\w\ \-'._@]+$")] private static partial Regex ValidUsernameRegex(); /// diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 14417a5e4..03c778c07 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -2947,7 +2947,7 @@ namespace MediaBrowser.Controller.MediaEncoding return string.Format( CultureInfo.InvariantCulture, - "scale=trunc(min(max(iw\\,ih*a)\\,min({0}\\,{1}*a))/{2})*{2}:trunc(min(max(iw/a\\,ih)\\,min({0}/a\\,{1}))/2)*2", + @"scale=trunc(min(max(iw\,ih*a)\,min({0}\,{1}*a))/{2})*{2}:trunc(min(max(iw/a\,ih)\,min({0}/a\,{1}))/2)*2", maxWidthParam, maxHeightParam, scaleVal); @@ -2989,7 +2989,7 @@ namespace MediaBrowser.Controller.MediaEncoding return string.Format( CultureInfo.InvariantCulture, - "scale=trunc(min(max(iw\\,ih*a)\\,{0})/{1})*{1}:trunc(ow/a/2)*2", + @"scale=trunc(min(max(iw\,ih*a)\,{0})/{1})*{1}:trunc(ow/a/2)*2", maxWidthParam, scaleVal); } @@ -3001,7 +3001,7 @@ namespace MediaBrowser.Controller.MediaEncoding return string.Format( CultureInfo.InvariantCulture, - "scale=trunc(oh*a/{1})*{1}:min(max(iw/a\\,ih)\\,{0})", + @"scale=trunc(oh*a/{1})*{1}:min(max(iw/a\,ih)\,{0})", maxHeightParam, scaleVal); } @@ -3021,19 +3021,19 @@ namespace MediaBrowser.Controller.MediaEncoding switch (threedFormat.Value) { case Video3DFormat.HalfSideBySide: - filter = "crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2"; + filter = @"crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2"; // hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to requestedWidth. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not. break; case Video3DFormat.FullSideBySide: - filter = "crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2"; + filter = @"crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2"; // fsbs crop width in half,set the display aspect,crop out any black bars we may have made the scale width to requestedWidth. break; case Video3DFormat.HalfTopAndBottom: - filter = "crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2"; + filter = @"crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2"; // htab crop height in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to requestedWidth break; case Video3DFormat.FullTopAndBottom: - filter = "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2"; + filter = @"crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2"; // ftab crop height in half, set the display aspect,crop out any black bars we may have made the scale width to requestedWidth break; default: diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 9bd99f030..0241b77a1 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -680,13 +680,13 @@ namespace MediaBrowser.MediaEncoding.Encoder var scaler = threedFormat switch { // hsbs crop width in half,scale to correct size, set the display aspect,crop out any black bars we may have made. Work out the correct height based on the display aspect it will maintain the aspect where -1 in this case (3d) may not. - Video3DFormat.HalfSideBySide => "crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", + Video3DFormat.HalfSideBySide => @"crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,setsar=sar=1", // fsbs crop width in half,set the display aspect,crop out any black bars we may have made - Video3DFormat.FullSideBySide => "crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", + Video3DFormat.FullSideBySide => @"crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,setsar=sar=1", // htab crop height in half,scale to correct size, set the display aspect,crop out any black bars we may have made - Video3DFormat.HalfTopAndBottom => "crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", + Video3DFormat.HalfTopAndBottom => @"crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,setsar=sar=1", // ftab crop height in half, set the display aspect,crop out any black bars we may have made - Video3DFormat.FullTopAndBottom => "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", + Video3DFormat.FullTopAndBottom => @"crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,setsar=sar=1", _ => "scale=trunc(iw*sar):ih" }; @@ -858,7 +858,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping // We need to double escape - return path.Replace('\\', '/').Replace(":", "\\:", StringComparison.Ordinal).Replace("'", "'\\\\\\''", StringComparison.Ordinal); + return path.Replace('\\', '/').Replace(":", "\\:", StringComparison.Ordinal).Replace("'", @"'\\\''", StringComparison.Ordinal); } /// diff --git a/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs b/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs index 59b7c6e27..d81704227 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Providers.MediaInfo _mediaSourceManager = mediaSourceManager; } - [GeneratedRegex("I:\\s+(.*?)\\s+LUFS")] + [GeneratedRegex(@"I:\s+(.*?)\s+LUFS")] private static partial Regex LUFSRegex(); /// diff --git a/tests/Jellyfin.Naming.Tests/TV/EpisodePathParserTest.cs b/tests/Jellyfin.Naming.Tests/TV/EpisodePathParserTest.cs index 7604ddc80..5397f1371 100644 --- a/tests/Jellyfin.Naming.Tests/TV/EpisodePathParserTest.cs +++ b/tests/Jellyfin.Naming.Tests/TV/EpisodePathParserTest.cs @@ -13,10 +13,10 @@ namespace Jellyfin.Naming.Tests.TV [InlineData("/media/Foo - S04E011", true, "Foo", 4, 11)] [InlineData("/media/Foo/Foo s01x01", true, "Foo", 1, 1)] [InlineData("/media/Foo (2019)/Season 4/Foo (2019).S04E03", true, "Foo (2019)", 4, 3)] - [InlineData("D:\\media\\Foo\\Foo-S01E01", true, "Foo", 1, 1)] - [InlineData("D:\\media\\Foo - S04E011", true, "Foo", 4, 11)] - [InlineData("D:\\media\\Foo\\Foo s01x01", true, "Foo", 1, 1)] - [InlineData("D:\\media\\Foo (2019)\\Season 4\\Foo (2019).S04E03", true, "Foo (2019)", 4, 3)] + [InlineData(@"D:\media\Foo\Foo-S01E01", true, "Foo", 1, 1)] + [InlineData(@"D:\media\Foo - S04E011", true, "Foo", 4, 11)] + [InlineData(@"D:\media\Foo\Foo s01x01", true, "Foo", 1, 1)] + [InlineData(@"D:\media\Foo (2019)\Season 4\Foo (2019).S04E03", true, "Foo (2019)", 4, 3)] [InlineData("/Season 2/Elementary - 02x03-04-15 - Ep Name.mp4", false, "Elementary", 2, 3)] [InlineData("/Season 1/seriesname S01E02 blah.avi", false, "seriesname", 1, 2)] [InlineData("/Running Man/Running Man S2017E368.mkv", false, "Running Man", 2017, 368)] diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs index c33a957e6..1c35eb3f5 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/PathExtensionsTests.cs @@ -48,10 +48,10 @@ namespace Jellyfin.Server.Implementations.Tests.Library [InlineData("C:/Users/jeff/myfile.mkv", "C:/Users/jeff", "/home/jeff", "/home/jeff/myfile.mkv")] [InlineData("C:/Users/jeff/myfile.mkv", "C:/Users/jeff/", "/home/jeff", "/home/jeff/myfile.mkv")] [InlineData("/home/jeff/music/jeff's band/consistently inconsistent.mp3", "/home/jeff/music/jeff's band", "/home/not jeff", "/home/not jeff/consistently inconsistent.mp3")] - [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff", "/home/jeff", "/home/jeff/myfile.mkv")] - [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff", "/home/jeff/", "/home/jeff/myfile.mkv")] - [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff/", "/home/jeff/", "/home/jeff/myfile.mkv")] - [InlineData("C:\\Users\\jeff\\myfile.mkv", "C:\\Users/jeff/", "/", "/myfile.mkv")] + [InlineData(@"C:\Users\jeff\myfile.mkv", "C:\\Users/jeff", "/home/jeff", "/home/jeff/myfile.mkv")] + [InlineData(@"C:\Users\jeff\myfile.mkv", "C:\\Users/jeff", "/home/jeff/", "/home/jeff/myfile.mkv")] + [InlineData(@"C:\Users\jeff\myfile.mkv", "C:\\Users/jeff/", "/home/jeff/", "/home/jeff/myfile.mkv")] + [InlineData(@"C:\Users\jeff\myfile.mkv", "C:\\Users/jeff/", "/", "/myfile.mkv")] [InlineData("/o", "/o", "/s", "/s")] // regression test for #5977 public void TryReplaceSubPath_ValidArgs_Correct(string path, string subPath, string newSubPath, string? expectedResult) { @@ -78,10 +78,10 @@ namespace Jellyfin.Server.Implementations.Tests.Library [Theory] [InlineData(null, '/', null)] [InlineData(null, '\\', null)] - [InlineData("/home/jeff/myfile.mkv", '\\', "\\home\\jeff\\myfile.mkv")] - [InlineData("C:\\Users\\Jeff\\myfile.mkv", '/', "C:/Users/Jeff/myfile.mkv")] - [InlineData("\\home/jeff\\myfile.mkv", '\\', "\\home\\jeff\\myfile.mkv")] - [InlineData("\\home/jeff\\myfile.mkv", '/', "/home/jeff/myfile.mkv")] + [InlineData("/home/jeff/myfile.mkv", '\\', @"\home\jeff\myfile.mkv")] + [InlineData(@"C:\Users\Jeff\myfile.mkv", '/', "C:/Users/Jeff/myfile.mkv")] + [InlineData(@"\home/jeff\myfile.mkv", '\\', @"\home\jeff\myfile.mkv")] + [InlineData(@"\home/jeff\myfile.mkv", '/', "/home/jeff/myfile.mkv")] [InlineData("", '/', "")] public void NormalizePath_SpecifyingSeparator_Normalizes(string path, char separator, string expectedPath) { @@ -90,8 +90,8 @@ namespace Jellyfin.Server.Implementations.Tests.Library [Theory] [InlineData("/home/jeff/myfile.mkv")] - [InlineData("C:\\Users\\Jeff\\myfile.mkv")] - [InlineData("\\home/jeff\\myfile.mkv")] + [InlineData(@"C:\Users\Jeff\myfile.mkv")] + [InlineData(@"\home/jeff\myfile.mkv")] public void NormalizePath_NoArgs_UsesDirectorySeparatorChar(string path) { var separator = Path.DirectorySeparatorChar; @@ -101,8 +101,8 @@ namespace Jellyfin.Server.Implementations.Tests.Library [Theory] [InlineData("/home/jeff/myfile.mkv", '/')] - [InlineData("C:\\Users\\Jeff\\myfile.mkv", '\\')] - [InlineData("\\home/jeff\\myfile.mkv", '/')] + [InlineData(@"C:\Users\Jeff\myfile.mkv", '\\')] + [InlineData(@"\home/jeff\myfile.mkv", '/')] public void NormalizePath_OutVar_Correct(string path, char expectedSeparator) { var result = path.NormalizePath(out var separator); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs index f2a08e43c..934024826 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Plugins/PluginManagerTests.cs @@ -119,8 +119,8 @@ namespace Jellyfin.Server.Implementations.Tests.Plugins [InlineData("C:\\some.dll")] // Windows root path. [InlineData("test.txt")] // Not a DLL [InlineData(".././.././../some.dll")] // Traversal with current and parent - [InlineData("..\\.\\..\\.\\..\\some.dll")] // Windows traversal with current and parent - [InlineData("\\\\network\\resource.dll")] // UNC Path + [InlineData(@"..\.\..\.\..\some.dll")] // Windows traversal with current and parent + [InlineData(@"\\network\resource.dll")] // UNC Path [InlineData("https://jellyfin.org/some.dll")] // URL [InlineData("~/some.dll")] // Tilde poses a shell expansion risk, but is a valid path character. public void Constructor_DiscoversUnsafePluginAssembly_Status_Malfunctioned(string unsafePath) diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs index f56f58c6f..0a153b9cc 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs @@ -60,7 +60,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers { Exists = true, FullName = OperatingSystem.IsWindows() ? - "C:\\media\\movies\\Justice League (2017).jpg" + @"C:\media\movies\Justice League (2017).jpg" : "/media/movies/Justice League (2017).jpg" }; directoryService.Setup(x => x.GetFile(_localImageFileMetadata.FullName)) -- cgit v1.2.3 From f84469d50029801003e76cfe8a156d559182432d Mon Sep 17 00:00:00 2001 From: Stepan Goremykin Date: Sun, 8 Oct 2023 00:50:02 +0200 Subject: Remove redundant using directives --- Emby.Server.Implementations/HttpServer/WebSocketConnection.cs | 1 - Emby.Server.Implementations/Library/LibraryManager.cs | 1 - Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs | 1 - Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs | 1 - .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 1 - Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs | 2 -- Jellyfin.Networking/Extensions/NetworkExtensions.cs | 1 - .../Events/Consumers/Security/AuthenticationSucceededLogger.cs | 1 - .../Events/EventingServiceCollectionExtensions.cs | 3 +-- Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs | 1 - Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs | 1 - Jellyfin.Server/Startup.cs | 1 - MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs | 1 - MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs | 1 - MediaBrowser.Controller/Providers/IProviderManager.cs | 1 - MediaBrowser.Providers/Manager/MetadataService.cs | 1 - MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs | 1 - 17 files changed, 1 insertion(+), 19 deletions(-) (limited to 'Emby.Server.Implementations/Library') diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 7f620d666..f83da566b 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -12,7 +12,6 @@ using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net.WebSocketMessages; using MediaBrowser.Controller.Net.WebSocketMessages.Outbound; using MediaBrowser.Model.Session; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.HttpServer diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 9de36d73c..6e6c14a51 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -46,7 +46,6 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.Library; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Tasks; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Episode = MediaBrowser.Controller.Entities.TV.Episode; using EpisodeInfo = Emby.Naming.TV.EpisodeInfo; diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index b77c6b204..c860391fc 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; using Emby.Naming.Common; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index 1721be9e2..ff25ee585 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -17,7 +17,6 @@ using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.TunerHosts diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 7e588f681..04b0cb017 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -27,7 +27,6 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Net; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 613ea117f..db5e81df5 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.IO; using System.Linq; using System.Net.Http; using System.Threading; @@ -22,7 +21,6 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.MediaInfo; -using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Microsoft.Net.Http.Headers; diff --git a/Jellyfin.Networking/Extensions/NetworkExtensions.cs b/Jellyfin.Networking/Extensions/NetworkExtensions.cs index 910a33c0f..1b5afee55 100644 --- a/Jellyfin.Networking/Extensions/NetworkExtensions.cs +++ b/Jellyfin.Networking/Extensions/NetworkExtensions.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.Net; using System.Net.Sockets; using System.Text.RegularExpressions; diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs index 2ee5b4e88..3f3a0dec5 100644 --- a/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs +++ b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs @@ -1,7 +1,6 @@ using System.Globalization; using System.Threading.Tasks; using Jellyfin.Data.Entities; -using Jellyfin.Data.Events; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Events.Authentication; using MediaBrowser.Model.Activity; diff --git a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs index 9a473de52..9626817e9 100644 --- a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs +++ b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs @@ -1,5 +1,4 @@ -using Jellyfin.Data.Events; -using Jellyfin.Data.Events.System; +using Jellyfin.Data.Events.System; using Jellyfin.Data.Events.Users; using Jellyfin.Server.Implementations.Events.Consumers.Library; using Jellyfin.Server.Implementations.Events.Consumers.Security; diff --git a/Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs b/Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs index 3cb791b57..1664a751d 100644 --- a/Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs +++ b/Jellyfin.Server/Extensions/WebHostBuilderExtensions.cs @@ -3,7 +3,6 @@ using System.IO; using System.Net; using Jellyfin.Server.Helpers; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Extensions; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; diff --git a/Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs b/Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs index e1a43bb48..ac5047401 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.IO; using Emby.Server.Implementations.Data; using MediaBrowser.Controller; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Globalization; using Microsoft.Data.Sqlite; using Microsoft.Extensions.Logging; diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs index b759b6bca..1393f76aa 100644 --- a/Jellyfin.Server/Startup.cs +++ b/Jellyfin.Server/Startup.cs @@ -27,7 +27,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Hosting; -using Microsoft.VisualBasic; using Prometheus; namespace Jellyfin.Server diff --git a/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs b/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs index b263c173e..6acab13fe 100644 --- a/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs +++ b/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using Jellyfin.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; diff --git a/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs b/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs index ac20120d9..975218ad7 100644 --- a/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs +++ b/MediaBrowser.Controller/BaseItemManager/IBaseItemManager.cs @@ -1,4 +1,3 @@ -using System.Threading; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Configuration; diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 16943f6aa..eb5069b06 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Events; diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 75291b317..e336c8825 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -12,7 +12,6 @@ using Jellyfin.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; diff --git a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs index f22b861eb..f4b4eccf8 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Globalization; using System.Xml; using MediaBrowser.Common.Configuration; -- cgit v1.2.3 From d7748cfa0476280cce9dba34b4512cc58760c8bb Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 11 Oct 2023 18:32:57 +0200 Subject: Multiple Stream changes * Remove useless MemoryStream in DlnaHttpClient * Use HttpContent.ReadFromJsonAsync extension * Call ConfigureAwait for IAsyncDisposable * Use HttpContent.CopyToAsync where possible --- Emby.Dlna/PlayTo/DlnaHttpClient.cs | 55 +++++++++---------- .../Channels/ChannelManager.cs | 7 ++- .../Emby.Server.Implementations.csproj | 2 - .../Library/LiveStreamHelper.cs | 18 +++++-- .../Library/MediaSourceManager.cs | 15 ++++-- .../LiveTv/EmbyTV/EmbyTV.cs | 14 +++-- .../LiveTv/Listings/SchedulesDirect.cs | 25 +++------ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 61 +++++++++++----------- .../Localization/LocalizationManager.cs | 37 +++++++------ .../Plugins/PluginManager.cs | 18 +++++-- .../Updates/InstallationManager.cs | 5 +- Jellyfin.Api/Jellyfin.Api.csproj | 2 - .../ClientEvent/ClientEventLogger.cs | 9 ++-- .../Plugins/AudioDb/AudioDbAlbumProvider.cs | 15 ++---- .../Plugins/AudioDb/AudioDbArtistProvider.cs | 21 +++----- .../Plugins/Omdb/OmdbItemProvider.cs | 35 ++++++------- .../AuthHelper.cs | 11 ++-- .../Controllers/BrandingControllerTests.cs | 4 +- .../Controllers/DashboardControllerTests.cs | 7 ++- .../Controllers/DlnaControllerTests.cs | 12 ++--- .../Controllers/ItemsControllerTests.cs | 5 +- .../Controllers/StartupControllerTests.cs | 9 ++-- .../Controllers/UserControllerTests.cs | 9 ++-- .../Controllers/UserLibraryControllerTests.cs | 13 ++--- .../OpenApiSpecTests.cs | 4 +- 25 files changed, 197 insertions(+), 216 deletions(-) (limited to 'Emby.Server.Implementations/Library') diff --git a/Emby.Dlna/PlayTo/DlnaHttpClient.cs b/Emby.Dlna/PlayTo/DlnaHttpClient.cs index 220aa1a8d..255c51f19 100644 --- a/Emby.Dlna/PlayTo/DlnaHttpClient.cs +++ b/Emby.Dlna/PlayTo/DlnaHttpClient.cs @@ -55,41 +55,42 @@ namespace Emby.Dlna.PlayTo var client = _httpClientFactory.CreateClient(NamedClient.Dlna); using var response = await client.SendAsync(request, cancellationToken).ConfigureAwait(false); response.EnsureSuccessStatusCode(); - await using MemoryStream ms = new MemoryStream(); - await response.Content.CopyToAsync(ms, cancellationToken).ConfigureAwait(false); - ms.Position = 0; - try + Stream stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); + await using (stream.ConfigureAwait(false)) { - return await XDocument.LoadAsync( - ms, - LoadOptions.None, - cancellationToken).ConfigureAwait(false); - } - catch (XmlException) - { - // try correcting the Xml response with common errors - ms.Position = 0; - using StreamReader sr = new StreamReader(ms); - var xmlString = await sr.ReadToEndAsync(cancellationToken).ConfigureAwait(false); - - // find and replace unescaped ampersands (&) - xmlString = EscapeAmpersandRegex().Replace(xmlString, "&"); - try { - // retry reading Xml - using var xmlReader = new StringReader(xmlString); return await XDocument.LoadAsync( - xmlReader, + stream, LoadOptions.None, cancellationToken).ConfigureAwait(false); } - catch (XmlException ex) + catch (XmlException) { - _logger.LogError(ex, "Failed to parse response"); - _logger.LogDebug("Malformed response: {Content}\n", xmlString); - - return null; + // try correcting the Xml response with common errors + stream.Position = 0; + using StreamReader sr = new StreamReader(stream); + var xmlString = await sr.ReadToEndAsync(cancellationToken).ConfigureAwait(false); + + // find and replace unescaped ampersands (&) + xmlString = EscapeAmpersandRegex().Replace(xmlString, "&"); + + try + { + // retry reading Xml + using var xmlReader = new StringReader(xmlString); + return await XDocument.LoadAsync( + xmlReader, + LoadOptions.None, + cancellationToken).ConfigureAwait(false); + } + catch (XmlException ex) + { + _logger.LogError(ex, "Failed to parse response"); + _logger.LogDebug("Malformed response: {Content}\n", xmlString); + + return null; + } } } } diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 961e225e9..3036cbcf7 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -371,8 +371,11 @@ namespace Emby.Server.Implementations.Channels Directory.CreateDirectory(Path.GetDirectoryName(path)); - await using FileStream createStream = File.Create(path); - await JsonSerializer.SerializeAsync(createStream, mediaSources, _jsonOptions).ConfigureAwait(false); + FileStream createStream = File.Create(path); + await using (createStream.ConfigureAwait(false)) + { + await JsonSerializer.SerializeAsync(createStream, mediaSources, _jsonOptions).ConfigureAwait(false); + } } /// diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 3aab0a5e9..80263c139 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -43,8 +43,6 @@ net7.0 false true - - AD0001 diff --git a/Emby.Server.Implementations/Library/LiveStreamHelper.cs b/Emby.Server.Implementations/Library/LiveStreamHelper.cs index 936a08da8..59d705ace 100644 --- a/Emby.Server.Implementations/Library/LiveStreamHelper.cs +++ b/Emby.Server.Implementations/Library/LiveStreamHelper.cs @@ -48,15 +48,20 @@ namespace Emby.Server.Implementations.Library if (!string.IsNullOrEmpty(cacheKey)) { + FileStream jsonStream = AsyncFile.OpenRead(cacheFilePath); try { - await using FileStream jsonStream = AsyncFile.OpenRead(cacheFilePath); mediaInfo = await JsonSerializer.DeserializeAsync(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); // _logger.LogDebug("Found cached media info"); } - catch + catch (Exception ex) { + _logger.LogError(ex, "Error deserializing mediainfo cache"); + } + finally + { + await jsonStream.DisposeAsync().ConfigureAwait(false); } } @@ -84,10 +89,13 @@ namespace Emby.Server.Implementations.Library if (cacheFilePath is not null) { Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); - await using FileStream createStream = AsyncFile.OpenWrite(cacheFilePath); - await JsonSerializer.SerializeAsync(createStream, mediaInfo, _jsonOptions, cancellationToken).ConfigureAwait(false); + FileStream createStream = AsyncFile.OpenWrite(cacheFilePath); + await using (createStream.ConfigureAwait(false)) + { + await JsonSerializer.SerializeAsync(createStream, mediaInfo, _jsonOptions, cancellationToken).ConfigureAwait(false); + } - // _logger.LogDebug("Saved media info to {0}", cacheFilePath); + _logger.LogDebug("Saved media info to {0}", cacheFilePath); } } diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index c9a26a30f..91469dba9 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -625,17 +625,19 @@ namespace Emby.Server.Implementations.Library if (!string.IsNullOrEmpty(cacheKey)) { + FileStream jsonStream = AsyncFile.OpenRead(cacheFilePath); try { - await using FileStream jsonStream = AsyncFile.OpenRead(cacheFilePath); mediaInfo = await JsonSerializer.DeserializeAsync(jsonStream, _jsonOptions, cancellationToken).ConfigureAwait(false); - - // _logger.LogDebug("Found cached media info"); } catch (Exception ex) { _logger.LogDebug(ex, "_jsonSerializer.DeserializeFromFile threw an exception."); } + finally + { + await jsonStream.DisposeAsync().ConfigureAwait(false); + } } if (mediaInfo is null) @@ -664,8 +666,11 @@ namespace Emby.Server.Implementations.Library if (cacheFilePath is not null) { Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); - await using FileStream createStream = File.Create(cacheFilePath); - await JsonSerializer.SerializeAsync(createStream, mediaInfo, _jsonOptions, cancellationToken).ConfigureAwait(false); + FileStream createStream = File.Create(cacheFilePath); + await using (createStream.ConfigureAwait(false)) + { + await JsonSerializer.SerializeAsync(createStream, mediaInfo, _jsonOptions, cancellationToken).ConfigureAwait(false); + } // _logger.LogDebug("Saved media info to {0}", cacheFilePath); } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index b9d0f170a..74b62ca3f 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1851,7 +1851,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - await using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None)) + var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None); + await using (stream.ConfigureAwait(false)) { var settings = new XmlWriterSettings { @@ -1860,7 +1861,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Async = true }; - await using (var writer = XmlWriter.Create(stream, settings)) + var writer = XmlWriter.Create(stream, settings); + await using (writer.ConfigureAwait(false)) { await writer.WriteStartDocumentAsync(true).ConfigureAwait(false); await writer.WriteStartElementAsync(null, "tvshow", null).ConfigureAwait(false); @@ -1914,7 +1916,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - await using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None)) + var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None); + await using (stream.ConfigureAwait(false)) { var settings = new XmlWriterSettings { @@ -1927,7 +1930,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var isSeriesEpisode = timer.IsProgramSeries; - await using (var writer = XmlWriter.Create(stream, settings)) + var writer = XmlWriter.Create(stream, settings); + await using (writer.ConfigureAwait(false)) { await writer.WriteStartDocumentAsync(true).ConfigureAwait(false); @@ -1965,7 +1969,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } else { - await writer.WriteStartElementAsync(null, "movie", null); + await writer.WriteStartElementAsync(null, "movie", null).ConfigureAwait(false); if (!string.IsNullOrWhiteSpace(item.Name)) { diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 7645c6c52..6b0520ad0 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -106,8 +106,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings options.Content = JsonContent.Create(requestList, options: _jsonOptions); options.Headers.TryAddWithoutValidation("token", token); using var response = await Send(options, true, info, cancellationToken).ConfigureAwait(false); - await using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var dailySchedules = await JsonSerializer.DeserializeAsync>(responseStream, _jsonOptions, cancellationToken).ConfigureAwait(false); + var dailySchedules = await response.Content.ReadFromJsonAsync>(_jsonOptions, cancellationToken).ConfigureAwait(false); if (dailySchedules is null) { return Array.Empty(); @@ -122,8 +121,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings programRequestOptions.Content = JsonContent.Create(programIds, options: _jsonOptions); using var innerResponse = await Send(programRequestOptions, true, info, cancellationToken).ConfigureAwait(false); - await using var innerResponseStream = await innerResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var programDetails = await JsonSerializer.DeserializeAsync>(innerResponseStream, _jsonOptions, cancellationToken).ConfigureAwait(false); + var programDetails = await innerResponse.Content.ReadFromJsonAsync>(_jsonOptions, cancellationToken).ConfigureAwait(false); if (programDetails is null) { return Array.Empty(); @@ -482,8 +480,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings try { using var innerResponse2 = await Send(message, true, info, cancellationToken).ConfigureAwait(false); - await using var response = await innerResponse2.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - return await JsonSerializer.DeserializeAsync>(response, _jsonOptions, cancellationToken).ConfigureAwait(false); + return await innerResponse2.Content.ReadFromJsonAsync>(_jsonOptions, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { @@ -510,10 +507,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings try { using var httpResponse = await Send(options, false, info, cancellationToken).ConfigureAwait(false); - await using var response = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - - var root = await JsonSerializer.DeserializeAsync>(response, _jsonOptions, cancellationToken).ConfigureAwait(false); - + var root = await httpResponse.Content.ReadFromJsonAsync>(_jsonOptions, cancellationToken).ConfigureAwait(false); if (root is not null) { foreach (HeadendsDto headend in root) @@ -649,8 +643,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var response = await Send(options, false, null, cancellationToken).ConfigureAwait(false); response.EnsureSuccessStatusCode(); - await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var root = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); + var root = await response.Content.ReadFromJsonAsync(_jsonOptions, cancellationToken).ConfigureAwait(false); if (string.Equals(root?.Message, "OK", StringComparison.Ordinal)) { _logger.LogInformation("Authenticated with Schedules Direct token: {Token}", root.Token); @@ -691,10 +684,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { using var httpResponse = await Send(options, false, null, cancellationToken).ConfigureAwait(false); httpResponse.EnsureSuccessStatusCode(); - await using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - using var response = httpResponse.Content; - var root = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); - + var root = await httpResponse.Content.ReadFromJsonAsync(_jsonOptions, cancellationToken).ConfigureAwait(false); return root?.Lineups.Any(i => string.Equals(info.ListingsId, i.Lineup, StringComparison.OrdinalIgnoreCase)) ?? false; } catch (HttpRequestException ex) @@ -748,8 +738,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings options.Headers.TryAddWithoutValidation("token", token); using var httpResponse = await Send(options, true, info, cancellationToken).ConfigureAwait(false); - await using var stream = await httpResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var root = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); + var root = await httpResponse.Content.ReadFromJsonAsync(_jsonOptions, cancellationToken).ConfigureAwait(false); if (root is null) { return new List(); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 7e588f681..4f96dde44 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -9,6 +9,7 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Json; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -76,13 +77,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var model = await GetModelInfo(info, false, cancellationToken).ConfigureAwait(false); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(model.LineupURL ?? model.BaseURL + "/lineup.json", HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var lineup = await JsonSerializer.DeserializeAsync>(stream, _jsonOptions, cancellationToken) - .ConfigureAwait(false) ?? new List(); - + var lineup = await response.Content.ReadFromJsonAsync>(_jsonOptions, cancellationToken).ConfigureAwait(false) ?? Enumerable.Empty(); if (info.ImportFavoritesOnly) { - lineup = lineup.Where(i => i.Favorite).ToList(); + lineup = lineup.Where(i => i.Favorite); } return lineup.Where(i => !i.DRM).ToList(); @@ -129,9 +127,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun .GetAsync(GetApiUrl(info) + "/discover.json", HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); response.EnsureSuccessStatusCode(); - await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - var discoverResponse = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken) - .ConfigureAwait(false); + var discoverResponse = await response.Content.ReadFromJsonAsync(_jsonOptions, cancellationToken).ConfigureAwait(false); if (!string.IsNullOrEmpty(cacheKey)) { @@ -175,34 +171,37 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .GetAsync(string.Format(CultureInfo.InvariantCulture, "{0}/tuners.html", GetApiUrl(info)), HttpCompletionOption.ResponseHeadersRead, cancellationToken) .ConfigureAwait(false); - await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - using var sr = new StreamReader(stream, System.Text.Encoding.UTF8); var tuners = new List(); - await foreach (var line in sr.ReadAllLinesAsync().ConfigureAwait(false)) + var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); + await using (stream.ConfigureAwait(false)) { - string stripedLine = StripXML(line); - if (stripedLine.Contains("Channel", StringComparison.Ordinal)) + using var sr = new StreamReader(stream, System.Text.Encoding.UTF8); + await foreach (var line in sr.ReadAllLinesAsync().ConfigureAwait(false)) { - LiveTvTunerStatus status; - var index = stripedLine.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); - var name = stripedLine.Substring(0, index - 1); - var currentChannel = stripedLine.Substring(index + 7); - if (string.Equals(currentChannel, "none", StringComparison.Ordinal)) + string stripedLine = StripXML(line); + if (stripedLine.Contains("Channel", StringComparison.Ordinal)) { - status = LiveTvTunerStatus.LiveTv; - } - else - { - status = LiveTvTunerStatus.Available; - } + LiveTvTunerStatus status; + var index = stripedLine.IndexOf("Channel", StringComparison.OrdinalIgnoreCase); + var name = stripedLine.Substring(0, index - 1); + var currentChannel = stripedLine.Substring(index + 7); + if (string.Equals(currentChannel, "none", StringComparison.Ordinal)) + { + status = LiveTvTunerStatus.LiveTv; + } + else + { + status = LiveTvTunerStatus.Available; + } - tuners.Add(new LiveTvTunerInfo - { - Name = name, - SourceType = string.IsNullOrWhiteSpace(model.ModelNumber) ? Name : model.ModelNumber, - ProgramName = currentChannel, - Status = status - }); + tuners.Add(new LiveTvTunerInfo + { + Name = name, + SourceType = string.IsNullOrWhiteSpace(model.ModelNumber) ? Name : model.ModelNumber, + ProgramName = currentChannel, + Status = status + }); + } } } diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 96f435399..16776b6bd 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -71,25 +71,28 @@ namespace Emby.Server.Implementations.Localization string countryCode = resource.Substring(RatingsPath.Length, 2); var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); - await using var stream = _assembly.GetManifestResourceStream(resource); - using var reader = new StreamReader(stream!); // shouldn't be null here, we just got the resource path from Assembly.GetManifestResourceNames() - await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) + var stream = _assembly.GetManifestResourceStream(resource); + await using (stream!.ConfigureAwait(false)) // shouldn't be null here, we just got the resource path from Assembly.GetManifestResourceNames() { - if (string.IsNullOrWhiteSpace(line)) + using var reader = new StreamReader(stream!); + await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) { - continue; - } - - string[] parts = line.Split(','); - if (parts.Length == 2 - && int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) - { - var name = parts[0]; - dict.Add(name, new ParentalRating(name, value)); - } - else - { - _logger.LogWarning("Malformed line in ratings file for country {CountryCode}", countryCode); + if (string.IsNullOrWhiteSpace(line)) + { + continue; + } + + string[] parts = line.Split(','); + if (parts.Length == 2 + && int.TryParse(parts[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) + { + var name = parts[0]; + dict.Add(name, new ParentalRating(name, value)); + } + else + { + _logger.LogWarning("Malformed line in ratings file for country {CountryCode}", countryCode); + } } } diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index d7189ef0c..20793ee39 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -386,11 +386,11 @@ namespace Emby.Server.Implementations.Plugins var url = new Uri(packageInfo.ImageUrl); imagePath = Path.Join(path, url.Segments[^1]); - await using var fileStream = AsyncFile.OpenWrite(imagePath); - + var fileStream = AsyncFile.OpenWrite(imagePath); + Stream? downloadStream = null; try { - await using var downloadStream = await HttpClientFactory + downloadStream = await HttpClientFactory .CreateClient(NamedClient.Default) .GetStreamAsync(url) .ConfigureAwait(false); @@ -402,6 +402,14 @@ namespace Emby.Server.Implementations.Plugins _logger.LogError(ex, "Failed to download image to path {Path} on disk.", imagePath); imagePath = string.Empty; } + finally + { + await fileStream.DisposeAsync().ConfigureAwait(false); + if (downloadStream is not null) + { + await downloadStream.DisposeAsync().ConfigureAwait(false); + } + } } var manifest = new PluginManifest @@ -421,7 +429,7 @@ namespace Emby.Server.Implementations.Plugins ImagePath = imagePath }; - if (!await ReconcileManifest(manifest, path)) + if (!await ReconcileManifest(manifest, path).ConfigureAwait(false)) { // An error occurred during reconciliation and saving could be undesirable. return false; @@ -458,7 +466,7 @@ namespace Emby.Server.Implementations.Plugins } using var metaStream = File.OpenRead(metafile); - var localManifest = await JsonSerializer.DeserializeAsync(metaStream, _jsonOptions); + var localManifest = await JsonSerializer.DeserializeAsync(metaStream, _jsonOptions).ConfigureAwait(false); localManifest ??= new PluginManifest(); if (!Equals(localManifest.Id, manifest.Id)) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 77d385ba1..c717744b1 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -520,10 +520,9 @@ namespace Emby.Server.Implementations.Updates // CA5351: Do Not Use Broken Cryptographic Algorithms #pragma warning disable CA5351 - using var md5 = MD5.Create(); cancellationToken.ThrowIfCancellationRequested(); - var hash = Convert.ToHexString(md5.ComputeHash(stream)); + var hash = Convert.ToHexString(await MD5.HashDataAsync(stream, cancellationToken).ConfigureAwait(false)); if (!string.Equals(package.Checksum, hash, StringComparison.OrdinalIgnoreCase)) { _logger.LogError( @@ -556,7 +555,7 @@ namespace Emby.Server.Implementations.Updates reader.ExtractToDirectory(targetDir, true); // Ensure we create one or populate existing ones with missing data. - await _pluginManager.PopulateManifest(package.PackageInfo, package.Version, targetDir, status); + await _pluginManager.PopulateManifest(package.PackageInfo, package.Version, targetDir, status).ConfigureAwait(false); _pluginManager.ImportPluginFrom(targetDir); } diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 6a0a4706b..7ac231885 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -8,8 +8,6 @@ net7.0 true - - AD0001 diff --git a/MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs b/MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs index dea1c2f32..2a7e6be0f 100644 --- a/MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs +++ b/MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs @@ -23,9 +23,12 @@ namespace MediaBrowser.Controller.ClientEvent { var fileName = $"upload_{clientName}_{clientVersion}_{DateTime.UtcNow:yyyyMMddHHmmss}_{Guid.NewGuid():N}.log"; var logFilePath = Path.Combine(_applicationPaths.LogDirectoryPath, fileName); - await using var fileStream = new FileStream(logFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.None); - await fileContents.CopyToAsync(fileStream).ConfigureAwait(false); - return fileName; + var fileStream = new FileStream(logFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.None); + await using (fileStream.ConfigureAwait(false)) + { + await fileContents.CopyToAsync(fileStream).ConfigureAwait(false); + return fileName; + } } } } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs index 55e2474a5..daad9706c 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs @@ -176,17 +176,12 @@ namespace MediaBrowser.Providers.Plugins.AudioDb Directory.CreateDirectory(Path.GetDirectoryName(path)); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); - var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using (stream.ConfigureAwait(false)) + var fileStreamOptions = AsyncFile.WriteOptions; + fileStreamOptions.Mode = FileMode.Create; + var fs = new FileStream(path, fileStreamOptions); + await using (fs.ConfigureAwait(false)) { - var fileStreamOptions = AsyncFile.WriteOptions; - fileStreamOptions.Mode = FileMode.Create; - fileStreamOptions.PreallocationSize = stream.Length; - var xmlFileStream = new FileStream(path, fileStreamOptions); - await using (xmlFileStream.ConfigureAwait(false)) - { - await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); - } + await response.Content.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs index f3385b3a9..92742b1aa 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs @@ -154,20 +154,15 @@ namespace MediaBrowser.Providers.Plugins.AudioDb using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); response.EnsureSuccessStatusCode(); - var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using (stream.ConfigureAwait(false)) + var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId); + Directory.CreateDirectory(Path.GetDirectoryName(path)); + + var fileStreamOptions = AsyncFile.WriteOptions; + fileStreamOptions.Mode = FileMode.Create; + var xmlFileStream = new FileStream(path, fileStreamOptions); + await using (xmlFileStream.ConfigureAwait(false)) { - var path = GetArtistInfoPath(_config.ApplicationPaths, musicBrainzId); - Directory.CreateDirectory(Path.GetDirectoryName(path)); - - var fileStreamOptions = AsyncFile.WriteOptions; - fileStreamOptions.Mode = FileMode.Create; - fileStreamOptions.PreallocationSize = stream.Length; - var xmlFileStream = new FileStream(path, fileStreamOptions); - await using (xmlFileStream.ConfigureAwait(false)) - { - await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); - } + await response.Content.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs index e4bb4eaea..e84f1359b 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs @@ -8,6 +8,7 @@ using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Json; using System.Text; using System.Text.Json; using System.Threading; @@ -137,31 +138,27 @@ namespace MediaBrowser.Providers.Plugins.Omdb var url = OmdbProvider.GetOmdbUrl(urlQuery.ToString()); using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); - var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - await using (stream.ConfigureAwait(false)) + if (isSearch) { - if (isSearch) + var searchResultList = await response.Content.ReadFromJsonAsync(_jsonOptions, cancellationToken).ConfigureAwait(false); + if (searchResultList?.Search is not null) { - var searchResultList = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); - if (searchResultList?.Search is not null) + var resultCount = searchResultList.Search.Count; + var result = new RemoteSearchResult[resultCount]; + for (var i = 0; i < resultCount; i++) { - var resultCount = searchResultList.Search.Count; - var result = new RemoteSearchResult[resultCount]; - for (var i = 0; i < resultCount; i++) - { - result[i] = ResultToMetadataResult(searchResultList.Search[i], searchInfo, indexNumberEnd); - } - - return result; + result[i] = ResultToMetadataResult(searchResultList.Search[i], searchInfo, indexNumberEnd); } + + return result; } - else + } + else + { + var result = await response.Content.ReadFromJsonAsync(_jsonOptions, cancellationToken).ConfigureAwait(false); + if (string.Equals(result?.Response, "true", StringComparison.OrdinalIgnoreCase)) { - var result = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); - if (string.Equals(result?.Response, "true", StringComparison.OrdinalIgnoreCase)) - { - return new[] { ResultToMetadataResult(result, searchInfo, indexNumberEnd) }; - } + return new[] { ResultToMetadataResult(result, searchInfo, indexNumberEnd) }; } } diff --git a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs index 5ddbd30d1..4e8aec9f1 100644 --- a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs +++ b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs @@ -40,9 +40,7 @@ namespace Jellyfin.Server.Integration.Tests using var authResponse = await client.SendAsync(httpRequest); authResponse.EnsureSuccessStatusCode(); - var auth = await JsonSerializer.DeserializeAsync( - await authResponse.Content.ReadAsStreamAsync(), - jsonOptions); + var auth = await authResponse.Content.ReadFromJsonAsync(jsonOptions); return auth!.AccessToken; } @@ -51,8 +49,7 @@ namespace Jellyfin.Server.Integration.Tests { using var response = await client.GetAsync("Users/Me"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var userDto = await JsonSerializer.DeserializeAsync( - await response.Content.ReadAsStreamAsync(), JsonDefaults.Options); + var userDto = await response.Content.ReadFromJsonAsync(JsonDefaults.Options); Assert.NotNull(userDto); return userDto; } @@ -67,9 +64,7 @@ namespace Jellyfin.Server.Integration.Tests var response = await client.GetAsync($"Users/{userId}/Items/Root"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var rootDto = await JsonSerializer.DeserializeAsync( - await response.Content.ReadAsStreamAsync(), - JsonDefaults.Options); + var rootDto = await response.Content.ReadFromJsonAsync(JsonDefaults.Options); Assert.NotNull(rootDto); return rootDto; } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs index 87136dfc8..8761cf69b 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs @@ -1,4 +1,5 @@ using System.Net; +using System.Net.Http.Json; using System.Net.Mime; using System.Text; using System.Text.Json; @@ -30,8 +31,7 @@ namespace Jellyfin.Server.Integration.Tests Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var responseBody = await response.Content.ReadAsStreamAsync(); - _ = await JsonSerializer.DeserializeAsync(responseBody); + await response.Content.ReadFromJsonAsync(); } [Theory] diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs index bd6e1b690..39d449e27 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs @@ -1,5 +1,6 @@ using System.IO; using System.Net; +using System.Net.Http.Json; using System.Net.Mime; using System.Text; using System.Text.Json; @@ -64,8 +65,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var res = await response.Content.ReadAsStreamAsync(); - _ = await JsonSerializer.DeserializeAsync(res, _jsonOpions); + _ = await response.Content.ReadFromJsonAsync(_jsonOpions); // TODO: check content } @@ -81,8 +81,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var res = await response.Content.ReadAsStreamAsync(); - var data = await JsonSerializer.DeserializeAsync(res, _jsonOpions); + var data = await response.Content.ReadFromJsonAsync(_jsonOpions); Assert.NotNull(data); Assert.Empty(data); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs index 65e70caa0..e5d5e785c 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs @@ -93,9 +93,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var profiles = await JsonSerializer.DeserializeAsync( - await response.Content.ReadAsStreamAsync(), - _jsonOptions); + var profiles = await response.Content.ReadFromJsonAsync(_jsonOptions); var newProfile = profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsNew", StringComparison.Ordinal)); Assert.NotNull(newProfile); @@ -124,9 +122,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var profiles = await JsonSerializer.DeserializeAsync( - await response.Content.ReadAsStreamAsync(), - _jsonOptions); + var profiles = await response.Content.ReadFromJsonAsync(_jsonOptions); Assert.Null(profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsNew", StringComparison.Ordinal))); var newProfile = profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsUpdated", StringComparison.Ordinal)); @@ -150,9 +146,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); Assert.Equal(Encoding.UTF8.BodyName, response.Content.Headers.ContentType?.CharSet); - var profiles = await JsonSerializer.DeserializeAsync( - await response.Content.ReadAsStreamAsync(), - _jsonOptions); + var profiles = await response.Content.ReadFromJsonAsync(_jsonOptions); Assert.Null(profiles?.FirstOrDefault(x => string.Equals(x.Name, "ThisProfileIsUpdated", StringComparison.Ordinal))); } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs index a12e7ca0d..23de2489e 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/ItemsControllerTests.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Net; +using System.Net.Http.Json; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Extensions.Json; @@ -56,9 +57,7 @@ public sealed class ItemsControllerTests : IClassFixture>( - await response.Content.ReadAsStreamAsync(), - _jsonOptions); + var items = await response.Content.ReadFromJsonAsync>(_jsonOptions); Assert.NotNull(items); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs index 2d3879bdb..36861294b 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs @@ -43,8 +43,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(HttpStatusCode.OK, getResponse.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, getResponse.Content.Headers.ContentType?.MediaType); - using var responseStream = await getResponse.Content.ReadAsStreamAsync(); - var newConfig = await JsonSerializer.DeserializeAsync(responseStream, _jsonOptions); + var newConfig = await getResponse.Content.ReadFromJsonAsync(_jsonOptions); Assert.Equal(config.UICulture, newConfig!.UICulture); Assert.Equal(config.MetadataCountryCode, newConfig.MetadataCountryCode); Assert.Equal(config.PreferredMetadataLanguage, newConfig.PreferredMetadataLanguage); @@ -60,8 +59,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, response.Content.Headers.ContentType?.MediaType); - using var contentStream = await response.Content.ReadAsStreamAsync(); - var user = await JsonSerializer.DeserializeAsync(contentStream, _jsonOptions); + var user = await response.Content.ReadFromJsonAsync(_jsonOptions); Assert.NotNull(user); Assert.NotNull(user.Name); Assert.NotEmpty(user.Name); @@ -87,8 +85,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(HttpStatusCode.OK, getResponse.StatusCode); Assert.Equal(MediaTypeNames.Application.Json, getResponse.Content.Headers.ContentType?.MediaType); - var contentStream = await getResponse.Content.ReadAsStreamAsync(); - var newUser = await JsonSerializer.DeserializeAsync(contentStream, _jsonOptions); + var newUser = await getResponse.Content.ReadFromJsonAsync(_jsonOptions); Assert.NotNull(newUser); Assert.Equal(user.Name, newUser.Name); Assert.NotNull(newUser.Password); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs index 79d03d539..4fcacd2ca 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs @@ -43,8 +43,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers using var response = await client.GetAsync("Users/Public"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var users = await JsonSerializer.DeserializeAsync( - await response.Content.ReadAsStreamAsync(), _jsonOpions); + var users = await response.Content.ReadFromJsonAsync(_jsonOpions); // User are hidden by default Assert.NotNull(users); Assert.Empty(users); @@ -59,8 +58,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers using var response = await client.GetAsync("Users"); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var users = await JsonSerializer.DeserializeAsync( - await response.Content.ReadAsStreamAsync(), _jsonOpions); + var users = await response.Content.ReadFromJsonAsync(_jsonOpions); Assert.NotNull(users); Assert.Single(users); Assert.False(users![0].HasConfiguredPassword); @@ -92,8 +90,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers using var response = await CreateUserByName(client, createRequest); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - var user = await JsonSerializer.DeserializeAsync( - await response.Content.ReadAsStreamAsync(), _jsonOpions); + var user = await response.Content.ReadFromJsonAsync(_jsonOpions); Assert.Equal(TestUsername, user!.Name); Assert.False(user.HasPassword); Assert.False(user.HasConfiguredPassword); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs index 826a0a69d..130281c6d 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserLibraryControllerTests.cs @@ -1,6 +1,7 @@ using System; using System.Globalization; using System.Net; +using System.Net.Http.Json; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Extensions.Json; @@ -85,9 +86,7 @@ public sealed class UserLibraryControllerTests : IClassFixture( - await response.Content.ReadAsStreamAsync(), - _jsonOptions); + var rootDto = await response.Content.ReadFromJsonAsync(_jsonOptions); Assert.NotNull(rootDto); } @@ -102,9 +101,7 @@ public sealed class UserLibraryControllerTests : IClassFixture>( - await response.Content.ReadAsStreamAsync(), - _jsonOptions); + var rootDto = await response.Content.ReadFromJsonAsync>(_jsonOptions); Assert.NotNull(rootDto); } @@ -121,9 +118,7 @@ public sealed class UserLibraryControllerTests : IClassFixture( - await response.Content.ReadAsStreamAsync(), - _jsonOptions); + var rootDto = await response.Content.ReadFromJsonAsync(_jsonOptions); Assert.NotNull(rootDto); } } diff --git a/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs b/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs index 0ade345a1..98195a294 100644 --- a/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/OpenApiSpecTests.cs @@ -31,10 +31,10 @@ namespace Jellyfin.Server.Integration.Tests Assert.Equal("application/json; charset=utf-8", response.Content.Headers.ContentType?.ToString()); // Write out for publishing - var responseBody = await response.Content.ReadAsStringAsync(); string outputPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ".", "openapi.json")); _outputHelper.WriteLine("Writing OpenAPI Spec JSON to '{0}'.", outputPath); - File.WriteAllText(outputPath, responseBody); + await using var fs = File.Create(outputPath); + await response.Content.CopyToAsync(fs); } } } -- cgit v1.2.3 From c7a94d48ae019f41d5f06340bca7efe0788ad5ad Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Thu, 9 Nov 2023 14:00:13 -0700 Subject: Convert ItemSortBy to enum (#9765) * Convert ItemSortBy to enum * Rename Unknown to Default --- Emby.Dlna/ContentDirectory/ControlHandler.cs | 18 +- .../Data/SqliteItemRepository.cs | 205 +++++---------------- .../Images/BaseFolderImageProvider.cs | 2 +- .../Library/LibraryManager.cs | 8 +- .../LiveTv/LiveTvManager.cs | 2 +- .../Sorting/AiredEpisodeOrderComparer.cs | 3 +- .../Sorting/AlbumArtistComparer.cs | 3 +- .../Sorting/AlbumComparer.cs | 3 +- .../Sorting/ArtistComparer.cs | 3 +- .../Sorting/CommunityRatingComparer.cs | 3 +- .../Sorting/CriticRatingComparer.cs | 3 +- .../Sorting/DateCreatedComparer.cs | 3 +- .../Sorting/DateLastMediaAddedComparer.cs | 3 +- .../Sorting/DatePlayedComparer.cs | 3 +- .../Sorting/IndexNumberComparer.cs | 3 +- .../Sorting/IsFavoriteOrLikeComparer.cs | 3 +- .../Sorting/IsFolderComparer.cs | 3 +- .../Sorting/IsPlayedComparer.cs | 3 +- .../Sorting/IsUnplayedComparer.cs | 3 +- .../Sorting/NameComparer.cs | 3 +- .../Sorting/OfficialRatingComparer.cs | 3 +- .../Sorting/ParentIndexNumberComparer.cs | 3 +- .../Sorting/PlayCountComparer.cs | 3 +- .../Sorting/PremiereDateComparer.cs | 3 +- .../Sorting/ProductionYearComparer.cs | 3 +- .../Sorting/RandomComparer.cs | 3 +- .../Sorting/RuntimeComparer.cs | 3 +- .../Sorting/SeriesSortNameComparer.cs | 3 +- .../Sorting/SortNameComparer.cs | 3 +- .../Sorting/StartDateComparer.cs | 3 +- .../Sorting/StudioComparer.cs | 3 +- Jellyfin.Api/Controllers/ArtistsController.cs | 4 +- Jellyfin.Api/Controllers/ChannelsController.cs | 2 +- Jellyfin.Api/Controllers/GenresController.cs | 2 +- Jellyfin.Api/Controllers/ItemsController.cs | 4 +- Jellyfin.Api/Controllers/LiveTvController.cs | 4 +- Jellyfin.Api/Controllers/MusicGenresController.cs | 2 +- Jellyfin.Api/Controllers/TrailersController.cs | 2 +- Jellyfin.Api/Controllers/TvShowsController.cs | 4 +- Jellyfin.Api/Controllers/YearsController.cs | 2 +- Jellyfin.Api/Helpers/RequestHelpers.cs | 6 +- Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs | 2 +- Jellyfin.Data/Enums/ItemSortBy.cs | 167 +++++++++++++++++ .../Entities/IHasDisplayOrder.cs | 2 + .../Entities/InternalItemsQuery.cs | 4 +- MediaBrowser.Controller/Entities/Movies/BoxSet.cs | 8 +- MediaBrowser.Controller/Library/ILibraryManager.cs | 4 +- MediaBrowser.Controller/Providers/EpisodeInfo.cs | 1 + .../Sorting/IBaseItemComparer.cs | 6 +- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 1 + MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs | 4 +- MediaBrowser.Model/Querying/ItemSortBy.cs | 163 ---------------- MediaBrowser.Providers/Manager/MetadataService.cs | 1 + .../Plugins/Tmdb/TmdbClientManager.cs | 1 + .../Helpers/RequestHelpersTests.cs | 36 ++-- 55 files changed, 329 insertions(+), 416 deletions(-) create mode 100644 Jellyfin.Data/Enums/ItemSortBy.cs delete mode 100644 MediaBrowser.Model/Querying/ItemSortBy.cs (limited to 'Emby.Server.Implementations/Library') diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index abd594a3a..e685d252e 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -917,7 +917,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult GetGenres(BaseItem parent, InternalItemsQuery query) { // Don't sort - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); query.AncestorIds = new[] { parent.Id }; var genresResult = _libraryManager.GetGenres(query); @@ -933,7 +933,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult GetMusicGenres(BaseItem parent, InternalItemsQuery query) { // Don't sort - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); query.AncestorIds = new[] { parent.Id }; var genresResult = _libraryManager.GetMusicGenres(query); @@ -949,7 +949,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult GetMusicAlbumArtists(BaseItem parent, InternalItemsQuery query) { // Don't sort - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); query.AncestorIds = new[] { parent.Id }; var artists = _libraryManager.GetAlbumArtists(query); @@ -965,7 +965,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult GetMusicArtists(BaseItem parent, InternalItemsQuery query) { // Don't sort - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); query.AncestorIds = new[] { parent.Id }; var artists = _libraryManager.GetArtists(query); return ToResult(query.StartIndex, artists); @@ -980,7 +980,7 @@ namespace Emby.Dlna.ContentDirectory private QueryResult GetFavoriteArtists(BaseItem parent, InternalItemsQuery query) { // Don't sort - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); query.AncestorIds = new[] { parent.Id }; query.IsFavorite = true; var artists = _libraryManager.GetArtists(query); @@ -1011,7 +1011,7 @@ namespace Emby.Dlna.ContentDirectory /// The . private QueryResult GetNextUp(BaseItem parent, InternalItemsQuery query) { - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); var result = _tvSeriesManager.GetNextUp( new NextUpQuery @@ -1036,7 +1036,7 @@ namespace Emby.Dlna.ContentDirectory /// The . private QueryResult GetLatest(BaseItem parent, InternalItemsQuery query, BaseItemKind itemType) { - query.OrderBy = Array.Empty<(string, SortOrder)>(); + query.OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); var items = _userViewManager.GetLatestItems( new LatestItemsQuery @@ -1203,9 +1203,9 @@ namespace Emby.Dlna.ContentDirectory /// /// The . /// True if pre-sorted. - private static (string SortName, SortOrder SortOrder)[] GetOrderBy(SortCriteria sort, bool isPreSorted) + private static (ItemSortBy SortName, SortOrder SortOrder)[] GetOrderBy(SortCriteria sort, bool isPreSorted) { - return isPreSorted ? Array.Empty<(string, SortOrder)>() : new[] { (ItemSortBy.SortName, sort.SortOrder) }; + return isPreSorted ? Array.Empty<(ItemSortBy, SortOrder)>() : new[] { (ItemSortBy.SortName, sort.SortOrder) }; } /// diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index e519364c2..fadd4f2f3 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -2042,7 +2042,7 @@ namespace Emby.Server.Implementations.Data return false; } - var sortingFields = new HashSet(query.OrderBy.Select(i => i.OrderBy), StringComparer.OrdinalIgnoreCase); + var sortingFields = new HashSet(query.OrderBy.Select(i => i.OrderBy)); return sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked) || sortingFields.Contains(ItemSortBy.IsPlayed) @@ -2832,20 +2832,20 @@ namespace Emby.Server.Implementations.Data if (hasSimilar || hasSearch) { - List<(string, SortOrder)> prepend = new List<(string, SortOrder)>(4); + List<(ItemSortBy, SortOrder)> prepend = new List<(ItemSortBy, SortOrder)>(4); if (hasSearch) { - prepend.Add(("SearchScore", SortOrder.Descending)); + prepend.Add((ItemSortBy.SearchScore, SortOrder.Descending)); prepend.Add((ItemSortBy.SortName, SortOrder.Ascending)); } if (hasSimilar) { - prepend.Add(("SimilarityScore", SortOrder.Descending)); + prepend.Add((ItemSortBy.SimilarityScore, SortOrder.Descending)); prepend.Add((ItemSortBy.Random, SortOrder.Ascending)); } - var arr = new (string, SortOrder)[prepend.Count + orderBy.Count]; + var arr = new (ItemSortBy, SortOrder)[prepend.Count + orderBy.Count]; prepend.CopyTo(arr, 0); orderBy.CopyTo(arr, prepend.Count); orderBy = query.OrderBy = arr; @@ -2863,166 +2863,43 @@ namespace Emby.Server.Implementations.Data })); } - private string MapOrderByField(string name, InternalItemsQuery query) + private string MapOrderByField(ItemSortBy sortBy, InternalItemsQuery query) { - if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase)) - { - // TODO - return "SortName"; - } - - if (string.Equals(name, ItemSortBy.Runtime, StringComparison.OrdinalIgnoreCase)) - { - return "RuntimeTicks"; - } - - if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) - { - return "RANDOM()"; - } - - if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase)) - { - if (query.GroupBySeriesPresentationUniqueKey) - { - return "MAX(LastPlayedDate)"; - } - - return "LastPlayedDate"; - } - - if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.PlayCount; - } - - if (string.Equals(name, ItemSortBy.IsFavoriteOrLiked, StringComparison.OrdinalIgnoreCase)) - { - return "(Select Case When IsFavorite is null Then 0 Else IsFavorite End )"; - } - - if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.IsFolder; - } - - if (string.Equals(name, ItemSortBy.IsPlayed, StringComparison.OrdinalIgnoreCase)) - { - return "played"; - } - - if (string.Equals(name, ItemSortBy.IsUnplayed, StringComparison.OrdinalIgnoreCase)) - { - return "played"; - } - - if (string.Equals(name, ItemSortBy.DateLastContentAdded, StringComparison.OrdinalIgnoreCase)) - { - return "DateLastMediaAdded"; - } - - if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase)) - { - return "(select CleanValue from ItemValues where ItemId=Guid and Type=0 LIMIT 1)"; - } - - if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase)) - { - return "(select CleanValue from ItemValues where ItemId=Guid and Type=1 LIMIT 1)"; - } - - if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase)) - { - return "InheritedParentalRatingValue"; - } - - if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase)) - { - return "(select CleanValue from ItemValues where ItemId=Guid and Type=3 LIMIT 1)"; - } - - if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase)) - { - return "(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)"; - } - - if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase)) - { - return "SeriesName"; - } - - if (string.Equals(name, ItemSortBy.AiredEpisodeOrder, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.AiredEpisodeOrder; - } - - if (string.Equals(name, ItemSortBy.Album, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.Album; - } - - if (string.Equals(name, ItemSortBy.DateCreated, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.DateCreated; - } - - if (string.Equals(name, ItemSortBy.PremiereDate, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.PremiereDate; - } - - if (string.Equals(name, ItemSortBy.StartDate, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.StartDate; - } - - if (string.Equals(name, ItemSortBy.Name, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.Name; - } - - if (string.Equals(name, ItemSortBy.CommunityRating, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.CommunityRating; - } - - if (string.Equals(name, ItemSortBy.ProductionYear, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.ProductionYear; - } - - if (string.Equals(name, ItemSortBy.CriticRating, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.CriticRating; - } - - if (string.Equals(name, ItemSortBy.VideoBitRate, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.VideoBitRate; - } - - if (string.Equals(name, ItemSortBy.ParentIndexNumber, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.ParentIndexNumber; - } - - if (string.Equals(name, ItemSortBy.IndexNumber, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.IndexNumber; - } - - if (string.Equals(name, ItemSortBy.SimilarityScore, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.SimilarityScore; - } - - if (string.Equals(name, ItemSortBy.SearchScore, StringComparison.OrdinalIgnoreCase)) - { - return ItemSortBy.SearchScore; - } - - // Unknown SortBy, just sort by the SortName. - return ItemSortBy.SortName; + return sortBy switch + { + ItemSortBy.AirTime => "SortName", // TODO + ItemSortBy.Runtime => "RuntimeTicks", + ItemSortBy.Random => "RANDOM()", + ItemSortBy.DatePlayed when query.GroupBySeriesPresentationUniqueKey => "MAX(LastPlayedDate)", + ItemSortBy.DatePlayed => "LastPlayedDate", + ItemSortBy.PlayCount => "PlayCount", + ItemSortBy.IsFavoriteOrLiked => "(Select Case When IsFavorite is null Then 0 Else IsFavorite End )", + ItemSortBy.IsFolder => "IsFolder", + ItemSortBy.IsPlayed => "played", + ItemSortBy.IsUnplayed => "played", + ItemSortBy.DateLastContentAdded => "DateLastMediaAdded", + ItemSortBy.Artist => "(select CleanValue from ItemValues where ItemId=Guid and Type=0 LIMIT 1)", + ItemSortBy.AlbumArtist => "(select CleanValue from ItemValues where ItemId=Guid and Type=1 LIMIT 1)", + ItemSortBy.OfficialRating => "InheritedParentalRatingValue", + ItemSortBy.Studio => "(select CleanValue from ItemValues where ItemId=Guid and Type=3 LIMIT 1)", + ItemSortBy.SeriesDatePlayed => "(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", + ItemSortBy.SeriesSortName => "SeriesName", + ItemSortBy.AiredEpisodeOrder => "AiredEpisodeOrder", + ItemSortBy.Album => "Album", + ItemSortBy.DateCreated => "DateCreated", + ItemSortBy.PremiereDate => "PremiereDate", + ItemSortBy.StartDate => "StartDate", + ItemSortBy.Name => "Name", + ItemSortBy.CommunityRating => "CommunityRating", + ItemSortBy.ProductionYear => "ProductionYear", + ItemSortBy.CriticRating => "CriticRating", + ItemSortBy.VideoBitRate => "VideoBitRate", + ItemSortBy.ParentIndexNumber => "ParentIndexNumber", + ItemSortBy.IndexNumber => "IndexNumber", + ItemSortBy.SimilarityScore => "SimilarityScore", + ItemSortBy.SearchScore => "SearchScore", + _ => "SortName" + }; } public List GetItemIdsList(InternalItemsQuery query) diff --git a/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs b/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs index 539d4a63a..04d90af3c 100644 --- a/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs @@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.Images Recursive = true, DtoOptions = new DtoOptions(true), ImageTypes = new ImageType[] { ImageType.Primary }, - OrderBy = new (string, SortOrder)[] + OrderBy = new (ItemSortBy, SortOrder)[] { (ItemSortBy.IsFolder, SortOrder.Ascending), (ItemSortBy.SortName, SortOrder.Ascending) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 4f0983564..5c76e77be 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1678,7 +1678,7 @@ namespace Emby.Server.Implementations.Library /// The sort by. /// The sort order. /// IEnumerable{BaseItem}. - public IEnumerable Sort(IEnumerable items, User user, IEnumerable sortBy, SortOrder sortOrder) + public IEnumerable Sort(IEnumerable items, User user, IEnumerable sortBy, SortOrder sortOrder) { var isFirst = true; @@ -1701,7 +1701,7 @@ namespace Emby.Server.Implementations.Library return orderedItems ?? items; } - public IEnumerable Sort(IEnumerable items, User user, IEnumerable<(string OrderBy, SortOrder SortOrder)> orderBy) + public IEnumerable Sort(IEnumerable items, User user, IEnumerable<(ItemSortBy OrderBy, SortOrder SortOrder)> orderBy) { var isFirst = true; @@ -1736,9 +1736,9 @@ namespace Emby.Server.Implementations.Library /// The name. /// The user. /// IBaseItemComparer. - private IBaseItemComparer GetComparer(string name, User user) + private IBaseItemComparer GetComparer(ItemSortBy name, User user) { - var comparer = Comparers.FirstOrDefault(c => string.Equals(name, c.Name, StringComparison.OrdinalIgnoreCase)); + var comparer = Comparers.FirstOrDefault(c => name == c.Type); // If it requires a user, create a new one, and assign the user if (comparer is IUserBaseItemComparer) diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index ee039ff0f..dd427c736 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -207,7 +207,7 @@ namespace Emby.Server.Implementations.LiveTv orderBy.Insert(0, (ItemSortBy.IsFavoriteOrLiked, SortOrder.Descending)); } - if (!internalQuery.OrderBy.Any(i => string.Equals(i.OrderBy, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase))) + if (internalQuery.OrderBy.All(i => i.OrderBy != ItemSortBy.SortName)) { orderBy.Add((ItemSortBy.SortName, SortOrder.Ascending)); } diff --git a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index 964004ecc..6d13c6d57 100644 --- a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Sorting; @@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.AiredEpisodeOrder; + public ItemSortBy Type => ItemSortBy.AiredEpisodeOrder; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs b/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs index 67a9fbd3b..65c8599e7 100644 --- a/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs +++ b/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Sorting; @@ -16,7 +17,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.AlbumArtist; + public ItemSortBy Type => ItemSortBy.AlbumArtist; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/AlbumComparer.cs b/Emby.Server.Implementations/Sorting/AlbumComparer.cs index 4bed0fca1..e07113655 100644 --- a/Emby.Server.Implementations/Sorting/AlbumComparer.cs +++ b/Emby.Server.Implementations/Sorting/AlbumComparer.cs @@ -1,4 +1,5 @@ using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Sorting; @@ -15,7 +16,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.Album; + public ItemSortBy Type => ItemSortBy.Album; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/ArtistComparer.cs b/Emby.Server.Implementations/Sorting/ArtistComparer.cs index a8bb55e2b..f99977e5c 100644 --- a/Emby.Server.Implementations/Sorting/ArtistComparer.cs +++ b/Emby.Server.Implementations/Sorting/ArtistComparer.cs @@ -1,4 +1,5 @@ using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Sorting; @@ -12,7 +13,7 @@ namespace Emby.Server.Implementations.Sorting public class ArtistComparer : IBaseItemComparer { /// - public string Name => ItemSortBy.Artist; + public ItemSortBy Type => ItemSortBy.Artist; /// public int Compare(BaseItem? x, BaseItem? y) diff --git a/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs b/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs index 5cb11ab46..9e02ea2ae 100644 --- a/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -13,7 +14,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.CommunityRating; + public ItemSortBy Type => ItemSortBy.CommunityRating; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs b/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs index ba1835e4f..d4a8d4689 100644 --- a/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs @@ -1,3 +1,4 @@ +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -13,7 +14,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.CriticRating; + public ItemSortBy Type => ItemSortBy.CriticRating; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs index 6133aaccc..b86b4432f 100644 --- a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs @@ -1,4 +1,5 @@ using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.DateCreated; + public ItemSortBy Type => ItemSortBy.DateCreated; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs b/Emby.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs index b1cb123ce..e1c26d012 100644 --- a/Emby.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs @@ -3,6 +3,7 @@ using System; using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Sorting; @@ -34,7 +35,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.DateLastContentAdded; + public ItemSortBy Type => ItemSortBy.DateLastContentAdded; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs b/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs index 453d817c7..d668c17bf 100644 --- a/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs @@ -2,6 +2,7 @@ using System; using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Sorting; @@ -36,7 +37,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.DatePlayed; + public ItemSortBy Type => ItemSortBy.DatePlayed; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/IndexNumberComparer.cs b/Emby.Server.Implementations/Sorting/IndexNumberComparer.cs index 1bcaccd8a..11cad6256 100644 --- a/Emby.Server.Implementations/Sorting/IndexNumberComparer.cs +++ b/Emby.Server.Implementations/Sorting/IndexNumberComparer.cs @@ -1,4 +1,5 @@ using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.IndexNumber; + public ItemSortBy Type => ItemSortBy.IndexNumber; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs b/Emby.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs index 73e628cf7..622a341b6 100644 --- a/Emby.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs +++ b/Emby.Server.Implementations/Sorting/IsFavoriteOrLikeComparer.cs @@ -2,6 +2,7 @@ #pragma warning disable CS1591 using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Sorting; @@ -21,7 +22,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.IsFavoriteOrLiked; + public ItemSortBy Type => ItemSortBy.IsFavoriteOrLiked; /// /// Gets or sets the user data repository. diff --git a/Emby.Server.Implementations/Sorting/IsFolderComparer.cs b/Emby.Server.Implementations/Sorting/IsFolderComparer.cs index 3c5ddeefa..6f0ca59c5 100644 --- a/Emby.Server.Implementations/Sorting/IsFolderComparer.cs +++ b/Emby.Server.Implementations/Sorting/IsFolderComparer.cs @@ -1,5 +1,6 @@ #pragma warning disable CS1591 +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -12,7 +13,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.IsFolder; + public ItemSortBy Type => ItemSortBy.IsFolder; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/IsPlayedComparer.cs b/Emby.Server.Implementations/Sorting/IsPlayedComparer.cs index 7d77a8bc5..2a3e456c2 100644 --- a/Emby.Server.Implementations/Sorting/IsPlayedComparer.cs +++ b/Emby.Server.Implementations/Sorting/IsPlayedComparer.cs @@ -3,6 +3,7 @@ #pragma warning disable CS1591 using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Sorting; @@ -22,7 +23,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.IsUnplayed; + public ItemSortBy Type => ItemSortBy.IsUnplayed; /// /// Gets or sets the user data repository. diff --git a/Emby.Server.Implementations/Sorting/IsUnplayedComparer.cs b/Emby.Server.Implementations/Sorting/IsUnplayedComparer.cs index 926835f90..afd8ccf9f 100644 --- a/Emby.Server.Implementations/Sorting/IsUnplayedComparer.cs +++ b/Emby.Server.Implementations/Sorting/IsUnplayedComparer.cs @@ -3,6 +3,7 @@ #pragma warning disable CS1591 using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Sorting; @@ -22,7 +23,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.IsUnplayed; + public ItemSortBy Type => ItemSortBy.IsUnplayed; /// /// Gets or sets the user data repository. diff --git a/Emby.Server.Implementations/Sorting/NameComparer.cs b/Emby.Server.Implementations/Sorting/NameComparer.cs index 93bec4db9..72d9c7973 100644 --- a/Emby.Server.Implementations/Sorting/NameComparer.cs +++ b/Emby.Server.Implementations/Sorting/NameComparer.cs @@ -1,4 +1,5 @@ using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.Name; + public ItemSortBy Type => ItemSortBy.Name; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs b/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs index ce44f99a6..b4ee2c723 100644 --- a/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Globalization; @@ -21,7 +22,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.OfficialRating; + public ItemSortBy Type => ItemSortBy.OfficialRating; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs b/Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs index c54750843..5aeac29be 100644 --- a/Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs +++ b/Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs @@ -1,4 +1,5 @@ using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.ParentIndexNumber; + public ItemSortBy Type => ItemSortBy.ParentIndexNumber; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/PlayCountComparer.cs b/Emby.Server.Implementations/Sorting/PlayCountComparer.cs index 16f1b79b3..12f88bf4d 100644 --- a/Emby.Server.Implementations/Sorting/PlayCountComparer.cs +++ b/Emby.Server.Implementations/Sorting/PlayCountComparer.cs @@ -1,6 +1,7 @@ #nullable disable using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Sorting; @@ -23,7 +24,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.PlayCount; + public ItemSortBy Type => ItemSortBy.PlayCount; /// /// Gets or sets the user data repository. diff --git a/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs b/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs index db86b8002..8c8b8824f 100644 --- a/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs +++ b/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs @@ -1,4 +1,5 @@ using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.PremiereDate; + public ItemSortBy Type => ItemSortBy.PremiereDate; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs b/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs index 7fd1e024d..9aec87f18 100644 --- a/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs +++ b/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs @@ -1,3 +1,4 @@ +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -13,7 +14,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.ProductionYear; + public ItemSortBy Type => ItemSortBy.ProductionYear; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/RandomComparer.cs b/Emby.Server.Implementations/Sorting/RandomComparer.cs index bf0168222..6f8ea5b74 100644 --- a/Emby.Server.Implementations/Sorting/RandomComparer.cs +++ b/Emby.Server.Implementations/Sorting/RandomComparer.cs @@ -1,4 +1,5 @@ using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.Random; + public ItemSortBy Type => ItemSortBy.Random; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs index 753e58324..3c096ab02 100644 --- a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs +++ b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs @@ -1,4 +1,5 @@ using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.Runtime; + public ItemSortBy Type => ItemSortBy.Runtime; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs b/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs index 5b6c64f63..ed42fd6d5 100644 --- a/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs +++ b/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -13,7 +14,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.SeriesSortName; + public ItemSortBy Type => ItemSortBy.SeriesSortName; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/SortNameComparer.cs b/Emby.Server.Implementations/Sorting/SortNameComparer.cs index 19abafe19..314c25d12 100644 --- a/Emby.Server.Implementations/Sorting/SortNameComparer.cs +++ b/Emby.Server.Implementations/Sorting/SortNameComparer.cs @@ -1,4 +1,5 @@ using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.SortName; + public ItemSortBy Type => ItemSortBy.SortName; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/StartDateComparer.cs b/Emby.Server.Implementations/Sorting/StartDateComparer.cs index 2759d20de..e0b438ef1 100644 --- a/Emby.Server.Implementations/Sorting/StartDateComparer.cs +++ b/Emby.Server.Implementations/Sorting/StartDateComparer.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Sorting; @@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.StartDate; + public ItemSortBy Type => ItemSortBy.StartDate; /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/StudioComparer.cs b/Emby.Server.Implementations/Sorting/StudioComparer.cs index 89d10f3d2..0edffb783 100644 --- a/Emby.Server.Implementations/Sorting/StudioComparer.cs +++ b/Emby.Server.Implementations/Sorting/StudioComparer.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System; +using Jellyfin.Data.Enums; using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; @@ -14,7 +15,7 @@ namespace Emby.Server.Implementations.Sorting /// Gets the name. /// /// The name. - public string Name => ItemSortBy.Studio; + public ItemSortBy Type => ItemSortBy.Studio; /// /// Compares the specified x. diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs index c9d2f67f9..c3c43982b 100644 --- a/Jellyfin.Api/Controllers/ArtistsController.cs +++ b/Jellyfin.Api/Controllers/ArtistsController.cs @@ -113,7 +113,7 @@ public class ArtistsController : BaseJellyfinApiController [FromQuery] string? nameStartsWithOrGreater, [FromQuery] string? nameStartsWith, [FromQuery] string? nameLessThan, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder, [FromQuery] bool? enableImages = true, [FromQuery] bool enableTotalRecordCount = true) @@ -317,7 +317,7 @@ public class ArtistsController : BaseJellyfinApiController [FromQuery] string? nameStartsWithOrGreater, [FromQuery] string? nameStartsWith, [FromQuery] string? nameLessThan, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder, [FromQuery] bool? enableImages = true, [FromQuery] bool enableTotalRecordCount = true) diff --git a/Jellyfin.Api/Controllers/ChannelsController.cs b/Jellyfin.Api/Controllers/ChannelsController.cs index 11c4ac376..fdc16ee23 100644 --- a/Jellyfin.Api/Controllers/ChannelsController.cs +++ b/Jellyfin.Api/Controllers/ChannelsController.cs @@ -122,7 +122,7 @@ public class ChannelsController : BaseJellyfinApiController [FromQuery] int? limit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields) { userId = RequestHelpers.GetUserId(User, userId); diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs index da60f2c60..51f04fa27 100644 --- a/Jellyfin.Api/Controllers/GenresController.cs +++ b/Jellyfin.Api/Controllers/GenresController.cs @@ -85,7 +85,7 @@ public class GenresController : BaseJellyfinApiController [FromQuery] string? nameStartsWithOrGreater, [FromQuery] string? nameStartsWith, [FromQuery] string? nameLessThan, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder, [FromQuery] bool? enableImages = true, [FromQuery] bool enableTotalRecordCount = true) diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 80128536d..891cf88a7 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -197,7 +197,7 @@ public class ItemsController : BaseJellyfinApiController [FromQuery] bool? isFavorite, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] imageTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy, [FromQuery] bool? isPlayed, [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] genres, [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] officialRatings, @@ -654,7 +654,7 @@ public class ItemsController : BaseJellyfinApiController [FromQuery] bool? isFavorite, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] imageTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy, [FromQuery] bool? isPlayed, [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] genres, [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] officialRatings, diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index 649397d68..58159406a 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -143,7 +143,7 @@ public class LiveTvController : BaseJellyfinApiController [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, [FromQuery] bool? enableUserData, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy, [FromQuery] SortOrder? sortOrder, [FromQuery] bool enableFavoriteSorting = false, [FromQuery] bool addCurrentProgram = true) @@ -547,7 +547,7 @@ public class LiveTvController : BaseJellyfinApiController [FromQuery] bool? isSports, [FromQuery] int? startIndex, [FromQuery] int? limit, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder, [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] genres, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] genreIds, diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs index 435457af6..94c899357 100644 --- a/Jellyfin.Api/Controllers/MusicGenresController.cs +++ b/Jellyfin.Api/Controllers/MusicGenresController.cs @@ -85,7 +85,7 @@ public class MusicGenresController : BaseJellyfinApiController [FromQuery] string? nameStartsWithOrGreater, [FromQuery] string? nameStartsWith, [FromQuery] string? nameLessThan, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder, [FromQuery] bool? enableImages = true, [FromQuery] bool enableTotalRecordCount = true) diff --git a/Jellyfin.Api/Controllers/TrailersController.cs b/Jellyfin.Api/Controllers/TrailersController.cs index b5b640620..1246efd49 100644 --- a/Jellyfin.Api/Controllers/TrailersController.cs +++ b/Jellyfin.Api/Controllers/TrailersController.cs @@ -162,7 +162,7 @@ public class TrailersController : BaseJellyfinApiController [FromQuery] bool? isFavorite, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] imageTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy, [FromQuery] bool? isPlayed, [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] genres, [FromQuery, ModelBinder(typeof(PipeDelimitedArrayModelBinder))] string[] officialRatings, diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index af403fa80..55a30d469 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -219,7 +219,7 @@ public class TvShowsController : BaseJellyfinApiController [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, [FromQuery] bool? enableUserData, - [FromQuery] string? sortBy) + [FromQuery] ItemSortBy? sortBy) { userId = RequestHelpers.GetUserId(User, userId); var user = userId.Value.Equals(default) @@ -289,7 +289,7 @@ public class TvShowsController : BaseJellyfinApiController episodes = UserViewBuilder.FilterForAdjacency(episodes, adjacentTo.Value).ToList(); } - if (string.Equals(sortBy, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) + if (sortBy == ItemSortBy.Random) { episodes.Shuffle(); } diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs index 74370db50..641cdd81e 100644 --- a/Jellyfin.Api/Controllers/YearsController.cs +++ b/Jellyfin.Api/Controllers/YearsController.cs @@ -77,7 +77,7 @@ public class YearsController : BaseJellyfinApiController [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemSortBy[] sortBy, [FromQuery] bool? enableUserData, [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs index bc12ca388..be3d4dfb6 100644 --- a/Jellyfin.Api/Helpers/RequestHelpers.cs +++ b/Jellyfin.Api/Helpers/RequestHelpers.cs @@ -30,14 +30,14 @@ public static class RequestHelpers /// Sort By. Comma delimited string. /// Sort Order. Comma delimited string. /// Order By. - public static (string, SortOrder)[] GetOrderBy(IReadOnlyList sortBy, IReadOnlyList requestedSortOrder) + public static (ItemSortBy, SortOrder)[] GetOrderBy(IReadOnlyList sortBy, IReadOnlyList requestedSortOrder) { if (sortBy.Count == 0) { - return Array.Empty<(string, SortOrder)>(); + return Array.Empty<(ItemSortBy, SortOrder)>(); } - var result = new (string, SortOrder)[sortBy.Count]; + var result = new (ItemSortBy, SortOrder)[sortBy.Count]; var i = 0; // Add elements which have a SortOrder specified for (; i < requestedSortOrder.Count; i++) diff --git a/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs b/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs index 5e7dd689e..6a30de5e6 100644 --- a/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs +++ b/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs @@ -107,7 +107,7 @@ public class GetProgramsDto /// Optional. /// [JsonConverter(typeof(JsonCommaDelimitedArrayConverterFactory))] - public IReadOnlyList SortBy { get; set; } = Array.Empty(); + public IReadOnlyList SortBy { get; set; } = Array.Empty(); /// /// Gets or sets sort Order - Ascending,Descending. diff --git a/Jellyfin.Data/Enums/ItemSortBy.cs b/Jellyfin.Data/Enums/ItemSortBy.cs new file mode 100644 index 000000000..17bf1166d --- /dev/null +++ b/Jellyfin.Data/Enums/ItemSortBy.cs @@ -0,0 +1,167 @@ +namespace Jellyfin.Data.Enums; + +/// +/// These represent sort orders. +/// +public enum ItemSortBy +{ + /// + /// Default sort order. + /// + Default = 0, + + /// + /// The aired episode order. + /// + AiredEpisodeOrder = 1, + + /// + /// The album. + /// + Album = 2, + + /// + /// The album artist. + /// + AlbumArtist = 3, + + /// + /// The artist. + /// + Artist = 4, + + /// + /// The date created. + /// + DateCreated = 5, + + /// + /// The official rating. + /// + OfficialRating = 6, + + /// + /// The date played. + /// + DatePlayed = 7, + + /// + /// The premiere date. + /// + PremiereDate = 8, + + /// + /// The start date. + /// + StartDate = 9, + + /// + /// The sort name. + /// + SortName = 10, + + /// + /// The name. + /// + Name = 11, + + /// + /// The random. + /// + Random = 12, + + /// + /// The runtime. + /// + Runtime = 13, + + /// + /// The community rating. + /// + CommunityRating = 14, + + /// + /// The production year. + /// + ProductionYear = 15, + + /// + /// The play count. + /// + PlayCount = 16, + + /// + /// The critic rating. + /// + CriticRating = 17, + + /// + /// The IsFolder boolean. + /// + IsFolder = 18, + + /// + /// The IsUnplayed boolean. + /// + IsUnplayed = 19, + + /// + /// The IsPlayed boolean. + /// + IsPlayed = 20, + + /// + /// The series sort. + /// + SeriesSortName = 21, + + /// + /// The video bitrate. + /// + VideoBitRate = 22, + + /// + /// The air time. + /// + AirTime = 23, + + /// + /// The studio. + /// + Studio = 24, + + /// + /// The IsFavouriteOrLiked boolean. + /// + IsFavoriteOrLiked = 25, + + /// + /// The last content added date. + /// + DateLastContentAdded = 26, + + /// + /// The series last played date. + /// + SeriesDatePlayed = 27, + + /// + /// The parent index number. + /// + ParentIndexNumber = 28, + + /// + /// The index number. + /// + IndexNumber = 29, + + /// + /// The similarity score. + /// + SimilarityScore = 30, + + /// + /// The search score. + /// + SearchScore = 31, +} diff --git a/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs b/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs index 14459624e..7a73f3eaf 100644 --- a/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs +++ b/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs @@ -1,5 +1,7 @@ #nullable disable +using Jellyfin.Data.Enums; + namespace MediaBrowser.Controller.Entities { /// diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index a51299284..fb50a4546 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -39,7 +39,7 @@ namespace MediaBrowser.Controller.Entities MediaTypes = Array.Empty(); MinSimilarityScore = 20; OfficialRatings = Array.Empty(); - OrderBy = Array.Empty<(string, SortOrder)>(); + OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); PersonIds = Array.Empty(); PersonTypes = Array.Empty(); PresetViews = Array.Empty(); @@ -284,7 +284,7 @@ namespace MediaBrowser.Controller.Entities public bool? HasChapterImages { get; set; } - public IReadOnlyList<(string OrderBy, SortOrder SortOrder)> OrderBy { get; set; } + public IReadOnlyList<(ItemSortBy OrderBy, SortOrder SortOrder)> OrderBy { get; set; } public DateTime? MinDateCreated { get; set; } diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 66210cb6c..d7ccfd8ae 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Controller.Entities.Movies { public BoxSet() { - DisplayOrder = ItemSortBy.PremiereDate; + DisplayOrder = "PremiereDate"; } [JsonIgnore] @@ -116,13 +116,13 @@ namespace MediaBrowser.Controller.Entities.Movies { var children = base.GetChildren(user, includeLinkedChildren, query); - if (string.Equals(DisplayOrder, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(DisplayOrder, "SortName", StringComparison.OrdinalIgnoreCase)) { // Sort by name return LibraryManager.Sort(children, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList(); } - if (string.Equals(DisplayOrder, ItemSortBy.PremiereDate, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(DisplayOrder, "PremiereDate", StringComparison.OrdinalIgnoreCase)) { // Sort by release date return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList(); @@ -136,7 +136,7 @@ namespace MediaBrowser.Controller.Entities.Movies { var children = base.GetRecursiveChildren(user, query); - if (string.Equals(DisplayOrder, ItemSortBy.PremiereDate, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(DisplayOrder, "PremiereDate", StringComparison.OrdinalIgnoreCase)) { // Sort by release date return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList(); diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index f34e3d68d..52d546a4f 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -199,9 +199,9 @@ namespace MediaBrowser.Controller.Library /// The sort by. /// The sort order. /// IEnumerable{BaseItem}. - IEnumerable Sort(IEnumerable items, User user, IEnumerable sortBy, SortOrder sortOrder); + IEnumerable Sort(IEnumerable items, User user, IEnumerable sortBy, SortOrder sortOrder); - IEnumerable Sort(IEnumerable items, User user, IEnumerable<(string OrderBy, SortOrder SortOrder)> orderBy); + IEnumerable Sort(IEnumerable items, User user, IEnumerable<(ItemSortBy OrderBy, SortOrder SortOrder)> orderBy); /// /// Gets the user root folder. diff --git a/MediaBrowser.Controller/Providers/EpisodeInfo.cs b/MediaBrowser.Controller/Providers/EpisodeInfo.cs index c4ad352a3..2f7ebb5cc 100644 --- a/MediaBrowser.Controller/Providers/EpisodeInfo.cs +++ b/MediaBrowser.Controller/Providers/EpisodeInfo.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using Jellyfin.Data.Enums; namespace MediaBrowser.Controller.Providers { diff --git a/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs b/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs index 07fe1ea8a..96f8a2af5 100644 --- a/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs +++ b/MediaBrowser.Controller/Sorting/IBaseItemComparer.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; namespace MediaBrowser.Controller.Sorting @@ -9,9 +10,8 @@ namespace MediaBrowser.Controller.Sorting public interface IBaseItemComparer : IComparer { /// - /// Gets the name. + /// Gets the comparer type. /// - /// The name. - string Name { get; } + ItemSortBy Type { get; } } } diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index f913b2320..5a7193079 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -6,6 +6,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; diff --git a/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs b/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs index 673d97a9e..d872572b7 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.Model.LiveTv public LiveTvChannelQuery() { EnableUserData = true; - SortBy = Array.Empty(); + SortBy = Array.Empty(); } /// @@ -99,7 +99,7 @@ namespace MediaBrowser.Model.LiveTv public bool? IsSeries { get; set; } - public string[] SortBy { get; set; } + public ItemSortBy[] SortBy { get; set; } /// /// Gets or sets the sort order to return results with. diff --git a/MediaBrowser.Model/Querying/ItemSortBy.cs b/MediaBrowser.Model/Querying/ItemSortBy.cs deleted file mode 100644 index 1a7c9a63b..000000000 --- a/MediaBrowser.Model/Querying/ItemSortBy.cs +++ /dev/null @@ -1,163 +0,0 @@ -namespace MediaBrowser.Model.Querying -{ - /// - /// These represent sort orders that are known by the core. - /// - public static class ItemSortBy - { - /// - /// The aired episode order. - /// - public const string AiredEpisodeOrder = "AiredEpisodeOrder"; - - /// - /// The album. - /// - public const string Album = "Album"; - - /// - /// The album artist. - /// - public const string AlbumArtist = "AlbumArtist"; - - /// - /// The artist. - /// - public const string Artist = "Artist"; - - /// - /// The date created. - /// - public const string DateCreated = "DateCreated"; - - /// - /// The official rating. - /// - public const string OfficialRating = "OfficialRating"; - - /// - /// The date played. - /// - public const string DatePlayed = "DatePlayed"; - - /// - /// The premiere date. - /// - public const string PremiereDate = "PremiereDate"; - - /// - /// The start date. - /// - public const string StartDate = "StartDate"; - - /// - /// The sort name. - /// - public const string SortName = "SortName"; - - /// - /// The name. - /// - public const string Name = "Name"; - - /// - /// The random. - /// - public const string Random = "Random"; - - /// - /// The runtime. - /// - public const string Runtime = "Runtime"; - - /// - /// The community rating. - /// - public const string CommunityRating = "CommunityRating"; - - /// - /// The production year. - /// - public const string ProductionYear = "ProductionYear"; - - /// - /// The play count. - /// - public const string PlayCount = "PlayCount"; - - /// - /// The critic rating. - /// - public const string CriticRating = "CriticRating"; - - /// - /// The IsFolder boolean. - /// - public const string IsFolder = "IsFolder"; - - /// - /// The IsUnplayed boolean. - /// - public const string IsUnplayed = "IsUnplayed"; - - /// - /// The IsPlayed boolean. - /// - public const string IsPlayed = "IsPlayed"; - - /// - /// The series sort. - /// - public const string SeriesSortName = "SeriesSortName"; - - /// - /// The video bitrate. - /// - public const string VideoBitRate = "VideoBitRate"; - - /// - /// The air time. - /// - public const string AirTime = "AirTime"; - - /// - /// The studio. - /// - public const string Studio = "Studio"; - - /// - /// The IsFavouriteOrLiked boolean. - /// - public const string IsFavoriteOrLiked = "IsFavoriteOrLiked"; - - /// - /// The last content added date. - /// - public const string DateLastContentAdded = "DateLastContentAdded"; - - /// - /// The series last played date. - /// - public const string SeriesDatePlayed = "SeriesDatePlayed"; - - /// - /// The parent index number. - /// - public const string ParentIndexNumber = "ParentIndexNumber"; - - /// - /// The index number. - /// - public const string IndexNumber = "IndexNumber"; - - /// - /// The similarity score. - /// - public const string SimilarityScore = "SimilarityScore"; - - /// - /// The search score. - /// - public const string SearchScore = "SearchScore"; - } -} diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index e336c8825..06445c90d 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Enums; using Jellyfin.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs b/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs index 500ebaf71..72e59c9ac 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Enums; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; diff --git a/tests/Jellyfin.Api.Tests/Helpers/RequestHelpersTests.cs b/tests/Jellyfin.Api.Tests/Helpers/RequestHelpersTests.cs index 2d7741d81..a2d1b3607 100644 --- a/tests/Jellyfin.Api.Tests/Helpers/RequestHelpersTests.cs +++ b/tests/Jellyfin.Api.Tests/Helpers/RequestHelpersTests.cs @@ -14,7 +14,7 @@ namespace Jellyfin.Api.Tests.Helpers { [Theory] [MemberData(nameof(GetOrderBy_Success_TestData))] - public static void GetOrderBy_Success(IReadOnlyList sortBy, IReadOnlyList requestedSortOrder, (string, SortOrder)[] expected) + public static void GetOrderBy_Success(IReadOnlyList sortBy, IReadOnlyList requestedSortOrder, (ItemSortBy, SortOrder)[] expected) { Assert.Equal(expected, RequestHelpers.GetOrderBy(sortBy, requestedSortOrder)); } @@ -95,42 +95,42 @@ namespace Jellyfin.Api.Tests.Helpers Assert.Throws(() => RequestHelpers.GetUserId(principal, requestUserId)); } - public static TheoryData, IReadOnlyList, (string, SortOrder)[]> GetOrderBy_Success_TestData() + public static TheoryData, IReadOnlyList, (ItemSortBy, SortOrder)[]> GetOrderBy_Success_TestData() { - var data = new TheoryData, IReadOnlyList, (string, SortOrder)[]>(); + var data = new TheoryData, IReadOnlyList, (ItemSortBy, SortOrder)[]>(); data.Add( - Array.Empty(), + Array.Empty(), Array.Empty(), - Array.Empty<(string, SortOrder)>()); + Array.Empty<(ItemSortBy, SortOrder)>()); data.Add( - new string[] + new[] { - "IsFavoriteOrLiked", - "Random" + ItemSortBy.IsFavoriteOrLiked, + ItemSortBy.Random }, Array.Empty(), - new (string, SortOrder)[] + new (ItemSortBy, SortOrder)[] { - ("IsFavoriteOrLiked", SortOrder.Ascending), - ("Random", SortOrder.Ascending), + (ItemSortBy.IsFavoriteOrLiked, SortOrder.Ascending), + (ItemSortBy.Random, SortOrder.Ascending), }); data.Add( - new string[] + new[] { - "SortName", - "ProductionYear" + ItemSortBy.SortName, + ItemSortBy.ProductionYear }, - new SortOrder[] + new[] { SortOrder.Descending }, - new (string, SortOrder)[] + new (ItemSortBy, SortOrder)[] { - ("SortName", SortOrder.Descending), - ("ProductionYear", SortOrder.Descending), + (ItemSortBy.SortName, SortOrder.Descending), + (ItemSortBy.ProductionYear, SortOrder.Descending), }); return data; -- cgit v1.2.3 From 906f701fa81c7cde1a9a01b066f3f29ff98552a5 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Thu, 9 Nov 2023 14:00:29 -0700 Subject: Convert CollectionType, SpecialFolderType to enum (#9764) * Convert CollectionType, SpecialFolderType to enum * Hide internal enum CollectionType values * Apply suggestions from code review Co-authored-by: Shadowghost * Fix recent change * Update Jellyfin.Data/Attributes/OpenApiIgnoreEnumAttribute.cs Co-authored-by: Patrick Barron --------- Co-authored-by: Shadowghost Co-authored-by: Patrick Barron --- Emby.Dlna/ContentDirectory/ControlHandler.cs | 34 ++--- .../Images/CollectionFolderImageProvider.cs | 60 ++++---- .../Images/DynamicImageProvider.cs | 6 +- .../Library/LibraryManager.cs | 69 +++++---- .../Library/Resolvers/Audio/AudioResolver.cs | 14 +- .../Library/Resolvers/Audio/MusicAlbumResolver.cs | 3 +- .../Library/Resolvers/Audio/MusicArtistResolver.cs | 3 +- .../Library/Resolvers/Books/BookResolver.cs | 3 +- .../Library/Resolvers/Movies/MovieResolver.cs | 62 ++++---- .../Library/Resolvers/PhotoAlbumResolver.cs | 5 +- .../Library/Resolvers/PhotoResolver.cs | 5 +- .../Library/Resolvers/PlaylistResolver.cs | 7 +- .../Library/Resolvers/SpecialFolderResolver.cs | 6 +- .../Library/Resolvers/TV/EpisodeResolver.cs | 7 +- .../Library/Resolvers/TV/SeriesResolver.cs | 7 +- .../Library/UserViewManager.cs | 35 +++-- .../Playlists/PlaylistsFolder.cs | 2 +- Jellyfin.Api/Controllers/GenresController.cs | 4 +- Jellyfin.Api/Controllers/ItemUpdateController.cs | 9 +- Jellyfin.Api/Controllers/ItemsController.cs | 4 +- Jellyfin.Api/Controllers/LibraryController.cs | 4 +- Jellyfin.Api/Controllers/UserViewsController.cs | 3 +- .../Attributes/OpenApiIgnoreEnumAttribute.cs | 11 ++ Jellyfin.Data/Enums/CollectionType.cs | 164 +++++++++++++++++++++ .../Extensions/ApiServiceCollectionExtensions.cs | 1 + Jellyfin.Server/Filters/IgnoreEnumSchemaFilter.cs | 42 ++++++ MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- .../Entities/BasePluginFolder.cs | 3 +- .../Entities/CollectionFolder.cs | 3 +- .../Entities/ICollectionFolder.cs | 3 +- .../Entities/InternalItemsQuery.cs | 4 +- MediaBrowser.Controller/Entities/UserView.cs | 37 ++--- .../Entities/UserViewBuilder.cs | 78 +++++----- MediaBrowser.Controller/Library/ILibraryManager.cs | 20 +-- .../Library/IUserViewManager.cs | 3 +- MediaBrowser.Controller/Library/ItemResolveArgs.cs | 7 +- MediaBrowser.Controller/Resolvers/IItemResolver.cs | 3 +- MediaBrowser.Model/Dto/BaseItemDto.cs | 2 +- MediaBrowser.Model/Dto/MetadataEditorInfo.cs | 3 +- MediaBrowser.Model/Entities/CollectionType.cs | 27 ---- MediaBrowser.Model/Library/UserViewQuery.cs | 5 +- .../Library/AudioResolverTests.cs | 3 +- .../Library/EpisodeResolverTest.cs | 1 + 43 files changed, 486 insertions(+), 288 deletions(-) create mode 100644 Jellyfin.Data/Attributes/OpenApiIgnoreEnumAttribute.cs create mode 100644 Jellyfin.Data/Enums/CollectionType.cs create mode 100644 Jellyfin.Server/Filters/IgnoreEnumSchemaFilter.cs delete mode 100644 MediaBrowser.Model/Entities/CollectionType.cs (limited to 'Emby.Server.Implementations/Library') diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index e685d252e..7d53263a6 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -565,30 +565,18 @@ namespace Emby.Dlna.ContentDirectory if (stubType != StubType.Folder && item is IHasCollectionType collectionFolder) { - var collectionType = collectionFolder.CollectionType; - if (string.Equals(CollectionType.Music, collectionType, StringComparison.OrdinalIgnoreCase)) + switch (collectionFolder.CollectionType) { - return GetMusicFolders(item, user, stubType, sort, startIndex, limit); - } - - if (string.Equals(CollectionType.Movies, collectionType, StringComparison.OrdinalIgnoreCase)) - { - return GetMovieFolders(item, user, stubType, sort, startIndex, limit); - } - - if (string.Equals(CollectionType.TvShows, collectionType, StringComparison.OrdinalIgnoreCase)) - { - return GetTvFolders(item, user, stubType, sort, startIndex, limit); - } - - if (string.Equals(CollectionType.Folders, collectionType, StringComparison.OrdinalIgnoreCase)) - { - return GetFolders(user, startIndex, limit); - } - - if (string.Equals(CollectionType.LiveTv, collectionType, StringComparison.OrdinalIgnoreCase)) - { - return GetLiveTvChannels(user, sort, startIndex, limit); + case CollectionType.Music: + return GetMusicFolders(item, user, stubType, sort, startIndex, limit); + case CollectionType.Movies: + return GetMovieFolders(item, user, stubType, sort, startIndex, limit); + case CollectionType.TvShows: + return GetTvFolders(item, user, stubType, sort, startIndex, limit); + case CollectionType.Folders: + return GetFolders(user, startIndex, limit); + case CollectionType.LiveTv: + return GetLiveTvChannels(user, sort, startIndex, limit); } } diff --git a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs index 8a0e627b9..6e8f77977 100644 --- a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs @@ -30,47 +30,43 @@ namespace Emby.Server.Implementations.Images BaseItemKind[] includeItemTypes; - if (string.Equals(viewType, CollectionType.Movies, StringComparison.Ordinal)) + switch (viewType) { - includeItemTypes = new[] { BaseItemKind.Movie }; - } - else if (string.Equals(viewType, CollectionType.TvShows, StringComparison.Ordinal)) - { - includeItemTypes = new[] { BaseItemKind.Series }; - } - else if (string.Equals(viewType, CollectionType.Music, StringComparison.Ordinal)) - { - includeItemTypes = new[] { BaseItemKind.MusicAlbum }; - } - else if (string.Equals(viewType, CollectionType.MusicVideos, StringComparison.Ordinal)) - { - includeItemTypes = new[] { BaseItemKind.MusicVideo }; - } - else if (string.Equals(viewType, CollectionType.Books, StringComparison.Ordinal)) - { - includeItemTypes = new[] { BaseItemKind.Book, BaseItemKind.AudioBook }; - } - else if (string.Equals(viewType, CollectionType.BoxSets, StringComparison.Ordinal)) - { - includeItemTypes = new[] { BaseItemKind.BoxSet }; - } - else if (string.Equals(viewType, CollectionType.HomeVideos, StringComparison.Ordinal) || string.Equals(viewType, CollectionType.Photos, StringComparison.Ordinal)) - { - includeItemTypes = new[] { BaseItemKind.Video, BaseItemKind.Photo }; - } - else - { - includeItemTypes = new[] { BaseItemKind.Video, BaseItemKind.Audio, BaseItemKind.Photo, BaseItemKind.Movie, BaseItemKind.Series }; + case CollectionType.Movies: + includeItemTypes = new[] { BaseItemKind.Movie }; + break; + case CollectionType.TvShows: + includeItemTypes = new[] { BaseItemKind.Series }; + break; + case CollectionType.Music: + includeItemTypes = new[] { BaseItemKind.MusicAlbum }; + break; + case CollectionType.MusicVideos: + includeItemTypes = new[] { BaseItemKind.MusicVideo }; + break; + case CollectionType.Books: + includeItemTypes = new[] { BaseItemKind.Book, BaseItemKind.AudioBook }; + break; + case CollectionType.BoxSets: + includeItemTypes = new[] { BaseItemKind.BoxSet }; + break; + case CollectionType.HomeVideos: + case CollectionType.Photos: + includeItemTypes = new[] { BaseItemKind.Video, BaseItemKind.Photo }; + break; + default: + includeItemTypes = new[] { BaseItemKind.Video, BaseItemKind.Audio, BaseItemKind.Photo, BaseItemKind.Movie, BaseItemKind.Series }; + break; } - var recursive = !string.Equals(CollectionType.Playlists, viewType, StringComparison.OrdinalIgnoreCase); + var recursive = viewType != CollectionType.Playlists; return view.GetItemList(new InternalItemsQuery { CollapseBoxSetItems = false, Recursive = recursive, DtoOptions = new DtoOptions(false), - ImageTypes = new ImageType[] { ImageType.Primary }, + ImageTypes = new[] { ImageType.Primary }, Limit = 8, OrderBy = new[] { diff --git a/Emby.Server.Implementations/Images/DynamicImageProvider.cs b/Emby.Server.Implementations/Images/DynamicImageProvider.cs index 0bd5fdce0..5de53df73 100644 --- a/Emby.Server.Implementations/Images/DynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/DynamicImageProvider.cs @@ -36,7 +36,7 @@ namespace Emby.Server.Implementations.Images var view = (UserView)item; var isUsingCollectionStrip = IsUsingCollectionStrip(view); - var recursive = isUsingCollectionStrip && !new[] { CollectionType.BoxSets, CollectionType.Playlists }.Contains(view.ViewType ?? string.Empty, StringComparison.OrdinalIgnoreCase); + var recursive = isUsingCollectionStrip && view?.ViewType is not null && view.ViewType != CollectionType.BoxSets && view.ViewType != CollectionType.Playlists; var result = view.GetItemList(new InternalItemsQuery { @@ -112,14 +112,14 @@ namespace Emby.Server.Implementations.Images private static bool IsUsingCollectionStrip(UserView view) { - string[] collectionStripViewTypes = + CollectionType[] collectionStripViewTypes = { CollectionType.Movies, CollectionType.TvShows, CollectionType.Playlists }; - return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty); + return view?.ViewType is not null && collectionStripViewTypes.Contains(view.ViewType.Value); } protected override string CreateImage(BaseItem item, IReadOnlyCollection itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 5c76e77be..f40177fa7 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -525,14 +525,14 @@ namespace Emby.Server.Implementations.Library IDirectoryService directoryService, IItemResolver[] resolvers, Folder parent = null, - string collectionType = null, + CollectionType? collectionType = null, LibraryOptions libraryOptions = null) { ArgumentNullException.ThrowIfNull(fileInfo); var fullPath = fileInfo.FullName; - if (string.IsNullOrEmpty(collectionType) && parent is not null) + if (collectionType is null && parent is not null) { collectionType = GetContentTypeOverride(fullPath, true); } @@ -635,7 +635,7 @@ namespace Emby.Server.Implementations.Library return !args.ContainsFileSystemEntryByName(".ignore"); } - public IEnumerable ResolvePaths(IEnumerable files, IDirectoryService directoryService, Folder parent, LibraryOptions libraryOptions, string collectionType = null) + public IEnumerable ResolvePaths(IEnumerable files, IDirectoryService directoryService, Folder parent, LibraryOptions libraryOptions, CollectionType? collectionType = null) { return ResolvePaths(files, directoryService, parent, libraryOptions, collectionType, EntityResolvers); } @@ -645,7 +645,7 @@ namespace Emby.Server.Implementations.Library IDirectoryService directoryService, Folder parent, LibraryOptions libraryOptions, - string collectionType, + CollectionType? collectionType, IItemResolver[] resolvers) { var fileList = files.Where(i => !IgnoreFile(i, parent)).ToList(); @@ -675,7 +675,7 @@ namespace Emby.Server.Implementations.Library IReadOnlyList fileList, IDirectoryService directoryService, Folder parent, - string collectionType, + CollectionType? collectionType, IItemResolver[] resolvers, LibraryOptions libraryOptions) { @@ -1514,7 +1514,7 @@ namespace Emby.Server.Implementations.Library { if (item is UserView view) { - if (string.Equals(view.ViewType, CollectionType.LiveTv, StringComparison.Ordinal)) + if (view.ViewType == CollectionType.LiveTv) { return new[] { view.Id }; } @@ -1543,13 +1543,13 @@ namespace Emby.Server.Implementations.Library } // Handle grouping - if (user is not null && !string.IsNullOrEmpty(view.ViewType) && UserView.IsEligibleForGrouping(view.ViewType) + if (user is not null && view.ViewType != CollectionType.Unknown && UserView.IsEligibleForGrouping(view.ViewType) && user.GetPreference(PreferenceKind.GroupedFolders).Length > 0) { return GetUserRootFolder() .GetChildren(user, true) .OfType() - .Where(i => string.IsNullOrEmpty(i.CollectionType) || string.Equals(i.CollectionType, view.ViewType, StringComparison.OrdinalIgnoreCase)) + .Where(i => i.CollectionType is null || i.CollectionType == view.ViewType) .Where(i => user.IsFolderGrouped(i.Id)) .SelectMany(i => GetTopParentIdsForQuery(i, user)); } @@ -2065,16 +2065,16 @@ namespace Emby.Server.Implementations.Library : collectionFolder.GetLibraryOptions(); } - public string GetContentType(BaseItem item) + public CollectionType? GetContentType(BaseItem item) { - string configuredContentType = GetConfiguredContentType(item, false); - if (!string.IsNullOrEmpty(configuredContentType)) + var configuredContentType = GetConfiguredContentType(item, false); + if (configuredContentType is not null) { return configuredContentType; } configuredContentType = GetConfiguredContentType(item, true); - if (!string.IsNullOrEmpty(configuredContentType)) + if (configuredContentType is not null) { return configuredContentType; } @@ -2082,31 +2082,31 @@ namespace Emby.Server.Implementations.Library return GetInheritedContentType(item); } - public string GetInheritedContentType(BaseItem item) + public CollectionType? GetInheritedContentType(BaseItem item) { var type = GetTopFolderContentType(item); - if (!string.IsNullOrEmpty(type)) + if (type is not null) { return type; } return item.GetParents() .Select(GetConfiguredContentType) - .LastOrDefault(i => !string.IsNullOrEmpty(i)); + .LastOrDefault(i => i is not null); } - public string GetConfiguredContentType(BaseItem item) + public CollectionType? GetConfiguredContentType(BaseItem item) { return GetConfiguredContentType(item, false); } - public string GetConfiguredContentType(string path) + public CollectionType? GetConfiguredContentType(string path) { return GetContentTypeOverride(path, false); } - public string GetConfiguredContentType(BaseItem item, bool inheritConfiguredPath) + public CollectionType? GetConfiguredContentType(BaseItem item, bool inheritConfiguredPath) { if (item is ICollectionFolder collectionFolder) { @@ -2116,16 +2116,21 @@ namespace Emby.Server.Implementations.Library return GetContentTypeOverride(item.ContainingFolderPath, inheritConfiguredPath); } - private string GetContentTypeOverride(string path, bool inherit) + private CollectionType? GetContentTypeOverride(string path, bool inherit) { var nameValuePair = _configurationManager.Configuration.ContentTypes .FirstOrDefault(i => _fileSystem.AreEqual(i.Name, path) || (inherit && !string.IsNullOrEmpty(i.Name) && _fileSystem.ContainsSubPath(i.Name, path))); - return nameValuePair?.Value; + if (Enum.TryParse(nameValuePair?.Value, out var collectionType)) + { + return collectionType; + } + + return null; } - private string GetTopFolderContentType(BaseItem item) + private CollectionType? GetTopFolderContentType(BaseItem item) { if (item is null) { @@ -2147,13 +2152,13 @@ namespace Emby.Server.Implementations.Library .OfType() .Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path)) .Select(i => i.CollectionType) - .FirstOrDefault(i => !string.IsNullOrEmpty(i)); + .FirstOrDefault(i => i is not null); } public UserView GetNamedView( User user, string name, - string viewType, + CollectionType? viewType, string sortName) { return GetNamedView(user, name, Guid.Empty, viewType, sortName); @@ -2161,13 +2166,13 @@ namespace Emby.Server.Implementations.Library public UserView GetNamedView( string name, - string viewType, + CollectionType viewType, string sortName) { var path = Path.Combine( _configurationManager.ApplicationPaths.InternalMetadataPath, "views", - _fileSystem.GetValidFilename(viewType)); + _fileSystem.GetValidFilename(viewType.ToString())); var id = GetNewItemId(path + "_namedview_" + name, typeof(UserView)); @@ -2207,13 +2212,13 @@ namespace Emby.Server.Implementations.Library User user, string name, Guid parentId, - string viewType, + CollectionType? viewType, string sortName) { var parentIdString = parentId.Equals(default) ? null : parentId.ToString("N", CultureInfo.InvariantCulture); - var idValues = "38_namedview_" + name + user.Id.ToString("N", CultureInfo.InvariantCulture) + (parentIdString ?? string.Empty) + (viewType ?? string.Empty); + var idValues = "38_namedview_" + name + user.Id.ToString("N", CultureInfo.InvariantCulture) + (parentIdString ?? string.Empty) + (viewType?.ToString() ?? string.Empty); var id = GetNewItemId(idValues, typeof(UserView)); @@ -2269,7 +2274,7 @@ namespace Emby.Server.Implementations.Library public UserView GetShadowView( BaseItem parent, - string viewType, + CollectionType? viewType, string sortName) { ArgumentNullException.ThrowIfNull(parent); @@ -2277,7 +2282,7 @@ namespace Emby.Server.Implementations.Library var name = parent.Name; var parentId = parent.Id; - var idValues = "38_namedview_" + name + parentId + (viewType ?? string.Empty); + var idValues = "38_namedview_" + name + parentId + (viewType?.ToString() ?? string.Empty); var id = GetNewItemId(idValues, typeof(UserView)); @@ -2334,7 +2339,7 @@ namespace Emby.Server.Implementations.Library public UserView GetNamedView( string name, Guid parentId, - string viewType, + CollectionType? viewType, string sortName, string uniqueId) { @@ -2343,7 +2348,7 @@ namespace Emby.Server.Implementations.Library var parentIdString = parentId.Equals(default) ? null : parentId.ToString("N", CultureInfo.InvariantCulture); - var idValues = "37_namedview_" + name + (parentIdString ?? string.Empty) + (viewType ?? string.Empty); + var idValues = "37_namedview_" + name + (parentIdString ?? string.Empty) + (viewType?.ToString() ?? string.Empty); if (!string.IsNullOrEmpty(uniqueId)) { idValues += uniqueId; @@ -2378,7 +2383,7 @@ namespace Emby.Server.Implementations.Library isNew = true; } - if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase)) + if (viewType != item.ViewType) { item.ViewType = viewType; item.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, CancellationToken.None).GetAwaiter().GetResult(); diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs index 862f144e6..ac423ed09 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs @@ -10,11 +10,11 @@ using Emby.Naming.Audio; using Emby.Naming.AudioBook; using Emby.Naming.Common; using Emby.Naming.Video; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers.Audio @@ -40,7 +40,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio public MultiItemResolverResult ResolveMultiple( Folder parent, List files, - string collectionType, + CollectionType? collectionType, IDirectoryService directoryService) { var result = ResolveMultipleInternal(parent, files, collectionType); @@ -59,9 +59,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio private MultiItemResolverResult ResolveMultipleInternal( Folder parent, List files, - string collectionType) + CollectionType? collectionType) { - if (string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase)) + if (collectionType == CollectionType.Books) { return ResolveMultipleAudio(parent, files, true); } @@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio var collectionType = args.GetCollectionType(); - var isBooksCollectionType = string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase); + var isBooksCollectionType = collectionType == CollectionType.Books; if (args.IsDirectory) { @@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio return null; } - var isMixedCollectionType = string.IsNullOrEmpty(collectionType); + var isMixedCollectionType = collectionType is null; // For conflicting extensions, give priority to videos if (isMixedCollectionType && VideoResolver.IsVideoFile(args.Path, _namingOptions)) @@ -112,7 +112,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio MediaBrowser.Controller.Entities.Audio.Audio item = null; - var isMusicCollectionType = string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase); + var isMusicCollectionType = collectionType == CollectionType.Music; // Use regular audio type for mixed libraries, owned items and music if (isMixedCollectionType || diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index bbc70701c..06e292f4c 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using Emby.Naming.Audio; using Emby.Naming.Common; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; @@ -54,7 +55,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio protected override MusicAlbum Resolve(ItemResolveArgs args) { var collectionType = args.GetCollectionType(); - var isMusicMediaFolder = string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase); + var isMusicMediaFolder = collectionType == CollectionType.Music; // If there's a collection type and it's not music, don't allow it. if (!isMusicMediaFolder) diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs index c858dc53d..7d6f97b12 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs @@ -4,6 +4,7 @@ using System; using System.Linq; using System.Threading.Tasks; using Emby.Naming.Common; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; @@ -64,7 +65,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio var collectionType = args.GetCollectionType(); - var isMusicMediaFolder = string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase); + var isMusicMediaFolder = collectionType == CollectionType.Music; // If there's a collection type and it's not music, it can't be a music artist if (!isMusicMediaFolder) diff --git a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs index 73861ff59..b76bfe427 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; +using Jellyfin.Data.Enums; using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -22,7 +23,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books var collectionType = args.GetCollectionType(); // Only process items that are in a collection folder containing books - if (!string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase)) + if (collectionType != CollectionType.Books) { return null; } diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 0b65bf921..50fd8b877 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Text.RegularExpressions; using Emby.Naming.Common; using Emby.Naming.Video; +using Jellyfin.Data.Enums; using Jellyfin.Extensions; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; @@ -28,13 +29,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies { private readonly IImageProcessor _imageProcessor; - private string[] _validCollectionTypes = new[] + private static readonly CollectionType[] _validCollectionTypes = new[] { - CollectionType.Movies, - CollectionType.HomeVideos, - CollectionType.MusicVideos, - CollectionType.TvShows, - CollectionType.Photos + CollectionType.Movies, + CollectionType.HomeVideos, + CollectionType.MusicVideos, + CollectionType.TvShows, + CollectionType.Photos }; /// @@ -63,7 +64,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies public MultiItemResolverResult ResolveMultiple( Folder parent, List files, - string collectionType, + CollectionType? collectionType, IDirectoryService directoryService) { var result = ResolveMultipleInternal(parent, files, collectionType); @@ -99,17 +100,17 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies Video movie = null; var files = args.GetActualFileSystemChildren().ToList(); - if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) + if (collectionType == CollectionType.MusicVideos) { movie = FindMovie(args, args.Path, args.Parent, files, DirectoryService, collectionType, false); } - if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)) + if (collectionType == CollectionType.HomeVideos) { movie = FindMovie /// Movie. - private T FindMovie(ItemResolveArgs args, string path, Folder parent, List fileSystemEntries, IDirectoryService directoryService, string collectionType, bool parseName) + private T FindMovie(ItemResolveArgs args, string path, Folder parent, List fileSystemEntries, IDirectoryService directoryService, CollectionType? collectionType, bool parseName) where T : Video, new() { var multiDiscFolders = new List(); var libraryOptions = args.LibraryOptions; - var supportPhotos = string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && libraryOptions.EnablePhotos; + var supportPhotos = collectionType == CollectionType.HomeVideos && libraryOptions.EnablePhotos; var photos = new List(); // Search for a folder rip @@ -460,8 +459,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies var result = ResolveVideos(parent, fileSystemEntries, SupportsMultiVersion, collectionType, parseName) ?? new MultiItemResolverResult(); - var isPhotosCollection = string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) - || string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase); + var isPhotosCollection = collectionType == CollectionType.HomeVideos || collectionType == CollectionType.Photos; if (!isPhotosCollection && result.Items.Count == 1) { var videoPath = result.Items[0].Path; @@ -562,7 +560,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return returnVideo; } - private bool IsInvalid(Folder parent, ReadOnlySpan collectionType) + private bool IsInvalid(Folder parent, CollectionType? collectionType) { if (parent is not null) { @@ -572,12 +570,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies } } - if (collectionType.IsEmpty) + if (collectionType is null) { return false; } - return !_validCollectionTypes.Contains(collectionType, StringComparison.OrdinalIgnoreCase); + return !_validCollectionTypes.Contains(collectionType.Value); } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs index 7dd0ab185..29d540700 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs @@ -2,6 +2,7 @@ using System; using Emby.Naming.Common; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -45,8 +46,8 @@ namespace Emby.Server.Implementations.Library.Resolvers // Must be an image file within a photo collection var collectionType = args.GetCollectionType(); - if (string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase) - || (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && args.LibraryOptions.EnablePhotos)) + if (collectionType == CollectionType.Photos + || (collectionType == CollectionType.HomeVideos && args.LibraryOptions.EnablePhotos)) { if (HasPhotos(args)) { diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index c860391fc..d166ac37f 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using Emby.Naming.Common; using Emby.Naming.Video; +using Jellyfin.Data.Enums; using Jellyfin.Extensions; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; @@ -60,8 +61,8 @@ namespace Emby.Server.Implementations.Library.Resolvers // Must be an image file within a photo collection var collectionType = args.CollectionType; - if (string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase) - || (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && args.LibraryOptions.EnablePhotos)) + if (collectionType == CollectionType.Photos + || (collectionType == CollectionType.HomeVideos && args.LibraryOptions.EnablePhotos)) { if (IsImageFile(args.Path, _imageProcessor)) { diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs index 5d569009d..d4b3722c9 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; +using Jellyfin.Data.Enums; using Jellyfin.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Playlists; @@ -19,9 +20,9 @@ namespace Emby.Server.Implementations.Library.Resolvers /// public class PlaylistResolver : GenericFolderResolver { - private string[] _musicPlaylistCollectionTypes = + private CollectionType?[] _musicPlaylistCollectionTypes = { - string.Empty, + null, CollectionType.Music }; @@ -62,7 +63,7 @@ namespace Emby.Server.Implementations.Library.Resolvers // Check if this is a music playlist file // It should have the correct collection type and a supported file extension - else if (_musicPlaylistCollectionTypes.Contains(args.CollectionType ?? string.Empty, StringComparison.OrdinalIgnoreCase)) + else if (_musicPlaylistCollectionTypes.Contains(args.CollectionType)) { var extension = Path.GetExtension(args.Path.AsSpan()); if (Playlist.SupportedExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)) diff --git a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs index 6bb999641..3d91ed242 100644 --- a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; +using Jellyfin.Data.Enums; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -62,7 +63,7 @@ namespace Emby.Server.Implementations.Library.Resolvers return null; } - private string GetCollectionType(ItemResolveArgs args) + private CollectionType? GetCollectionType(ItemResolveArgs args) { return args.FileSystemChildren .Where(i => @@ -78,7 +79,8 @@ namespace Emby.Server.Implementations.Library.Resolvers } }) .Select(i => _fileSystem.GetFileNameWithoutExtension(i)) - .FirstOrDefault(); + .Select(i => Enum.TryParse(i, out var collectionType) ? collectionType : (CollectionType?)null) + .FirstOrDefault(i => i is not null); } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index 392ee4c77..8274881be 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -3,6 +3,7 @@ using System; using System.Linq; using Emby.Naming.Common; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; @@ -48,9 +49,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV // If the parent is a Season or Series and the parent is not an extras folder, then this is an Episode if the VideoResolver returns something // Also handle flat tv folders - if (season is not null || - string.Equals(args.GetCollectionType(), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || - args.HasParent()) + if (season is not null + || args.GetCollectionType() == CollectionType.TvShows + || args.HasParent()) { var episode = ResolveVideo(args, false); diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index d4f275bed..2ae1138a5 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -8,6 +8,7 @@ using System.IO; using Emby.Naming.Common; using Emby.Naming.TV; using Emby.Naming.Video; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; @@ -59,11 +60,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV var seriesInfo = Naming.TV.SeriesResolver.Resolve(_namingOptions, args.Path); var collectionType = args.GetCollectionType(); - if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) + if (collectionType == CollectionType.TvShows) { // TODO refactor into separate class or something, this is copied from LibraryManager.GetConfiguredContentType var configuredContentType = args.GetConfiguredContentType(); - if (!string.Equals(configuredContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) + if (configuredContentType != CollectionType.TvShows) { return new Series { @@ -72,7 +73,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV }; } } - else if (string.IsNullOrEmpty(collectionType)) + else if (collectionType is null) { if (args.ContainsFileSystemEntryByName("tvshow.nfo")) { diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs index 2c3dc1857..df5610996 100644 --- a/Emby.Server.Implementations/Library/UserViewManager.cs +++ b/Emby.Server.Implementations/Library/UserViewManager.cs @@ -8,7 +8,6 @@ using System.Linq; using System.Threading; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; -using Jellyfin.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; @@ -64,8 +63,8 @@ namespace Emby.Server.Implementations.Library var collectionFolder = folder as ICollectionFolder; var folderViewType = collectionFolder?.CollectionType; - // Playlist library requires special handling because the folder only refrences user playlists - if (string.Equals(folderViewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase)) + // Playlist library requires special handling because the folder only references user playlists + if (folderViewType == CollectionType.Playlists) { var items = folder.GetItemList(new InternalItemsQuery(user) { @@ -90,7 +89,7 @@ namespace Emby.Server.Implementations.Library continue; } - if (query.PresetViews.Contains(folderViewType ?? string.Empty, StringComparison.OrdinalIgnoreCase)) + if (query.PresetViews.Contains(folderViewType)) { list.Add(GetUserView(folder, folderViewType, string.Empty)); } @@ -102,14 +101,14 @@ namespace Emby.Server.Implementations.Library foreach (var viewType in new[] { CollectionType.Movies, CollectionType.TvShows }) { - var parents = groupedFolders.Where(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase) || string.IsNullOrEmpty(i.CollectionType)) + var parents = groupedFolders.Where(i => i.CollectionType == viewType || i.CollectionType is null) .ToList(); if (parents.Count > 0) { - var localizationKey = string.Equals(viewType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) ? - "TvShows" : - "Movies"; + var localizationKey = viewType == CollectionType.TvShows + ? "TvShows" + : "Movies"; list.Add(GetUserView(parents, viewType, localizationKey, string.Empty, user, query.PresetViews)); } @@ -164,14 +163,14 @@ namespace Emby.Server.Implementations.Library .ToArray(); } - public UserView GetUserSubViewWithName(string name, Guid parentId, string type, string sortName) + public UserView GetUserSubViewWithName(string name, Guid parentId, CollectionType? type, string sortName) { var uniqueId = parentId + "subview" + type; return _libraryManager.GetNamedView(name, parentId, type, sortName, uniqueId); } - public UserView GetUserSubView(Guid parentId, string type, string localizationKey, string sortName) + public UserView GetUserSubView(Guid parentId, CollectionType? type, string localizationKey, string sortName) { var name = _localizationManager.GetLocalizedString(localizationKey); @@ -180,15 +179,15 @@ namespace Emby.Server.Implementations.Library private Folder GetUserView( List parents, - string viewType, + CollectionType? viewType, string localizationKey, string sortName, User user, - string[] presetViews) + CollectionType?[] presetViews) { - if (parents.Count == 1 && parents.All(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase))) + if (parents.Count == 1 && parents.All(i => i.CollectionType == viewType)) { - if (!presetViews.Contains(viewType, StringComparison.OrdinalIgnoreCase)) + if (!presetViews.Contains(viewType)) { return (Folder)parents[0]; } @@ -200,7 +199,7 @@ namespace Emby.Server.Implementations.Library return _libraryManager.GetNamedView(user, name, viewType, sortName); } - public UserView GetUserView(Folder parent, string viewType, string sortName) + public UserView GetUserView(Folder parent, CollectionType? viewType, string sortName) { return _libraryManager.GetShadowView(parent, viewType, sortName); } @@ -280,7 +279,7 @@ namespace Emby.Server.Implementations.Library var isPlayed = request.IsPlayed; - if (parents.OfType().Any(i => string.Equals(i.CollectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))) + if (parents.OfType().Any(i => i.CollectionType == CollectionType.Music)) { isPlayed = null; } @@ -306,11 +305,11 @@ namespace Emby.Server.Implementations.Library var hasCollectionType = parents.OfType().ToArray(); if (hasCollectionType.Length > 0) { - if (hasCollectionType.All(i => string.Equals(i.CollectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))) + if (hasCollectionType.All(i => i.CollectionType == CollectionType.Movies)) { includeItemTypes = new[] { BaseItemKind.Movie }; } - else if (hasCollectionType.All(i => string.Equals(i.CollectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))) + else if (hasCollectionType.All(i => i.CollectionType == CollectionType.TvShows)) { includeItemTypes = new[] { BaseItemKind.Episode }; } diff --git a/Emby.Server.Implementations/Playlists/PlaylistsFolder.cs b/Emby.Server.Implementations/Playlists/PlaylistsFolder.cs index d67caa52d..5c616d534 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistsFolder.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistsFolder.cs @@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Playlists public override bool SupportsInheritedParentImages => false; [JsonIgnore] - public override string CollectionType => MediaBrowser.Model.Entities.CollectionType.Playlists; + public override CollectionType? CollectionType => Jellyfin.Data.Enums.CollectionType.Playlists; protected override IEnumerable GetEligibleChildrenForRecursiveChildren(User user) { diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs index 51f04fa27..062e1062d 100644 --- a/Jellyfin.Api/Controllers/GenresController.cs +++ b/Jellyfin.Api/Controllers/GenresController.cs @@ -131,8 +131,8 @@ public class GenresController : BaseJellyfinApiController QueryResult<(BaseItem, ItemCounts)> result; if (parentItem is ICollectionFolder parentCollectionFolder - && (string.Equals(parentCollectionFolder.CollectionType, CollectionType.Music, StringComparison.Ordinal) - || string.Equals(parentCollectionFolder.CollectionType, CollectionType.MusicVideos, StringComparison.Ordinal))) + && (parentCollectionFolder.CollectionType == CollectionType.Music + || parentCollectionFolder.CollectionType == CollectionType.MusicVideos)) { result = _libraryManager.GetMusicGenres(query); } diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs index 504f2fa1d..3be891b93 100644 --- a/Jellyfin.Api/Controllers/ItemUpdateController.cs +++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Constants; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -164,18 +165,16 @@ public class ItemUpdateController : BaseJellyfinApiController var inheritedContentType = _libraryManager.GetInheritedContentType(item); var configuredContentType = _libraryManager.GetConfiguredContentType(item); - if (string.IsNullOrWhiteSpace(inheritedContentType) || - !string.IsNullOrWhiteSpace(configuredContentType)) + if (inheritedContentType is null || configuredContentType is not null) { info.ContentTypeOptions = GetContentTypeOptions(true).ToArray(); info.ContentType = configuredContentType; - if (string.IsNullOrWhiteSpace(inheritedContentType) - || string.Equals(inheritedContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) + if (inheritedContentType is null || inheritedContentType == CollectionType.TvShows) { info.ContentTypeOptions = info.ContentTypeOptions .Where(i => string.IsNullOrWhiteSpace(i.Value) - || string.Equals(i.Value, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) + || string.Equals(i.Value, "TvShows", StringComparison.OrdinalIgnoreCase)) .ToArray(); } } diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 891cf88a7..3920d6599 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -269,13 +269,13 @@ public class ItemsController : BaseJellyfinApiController folder = _libraryManager.GetUserRootFolder(); } - string? collectionType = null; + CollectionType? collectionType = null; if (folder is IHasCollectionType hasCollectionType) { collectionType = hasCollectionType.CollectionType; } - if (string.Equals(collectionType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase)) + if (collectionType == CollectionType.Playlists) { recursive = true; includeItemTypes = new[] { BaseItemKind.Playlist }; diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 21941ff94..3cd78b086 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -788,7 +788,7 @@ public class LibraryController : BaseJellyfinApiController [Authorize(Policy = Policies.FirstTimeSetupOrDefault)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetLibraryOptionsInfo( - [FromQuery] string? libraryContentType, + [FromQuery] CollectionType? libraryContentType, [FromQuery] bool isNewLibrary = false) { var result = new LibraryOptionsResultDto(); @@ -922,7 +922,7 @@ public class LibraryController : BaseJellyfinApiController } } - private static string[] GetRepresentativeItemTypes(string? contentType) + private static string[] GetRepresentativeItemTypes(CollectionType? contentType) { return contentType switch { diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs index 838b43234..0ffa3ab1a 100644 --- a/Jellyfin.Api/Controllers/UserViewsController.cs +++ b/Jellyfin.Api/Controllers/UserViewsController.cs @@ -6,6 +6,7 @@ using System.Linq; using Jellyfin.Api.Extensions; using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.UserViewDtos; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -63,7 +64,7 @@ public class UserViewsController : BaseJellyfinApiController public QueryResult GetUserViews( [FromRoute, Required] Guid userId, [FromQuery] bool? includeExternalContent, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] presetViews, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] CollectionType?[] presetViews, [FromQuery] bool includeHidden = false) { var query = new UserViewQuery diff --git a/Jellyfin.Data/Attributes/OpenApiIgnoreEnumAttribute.cs b/Jellyfin.Data/Attributes/OpenApiIgnoreEnumAttribute.cs new file mode 100644 index 000000000..ff613d9f8 --- /dev/null +++ b/Jellyfin.Data/Attributes/OpenApiIgnoreEnumAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace Jellyfin.Data.Attributes; + +/// +/// Attribute to specify that the enum value is to be ignored when generating the openapi spec. +/// +[AttributeUsage(AttributeTargets.Field)] +public sealed class OpenApiIgnoreEnumAttribute : Attribute +{ +} diff --git a/Jellyfin.Data/Enums/CollectionType.cs b/Jellyfin.Data/Enums/CollectionType.cs new file mode 100644 index 000000000..e2044a0bc --- /dev/null +++ b/Jellyfin.Data/Enums/CollectionType.cs @@ -0,0 +1,164 @@ +using Jellyfin.Data.Attributes; + +namespace Jellyfin.Data.Enums; + +/// +/// Collection type. +/// +public enum CollectionType +{ + /// + /// Unknown collection. + /// + Unknown = 0, + + /// + /// Movies collection. + /// + Movies = 1, + + /// + /// Tv shows collection. + /// + TvShows = 2, + + /// + /// Music collection. + /// + Music = 3, + + /// + /// Music videos collection. + /// + MusicVideos = 4, + + /// + /// Trailers collection. + /// + Trailers = 5, + + /// + /// Home videos collection. + /// + HomeVideos = 6, + + /// + /// Box sets collection. + /// + BoxSets = 7, + + /// + /// Books collection. + /// + Books = 8, + + /// + /// Photos collection. + /// + Photos = 9, + + /// + /// Live tv collection. + /// + LiveTv = 10, + + /// + /// Playlists collection. + /// + Playlists = 11, + + /// + /// Folders collection. + /// + Folders = 12, + + /// + /// Tv show series collection. + /// + [OpenApiIgnoreEnum] + TvShowSeries = 101, + + /// + /// Tv genres collection. + /// + [OpenApiIgnoreEnum] + TvGenres = 102, + + /// + /// Tv genre collection. + /// + [OpenApiIgnoreEnum] + TvGenre = 103, + + /// + /// Tv latest collection. + /// + [OpenApiIgnoreEnum] + TvLatest = 104, + + /// + /// Tv next up collection. + /// + [OpenApiIgnoreEnum] + TvNextUp = 105, + + /// + /// Tv resume collection. + /// + [OpenApiIgnoreEnum] + TvResume = 106, + + /// + /// Tv favorite series collection. + /// + [OpenApiIgnoreEnum] + TvFavoriteSeries = 107, + + /// + /// Tv favorite episodes collection. + /// + [OpenApiIgnoreEnum] + TvFavoriteEpisodes = 108, + + /// + /// Latest movies collection. + /// + [OpenApiIgnoreEnum] + MovieLatest = 109, + + /// + /// Movies to resume collection. + /// + [OpenApiIgnoreEnum] + MovieResume = 110, + + /// + /// Movie movie collection. + /// + [OpenApiIgnoreEnum] + MovieMovies = 111, + + /// + /// Movie collections collection. + /// + [OpenApiIgnoreEnum] + MovieCollections = 112, + + /// + /// Movie favorites collection. + /// + [OpenApiIgnoreEnum] + MovieFavorites = 113, + + /// + /// Movie genres collection. + /// + [OpenApiIgnoreEnum] + MovieGenres = 114, + + /// + /// Movie genre collection. + /// + [OpenApiIgnoreEnum] + MovieGenre = 115 +} diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index b7e71a81d..16b58808f 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -246,6 +246,7 @@ namespace Jellyfin.Server.Extensions // TODO - remove when all types are supported in System.Text.Json c.AddSwaggerTypeMappings(); + c.SchemaFilter(); c.OperationFilter(); c.OperationFilter(); c.OperationFilter(); diff --git a/Jellyfin.Server/Filters/IgnoreEnumSchemaFilter.cs b/Jellyfin.Server/Filters/IgnoreEnumSchemaFilter.cs new file mode 100644 index 000000000..eb9ad03c2 --- /dev/null +++ b/Jellyfin.Server/Filters/IgnoreEnumSchemaFilter.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Jellyfin.Data.Attributes; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace Jellyfin.Server.Filters; + +/// +/// Filter to remove ignored enum values. +/// +public class IgnoreEnumSchemaFilter : ISchemaFilter +{ + /// + public void Apply(OpenApiSchema schema, SchemaFilterContext context) + { + if (context.Type.IsEnum || (Nullable.GetUnderlyingType(context.Type)?.IsEnum ?? false)) + { + var type = context.Type.IsEnum ? context.Type : Nullable.GetUnderlyingType(context.Type); + if (type is null) + { + return; + } + + var enumOpenApiStrings = new List(); + + foreach (var enumName in Enum.GetNames(type)) + { + var member = type.GetMember(enumName)[0]; + if (!member.GetCustomAttributes().Any()) + { + enumOpenApiStrings.Add(new OpenApiString(enumName)); + } + } + + schema.Enum = enumOpenApiStrings; + } + } +} diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 9f3e8eec9..87a021d41 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -724,7 +724,7 @@ namespace MediaBrowser.Controller.Entities if (this is IHasCollectionType view) { - if (string.Equals(view.CollectionType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase)) + if (view.CollectionType == CollectionType.LiveTv) { return true; } diff --git a/MediaBrowser.Controller/Entities/BasePluginFolder.cs b/MediaBrowser.Controller/Entities/BasePluginFolder.cs index afafaf1c2..4bf21061c 100644 --- a/MediaBrowser.Controller/Entities/BasePluginFolder.cs +++ b/MediaBrowser.Controller/Entities/BasePluginFolder.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System.Text.Json.Serialization; +using Jellyfin.Data.Enums; namespace MediaBrowser.Controller.Entities { @@ -11,7 +12,7 @@ namespace MediaBrowser.Controller.Entities public abstract class BasePluginFolder : Folder, ICollectionFolder { [JsonIgnore] - public virtual string? CollectionType => null; + public virtual CollectionType? CollectionType => null; [JsonIgnore] public override bool SupportsInheritedParentImages => false; diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index f51162f9d..992bb19bb 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -11,6 +11,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Data.Enums; using Jellyfin.Extensions.Json; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; @@ -69,7 +70,7 @@ namespace MediaBrowser.Controller.Entities [JsonIgnore] public override bool SupportsInheritedParentImages => false; - public string CollectionType { get; set; } + public CollectionType? CollectionType { get; set; } /// /// Gets the item's children. diff --git a/MediaBrowser.Controller/Entities/ICollectionFolder.cs b/MediaBrowser.Controller/Entities/ICollectionFolder.cs index 89e494ebc..742691b00 100644 --- a/MediaBrowser.Controller/Entities/ICollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/ICollectionFolder.cs @@ -3,6 +3,7 @@ #pragma warning disable CA1819, CS1591 using System; +using Jellyfin.Data.Enums; namespace MediaBrowser.Controller.Entities { @@ -27,6 +28,6 @@ namespace MediaBrowser.Controller.Entities public interface IHasCollectionType { - string CollectionType { get; } + CollectionType? CollectionType { get; } } } diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index fb50a4546..c0bba60eb 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Controller.Entities OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); PersonIds = Array.Empty(); PersonTypes = Array.Empty(); - PresetViews = Array.Empty(); + PresetViews = Array.Empty(); SeriesStatuses = Array.Empty(); SourceTypes = Array.Empty(); StudioIds = Array.Empty(); @@ -248,7 +248,7 @@ namespace MediaBrowser.Controller.Entities public Guid[] TopParentIds { get; set; } - public string[] PresetViews { get; set; } + public CollectionType?[] PresetViews { get; set; } public TrailerType[] TrailerTypes { get; set; } diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 47432ee93..1f94cf767 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Text.Json.Serialization; using System.Threading.Tasks; using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; using Jellyfin.Extensions; using MediaBrowser.Controller.TV; using MediaBrowser.Model.Querying; @@ -16,21 +17,21 @@ namespace MediaBrowser.Controller.Entities { public class UserView : Folder, IHasCollectionType { - private static readonly string[] _viewTypesEligibleForGrouping = new string[] + private static readonly CollectionType?[] _viewTypesEligibleForGrouping = { - Model.Entities.CollectionType.Movies, - Model.Entities.CollectionType.TvShows, - string.Empty + Jellyfin.Data.Enums.CollectionType.Movies, + Jellyfin.Data.Enums.CollectionType.TvShows, + null }; - private static readonly string[] _originalFolderViewTypes = new string[] + private static readonly CollectionType?[] _originalFolderViewTypes = { - Model.Entities.CollectionType.Books, - Model.Entities.CollectionType.MusicVideos, - Model.Entities.CollectionType.HomeVideos, - Model.Entities.CollectionType.Photos, - Model.Entities.CollectionType.Music, - Model.Entities.CollectionType.BoxSets + Jellyfin.Data.Enums.CollectionType.Books, + Jellyfin.Data.Enums.CollectionType.MusicVideos, + Jellyfin.Data.Enums.CollectionType.HomeVideos, + Jellyfin.Data.Enums.CollectionType.Photos, + Jellyfin.Data.Enums.CollectionType.Music, + Jellyfin.Data.Enums.CollectionType.BoxSets }; public static ITVSeriesManager TVSeriesManager { get; set; } @@ -38,7 +39,7 @@ namespace MediaBrowser.Controller.Entities /// /// Gets or sets the view type. /// - public string ViewType { get; set; } + public CollectionType? ViewType { get; set; } /// /// Gets or sets the display parent id. @@ -52,7 +53,7 @@ namespace MediaBrowser.Controller.Entities /// [JsonIgnore] - public string CollectionType => ViewType; + public CollectionType? CollectionType => ViewType; /// [JsonIgnore] @@ -160,7 +161,7 @@ namespace MediaBrowser.Controller.Entities return true; } - return string.Equals(Model.Entities.CollectionType.Playlists, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase); + return collectionFolder.CollectionType == Jellyfin.Data.Enums.CollectionType.Playlists; } public static bool IsEligibleForGrouping(Folder folder) @@ -169,14 +170,14 @@ namespace MediaBrowser.Controller.Entities && IsEligibleForGrouping(collectionFolder.CollectionType); } - public static bool IsEligibleForGrouping(string viewType) + public static bool IsEligibleForGrouping(CollectionType? viewType) { - return _viewTypesEligibleForGrouping.Contains(viewType ?? string.Empty, StringComparison.OrdinalIgnoreCase); + return _viewTypesEligibleForGrouping.Contains(viewType); } - public static bool EnableOriginalFolder(string viewType) + public static bool EnableOriginalFolder(CollectionType? viewType) { - return _originalFolderViewTypes.Contains(viewType ?? string.Empty, StringComparison.OrdinalIgnoreCase); + return _originalFolderViewTypes.Contains(viewType); } protected override Task ValidateChildrenInternal(IProgress progress, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService, System.Threading.CancellationToken cancellationToken) diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index c276ab463..a134735b2 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Controller.Entities _tvSeriesManager = tvSeriesManager; } - public QueryResult GetUserItems(Folder queryParent, Folder displayParent, string viewType, InternalItemsQuery query) + public QueryResult GetUserItems(Folder queryParent, Folder displayParent, CollectionType? viewType, InternalItemsQuery query) { var user = query.User; @@ -67,49 +67,49 @@ namespace MediaBrowser.Controller.Entities case CollectionType.Movies: return GetMovieFolders(queryParent, user, query); - case SpecialFolder.TvShowSeries: + case CollectionType.TvShowSeries: return GetTvSeries(queryParent, user, query); - case SpecialFolder.TvGenres: + case CollectionType.TvGenres: return GetTvGenres(queryParent, user, query); - case SpecialFolder.TvGenre: + case CollectionType.TvGenre: return GetTvGenreItems(queryParent, displayParent, user, query); - case SpecialFolder.TvResume: + case CollectionType.TvResume: return GetTvResume(queryParent, user, query); - case SpecialFolder.TvNextUp: + case CollectionType.TvNextUp: return GetTvNextUp(queryParent, query); - case SpecialFolder.TvLatest: + case CollectionType.TvLatest: return GetTvLatest(queryParent, user, query); - case SpecialFolder.MovieFavorites: + case CollectionType.MovieFavorites: return GetFavoriteMovies(queryParent, user, query); - case SpecialFolder.MovieLatest: + case CollectionType.MovieLatest: return GetMovieLatest(queryParent, user, query); - case SpecialFolder.MovieGenres: + case CollectionType.MovieGenres: return GetMovieGenres(queryParent, user, query); - case SpecialFolder.MovieGenre: + case CollectionType.MovieGenre: return GetMovieGenreItems(queryParent, displayParent, user, query); - case SpecialFolder.MovieResume: + case CollectionType.MovieResume: return GetMovieResume(queryParent, user, query); - case SpecialFolder.MovieMovies: + case CollectionType.MovieMovies: return GetMovieMovies(queryParent, user, query); - case SpecialFolder.MovieCollections: + case CollectionType.MovieCollections: return GetMovieCollections(user, query); - case SpecialFolder.TvFavoriteEpisodes: + case CollectionType.TvFavoriteEpisodes: return GetFavoriteEpisodes(queryParent, user, query); - case SpecialFolder.TvFavoriteSeries: + case CollectionType.TvFavoriteSeries: return GetFavoriteSeries(queryParent, user, query); default: @@ -146,12 +146,12 @@ namespace MediaBrowser.Controller.Entities var list = new List { - GetUserView(SpecialFolder.MovieResume, "HeaderContinueWatching", "0", parent), - GetUserView(SpecialFolder.MovieLatest, "Latest", "1", parent), - GetUserView(SpecialFolder.MovieMovies, "Movies", "2", parent), - GetUserView(SpecialFolder.MovieCollections, "Collections", "3", parent), - GetUserView(SpecialFolder.MovieFavorites, "Favorites", "4", parent), - GetUserView(SpecialFolder.MovieGenres, "Genres", "5", parent) + GetUserView(CollectionType.MovieResume, "HeaderContinueWatching", "0", parent), + GetUserView(CollectionType.MovieLatest, "Latest", "1", parent), + GetUserView(CollectionType.MovieMovies, "Movies", "2", parent), + GetUserView(CollectionType.MovieCollections, "Collections", "3", parent), + GetUserView(CollectionType.MovieFavorites, "Favorites", "4", parent), + GetUserView(CollectionType.MovieGenres, "Genres", "5", parent) }; return GetResult(list, query); @@ -264,7 +264,7 @@ namespace MediaBrowser.Controller.Entities } }) .Where(i => i is not null) - .Select(i => GetUserViewWithName(SpecialFolder.MovieGenre, i.SortName, parent)); + .Select(i => GetUserViewWithName(CollectionType.MovieGenre, i.SortName, parent)); return GetResult(genres, query); } @@ -303,13 +303,13 @@ namespace MediaBrowser.Controller.Entities var list = new List { - GetUserView(SpecialFolder.TvResume, "HeaderContinueWatching", "0", parent), - GetUserView(SpecialFolder.TvNextUp, "HeaderNextUp", "1", parent), - GetUserView(SpecialFolder.TvLatest, "Latest", "2", parent), - GetUserView(SpecialFolder.TvShowSeries, "Shows", "3", parent), - GetUserView(SpecialFolder.TvFavoriteSeries, "HeaderFavoriteShows", "4", parent), - GetUserView(SpecialFolder.TvFavoriteEpisodes, "HeaderFavoriteEpisodes", "5", parent), - GetUserView(SpecialFolder.TvGenres, "Genres", "6", parent) + GetUserView(CollectionType.TvResume, "HeaderContinueWatching", "0", parent), + GetUserView(CollectionType.TvNextUp, "HeaderNextUp", "1", parent), + GetUserView(CollectionType.TvLatest, "Latest", "2", parent), + GetUserView(CollectionType.TvShowSeries, "Shows", "3", parent), + GetUserView(CollectionType.TvFavoriteSeries, "HeaderFavoriteShows", "4", parent), + GetUserView(CollectionType.TvFavoriteEpisodes, "HeaderFavoriteEpisodes", "5", parent), + GetUserView(CollectionType.TvGenres, "Genres", "6", parent) }; return GetResult(list, query); @@ -330,7 +330,7 @@ namespace MediaBrowser.Controller.Entities private QueryResult GetTvNextUp(Folder parent, InternalItemsQuery query) { - var parentFolders = GetMediaFolders(parent, query.User, new[] { CollectionType.TvShows, string.Empty }); + var parentFolders = GetMediaFolders(parent, query.User, new[] { CollectionType.TvShows }); var result = _tvSeriesManager.GetNextUp( new NextUpQuery @@ -392,7 +392,7 @@ namespace MediaBrowser.Controller.Entities } }) .Where(i => i is not null) - .Select(i => GetUserViewWithName(SpecialFolder.TvGenre, i.SortName, parent)); + .Select(i => GetUserViewWithName(CollectionType.TvGenre, i.SortName, parent)); return GetResult(genres, query); } @@ -943,7 +943,7 @@ namespace MediaBrowser.Controller.Entities .Where(i => user.IsFolderGrouped(i.Id) && UserView.IsEligibleForGrouping(i)); } - private BaseItem[] GetMediaFolders(User user, IEnumerable viewTypes) + private BaseItem[] GetMediaFolders(User user, IEnumerable viewTypes) { if (user is null) { @@ -952,7 +952,7 @@ namespace MediaBrowser.Controller.Entities { var folder = i as ICollectionFolder; - return folder is not null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparison.OrdinalIgnoreCase); + return folder?.CollectionType is not null && viewTypes.Contains(folder.CollectionType.Value); }).ToArray(); } @@ -961,11 +961,11 @@ namespace MediaBrowser.Controller.Entities { var folder = i as ICollectionFolder; - return folder is not null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparison.OrdinalIgnoreCase); + return folder?.CollectionType is not null && viewTypes.Contains(folder.CollectionType.Value); }).ToArray(); } - private BaseItem[] GetMediaFolders(Folder parent, User user, IEnumerable viewTypes) + private BaseItem[] GetMediaFolders(Folder parent, User user, IEnumerable viewTypes) { if (parent is null || parent is UserView) { @@ -975,12 +975,12 @@ namespace MediaBrowser.Controller.Entities return new BaseItem[] { parent }; } - private UserView GetUserViewWithName(string type, string sortName, BaseItem parent) + private UserView GetUserViewWithName(CollectionType? type, string sortName, BaseItem parent) { - return _userViewManager.GetUserSubView(parent.Id, parent.Id.ToString("N", CultureInfo.InvariantCulture), type, sortName); + return _userViewManager.GetUserSubView(parent.Id, type, parent.Id.ToString("N", CultureInfo.InvariantCulture), sortName); } - private UserView GetUserView(string type, string localizationKey, string sortName, BaseItem parent) + private UserView GetUserView(CollectionType? type, string localizationKey, string sortName, BaseItem parent) { return _userViewManager.GetUserSubView(parent.Id, type, localizationKey, sortName); } diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 52d546a4f..9ec22324f 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Controller.Library IDirectoryService directoryService, Folder parent, LibraryOptions libraryOptions, - string collectionType = null); + CollectionType? collectionType = null); /// /// Gets a Person. @@ -256,28 +256,28 @@ namespace MediaBrowser.Controller.Library /// /// The item. /// System.String. - string GetContentType(BaseItem item); + CollectionType? GetContentType(BaseItem item); /// /// Gets the type of the inherited content. /// /// The item. /// System.String. - string GetInheritedContentType(BaseItem item); + CollectionType? GetInheritedContentType(BaseItem item); /// /// Gets the type of the configured content. /// /// The item. /// System.String. - string GetConfiguredContentType(BaseItem item); + CollectionType? GetConfiguredContentType(BaseItem item); /// /// Gets the type of the configured content. /// /// The path. /// System.String. - string GetConfiguredContentType(string path); + CollectionType? GetConfiguredContentType(string path); /// /// Normalizes the root path list. @@ -329,7 +329,7 @@ namespace MediaBrowser.Controller.Library User user, string name, Guid parentId, - string viewType, + CollectionType? viewType, string sortName); /// @@ -343,7 +343,7 @@ namespace MediaBrowser.Controller.Library UserView GetNamedView( User user, string name, - string viewType, + CollectionType? viewType, string sortName); /// @@ -355,7 +355,7 @@ namespace MediaBrowser.Controller.Library /// The named view. UserView GetNamedView( string name, - string viewType, + CollectionType viewType, string sortName); /// @@ -370,7 +370,7 @@ namespace MediaBrowser.Controller.Library UserView GetNamedView( string name, Guid parentId, - string viewType, + CollectionType? viewType, string sortName, string uniqueId); @@ -383,7 +383,7 @@ namespace MediaBrowser.Controller.Library /// The shadow view. UserView GetShadowView( BaseItem parent, - string viewType, + CollectionType? viewType, string sortName); /// diff --git a/MediaBrowser.Controller/Library/IUserViewManager.cs b/MediaBrowser.Controller/Library/IUserViewManager.cs index 055627d3e..a565dc88b 100644 --- a/MediaBrowser.Controller/Library/IUserViewManager.cs +++ b/MediaBrowser.Controller/Library/IUserViewManager.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Library; @@ -28,7 +29,7 @@ namespace MediaBrowser.Controller.Library /// Localization key to use. /// Sort to use. /// User view. - UserView GetUserSubView(Guid parentId, string type, string localizationKey, string sortName); + UserView GetUserSubView(Guid parentId, CollectionType? type, string localizationKey, string sortName); /// /// Gets latest items. diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index dcd0110fb..6202f92f5 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.IO; @@ -120,7 +121,7 @@ namespace MediaBrowser.Controller.Library } } - public string CollectionType { get; set; } + public CollectionType? CollectionType { get; set; } public bool HasParent() where T : Folder @@ -220,7 +221,7 @@ namespace MediaBrowser.Controller.Library return GetFileSystemEntryByName(name) is not null; } - public string GetCollectionType() + public CollectionType? GetCollectionType() { return CollectionType; } @@ -229,7 +230,7 @@ namespace MediaBrowser.Controller.Library /// Gets the configured content type for the path. /// /// The configured content type. - public string GetConfiguredContentType() + public CollectionType? GetConfiguredContentType() { return _libraryManager.GetConfiguredContentType(Path); } diff --git a/MediaBrowser.Controller/Resolvers/IItemResolver.cs b/MediaBrowser.Controller/Resolvers/IItemResolver.cs index 282aa721e..0699734c4 100644 --- a/MediaBrowser.Controller/Resolvers/IItemResolver.cs +++ b/MediaBrowser.Controller/Resolvers/IItemResolver.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System.Collections.Generic; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; @@ -32,7 +33,7 @@ namespace MediaBrowser.Controller.Resolvers MultiItemResolverResult ResolveMultiple( Folder parent, List files, - string collectionType, + CollectionType? collectionType, IDirectoryService directoryService); } diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 287966dd0..709039fc5 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -420,7 +420,7 @@ namespace MediaBrowser.Model.Dto /// Gets or sets the type of the collection. /// /// The type of the collection. - public string CollectionType { get; set; } + public CollectionType? CollectionType { get; set; } /// /// Gets or sets the display order. diff --git a/MediaBrowser.Model/Dto/MetadataEditorInfo.cs b/MediaBrowser.Model/Dto/MetadataEditorInfo.cs index d098669ba..a3035bf61 100644 --- a/MediaBrowser.Model/Dto/MetadataEditorInfo.cs +++ b/MediaBrowser.Model/Dto/MetadataEditorInfo.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using Jellyfin.Data.Enums; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Providers; @@ -27,7 +28,7 @@ namespace MediaBrowser.Model.Dto public IReadOnlyList ExternalIdInfos { get; set; } - public string? ContentType { get; set; } + public CollectionType? ContentType { get; set; } public IReadOnlyList ContentTypeOptions { get; set; } } diff --git a/MediaBrowser.Model/Entities/CollectionType.cs b/MediaBrowser.Model/Entities/CollectionType.cs deleted file mode 100644 index 60b69d4b0..000000000 --- a/MediaBrowser.Model/Entities/CollectionType.cs +++ /dev/null @@ -1,27 +0,0 @@ -#pragma warning disable CS1591 - -namespace MediaBrowser.Model.Entities -{ - public static class CollectionType - { - public const string Movies = "movies"; - - public const string TvShows = "tvshows"; - - public const string Music = "music"; - - public const string MusicVideos = "musicvideos"; - - public const string Trailers = "trailers"; - - public const string HomeVideos = "homevideos"; - - public const string BoxSets = "boxsets"; - - public const string Books = "books"; - public const string Photos = "photos"; - public const string LiveTv = "livetv"; - public const string Playlists = "playlists"; - public const string Folders = "folders"; - } -} diff --git a/MediaBrowser.Model/Library/UserViewQuery.cs b/MediaBrowser.Model/Library/UserViewQuery.cs index 8a49b6863..e20d6af49 100644 --- a/MediaBrowser.Model/Library/UserViewQuery.cs +++ b/MediaBrowser.Model/Library/UserViewQuery.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System; +using Jellyfin.Data.Enums; namespace MediaBrowser.Model.Library { @@ -9,7 +10,7 @@ namespace MediaBrowser.Model.Library public UserViewQuery() { IncludeExternalContent = true; - PresetViews = Array.Empty(); + PresetViews = Array.Empty(); } /// @@ -30,6 +31,6 @@ namespace MediaBrowser.Model.Library /// true if [include hidden]; otherwise, false. public bool IncludeHidden { get; set; } - public string[] PresetViews { get; set; } + public CollectionType?[] PresetViews { get; set; } } } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs index d136c1bc6..16202aea9 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs @@ -1,6 +1,7 @@ using System.Linq; using Emby.Naming.Common; using Emby.Server.Implementations.Library.Resolvers.Audio; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Model.IO; @@ -62,7 +63,7 @@ public class AudioResolverTests null, Mock.Of()) { - CollectionType = "books", + CollectionType = CollectionType.Books, FileInfo = new FileSystemMetadata { FullName = parent, diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs index 6d0ed7bbb..92bac722b 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs @@ -1,5 +1,6 @@ using Emby.Naming.Common; using Emby.Server.Implementations.Library.Resolvers.TV; +using Jellyfin.Data.Enums; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; -- cgit v1.2.3