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 b0a4a4151a..9de36d73cd 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 692edae4a9..b63c8f10e5 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 18b00ce0b2..79eca4022a 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 e9538a5c97..858c5b2812 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 94ac4798ca..22bfd7e6f2 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 14417a5e43..03c778c07f 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 9bd99f030c..0241b77a12 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 59b7c6e279..d817042274 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 7604ddc803..5397f13712 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 c33a957e69..1c35eb3f50 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 f2a08e43cf..934024826b 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 f56f58c6fe..0a153b9cc1 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 7f620d666d..f83da566b2 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 9de36d73cd..6e6c14a51a 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 b77c6b204b..c860391fc2 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 1721be9e23..ff25ee5854 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 7e588f6812..04b0cb0177 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 613ea117f4..db5e81df5f 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 910a33c0f0..1b5afee557 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 2ee5b4e88d..3f3a0dec5e 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 9a473de52d..9626817e90 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 3cb791b571..1664a751de 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 e1a43bb489..ac50474010 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 b759b6bca5..1393f76aab 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 b263c173eb..6acab13fe0 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 ac20120d97..975218ad75 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 16943f6aaa..eb5069b062 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 75291b3178..e336c8825e 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 f22b861eba..f4b4eccf88 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 220aa1a8dc..255c51f19a 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 961e225e9e..3036cbcf7c 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 3aab0a5e9d..80263c1394 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 936a08da81..59d705acef 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 c9a26a30f5..91469dba99 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 b9d0f170ac..74b62ca3f2 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 7645c6c52d..6b0520ad0f 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 7e588f6812..4f96dde445 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 96f4353998..16776b6bd6 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 d7189ef0ca..20793ee394 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 77d385ba1c..c717744b12 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 6a0a4706be..7ac231885e 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 dea1c2f32a..2a7e6be0fd 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 55e2474a5a..daad9706cd 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 f3385b3a91..92742b1aa5 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 e4bb4eaead..e84f1359b7 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 5ddbd30d1e..4e8aec9f19 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 87136dfc8a..8761cf69bc 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 bd6e1b690a..39d449e27e 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 65e70caa02..e5d5e785cb 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 a12e7ca0d8..23de2489e5 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 2d3879bdb6..36861294b5 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 79d03d539a..4fcacd2cad 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 826a0a69dd..130281c6d2 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 0ade345a1a..98195a2943 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 abd594a3a1..e685d252e4 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 e519364c22..fadd4f2f38 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 539d4a63af..04d90af3c3 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 4f0983564d..5c76e77be1 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 ee039ff0f7..dd427c7368 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 964004eccb..6d13c6d573 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 67a9fbd3bc..65c8599e75 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 4bed0fca12..e071136551 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 a8bb55e2bc..f99977e5c5 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 5cb11ab465..9e02ea2ae8 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 ba1835e4f2..d4a8d46898 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 6133aaccc6..b86b4432f8 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 b1cb123ce1..e1c26d0121 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 453d817c76..d668c17bfc 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 1bcaccd8a3..11cad62567 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 73e628cf75..622a341b6a 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 3c5ddeefaa..6f0ca59c53 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 7d77a8bc5a..2a3e456c2d 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 926835f906..afd8ccf9f3 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 93bec4db99..72d9c79739 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 ce44f99a69..b4ee2c7234 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 c54750843e..5aeac29be4 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 16f1b79b3e..12f88bf4da 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 db86b8002d..8c8b8824f3 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 7fd1e024d0..9aec87f183 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 bf0168222d..6f8ea5b741 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 753e58324c..3c096ab023 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 5b6c64f63a..ed42fd6d55 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 19abafe192..314c25d128 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 2759d20de8..e0b438ef1a 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 89d10f3d23..0edffb783b 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 c9d2f67f92..c3c43982bf 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 11c4ac3768..fdc16ee23f 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 da60f2c60b..51f04fa276 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 80128536da..891cf88a7c 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 649397d68d..58159406a2 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 435457af67..94c8993575 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 b5b6406206..1246efd494 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 af403fa80e..55a30d4692 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 74370db50b..641cdd81e7 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 bc12ca3889..be3d4dfb67 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 5e7dd689e8..6a30de5e6c 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 0000000000..17bf1166de --- /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 14459624e9..7a73f3eaf9 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 a51299284b..fb50a45462 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 66210cb6c4..d7ccfd8aee 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 f34e3d68d9..52d546a4f1 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 c4ad352a3b..2f7ebb5cce 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 07fe1ea8a9..96f8a2af5d 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 f913b2320d..5a71930799 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 673d97a9ed..d872572b77 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 1a7c9a63b0..0000000000 --- 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 e336c8825e..06445c90d9 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 500ebaf71c..72e59c9ac4 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 2d7741d81a..a2d1b3607b 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 e685d252e4..7d53263a66 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 8a0e627b9c..6e8f77977e 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 0bd5fdce0a..5de53df739 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 5c76e77be1..f40177fa77 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 862f144e68..ac423ed091 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 bbc70701cb..06e292f4cf 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 c858dc53d9..7d6f97b121 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 73861ff599..b76bfe4274 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 0b65bf921e..50fd8b8779 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 7dd0ab1853..29d5407003 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 c860391fc2..d166ac37fb 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 5d569009d3..d4b3722c9a 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 6bb9996415..3d91ed242b 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 392ee4c771..8274881be1 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 d4f275bed4..2ae1138a53 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 2c3dc18574..df56109962 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 d67caa52dc..5c616d5349 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 51f04fa276..062e1062d7 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 504f2fa1d7..3be891b930 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 891cf88a7c..3920d65992 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 21941ff942..3cd78b0863 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 838b432340..0ffa3ab1ad 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 0000000000..ff613d9f8d --- /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 0000000000..e2044a0bc8 --- /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 b7e71a81db..16b58808f3 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 0000000000..eb9ad03c21 --- /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 9f3e8eec96..87a021d418 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 afafaf1c24..4bf21061ca 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 f51162f9d2..992bb19bb1 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 89e494ebc3..742691b003 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 fb50a45462..c0bba60ebc 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 47432ee93e..1f94cf767d 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 c276ab463a..a134735b23 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 52d546a4f1..9ec22324f2 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 055627d3e3..a565dc88b0 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 dcd0110fb5..6202f92f56 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 282aa721e8..0699734c4b 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 287966dd0e..709039fc5b 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 d098669baa..a3035bf612 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 60b69d4b01..0000000000 --- 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 8a49b68637..e20d6af49e 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 d136c1bc68..16202aea90 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 6d0ed7bbba..92bac722bf 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