From 80877aa945c5af9ffd6ca811d981ba417942ed9f Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 17 Apr 2021 09:27:58 +0100 Subject: Cleaned up "value assigned is not used in any execution path" --- Emby.Server.Implementations/HttpServer/WebSocketConnection.cs | 4 ++-- .../LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 2 +- Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 06acb5606..c661e6757 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System; using System.Buffers; @@ -182,7 +182,7 @@ namespace Emby.Server.Implementations.HttpServer } WebSocketMessage? stub; - long bytesConsumed = 0; + long bytesConsumed; try { stub = DeserializeWebSocketMessage(buffer, out bytesConsumed); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index b16ccc561..61262eb14 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -87,7 +87,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun Logger.LogInformation("Opening HDHR UDP Live stream from {host}", uri.Host); var remoteAddress = IPAddress.Parse(uri.Host); - IPAddress localAddress = null; + IPAddress localAddress; using (var tcpClient = new TcpClient()) { try diff --git a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs index 7bed06de3..0e5f65c72 100644 --- a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs +++ b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs @@ -258,7 +258,6 @@ namespace Emby.Server.Implementations.QuickConnect } // Expire stale connection requests - var code = string.Empty; var values = _currentRequests.Values.ToList(); for (int i = 0; i < values.Count; i++) @@ -266,7 +265,7 @@ namespace Emby.Server.Implementations.QuickConnect var added = values[i].DateAdded ?? DateTime.UnixEpoch; if (DateTime.UtcNow > added.AddMinutes(Timeout) || expireAll) { - code = values[i].Code; + var code = values[i].Code; _logger.LogDebug("Removing expired request {code}", code); if (!_currentRequests.TryRemove(code, out _)) -- cgit v1.2.3 From 1d6224c9c66b31c9df602b4281c870a9c400767c Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 26 Apr 2021 07:02:26 -0600 Subject: Add endpoint to log client events --- Emby.Server.Implementations/ApplicationHost.cs | 3 + Jellyfin.Api/Controllers/ClientLogController.cs | 69 ++++++++++++++++++++ .../Models/ClientLogDtos/ClientLogEventDto.cs | 54 ++++++++++++++++ Jellyfin.Server/Jellyfin.Server.csproj | 1 + Jellyfin.Server/Program.cs | 49 ++++++++++---- .../ClientEvent/ClientEventLogger.cs | 38 +++++++++++ .../ClientEvent/IClientEventLogger.cs | 16 +++++ .../MediaBrowser.Controller.csproj | 2 +- MediaBrowser.Model/ClientLog/ClientLogEvent.cs | 75 ++++++++++++++++++++++ 9 files changed, 295 insertions(+), 12 deletions(-) create mode 100644 Jellyfin.Api/Controllers/ClientLogController.cs create mode 100644 Jellyfin.Api/Models/ClientLogDtos/ClientLogEventDto.cs create mode 100644 MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs create mode 100644 MediaBrowser.Controller/ClientEvent/IClientEventLogger.cs create mode 100644 MediaBrowser.Model/ClientLog/ClientLogEvent.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 703f8d20d..b05e0409d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -55,6 +55,7 @@ using MediaBrowser.Common.Updates; using MediaBrowser.Controller; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Chapters; +using MediaBrowser.Controller.ClientEvent; using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; @@ -680,6 +681,8 @@ namespace Emby.Server.Implementations ServiceCollection.AddScoped(); ServiceCollection.AddScoped(); + ServiceCollection.AddScoped(); + ServiceCollection.AddSingleton(); } diff --git a/Jellyfin.Api/Controllers/ClientLogController.cs b/Jellyfin.Api/Controllers/ClientLogController.cs new file mode 100644 index 000000000..8e38cd13c --- /dev/null +++ b/Jellyfin.Api/Controllers/ClientLogController.cs @@ -0,0 +1,69 @@ +using Jellyfin.Api.Models.ClientLogDtos; +using MediaBrowser.Controller.ClientEvent; +using MediaBrowser.Model.ClientLog; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace Jellyfin.Api.Controllers +{ + /// + /// Client log controller. + /// + public class ClientLogController : BaseJellyfinApiController + { + private readonly IClientEventLogger _clientEventLogger; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + public ClientLogController(IClientEventLogger clientEventLogger) + { + _clientEventLogger = clientEventLogger; + } + + /// + /// Post event from client. + /// + /// The client log dto. + /// Event logged. + /// Submission status. + [HttpPost] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public ActionResult LogEvent([FromBody] ClientLogEventDto clientLogEventDto) + { + Log(clientLogEventDto); + return NoContent(); + } + + /// + /// Bulk post events from client. + /// + /// The list of client log dtos. + /// All events logged. + /// Submission status. + [HttpPost("Bulk")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public ActionResult LogEvents([FromBody] ClientLogEventDto[] clientLogEventDtos) + { + foreach (var dto in clientLogEventDtos) + { + Log(dto); + } + + return NoContent(); + } + + private void Log(ClientLogEventDto dto) + { + _clientEventLogger.Log(new ClientLogEvent( + dto.Timestamp, + dto.Level, + dto.UserId, + dto.ClientName, + dto.ClientVersion, + dto.DeviceId, + dto.Message)); + } + } +} \ No newline at end of file diff --git a/Jellyfin.Api/Models/ClientLogDtos/ClientLogEventDto.cs b/Jellyfin.Api/Models/ClientLogDtos/ClientLogEventDto.cs new file mode 100644 index 000000000..8ee1eab72 --- /dev/null +++ b/Jellyfin.Api/Models/ClientLogDtos/ClientLogEventDto.cs @@ -0,0 +1,54 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Api.Models.ClientLogDtos +{ + /// + /// The client log dto. + /// + public class ClientLogEventDto + { + /// + /// Gets or sets the event timestamp. + /// + [Required] + public DateTime Timestamp { get; set; } + + /// + /// Gets or sets the log level. + /// + [Required] + public LogLevel Level { get; set; } + + /// + /// Gets or sets the user id. + /// + public Guid? UserId { get; set; } + + /// + /// Gets or sets the client name. + /// + [Required] + public string ClientName { get; set; } = string.Empty; + + /// + /// Gets or sets the client version. + /// + [Required] + public string ClientVersion { get; set; } = string.Empty; + + /// + /// + /// Gets or sets the device id. + /// + [Required] + public string DeviceId { get; set; } = string.Empty; + + /// + /// Gets or sets the log message. + /// + [Required] + public string Message { get; set; } = string.Empty; + } +} \ No newline at end of file diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 3496cabe8..ef842ee26 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -49,6 +49,7 @@ + diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index c10b2ddb3..b8d3ba239 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -14,6 +14,7 @@ using Emby.Server.Implementations; using Emby.Server.Implementations.IO; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; +using MediaBrowser.Controller.ClientEvent; using MediaBrowser.Controller.Extensions; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -24,6 +25,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Serilog; using Serilog.Extensions.Logging; +using Serilog.Filters; using SQLitePCL; using ConfigurationExtensions = MediaBrowser.Controller.Extensions.ConfigurationExtensions; using ILogger = Microsoft.Extensions.Logging.ILogger; @@ -585,22 +587,47 @@ namespace Jellyfin.Server { // Serilog.Log is used by SerilogLoggerFactory when no logger is specified Serilog.Log.Logger = new LoggerConfiguration() - .ReadFrom.Configuration(configuration) - .Enrich.FromLogContext() - .Enrich.WithThreadId() + .WriteTo.Logger(lc => + lc.ReadFrom.Configuration(configuration) + .Enrich.FromLogContext() + .Enrich.WithThreadId() + .Filter.ByExcluding(Matching.FromSource())) + .WriteTo.Logger(lc => + lc + .WriteTo.Map( + "ClientName", + (clientName, wt) + => wt.File( + Path.Combine(appPaths.LogDirectoryPath, $"log_{clientName}_.log"), + rollingInterval: RollingInterval.Day, + outputTemplate: "{Message:l}{NewLine}{Exception}", + encoding: Encoding.UTF8)) + .Filter.ByIncludingOnly(Matching.FromSource())) .CreateLogger(); } catch (Exception ex) { Serilog.Log.Logger = new LoggerConfiguration() - .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message:lj}{NewLine}{Exception}") - .WriteTo.Async(x => x.File( - Path.Combine(appPaths.LogDirectoryPath, "log_.log"), - rollingInterval: RollingInterval.Day, - outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message}{NewLine}{Exception}", - encoding: Encoding.UTF8)) - .Enrich.FromLogContext() - .Enrich.WithThreadId() + .WriteTo.Logger(lc => + lc.WriteTo.Async(x => x.File( + Path.Combine(appPaths.LogDirectoryPath, "log_.log"), + rollingInterval: RollingInterval.Day, + outputTemplate: "{Message:l}{NewLine}{Exception}", + encoding: Encoding.UTF8)) + .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message:lj}{NewLine}{Exception}") + .Enrich.FromLogContext() + .Enrich.WithThreadId()) + .WriteTo.Logger(lc => + lc + .WriteTo.Map( + "ClientName", + (clientName, wt) + => wt.File( + Path.Combine(appPaths.LogDirectoryPath, $"log_{clientName}_.log"), + rollingInterval: RollingInterval.Day, + outputTemplate: "{Message:l}{NewLine}{Exception}", + encoding: Encoding.UTF8)) + .Filter.ByIncludingOnly(Matching.FromSource())) .CreateLogger(); Serilog.Log.Logger.Fatal(ex, "Failed to create/read logger configuration"); diff --git a/MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs b/MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs new file mode 100644 index 000000000..c00a38d1b --- /dev/null +++ b/MediaBrowser.Controller/ClientEvent/ClientEventLogger.cs @@ -0,0 +1,38 @@ +using System; +using MediaBrowser.Model.ClientLog; +using Microsoft.Extensions.Logging; + +namespace MediaBrowser.Controller.ClientEvent +{ + /// + public class ClientEventLogger : IClientEventLogger + { + private const string LogString = "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level}] [{ClientName}:{ClientVersion}]: UserId: {UserId} DeviceId: {DeviceId}{NewLine}{Message}"; + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + public ClientEventLogger(ILogger logger) + { + _logger = logger; + } + + /// + public void Log(ClientLogEvent clientLogEvent) + { + _logger.Log( + LogLevel.Critical, + LogString, + clientLogEvent.Timestamp, + clientLogEvent.Level.ToString(), + clientLogEvent.ClientName, + clientLogEvent.ClientVersion, + clientLogEvent.UserId ?? Guid.Empty, + clientLogEvent.DeviceId, + Environment.NewLine, + clientLogEvent.Message); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/ClientEvent/IClientEventLogger.cs b/MediaBrowser.Controller/ClientEvent/IClientEventLogger.cs new file mode 100644 index 000000000..bf799c7bf --- /dev/null +++ b/MediaBrowser.Controller/ClientEvent/IClientEventLogger.cs @@ -0,0 +1,16 @@ +using MediaBrowser.Model.ClientLog; + +namespace MediaBrowser.Controller.ClientEvent +{ + /// + /// The client event logger. + /// + public interface IClientEventLogger + { + /// + /// Logs the event from the client. + /// + /// The client log event. + void Log(ClientLogEvent clientLogEvent); + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 8c68b47dd..7c95ab818 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -16,7 +16,7 @@ - + diff --git a/MediaBrowser.Model/ClientLog/ClientLogEvent.cs b/MediaBrowser.Model/ClientLog/ClientLogEvent.cs new file mode 100644 index 000000000..e4ee88145 --- /dev/null +++ b/MediaBrowser.Model/ClientLog/ClientLogEvent.cs @@ -0,0 +1,75 @@ +using System; +using Microsoft.Extensions.Logging; + +namespace MediaBrowser.Model.ClientLog +{ + /// + /// The client log event. + /// + public class ClientLogEvent + { + /// + /// Initializes a new instance of the class. + /// + /// The log timestamp. + /// The log level. + /// The user id. + /// The client name. + /// The client version. + /// The device id. + /// The message. + public ClientLogEvent( + DateTime timestamp, + LogLevel level, + Guid? userId, + string clientName, + string clientVersion, + string deviceId, + string message) + { + Timestamp = timestamp; + UserId = userId; + ClientName = clientName; + ClientVersion = clientVersion; + DeviceId = deviceId; + Message = message; + Level = level; + } + + /// + /// Gets the event timestamp. + /// + public DateTime Timestamp { get; } + + /// + /// Gets the log level. + /// + public LogLevel Level { get; } + + /// + /// Gets the user id. + /// + public Guid? UserId { get; } + + /// + /// Gets the client name. + /// + public string ClientName { get; } + + /// + /// Gets the client version. + /// + public string ClientVersion { get; } + + /// + /// + /// Gets the device id. + /// + public string DeviceId { get; } + + /// + /// Gets the log message. + /// + public string Message { get; } + } +} \ No newline at end of file -- cgit v1.2.3 From 5741fa7dfa4b1e8e8cb1f977a7eb531b994b93ae Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 24 Apr 2021 23:54:48 +0100 Subject: Fix url for LiveTV --- Emby.Server.Implementations/ApplicationHost.cs | 8 +--- Jellyfin.Networking/Manager/NetworkManager.cs | 1 + .../NetworkManagerTests.cs | 2 +- .../Jellyfin.Networking.Tests/NetworkParseTests.cs | 48 ++++++++++++++++++++++ 4 files changed, 52 insertions(+), 7 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 703f8d20d..7b4592fbc 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1203,12 +1203,8 @@ namespace Emby.Server.Implementations /// public string GetLoopbackHttpApiUrl() { - if (NetManager.IsIP6Enabled) - { - return GetLocalApiUrl("::1", Uri.UriSchemeHttp, HttpPort); - } - - return GetLocalApiUrl("127.0.0.1", Uri.UriSchemeHttp, HttpPort); + // Passing an external address cause GetBindInterface to return an externally accessible interface (if possible). + return GetLocalApiUrl(NetManager.GetBindInterface("8.8.8.8", out var _), Uri.UriSchemeHttp, HttpPort); } /// diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index 73e8b2cd7..fd8455dc8 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -990,6 +990,7 @@ namespace Jellyfin.Networking.Manager // Read and parse bind addresses and exclusions, removing ones that don't exist. _bindAddresses = CreateIPCollection(lanAddresses).ThatAreContainedInNetworks(_interfaceAddresses); _bindExclusions = CreateIPCollection(lanAddresses, true).ThatAreContainedInNetworks(_interfaceAddresses); + _logger.LogInformation("Using bind addresses: {0}", _bindAddresses.AsString()); _logger.LogInformation("Using bind exclusions: {0}", _bindExclusions.AsString()); } diff --git a/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs b/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs index 1cad625b7..61f913252 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkManagerTests.cs @@ -34,7 +34,7 @@ namespace Jellyfin.Networking.Tests } /// - /// Checks that thge given IP address is not in the network provided. + /// Checks that the given IP address is not in the network provided. /// /// Network address(es). /// The IP to check. diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs index 9b0da2b3c..ea1477291 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.ObjectModel; +using System.Linq; using System.Net; using Jellyfin.Networking.Configuration; using Jellyfin.Networking.Manager; @@ -530,5 +531,52 @@ namespace Jellyfin.Networking.Tests Assert.NotEqual(nm.HasRemoteAccess(IPAddress.Parse(remoteIp)), denied); } + + [Theory] + [InlineData("192.168.1.209/24,-16,eth16", "192.168.1.0/24", "", "192.168.1.209")] // Only 1 address so use it. + [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "", "192.168.1.208")] // LAN address is specified by default. + [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "10.0.0.1", "10.0.0.1")] // return bind address + [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "10.0.0.1", "192.168.1.209")] // return internal bind address (Internal takes priority) + + public void Get_Appropriate_Interface_NoSource(string interfaces, string lan, string bind, string result) + { + var conf = new NetworkConfiguration() + { + EnableIPV4 = true, + LocalNetworkSubnets = lan.Split(','), + LocalNetworkAddresses = bind.Split(',') + }; + + NetworkManager.MockNetworkSettings = interfaces; + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); + + var interfaceToUse = nm.GetBindInterface(string.Empty, out var port); + + Assert.Equal(interfaceToUse, result); + } + + [Theory] + [InlineData("192.168.1.209/24,-16,eth16", "192.168.1.0/24", "", "192.168.1.210", "192.168.1.209")] // Source on LAN + [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "", "192.168.1.209", "192.168.1.208")] // Source on LAN + [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "", "8.8.8.8", "10.0.0.1")] // Source external. + [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "10.0.0.1", "192.168.1.209", "10.0.0.1")] // LAN not bound, so return external. + [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "192.168.1.208,10.0.0.1", "8.8.8.8", "10.0.0.1")] // return external bind address + [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "192.168.1.208,10.0.0.1", "192.168.1.210", "192.168.1.208")] // return LAN bind address + public void Get_Appropriate_Interface_ForSource(string interfaces, string lan, string bind, string source, string result) + { + var conf = new NetworkConfiguration() + { + EnableIPV4 = true, + LocalNetworkSubnets = lan.Split(','), + LocalNetworkAddresses = bind.Split(',') + }; + + NetworkManager.MockNetworkSettings = interfaces; + using var nm = new NetworkManager(GetMockConfig(conf), new NullLogger()); + + var interfaceToUse = nm.GetBindInterface(source, out var port); + + Assert.Equal(interfaceToUse, result); + } } } -- cgit v1.2.3 From 78e97dbaa99a9acc8b0abc04a72480976aef3c24 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Mon, 26 Apr 2021 19:56:15 +0100 Subject: updated comment --- Emby.Server.Implementations/ApplicationHost.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 7b4592fbc..e7ca70d04 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1203,7 +1203,8 @@ namespace Emby.Server.Implementations /// public string GetLoopbackHttpApiUrl() { - // Passing an external address cause GetBindInterface to return an externally accessible interface (if possible). + // Passing an external address cause GetBindInterface to return the externally facing interface on a multi-adapter system. + // LocalNetworkSubnets and LocalNetworkAddresses are used in conjunction with the ip address to help select the best interface. return GetLocalApiUrl(NetManager.GetBindInterface("8.8.8.8", out var _), Uri.UriSchemeHttp, HttpPort); } -- cgit v1.2.3 From 851f610e11907a7c90e10d00400514a6585f50c6 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Mon, 26 Apr 2021 19:59:35 +0100 Subject: Changed other method to match for consistency. --- Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index 3a738fd5d..d7ea9d640 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.LiveTv // Dummy this up so that direct play checks can still run if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http) { - source.Path = _appHost.GetSmartApiUrl(string.Empty); + source.Path = _appHost.GetLoopbackHttpApiUrl(); } } -- cgit v1.2.3 From 21826405197ad6a5ac51a3eccc5bb50004bdc54b Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Fri, 30 Apr 2021 09:08:56 +0100 Subject: Update Emby.Server.Implementations/ApplicationHost.cs Co-authored-by: Cody Robibero --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index e7ca70d04..26a2d7298 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1205,7 +1205,7 @@ namespace Emby.Server.Implementations { // Passing an external address cause GetBindInterface to return the externally facing interface on a multi-adapter system. // LocalNetworkSubnets and LocalNetworkAddresses are used in conjunction with the ip address to help select the best interface. - return GetLocalApiUrl(NetManager.GetBindInterface("8.8.8.8", out var _), Uri.UriSchemeHttp, HttpPort); + return GetLocalApiUrl(NetManager.GetBindInterface("0.0.0.0", out var _), Uri.UriSchemeHttp, HttpPort); } /// -- cgit v1.2.3 From a5aabbb88538f8ab3f95f3accf31adb1be24503d Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 1 May 2021 17:14:37 +0100 Subject: Update ApplicationHost.cs Renamed method --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 26a2d7298..c28b4ae1c 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1201,7 +1201,7 @@ namespace Emby.Server.Implementations } /// - public string GetLoopbackHttpApiUrl() + public string GetExternalFacingHttpApiUrl() { // Passing an external address cause GetBindInterface to return the externally facing interface on a multi-adapter system. // LocalNetworkSubnets and LocalNetworkAddresses are used in conjunction with the ip address to help select the best interface. -- cgit v1.2.3 From 2fbc1190bcb287407722a75db6992c5c65adfd70 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 1 May 2021 17:15:45 +0100 Subject: Update LiveTvMediaSourceProvider.cs --- Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index d7ea9d640..804794caa 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.LiveTv // Dummy this up so that direct play checks can still run if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http) { - source.Path = _appHost.GetLoopbackHttpApiUrl(); + source.Path = _appHost.GetExternalFacingHttpApiUrl(); } } -- cgit v1.2.3 From 7936ea59eb199980eaa47891a0e017143bbf8319 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Sat, 1 May 2021 17:21:14 +0100 Subject: Changed selection method --- Emby.Server.Implementations/ApplicationHost.cs | 22 ++++++++++++--- .../LiveTv/EmbyTV/EmbyTV.cs | 2 +- .../LiveTv/LiveTvMediaSourceProvider.cs | 2 +- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 2 +- .../LiveTv/TunerHosts/SharedHttpStream.cs | 2 +- Jellyfin.Networking/Manager/NetworkManager.cs | 31 +++------------------- MediaBrowser.Controller/IServerApplicationHost.cs | 5 ++-- .../Jellyfin.Networking.Tests/NetworkParseTests.cs | 4 +-- 8 files changed, 29 insertions(+), 41 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index c28b4ae1c..bd2bb54bd 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1201,11 +1201,25 @@ namespace Emby.Server.Implementations } /// - public string GetExternalFacingHttpApiUrl() + public string GetInterfaceHttpApiUrl() { - // Passing an external address cause GetBindInterface to return the externally facing interface on a multi-adapter system. - // LocalNetworkSubnets and LocalNetworkAddresses are used in conjunction with the ip address to help select the best interface. - return GetLocalApiUrl(NetManager.GetBindInterface("0.0.0.0", out var _), Uri.UriSchemeHttp, HttpPort); + // Published server ends with a / + if (!string.IsNullOrEmpty(PublishedServerUrl)) + { + // Published server ends with a '/', so we need to remove it. + return PublishedServerUrl.Trim('/'); + } + + var bind = NetManager.GetInternalBindAddresses().FirstOrDefault() ?? new IPNetAddress(IPAddress.None); + + string smart = NetManager.GetBindInterface(bind, out var port); + // If the smartAPI doesn't start with http then treat it as a host or ip. + if (smart.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + return smart.Trim('/'); + } + + return GetLocalApiUrl(smart.Trim('/'), null, port); } /// diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index c9d9cc49a..d61f74dd2 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1031,7 +1031,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { var stream = new MediaSourceInfo { - EncoderPath = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveRecordings/" + info.Id + "/stream", + EncoderPath = _appHost.GetInterfaceHttpApiUrl() + "/LiveTv/LiveRecordings/" + info.Id + "/stream", EncoderProtocol = MediaProtocol.Http, Path = info.Path, Protocol = MediaProtocol.File, diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index 804794caa..b5f0b2118 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.LiveTv // Dummy this up so that direct play checks can still run if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http) { - source.Path = _appHost.GetExternalFacingHttpApiUrl(); + source.Path = _appHost.GetInterfaceHttpApiUrl(); } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index b16ccc561..d6ea320ea 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -148,7 +148,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun // OpenedMediaSource.Path = tempFile; // OpenedMediaSource.ReadAtNativeFramerate = true; - MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; + MediaSource.Path = _appHost.GetInterfaceHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; // OpenedMediaSource.SupportsDirectPlay = false; // OpenedMediaSource.SupportsDirectStream = true; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index eeb2426f4..b9a567e40 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -97,7 +97,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts // OpenedMediaSource.Path = tempFile; // OpenedMediaSource.ReadAtNativeFramerate = true; - MediaSource.Path = _appHost.GetLoopbackHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; + MediaSource.Path = _appHost.GetInterfaceHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; // OpenedMediaSource.Path = TempFilePath; diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index fd8455dc8..52e2f7964 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -455,10 +455,10 @@ namespace Jellyfin.Networking.Manager } // No bind address, so return all internal interfaces. - return CreateCollection(_internalInterfaces.Where(p => !p.IsLoopback())); + return CreateCollection(_internalInterfaces); } - return new Collection(_bindAddresses); + return new Collection(_bindAddresses.Where(IsInLocalNetwork).ToArray()); } /// @@ -481,7 +481,7 @@ namespace Jellyfin.Networking.Manager } // As private addresses can be redefined by Configuration.LocalNetworkAddresses - return _lanSubnets.ContainsAddress(address) && !_excludedSubnets.ContainsAddress(address); + return address.IsLoopback() || (_lanSubnets.ContainsAddress(address) && !_excludedSubnets.ContainsAddress(address)); } /// @@ -647,16 +647,6 @@ namespace Jellyfin.Networking.Manager _interfaceAddresses.AddItem(address, false); _interfaceNames[parts[2]] = Math.Abs(index); } - - if (IsIP4Enabled) - { - _interfaceAddresses.AddItem(IPNetAddress.IP4Loopback); - } - - if (IsIP6Enabled) - { - _interfaceAddresses.AddItem(IPNetAddress.IP6Loopback); - } } InitialiseLAN(config); @@ -990,7 +980,6 @@ namespace Jellyfin.Networking.Manager // Read and parse bind addresses and exclusions, removing ones that don't exist. _bindAddresses = CreateIPCollection(lanAddresses).ThatAreContainedInNetworks(_interfaceAddresses); _bindExclusions = CreateIPCollection(lanAddresses, true).ThatAreContainedInNetworks(_interfaceAddresses); - _logger.LogInformation("Using bind addresses: {0}", _bindAddresses.AsString()); _logger.LogInformation("Using bind exclusions: {0}", _bindExclusions.AsString()); } @@ -1038,17 +1027,14 @@ namespace Jellyfin.Networking.Manager // Subnets are the same as the calculated internal interface. _lanSubnets = new Collection(); - // We must listen on loopback for LiveTV to function regardless of the settings. if (IsIP6Enabled) { - _lanSubnets.AddItem(IPNetAddress.IP6Loopback); _lanSubnets.AddItem(IPNetAddress.Parse("fc00::/7")); // ULA _lanSubnets.AddItem(IPNetAddress.Parse("fe80::/10")); // Site local } if (IsIP4Enabled) { - _lanSubnets.AddItem(IPNetAddress.IP4Loopback); _lanSubnets.AddItem(IPNetAddress.Parse("10.0.0.0/8")); _lanSubnets.AddItem(IPNetAddress.Parse("172.16.0.0/12")); _lanSubnets.AddItem(IPNetAddress.Parse("192.168.0.0/16")); @@ -1056,17 +1042,6 @@ namespace Jellyfin.Networking.Manager } else { - // We must listen on loopback for LiveTV to function regardless of the settings. - if (IsIP6Enabled) - { - _lanSubnets.AddItem(IPNetAddress.IP6Loopback); - } - - if (IsIP4Enabled) - { - _lanSubnets.AddItem(IPNetAddress.IP4Loopback); - } - // Internal interfaces must be private, not excluded and part of the LocalNetworkSubnet. _internalInterfaces = CreateCollection(_interfaceAddresses.Where(i => IsInLocalNetwork(i))); } diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 6a65a8e47..a284dceca 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -88,11 +88,10 @@ namespace MediaBrowser.Controller string GetSmartApiUrl(string hostname, int? port = null); /// - /// Gets a localhost URL that can be used to access the API using the loop-back IP address. - /// over HTTP (not HTTPS). + /// Gets an URL that can be used to access the API over HTTP (not HTTPS). /// /// The API URL. - string GetLoopbackHttpApiUrl(); + string GetInterfaceHttpApiUrl(); /// /// Gets a local (LAN) URL that can be used to access the API. diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs index f203f9b42..53c17bfb1 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs @@ -35,9 +35,9 @@ namespace Jellyfin.Networking.Tests // eth16 only [InlineData("192.168.1.208/24,-16,eth16|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[192.168.1.208/24]")] // All interfaces excluded. (including loopbacks) - [InlineData("192.168.1.208/24,-16,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[127.0.0.1/8,::1/128]")] + [InlineData("192.168.1.208/24,-16,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[]")] // vEthernet1 and vEthernet212 should be excluded. - [InlineData("192.168.1.200/24,-20,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.200/24", "[200.200.200.200/24,127.0.0.1/8,::1/128]")] + [InlineData("192.168.1.200/24,-20,vEthernet1|192.168.2.208/24,-16,vEthernet212|200.200.200.200/24,11,eth11", "192.168.1.0/24;200.200.200.200/24", "[200.200.200.200/24]")] // Overlapping interface, [InlineData("192.168.1.110/24,-20,br0|192.168.1.10/24,-16,br0|200.200.200.200/24,11,eth11", "192.168.1.0/24", "[192.168.1.110/24,192.168.1.10/24]")] public void IgnoreVirtualInterfaces(string interfaces, string lan, string value) -- cgit v1.2.3 From 7ff52bf755b6bed22ecef8d22fafacfce83890b7 Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Mon, 3 May 2021 19:30:56 +0100 Subject: Renamed --- Emby.Server.Implementations/ApplicationHost.cs | 21 ++++----------------- Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 2 +- .../LiveTv/LiveTvMediaSourceProvider.cs | 2 +- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 2 +- .../LiveTv/TunerHosts/SharedHttpStream.cs | 2 +- MediaBrowser.Controller/IServerApplicationHost.cs | 2 +- 6 files changed, 9 insertions(+), 22 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bd2bb54bd..b94036533 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1201,25 +1201,12 @@ namespace Emby.Server.Implementations } /// - public string GetInterfaceHttpApiUrl() + public string GetUrlForUseByHttpApi() { - // Published server ends with a / - if (!string.IsNullOrEmpty(PublishedServerUrl)) - { - // Published server ends with a '/', so we need to remove it. - return PublishedServerUrl.Trim('/'); - } - - var bind = NetManager.GetInternalBindAddresses().FirstOrDefault() ?? new IPNetAddress(IPAddress.None); + var bind = NetManager.GetInternalBindAddresses().FirstOrDefault() ?? + NetManager.GetAllBindInterfaces(true).FirstOrDefault(); - string smart = NetManager.GetBindInterface(bind, out var port); - // If the smartAPI doesn't start with http then treat it as a host or ip. - if (smart.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - return smart.Trim('/'); - } - - return GetLocalApiUrl(smart.Trim('/'), null, port); + return GetLocalApiUrl(bind.Address.ToString(), Uri.UriSchemeHttp); } /// diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index d61f74dd2..c580a6ebf 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1031,7 +1031,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { var stream = new MediaSourceInfo { - EncoderPath = _appHost.GetInterfaceHttpApiUrl() + "/LiveTv/LiveRecordings/" + info.Id + "/stream", + EncoderPath = _appHost.GetUrlForUseByHttpApi() + "/LiveTv/LiveRecordings/" + info.Id + "/stream", EncoderProtocol = MediaProtocol.Http, Path = info.Path, Protocol = MediaProtocol.File, diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index b5f0b2118..09a856315 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.LiveTv // Dummy this up so that direct play checks can still run if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http) { - source.Path = _appHost.GetInterfaceHttpApiUrl(); + source.Path = _appHost.GetUrlForUseByHttpApi(); } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index d6ea320ea..6404ba19c 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -148,7 +148,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun // OpenedMediaSource.Path = tempFile; // OpenedMediaSource.ReadAtNativeFramerate = true; - MediaSource.Path = _appHost.GetInterfaceHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; + MediaSource.Path = _appHost.GetUrlForUseByHttpApi() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; // OpenedMediaSource.SupportsDirectPlay = false; // OpenedMediaSource.SupportsDirectStream = true; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index b9a567e40..23c8d8dd5 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -97,7 +97,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts // OpenedMediaSource.Path = tempFile; // OpenedMediaSource.ReadAtNativeFramerate = true; - MediaSource.Path = _appHost.GetInterfaceHttpApiUrl() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; + MediaSource.Path = _appHost.GetUrlForUseByHttpApi() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; // OpenedMediaSource.Path = TempFilePath; diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index a284dceca..d054e2a19 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -91,7 +91,7 @@ namespace MediaBrowser.Controller /// Gets an URL that can be used to access the API over HTTP (not HTTPS). /// /// The API URL. - string GetInterfaceHttpApiUrl(); + string GetUrlForUseByHttpApi(); /// /// Gets a local (LAN) URL that can be used to access the API. -- cgit v1.2.3 From 417a7011c7b5fe4a5ca5ce7c0b61c14f15bc748b Mon Sep 17 00:00:00 2001 From: BaronGreenback Date: Tue, 4 May 2021 16:32:17 +0100 Subject: changed to first --- Emby.Server.Implementations/ApplicationHost.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index b94036533..ce24e933d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1203,8 +1203,9 @@ namespace Emby.Server.Implementations /// public string GetUrlForUseByHttpApi() { + // GetBindInterfaces will return an interface. var bind = NetManager.GetInternalBindAddresses().FirstOrDefault() ?? - NetManager.GetAllBindInterfaces(true).FirstOrDefault(); + NetManager.GetAllBindInterfaces(true).First(); return GetLocalApiUrl(bind.Address.ToString(), Uri.UriSchemeHttp); } -- cgit v1.2.3 From 95988ce33dccd36cb5d4e82a83ef8e4b3bc2382b Mon Sep 17 00:00:00 2001 From: Deathspike Date: Tue, 17 Aug 2021 20:10:15 +0200 Subject: Fix embedded subtitles taking priority over external ones --- .../Library/MediaStreamSelector.cs | 30 ++++++++++++++-------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/MediaStreamSelector.cs b/Emby.Server.Implementations/Library/MediaStreamSelector.cs index b833122ea..71e3404d0 100644 --- a/Emby.Server.Implementations/Library/MediaStreamSelector.cs +++ b/Emby.Server.Implementations/Library/MediaStreamSelector.cs @@ -57,14 +57,18 @@ namespace Emby.Server.Implementations.Library { // Prefer embedded metadata over smart logic - stream = streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ?? - streams.FirstOrDefault(s => s.IsForced) ?? - streams.FirstOrDefault(s => s.IsDefault); + stream = streams.FirstOrDefault(s => s.IsExternal && s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ?? + streams.FirstOrDefault(s => s.IsExternal && s.IsForced) ?? + streams.FirstOrDefault(s => s.IsExternal && s.IsDefault) ?? + streams.FirstOrDefault(s => s.IsExternal) ?? + streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ?? + streams.FirstOrDefault(s => s.IsForced) ?? + streams.FirstOrDefault(s => s.IsDefault); // if the audio language is not understood by the user, load their preferred subs, if there are any if (stream == null && !preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase)) { - stream = streams.Where(s => !s.IsForced).FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)); + stream = streams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)); } } else if (mode == SubtitlePlaybackMode.Smart) @@ -74,24 +78,30 @@ namespace Emby.Server.Implementations.Library // if the audio language is not understood by the user, load their preferred subs, if there are any if (!preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase)) { - stream = streams.Where(s => !s.IsForced).FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)) ?? - streams.FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)); + stream = streams.FirstOrDefault(s => s.IsExternal && !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)) ?? + streams.FirstOrDefault(s => s.IsExternal && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)) ?? + streams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)) ?? + streams.FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)); } } else if (mode == SubtitlePlaybackMode.Always) { // always load the most suitable full subtitles - stream = streams.FirstOrDefault(s => !s.IsForced); + stream = streams.FirstOrDefault(s => s.IsExternal && !s.IsForced) ?? + streams.FirstOrDefault(s => !s.IsForced); } else if (mode == SubtitlePlaybackMode.OnlyForced) { // always load the most suitable full subtitles - stream = streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ?? - streams.FirstOrDefault(s => s.IsForced); + stream = streams.FirstOrDefault(s => s.IsExternal && s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ?? + streams.FirstOrDefault(s => s.IsExternal && s.IsForced) ?? + streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ?? + streams.FirstOrDefault(s => s.IsForced); } // load forced subs if we have found no suitable full subtitles - stream ??= streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)); + stream ??= streams.FirstOrDefault(s => s.IsExternal && s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ?? + streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)); if (stream != null) { -- cgit v1.2.3 From 47be1bf69f62d72ecf81cc95347f3c8c5a6a5174 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Fri, 3 Sep 2021 10:59:40 -0600 Subject: Enable nullable for SchedulesDirect --- .../LiveTv/Listings/SchedulesDirect.cs | 22 ++++------ .../Listings/SchedulesDirectDtos/BroadcasterDto.cs | 10 ++--- .../Listings/SchedulesDirectDtos/CaptionDto.cs | 6 +-- .../LiveTv/Listings/SchedulesDirectDtos/CastDto.cs | 14 +++---- .../Listings/SchedulesDirectDtos/ChannelDto.cs | 9 ++-- .../SchedulesDirectDtos/ContentRatingDto.cs | 6 +-- .../LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs | 12 +++--- .../LiveTv/Listings/SchedulesDirectDtos/DayDto.cs | 17 ++------ .../SchedulesDirectDtos/Description1000Dto.cs | 6 +-- .../SchedulesDirectDtos/Description100Dto.cs | 6 +-- .../SchedulesDirectDtos/DescriptionsProgramDto.cs | 7 ++-- .../SchedulesDirectDtos/EventDetailsDto.cs | 4 +- .../Listings/SchedulesDirectDtos/GracenoteDto.cs | 2 - .../Listings/SchedulesDirectDtos/HeadendsDto.cs | 11 +++-- .../Listings/SchedulesDirectDtos/ImageDataDto.cs | 22 +++++----- .../Listings/SchedulesDirectDtos/LineupDto.cs | 12 +++--- .../Listings/SchedulesDirectDtos/LineupsDto.cs | 9 ++-- .../LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs | 6 +-- .../LiveTv/Listings/SchedulesDirectDtos/MapDto.cs | 8 ++-- .../Listings/SchedulesDirectDtos/MetadataDto.cs | 8 ++-- .../SchedulesDirectDtos/MetadataProgramsDto.cs | 4 +- .../SchedulesDirectDtos/MetadataScheduleDto.cs | 10 ++--- .../Listings/SchedulesDirectDtos/MovieDto.cs | 7 ++-- .../Listings/SchedulesDirectDtos/MultipartDto.cs | 2 - .../SchedulesDirectDtos/ProgramDetailsDto.cs | 49 +++++++++++----------- .../Listings/SchedulesDirectDtos/ProgramDto.cs | 21 +++++----- .../SchedulesDirectDtos/QualityRatingDto.cs | 12 +++--- .../Listings/SchedulesDirectDtos/RatingDto.cs | 6 +-- .../SchedulesDirectDtos/RecommendationDto.cs | 6 +-- .../RequestScheduleForChannelDto.cs | 7 ++-- .../Listings/SchedulesDirectDtos/ShowImagesDto.cs | 7 ++-- .../Listings/SchedulesDirectDtos/StationDto.cs | 19 ++++----- .../Listings/SchedulesDirectDtos/TitleDto.cs | 4 +- .../Listings/SchedulesDirectDtos/TokenDto.cs | 15 ++++--- 34 files changed, 153 insertions(+), 213 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 8125ed57d..41c3bafa0 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -16,7 +16,6 @@ using System.Threading; using System.Threading.Tasks; using Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos; using Jellyfin.Extensions.Json; -using MediaBrowser.Common; using MediaBrowser.Common.Net; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Cryptography; @@ -34,7 +33,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings private readonly ILogger _logger; private readonly IHttpClientFactory _httpClientFactory; private readonly SemaphoreSlim _tokenSemaphore = new SemaphoreSlim(1, 1); - private readonly IApplicationHost _appHost; private readonly ICryptoProvider _cryptoProvider; private readonly ConcurrentDictionary _tokens = new ConcurrentDictionary(); @@ -44,12 +42,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings public SchedulesDirect( ILogger logger, IHttpClientFactory httpClientFactory, - IApplicationHost appHost, ICryptoProvider cryptoProvider) { _logger = logger; _httpClientFactory = httpClientFactory; - _appHost = appHost; _cryptoProvider = cryptoProvider; } @@ -120,8 +116,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var programRequestOptions = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/programs"); programRequestOptions.Headers.TryAddWithoutValidation("token", token); - var programsID = dailySchedules.SelectMany(d => d.Programs.Select(s => s.ProgramId)).Distinct(); - programRequestOptions.Content = new StringContent("[\"" + string.Join("\", \"", programsID) + "\"]", Encoding.UTF8, MediaTypeNames.Application.Json); + var programIds = dailySchedules.SelectMany(d => d.Programs.Select(s => s.ProgramId)).Distinct(); + programRequestOptions.Content = new StringContent("[\"" + string.Join("\", \"", programIds) + "\"]", Encoding.UTF8, MediaTypeNames.Application.Json); using var innerResponse = await Send(programRequestOptions, true, info, cancellationToken).ConfigureAwait(false); await using var innerResponseStream = await innerResponse.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); @@ -225,21 +221,21 @@ namespace Emby.Server.Implementations.LiveTv.Listings string newID = programId + "T" + startAt.Ticks + "C" + channelId; - if (programInfo.AudioProperties != null) + if (programInfo.AudioProperties.Count != 0) { - if (programInfo.AudioProperties.Exists(item => string.Equals(item, "atmos", StringComparison.OrdinalIgnoreCase))) + if (programInfo.AudioProperties.Contains("atmos", StringComparer.OrdinalIgnoreCase)) { audioType = ProgramAudio.Atmos; } - else if (programInfo.AudioProperties.Exists(item => string.Equals(item, "dd 5.1", StringComparison.OrdinalIgnoreCase))) + else if (programInfo.AudioProperties.Contains("dd 5.1", StringComparer.OrdinalIgnoreCase)) { audioType = ProgramAudio.DolbyDigital; } - else if (programInfo.AudioProperties.Exists(item => string.Equals(item, "dd", StringComparison.OrdinalIgnoreCase))) + else if (programInfo.AudioProperties.Contains("dd", StringComparer.OrdinalIgnoreCase)) { audioType = ProgramAudio.DolbyDigital; } - else if (programInfo.AudioProperties.Exists(item => string.Equals(item, "stereo", StringComparison.OrdinalIgnoreCase))) + else if (programInfo.AudioProperties.Contains("stereo", StringComparer.OrdinalIgnoreCase)) { audioType = ProgramAudio.Stereo; } @@ -520,7 +516,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings lineups.Add(new NameIdPair { Name = string.IsNullOrWhiteSpace(lineup.Name) ? lineup.Lineup : lineup.Name, - Id = lineup.Uri[18..] + Id = lineup.Uri?[18..] }); } } @@ -790,7 +786,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { var channelNumber = GetChannelNumber(channel); - var station = allStations.Find(item => string.Equals(item.StationId, channel.StationId, StringComparison.OrdinalIgnoreCase)) + var station = allStations.FirstOrDefault(item => string.Equals(item.StationId, channel.StationId, StringComparison.OrdinalIgnoreCase)) ?? new StationDto { StationId = channel.StationId diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs index b881b307c..95ac996e0 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/BroadcasterDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,24 +11,24 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the city. /// [JsonPropertyName("city")] - public string City { get; set; } + public string? City { get; set; } /// /// Gets or sets the state. /// [JsonPropertyName("state")] - public string State { get; set; } + public string? State { get; set; } /// /// Gets or sets the postal code. /// [JsonPropertyName("postalCode")] - public string Postalcode { get; set; } + public string? Postalcode { get; set; } /// /// Gets or sets the country. /// [JsonPropertyName("country")] - public string Country { get; set; } + public string? Country { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs index 96b67d1eb..f6251b9ad 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CaptionDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,12 +11,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the content. /// [JsonPropertyName("content")] - public string Content { get; set; } + public string? Content { get; set; } /// /// Gets or sets the lang. /// [JsonPropertyName("lang")] - public string Lang { get; set; } + public string? Lang { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs index dac6f5f3e..0b7a2c63a 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CastDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,36 +11,36 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the billing order. /// [JsonPropertyName("billingOrder")] - public string BillingOrder { get; set; } + public string? BillingOrder { get; set; } /// /// Gets or sets the role. /// [JsonPropertyName("role")] - public string Role { get; set; } + public string? Role { get; set; } /// /// Gets or sets the name id. /// [JsonPropertyName("nameId")] - public string NameId { get; set; } + public string? NameId { get; set; } /// /// Gets or sets the person id. /// [JsonPropertyName("personId")] - public string PersonId { get; set; } + public string? PersonId { get; set; } /// /// Gets or sets the name. /// [JsonPropertyName("name")] - public string Name { get; set; } + public string? Name { get; set; } /// /// Gets or sets the character name. /// [JsonPropertyName("characterName")] - public string CharacterName { get; set; } + public string? CharacterName { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs index 8c9c2c1fc..87c327ed8 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ChannelDto.cs @@ -1,5 +1,4 @@ -#nullable disable - +using System; using System.Collections.Generic; using System.Text.Json.Serialization; @@ -14,18 +13,18 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the list of maps. /// [JsonPropertyName("map")] - public List Map { get; set; } + public IReadOnlyList Map { get; set; } = Array.Empty(); /// /// Gets or sets the list of stations. /// [JsonPropertyName("stations")] - public List Stations { get; set; } + public IReadOnlyList Stations { get; set; } = Array.Empty(); /// /// Gets or sets the metadata. /// [JsonPropertyName("metadata")] - public MetadataDto Metadata { get; set; } + public MetadataDto? Metadata { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs index 135b5bb08..c19cd2e48 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ContentRatingDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,12 +11,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the body. /// [JsonPropertyName("body")] - public string Body { get; set; } + public string? Body { get; set; } /// /// Gets or sets the code. /// [JsonPropertyName("code")] - public string Code { get; set; } + public string? Code { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs index 82d1001c8..f00c9accd 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/CrewDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,30 +11,30 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the billing order. /// [JsonPropertyName("billingOrder")] - public string BillingOrder { get; set; } + public string? BillingOrder { get; set; } /// /// Gets or sets the role. /// [JsonPropertyName("role")] - public string Role { get; set; } + public string? Role { get; set; } /// /// Gets or sets the name id. /// [JsonPropertyName("nameId")] - public string NameId { get; set; } + public string? NameId { get; set; } /// /// Gets or sets the person id. /// [JsonPropertyName("personId")] - public string PersonId { get; set; } + public string? PersonId { get; set; } /// /// Gets or sets the name. /// [JsonPropertyName("name")] - public string Name { get; set; } + public string? Name { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs index 68876b068..1a371965c 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DayDto.cs @@ -1,5 +1,4 @@ -#nullable disable - +using System; using System.Collections.Generic; using System.Text.Json.Serialization; @@ -10,30 +9,22 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// public class DayDto { - /// - /// Initializes a new instance of the class. - /// - public DayDto() - { - Programs = new List(); - } - /// /// Gets or sets the station id. /// [JsonPropertyName("stationID")] - public string StationId { get; set; } + public string? StationId { get; set; } /// /// Gets or sets the list of programs. /// [JsonPropertyName("programs")] - public List Programs { get; set; } + public IReadOnlyList Programs { get; set; } = Array.Empty(); /// /// Gets or sets the metadata schedule. /// [JsonPropertyName("metadata")] - public MetadataScheduleDto Metadata { get; set; } + public MetadataScheduleDto? Metadata { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs index d3e6ff393..ca6ae7fb1 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description1000Dto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,12 +11,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the description language. /// [JsonPropertyName("descriptionLanguage")] - public string DescriptionLanguage { get; set; } + public string? DescriptionLanguage { get; set; } /// /// Gets or sets the description. /// [JsonPropertyName("description")] - public string Description { get; set; } + public string? Description { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs index 04360266c..1577219ed 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/Description100Dto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,12 +11,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the description language. /// [JsonPropertyName("descriptionLanguage")] - public string DescriptionLanguage { get; set; } + public string? DescriptionLanguage { get; set; } /// /// Gets or sets the description. /// [JsonPropertyName("description")] - public string Description { get; set; } + public string? Description { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs index 3af36ae96..eaf4a340b 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/DescriptionsProgramDto.cs @@ -1,5 +1,4 @@ -#nullable disable - +using System; using System.Collections.Generic; using System.Text.Json.Serialization; @@ -14,12 +13,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the list of description 100. /// [JsonPropertyName("description100")] - public List Description100 { get; set; } + public IReadOnlyList Description100 { get; set; } = Array.Empty(); /// /// Gets or sets the list of description1000. /// [JsonPropertyName("description1000")] - public List Description1000 { get; set; } + public IReadOnlyList Description1000 { get; set; } = Array.Empty(); } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs index c3b2bd9c1..fbdfb1f71 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/EventDetailsDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,6 +11,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the sub type. /// [JsonPropertyName("subType")] - public string SubType { get; set; } + public string? SubType { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs index 3d8bea362..6852d89d7 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/GracenoteDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs index 1fb3decb2..b9844562f 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/HeadendsDto.cs @@ -1,5 +1,4 @@ -#nullable disable - +using System; using System.Collections.Generic; using System.Text.Json.Serialization; @@ -14,24 +13,24 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the headend. /// [JsonPropertyName("headend")] - public string Headend { get; set; } + public string? Headend { get; set; } /// /// Gets or sets the transport. /// [JsonPropertyName("transport")] - public string Transport { get; set; } + public string? Transport { get; set; } /// /// Gets or sets the location. /// [JsonPropertyName("location")] - public string Location { get; set; } + public string? Location { get; set; } /// /// Gets or sets the list of lineups. /// [JsonPropertyName("lineups")] - public List Lineups { get; set; } + public IReadOnlyList Lineups { get; set; } = Array.Empty(); } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs index 912e680dd..7e554ff1c 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,60 +11,60 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the width. /// [JsonPropertyName("width")] - public string Width { get; set; } + public string? Width { get; set; } /// /// Gets or sets the height. /// [JsonPropertyName("height")] - public string Height { get; set; } + public string? Height { get; set; } /// /// Gets or sets the uri. /// [JsonPropertyName("uri")] - public string Uri { get; set; } + public string? Uri { get; set; } /// /// Gets or sets the size. /// [JsonPropertyName("size")] - public string Size { get; set; } + public string? Size { get; set; } /// /// Gets or sets the aspect. /// [JsonPropertyName("aspect")] - public string aspect { get; set; } + public string? aspect { get; set; } /// /// Gets or sets the category. /// [JsonPropertyName("category")] - public string Category { get; set; } + public string? Category { get; set; } /// /// Gets or sets the text. /// [JsonPropertyName("text")] - public string Text { get; set; } + public string? Text { get; set; } /// /// Gets or sets the primary. /// [JsonPropertyName("primary")] - public string Primary { get; set; } + public string? Primary { get; set; } /// /// Gets or sets the tier. /// [JsonPropertyName("tier")] - public string Tier { get; set; } + public string? Tier { get; set; } /// /// Gets or sets the caption. /// [JsonPropertyName("caption")] - public CaptionDto Caption { get; set; } + public CaptionDto? Caption { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs index 52e920aa6..676e74525 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,30 +11,30 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the linup. /// [JsonPropertyName("lineup")] - public string Lineup { get; set; } + public string? Lineup { get; set; } /// /// Gets or sets the lineup name. /// [JsonPropertyName("name")] - public string Name { get; set; } + public string? Name { get; set; } /// /// Gets or sets the transport. /// [JsonPropertyName("transport")] - public string Transport { get; set; } + public string? Transport { get; set; } /// /// Gets or sets the location. /// [JsonPropertyName("location")] - public string Location { get; set; } + public string? Location { get; set; } /// /// Gets or sets the uri. /// [JsonPropertyName("uri")] - public string Uri { get; set; } + public string? Uri { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs index 15139ba3b..b0ee0ac8e 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs @@ -1,5 +1,4 @@ -#nullable disable - +using System; using System.Collections.Generic; using System.Text.Json.Serialization; @@ -20,18 +19,18 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the server id. /// [JsonPropertyName("serverID")] - public string ServerId { get; set; } + public string? ServerId { get; set; } /// /// Gets or sets the datetime. /// [JsonPropertyName("datetime")] - public string Datetime { get; set; } + public string? Datetime { get; set; } /// /// Gets or sets the list of lineups. /// [JsonPropertyName("lineups")] - public List Lineups { get; set; } + public IReadOnlyList Lineups { get; set; } = Array.Empty(); } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs index 7b235ed7f..fecc55e03 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LogoDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,7 +11,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the url. /// [JsonPropertyName("URL")] - public string Url { get; set; } + public string? Url { get; set; } /// /// Gets or sets the height. @@ -31,6 +29,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the md5. /// [JsonPropertyName("md5")] - public string Md5 { get; set; } + public string? Md5 { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs index 5140277b2..cc1841c17 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,19 +11,19 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the station id. /// [JsonPropertyName("stationID")] - public string StationId { get; set; } + public string? StationId { get; set; } /// /// Gets or sets the channel. /// [JsonPropertyName("channel")] - public string Channel { get; set; } + public string? Channel { get; set; } /// /// Gets or sets the logical channel number. /// [JsonPropertyName("logicalChannelNumber")] - public string LogicalChannelNumber { get; set; } + public string? LogicalChannelNumber { get; set; } /// /// Gets or sets the uhfvhf. diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs index 5a3893a35..40faa493c 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,18 +11,18 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the linup. /// [JsonPropertyName("lineup")] - public string Lineup { get; set; } + public string? Lineup { get; set; } /// /// Gets or sets the modified timestamp. /// [JsonPropertyName("modified")] - public string Modified { get; set; } + public string? Modified { get; set; } /// /// Gets or sets the transport. /// [JsonPropertyName("transport")] - public string Transport { get; set; } + public string? Transport { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs index 4057e9802..843ef9091 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,6 +11,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the gracenote object. /// [JsonPropertyName("gracenote")] - public GracenoteDto Gracenote { get; set; } + public GracenoteDto? Gracenote { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs index 4979296da..68fbeec46 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,25 +11,25 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the modified timestamp. /// [JsonPropertyName("modified")] - public string Modified { get; set; } + public string? Modified { get; set; } /// /// Gets or sets the md5. /// [JsonPropertyName("md5")] - public string Md5 { get; set; } + public string? Md5 { get; set; } /// /// Gets or sets the start date. /// [JsonPropertyName("startDate")] - public string StartDate { get; set; } + public string? StartDate { get; set; } /// /// Gets or sets the end date. /// [JsonPropertyName("endDate")] - public string EndDate { get; set; } + public string? EndDate { get; set; } /// /// Gets or sets the days count. diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs index 48d731d89..31bef423b 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MovieDto.cs @@ -1,5 +1,4 @@ -#nullable disable - +using System; using System.Collections.Generic; using System.Text.Json.Serialization; @@ -14,7 +13,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the year. /// [JsonPropertyName("year")] - public string Year { get; set; } + public string? Year { get; set; } /// /// Gets or sets the duration. @@ -26,6 +25,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the list of quality rating. /// [JsonPropertyName("qualityRating")] - public List QualityRating { get; set; } + public IReadOnlyList QualityRating { get; set; } = Array.Empty(); } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs index 42eddfff2..e8b15dc07 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MultipartDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs index a84c47c12..bfaed1e08 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs @@ -1,5 +1,4 @@ -#nullable disable - +using System; using System.Collections.Generic; using System.Text.Json.Serialization; @@ -14,85 +13,85 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the audience. /// [JsonPropertyName("audience")] - public string Audience { get; set; } + public string? Audience { get; set; } /// /// Gets or sets the program id. /// [JsonPropertyName("programID")] - public string ProgramId { get; set; } + public string? ProgramId { get; set; } /// /// Gets or sets the list of titles. /// [JsonPropertyName("titles")] - public List Titles { get; set; } + public IReadOnlyList Titles { get; set; } = Array.Empty(); /// /// Gets or sets the event details object. /// [JsonPropertyName("eventDetails")] - public EventDetailsDto EventDetails { get; set; } + public EventDetailsDto? EventDetails { get; set; } /// /// Gets or sets the descriptions. /// [JsonPropertyName("descriptions")] - public DescriptionsProgramDto Descriptions { get; set; } + public DescriptionsProgramDto? Descriptions { get; set; } /// /// Gets or sets the original air date. /// [JsonPropertyName("originalAirDate")] - public string OriginalAirDate { get; set; } + public string? OriginalAirDate { get; set; } /// /// Gets or sets the list of genres. /// [JsonPropertyName("genres")] - public List Genres { get; set; } + public IReadOnlyList Genres { get; set; } = Array.Empty(); /// /// Gets or sets the episode title. /// [JsonPropertyName("episodeTitle150")] - public string EpisodeTitle150 { get; set; } + public string? EpisodeTitle150 { get; set; } /// /// Gets or sets the list of metadata. /// [JsonPropertyName("metadata")] - public List Metadata { get; set; } + public IReadOnlyList Metadata { get; set; } = Array.Empty(); /// /// Gets or sets the list of content raitings. /// [JsonPropertyName("contentRating")] - public List ContentRating { get; set; } + public IReadOnlyList ContentRating { get; set; } = Array.Empty(); /// /// Gets or sets the list of cast. /// [JsonPropertyName("cast")] - public List Cast { get; set; } + public IReadOnlyList Cast { get; set; } = Array.Empty(); /// /// Gets or sets the list of crew. /// [JsonPropertyName("crew")] - public List Crew { get; set; } + public IReadOnlyList Crew { get; set; } = Array.Empty(); /// /// Gets or sets the entity type. /// [JsonPropertyName("entityType")] - public string EntityType { get; set; } + public string? EntityType { get; set; } /// /// Gets or sets the show type. /// [JsonPropertyName("showType")] - public string ShowType { get; set; } + public string? ShowType { get; set; } /// /// Gets or sets a value indicating whether there is image artwork. @@ -104,54 +103,54 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the primary image. /// [JsonPropertyName("primaryImage")] - public string PrimaryImage { get; set; } + public string? PrimaryImage { get; set; } /// /// Gets or sets the thumb image. /// [JsonPropertyName("thumbImage")] - public string ThumbImage { get; set; } + public string? ThumbImage { get; set; } /// /// Gets or sets the backdrop image. /// [JsonPropertyName("backdropImage")] - public string BackdropImage { get; set; } + public string? BackdropImage { get; set; } /// /// Gets or sets the banner image. /// [JsonPropertyName("bannerImage")] - public string BannerImage { get; set; } + public string? BannerImage { get; set; } /// /// Gets or sets the image id. /// [JsonPropertyName("imageID")] - public string ImageId { get; set; } + public string? ImageId { get; set; } /// /// Gets or sets the md5. /// [JsonPropertyName("md5")] - public string Md5 { get; set; } + public string? Md5 { get; set; } /// /// Gets or sets the list of content advisory. /// [JsonPropertyName("contentAdvisory")] - public List ContentAdvisory { get; set; } + public IReadOnlyList ContentAdvisory { get; set; } = Array.Empty(); /// /// Gets or sets the movie object. /// [JsonPropertyName("movie")] - public MovieDto Movie { get; set; } + public MovieDto? Movie { get; set; } /// /// Gets or sets the list of recommendations. /// [JsonPropertyName("recommendations")] - public List Recommendations { get; set; } + public IReadOnlyList Recommendations { get; set; } = Array.Empty(); } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs index ad5389100..ff039c1cf 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs @@ -1,5 +1,4 @@ -#nullable disable - +using System; using System.Collections.Generic; using System.Text.Json.Serialization; @@ -14,13 +13,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the program id. /// [JsonPropertyName("programID")] - public string ProgramId { get; set; } + public string? ProgramId { get; set; } /// /// Gets or sets the air date time. /// [JsonPropertyName("airDateTime")] - public string AirDateTime { get; set; } + public string? AirDateTime { get; set; } /// /// Gets or sets the duration. @@ -32,25 +31,25 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the md5. /// [JsonPropertyName("md5")] - public string Md5 { get; set; } + public string? Md5 { get; set; } /// /// Gets or sets the list of audio properties. /// [JsonPropertyName("audioProperties")] - public List AudioProperties { get; set; } + public IReadOnlyList AudioProperties { get; set; } = Array.Empty(); /// /// Gets or sets the list of video properties. /// [JsonPropertyName("videoProperties")] - public List VideoProperties { get; set; } + public IReadOnlyList VideoProperties { get; set; } = Array.Empty(); /// /// Gets or sets the list of ratings. /// [JsonPropertyName("ratings")] - public List Ratings { get; set; } + public IReadOnlyList Ratings { get; set; } = Array.Empty(); /// /// Gets or sets a value indicating whether this program is new. @@ -62,13 +61,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the multipart object. /// [JsonPropertyName("multipart")] - public MultipartDto Multipart { get; set; } + public MultipartDto? Multipart { get; set; } /// /// Gets or sets the live tape delay. /// [JsonPropertyName("liveTapeDelay")] - public string LiveTapeDelay { get; set; } + public string? LiveTapeDelay { get; set; } /// /// Gets or sets a value indicating whether this is the premiere. @@ -86,6 +85,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the premiere or finale. /// [JsonPropertyName("isPremiereOrFinale")] - public string IsPremiereOrFinale { get; set; } + public string? IsPremiereOrFinale { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs index 5cd0a7459..c5ddcf7c5 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/QualityRatingDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,30 +11,30 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the ratings body. /// [JsonPropertyName("ratingsBody")] - public string RatingsBody { get; set; } + public string? RatingsBody { get; set; } /// /// Gets or sets the rating. /// [JsonPropertyName("rating")] - public string Rating { get; set; } + public string? Rating { get; set; } /// /// Gets or sets the min rating. /// [JsonPropertyName("minRating")] - public string MinRating { get; set; } + public string? MinRating { get; set; } /// /// Gets or sets the max rating. /// [JsonPropertyName("maxRating")] - public string MaxRating { get; set; } + public string? MaxRating { get; set; } /// /// Gets or sets the increment. /// [JsonPropertyName("increment")] - public string Increment { get; set; } + public string? Increment { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs index 948b83144..e04b619a4 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RatingDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,12 +11,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the body. /// [JsonPropertyName("body")] - public string Body { get; set; } + public string? Body { get; set; } /// /// Gets or sets the code. /// [JsonPropertyName("code")] - public string Code { get; set; } + public string? Code { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs index 1308f45ce..c8f79fd1c 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RecommendationDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,12 +11,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the program id. /// [JsonPropertyName("programID")] - public string ProgramId { get; set; } + public string? ProgramId { get; set; } /// /// Gets or sets the title. /// [JsonPropertyName("title120")] - public string Title120 { get; set; } + public string? Title120 { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs index fb7a31ac8..0cd05709b 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/RequestScheduleForChannelDto.cs @@ -1,5 +1,4 @@ -#nullable disable - +using System; using System.Collections.Generic; using System.Text.Json.Serialization; @@ -14,12 +13,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the station id. /// [JsonPropertyName("stationID")] - public string StationId { get; set; } + public string? StationId { get; set; } /// /// Gets or sets the list of dates. /// [JsonPropertyName("date")] - public List Date { get; set; } + public IReadOnlyList Date { get; set; } = Array.Empty(); } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs index 34302370d..84e224b71 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ShowImagesDto.cs @@ -1,5 +1,4 @@ -#nullable disable - +using System; using System.Collections.Generic; using System.Text.Json.Serialization; @@ -14,12 +13,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the program id. /// [JsonPropertyName("programID")] - public string ProgramId { get; set; } + public string? ProgramId { get; set; } /// /// Gets or sets the list of data. /// [JsonPropertyName("data")] - public List Data { get; set; } + public IReadOnlyList Data { get; set; } = Array.Empty(); } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs index 12f3576c6..1b76b22e3 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs @@ -1,5 +1,4 @@ -#nullable disable - +using System; using System.Collections.Generic; using System.Text.Json.Serialization; @@ -14,49 +13,49 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the station id. /// [JsonPropertyName("stationID")] - public string StationId { get; set; } + public string? StationId { get; set; } /// /// Gets or sets the name. /// [JsonPropertyName("name")] - public string Name { get; set; } + public string? Name { get; set; } /// /// Gets or sets the callsign. /// [JsonPropertyName("callsign")] - public string Callsign { get; set; } + public string? Callsign { get; set; } /// /// Gets or sets the broadcast language. /// [JsonPropertyName("broadcastLanguage")] - public List BroadcastLanguage { get; set; } + public IReadOnlyList BroadcastLanguage { get; set; } = Array.Empty(); /// /// Gets or sets the description language. /// [JsonPropertyName("descriptionLanguage")] - public List DescriptionLanguage { get; set; } + public IReadOnlyList DescriptionLanguage { get; set; } = Array.Empty(); /// /// Gets or sets the broadcaster. /// [JsonPropertyName("broadcaster")] - public BroadcasterDto Broadcaster { get; set; } + public BroadcasterDto? Broadcaster { get; set; } /// /// Gets or sets the affiliate. /// [JsonPropertyName("affiliate")] - public string Affiliate { get; set; } + public string? Affiliate { get; set; } /// /// Gets or sets the logo. /// [JsonPropertyName("logo")] - public LogoDto Logo { get; set; } + public LogoDto? Logo { get; set; } /// /// Gets or set a value indicating whether it is commercial free. diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs index 06c95524b..61cd4a9b0 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TitleDto.cs @@ -1,5 +1,3 @@ -#nullable disable - using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -13,6 +11,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the title. /// [JsonPropertyName("title120")] - public string Title120 { get; set; } + public string? Title120 { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs index c3ec1c7d6..fb5ed95ac 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs @@ -1,5 +1,4 @@ -#nullable disable - +using System; using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -19,18 +18,24 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the response message. /// [JsonPropertyName("message")] - public string Message { get; set; } + public string? Message { get; set; } /// /// Gets or sets the server id. /// [JsonPropertyName("serverID")] - public string ServerId { get; set; } + public string? ServerId { get; set; } /// /// Gets or sets the token. /// [JsonPropertyName("token")] - public string Token { get; set; } + public string? Token { get; set; } + + /// + /// Gets or sets the current datetime. + /// + [JsonPropertyName("datetime")] + public DateTime? DateTime { get; set; } } } -- cgit v1.2.3 From 47e24a2cf77e6c3fe50eb5398fa56950a047ed7b Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Fri, 3 Sep 2021 12:35:52 -0600 Subject: Add SchedulesDirect json tests --- .../LiveTv/Listings/SchedulesDirect.cs | 62 +++--- .../Listings/SchedulesDirectDtos/ImageDataDto.cs | 2 +- .../Listings/SchedulesDirectDtos/LineupDto.cs | 6 + .../Listings/SchedulesDirectDtos/LineupsDto.cs | 2 +- .../LiveTv/Listings/SchedulesDirectDtos/MapDto.cs | 12 + .../SchedulesDirectDtos/MetadataProgramsDto.cs | 2 +- .../SchedulesDirectDtos/ProgramDetailsDto.cs | 2 +- .../Listings/SchedulesDirectDtos/ProgramDto.cs | 2 +- .../Listings/SchedulesDirectDtos/TokenDto.cs | 6 + .../Jellyfin.Server.Implementations.Tests.csproj | 3 + .../SchedulesDirectDeserializeTests.cs | 245 +++++++++++++++++++++ .../TestData/headends_response.json | 113 ++++++++++ .../SchedulesDirect/TestData/lineup_response.json | 18 ++ .../SchedulesDirect/TestData/lineups_response.json | 40 ++++ .../TestData/metadata_programs_response.json | 51 +++++ .../TestData/programs_response.json | 245 +++++++++++++++++++++ .../TestData/schedules_request.json | 16 ++ .../TestData/schedules_response.json | 35 +++ .../TestData/token_live_response.json | 7 + .../TestData/token_offline_response.json | 8 + 20 files changed, 841 insertions(+), 36 deletions(-) create mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs create mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/headends_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineup_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineups_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/metadata_programs_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/programs_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_request.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_live_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_offline_response.json (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 41c3bafa0..e8562b8c5 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -9,12 +9,14 @@ using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Json; using System.Net.Mime; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos; +using Jellyfin.Extensions; using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller.LiveTv; @@ -110,19 +112,19 @@ namespace Emby.Server.Implementations.LiveTv.Listings 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); - _logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId); + var dailySchedules = await JsonSerializer.DeserializeAsync>(responseStream, _jsonOptions, cancellationToken).ConfigureAwait(false); + _logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules!.Count, channelId); using var programRequestOptions = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/programs"); programRequestOptions.Headers.TryAddWithoutValidation("token", token); var programIds = dailySchedules.SelectMany(d => d.Programs.Select(s => s.ProgramId)).Distinct(); - programRequestOptions.Content = new StringContent("[\"" + string.Join("\", \"", programIds) + "\"]", Encoding.UTF8, MediaTypeNames.Application.Json); + programRequestOptions.Content = new StringContent(JsonSerializer.Serialize(programIds), Encoding.UTF8, MediaTypeNames.Application.Json); 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 programDict = programDetails.ToDictionary(p => p.ProgramId, y => y); + var programDetails = await JsonSerializer.DeserializeAsync>(innerResponseStream, _jsonOptions, cancellationToken).ConfigureAwait(false); + var programDict = programDetails!.ToDictionary(p => p.ProgramId, y => y); var programIdsWithImages = programDetails .Where(p => p.HasImageArtwork).Select(p => p.ProgramId) @@ -138,6 +140,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings // schedule.ProgramId + " which says it has images? " + // programDict[schedule.ProgramId].hasImageArtwork); + if (string.IsNullOrEmpty(schedule.ProgramId)) + { + continue; + } + if (images != null) { var imageIndex = images.FindIndex(i => i.ProgramId == schedule.ProgramId[..10]); @@ -145,7 +152,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings { var programEntry = programDict[schedule.ProgramId]; - var allImages = images[imageIndex].Data ?? new List(); + var allImages = images[imageIndex].Data; var imagesWithText = allImages.Where(i => string.Equals(i.Text, "yes", StringComparison.OrdinalIgnoreCase)); var imagesWithoutText = allImages.Where(i => string.Equals(i.Text, "no", StringComparison.OrdinalIgnoreCase)); @@ -213,7 +220,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings private ProgramInfo GetProgram(string channelId, ProgramDto programInfo, ProgramDetailsDto details) { - var startAt = GetDate(programInfo.AirDateTime); + if (programInfo.AirDateTime == null) + { + return null; + } + + var startAt = programInfo.AirDateTime.Value; var endAt = startAt.AddSeconds(programInfo.Duration); var audioType = ProgramAudio.Stereo; @@ -351,9 +363,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings } } - if (!string.IsNullOrWhiteSpace(details.OriginalAirDate)) + if (details.OriginalAirDate != null) { - info.OriginalAirDate = DateTime.Parse(details.OriginalAirDate, CultureInfo.InvariantCulture); + info.OriginalAirDate = details.OriginalAirDate; info.ProductionYear = info.OriginalAirDate.Value.Year; } @@ -380,18 +392,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings return info; } - private static DateTime GetDate(string value) - { - var date = DateTime.ParseExact(value, "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", CultureInfo.InvariantCulture); - - if (date.Kind != DateTimeKind.Utc) - { - date = DateTime.SpecifyKind(date, DateTimeKind.Utc); - } - - return date; - } - private string GetProgramImage(string apiUrl, IEnumerable images, bool returnDefaultImage, double desiredAspect) { var match = images @@ -445,14 +445,14 @@ namespace Emby.Server.Implementations.LiveTv.Listings return result; } - private async Task> GetImageForPrograms( + private async Task> GetImageForPrograms( ListingsProviderInfo info, IReadOnlyList programIds, CancellationToken cancellationToken) { if (programIds.Count == 0) { - return new List(); + return Array.Empty(); } StringBuilder str = new StringBuilder("[", 1 + (programIds.Count * 13)); @@ -476,13 +476,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings { 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 JsonSerializer.DeserializeAsync>(response, _jsonOptions, cancellationToken).ConfigureAwait(false); } catch (Exception ex) { _logger.LogError(ex, "Error getting image info from schedules direct"); - return new List(); + return Array.Empty(); } } @@ -505,7 +505,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings 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 JsonSerializer.DeserializeAsync>(response, _jsonOptions, cancellationToken).ConfigureAwait(false); if (root != null) { @@ -647,7 +647,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings response.EnsureSuccessStatusCode(); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); var root = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); - if (string.Equals(root.Message, "OK", StringComparison.Ordinal)) + if (string.Equals(root?.Message, "OK", StringComparison.Ordinal)) { _logger.LogInformation("Authenticated with Schedules Direct token: {Token}", root.Token); return root.Token; @@ -704,12 +704,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var response = httpResponse.Content; var root = await JsonSerializer.DeserializeAsync(stream, _jsonOptions, cancellationToken).ConfigureAwait(false); - return root.Lineups.Any(i => string.Equals(info.ListingsId, i.Lineup, StringComparison.OrdinalIgnoreCase)); + return root?.Lineups.Any(i => string.Equals(info.ListingsId, i.Lineup, StringComparison.OrdinalIgnoreCase)) ?? false; } catch (HttpRequestException ex) { // SchedulesDirect returns 400 if no lineups are configured. - if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.BadRequest) + if (ex.StatusCode is HttpStatusCode.BadRequest) { return false; } @@ -775,10 +775,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings 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); - _logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.Map.Count); + _logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root!.Map.Count); _logger.LogInformation("Mapping Stations to Channel"); - var allStations = root.Stations ?? new List(); + var allStations = root.Stations; var map = root.Map; var list = new List(map.Count); diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs index 7e554ff1c..a1ae3ca6d 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs @@ -35,7 +35,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the aspect. /// [JsonPropertyName("aspect")] - public string? aspect { get; set; } + public string? Aspect { get; set; } /// /// Gets or sets the category. diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs index 676e74525..3dc64e5d8 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupDto.cs @@ -36,5 +36,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// [JsonPropertyName("uri")] public string? Uri { get; set; } + + /// + /// Gets or sets a value indicating whether this lineup was deleted. + /// + [JsonPropertyName("isDeleted")] + public bool? IsDeleted { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs index b0ee0ac8e..a635c5987 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs @@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the datetime. /// [JsonPropertyName("datetime")] - public string? Datetime { get; set; } + public DateTime? Datetime { get; set; } /// /// Gets or sets the list of lineups. diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs index cc1841c17..2420307b4 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs @@ -19,6 +19,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos [JsonPropertyName("channel")] public string? Channel { get; set; } + /// + /// Gets or sets the provider callsign. + /// + [JsonPropertyName("providerCallsign")] + public string? ProvderCallsign { get; set; } + /// /// Gets or sets the logical channel number. /// @@ -42,5 +48,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// [JsonPropertyName("atscMinor")] public int AtscMinor { get; set; } + + /// + /// Gets or sets the match type. + /// + [JsonPropertyName("matchType")] + public string? MatchType { get;set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs index 843ef9091..43f290156 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataProgramsDto.cs @@ -10,7 +10,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// /// Gets or sets the gracenote object. /// - [JsonPropertyName("gracenote")] + [JsonPropertyName("Gracenote")] public GracenoteDto? Gracenote { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs index bfaed1e08..84c48f67f 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDetailsDto.cs @@ -43,7 +43,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the original air date. /// [JsonPropertyName("originalAirDate")] - public string? OriginalAirDate { get; set; } + public DateTime? OriginalAirDate { get; set; } /// /// Gets or sets the list of genres. diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs index ff039c1cf..60389b45b 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ProgramDto.cs @@ -19,7 +19,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the air date time. /// [JsonPropertyName("airDateTime")] - public string? AirDateTime { get; set; } + public DateTime? AirDateTime { get; set; } /// /// Gets or sets the duration. diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs index fb5ed95ac..561f79c5a 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs @@ -37,5 +37,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// [JsonPropertyName("datetime")] public DateTime? DateTime { get; set; } + + /// + /// Gets or sets the response message. + /// + [JsonPropertyName("response")] + public string? Response { get; set; } } } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index 9b6ab7bdf..e02e357ca 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -16,6 +16,9 @@ PreserveNewest + + PreserveNewest + diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs new file mode 100644 index 000000000..84ac3ea47 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs @@ -0,0 +1,245 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos; +using Jellyfin.Extensions.Json; +using Xunit; + +namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect +{ + public class SchedulesDirectDeserializeTests + { + private readonly JsonSerializerOptions _jsonOptions; + + public SchedulesDirectDeserializeTests() + { + _jsonOptions = JsonDefaults.Options; + } + + /// + /// /token reponse. + /// + [Fact] + public void Deserialize_Token_Response_Live_Success() + { + var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/token_live_response.json"); + var tokenDto = JsonSerializer.Deserialize(bytes); + + Assert.NotNull(tokenDto); + Assert.Equal(0, tokenDto!.Code); + Assert.Equal("OK", tokenDto.Message); + Assert.Equal("AWS-SD-web.1", tokenDto.ServerId); + Assert.Equal(new DateTime(2016, 08, 23, 13, 55, 25, DateTimeKind.Utc), tokenDto.DateTime); + Assert.Equal("f3fca79989cafe7dead71beefedc812b", tokenDto.Token); + } + + /// + /// /token response. + /// + [Fact] + public void Deserialize_Token_Response_Offline_Success() + { + var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/token_offline_response.json"); + var tokenDto = JsonSerializer.Deserialize(bytes); + + Assert.NotNull(tokenDto); + Assert.Equal(3_000, tokenDto!.Code); + Assert.Equal("Server offline for maintenance.", tokenDto.Message); + Assert.Equal("20141201.web.1", tokenDto.ServerId); + Assert.Equal(new DateTime(2015, 04, 23, 00, 03, 32, DateTimeKind.Utc), tokenDto.DateTime); + Assert.Equal("CAFEDEADBEEFCAFEDEADBEEFCAFEDEADBEEFCAFE", tokenDto.Token); + Assert.Equal("SERVICE_OFFLINE", tokenDto.Response); + } + + /// + /// /schedules request. + /// + [Fact] + public void Serialize_Schedule_Request_Success() + { + var expectedString = File.ReadAllText("LiveTv/SchedulesDirect/TestData/schedules_request.json").Trim(); + + var requestObject = new RequestScheduleForChannelDto[] + { + new RequestScheduleForChannelDto + { + StationId = "20454", + Date = new[] + { + "2015-03-13", + "2015-03-17" + } + }, + new RequestScheduleForChannelDto + { + StationId = "10021", + Date = new[] + { + "2015-03-12", + "2015-03-13" + } + } + }; + + var jsonOptions = new JsonSerializerOptions(_jsonOptions) + { + WriteIndented = true + }; + + var requestString = JsonSerializer.Serialize(requestObject, jsonOptions); + Assert.Equal(expectedString, requestString); + } + + /// + /// /schedules response. + /// + [Fact] + public void Deserialize_Schedule_Response_Success() + { + var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/schedules_response.json"); + var days = JsonSerializer.Deserialize>(bytes); + + Assert.NotNull(days); + Assert.Equal(1, days!.Count); + + var dayDto = days[0]; + Assert.Equal("20454", dayDto.StationId); + Assert.Equal(2, dayDto.Programs.Count); + + Assert.Equal("SH005371070000", dayDto.Programs[0].ProgramId); + Assert.Equal(new DateTime(2015, 03, 03, 00, 00, 00, DateTimeKind.Utc), dayDto.Programs[0].AirDateTime); + Assert.Equal(1_800, dayDto.Programs[0].Duration); + Assert.Equal("Sy8HEMBPcuiAx3FBukUhKQ", dayDto.Programs[0].Md5); + Assert.True(dayDto.Programs[0].New); + Assert.Equal(2, dayDto.Programs[0].AudioProperties.Count); + Assert.Equal("stereo", dayDto.Programs[0].AudioProperties[0]); + Assert.Equal("cc", dayDto.Programs[0].AudioProperties[1]); + Assert.Equal(1, dayDto.Programs[0].VideoProperties.Count); + Assert.Equal("hdtv", dayDto.Programs[0].VideoProperties[0]); + } + + /// + /// /programs response. + /// + [Fact] + public void Deserialize_Program_Response_Success() + { + var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/programs_response.json"); + var programDtos = JsonSerializer.Deserialize>(bytes); + + Assert.NotNull(programDtos); + Assert.Equal(2, programDtos!.Count); + Assert.Equal("EP000000060003", programDtos[0].ProgramId); + Assert.Equal(1, programDtos[0].Titles.Count); + Assert.Equal("'Allo 'Allo!", programDtos[0].Titles[0].Title120); + Assert.Equal("Series", programDtos[0].EventDetails?.SubType); + Assert.Equal("en", programDtos[0].Descriptions?.Description1000[0].DescriptionLanguage); + Assert.Equal("A disguised British Intelligence officer is sent to help the airmen.", programDtos[0].Descriptions?.Description1000[0].Description); + Assert.Equal(new DateTime(1985, 11, 04), programDtos[0].OriginalAirDate); + Assert.Equal(1, programDtos[0].Genres.Count); + Assert.Equal("Sitcom", programDtos[0].Genres[0]); + Assert.Equal("The Poloceman Cometh", programDtos[0].EpisodeTitle150); + Assert.Equal(2, programDtos[0].Metadata[0].Gracenote?.Season); + Assert.Equal(3, programDtos[0].Metadata[0].Gracenote?.Episode); + Assert.Equal(13, programDtos[0].Cast.Count); + Assert.Equal("383774", programDtos[0].Cast[0].PersonId); + Assert.Equal("392649", programDtos[0].Cast[0].NameId); + Assert.Equal("Gorden Kaye", programDtos[0].Cast[0].Name); + Assert.Equal("Actor", programDtos[0].Cast[0].Role); + Assert.Equal("01", programDtos[0].Cast[0].BillingOrder); + Assert.Equal(3, programDtos[0].Crew.Count); + Assert.Equal("354407", programDtos[0].Crew[0].PersonId); + Assert.Equal("363281", programDtos[0].Crew[0].NameId); + Assert.Equal("David Croft", programDtos[0].Crew[0].Name); + Assert.Equal("Director", programDtos[0].Crew[0].Role); + Assert.Equal("01", programDtos[0].Crew[0].BillingOrder); + } + + /// + /// /metadata/programs response. + /// + [Fact] + public void Deserialize_Metadata_Programs_Response_Success() + { + var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/metadata_programs_response.json"); + var showImagesDtos = JsonSerializer.Deserialize>(bytes); + + Assert.NotNull(showImagesDtos); + Assert.Equal(1, showImagesDtos!.Count); + Assert.Equal("SH00712240", showImagesDtos[0].ProgramId); + Assert.Equal(4, showImagesDtos[0].Data.Count); + Assert.Equal("135", showImagesDtos[0].Data[0].Width); + Assert.Equal("180", showImagesDtos[0].Data[0].Height); + Assert.Equal("assets/p282288_b_v2_aa.jpg", showImagesDtos[0].Data[0].Uri); + Assert.Equal("Sm", showImagesDtos[0].Data[0].Size); + Assert.Equal("3x4", showImagesDtos[0].Data[0].Aspect); + Assert.Equal("Banner-L3", showImagesDtos[0].Data[0].Category); + Assert.Equal("yes", showImagesDtos[0].Data[0].Text); + Assert.Equal("true", showImagesDtos[0].Data[0].Primary); + Assert.Equal("Series", showImagesDtos[0].Data[0].Tier); + } + + /// + /// /headends response. + /// + [Fact] + public void Deserialize_Headends_Response_Success() + { + var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/headends_response.json"); + var headendsDtos = JsonSerializer.Deserialize>(bytes); + + Assert.NotNull(headendsDtos); + Assert.Equal(8, headendsDtos!.Count); + Assert.Equal("CA00053", headendsDtos[0].Headend); + Assert.Equal("Cable", headendsDtos[0].Transport); + Assert.Equal("Beverly Hills", headendsDtos[0].Location); + Assert.Equal(2, headendsDtos[0].Lineups.Count); + Assert.Equal("Time Warner Cable - Cable", headendsDtos[0].Lineups[0].Name); + Assert.Equal("USA-CA00053-DEFAULT", headendsDtos[0].Lineups[0].Lineup); + Assert.Equal("/20141201/lineups/USA-CA00053-DEFAULT", headendsDtos[0].Lineups[0].Uri); + } + + /// + /// /lineups response. + /// + [Fact] + public void Deserialize_Lineups_Response_Success() + { + var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/lineups_response.json"); + var lineupsDto = JsonSerializer.Deserialize(bytes); + + Assert.NotNull(lineupsDto); + Assert.Equal(0, lineupsDto!.Code); + Assert.Equal("20141201.web.1", lineupsDto.ServerId); + Assert.Equal(new DateTime(2015, 04, 17, 14, 22, 17, DateTimeKind.Utc), lineupsDto.Datetime); + Assert.Equal(5, lineupsDto.Lineups.Count); + Assert.Equal("GBR-0001317-DEFAULT", lineupsDto.Lineups[0].Lineup); + Assert.Equal("Freeview - Carlton - LWT (Southeast)", lineupsDto.Lineups[0].Name); + Assert.Equal("DVB-T", lineupsDto.Lineups[0].Transport); + Assert.Equal("London", lineupsDto.Lineups[0].Location); + Assert.Equal("/20141201/lineups/GBR-0001317-DEFAULT", lineupsDto.Lineups[0].Uri); + + Assert.Equal("DELETED LINEUP", lineupsDto.Lineups[4].Name); + Assert.True(lineupsDto.Lineups[4].IsDeleted); + } + + /// + /// /lineup/:id response. + /// + [Fact] + public void Deserialize_Lineup_Response_Success() + { + var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/lineup_response.json"); + var channelDto = JsonSerializer.Deserialize(bytes); + + Assert.NotNull(channelDto); + Assert.Equal(2, channelDto!.Map.Count); + Assert.Equal("24326", channelDto.Map[0].StationId); + Assert.Equal("001", channelDto.Map[0].Channel); + Assert.Equal("BBC ONE South", channelDto.Map[0].ProvderCallsign); + Assert.Equal("1", channelDto.Map[0].LogicalChannelNumber); + Assert.Equal("providerCallsign", channelDto.Map[0].MatchType); + } + } +} diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/headends_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/headends_response.json new file mode 100644 index 000000000..a1a96cf87 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/headends_response.json @@ -0,0 +1,113 @@ +[ + { + "headend": "CA00053", + "transport": "Cable", + "location": "Beverly Hills", + "lineups": [ + { + "name": "Time Warner Cable - Cable", + "lineup": "USA-CA00053-DEFAULT", + "uri": "/20141201/lineups/USA-CA00053-DEFAULT" + }, + { + "name": "Time Warner Cable - Digital", + "lineup": "USA-CA00053-X", + "uri": "/20141201/lineups/USA-CA00053-X" + } + ] + }, + { + "headend": "CA61222", + "transport": "Cable", + "location": "Beverly Hills", + "lineups": [ + { + "name": "Mulholland Estates - Cable", + "lineup": "USA-CA61222-DEFAULT", + "uri": "/20141201/lineups/USA-CA61222-DEFAULT" + } + ] + }, + { + "headend": "CA66511", + "transport": "Cable", + "location": "Los Angeles", + "lineups": [ + { + "name": "AT&T U-verse TV - Digital", + "lineup": "USA-CA66511-X", + "uri": "/20141201/lineups/USA-CA66511-X" + } + ] + }, + { + "headend": "CA67309", + "transport": "Cable", + "location": "Westchester", + "lineups": [ + { + "name": "Time Warner Cable Sherman Oaks - Cable", + "lineup": "USA-CA67309-DEFAULT", + "uri": "/20141201/lineups/USA-CA67309-DEFAULT" + }, + { + "name": "Time Warner Cable Sherman Oaks - Digital", + "lineup": "USA-CA67309-X", + "uri": "/20141201/lineups/USA-CA67309-X" + } + ] + }, + { + "headend": "CA67310", + "transport": "Cable", + "location": "Eagle Rock", + "lineups": [ + { + "name": "Time Warner Cable City of Los Angeles - Cable", + "lineup": "USA-CA67310-DEFAULT", + "uri": "/20141201/lineups/USA-CA67310-DEFAULT" + }, + { + "name": "Time Warner Cable City of Los Angeles - Digital", + "lineup": "USA-CA67310-X", + "uri": "/20141201/lineups/USA-CA67310-X" + } + ] + }, + { + "headend": "DISH803", + "transport": "Satellite", + "location": "Los Angeles", + "lineups": [ + { + "name": "DISH Los Angeles - Satellite", + "lineup": "USA-DISH803-DEFAULT", + "uri": "/20141201/lineups/USA-DISH803-DEFAULT" + } + ] + }, + { + "headend": "DITV803", + "transport": "Satellite", + "location": "Los Angeles", + "lineups": [ + { + "name": "DIRECTV Los Angeles - Satellite", + "lineup": "USA-DITV803-DEFAULT", + "uri": "/20141201/lineups/USA-DITV803-DEFAULT" + } + ] + }, + { + "headend": "90210", + "transport": "Antenna", + "location": "90210", + "lineups": [ + { + "name": "Antenna", + "lineup": "USA-OTA-90210", + "uri": "/20141201/lineups/USA-OTA-90210" + } + ] + } +] diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineup_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineup_response.json new file mode 100644 index 000000000..5c5e36e30 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineup_response.json @@ -0,0 +1,18 @@ +{ + "map": [ + { + "stationID": "24326", + "channel": "001", + "providerCallsign": "BBC ONE South", + "logicalChannelNumber": "1", + "matchType": "providerCallsign" + }, + { + "stationID": "17154", + "channel": "002", + "providerCallsign": "BBC TWO", + "logicalChannelNumber": "2", + "matchType": "providerCallsign" + } + ] +} diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineups_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineups_response.json new file mode 100644 index 000000000..257b682ee --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineups_response.json @@ -0,0 +1,40 @@ +{ + "code": 0, + "serverID": "20141201.web.1", + "datetime": "2015-04-17T14:22:17Z", + "lineups": [ + { + "lineup": "GBR-0001317-DEFAULT", + "name": "Freeview - Carlton - LWT (Southeast)", + "transport": "DVB-T", + "location": "London", + "uri": "/20141201/lineups/GBR-0001317-DEFAULT" + }, + { + "lineup": "USA-IL57303-X", + "name": "Comcast Waukegan/Lake Forest Area - Digital", + "transport": "Cable", + "location": "Lake Forest", + "uri": "/20141201/lineups/USA-IL57303-X" + }, + { + "lineup": "USA-NY67791-X", + "name": "Verizon Fios Queens - Digital", + "transport": "Cable", + "location": "Fresh Meadows", + "uri": "/20141201/lineups/USA-NY67791-X" + }, + { + "lineup": "USA-OTA-60030", + "name": "Local Over the Air Broadcast", + "transport": "Antenna", + "location": "60030", + "uri": "/20141201/lineups/USA-OTA-60030" + }, + { + "lineup": "USA-WI61859-DEFAULT", + "name": "DELETED LINEUP", + "isDeleted": true + } + ] +} diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/metadata_programs_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/metadata_programs_response.json new file mode 100644 index 000000000..b75e777b4 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/metadata_programs_response.json @@ -0,0 +1,51 @@ +[ + { + "programID": "SH00712240", + "data": [ + { + "width": "135", + "height": "180", + "uri": "assets/p282288_b_v2_aa.jpg", + "size": "Sm", + "aspect": "3x4", + "category": "Banner-L3", + "text": "yes", + "primary": "true", + "tier": "Series" + }, + { + "width": "720", + "height": "540", + "uri": "assets/p282288_b_h6_aa.jpg", + "size": "Lg", + "aspect": "4x3", + "category": "Banner-L3", + "text": "yes", + "primary": "true", + "tier": "Series" + }, + { + "width": "960", + "height": "1440", + "uri": "assets/p282288_b_v8_aa.jpg", + "size": "Ms", + "aspect": "2x3", + "category": "Banner-L3", + "text": "yes", + "primary": "true", + "tier": "Series" + }, + { + "width": "180", + "height": "135", + "uri": "assets/p282288_b_h5_aa.jpg", + "size": "Sm", + "aspect": "4x3", + "category": "Banner-L3", + "text": "yes", + "primary": "true", + "tier": "Series" + } + ] + } +] diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/programs_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/programs_response.json new file mode 100644 index 000000000..154c02f97 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/programs_response.json @@ -0,0 +1,245 @@ +[ + { + "programID": "EP000000060003", + "titles": [{ + "title120": "'Allo 'Allo!" + }], + "eventDetails": { + "subType": "Series" + }, + "descriptions": { + "description1000": [{ + "descriptionLanguage": "en", + "description": "A disguised British Intelligence officer is sent to help the airmen." + }] + }, + "originalAirDate": "1985-11-04", + "genres": ["Sitcom"], + "episodeTitle150": "The Poloceman Cometh", + "metadata": [{ + "Gracenote": { + "season": 2, + "episode": 3 + } + }], + "cast": [{ + "personId": "383774", + "nameId": "392649", + "name": "Gorden Kaye", + "role": "Actor", + "billingOrder": "01" + }, { + "personId": "246840", + "nameId": "250387", + "name": "Carmen Silvera", + "role": "Actor", + "billingOrder": "02" + }, { + "personId": "376955", + "nameId": "385830", + "name": "Rose Hill", + "role": "Actor", + "billingOrder": "03" + }, { + "personId": "259773", + "nameId": "263340", + "name": "Vicki Michelle", + "role": "Actor", + "billingOrder": "04" + }, { + "personId": "353113", + "nameId": "361987", + "name": "Kirsten Cooke", + "role": "Actor", + "billingOrder": "05" + }, { + "personId": "77787", + "nameId": "77787", + "name": "Richard Marner", + "role": "Actor", + "billingOrder": "06" + }, { + "personId": "230921", + "nameId": "234193", + "name": "Guy Siner", + "role": "Actor", + "billingOrder": "07" + }, { + "personId": "374934", + "nameId": "383809", + "name": "Kim Hartman", + "role": "Actor", + "billingOrder": "08" + }, { + "personId": "369151", + "nameId": "378026", + "name": "Richard Gibson", + "role": "Actor", + "billingOrder": "09" + }, { + "personId": "343690", + "nameId": "352564", + "name": "Arthur Bostrom", + "role": "Actor", + "billingOrder": "10" + }, { + "personId": "352557", + "nameId": "361431", + "name": "John D. Collins", + "role": "Actor", + "billingOrder": "11" + }, { + "personId": "605275", + "nameId": "627734", + "name": "Nicholas Frankau", + "role": "Actor", + "billingOrder": "12" + }, { + "personId": "373394", + "nameId": "382269", + "name": "Jack Haig", + "role": "Actor", + "billingOrder": "13" + }], + "crew": [{ + "personId": "354407", + "nameId": "363281", + "name": "David Croft", + "role": "Director", + "billingOrder": "01" + }, { + "personId": "354407", + "nameId": "363281", + "name": "David Croft", + "role": "Writer", + "billingOrder": "02" + }, { + "personId": "105145", + "nameId": "105145", + "name": "Jeremy Lloyd", + "role": "Writer", + "billingOrder": "03" + }], + "showType": "Series", + "hasImageArtwork": true, + "md5": "Jo5NKxoo44xRvBCAq8QT2A" + }, + { + "programID": "EP000000510142", + "titles": [{ + "title120": "A Different World" + }], + "eventDetails": { + "subType": "Series" + }, + "descriptions": { + "description1000": [{ + "descriptionLanguage": "en", + "description": "Whitley and Dwayne tell new students about their honeymoon in Los Angeles." + }] + }, + "originalAirDate": "1992-09-24", + "genres": ["Sitcom"], + "episodeTitle150": "Honeymoon in L.A.", + "metadata": [{ + "Gracenote": { + "season": 6, + "episode": 1 + } + }], + "cast": [{ + "personId": "700", + "nameId": "700", + "name": "Jasmine Guy", + "role": "Actor", + "billingOrder": "01" + }, { + "personId": "729", + "nameId": "729", + "name": "Kadeem Hardison", + "role": "Actor", + "billingOrder": "02" + }, { + "personId": "120", + "nameId": "120", + "name": "Darryl M. Bell", + "role": "Actor", + "billingOrder": "03" + }, { + "personId": "1729", + "nameId": "1729", + "name": "Cree Summer", + "role": "Actor", + "billingOrder": "04" + }, { + "personId": "217", + "nameId": "217", + "name": "Charnele Brown", + "role": "Actor", + "billingOrder": "05" + }, { + "personId": "1811", + "nameId": "1811", + "name": "Glynn Turman", + "role": "Actor", + "billingOrder": "06" + }, { + "personId": "1232", + "nameId": "1232", + "name": "Lou Myers", + "role": "Actor", + "billingOrder": "07" + }, { + "personId": "1363", + "nameId": "1363", + "name": "Jada Pinkett", + "role": "Guest Star", + "billingOrder": "08" + }, { + "personId": "222967", + "nameId": "225536", + "name": "Ajai Sanders", + "role": "Guest Star", + "billingOrder": "09" + }, { + "personId": "181744", + "nameId": "183292", + "name": "Karen Malina White", + "role": "Guest Star", + "billingOrder": "10" + }, { + "personId": "305017", + "nameId": "318897", + "name": "Patrick Y. Malone", + "role": "Guest Star", + "billingOrder": "11" + }, { + "personId": "9841", + "nameId": "9841", + "name": "Bumper Robinson", + "role": "Guest Star", + "billingOrder": "12" + }, { + "personId": "426422", + "nameId": "435297", + "name": "Sister Souljah", + "role": "Guest Star", + "billingOrder": "13" + }, { + "personId": "25", + "nameId": "25", + "name": "Debbie Allen", + "role": "Guest Star", + "billingOrder": "14" + }, { + "personId": "668", + "nameId": "668", + "name": "Gilbert Gottfried", + "role": "Guest Star", + "billingOrder": "15" + }], + "showType": "Series", + "hasImageArtwork": true, + "md5": "P5kz0QmCeYxIA+yL0H4DWw" + } +] diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_request.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_request.json new file mode 100644 index 000000000..72248921a --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_request.json @@ -0,0 +1,16 @@ +[ + { + "stationID": "20454", + "date": [ + "2015-03-13", + "2015-03-17" + ] + }, + { + "stationID": "10021", + "date": [ + "2015-03-12", + "2015-03-13" + ] + } +] diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_response.json new file mode 100644 index 000000000..f474f3aff --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_response.json @@ -0,0 +1,35 @@ +[ + { + "stationID": "20454", + "programs": [ + { + "programID": "SH005371070000", + "airDateTime": "2015-03-03T00:00:00Z", + "duration": 1800, + "md5": "Sy8HEMBPcuiAx3FBukUhKQ", + "new": true, + "audioProperties": [ + "stereo", + "cc" + ], + "videoProperties": [ + "hdtv" + ] + }, + { + "programID": "EP000014577244", + "airDateTime": "2015-03-03T00:30:00Z", + "duration": 1800, + "md5": "25DNXVXO192JI7Y9vSW9lQ", + "new": true, + "audioProperties": [ + "stereo", + "cc" + ], + "videoProperties": [ + "hdtv" + ] + } + ] + } +] diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_live_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_live_response.json new file mode 100644 index 000000000..73b0a54c4 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_live_response.json @@ -0,0 +1,7 @@ +{ + "code": 0, + "message": "OK", + "serverID": "AWS-SD-web.1", + "datetime": "2016-08-23T13:55:25Z", + "token": "f3fca79989cafe7dead71beefedc812b" +} diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_offline_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_offline_response.json new file mode 100644 index 000000000..b630c2404 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_offline_response.json @@ -0,0 +1,8 @@ +{ + "response": "SERVICE_OFFLINE", + "code": 3000, + "serverID": "20141201.web.1", + "message": "Server offline for maintenance.", + "datetime": "2015-04-23T00:03:32Z", + "token": "CAFEDEADBEEFCAFEDEADBEEFCAFEDEADBEEFCAFE" +} -- cgit v1.2.3 From 0587b539ec899c35b5bea73801d5007575f86b94 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Fri, 3 Sep 2021 13:36:07 -0600 Subject: Suggestions from review --- .../LiveTv/Listings/SchedulesDirect.cs | 25 ++- .../Jellyfin.Server.Implementations.Tests.csproj | 3 - .../SchedulesDirectDeserializeTests.cs | 25 +-- .../TestData/headends_response.json | 113 ---------- .../SchedulesDirect/TestData/lineup_response.json | 18 -- .../SchedulesDirect/TestData/lineups_response.json | 40 ---- .../TestData/metadata_programs_response.json | 51 ----- .../TestData/programs_response.json | 245 --------------------- .../TestData/schedules_request.json | 16 -- .../TestData/schedules_response.json | 35 --- .../TestData/token_live_response.json | 7 - .../TestData/token_offline_response.json | 8 - .../SchedulesDirect/headends_response.json | 1 + .../Test Data/SchedulesDirect/lineup_response.json | 1 + .../SchedulesDirect/lineups_response.json | 1 + .../metadata_programs_response.json | 1 + .../SchedulesDirect/programs_response.json | 1 + .../SchedulesDirect/schedules_request.json | 1 + .../SchedulesDirect/schedules_response.json | 1 + .../SchedulesDirect/token_live_response.json | 1 + .../SchedulesDirect/token_offline_response.json | 1 + 21 files changed, 40 insertions(+), 555 deletions(-) delete mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/headends_response.json delete mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineup_response.json delete mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineups_response.json delete mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/metadata_programs_response.json delete mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/programs_response.json delete mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_request.json delete mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_response.json delete mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_live_response.json delete mode 100644 tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_offline_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/headends_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/lineup_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/lineups_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/metadata_programs_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/programs_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/schedules_request.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/schedules_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/token_live_response.json create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/token_offline_response.json (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index e8562b8c5..6686b625f 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -9,6 +9,7 @@ using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Headers; using System.Net.Http.Json; using System.Net.Mime; using System.Text; @@ -113,18 +114,29 @@ namespace Emby.Server.Implementations.LiveTv.Listings 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); - _logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules!.Count, channelId); + if (dailySchedules == null) + { + return Array.Empty(); + } + + _logger.LogDebug("Found {ScheduleCount} programs on {ChannelID} ScheduleDirect", dailySchedules.Count, channelId); using var programRequestOptions = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/programs"); programRequestOptions.Headers.TryAddWithoutValidation("token", token); var programIds = dailySchedules.SelectMany(d => d.Programs.Select(s => s.ProgramId)).Distinct(); - programRequestOptions.Content = new StringContent(JsonSerializer.Serialize(programIds), Encoding.UTF8, MediaTypeNames.Application.Json); + programRequestOptions.Content = new ByteArrayContent(JsonSerializer.SerializeToUtf8Bytes(programIds, _jsonOptions)); + programRequestOptions.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(MediaTypeNames.Application.Json); 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 programDict = programDetails!.ToDictionary(p => p.ProgramId, y => y); + if (programDetails == null) + { + return Array.Empty(); + } + + var programDict = programDetails.ToDictionary(p => p.ProgramId, y => y); var programIdsWithImages = programDetails .Where(p => p.HasImageArtwork).Select(p => p.ProgramId) @@ -775,7 +787,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings 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); - _logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root!.Map.Count); + if (root == null) + { + return new List(); + } + + _logger.LogInformation("Found {ChannelCount} channels on the lineup on ScheduleDirect", root.Map.Count); _logger.LogInformation("Mapping Stations to Channel"); var allStations = root.Stations; diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index e02e357ca..9b6ab7bdf 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -16,9 +16,6 @@ PreserveNewest - - PreserveNewest - diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs index 84ac3ea47..ab08e22ab 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs @@ -23,7 +23,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect [Fact] public void Deserialize_Token_Response_Live_Success() { - var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/token_live_response.json"); + var bytes = File.ReadAllBytes("Test Data/SchedulesDirect/token_live_response.json"); var tokenDto = JsonSerializer.Deserialize(bytes); Assert.NotNull(tokenDto); @@ -40,7 +40,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect [Fact] public void Deserialize_Token_Response_Offline_Success() { - var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/token_offline_response.json"); + var bytes = File.ReadAllBytes("Test Data/SchedulesDirect/token_offline_response.json"); var tokenDto = JsonSerializer.Deserialize(bytes); Assert.NotNull(tokenDto); @@ -58,7 +58,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect [Fact] public void Serialize_Schedule_Request_Success() { - var expectedString = File.ReadAllText("LiveTv/SchedulesDirect/TestData/schedules_request.json").Trim(); + var expectedString = File.ReadAllText("Test Data/SchedulesDirect/schedules_request.json").Trim(); var requestObject = new RequestScheduleForChannelDto[] { @@ -82,12 +82,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect } }; - var jsonOptions = new JsonSerializerOptions(_jsonOptions) - { - WriteIndented = true - }; - - var requestString = JsonSerializer.Serialize(requestObject, jsonOptions); + var requestString = JsonSerializer.Serialize(requestObject, _jsonOptions); Assert.Equal(expectedString, requestString); } @@ -97,7 +92,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect [Fact] public void Deserialize_Schedule_Response_Success() { - var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/schedules_response.json"); + var bytes = File.ReadAllBytes("Test Data/SchedulesDirect/schedules_response.json"); var days = JsonSerializer.Deserialize>(bytes); Assert.NotNull(days); @@ -125,7 +120,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect [Fact] public void Deserialize_Program_Response_Success() { - var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/programs_response.json"); + var bytes = File.ReadAllBytes("Test Data/SchedulesDirect/programs_response.json"); var programDtos = JsonSerializer.Deserialize>(bytes); Assert.NotNull(programDtos); @@ -162,7 +157,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect [Fact] public void Deserialize_Metadata_Programs_Response_Success() { - var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/metadata_programs_response.json"); + var bytes = File.ReadAllBytes("Test Data/SchedulesDirect/metadata_programs_response.json"); var showImagesDtos = JsonSerializer.Deserialize>(bytes); Assert.NotNull(showImagesDtos); @@ -186,7 +181,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect [Fact] public void Deserialize_Headends_Response_Success() { - var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/headends_response.json"); + var bytes = File.ReadAllBytes("Test Data/SchedulesDirect/headends_response.json"); var headendsDtos = JsonSerializer.Deserialize>(bytes); Assert.NotNull(headendsDtos); @@ -206,7 +201,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect [Fact] public void Deserialize_Lineups_Response_Success() { - var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/lineups_response.json"); + var bytes = File.ReadAllBytes("Test Data/SchedulesDirect/lineups_response.json"); var lineupsDto = JsonSerializer.Deserialize(bytes); Assert.NotNull(lineupsDto); @@ -230,7 +225,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect [Fact] public void Deserialize_Lineup_Response_Success() { - var bytes = File.ReadAllBytes("LiveTv/SchedulesDirect/TestData/lineup_response.json"); + var bytes = File.ReadAllBytes("Test Data/SchedulesDirect/lineup_response.json"); var channelDto = JsonSerializer.Deserialize(bytes); Assert.NotNull(channelDto); diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/headends_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/headends_response.json deleted file mode 100644 index a1a96cf87..000000000 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/headends_response.json +++ /dev/null @@ -1,113 +0,0 @@ -[ - { - "headend": "CA00053", - "transport": "Cable", - "location": "Beverly Hills", - "lineups": [ - { - "name": "Time Warner Cable - Cable", - "lineup": "USA-CA00053-DEFAULT", - "uri": "/20141201/lineups/USA-CA00053-DEFAULT" - }, - { - "name": "Time Warner Cable - Digital", - "lineup": "USA-CA00053-X", - "uri": "/20141201/lineups/USA-CA00053-X" - } - ] - }, - { - "headend": "CA61222", - "transport": "Cable", - "location": "Beverly Hills", - "lineups": [ - { - "name": "Mulholland Estates - Cable", - "lineup": "USA-CA61222-DEFAULT", - "uri": "/20141201/lineups/USA-CA61222-DEFAULT" - } - ] - }, - { - "headend": "CA66511", - "transport": "Cable", - "location": "Los Angeles", - "lineups": [ - { - "name": "AT&T U-verse TV - Digital", - "lineup": "USA-CA66511-X", - "uri": "/20141201/lineups/USA-CA66511-X" - } - ] - }, - { - "headend": "CA67309", - "transport": "Cable", - "location": "Westchester", - "lineups": [ - { - "name": "Time Warner Cable Sherman Oaks - Cable", - "lineup": "USA-CA67309-DEFAULT", - "uri": "/20141201/lineups/USA-CA67309-DEFAULT" - }, - { - "name": "Time Warner Cable Sherman Oaks - Digital", - "lineup": "USA-CA67309-X", - "uri": "/20141201/lineups/USA-CA67309-X" - } - ] - }, - { - "headend": "CA67310", - "transport": "Cable", - "location": "Eagle Rock", - "lineups": [ - { - "name": "Time Warner Cable City of Los Angeles - Cable", - "lineup": "USA-CA67310-DEFAULT", - "uri": "/20141201/lineups/USA-CA67310-DEFAULT" - }, - { - "name": "Time Warner Cable City of Los Angeles - Digital", - "lineup": "USA-CA67310-X", - "uri": "/20141201/lineups/USA-CA67310-X" - } - ] - }, - { - "headend": "DISH803", - "transport": "Satellite", - "location": "Los Angeles", - "lineups": [ - { - "name": "DISH Los Angeles - Satellite", - "lineup": "USA-DISH803-DEFAULT", - "uri": "/20141201/lineups/USA-DISH803-DEFAULT" - } - ] - }, - { - "headend": "DITV803", - "transport": "Satellite", - "location": "Los Angeles", - "lineups": [ - { - "name": "DIRECTV Los Angeles - Satellite", - "lineup": "USA-DITV803-DEFAULT", - "uri": "/20141201/lineups/USA-DITV803-DEFAULT" - } - ] - }, - { - "headend": "90210", - "transport": "Antenna", - "location": "90210", - "lineups": [ - { - "name": "Antenna", - "lineup": "USA-OTA-90210", - "uri": "/20141201/lineups/USA-OTA-90210" - } - ] - } -] diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineup_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineup_response.json deleted file mode 100644 index 5c5e36e30..000000000 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineup_response.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "map": [ - { - "stationID": "24326", - "channel": "001", - "providerCallsign": "BBC ONE South", - "logicalChannelNumber": "1", - "matchType": "providerCallsign" - }, - { - "stationID": "17154", - "channel": "002", - "providerCallsign": "BBC TWO", - "logicalChannelNumber": "2", - "matchType": "providerCallsign" - } - ] -} diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineups_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineups_response.json deleted file mode 100644 index 257b682ee..000000000 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/lineups_response.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "code": 0, - "serverID": "20141201.web.1", - "datetime": "2015-04-17T14:22:17Z", - "lineups": [ - { - "lineup": "GBR-0001317-DEFAULT", - "name": "Freeview - Carlton - LWT (Southeast)", - "transport": "DVB-T", - "location": "London", - "uri": "/20141201/lineups/GBR-0001317-DEFAULT" - }, - { - "lineup": "USA-IL57303-X", - "name": "Comcast Waukegan/Lake Forest Area - Digital", - "transport": "Cable", - "location": "Lake Forest", - "uri": "/20141201/lineups/USA-IL57303-X" - }, - { - "lineup": "USA-NY67791-X", - "name": "Verizon Fios Queens - Digital", - "transport": "Cable", - "location": "Fresh Meadows", - "uri": "/20141201/lineups/USA-NY67791-X" - }, - { - "lineup": "USA-OTA-60030", - "name": "Local Over the Air Broadcast", - "transport": "Antenna", - "location": "60030", - "uri": "/20141201/lineups/USA-OTA-60030" - }, - { - "lineup": "USA-WI61859-DEFAULT", - "name": "DELETED LINEUP", - "isDeleted": true - } - ] -} diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/metadata_programs_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/metadata_programs_response.json deleted file mode 100644 index b75e777b4..000000000 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/metadata_programs_response.json +++ /dev/null @@ -1,51 +0,0 @@ -[ - { - "programID": "SH00712240", - "data": [ - { - "width": "135", - "height": "180", - "uri": "assets/p282288_b_v2_aa.jpg", - "size": "Sm", - "aspect": "3x4", - "category": "Banner-L3", - "text": "yes", - "primary": "true", - "tier": "Series" - }, - { - "width": "720", - "height": "540", - "uri": "assets/p282288_b_h6_aa.jpg", - "size": "Lg", - "aspect": "4x3", - "category": "Banner-L3", - "text": "yes", - "primary": "true", - "tier": "Series" - }, - { - "width": "960", - "height": "1440", - "uri": "assets/p282288_b_v8_aa.jpg", - "size": "Ms", - "aspect": "2x3", - "category": "Banner-L3", - "text": "yes", - "primary": "true", - "tier": "Series" - }, - { - "width": "180", - "height": "135", - "uri": "assets/p282288_b_h5_aa.jpg", - "size": "Sm", - "aspect": "4x3", - "category": "Banner-L3", - "text": "yes", - "primary": "true", - "tier": "Series" - } - ] - } -] diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/programs_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/programs_response.json deleted file mode 100644 index 154c02f97..000000000 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/programs_response.json +++ /dev/null @@ -1,245 +0,0 @@ -[ - { - "programID": "EP000000060003", - "titles": [{ - "title120": "'Allo 'Allo!" - }], - "eventDetails": { - "subType": "Series" - }, - "descriptions": { - "description1000": [{ - "descriptionLanguage": "en", - "description": "A disguised British Intelligence officer is sent to help the airmen." - }] - }, - "originalAirDate": "1985-11-04", - "genres": ["Sitcom"], - "episodeTitle150": "The Poloceman Cometh", - "metadata": [{ - "Gracenote": { - "season": 2, - "episode": 3 - } - }], - "cast": [{ - "personId": "383774", - "nameId": "392649", - "name": "Gorden Kaye", - "role": "Actor", - "billingOrder": "01" - }, { - "personId": "246840", - "nameId": "250387", - "name": "Carmen Silvera", - "role": "Actor", - "billingOrder": "02" - }, { - "personId": "376955", - "nameId": "385830", - "name": "Rose Hill", - "role": "Actor", - "billingOrder": "03" - }, { - "personId": "259773", - "nameId": "263340", - "name": "Vicki Michelle", - "role": "Actor", - "billingOrder": "04" - }, { - "personId": "353113", - "nameId": "361987", - "name": "Kirsten Cooke", - "role": "Actor", - "billingOrder": "05" - }, { - "personId": "77787", - "nameId": "77787", - "name": "Richard Marner", - "role": "Actor", - "billingOrder": "06" - }, { - "personId": "230921", - "nameId": "234193", - "name": "Guy Siner", - "role": "Actor", - "billingOrder": "07" - }, { - "personId": "374934", - "nameId": "383809", - "name": "Kim Hartman", - "role": "Actor", - "billingOrder": "08" - }, { - "personId": "369151", - "nameId": "378026", - "name": "Richard Gibson", - "role": "Actor", - "billingOrder": "09" - }, { - "personId": "343690", - "nameId": "352564", - "name": "Arthur Bostrom", - "role": "Actor", - "billingOrder": "10" - }, { - "personId": "352557", - "nameId": "361431", - "name": "John D. Collins", - "role": "Actor", - "billingOrder": "11" - }, { - "personId": "605275", - "nameId": "627734", - "name": "Nicholas Frankau", - "role": "Actor", - "billingOrder": "12" - }, { - "personId": "373394", - "nameId": "382269", - "name": "Jack Haig", - "role": "Actor", - "billingOrder": "13" - }], - "crew": [{ - "personId": "354407", - "nameId": "363281", - "name": "David Croft", - "role": "Director", - "billingOrder": "01" - }, { - "personId": "354407", - "nameId": "363281", - "name": "David Croft", - "role": "Writer", - "billingOrder": "02" - }, { - "personId": "105145", - "nameId": "105145", - "name": "Jeremy Lloyd", - "role": "Writer", - "billingOrder": "03" - }], - "showType": "Series", - "hasImageArtwork": true, - "md5": "Jo5NKxoo44xRvBCAq8QT2A" - }, - { - "programID": "EP000000510142", - "titles": [{ - "title120": "A Different World" - }], - "eventDetails": { - "subType": "Series" - }, - "descriptions": { - "description1000": [{ - "descriptionLanguage": "en", - "description": "Whitley and Dwayne tell new students about their honeymoon in Los Angeles." - }] - }, - "originalAirDate": "1992-09-24", - "genres": ["Sitcom"], - "episodeTitle150": "Honeymoon in L.A.", - "metadata": [{ - "Gracenote": { - "season": 6, - "episode": 1 - } - }], - "cast": [{ - "personId": "700", - "nameId": "700", - "name": "Jasmine Guy", - "role": "Actor", - "billingOrder": "01" - }, { - "personId": "729", - "nameId": "729", - "name": "Kadeem Hardison", - "role": "Actor", - "billingOrder": "02" - }, { - "personId": "120", - "nameId": "120", - "name": "Darryl M. Bell", - "role": "Actor", - "billingOrder": "03" - }, { - "personId": "1729", - "nameId": "1729", - "name": "Cree Summer", - "role": "Actor", - "billingOrder": "04" - }, { - "personId": "217", - "nameId": "217", - "name": "Charnele Brown", - "role": "Actor", - "billingOrder": "05" - }, { - "personId": "1811", - "nameId": "1811", - "name": "Glynn Turman", - "role": "Actor", - "billingOrder": "06" - }, { - "personId": "1232", - "nameId": "1232", - "name": "Lou Myers", - "role": "Actor", - "billingOrder": "07" - }, { - "personId": "1363", - "nameId": "1363", - "name": "Jada Pinkett", - "role": "Guest Star", - "billingOrder": "08" - }, { - "personId": "222967", - "nameId": "225536", - "name": "Ajai Sanders", - "role": "Guest Star", - "billingOrder": "09" - }, { - "personId": "181744", - "nameId": "183292", - "name": "Karen Malina White", - "role": "Guest Star", - "billingOrder": "10" - }, { - "personId": "305017", - "nameId": "318897", - "name": "Patrick Y. Malone", - "role": "Guest Star", - "billingOrder": "11" - }, { - "personId": "9841", - "nameId": "9841", - "name": "Bumper Robinson", - "role": "Guest Star", - "billingOrder": "12" - }, { - "personId": "426422", - "nameId": "435297", - "name": "Sister Souljah", - "role": "Guest Star", - "billingOrder": "13" - }, { - "personId": "25", - "nameId": "25", - "name": "Debbie Allen", - "role": "Guest Star", - "billingOrder": "14" - }, { - "personId": "668", - "nameId": "668", - "name": "Gilbert Gottfried", - "role": "Guest Star", - "billingOrder": "15" - }], - "showType": "Series", - "hasImageArtwork": true, - "md5": "P5kz0QmCeYxIA+yL0H4DWw" - } -] diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_request.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_request.json deleted file mode 100644 index 72248921a..000000000 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_request.json +++ /dev/null @@ -1,16 +0,0 @@ -[ - { - "stationID": "20454", - "date": [ - "2015-03-13", - "2015-03-17" - ] - }, - { - "stationID": "10021", - "date": [ - "2015-03-12", - "2015-03-13" - ] - } -] diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_response.json deleted file mode 100644 index f474f3aff..000000000 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/schedules_response.json +++ /dev/null @@ -1,35 +0,0 @@ -[ - { - "stationID": "20454", - "programs": [ - { - "programID": "SH005371070000", - "airDateTime": "2015-03-03T00:00:00Z", - "duration": 1800, - "md5": "Sy8HEMBPcuiAx3FBukUhKQ", - "new": true, - "audioProperties": [ - "stereo", - "cc" - ], - "videoProperties": [ - "hdtv" - ] - }, - { - "programID": "EP000014577244", - "airDateTime": "2015-03-03T00:30:00Z", - "duration": 1800, - "md5": "25DNXVXO192JI7Y9vSW9lQ", - "new": true, - "audioProperties": [ - "stereo", - "cc" - ], - "videoProperties": [ - "hdtv" - ] - } - ] - } -] diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_live_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_live_response.json deleted file mode 100644 index 73b0a54c4..000000000 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_live_response.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "code": 0, - "message": "OK", - "serverID": "AWS-SD-web.1", - "datetime": "2016-08-23T13:55:25Z", - "token": "f3fca79989cafe7dead71beefedc812b" -} diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_offline_response.json b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_offline_response.json deleted file mode 100644 index b630c2404..000000000 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/TestData/token_offline_response.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "response": "SERVICE_OFFLINE", - "code": 3000, - "serverID": "20141201.web.1", - "message": "Server offline for maintenance.", - "datetime": "2015-04-23T00:03:32Z", - "token": "CAFEDEADBEEFCAFEDEADBEEFCAFEDEADBEEFCAFE" -} diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/headends_response.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/headends_response.json new file mode 100644 index 000000000..015afeecc --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/headends_response.json @@ -0,0 +1 @@ +[{"headend":"CA00053","transport":"Cable","location":"Beverly Hills","lineups":[{"name":"Time Warner Cable - Cable","lineup":"USA-CA00053-DEFAULT","uri":"/20141201/lineups/USA-CA00053-DEFAULT"},{"name":"Time Warner Cable - Digital","lineup":"USA-CA00053-X","uri":"/20141201/lineups/USA-CA00053-X"}]},{"headend":"CA61222","transport":"Cable","location":"Beverly Hills","lineups":[{"name":"Mulholland Estates - Cable","lineup":"USA-CA61222-DEFAULT","uri":"/20141201/lineups/USA-CA61222-DEFAULT"}]},{"headend":"CA66511","transport":"Cable","location":"Los Angeles","lineups":[{"name":"AT&T U-verse TV - Digital","lineup":"USA-CA66511-X","uri":"/20141201/lineups/USA-CA66511-X"}]},{"headend":"CA67309","transport":"Cable","location":"Westchester","lineups":[{"name":"Time Warner Cable Sherman Oaks - Cable","lineup":"USA-CA67309-DEFAULT","uri":"/20141201/lineups/USA-CA67309-DEFAULT"},{"name":"Time Warner Cable Sherman Oaks - Digital","lineup":"USA-CA67309-X","uri":"/20141201/lineups/USA-CA67309-X"}]},{"headend":"CA67310","transport":"Cable","location":"Eagle Rock","lineups":[{"name":"Time Warner Cable City of Los Angeles - Cable","lineup":"USA-CA67310-DEFAULT","uri":"/20141201/lineups/USA-CA67310-DEFAULT"},{"name":"Time Warner Cable City of Los Angeles - Digital","lineup":"USA-CA67310-X","uri":"/20141201/lineups/USA-CA67310-X"}]},{"headend":"DISH803","transport":"Satellite","location":"Los Angeles","lineups":[{"name":"DISH Los Angeles - Satellite","lineup":"USA-DISH803-DEFAULT","uri":"/20141201/lineups/USA-DISH803-DEFAULT"}]},{"headend":"DITV803","transport":"Satellite","location":"Los Angeles","lineups":[{"name":"DIRECTV Los Angeles - Satellite","lineup":"USA-DITV803-DEFAULT","uri":"/20141201/lineups/USA-DITV803-DEFAULT"}]},{"headend":"90210","transport":"Antenna","location":"90210","lineups":[{"name":"Antenna","lineup":"USA-OTA-90210","uri":"/20141201/lineups/USA-OTA-90210"}]}] diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/lineup_response.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/lineup_response.json new file mode 100644 index 000000000..072089470 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/lineup_response.json @@ -0,0 +1 @@ +{"map":[{"stationID":"24326","channel":"001","providerCallsign":"BBC ONE South","logicalChannelNumber":"1","matchType":"providerCallsign"},{"stationID":"17154","channel":"002","providerCallsign":"BBC TWO","logicalChannelNumber":"2","matchType":"providerCallsign"}]} diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/lineups_response.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/lineups_response.json new file mode 100644 index 000000000..032a84e59 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/lineups_response.json @@ -0,0 +1 @@ +{"code":0,"serverID":"20141201.web.1","datetime":"2015-04-17T14:22:17Z","lineups":[{"lineup":"GBR-0001317-DEFAULT","name":"Freeview - Carlton - LWT (Southeast)","transport":"DVB-T","location":"London","uri":"/20141201/lineups/GBR-0001317-DEFAULT"},{"lineup":"USA-IL57303-X","name":"Comcast Waukegan/Lake Forest Area - Digital","transport":"Cable","location":"Lake Forest","uri":"/20141201/lineups/USA-IL57303-X"},{"lineup":"USA-NY67791-X","name":"Verizon Fios Queens - Digital","transport":"Cable","location":"Fresh Meadows","uri":"/20141201/lineups/USA-NY67791-X"},{"lineup":"USA-OTA-60030","name":"Local Over the Air Broadcast","transport":"Antenna","location":"60030","uri":"/20141201/lineups/USA-OTA-60030"},{"lineup":"USA-WI61859-DEFAULT","name":"DELETED LINEUP","isDeleted":true}]} diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/metadata_programs_response.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/metadata_programs_response.json new file mode 100644 index 000000000..78166f09a --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/metadata_programs_response.json @@ -0,0 +1 @@ +[{"programID":"SH00712240","data":[{"width":"135","height":"180","uri":"assets/p282288_b_v2_aa.jpg","size":"Sm","aspect":"3x4","category":"Banner-L3","text":"yes","primary":"true","tier":"Series"},{"width":"720","height":"540","uri":"assets/p282288_b_h6_aa.jpg","size":"Lg","aspect":"4x3","category":"Banner-L3","text":"yes","primary":"true","tier":"Series"},{"width":"960","height":"1440","uri":"assets/p282288_b_v8_aa.jpg","size":"Ms","aspect":"2x3","category":"Banner-L3","text":"yes","primary":"true","tier":"Series"},{"width":"180","height":"135","uri":"assets/p282288_b_h5_aa.jpg","size":"Sm","aspect":"4x3","category":"Banner-L3","text":"yes","primary":"true","tier":"Series"}]}] diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/programs_response.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/programs_response.json new file mode 100644 index 000000000..fe2a94436 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/programs_response.json @@ -0,0 +1 @@ +[{"programID":"EP000000060003","titles":[{"title120":"'Allo 'Allo!"}],"eventDetails":{"subType":"Series"},"descriptions":{"description1000":[{"descriptionLanguage":"en","description":"A disguised British Intelligence officer is sent to help the airmen."}]},"originalAirDate":"1985-11-04","genres":["Sitcom"],"episodeTitle150":"The Poloceman Cometh","metadata":[{"Gracenote":{"season":2,"episode":3}}],"cast":[{"personId":"383774","nameId":"392649","name":"Gorden Kaye","role":"Actor","billingOrder":"01"},{"personId":"246840","nameId":"250387","name":"Carmen Silvera","role":"Actor","billingOrder":"02"},{"personId":"376955","nameId":"385830","name":"Rose Hill","role":"Actor","billingOrder":"03"},{"personId":"259773","nameId":"263340","name":"Vicki Michelle","role":"Actor","billingOrder":"04"},{"personId":"353113","nameId":"361987","name":"Kirsten Cooke","role":"Actor","billingOrder":"05"},{"personId":"77787","nameId":"77787","name":"Richard Marner","role":"Actor","billingOrder":"06"},{"personId":"230921","nameId":"234193","name":"Guy Siner","role":"Actor","billingOrder":"07"},{"personId":"374934","nameId":"383809","name":"Kim Hartman","role":"Actor","billingOrder":"08"},{"personId":"369151","nameId":"378026","name":"Richard Gibson","role":"Actor","billingOrder":"09"},{"personId":"343690","nameId":"352564","name":"Arthur Bostrom","role":"Actor","billingOrder":"10"},{"personId":"352557","nameId":"361431","name":"John D. Collins","role":"Actor","billingOrder":"11"},{"personId":"605275","nameId":"627734","name":"Nicholas Frankau","role":"Actor","billingOrder":"12"},{"personId":"373394","nameId":"382269","name":"Jack Haig","role":"Actor","billingOrder":"13"}],"crew":[{"personId":"354407","nameId":"363281","name":"David Croft","role":"Director","billingOrder":"01"},{"personId":"354407","nameId":"363281","name":"David Croft","role":"Writer","billingOrder":"02"},{"personId":"105145","nameId":"105145","name":"Jeremy Lloyd","role":"Writer","billingOrder":"03"}],"showType":"Series","hasImageArtwork":true,"md5":"Jo5NKxoo44xRvBCAq8QT2A"},{"programID":"EP000000510142","titles":[{"title120":"A Different World"}],"eventDetails":{"subType":"Series"},"descriptions":{"description1000":[{"descriptionLanguage":"en","description":"Whitley and Dwayne tell new students about their honeymoon in Los Angeles."}]},"originalAirDate":"1992-09-24","genres":["Sitcom"],"episodeTitle150":"Honeymoon in L.A.","metadata":[{"Gracenote":{"season":6,"episode":1}}],"cast":[{"personId":"700","nameId":"700","name":"Jasmine Guy","role":"Actor","billingOrder":"01"},{"personId":"729","nameId":"729","name":"Kadeem Hardison","role":"Actor","billingOrder":"02"},{"personId":"120","nameId":"120","name":"Darryl M. Bell","role":"Actor","billingOrder":"03"},{"personId":"1729","nameId":"1729","name":"Cree Summer","role":"Actor","billingOrder":"04"},{"personId":"217","nameId":"217","name":"Charnele Brown","role":"Actor","billingOrder":"05"},{"personId":"1811","nameId":"1811","name":"Glynn Turman","role":"Actor","billingOrder":"06"},{"personId":"1232","nameId":"1232","name":"Lou Myers","role":"Actor","billingOrder":"07"},{"personId":"1363","nameId":"1363","name":"Jada Pinkett","role":"Guest Star","billingOrder":"08"},{"personId":"222967","nameId":"225536","name":"Ajai Sanders","role":"Guest Star","billingOrder":"09"},{"personId":"181744","nameId":"183292","name":"Karen Malina White","role":"Guest Star","billingOrder":"10"},{"personId":"305017","nameId":"318897","name":"Patrick Y. Malone","role":"Guest Star","billingOrder":"11"},{"personId":"9841","nameId":"9841","name":"Bumper Robinson","role":"Guest Star","billingOrder":"12"},{"personId":"426422","nameId":"435297","name":"Sister Souljah","role":"Guest Star","billingOrder":"13"},{"personId":"25","nameId":"25","name":"Debbie Allen","role":"Guest Star","billingOrder":"14"},{"personId":"668","nameId":"668","name":"Gilbert Gottfried","role":"Guest Star","billingOrder":"15"}],"showType":"Series","hasImageArtwork":true,"md5":"P5kz0QmCeYxIA+yL0H4DWw"}] diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/schedules_request.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/schedules_request.json new file mode 100644 index 000000000..5ef1bfb1c --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/schedules_request.json @@ -0,0 +1 @@ +[{"stationID":"20454","date":["2015-03-13","2015-03-17"]},{"stationID":"10021","date":["2015-03-12","2015-03-13"]}] diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/schedules_response.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/schedules_response.json new file mode 100644 index 000000000..4a97e5517 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/schedules_response.json @@ -0,0 +1 @@ +[{"stationID":"20454","programs":[{"programID":"SH005371070000","airDateTime":"2015-03-03T00:00:00Z","duration":1800,"md5":"Sy8HEMBPcuiAx3FBukUhKQ","new":true,"audioProperties":["stereo","cc"],"videoProperties":["hdtv"]},{"programID":"EP000014577244","airDateTime":"2015-03-03T00:30:00Z","duration":1800,"md5":"25DNXVXO192JI7Y9vSW9lQ","new":true,"audioProperties":["stereo","cc"],"videoProperties":["hdtv"]}]}] diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/token_live_response.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/token_live_response.json new file mode 100644 index 000000000..e5fb64a6f --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/token_live_response.json @@ -0,0 +1 @@ +{"code":0,"message":"OK","serverID":"AWS-SD-web.1","datetime":"2016-08-23T13:55:25Z","token":"f3fca79989cafe7dead71beefedc812b"} diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/token_offline_response.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/token_offline_response.json new file mode 100644 index 000000000..b66a4ed0c --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/SchedulesDirect/token_offline_response.json @@ -0,0 +1 @@ +{"response":"SERVICE_OFFLINE","code":3000,"serverID":"20141201.web.1","message":"Server offline for maintenance.","datetime":"2015-04-23T00:03:32Z","token":"CAFEDEADBEEFCAFEDEADBEEFCAFEDEADBEEFCAFE"} -- cgit v1.2.3 From 23e6c918a22c85751cc0907cd0074ee3f3445664 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Mon, 6 Sep 2021 11:08:40 -0600 Subject: Remove Linq to index search --- Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 6686b625f..1f963e4a2 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -10,7 +10,6 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; -using System.Net.Http.Json; using System.Net.Mime; using System.Text; using System.Text.Json; @@ -803,11 +802,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings { var channelNumber = GetChannelNumber(channel); - var station = allStations.FirstOrDefault(item => string.Equals(item.StationId, channel.StationId, StringComparison.OrdinalIgnoreCase)) - ?? new StationDto - { - StationId = channel.StationId - }; + var stationIndex = allStations.FindIndex(item => string.Equals(item.StationId, channel.StationId, StringComparison.OrdinalIgnoreCase)); + var station = stationIndex == -1 + ? new StationDto { StationId = channel.StationId } + : allStations[stationIndex]; var channelInfo = new ChannelInfo { -- cgit v1.2.3 From be9663ae896dd28aa9a455469391f0304cc73a5f Mon Sep 17 00:00:00 2001 From: cvium Date: Tue, 7 Sep 2021 10:27:55 +0200 Subject: Use GetSmartApiUrl instead (hopefully it works) --- Emby.Server.Implementations/ApplicationHost.cs | 9 +-------- tests/Jellyfin.Networking.Tests/NetworkParseTests.cs | 8 ++++---- 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index c244e7cfa..da99ea647 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1186,14 +1186,7 @@ namespace Emby.Server.Implementations } /// - public string GetUrlForUseByHttpApi() - { - // GetBindInterfaces will return an interface. - var bind = NetManager.GetInternalBindAddresses().FirstOrDefault() ?? - NetManager.GetAllBindInterfaces(true).First(); - - return GetLocalApiUrl(bind.Address.ToString(), Uri.UriSchemeHttp); - } + public string GetUrlForUseByHttpApi() => GetSmartApiUrl(string.Empty); /// public string GetLocalApiUrl(string hostname, string scheme = null, int? port = null) diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs index 170f0279f..b7385fde8 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs @@ -482,9 +482,9 @@ namespace Jellyfin.Networking.Tests [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "", "192.168.1.208")] // LAN address is specified by default. [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "10.0.0.1", "10.0.0.1")] // return bind address - public void Get_Appropriate_Interface_NoSource(string interfaces, string lan, string bind, string result) + public void GetBindInterface_NoSourceGiven_Success(string interfaces, string lan, string bind, string result) { - var conf = new NetworkConfiguration() + var conf = new NetworkConfiguration { EnableIPV4 = true, LocalNetworkSubnets = lan.Split(','), @@ -506,9 +506,9 @@ namespace Jellyfin.Networking.Tests [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "10.0.0.1", "192.168.1.209", "10.0.0.1")] // LAN not bound, so return external. [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "192.168.1.208,10.0.0.1", "8.8.8.8", "10.0.0.1")] // return external bind address [InlineData("192.168.1.208/24,-16,eth16|10.0.0.1/24,10,eth7", "192.168.1.0/24", "192.168.1.208,10.0.0.1", "192.168.1.210", "192.168.1.208")] // return LAN bind address - public void Get_Appropriate_Interface_ForSource(string interfaces, string lan, string bind, string source, string result) + public void GetBindInterface_ValidSourceGiven_Success(string interfaces, string lan, string bind, string source, string result) { - var conf = new NetworkConfiguration() + var conf = new NetworkConfiguration { EnableIPV4 = true, LocalNetworkSubnets = lan.Split(','), -- cgit v1.2.3 From 153e9202397f236a4a415bd033c3b398b6e6573c Mon Sep 17 00:00:00 2001 From: cvium Date: Tue, 7 Sep 2021 11:48:06 +0200 Subject: Ignore published server url for local access --- Emby.Server.Implementations/ApplicationHost.cs | 31 ++++++++-------------- .../LiveTv/EmbyTV/EmbyTV.cs | 2 +- .../LiveTv/LiveTvMediaSourceProvider.cs | 2 +- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 2 +- .../LiveTv/TunerHosts/SharedHttpStream.cs | 2 +- MediaBrowser.Controller/IServerApplicationHost.cs | 2 +- 6 files changed, 16 insertions(+), 25 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index da99ea647..d507c3fd1 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1135,12 +1135,6 @@ namespace Emby.Server.Implementations } string smart = NetManager.GetBindInterface(remoteAddr, out port); - // If the smartAPI doesn't start with http then treat it as a host or ip. - if (smart.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - return smart.Trim('/'); - } - return GetLocalApiUrl(smart.Trim('/'), null, port); } @@ -1155,12 +1149,6 @@ namespace Emby.Server.Implementations } string smart = NetManager.GetBindInterface(request, out port); - // If the smartAPI doesn't start with http then treat it as a host or ip. - if (smart.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - return smart.Trim('/'); - } - return GetLocalApiUrl(smart.Trim('/'), request.Scheme, port); } @@ -1175,22 +1163,25 @@ namespace Emby.Server.Implementations } string smart = NetManager.GetBindInterface(hostname, out port); - - // If the smartAPI doesn't start with http then treat it as a host or ip. - if (smart.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - return smart.Trim('/'); - } - return GetLocalApiUrl(smart.Trim('/'), null, port); } /// - public string GetUrlForUseByHttpApi() => GetSmartApiUrl(string.Empty); + public string GetApiUrlForLocalAccess() + { + string smart = NetManager.GetBindInterface(string.Empty, out var port); + return GetLocalApiUrl(smart.Trim('/'), null, port); + } /// public string GetLocalApiUrl(string hostname, string scheme = null, int? port = null) { + // If the smartAPI doesn't start with http then treat it as a host or ip. + if (hostname.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + return hostname.TrimEnd('/'); + } + // NOTE: If no BaseUrl is set then UriBuilder appends a trailing slash, but if there is no BaseUrl it does // not. For consistency, always trim the trailing slash. return new UriBuilder diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 0205ed9e5..67f824e71 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1027,7 +1027,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { var stream = new MediaSourceInfo { - EncoderPath = _appHost.GetUrlForUseByHttpApi() + "/LiveTv/LiveRecordings/" + info.Id + "/stream", + EncoderPath = _appHost.GetApiUrlForLocalAccess() + "/LiveTv/LiveRecordings/" + info.Id + "/stream", EncoderProtocol = MediaProtocol.Http, Path = info.Path, Protocol = MediaProtocol.File, diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index 1af9396d7..4b7584af3 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -104,7 +104,7 @@ namespace Emby.Server.Implementations.LiveTv // Dummy this up so that direct play checks can still run if (string.IsNullOrEmpty(source.Path) && source.Protocol == MediaProtocol.Http) { - source.Path = _appHost.GetUrlForUseByHttpApi(); + source.Path = _appHost.GetApiUrlForLocalAccess(); } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index a8a8ac729..9901f41f9 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -146,7 +146,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun // OpenedMediaSource.Path = tempFile; // OpenedMediaSource.ReadAtNativeFramerate = true; - MediaSource.Path = _appHost.GetUrlForUseByHttpApi() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; + MediaSource.Path = _appHost.GetApiUrlForLocalAccess() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; // OpenedMediaSource.SupportsDirectPlay = false; // OpenedMediaSource.SupportsDirectStream = true; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index b3e554139..67879cbae 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -97,7 +97,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts // OpenedMediaSource.Path = tempFile; // OpenedMediaSource.ReadAtNativeFramerate = true; - MediaSource.Path = _appHost.GetUrlForUseByHttpApi() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; + MediaSource.Path = _appHost.GetApiUrlForLocalAccess() + "/LiveTv/LiveStreamFiles/" + UniqueId + "/stream.ts"; MediaSource.Protocol = MediaProtocol.Http; // OpenedMediaSource.Path = TempFilePath; diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 52a7ff204..3c275391f 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -85,7 +85,7 @@ namespace MediaBrowser.Controller /// Gets an URL that can be used to access the API over HTTP (not HTTPS). /// /// The API URL. - string GetUrlForUseByHttpApi(); + string GetApiUrlForLocalAccess(); /// /// Gets a local (LAN) URL that can be used to access the API. -- cgit v1.2.3 From 1a8dcae5e4024ba30aa2f3e998e0df87ea6f4f1b Mon Sep 17 00:00:00 2001 From: "Mr. Chip53" Date: Sun, 12 Sep 2021 13:30:53 -0500 Subject: Fix #6171 --- .../LiveTv/Listings/XmlTvListingsProvider.cs | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 8202fab86..1c103f402 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -59,34 +59,34 @@ namespace Emby.Server.Implementations.LiveTv.Listings return _config.Configuration.PreferredMetadataLanguage; } - private async Task GetXml(string path, CancellationToken cancellationToken) + private async Task GetXml(ListingsProviderInfo info, CancellationToken cancellationToken) { - _logger.LogInformation("xmltv path: {Path}", path); + _logger.LogInformation("xmltv path: {Path}", info.Path); - if (!path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + if (!info.Path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { - return UnzipIfNeeded(path, path); + return UnzipIfNeeded(info.Path, info.Path); } - string cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "-" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + ".xml"; + string cacheFilename = DateTime.UtcNow.DayOfYear.ToString(CultureInfo.InvariantCulture) + "-" + DateTime.UtcNow.Hour.ToString(CultureInfo.InvariantCulture) + "-" + info.Id + ".xml"; string cacheFile = Path.Combine(_config.ApplicationPaths.CachePath, "xmltv", cacheFilename); if (File.Exists(cacheFile)) { - return UnzipIfNeeded(path, cacheFile); + return UnzipIfNeeded(info.Path, cacheFile); } - _logger.LogInformation("Downloading xmltv listings from {Path}", path); + _logger.LogInformation("Downloading xmltv listings from {Path}", info.Path); Directory.CreateDirectory(Path.GetDirectoryName(cacheFile)); - using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(path, cancellationToken).ConfigureAwait(false); + using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(info.Path, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, AsyncFile.UseAsyncIO)) { await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false); } - return UnzipIfNeeded(path, cacheFile); + return UnzipIfNeeded(info.Path, cacheFile); } private string UnzipIfNeeded(string originalUrl, string file) @@ -162,7 +162,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings _logger.LogDebug("Getting xmltv programs for channel {Id}", channelId); - string path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); + string path = await GetXml(info, cancellationToken).ConfigureAwait(false); _logger.LogDebug("Opening XmlTvReader for {Path}", path); var reader = new XmlTvReader(path, GetLanguage(info)); @@ -256,7 +256,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings public async Task> GetLineups(ListingsProviderInfo info, string country, string location) { // In theory this should never be called because there is always only one lineup - string path = await GetXml(info.Path, CancellationToken.None).ConfigureAwait(false); + string path = await GetXml(info, CancellationToken.None).ConfigureAwait(false); _logger.LogDebug("Opening XmlTvReader for {Path}", path); var reader = new XmlTvReader(path, GetLanguage(info)); IEnumerable results = reader.GetChannels(); @@ -268,7 +268,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings public async Task> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken) { // In theory this should never be called because there is always only one lineup - string path = await GetXml(info.Path, cancellationToken).ConfigureAwait(false); + string path = await GetXml(info, cancellationToken).ConfigureAwait(false); _logger.LogDebug("Opening XmlTvReader for {Path}", path); var reader = new XmlTvReader(path, GetLanguage(info)); var results = reader.GetChannels(); -- cgit v1.2.3 From 7a7fe3e681eca87cde631336c9af565fd6dfe0d7 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Sun, 12 Sep 2021 13:56:26 -0600 Subject: Fix types and property names --- .../LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs | 2 +- .../LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs | 5 +++-- .../LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs | 2 +- .../LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs | 6 +++--- 4 files changed, 8 insertions(+), 7 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs index a635c5987..f19081781 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/LineupsDto.cs @@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the datetime. /// [JsonPropertyName("datetime")] - public DateTime? Datetime { get; set; } + public DateTime? LineupTimestamp { get; set; } /// /// Gets or sets the list of lineups. diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs index 68fbeec46..04560ab55 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MetadataScheduleDto.cs @@ -1,3 +1,4 @@ +using System; using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos @@ -23,13 +24,13 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the start date. /// [JsonPropertyName("startDate")] - public string? StartDate { get; set; } + public DateTime? StartDate { get; set; } /// /// Gets or sets the end date. /// [JsonPropertyName("endDate")] - public string? EndDate { get; set; } + public DateTime? EndDate { get; set; } /// /// Gets or sets the days count. diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs index 561f79c5a..afb999486 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/TokenDto.cs @@ -36,7 +36,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the current datetime. /// [JsonPropertyName("datetime")] - public DateTime? DateTime { get; set; } + public DateTime? TokenTimestamp { get; set; } /// /// Gets or sets the response message. diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs index a494d883e..3b3e38bd1 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs @@ -30,7 +30,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect Assert.Equal(0, tokenDto!.Code); Assert.Equal("OK", tokenDto.Message); Assert.Equal("AWS-SD-web.1", tokenDto.ServerId); - Assert.Equal(new DateTime(2016, 08, 23, 13, 55, 25, DateTimeKind.Utc), tokenDto.DateTime); + Assert.Equal(new DateTime(2016, 08, 23, 13, 55, 25, DateTimeKind.Utc), tokenDto.TokenTimestamp); Assert.Equal("f3fca79989cafe7dead71beefedc812b", tokenDto.Token); } @@ -47,7 +47,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect Assert.Equal(3_000, tokenDto!.Code); Assert.Equal("Server offline for maintenance.", tokenDto.Message); Assert.Equal("20141201.web.1", tokenDto.ServerId); - Assert.Equal(new DateTime(2015, 04, 23, 00, 03, 32, DateTimeKind.Utc), tokenDto.DateTime); + Assert.Equal(new DateTime(2015, 04, 23, 00, 03, 32, DateTimeKind.Utc), tokenDto.TokenTimestamp); Assert.Equal("CAFEDEADBEEFCAFEDEADBEEFCAFEDEADBEEFCAFE", tokenDto.Token); Assert.Equal("SERVICE_OFFLINE", tokenDto.Response); } @@ -207,7 +207,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect Assert.NotNull(lineupsDto); Assert.Equal(0, lineupsDto!.Code); Assert.Equal("20141201.web.1", lineupsDto.ServerId); - Assert.Equal(new DateTime(2015, 04, 17, 14, 22, 17, DateTimeKind.Utc), lineupsDto.Datetime); + Assert.Equal(new DateTime(2015, 04, 17, 14, 22, 17, DateTimeKind.Utc), lineupsDto.LineupTimestamp); Assert.Equal(5, lineupsDto.Lineups.Count); Assert.Equal("GBR-0001317-DEFAULT", lineupsDto.Lineups[0].Lineup); Assert.Equal("Freeview - Carlton - LWT (Southeast)", lineupsDto.Lineups[0].Name); -- cgit v1.2.3 From ea439c5ccf7a61157544accd60109afc12dbc2d2 Mon Sep 17 00:00:00 2001 From: Fredrik Lindberg Date: Thu, 26 Aug 2021 20:01:56 +0200 Subject: Improve series name matching Add a series path resolver that attempts to extract only the series name from a path that contains more information that just the name. --- Emby.Naming/Common/NamingOptions.cs | 14 +++++ Emby.Naming/TV/SeriesInfo.cs | 29 ++++++++++ Emby.Naming/TV/SeriesPathParser.cs | 61 ++++++++++++++++++++++ Emby.Naming/TV/SeriesPathParserResult.cs | 19 +++++++ Emby.Naming/TV/SeriesResolver.cs | 49 +++++++++++++++++ .../Library/Resolvers/TV/SeriesResolver.cs | 8 +-- .../TV/SeriesPathParserTest.cs | 28 ++++++++++ .../TV/SeriesResolverTests.cs | 28 ++++++++++ 8 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 Emby.Naming/TV/SeriesInfo.cs create mode 100644 Emby.Naming/TV/SeriesPathParser.cs create mode 100644 Emby.Naming/TV/SeriesPathParserResult.cs create mode 100644 Emby.Naming/TV/SeriesResolver.cs create mode 100644 tests/Jellyfin.Naming.Tests/TV/SeriesPathParserTest.cs create mode 100644 tests/Jellyfin.Naming.Tests/TV/SeriesResolverTests.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 915ce42cc..192171a38 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -368,6 +368,20 @@ namespace Emby.Naming.Common IsOptimistic = true, IsNamed = true }, + + // Series and season only expression + // "the show/season 1", "the show/s01" + new EpisodeExpression(@"(.*(\\|\/))*(?.+)\/[Ss](eason)?[\. _\-]*(?[0-9]+)") + { + IsNamed = true + }, + + // Series and season only expression + // "the show S01", "the show season 1" + new EpisodeExpression(@"(.*(\\|\/))*(?.+)[\. _\-]+[sS](eason)?[\. _\-]*(?[0-9]+)") + { + IsNamed = true + }, }; EpisodeWithoutSeasonExpressions = new[] diff --git a/Emby.Naming/TV/SeriesInfo.cs b/Emby.Naming/TV/SeriesInfo.cs new file mode 100644 index 000000000..5d6cb4bd3 --- /dev/null +++ b/Emby.Naming/TV/SeriesInfo.cs @@ -0,0 +1,29 @@ +namespace Emby.Naming.TV +{ + /// + /// Holder object for Series information. + /// + public class SeriesInfo + { + /// + /// Initializes a new instance of the class. + /// + /// Path to the file. + public SeriesInfo(string path) + { + Path = path; + } + + /// + /// Gets or sets the path. + /// + /// The path. + public string Path { get; set; } + + /// + /// Gets or sets the name of the series. + /// + /// The name of the series. + public string? Name { get; set; } + } +} diff --git a/Emby.Naming/TV/SeriesPathParser.cs b/Emby.Naming/TV/SeriesPathParser.cs new file mode 100644 index 000000000..a62e5f4d6 --- /dev/null +++ b/Emby.Naming/TV/SeriesPathParser.cs @@ -0,0 +1,61 @@ +using System.Globalization; +using Emby.Naming.Common; + +namespace Emby.Naming.TV +{ + /// + /// Used to parse information about series from paths containing more information that only the series name. + /// Uses the same regular expressions as the EpisodePathParser but have different success criteria. + /// + public static class SeriesPathParser + { + /// + /// Parses information about series from path. + /// + /// object containing EpisodeExpressions and MultipleEpisodeExpressions. + /// Path. + /// Returns object. + public static SeriesPathParserResult Parse(NamingOptions options, string path) + { + SeriesPathParserResult? result = null; + + foreach (var expression in options.EpisodeExpressions) + { + var currentResult = Parse(path, expression); + if (currentResult.Success) + { + result = currentResult; + break; + } + } + + if (result != null) + { + if (!string.IsNullOrEmpty(result.SeriesName)) + { + result.SeriesName = result.SeriesName.Trim(' ', '_', '.', '-'); + } + } + + return result ?? new SeriesPathParserResult(); + } + + private static SeriesPathParserResult Parse(string name, EpisodeExpression expression) + { + var result = new SeriesPathParserResult(); + + var match = expression.Regex.Match(name); + + if (match.Success && match.Groups.Count >= 3) + { + if (expression.IsNamed) + { + result.SeriesName = match.Groups["seriesname"].Value; + result.Success = !string.IsNullOrEmpty(result.SeriesName) && !string.IsNullOrEmpty(match.Groups["seasonnumber"]?.Value); + } + } + + return result; + } + } +} diff --git a/Emby.Naming/TV/SeriesPathParserResult.cs b/Emby.Naming/TV/SeriesPathParserResult.cs new file mode 100644 index 000000000..44cd2fdfa --- /dev/null +++ b/Emby.Naming/TV/SeriesPathParserResult.cs @@ -0,0 +1,19 @@ +namespace Emby.Naming.TV +{ + /// + /// Holder object for result. + /// + public class SeriesPathParserResult + { + /// + /// Gets or sets the name of the series. + /// + /// The name of the series. + public string? SeriesName { get; set; } + + /// + /// Gets or sets a value indicating whether parsing was successful. + /// + public bool Success { get; set; } + } +} diff --git a/Emby.Naming/TV/SeriesResolver.cs b/Emby.Naming/TV/SeriesResolver.cs new file mode 100644 index 000000000..156a03c9e --- /dev/null +++ b/Emby.Naming/TV/SeriesResolver.cs @@ -0,0 +1,49 @@ +using System.IO; +using System.Text.RegularExpressions; +using Emby.Naming.Common; + +namespace Emby.Naming.TV +{ + /// + /// Used to resolve information about series from path. + /// + public static class SeriesResolver + { + /// + /// Regex that matches strings of at least 2 characters separated by a dot or underscore. + /// Used for removing separators between words, i.e turns "The_show" into "The show" while + /// preserving namings like "S.H.O.W". + /// + private static readonly Regex _seriesNameRegex = new Regex(@"((?[^\._]{2,})[\._]*)|([\._](?[^\._]{2,}))"); + + /// + /// Resolve information about series from path. + /// + /// object passed to . + /// Path to series. + /// SeriesInfo. + public static SeriesInfo Resolve(NamingOptions options, string path) + { + string seriesName = Path.GetFileName(path); + + SeriesPathParserResult result = SeriesPathParser.Parse(options, path); + if (result.Success) + { + if (!string.IsNullOrEmpty(result.SeriesName)) + { + seriesName = result.SeriesName; + } + } + + if (!string.IsNullOrEmpty(seriesName)) + { + seriesName = _seriesNameRegex.Replace(seriesName, "${a} ${b}").Trim(); + } + + return new SeriesInfo(path) + { + Name = seriesName + }; + } + } +} diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index a1562abd3..a997584a6 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -55,6 +55,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return null; } + var seriesInfo = Naming.TV.SeriesResolver.Resolve(_libraryManager.GetNamingOptions(), args.Path); + var collectionType = args.GetCollectionType(); if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) { @@ -64,7 +66,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return new Series { Path = args.Path, - Name = Path.GetFileName(args.Path) + Name = seriesInfo.Name }; } } @@ -81,7 +83,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return new Series { Path = args.Path, - Name = Path.GetFileName(args.Path) + Name = seriesInfo.Name }; } @@ -95,7 +97,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return new Series { Path = args.Path, - Name = Path.GetFileName(args.Path) + Name = seriesInfo.Name }; } } diff --git a/tests/Jellyfin.Naming.Tests/TV/SeriesPathParserTest.cs b/tests/Jellyfin.Naming.Tests/TV/SeriesPathParserTest.cs new file mode 100644 index 000000000..ceb5f8b73 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/TV/SeriesPathParserTest.cs @@ -0,0 +1,28 @@ +using Emby.Naming.Common; +using Emby.Naming.TV; +using Xunit; + +namespace Jellyfin.Naming.Tests.TV +{ + public class SeriesPathParserTest + { + [Theory] + [InlineData("The.Show.S01", "The.Show")] + [InlineData("/The.Show.S01", "The.Show")] + [InlineData("/some/place/The.Show.S01", "The.Show")] + [InlineData("/something/The.Show.S01", "The.Show")] + [InlineData("The Show Season 10", "The Show")] + [InlineData("The Show S01E01", "The Show")] + [InlineData("The Show S01E01 Episode", "The Show")] + [InlineData("/something/The Show/Season 1", "The Show")] + [InlineData("/something/The Show/S01", "The Show")] + public void SeriesPathParserParseTest(string path, string name) + { + NamingOptions o = new NamingOptions(); + var res = SeriesPathParser.Parse(o, path); + + Assert.Equal(name, res.SeriesName); + Assert.True(res.Success); + } + } +} diff --git a/tests/Jellyfin.Naming.Tests/TV/SeriesResolverTests.cs b/tests/Jellyfin.Naming.Tests/TV/SeriesResolverTests.cs new file mode 100644 index 000000000..97f4b4058 --- /dev/null +++ b/tests/Jellyfin.Naming.Tests/TV/SeriesResolverTests.cs @@ -0,0 +1,28 @@ +using Emby.Naming.Common; +using Emby.Naming.TV; +using Xunit; + +namespace Jellyfin.Naming.Tests.TV +{ + public class SeriesResolverTests + { + [Theory] + [InlineData("The.Show.S01", "The Show")] + [InlineData("The.Show.S01.COMPLETE", "The Show")] + [InlineData("S.H.O.W.S01", "S.H.O.W")] + [InlineData("The.Show.P.I.S01", "The Show P.I")] + [InlineData("The_Show_Season_1", "The Show")] + [InlineData("/something/The_Show/Season 10", "The Show")] + [InlineData("The Show", "The Show")] + [InlineData("/some/path/The Show", "The Show")] + [InlineData("/some/path/The Show s02e10 720p hdtv", "The Show")] + [InlineData("/some/path/The Show s02e10 the episode 720p hdtv", "The Show")] + public void SeriesResolverResolveTest(string path, string name) + { + NamingOptions o = new NamingOptions(); + var res = SeriesResolver.Resolve(o, path); + + Assert.Equal(name, res.Name); + } + } +} -- cgit v1.2.3 From 90174f68e2b477e613d756d78cbfd89c2a33f30a Mon Sep 17 00:00:00 2001 From: Fredrik Lindberg Date: Tue, 31 Aug 2021 22:22:55 +0200 Subject: Dynamically populate LocalAddress based on HTTP request Support populating the LocalAddress field in the system info endpoint based on the x-forwarded-host and x-forwarded-proto header. The x-forwarded-host header must contain both the host and port for the url to be properly constructed. Behind network configuration option that is disabled by default. --- Emby.Server.Implementations/ApplicationHost.cs | 22 +++++++++++++++++----- Jellyfin.Api/Controllers/SystemController.cs | 4 ++-- .../Configuration/NetworkConfiguration.cs | 5 +++++ .../Extensions/ApiServiceCollectionExtensions.cs | 3 ++- MediaBrowser.Controller/IServerApplicationHost.cs | 6 +++--- 5 files changed, 29 insertions(+), 11 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bf7ddace2..64ec5833f 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1073,9 +1073,9 @@ namespace Emby.Server.Implementations /// /// Gets the system status. /// - /// Where this request originated. + /// Where this request originated. /// SystemInfo. - public SystemInfo GetSystemInfo(IPAddress source) + public SystemInfo GetSystemInfo(HttpRequest request) { return new SystemInfo { @@ -1097,7 +1097,7 @@ namespace Emby.Server.Implementations CanLaunchWebBrowser = CanLaunchWebBrowser, TranscodingTempPath = ConfigurationManager.GetTranscodePath(), ServerName = FriendlyName, - LocalAddress = GetSmartApiUrl(source), + LocalAddress = GetSmartApiUrl(request), SupportsLibraryMonitor = true, EncoderLocation = _mediaEncoder.EncoderLocation, SystemArchitecture = RuntimeInformation.OSArchitecture, @@ -1110,7 +1110,7 @@ namespace Emby.Server.Implementations .Select(i => new WakeOnLanInfo(i)) .ToList(); - public PublicSystemInfo GetPublicSystemInfo(IPAddress address) + public PublicSystemInfo GetPublicSystemInfo(HttpRequest request) { return new PublicSystemInfo { @@ -1119,7 +1119,7 @@ namespace Emby.Server.Implementations Id = SystemId, OperatingSystem = MediaBrowser.Common.System.OperatingSystem.Id.ToString(), ServerName = FriendlyName, - LocalAddress = GetSmartApiUrl(address), + LocalAddress = GetSmartApiUrl(request), StartupWizardCompleted = ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted }; } @@ -1150,6 +1150,18 @@ namespace Emby.Server.Implementations /// public string GetSmartApiUrl(HttpRequest request, int? port = null) { + // Return the host in the HTTP request as the API url + if (ConfigurationManager.GetNetworkConfiguration().EnablePublishedServerUriByRequest) + { + int? requestPort = request.Host.Port; + if ((requestPort == 80 && string.Equals(request.Scheme, "http", StringComparison.OrdinalIgnoreCase)) || (requestPort == 443 && string.Equals(request.Scheme, "https", StringComparison.OrdinalIgnoreCase))) + { + requestPort = -1; + } + + return GetLocalApiUrl(request.Host.Host, request.Scheme, requestPort); + } + // Published server ends with a / if (!string.IsNullOrEmpty(PublishedServerUrl)) { diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index bbbe5fb8d..ff81cc53b 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -66,7 +66,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetSystemInfo() { - return _appHost.GetSystemInfo(Request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback); + return _appHost.GetSystemInfo(Request); } /// @@ -78,7 +78,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetPublicSystemInfo() { - return _appHost.GetPublicSystemInfo(Request.HttpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback); + return _appHost.GetPublicSystemInfo(Request); } /// diff --git a/Jellyfin.Networking/Configuration/NetworkConfiguration.cs b/Jellyfin.Networking/Configuration/NetworkConfiguration.cs index faf814c06..61db223d9 100644 --- a/Jellyfin.Networking/Configuration/NetworkConfiguration.cs +++ b/Jellyfin.Networking/Configuration/NetworkConfiguration.cs @@ -226,5 +226,10 @@ namespace Jellyfin.Networking.Configuration /// Gets or sets the known proxies. If the proxy is a network, it's added to the KnownNetworks. /// public string[] KnownProxies { get; set; } = Array.Empty(); + + /// + /// Gets or sets a value indicating whether the published server uri is based on information in HTTP requests. + /// + public bool EnablePublishedServerUriByRequest { get; set; } = false; } } diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index f19e87aba..266dfef69 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -188,7 +188,8 @@ namespace Jellyfin.Server.Extensions // https://github.com/dotnet/aspnetcore/blob/master/src/Middleware/HttpOverrides/src/ForwardedHeadersMiddleware.cs // Enable debug logging on Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware to help investigate issues. - options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; + options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost; + if (config.KnownProxies.Length == 0) { options.KnownNetworks.Clear(); diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 753c18bc7..07aea6ad1 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -51,11 +51,11 @@ namespace MediaBrowser.Controller /// /// Gets the system info. /// - /// The originator of the request. + /// The HTTP request. /// SystemInfo. - SystemInfo GetSystemInfo(IPAddress source); + SystemInfo GetSystemInfo(HttpRequest request); - PublicSystemInfo GetPublicSystemInfo(IPAddress address); + PublicSystemInfo GetPublicSystemInfo(HttpRequest request); /// /// Gets a URL specific for the request. -- cgit v1.2.3 From 9234e5bf80194e45acac25c60cb76f401bffaf96 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Sun, 26 Sep 2021 08:14:36 -0600 Subject: Remove all instances of en-US culture --- Emby.Dlna/Didl/DidlBuilder.cs | 28 +++++++-------- Emby.Dlna/Eventing/DlnaEventManager.cs | 8 ++--- Emby.Dlna/PlayTo/Device.cs | 12 +++---- Emby.Dlna/PlayTo/PlayToController.cs | 8 ++--- Emby.Dlna/PlayTo/SsdpHttpClient.cs | 8 ++--- Emby.Dlna/Server/DescriptionXmlBuilder.cs | 5 ++- .../MediaEncoder/EncodingManager.cs | 3 +- Jellyfin.Api/Controllers/ImageController.cs | 2 +- Jellyfin.Api/Controllers/SubtitleController.cs | 2 +- MediaBrowser.Controller/Entities/Year.cs | 4 +-- .../MediaEncoding/EncodingHelper.cs | 42 +++++++++++----------- MediaBrowser.Controller/MediaEncoding/JobLogger.cs | 11 +++--- .../Images/LocalImageProvider.cs | 4 +-- .../Parsers/BaseItemXmlParser.cs | 8 ++--- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 12 +++---- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 11 ++---- .../Probing/ProbeResultNormalizer.cs | 27 +++++++------- .../Globalization/ILocalizationManager.cs | 4 +-- MediaBrowser.Providers/Manager/ImageSaver.cs | 18 +++++----- .../Plugins/Omdb/OmdbProvider.cs | 13 ++++--- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 10 +++--- .../Parsers/EpisodeNfoParser.cs | 10 +++--- .../Savers/EpisodeNfoSaver.cs | 18 +++++----- 23 files changed, 116 insertions(+), 152 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index c00078499..0a84f30c4 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -41,8 +41,6 @@ namespace Emby.Dlna.Didl private const string NsUpnp = "urn:schemas-upnp-org:metadata-1-0/upnp/"; private const string NsDlna = "urn:schemas-dlna-org:metadata-1-0/"; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly DeviceProfile _profile; private readonly IImageProcessor _imageProcessor; private readonly string _serverAddress; @@ -317,7 +315,7 @@ namespace Emby.Dlna.Didl if (mediaSource.RunTimeTicks.HasValue) { - writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture)); + writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", CultureInfo.InvariantCulture)); } if (filter.Contains("res@size")) @@ -328,7 +326,7 @@ namespace Emby.Dlna.Didl if (size.HasValue) { - writer.WriteAttributeString("size", size.Value.ToString(_usCulture)); + writer.WriteAttributeString("size", size.Value.ToString(CultureInfo.InvariantCulture)); } } } @@ -342,7 +340,7 @@ namespace Emby.Dlna.Didl if (targetChannels.HasValue) { - writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(_usCulture)); + writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(CultureInfo.InvariantCulture)); } if (filter.Contains("res@resolution")) @@ -361,12 +359,12 @@ namespace Emby.Dlna.Didl if (targetSampleRate.HasValue) { - writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(_usCulture)); + writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(CultureInfo.InvariantCulture)); } if (totalBitrate.HasValue) { - writer.WriteAttributeString("bitrate", totalBitrate.Value.ToString(_usCulture)); + writer.WriteAttributeString("bitrate", totalBitrate.Value.ToString(CultureInfo.InvariantCulture)); } var mediaProfile = _profile.GetVideoMediaProfile( @@ -552,7 +550,7 @@ namespace Emby.Dlna.Didl if (mediaSource.RunTimeTicks.HasValue) { - writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", _usCulture)); + writer.WriteAttributeString("duration", TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value).ToString("c", CultureInfo.InvariantCulture)); } if (filter.Contains("res@size")) @@ -563,7 +561,7 @@ namespace Emby.Dlna.Didl if (size.HasValue) { - writer.WriteAttributeString("size", size.Value.ToString(_usCulture)); + writer.WriteAttributeString("size", size.Value.ToString(CultureInfo.InvariantCulture)); } } } @@ -575,17 +573,17 @@ namespace Emby.Dlna.Didl if (targetChannels.HasValue) { - writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(_usCulture)); + writer.WriteAttributeString("nrAudioChannels", targetChannels.Value.ToString(CultureInfo.InvariantCulture)); } if (targetSampleRate.HasValue) { - writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(_usCulture)); + writer.WriteAttributeString("sampleFrequency", targetSampleRate.Value.ToString(CultureInfo.InvariantCulture)); } if (targetAudioBitrate.HasValue) { - writer.WriteAttributeString("bitrate", targetAudioBitrate.Value.ToString(_usCulture)); + writer.WriteAttributeString("bitrate", targetAudioBitrate.Value.ToString(CultureInfo.InvariantCulture)); } var mediaProfile = _profile.GetAudioMediaProfile( @@ -639,7 +637,7 @@ namespace Emby.Dlna.Didl writer.WriteAttributeString("restricted", "1"); writer.WriteAttributeString("searchable", "1"); - writer.WriteAttributeString("childCount", childCount.ToString(_usCulture)); + writer.WriteAttributeString("childCount", childCount.ToString(CultureInfo.InvariantCulture)); var clientId = GetClientId(folder, stubType); @@ -931,11 +929,11 @@ namespace Emby.Dlna.Didl if (item.IndexNumber.HasValue) { - AddValue(writer, "upnp", "originalTrackNumber", item.IndexNumber.Value.ToString(_usCulture), NsUpnp); + AddValue(writer, "upnp", "originalTrackNumber", item.IndexNumber.Value.ToString(CultureInfo.InvariantCulture), NsUpnp); if (item is Episode) { - AddValue(writer, "upnp", "episodeNumber", item.IndexNumber.Value.ToString(_usCulture), NsUpnp); + AddValue(writer, "upnp", "episodeNumber", item.IndexNumber.Value.ToString(CultureInfo.InvariantCulture), NsUpnp); } } } diff --git a/Emby.Dlna/Eventing/DlnaEventManager.cs b/Emby.Dlna/Eventing/DlnaEventManager.cs index b39bd5ce9..d17e23871 100644 --- a/Emby.Dlna/Eventing/DlnaEventManager.cs +++ b/Emby.Dlna/Eventing/DlnaEventManager.cs @@ -26,8 +26,6 @@ namespace Emby.Dlna.Eventing private readonly ILogger _logger; private readonly IHttpClientFactory _httpClientFactory; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - public DlnaEventManager(ILogger logger, IHttpClientFactory httpClientFactory) { _httpClientFactory = httpClientFactory; @@ -83,7 +81,7 @@ namespace Emby.Dlna.Eventing if (!string.IsNullOrEmpty(header)) { // Starts with SECOND- - if (int.TryParse(header.AsSpan().RightPart('-'), NumberStyles.Integer, _usCulture, out var val)) + if (int.TryParse(header.AsSpan().RightPart('-'), NumberStyles.Integer, CultureInfo.InvariantCulture, out var val)) { return val; } @@ -106,7 +104,7 @@ namespace Emby.Dlna.Eventing var response = new EventSubscriptionResponse(string.Empty, "text/plain"); response.Headers["SID"] = subscriptionId; - response.Headers["TIMEOUT"] = string.IsNullOrEmpty(requestedTimeoutString) ? ("SECOND-" + timeoutSeconds.ToString(_usCulture)) : requestedTimeoutString; + response.Headers["TIMEOUT"] = string.IsNullOrEmpty(requestedTimeoutString) ? ("SECOND-" + timeoutSeconds.ToString(CultureInfo.InvariantCulture)) : requestedTimeoutString; return response; } @@ -163,7 +161,7 @@ namespace Emby.Dlna.Eventing options.Headers.TryAddWithoutValidation("NT", subscription.NotificationType); options.Headers.TryAddWithoutValidation("NTS", "upnp:propchange"); options.Headers.TryAddWithoutValidation("SID", subscription.Id); - options.Headers.TryAddWithoutValidation("SEQ", subscription.TriggerCount.ToString(_usCulture)); + options.Headers.TryAddWithoutValidation("SEQ", subscription.TriggerCount.ToString(CultureInfo.InvariantCulture)); try { diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 11fcd81cf..0b2288000 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -20,8 +20,6 @@ namespace Emby.Dlna.PlayTo { public class Device : IDisposable { - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger _logger; @@ -640,7 +638,7 @@ namespace Emby.Dlna.PlayTo return; } - Volume = int.Parse(volumeValue, UsCulture); + Volume = int.Parse(volumeValue, CultureInfo.InvariantCulture); if (Volume > 0) { @@ -842,7 +840,7 @@ namespace Emby.Dlna.PlayTo if (!string.IsNullOrWhiteSpace(duration) && !string.Equals(duration, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase)) { - Duration = TimeSpan.Parse(duration, UsCulture); + Duration = TimeSpan.Parse(duration, CultureInfo.InvariantCulture); } else { @@ -854,7 +852,7 @@ namespace Emby.Dlna.PlayTo if (!string.IsNullOrWhiteSpace(position) && !string.Equals(position, "NOT_IMPLEMENTED", StringComparison.OrdinalIgnoreCase)) { - Position = TimeSpan.Parse(position, UsCulture); + Position = TimeSpan.Parse(position, CultureInfo.InvariantCulture); } var track = result.Document.Descendants("TrackMetaData").FirstOrDefault(); @@ -1194,8 +1192,8 @@ namespace Emby.Dlna.PlayTo var depth = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("depth")); var url = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("url")); - var widthValue = int.Parse(width, NumberStyles.Integer, UsCulture); - var heightValue = int.Parse(height, NumberStyles.Integer, UsCulture); + var widthValue = int.Parse(width, NumberStyles.Integer, CultureInfo.InvariantCulture); + var heightValue = int.Parse(height, NumberStyles.Integer, CultureInfo.InvariantCulture); return new DeviceIcon { diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index 0e49fd2c0..f25d8017e 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -30,8 +30,6 @@ namespace Emby.Dlna.PlayTo { public class PlayToController : ISessionController, IDisposable { - private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US")); - private readonly SessionInfo _session; private readonly ISessionManager _sessionManager; private readonly ILibraryManager _libraryManager; @@ -716,7 +714,7 @@ namespace Emby.Dlna.PlayTo case GeneralCommandType.SetAudioStreamIndex: if (command.Arguments.TryGetValue("Index", out string index)) { - if (int.TryParse(index, NumberStyles.Integer, _usCulture, out var val)) + if (int.TryParse(index, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val)) { return SetAudioStreamIndex(val); } @@ -728,7 +726,7 @@ namespace Emby.Dlna.PlayTo case GeneralCommandType.SetSubtitleStreamIndex: if (command.Arguments.TryGetValue("Index", out index)) { - if (int.TryParse(index, NumberStyles.Integer, _usCulture, out var val)) + if (int.TryParse(index, NumberStyles.Integer, CultureInfo.InvariantCulture, out var val)) { return SetSubtitleStreamIndex(val); } @@ -740,7 +738,7 @@ namespace Emby.Dlna.PlayTo case GeneralCommandType.SetVolume: if (command.Arguments.TryGetValue("Volume", out string vol)) { - if (int.TryParse(vol, NumberStyles.Integer, _usCulture, out var volume)) + if (int.TryParse(vol, NumberStyles.Integer, CultureInfo.InvariantCulture, out var volume)) { return _device.SetVolume(volume, cancellationToken); } diff --git a/Emby.Dlna/PlayTo/SsdpHttpClient.cs b/Emby.Dlna/PlayTo/SsdpHttpClient.cs index 4b92fbff4..cade7b4c2 100644 --- a/Emby.Dlna/PlayTo/SsdpHttpClient.cs +++ b/Emby.Dlna/PlayTo/SsdpHttpClient.cs @@ -20,8 +20,6 @@ namespace Emby.Dlna.PlayTo private const string USERAGENT = "Microsoft-Windows/6.2 UPnP/1.0 Microsoft-DLNA DLNADOC/1.50"; private const string FriendlyName = "Jellyfin"; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IHttpClientFactory _httpClientFactory; public SsdpHttpClient(IHttpClientFactory httpClientFactory) @@ -80,10 +78,10 @@ namespace Emby.Dlna.PlayTo { using var options = new HttpRequestMessage(new HttpMethod("SUBSCRIBE"), url); options.Headers.UserAgent.ParseAdd(USERAGENT); - options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(_usCulture)); - options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(_usCulture) + ">"); + options.Headers.TryAddWithoutValidation("HOST", ip + ":" + port.ToString(CultureInfo.InvariantCulture)); + options.Headers.TryAddWithoutValidation("CALLBACK", "<" + localIp + ":" + eventport.ToString(CultureInfo.InvariantCulture) + ">"); options.Headers.TryAddWithoutValidation("NT", "upnp:event"); - options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(_usCulture)); + options.Headers.TryAddWithoutValidation("TIMEOUT", "Second-" + timeOut.ToString(CultureInfo.InvariantCulture)); using var response = await _httpClientFactory.CreateClient(NamedClient.Default) .SendAsync(options, HttpCompletionOption.ResponseHeadersRead) diff --git a/Emby.Dlna/Server/DescriptionXmlBuilder.cs b/Emby.Dlna/Server/DescriptionXmlBuilder.cs index 09525aae4..80a45f2b2 100644 --- a/Emby.Dlna/Server/DescriptionXmlBuilder.cs +++ b/Emby.Dlna/Server/DescriptionXmlBuilder.cs @@ -15,7 +15,6 @@ namespace Emby.Dlna.Server { private readonly DeviceProfile _profile; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly string _serverUdn; private readonly string _serverAddress; private readonly string _serverName; @@ -193,10 +192,10 @@ namespace Emby.Dlna.Server .Append(SecurityElement.Escape(icon.MimeType ?? string.Empty)) .Append(""); builder.Append("") - .Append(SecurityElement.Escape(icon.Width.ToString(_usCulture))) + .Append(SecurityElement.Escape(icon.Width.ToString(CultureInfo.InvariantCulture))) .Append(""); builder.Append("") - .Append(SecurityElement.Escape(icon.Height.ToString(_usCulture))) + .Append(SecurityElement.Escape(icon.Height.ToString(CultureInfo.InvariantCulture))) .Append(""); builder.Append("") .Append(SecurityElement.Escape(icon.Depth ?? string.Empty)) diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index 8aaa1f7bb..ac6606d39 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -23,7 +23,6 @@ namespace Emby.Server.Implementations.MediaEncoder { public class EncodingManager : IEncodingManager { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IFileSystem _fileSystem; private readonly ILogger _logger; private readonly IMediaEncoder _encoder; @@ -193,7 +192,7 @@ namespace Emby.Server.Implementations.MediaEncoder private string GetChapterImagePath(Video video, long chapterPositionTicks) { - var filename = video.DateModified.Ticks.ToString(_usCulture) + "_" + chapterPositionTicks.ToString(_usCulture) + ".jpg"; + var filename = video.DateModified.Ticks.ToString(CultureInfo.InvariantCulture) + "_" + chapterPositionTicks.ToString(CultureInfo.InvariantCulture) + ".jpg"; return Path.Combine(GetChapterImagesPath(video), filename); } diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index b1c860d61..86933074d 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -2007,7 +2007,7 @@ namespace Jellyfin.Api.Controllers Response.Headers.Add(HeaderNames.CacheControl, "public"); } - Response.Headers.Add(HeaderNames.LastModified, dateImageModified.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss \"GMT\"", new CultureInfo("en-US", false))); + Response.Headers.Add(HeaderNames.LastModified, dateImageModified.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss \"GMT\"", CultureInfo.InvariantCulture)); // if the image was not modified since "ifModifiedSinceHeader"-header, return a HTTP status code 304 not modified if (!(dateImageModified > ifModifiedSinceHeader) && cacheDuration.HasValue) diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index 11f67ee89..1849dd047 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -376,7 +376,7 @@ namespace Jellyfin.Api.Controllers var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks); var url = string.Format( - CultureInfo.CurrentCulture, + CultureInfo.InvariantCulture, "stream.vtt?CopyTimestamps=true&AddVttTimeMap=true&StartPositionTicks={0}&EndPositionTicks={1}&api_key={2}", positionTicks.ToString(CultureInfo.InvariantCulture), endPositionTicks.ToString(CultureInfo.InvariantCulture), diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index 0853200dd..afdaf448b 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -57,9 +57,7 @@ namespace MediaBrowser.Controller.Entities public IList GetTaggedItems(InternalItemsQuery query) { - var usCulture = new CultureInfo("en-US"); - - if (!int.TryParse(Name, NumberStyles.Integer, usCulture, out var year)) + if (!int.TryParse(Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var year)) { return new List(); } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index bdb379332..5715194b8 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -21,8 +21,6 @@ namespace MediaBrowser.Controller.MediaEncoding { public class EncodingHelper { - private static readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IMediaEncoder _mediaEncoder; private readonly ISubtitleEncoder _subtitleEncoder; @@ -816,7 +814,7 @@ namespace MediaBrowser.Controller.MediaEncoding public static string NormalizeTranscodingLevel(EncodingJobInfo state, string level) { - if (double.TryParse(level, NumberStyles.Any, _usCulture, out double requestLevel)) + if (double.TryParse(level, NumberStyles.Any, CultureInfo.InvariantCulture, out double requestLevel)) { if (string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase) || string.Equals(state.ActualOutputVideoCodec, "h265", StringComparison.OrdinalIgnoreCase)) @@ -911,7 +909,7 @@ namespace MediaBrowser.Controller.MediaEncoding CultureInfo.InvariantCulture, "subtitles='{0}:si={1}'{2}", _mediaEncoder.EscapeSubtitleFilterPath(mediaPath), - state.InternalSubtitleStreamOffset.ToString(_usCulture), + state.InternalSubtitleStreamOffset.ToString(CultureInfo.InvariantCulture), // fallbackFontParam, setPtsParam); } @@ -1217,7 +1215,7 @@ namespace MediaBrowser.Controller.MediaEncoding param += string.Format( CultureInfo.InvariantCulture, " -speed 16 -quality good -profile:v {0} -slices 8 -crf {1} -qmin {2} -qmax {3}", - profileScore.ToString(_usCulture), + profileScore.ToString(CultureInfo.InvariantCulture), crf, qmin, qmax); @@ -1289,7 +1287,7 @@ namespace MediaBrowser.Controller.MediaEncoding var framerate = GetFramerateParam(state); if (framerate.HasValue) { - param += string.Format(CultureInfo.InvariantCulture, " -r {0}", framerate.Value.ToString(_usCulture)); + param += string.Format(CultureInfo.InvariantCulture, " -r {0}", framerate.Value.ToString(CultureInfo.InvariantCulture)); } var targetVideoCodec = state.ActualOutputVideoCodec; @@ -1393,7 +1391,7 @@ namespace MediaBrowser.Controller.MediaEncoding else if (string.Equals(videoEncoder, "hevc_qsv", StringComparison.OrdinalIgnoreCase)) { // hevc_qsv use -level 51 instead of -level 153. - if (double.TryParse(level, NumberStyles.Any, _usCulture, out double hevcLevel)) + if (double.TryParse(level, NumberStyles.Any, CultureInfo.InvariantCulture, out double hevcLevel)) { param += " -level " + (hevcLevel / 3); } @@ -1555,7 +1553,7 @@ namespace MediaBrowser.Controller.MediaEncoding // If a specific level was requested, the source must match or be less than var level = state.GetRequestedLevel(videoStream.Codec); if (!string.IsNullOrEmpty(level) - && double.TryParse(level, NumberStyles.Any, _usCulture, out var requestLevel)) + && double.TryParse(level, NumberStyles.Any, CultureInfo.InvariantCulture, out var requestLevel)) { if (!videoStream.Level.HasValue) { @@ -1803,7 +1801,7 @@ namespace MediaBrowser.Controller.MediaEncoding && state.AudioStream.Channels.Value > 5 && !encodingOptions.DownMixAudioBoost.Equals(1)) { - filters.Add("volume=" + encodingOptions.DownMixAudioBoost.ToString(_usCulture)); + filters.Add("volume=" + encodingOptions.DownMixAudioBoost.ToString(CultureInfo.InvariantCulture)); } var isCopyingTimestamps = state.CopyTimestamps || state.TranscodingType != TranscodingJobType.Progressive; @@ -2434,8 +2432,8 @@ namespace MediaBrowser.Controller.MediaEncoding { if (isExynosV4L2) { - var widthParam = requestedWidth.Value.ToString(_usCulture); - var heightParam = requestedHeight.Value.ToString(_usCulture); + var widthParam = requestedWidth.Value.ToString(CultureInfo.InvariantCulture); + var heightParam = requestedHeight.Value.ToString(CultureInfo.InvariantCulture); filters.Add( string.Format( @@ -2453,8 +2451,8 @@ namespace MediaBrowser.Controller.MediaEncoding // If Max dimensions were supplied, for width selects lowest even number between input width and width req size and selects lowest even number from in width*display aspect and requested size else if (requestedMaxWidth.HasValue && requestedMaxHeight.HasValue) { - var maxWidthParam = requestedMaxWidth.Value.ToString(_usCulture); - var maxHeightParam = requestedMaxHeight.Value.ToString(_usCulture); + var maxWidthParam = requestedMaxWidth.Value.ToString(CultureInfo.InvariantCulture); + var maxHeightParam = requestedMaxHeight.Value.ToString(CultureInfo.InvariantCulture); if (isExynosV4L2) { @@ -2486,7 +2484,7 @@ namespace MediaBrowser.Controller.MediaEncoding } else { - var widthParam = requestedWidth.Value.ToString(_usCulture); + var widthParam = requestedWidth.Value.ToString(CultureInfo.InvariantCulture); filters.Add( string.Format( @@ -2499,7 +2497,7 @@ namespace MediaBrowser.Controller.MediaEncoding // If a fixed height was requested else if (requestedHeight.HasValue) { - var heightParam = requestedHeight.Value.ToString(_usCulture); + var heightParam = requestedHeight.Value.ToString(CultureInfo.InvariantCulture); if (isExynosV4L2) { @@ -2522,7 +2520,7 @@ namespace MediaBrowser.Controller.MediaEncoding // If a max width was requested else if (requestedMaxWidth.HasValue) { - var maxWidthParam = requestedMaxWidth.Value.ToString(_usCulture); + var maxWidthParam = requestedMaxWidth.Value.ToString(CultureInfo.InvariantCulture); if (isExynosV4L2) { @@ -2545,7 +2543,7 @@ namespace MediaBrowser.Controller.MediaEncoding // If a max height was requested else if (requestedMaxHeight.HasValue) { - var maxHeightParam = requestedMaxHeight.Value.ToString(_usCulture); + var maxHeightParam = requestedMaxHeight.Value.ToString(CultureInfo.InvariantCulture); if (isExynosV4L2) { @@ -4122,12 +4120,12 @@ namespace MediaBrowser.Controller.MediaEncoding if (bitrate.HasValue) { - args += " -ab " + bitrate.Value.ToString(_usCulture); + args += " -ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture); } if (state.OutputAudioSampleRate.HasValue) { - args += " -ar " + state.OutputAudioSampleRate.Value.ToString(_usCulture); + args += " -ar " + state.OutputAudioSampleRate.Value.ToString(CultureInfo.InvariantCulture); } args += GetAudioFilterParam(state, encodingOptions); @@ -4143,12 +4141,12 @@ namespace MediaBrowser.Controller.MediaEncoding if (bitrate.HasValue) { - audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(_usCulture)); + audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(CultureInfo.InvariantCulture)); } if (state.OutputAudioChannels.HasValue) { - audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(_usCulture)); + audioTranscodeParams.Add("-ac " + state.OutputAudioChannels.Value.ToString(CultureInfo.InvariantCulture)); } // opus will fail on 44100 @@ -4156,7 +4154,7 @@ namespace MediaBrowser.Controller.MediaEncoding { if (state.OutputAudioSampleRate.HasValue) { - audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(_usCulture)); + audioTranscodeParams.Add("-ar " + state.OutputAudioSampleRate.Value.ToString(CultureInfo.InvariantCulture)); } } diff --git a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs index c4ddc5618..933f440ac 100644 --- a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs +++ b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs @@ -13,7 +13,6 @@ namespace MediaBrowser.Controller.MediaEncoding { public class JobLogger { - private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US")); private readonly ILogger _logger; public JobLogger(ILogger logger) @@ -87,7 +86,7 @@ namespace MediaBrowser.Controller.MediaEncoding { var rate = parts[i + 1]; - if (float.TryParse(rate, NumberStyles.Any, _usCulture, out var val)) + if (float.TryParse(rate, NumberStyles.Any, CultureInfo.InvariantCulture, out var val)) { framerate = val; } @@ -96,7 +95,7 @@ namespace MediaBrowser.Controller.MediaEncoding { var rate = part.Split('=', 2)[^1]; - if (float.TryParse(rate, NumberStyles.Any, _usCulture, out var val)) + if (float.TryParse(rate, NumberStyles.Any, CultureInfo.InvariantCulture, out var val)) { framerate = val; } @@ -106,7 +105,7 @@ namespace MediaBrowser.Controller.MediaEncoding { var time = part.Split('=', 2)[^1]; - if (TimeSpan.TryParse(time, _usCulture, out var val)) + if (TimeSpan.TryParse(time, CultureInfo.InvariantCulture, out var val)) { var currentMs = startMs + val.TotalMilliseconds; @@ -128,7 +127,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (scale.HasValue) { - if (long.TryParse(size, NumberStyles.Any, _usCulture, out var val)) + if (long.TryParse(size, NumberStyles.Any, CultureInfo.InvariantCulture, out var val)) { bytesTranscoded = val * scale.Value; } @@ -147,7 +146,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (scale.HasValue) { - if (float.TryParse(rate, NumberStyles.Any, _usCulture, out var val)) + if (float.TryParse(rate, NumberStyles.Any, CultureInfo.InvariantCulture, out var val)) { bitRate = (int)Math.Ceiling(val * scale.Value); } diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs index b7398880e..988581df9 100644 --- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs @@ -60,8 +60,6 @@ namespace MediaBrowser.LocalMetadata.Images private readonly IFileSystem _fileSystem; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - /// /// Initializes a new instance of the class. /// @@ -434,7 +432,7 @@ namespace MediaBrowser.LocalMetadata.Images var seasonMarker = seasonNumber.Value == 0 ? "-specials" - : seasonNumber.Value.ToString("00", _usCulture); + : seasonNumber.Value.ToString("00", CultureInfo.InvariantCulture); // Get this one directly from the file system since we have to go up a level if (!string.Equals(prefix, seasonMarker, StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 7c9e681d6..5a36c1663 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -21,8 +21,6 @@ namespace MediaBrowser.LocalMetadata.Parsers public class BaseItemXmlParser where T : BaseItem { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private Dictionary? _validProviderIds; /// @@ -180,7 +178,7 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrEmpty(text)) { - if (float.TryParse(text, NumberStyles.Any, _usCulture, out var value)) + if (float.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { item.CriticRating = value; } @@ -332,7 +330,7 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrWhiteSpace(text)) { - if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, _usCulture, out var runtime)) + if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, CultureInfo.InvariantCulture, out var runtime)) { item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; } @@ -1095,7 +1093,7 @@ namespace MediaBrowser.LocalMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - if (int.TryParse(val, NumberStyles.Integer, _usCulture, out var intVal)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intVal)) { sortOrder = intVal; } diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 6a3896eb6..6f66fd61b 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -25,8 +25,6 @@ namespace MediaBrowser.LocalMetadata.Savers /// public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss"; - private static readonly CultureInfo _usCulture = new CultureInfo("en-US"); - /// /// Initializes a new instance of the class. /// @@ -205,7 +203,7 @@ namespace MediaBrowser.LocalMetadata.Savers if (item.CriticRating.HasValue) { - writer.WriteElementString("CriticRating", item.CriticRating.Value.ToString(_usCulture)); + writer.WriteElementString("CriticRating", item.CriticRating.Value.ToString(CultureInfo.InvariantCulture)); } if (!string.IsNullOrEmpty(item.Overview)) @@ -289,12 +287,12 @@ namespace MediaBrowser.LocalMetadata.Savers if (item.CommunityRating.HasValue) { - writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(_usCulture)); + writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(CultureInfo.InvariantCulture)); } if (item.ProductionYear.HasValue && item is not Person) { - writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(_usCulture)); + writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(CultureInfo.InvariantCulture)); } if (item is IHasAspectRatio hasAspectRatio) @@ -322,7 +320,7 @@ namespace MediaBrowser.LocalMetadata.Savers { var timespan = TimeSpan.FromTicks(runTimeTicks.Value); - writer.WriteElementString("RunningTime", Math.Floor(timespan.TotalMinutes).ToString(_usCulture)); + writer.WriteElementString("RunningTime", Math.Floor(timespan.TotalMinutes).ToString(CultureInfo.InvariantCulture)); } if (item.ProviderIds != null) @@ -395,7 +393,7 @@ namespace MediaBrowser.LocalMetadata.Savers if (person.SortOrder.HasValue) { - writer.WriteElementString("SortOrder", person.SortOrder.Value.ToString(_usCulture)); + writer.WriteElementString("SortOrder", person.SortOrder.Value.ToString(CultureInfo.InvariantCulture)); } writer.WriteEndElement(); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4cbd1bbc8..06fe95ce8 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -43,11 +43,6 @@ namespace MediaBrowser.MediaEncoding.Encoder /// internal const int DefaultHdrImageExtractionTimeout = 20000; - /// - /// The us culture. - /// - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly ILogger _logger; private readonly IServerConfigurationManager _configurationManager; private readonly IFileSystem _fileSystem; @@ -687,7 +682,7 @@ namespace MediaBrowser.MediaEncoding.Encoder public string GetTimeParameter(TimeSpan time) { - return time.ToString(@"hh\:mm\:ss\.fff", _usCulture); + return time.ToString(@"hh\:mm\:ss\.fff", CultureInfo.InvariantCulture); } public async Task ExtractVideoImagesOnInterval( @@ -704,11 +699,11 @@ namespace MediaBrowser.MediaEncoding.Encoder { var inputArgument = GetInputArgument(inputFile, mediaSource); - var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(_usCulture); + var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(CultureInfo.InvariantCulture); if (maxWidth.HasValue) { - var maxWidthParam = maxWidth.Value.ToString(_usCulture); + var maxWidthParam = maxWidth.Value.ToString(CultureInfo.InvariantCulture); vf += string.Format(CultureInfo.InvariantCulture, ",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam); } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 26f629a31..9ed6c264e 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -30,7 +30,6 @@ namespace MediaBrowser.MediaEncoding.Probing private static readonly Regex _performerPattern = new (@"(?.*) \((?.*)\)"); - private readonly CultureInfo _usCulture = new ("en-US"); private readonly ILogger _logger; private readonly ILocalizationManager _localization; @@ -83,7 +82,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (!string.IsNullOrEmpty(data.Format.BitRate)) { - if (int.TryParse(data.Format.BitRate, NumberStyles.Any, _usCulture, out var value)) + if (int.TryParse(data.Format.BitRate, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { info.Bitrate = value; } @@ -191,7 +190,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (data.Format != null && !string.IsNullOrEmpty(data.Format.Duration)) { - info.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.Format.Duration, _usCulture)).Ticks; + info.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.Format.Duration, CultureInfo.InvariantCulture)).Ticks; } FetchWtvInfo(info, data); @@ -673,7 +672,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (!string.IsNullOrEmpty(streamInfo.SampleRate)) { - if (int.TryParse(streamInfo.SampleRate, NumberStyles.Any, _usCulture, out var value)) + if (int.TryParse(streamInfo.SampleRate, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { stream.SampleRate = value; } @@ -802,7 +801,7 @@ namespace MediaBrowser.MediaEncoding.Probing if (!string.IsNullOrEmpty(streamInfo.BitRate)) { - if (int.TryParse(streamInfo.BitRate, NumberStyles.Any, _usCulture, out var value)) + if (int.TryParse(streamInfo.BitRate, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { bitrate = value; } @@ -815,7 +814,7 @@ namespace MediaBrowser.MediaEncoding.Probing && (stream.Type == MediaStreamType.Video || (isAudio && stream.Type == MediaStreamType.Audio))) { // If the stream info doesn't have a bitrate get the value from the media format info - if (int.TryParse(formatInfo.BitRate, NumberStyles.Any, _usCulture, out var value)) + if (int.TryParse(formatInfo.BitRate, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { bitrate = value; } @@ -921,8 +920,8 @@ namespace MediaBrowser.MediaEncoding.Probing var parts = (original ?? string.Empty).Split(':'); if (!(parts.Length == 2 && - int.TryParse(parts[0], NumberStyles.Any, _usCulture, out var width) && - int.TryParse(parts[1], NumberStyles.Any, _usCulture, out var height) && + int.TryParse(parts[0], NumberStyles.Any, CultureInfo.InvariantCulture, out var width) && + int.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var height) && width > 0 && height > 0)) { @@ -1008,11 +1007,11 @@ namespace MediaBrowser.MediaEncoding.Probing if (parts.Length == 2) { - result = float.Parse(parts[0], _usCulture) / float.Parse(parts[1], _usCulture); + result = float.Parse(parts[0], CultureInfo.InvariantCulture) / float.Parse(parts[1], CultureInfo.InvariantCulture); } else { - result = float.Parse(parts[0], _usCulture); + result = float.Parse(parts[0], CultureInfo.InvariantCulture); } return float.IsNaN(result) ? null : result; @@ -1039,7 +1038,7 @@ namespace MediaBrowser.MediaEncoding.Probing // If we got something, parse it if (!string.IsNullOrEmpty(duration)) { - data.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, _usCulture)).Ticks; + data.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, CultureInfo.InvariantCulture)).Ticks; } } @@ -1101,7 +1100,7 @@ namespace MediaBrowser.MediaEncoding.Probing return; } - info.Size = string.IsNullOrEmpty(data.Format.Size) ? null : long.Parse(data.Format.Size, _usCulture); + info.Size = string.IsNullOrEmpty(data.Format.Size) ? null : long.Parse(data.Format.Size, CultureInfo.InvariantCulture); } private void SetAudioInfoFromTags(MediaInfo audio, IReadOnlyDictionary tags) @@ -1144,7 +1143,7 @@ namespace MediaBrowser.MediaEncoding.Probing { Name = match.Groups["name"].Value, Type = PersonType.Actor, - Role = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(match.Groups["instrument"].Value) + Role = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(match.Groups["instrument"].Value) }); } } @@ -1443,7 +1442,7 @@ namespace MediaBrowser.MediaEncoding.Probing .ToArray(); } - if (tags.TryGetValue("WM/OriginalReleaseTime", out var year) && int.TryParse(year, NumberStyles.Integer, _usCulture, out var parsedYear)) + if (tags.TryGetValue("WM/OriginalReleaseTime", out var year) && int.TryParse(year, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedYear)) { video.ProductionYear = parsedYear; } diff --git a/MediaBrowser.Model/Globalization/ILocalizationManager.cs b/MediaBrowser.Model/Globalization/ILocalizationManager.cs index b213e7aa0..406d32cde 100644 --- a/MediaBrowser.Model/Globalization/ILocalizationManager.cs +++ b/MediaBrowser.Model/Globalization/ILocalizationManager.cs @@ -56,10 +56,10 @@ namespace MediaBrowser.Model.Globalization IEnumerable GetLocalizationOptions(); /// - /// Returns the correct for the given language. + /// Returns the correct for the given language. /// /// The language. - /// The correct for the given language. + /// The correct for the given language. CultureDto? FindLanguageInfo(string language); } } diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 7d259a9d3..4b05edd67 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -29,8 +29,6 @@ namespace MediaBrowser.Providers.Manager /// public class ImageSaver { - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - /// /// The _config. /// @@ -377,7 +375,7 @@ namespace MediaBrowser.Providers.Manager var seasonMarker = season.IndexNumber.Value == 0 ? "-specials" - : season.IndexNumber.Value.ToString("00", UsCulture); + : season.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture); var imageFilename = "season" + seasonMarker + "-landscape" + extension; @@ -400,7 +398,7 @@ namespace MediaBrowser.Providers.Manager var seasonMarker = season.IndexNumber.Value == 0 ? "-specials" - : season.IndexNumber.Value.ToString("00", UsCulture); + : season.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture); var imageFilename = "season" + seasonMarker + "-banner" + extension; @@ -495,12 +493,12 @@ namespace MediaBrowser.Providers.Manager var filenames = images.Select(i => Path.GetFileNameWithoutExtension(i.Path)).ToList(); var current = 1; - while (filenames.Contains(numberedIndexPrefix + current.ToString(UsCulture), StringComparer.OrdinalIgnoreCase)) + while (filenames.Contains(numberedIndexPrefix + current.ToString(CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase)) { current++; } - return numberedIndexPrefix + current.ToString(UsCulture); + return numberedIndexPrefix + current.ToString(CultureInfo.InvariantCulture); } /// @@ -539,7 +537,7 @@ namespace MediaBrowser.Providers.Manager var seasonMarker = season.IndexNumber.Value == 0 ? "-specials" - : season.IndexNumber.Value.ToString("00", UsCulture); + : season.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture); var imageFilename = "season" + seasonMarker + "-fanart" + extension; @@ -556,7 +554,7 @@ namespace MediaBrowser.Providers.Manager if (item.IsInMixedFolder) { - return new[] { GetSavePathForItemInMixedFolder(item, type, "fanart" + outputIndex.ToString(UsCulture), extension) }; + return new[] { GetSavePathForItemInMixedFolder(item, type, "fanart" + outputIndex.ToString(CultureInfo.InvariantCulture), extension) }; } var extraFanartFilename = GetBackdropSaveFilename(item.GetImages(ImageType.Backdrop), "fanart", "fanart", outputIndex); @@ -568,7 +566,7 @@ namespace MediaBrowser.Providers.Manager if (EnableExtraThumbsDuplication) { - list.Add(Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + outputIndex.ToString(UsCulture) + extension)); + list.Add(Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + outputIndex.ToString(CultureInfo.InvariantCulture) + extension)); } return list.ToArray(); @@ -582,7 +580,7 @@ namespace MediaBrowser.Providers.Manager var seasonMarker = season.IndexNumber.Value == 0 ? "-specials" - : season.IndexNumber.Value.ToString("00", UsCulture); + : season.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture); var imageFilename = "season" + seasonMarker + "-poster" + extension; diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 479ae0f39..b2bc58eea 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -26,7 +26,6 @@ namespace MediaBrowser.Providers.Plugins.Omdb private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _configurationManager; private readonly IHttpClientFactory _httpClientFactory; - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IApplicationHost _appHost; private readonly JsonSerializerOptions _jsonOptions; @@ -79,7 +78,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb } if (!string.IsNullOrEmpty(result.Year) && result.Year.Length >= 4 - && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, _usCulture, out var year) + && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, CultureInfo.InvariantCulture, out var year) && year >= 0) { item.ProductionYear = year; @@ -93,14 +92,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb } if (!string.IsNullOrEmpty(result.imdbVotes) - && int.TryParse(result.imdbVotes, NumberStyles.Number, _usCulture, out var voteCount) + && int.TryParse(result.imdbVotes, NumberStyles.Number, CultureInfo.InvariantCulture, out var voteCount) && voteCount >= 0) { // item.VoteCount = voteCount; } if (!string.IsNullOrEmpty(result.imdbRating) - && float.TryParse(result.imdbRating, NumberStyles.Any, _usCulture, out var imdbRating) + && float.TryParse(result.imdbRating, NumberStyles.Any, CultureInfo.InvariantCulture, out var imdbRating) && imdbRating >= 0) { item.CommunityRating = imdbRating; @@ -191,7 +190,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb } if (!string.IsNullOrEmpty(result.Year) && result.Year.Length >= 4 - && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, _usCulture, out var year) + && int.TryParse(result.Year.AsSpan().Slice(0, 4), NumberStyles.Number, CultureInfo.InvariantCulture, out var year) && year >= 0) { item.ProductionYear = year; @@ -205,14 +204,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb } if (!string.IsNullOrEmpty(result.imdbVotes) - && int.TryParse(result.imdbVotes, NumberStyles.Number, _usCulture, out var voteCount) + && int.TryParse(result.imdbVotes, NumberStyles.Number, CultureInfo.InvariantCulture, out var voteCount) && voteCount >= 0) { // item.VoteCount = voteCount; } if (!string.IsNullOrEmpty(result.imdbRating) - && float.TryParse(result.imdbRating, NumberStyles.Any, _usCulture, out var imdbRating) + && float.TryParse(result.imdbRating, NumberStyles.Any, CultureInfo.InvariantCulture, out var imdbRating) && imdbRating >= 0) { item.CommunityRating = imdbRating; diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index f7f4ea065..9d558b6ce 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -58,8 +58,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers _directoryService = directoryService; } - protected CultureInfo UsCulture { get; } = new CultureInfo("en-US"); - /// /// Gets the logger. /// @@ -309,7 +307,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrEmpty(text)) { - if (float.TryParse(text, NumberStyles.Any, UsCulture, out var value)) + if (float.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) { item.CriticRating = value; } @@ -370,7 +368,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers var val = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(val) && userData != null) { - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var count)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var count)) { userData.PlayCount = count; } @@ -475,7 +473,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(text)) { - if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, UsCulture, out var runtime)) + if (int.TryParse(text.AsSpan().LeftPart(' '), NumberStyles.Integer, CultureInfo.InvariantCulture, out var runtime)) { item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks; } @@ -1265,7 +1263,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var intVal)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intVal)) { sortOrder = intVal; } diff --git a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs index 3a305024e..d2f349ad7 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs @@ -163,7 +163,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) { item.AirsBeforeEpisodeNumber = rval; } @@ -179,7 +179,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) { item.AirsAfterSeasonNumber = rval; } @@ -195,7 +195,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) { item.AirsBeforeSeasonNumber = rval; } @@ -211,7 +211,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) { item.AirsBeforeSeasonNumber = rval; } @@ -227,7 +227,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { // int.TryParse is local aware, so it can be problematic, force us culture - if (int.TryParse(val, NumberStyles.Integer, UsCulture, out var rval)) + if (int.TryParse(val, NumberStyles.Integer, CultureInfo.InvariantCulture, out var rval)) { item.AirsBeforeEpisodeNumber = rval; } diff --git a/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs index 62f80e81b..2cd3fdf02 100644 --- a/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs @@ -17,8 +17,6 @@ namespace MediaBrowser.XbmcMetadata.Savers /// public class EpisodeNfoSaver : BaseNfoSaver { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - /// /// Initializes a new instance of the class. /// @@ -60,17 +58,17 @@ namespace MediaBrowser.XbmcMetadata.Savers if (episode.IndexNumber.HasValue) { - writer.WriteElementString("episode", episode.IndexNumber.Value.ToString(_usCulture)); + writer.WriteElementString("episode", episode.IndexNumber.Value.ToString(CultureInfo.InvariantCulture)); } if (episode.IndexNumberEnd.HasValue) { - writer.WriteElementString("episodenumberend", episode.IndexNumberEnd.Value.ToString(_usCulture)); + writer.WriteElementString("episodenumberend", episode.IndexNumberEnd.Value.ToString(CultureInfo.InvariantCulture)); } if (episode.ParentIndexNumber.HasValue) { - writer.WriteElementString("season", episode.ParentIndexNumber.Value.ToString(_usCulture)); + writer.WriteElementString("season", episode.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture)); } if (episode.PremiereDate.HasValue) @@ -84,28 +82,28 @@ namespace MediaBrowser.XbmcMetadata.Savers { if (episode.AirsAfterSeasonNumber.HasValue && episode.AirsAfterSeasonNumber.Value != -1) { - writer.WriteElementString("airsafter_season", episode.AirsAfterSeasonNumber.Value.ToString(_usCulture)); + writer.WriteElementString("airsafter_season", episode.AirsAfterSeasonNumber.Value.ToString(CultureInfo.InvariantCulture)); } if (episode.AirsBeforeEpisodeNumber.HasValue && episode.AirsBeforeEpisodeNumber.Value != -1) { - writer.WriteElementString("airsbefore_episode", episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)); + writer.WriteElementString("airsbefore_episode", episode.AirsBeforeEpisodeNumber.Value.ToString(CultureInfo.InvariantCulture)); } if (episode.AirsBeforeSeasonNumber.HasValue && episode.AirsBeforeSeasonNumber.Value != -1) { - writer.WriteElementString("airsbefore_season", episode.AirsBeforeSeasonNumber.Value.ToString(_usCulture)); + writer.WriteElementString("airsbefore_season", episode.AirsBeforeSeasonNumber.Value.ToString(CultureInfo.InvariantCulture)); } if (episode.AirsBeforeEpisodeNumber.HasValue && episode.AirsBeforeEpisodeNumber.Value != -1) { - writer.WriteElementString("displayepisode", episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)); + writer.WriteElementString("displayepisode", episode.AirsBeforeEpisodeNumber.Value.ToString(CultureInfo.InvariantCulture)); } var specialSeason = episode.AiredSeasonNumber; if (specialSeason.HasValue && specialSeason.Value != -1) { - writer.WriteElementString("displayseason", specialSeason.Value.ToString(_usCulture)); + writer.WriteElementString("displayseason", specialSeason.Value.ToString(CultureInfo.InvariantCulture)); } } } -- cgit v1.2.3 From 7668cd13f559d25833ad53e85e939f1d7b836111 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Sun, 26 Sep 2021 16:23:43 -0600 Subject: Create output directory when extracting archive files --- Emby.Server.Implementations/Archiving/ZipClient.cs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Archiving/ZipClient.cs b/Emby.Server.Implementations/Archiving/ZipClient.cs index 591ae547d..9e1d550eb 100644 --- a/Emby.Server.Implementations/Archiving/ZipClient.cs +++ b/Emby.Server.Implementations/Archiving/ZipClient.cs @@ -45,6 +45,7 @@ namespace Emby.Server.Implementations.Archiving options.Overwrite = true; } + Directory.CreateDirectory(targetPath); reader.WriteAllToDirectory(targetPath, options); } @@ -58,6 +59,7 @@ namespace Emby.Server.Implementations.Archiving Overwrite = overwriteExistingFiles }; + Directory.CreateDirectory(targetPath); reader.WriteAllToDirectory(targetPath, options); } @@ -71,6 +73,7 @@ namespace Emby.Server.Implementations.Archiving Overwrite = overwriteExistingFiles }; + Directory.CreateDirectory(targetPath); reader.WriteAllToDirectory(targetPath, options); } @@ -120,6 +123,7 @@ namespace Emby.Server.Implementations.Archiving Overwrite = overwriteExistingFiles }; + Directory.CreateDirectory(targetPath); reader.WriteAllToDirectory(targetPath, options); } @@ -151,6 +155,7 @@ namespace Emby.Server.Implementations.Archiving Overwrite = overwriteExistingFiles }; + Directory.CreateDirectory(targetPath); reader.WriteAllToDirectory(targetPath, options); } } -- cgit v1.2.3 From 7bf2ece20e11cefca9160d75cd0d9e80bb04fe46 Mon Sep 17 00:00:00 2001 From: Tim040 Date: Wed, 29 Sep 2021 14:19:51 +0000 Subject: Translated using Weblate (Dutch) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/nl/ --- Emby.Server.Implementations/Localization/Core/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json index f79840c78..79f921bcb 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -15,7 +15,7 @@ "Favorites": "Favorieten", "Folders": "Mappen", "Genres": "Genres", - "HeaderAlbumArtists": "Albumartiesten", + "HeaderAlbumArtists": "Artiests Album", "HeaderContinueWatching": "Kijken hervatten", "HeaderFavoriteAlbums": "Favoriete albums", "HeaderFavoriteArtists": "Favoriete artiesten", -- cgit v1.2.3 From 1ee58bf0200986cbddcab8ce9fd4fa930bee84e1 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 1 Oct 2021 11:21:22 +0200 Subject: Enable nullable for ItemDataProvider --- .../LiveTv/EmbyTV/ItemDataProvider.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index 4a031e475..46979bfc5 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -1,9 +1,8 @@ -#nullable disable - #pragma warning disable CS1591 using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text.Json; @@ -18,7 +17,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private readonly string _dataPath; private readonly object _fileDataLock = new object(); private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; - private T[] _items; + private T[]? _items; public ItemDataProvider( ILogger logger, @@ -34,6 +33,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV protected Func EqualityComparer { get; } + [MemberNotNull(nameof(_items))] private void EnsureLoaded() { if (_items != null) @@ -49,6 +49,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { var bytes = File.ReadAllBytes(_dataPath); _items = JsonSerializer.Deserialize(bytes, _jsonOptions); + if (_items == null) + { + Logger.LogError("Error deserializing {Path}, data was null", _dataPath); + _items = Array.Empty(); + } + return; } catch (JsonException ex) @@ -62,7 +68,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private void SaveList() { - Directory.CreateDirectory(Path.GetDirectoryName(_dataPath)); + Directory.CreateDirectory(Path.GetDirectoryName(_dataPath) ?? throw new ArgumentException("Path can't be a root directory.", nameof(_dataPath))); var jsonString = JsonSerializer.Serialize(_items, _jsonOptions); File.WriteAllText(_dataPath, jsonString); } -- cgit v1.2.3 From 5043a887cc1a837fae76b7ebd7403750dfef6c7d Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 2 Oct 2021 11:54:31 -0400 Subject: Document IStartupOptions --- Emby.Server.Implementations/IStartupOptions.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/IStartupOptions.cs b/Emby.Server.Implementations/IStartupOptions.cs index 1d97882db..3769ae4dd 100644 --- a/Emby.Server.Implementations/IStartupOptions.cs +++ b/Emby.Server.Implementations/IStartupOptions.cs @@ -1,7 +1,8 @@ -#pragma warning disable CS1591 - namespace Emby.Server.Implementations { + /// + /// Specifies the contract for server startup options. + /// public interface IStartupOptions { /// @@ -10,7 +11,7 @@ namespace Emby.Server.Implementations string? FFmpegPath { get; } /// - /// Gets a value value indicating whether to run as service by the --service command line option. + /// Gets a value indicating whether to run as service by the --service command line option. /// bool IsService { get; } -- cgit v1.2.3 From 4ba9b6c30568c239ab9070734746c03765faac8f Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 2 Oct 2021 12:53:51 -0400 Subject: Fix warnings in ScheduledTasks --- .../ScheduledTasks/ScheduledTaskWorker.cs | 14 ++++----- .../ScheduledTasks/TaskManager.cs | 26 ++++++++--------- .../ScheduledTasks/Tasks/ChapterImagesTask.cs | 6 ++++ .../ScheduledTasks/Tasks/OptimizeDatabaseTask.cs | 3 ++ .../ScheduledTasks/Tasks/PeopleValidationTask.cs | 29 ++++++++++--------- .../Tasks/RefreshMediaLibraryTask.cs | 33 ++++++++-------------- 6 files changed, 56 insertions(+), 55 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index fb93c375d..f2cdfeb16 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -10,9 +10,9 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Events; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using Jellyfin.Extensions.Json; using MediaBrowser.Common.Progress; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; @@ -24,6 +24,11 @@ namespace Emby.Server.Implementations.ScheduledTasks /// public class ScheduledTaskWorker : IScheduledTaskWorker { + /// + /// The options for the json Serializer. + /// + private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; + /// /// Gets or sets the application paths. /// @@ -66,11 +71,6 @@ namespace Emby.Server.Implementations.ScheduledTasks /// private string _id; - /// - /// The options for the json Serializer. - /// - private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; - /// /// Initializes a new instance of the class. /// @@ -365,7 +365,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// /// Task options. /// Task. - /// Cannot execute a Task that is already running + /// Cannot execute a Task that is already running. public async Task Execute(TaskOptions options) { var task = Task.Run(async () => await ExecuteInternal(options).ConfigureAwait(false)); diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs index 4f0df75bf..0431858fc 100644 --- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs +++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs @@ -19,16 +19,6 @@ namespace Emby.Server.Implementations.ScheduledTasks /// public class TaskManager : ITaskManager { - public event EventHandler> TaskExecuting; - - public event EventHandler TaskCompleted; - - /// - /// Gets the list of Scheduled Tasks. - /// - /// The scheduled tasks. - public IScheduledTaskWorker[] ScheduledTasks { get; private set; } - /// /// The _task queue. /// @@ -53,10 +43,20 @@ namespace Emby.Server.Implementations.ScheduledTasks ScheduledTasks = Array.Empty(); } + public event EventHandler> TaskExecuting; + + public event EventHandler TaskCompleted; + + /// + /// Gets the list of Scheduled Tasks. + /// + /// The scheduled tasks. + public IScheduledTaskWorker[] ScheduledTasks { get; private set; } + /// /// Cancels if running and queue. /// - /// + /// The task type. /// Task options. public void CancelIfRunningAndQueue(TaskOptions options) where T : IScheduledTask @@ -76,7 +76,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// /// Cancels if running. /// - /// + /// The task type. public void CancelIfRunning() where T : IScheduledTask { @@ -87,7 +87,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// /// Queues the scheduled task. /// - /// + /// The task type. /// Task options. public void QueueScheduledTask(TaskOptions options) where T : IScheduledTask diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index b764a139c..09ea6271d 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -39,6 +39,12 @@ namespace Emby.Server.Implementations.ScheduledTasks /// /// Initializes a new instance of the class. /// + /// The library manager.. + /// The item repository. + /// The application paths. + /// The encoding manager. + /// The filesystem. + /// The localization manager. public ChapterImagesTask( ILibraryManager libraryManager, IItemRepository itemRepo, diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs index 1ad1d0f50..35a4aeef6 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/OptimizeDatabaseTask.cs @@ -22,6 +22,9 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks /// /// Initializes a new instance of the class. /// + /// The logger. + /// The localization manager. + /// The jellyfin DB context provider. public OptimizeDatabaseTask( ILogger logger, ILocalizationManager localization, diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs index 57d294a40..53c692a46 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs @@ -32,9 +32,24 @@ namespace Emby.Server.Implementations.ScheduledTasks _localization = localization; } + public string Name => _localization.GetLocalizedString("TaskRefreshPeople"); + + public string Description => _localization.GetLocalizedString("TaskRefreshPeopleDescription"); + + public string Category => _localization.GetLocalizedString("TasksLibraryCategory"); + + public string Key => "RefreshPeople"; + + public bool IsHidden => false; + + public bool IsEnabled => true; + + public bool IsLogged => true; + /// /// Creates the triggers that define when the task will run. /// + /// An containing the default trigger infos for this task. public IEnumerable GetDefaultTriggers() { return new[] @@ -57,19 +72,5 @@ namespace Emby.Server.Implementations.ScheduledTasks { return _libraryManager.ValidatePeople(cancellationToken, progress); } - - public string Name => _localization.GetLocalizedString("TaskRefreshPeople"); - - public string Description => _localization.GetLocalizedString("TaskRefreshPeopleDescription"); - - public string Category => _localization.GetLocalizedString("TasksLibraryCategory"); - - public string Key => "RefreshPeople"; - - public bool IsHidden => false; - - public bool IsEnabled => true; - - public bool IsLogged => true; } } diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs index 51b620404..2184b3d03 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs @@ -33,6 +33,18 @@ namespace Emby.Server.Implementations.ScheduledTasks _localization = localization; } + /// + public string Name => _localization.GetLocalizedString("TaskRefreshLibrary"); + + /// + public string Description => _localization.GetLocalizedString("TaskRefreshLibraryDescription"); + + /// + public string Category => _localization.GetLocalizedString("TasksLibraryCategory"); + + /// + public string Key => "RefreshLibrary"; + /// /// Creates the triggers that define when the task will run. /// @@ -60,26 +72,5 @@ namespace Emby.Server.Implementations.ScheduledTasks return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken); } - - /// - public string Name => _localization.GetLocalizedString("TaskRefreshLibrary"); - - /// - public string Description => _localization.GetLocalizedString("TaskRefreshLibraryDescription"); - - /// - public string Category => _localization.GetLocalizedString("TasksLibraryCategory"); - - /// - public string Key => "RefreshLibrary"; - - /// - public bool IsHidden => false; - - /// - public bool IsEnabled => true; - - /// - public bool IsLogged => true; } } -- cgit v1.2.3 From 21007aec2038b88734ae19287081bcb1b04f6300 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 2 Oct 2021 13:03:04 -0400 Subject: Fix warnings in Data --- .../Data/BaseSqliteRepository.cs | 51 --- .../Data/ManagedConnection.cs | 4 +- .../Data/SqliteItemRepository.cs | 481 +++++++++++---------- .../Data/SqliteUserDataRepository.cs | 7 +- .../Data/SynchronouseMode.cs | 30 ++ Emby.Server.Implementations/Data/TempStoreMode.cs | 23 + 6 files changed, 302 insertions(+), 294 deletions(-) create mode 100644 Emby.Server.Implementations/Data/SynchronouseMode.cs create mode 100644 Emby.Server.Implementations/Data/TempStoreMode.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 01c9fbca8..4f6c81102 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -249,55 +249,4 @@ namespace Emby.Server.Implementations.Data _disposed = true; } } - - /// - /// The disk synchronization mode, controls how aggressively SQLite will write data - /// all the way out to physical storage. - /// - public enum SynchronousMode - { - /// - /// SQLite continues without syncing as soon as it has handed data off to the operating system. - /// - Off = 0, - - /// - /// SQLite database engine will still sync at the most critical moments. - /// - Normal = 1, - - /// - /// SQLite database engine will use the xSync method of the VFS - /// to ensure that all content is safely written to the disk surface prior to continuing. - /// - Full = 2, - - /// - /// EXTRA synchronous is like FULL with the addition that the directory containing a rollback journal - /// is synced after that journal is unlinked to commit a transaction in DELETE mode. - /// - Extra = 3 - } - - /// - /// Storage mode used by temporary database files. - /// - public enum TempStoreMode - { - /// - /// The compile-time C preprocessor macro SQLITE_TEMP_STORE - /// is used to determine where temporary tables and indices are stored. - /// - Default = 0, - - /// - /// Temporary tables and indices are stored in a file. - /// - File = 1, - - /// - /// Temporary tables and indices are kept in as if they were pure in-memory databases memory. - /// - Memory = 2 - } } diff --git a/Emby.Server.Implementations/Data/ManagedConnection.cs b/Emby.Server.Implementations/Data/ManagedConnection.cs index afc8966f9..44dad5b17 100644 --- a/Emby.Server.Implementations/Data/ManagedConnection.cs +++ b/Emby.Server.Implementations/Data/ManagedConnection.cs @@ -9,8 +9,10 @@ namespace Emby.Server.Implementations.Data { public class ManagedConnection : IDisposable { - private SQLiteDatabaseConnection? _db; private readonly SemaphoreSlim _writeLock; + + private SQLiteDatabaseConnection? _db; + private bool _disposed = false; public ManagedConnection(SQLiteDatabaseConnection db, SemaphoreSlim writeLock) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 0a48b844d..13f1df7c8 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -46,6 +46,11 @@ namespace Emby.Server.Implementations.Data private const string FromText = " from TypedBaseItems A"; private const string ChaptersTableName = "Chapters2"; + private const string SaveItemCommandText = + @"replace into TypedBaseItems + (guid,type,data,Path,StartDate,EndDate,ChannelId,IsMovie,IsSeries,EpisodeTitle,IsRepeat,CommunityRating,CustomRating,IndexNumber,IsLocked,Name,OfficialRating,MediaType,Overview,ParentIndexNumber,PremiereDate,ProductionYear,ParentId,Genres,InheritedParentalRatingValue,SortName,ForcedSortName,RunTimeTicks,Size,DateCreated,DateModified,PreferredMetadataLanguage,PreferredMetadataCountryCode,Width,Height,DateLastRefreshed,DateLastSaved,IsInMixedFolder,LockedFields,Studios,Audio,ExternalServiceId,Tags,IsFolder,UnratedType,TopParentId,TrailerTypes,CriticRating,CleanName,PresentationUniqueKey,OriginalTitle,PrimaryVersionId,DateLastMediaAdded,Album,IsVirtualItem,SeriesName,UserDataKey,SeasonName,SeasonId,SeriesId,ExternalSeriesId,Tagline,ProviderIds,Images,ProductionLocations,ExtraIds,TotalBitrate,ExtraType,Artists,AlbumArtists,ExternalId,SeriesPresentationUniqueKey,ShowId,OwnerId) + values (@guid,@type,@data,@Path,@StartDate,@EndDate,@ChannelId,@IsMovie,@IsSeries,@EpisodeTitle,@IsRepeat,@CommunityRating,@CustomRating,@IndexNumber,@IsLocked,@Name,@OfficialRating,@MediaType,@Overview,@ParentIndexNumber,@PremiereDate,@ProductionYear,@ParentId,@Genres,@InheritedParentalRatingValue,@SortName,@ForcedSortName,@RunTimeTicks,@Size,@DateCreated,@DateModified,@PreferredMetadataLanguage,@PreferredMetadataCountryCode,@Width,@Height,@DateLastRefreshed,@DateLastSaved,@IsInMixedFolder,@LockedFields,@Studios,@Audio,@ExternalServiceId,@Tags,@IsFolder,@UnratedType,@TopParentId,@TrailerTypes,@CriticRating,@CleanName,@PresentationUniqueKey,@OriginalTitle,@PrimaryVersionId,@DateLastMediaAdded,@Album,@IsVirtualItem,@SeriesName,@UserDataKey,@SeasonName,@SeasonId,@SeriesId,@ExternalSeriesId,@Tagline,@ProviderIds,@Images,@ProductionLocations,@ExtraIds,@TotalBitrate,@ExtraType,@Artists,@AlbumArtists,@ExternalId,@SeriesPresentationUniqueKey,@ShowId,@OwnerId)"; + private readonly IServerConfigurationManager _config; private readonly IServerApplicationHost _appHost; private readonly ILocalizationManager _localization; @@ -55,6 +60,231 @@ namespace Emby.Server.Implementations.Data private readonly TypeMapper _typeMapper; private readonly JsonSerializerOptions _jsonOptions; + private readonly ItemFields[] _allItemFields = Enum.GetValues(); + + private static readonly string[] _retriveItemColumns = + { + "type", + "data", + "StartDate", + "EndDate", + "ChannelId", + "IsMovie", + "IsSeries", + "EpisodeTitle", + "IsRepeat", + "CommunityRating", + "CustomRating", + "IndexNumber", + "IsLocked", + "PreferredMetadataLanguage", + "PreferredMetadataCountryCode", + "Width", + "Height", + "DateLastRefreshed", + "Name", + "Path", + "PremiereDate", + "Overview", + "ParentIndexNumber", + "ProductionYear", + "OfficialRating", + "ForcedSortName", + "RunTimeTicks", + "Size", + "DateCreated", + "DateModified", + "guid", + "Genres", + "ParentId", + "Audio", + "ExternalServiceId", + "IsInMixedFolder", + "DateLastSaved", + "LockedFields", + "Studios", + "Tags", + "TrailerTypes", + "OriginalTitle", + "PrimaryVersionId", + "DateLastMediaAdded", + "Album", + "CriticRating", + "IsVirtualItem", + "SeriesName", + "SeasonName", + "SeasonId", + "SeriesId", + "PresentationUniqueKey", + "InheritedParentalRatingValue", + "ExternalSeriesId", + "Tagline", + "ProviderIds", + "Images", + "ProductionLocations", + "ExtraIds", + "TotalBitrate", + "ExtraType", + "Artists", + "AlbumArtists", + "ExternalId", + "SeriesPresentationUniqueKey", + "ShowId", + "OwnerId" + }; + + private static readonly string _retriveItemColumnsSelectQuery = $"select {string.Join(',', _retriveItemColumns)} from TypedBaseItems where guid = @guid"; + + private static readonly string[] _mediaStreamSaveColumns = + { + "ItemId", + "StreamIndex", + "StreamType", + "Codec", + "Language", + "ChannelLayout", + "Profile", + "AspectRatio", + "Path", + "IsInterlaced", + "BitRate", + "Channels", + "SampleRate", + "IsDefault", + "IsForced", + "IsExternal", + "Height", + "Width", + "AverageFrameRate", + "RealFrameRate", + "Level", + "PixelFormat", + "BitDepth", + "IsAnamorphic", + "RefFrames", + "CodecTag", + "Comment", + "NalLengthSize", + "IsAvc", + "Title", + "TimeBase", + "CodecTimeBase", + "ColorPrimaries", + "ColorSpace", + "ColorTransfer" + }; + + private static readonly string _mediaStreamSaveColumnsInsertQuery = + $"insert into mediastreams ({string.Join(',', _mediaStreamSaveColumns)}) values "; + + private static readonly string _mediaStreamSaveColumnsSelectQuery = + $"select {string.Join(',', _mediaStreamSaveColumns)} from mediastreams where ItemId=@ItemId"; + + private static readonly string[] _mediaAttachmentSaveColumns = + { + "ItemId", + "AttachmentIndex", + "Codec", + "CodecTag", + "Comment", + "Filename", + "MIMEType" + }; + + private static readonly string _mediaAttachmentSaveColumnsSelectQuery = + $"select {string.Join(',', _mediaAttachmentSaveColumns)} from mediaattachments where ItemId=@ItemId"; + + private static readonly string _mediaAttachmentInsertPrefix; + + private static readonly HashSet _programTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Program", + "TvChannel", + "LiveTvProgram", + "LiveTvTvChannel" + }; + + private static readonly HashSet _programExcludeParentTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Series", + "Season", + "MusicAlbum", + "MusicArtist", + "PhotoAlbum" + }; + + private static readonly HashSet _serviceTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "TvChannel", + "LiveTvTvChannel" + }; + + private static readonly HashSet _startDateTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Program", + "LiveTvProgram" + }; + + private static readonly HashSet _seriesTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Book", + "AudioBook", + "Episode", + "Season" + }; + + private static readonly HashSet _artistExcludeParentTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Series", + "Season", + "PhotoAlbum" + }; + + private static readonly HashSet _artistsTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Audio", + "MusicAlbum", + "MusicVideo", + "AudioBook", + "AudioPodcast" + }; + + private static readonly Type[] _knownTypes = + { + typeof(LiveTvProgram), + typeof(LiveTvChannel), + typeof(Series), + typeof(Audio), + typeof(MusicAlbum), + typeof(MusicArtist), + typeof(MusicGenre), + typeof(MusicVideo), + typeof(Movie), + typeof(Playlist), + typeof(AudioBook), + typeof(Trailer), + typeof(BoxSet), + typeof(Episode), + typeof(Season), + typeof(Series), + typeof(Book), + typeof(CollectionFolder), + typeof(Folder), + typeof(Genre), + typeof(Person), + typeof(Photo), + typeof(PhotoAlbum), + typeof(Studio), + typeof(UserRootFolder), + typeof(UserView), + typeof(Video), + typeof(Year), + typeof(Channel), + typeof(AggregateFolder) + }; + + private readonly Dictionary _types = GetTypeMapDictionary(); + static SqliteItemRepository() { var queryPrefixText = new StringBuilder(); @@ -115,6 +345,8 @@ namespace Emby.Server.Implementations.Data /// /// Opens the connection to the database. /// + /// The user data repository. + /// The user manager. public void Initialize(SqliteUserDataRepository userDataRepo, IUserManager userManager) { const string CreateMediaStreamsTableCommand @@ -154,7 +386,7 @@ namespace Emby.Server.Implementations.Data "drop index if exists idx_TypedBaseItems", "drop index if exists idx_mediastreams", "drop index if exists idx_mediastreams1", - "drop index if exists idx_"+ChaptersTableName, + "drop index if exists idx_" + ChaptersTableName, "drop index if exists idx_UserDataKeys1", "drop index if exists idx_UserDataKeys2", "drop index if exists idx_TypeTopParentId3", @@ -340,151 +572,12 @@ namespace Emby.Server.Implementations.Data userDataRepo.Initialize(userManager, WriteLock, WriteConnection); } - private static readonly string[] _retriveItemColumns = - { - "type", - "data", - "StartDate", - "EndDate", - "ChannelId", - "IsMovie", - "IsSeries", - "EpisodeTitle", - "IsRepeat", - "CommunityRating", - "CustomRating", - "IndexNumber", - "IsLocked", - "PreferredMetadataLanguage", - "PreferredMetadataCountryCode", - "Width", - "Height", - "DateLastRefreshed", - "Name", - "Path", - "PremiereDate", - "Overview", - "ParentIndexNumber", - "ProductionYear", - "OfficialRating", - "ForcedSortName", - "RunTimeTicks", - "Size", - "DateCreated", - "DateModified", - "guid", - "Genres", - "ParentId", - "Audio", - "ExternalServiceId", - "IsInMixedFolder", - "DateLastSaved", - "LockedFields", - "Studios", - "Tags", - "TrailerTypes", - "OriginalTitle", - "PrimaryVersionId", - "DateLastMediaAdded", - "Album", - "CriticRating", - "IsVirtualItem", - "SeriesName", - "SeasonName", - "SeasonId", - "SeriesId", - "PresentationUniqueKey", - "InheritedParentalRatingValue", - "ExternalSeriesId", - "Tagline", - "ProviderIds", - "Images", - "ProductionLocations", - "ExtraIds", - "TotalBitrate", - "ExtraType", - "Artists", - "AlbumArtists", - "ExternalId", - "SeriesPresentationUniqueKey", - "ShowId", - "OwnerId" - }; - - private static readonly string _retriveItemColumnsSelectQuery = $"select {string.Join(',', _retriveItemColumns)} from TypedBaseItems where guid = @guid"; - - private static readonly string[] _mediaStreamSaveColumns = - { - "ItemId", - "StreamIndex", - "StreamType", - "Codec", - "Language", - "ChannelLayout", - "Profile", - "AspectRatio", - "Path", - "IsInterlaced", - "BitRate", - "Channels", - "SampleRate", - "IsDefault", - "IsForced", - "IsExternal", - "Height", - "Width", - "AverageFrameRate", - "RealFrameRate", - "Level", - "PixelFormat", - "BitDepth", - "IsAnamorphic", - "RefFrames", - "CodecTag", - "Comment", - "NalLengthSize", - "IsAvc", - "Title", - "TimeBase", - "CodecTimeBase", - "ColorPrimaries", - "ColorSpace", - "ColorTransfer" - }; - - private static readonly string _mediaStreamSaveColumnsInsertQuery = - $"insert into mediastreams ({string.Join(',', _mediaStreamSaveColumns)}) values "; - - private static readonly string _mediaStreamSaveColumnsSelectQuery = - $"select {string.Join(',', _mediaStreamSaveColumns)} from mediastreams where ItemId=@ItemId"; - - private static readonly string[] _mediaAttachmentSaveColumns = - { - "ItemId", - "AttachmentIndex", - "Codec", - "CodecTag", - "Comment", - "Filename", - "MIMEType" - }; - - private static readonly string _mediaAttachmentSaveColumnsSelectQuery = - $"select {string.Join(',', _mediaAttachmentSaveColumns)} from mediaattachments where ItemId=@ItemId"; - - private static readonly string _mediaAttachmentInsertPrefix; - - private const string SaveItemCommandText = - @"replace into TypedBaseItems - (guid,type,data,Path,StartDate,EndDate,ChannelId,IsMovie,IsSeries,EpisodeTitle,IsRepeat,CommunityRating,CustomRating,IndexNumber,IsLocked,Name,OfficialRating,MediaType,Overview,ParentIndexNumber,PremiereDate,ProductionYear,ParentId,Genres,InheritedParentalRatingValue,SortName,ForcedSortName,RunTimeTicks,Size,DateCreated,DateModified,PreferredMetadataLanguage,PreferredMetadataCountryCode,Width,Height,DateLastRefreshed,DateLastSaved,IsInMixedFolder,LockedFields,Studios,Audio,ExternalServiceId,Tags,IsFolder,UnratedType,TopParentId,TrailerTypes,CriticRating,CleanName,PresentationUniqueKey,OriginalTitle,PrimaryVersionId,DateLastMediaAdded,Album,IsVirtualItem,SeriesName,UserDataKey,SeasonName,SeasonId,SeriesId,ExternalSeriesId,Tagline,ProviderIds,Images,ProductionLocations,ExtraIds,TotalBitrate,ExtraType,Artists,AlbumArtists,ExternalId,SeriesPresentationUniqueKey,ShowId,OwnerId) - values (@guid,@type,@data,@Path,@StartDate,@EndDate,@ChannelId,@IsMovie,@IsSeries,@EpisodeTitle,@IsRepeat,@CommunityRating,@CustomRating,@IndexNumber,@IsLocked,@Name,@OfficialRating,@MediaType,@Overview,@ParentIndexNumber,@PremiereDate,@ProductionYear,@ParentId,@Genres,@InheritedParentalRatingValue,@SortName,@ForcedSortName,@RunTimeTicks,@Size,@DateCreated,@DateModified,@PreferredMetadataLanguage,@PreferredMetadataCountryCode,@Width,@Height,@DateLastRefreshed,@DateLastSaved,@IsInMixedFolder,@LockedFields,@Studios,@Audio,@ExternalServiceId,@Tags,@IsFolder,@UnratedType,@TopParentId,@TrailerTypes,@CriticRating,@CleanName,@PresentationUniqueKey,@OriginalTitle,@PrimaryVersionId,@DateLastMediaAdded,@Album,@IsVirtualItem,@SeriesName,@UserDataKey,@SeasonName,@SeasonId,@SeriesId,@ExternalSeriesId,@Tagline,@ProviderIds,@Images,@ProductionLocations,@ExtraIds,@TotalBitrate,@ExtraType,@Artists,@AlbumArtists,@ExternalId,@SeriesPresentationUniqueKey,@ShowId,@OwnerId)"; - /// /// Save a standard item in the repo. /// /// The item. /// The cancellation token. - /// item + /// is null. public void SaveItem(BaseItem item, CancellationToken cancellationToken) { if (item == null) @@ -509,7 +602,7 @@ namespace Emby.Server.Implementations.Data connection.RunInTransaction( db => { - using (var saveImagesStatement = base.PrepareStatement(db, "Update TypedBaseItems set Images=@Images where guid=@Id")) + using (var saveImagesStatement = PrepareStatement(db, "Update TypedBaseItems set Images=@Images where guid=@Id")) { saveImagesStatement.TryBind("@Id", item.Id.ToByteArray()); saveImagesStatement.TryBind("@Images", SerializeImages(item.ImageInfos)); @@ -526,9 +619,7 @@ namespace Emby.Server.Implementations.Data /// The items. /// The cancellation token. /// - /// items - /// or - /// cancellationToken + /// or is null. /// public void SaveItems(IEnumerable items, CancellationToken cancellationToken) { @@ -1216,8 +1307,8 @@ namespace Emby.Server.Implementations.Data /// /// The id. /// BaseItem. - /// id - /// + /// is null. + /// is . public BaseItem RetrieveItem(Guid id) { if (id == Guid.Empty) @@ -1986,6 +2077,8 @@ namespace Emby.Server.Implementations.Data /// /// Saves the chapters. /// + /// The item id. + /// The chapters. public void SaveChapters(Guid id, IReadOnlyList chapters) { CheckDisposed(); @@ -2085,8 +2178,6 @@ namespace Emby.Server.Implementations.Data || query.IsLiked.HasValue; } - private readonly ItemFields[] _allFields = Enum.GetValues(); - private bool HasField(InternalItemsQuery query, ItemFields name) { switch (name) @@ -2119,23 +2210,6 @@ namespace Emby.Server.Implementations.Data } } - private static readonly HashSet _programExcludeParentTypes = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "Series", - "Season", - "MusicAlbum", - "MusicArtist", - "PhotoAlbum" - }; - - private static readonly HashSet _programTypes = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "Program", - "TvChannel", - "LiveTvProgram", - "LiveTvTvChannel" - }; - private bool HasProgramAttributes(InternalItemsQuery query) { if (_programExcludeParentTypes.Contains(query.ParentType)) @@ -2151,12 +2225,6 @@ namespace Emby.Server.Implementations.Data return query.IncludeItemTypes.Any(x => _programTypes.Contains(x)); } - private static readonly HashSet _serviceTypes = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "TvChannel", - "LiveTvTvChannel" - }; - private bool HasServiceName(InternalItemsQuery query) { if (_programExcludeParentTypes.Contains(query.ParentType)) @@ -2172,12 +2240,6 @@ namespace Emby.Server.Implementations.Data return query.IncludeItemTypes.Any(x => _serviceTypes.Contains(x)); } - private static readonly HashSet _startDateTypes = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "Program", - "LiveTvProgram" - }; - private bool HasStartDate(InternalItemsQuery query) { if (_programExcludeParentTypes.Contains(query.ParentType)) @@ -2213,22 +2275,6 @@ namespace Emby.Server.Implementations.Data return query.IncludeItemTypes.Contains("Trailer", StringComparer.OrdinalIgnoreCase); } - private static readonly HashSet _artistExcludeParentTypes = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "Series", - "Season", - "PhotoAlbum" - }; - - private static readonly HashSet _artistsTypes = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "Audio", - "MusicAlbum", - "MusicVideo", - "AudioBook", - "AudioPodcast" - }; - private bool HasArtistFields(InternalItemsQuery query) { if (_artistExcludeParentTypes.Contains(query.ParentType)) @@ -2244,14 +2290,6 @@ namespace Emby.Server.Implementations.Data return query.IncludeItemTypes.Any(x => _artistsTypes.Contains(x)); } - private static readonly HashSet _seriesTypes = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "Book", - "AudioBook", - "Episode", - "Season" - }; - private bool HasSeriesFields(InternalItemsQuery query) { if (string.Equals(query.ParentType, "PhotoAlbum", StringComparison.OrdinalIgnoreCase)) @@ -2269,7 +2307,7 @@ namespace Emby.Server.Implementations.Data private void SetFinalColumnsToSelect(InternalItemsQuery query, List columns) { - foreach (var field in _allFields) + foreach (var field in _allItemFields) { if (!HasField(query, field)) { @@ -4811,40 +4849,6 @@ namespace Emby.Server.Implementations.Data return false; } - private static readonly Type[] _knownTypes = - { - typeof(LiveTvProgram), - typeof(LiveTvChannel), - typeof(Series), - typeof(Audio), - typeof(MusicAlbum), - typeof(MusicArtist), - typeof(MusicGenre), - typeof(MusicVideo), - typeof(Movie), - typeof(Playlist), - typeof(AudioBook), - typeof(Trailer), - typeof(BoxSet), - typeof(Episode), - typeof(Season), - typeof(Series), - typeof(Book), - typeof(CollectionFolder), - typeof(Folder), - typeof(Genre), - typeof(Person), - typeof(Photo), - typeof(PhotoAlbum), - typeof(Studio), - typeof(UserRootFolder), - typeof(UserView), - typeof(Video), - typeof(Year), - typeof(Channel), - typeof(AggregateFolder) - }; - public void UpdateInheritedValues() { string sql = string.Join( @@ -4886,9 +4890,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type return dict; } - // Not crazy about having this all the way down here, but at least it's in one place - private readonly Dictionary _types = GetTypeMapDictionary(); - private string MapIncludeItemTypes(string value) { if (_types.TryGetValue(value, out string result)) diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index 829f1de2f..107096b5f 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -32,6 +32,9 @@ namespace Emby.Server.Implementations.Data /// /// Opens the connection to the database. /// + /// The user manager. + /// The lock to use for database IO. + /// The connection to use for database IO. public void Initialize(IUserManager userManager, SemaphoreSlim dbLock, SQLiteDatabaseConnection dbConnection) { WriteLock.Dispose(); @@ -49,8 +52,8 @@ namespace Emby.Server.Implementations.Data connection.RunInTransaction( db => { - db.ExecuteAll(string.Join(';', new[] { - + db.ExecuteAll(string.Join(';', new[] + { "create table if not exists UserDatas (key nvarchar not null, userId INT not null, rating float null, played bit not null, playCount int not null, isFavorite bit not null, playbackPositionTicks bigint not null, lastPlayedDate datetime null, AudioStreamIndex INT, SubtitleStreamIndex INT)", "drop index if exists idx_userdata", diff --git a/Emby.Server.Implementations/Data/SynchronouseMode.cs b/Emby.Server.Implementations/Data/SynchronouseMode.cs new file mode 100644 index 000000000..cde524e2e --- /dev/null +++ b/Emby.Server.Implementations/Data/SynchronouseMode.cs @@ -0,0 +1,30 @@ +namespace Emby.Server.Implementations.Data; + +/// +/// The disk synchronization mode, controls how aggressively SQLite will write data +/// all the way out to physical storage. +/// +public enum SynchronousMode +{ + /// + /// SQLite continues without syncing as soon as it has handed data off to the operating system. + /// + Off = 0, + + /// + /// SQLite database engine will still sync at the most critical moments. + /// + Normal = 1, + + /// + /// SQLite database engine will use the xSync method of the VFS + /// to ensure that all content is safely written to the disk surface prior to continuing. + /// + Full = 2, + + /// + /// EXTRA synchronous is like FULL with the addition that the directory containing a rollback journal + /// is synced after that journal is unlinked to commit a transaction in DELETE mode. + /// + Extra = 3 +} diff --git a/Emby.Server.Implementations/Data/TempStoreMode.cs b/Emby.Server.Implementations/Data/TempStoreMode.cs new file mode 100644 index 000000000..d2427ce47 --- /dev/null +++ b/Emby.Server.Implementations/Data/TempStoreMode.cs @@ -0,0 +1,23 @@ +namespace Emby.Server.Implementations.Data; + +/// +/// Storage mode used by temporary database files. +/// +public enum TempStoreMode +{ + /// + /// The compile-time C preprocessor macro SQLITE_TEMP_STORE + /// is used to determine where temporary tables and indices are stored. + /// + Default = 0, + + /// + /// Temporary tables and indices are stored in a file. + /// + File = 1, + + /// + /// Temporary tables and indices are kept in as if they were pure in-memory databases memory. + /// + Memory = 2 +} -- cgit v1.2.3 From 9af16fcb6c892238b734c267873b1fc137d38e66 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 3 Oct 2021 19:52:38 +0200 Subject: Remove workaround for dotnet/runtime#42790 --- Emby.Dlna/DlnaManager.cs | 9 ++++--- Emby.Drawing/ImageProcessor.cs | 2 +- .../AppBase/ConfigurationHelper.cs | 9 +++---- .../LiveTv/EmbyTV/DirectRecorder.cs | 6 ++--- .../LiveTv/EmbyTV/EmbyTV.cs | 12 +++------ .../LiveTv/EmbyTV/EncodedRecorder.cs | 2 +- Jellyfin.Api/Controllers/RemoteImageController.cs | 31 ---------------------- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 12 +++++++-- .../Subtitles/SubtitleEncoder.cs | 1 - MediaBrowser.Model/IO/AsyncFile.cs | 19 +++++++++++++ MediaBrowser.Providers/Manager/ImageSaver.cs | 6 +++-- .../Manager/ItemImageProvider.cs | 2 +- MediaBrowser.Providers/Manager/ProviderManager.cs | 3 +-- .../Plugins/AudioDb/AudioDbAlbumProvider.cs | 7 +++-- .../Plugins/AudioDb/AudioDbArtistProvider.cs | 6 +++-- .../Studios/StudiosImageProvider.cs | 7 ++--- .../Subtitles/SubtitleManager.cs | 6 +++-- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 11 ++++++-- 18 files changed, 77 insertions(+), 74 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 8fe9d484e..73e8a0008 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -359,14 +359,17 @@ namespace Emby.Dlna // The stream should exist as we just got its name from GetManifestResourceNames using (var stream = _assembly.GetManifestResourceStream(name)!) { + var length = stream.Length; var fileInfo = _fileSystem.GetFileInfo(path); - if (!fileInfo.Exists || fileInfo.Length != stream.Length) + if (!fileInfo.Exists || fileInfo.Length != length) { Directory.CreateDirectory(systemProfilesPath); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) + var fileOptions = AsyncFile.WriteOptions; + fileOptions.Mode = FileMode.CreateNew; + fileOptions.PreallocationSize = length; + using (var fileStream = new FileStream(path, fileOptions)) { await stream.CopyToAsync(fileStream).ConfigureAwait(false); } diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 9b130fdfd..ac73cfa42 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -102,7 +102,7 @@ namespace Emby.Drawing { var file = await ProcessImage(options).ConfigureAwait(false); - using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) + using (var fileStream = AsyncFile.OpenRead(file.Item1)) { await fileStream.CopyToAsync(toStream).ConfigureAwait(false); } diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index 0308a68e4..3a916e5c0 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -41,20 +41,19 @@ namespace Emby.Server.Implementations.AppBase xmlSerializer.SerializeToStream(configuration, stream); // Take the object we just got and serialize it back to bytes - byte[] newBytes = stream.GetBuffer(); - int newBytesLen = (int)stream.Length; + Span newBytes = stream.GetBuffer().AsSpan(0, (int)stream.Length); // If the file didn't exist before, or if something has changed, re-save - if (buffer == null || !newBytes.AsSpan(0, newBytesLen).SequenceEqual(buffer)) + if (buffer == null || !newBytes.SequenceEqual(buffer)) { var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path)); Directory.CreateDirectory(directory); + // Save it after load in case we got new items - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) { - fs.Write(newBytes, 0, newBytesLen); + fs.Write(newBytes); } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 41381d55b..6937cc097 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -46,8 +46,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile))); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) + using (var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) { onStarted(); @@ -79,8 +78,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile))); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous); + await using var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.CopyToBufferSize, FileOptions.Asynchronous); onStarted(); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 64e54aa99..980b42729 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1848,14 +1848,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None)) + using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { var settings = new XmlWriterSettings { Indent = true, - Encoding = Encoding.UTF8, - CloseOutput = false + Encoding = Encoding.UTF8 }; using (var writer = XmlWriter.Create(stream, settings)) @@ -1913,14 +1911,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return; } - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var stream = new FileStream(nfoPath, FileMode.Create, FileAccess.Write, FileShare.None)) + using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { var settings = new XmlWriterSettings { Indent = true, - Encoding = Encoding.UTF8, - CloseOutput = false + Encoding = Encoding.UTF8 }; var options = _config.GetNfoConfiguration(); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 3633fa3e1..016a3e83f 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - _logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); + _logFileStream = new FileStream(logFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false); await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 8a33b12f4..35921ede8 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -183,36 +183,5 @@ namespace Jellyfin.Api.Controllers { return Path.Combine(_applicationPaths.CachePath, "remote-images", filename.Substring(0, 1), filename); } - - /// - /// Downloads the image. - /// - /// The URL. - /// The URL hash. - /// The pointer cache path. - /// Task. - private async Task DownloadImage(Uri url, Guid urlHash, string pointerCachePath) - { - var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); - using var response = await httpClient.GetAsync(url).ConfigureAwait(false); - if (response.Content.Headers.ContentType?.MediaType == null) - { - throw new ResourceNotFoundException(nameof(response.Content.Headers.ContentType)); - } - - var ext = response.Content.Headers.ContentType.MediaType.AsSpan().RightPart('/').ToString(); - var fullCachePath = GetFullCachePath(urlHash + "." + ext); - - var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid."); - Directory.CreateDirectory(fullCacheDirectory); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); - await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); - - var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ArgumentException($"Provided path ({pointerCachePath}) is not valid.", nameof(pointerCachePath)); - Directory.CreateDirectory(pointerCacheDirectory); - await System.IO.File.WriteAllTextAsync(pointerCachePath, fullCachePath, CancellationToken.None) - .ConfigureAwait(false); - } } } diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 6f66fd61b..5e7af23fc 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -113,11 +113,19 @@ namespace MediaBrowser.LocalMetadata.Savers { var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path)); Directory.CreateDirectory(directory); + // On Windows, savint the file will fail if the file is hidden or readonly FileSystem.SetAttributes(path, false, false); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) + var fileStreamOptions = new FileStreamOptions() + { + Mode = FileMode.Create, + Access = FileAccess.Write, + Share = FileShare.None, + PreallocationSize = stream.Length + }; + + using (var filestream = new FileStream(path, fileStreamOptions)) { stream.CopyTo(filestream); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 022cdbe9d..bfc17904c 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -679,7 +679,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (!string.Equals(text, newText, StringComparison.Ordinal)) { - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) using (var writer = new StreamWriter(fileStream, encoding)) { diff --git a/MediaBrowser.Model/IO/AsyncFile.cs b/MediaBrowser.Model/IO/AsyncFile.cs index caee9c528..3c8007d1c 100644 --- a/MediaBrowser.Model/IO/AsyncFile.cs +++ b/MediaBrowser.Model/IO/AsyncFile.cs @@ -7,6 +7,25 @@ namespace MediaBrowser.Model.IO /// public static class AsyncFile { + /// + /// Gets the default for reading files async. + /// + public static FileStreamOptions ReadOptions => new FileStreamOptions() + { + Options = FileOptions.Asynchronous + }; + + /// + /// Gets the default for writing files async. + /// + public static FileStreamOptions WriteOptions => new FileStreamOptions() + { + Mode = FileMode.OpenOrCreate, + Access = FileAccess.Write, + Share = FileShare.None, + Options = FileOptions.Asynchronous + }; + /// /// Opens an existing file for reading. /// diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 4b05edd67..3d8dd1486 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -261,8 +261,10 @@ namespace MediaBrowser.Providers.Manager _fileSystem.SetAttributes(path, false, false); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous)) + var fileStreamOptions = AsyncFile.WriteOptions; + fileStreamOptions.Mode = FileMode.Create; + fileStreamOptions.PreallocationSize = source.Length; + await using (var fs = new FileStream(path, fileStreamOptions)) { await source.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 73bca5aa5..3593697d7 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.Manager { var mimeType = MimeTypes.GetMimeType(response.Path); - var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); + var stream = AsyncFile.OpenRead(response.Path); await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index b51a25417..9be887e9c 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -210,8 +210,7 @@ namespace MediaBrowser.Providers.Manager throw new ArgumentNullException(nameof(source)); } - var fileStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - + var fileStream = AsyncFile.OpenRead(source); return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs index 3e0b0014e..ebdcb94eb 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumProvider.cs @@ -172,8 +172,11 @@ namespace MediaBrowser.Providers.Plugins.AudioDb using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); + + var fileStreamOptions = AsyncFile.WriteOptions; + fileStreamOptions.Mode = FileMode.Create; + fileStreamOptions.PreallocationSize = stream.Length; + await using var xmlFileStream = new FileStream(path, fileStreamOptions); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs index e0b2f9c58..321013b17 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistProvider.cs @@ -154,8 +154,10 @@ namespace MediaBrowser.Providers.Plugins.AudioDb Directory.CreateDirectory(Path.GetDirectoryName(path)); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); + var fileStreamOptions = AsyncFile.WriteOptions; + fileStreamOptions.Mode = FileMode.Create; + fileStreamOptions.PreallocationSize = stream.Length; + await using var xmlFileStream = new FileStream(path, fileStreamOptions); await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index 7b2454efc..a1873eaae 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -172,19 +172,16 @@ namespace MediaBrowser.Providers.Studios public IEnumerable GetAvailableImages(string file) { - using var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read); + using var fileStream = File.OpenRead(file); using var reader = new StreamReader(fileStream); - var lines = new List(); foreach (var line in reader.ReadAllLines()) { if (!string.IsNullOrWhiteSpace(line)) { - lines.Add(line); + yield return line; } } - - return lines; } } } diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index 772e617ab..e625b0dd2 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -244,8 +244,10 @@ namespace MediaBrowser.Providers.Subtitles { Directory.CreateDirectory(Path.GetDirectoryName(savePath)); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, FileOptions.Asynchronous); + var fileOptions = AsyncFile.WriteOptions; + fileOptions.Mode = FileMode.CreateNew; + fileOptions.PreallocationSize = stream.Length; + using var fs = new FileStream(savePath, fileOptions); await stream.CopyToAsync(fs).ConfigureAwait(false); return; diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 38726a6f0..594402258 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -203,8 +203,15 @@ namespace MediaBrowser.XbmcMetadata.Savers // On Windows, saving the file will fail if the file is hidden or readonly FileSystem.SetAttributes(path, false, false); - // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 . - using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None)) + var fileStreamOptions = new FileStreamOptions() + { + Mode = FileMode.Create, + Access = FileAccess.Write, + Share = FileShare.None, + PreallocationSize = stream.Length + }; + + using (var filestream = new FileStream(path, fileStreamOptions)) { stream.CopyTo(filestream); } -- cgit v1.2.3 From 078200d8d4ba6d986cce8881b17d30b82e58b038 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 2 Oct 2021 13:23:05 -0400 Subject: Fix warnings in Sorting --- .../Sorting/AiredEpisodeOrderComparer.cs | 12 ++++---- .../Sorting/AlbumArtistComparer.cs | 12 ++++---- .../Sorting/AlbumComparer.cs | 12 ++++---- .../Sorting/CriticRatingComparer.cs | 12 ++++---- .../Sorting/DateCreatedComparer.cs | 12 ++++---- .../Sorting/DatePlayedComparer.cs | 12 ++++---- .../Sorting/NameComparer.cs | 12 ++++---- .../Sorting/PlayCountComparer.cs | 36 +++++++++++----------- .../Sorting/PremiereDateComparer.cs | 12 ++++---- .../Sorting/ProductionYearComparer.cs | 12 ++++---- .../Sorting/RandomComparer.cs | 12 ++++---- .../Sorting/RuntimeComparer.cs | 12 ++++---- .../Sorting/SortNameComparer.cs | 12 ++++---- .../Sorting/StudioComparer.cs | 12 ++++---- 14 files changed, 96 insertions(+), 96 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index 037eb170a..db8b68949 100644 --- a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -10,6 +10,12 @@ namespace Emby.Server.Implementations.Sorting { public class AiredEpisodeOrderComparer : IBaseItemComparer { + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.AiredEpisodeOrder; + /// /// Compares the specified x. /// @@ -155,11 +161,5 @@ namespace Emby.Server.Implementations.Sorting return comparisonResult; } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.AiredEpisodeOrder; } } diff --git a/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs b/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs index 42e644970..bd1966623 100644 --- a/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs +++ b/Emby.Server.Implementations/Sorting/AlbumArtistComparer.cs @@ -12,6 +12,12 @@ namespace Emby.Server.Implementations.Sorting /// public class AlbumArtistComparer : IBaseItemComparer { + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.AlbumArtist; + /// /// Compares the specified x. /// @@ -34,11 +40,5 @@ namespace Emby.Server.Implementations.Sorting return audio?.AlbumArtists.FirstOrDefault(); } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.AlbumArtist; } } diff --git a/Emby.Server.Implementations/Sorting/AlbumComparer.cs b/Emby.Server.Implementations/Sorting/AlbumComparer.cs index 1db3f5e9c..fe7dc84cb 100644 --- a/Emby.Server.Implementations/Sorting/AlbumComparer.cs +++ b/Emby.Server.Implementations/Sorting/AlbumComparer.cs @@ -11,6 +11,12 @@ namespace Emby.Server.Implementations.Sorting /// public class AlbumComparer : IBaseItemComparer { + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.Album; + /// /// Compares the specified x. /// @@ -33,11 +39,5 @@ namespace Emby.Server.Implementations.Sorting return audio == null ? string.Empty : audio.Album; } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.Album; } } diff --git a/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs b/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs index d20dedc2d..ba1835e4f 100644 --- a/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/CriticRatingComparer.cs @@ -9,6 +9,12 @@ namespace Emby.Server.Implementations.Sorting /// public class CriticRatingComparer : IBaseItemComparer { + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.CriticRating; + /// /// Compares the specified x. /// @@ -24,11 +30,5 @@ namespace Emby.Server.Implementations.Sorting { return x?.CriticRating ?? 0; } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.CriticRating; } } diff --git a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs index d3f10f78c..8b460166c 100644 --- a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs @@ -10,6 +10,12 @@ namespace Emby.Server.Implementations.Sorting /// public class DateCreatedComparer : IBaseItemComparer { + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.DateCreated; + /// /// Compares the specified x. /// @@ -30,11 +36,5 @@ namespace Emby.Server.Implementations.Sorting return DateTime.Compare(x.DateCreated, y.DateCreated); } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.DateCreated; } } diff --git a/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs b/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs index 08a44319f..ec818253b 100644 --- a/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DatePlayedComparer.cs @@ -32,6 +32,12 @@ namespace Emby.Server.Implementations.Sorting /// The user data repository. public IUserDataManager UserDataRepository { get; set; } + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.DatePlayed; + /// /// Compares the specified x. /// @@ -59,11 +65,5 @@ namespace Emby.Server.Implementations.Sorting return DateTime.MinValue; } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.DatePlayed; } } diff --git a/Emby.Server.Implementations/Sorting/NameComparer.cs b/Emby.Server.Implementations/Sorting/NameComparer.cs index 4de81a69e..8f87717f4 100644 --- a/Emby.Server.Implementations/Sorting/NameComparer.cs +++ b/Emby.Server.Implementations/Sorting/NameComparer.cs @@ -10,6 +10,12 @@ namespace Emby.Server.Implementations.Sorting /// public class NameComparer : IBaseItemComparer { + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.Name; + /// /// Compares the specified x. /// @@ -30,11 +36,5 @@ namespace Emby.Server.Implementations.Sorting return string.Compare(x.Name, y.Name, StringComparison.CurrentCultureIgnoreCase); } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.Name; } } diff --git a/Emby.Server.Implementations/Sorting/PlayCountComparer.cs b/Emby.Server.Implementations/Sorting/PlayCountComparer.cs index 04e4865cb..45c9044c5 100644 --- a/Emby.Server.Implementations/Sorting/PlayCountComparer.cs +++ b/Emby.Server.Implementations/Sorting/PlayCountComparer.cs @@ -19,6 +19,24 @@ namespace Emby.Server.Implementations.Sorting /// The user. public User User { get; set; } + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.PlayCount; + + /// + /// Gets or sets the user data repository. + /// + /// The user data repository. + public IUserDataManager UserDataRepository { get; set; } + + /// + /// Gets or sets the user manager. + /// + /// The user manager. + public IUserManager UserManager { get; set; } + /// /// Compares the specified x. /// @@ -41,23 +59,5 @@ namespace Emby.Server.Implementations.Sorting return userdata == null ? 0 : userdata.PlayCount; } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.PlayCount; - - /// - /// Gets or sets the user data repository. - /// - /// The user data repository. - public IUserDataManager UserDataRepository { get; set; } - - /// - /// Gets or sets the user manager. - /// - /// The user manager. - public IUserManager UserManager { get; set; } } } diff --git a/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs b/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs index c98f97bf1..b217556ef 100644 --- a/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs +++ b/Emby.Server.Implementations/Sorting/PremiereDateComparer.cs @@ -10,6 +10,12 @@ namespace Emby.Server.Implementations.Sorting /// public class PremiereDateComparer : IBaseItemComparer { + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.PremiereDate; + /// /// Compares the specified x. /// @@ -52,11 +58,5 @@ namespace Emby.Server.Implementations.Sorting return DateTime.MinValue; } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.PremiereDate; } } diff --git a/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs b/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs index df9f9957d..d2022df7a 100644 --- a/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs +++ b/Emby.Server.Implementations/Sorting/ProductionYearComparer.cs @@ -9,6 +9,12 @@ namespace Emby.Server.Implementations.Sorting /// public class ProductionYearComparer : IBaseItemComparer { + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.ProductionYear; + /// /// Compares the specified x. /// @@ -44,11 +50,5 @@ namespace Emby.Server.Implementations.Sorting return 0; } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.ProductionYear; } } diff --git a/Emby.Server.Implementations/Sorting/RandomComparer.cs b/Emby.Server.Implementations/Sorting/RandomComparer.cs index af3bc2750..bf0168222 100644 --- a/Emby.Server.Implementations/Sorting/RandomComparer.cs +++ b/Emby.Server.Implementations/Sorting/RandomComparer.cs @@ -10,6 +10,12 @@ namespace Emby.Server.Implementations.Sorting /// public class RandomComparer : IBaseItemComparer { + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.Random; + /// /// Compares the specified x. /// @@ -20,11 +26,5 @@ namespace Emby.Server.Implementations.Sorting { return Guid.NewGuid().CompareTo(Guid.NewGuid()); } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.Random; } } diff --git a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs index 129315303..e32e5552e 100644 --- a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs +++ b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs @@ -12,6 +12,12 @@ namespace Emby.Server.Implementations.Sorting /// public class RuntimeComparer : IBaseItemComparer { + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.Runtime; + /// /// Compares the specified x. /// @@ -32,11 +38,5 @@ namespace Emby.Server.Implementations.Sorting return (x.RunTimeTicks ?? 0).CompareTo(y.RunTimeTicks ?? 0); } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.Runtime; } } diff --git a/Emby.Server.Implementations/Sorting/SortNameComparer.cs b/Emby.Server.Implementations/Sorting/SortNameComparer.cs index 8d30716d3..fb97a0349 100644 --- a/Emby.Server.Implementations/Sorting/SortNameComparer.cs +++ b/Emby.Server.Implementations/Sorting/SortNameComparer.cs @@ -12,6 +12,12 @@ namespace Emby.Server.Implementations.Sorting /// public class SortNameComparer : IBaseItemComparer { + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.SortName; + /// /// Compares the specified x. /// @@ -32,11 +38,5 @@ namespace Emby.Server.Implementations.Sorting return string.Compare(x.SortName, y.SortName, StringComparison.CurrentCultureIgnoreCase); } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.SortName; } } diff --git a/Emby.Server.Implementations/Sorting/StudioComparer.cs b/Emby.Server.Implementations/Sorting/StudioComparer.cs index 6826aee3b..4d89cfa8b 100644 --- a/Emby.Server.Implementations/Sorting/StudioComparer.cs +++ b/Emby.Server.Implementations/Sorting/StudioComparer.cs @@ -13,6 +13,12 @@ namespace Emby.Server.Implementations.Sorting { public class StudioComparer : IBaseItemComparer { + /// + /// Gets the name. + /// + /// The name. + public string Name => ItemSortBy.Studio; + /// /// Compares the specified x. /// @@ -33,11 +39,5 @@ namespace Emby.Server.Implementations.Sorting return AlphanumericComparator.CompareValues(x.Studios.FirstOrDefault(), y.Studios.FirstOrDefault()); } - - /// - /// Gets the name. - /// - /// The name. - public string Name => ItemSortBy.Studio; } } -- cgit v1.2.3 From c09ef74b516c04b820bf7cdd1060ab7ceb102c13 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 2 Oct 2021 13:31:31 -0400 Subject: Fix warnings in IO --- Emby.Server.Implementations/IO/LibraryMonitor.cs | 36 ++++++++++++---------- .../IO/ManagedFileSystem.cs | 18 +++++------ 2 files changed, 29 insertions(+), 25 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index aa80bccd7..e9d069cd3 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -41,6 +41,25 @@ namespace Emby.Server.Implementations.IO private bool _disposed = false; + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The library manager. + /// The configuration manager. + /// The filesystem. + public LibraryMonitor( + ILogger logger, + ILibraryManager libraryManager, + IServerConfigurationManager configurationManager, + IFileSystem fileSystem) + { + _libraryManager = libraryManager; + _logger = logger; + _configurationManager = configurationManager; + _fileSystem = fileSystem; + } + /// /// Add the path to our temporary ignore list. Use when writing to a path within our listening scope. /// @@ -95,21 +114,6 @@ namespace Emby.Server.Implementations.IO } } - /// - /// Initializes a new instance of the class. - /// - public LibraryMonitor( - ILogger logger, - ILibraryManager libraryManager, - IServerConfigurationManager configurationManager, - IFileSystem fileSystem) - { - _libraryManager = libraryManager; - _logger = logger; - _configurationManager = configurationManager; - _fileSystem = fileSystem; - } - private bool IsLibraryMonitorEnabled(BaseItem item) { if (item is BasePluginFolder) @@ -199,7 +203,7 @@ namespace Emby.Server.Implementations.IO /// The LST. /// The path. /// true if [contains parent folder] [the specified LST]; otherwise, false. - /// path + /// is null. private static bool ContainsParentFolder(IEnumerable lst, string path) { if (string.IsNullOrEmpty(path)) diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 77da46cd6..eeee28842 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.IO /// public class ManagedFileSystem : IFileSystem { - protected ILogger Logger; + private readonly ILogger _logger; private readonly List _shortcutHandlers = new List(); private readonly string _tempPath; @@ -27,7 +27,7 @@ namespace Emby.Server.Implementations.IO ILogger logger, IApplicationPaths applicationPaths) { - Logger = logger; + _logger = logger; _tempPath = applicationPaths.TempDirectory; } @@ -41,7 +41,7 @@ namespace Emby.Server.Implementations.IO /// /// The filename. /// true if the specified filename is shortcut; otherwise, false. - /// filename + /// is null. public virtual bool IsShortcut(string filename) { if (string.IsNullOrEmpty(filename)) @@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.IO /// /// The filename. /// System.String. - /// filename + /// is null. public virtual string? ResolveShortcut(string filename) { if (string.IsNullOrEmpty(filename)) @@ -233,9 +233,9 @@ namespace Emby.Server.Implementations.IO result.IsDirectory = info is DirectoryInfo || (info.Attributes & FileAttributes.Directory) == FileAttributes.Directory; // if (!result.IsDirectory) - //{ + // { // result.IsHidden = (info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden; - //} + // } if (info is FileInfo fileInfo) { @@ -254,7 +254,7 @@ namespace Emby.Server.Implementations.IO catch (FileNotFoundException ex) { // Dangling symlinks cannot be detected before opening the file unfortunately... - Logger.LogError(ex, "Reading the file size of the symlink at {Path} failed. Marking the file as not existing.", fileInfo.FullName); + _logger.LogError(ex, "Reading the file size of the symlink at {Path} failed. Marking the file as not existing.", fileInfo.FullName); result.Exists = false; } } @@ -343,7 +343,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError(ex, "Error determining CreationTimeUtc for {FullName}", info.FullName); + _logger.LogError(ex, "Error determining CreationTimeUtc for {FullName}", info.FullName); return DateTime.MinValue; } } @@ -382,7 +382,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError(ex, "Error determining LastAccessTimeUtc for {FullName}", info.FullName); + _logger.LogError(ex, "Error determining LastAccessTimeUtc for {FullName}", info.FullName); return DateTime.MinValue; } } -- cgit v1.2.3 From 8c8ca9adedf3e9df3c6fb83ee0967f0af5fc9fc3 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 2 Oct 2021 13:35:06 -0400 Subject: Fix warnings in UdpSocket --- Emby.Server.Implementations/Net/UdpSocket.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Net/UdpSocket.cs b/Emby.Server.Implementations/Net/UdpSocket.cs index 9b799e854..0c451ccb6 100644 --- a/Emby.Server.Implementations/Net/UdpSocket.cs +++ b/Emby.Server.Implementations/Net/UdpSocket.cs @@ -16,11 +16,7 @@ namespace Emby.Server.Implementations.Net public sealed class UdpSocket : ISocket, IDisposable { - private Socket _socket; private readonly int _localPort; - private bool _disposed = false; - - public Socket Socket => _socket; private readonly SocketAsyncEventArgs _receiveSocketAsyncEventArgs = new SocketAsyncEventArgs() { @@ -32,6 +28,8 @@ namespace Emby.Server.Implementations.Net SocketFlags = SocketFlags.None }; + private Socket _socket; + private bool _disposed = false; private TaskCompletionSource _currentReceiveTaskCompletionSource; private TaskCompletionSource _currentSendTaskCompletionSource; @@ -64,6 +62,8 @@ namespace Emby.Server.Implementations.Net InitReceiveSocketAsyncEventArgs(); } + public Socket Socket => _socket; + public IPAddress LocalIPAddress { get; } private void InitReceiveSocketAsyncEventArgs() -- cgit v1.2.3 From 7ae055f740aa72ebe585d3c34a015a4a96e01ea2 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 2 Oct 2021 13:36:56 -0400 Subject: Fix warnings in UdpServer --- Emby.Server.Implementations/Udp/UdpServer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Udp/UdpServer.cs b/Emby.Server.Implementations/Udp/UdpServer.cs index 8179e26c5..bf51c3968 100644 --- a/Emby.Server.Implementations/Udp/UdpServer.cs +++ b/Emby.Server.Implementations/Udp/UdpServer.cs @@ -29,10 +29,10 @@ namespace Emby.Server.Implementations.Udp private readonly IServerApplicationHost _appHost; private readonly IConfiguration _config; - private Socket _udpSocket; - private IPEndPoint _endpoint; private readonly byte[] _receiveBuffer = new byte[8192]; + private Socket _udpSocket; + private IPEndPoint _endpoint; private bool _disposed = false; /// -- cgit v1.2.3 From b17a452d1677f6511fa9c066e16c9c7a00dca518 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 2 Oct 2021 13:41:42 -0400 Subject: Fix warnings in ServerApplicationPaths --- Emby.Server.Implementations/ServerApplicationPaths.cs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ServerApplicationPaths.cs b/Emby.Server.Implementations/ServerApplicationPaths.cs index 6cf9a8f71..369a2b0d8 100644 --- a/Emby.Server.Implementations/ServerApplicationPaths.cs +++ b/Emby.Server.Implementations/ServerApplicationPaths.cs @@ -12,6 +12,11 @@ namespace Emby.Server.Implementations /// /// Initializes a new instance of the class. /// + /// The path for Jellyfin's data. + /// The path for Jellyfin's logging directory. + /// The path for Jellyfin's configuration directory. + /// The path for Jellyfin's cache directory. + /// The path for Jellyfin's web UI. public ServerApplicationPaths( string programDataPath, string logDirectoryPath, -- cgit v1.2.3 From 7ea4c844c89e0bfa7a21c7a34e51182ec791ee8c Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 2 Oct 2021 13:45:11 -0400 Subject: Fix warnings in InstallationManager --- Emby.Server.Implementations/Updates/InstallationManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 7b0afa4e2..4a022c5db 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -10,8 +10,8 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Events; -using MediaBrowser.Common.Configuration; using Jellyfin.Extensions.Json; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; -- cgit v1.2.3 From aa3c33060d775c8d050bd3975cd692c80081ea66 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 2 Oct 2021 13:46:25 -0400 Subject: Fix warnings in Playlists --- .../Playlists/ManualPlaylistsFolder.cs | 58 ---------------------- .../Playlists/PlaylistsFolder.cs | 58 ++++++++++++++++++++++ 2 files changed, 58 insertions(+), 58 deletions(-) delete mode 100644 Emby.Server.Implementations/Playlists/ManualPlaylistsFolder.cs create mode 100644 Emby.Server.Implementations/Playlists/PlaylistsFolder.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Playlists/ManualPlaylistsFolder.cs b/Emby.Server.Implementations/Playlists/ManualPlaylistsFolder.cs deleted file mode 100644 index 8b1cee89d..000000000 --- a/Emby.Server.Implementations/Playlists/ManualPlaylistsFolder.cs +++ /dev/null @@ -1,58 +0,0 @@ -#pragma warning disable CS1591 - -using System.Collections.Generic; -using System.Linq; -using System.Text.Json.Serialization; -using Jellyfin.Data.Entities; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Playlists; -using MediaBrowser.Model.Querying; - -namespace Emby.Server.Implementations.Playlists -{ - public class PlaylistsFolder : BasePluginFolder - { - public PlaylistsFolder() - { - Name = "Playlists"; - } - - [JsonIgnore] - public override bool IsHidden => true; - - [JsonIgnore] - public override bool SupportsInheritedParentImages => false; - - [JsonIgnore] - public override string CollectionType => MediaBrowser.Model.Entities.CollectionType.Playlists; - - public override bool IsVisible(User user) - { - return base.IsVisible(user) && GetChildren(user, true).Any(); - } - - protected override IEnumerable GetEligibleChildrenForRecursiveChildren(User user) - { - return base.GetEligibleChildrenForRecursiveChildren(user).OfType(); - } - - protected override QueryResult GetItemsInternal(InternalItemsQuery query) - { - if (query.User == null) - { - query.Recursive = false; - return base.GetItemsInternal(query); - } - - query.Recursive = true; - query.IncludeItemTypes = new[] { "Playlist" }; - query.Parent = null; - return LibraryManager.GetItemsResult(query); - } - - public override string GetClientTypeName() - { - return "ManualPlaylistsFolder"; - } - } -} diff --git a/Emby.Server.Implementations/Playlists/PlaylistsFolder.cs b/Emby.Server.Implementations/Playlists/PlaylistsFolder.cs new file mode 100644 index 000000000..8b1cee89d --- /dev/null +++ b/Emby.Server.Implementations/Playlists/PlaylistsFolder.cs @@ -0,0 +1,58 @@ +#pragma warning disable CS1591 + +using System.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; +using Jellyfin.Data.Entities; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Playlists; +using MediaBrowser.Model.Querying; + +namespace Emby.Server.Implementations.Playlists +{ + public class PlaylistsFolder : BasePluginFolder + { + public PlaylistsFolder() + { + Name = "Playlists"; + } + + [JsonIgnore] + public override bool IsHidden => true; + + [JsonIgnore] + public override bool SupportsInheritedParentImages => false; + + [JsonIgnore] + public override string CollectionType => MediaBrowser.Model.Entities.CollectionType.Playlists; + + public override bool IsVisible(User user) + { + return base.IsVisible(user) && GetChildren(user, true).Any(); + } + + protected override IEnumerable GetEligibleChildrenForRecursiveChildren(User user) + { + return base.GetEligibleChildrenForRecursiveChildren(user).OfType(); + } + + protected override QueryResult GetItemsInternal(InternalItemsQuery query) + { + if (query.User == null) + { + query.Recursive = false; + return base.GetItemsInternal(query); + } + + query.Recursive = true; + query.IncludeItemTypes = new[] { "Playlist" }; + query.Parent = null; + return LibraryManager.GetItemsResult(query); + } + + public override string GetClientTypeName() + { + return "ManualPlaylistsFolder"; + } + } +} -- cgit v1.2.3 From 876a902356fb5c0e502b440d591287a53e2488fc Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Sat, 2 Oct 2021 13:59:58 -0400 Subject: Fix warnings in Library --- Emby.Server.Implementations/Library/LibraryManager.cs | 4 ++-- Emby.Server.Implementations/Library/MediaSourceManager.cs | 2 +- Emby.Server.Implementations/Library/PathExtensions.cs | 2 +- .../Library/Resolvers/Audio/MusicAlbumResolver.cs | 3 +++ .../Library/Resolvers/BaseVideoResolver.cs | 4 ++++ .../Library/Resolvers/Books/BookResolver.cs | 7 +++---- .../Library/Resolvers/Movies/MovieResolver.cs | 4 ++-- .../Library/Resolvers/SpecialFolderResolver.cs | 1 - Emby.Server.Implementations/Library/SearchEngine.cs | 2 +- Emby.Server.Implementations/Library/UserDataManager.cs | 15 +++++++-------- Emby.Server.Implementations/Library/UserViewManager.cs | 3 ++- .../Library/Validators/ArtistsValidator.cs | 11 +++++++---- 12 files changed, 33 insertions(+), 25 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 132486b4a..1326f60fe 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -647,7 +647,7 @@ namespace Emby.Server.Implementations.Library /// Determines whether a path should be ignored based on its contents - called after the contents have been read. /// /// The args. - /// true if XXXX, false otherwise + /// true if XXXX, false otherwise. private static bool ShouldResolvePathContents(ItemResolveArgs args) { // Ignore any folders containing a file called .ignore @@ -1266,7 +1266,7 @@ namespace Emby.Server.Implementations.Library /// /// The id. /// BaseItem. - /// id + /// is null. public BaseItem GetItemById(Guid id) { if (id == Guid.Empty) diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 16231c73f..351fced34 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -13,9 +13,9 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using Jellyfin.Extensions.Json; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs index 86b8039fa..d5b855cdf 100644 --- a/Emby.Server.Implementations/Library/PathExtensions.cs +++ b/Emby.Server.Implementations/Library/PathExtensions.cs @@ -53,7 +53,7 @@ namespace Emby.Server.Implementations.Library /// The original path. /// The original sub path. /// The new sub path. - /// The result of the sub path replacement + /// The result of the sub path replacement. /// The path after replacing the sub path. /// , or is empty. public static bool TryReplaceSubPath( diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index 8e1eccb10..60720dd2f 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -82,6 +82,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio /// /// Determine if the supplied file data points to a music album. /// + /// The path to check. + /// The directory service. + /// true if the provided path points to a music album, false otherwise. public bool IsMusicAlbum(string path, IDirectoryService directoryService) { return ContainsMusic(directoryService.GetFileSystemEntries(path), true, directoryService, _logger, _fileSystem, _libraryManager); diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index b102b86cf..9ff99fa43 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -275,6 +275,10 @@ namespace Emby.Server.Implementations.Library.Resolvers /// /// Determines whether [is DVD directory] [the specified directory name]. /// + /// The full path of the directory. + /// The name of the directory. + /// The directory service. + /// true if the provided directory is a DVD directory, false otherwise. protected bool IsDvdDirectory(string fullPath, string directoryName, IDirectoryService directoryService) { if (!string.Equals(directoryName, "video_ts", StringComparison.OrdinalIgnoreCase)) diff --git a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs index 68076730b..e685c87f1 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs @@ -49,13 +49,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books { var bookFiles = args.FileSystemChildren.Where(f => { - var fileExtension = Path.GetExtension(f.FullName) ?? - string.Empty; + var fileExtension = Path.GetExtension(f.FullName) + ?? string.Empty; return _validExtensions.Contains( fileExtension, - StringComparer - .OrdinalIgnoreCase); + StringComparer.OrdinalIgnoreCase); }).ToList(); // Don't return a Book if there is more (or less) than one document in the directory diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 8b55a7744..f3b6ef0a2 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -24,6 +24,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies /// public class MovieResolver : BaseVideoResolver -- cgit v1.2.3 From fc96305e780904dd49e315a5a8b17784ee9b3492 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Oct 2021 12:01:09 +0000 Subject: Bump DotNet.Glob from 3.1.2 to 3.1.3 Bumps [DotNet.Glob](https://github.com/dazinator/DotNet.Glob) from 3.1.2 to 3.1.3. - [Release notes](https://github.com/dazinator/DotNet.Glob/releases) - [Changelog](https://github.com/dazinator/DotNet.Glob/blob/develop/ReleaseNotes.md) - [Commits](https://github.com/dazinator/DotNet.Glob/compare/3.1.2...3.1.3) --- updated-dependencies: - dependency-name: DotNet.Glob dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 0e1386ef5..062ad4885 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -34,7 +34,7 @@ - + -- cgit v1.2.3 From 017380f1ddccb46ce270f1d0df8e07d639ba3704 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Mon, 4 Oct 2021 07:43:40 -0600 Subject: Reference dotnet6-rc1 packages --- Emby.Dlna/Emby.Dlna.csproj | 2 +- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 10 +++++----- Jellyfin.Api/Jellyfin.Api.csproj | 4 ++-- Jellyfin.Data/Jellyfin.Data.csproj | 2 +- .../Jellyfin.Server.Implementations.csproj | 8 ++++---- .../Security/AuthorizationContext.cs | 2 +- Jellyfin.Server.Implementations/Users/UserManager.cs | 5 +++++ Jellyfin.Server/Jellyfin.Server.csproj | 8 ++++---- MediaBrowser.Common/MediaBrowser.Common.csproj | 4 ++-- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 6 +++--- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 4 ++-- MediaBrowser.Model/MediaBrowser.Model.csproj | 4 ++-- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 6 +++--- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 4 ++-- .../Jellyfin.Server.Integration.Tests.csproj | 6 +++--- tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj | 6 +++--- 16 files changed, 43 insertions(+), 38 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 1d4e3b047..5348aed63 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -73,7 +73,7 @@ - + diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 428cad071..fb1972610 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -25,11 +25,11 @@ - - - - - + + + + + diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 1c451ef6c..f46c0cbd1 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -14,8 +14,8 @@ - - + + diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 19aef704c..f1bfaa63e 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -35,7 +35,7 @@ - + diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index 337f5cb82..d9e6d794b 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -19,13 +19,13 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index ba2cfc724..3ab043c64 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -2,12 +2,12 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net; using System.Threading.Tasks; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; using Microsoft.Net.Http.Headers; namespace Jellyfin.Server.Implementations.Security diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 02377bfd7..704a6a84e 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -701,6 +701,11 @@ namespace Jellyfin.Server.Implementations.Users /// public async Task ClearProfileImageAsync(User user) { + if (user.ProfileImage == null) + { + return; + } + await using var dbContext = _dbProvider.CreateContext(); dbContext.Remove(user.ProfileImage); await dbContext.SaveChangesAsync().ConfigureAwait(false); diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 074d43fba..6603105fa 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -31,10 +31,10 @@ - - - - + + + + diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 6358c0000..c87d58a14 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -19,8 +19,8 @@ - - + + diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 47cec7d77..997772c04 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -15,10 +15,10 @@ - - + + - + diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 30cfb904e..22bba2366 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -24,8 +24,8 @@ - - + + diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index b0a12a9c9..0ac58e355 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -35,9 +35,9 @@ - + - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 29d6b01f2..71a3554fd 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index b52ea078a..8b581857f 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 7939c7118..38687ae61 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -9,14 +9,14 @@ - - + + - + diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index b30e690a5..db24df240 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -10,13 +10,13 @@ - - + + - + -- cgit v1.2.3 From d245e45254057c62d058cfad3e56484a77093718 Mon Sep 17 00:00:00 2001 From: joanMelchor Date: Sun, 3 Oct 2021 17:12:37 +0000 Subject: Translated using Weblate (Catalan) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ca/ --- Emby.Server.Implementations/Localization/Core/ca.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/ca.json b/Emby.Server.Implementations/Localization/Core/ca.json index 7715daa7c..db3c13d80 100644 --- a/Emby.Server.Implementations/Localization/Core/ca.json +++ b/Emby.Server.Implementations/Localization/Core/ca.json @@ -15,7 +15,7 @@ "Favorites": "Preferits", "Folders": "Carpetes", "Genres": "Gèneres", - "HeaderAlbumArtists": "Artistes del Àlbum", + "HeaderAlbumArtists": "Àlbum de l'artista", "HeaderContinueWatching": "Continua Veient", "HeaderFavoriteAlbums": "Àlbums Preferits", "HeaderFavoriteArtists": "Artistes Predilectes", -- cgit v1.2.3 From e0db541381a669ff5ba618e618e162ba0d0ef1c9 Mon Sep 17 00:00:00 2001 From: Patrick Barron <18354464+barronpm@users.noreply.github.com> Date: Tue, 5 Oct 2021 22:07:16 -0400 Subject: Update indentation --- Emby.Server.Implementations/Library/UserViewManager.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs index b4ac49a38..eda494815 100644 --- a/Emby.Server.Implementations/Library/UserViewManager.cs +++ b/Emby.Server.Implementations/Library/UserViewManager.cs @@ -341,14 +341,15 @@ namespace Emby.Server.Implementations.Library mediaTypes = mediaTypes.Distinct().ToList(); } - var excludeItemTypes = includeItemTypes.Length == 0 && mediaTypes.Count == 0 ? new[] - { - nameof(Person), - nameof(Studio), - nameof(Year), - nameof(MusicGenre), - nameof(Genre) - } + var excludeItemTypes = includeItemTypes.Length == 0 && mediaTypes.Count == 0 + ? new[] + { + nameof(Person), + nameof(Studio), + nameof(Year), + nameof(MusicGenre), + nameof(Genre) + } : Array.Empty(); var query = new InternalItemsQuery(user) -- cgit v1.2.3 From 03f933aaa07113b0ae6971921249691c8455d5ba Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 6 Oct 2021 11:30:45 +0200 Subject: Fix the last few warnings Enables TreatWarningsAsErrors for all projects --- Emby.Server.Implementations/ApplicationHost.cs | 38 +++----- .../Data/BaseSqliteRepository.cs | 2 +- .../Emby.Server.Implementations.csproj | 5 -- .../Images/BaseDynamicImageProvider.cs | 4 +- .../Images/BaseFolderImageProvider.cs | 67 ++++++++++++++ .../Images/FolderImageProvider.cs | 69 -------------- .../Images/GenreImageProvider.cs | 41 --------- .../Images/MusicAlbumImageProvider.cs | 19 ++++ .../Images/MusicGenreImageProvider.cs | 59 ++++++++++++ .../Images/PhotoAlbumImageProvider.cs | 19 ++++ .../Library/Resolvers/FolderResolver.cs | 22 +---- .../Library/Resolvers/GenericFolderResolver.cs | 27 ++++++ .../Library/Resolvers/Movies/BoxSetResolver.cs | 2 +- .../Library/Resolvers/PhotoAlbumResolver.cs | 2 +- .../Library/Resolvers/PlaylistResolver.cs | 2 +- .../Library/Resolvers/SpecialFolderResolver.cs | 2 +- .../Library/Resolvers/TV/SeasonResolver.cs | 2 +- .../Library/Resolvers/TV/SeriesResolver.cs | 2 +- .../Listings/SchedulesDirectDtos/ImageDataDto.cs | 2 +- .../Listings/SchedulesDirectDtos/StationDto.cs | 100 ++++++++++----------- .../HdHomerun/HdHomerunChannelCommands.cs | 35 ++++++++ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 10 +-- .../TunerHosts/HdHomerun/HdHomerunManager.cs | 66 -------------- .../HdHomerun/IHdHomerunChannelCommands.cs | 11 +++ .../HdHomerun/LegacyHdHomerunChannelCommands.cs | 38 ++++++++ .../MediaBrowser.Controller.csproj | 5 -- MediaBrowser.Model/MediaBrowser.Model.csproj | 5 -- 27 files changed, 353 insertions(+), 303 deletions(-) create mode 100644 Emby.Server.Implementations/Images/BaseFolderImageProvider.cs create mode 100644 Emby.Server.Implementations/Images/MusicAlbumImageProvider.cs create mode 100644 Emby.Server.Implementations/Images/MusicGenreImageProvider.cs create mode 100644 Emby.Server.Implementations/Images/PhotoAlbumImageProvider.cs create mode 100644 Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs create mode 100644 Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs create mode 100644 Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs create mode 100644 Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 3a504d2f4..1f11bdad7 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -306,7 +306,7 @@ namespace Emby.Server.Implementations /// public string Name => ApplicationProductName; - private CertificateInfo CertificateInfo { get; set; } + private string CertificatePath { get; set; } public X509Certificate2 Certificate { get; private set; } @@ -548,12 +548,8 @@ namespace Emby.Server.Implementations HttpsPort = NetworkConfiguration.DefaultHttpsPort; } - CertificateInfo = new CertificateInfo - { - Path = networkConfiguration.CertificatePath, - Password = networkConfiguration.CertificatePassword - }; - Certificate = GetCertificate(CertificateInfo); + CertificatePath = networkConfiguration.CertificatePath; + Certificate = GetCertificate(CertificatePath, networkConfiguration.CertificatePassword); RegisterServices(); @@ -729,30 +725,27 @@ namespace Emby.Server.Implementations logger.LogInformation("Application directory: {ApplicationPath}", appPaths.ProgramSystemPath); } - private X509Certificate2 GetCertificate(CertificateInfo info) + private X509Certificate2 GetCertificate(string path, string password) { - var certificateLocation = info?.Path; - - if (string.IsNullOrWhiteSpace(certificateLocation)) + if (string.IsNullOrWhiteSpace(path)) { return null; } try { - if (!File.Exists(certificateLocation)) + if (!File.Exists(path)) { return null; } // Don't use an empty string password - var password = string.IsNullOrWhiteSpace(info.Password) ? null : info.Password; + password = string.IsNullOrWhiteSpace(password) ? null : password; - var localCert = new X509Certificate2(certificateLocation, password, X509KeyStorageFlags.UserKeySet); - // localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA; + var localCert = new X509Certificate2(path, password, X509KeyStorageFlags.UserKeySet); if (!localCert.HasPrivateKey) { - Logger.LogError("No private key included in SSL cert {CertificateLocation}.", certificateLocation); + Logger.LogError("No private key included in SSL cert {CertificateLocation}.", path); return null; } @@ -760,7 +753,7 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError(ex, "Error loading cert from {CertificateLocation}", certificateLocation); + Logger.LogError(ex, "Error loading cert from {CertificateLocation}", path); return null; } } @@ -882,7 +875,7 @@ namespace Emby.Server.Implementations "http://" + i + ":" + HttpPort + "/" }; - if (CertificateInfo != null) + if (Certificate != null) { prefixes.Add("https://" + i + ":" + HttpsPort + "/"); } @@ -946,7 +939,7 @@ namespace Emby.Server.Implementations var newPath = networkConfig.CertificatePath; if (!string.IsNullOrWhiteSpace(newPath) - && !string.Equals(CertificateInfo?.Path, newPath, StringComparison.Ordinal)) + && !string.Equals(CertificatePath, newPath, StringComparison.Ordinal)) { if (File.Exists(newPath)) { @@ -1293,11 +1286,4 @@ namespace Emby.Server.Implementations _disposed = true; } } - - internal class CertificateInfo - { - public string Path { get; set; } - - public string Password { get; set; } - } } diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 4f6c81102..73c31f49d 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -98,7 +98,7 @@ namespace Emby.Server.Implementations.Data /// The write connection. protected SQLiteDatabaseConnection WriteConnection { get; set; } - protected ManagedConnection GetConnection(bool _ = false) + protected ManagedConnection GetConnection(bool readOnly = false) { WriteLock.Wait(); if (WriteConnection != null) diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 428cad071..82e4c3d69 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -47,11 +47,6 @@ true AD0001 - false - - - - true diff --git a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs index 4a026fd21..758986945 100644 --- a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs @@ -65,13 +65,13 @@ namespace Emby.Server.Implementations.Images if (SupportedImages.Contains(ImageType.Primary)) { var primaryResult = await FetchAsync(item, ImageType.Primary, options, cancellationToken).ConfigureAwait(false); - updateType = updateType | primaryResult; + updateType |= primaryResult; } if (SupportedImages.Contains(ImageType.Thumb)) { var thumbResult = await FetchAsync(item, ImageType.Thumb, options, cancellationToken).ConfigureAwait(false); - updateType = updateType | thumbResult; + updateType |= thumbResult; } return updateType; diff --git a/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs b/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs new file mode 100644 index 000000000..1c69056d2 --- /dev/null +++ b/Emby.Server.Implementations/Images/BaseFolderImageProvider.cs @@ -0,0 +1,67 @@ +#nullable disable + +#pragma warning disable CS1591 + +using System.Collections.Generic; +using Jellyfin.Data.Enums; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Querying; + +namespace Emby.Server.Implementations.Images +{ + public abstract class BaseFolderImageProvider : BaseDynamicImageProvider + where T : Folder, new() + { + private readonly ILibraryManager _libraryManager; + + public BaseFolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) + : base(fileSystem, providerManager, applicationPaths, imageProcessor) + { + _libraryManager = libraryManager; + } + + protected override IReadOnlyList GetItemsWithImages(BaseItem item) + { + return _libraryManager.GetItemList(new InternalItemsQuery + { + Parent = item, + DtoOptions = new DtoOptions(true), + ImageTypes = new ImageType[] { ImageType.Primary }, + OrderBy = new (string, SortOrder)[] + { + (ItemSortBy.IsFolder, SortOrder.Ascending), + (ItemSortBy.SortName, SortOrder.Ascending) + }, + Limit = 1 + }); + } + + protected override string CreateImage(BaseItem item, IReadOnlyCollection itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) + { + return CreateSingleImage(itemsWithImages, outputPathWithoutExtension, ImageType.Primary); + } + + protected override bool Supports(BaseItem item) + { + return item is T; + } + + protected override bool HasChangedByDate(BaseItem item, ItemImageInfo image) + { + if (item is MusicAlbum) + { + return false; + } + + return base.HasChangedByDate(item, image); + } + } +} diff --git a/Emby.Server.Implementations/Images/FolderImageProvider.cs b/Emby.Server.Implementations/Images/FolderImageProvider.cs index 859017f86..4376bd356 100644 --- a/Emby.Server.Implementations/Images/FolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/FolderImageProvider.cs @@ -2,69 +2,16 @@ #pragma warning disable CS1591 -using System.Collections.Generic; -using Jellyfin.Data.Enums; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Images { - public abstract class BaseFolderImageProvider : BaseDynamicImageProvider - where T : Folder, new() - { - protected ILibraryManager _libraryManager; - - public BaseFolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) - : base(fileSystem, providerManager, applicationPaths, imageProcessor) - { - _libraryManager = libraryManager; - } - - protected override IReadOnlyList GetItemsWithImages(BaseItem item) - { - return _libraryManager.GetItemList(new InternalItemsQuery - { - Parent = item, - DtoOptions = new DtoOptions(true), - ImageTypes = new ImageType[] { ImageType.Primary }, - OrderBy = new System.ValueTuple[] - { - new System.ValueTuple(ItemSortBy.IsFolder, SortOrder.Ascending), - new System.ValueTuple(ItemSortBy.SortName, SortOrder.Ascending) - }, - Limit = 1 - }); - } - - protected override string CreateImage(BaseItem item, IReadOnlyCollection itemsWithImages, string outputPathWithoutExtension, ImageType imageType, int imageIndex) - { - return CreateSingleImage(itemsWithImages, outputPathWithoutExtension, ImageType.Primary); - } - - protected override bool Supports(BaseItem item) - { - return item is T; - } - - protected override bool HasChangedByDate(BaseItem item, ItemImageInfo image) - { - if (item is MusicAlbum) - { - return false; - } - - return base.HasChangedByDate(item, image); - } - } - public class FolderImageProvider : BaseFolderImageProvider { public FolderImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) @@ -87,20 +34,4 @@ namespace Emby.Server.Implementations.Images return true; } } - - public class MusicAlbumImageProvider : BaseFolderImageProvider - { - public MusicAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) - : base(fileSystem, providerManager, applicationPaths, imageProcessor, libraryManager) - { - } - } - - public class PhotoAlbumImageProvider : BaseFolderImageProvider - { - public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) - : base(fileSystem, providerManager, applicationPaths, imageProcessor, libraryManager) - { - } - } } diff --git a/Emby.Server.Implementations/Images/GenreImageProvider.cs b/Emby.Server.Implementations/Images/GenreImageProvider.cs index 6da431c68..1f5090f7f 100644 --- a/Emby.Server.Implementations/Images/GenreImageProvider.cs +++ b/Emby.Server.Implementations/Images/GenreImageProvider.cs @@ -8,7 +8,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; @@ -19,46 +18,6 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Images { - /// - /// Class MusicGenreImageProvider. - /// - public class MusicGenreImageProvider : BaseDynamicImageProvider - { - /// - /// The library manager. - /// - private readonly ILibraryManager _libraryManager; - - public MusicGenreImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) : base(fileSystem, providerManager, applicationPaths, imageProcessor) - { - _libraryManager = libraryManager; - } - - /// - /// Get children objects used to create an music genre image. - /// - /// The music genre used to create the image. - /// Any relevant children objects. - protected override IReadOnlyList GetItemsWithImages(BaseItem item) - { - return _libraryManager.GetItemList(new InternalItemsQuery - { - Genres = new[] { item.Name }, - IncludeItemTypes = new[] - { - nameof(MusicAlbum), - nameof(MusicVideo), - nameof(Audio) - }, - OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) }, - Limit = 4, - Recursive = true, - ImageTypes = new[] { ImageType.Primary }, - DtoOptions = new DtoOptions(false) - }); - } - } - /// /// Class GenreImageProvider. /// diff --git a/Emby.Server.Implementations/Images/MusicAlbumImageProvider.cs b/Emby.Server.Implementations/Images/MusicAlbumImageProvider.cs new file mode 100644 index 000000000..ce8367363 --- /dev/null +++ b/Emby.Server.Implementations/Images/MusicAlbumImageProvider.cs @@ -0,0 +1,19 @@ +#pragma warning disable CS1591 + +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.IO; + +namespace Emby.Server.Implementations.Images +{ + public class MusicAlbumImageProvider : BaseFolderImageProvider + { + public MusicAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) + : base(fileSystem, providerManager, applicationPaths, imageProcessor, libraryManager) + { + } + } +} diff --git a/Emby.Server.Implementations/Images/MusicGenreImageProvider.cs b/Emby.Server.Implementations/Images/MusicGenreImageProvider.cs new file mode 100644 index 000000000..baf1c9051 --- /dev/null +++ b/Emby.Server.Implementations/Images/MusicGenreImageProvider.cs @@ -0,0 +1,59 @@ +#nullable disable + +#pragma warning disable CS1591 + +using System.Collections.Generic; +using Jellyfin.Data.Enums; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Dto; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Querying; + +namespace Emby.Server.Implementations.Images +{ + /// + /// Class MusicGenreImageProvider. + /// + public class MusicGenreImageProvider : BaseDynamicImageProvider + { + /// + /// The library manager. + /// + private readonly ILibraryManager _libraryManager; + + public MusicGenreImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) : base(fileSystem, providerManager, applicationPaths, imageProcessor) + { + _libraryManager = libraryManager; + } + + /// + /// Get children objects used to create an music genre image. + /// + /// The music genre used to create the image. + /// Any relevant children objects. + protected override IReadOnlyList GetItemsWithImages(BaseItem item) + { + return _libraryManager.GetItemList(new InternalItemsQuery + { + Genres = new[] { item.Name }, + IncludeItemTypes = new[] + { + nameof(MusicAlbum), + nameof(MusicVideo), + nameof(Audio) + }, + OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) }, + Limit = 4, + Recursive = true, + ImageTypes = new[] { ImageType.Primary }, + DtoOptions = new DtoOptions(false) + }); + } + } +} diff --git a/Emby.Server.Implementations/Images/PhotoAlbumImageProvider.cs b/Emby.Server.Implementations/Images/PhotoAlbumImageProvider.cs new file mode 100644 index 000000000..1ddb4c757 --- /dev/null +++ b/Emby.Server.Implementations/Images/PhotoAlbumImageProvider.cs @@ -0,0 +1,19 @@ +#pragma warning disable CS1591 + +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.IO; + +namespace Emby.Server.Implementations.Images +{ + public class PhotoAlbumImageProvider : BaseFolderImageProvider + { + public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, ILibraryManager libraryManager) + : base(fileSystem, providerManager, applicationPaths, imageProcessor, libraryManager) + { + } + } +} diff --git a/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs index 7aaee017d..db7703cd6 100644 --- a/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs @@ -9,7 +9,7 @@ namespace Emby.Server.Implementations.Library.Resolvers /// /// Class FolderResolver. /// - public class FolderResolver : FolderResolver + public class FolderResolver : GenericFolderResolver { /// /// Gets the priority. @@ -32,24 +32,4 @@ namespace Emby.Server.Implementations.Library.Resolvers return null; } } - - /// - /// Class FolderResolver. - /// - /// The type of the T item type. - public abstract class FolderResolver : ItemResolver - where TItemType : Folder, new() - { - /// - /// Sets the initial item values. - /// - /// The item. - /// The args. - protected override void SetInitialItemValues(TItemType item, ItemResolveArgs args) - { - base.SetInitialItemValues(item, args); - - item.IsRoot = args.Parent == null; - } - } } diff --git a/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs new file mode 100644 index 000000000..f109a5e9a --- /dev/null +++ b/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs @@ -0,0 +1,27 @@ +#nullable disable + +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; + +namespace Emby.Server.Implementations.Library.Resolvers +{ + /// + /// Class FolderResolver. + /// + /// The type of the T item type. + public abstract class GenericFolderResolver : ItemResolver + where TItemType : Folder, new() + { + /// + /// Sets the initial item values. + /// + /// The item. + /// The args. + protected override void SetInitialItemValues(TItemType item, ItemResolveArgs args) + { + base.SetInitialItemValues(item, args); + + item.IsRoot = args.Parent == null; + } + } +} diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs index 69d71d0d9..e7abe1e6d 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs @@ -12,7 +12,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies /// /// Class BoxSetResolver. /// - public class BoxSetResolver : FolderResolver + public class BoxSetResolver : GenericFolderResolver { /// /// Resolves the specified args. diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs index 534bc80dd..1c560e8a6 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs @@ -12,7 +12,7 @@ namespace Emby.Server.Implementations.Library.Resolvers /// /// Class PhotoAlbumResolver. /// - public class PhotoAlbumResolver : FolderResolver + public class PhotoAlbumResolver : GenericFolderResolver { private readonly IImageProcessor _imageProcessor; private readonly ILibraryManager _libraryManager; diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs index 2c4ead719..8ce59717d 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.Library.Resolvers /// /// for library items. /// - public class PlaylistResolver : FolderResolver + public class PlaylistResolver : GenericFolderResolver { private string[] _musicPlaylistCollectionTypes = { diff --git a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs index a42ac4144..6bb999641 100644 --- a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs @@ -13,7 +13,7 @@ using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers { - public class SpecialFolderResolver : FolderResolver + public class SpecialFolderResolver : GenericFolderResolver { private readonly IFileSystem _fileSystem; private readonly IServerApplicationPaths _appPaths; diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index 7d707df18..063f67543 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -12,7 +12,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV /// /// Class SeasonResolver. /// - public class SeasonResolver : FolderResolver + public class SeasonResolver : GenericFolderResolver { private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localization; diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 4d8a6494c..b7fbe01c5 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -18,7 +18,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV /// /// Class SeriesResolver. /// - public class SeriesResolver : FolderResolver + public class SeriesResolver : GenericFolderResolver { private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs index 912e680dd..4e9efc60f 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/ImageDataDto.cs @@ -37,7 +37,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the aspect. /// [JsonPropertyName("aspect")] - public string aspect { get; set; } + public string Aspect { get; set; } /// /// Gets or sets the category. diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs index 12f3576c6..c37f19678 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs @@ -6,62 +6,62 @@ using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos { /// - /// Station dto. - /// - public class StationDto - { - /// - /// Gets or sets the station id. - /// - [JsonPropertyName("stationID")] - public string StationId { get; set; } + /// Station dto. + /// + public class StationDto + { + /// + /// Gets or sets the station id. + /// + [JsonPropertyName("stationID")] + public string StationId { get; set; } - /// - /// Gets or sets the name. - /// - [JsonPropertyName("name")] - public string Name { get; set; } + /// + /// Gets or sets the name. + /// + [JsonPropertyName("name")] + public string Name { get; set; } - /// - /// Gets or sets the callsign. - /// - [JsonPropertyName("callsign")] - public string Callsign { get; set; } + /// + /// Gets or sets the callsign. + /// + [JsonPropertyName("callsign")] + public string Callsign { get; set; } - /// - /// Gets or sets the broadcast language. - /// - [JsonPropertyName("broadcastLanguage")] - public List BroadcastLanguage { get; set; } + /// + /// Gets or sets the broadcast language. + /// + [JsonPropertyName("broadcastLanguage")] + public List BroadcastLanguage { get; set; } - /// - /// Gets or sets the description language. - /// - [JsonPropertyName("descriptionLanguage")] - public List DescriptionLanguage { get; set; } + /// + /// Gets or sets the description language. + /// + [JsonPropertyName("descriptionLanguage")] + public List DescriptionLanguage { get; set; } - /// - /// Gets or sets the broadcaster. - /// - [JsonPropertyName("broadcaster")] - public BroadcasterDto Broadcaster { get; set; } + /// + /// Gets or sets the broadcaster. + /// + [JsonPropertyName("broadcaster")] + public BroadcasterDto Broadcaster { get; set; } - /// - /// Gets or sets the affiliate. - /// - [JsonPropertyName("affiliate")] - public string Affiliate { get; set; } + /// + /// Gets or sets the affiliate. + /// + [JsonPropertyName("affiliate")] + public string Affiliate { get; set; } - /// - /// Gets or sets the logo. - /// - [JsonPropertyName("logo")] - public LogoDto Logo { get; set; } + /// + /// Gets or sets the logo. + /// + [JsonPropertyName("logo")] + public LogoDto Logo { get; set; } - /// - /// Gets or set a value indicating whether it is commercial free. - /// - [JsonPropertyName("isCommercialFree")] - public bool? IsCommercialFree { get; set; } - } + /// + /// Gets or sets a value indicating whether it is commercial free. + /// + [JsonPropertyName("isCommercialFree")] + public bool? IsCommercialFree { get; set; } + } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs new file mode 100644 index 000000000..069b4fab6 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs @@ -0,0 +1,35 @@ +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; + +namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun +{ + public class HdHomerunChannelCommands : IHdHomerunChannelCommands + { + private string? _channel; + private string? _profile; + + public HdHomerunChannelCommands(string? channel, string? profile) + { + _channel = channel; + _profile = profile; + } + + public IEnumerable<(string, string)> GetCommands() + { + if (!string.IsNullOrEmpty(_channel)) + { + if (!string.IsNullOrEmpty(_profile) + && !string.Equals(_profile, "native", StringComparison.OrdinalIgnoreCase)) + { + yield return ("vchannel", $"{_channel} transcode={_profile}"); + } + else + { + yield return ("vchannel", _channel); + } + } + } + } +} diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 4d538c604..78ea7bd0f 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -87,11 +87,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return lineup.Where(i => !i.DRM).ToList(); } - private class HdHomerunChannelInfo : ChannelInfo - { - public bool IsLegacyTuner { get; set; } - } - protected override async Task> GetChannelsInternal(TunerHostInfo tuner, CancellationToken cancellationToken) { var lineup = await GetLineup(tuner, cancellationToken).ConfigureAwait(false); @@ -715,5 +710,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun return hostInfo; } + + private class HdHomerunChannelInfo : ChannelInfo + { + public bool IsLegacyTuner { get; set; } + } } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index b2e555c7d..f0f61297f 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -5,12 +5,10 @@ using System; using System.Buffers; using System.Buffers.Binary; -using System.Collections.Generic; using System.Globalization; using System.Net; using System.Net.Sockets; using System.Text; -using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; @@ -18,70 +16,6 @@ using MediaBrowser.Controller.LiveTv; namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { - public interface IHdHomerunChannelCommands - { - IEnumerable<(string, string)> GetCommands(); - } - - public class LegacyHdHomerunChannelCommands : IHdHomerunChannelCommands - { - private string _channel; - private string _program; - - public LegacyHdHomerunChannelCommands(string url) - { - // parse url for channel and program - var regExp = new Regex(@"\/ch([0-9]+)-?([0-9]*)"); - var match = regExp.Match(url); - if (match.Success) - { - _channel = match.Groups[1].Value; - _program = match.Groups[2].Value; - } - } - - public IEnumerable<(string, string)> GetCommands() - { - if (!string.IsNullOrEmpty(_channel)) - { - yield return ("channel", _channel); - } - - if (!string.IsNullOrEmpty(_program)) - { - yield return ("program", _program); - } - } - } - - public class HdHomerunChannelCommands : IHdHomerunChannelCommands - { - private string _channel; - private string _profile; - - public HdHomerunChannelCommands(string channel, string profile) - { - _channel = channel; - _profile = profile; - } - - public IEnumerable<(string, string)> GetCommands() - { - if (!string.IsNullOrEmpty(_channel)) - { - if (!string.IsNullOrEmpty(_profile) - && !string.Equals(_profile, "native", StringComparison.OrdinalIgnoreCase)) - { - yield return ("vchannel", $"{_channel} transcode={_profile}"); - } - else - { - yield return ("vchannel", _channel); - } - } - } - } - public sealed class HdHomerunManager : IDisposable { public const int HdHomeRunPort = 65001; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs new file mode 100644 index 000000000..153354932 --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs @@ -0,0 +1,11 @@ +#pragma warning disable CS1591 + +using System.Collections.Generic; + +namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun +{ + public interface IHdHomerunChannelCommands + { + IEnumerable<(string, string)> GetCommands(); + } +} diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs new file mode 100644 index 000000000..26627b8aa --- /dev/null +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs @@ -0,0 +1,38 @@ +#pragma warning disable CS1591 + +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun +{ + public class LegacyHdHomerunChannelCommands : IHdHomerunChannelCommands + { + private string? _channel; + private string? _program; + + public LegacyHdHomerunChannelCommands(string url) + { + // parse url for channel and program + var regExp = new Regex(@"\/ch([0-9]+)-?([0-9]*)"); + var match = regExp.Match(url); + if (match.Success) + { + _channel = match.Groups[1].Value; + _program = match.Groups[2].Value; + } + } + + public IEnumerable<(string, string)> GetCommands() + { + if (!string.IsNullOrEmpty(_channel)) + { + yield return ("channel", _channel); + } + + if (!string.IsNullOrEmpty(_program)) + { + yield return ("program", _program); + } + } + } +} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 47cec7d77..4b3a75b90 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -39,11 +39,6 @@ true true snupkg - false - - - - true diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index b0a12a9c9..91803ade6 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -21,11 +21,6 @@ true true snupkg - false - - - - true -- cgit v1.2.3 From 6297fa5bf70880a2254f226d33da658b6b4ff05a Mon Sep 17 00:00:00 2001 From: Systerm Date: Wed, 6 Oct 2021 20:50:46 +0000 Subject: Translated using Weblate (Portuguese) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt/ --- .../Localization/Core/pt.json | 75 +++++++++++----------- 1 file changed, 38 insertions(+), 37 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/pt.json b/Emby.Server.Implementations/Localization/Core/pt.json index 474dacd7c..a9dbd53ea 100644 --- a/Emby.Server.Implementations/Localization/Core/pt.json +++ b/Emby.Server.Implementations/Localization/Core/pt.json @@ -1,6 +1,6 @@ { - "HeaderLiveTV": "TV em Directo", - "Collections": "Colecções", + "HeaderLiveTV": "TV Ao Vivo", + "Collections": "Coleções", "Books": "Livros", "Artists": "Artistas", "Albums": "Álbuns", @@ -10,29 +10,29 @@ "HeaderFavoriteAlbums": "Álbuns Favoritos", "HeaderFavoriteEpisodes": "Episódios Favoritos", "HeaderFavoriteShows": "Séries Favoritas", - "HeaderContinueWatching": "Continuar a Assistir", + "HeaderContinueWatching": "Continuar assistindo", "HeaderAlbumArtists": "Artistas do Álbum", - "Genres": "Géneros", - "Folders": "Directórios", + "Genres": "Gêneros", + "Folders": "Diretórios", "Favorites": "Favoritos", "Channels": "Canais", - "UserDownloadingItemWithValues": "{0} está a ser transferido {1}", + "UserDownloadingItemWithValues": "{0} está sendo baixado {1}", "VersionNumber": "Versão {0}", "ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua biblioteca multimédia", "UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}", - "UserStartedPlayingItemWithValues": "{0} está a reproduzir {1} em {2}", - "UserPolicyUpdatedWithName": "A política do utilizador {0} foi alterada", - "UserPasswordChangedWithName": "A palavra-passe do utilizador {0} foi alterada", - "UserOnlineFromDevice": "{0} ligou-se a partir de {1}", + "UserStartedPlayingItemWithValues": "{0} está reproduzindo {1} em {2}", + "UserPolicyUpdatedWithName": "A política do usuário {0} foi alterada", + "UserPasswordChangedWithName": "A senha do usuário {0} foi alterada", + "UserOnlineFromDevice": "{0} está online a partir de {1}", "UserOfflineFromDevice": "{0} desconectou-se a partir de {1}", - "UserLockedOutWithName": "O utilizador {0} foi bloqueado", - "UserDeletedWithName": "O utilizador {0} foi removido", - "UserCreatedWithName": "O utilizador {0} foi criado", - "User": "Utilizador", + "UserLockedOutWithName": "O usuário {0} foi bloqueado", + "UserDeletedWithName": "O usuário {0} foi removido", + "UserCreatedWithName": "O usuário {0} foi criado", + "User": "Usuário", "TvShows": "Séries", "System": "Sistema", "SubtitleDownloadFailureFromForItem": "Falha na transferência de legendas de {0} para {1}", - "StartupEmbyServerIsLoading": "O servidor Jellyfin está a iniciar. Tente novamente dentro de momentos.", + "StartupEmbyServerIsLoading": "O servidor Jellyfin está iniciando. Tente novamente dentro de momentos.", "ServerNameNeedsToBeRestarted": "{0} necessita ser reiniciado", "ScheduledTaskStartedWithName": "{0} iniciou", "ScheduledTaskFailedWithName": "{0} falhou", @@ -43,38 +43,38 @@ "Plugin": "Plugin", "NotificationOptionVideoPlaybackStopped": "Reprodução de vídeo parada", "NotificationOptionVideoPlayback": "Reprodução de vídeo iniciada", - "NotificationOptionUserLockedOut": "Utilizador bloqueado", - "NotificationOptionTaskFailed": "Falha em tarefa agendada", + "NotificationOptionUserLockedOut": "Usuário bloqueado", + "NotificationOptionTaskFailed": "Falha na tarefa agendada", "NotificationOptionServerRestartRequired": "É necessário reiniciar o servidor", - "NotificationOptionPluginUpdateInstalled": "Plugin actualizado", + "NotificationOptionPluginUpdateInstalled": "Plugin atualizado", "NotificationOptionPluginUninstalled": "Plugin desinstalado", "NotificationOptionPluginInstalled": "Plugin instalado", "NotificationOptionPluginError": "Falha no plugin", "NotificationOptionNewLibraryContent": "Novo conteúdo adicionado", "NotificationOptionInstallationFailed": "Falha de instalação", - "NotificationOptionCameraImageUploaded": "Imagem de câmara enviada", + "NotificationOptionCameraImageUploaded": "Imagem de câmera enviada", "NotificationOptionAudioPlaybackStopped": "Reprodução Parada", "NotificationOptionAudioPlayback": "Reprodução Iniciada", - "NotificationOptionApplicationUpdateInstalled": "A actualização da aplicação foi instalada", - "NotificationOptionApplicationUpdateAvailable": "Uma actualização da aplicação está disponível", - "NewVersionIsAvailable": "Uma nova versão do servidor Jellyfin está disponível para transferência.", + "NotificationOptionApplicationUpdateInstalled": "A atualização do aplicativo foi instalada", + "NotificationOptionApplicationUpdateAvailable": "Uma atualização do aplicativo está disponível", + "NewVersionIsAvailable": "Uma nova versão do servidor Jellyfin está disponível para download.", "NameSeasonUnknown": "Temporada Desconhecida", "NameSeasonNumber": "Temporada {0}", "NameInstallFailed": "Falha na instalação de {0}", "MusicVideos": "Videoclipes", "Music": "Música", - "MixedContent": "Conteúdo Misto", - "MessageServerConfigurationUpdated": "A configuração do servidor foi actualizada", - "MessageNamedServerConfigurationUpdatedWithValue": "As configurações do servidor na secção {0} foram atualizadas", + "MixedContent": "Conteúdo diverso", + "MessageServerConfigurationUpdated": "A configuração do servidor foi atualizada", + "MessageNamedServerConfigurationUpdatedWithValue": "As configurações do servidor na seção {0} foram atualizadas", "MessageApplicationUpdatedTo": "O servidor Jellyfin foi atualizado para a versão {0}", - "MessageApplicationUpdated": "O servidor Jellyfin foi actualizado", + "MessageApplicationUpdated": "O servidor Jellyfin foi atualizado", "Latest": "Mais Recente", "LabelRunningTimeValue": "Duração: {0}", "LabelIpAddressValue": "Endereço de IP: {0}", "ItemRemovedWithName": "{0} foi removido da biblioteca", "ItemAddedWithName": "{0} foi adicionado à biblioteca", "Inherit": "Herdar", - "HomeVideos": "Vídeos Caseiros", + "HomeVideos": "Vídeos principais", "HeaderRecordingGroups": "Grupos de Gravação", "ValueSpecialEpisodeName": "Episódio Especial - {0}", "Sync": "Sincronização", @@ -83,22 +83,22 @@ "Playlists": "Listas de Reprodução", "Photos": "Fotografias", "Movies": "Filmes", - "FailedLoginAttemptWithUserName": "Tentativa de ligação falhada a partir de {0}", - "DeviceOnlineWithName": "{0} está connectado", + "FailedLoginAttemptWithUserName": "Tentativa falha de login a partir de {0}", + "DeviceOnlineWithName": "{0} está conectado", "DeviceOfflineWithName": "{0} desconectou-se", "ChapterNameValue": "Capítulo {0}", "CameraImageUploadedFrom": "Uma nova imagem da câmara foi enviada a partir de {0}", "AuthenticationSucceededWithUserName": "{0} autenticado com sucesso", - "Application": "Aplicação", - "AppDeviceValues": "Aplicação {0}, Dispositivo: {1}", + "Application": "Aplicativo", + "AppDeviceValues": "Aplicativo {0}, Dispositivo: {1}", "TaskCleanCache": "Limpar Diretório de Cache", - "TasksApplicationCategory": "Aplicação", + "TasksApplicationCategory": "Aplicativo", "TasksLibraryCategory": "Biblioteca", "TasksMaintenanceCategory": "Manutenção", "TaskRefreshChannels": "Atualizar Canais", "TaskUpdatePlugins": "Atualizar Plugins", "TaskCleanLogsDescription": "Deletar arquivos de log que existe a mais de {0} dias.", - "TaskCleanLogs": "Limpar diretório de log", + "TaskCleanLogs": "Limpar diretório de logs", "TaskRefreshLibrary": "Escanear biblioteca de mídias", "TaskRefreshChapterImagesDescription": "Cria miniaturas para vídeos que têm capítulos.", "TaskCleanCacheDescription": "Apaga ficheiros em cache que já não são usados pelo sistema.", @@ -109,14 +109,15 @@ "TaskRefreshChannelsDescription": "Atualiza as informações do canal da Internet.", "TaskCleanTranscodeDescription": "Apagar os ficheiros com mais de um dia, de Transcode.", "TaskCleanTranscode": "Limpar o diretório de Transcode", - "TaskUpdatePluginsDescription": "Download e instala as atualizações para plug-ins configurados para atualização automática.", + "TaskUpdatePluginsDescription": "Baixa e instala as atualizações para plug-ins configurados para atualização automática.", "TaskRefreshPeopleDescription": "Atualiza os metadados para atores e diretores na tua biblioteca de media.", "TaskRefreshPeople": "Atualizar pessoas", - "TaskRefreshLibraryDescription": "Pesquisa a tua biblioteca de media por novos ficheiros e atualiza os metadados.", - "TaskCleanActivityLog": "Limpar registo de atividade", + "TaskRefreshLibraryDescription": "Pesquisa sua biblioteca de media por novos arquivos e atualiza os metadados.", + "TaskCleanActivityLog": "Limpar registro de atividade", "Undefined": "Indefinido", "Forced": "Forçado", "Default": "Predefinição", "TaskCleanActivityLogDescription": "Apaga itens no registro com idade acima do que é configurado.", - "TaskOptimizeDatabase": "Otimizar base de dados" + "TaskOptimizeDatabase": "Otimizar base de dados", + "TaskOptimizeDatabaseDescription": "Base de dados compacta e corta espaço livre. A execução desta tarefa depois de digitalizar a biblioteca ou de fazer outras alterações que impliquem modificações na base de dados pode melhorar o desempenho." } -- cgit v1.2.3 From 3b492d4af8c432cc11b11e946b72aaf97cf63c95 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 8 Oct 2021 15:02:58 +0200 Subject: Use static crypto rng --- .../Cryptography/CryptographyProvider.cs | 54 +++------------------- .../Users/DefaultPasswordResetProvider.cs | 11 ++--- 2 files changed, 9 insertions(+), 56 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs index 4a9b28085..673810c49 100644 --- a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs +++ b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs @@ -10,8 +10,12 @@ namespace Emby.Server.Implementations.Cryptography /// /// Class providing abstractions over cryptographic functions. /// - public class CryptographyProvider : ICryptoProvider, IDisposable + public class CryptographyProvider : ICryptoProvider { + // FIXME: When we get DotNet Standard 2.1 we need to revisit how we do the crypto + // Currently supported hash methods from https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptoconfig?view=netcore-2.1 + // there might be a better way to autogenerate this list as dotnet updates, but I couldn't find one + // Please note the default method of PBKDF2 is not included, it cannot be used to generate hashes cleanly as it is actually a pbkdf with sha1 private static readonly HashSet _supportedHashMethods = new HashSet() { "MD5", @@ -30,22 +34,6 @@ namespace Emby.Server.Implementations.Cryptography "System.Security.Cryptography.SHA512" }; - private RandomNumberGenerator _randomNumberGenerator; - - private bool _disposed; - - /// - /// Initializes a new instance of the class. - /// - public CryptographyProvider() - { - // FIXME: When we get DotNet Standard 2.1 we need to revisit how we do the crypto - // Currently supported hash methods from https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptoconfig?view=netcore-2.1 - // there might be a better way to autogenerate this list as dotnet updates, but I couldn't find one - // Please note the default method of PBKDF2 is not included, it cannot be used to generate hashes cleanly as it is actually a pbkdf with sha1 - _randomNumberGenerator = RandomNumberGenerator.Create(); - } - /// public string DefaultHashMethod => "PBKDF2"; @@ -101,36 +89,6 @@ namespace Emby.Server.Implementations.Cryptography /// public byte[] GenerateSalt(int length) - { - byte[] salt = new byte[length]; - _randomNumberGenerator.GetBytes(salt); - return salt; - } - - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - protected virtual void Dispose(bool disposing) - { - if (_disposed) - { - return; - } - - if (disposing) - { - _randomNumberGenerator.Dispose(); - } - - _disposed = true; - } + => RandomNumberGenerator.GetBytes(length); } } diff --git a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs index 25ef01dce..5e84255f9 100644 --- a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs +++ b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs @@ -93,13 +93,9 @@ namespace Jellyfin.Server.Implementations.Users /// public async Task StartForgotPasswordProcess(User user, bool isInNetwork) { - string pin; - using (var cryptoRandom = RandomNumberGenerator.Create()) - { - byte[] bytes = new byte[4]; - cryptoRandom.GetBytes(bytes); - pin = BitConverter.ToString(bytes); - } + byte[] bytes = new byte[4]; + RandomNumberGenerator.Fill(bytes); + string pin = BitConverter.ToString(bytes); DateTime expireTime = DateTime.UtcNow.AddMinutes(30); string filePath = _passwordResetFileBase + user.Id + ".json"; @@ -114,7 +110,6 @@ namespace Jellyfin.Server.Implementations.Users await using (FileStream fileStream = AsyncFile.OpenWrite(filePath)) { await JsonSerializer.SerializeAsync(fileStream, spr).ConfigureAwait(false); - await fileStream.FlushAsync().ConfigureAwait(false); } user.EasyPassword = pin; -- cgit v1.2.3 From d05062fec06ecba1049beefffe8d8f521d3e1881 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 8 Oct 2021 15:40:13 +0200 Subject: Use new Random.Shared instead of creating new instances --- Emby.Server.Implementations/Dto/DtoService.cs | 2 +- .../LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs | 3 +-- Jellyfin.Api/Controllers/MediaInfoController.cs | 2 +- tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs | 4 +--- 4 files changed, 4 insertions(+), 7 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 74400b512..ad76f3d6d 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -420,7 +420,7 @@ namespace Emby.Server.Implementations.Dto // Just return something so that apps that are expecting a value won't think the folders are empty if (folder is ICollectionFolder || folder is UserView) { - return new Random().Next(1, 10); + return Random.Shared.Next(1, 10); } return folder.GetChildCount(user); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index b2e555c7d..08ed1a32a 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -150,8 +150,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun if (!_lockkey.HasValue) { - var rand = new Random(); - _lockkey = (uint)rand.Next(); + _lockkey = (uint)Random.Shared.Next(); } var lockKeyValue = _lockkey.Value; diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index 96ef2d678..b422eb78c 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -316,7 +316,7 @@ namespace Jellyfin.Api.Controllers byte[] buffer = ArrayPool.Shared.Rent(size); try { - new Random().NextBytes(buffer); + Random.Shared.NextBytes(buffer); return File(buffer, MediaTypeNames.Application.Octet); } finally diff --git a/tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs index c72216d94..a73cfb078 100644 --- a/tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs +++ b/tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs @@ -5,13 +5,11 @@ namespace Jellyfin.Extensions.Tests { public static class ShuffleExtensionsTests { - private static readonly Random _rng = new Random(); - [Fact] public static void Shuffle_Valid_Correct() { byte[] original = new byte[1 << 6]; - _rng.NextBytes(original); + Random.Shared.NextBytes(original); byte[] shuffled = (byte[])original.Clone(); shuffled.Shuffle(); -- cgit v1.2.3 From a81dfabdb649b98e1a809dfee941b75637623e9e Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Sat, 9 Oct 2021 07:16:50 -0600 Subject: Fix indentation and build errors --- .../LiveTv/Listings/SchedulesDirectDtos/MapDto.cs | 2 +- .../Listings/SchedulesDirectDtos/StationDto.cs | 100 ++++++++++----------- 2 files changed, 51 insertions(+), 51 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs index 2420307b4..ffd02d474 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/MapDto.cs @@ -53,6 +53,6 @@ namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos /// Gets or sets the match type. /// [JsonPropertyName("matchType")] - public string? MatchType { get;set; } + public string? MatchType { get; set; } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs index 1b76b22e3..d797fd49b 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirectDtos/StationDto.cs @@ -5,62 +5,62 @@ using System.Text.Json.Serialization; namespace Emby.Server.Implementations.LiveTv.Listings.SchedulesDirectDtos { /// - /// Station dto. - /// - public class StationDto - { - /// - /// Gets or sets the station id. - /// - [JsonPropertyName("stationID")] - public string? StationId { get; set; } + /// Station dto. + /// + public class StationDto + { + /// + /// Gets or sets the station id. + /// + [JsonPropertyName("stationID")] + public string? StationId { get; set; } - /// - /// Gets or sets the name. - /// - [JsonPropertyName("name")] - public string? Name { get; set; } + /// + /// Gets or sets the name. + /// + [JsonPropertyName("name")] + public string? Name { get; set; } - /// - /// Gets or sets the callsign. - /// - [JsonPropertyName("callsign")] - public string? Callsign { get; set; } + /// + /// Gets or sets the callsign. + /// + [JsonPropertyName("callsign")] + public string? Callsign { get; set; } - /// - /// Gets or sets the broadcast language. - /// - [JsonPropertyName("broadcastLanguage")] - public IReadOnlyList BroadcastLanguage { get; set; } = Array.Empty(); + /// + /// Gets or sets the broadcast language. + /// + [JsonPropertyName("broadcastLanguage")] + public IReadOnlyList BroadcastLanguage { get; set; } = Array.Empty(); - /// - /// Gets or sets the description language. - /// - [JsonPropertyName("descriptionLanguage")] - public IReadOnlyList DescriptionLanguage { get; set; } = Array.Empty(); + /// + /// Gets or sets the description language. + /// + [JsonPropertyName("descriptionLanguage")] + public IReadOnlyList DescriptionLanguage { get; set; } = Array.Empty(); - /// - /// Gets or sets the broadcaster. - /// - [JsonPropertyName("broadcaster")] - public BroadcasterDto? Broadcaster { get; set; } + /// + /// Gets or sets the broadcaster. + /// + [JsonPropertyName("broadcaster")] + public BroadcasterDto? Broadcaster { get; set; } - /// - /// Gets or sets the affiliate. - /// - [JsonPropertyName("affiliate")] - public string? Affiliate { get; set; } + /// + /// Gets or sets the affiliate. + /// + [JsonPropertyName("affiliate")] + public string? Affiliate { get; set; } - /// - /// Gets or sets the logo. - /// - [JsonPropertyName("logo")] - public LogoDto? Logo { get; set; } + /// + /// Gets or sets the logo. + /// + [JsonPropertyName("logo")] + public LogoDto? Logo { get; set; } - /// - /// Gets or set a value indicating whether it is commercial free. - /// - [JsonPropertyName("isCommercialFree")] - public bool? IsCommercialFree { get; set; } - } + /// + /// Gets or sets a value indicating whether it is commercial free. + /// + [JsonPropertyName("isCommercialFree")] + public bool? IsCommercialFree { get; set; } + } } -- cgit v1.2.3 From 2b004e1f762c5e43c8321bc1aa9740d8102a0426 Mon Sep 17 00:00:00 2001 From: Dmitry Lyzo Date: Sat, 9 Oct 2021 21:36:39 +0300 Subject: Add more sorting to Latest --- Emby.Server.Implementations/Library/UserViewManager.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs index eda494815..711647e7a 100644 --- a/Emby.Server.Implementations/Library/UserViewManager.cs +++ b/Emby.Server.Implementations/Library/UserViewManager.cs @@ -355,7 +355,12 @@ namespace Emby.Server.Implementations.Library var query = new InternalItemsQuery(user) { IncludeItemTypes = includeItemTypes, - OrderBy = new[] { (ItemSortBy.DateCreated, SortOrder.Descending) }, + OrderBy = new[] + { + (ItemSortBy.DateCreated, SortOrder.Descending), + (ItemSortBy.SortName, SortOrder.Descending), + (ItemSortBy.ProductionYear, SortOrder.Descending) + }, IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null, ExcludeItemTypes = excludeItemTypes, IsVirtualItem = false, -- cgit v1.2.3 From aa93774b29193680799979c9c94bbb5ae2316a8a Mon Sep 17 00:00:00 2001 From: TheGoose Date: Sat, 9 Oct 2021 10:10:41 +0000 Subject: Translated using Weblate (English (United Kingdom)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/en_GB/ --- Emby.Server.Implementations/Localization/Core/en-GB.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/en-GB.json b/Emby.Server.Implementations/Localization/Core/en-GB.json index 8b2e8b6b1..86ce9240e 100644 --- a/Emby.Server.Implementations/Localization/Core/en-GB.json +++ b/Emby.Server.Implementations/Localization/Core/en-GB.json @@ -15,7 +15,7 @@ "Favorites": "Favourites", "Folders": "Folders", "Genres": "Genres", - "HeaderAlbumArtists": "Album Artists", + "HeaderAlbumArtists": "Artist's Album", "HeaderContinueWatching": "Continue Watching", "HeaderFavoriteAlbums": "Favourite Albums", "HeaderFavoriteArtists": "Favourite Artists", @@ -25,7 +25,7 @@ "HeaderLiveTV": "Live TV", "HeaderNextUp": "Next Up", "HeaderRecordingGroups": "Recording Groups", - "HomeVideos": "Home videos", + "HomeVideos": "Home Videos", "Inherit": "Inherit", "ItemAddedWithName": "{0} was added to the library", "ItemRemovedWithName": "{0} was removed from the library", @@ -39,7 +39,7 @@ "MixedContent": "Mixed content", "Movies": "Movies", "Music": "Music", - "MusicVideos": "Music videos", + "MusicVideos": "Music Videos", "NameInstallFailed": "{0} installation failed", "NameSeasonNumber": "Season {0}", "NameSeasonUnknown": "Season Unknown", -- cgit v1.2.3 From e3edd7ae2c7d8bc564537bca7e7b1cbf91c2713e Mon Sep 17 00:00:00 2001 From: rimasx Date: Mon, 11 Oct 2021 15:39:56 -0400 Subject: Added translation using Weblate (Estonian) --- Emby.Server.Implementations/Localization/Core/et.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 Emby.Server.Implementations/Localization/Core/et.json (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/et.json b/Emby.Server.Implementations/Localization/Core/et.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/Emby.Server.Implementations/Localization/Core/et.json @@ -0,0 +1 @@ +{} -- cgit v1.2.3 From 2b10251b32ad00290f6be00060ec6ccf47574b5d Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Tue, 12 Oct 2021 18:31:58 -0600 Subject: Update to dotnet6.rc2 --- Emby.Dlna/Emby.Dlna.csproj | 2 +- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 10 +++++----- Jellyfin.Api/Jellyfin.Api.csproj | 4 ++-- Jellyfin.Data/Jellyfin.Data.csproj | 2 +- .../Jellyfin.Server.Implementations.csproj | 8 ++++---- Jellyfin.Server/Jellyfin.Server.csproj | 8 ++++---- MediaBrowser.Common/MediaBrowser.Common.csproj | 4 ++-- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 6 +++--- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 4 ++-- MediaBrowser.Model/MediaBrowser.Model.csproj | 4 ++-- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 6 +++--- deployment/Dockerfile.centos.amd64 | 2 +- deployment/Dockerfile.fedora.amd64 | 2 +- deployment/Dockerfile.ubuntu.amd64 | 2 +- deployment/Dockerfile.ubuntu.arm64 | 2 +- deployment/Dockerfile.ubuntu.armhf | 2 +- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 4 ++-- .../Jellyfin.Server.Integration.Tests.csproj | 4 ++-- tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj | 4 ++-- 19 files changed, 40 insertions(+), 40 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index e4f30d4e0..c8332e44e 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -72,7 +72,7 @@ - + diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index dafcded08..9372cba9f 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -25,11 +25,11 @@ - - - - - + + + + + diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index cdc69618a..8a559704c 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index f1bfaa63e..2de53e7c8 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -35,7 +35,7 @@ - + diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index d9e6d794b..e26cf093b 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -19,13 +19,13 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index be2318c54..8983eb50f 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -31,10 +31,10 @@ - - - - + + + + diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index c87d58a14..9c8ce4ac5 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -19,8 +19,8 @@ - - + + diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 007355acd..d37880865 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -15,10 +15,10 @@ - - + + - + diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 22bba2366..a6caca8db 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -24,8 +24,8 @@ - - + + diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index e6a5b1711..16bc4adf8 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -30,9 +30,9 @@ - + - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 71a3554fd..15badfad7 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/deployment/Dockerfile.centos.amd64 b/deployment/Dockerfile.centos.amd64 index 178f94f71..78f051e4f 100644 --- a/deployment/Dockerfile.centos.amd64 +++ b/deployment/Dockerfile.centos.amd64 @@ -13,7 +13,7 @@ RUN yum update -yq \ && yum install -yq @buildsys-build rpmdevtools yum-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel git wget # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.fedora.amd64 b/deployment/Dockerfile.fedora.amd64 index f0f2977a4..14eeb6eed 100644 --- a/deployment/Dockerfile.fedora.amd64 +++ b/deployment/Dockerfile.fedora.amd64 @@ -12,7 +12,7 @@ RUN dnf update -yq \ && dnf install -yq @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd wget # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index fe1b4981b..8733be89c 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -17,7 +17,7 @@ RUN apt-get update -yqq \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index d984f5d89..6ae0d53cc 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -16,7 +16,7 @@ RUN apt-get update -yqq \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index c013e6797..154388148 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -16,7 +16,7 @@ RUN apt-get update -yqq \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/5fcb98bb-21e1-47a5-bb8e-bb25f41a3e52/04811d5d05b7e694f040d2a13c1aae4c/dotnet-sdk-6.0.100-rc.1.21463.6-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 8b581857f..922b3d94f 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 38687ae61..9d7b447ed 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index db24df240..67ae0e080 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -10,8 +10,8 @@ - - + + -- cgit v1.2.3 From e88e1fa8e9aa49323f4b55fd8cc6185cd9fb9059 Mon Sep 17 00:00:00 2001 From: JULIAN AUGUSTO RUIZ MARTINEZ Date: Wed, 13 Oct 2021 19:30:04 +0000 Subject: Translated using Weblate (Pirate) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pr/ --- Emby.Server.Implementations/Localization/Core/pr.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/pr.json b/Emby.Server.Implementations/Localization/Core/pr.json index 0967ef424..e3a3bfaf1 100644 --- a/Emby.Server.Implementations/Localization/Core/pr.json +++ b/Emby.Server.Implementations/Localization/Core/pr.json @@ -1 +1,5 @@ -{} +{ + "Books": "Libros", + "AuthenticationSucceededWithUserName": "{0} autentificado correctamente", + "Artists": "Artistas" +} -- cgit v1.2.3 From a720b12ec33f3b3d9dc1121d71f929a739a70012 Mon Sep 17 00:00:00 2001 From: lyaschuchenko Date: Tue, 12 Oct 2021 14:24:18 +0000 Subject: Translated using Weblate (Ukrainian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/uk/ --- Emby.Server.Implementations/Localization/Core/uk.json | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/uk.json b/Emby.Server.Implementations/Localization/Core/uk.json index 5a2069df5..e99ed6f0b 100644 --- a/Emby.Server.Implementations/Localization/Core/uk.json +++ b/Emby.Server.Implementations/Localization/Core/uk.json @@ -1,5 +1,5 @@ { - "MusicVideos": "Музичні відеокліпи", + "MusicVideos": "Відеокліпи", "Music": "Музика", "Movies": "Фільми", "MessageApplicationUpdatedTo": "Jellyfin Server оновлено до версії {0}", @@ -16,7 +16,7 @@ "HeaderFavoriteArtists": "Улюблені виконавці", "HeaderFavoriteAlbums": "Улюблені альбоми", "HeaderContinueWatching": "Продовжити перегляд", - "HeaderAlbumArtists": "Виконавці альбому", + "HeaderAlbumArtists": "Виконавці альбомів", "Genres": "Жанри", "Folders": "Каталоги", "Favorites": "Улюблені", @@ -38,7 +38,7 @@ "NotificationOptionPluginInstalled": "Плагін встановлено", "NotificationOptionPluginError": "Помилка плагіна", "NotificationOptionNewLibraryContent": "Додано новий контент", - "HomeVideos": "Домашнє відео", + "HomeVideos": "Мої відео", "FailedLoginAttemptWithUserName": "Невдала спроба входу від {0}", "LabelRunningTimeValue": "Тривалість: {0}", "TaskDownloadMissingSubtitlesDescription": "Шукає в Інтернеті відсутні субтитри на основі конфігурації метаданих.", @@ -117,5 +117,7 @@ "TaskCleanActivityLogDescription": "Видаляє старші за встановлений термін записи з журналу активності.", "TaskCleanActivityLog": "Очистити журнал активності", "Undefined": "Не визначено", - "Default": "За замовчуванням" + "Default": "За замовчуванням", + "TaskOptimizeDatabase": "Оптимізувати базу даних", + "TaskOptimizeDatabaseDescription": "Стиснення бази даних та збільшення вільного простору. Виконання цього завдання після сканування бібліотеки або внесення інших змін, які передбачають модифікацію бази даних, може покращити продуктивність." } -- cgit v1.2.3 From 6cc4be85fc6362b2f0552b315ff73dbad686eccd Mon Sep 17 00:00:00 2001 From: rimasx Date: Wed, 13 Oct 2021 13:54:46 +0000 Subject: Translated using Weblate (Estonian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/et/ --- .../Localization/Core/et.json | 119 ++++++++++++++++++++- 1 file changed, 118 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/et.json b/Emby.Server.Implementations/Localization/Core/et.json index 0967ef424..3e57d96ca 100644 --- a/Emby.Server.Implementations/Localization/Core/et.json +++ b/Emby.Server.Implementations/Localization/Core/et.json @@ -1 +1,118 @@ -{} +{ + "TaskCleanActivityLogDescription": "Kustutab määratud ajast vanemad tegevuslogi kirjed.", + "UserDownloadingItemWithValues": "{0} laeb alla {1}", + "HeaderRecordingGroups": "Salvestusrühmad", + "TaskOptimizeDatabaseDescription": "Tihendab ja puhastab andmebaasi. Selle toimingu tegemine pärast meediakogu andmebaasiga seotud muudatuste skannimist võib jõudlust parandada.", + "TaskOptimizeDatabase": "Optimeeri andmebaasi", + "TaskDownloadMissingSubtitlesDescription": "Otsib veebist puuduvaid subtiitreid vastavalt määratud metaandmete seadetele.", + "TaskDownloadMissingSubtitles": "Laadi alla puuduvad subtiitrid", + "TaskRefreshChannelsDescription": "Värskendab veebikanalite teavet.", + "TaskRefreshChannels": "Värskenda kanaleid", + "TaskCleanTranscodeDescription": "Kustutab üle ühe päeva vanused transkodeerimisfailid.", + "TaskCleanTranscode": "Puhasta transkoodimise kataloog", + "TaskUpdatePluginsDescription": "Laadib alla ja paigaldab nende pluginate uuendused, mis on seadistatud automaatselt uuenduma.", + "TaskUpdatePlugins": "Uuenda pluginaid", + "TaskRefreshPeopleDescription": "Värskendab meediakogus näitlejate ja režissööride metaandmeid.", + "TaskRefreshPeople": "Värskenda inimesi", + "TaskCleanLogsDescription": "Kustutab logifailid, mis on vanemad kui {0} päeva.", + "TaskCleanLogs": "Puhasta logikataloog", + "TaskRefreshLibraryDescription": "Otsib meedikogust uusi faile ja värskendab metaandmeid.", + "Collections": "Kollektsioonid", + "TaskRefreshLibrary": "Skaneeri meediakogu", + "TaskRefreshChapterImagesDescription": "Loob peatükkidega videote jaoks pisipildid.", + "TaskRefreshChapterImages": "Eralda peatükipildid", + "TaskCleanCacheDescription": "Kustutab vahemälufailid, mida süsteem enam ei vaja.", + "TaskCleanCache": "Puhasta vahemälu kataloog", + "TaskCleanActivityLog": "Puhasta tegevuslogi", + "TasksChannelsCategory": "Veebikanalid", + "TasksApplicationCategory": "Rakendus", + "TasksLibraryCategory": "Meediakogu", + "TasksMaintenanceCategory": "Hooldus", + "VersionNumber": "Versioon {0}", + "ValueSpecialEpisodeName": "Eriepisood - {0}", + "ValueHasBeenAddedToLibrary": "{0} lisati meediakogusse", + "UserStartedPlayingItemWithValues": "{0} taasesitab {1} serveris {2}", + "UserPasswordChangedWithName": "Kasutaja {0} parooli on muudetud", + "UserLockedOutWithName": "Kasutaja {0} on lukustatud", + "UserDeletedWithName": "Kasutaja {0} on kustutatud", + "UserCreatedWithName": "Kasutaja {0} on loodud", + "ScheduledTaskStartedWithName": "{0} käivitati", + "ProviderValue": "Allikas: {0}", + "StartupEmbyServerIsLoading": "Jellyfin server laadib. Proovi varsti uuesti.", + "User": "Kasutaja", + "Undefined": "Määratlemata", + "TvShows": "Seriaalid", + "System": "Süsteem", + "Sync": "Sünkrooni", + "Songs": "Laulud", + "Shows": "Seriaalid", + "ServerNameNeedsToBeRestarted": "{0} tuleb taaskäivitada", + "ScheduledTaskFailedWithName": "{0} nurjus", + "PluginUpdatedWithName": "{0} uuendati", + "PluginUninstalledWithName": "{0} eemaldati", + "PluginInstalledWithName": "{0} paigaldati", + "Plugin": "Plugin", + "Playlists": "Pleilistid", + "Photos": "Fotod", + "NotificationOptionVideoPlaybackStopped": "Video taasesitus on peatatud", + "NotificationOptionVideoPlayback": "Video taasesitus algas", + "NotificationOptionUserLockedOut": "Kasutaja on lukustatud", + "NotificationOptionTaskFailed": "Ajastatud ülesanne nurjus", + "NotificationOptionServerRestartRequired": "Vajalik on serveri taaskäivitamine", + "NotificationOptionPluginUpdateInstalled": "Paigaldati plugina uuendus", + "NotificationOptionPluginUninstalled": "Plugin eemaldati", + "NotificationOptionPluginInstalled": "Plugin paigaldati", + "NotificationOptionPluginError": "Plugina tõrge", + "NotificationOptionNewLibraryContent": "Lisati uut sisu", + "NotificationOptionInstallationFailed": "Paigaldamine nurjus", + "NotificationOptionCameraImageUploaded": "Kaamera pilt on üles laaditud", + "NotificationOptionAudioPlaybackStopped": "Heli taasesitus peatati", + "NotificationOptionAudioPlayback": "Heli taasesitus algas", + "NotificationOptionApplicationUpdateInstalled": "Rakenduse uuendus paigaldati", + "NotificationOptionApplicationUpdateAvailable": "Rakenduse uuendus on saadaval", + "NewVersionIsAvailable": "Jellyfin serveri uus versioon on allalaadimiseks saadaval.", + "NameSeasonUnknown": "Tundmatu hooaeg", + "NameSeasonNumber": "Hooaeg {0}", + "NameInstallFailed": "{0} paigaldamine nurjus", + "MusicVideos": "Muusikavideod", + "Music": "Muusika", + "Movies": "Filmid", + "MixedContent": "Segatud sisu", + "MessageServerConfigurationUpdated": "Serveri seadistust uuendati", + "MessageNamedServerConfigurationUpdatedWithValue": "Serveri seadistusosa {0} uuendati", + "MessageApplicationUpdatedTo": "Jellyfin server uuendati versioonile {0}", + "MessageApplicationUpdated": "Jellyfin server uuendati", + "Latest": "Uusimad", + "LabelRunningTimeValue": "Kestus: {0}", + "LabelIpAddressValue": "IP aadress: {0}", + "ItemRemovedWithName": "{0} eemaldati meediakogust", + "ItemAddedWithName": "{0} lisati meediakogusse", + "Inherit": "Päri", + "HomeVideos": "Koduvideod", + "HeaderNextUp": "Järgmisena", + "HeaderLiveTV": "Otse TV", + "HeaderFavoriteSongs": "Lemmiklood", + "HeaderFavoriteShows": "Lemmikseriaalid", + "HeaderFavoriteEpisodes": "Lemmikepisoodid", + "HeaderFavoriteArtists": "Lemmikesitajad", + "HeaderFavoriteAlbums": "Lemmikalbumid", + "HeaderContinueWatching": "Jätka vaatamist", + "HeaderAlbumArtists": "Albumi esitaja", + "Genres": "Žanrid", + "Forced": "Sunnitud", + "Folders": "Kaustad", + "Favorites": "Lemmikud", + "FailedLoginAttemptWithUserName": "Ebaõnnestunud sisselogimiskatse kasutajalt {0}", + "DeviceOnlineWithName": "{0} on ühendatud", + "DeviceOfflineWithName": "{0} katkestas ühenduse", + "Default": "Vaikimisi", + "ChapterNameValue": "Peatükk {0}", + "Channels": "Kanalid", + "CameraImageUploadedFrom": "Uus kaamera pilt laaditi üles allikalt {0}", + "Books": "Raamatud", + "AuthenticationSucceededWithUserName": "{0} autentimine õnnestus", + "Artists": "Esitajad", + "Application": "Rakendus", + "AppDeviceValues": "Rakendus: {0}, seade: {1}", + "Albums": "Albumid" +} -- cgit v1.2.3 From b084afa1a04dd97bd5e9ffbae50e8d4848eec259 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Oct 2021 12:01:09 +0000 Subject: Bump prometheus-net.DotNetRuntime from 4.2.1 to 4.2.2 Bumps [prometheus-net.DotNetRuntime](https://github.com/djluck/prometheus-net.DotNetRuntime) from 4.2.1 to 4.2.2. - [Release notes](https://github.com/djluck/prometheus-net.DotNetRuntime/releases) - [Commits](https://github.com/djluck/prometheus-net.DotNetRuntime/compare/4.2.1...4.2.2) --- updated-dependencies: - dependency-name: prometheus-net.DotNetRuntime dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 9372cba9f..c1ce4b557 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -31,7 +31,7 @@ - + -- cgit v1.2.3 From dd0c1d3d27b455cc73d03bcc48becef298404dee Mon Sep 17 00:00:00 2001 From: Jessica Date: Mon, 18 Oct 2021 14:01:33 -0400 Subject: Added translation using Weblate (Welsh) --- Emby.Server.Implementations/Localization/Core/cy.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 Emby.Server.Implementations/Localization/Core/cy.json (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/cy.json b/Emby.Server.Implementations/Localization/Core/cy.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/Emby.Server.Implementations/Localization/Core/cy.json @@ -0,0 +1 @@ +{} -- cgit v1.2.3 From 4d324707157d444efa43c21869f73b8378901dd3 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Mon, 18 Oct 2021 13:39:48 +0000 Subject: Translated using Weblate (Esperanto) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/ --- Emby.Server.Implementations/Localization/Core/eo.json | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/eo.json b/Emby.Server.Implementations/Localization/Core/eo.json index ca615cc8c..a6516a130 100644 --- a/Emby.Server.Implementations/Localization/Core/eo.json +++ b/Emby.Server.Implementations/Localization/Core/eo.json @@ -1,17 +1,17 @@ { "NotificationOptionInstallationFailed": "Instalada fiasko", - "NotificationOptionAudioPlaybackStopped": "Sono de ludado haltis", + "NotificationOptionAudioPlaybackStopped": "Ludado de sono haltis", "NotificationOptionAudioPlayback": "Ludado de sono startis", "NameSeasonUnknown": "Sezono Nekonata", "NameSeasonNumber": "Sezono {0}", "NameInstallFailed": "{0} instalado fiaskis", "Music": "Muziko", "Movies": "Filmoj", - "ItemRemovedWithName": "{0} forigis el la biblioteko", - "ItemAddedWithName": "{0} aldonis al la biblioteko", + "ItemRemovedWithName": "{0} forigis el la libraro", + "ItemAddedWithName": "{0} aldonis al la libraro", "HeaderLiveTV": "Viva Televido", "HeaderContinueWatching": "Daŭrigi Spektado", - "HeaderAlbumArtists": "Artistoj de Albumo", + "HeaderAlbumArtists": "Albumo de artisto", "Folders": "Dosierujoj", "DeviceOnlineWithName": "{0} estas konektita", "Default": "Defaŭlte", @@ -30,7 +30,7 @@ "User": "Uzanto", "System": "Sistemo", "Songs": "Kantoj", - "ScheduledTaskStartedWithName": "{0} komencis", + "ScheduledTaskStartedWithName": "{0} startis", "ScheduledTaskFailedWithName": "{0} malsukcesis", "PluginUninstalledWithName": "{0} malinstaliĝis", "PluginInstalledWithName": "{0} instaliĝis", @@ -43,5 +43,10 @@ "MusicVideos": "Muzikvideoj", "LabelIpAddressValue": "IP-adreso: {0}", "Genres": "Ĝenroj", - "DeviceOfflineWithName": "{0} malkonektis" + "DeviceOfflineWithName": "{0} malkonektis", + "HeaderFavoriteArtists": "Favorataj Artistoj", + "Shows": "Serioj", + "HeaderFavoriteShows": "Favorataj Serioj", + "TvShows": "TV-serioj", + "Favorites": "Favoratoj" } -- cgit v1.2.3 From 8388f7c462d50065a931a42ff2c7b34a0d7e1c34 Mon Sep 17 00:00:00 2001 From: Jessica Date: Mon, 18 Oct 2021 18:19:17 +0000 Subject: Translated using Weblate (Welsh) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/cy/ --- Emby.Server.Implementations/Localization/Core/cy.json | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/cy.json b/Emby.Server.Implementations/Localization/Core/cy.json index 0967ef424..0fa72dea4 100644 --- a/Emby.Server.Implementations/Localization/Core/cy.json +++ b/Emby.Server.Implementations/Localization/Core/cy.json @@ -1 +1,14 @@ -{} +{ + "DeviceOnlineWithName": "Mae {0} wedi'i gysylltu", + "DeviceOfflineWithName": "Mae {0} wedi datgysylltu", + "Default": "Diofyn", + "Collections": "Casgliadau", + "ChapterNameValue": "Pennod {0}", + "Channels": "Sianeli", + "CameraImageUploadedFrom": "Mae delwedd camera newydd wedi'i lanlwytho o {0}", + "Books": "Llyfrau", + "AuthenticationSucceededWithUserName": "{0} wedi’i ddilysu’n llwyddiannus", + "Artists": "Artistiaid", + "AppDeviceValues": "Ap: {0}, Dyfais: {1}", + "Albums": "Albwmau" +} -- cgit v1.2.3 From 7d8fb947b65638c41a9f6475306a1b81c577f089 Mon Sep 17 00:00:00 2001 From: "Sindre S. Kjær" Date: Tue, 19 Oct 2021 19:19:17 +0000 Subject: Translated using Weblate (Norwegian Bokmål) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/nb_NO/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Emby.Server.Implementations/Localization/Core/nb.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/nb.json b/Emby.Server.Implementations/Localization/Core/nb.json index 81c1eefe7..317bdcfcb 100644 --- a/Emby.Server.Implementations/Localization/Core/nb.json +++ b/Emby.Server.Implementations/Localization/Core/nb.json @@ -119,5 +119,6 @@ "Forced": "Tvunget", "Default": "Standard", "TaskCleanActivityLogDescription": "Sletter oppføringer i aktivitetsloggen som er eldre enn den konfigurerte alderen.", - "TaskOptimizeDatabase": "Optimiser database" + "TaskOptimizeDatabase": "Optimiser database", + "TaskOptimizeDatabaseDescription": "Komprimerer database og frigjør plass. Denne prosessen kan forbedre ytelsen etter skanning av bibliotek eller andre handlinger som fører til databaseendringer." } -- cgit v1.2.3 From b53dea7113726c052a13e3cfa309730787db22cb Mon Sep 17 00:00:00 2001 From: WWWesten Date: Thu, 21 Oct 2021 11:21:38 +0000 Subject: Translated using Weblate (Esperanto) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/ --- .../Localization/Core/eo.json | 27 ++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/eo.json b/Emby.Server.Implementations/Localization/Core/eo.json index a6516a130..e04f3c241 100644 --- a/Emby.Server.Implementations/Localization/Core/eo.json +++ b/Emby.Server.Implementations/Localization/Core/eo.json @@ -10,7 +10,7 @@ "ItemRemovedWithName": "{0} forigis el la libraro", "ItemAddedWithName": "{0} aldonis al la libraro", "HeaderLiveTV": "Viva Televido", - "HeaderContinueWatching": "Daŭrigi Spektado", + "HeaderContinueWatching": "Daŭrigi Spektadon", "HeaderAlbumArtists": "Albumo de artisto", "Folders": "Dosierujoj", "DeviceOnlineWithName": "{0} estas konektita", @@ -48,5 +48,28 @@ "Shows": "Serioj", "HeaderFavoriteShows": "Favorataj Serioj", "TvShows": "TV-serioj", - "Favorites": "Favoratoj" + "Favorites": "Favoratoj", + "TaskCleanLogs": "Purigi Ĵurnalan Katalogon", + "TaskRefreshLibrary": "Skanu Plurmedian Libraron", + "ValueSpecialEpisodeName": "Speciala - {0}", + "TaskOptimizeDatabase": "Optimigi datumbazon", + "TaskRefreshChannels": "Refreŝigi Kanalojn", + "TaskUpdatePlugins": "Ĝisdatigi Kromprogramojn", + "TaskRefreshPeople": "Refreŝigi Homojn", + "TasksChannelsCategory": "Interretaj Kanaloj", + "ProviderValue": "Provizanto: {0}", + "NotificationOptionPluginError": "Kromprograma malsukceso", + "MixedContent": "Miksita enhavo", + "TasksApplicationCategory": "Aplikaĵo", + "TasksMaintenanceCategory": "Prizorgado", + "Undefined": "Nedifinita", + "Sync": "Sinkronigo", + "Latest": "Plej novaj", + "Inherit": "Hereda", + "HomeVideos": "Hejmaj Videoj", + "HeaderNextUp": "Sekva Plue", + "HeaderFavoriteSongs": "Favorataj Kantoj", + "HeaderFavoriteEpisodes": "Favorataj Epizodoj", + "HeaderFavoriteAlbums": "Favorataj Albumoj", + "Forced": "Forcita" } -- cgit v1.2.3 From 1e69530752d52af9e091d5325a7bd01d125cbe25 Mon Sep 17 00:00:00 2001 From: rimasx Date: Wed, 20 Oct 2021 04:30:06 +0000 Subject: Translated using Weblate (Estonian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/et/ --- Emby.Server.Implementations/Localization/Core/et.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/et.json b/Emby.Server.Implementations/Localization/Core/et.json index 3e57d96ca..c3596ecf1 100644 --- a/Emby.Server.Implementations/Localization/Core/et.json +++ b/Emby.Server.Implementations/Localization/Core/et.json @@ -45,7 +45,7 @@ "System": "Süsteem", "Sync": "Sünkrooni", "Songs": "Laulud", - "Shows": "Seriaalid", + "Shows": "Sarjad", "ServerNameNeedsToBeRestarted": "{0} tuleb taaskäivitada", "ScheduledTaskFailedWithName": "{0} nurjus", "PluginUpdatedWithName": "{0} uuendati", -- cgit v1.2.3 From d4c1912e64f5e9d82f2106f1c9ca47d6addf16fa Mon Sep 17 00:00:00 2001 From: WWWesten Date: Sat, 23 Oct 2021 10:15:08 +0000 Subject: Translated using Weblate (Esperanto) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/ --- .../Localization/Core/eo.json | 56 ++++++++++++++++++++-- 1 file changed, 52 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/eo.json b/Emby.Server.Implementations/Localization/Core/eo.json index e04f3c241..7ce87502c 100644 --- a/Emby.Server.Implementations/Localization/Core/eo.json +++ b/Emby.Server.Implementations/Localization/Core/eo.json @@ -1,7 +1,7 @@ { "NotificationOptionInstallationFailed": "Instalada fiasko", "NotificationOptionAudioPlaybackStopped": "Ludado de sono haltis", - "NotificationOptionAudioPlayback": "Ludado de sono startis", + "NotificationOptionAudioPlayback": "Ludado de sono lanĉis", "NameSeasonUnknown": "Sezono Nekonata", "NameSeasonNumber": "Sezono {0}", "NameInstallFailed": "{0} instalado fiaskis", @@ -9,7 +9,7 @@ "Movies": "Filmoj", "ItemRemovedWithName": "{0} forigis el la libraro", "ItemAddedWithName": "{0} aldonis al la libraro", - "HeaderLiveTV": "Viva Televido", + "HeaderLiveTV": "TV-etero", "HeaderContinueWatching": "Daŭrigi Spektadon", "HeaderAlbumArtists": "Albumo de artisto", "Folders": "Dosierujoj", @@ -30,7 +30,7 @@ "User": "Uzanto", "System": "Sistemo", "Songs": "Kantoj", - "ScheduledTaskStartedWithName": "{0} startis", + "ScheduledTaskStartedWithName": "{0} lanĉis", "ScheduledTaskFailedWithName": "{0} malsukcesis", "PluginUninstalledWithName": "{0} malinstaliĝis", "PluginInstalledWithName": "{0} instaliĝis", @@ -71,5 +71,53 @@ "HeaderFavoriteSongs": "Favorataj Kantoj", "HeaderFavoriteEpisodes": "Favorataj Epizodoj", "HeaderFavoriteAlbums": "Favorataj Albumoj", - "Forced": "Forcita" + "Forced": "Forcita", + "ServerNameNeedsToBeRestarted": "{0} devas esti relanĉita", + "NotificationOptionVideoPlayback": "La videoludado lanĉis", + "NotificationOptionServerRestartRequired": "Servila relanĉigo bezonata", + "TaskOptimizeDatabaseDescription": "Kompaktigas datenbazon kaj trunkas liberan lokon. Lanĉi ĉi tiun taskon post la librara skanado aŭ fari aliajn ŝanĝojn, kiuj implicas datenbazajn modifojn, povus plibonigi rendimenton.", + "TaskUpdatePluginsDescription": "Elŝutas kaj instalas ĝisdatigojn por kromprogramojn, kiuj estas agorditaj por ĝisdatigi aŭtomate.", + "TaskDownloadMissingSubtitlesDescription": "Serĉas en interreto mankantajn subtekstojn surbaze de metadatena agordaro.", + "TaskRefreshPeopleDescription": "Ĝisdatigas metadatenojn por aktoroj kaj reĵisoroj en via plurmedia libraro.", + "TaskCleanLogsDescription": "Forigas ĵurnalajn dosierojn aĝajn pli ol {0} tagojn.", + "TaskRefreshLibraryDescription": "Skanas vian plurmedian libraron por novaj dosieroj kaj refreŝigas metadatenaron.", + "NewVersionIsAvailable": "Nova versio de Jellyfin Server estas elŝutebla.", + "TaskCleanCacheDescription": "Forigas stapla dosierojn ne plu necesajn de la sistemo.", + "TaskCleanActivityLogDescription": "Forigas aktivecan ĵurnalaĵojn pli malnovajn ol la agordita aĝo.", + "TaskCleanTranscodeDescription": "Forigas transkodajn dosierojn aĝajn pli ol unu tagon.", + "ValueHasBeenAddedToLibrary": "{0} estis aldonita al via plurmedia libraro", + "SubtitleDownloadFailureFromForItem": "Subtekstoj malsukcesis elŝuti de {0} por {1}", + "StartupEmbyServerIsLoading": "Jellyfin Server ŝarĝas. Provi denove baldaŭ.", + "TaskRefreshChapterImagesDescription": "Kreas bildetojn por videoj kiuj havas ĉapitrojn.", + "UserStoppedPlayingItemWithValues": "{0} finis ludi {1} ĉe {2}", + "UserPolicyUpdatedWithName": "Uzanta politiko estis ĝisdatigita por {0}", + "UserPasswordChangedWithName": "Pasvorto estis ŝanĝita por uzanto {0}", + "UserStartedPlayingItemWithValues": "{0} ludas {1} ĉe {2}", + "UserLockedOutWithName": "Uzanto {0} estas elŝlosita", + "UserOnlineFromDevice": "{0} estas enreta de {1}", + "UserOfflineFromDevice": "{0} malkonektis de {1}", + "UserDeletedWithName": "Uzanto {0} estis forigita", + "MessageServerConfigurationUpdated": "Servila agordaro estis ĝisdatigita", + "MessageNamedServerConfigurationUpdatedWithValue": "Servila agorda sekcio {0} estis ĝisdatigita", + "MessageApplicationUpdatedTo": "Jellyfin Server estis ĝisdatigita al {0}", + "MessageApplicationUpdated": "Jellyfin Server estis ĝisdatigita", + "TaskRefreshChannelsDescription": "Refreŝigas informon pri interretaj kanaloj.", + "TaskDownloadMissingSubtitles": "Elŝutu mankantajn subtekstojn", + "TaskCleanTranscode": "Malplenigi Transkodadan Katalogon", + "TaskRefreshChapterImages": "Eltiru Ĉapitro-Bildojn", + "TaskCleanCache": "Malplenigi Staplan Katalogon", + "TaskCleanActivityLog": "Malplenigi Aktivecan Ĵurnalon", + "PluginUpdatedWithName": "{0} estis ĝisdatigita", + "NotificationOptionVideoPlaybackStopped": "La videoludado haltis", + "NotificationOptionUserLockedOut": "Uzanto ŝlosita", + "NotificationOptionTaskFailed": "Planita tasko malsukcesis", + "NotificationOptionPluginUpdateInstalled": "Ĝisdatigo de kromprogramo instalita", + "NotificationOptionCameraImageUploaded": "Kamera bildo alŝutita", + "NotificationOptionApplicationUpdateInstalled": "Aplikaĵa ĝisdatigo instalita", + "NotificationOptionApplicationUpdateAvailable": "Ĝisdatigo de aplikaĵo havebla", + "LabelRunningTimeValue": "Ludada tempo: {0}", + "HeaderRecordingGroups": "Rikordadaj Grupoj", + "FailedLoginAttemptWithUserName": "Malsukcesa ensaluta provo de {0}", + "CameraImageUploadedFrom": "Nova kamera bildo estis alŝutita de {0}", + "AuthenticationSucceededWithUserName": "{0} sukcese aŭtentikigis" } -- cgit v1.2.3 From f2656b7ee2ea9c395a796d2117ffe445a26d7603 Mon Sep 17 00:00:00 2001 From: ButterflyOfFire Date: Sat, 23 Oct 2021 11:25:19 +0000 Subject: Translated using Weblate (Arabic) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/ --- Emby.Server.Implementations/Localization/Core/ar.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/ar.json b/Emby.Server.Implementations/Localization/Core/ar.json index 5a4a4d5a9..ee70aa8d8 100644 --- a/Emby.Server.Implementations/Localization/Core/ar.json +++ b/Emby.Server.Implementations/Localization/Core/ar.json @@ -15,7 +15,7 @@ "Favorites": "المفضلة", "Folders": "المجلدات", "Genres": "التضنيفات", - "HeaderAlbumArtists": "فناني الألبومات", + "HeaderAlbumArtists": "ألبوم الفنان", "HeaderContinueWatching": "استئناف", "HeaderFavoriteAlbums": "الألبومات المفضلة", "HeaderFavoriteArtists": "الفنانون المفضلون", @@ -25,7 +25,7 @@ "HeaderLiveTV": "التلفاز المباشر", "HeaderNextUp": "التالي", "HeaderRecordingGroups": "مجموعات التسجيل", - "HomeVideos": "الفيديوهات المنزلية", + "HomeVideos": "الفيديوهات الشخصية", "Inherit": "توريث", "ItemAddedWithName": "تم إضافة {0} للمكتبة", "ItemRemovedWithName": "تم إزالة {0} من المكتبة", -- cgit v1.2.3 From b830d38a347fd045e0a8573e69180dd5d296fdd9 Mon Sep 17 00:00:00 2001 From: Roel van Uden <> Date: Tue, 26 Oct 2021 12:59:11 +0200 Subject: Rework subtitle selection to reduce code clutter --- .../Library/MediaStreamSelector.cs | 49 +++++++--------------- 1 file changed, 15 insertions(+), 34 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/MediaStreamSelector.cs b/Emby.Server.Implementations/Library/MediaStreamSelector.cs index 71e3404d0..f94eeda8f 100644 --- a/Emby.Server.Implementations/Library/MediaStreamSelector.cs +++ b/Emby.Server.Implementations/Library/MediaStreamSelector.cs @@ -38,14 +38,11 @@ namespace Emby.Server.Implementations.Library } public static int? GetDefaultSubtitleStreamIndex( - List streams, + IEnumerable streams, string[] preferredLanguages, SubtitlePlaybackMode mode, string audioTrackLanguage) { - streams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages) - .ToList(); - MediaStream stream = null; if (mode == SubtitlePlaybackMode.None) @@ -53,62 +50,46 @@ namespace Emby.Server.Implementations.Library return null; } + var sortedStreams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages) + .OrderByDescending(x => x.IsExternal) + .ThenByDescending(x => x.IsForced && string.Equals(x.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) + .ThenByDescending(x => x.IsForced) + .ThenByDescending(x => x.IsDefault) + .ToList(); + if (mode == SubtitlePlaybackMode.Default) { // Prefer embedded metadata over smart logic - - stream = streams.FirstOrDefault(s => s.IsExternal && s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ?? - streams.FirstOrDefault(s => s.IsExternal && s.IsForced) ?? - streams.FirstOrDefault(s => s.IsExternal && s.IsDefault) ?? - streams.FirstOrDefault(s => s.IsExternal) ?? - streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ?? - streams.FirstOrDefault(s => s.IsForced) ?? - streams.FirstOrDefault(s => s.IsDefault); + stream = sortedStreams.FirstOrDefault(s => s.IsExternal || s.IsForced || s.IsDefault); // if the audio language is not understood by the user, load their preferred subs, if there are any if (stream == null && !preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase)) { - stream = streams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)); + stream = sortedStreams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)); } } else if (mode == SubtitlePlaybackMode.Smart) { - // Prefer smart logic over embedded metadata - // if the audio language is not understood by the user, load their preferred subs, if there are any if (!preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase)) { - stream = streams.FirstOrDefault(s => s.IsExternal && !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)) ?? - streams.FirstOrDefault(s => s.IsExternal && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)) ?? - streams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)) ?? - streams.FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)); + stream = sortedStreams.FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)); } } else if (mode == SubtitlePlaybackMode.Always) { // always load the most suitable full subtitles - stream = streams.FirstOrDefault(s => s.IsExternal && !s.IsForced) ?? - streams.FirstOrDefault(s => !s.IsForced); + stream = sortedStreams.FirstOrDefault(s => !s.IsForced); } else if (mode == SubtitlePlaybackMode.OnlyForced) { // always load the most suitable full subtitles - stream = streams.FirstOrDefault(s => s.IsExternal && s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ?? - streams.FirstOrDefault(s => s.IsExternal && s.IsForced) ?? - streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ?? - streams.FirstOrDefault(s => s.IsForced); + stream = sortedStreams.FirstOrDefault(x => x.IsForced); } // load forced subs if we have found no suitable full subtitles - stream ??= streams.FirstOrDefault(s => s.IsExternal && s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) ?? - streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)); - - if (stream != null) - { - return stream.Index; - } - - return null; + stream ??= sortedStreams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)); + return stream?.Index; } private static IEnumerable GetSortedStreams(IEnumerable streams, MediaStreamType type, string[] languagePreferences) -- cgit v1.2.3 From 1b6eb2ff2d2cc3973fa529c721cf50e3ad849646 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 26 Oct 2021 13:56:30 +0200 Subject: Enable nullable for more files --- Emby.Server.Implementations/Channels/ChannelManager.cs | 4 +--- Jellyfin.Server.Implementations/Users/UserManager.cs | 6 +----- MediaBrowser.Model/Channels/ChannelFeatures.cs | 8 +++++--- MediaBrowser.Model/Channels/ChannelQuery.cs | 5 ++--- .../Configuration/BaseApplicationConfiguration.cs | 7 +++---- MediaBrowser.Model/Configuration/LibraryOptions.cs | 13 ++++++------- MediaBrowser.Model/Configuration/UserConfiguration.cs | 5 ++--- MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs | 3 +-- MediaBrowser.Model/Dlna/DeviceIdentification.cs | 1 - MediaBrowser.Model/Dlna/ITranscoderSupport.cs | 1 - MediaBrowser.Model/Users/PinRedeemResult.cs | 5 +++-- 11 files changed, 24 insertions(+), 34 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 178f30de0..09aee602a 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -586,7 +586,7 @@ namespace Emby.Server.Implementations.Channels { var supportsLatest = provider is ISupportsLatestMedia; - return new ChannelFeatures + return new ChannelFeatures(channel.Name, channel.Id) { CanFilter = !features.MaxPageSize.HasValue, CanSearch = provider is ISearchableChannel, @@ -596,8 +596,6 @@ namespace Emby.Server.Implementations.Channels MediaTypes = features.MediaTypes.ToArray(), SupportsSortOrderToggle = features.SupportsSortOrderToggle, SupportsLatestMedia = supportsLatest, - Name = channel.Name, - Id = channel.Id.ToString("N", CultureInfo.InvariantCulture), SupportsContentDownloading = features.SupportsContentDownloading, AutoRefreshLevels = features.AutoRefreshLevels }; diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 704a6a84e..8ca6e8d21 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -530,11 +530,7 @@ namespace Jellyfin.Server.Implementations.Users } } - return new PinRedeemResult - { - Success = false, - UsersReset = Array.Empty() - }; + return new PinRedeemResult(); } /// diff --git a/MediaBrowser.Model/Channels/ChannelFeatures.cs b/MediaBrowser.Model/Channels/ChannelFeatures.cs index d925b78b6..1ca8e80a6 100644 --- a/MediaBrowser.Model/Channels/ChannelFeatures.cs +++ b/MediaBrowser.Model/Channels/ChannelFeatures.cs @@ -1,4 +1,3 @@ -#nullable disable #pragma warning disable CS1591 using System; @@ -7,11 +6,14 @@ namespace MediaBrowser.Model.Channels { public class ChannelFeatures { - public ChannelFeatures() + public ChannelFeatures(string name, Guid id) { MediaTypes = Array.Empty(); ContentTypes = Array.Empty(); DefaultSortFields = Array.Empty(); + + Name = name; + Id = id; } /// @@ -24,7 +26,7 @@ namespace MediaBrowser.Model.Channels /// Gets or sets the identifier. /// /// The identifier. - public string Id { get; set; } + public Guid Id { get; set; } /// /// Gets or sets a value indicating whether this instance can search. diff --git a/MediaBrowser.Model/Channels/ChannelQuery.cs b/MediaBrowser.Model/Channels/ChannelQuery.cs index 59966127f..f9380ce3a 100644 --- a/MediaBrowser.Model/Channels/ChannelQuery.cs +++ b/MediaBrowser.Model/Channels/ChannelQuery.cs @@ -1,4 +1,3 @@ -#nullable disable #pragma warning disable CS1591 using System; @@ -13,13 +12,13 @@ namespace MediaBrowser.Model.Channels /// Gets or sets the fields to return within the items, in addition to basic information. /// /// The fields. - public ItemFields[] Fields { get; set; } + public ItemFields[]? Fields { get; set; } public bool? EnableImages { get; set; } public int? ImageTypeLimit { get; set; } - public ImageType[] EnableImageTypes { get; set; } + public ImageType[]? EnableImageTypes { get; set; } /// /// Gets or sets the user identifier. diff --git a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs index b00d2fffb..57759a7d3 100644 --- a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs +++ b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs @@ -1,4 +1,3 @@ -#nullable disable using System; using System.Xml.Serialization; @@ -35,21 +34,21 @@ namespace MediaBrowser.Model.Configuration /// Gets or sets the cache path. /// /// The cache path. - public string CachePath { get; set; } + public string? CachePath { get; set; } /// /// Gets or sets the last known version that was ran using the configuration. /// /// The version from previous run. [XmlIgnore] - public Version PreviousVersion { get; set; } + public Version? PreviousVersion { get; set; } /// /// Gets or sets the stringified PreviousVersion to be stored/loaded, /// because System.Version itself isn't xml-serializable. /// /// String value of PreviousVersion. - public string PreviousVersionStr + public string? PreviousVersionStr { get => PreviousVersion?.ToString(); set diff --git a/MediaBrowser.Model/Configuration/LibraryOptions.cs b/MediaBrowser.Model/Configuration/LibraryOptions.cs index 24698360e..aae5359b1 100644 --- a/MediaBrowser.Model/Configuration/LibraryOptions.cs +++ b/MediaBrowser.Model/Configuration/LibraryOptions.cs @@ -1,4 +1,3 @@ -#nullable disable #pragma warning disable CS1591 using System; @@ -52,21 +51,21 @@ namespace MediaBrowser.Model.Configuration /// Gets or sets the preferred metadata language. /// /// The preferred metadata language. - public string PreferredMetadataLanguage { get; set; } + public string? PreferredMetadataLanguage { get; set; } /// /// Gets or sets the metadata country code. /// /// The metadata country code. - public string MetadataCountryCode { get; set; } + public string? MetadataCountryCode { get; set; } public string SeasonZeroDisplayName { get; set; } - public string[] MetadataSavers { get; set; } + public string[]? MetadataSavers { get; set; } public string[] DisabledLocalMetadataReaders { get; set; } - public string[] LocalMetadataReaderOrder { get; set; } + public string[]? LocalMetadataReaderOrder { get; set; } public string[] DisabledSubtitleFetchers { get; set; } @@ -76,7 +75,7 @@ namespace MediaBrowser.Model.Configuration public bool SkipSubtitlesIfAudioTrackMatches { get; set; } - public string[] SubtitleDownloadLanguages { get; set; } + public string[]? SubtitleDownloadLanguages { get; set; } public bool RequirePerfectSubtitleMatch { get; set; } @@ -84,7 +83,7 @@ namespace MediaBrowser.Model.Configuration public TypeOptions[] TypeOptions { get; set; } - public TypeOptions GetTypeOptions(string type) + public TypeOptions? GetTypeOptions(string type) { foreach (var options in TypeOptions) { diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index 935e6cbe1..81359462c 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -1,4 +1,3 @@ -#nullable disable #pragma warning disable CS1591 using System; @@ -33,7 +32,7 @@ namespace MediaBrowser.Model.Configuration /// Gets or sets the audio language preference. /// /// The audio language preference. - public string AudioLanguagePreference { get; set; } + public string? AudioLanguagePreference { get; set; } /// /// Gets or sets a value indicating whether [play default audio track]. @@ -45,7 +44,7 @@ namespace MediaBrowser.Model.Configuration /// Gets or sets the subtitle language preference. /// /// The subtitle language preference. - public string SubtitleLanguagePreference { get; set; } + public string? SubtitleLanguagePreference { get; set; } public bool DisplayMissingEpisodes { get; set; } diff --git a/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs index 8ad070dcb..07129d715 100644 --- a/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs +++ b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs @@ -1,4 +1,3 @@ -#nullable disable #pragma warning disable CS1591 namespace MediaBrowser.Model.Configuration @@ -13,7 +12,7 @@ namespace MediaBrowser.Model.Configuration EnablePathSubstitution = true; } - public string UserId { get; set; } + public string? UserId { get; set; } public string ReleaseDateFormat { get; set; } diff --git a/MediaBrowser.Model/Dlna/DeviceIdentification.cs b/MediaBrowser.Model/Dlna/DeviceIdentification.cs index c511801f4..6625b7981 100644 --- a/MediaBrowser.Model/Dlna/DeviceIdentification.cs +++ b/MediaBrowser.Model/Dlna/DeviceIdentification.cs @@ -1,4 +1,3 @@ -#nullable disable #pragma warning disable CS1591 using System; diff --git a/MediaBrowser.Model/Dlna/ITranscoderSupport.cs b/MediaBrowser.Model/Dlna/ITranscoderSupport.cs index d9bd094d9..a70ce44cc 100644 --- a/MediaBrowser.Model/Dlna/ITranscoderSupport.cs +++ b/MediaBrowser.Model/Dlna/ITranscoderSupport.cs @@ -1,4 +1,3 @@ -#nullable disable #pragma warning disable CS1591 namespace MediaBrowser.Model.Dlna diff --git a/MediaBrowser.Model/Users/PinRedeemResult.cs b/MediaBrowser.Model/Users/PinRedeemResult.cs index 7e4553bac..23fa631e8 100644 --- a/MediaBrowser.Model/Users/PinRedeemResult.cs +++ b/MediaBrowser.Model/Users/PinRedeemResult.cs @@ -1,6 +1,7 @@ -#nullable disable #pragma warning disable CS1591 +using System; + namespace MediaBrowser.Model.Users { public class PinRedeemResult @@ -15,6 +16,6 @@ namespace MediaBrowser.Model.Users /// Gets or sets the users reset. /// /// The users reset. - public string[] UsersReset { get; set; } + public string[] UsersReset { get; set; } = Array.Empty(); } } -- cgit v1.2.3 From 2410b3a3cfeff716740c0c6c15f1896a224771a9 Mon Sep 17 00:00:00 2001 From: Deathspike Date: Tue, 26 Oct 2021 20:51:35 +0200 Subject: Resolve subtitle selection feedback (#6446) --- Emby.Server.Implementations/Library/MediaStreamSelector.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Library/MediaStreamSelector.cs b/Emby.Server.Implementations/Library/MediaStreamSelector.cs index f94eeda8f..b3837fedb 100644 --- a/Emby.Server.Implementations/Library/MediaStreamSelector.cs +++ b/Emby.Server.Implementations/Library/MediaStreamSelector.cs @@ -50,7 +50,8 @@ namespace Emby.Server.Implementations.Library return null; } - var sortedStreams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages) + var sortedStreams = streams + .Where(i => i.Type == MediaStreamType.Subtitle) .OrderByDescending(x => x.IsExternal) .ThenByDescending(x => x.IsForced && string.Equals(x.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) .ThenByDescending(x => x.IsForced) @@ -73,7 +74,8 @@ namespace Emby.Server.Implementations.Library // if the audio language is not understood by the user, load their preferred subs, if there are any if (!preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase)) { - stream = sortedStreams.FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)); + stream = streams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)) ?? + streams.FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)); } } else if (mode == SubtitlePlaybackMode.Always) -- cgit v1.2.3 From a1b63aaa08ec318df7e3992e4cfc3e9fce5c8b48 Mon Sep 17 00:00:00 2001 From: Alan Azar Date: Mon, 25 Oct 2021 18:31:58 +0000 Subject: Translated using Weblate (Arabic) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/ --- Emby.Server.Implementations/Localization/Core/ar.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/ar.json b/Emby.Server.Implementations/Localization/Core/ar.json index ee70aa8d8..f60d2fd01 100644 --- a/Emby.Server.Implementations/Localization/Core/ar.json +++ b/Emby.Server.Implementations/Localization/Core/ar.json @@ -33,7 +33,7 @@ "LabelRunningTimeValue": "المدة: {0}", "Latest": "الأحدث", "MessageApplicationUpdated": "لقد تم تحديث خادم Jellyfin", - "MessageApplicationUpdatedTo": "تم تحديث سيرفر Jellyfin الى {0}", + "MessageApplicationUpdatedTo": "تم تحديث خادم Jellyfin الى {0}", "MessageNamedServerConfigurationUpdatedWithValue": "تم تحديث إعدادات الخادم في قسم {0}", "MessageServerConfigurationUpdated": "تم تحديث إعدادات الخادم", "MixedContent": "محتوى مختلط", @@ -43,7 +43,7 @@ "NameInstallFailed": "فشل التثبيت {0}", "NameSeasonNumber": "الموسم {0}", "NameSeasonUnknown": "الموسم غير معروف", - "NewVersionIsAvailable": "نسخة جديدة من سيرفر Jellyfin متوفرة للتحميل.", + "NewVersionIsAvailable": "نسخة جديدة من خادم Jellyfin متوفرة للتحميل.", "NotificationOptionApplicationUpdateAvailable": "يوجد تحديث للتطبيق", "NotificationOptionApplicationUpdateInstalled": "تم تحديث التطبيق", "NotificationOptionAudioPlayback": "بدأ تشغيل المقطع الصوتي", @@ -55,7 +55,7 @@ "NotificationOptionPluginInstalled": "تم تثبيت الملحق", "NotificationOptionPluginUninstalled": "تمت إزالة الملحق", "NotificationOptionPluginUpdateInstalled": "تم تثبيت تحديثات الملحق", - "NotificationOptionServerRestartRequired": "يجب إعادة تشغيل السيرفر", + "NotificationOptionServerRestartRequired": "يجب إعادة تشغيل الخادم", "NotificationOptionTaskFailed": "فشل في المهمة المجدولة", "NotificationOptionUserLockedOut": "تم إقفال حساب المستخدم", "NotificationOptionVideoPlayback": "بدأ تشغيل الفيديو", @@ -72,7 +72,7 @@ "ServerNameNeedsToBeRestarted": "يحتاج لإعادة تشغيله {0}", "Shows": "الحلقات", "Songs": "الأغاني", - "StartupEmbyServerIsLoading": "سيرفر Jellyfin قيد التشغيل . الرجاء المحاولة بعد قليل.", + "StartupEmbyServerIsLoading": "خادم Jellyfin قيد التشغيل . الرجاء المحاولة بعد قليل.", "SubtitleDownloadFailureForItem": "عملية إنزال الترجمة فشلت لـ{0}", "SubtitleDownloadFailureFromForItem": "الترجمات فشلت في التحميل من {0} الى {1}", "Sync": "مزامنة", -- cgit v1.2.3 From 91655bb5fea6c711c66d3527aceee91edd9a4000 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Tue, 26 Oct 2021 11:54:25 +0000 Subject: Translated using Weblate (Esperanto) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/ --- Emby.Server.Implementations/Localization/Core/eo.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/eo.json b/Emby.Server.Implementations/Localization/Core/eo.json index 7ce87502c..f92b5f673 100644 --- a/Emby.Server.Implementations/Localization/Core/eo.json +++ b/Emby.Server.Implementations/Localization/Core/eo.json @@ -7,8 +7,8 @@ "NameInstallFailed": "{0} instalado fiaskis", "Music": "Muziko", "Movies": "Filmoj", - "ItemRemovedWithName": "{0} forigis el la libraro", - "ItemAddedWithName": "{0} aldonis al la libraro", + "ItemRemovedWithName": "{0} forigis el la plurmediteko", + "ItemAddedWithName": "{0} aldonis al la plurmediteko", "HeaderLiveTV": "TV-etero", "HeaderContinueWatching": "Daŭrigi Spektadon", "HeaderAlbumArtists": "Albumo de artisto", @@ -23,7 +23,7 @@ "Application": "Aplikaĵo", "AppDeviceValues": "Aplikaĵo: {0}, Aparato: {1}", "Albums": "Albumoj", - "TasksLibraryCategory": "Libraro", + "TasksLibraryCategory": "Plurmediteko", "VersionNumber": "Versio {0}", "UserDownloadingItemWithValues": "{0} elŝutas {1}", "UserCreatedWithName": "Uzanto {0} kreiĝis", @@ -50,7 +50,7 @@ "TvShows": "TV-serioj", "Favorites": "Favoratoj", "TaskCleanLogs": "Purigi Ĵurnalan Katalogon", - "TaskRefreshLibrary": "Skanu Plurmedian Libraron", + "TaskRefreshLibrary": "Skanu Plurmeditekon", "ValueSpecialEpisodeName": "Speciala - {0}", "TaskOptimizeDatabase": "Optimigi datumbazon", "TaskRefreshChannels": "Refreŝigi Kanalojn", @@ -75,17 +75,17 @@ "ServerNameNeedsToBeRestarted": "{0} devas esti relanĉita", "NotificationOptionVideoPlayback": "La videoludado lanĉis", "NotificationOptionServerRestartRequired": "Servila relanĉigo bezonata", - "TaskOptimizeDatabaseDescription": "Kompaktigas datenbazon kaj trunkas liberan lokon. Lanĉi ĉi tiun taskon post la librara skanado aŭ fari aliajn ŝanĝojn, kiuj implicas datenbazajn modifojn, povus plibonigi rendimenton.", + "TaskOptimizeDatabaseDescription": "Kompaktigas datenbazon kaj trunkas liberan lokon. Lanĉi ĉi tiun taskon post la teka skanado aŭ fari aliajn ŝanĝojn, kiuj implicas datenbazajn modifojn, povus plibonigi rendimenton.", "TaskUpdatePluginsDescription": "Elŝutas kaj instalas ĝisdatigojn por kromprogramojn, kiuj estas agorditaj por ĝisdatigi aŭtomate.", "TaskDownloadMissingSubtitlesDescription": "Serĉas en interreto mankantajn subtekstojn surbaze de metadatena agordaro.", - "TaskRefreshPeopleDescription": "Ĝisdatigas metadatenojn por aktoroj kaj reĵisoroj en via plurmedia libraro.", + "TaskRefreshPeopleDescription": "Ĝisdatigas metadatenojn por aktoroj kaj reĵisoroj en via plurmediteko.", "TaskCleanLogsDescription": "Forigas ĵurnalajn dosierojn aĝajn pli ol {0} tagojn.", - "TaskRefreshLibraryDescription": "Skanas vian plurmedian libraron por novaj dosieroj kaj refreŝigas metadatenaron.", + "TaskRefreshLibraryDescription": "Skanas vian plurmeditekon por novaj dosieroj kaj refreŝigas metadatenaron.", "NewVersionIsAvailable": "Nova versio de Jellyfin Server estas elŝutebla.", "TaskCleanCacheDescription": "Forigas stapla dosierojn ne plu necesajn de la sistemo.", "TaskCleanActivityLogDescription": "Forigas aktivecan ĵurnalaĵojn pli malnovajn ol la agordita aĝo.", "TaskCleanTranscodeDescription": "Forigas transkodajn dosierojn aĝajn pli ol unu tagon.", - "ValueHasBeenAddedToLibrary": "{0} estis aldonita al via plurmedia libraro", + "ValueHasBeenAddedToLibrary": "{0} estis aldonita al via plurmediteko", "SubtitleDownloadFailureFromForItem": "Subtekstoj malsukcesis elŝuti de {0} por {1}", "StartupEmbyServerIsLoading": "Jellyfin Server ŝarĝas. Provi denove baldaŭ.", "TaskRefreshChapterImagesDescription": "Kreas bildetojn por videoj kiuj havas ĉapitrojn.", -- cgit v1.2.3 From 4599ce659c75ffb6dcd21bdbff62cab1eb24c99c Mon Sep 17 00:00:00 2001 From: De sousa John Date: Mon, 25 Oct 2021 07:40:39 +0000 Subject: Translated using Weblate (French) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/ --- Emby.Server.Implementations/Localization/Core/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json index c3e52eb81..1265b6ef5 100644 --- a/Emby.Server.Implementations/Localization/Core/fr.json +++ b/Emby.Server.Implementations/Localization/Core/fr.json @@ -1,7 +1,7 @@ { "Albums": "Albums", "AppDeviceValues": "Application : {0}, Appareil : {1}", - "Application": "Application", + "Application": "Applications", "Artists": "Artistes", "AuthenticationSucceededWithUserName": "{0} authentifié avec succès", "Books": "Livres", -- cgit v1.2.3 From fc2e826b4de1582f2ae2d453bdc6d71262c72d67 Mon Sep 17 00:00:00 2001 From: Alan Azar Date: Wed, 27 Oct 2021 15:21:02 +0000 Subject: Translated using Weblate (Arabic) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/ --- Emby.Server.Implementations/Localization/Core/ar.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/ar.json b/Emby.Server.Implementations/Localization/Core/ar.json index f60d2fd01..99220cca9 100644 --- a/Emby.Server.Implementations/Localization/Core/ar.json +++ b/Emby.Server.Implementations/Localization/Core/ar.json @@ -16,7 +16,7 @@ "Folders": "المجلدات", "Genres": "التضنيفات", "HeaderAlbumArtists": "ألبوم الفنان", - "HeaderContinueWatching": "استئناف", + "HeaderContinueWatching": "استمر بالمشاهدة", "HeaderFavoriteAlbums": "الألبومات المفضلة", "HeaderFavoriteArtists": "الفنانون المفضلون", "HeaderFavoriteEpisodes": "الحلقات المفضلة", -- cgit v1.2.3 From 17973964faed0958190817484bba1603dd8ad51d Mon Sep 17 00:00:00 2001 From: Kenneth SB Date: Wed, 27 Oct 2021 16:49:49 +0000 Subject: Translated using Weblate (Danish) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/da/ --- Emby.Server.Implementations/Localization/Core/da.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json index b2c484a31..cfe365f57 100644 --- a/Emby.Server.Implementations/Localization/Core/da.json +++ b/Emby.Server.Implementations/Localization/Core/da.json @@ -15,7 +15,7 @@ "Favorites": "Favoritter", "Folders": "Mapper", "Genres": "Genrer", - "HeaderAlbumArtists": "Albumkunstnere", + "HeaderAlbumArtists": "Kunstnerens album", "HeaderContinueWatching": "Fortsæt Afspilning", "HeaderFavoriteAlbums": "Favoritalbummer", "HeaderFavoriteArtists": "Favoritkunstnere", -- cgit v1.2.3 From 5a7433472ef88c7e8e52840425a7296e242155ee Mon Sep 17 00:00:00 2001 From: Alan Azar Date: Fri, 29 Oct 2021 04:42:23 +0000 Subject: Translated using Weblate (Arabic) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ar/ --- Emby.Server.Implementations/Localization/Core/ar.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/ar.json b/Emby.Server.Implementations/Localization/Core/ar.json index 99220cca9..a83a453b4 100644 --- a/Emby.Server.Implementations/Localization/Core/ar.json +++ b/Emby.Server.Implementations/Localization/Core/ar.json @@ -12,7 +12,7 @@ "DeviceOfflineWithName": "قُطِع الاتصال ب{0}", "DeviceOnlineWithName": "{0} متصل", "FailedLoginAttemptWithUserName": "عملية تسجيل الدخول فشلت من {0}", - "Favorites": "المفضلة", + "Favorites": "مفضلات", "Folders": "المجلدات", "Genres": "التضنيفات", "HeaderAlbumArtists": "ألبوم الفنان", -- cgit v1.2.3 From a22c57ff3323c3e06ffdd828f887ee37933e8ece Mon Sep 17 00:00:00 2001 From: Pedro Almeida Date: Sun, 31 Oct 2021 15:13:23 +0000 Subject: Fix localization typo with Réunion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Emby.Server.Implementations/Localization/countries.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/countries.json b/Emby.Server.Implementations/Localization/countries.json index b08a3ae79..22ffc5e09 100644 --- a/Emby.Server.Implementations/Localization/countries.json +++ b/Emby.Server.Implementations/Localization/countries.json @@ -630,7 +630,7 @@ "TwoLetterISORegionName": "MD" }, { - "DisplayName": "Réunion", + "DisplayName": "Réunion", "Name": "RE", "ThreeLetterISORegionName": "REU", "TwoLetterISORegionName": "RE" -- cgit v1.2.3 From 10a173c01164304449787f275df5b70d58b4debd Mon Sep 17 00:00:00 2001 From: Pedro Almeida Date: Sun, 31 Oct 2021 15:28:51 +0000 Subject: Add pt-pt as culture Makes pt-pt selectable as metadata language --- Emby.Server.Implementations/Localization/iso6392.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/iso6392.txt b/Emby.Server.Implementations/Localization/iso6392.txt index 488901822..66fba3330 100644 --- a/Emby.Server.Implementations/Localization/iso6392.txt +++ b/Emby.Server.Implementations/Localization/iso6392.txt @@ -349,7 +349,8 @@ pli||pi|Pali|pali pol||pl|Polish|polonais pon|||Pohnpeian|pohnpei por||pt|Portuguese|portugais -pob||pt-br|Portuguese (Brazil)|portugais +pop||pt-pt|Portuguese (Portugal)|portugais (pt-pt) +pob||pt-br|Portuguese (Brazil)|portugais (pt-br) pra|||Prakrit languages|prâkrit, langues pro|||Provençal, Old (to 1500)|provençal ancien (jusqu'à 1500) pus||ps|Pushto; Pashto|pachto -- cgit v1.2.3 From a229526454750de978397571b0b19426f195dd3d Mon Sep 17 00:00:00 2001 From: WWWesten <4700006+WWWesten@users.noreply.github.com> Date: Mon, 1 Nov 2021 23:47:31 +0500 Subject: Update LocalizationManager.cs --- .../Localization/LocalizationManager.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 03919197e..a5a530a56 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -372,9 +372,11 @@ namespace Emby.Server.Implementations.Localization /// public IEnumerable GetLocalizationOptions() { - yield return new LocalizationOption("Arabic", "ar"); + yield return new LocalizationOption("Afrikaans", "af"); + yield return new LocalizationOption("Arabic", "ar"); yield return new LocalizationOption("Bulgarian (Bulgaria)", "bg-BG"); yield return new LocalizationOption("Catalan", "ca"); + yield return new LocalizationOption("Chinese (Hong Kong)", "zh-HK"); yield return new LocalizationOption("Chinese Simplified", "zh-CN"); yield return new LocalizationOption("Chinese Traditional", "zh-TW"); yield return new LocalizationOption("Croatian", "hr"); @@ -383,32 +385,48 @@ namespace Emby.Server.Implementations.Localization yield return new LocalizationOption("Dutch", "nl"); yield return new LocalizationOption("English (United Kingdom)", "en-GB"); yield return new LocalizationOption("English (United States)", "en-US"); + yield return new LocalizationOption("Esperanto", "eo"); + yield return new LocalizationOption("Estonian", "et"); + yield return new LocalizationOption("Finnish", "fi"); yield return new LocalizationOption("French", "fr"); yield return new LocalizationOption("French (Canada)", "fr-CA"); yield return new LocalizationOption("German", "de"); yield return new LocalizationOption("Greek", "el"); yield return new LocalizationOption("Hebrew", "he"); yield return new LocalizationOption("Hungarian", "hu"); + yield return new LocalizationOption("Icelandic", "is"); + yield return new LocalizationOption("Indonesian", "id"); yield return new LocalizationOption("Italian", "it"); + yield return new LocalizationOption("Japanese", "ja"); yield return new LocalizationOption("Kazakh", "kk"); yield return new LocalizationOption("Korean", "ko"); + yield return new LocalizationOption("Latvian", "lv"); yield return new LocalizationOption("Lithuanian", "lt-LT"); yield return new LocalizationOption("Malay", "ms"); + yield return new LocalizationOption("Malayalam", "ml"); yield return new LocalizationOption("Norwegian Bokmål", "nb"); + yield return new LocalizationOption("Norwegian Nynorsk", "nn"); yield return new LocalizationOption("Persian", "fa"); yield return new LocalizationOption("Polish", "pl"); + yield return new LocalizationOption("Portuguese", "pt"); yield return new LocalizationOption("Portuguese (Brazil)", "pt-BR"); yield return new LocalizationOption("Portuguese (Portugal)", "pt-PT"); + yield return new LocalizationOption("Romanian", "ro"); yield return new LocalizationOption("Russian", "ru"); + yield return new LocalizationOption("Serbian", "sr"); yield return new LocalizationOption("Slovak", "sk"); yield return new LocalizationOption("Slovenian (Slovenia)", "sl-SI"); yield return new LocalizationOption("Spanish", "es"); yield return new LocalizationOption("Spanish (Argentina)", "es-AR"); + yield return new LocalizationOption("Spanish (Latin America)", "es-419"); yield return new LocalizationOption("Spanish (Mexico)", "es-MX"); yield return new LocalizationOption("Swedish", "sv"); yield return new LocalizationOption("Swiss German", "gsw"); + yield return new LocalizationOption("Tamil", "ta"); + yield return new LocalizationOption("Telugu", "te"); yield return new LocalizationOption("Turkish", "tr"); yield return new LocalizationOption("Tiếng Việt", "vi"); + yield return new LocalizationOption("Ukrainian", "uk"); } } } -- cgit v1.2.3 From 967fd66ca9b416bb8ca0796304ab912a45f3dd1d Mon Sep 17 00:00:00 2001 From: WWWesten <4700006+WWWesten@users.noreply.github.com> Date: Tue, 2 Nov 2021 00:22:16 +0500 Subject: Update LocalizationManager.cs --- .../Localization/LocalizationManager.cs | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index a5a530a56..1524fcdb2 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -372,11 +372,11 @@ namespace Emby.Server.Implementations.Localization /// public IEnumerable GetLocalizationOptions() { - yield return new LocalizationOption("Afrikaans", "af"); - yield return new LocalizationOption("Arabic", "ar"); + yield return new LocalizationOption("Afrikaans", "af"); + yield return new LocalizationOption("Arabic", "ar"); yield return new LocalizationOption("Bulgarian (Bulgaria)", "bg-BG"); yield return new LocalizationOption("Catalan", "ca"); - yield return new LocalizationOption("Chinese (Hong Kong)", "zh-HK"); + yield return new LocalizationOption("Chinese (Hong Kong)", "zh-HK"); yield return new LocalizationOption("Chinese Simplified", "zh-CN"); yield return new LocalizationOption("Chinese Traditional", "zh-TW"); yield return new LocalizationOption("Croatian", "hr"); @@ -385,48 +385,48 @@ namespace Emby.Server.Implementations.Localization yield return new LocalizationOption("Dutch", "nl"); yield return new LocalizationOption("English (United Kingdom)", "en-GB"); yield return new LocalizationOption("English (United States)", "en-US"); - yield return new LocalizationOption("Esperanto", "eo"); - yield return new LocalizationOption("Estonian", "et"); - yield return new LocalizationOption("Finnish", "fi"); + yield return new LocalizationOption("Esperanto", "eo"); + yield return new LocalizationOption("Estonian", "et"); + yield return new LocalizationOption("Finnish", "fi"); yield return new LocalizationOption("French", "fr"); yield return new LocalizationOption("French (Canada)", "fr-CA"); yield return new LocalizationOption("German", "de"); yield return new LocalizationOption("Greek", "el"); yield return new LocalizationOption("Hebrew", "he"); yield return new LocalizationOption("Hungarian", "hu"); - yield return new LocalizationOption("Icelandic", "is"); - yield return new LocalizationOption("Indonesian", "id"); + yield return new LocalizationOption("Icelandic", "is"); + yield return new LocalizationOption("Indonesian", "id"); yield return new LocalizationOption("Italian", "it"); - yield return new LocalizationOption("Japanese", "ja"); + yield return new LocalizationOption("Japanese", "ja"); yield return new LocalizationOption("Kazakh", "kk"); yield return new LocalizationOption("Korean", "ko"); - yield return new LocalizationOption("Latvian", "lv"); + yield return new LocalizationOption("Latvian", "lv"); yield return new LocalizationOption("Lithuanian", "lt-LT"); yield return new LocalizationOption("Malay", "ms"); - yield return new LocalizationOption("Malayalam", "ml"); + yield return new LocalizationOption("Malayalam", "ml"); yield return new LocalizationOption("Norwegian Bokmål", "nb"); - yield return new LocalizationOption("Norwegian Nynorsk", "nn"); + yield return new LocalizationOption("Norwegian Nynorsk", "nn"); yield return new LocalizationOption("Persian", "fa"); yield return new LocalizationOption("Polish", "pl"); - yield return new LocalizationOption("Portuguese", "pt"); + yield return new LocalizationOption("Portuguese", "pt"); yield return new LocalizationOption("Portuguese (Brazil)", "pt-BR"); yield return new LocalizationOption("Portuguese (Portugal)", "pt-PT"); - yield return new LocalizationOption("Romanian", "ro"); + yield return new LocalizationOption("Romanian", "ro"); yield return new LocalizationOption("Russian", "ru"); - yield return new LocalizationOption("Serbian", "sr"); + yield return new LocalizationOption("Serbian", "sr"); yield return new LocalizationOption("Slovak", "sk"); yield return new LocalizationOption("Slovenian (Slovenia)", "sl-SI"); yield return new LocalizationOption("Spanish", "es"); yield return new LocalizationOption("Spanish (Argentina)", "es-AR"); - yield return new LocalizationOption("Spanish (Latin America)", "es-419"); + yield return new LocalizationOption("Spanish (Latin America)", "es-419"); yield return new LocalizationOption("Spanish (Mexico)", "es-MX"); yield return new LocalizationOption("Swedish", "sv"); yield return new LocalizationOption("Swiss German", "gsw"); - yield return new LocalizationOption("Tamil", "ta"); - yield return new LocalizationOption("Telugu", "te"); + yield return new LocalizationOption("Tamil", "ta"); + yield return new LocalizationOption("Telugu", "te"); yield return new LocalizationOption("Turkish", "tr"); yield return new LocalizationOption("Tiếng Việt", "vi"); - yield return new LocalizationOption("Ukrainian", "uk"); + yield return new LocalizationOption("Ukrainian", "uk"); } } } -- cgit v1.2.3 From 5529625025f53b6397c500d8cce2b3c5be28e63c Mon Sep 17 00:00:00 2001 From: Pedro Almeida Date: Mon, 1 Nov 2021 15:38:14 +0000 Subject: Translated using Weblate (Portuguese (Portugal)) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/pt_PT/ --- Emby.Server.Implementations/Localization/Core/pt-PT.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/pt-PT.json b/Emby.Server.Implementations/Localization/Core/pt-PT.json index 8c41edf96..525a02c88 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-PT.json +++ b/Emby.Server.Implementations/Localization/Core/pt-PT.json @@ -39,7 +39,7 @@ "MixedContent": "Conteúdo Misto", "Movies": "Filmes", "Music": "Música", - "MusicVideos": "Videoclips", + "MusicVideos": "Videoclipes", "NameInstallFailed": "{0} falha na instalação", "NameSeasonNumber": "Temporada {0}", "NameSeasonUnknown": "Temporada Desconhecida", @@ -118,5 +118,7 @@ "TaskCleanActivityLog": "Limpar registo de atividade", "Undefined": "Indefinido", "Forced": "Forçado", - "Default": "Padrão" + "Default": "Padrão", + "TaskOptimizeDatabaseDescription": "Base de dados compacta e corta espaço livre. A execução desta tarefa depois de digitalizar a biblioteca ou de fazer outras alterações que impliquem modificações na base de dados pode melhorar o desempenho.", + "TaskOptimizeDatabase": "Otimizar base de dados" } -- cgit v1.2.3 From 104e36f2f9c6440a7547a4c76d80a69d5af84eea Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 2 Nov 2021 16:02:52 +0100 Subject: Streamline startup code --- Emby.Server.Implementations/ApplicationHost.cs | 150 ++++++++++----------- Jellyfin.Server/CoreAppHost.cs | 49 +++---- Jellyfin.Server/Program.cs | 41 +++--- MediaBrowser.Common/IApplicationHost.cs | 4 +- .../JellyfinApplicationFactory.cs | 10 +- .../TestAppHost.cs | 12 +- 6 files changed, 123 insertions(+), 143 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 6fd152a42..512700ac2 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -147,25 +147,20 @@ namespace Emby.Server.Implementations /// Instance of the interface. /// Instance of the interface. /// The interface. - /// Instance of the interface. - /// Instance of the interface. public ApplicationHost( IServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, IStartupOptions options, - IConfiguration startupConfig, - IFileSystem fileSystem, - IServiceCollection serviceCollection) + IConfiguration startupConfig) { ApplicationPaths = applicationPaths; LoggerFactory = loggerFactory; _startupOptions = options; _startupConfig = startupConfig; - _fileSystemManager = fileSystem; - ServiceCollection = serviceCollection; + _fileSystemManager = new ManagedFileSystem(LoggerFactory.CreateLogger(), applicationPaths); Logger = LoggerFactory.CreateLogger(); - fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); + _fileSystemManager.AddShortcutHandler(new MbLinkShortcutHandler(_fileSystemManager)); ApplicationVersion = typeof(ApplicationHost).Assembly.GetName().Version; ApplicationVersionString = ApplicationVersion.ToString(3); @@ -230,8 +225,6 @@ namespace Emby.Server.Implementations /// protected ILogger Logger { get; } - protected IServiceCollection ServiceCollection { get; } - /// /// Gets the logger factory. /// @@ -521,7 +514,7 @@ namespace Emby.Server.Implementations } /// - public void Init() + public void Init(IServiceCollection serviceCollection) { DiscoverTypes(); @@ -551,128 +544,129 @@ namespace Emby.Server.Implementations CertificatePath = networkConfiguration.CertificatePath; Certificate = GetCertificate(CertificatePath, networkConfiguration.CertificatePassword); - RegisterServices(); + RegisterServices(serviceCollection); - _pluginManager.RegisterServices(ServiceCollection); + _pluginManager.RegisterServices(serviceCollection); } /// /// Registers services/resources with the service collection that will be available via DI. /// - protected virtual void RegisterServices() + /// Instance of the interface. + protected virtual void RegisterServices(IServiceCollection serviceCollection) { - ServiceCollection.AddSingleton(_startupOptions); + serviceCollection.AddSingleton(_startupOptions); - ServiceCollection.AddMemoryCache(); + serviceCollection.AddMemoryCache(); - ServiceCollection.AddSingleton(ConfigurationManager); - ServiceCollection.AddSingleton(ConfigurationManager); - ServiceCollection.AddSingleton(this); - ServiceCollection.AddSingleton(_pluginManager); - ServiceCollection.AddSingleton(ApplicationPaths); + serviceCollection.AddSingleton(ConfigurationManager); + serviceCollection.AddSingleton(ConfigurationManager); + serviceCollection.AddSingleton(this); + serviceCollection.AddSingleton(_pluginManager); + serviceCollection.AddSingleton(ApplicationPaths); - ServiceCollection.AddSingleton(_fileSystemManager); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(_fileSystemManager); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(NetManager); + serviceCollection.AddSingleton(NetManager); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(_xmlSerializer); + serviceCollection.AddSingleton(_xmlSerializer); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(this); - ServiceCollection.AddSingleton(ApplicationPaths); + serviceCollection.AddSingleton(this); + serviceCollection.AddSingleton(ApplicationPaths); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); // TODO: Refactor to eliminate the circular dependencies here so that Lazy isn't required - ServiceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); - ServiceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); - ServiceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); - ServiceCollection.AddSingleton(); + serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); + serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); + serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); // TODO: Refactor to eliminate the circular dependency here so that Lazy isn't required - ServiceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); - ServiceCollection.AddSingleton(); + serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddScoped(); + serviceCollection.AddScoped(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddScoped(); - ServiceCollection.AddScoped(); - ServiceCollection.AddScoped(); + serviceCollection.AddSingleton(); + serviceCollection.AddScoped(); + serviceCollection.AddScoped(); + serviceCollection.AddScoped(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); } /// diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 21bd9ba01..67e50b92d 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -22,7 +22,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Security; using MediaBrowser.Model.Activity; -using MediaBrowser.Model.IO; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -42,67 +41,61 @@ namespace Jellyfin.Server /// The to be used by the . /// The to be used by the . /// The to be used by the . - /// The to be used by the . - /// The to be used by the . public CoreAppHost( IServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, IStartupOptions options, - IConfiguration startupConfig, - IFileSystem fileSystem, - IServiceCollection collection) + IConfiguration startupConfig) : base( applicationPaths, loggerFactory, options, - startupConfig, - fileSystem, - collection) + startupConfig) { } /// - protected override void RegisterServices() + protected override void RegisterServices(IServiceCollection serviceCollection) { // Register an image encoder bool useSkiaEncoder = SkiaEncoder.IsNativeLibAvailable(); Type imageEncoderType = useSkiaEncoder ? typeof(SkiaEncoder) : typeof(NullImageEncoder); - ServiceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType); + serviceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType); // Log a warning if the Skia encoder could not be used if (!useSkiaEncoder) { - Logger.LogWarning($"Skia not available. Will fallback to {nameof(NullImageEncoder)}."); + Logger.LogWarning("Skia not available. Will fallback to {ImageEncoder}.", nameof(NullImageEncoder)); } - ServiceCollection.AddDbContextPool( + serviceCollection.AddDbContextPool( options => options .UseLoggerFactory(LoggerFactory) .UseSqlite($"Filename={Path.Combine(ApplicationPaths.DataPath, "jellyfin.db")}")); - ServiceCollection.AddEventServices(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddEventServices(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); // TODO search the assemblies instead of adding them manually? - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + serviceCollection.AddSingleton(); - ServiceCollection.AddScoped(); + serviceCollection.AddScoped(); - base.RegisterServices(); + base.RegisterServices(serviceCollection); } /// diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 45699f3af..5f848be9e 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -10,7 +10,6 @@ using System.Threading; using System.Threading.Tasks; using CommandLine; using Emby.Server.Implementations; -using Emby.Server.Implementations.IO; using Jellyfin.Server.Implementations; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; @@ -157,34 +156,36 @@ namespace Jellyfin.Server ApplicationHost.LogEnvironmentInfo(_logger, appPaths); + // If hosting the web client, validate the client content path + if (startupConfig.HostWebClient()) + { + string? webContentPath = appPaths.WebPath; + if (!Directory.Exists(webContentPath) || !Directory.EnumerateFiles(webContentPath).Any()) + { + _logger.LogError( + "The server is expected to host the web client, but the provided content directory is either " + + "invalid or empty: {WebContentPath}. If you do not want to host the web client with the " + + "server, you may set the '--nowebclient' command line flag, or set" + + "'{ConfigKey}=false' in your config settings.", + webContentPath, + ConfigurationExtensions.HostWebClientKey); + Environment.ExitCode = 1; + return; + } + } + PerformStaticInitialization(); - var serviceCollection = new ServiceCollection(); var appHost = new CoreAppHost( appPaths, _loggerFactory, options, - startupConfig, - new ManagedFileSystem(_loggerFactory.CreateLogger(), appPaths), - serviceCollection); + startupConfig); try { - // If hosting the web client, validate the client content path - if (startupConfig.HostWebClient()) - { - string? webContentPath = appHost.ConfigurationManager.ApplicationPaths.WebPath; - if (!Directory.Exists(webContentPath) || Directory.GetFiles(webContentPath).Length == 0) - { - throw new InvalidOperationException( - "The server is expected to host the web client, but the provided content directory is either " + - $"invalid or empty: {webContentPath}. If you do not want to host the web client with the " + - "server, you may set the '--nowebclient' command line flag, or set" + - $"'{ConfigurationExtensions.HostWebClientKey}=false' in your config settings."); - } - } - - appHost.Init(); + var serviceCollection = new ServiceCollection(); + appHost.Init(serviceCollection); var webHost = new WebHostBuilder().ConfigureWebHostBuilder(appHost, serviceCollection, options, startupConfig, appPaths).Build(); diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index 192a77611..e49ab41f4 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Reflection; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; namespace MediaBrowser.Common { @@ -137,7 +138,8 @@ namespace MediaBrowser.Common /// /// Initializes this instance. /// - void Init(); + /// Instance of the interface. + void Init(IServiceCollection serviceCollection); /// /// Creates the instance. diff --git a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs index 976e19d46..3d34a18e7 100644 --- a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs +++ b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs @@ -3,7 +3,6 @@ using System.Collections.Concurrent; using System.IO; using System.Threading; using Emby.Server.Implementations; -using Emby.Server.Implementations.IO; using MediaBrowser.Common; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; @@ -67,7 +66,7 @@ namespace Jellyfin.Server.Integration.Tests var startupConfig = Program.CreateAppConfiguration(commandLineOpts, appPaths); ILoggerFactory loggerFactory = new SerilogLoggerFactory(); - var serviceCollection = new ServiceCollection(); + _disposableComponents.Add(loggerFactory); // Create the app host and initialize it @@ -75,11 +74,10 @@ namespace Jellyfin.Server.Integration.Tests appPaths, loggerFactory, commandLineOpts, - new ConfigurationBuilder().Build(), - new ManagedFileSystem(loggerFactory.CreateLogger(), appPaths), - serviceCollection); + new ConfigurationBuilder().Build()); _disposableComponents.Add(appHost); - appHost.Init(); + var serviceCollection = new ServiceCollection(); + appHost.Init(serviceCollection); // Configure the web host builder Program.ConfigureWebHostBuilder(builder, appHost, serviceCollection, commandLineOpts, startupConfig, appPaths); diff --git a/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs b/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs index 0a463cfa3..bf74efa09 100644 --- a/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs +++ b/tests/Jellyfin.Server.Integration.Tests/TestAppHost.cs @@ -2,9 +2,7 @@ using System.Collections.Generic; using System.Reflection; using Emby.Server.Implementations; using MediaBrowser.Controller; -using MediaBrowser.Model.IO; using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Jellyfin.Server.Integration.Tests @@ -21,22 +19,16 @@ namespace Jellyfin.Server.Integration.Tests /// The to be used by the . /// The to be used by the . /// The to be used by the . - /// The to be used by the . - /// The to be used by the . public TestAppHost( IServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, IStartupOptions options, - IConfiguration startup, - IFileSystem fileSystem, - IServiceCollection collection) + IConfiguration startup) : base( applicationPaths, loggerFactory, options, - startup, - fileSystem, - collection) + startup) { } -- cgit v1.2.3 From 70b9f9bf560e4f9ff47ecb00c22561e3065a20de Mon Sep 17 00:00:00 2001 From: nextlooper42 Date: Tue, 2 Nov 2021 22:26:20 +0000 Subject: Translated using Weblate (Slovak) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/sk/ --- Emby.Server.Implementations/Localization/Core/sk.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/sk.json b/Emby.Server.Implementations/Localization/Core/sk.json index ad90bd813..37da7d5ab 100644 --- a/Emby.Server.Implementations/Localization/Core/sk.json +++ b/Emby.Server.Implementations/Localization/Core/sk.json @@ -39,7 +39,7 @@ "MixedContent": "Zmiešaný obsah", "Movies": "Filmy", "Music": "Hudba", - "MusicVideos": "Hudobné videá", + "MusicVideos": "Hudobné videoklipy", "NameInstallFailed": "Inštalácia {0} zlyhala", "NameSeasonNumber": "Séria {0}", "NameSeasonUnknown": "Neznáma séria", -- cgit v1.2.3 From 654bd6fff141fb53661e2a99fc6a48478c92e8dd Mon Sep 17 00:00:00 2001 From: WWWesten Date: Thu, 4 Nov 2021 08:18:21 +0000 Subject: Translated using Weblate (Turkish) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/tr/ --- Emby.Server.Implementations/Localization/Core/tr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/tr.json b/Emby.Server.Implementations/Localization/Core/tr.json index e661299c4..8fadb88ac 100644 --- a/Emby.Server.Implementations/Localization/Core/tr.json +++ b/Emby.Server.Implementations/Localization/Core/tr.json @@ -8,7 +8,7 @@ "CameraImageUploadedFrom": "{0} 'den yeni bir kamera resmi yüklendi", "Channels": "Kanallar", "ChapterNameValue": "Bölüm {0}", - "Collections": "Koleksiyon", + "Collections": "Koleksiyonlar", "DeviceOfflineWithName": "{0} bağlantısı kesildi", "DeviceOnlineWithName": "{0} bağlı", "FailedLoginAttemptWithUserName": "{0} adresinden giriş başarısız oldu", -- cgit v1.2.3 From 5aadf8c291df8a9f9a3bb6d4407979fc456ab6d4 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Wed, 3 Nov 2021 06:33:55 +0000 Subject: Translated using Weblate (Esperanto) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/ --- Emby.Server.Implementations/Localization/Core/eo.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/eo.json b/Emby.Server.Implementations/Localization/Core/eo.json index f92b5f673..8ac466908 100644 --- a/Emby.Server.Implementations/Localization/Core/eo.json +++ b/Emby.Server.Implementations/Localization/Core/eo.json @@ -1,5 +1,5 @@ { - "NotificationOptionInstallationFailed": "Instalada fiasko", + "NotificationOptionInstallationFailed": "Instalada malsukceso", "NotificationOptionAudioPlaybackStopped": "Ludado de sono haltis", "NotificationOptionAudioPlayback": "Ludado de sono lanĉis", "NameSeasonUnknown": "Sezono Nekonata", @@ -48,17 +48,17 @@ "Shows": "Serioj", "HeaderFavoriteShows": "Favorataj Serioj", "TvShows": "TV-serioj", - "Favorites": "Favoratoj", + "Favorites": "Favorataj", "TaskCleanLogs": "Purigi Ĵurnalan Katalogon", - "TaskRefreshLibrary": "Skanu Plurmeditekon", + "TaskRefreshLibrary": "Skani Plurmeditekon", "ValueSpecialEpisodeName": "Speciala - {0}", - "TaskOptimizeDatabase": "Optimigi datumbazon", + "TaskOptimizeDatabase": "Optimigi datenbazon", "TaskRefreshChannels": "Refreŝigi Kanalojn", "TaskUpdatePlugins": "Ĝisdatigi Kromprogramojn", "TaskRefreshPeople": "Refreŝigi Homojn", "TasksChannelsCategory": "Interretaj Kanaloj", "ProviderValue": "Provizanto: {0}", - "NotificationOptionPluginError": "Kromprograma malsukceso", + "NotificationOptionPluginError": "Kromprogramo malsukcesis", "MixedContent": "Miksita enhavo", "TasksApplicationCategory": "Aplikaĵo", "TasksMaintenanceCategory": "Prizorgado", @@ -102,9 +102,9 @@ "MessageApplicationUpdatedTo": "Jellyfin Server estis ĝisdatigita al {0}", "MessageApplicationUpdated": "Jellyfin Server estis ĝisdatigita", "TaskRefreshChannelsDescription": "Refreŝigas informon pri interretaj kanaloj.", - "TaskDownloadMissingSubtitles": "Elŝutu mankantajn subtekstojn", + "TaskDownloadMissingSubtitles": "Elŝuti mankantajn subtekstojn", "TaskCleanTranscode": "Malplenigi Transkodadan Katalogon", - "TaskRefreshChapterImages": "Eltiru Ĉapitro-Bildojn", + "TaskRefreshChapterImages": "Eltiri Ĉapitraj Bildojn", "TaskCleanCache": "Malplenigi Staplan Katalogon", "TaskCleanActivityLog": "Malplenigi Aktivecan Ĵurnalon", "PluginUpdatedWithName": "{0} estis ĝisdatigita", -- cgit v1.2.3 From 13668a6ecb40b4b68f1cfaebfb7bb3807e9a9cef Mon Sep 17 00:00:00 2001 From: WWWesten Date: Thu, 4 Nov 2021 10:35:48 +0000 Subject: Translated using Weblate (Russian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ru/ --- Emby.Server.Implementations/Localization/Core/ru.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json index cd016b51b..36f4e3e7c 100644 --- a/Emby.Server.Implementations/Localization/Core/ru.json +++ b/Emby.Server.Implementations/Localization/Core/ru.json @@ -119,6 +119,6 @@ "Undefined": "Не определено", "Forced": "Форсир-ые", "Default": "По умолчанию", - "TaskOptimizeDatabaseDescription": "Сжимает базу данных и обрезает свободное место. Выполнение этой задачи после сканирования библиотеки или внесения других изменений, предполагающих модификации базы данных, может повысить производительность.", + "TaskOptimizeDatabaseDescription": "Сжимает базу данных и вырезает свободные места. Выполнение этой задачи после сканирования библиотеки или внесения других изменений, предполагающих модификации базы данных, может повысить производительность.", "TaskOptimizeDatabase": "Оптимизировать базу данных" } -- cgit v1.2.3 From 1e93c6ae3052653efbadba29657f83c660b35941 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Thu, 4 Nov 2021 10:32:21 +0000 Subject: Translated using Weblate (Esperanto) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/eo/ --- Emby.Server.Implementations/Localization/Core/eo.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/eo.json b/Emby.Server.Implementations/Localization/Core/eo.json index 8ac466908..12541a756 100644 --- a/Emby.Server.Implementations/Localization/Core/eo.json +++ b/Emby.Server.Implementations/Localization/Core/eo.json @@ -52,7 +52,7 @@ "TaskCleanLogs": "Purigi Ĵurnalan Katalogon", "TaskRefreshLibrary": "Skani Plurmeditekon", "ValueSpecialEpisodeName": "Speciala - {0}", - "TaskOptimizeDatabase": "Optimigi datenbazon", + "TaskOptimizeDatabase": "Optimumigi datenbazon", "TaskRefreshChannels": "Refreŝigi Kanalojn", "TaskUpdatePlugins": "Ĝisdatigi Kromprogramojn", "TaskRefreshPeople": "Refreŝigi Homojn", @@ -75,7 +75,7 @@ "ServerNameNeedsToBeRestarted": "{0} devas esti relanĉita", "NotificationOptionVideoPlayback": "La videoludado lanĉis", "NotificationOptionServerRestartRequired": "Servila relanĉigo bezonata", - "TaskOptimizeDatabaseDescription": "Kompaktigas datenbazon kaj trunkas liberan lokon. Lanĉi ĉi tiun taskon post la teka skanado aŭ fari aliajn ŝanĝojn, kiuj implicas datenbazajn modifojn, povus plibonigi rendimenton.", + "TaskOptimizeDatabaseDescription": "Kompaktigas datenbazon kaj trunkas liberan lokon. Lanĉi ĉi tiun taskon post la plurmediteka skanado aŭ fari aliajn ŝanĝojn, kiuj implicas datenbazajn modifojn, povus plibonigi rendimenton.", "TaskUpdatePluginsDescription": "Elŝutas kaj instalas ĝisdatigojn por kromprogramojn, kiuj estas agorditaj por ĝisdatigi aŭtomate.", "TaskDownloadMissingSubtitlesDescription": "Serĉas en interreto mankantajn subtekstojn surbaze de metadatena agordaro.", "TaskRefreshPeopleDescription": "Ĝisdatigas metadatenojn por aktoroj kaj reĵisoroj en via plurmediteko.", -- cgit v1.2.3 From b4bf5af7c8b169c616ca5a9bc83248a80636bedb Mon Sep 17 00:00:00 2001 From: Joe Rogers <1337joe@gmail.com> Date: Fri, 5 Nov 2021 21:31:12 +0100 Subject: Remove ImageType.Screenshot and ItemFields.Screenshot --- Emby.Server.Implementations/Dto/DtoService.cs | 9 -------- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.Model/Entities/ImageType.cs | 3 +++ MediaBrowser.Model/Querying/ItemFields.cs | 3 +++ MediaBrowser.Providers/Manager/ImageSaver.cs | 3 --- .../Manager/ItemImageProvider.cs | 26 +++------------------- .../Manager/ItemImageProviderTests.cs | 2 -- 7 files changed, 10 insertions(+), 38 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index ad76f3d6d..9287f5272 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -755,15 +755,6 @@ namespace Emby.Server.Implementations.Dto dto.BackdropImageTags = GetTagsAndFillBlurhashes(dto, item, ImageType.Backdrop, backdropLimit); } - if (options.ContainsField(ItemFields.ScreenshotImageTags)) - { - var screenshotLimit = options.GetImageLimit(ImageType.Screenshot); - if (screenshotLimit > 0) - { - dto.ScreenshotImageTags = GetTagsAndFillBlurhashes(dto, item, ImageType.Screenshot, screenshotLimit); - } - } - if (options.ContainsField(ItemFields.Genres)) { dto.Genres = item.Genres; diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 0df70705e..63749b1f3 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2577,7 +2577,7 @@ namespace MediaBrowser.Controller.Entities public bool AllowsMultipleImages(ImageType type) { - return type == ImageType.Backdrop || type == ImageType.Screenshot || type == ImageType.Chapter; + return type == ImageType.Backdrop || type == ImageType.Chapter; } public Task SwapImagesAsync(ImageType type, int index1, int index2) diff --git a/MediaBrowser.Model/Entities/ImageType.cs b/MediaBrowser.Model/Entities/ImageType.cs index 6ea9ee419..ee7410632 100644 --- a/MediaBrowser.Model/Entities/ImageType.cs +++ b/MediaBrowser.Model/Entities/ImageType.cs @@ -1,3 +1,5 @@ +using System; + namespace MediaBrowser.Model.Entities { /// @@ -48,6 +50,7 @@ namespace MediaBrowser.Model.Entities /// /// The screenshot. /// + [Obsolete("Screenshot image type is no longer used.")] Screenshot = 8, /// diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index ef4698f3f..e6c3a6c26 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -1,5 +1,7 @@ #pragma warning disable CS1591 +using System; + namespace MediaBrowser.Model.Querying { /// @@ -143,6 +145,7 @@ namespace MediaBrowser.Model.Querying /// /// The screenshot image tags. /// + [Obsolete("Screenshot image type is no longer used.")] ScreenshotImageTags, SeriesPrimaryImage, diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 8ded2d144..d2a3344be 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -439,9 +439,6 @@ namespace MediaBrowser.Providers.Manager case ImageType.Backdrop: filename = GetBackdropSaveFilename(item.GetImages(type), "backdrop", "backdrop", imageIndex); break; - case ImageType.Screenshot: - filename = GetBackdropSaveFilename(item.GetImages(type), "screenshot", "screenshot", imageIndex); - break; default: filename = type.ToString().ToLowerInvariant(); break; diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index d5959db77..1022a3fae 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -109,12 +109,6 @@ namespace MediaBrowser.Providers.Manager oldBackdropImages = item.GetImages(ImageType.Backdrop).ToArray(); } - var oldScreenshotImages = Array.Empty(); - if (refreshOptions.IsReplacingImage(ImageType.Screenshot)) - { - oldScreenshotImages = item.GetImages(ImageType.Screenshot).ToArray(); - } - var result = new RefreshResult { UpdateType = ItemUpdateType.None }; var typeName = item.GetType().Name; @@ -122,14 +116,13 @@ namespace MediaBrowser.Providers.Manager // track library limits, adding buffer to allow lazy replacing of current images var backdropLimit = typeOptions.GetLimit(ImageType.Backdrop) + oldBackdropImages.Length; - var screenshotLimit = typeOptions.GetLimit(ImageType.Screenshot) + oldScreenshotImages.Length; var downloadedImages = new List(); foreach (var provider in providers) { if (provider is IRemoteImageProvider remoteProvider) { - await RefreshFromProvider(item, remoteProvider, refreshOptions, typeOptions, backdropLimit, screenshotLimit, downloadedImages, result, cancellationToken).ConfigureAwait(false); + await RefreshFromProvider(item, remoteProvider, refreshOptions, typeOptions, backdropLimit, downloadedImages, result, cancellationToken).ConfigureAwait(false); continue; } @@ -145,11 +138,6 @@ namespace MediaBrowser.Providers.Manager PruneImages(item, oldBackdropImages); } - if (oldScreenshotImages.Length > 0 && oldScreenshotImages.Length < item.GetImages(ImageType.Screenshot).Count()) - { - PruneImages(item, oldScreenshotImages); - } - return result; } @@ -243,9 +231,8 @@ namespace MediaBrowser.Providers.Manager /// The images. /// The saved options. /// The backdrop limit. - /// The screenshot limit. /// true if the specified item contains images; otherwise, false. - private bool ContainsImages(BaseItem item, List images, TypeOptions savedOptions, int backdropLimit, int screenshotLimit) + private bool ContainsImages(BaseItem item, List images, TypeOptions savedOptions, int backdropLimit) { // Using .Any causes the creation of a DisplayClass aka. variable capture for (var i = 0; i < _singularImages.Length; i++) @@ -262,11 +249,6 @@ namespace MediaBrowser.Providers.Manager return false; } - if (images.Contains(ImageType.Screenshot) && item.GetImages(ImageType.Screenshot).Count() < screenshotLimit) - { - return false; - } - return true; } @@ -278,7 +260,6 @@ namespace MediaBrowser.Providers.Manager /// The refresh options. /// The saved options. /// The backdrop limit. - /// The screenshot limit. /// The downloaded images. /// The result. /// The cancellation token. @@ -289,7 +270,6 @@ namespace MediaBrowser.Providers.Manager ImageRefreshOptions refreshOptions, TypeOptions savedOptions, int backdropLimit, - int screenshotLimit, ICollection downloadedImages, RefreshResult result, CancellationToken cancellationToken) @@ -303,7 +283,7 @@ namespace MediaBrowser.Providers.Manager if (!refreshOptions.ReplaceAllImages && refreshOptions.ReplaceImages.Length == 0 && - ContainsImages(item, provider.GetSupportedImages(item).ToList(), savedOptions, backdropLimit, screenshotLimit)) + ContainsImages(item, provider.GetSupportedImages(item).ToList(), savedOptions, backdropLimit)) { return; } diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs index 6011c8dd5..9f73ed7fc 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs @@ -207,10 +207,8 @@ namespace Jellyfin.Providers.Tests.Manager [Theory] [InlineData(ImageType.Primary, 1, false)] [InlineData(ImageType.Backdrop, 2, false)] - [InlineData(ImageType.Screenshot, 2, false)] [InlineData(ImageType.Primary, 1, true)] [InlineData(ImageType.Backdrop, 2, true)] - [InlineData(ImageType.Screenshot, 2, true)] public async void RefreshImages_PopulatedItemPopulatedProviderDynamic_UpdatesImagesIfForced(ImageType imageType, int imageCount, bool forceRefresh) { var item = GetItemWithImages(imageType, imageCount, false); -- cgit v1.2.3 From d95c281142462277560e1f9ac8d9e28db9c7b242 Mon Sep 17 00:00:00 2001 From: cvium Date: Sat, 6 Nov 2021 22:44:05 +0100 Subject: Load all types when checking plugin DLLs --- Emby.Server.Implementations/Plugins/PluginManager.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index d52c0b2a1..d70a15dbc 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -126,7 +126,8 @@ namespace Emby.Server.Implementations.Plugins { assembly = Assembly.LoadFrom(file); - assembly.GetExportedTypes(); + // Load all required types to verify that the plugin will load + assembly.GetTypes(); } catch (FileLoadException ex) { @@ -134,7 +135,7 @@ namespace Emby.Server.Implementations.Plugins ChangePluginState(plugin, PluginStatus.Malfunctioned); continue; } - catch (TypeLoadException ex) // Undocumented exception + catch (SystemException ex) when (ex is TypeLoadException or ReflectionTypeLoadException) // Undocumented exception { _logger.LogError(ex, "Failed to load assembly {Path}. This error occurs when a plugin references an incompatible version of one of the shared libraries. Disabling plugin.", file); ChangePluginState(plugin, PluginStatus.NotSupported); -- cgit v1.2.3 From 0f528966919518a190c33291946ba5947cc29670 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 7 Nov 2021 15:33:39 +0100 Subject: Fix UnauthorizedAccessException in GetDrives ``` [15:01:24] [ERR] [55] Jellyfin.Server.Middleware.ExceptionMiddleware: Error processing request. URL GET /Environment/Drives. System.UnauthorizedAccessException: Access to the path is denied. ---> System.IO.IOException: Operation not permitted --- End of inner exception stack trace --- at System.IO.DriveInfo.CheckStatfsResultAndThrowIfNecessary(Int32 result) at System.IO.DriveInfo.get_TotalSize() at Emby.Server.Implementations.IO.ManagedFileSystem.<>c.b__32_0(DriveInfo d) in /home/bond/dev/jellyfin/Emby.Server.Implementations/IO/ManagedFileSystem.cs:line 583 at System.Linq.Enumerable.WhereSelectArrayIterator`2.ToList() at Emby.Server.Implementations.IO.ManagedFileSystem.GetDrives() in /home/bond/dev/jellyfin/Emby.Server.Implementations/IO/ManagedFileSystem.cs:line 583 at Jellyfin.Api.Controllers.EnvironmentController.GetDrives() in /home/bond/dev/jellyfin/Jellyfin.Api/Controllers/EnvironmentController.cs:line 153 at lambda_method559(Closure , Object , Object[] ) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync() at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync() ``` --- Emby.Server.Implementations/IO/ManagedFileSystem.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index eeee28842..3aefb841e 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -580,7 +580,11 @@ namespace Emby.Server.Implementations.IO { // check for ready state to avoid waiting for drives to timeout // some drives on linux have no actual size or are used for other purposes - return DriveInfo.GetDrives().Where(d => d.IsReady && d.TotalSize != 0 && d.DriveType != DriveType.Ram) + return DriveInfo.GetDrives() + .Where( + d => (d.DriveType == DriveType.Fixed || d.DriveType == DriveType.Network || d.DriveType == DriveType.Removable) + && d.IsReady + && d.TotalSize != 0) .Select(d => new FileSystemMetadata { Name = d.Name, -- cgit v1.2.3 From 4dfb7b18ae6e49003da702aefa449bca0bbecaf4 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 7 Nov 2021 22:32:08 +0100 Subject: Add some docs and tests --- .../IO/ManagedFileSystem.cs | 37 ++++++++++++++++++---- .../Library/MediaSourceManager.cs | 37 ++++++++-------------- .../Library/IMediaSourceManager.cs | 7 ---- .../Library/MediaSourceManagerTests.cs | 32 +++++++++++++++++++ 4 files changed, 75 insertions(+), 38 deletions(-) create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Library/MediaSourceManagerTests.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 3aefb841e..777cd2cd4 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -1,5 +1,3 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.Globalization; @@ -23,6 +21,11 @@ namespace Emby.Server.Implementations.IO private readonly string _tempPath; private static readonly bool _isEnvironmentCaseInsensitive = OperatingSystem.IsWindows(); + /// + /// Initializes a new instance of the class. + /// + /// The instance to use. + /// The instance to use. public ManagedFileSystem( ILogger logger, IApplicationPaths applicationPaths) @@ -31,6 +34,7 @@ namespace Emby.Server.Implementations.IO _tempPath = applicationPaths.TempDirectory; } + /// public virtual void AddShortcutHandler(IShortcutHandler handler) { _shortcutHandlers.Add(handler); @@ -72,6 +76,7 @@ namespace Emby.Server.Implementations.IO return handler?.Resolve(filename); } + /// public virtual string MakeAbsolutePath(string folderPath, string filePath) { // path is actually a stream @@ -358,11 +363,13 @@ namespace Emby.Server.Implementations.IO return GetCreationTimeUtc(GetFileSystemInfo(path)); } + /// public virtual DateTime GetCreationTimeUtc(FileSystemMetadata info) { return info.CreationTimeUtc; } + /// public virtual DateTime GetLastWriteTimeUtc(FileSystemMetadata info) { return info.LastWriteTimeUtc; @@ -397,6 +404,7 @@ namespace Emby.Server.Implementations.IO return GetLastWriteTimeUtc(GetFileSystemInfo(path)); } + /// public virtual void SetHidden(string path, bool isHidden) { if (!OperatingSystem.IsWindows()) @@ -421,6 +429,7 @@ namespace Emby.Server.Implementations.IO } } + /// public virtual void SetAttributes(string path, bool isHidden, bool readOnly) { if (!OperatingSystem.IsWindows()) @@ -444,7 +453,7 @@ namespace Emby.Server.Implementations.IO if (readOnly) { - attributes = attributes | FileAttributes.ReadOnly; + attributes |= FileAttributes.ReadOnly; } else { @@ -453,7 +462,7 @@ namespace Emby.Server.Implementations.IO if (isHidden) { - attributes = attributes | FileAttributes.Hidden; + attributes |= FileAttributes.Hidden; } else { @@ -498,6 +507,7 @@ namespace Emby.Server.Implementations.IO File.Copy(temp1, file2, true); } + /// public virtual bool ContainsSubPath(string parentPath, string path) { if (string.IsNullOrEmpty(parentPath)) @@ -515,6 +525,7 @@ namespace Emby.Server.Implementations.IO _isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); } + /// public virtual string NormalizePath(string path) { if (string.IsNullOrEmpty(path)) @@ -530,6 +541,7 @@ namespace Emby.Server.Implementations.IO return Path.TrimEndingDirectorySeparator(path); } + /// public virtual bool AreEqual(string path1, string path2) { if (path1 == null && path2 == null) @@ -548,6 +560,7 @@ namespace Emby.Server.Implementations.IO _isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); } + /// public virtual string GetFileNameWithoutExtension(FileSystemMetadata info) { if (info.IsDirectory) @@ -558,11 +571,11 @@ namespace Emby.Server.Implementations.IO return Path.GetFileNameWithoutExtension(info.FullName); } + /// public virtual bool IsPathFile(string path) { - // Cannot use Path.IsPathRooted because it returns false under mono when using windows-based paths, e.g. C:\\ - if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 && - !path.StartsWith("file://", StringComparison.OrdinalIgnoreCase)) + if (path.Contains("://", StringComparison.OrdinalIgnoreCase) + && !path.StartsWith("file://", StringComparison.OrdinalIgnoreCase)) { return false; } @@ -570,12 +583,14 @@ namespace Emby.Server.Implementations.IO return true; } + /// public virtual void DeleteFile(string path) { SetAttributes(path, false, false); File.Delete(path); } + /// public virtual List GetDrives() { // check for ready state to avoid waiting for drives to timeout @@ -593,16 +608,19 @@ namespace Emby.Server.Implementations.IO }).ToList(); } + /// public virtual IEnumerable GetDirectories(string path, bool recursive = false) { return ToMetadata(new DirectoryInfo(path).EnumerateDirectories("*", GetEnumerationOptions(recursive))); } + /// public virtual IEnumerable GetFiles(string path, bool recursive = false) { return GetFiles(path, null, false, recursive); } + /// public virtual IEnumerable GetFiles(string path, IReadOnlyList? extensions, bool enableCaseSensitiveExtensions, bool recursive = false) { var enumerationOptions = GetEnumerationOptions(recursive); @@ -633,6 +651,7 @@ namespace Emby.Server.Implementations.IO return ToMetadata(files); } + /// public virtual IEnumerable GetFileSystemEntries(string path, bool recursive = false) { var directoryInfo = new DirectoryInfo(path); @@ -646,16 +665,19 @@ namespace Emby.Server.Implementations.IO return infos.Select(GetFileSystemMetadata); } + /// public virtual IEnumerable GetDirectoryPaths(string path, bool recursive = false) { return Directory.EnumerateDirectories(path, "*", GetEnumerationOptions(recursive)); } + /// public virtual IEnumerable GetFilePaths(string path, bool recursive = false) { return GetFilePaths(path, null, false, recursive); } + /// public virtual IEnumerable GetFilePaths(string path, string[]? extensions, bool enableCaseSensitiveExtensions, bool recursive = false) { var enumerationOptions = GetEnumerationOptions(recursive); @@ -686,6 +708,7 @@ namespace Emby.Server.Implementations.IO return files; } + /// public virtual IEnumerable GetFileSystemEntryPaths(string path, bool recursive = false) { return Directory.EnumerateFileSystemEntries(path, "*", GetEnumerationOptions(recursive)); diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 351fced34..972d4ebbb 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -45,6 +45,7 @@ namespace Emby.Server.Implementations.Library private readonly IMediaEncoder _mediaEncoder; private readonly ILocalizationManager _localizationManager; private readonly IApplicationPaths _appPaths; + private readonly IDirectoryService _directoryService; private readonly ConcurrentDictionary _openStreams = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1); @@ -61,7 +62,8 @@ namespace Emby.Server.Implementations.Library ILogger logger, IFileSystem fileSystem, IUserDataManager userDataManager, - IMediaEncoder mediaEncoder) + IMediaEncoder mediaEncoder, + IDirectoryService directoryService) { _itemRepo = itemRepo; _userManager = userManager; @@ -72,6 +74,7 @@ namespace Emby.Server.Implementations.Library _mediaEncoder = mediaEncoder; _localizationManager = localizationManager; _appPaths = applicationPaths; + _directoryService = directoryService; } public void AddParts(IEnumerable providers) @@ -106,16 +109,6 @@ namespace Emby.Server.Implementations.Library return false; } - public List GetMediaStreams(string mediaSourceId) - { - var list = GetMediaStreams(new MediaStreamQuery - { - ItemId = new Guid(mediaSourceId) - }); - - return GetMediaStreamsForItem(list); - } - public List GetMediaStreams(Guid itemId) { var list = GetMediaStreams(new MediaStreamQuery @@ -161,7 +154,7 @@ namespace Emby.Server.Implementations.Library if (allowMediaProbe && mediaSources[0].Type != MediaSourceType.Placeholder && !mediaSources[0].MediaStreams.Any(i => i.Type == MediaStreamType.Audio || i.Type == MediaStreamType.Video)) { await item.RefreshMetadata( - new MetadataRefreshOptions(new DirectoryService(_fileSystem)) + new MetadataRefreshOptions(_directoryService) { EnableRemoteContentProbe = true, MetadataRefreshMode = MetadataRefreshMode.FullRefresh @@ -212,6 +205,7 @@ namespace Emby.Server.Implementations.Library return SortMediaSources(list); } + /// > public MediaProtocol GetPathProtocol(string path) { if (path.StartsWith("Rtsp", StringComparison.OrdinalIgnoreCase)) @@ -258,7 +252,7 @@ namespace Emby.Server.Implementations.Library { if (path != null) { - if (path.IndexOf(".m3u", StringComparison.OrdinalIgnoreCase) != -1) + if (path.Contains(".m3u", StringComparison.OrdinalIgnoreCase)) { return false; } @@ -297,7 +291,7 @@ namespace Emby.Server.Implementations.Library catch (Exception ex) { _logger.LogError(ex, "Error getting media sources"); - return new List(); + return Enumerable.Empty(); } } @@ -494,14 +488,11 @@ namespace Emby.Server.Implementations.Library _liveStreamSemaphore.Release(); } - // TODO: Don't hardcode this - const bool isAudio = false; - try { if (mediaSource.MediaStreams.Any(i => i.Index != -1) || !mediaSource.SupportsProbing) { - AddMediaInfo(mediaSource, isAudio); + AddMediaInfo(mediaSource); } else { @@ -509,14 +500,14 @@ namespace Emby.Server.Implementations.Library string cacheKey = request.OpenToken; await new LiveStreamHelper(_mediaEncoder, _logger, _appPaths) - .AddMediaInfoWithProbe(mediaSource, isAudio, cacheKey, true, cancellationToken) + .AddMediaInfoWithProbe(mediaSource, false, cacheKey, true, cancellationToken) .ConfigureAwait(false); } } catch (Exception ex) { _logger.LogError(ex, "Error probing live tv stream"); - AddMediaInfo(mediaSource, isAudio); + AddMediaInfo(mediaSource); } // TODO: @bond Fix @@ -536,7 +527,7 @@ namespace Emby.Server.Implementations.Library return new Tuple(new LiveStreamResponse(clone), liveStream as IDirectStreamProvider); } - private static void AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio) + private static void AddMediaInfo(MediaSourceInfo mediaSource) { mediaSource.DefaultSubtitleStreamIndex = null; @@ -855,9 +846,7 @@ namespace Emby.Server.Implementations.Library return (provider, keyId); } - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// + /// public void Dispose() { Dispose(true); diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index e802796d3..f1758a9d8 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -30,13 +30,6 @@ namespace MediaBrowser.Controller.Library /// IEnumerable<MediaStream>. List GetMediaStreams(Guid itemId); - /// - /// Gets the media streams. - /// - /// The media source identifier. - /// IEnumerable<MediaStream>. - List GetMediaStreams(string mediaSourceId); - /// /// Gets the media streams. /// diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/MediaSourceManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/MediaSourceManagerTests.cs new file mode 100644 index 000000000..8ed3d8b94 --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/MediaSourceManagerTests.cs @@ -0,0 +1,32 @@ +using AutoFixture; +using AutoFixture.AutoMoq; +using Emby.Server.Implementations.IO; +using Emby.Server.Implementations.Library; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.MediaInfo; +using Xunit; + +namespace Jellyfin.Server.Implementations.Tests.Library +{ + public class MediaSourceManagerTests + { + private readonly MediaSourceManager _mediaSourceManager; + + public MediaSourceManagerTests() + { + IFixture fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true }); + fixture.Inject(fixture.Create()); + _mediaSourceManager = fixture.Create(); + } + + [Theory] + [InlineData(@"C:\mydir\myfile.ext", MediaProtocol.File)] + [InlineData("/mydir/myfile.ext", MediaProtocol.File)] + [InlineData("file:///mydir/myfile.ext", MediaProtocol.File)] + [InlineData("http://example.com/stream.m3u8", MediaProtocol.Http)] + [InlineData("https://example.com/stream.m3u8", MediaProtocol.Http)] + [InlineData("rtsp://media.example.com:554/twister/audiotrack", MediaProtocol.Rtsp)] + public void GetPathProtocol_ValidArg_Correct(string path, MediaProtocol expected) + => Assert.Equal(expected, _mediaSourceManager.GetPathProtocol(path)); + } +} -- cgit v1.2.3 From 82e6a21f3bff6a3666a6c28d218ed936457cf5d1 Mon Sep 17 00:00:00 2001 From: cvium Date: Mon, 8 Nov 2021 10:58:04 +0100 Subject: Use the new method in DLNA --- Emby.Dlna/Main/DlnaEntryPoint.cs | 15 ++++----------- Emby.Server.Implementations/ApplicationHost.cs | 9 ++++++--- MediaBrowser.Controller/IServerApplicationHost.cs | 5 +++-- 3 files changed, 13 insertions(+), 16 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 5d252d8dc..8e89d9ae6 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -52,7 +52,6 @@ namespace Emby.Dlna.Main private readonly ISocketFactory _socketFactory; private readonly INetworkManager _networkManager; private readonly object _syncLock = new object(); - private readonly NetworkConfiguration _netConfig; private readonly bool _disabled; private PlayToManager _manager; @@ -125,8 +124,8 @@ namespace Emby.Dlna.Main config); Current = this; - _netConfig = config.GetConfiguration("network"); - _disabled = appHost.ListenWithHttps && _netConfig.RequireHttps; + var netConfig = config.GetConfiguration("network"); + _disabled = appHost.ListenWithHttps && netConfig.RequireHttps; if (_disabled && _config.GetDlnaConfiguration().EnableServer) { @@ -318,15 +317,9 @@ namespace Emby.Dlna.Main var fullService = "urn:schemas-upnp-org:device:MediaServer:1"; - _logger.LogInformation("Registering publisher for {0} on {1}", fullService, address); + _logger.LogInformation("Registering publisher for {ResourceName} on {DeviceAddress}", fullService, address); - var uri = new UriBuilder(_appHost.GetSmartApiUrl(address.Address) + descriptorUri); - if (!string.IsNullOrEmpty(_appHost.PublishedServerUrl)) - { - // DLNA will only work over http, so we must reset to http:// : {port}. - uri.Scheme = "http"; - uri.Port = _netConfig.HttpServerPortNumber; - } + var uri = new UriBuilder(_appHost.GetApiUrlForLocalAccess(false) + descriptorUri); var device = new SsdpRootDevice { diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 7da0e2f21..4f2fdfd3c 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -1166,10 +1166,13 @@ namespace Emby.Server.Implementations } /// - public string GetApiUrlForLocalAccess() + public string GetApiUrlForLocalAccess(bool allowHttps) { - string smart = NetManager.GetBindInterface(string.Empty, out var port); - return GetLocalApiUrl(smart.Trim('/'), null, port); + // With an empty source, the port will be null + string smart = NetManager.GetBindInterface(string.Empty, out _); + var scheme = allowHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp; + var port = allowHttps ? HttpsPort : HttpPort; + return GetLocalApiUrl(smart.Trim('/'), scheme, port); } /// diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index ff7f9372f..7da492af3 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -81,10 +81,11 @@ namespace MediaBrowser.Controller string GetSmartApiUrl(string hostname, int? port = null); /// - /// Gets an URL that can be used to access the API over HTTP (not HTTPS). + /// Gets an URL that can be used to access the API over LAN. /// + /// A value indicating whether to allow HTTPS. /// The API URL. - string GetApiUrlForLocalAccess(); + string GetApiUrlForLocalAccess(bool allowHttps = true); /// /// Gets a local (LAN) URL that can be used to access the API. -- cgit v1.2.3 From 15dd23e4da10847537e7a8a49d0f75ab0b2fd339 Mon Sep 17 00:00:00 2001 From: rimasx Date: Sun, 7 Nov 2021 20:49:19 +0000 Subject: Translated using Weblate (Estonian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/et/ --- Emby.Server.Implementations/Localization/Core/et.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/et.json b/Emby.Server.Implementations/Localization/Core/et.json index c3596ecf1..e5405e515 100644 --- a/Emby.Server.Implementations/Localization/Core/et.json +++ b/Emby.Server.Implementations/Localization/Core/et.json @@ -17,7 +17,7 @@ "TaskCleanLogsDescription": "Kustutab logifailid, mis on vanemad kui {0} päeva.", "TaskCleanLogs": "Puhasta logikataloog", "TaskRefreshLibraryDescription": "Otsib meedikogust uusi faile ja värskendab metaandmeid.", - "Collections": "Kollektsioonid", + "Collections": "Kogumikud", "TaskRefreshLibrary": "Skaneeri meediakogu", "TaskRefreshChapterImagesDescription": "Loob peatükkidega videote jaoks pisipildid.", "TaskRefreshChapterImages": "Eralda peatükipildid", -- cgit v1.2.3 From 40045d21470ce0eb15e5c9700d6a1449dbf7c36e Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Mon, 8 Nov 2021 06:55:16 -0700 Subject: Update to full dotnet 6 --- .ci/azure-pipelines-abi.yml | 1 - .ci/azure-pipelines-main.yml | 1 - .ci/azure-pipelines-package.yml | 1 - .ci/azure-pipelines-test.yml | 1 - .github/workflows/codeql-analysis.yml | 3 +-- .github/workflows/openapi.yml | 2 -- Emby.Dlna/Emby.Dlna.csproj | 2 +- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 10 +++++----- Jellyfin.Api/Jellyfin.Api.csproj | 4 ++-- Jellyfin.Data/Jellyfin.Data.csproj | 2 +- .../Jellyfin.Server.Implementations.csproj | 8 ++++---- Jellyfin.Server/Jellyfin.Server.csproj | 8 ++++---- MediaBrowser.Common/MediaBrowser.Common.csproj | 4 ++-- MediaBrowser.Controller/MediaBrowser.Controller.csproj | 6 +++--- MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj | 4 ++-- MediaBrowser.Model/MediaBrowser.Model.csproj | 4 ++-- MediaBrowser.Providers/MediaBrowser.Providers.csproj | 6 +++--- deployment/Dockerfile.centos.amd64 | 2 +- deployment/Dockerfile.fedora.amd64 | 2 +- deployment/Dockerfile.ubuntu.amd64 | 2 +- deployment/Dockerfile.ubuntu.arm64 | 2 +- deployment/Dockerfile.ubuntu.armhf | 2 +- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 4 ++-- .../Jellyfin.Server.Integration.Tests.csproj | 4 ++-- tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj | 4 ++-- 25 files changed, 41 insertions(+), 48 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/.ci/azure-pipelines-abi.yml b/.ci/azure-pipelines-abi.yml index 31f861f63..cf74a4201 100644 --- a/.ci/azure-pipelines-abi.yml +++ b/.ci/azure-pipelines-abi.yml @@ -34,7 +34,6 @@ jobs: inputs: packageType: sdk version: ${{ parameters.DotNetSdkVersion }} - includePreviewVersions: true - task: DotNetCoreCLI@2 displayName: 'Install ABI CompatibilityChecker Tool' diff --git a/.ci/azure-pipelines-main.yml b/.ci/azure-pipelines-main.yml index 1086d51d2..b7112ba24 100644 --- a/.ci/azure-pipelines-main.yml +++ b/.ci/azure-pipelines-main.yml @@ -54,7 +54,6 @@ jobs: inputs: packageType: sdk version: ${{ parameters.DotNetSdkVersion }} - includePreviewVersions: true - task: DotNetCoreCLI@2 displayName: 'Publish Server' diff --git a/.ci/azure-pipelines-package.yml b/.ci/azure-pipelines-package.yml index 4abe52b43..e227d5fe6 100644 --- a/.ci/azure-pipelines-package.yml +++ b/.ci/azure-pipelines-package.yml @@ -199,7 +199,6 @@ jobs: inputs: packageType: 'sdk' version: '6.0.x' - includePreviewVersions: true - task: DotNetCoreCLI@2 displayName: 'Build Stable Nuget packages' diff --git a/.ci/azure-pipelines-test.yml b/.ci/azure-pipelines-test.yml index 80a5732ee..cc94dc2c5 100644 --- a/.ci/azure-pipelines-test.yml +++ b/.ci/azure-pipelines-test.yml @@ -41,7 +41,6 @@ jobs: inputs: packageType: sdk version: ${{ parameters.DotNetSdkVersion }} - includePreviewVersions: true - task: SonarCloudPrepare@1 displayName: 'Prepare analysis on SonarCloud' diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e07d913b5..ea1d30cdf 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -25,8 +25,7 @@ jobs: uses: actions/setup-dotnet@v1 with: dotnet-version: '6.0.x' - include-prerelease: true - + - name: Initialize CodeQL uses: github/codeql-action/init@v1 with: diff --git a/.github/workflows/openapi.yml b/.github/workflows/openapi.yml index ea9188f1b..3e9346840 100644 --- a/.github/workflows/openapi.yml +++ b/.github/workflows/openapi.yml @@ -20,7 +20,6 @@ jobs: uses: actions/setup-dotnet@v1 with: dotnet-version: '6.0.x' - include-prerelease: true - name: Generate openapi.json run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests" - name: Upload openapi.json @@ -45,7 +44,6 @@ jobs: uses: actions/setup-dotnet@v1 with: dotnet-version: '6.0.x' - include-prerelease: true - name: Generate openapi.json run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests" - name: Upload openapi.json diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index c8332e44e..7fdbd44f0 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -72,7 +72,7 @@ - + diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index c1ce4b557..03f9f50ea 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -25,11 +25,11 @@ - - - - - + + + + + diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 57480b2f3..a3598edfa 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 2de53e7c8..248b29cbb 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -35,7 +35,7 @@ - + diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index e26cf093b..73ee69424 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -19,13 +19,13 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index a75d747be..045ed6a2b 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -31,10 +31,10 @@ - - - - + + + + diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 9c8ce4ac5..587fbcee0 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -19,8 +19,8 @@ - - + + diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index d37880865..71466ce3a 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -15,10 +15,10 @@ - - + + - + diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index c1fd8e5fb..6bb8bcdab 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -24,8 +24,8 @@ - - + + diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 16bc4adf8..1ac0f1d5e 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -30,9 +30,9 @@ - + - + diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 9d0a6944b..b42112111 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/deployment/Dockerfile.centos.amd64 b/deployment/Dockerfile.centos.amd64 index 78f051e4f..3967a165d 100644 --- a/deployment/Dockerfile.centos.amd64 +++ b/deployment/Dockerfile.centos.amd64 @@ -13,7 +13,7 @@ RUN yum update -yq \ && yum install -yq @buildsys-build rpmdevtools yum-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel git wget # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/17b6759f-1af0-41bc-ab12-209ba0377779/e8d02195dbf1434b940e0f05ae086453/dotnet-sdk-6.0.100-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.fedora.amd64 b/deployment/Dockerfile.fedora.amd64 index 14eeb6eed..bc40a8059 100644 --- a/deployment/Dockerfile.fedora.amd64 +++ b/deployment/Dockerfile.fedora.amd64 @@ -12,7 +12,7 @@ RUN dnf update -yq \ && dnf install -yq @buildsys-build rpmdevtools git dnf-plugins-core libcurl-devel fontconfig-devel freetype-devel openssl-devel glibc-devel libicu-devel systemd wget # Install DotNET SDK -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/17b6759f-1af0-41bc-ab12-209ba0377779/e8d02195dbf1434b940e0f05ae086453/dotnet-sdk-6.0.100-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.amd64 b/deployment/Dockerfile.ubuntu.amd64 index 8733be89c..c1b541c59 100644 --- a/deployment/Dockerfile.ubuntu.amd64 +++ b/deployment/Dockerfile.ubuntu.amd64 @@ -17,7 +17,7 @@ RUN apt-get update -yqq \ libfreetype6-dev libssl-dev libssl1.1 liblttng-ust0 # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/17b6759f-1af0-41bc-ab12-209ba0377779/e8d02195dbf1434b940e0f05ae086453/dotnet-sdk-6.0.100-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.arm64 b/deployment/Dockerfile.ubuntu.arm64 index 6ae0d53cc..6aa98a289 100644 --- a/deployment/Dockerfile.ubuntu.arm64 +++ b/deployment/Dockerfile.ubuntu.arm64 @@ -16,7 +16,7 @@ RUN apt-get update -yqq \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/17b6759f-1af0-41bc-ab12-209ba0377779/e8d02195dbf1434b940e0f05ae086453/dotnet-sdk-6.0.100-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/deployment/Dockerfile.ubuntu.armhf b/deployment/Dockerfile.ubuntu.armhf index 154388148..cc9d8dc79 100644 --- a/deployment/Dockerfile.ubuntu.armhf +++ b/deployment/Dockerfile.ubuntu.armhf @@ -16,7 +16,7 @@ RUN apt-get update -yqq \ mmv build-essential lsb-release # Install dotnet repository -RUN wget -q https://download.visualstudio.microsoft.com/download/pr/20283373-1d83-4879-8278-0afb7fd4035e/56f204f174743b29a656499ad0fc93c3/dotnet-sdk-6.0.100-rc.2.21505.57-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ +RUN wget -q https://download.visualstudio.microsoft.com/download/pr/17b6759f-1af0-41bc-ab12-209ba0377779/e8d02195dbf1434b940e0f05ae086453/dotnet-sdk-6.0.100-linux-x64.tar.gz -O dotnet-sdk.tar.gz \ && mkdir -p dotnet-sdk \ && tar -xzf dotnet-sdk.tar.gz -C dotnet-sdk \ && ln -s $( pwd )/dotnet-sdk/dotnet /usr/bin/dotnet diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index 57ec86316..2aced0669 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index 889220d86..5b884cddf 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index 3daa45e56..29d7646a6 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -10,8 +10,8 @@ - - + + -- cgit v1.2.3 From 958a4f509c0d8a326eedc6a95a9f9e2d31e5391f Mon Sep 17 00:00:00 2001 From: hoanghuy309 Date: Mon, 8 Nov 2021 17:53:18 +0000 Subject: Translated using Weblate (Vietnamese) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/vi/ --- Emby.Server.Implementations/Localization/Core/vi.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/vi.json b/Emby.Server.Implementations/Localization/Core/vi.json index 33aa0eea0..548e395a9 100644 --- a/Emby.Server.Implementations/Localization/Core/vi.json +++ b/Emby.Server.Implementations/Localization/Core/vi.json @@ -62,11 +62,11 @@ "PluginUninstalledWithName": "{0} đã được gỡ bỏ", "PluginInstalledWithName": "{0} đã được cài đặt", "Plugin": "Plugin", - "NotificationOptionVideoPlaybackStopped": "Phát lại video đã dừng", + "NotificationOptionVideoPlaybackStopped": "Đã dừng phát lại video", "NotificationOptionVideoPlayback": "Đã bắt đầu phát lại video", "NotificationOptionUserLockedOut": "Người dùng bị khóa", "NotificationOptionTaskFailed": "Lỗi tác vụ đã lên lịch", - "NotificationOptionServerRestartRequired": "Yêu cầu khởi động lại Server", + "NotificationOptionServerRestartRequired": "Yêu cầu khởi động lại máy chủ", "NotificationOptionPluginUpdateInstalled": "Cập nhật Plugin đã được cài đặt", "NotificationOptionPluginUninstalled": "Đã gỡ bỏ Plugin", "NotificationOptionPluginInstalled": "Đã cài đặt Plugin", @@ -75,7 +75,7 @@ "NotificationOptionInstallationFailed": "Cài đặt thất bại", "NotificationOptionCameraImageUploaded": "Đã tải lên hình ảnh máy ảnh", "NotificationOptionAudioPlaybackStopped": "Phát lại âm thanh đã dừng", - "NotificationOptionAudioPlayback": "Phát lại âm thanh đã bắt đầu", + "NotificationOptionAudioPlayback": "Đã bắt đầu phát lại âm thanh", "NotificationOptionApplicationUpdateInstalled": "Bản cập nhật ứng dụng đã được cài đặt", "NotificationOptionApplicationUpdateAvailable": "Bản cập nhật ứng dụng hiện sẵn có", "NewVersionIsAvailable": "Một phiên bản mới của Jellyfin Server sẵn có để tải.", -- cgit v1.2.3 From 5726535a262ce5f671bb0b74dd00c485d17633f0 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 9 Nov 2021 13:14:31 +0100 Subject: Fix some warnings 609 left --- Emby.Naming/Common/NamingOptions.cs | 2 ++ Emby.Server.Implementations/Dto/DtoService.cs | 2 +- Emby.Server.Implementations/IO/LibraryMonitor.cs | 2 +- Emby.Server.Implementations/Library/LibraryManager.cs | 14 +++++++------- .../Library/Validators/PeopleValidator.cs | 2 +- Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 8 ++++---- .../LiveTv/EmbyTV/EncodedRecorder.cs | 12 ++++++------ Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs | 2 +- Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 6 +++--- .../LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 2 +- .../ScheduledTasks/Tasks/DeleteCacheFileTask.cs | 8 ++++---- .../ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs | 8 ++++---- Jellyfin.Api/Controllers/DynamicHlsController.cs | 6 +++--- Jellyfin.Api/Controllers/SubtitleController.cs | 2 +- Jellyfin.Server.Implementations/Events/EventManager.cs | 2 +- Jellyfin.Server/Middleware/ResponseTimeMiddleware.cs | 2 +- Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs | 2 +- Jellyfin.Server/Program.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 2 +- MediaBrowser.Controller/IO/FileData.cs | 4 ++-- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 2 +- MediaBrowser.Providers/Manager/ItemImageProvider.cs | 4 ++-- MediaBrowser.Providers/Manager/MetadataService.cs | 6 +++--- MediaBrowser.XbmcMetadata/EntryPoint.cs | 2 +- jellyfin.ruleset | 6 ++++++ .../Controllers/DashboardControllerTests.cs | 2 +- 27 files changed, 61 insertions(+), 53 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 5ddcf37fe..7bc9fbce8 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -1,3 +1,5 @@ +#pragma warning disable CA1819 + using System; using System.Linq; using System.Text.RegularExpressions; diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 9287f5272..c6b32a52c 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -497,7 +497,7 @@ namespace Emby.Server.Implementations.Dto } catch (Exception ex) { - _logger.LogError(ex, "Error getting {imageType} image info for {path}", image.Type, image.Path); + _logger.LogError(ex, "Error getting {ImageType} image info for {Path}", image.Type, image.Path); return null; } } diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index e9d069cd3..7ebc800b9 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -276,7 +276,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - _logger.LogError(ex, "Error watching path: {path}", path); + _logger.LogError(ex, "Error watching path: {Path}", path); } }); } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 1326f60fe..2dbb569c6 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -492,7 +492,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Error in {resolver} resolving {path}", resolver.GetType().Name, args.Path); + _logger.LogError(ex, "Error in {Resolver} resolving {Path}", resolver.GetType().Name, args.Path); return null; } } @@ -799,7 +799,7 @@ namespace Emby.Server.Implementations.Library { var userRootPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath; - _logger.LogDebug("Creating userRootPath at {path}", userRootPath); + _logger.LogDebug("Creating userRootPath at {Path}", userRootPath); Directory.CreateDirectory(userRootPath); var newItemId = GetNewItemId(userRootPath, typeof(UserRootFolder)); @@ -810,7 +810,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Error creating UserRootFolder {path}", newItemId); + _logger.LogError(ex, "Error creating UserRootFolder {Path}", newItemId); } if (tmpItem == null) @@ -827,7 +827,7 @@ namespace Emby.Server.Implementations.Library } _userRootFolder = tmpItem; - _logger.LogDebug("Setting userRootFolder: {folder}", _userRootFolder); + _logger.LogDebug("Setting userRootFolder: {Folder}", _userRootFolder); } } } @@ -1213,7 +1213,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Error resolving shortcut file {file}", i); + _logger.LogError(ex, "Error resolving shortcut file {File}", i); return null; } }) @@ -1698,7 +1698,7 @@ namespace Emby.Server.Implementations.Library if (video == null) { - _logger.LogError("Intro resolver returned null for {path}.", info.Path); + _logger.LogError("Intro resolver returned null for {Path}.", info.Path); } else { @@ -1717,7 +1717,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Error resolving path {path}.", info.Path); + _logger.LogError(ex, "Error resolving path {Path}.", info.Path); } } else diff --git a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs index 8739a9e1b..8a9a4b865 100644 --- a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs @@ -78,7 +78,7 @@ namespace Emby.Server.Implementations.Library.Validators } catch (Exception ex) { - _logger.LogError(ex, "Error validating IBN entry {person}", person); + _logger.LogError(ex, "Error validating IBN entry {Person}", person); } // Update progress diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 980b42729..e5abb523c 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1308,16 +1308,16 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV await recorder.Record(directStreamProvider, mediaStreamInfo, recordPath, duration, onStarted, activeRecordingInfo.CancellationTokenSource.Token).ConfigureAwait(false); recordingStatus = RecordingStatus.Completed; - _logger.LogInformation("Recording completed: {recordPath}", recordPath); + _logger.LogInformation("Recording completed: {RecordPath}", recordPath); } catch (OperationCanceledException) { - _logger.LogInformation("Recording stopped: {recordPath}", recordPath); + _logger.LogInformation("Recording stopped: {RecordPath}", recordPath); recordingStatus = RecordingStatus.Completed; } catch (Exception ex) { - _logger.LogError(ex, "Error recording to {recordPath}", recordPath); + _logger.LogError(ex, "Error recording to {RecordPath}", recordPath); recordingStatus = RecordingStatus.Error; } @@ -1404,7 +1404,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError(ex, "Error deleting 0-byte failed recording file {path}", path); + _logger.LogError(ex, "Error deleting 0-byte failed recording file {Path}", path); } } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 835028b92..8688688e9 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -225,13 +225,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { try { - _logger.LogInformation("Stopping ffmpeg recording process for {path}", _targetPath); + _logger.LogInformation("Stopping ffmpeg recording process for {Path}", _targetPath); _process.StandardInput.WriteLine("q"); } catch (Exception ex) { - _logger.LogError(ex, "Error stopping recording transcoding job for {path}", _targetPath); + _logger.LogError(ex, "Error stopping recording transcoding job for {Path}", _targetPath); } if (_hasExited) @@ -241,7 +241,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV try { - _logger.LogInformation("Calling recording process.WaitForExit for {path}", _targetPath); + _logger.LogInformation("Calling recording process.WaitForExit for {Path}", _targetPath); if (_process.WaitForExit(10000)) { @@ -250,7 +250,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError(ex, "Error waiting for recording process to exit for {path}", _targetPath); + _logger.LogError(ex, "Error waiting for recording process to exit for {Path}", _targetPath); } if (_hasExited) @@ -260,13 +260,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV try { - _logger.LogInformation("Killing ffmpeg recording process for {path}", _targetPath); + _logger.LogInformation("Killing ffmpeg recording process for {Path}", _targetPath); _process.Kill(); } catch (Exception ex) { - _logger.LogError(ex, "Error killing recording transcoding job for {path}", _targetPath); + _logger.LogError(ex, "Error killing recording transcoding job for {Path}", _targetPath); } } } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs index 21e1409ac..598e3f88a 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -393,7 +393,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError(ex, "Error getting image info for {name}", info.Name); + _logger.LogError(ex, "Error getting image info for {Name}", info.Name); } return null; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index ea1a28fe8..a41b63f28 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1054,7 +1054,7 @@ namespace Emby.Server.Implementations.LiveTv { cancellationToken.ThrowIfCancellationRequested(); - _logger.LogDebug("Refreshing guide from {name}", service.Name); + _logger.LogDebug("Refreshing guide from {Name}", service.Name); try { @@ -1135,7 +1135,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError(ex, "Error getting channel information for {name}", channelInfo.Item2.Name); + _logger.LogError(ex, "Error getting channel information for {Name}", channelInfo.Item2.Name); } numComplete++; @@ -1248,7 +1248,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError(ex, "Error getting programs for channel {name}", currentChannel.Name); + _logger.LogError(ex, "Error getting programs for channel {Name}", currentChannel.Name); } numComplete++; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 31445e1ec..b621055d8 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -82,7 +82,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath)); - Logger.LogInformation("Opening HDHR UDP Live stream from {host}", uri.Host); + Logger.LogInformation("Opening HDHR UDP Live stream from {Host}", uri.Host); var remoteAddress = IPAddress.Parse(uri.Host); IPAddress localAddress = null; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index a575b260c..0941902fc 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -161,11 +161,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } catch (UnauthorizedAccessException ex) { - _logger.LogError(ex, "Error deleting directory {path}", directory); + _logger.LogError(ex, "Error deleting directory {Path}", directory); } catch (IOException ex) { - _logger.LogError(ex, "Error deleting directory {path}", directory); + _logger.LogError(ex, "Error deleting directory {Path}", directory); } } } @@ -179,11 +179,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } catch (UnauthorizedAccessException ex) { - _logger.LogError(ex, "Error deleting file {path}", path); + _logger.LogError(ex, "Error deleting file {Path}", path); } catch (IOException ex) { - _logger.LogError(ex, "Error deleting file {path}", path); + _logger.LogError(ex, "Error deleting file {Path}", path); } } } diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs index b13fc7fc6..099d781cd 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs @@ -141,11 +141,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } catch (UnauthorizedAccessException ex) { - _logger.LogError(ex, "Error deleting directory {path}", directory); + _logger.LogError(ex, "Error deleting directory {Path}", directory); } catch (IOException ex) { - _logger.LogError(ex, "Error deleting directory {path}", directory); + _logger.LogError(ex, "Error deleting directory {Path}", directory); } } } @@ -159,11 +159,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } catch (UnauthorizedAccessException ex) { - _logger.LogError(ex, "Error deleting file {path}", path); + _logger.LogError(ex, "Error deleting file {Path}", path); } catch (IOException ex) { - _logger.LogError(ex, "Error deleting file {path}", path); + _logger.LogError(ex, "Error deleting file {Path}", path); } } } diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 475b80464..049fd503b 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1794,7 +1794,7 @@ namespace Jellyfin.Api.Controllers return; } - _logger.LogDebug("Deleting partial HLS file {path}", path); + _logger.LogDebug("Deleting partial HLS file {Path}", path); try { @@ -1802,7 +1802,7 @@ namespace Jellyfin.Api.Controllers } catch (IOException ex) { - _logger.LogError(ex, "Error deleting partial stream file(s) {path}", path); + _logger.LogError(ex, "Error deleting partial stream file(s) {Path}", path); var task = Task.Delay(100); task.Wait(); @@ -1810,7 +1810,7 @@ namespace Jellyfin.Api.Controllers } catch (Exception ex) { - _logger.LogError(ex, "Error deleting partial stream file(s) {path}", path); + _logger.LogError(ex, "Error deleting partial stream file(s) {Path}", path); } } diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index db8307f28..16acedcf3 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -528,7 +528,7 @@ namespace Jellyfin.Api.Controllers if (fontFile != null && fileSize != null && fileSize > 0) { - _logger.LogDebug("Fallback font size is {fileSize} Bytes", fileSize); + _logger.LogDebug("Fallback font size is {FileSize} Bytes", fileSize); return PhysicalFile(fontFile.FullName, MimeTypes.GetMimeType(fontFile.FullName)); } else diff --git a/Jellyfin.Server.Implementations/Events/EventManager.cs b/Jellyfin.Server.Implementations/Events/EventManager.cs index 8c5d8f2ce..7f7c4750d 100644 --- a/Jellyfin.Server.Implementations/Events/EventManager.cs +++ b/Jellyfin.Server.Implementations/Events/EventManager.cs @@ -57,7 +57,7 @@ namespace Jellyfin.Server.Implementations.Events } catch (Exception e) { - _logger.LogError(e, "Uncaught exception in EventConsumer {type}: ", service.GetType()); + _logger.LogError(e, "Uncaught exception in EventConsumer {Type}: ", service.GetType()); } } } diff --git a/Jellyfin.Server/Middleware/ResponseTimeMiddleware.cs b/Jellyfin.Server/Middleware/ResponseTimeMiddleware.cs index 74874da1b..da9b69136 100644 --- a/Jellyfin.Server/Middleware/ResponseTimeMiddleware.cs +++ b/Jellyfin.Server/Middleware/ResponseTimeMiddleware.cs @@ -68,7 +68,7 @@ namespace Jellyfin.Server.Middleware if (_enableWarning && watch.ElapsedMilliseconds > _warningThreshold) { _logger.LogWarning( - "Slow HTTP Response from {url} to {remoteIp} in {elapsed:g} with Status Code {statusCode}", + "Slow HTTP Response from {Url} to {RemoteIp} in {Elapsed:g} with Status Code {StatusCode}", context.Request.GetDisplayUrl(), context.GetNormalizedRemoteIp(), watch.Elapsed, diff --git a/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs b/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs index e4d2937e7..2f1d79157 100644 --- a/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs +++ b/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs @@ -51,7 +51,7 @@ namespace Jellyfin.Server.Middleware return; } - if (!key.Contains('=')) + if (!key.Contains('=', StringComparison.Ordinal)) { _store = value; return; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 5c7012d58..6e4c2280b 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -675,7 +675,7 @@ namespace Jellyfin.Server private static string NormalizeCommandLineArgument(string arg) { - if (!arg.Contains(" ", StringComparison.OrdinalIgnoreCase)) + if (!arg.Contains(' ', StringComparison.Ordinal)) { return arg; } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 63749b1f3..a76ca2305 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1452,7 +1452,7 @@ namespace MediaBrowser.Controller.Entities } catch (Exception ex) { - Logger.LogError(ex, "Error refreshing owned items for {path}", Path ?? Name); + Logger.LogError(ex, "Error refreshing owned items for {Path}", Path ?? Name); } } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index fc6380e1a..ffd1c7f0a 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -303,7 +303,7 @@ namespace MediaBrowser.Controller.Entities if (dictionary.ContainsKey(id)) { Logger.LogError( - "Found folder containing items with duplicate id. Path: {path}, Child Name: {ChildName}", + "Found folder containing items with duplicate id. Path: {Path}, Child Name: {ChildName}", Path ?? Name, child.Path ?? child.Name); } diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs index b8a0bf331..2429ac42d 100644 --- a/MediaBrowser.Controller/IO/FileData.cs +++ b/MediaBrowser.Controller/IO/FileData.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Controller.IO if (string.IsNullOrEmpty(newPath)) { // invalid shortcut - could be old or target could just be unavailable - logger.LogWarning("Encountered invalid shortcut: " + fullName); + logger.LogWarning("Encountered invalid shortcut: {Path}", fullName); continue; } @@ -83,7 +83,7 @@ namespace MediaBrowser.Controller.IO } catch (Exception ex) { - logger.LogError(ex, "Error resolving shortcut from {path}", fullName); + logger.LogError(ex, "Error resolving shortcut from {Path}", fullName); } } else if (flattenFolderDepth > 0 && isDirectory) diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 5e7af23fc..1a8b5bb4e 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -144,7 +144,7 @@ namespace MediaBrowser.LocalMetadata.Savers } catch (Exception ex) { - Logger.LogError(ex, "Error setting hidden attribute on {path}", path); + Logger.LogError(ex, "Error setting hidden attribute on {Path}", path); } } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 1022a3fae..5e1985611 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -215,7 +215,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { result.ErrorMessage = ex.Message; - _logger.LogError(ex, "Error in {provider}", provider.Name); + _logger.LogError(ex, "Error in {Provider}", provider.Name); } } @@ -331,7 +331,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { result.ErrorMessage = ex.Message; - _logger.LogError(ex, "Error in {provider}", provider.Name); + _logger.LogError(ex, "Error in {Provider}", provider.Name); } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index ffb3baeb1..90d14a973 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -713,7 +713,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - Logger.LogError(ex, "Error in {provider}", provider.Name); + Logger.LogError(ex, "Error in {Provider}", provider.Name); // If a local provider fails, consider that a failure refreshResult.ErrorMessage = ex.Message; @@ -785,7 +785,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { refreshResult.ErrorMessage = ex.Message; - Logger.LogError(ex, "Error in {provider}", provider.Name); + Logger.LogError(ex, "Error in {Provider}", provider.Name); } } @@ -837,7 +837,7 @@ namespace MediaBrowser.Providers.Manager { refreshResult.Failures++; refreshResult.ErrorMessage = ex.Message; - Logger.LogError(ex, "Error in {provider}", provider.Name); + Logger.LogError(ex, "Error in {Provider}", provider.Name); } } diff --git a/MediaBrowser.XbmcMetadata/EntryPoint.cs b/MediaBrowser.XbmcMetadata/EntryPoint.cs index d02aea556..935ff5f59 100644 --- a/MediaBrowser.XbmcMetadata/EntryPoint.cs +++ b/MediaBrowser.XbmcMetadata/EntryPoint.cs @@ -71,7 +71,7 @@ namespace MediaBrowser.XbmcMetadata } catch (Exception ex) { - _logger.LogError(ex, "Error saving metadata for {path}", item.Path ?? item.Name); + _logger.LogError(ex, "Error saving metadata for {Path}", item.Path ?? item.Name); } } } diff --git a/jellyfin.ruleset b/jellyfin.ruleset index dfb991170..3bced438c 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -42,6 +42,8 @@ + + @@ -77,6 +79,8 @@ + + @@ -90,6 +94,8 @@ + + diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs index 827365363..3396a94e5 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs @@ -40,7 +40,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Text.Html, response.Content.Headers.ContentType?.MediaType); StreamReader reader = new StreamReader(typeof(TestPlugin).Assembly.GetManifestResourceStream("Jellyfin.Server.Integration.Tests.TestPage.html")!); - Assert.Equal(await response.Content.ReadAsStringAsync(), reader.ReadToEnd()); + Assert.Equal(await response.Content.ReadAsStringAsync().ConfigureAwait(false), await reader.ReadToEndAsync().ConfigureAwait(false)); } [Fact] -- cgit v1.2.3 From ce1c36dbf2c652121e4b797dd432059243251785 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Nov 2021 14:26:19 +0000 Subject: Bump Mono.Nat from 3.0.1 to 3.0.2 Bumps [Mono.Nat](https://github.com/mono/Mono.Nat) from 3.0.1 to 3.0.2. - [Release notes](https://github.com/mono/Mono.Nat/releases) - [Commits](https://github.com/mono/Mono.Nat/compare/release-v3.0.1...release-v3.0.2) --- updated-dependencies: - dependency-name: Mono.Nat dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Emby.Server.Implementations/Emby.Server.Implementations.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 03f9f50ea..042b8f71a 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -30,7 +30,7 @@ - + -- cgit v1.2.3 From 6bd108877e3ab999203869188170eed04b2d64c3 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Tue, 9 Nov 2021 17:12:33 +0000 Subject: Translated using Weblate (Russian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ru/ --- Emby.Server.Implementations/Localization/Core/ru.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json index 36f4e3e7c..2d7163275 100644 --- a/Emby.Server.Implementations/Localization/Core/ru.json +++ b/Emby.Server.Implementations/Localization/Core/ru.json @@ -31,7 +31,7 @@ "ItemRemovedWithName": "{0} - изъято из медиатеки", "LabelIpAddressValue": "IP-адрес: {0}", "LabelRunningTimeValue": "Длительность: {0}", - "Latest": "Последнее", + "Latest": "Крайнее", "MessageApplicationUpdated": "Jellyfin Server был обновлён", "MessageApplicationUpdatedTo": "Jellyfin Server был обновлён до {0}", "MessageNamedServerConfigurationUpdatedWithValue": "Конфигурация сервера (раздел {0}) была обновлена", -- cgit v1.2.3 From 1d19a5be617c191a731b76e556fae1e395eb3788 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 9 Nov 2021 22:29:33 +0100 Subject: Fix some warnings down to 580 --- Emby.Dlna/DlnaManager.cs | 19 +--- Emby.Dlna/Main/DlnaEntryPoint.cs | 7 +- Emby.Server.Implementations/Dto/DtoService.cs | 7 +- Emby.Server.Implementations/IO/LibraryMonitor.cs | 2 +- .../Library/LibraryManager.cs | 3 +- .../Library/Resolvers/Audio/MusicAlbumResolver.cs | 2 +- .../LiveTv/EmbyTV/EmbyTV.cs | 2 +- .../LiveTv/EmbyTV/EncodedRecorder.cs | 5 +- .../ScheduledTasks/ScheduledTaskWorker.cs | 10 +- .../Updates/InstallationManager.cs | 2 +- Jellyfin.Api/Controllers/DynamicHlsController.cs | 2 +- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 6 +- .../Models/PlaybackDtos/TranscodingThrottler.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 4 +- .../MediaEncoding/IMediaEncoder.cs | 26 ----- .../Parsers/BaseItemXmlParser.cs | 2 +- .../Attachments/AttachmentExtractor.cs | 7 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 117 +-------------------- .../Subtitles/SubtitleEncoder.cs | 11 +- .../Parsers/SeriesNfoParser.cs | 2 +- jellyfin.ruleset | 4 + 21 files changed, 38 insertions(+), 204 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index f37d2d7d7..277a0e678 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -112,7 +112,7 @@ namespace Emby.Dlna if (profile == null) { - LogUnmatchedProfile(deviceInfo); + _logger.LogInformation("No matching device profile found. The default will need to be used. \n{@Profile}", deviceInfo); } else { @@ -122,23 +122,6 @@ namespace Emby.Dlna return profile; } - private void LogUnmatchedProfile(DeviceIdentification profile) - { - var builder = new StringBuilder(); - - builder.AppendLine("No matching device profile found. The default will need to be used."); - builder.Append("FriendlyName: ").AppendLine(profile.FriendlyName); - builder.Append("Manufacturer: ").AppendLine(profile.Manufacturer); - builder.Append("ManufacturerUrl: ").AppendLine(profile.ManufacturerUrl); - builder.Append("ModelDescription: ").AppendLine(profile.ModelDescription); - builder.Append("ModelName: ").AppendLine(profile.ModelName); - builder.Append("ModelNumber: ").AppendLine(profile.ModelNumber); - builder.Append("ModelUrl: ").AppendLine(profile.ModelUrl); - builder.Append("SerialNumber: ").AppendLine(profile.SerialNumber); - - _logger.LogInformation(builder.ToString()); - } - /// /// Attempts to match a device with a profile. /// Rules: diff --git a/Emby.Dlna/Main/DlnaEntryPoint.cs b/Emby.Dlna/Main/DlnaEntryPoint.cs index 8e89d9ae6..722428c73 100644 --- a/Emby.Dlna/Main/DlnaEntryPoint.cs +++ b/Emby.Dlna/Main/DlnaEntryPoint.cs @@ -218,11 +218,6 @@ namespace Emby.Dlna.Main } } - private void LogMessage(string msg) - { - _logger.LogDebug(msg); - } - private void StartDeviceDiscovery(ISsdpCommunicationsServer communicationsServer) { try @@ -272,7 +267,7 @@ namespace Emby.Dlna.Main Environment.OSVersion.VersionString, _config.GetDlnaConfiguration().SendOnlyMatchedHost) { - LogFunction = LogMessage, + LogFunction = (msg) => _logger.LogDebug("{Msg}", msg), SupportPnpRootDevice = false }; diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index c6b32a52c..67ecd04e0 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -134,14 +134,11 @@ namespace Emby.Server.Implementations.Dto var dto = GetBaseItemDtoInternal(item, options, user, owner); if (item is LiveTvChannel tvChannel) { - var list = new List<(BaseItemDto, LiveTvChannel)>(1) { (dto, tvChannel) }; - LivetvManager.AddChannelInfo(list, options, user); + LivetvManager.AddChannelInfo(new[] { (dto, tvChannel) }, options, user); } else if (item is LiveTvProgram) { - var list = new List<(BaseItem, BaseItemDto)>(1) { (item, dto) }; - var task = LivetvManager.AddInfoToProgramDto(list, options.Fields, user); - Task.WaitAll(task); + LivetvManager.AddInfoToProgramDto(new[] { (item, dto) }, options.Fields, user).GetAwaiter().GetResult(); } if (item is IItemByName itemByName diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index 7ebc800b9..b525f5a2f 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -267,7 +267,7 @@ namespace Emby.Server.Implementations.IO if (_fileSystemWatchers.TryAdd(path, newWatcher)) { newWatcher.EnableRaisingEvents = true; - _logger.LogInformation("Watching directory " + path); + _logger.LogInformation("Watching directory {Path}", path); } else { diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 2dbb569c6..559da7f5c 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -333,8 +333,7 @@ namespace Emby.Server.Implementations.Library { try { - var task = BaseItem.ChannelManager.DeleteItem(item); - Task.WaitAll(task); + BaseItem.ChannelManager.DeleteItem(item).GetAwaiter().GetResult(); } catch (ArgumentException) { diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index 60720dd2f..9e3f62276 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -151,7 +151,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio { if (parser.IsMultiPart(path)) { - logger.LogDebug("Found multi-disc folder: " + path); + logger.LogDebug("Found multi-disc folder: {Path}", path); Interlocked.Increment(ref discSubfolderCount); } else diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 367f3cb9e..644f9050d 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -957,7 +957,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public async Task GetChannelStreamWithDirectStreamProvider(string channelId, string streamId, List currentLiveStreams, CancellationToken cancellationToken) { - _logger.LogInformation("Streaming Channel " + channelId); + _logger.LogInformation("Streaming Channel {Id}", channelId); var result = string.IsNullOrEmpty(streamId) ? null : diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 8688688e9..5726d7158 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -87,8 +87,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV ErrorDialog = false }; - var commandLineLogMessage = processStartInfo.FileName + " " + processStartInfo.Arguments; - _logger.LogInformation(commandLineLogMessage); + _logger.LogInformation("{Filename} {Arguments}", processStartInfo.FileName, processStartInfo.Arguments); var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt"); Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); @@ -97,7 +96,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _logFileStream = new FileStream(logFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false); - await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false); + await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + processStartInfo.FileName + " " + processStartInfo.Arguments + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false); _process = new Process { diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index f2cdfeb16..21a7f4f5f 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -638,7 +638,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { try { - _logger.LogInformation(Name + ": Cancelling"); + _logger.LogInformation("{Name}: Cancelling", Name); token.Cancel(); } catch (Exception ex) @@ -652,16 +652,16 @@ namespace Emby.Server.Implementations.ScheduledTasks { try { - _logger.LogInformation(Name + ": Waiting on Task"); + _logger.LogInformation("{Name}: Waiting on Task", Name); var exited = task.Wait(2000); if (exited) { - _logger.LogInformation(Name + ": Task exited"); + _logger.LogInformation("{Name}: Task exited", Name); } else { - _logger.LogInformation(Name + ": Timed out waiting for task to stop"); + _logger.LogInformation("{Name}: Timed out waiting for task to stop", Name); } } catch (Exception ex) @@ -674,7 +674,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { try { - _logger.LogDebug(Name + ": Disposing CancellationToken"); + _logger.LogDebug("{Name}: Disposing CancellationToken", Name); token.Dispose(); } catch (Exception ex) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 4a022c5db..ef95ebf94 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -571,7 +571,7 @@ namespace Emby.Server.Implementations.Updates ?? _pluginManager.Plugins.FirstOrDefault(p => p.Name.Equals(package.Name, StringComparison.OrdinalIgnoreCase) && p.Version.Equals(package.Version)); await PerformPackageInstallation(package, plugin?.Manifest.Status ?? PluginStatus.Active, cancellationToken).ConfigureAwait(false); - _logger.LogInformation(plugin == null ? "New plugin installed: {PluginName} {PluginVersion}" : "Plugin updated: {PluginName} {PluginVersion}", package.Name, package.Version); + _logger.LogInformation("Plugin {Action}: {PluginName} {PluginVersion}", plugin == null ? "installed" : "updated", package.Name, package.Version); return plugin != null; } diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 049fd503b..caa3d2368 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1391,7 +1391,7 @@ namespace Jellyfin.Api.Controllers } else { - _logger.LogError("Invalid HLS segment container: " + segmentFormat); + _logger.LogError("Invalid HLS segment container: {SegmentFormat}", segmentFormat); } var maxMuxingQueueSize = _encodingOptions.MaxMuxingQueueSize > 128 diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index f435bbf00..9d80070eb 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -543,8 +543,7 @@ namespace Jellyfin.Api.Helpers state, cancellationTokenSource); - var commandLineLogMessage = process.StartInfo.FileName + " " + process.StartInfo.Arguments; - _logger.LogInformation(commandLineLogMessage); + _logger.LogInformation("{Filename} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); var logFilePrefix = "FFmpeg.Transcode-"; if (state.VideoRequest != null @@ -562,8 +561,9 @@ namespace Jellyfin.Api.Helpers // FFmpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); + var commandLineLogMessage = process.StartInfo.FileName + " " + process.StartInfo.Arguments; var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(request.Path + Environment.NewLine + Environment.NewLine + JsonSerializer.Serialize(state.MediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); - await logStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false); + await logStream.WriteAsync(commandLineLogMessageBytes, cancellationTokenSource.Token).ConfigureAwait(false); process.Exited += (sender, args) => OnFfMpegProcessExited(process, transcodingJob, state); diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs index 7b32d76ba..0136d9f86 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs @@ -197,7 +197,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos } } - _logger.LogDebug("No throttle data for " + path); + _logger.LogDebug("No throttle data for {Path}", path); return false; } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index ffd1c7f0a..ec1ebaabe 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -425,7 +425,7 @@ namespace MediaBrowser.Controller.Entities { if (item.IsFileProtocol) { - Logger.LogDebug("Removed item: " + item.Path); + Logger.LogDebug("Removed item: {Path}", item.Path); item.SetParent(null); LibraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false }, this, false); @@ -807,7 +807,7 @@ namespace MediaBrowser.Controller.Entities { if (this is not ICollectionFolder) { - Logger.LogDebug("Query requires post-filtering due to LinkedChildren. Type: " + GetType().Name); + Logger.LogDebug("{Type}: Query requires post-filtering due to LinkedChildren.", GetType().Name); return true; } } diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index e6511ca8d..7d62fb6e1 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -100,32 +100,6 @@ namespace MediaBrowser.Controller.MediaEncoding /// Location of video image. Task ExtractVideoImage(string inputFile, string container, MediaSourceInfo mediaSource, MediaStream imageStream, int? imageStreamIndex, string outputExtension, CancellationToken cancellationToken); - /// - /// Extracts the video images on interval. - /// - /// Input file. - /// Video container type. - /// Media stream information. - /// Media source information. - /// Video 3D format. - /// Time interval. - /// Directory to write images. - /// Filename prefix to use. - /// Maximum width of image. - /// CancellationToken to use for operation. - /// A task. - Task ExtractVideoImagesOnInterval( - string inputFile, - string container, - MediaStream videoStream, - MediaSourceInfo mediaSource, - Video3DFormat? threedFormat, - TimeSpan interval, - string targetDirectory, - string filenamePrefix, - int? maxWidth, - CancellationToken cancellationToken); - /// /// Gets the media info. /// diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 80eb45423..777fe6774 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -149,7 +149,7 @@ namespace MediaBrowser.LocalMetadata.Parsers } else { - Logger.LogWarning("Invalid Added value found: " + val); + Logger.LogWarning("Invalid Added value found: {Value}", val); } } diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index a524aeaa9..9ebc0d0cf 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -223,11 +223,10 @@ namespace MediaBrowser.MediaEncoding.Attachments if (failed) { - var msg = $"ffmpeg attachment extraction failed for {inputPath} to {outputPath}"; + _logger.LogError("ffmpeg attachment extraction failed for {InputPath} to {OutputPath}", inputPath, outputPath); - _logger.LogError(msg); - - throw new InvalidOperationException(msg); + throw new InvalidOperationException( + string.Format(CultureInfo.InvariantCulture, "ffmpeg attachment extraction failed for {0} to {1}", inputPath, outputPath)); } else { diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index fbc7ba72f..a2bac7b49 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -682,11 +682,9 @@ namespace MediaBrowser.MediaEncoding.Encoder if (exitCode == -1 || !file.Exists || file.Length == 0) { - var msg = string.Format(CultureInfo.InvariantCulture, "ffmpeg image extraction failed for {0}", inputPath); + _logger.LogError("ffmpeg image extraction failed for {Path}", inputPath); - _logger.LogError(msg); - - throw new FfmpegException(msg); + throw new FfmpegException(string.Format(CultureInfo.InvariantCulture, "ffmpeg image extraction failed for {0}", inputPath)); } return tempExtractPath; @@ -705,117 +703,6 @@ namespace MediaBrowser.MediaEncoding.Encoder return time.ToString(@"hh\:mm\:ss\.fff", CultureInfo.InvariantCulture); } - public async Task ExtractVideoImagesOnInterval( - string inputFile, - string container, - MediaStream videoStream, - MediaSourceInfo mediaSource, - Video3DFormat? threedFormat, - TimeSpan interval, - string targetDirectory, - string filenamePrefix, - int? maxWidth, - CancellationToken cancellationToken) - { - var inputArgument = GetInputArgument(inputFile, mediaSource); - - var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(CultureInfo.InvariantCulture); - - if (maxWidth.HasValue) - { - var maxWidthParam = maxWidth.Value.ToString(CultureInfo.InvariantCulture); - - vf += string.Format(CultureInfo.InvariantCulture, ",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam); - } - - Directory.CreateDirectory(targetDirectory); - var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg"); - - var args = string.Format(CultureInfo.InvariantCulture, "-i {0} -threads {3} -v quiet {2} -f image2 \"{1}\"", inputArgument, outputPath, vf, _threads); - - if (!string.IsNullOrWhiteSpace(container)) - { - var inputFormat = EncodingHelper.GetInputFormat(container); - if (!string.IsNullOrWhiteSpace(inputFormat)) - { - args = "-f " + inputFormat + " " + args; - } - } - - var processStartInfo = new ProcessStartInfo - { - CreateNoWindow = true, - UseShellExecute = false, - FileName = _ffmpegPath, - Arguments = args, - WindowStyle = ProcessWindowStyle.Hidden, - ErrorDialog = false - }; - - _logger.LogInformation(processStartInfo.FileName + " " + processStartInfo.Arguments); - - await _thumbnailResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - - bool ranToCompletion = false; - - var process = new Process - { - StartInfo = processStartInfo, - EnableRaisingEvents = true - }; - using (var processWrapper = new ProcessWrapper(process, this)) - { - try - { - StartProcess(processWrapper); - - // Need to give ffmpeg enough time to make all the thumbnails, which could be a while, - // but we still need to detect if the process hangs. - // Making the assumption that as long as new jpegs are showing up, everything is good. - - bool isResponsive = true; - int lastCount = 0; - - while (isResponsive) - { - if (await process.WaitForExitAsync(TimeSpan.FromSeconds(30)).ConfigureAwait(false)) - { - ranToCompletion = true; - break; - } - - cancellationToken.ThrowIfCancellationRequested(); - - var jpegCount = _fileSystem.GetFilePaths(targetDirectory) - .Count(i => string.Equals(Path.GetExtension(i), ".jpg", StringComparison.OrdinalIgnoreCase)); - - isResponsive = jpegCount > lastCount; - lastCount = jpegCount; - } - - if (!ranToCompletion) - { - StopProcess(processWrapper, 1000); - } - } - finally - { - _thumbnailResourcePool.Release(); - } - - var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1; - - if (exitCode == -1) - { - var msg = string.Format(CultureInfo.InvariantCulture, "ffmpeg image extraction failed for {0}", inputArgument); - - _logger.LogError(msg); - - throw new FfmpegException(msg); - } - } - } - private void StartProcess(ProcessWrapper process) { process.Process.Start(); diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 2b2de2ff6..89365a516 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -636,17 +636,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (failed) { - var msg = $"ffmpeg subtitle extraction failed for {inputPath} to {outputPath}"; + _logger.LogError("ffmpeg subtitle extraction failed for {InputPath} to {OutputPath}", inputPath, outputPath); - _logger.LogError(msg); - - throw new FfmpegException(msg); + throw new FfmpegException( + string.Format(CultureInfo.InvariantCulture, "ffmpeg subtitle extraction failed for {0} to {1}", inputPath, outputPath)); } else { - var msg = $"ffmpeg subtitle extraction completed for {inputPath} to {outputPath}"; - - _logger.LogInformation(msg); + _logger.LogInformation("ffmpeg subtitle extraction completed for {InputPath} to {OutputPath}", inputPath, outputPath); } if (string.Equals(outputCodec, "ass", StringComparison.OrdinalIgnoreCase)) diff --git a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs index 2c893ac9f..3011d65a6 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs @@ -103,7 +103,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers } else { - Logger.LogInformation("Unrecognized series status: " + status); + Logger.LogInformation("Unrecognized series status: {Status}", status); } } diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 3bced438c..e14c1c427 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -44,9 +44,13 @@ + + + + -- cgit v1.2.3 From 5265b3eee794762b4de39a68b5bfbf767faaac36 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 10 Nov 2021 22:34:54 +0100 Subject: Replace PBKDF2-SHA1 with PBKDF2-SHA512 This also migrates already created passwords on login Source for the number of iterations: https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#pbkdf2 --- .../Cryptography/CryptographyProvider.cs | 90 +++++---- .../LiveTv/Listings/SchedulesDirect.cs | 3 +- .../Users/DefaultAuthenticationProvider.cs | 35 ++-- .../Users/UserManager.cs | 8 +- MediaBrowser.Common/Cryptography/Constants.cs | 18 -- .../Cryptography/CryptoExtensions.cs | 35 ---- MediaBrowser.Common/Cryptography/PasswordHash.cs | 219 --------------------- MediaBrowser.Model/Cryptography/Constants.cs | 23 +++ MediaBrowser.Model/Cryptography/ICryptoProvider.cs | 13 +- MediaBrowser.Model/Cryptography/PasswordHash.cs | 219 +++++++++++++++++++++ .../Cryptography/PasswordHashTests.cs | 169 ---------------- .../Cryptography/PasswordHashTests.cs | 169 ++++++++++++++++ 12 files changed, 488 insertions(+), 513 deletions(-) delete mode 100644 MediaBrowser.Common/Cryptography/Constants.cs delete mode 100644 MediaBrowser.Common/Cryptography/CryptoExtensions.cs delete mode 100644 MediaBrowser.Common/Cryptography/PasswordHash.cs create mode 100644 MediaBrowser.Model/Cryptography/Constants.cs create mode 100644 MediaBrowser.Model/Cryptography/PasswordHash.cs delete mode 100644 tests/Jellyfin.Common.Tests/Cryptography/PasswordHashTests.cs create mode 100644 tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs index 673810c49..e9c005cea 100644 --- a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs +++ b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Security.Cryptography; +using System.Text; using MediaBrowser.Common.Extensions; using MediaBrowser.Model.Cryptography; -using static MediaBrowser.Common.Cryptography.Constants; +using static MediaBrowser.Model.Cryptography.Constants; namespace Emby.Server.Implementations.Cryptography { @@ -12,10 +14,7 @@ namespace Emby.Server.Implementations.Cryptography /// public class CryptographyProvider : ICryptoProvider { - // FIXME: When we get DotNet Standard 2.1 we need to revisit how we do the crypto - // Currently supported hash methods from https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptoconfig?view=netcore-2.1 - // there might be a better way to autogenerate this list as dotnet updates, but I couldn't find one - // Please note the default method of PBKDF2 is not included, it cannot be used to generate hashes cleanly as it is actually a pbkdf with sha1 + // TODO: remove when not needed for backwards compat private static readonly HashSet _supportedHashMethods = new HashSet() { "MD5", @@ -35,60 +34,81 @@ namespace Emby.Server.Implementations.Cryptography }; /// - public string DefaultHashMethod => "PBKDF2"; + public string DefaultHashMethod => "PBKDF2-SHA512"; /// - public IEnumerable GetSupportedHashMethods() - => _supportedHashMethods; - - private byte[] PBKDF2(string method, byte[] bytes, byte[] salt, int iterations) + public PasswordHash CreatePasswordHash(ReadOnlySpan password) { - // downgrading for now as we need this library to be dotnetstandard compliant - // with this downgrade we'll add a check to make sure we're on the downgrade method at the moment - if (method != DefaultHashMethod) - { - throw new CryptographicException($"Cannot currently use PBKDF2 with requested hash method: {method}"); - } - - using var r = new Rfc2898DeriveBytes(bytes, salt, iterations); - return r.GetBytes(32); + byte[] salt = GenerateSalt(); + return new PasswordHash( + DefaultHashMethod, + Rfc2898DeriveBytes.Pbkdf2( + password, + salt, + DefaultIterations, + HashAlgorithmName.SHA512, + DefaultOutputLength), + salt, + new Dictionary + { + { "iterations", DefaultIterations.ToString(CultureInfo.InvariantCulture) } + }); } /// - public byte[] ComputeHash(string hashMethod, byte[] bytes, byte[] salt) + public bool Verify(PasswordHash hash, ReadOnlySpan password) { - if (hashMethod == DefaultHashMethod) + if (string.Equals(hash.Id, "PBKDF2", StringComparison.Ordinal)) { - return PBKDF2(hashMethod, bytes, salt, DefaultIterations); + return hash.Hash.SequenceEqual( + Rfc2898DeriveBytes.Pbkdf2( + password, + hash.Salt, + int.Parse(hash.Parameters["iterations"], CultureInfo.InvariantCulture), + HashAlgorithmName.SHA1, + 32)); } - if (!_supportedHashMethods.Contains(hashMethod)) + if (string.Equals(hash.Id, "PBKDF2-SHA512", StringComparison.Ordinal)) { - throw new CryptographicException($"Requested hash method is not supported: {hashMethod}"); + return hash.Hash.SequenceEqual( + Rfc2898DeriveBytes.Pbkdf2( + password, + hash.Salt, + int.Parse(hash.Parameters["iterations"], CultureInfo.InvariantCulture), + HashAlgorithmName.SHA512, + DefaultOutputLength)); } - using var h = HashAlgorithm.Create(hashMethod) ?? throw new ResourceNotFoundException($"Unknown hash method: {hashMethod}."); - if (salt.Length == 0) + if (!_supportedHashMethods.Contains(hash.Id)) { - return h.ComputeHash(bytes); + throw new CryptographicException($"Requested hash method is not supported: {hash.Id}"); } - byte[] salted = new byte[bytes.Length + salt.Length]; + using var h = HashAlgorithm.Create(hash.Id) ?? throw new ResourceNotFoundException($"Unknown hash method: {hash.Id}."); + var bytes = Encoding.UTF8.GetBytes(password.ToArray()); + if (hash.Salt.Length == 0) + { + return hash.Hash.SequenceEqual(h.ComputeHash(bytes)); + } + + byte[] salted = new byte[bytes.Length + hash.Salt.Length]; Array.Copy(bytes, salted, bytes.Length); - Array.Copy(salt, 0, salted, bytes.Length, salt.Length); - return h.ComputeHash(salted); + hash.Salt.CopyTo(salted.AsSpan(bytes.Length)); + return hash.Hash.SequenceEqual(h.ComputeHash(salted)); } - /// - public byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt) - => PBKDF2(DefaultHashMethod, bytes, salt, DefaultIterations); - /// public byte[] GenerateSalt() => GenerateSalt(DefaultSaltLength); /// public byte[] GenerateSalt(int length) - => RandomNumberGenerator.GetBytes(length); + { + var salt = new byte[length]; + using var rng = RandomNumberGenerator.Create(); + rng.GetNonZeroBytes(salt); + return salt; + } } } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 1f963e4a2..615539db3 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -11,6 +11,7 @@ using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Net.Mime; +using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Threading; @@ -648,7 +649,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings CancellationToken cancellationToken) { using var options = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/token"); - var hashedPasswordBytes = _cryptoProvider.ComputeHash("SHA1", Encoding.ASCII.GetBytes(password), Array.Empty()); + var hashedPasswordBytes = SHA1.HashData(Encoding.ASCII.GetBytes(password)); // TODO: remove ToLower when Convert.ToHexString supports lowercase // Schedules Direct requires the hex to be lowercase string hashedPassword = Convert.ToHexString(hashedPasswordBytes).ToLowerInvariant(); diff --git a/Jellyfin.Server.Implementations/Users/DefaultAuthenticationProvider.cs b/Jellyfin.Server.Implementations/Users/DefaultAuthenticationProvider.cs index 6a78e7ee6..7480a05c2 100644 --- a/Jellyfin.Server.Implementations/Users/DefaultAuthenticationProvider.cs +++ b/Jellyfin.Server.Implementations/Users/DefaultAuthenticationProvider.cs @@ -1,9 +1,6 @@ using System; -using System.Linq; -using System.Text; using System.Threading.Tasks; using Jellyfin.Data.Entities; -using MediaBrowser.Common.Cryptography; using MediaBrowser.Controller.Authentication; using MediaBrowser.Model.Cryptography; @@ -61,35 +58,25 @@ namespace Jellyfin.Server.Implementations.Users } // Handle the case when the stored password is null, but the user tried to login with a password - if (resolvedUser.Password != null) + if (resolvedUser.Password == null) { - byte[] passwordBytes = Encoding.UTF8.GetBytes(password); - - PasswordHash readyHash = PasswordHash.Parse(resolvedUser.Password); - if (_cryptographyProvider.GetSupportedHashMethods().Contains(readyHash.Id) - || _cryptographyProvider.DefaultHashMethod == readyHash.Id) - { - byte[] calculatedHash = _cryptographyProvider.ComputeHash( - readyHash.Id, - passwordBytes, - readyHash.Salt.ToArray()); - - if (readyHash.Hash.SequenceEqual(calculatedHash)) - { - success = true; - } - } - else - { - throw new AuthenticationException($"Requested crypto method not available in provider: {readyHash.Id}"); - } + throw new AuthenticationException("Invalid username or password"); } + PasswordHash readyHash = PasswordHash.Parse(resolvedUser.Password); + success = _cryptographyProvider.Verify(readyHash, password); + if (!success) { throw new AuthenticationException("Invalid username or password"); } + // Migrate old hashes to the new default + if (!string.Equals(readyHash.Id, _cryptographyProvider.DefaultHashMethod, StringComparison.Ordinal)) + { + ChangePassword(resolvedUser, password); + } + return Task.FromResult(new ProviderAuthenticationResult { Username = username diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 8ca6e8d21..3d0a51ff6 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -5,7 +5,6 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using Jellyfin.Data.Entities; @@ -13,7 +12,6 @@ using Jellyfin.Data.Enums; using Jellyfin.Data.Events; using Jellyfin.Data.Events.Users; using MediaBrowser.Common; -using MediaBrowser.Common.Cryptography; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Authentication; @@ -818,11 +816,7 @@ namespace Jellyfin.Server.Implementations.Users { // Check easy password var passwordHash = PasswordHash.Parse(user.EasyPassword); - var hash = _cryptoProvider.ComputeHash( - passwordHash.Id, - Encoding.UTF8.GetBytes(password), - passwordHash.Salt.ToArray()); - success = passwordHash.Hash.SequenceEqual(hash); + success = _cryptoProvider.Verify(passwordHash, password); } return (authenticationProvider, username, success); diff --git a/MediaBrowser.Common/Cryptography/Constants.cs b/MediaBrowser.Common/Cryptography/Constants.cs deleted file mode 100644 index 354114232..000000000 --- a/MediaBrowser.Common/Cryptography/Constants.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace MediaBrowser.Common.Cryptography -{ - /// - /// Class containing global constants for Jellyfin Cryptography. - /// - public static class Constants - { - /// - /// The default length for new salts. - /// - public const int DefaultSaltLength = 64; - - /// - /// The default amount of iterations for hashing passwords. - /// - public const int DefaultIterations = 1000; - } -} diff --git a/MediaBrowser.Common/Cryptography/CryptoExtensions.cs b/MediaBrowser.Common/Cryptography/CryptoExtensions.cs deleted file mode 100644 index 157b0ed10..000000000 --- a/MediaBrowser.Common/Cryptography/CryptoExtensions.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using System.Text; -using MediaBrowser.Model.Cryptography; -using static MediaBrowser.Common.Cryptography.Constants; - -namespace MediaBrowser.Common.Cryptography -{ - /// - /// Class containing extension methods for working with Jellyfin cryptography objects. - /// - public static class CryptoExtensions - { - /// - /// Creates a new instance. - /// - /// The instance used. - /// The password that will be hashed. - /// A instance with the hash method, hash, salt and number of iterations. - public static PasswordHash CreatePasswordHash(this ICryptoProvider cryptoProvider, string password) - { - byte[] salt = cryptoProvider.GenerateSalt(); - return new PasswordHash( - cryptoProvider.DefaultHashMethod, - cryptoProvider.ComputeHashWithDefaultMethod( - Encoding.UTF8.GetBytes(password), - salt), - salt, - new Dictionary - { - { "iterations", DefaultIterations.ToString(CultureInfo.InvariantCulture) } - }); - } - } -} diff --git a/MediaBrowser.Common/Cryptography/PasswordHash.cs b/MediaBrowser.Common/Cryptography/PasswordHash.cs deleted file mode 100644 index 0e2065302..000000000 --- a/MediaBrowser.Common/Cryptography/PasswordHash.cs +++ /dev/null @@ -1,219 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Collections.Generic; -using System.Text; - -namespace MediaBrowser.Common.Cryptography -{ - // Defined from this hash storage spec - // https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md - // $[$=(,=)*][$[$]] - // with one slight amendment to ease the transition, we're writing out the bytes in hex - // rather than making them a BASE64 string with stripped padding - public class PasswordHash - { - private readonly Dictionary _parameters; - private readonly byte[] _salt; - private readonly byte[] _hash; - - public PasswordHash(string id, byte[] hash) - : this(id, hash, Array.Empty()) - { - } - - public PasswordHash(string id, byte[] hash, byte[] salt) - : this(id, hash, salt, new Dictionary()) - { - } - - public PasswordHash(string id, byte[] hash, byte[] salt, Dictionary parameters) - { - if (id == null) - { - throw new ArgumentNullException(nameof(id)); - } - - if (id.Length == 0) - { - throw new ArgumentException("String can't be empty", nameof(id)); - } - - Id = id; - _hash = hash; - _salt = salt; - _parameters = parameters; - } - - /// - /// Gets the symbolic name for the function used. - /// - /// Returns the symbolic name for the function used. - public string Id { get; } - - /// - /// Gets the additional parameters used by the hash function. - /// - public IReadOnlyDictionary Parameters => _parameters; - - /// - /// Gets the salt used for hashing the password. - /// - /// Returns the salt used for hashing the password. - public ReadOnlySpan Salt => _salt; - - /// - /// Gets the hashed password. - /// - /// Return the hashed password. - public ReadOnlySpan Hash => _hash; - - public static PasswordHash Parse(ReadOnlySpan hashString) - { - if (hashString.IsEmpty) - { - throw new ArgumentException("String can't be empty", nameof(hashString)); - } - - if (hashString[0] != '$') - { - throw new FormatException("Hash string must start with a $"); - } - - // Ignore first $ - hashString = hashString[1..]; - - int nextSegment = hashString.IndexOf('$'); - if (hashString.IsEmpty || nextSegment == 0) - { - throw new FormatException("Hash string must contain a valid id"); - } - else if (nextSegment == -1) - { - return new PasswordHash(hashString.ToString(), Array.Empty()); - } - - ReadOnlySpan id = hashString[..nextSegment]; - hashString = hashString[(nextSegment + 1)..]; - Dictionary? parameters = null; - - nextSegment = hashString.IndexOf('$'); - - // Optional parameters - ReadOnlySpan parametersSpan = nextSegment == -1 ? hashString : hashString[..nextSegment]; - if (parametersSpan.Contains('=')) - { - while (!parametersSpan.IsEmpty) - { - ReadOnlySpan parameter; - int index = parametersSpan.IndexOf(','); - if (index == -1) - { - parameter = parametersSpan; - parametersSpan = ReadOnlySpan.Empty; - } - else - { - parameter = parametersSpan[..index]; - parametersSpan = parametersSpan[(index + 1)..]; - } - - int splitIndex = parameter.IndexOf('='); - if (splitIndex == -1 || splitIndex == 0 || splitIndex == parameter.Length - 1) - { - throw new FormatException("Malformed parameter in password hash string"); - } - - (parameters ??= new Dictionary()).Add( - parameter[..splitIndex].ToString(), - parameter[(splitIndex + 1)..].ToString()); - } - - if (nextSegment == -1) - { - // parameters can't be null here - return new PasswordHash(id.ToString(), Array.Empty(), Array.Empty(), parameters!); - } - - hashString = hashString[(nextSegment + 1)..]; - nextSegment = hashString.IndexOf('$'); - } - - if (nextSegment == 0) - { - throw new FormatException("Hash string contains an empty segment"); - } - - byte[] hash; - byte[] salt; - - if (nextSegment == -1) - { - salt = Array.Empty(); - hash = Convert.FromHexString(hashString); - } - else - { - salt = Convert.FromHexString(hashString[..nextSegment]); - hashString = hashString[(nextSegment + 1)..]; - nextSegment = hashString.IndexOf('$'); - if (nextSegment != -1) - { - throw new FormatException("Hash string contains too many segments"); - } - - if (hashString.IsEmpty) - { - throw new FormatException("Hash segment is empty"); - } - - hash = Convert.FromHexString(hashString); - } - - return new PasswordHash(id.ToString(), hash, salt, parameters ?? new Dictionary()); - } - - private void SerializeParameters(StringBuilder stringBuilder) - { - if (_parameters.Count == 0) - { - return; - } - - stringBuilder.Append('$'); - foreach (var pair in _parameters) - { - stringBuilder.Append(pair.Key) - .Append('=') - .Append(pair.Value) - .Append(','); - } - - // Remove last ',' - stringBuilder.Length -= 1; - } - - /// - public override string ToString() - { - var str = new StringBuilder() - .Append('$') - .Append(Id); - SerializeParameters(str); - - if (_salt.Length != 0) - { - str.Append('$') - .Append(Convert.ToHexString(_salt)); - } - - if (_hash.Length != 0) - { - str.Append('$') - .Append(Convert.ToHexString(_hash)); - } - - return str.ToString(); - } - } -} diff --git a/MediaBrowser.Model/Cryptography/Constants.cs b/MediaBrowser.Model/Cryptography/Constants.cs new file mode 100644 index 000000000..f2ebb5d3d --- /dev/null +++ b/MediaBrowser.Model/Cryptography/Constants.cs @@ -0,0 +1,23 @@ +namespace MediaBrowser.Model.Cryptography +{ + /// + /// Class containing global constants for Jellyfin Cryptography. + /// + public static class Constants + { + /// + /// The default length for new salts. + /// + public const int DefaultSaltLength = 128 / 8; + + /// + /// The default output length. + /// + public const int DefaultOutputLength = 512 / 8; + + /// + /// The default amount of iterations for hashing passwords. + /// + public const int DefaultIterations = 120000; + } +} diff --git a/MediaBrowser.Model/Cryptography/ICryptoProvider.cs b/MediaBrowser.Model/Cryptography/ICryptoProvider.cs index d8b7d848a..6c521578c 100644 --- a/MediaBrowser.Model/Cryptography/ICryptoProvider.cs +++ b/MediaBrowser.Model/Cryptography/ICryptoProvider.cs @@ -1,6 +1,6 @@ #pragma warning disable CS1591 -using System.Collections.Generic; +using System; namespace MediaBrowser.Model.Cryptography { @@ -8,11 +8,14 @@ namespace MediaBrowser.Model.Cryptography { string DefaultHashMethod { get; } - IEnumerable GetSupportedHashMethods(); + /// + /// Creates a new instance. + /// + /// The password that will be hashed. + /// A instance with the hash method, hash, salt and number of iterations. + PasswordHash CreatePasswordHash(ReadOnlySpan password); - byte[] ComputeHash(string hashMethod, byte[] bytes, byte[] salt); - - byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt); + bool Verify(PasswordHash hash, ReadOnlySpan password); byte[] GenerateSalt(); diff --git a/MediaBrowser.Model/Cryptography/PasswordHash.cs b/MediaBrowser.Model/Cryptography/PasswordHash.cs new file mode 100644 index 000000000..eec541041 --- /dev/null +++ b/MediaBrowser.Model/Cryptography/PasswordHash.cs @@ -0,0 +1,219 @@ +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; +using System.Text; + +namespace MediaBrowser.Model.Cryptography +{ + // Defined from this hash storage spec + // https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md + // $[$=(,=)*][$[$]] + // with one slight amendment to ease the transition, we're writing out the bytes in hex + // rather than making them a BASE64 string with stripped padding + public class PasswordHash + { + private readonly Dictionary _parameters; + private readonly byte[] _salt; + private readonly byte[] _hash; + + public PasswordHash(string id, byte[] hash) + : this(id, hash, Array.Empty()) + { + } + + public PasswordHash(string id, byte[] hash, byte[] salt) + : this(id, hash, salt, new Dictionary()) + { + } + + public PasswordHash(string id, byte[] hash, byte[] salt, Dictionary parameters) + { + if (id == null) + { + throw new ArgumentNullException(nameof(id)); + } + + if (id.Length == 0) + { + throw new ArgumentException("String can't be empty", nameof(id)); + } + + Id = id; + _hash = hash; + _salt = salt; + _parameters = parameters; + } + + /// + /// Gets the symbolic name for the function used. + /// + /// Returns the symbolic name for the function used. + public string Id { get; } + + /// + /// Gets the additional parameters used by the hash function. + /// + public IReadOnlyDictionary Parameters => _parameters; + + /// + /// Gets the salt used for hashing the password. + /// + /// Returns the salt used for hashing the password. + public ReadOnlySpan Salt => _salt; + + /// + /// Gets the hashed password. + /// + /// Return the hashed password. + public ReadOnlySpan Hash => _hash; + + public static PasswordHash Parse(ReadOnlySpan hashString) + { + if (hashString.IsEmpty) + { + throw new ArgumentException("String can't be empty", nameof(hashString)); + } + + if (hashString[0] != '$') + { + throw new FormatException("Hash string must start with a $"); + } + + // Ignore first $ + hashString = hashString[1..]; + + int nextSegment = hashString.IndexOf('$'); + if (hashString.IsEmpty || nextSegment == 0) + { + throw new FormatException("Hash string must contain a valid id"); + } + else if (nextSegment == -1) + { + return new PasswordHash(hashString.ToString(), Array.Empty()); + } + + ReadOnlySpan id = hashString[..nextSegment]; + hashString = hashString[(nextSegment + 1)..]; + Dictionary? parameters = null; + + nextSegment = hashString.IndexOf('$'); + + // Optional parameters + ReadOnlySpan parametersSpan = nextSegment == -1 ? hashString : hashString[..nextSegment]; + if (parametersSpan.Contains('=')) + { + while (!parametersSpan.IsEmpty) + { + ReadOnlySpan parameter; + int index = parametersSpan.IndexOf(','); + if (index == -1) + { + parameter = parametersSpan; + parametersSpan = ReadOnlySpan.Empty; + } + else + { + parameter = parametersSpan[..index]; + parametersSpan = parametersSpan[(index + 1)..]; + } + + int splitIndex = parameter.IndexOf('='); + if (splitIndex == -1 || splitIndex == 0 || splitIndex == parameter.Length - 1) + { + throw new FormatException("Malformed parameter in password hash string"); + } + + (parameters ??= new Dictionary()).Add( + parameter[..splitIndex].ToString(), + parameter[(splitIndex + 1)..].ToString()); + } + + if (nextSegment == -1) + { + // parameters can't be null here + return new PasswordHash(id.ToString(), Array.Empty(), Array.Empty(), parameters!); + } + + hashString = hashString[(nextSegment + 1)..]; + nextSegment = hashString.IndexOf('$'); + } + + if (nextSegment == 0) + { + throw new FormatException("Hash string contains an empty segment"); + } + + byte[] hash; + byte[] salt; + + if (nextSegment == -1) + { + salt = Array.Empty(); + hash = Convert.FromHexString(hashString); + } + else + { + salt = Convert.FromHexString(hashString[..nextSegment]); + hashString = hashString[(nextSegment + 1)..]; + nextSegment = hashString.IndexOf('$'); + if (nextSegment != -1) + { + throw new FormatException("Hash string contains too many segments"); + } + + if (hashString.IsEmpty) + { + throw new FormatException("Hash segment is empty"); + } + + hash = Convert.FromHexString(hashString); + } + + return new PasswordHash(id.ToString(), hash, salt, parameters ?? new Dictionary()); + } + + private void SerializeParameters(StringBuilder stringBuilder) + { + if (_parameters.Count == 0) + { + return; + } + + stringBuilder.Append('$'); + foreach (var pair in _parameters) + { + stringBuilder.Append(pair.Key) + .Append('=') + .Append(pair.Value) + .Append(','); + } + + // Remove last ',' + stringBuilder.Length -= 1; + } + + /// + public override string ToString() + { + var str = new StringBuilder() + .Append('$') + .Append(Id); + SerializeParameters(str); + + if (_salt.Length != 0) + { + str.Append('$') + .Append(Convert.ToHexString(_salt)); + } + + if (_hash.Length != 0) + { + str.Append('$') + .Append(Convert.ToHexString(_hash)); + } + + return str.ToString(); + } + } +} diff --git a/tests/Jellyfin.Common.Tests/Cryptography/PasswordHashTests.cs b/tests/Jellyfin.Common.Tests/Cryptography/PasswordHashTests.cs deleted file mode 100644 index bfece97b6..000000000 --- a/tests/Jellyfin.Common.Tests/Cryptography/PasswordHashTests.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System; -using System.Collections.Generic; -using MediaBrowser.Common.Cryptography; -using Xunit; - -namespace Jellyfin.Common.Tests.Cryptography -{ - public static class PasswordHashTests - { - [Fact] - public static void Ctor_Null_ThrowsArgumentNullException() - { - Assert.Throws(() => new PasswordHash(null!, Array.Empty())); - } - - [Fact] - public static void Ctor_Empty_ThrowsArgumentException() - { - Assert.Throws(() => new PasswordHash(string.Empty, Array.Empty())); - } - - public static TheoryData Parse_Valid_TestData() - { - var data = new TheoryData(); - // Id - data.Add( - "$PBKDF2", - new PasswordHash("PBKDF2", Array.Empty())); - - // Id + parameter - data.Add( - "$PBKDF2$iterations=1000", - new PasswordHash( - "PBKDF2", - Array.Empty(), - Array.Empty(), - new Dictionary() - { - { "iterations", "1000" }, - })); - - // Id + parameters - data.Add( - "$PBKDF2$iterations=1000,m=120", - new PasswordHash( - "PBKDF2", - Array.Empty(), - Array.Empty(), - new Dictionary() - { - { "iterations", "1000" }, - { "m", "120" } - })); - - // Id + hash - data.Add( - "$PBKDF2$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D", - new PasswordHash( - "PBKDF2", - Convert.FromHexString("62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D"), - Array.Empty(), - new Dictionary())); - - // Id + salt + hash - data.Add( - "$PBKDF2$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D", - new PasswordHash( - "PBKDF2", - Convert.FromHexString("62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D"), - Convert.FromHexString("69F420"), - new Dictionary())); - - // Id + parameter + hash - data.Add( - "$PBKDF2$iterations=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D", - new PasswordHash( - "PBKDF2", - Convert.FromHexString("62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D"), - Array.Empty(), - new Dictionary() - { - { "iterations", "1000" } - })); - // Id + parameters + hash - data.Add( - "$PBKDF2$iterations=1000,m=120$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D", - new PasswordHash( - "PBKDF2", - Convert.FromHexString("62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D"), - Array.Empty(), - new Dictionary() - { - { "iterations", "1000" }, - { "m", "120" } - })); - // Id + parameters + salt + hash - data.Add( - "$PBKDF2$iterations=1000,m=120$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D", - new PasswordHash( - "PBKDF2", - Convert.FromHexString("62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D"), - Convert.FromHexString("69F420"), - new Dictionary() - { - { "iterations", "1000" }, - { "m", "120" } - })); - return data; - } - - [Theory] - [MemberData(nameof(Parse_Valid_TestData))] - public static void Parse_Valid_Success(string passwordHashString, PasswordHash expected) - { - var passwordHash = PasswordHash.Parse(passwordHashString); - Assert.Equal(expected.Id, passwordHash.Id); - Assert.Equal(expected.Parameters, passwordHash.Parameters); - Assert.Equal(expected.Salt.ToArray(), passwordHash.Salt.ToArray()); - Assert.Equal(expected.Hash.ToArray(), passwordHash.Hash.ToArray()); - Assert.Equal(expected.ToString(), passwordHash.ToString()); - } - - [Theory] - [InlineData("$PBKDF2")] - [InlineData("$PBKDF2$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] - [InlineData("$PBKDF2$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] - [InlineData("$PBKDF2$iterations=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] - [InlineData("$PBKDF2$iterations=1000,m=120$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] - [InlineData("$PBKDF2$iterations=1000,m=120$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] - [InlineData("$PBKDF2$iterations=1000,m=120")] - public static void ToString_Roundtrip_Success(string passwordHash) - { - Assert.Equal(passwordHash, PasswordHash.Parse(passwordHash).ToString()); - } - - [Fact] - public static void Parse_Null_ThrowsArgumentException() - { - Assert.Throws(() => PasswordHash.Parse(null)); - } - - [Fact] - public static void Parse_Empty_ThrowsArgumentException() - { - Assert.Throws(() => PasswordHash.Parse(string.Empty)); - } - - [Theory] - [InlineData("$")] // No id - [InlineData("$$")] // Empty segments - [InlineData("PBKDF2$")] // Doesn't start with $ - [InlineData("$PBKDF2$$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Empty segment - [InlineData("$PBKDF2$iterations=1000$$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Empty salt segment - [InlineData("$PBKDF2$iterations=1000$69F420$")] // Empty hash segment - [InlineData("$PBKDF2$=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter - [InlineData("$PBKDF2$=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter - [InlineData("$PBKDF2$iterations=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter - [InlineData("$PBKDF2$iterations=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Ends on $ - [InlineData("$PBKDF2$iterations=1000$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Extra segment - [InlineData("$PBKDF2$iterations=1000$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$anotherone")] // Extra segment - [InlineData("$PBKDF2$iterations=1000$invalidstalt$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid salt - [InlineData("$PBKDF2$iterations=1000$69F420$invalid hash")] // Invalid hash - [InlineData("$PBKDF2$69F420$")] // Empty hash - public static void Parse_InvalidFormat_ThrowsFormatException(string passwordHash) - { - Assert.Throws(() => PasswordHash.Parse(passwordHash)); - } - } -} diff --git a/tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs b/tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs new file mode 100644 index 000000000..6948280a3 --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using MediaBrowser.Model.Cryptography; +using Xunit; + +namespace Jellyfin.Model.Tests.Cryptography +{ + public static class PasswordHashTests + { + [Fact] + public static void Ctor_Null_ThrowsArgumentNullException() + { + Assert.Throws(() => new PasswordHash(null!, Array.Empty())); + } + + [Fact] + public static void Ctor_Empty_ThrowsArgumentException() + { + Assert.Throws(() => new PasswordHash(string.Empty, Array.Empty())); + } + + public static TheoryData Parse_Valid_TestData() + { + var data = new TheoryData(); + // Id + data.Add( + "$PBKDF2", + new PasswordHash("PBKDF2", Array.Empty())); + + // Id + parameter + data.Add( + "$PBKDF2$iterations=1000", + new PasswordHash( + "PBKDF2", + Array.Empty(), + Array.Empty(), + new Dictionary() + { + { "iterations", "1000" }, + })); + + // Id + parameters + data.Add( + "$PBKDF2$iterations=1000,m=120", + new PasswordHash( + "PBKDF2", + Array.Empty(), + Array.Empty(), + new Dictionary() + { + { "iterations", "1000" }, + { "m", "120" } + })); + + // Id + hash + data.Add( + "$PBKDF2$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D", + new PasswordHash( + "PBKDF2", + Convert.FromHexString("62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D"), + Array.Empty(), + new Dictionary())); + + // Id + salt + hash + data.Add( + "$PBKDF2$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D", + new PasswordHash( + "PBKDF2", + Convert.FromHexString("62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D"), + Convert.FromHexString("69F420"), + new Dictionary())); + + // Id + parameter + hash + data.Add( + "$PBKDF2$iterations=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D", + new PasswordHash( + "PBKDF2", + Convert.FromHexString("62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D"), + Array.Empty(), + new Dictionary() + { + { "iterations", "1000" } + })); + // Id + parameters + hash + data.Add( + "$PBKDF2$iterations=1000,m=120$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D", + new PasswordHash( + "PBKDF2", + Convert.FromHexString("62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D"), + Array.Empty(), + new Dictionary() + { + { "iterations", "1000" }, + { "m", "120" } + })); + // Id + parameters + salt + hash + data.Add( + "$PBKDF2$iterations=1000,m=120$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D", + new PasswordHash( + "PBKDF2", + Convert.FromHexString("62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D"), + Convert.FromHexString("69F420"), + new Dictionary() + { + { "iterations", "1000" }, + { "m", "120" } + })); + return data; + } + + [Theory] + [MemberData(nameof(Parse_Valid_TestData))] + public static void Parse_Valid_Success(string passwordHashString, PasswordHash expected) + { + var passwordHash = PasswordHash.Parse(passwordHashString); + Assert.Equal(expected.Id, passwordHash.Id); + Assert.Equal(expected.Parameters, passwordHash.Parameters); + Assert.Equal(expected.Salt.ToArray(), passwordHash.Salt.ToArray()); + Assert.Equal(expected.Hash.ToArray(), passwordHash.Hash.ToArray()); + Assert.Equal(expected.ToString(), passwordHash.ToString()); + } + + [Theory] + [InlineData("$PBKDF2")] + [InlineData("$PBKDF2$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] + [InlineData("$PBKDF2$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] + [InlineData("$PBKDF2$iterations=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] + [InlineData("$PBKDF2$iterations=1000,m=120$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] + [InlineData("$PBKDF2$iterations=1000,m=120$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] + [InlineData("$PBKDF2$iterations=1000,m=120")] + public static void ToString_Roundtrip_Success(string passwordHash) + { + Assert.Equal(passwordHash, PasswordHash.Parse(passwordHash).ToString()); + } + + [Fact] + public static void Parse_Null_ThrowsArgumentException() + { + Assert.Throws(() => PasswordHash.Parse(null)); + } + + [Fact] + public static void Parse_Empty_ThrowsArgumentException() + { + Assert.Throws(() => PasswordHash.Parse(string.Empty)); + } + + [Theory] + [InlineData("$")] // No id + [InlineData("$$")] // Empty segments + [InlineData("PBKDF2$")] // Doesn't start with $ + [InlineData("$PBKDF2$$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Empty segment + [InlineData("$PBKDF2$iterations=1000$$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Empty salt segment + [InlineData("$PBKDF2$iterations=1000$69F420$")] // Empty hash segment + [InlineData("$PBKDF2$=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter + [InlineData("$PBKDF2$=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter + [InlineData("$PBKDF2$iterations=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter + [InlineData("$PBKDF2$iterations=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Ends on $ + [InlineData("$PBKDF2$iterations=1000$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Extra segment + [InlineData("$PBKDF2$iterations=1000$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$anotherone")] // Extra segment + [InlineData("$PBKDF2$iterations=1000$invalidstalt$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid salt + [InlineData("$PBKDF2$iterations=1000$69F420$invalid hash")] // Invalid hash + [InlineData("$PBKDF2$69F420$")] // Empty hash + public static void Parse_InvalidFormat_ThrowsFormatException(string passwordHash) + { + Assert.Throws(() => PasswordHash.Parse(passwordHash)); + } + } +} -- cgit v1.2.3 From d10de5b7f93511daa3cf239b4b4c34dc79000969 Mon Sep 17 00:00:00 2001 From: cvium Date: Wed, 10 Nov 2021 23:25:01 +0100 Subject: Try to use Width and Height from ImageInfo to determine aspect ratio --- Emby.Server.Implementations/Dto/DtoService.cs | 40 +++++++++++---------------- 1 file changed, 16 insertions(+), 24 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 67ecd04e0..4193d0018 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -1398,41 +1398,33 @@ namespace Emby.Server.Implementations.Dto return null; } - ImageDimensions size; - - var defaultAspectRatio = item.GetDefaultPrimaryImageAspectRatio(); - - if (defaultAspectRatio > 0) - { - return defaultAspectRatio; - } - if (!imageInfo.IsLocalFile) { - return null; + return item.GetDefaultPrimaryImageAspectRatio(); } - try - { - size = _imageProcessor.GetImageDimensions(item, imageInfo); + var width = imageInfo.Width; + var height = imageInfo.Height; - if (size.Width <= 0 || size.Height <= 0) + // Fallback to the image processor if the image info is somehow incorrect + if (width <= 0 || height <= 0) + { + try { - return null; + var size = _imageProcessor.GetImageDimensions(item, imageInfo); + width = size.Width; + height = size.Height; + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to determine primary image aspect ratio for {ImagePath}", imageInfo.Path); + return item.GetDefaultPrimaryImageAspectRatio(); } - } - catch (Exception ex) - { - _logger.LogError(ex, "Failed to determine primary image aspect ratio for {0}", imageInfo.Path); - return null; } - var width = size.Width; - var height = size.Height; - if (width <= 0 || height <= 0) { - return null; + return item.GetDefaultPrimaryImageAspectRatio(); } return (double)width / height; -- cgit v1.2.3 From 0415d1ccef19c48a2eaa3c545648ce657f95cfb8 Mon Sep 17 00:00:00 2001 From: cvium Date: Wed, 10 Nov 2021 23:29:41 +0100 Subject: Reduce indentation --- Emby.Server.Implementations/Dto/DtoService.cs | 31 ++++++++++++++------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 4193d0018..f23f4a13f 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -1406,28 +1406,29 @@ namespace Emby.Server.Implementations.Dto var width = imageInfo.Width; var height = imageInfo.Height; + if (width > 0 && height > 0) + { + return (double)width / height; + } + // Fallback to the image processor if the image info is somehow incorrect - if (width <= 0 || height <= 0) + try { - try - { - var size = _imageProcessor.GetImageDimensions(item, imageInfo); - width = size.Width; - height = size.Height; - } - catch (Exception ex) - { - _logger.LogError(ex, "Failed to determine primary image aspect ratio for {ImagePath}", imageInfo.Path); - return item.GetDefaultPrimaryImageAspectRatio(); - } + var size = _imageProcessor.GetImageDimensions(item, imageInfo); + width = size.Width; + height = size.Height; + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to determine primary image aspect ratio for {ImagePath}", imageInfo.Path); } - if (width <= 0 || height <= 0) + if (width > 0 && height > 0) { - return item.GetDefaultPrimaryImageAspectRatio(); + return (double)width / height; } - return (double)width / height; + return item.GetDefaultPrimaryImageAspectRatio(); } } } -- cgit v1.2.3 From 5d19c26d5966db3ff48c73f409290509815cd89a Mon Sep 17 00:00:00 2001 From: cvium Date: Wed, 10 Nov 2021 23:46:56 +0100 Subject: Simplify --- Emby.Server.Implementations/Dto/DtoService.cs | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index f23f4a13f..ab5d45279 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -1403,31 +1403,21 @@ namespace Emby.Server.Implementations.Dto return item.GetDefaultPrimaryImageAspectRatio(); } - var width = imageInfo.Width; - var height = imageInfo.Height; - - if (width > 0 && height > 0) - { - return (double)width / height; - } - - // Fallback to the image processor if the image info is somehow incorrect try { var size = _imageProcessor.GetImageDimensions(item, imageInfo); - width = size.Width; - height = size.Height; + var width = size.Width; + var height = size.Height; + if (width > 0 && height > 0) + { + return (double)width / height; + } } catch (Exception ex) { _logger.LogError(ex, "Failed to determine primary image aspect ratio for {ImagePath}", imageInfo.Path); } - if (width > 0 && height > 0) - { - return (double)width / height; - } - return item.GetDefaultPrimaryImageAspectRatio(); } } -- cgit v1.2.3 From 26001fca934298f0694504963934fe77ab1ffcf8 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Fri, 12 Nov 2021 12:09:23 -0500 Subject: Added translation using Weblate (Belarusian) --- Emby.Server.Implementations/Localization/Core/be.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 Emby.Server.Implementations/Localization/Core/be.json (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/be.json b/Emby.Server.Implementations/Localization/Core/be.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/Emby.Server.Implementations/Localization/Core/be.json @@ -0,0 +1 @@ +{} -- cgit v1.2.3 From 412ae7f4d2b2146907f073f37adad8585678d9d8 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Fri, 12 Nov 2021 12:55:27 -0500 Subject: Added translation using Weblate (Zulu) --- Emby.Server.Implementations/Localization/Core/zu.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 Emby.Server.Implementations/Localization/Core/zu.json (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/zu.json b/Emby.Server.Implementations/Localization/Core/zu.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/Emby.Server.Implementations/Localization/Core/zu.json @@ -0,0 +1 @@ +{} -- cgit v1.2.3 From 1fbe1266e23267abb3e5905f60aebcb34cbac5ed Mon Sep 17 00:00:00 2001 From: WWWesten Date: Fri, 12 Nov 2021 12:56:18 -0500 Subject: Added translation using Weblate (Telugu) --- Emby.Server.Implementations/Localization/Core/te.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 Emby.Server.Implementations/Localization/Core/te.json (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/te.json b/Emby.Server.Implementations/Localization/Core/te.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/Emby.Server.Implementations/Localization/Core/te.json @@ -0,0 +1 @@ +{} -- cgit v1.2.3 From 5a65bc1e696b362760939107a989d24645676d4f Mon Sep 17 00:00:00 2001 From: cvium Date: Sat, 13 Nov 2021 14:37:26 +0100 Subject: Very light cleanup in applicationhost --- Emby.Server.Implementations/ApplicationHost.cs | 126 ++++++++-------------- Jellyfin.Api/Controllers/SystemController.cs | 5 +- MediaBrowser.Common/IApplicationHost.cs | 7 -- MediaBrowser.Controller/IServerApplicationHost.cs | 16 +-- 4 files changed, 52 insertions(+), 102 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 73919f306..c17d355e5 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -3,6 +3,7 @@ #pragma warning disable CS1591 using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; @@ -118,7 +119,7 @@ namespace Emby.Server.Implementations /// /// The disposable parts. /// - private readonly List _disposableParts = new List(); + private readonly ConcurrentDictionary _disposableParts = new (); private readonly IFileSystem _fileSystemManager; private readonly IConfiguration _startupConfig; @@ -129,7 +130,6 @@ namespace Emby.Server.Implementations private List _creatingInstances; private IMediaEncoder _mediaEncoder; private ISessionManager _sessionManager; - private string[] _urlPrefixes; /// /// Gets or sets all concrete types. @@ -210,7 +210,7 @@ namespace Emby.Server.Implementations /// /// Gets the singleton instance. /// - public INetworkManager NetManager { get; internal set; } + public INetworkManager NetManager { get; private set; } /// /// Gets a value indicating whether this instance has changes that require the entire application to restart. @@ -232,16 +232,16 @@ namespace Emby.Server.Implementations protected ILoggerFactory LoggerFactory { get; } /// - /// Gets or sets the application paths. + /// Gets the application paths. /// /// The application paths. - protected IServerApplicationPaths ApplicationPaths { get; set; } + protected IServerApplicationPaths ApplicationPaths { get; } /// - /// Gets or sets the configuration manager. + /// Gets the configuration manager. /// /// The configuration manager. - public ServerConfigurationManager ConfigurationManager { get; set; } + public ServerConfigurationManager ConfigurationManager { get; } /// /// Gets or sets the service provider. @@ -344,22 +344,6 @@ namespace Emby.Server.Implementations .Replace(appPaths.InternalMetadataPath, appPaths.VirtualInternalMetadataPath, StringComparison.OrdinalIgnoreCase); } - /// - /// Creates an instance of type and resolves all constructor dependencies. - /// - /// The type. - /// System.Object. - public object CreateInstance(Type type) - => ActivatorUtilities.CreateInstance(ServiceProvider, type); - - /// - /// Creates an instance of type and resolves all constructor dependencies. - /// - /// The type. - /// T. - public T CreateInstance() - => ActivatorUtilities.CreateInstance(ServiceProvider); - /// /// Creates the instance safe. /// @@ -369,7 +353,7 @@ namespace Emby.Server.Implementations { _creatingInstances ??= new List(); - if (_creatingInstances.IndexOf(type) != -1) + if (_creatingInstances.Contains(type)) { Logger.LogError("DI Loop detected in the attempted creation of {Type}", type.FullName); foreach (var entry in _creatingInstances) @@ -379,7 +363,7 @@ namespace Emby.Server.Implementations _pluginManager.FailPlugin(type.Assembly); - throw new ExternalException("DI Loop detected."); + throw new TypeLoadException("DI Loop detected"); } try @@ -412,8 +396,15 @@ namespace Emby.Server.Implementations public IEnumerable GetExportTypes() { var currentType = typeof(T); - - return _allConcreteTypes.Where(i => currentType.IsAssignableFrom(i)); + var numberOfConcreteTypes = _allConcreteTypes.Length; + for (var i = 0; i < numberOfConcreteTypes; i++) + { + var type = _allConcreteTypes[i]; + if (currentType.IsAssignableFrom(type)) + { + yield return type; + } + } } /// @@ -428,9 +419,9 @@ namespace Emby.Server.Implementations if (manageLifetime) { - lock (_disposableParts) + foreach (var part in parts.OfType()) { - _disposableParts.AddRange(parts.OfType()); + _disposableParts.TryAdd(part, byte.MinValue); } } @@ -449,9 +440,9 @@ namespace Emby.Server.Implementations if (manageLifetime) { - lock (_disposableParts) + foreach (var part in parts.OfType()) { - _disposableParts.AddRange(parts.OfType()); + _disposableParts.TryAdd(part, byte.MinValue); } } @@ -563,7 +554,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(ConfigurationManager); serviceCollection.AddSingleton(ConfigurationManager); serviceCollection.AddSingleton(this); - serviceCollection.AddSingleton(_pluginManager); + serviceCollection.AddSingleton(_pluginManager); serviceCollection.AddSingleton(ApplicationPaths); serviceCollection.AddSingleton(_fileSystemManager); @@ -586,7 +577,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); serviceCollection.AddSingleton(this); - serviceCollection.AddSingleton(ApplicationPaths); + serviceCollection.AddSingleton(ApplicationPaths); serviceCollection.AddSingleton(); @@ -790,8 +781,6 @@ namespace Emby.Server.Implementations _pluginManager.CreatePlugins(); - _urlPrefixes = GetUrlPrefixes().ToArray(); - Resolve().AddParts( GetExports(), GetExports(), @@ -859,32 +848,12 @@ namespace Emby.Server.Implementations } } - private IEnumerable GetUrlPrefixes() - { - var hosts = new[] { "+" }; - - return hosts.SelectMany(i => - { - var prefixes = new List - { - "http://" + i + ":" + HttpPort + "/" - }; - - if (Certificate != null) - { - prefixes.Add("https://" + i + ":" + HttpsPort + "/"); - } - - return prefixes; - }); - } - /// /// Called when [configuration updated]. /// /// The sender. /// The instance containing the event data. - protected void OnConfigurationUpdated(object sender, EventArgs e) + private void OnConfigurationUpdated(object sender, EventArgs e) { var requiresRestart = false; var networkConfiguration = ConfigurationManager.GetNetworkConfiguration(); @@ -893,8 +862,8 @@ namespace Emby.Server.Implementations if (HttpPort != 0 && HttpsPort != 0) { // Need to restart if ports have changed - if (networkConfiguration.HttpServerPortNumber != HttpPort || - networkConfiguration.HttpsPortNumber != HttpsPort) + if (networkConfiguration.HttpServerPortNumber != HttpPort + || networkConfiguration.HttpsPortNumber != HttpsPort) { if (ConfigurationManager.Configuration.IsPortAuthorized) { @@ -906,11 +875,6 @@ namespace Emby.Server.Implementations } } - if (!_urlPrefixes.SequenceEqual(GetUrlPrefixes(), StringComparer.OrdinalIgnoreCase)) - { - requiresRestart = true; - } - if (ValidateSslCertificate(networkConfiguration)) { requiresRestart = true; @@ -952,7 +916,7 @@ namespace Emby.Server.Implementations } /// - /// Notifies that the kernel that a change has been made that requires a restart. + /// Notifies the kernel that a change has been made that requires a restart. /// public void NotifyPendingRestart() { @@ -1093,11 +1057,6 @@ namespace Emby.Server.Implementations }; } - public IEnumerable GetWakeOnLanInfo() - => NetManager.GetMacAddresses() - .Select(i => new WakeOnLanInfo(i)) - .ToList(); - public PublicSystemInfo GetPublicSystemInfo(HttpRequest request) { return new PublicSystemInfo @@ -1113,7 +1072,7 @@ namespace Emby.Server.Implementations } /// - public string GetSmartApiUrl(IPAddress remoteAddr, int? port = null) + public string GetSmartApiUrl(IPAddress remoteAddr) { // Published server ends with a / if (!string.IsNullOrEmpty(PublishedServerUrl)) @@ -1122,12 +1081,12 @@ namespace Emby.Server.Implementations return PublishedServerUrl.Trim('/'); } - string smart = NetManager.GetBindInterface(remoteAddr, out port); + string smart = NetManager.GetBindInterface(remoteAddr, out var port); return GetLocalApiUrl(smart.Trim('/'), null, port); } /// - public string GetSmartApiUrl(HttpRequest request, int? port = null) + public string GetSmartApiUrl(HttpRequest request) { // Return the host in the HTTP request as the API url if (ConfigurationManager.GetNetworkConfiguration().EnablePublishedServerUriByRequest) @@ -1148,12 +1107,12 @@ namespace Emby.Server.Implementations return PublishedServerUrl.Trim('/'); } - string smart = NetManager.GetBindInterface(request, out port); + string smart = NetManager.GetBindInterface(request, out var port); return GetLocalApiUrl(smart.Trim('/'), request.Scheme, port); } /// - public string GetSmartApiUrl(string hostname, int? port = null) + public string GetSmartApiUrl(string hostname) { // Published server ends with a / if (!string.IsNullOrEmpty(PublishedServerUrl)) @@ -1162,7 +1121,7 @@ namespace Emby.Server.Implementations return PublishedServerUrl.Trim('/'); } - string smart = NetManager.GetBindInterface(hostname, out port); + string smart = NetManager.GetBindInterface(hostname, out var port); return GetLocalApiUrl(smart.Trim('/'), null, port); } @@ -1258,12 +1217,15 @@ namespace Emby.Server.Implementations Logger.LogInformation("Disposing {Type}", type.Name); - var parts = _disposableParts.Distinct().Where(i => i.GetType() != type).ToList(); - _disposableParts.Clear(); - - foreach (var part in parts) + foreach (var (part, _) in _disposableParts) { - Logger.LogInformation("Disposing {Type}", part.GetType().Name); + var partType = part.GetType(); + if (partType == type) + { + continue; + } + + Logger.LogInformation("Disposing {Type}", partType.Name); try { @@ -1271,9 +1233,11 @@ namespace Emby.Server.Implementations } catch (Exception ex) { - Logger.LogError(ex, "Error disposing {Type}", part.GetType().Name); + Logger.LogError(ex, "Error disposing {Type}", partType.Name); } } + + _disposableParts.Clear(); } _disposed = true; diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index 904738bb4..2ff85fd2a 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -212,10 +212,13 @@ namespace Jellyfin.Api.Controllers /// An with the WakeOnLan infos. [HttpGet("WakeOnLanInfo")] [Authorize(Policy = Policies.DefaultAuthorization)] + [Obsolete("This endpoint is obsolete.")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetWakeOnLanInfo() { - var result = _appHost.GetWakeOnLanInfo(); + var result = _network.GetMacAddresses() + .Select(i => new WakeOnLanInfo(i)) + .ToList(); return Ok(result); } } diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index e49ab41f4..53683cdbd 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -140,12 +140,5 @@ namespace MediaBrowser.Common /// /// Instance of the interface. void Init(IServiceCollection serviceCollection); - - /// - /// Creates the instance. - /// - /// The type. - /// System.Object. - object CreateInstance(Type type); } } diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 7da492af3..8f8cf75a6 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -42,11 +42,6 @@ namespace MediaBrowser.Controller /// The name of the friendly. string FriendlyName { get; } - /// - /// Gets the configured published server url. - /// - string PublishedServerUrl { get; } - /// /// Gets the system info. /// @@ -60,25 +55,22 @@ namespace MediaBrowser.Controller /// Gets a URL specific for the request. /// /// The instance. - /// Optional port number. /// An accessible URL. - string GetSmartApiUrl(HttpRequest request, int? port = null); + string GetSmartApiUrl(HttpRequest request); /// /// Gets a URL specific for the request. /// /// The remote of the connection. - /// Optional port number. /// An accessible URL. - string GetSmartApiUrl(IPAddress remoteAddr, int? port = null); + string GetSmartApiUrl(IPAddress remoteAddr); /// /// Gets a URL specific for the request. /// /// The hostname used in the connection. - /// Optional port number. /// An accessible URL. - string GetSmartApiUrl(string hostname, int? port = null); + string GetSmartApiUrl(string hostname); /// /// Gets an URL that can be used to access the API over LAN. @@ -103,8 +95,6 @@ namespace MediaBrowser.Controller /// The API URL. string GetLocalApiUrl(string hostname, string scheme = null, int? port = null); - IEnumerable GetWakeOnLanInfo(); - string ExpandVirtualPath(string path); string ReverseVirtualPath(string path); -- cgit v1.2.3 From 4a28f46cac30e2e1fabc84016d710bcd309a5344 Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Sat, 13 Nov 2021 07:27:28 -0700 Subject: Don't throw exception on unauthenticated requests --- Emby.Server.Implementations/HttpServer/Security/AuthService.cs | 2 +- Emby.Server.Implementations/HttpServer/WebSocketManager.cs | 7 ++++++- Jellyfin.Api/Auth/CustomAuthenticationHandler.cs | 5 +++++ tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs | 2 ++ 4 files changed, 14 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index e2ad07177..e7103ec95 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -24,7 +24,7 @@ namespace Emby.Server.Implementations.HttpServer.Security if (!auth.HasToken) { - throw new AuthenticationException("Request does not contain a token."); + return auth; } if (!auth.IsAuthenticated) diff --git a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs index f86bfd755..e99876dce 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs @@ -35,7 +35,12 @@ namespace Emby.Server.Implementations.HttpServer /// public async Task WebSocketRequestHandler(HttpContext context) { - _ = await _authService.Authenticate(context.Request).ConfigureAwait(false); + var authorizationInfo = await _authService.Authenticate(context.Request).ConfigureAwait(false); + if (!authorizationInfo.IsAuthenticated) + { + throw new SecurityException("Token is required"); + } + try { _logger.LogInformation("WS {IP} request", context.Connection.RemoteIpAddress); diff --git a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs index 369e846ae..bd3e7d9e3 100644 --- a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs +++ b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs @@ -45,6 +45,11 @@ namespace Jellyfin.Api.Auth try { var authorizationInfo = await _authService.Authenticate(Request).ConfigureAwait(false); + if (!authorizationInfo.HasToken) + { + return AuthenticateResult.NoResult(); + } + var role = UserRoles.User; if (authorizationInfo.IsApiKey || authorizationInfo.User.HasPermission(PermissionKind.IsAdministrator)) { diff --git a/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs b/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs index cd03958b6..6f5c0ed0c 100644 --- a/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs +++ b/tests/Jellyfin.Api.Tests/Auth/CustomAuthenticationHandlerTests.cs @@ -132,6 +132,8 @@ namespace Jellyfin.Api.Tests.Auth authorizationInfo.User.AddDefaultPreferences(); authorizationInfo.User.SetPermission(PermissionKind.IsAdministrator, isAdmin); authorizationInfo.IsApiKey = false; + authorizationInfo.HasToken = true; + authorizationInfo.Token = "fake-token"; _jellyfinAuthServiceMock.Setup( a => a.Authenticate( -- cgit v1.2.3 From 25f1cdbcb5026a62cea3b60be0f313c83e6b4d3a Mon Sep 17 00:00:00 2001 From: WWWesten Date: Sat, 13 Nov 2021 10:36:36 +0000 Subject: Translated using Weblate (Catalan) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ca/ --- Emby.Server.Implementations/Localization/Core/ca.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/ca.json b/Emby.Server.Implementations/Localization/Core/ca.json index db3c13d80..2dee5e327 100644 --- a/Emby.Server.Implementations/Localization/Core/ca.json +++ b/Emby.Server.Implementations/Localization/Core/ca.json @@ -25,7 +25,7 @@ "HeaderLiveTV": "TV en Directe", "HeaderNextUp": "A continuació", "HeaderRecordingGroups": "Grups d'Enregistrament", - "HomeVideos": "Vídeos domèstics", + "HomeVideos": "Vídeos Domèstics", "Inherit": "Hereta", "ItemAddedWithName": "{0} ha estat afegit a la biblioteca", "ItemRemovedWithName": "{0} ha estat eliminat de la biblioteca", @@ -39,7 +39,7 @@ "MixedContent": "Contingut barrejat", "Movies": "Pel·lícules", "Music": "Música", - "MusicVideos": "Vídeos musicals", + "MusicVideos": "Vídeos Musicals", "NameInstallFailed": "Instalació de {0} fallida", "NameSeasonNumber": "Temporada {0}", "NameSeasonUnknown": "Temporada Desconeguda", -- cgit v1.2.3 From 14b5e85461d7617cb37d5b9ac793d80c327fd821 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Sat, 13 Nov 2021 10:28:50 +0000 Subject: Translated using Weblate (Belarusian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/be/ --- Emby.Server.Implementations/Localization/Core/be.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/be.json b/Emby.Server.Implementations/Localization/Core/be.json index 0967ef424..56c4e7d39 100644 --- a/Emby.Server.Implementations/Localization/Core/be.json +++ b/Emby.Server.Implementations/Localization/Core/be.json @@ -1 +1,4 @@ -{} +{ + "Sync": "Сінхранізацыя", + "Playlists": "Плэйліст" +} -- cgit v1.2.3 From 5254e74719e666ab9c02dbda25de6c0da9412d43 Mon Sep 17 00:00:00 2001 From: Haadiy Rozzaq Date: Sat, 13 Nov 2021 20:50:30 +0000 Subject: Translated using Weblate (Indonesian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/id/ --- Emby.Server.Implementations/Localization/Core/id.json | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/id.json b/Emby.Server.Implementations/Localization/Core/id.json index ba3513870..37d59abd9 100644 --- a/Emby.Server.Implementations/Localization/Core/id.json +++ b/Emby.Server.Implementations/Localization/Core/id.json @@ -7,10 +7,10 @@ "MessageApplicationUpdated": "Jellyfin Server sudah diperbarui", "Latest": "Terbaru", "LabelIpAddressValue": "Alamat IP: {0}", - "ItemRemovedWithName": "{0} sudah dikeluarkan dari pustaka", + "ItemRemovedWithName": "{0} sudah dihapus dari pustaka", "ItemAddedWithName": "{0} telah dimasukkan ke dalam pustaka", - "Inherit": "Warisan", - "HomeVideos": "Video Rumah", + "Inherit": "Warisi", + "HomeVideos": "Video Rumahan", "HeaderRecordingGroups": "Grup Rekaman", "HeaderNextUp": "Selanjutnya", "HeaderLiveTV": "TV Live", @@ -73,7 +73,7 @@ "NotificationOptionCameraImageUploaded": "Gambar kamera terunggah", "NotificationOptionApplicationUpdateInstalled": "Pembaruan aplikasi terpasang", "NotificationOptionApplicationUpdateAvailable": "Pembaruan aplikasi tersedia", - "NewVersionIsAvailable": "Versi baru dari Jellyfin Server tersedia untuk diunduh.", + "NewVersionIsAvailable": "Versi baru dari Jellyfin Server sudah tersedia untuk diunduh.", "NameSeasonUnknown": "Musim tak diketahui", "NameSeasonNumber": "Musim {0}", "NameInstallFailed": "{0} penginstalan gagal", @@ -117,5 +117,7 @@ "TaskCleanActivityLog": "Bersihkan Log Aktivitas", "Undefined": "Tidak terdefinisi", "Forced": "Dipaksa", - "Default": "Bawaan" + "Default": "Bawaan", + "TaskOptimizeDatabaseDescription": "Rapihkan basis data dan membersihkan ruang kosong. Menjalankan tugas ini setelah memindai pustaka atau melakukan perubahan lain yang menyiratkan modifikasi basis data dapat meningkatkan kinerja.", + "TaskOptimizeDatabase": "Optimalkan basis data" } -- cgit v1.2.3 From 551c6f02a221f751942a49fe4f0685c06d3b7fd0 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Mon, 15 Nov 2021 07:48:22 -0500 Subject: Added translation using Weblate (Assamese) --- Emby.Server.Implementations/Localization/Core/as.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 Emby.Server.Implementations/Localization/Core/as.json (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/as.json b/Emby.Server.Implementations/Localization/Core/as.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/Emby.Server.Implementations/Localization/Core/as.json @@ -0,0 +1 @@ +{} -- cgit v1.2.3 From 9c74103fbe151cad7ec0c2ddf4061afc9378b203 Mon Sep 17 00:00:00 2001 From: rimasx Date: Sun, 14 Nov 2021 20:09:22 +0000 Subject: Translated using Weblate (Estonian) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/et/ --- Emby.Server.Implementations/Localization/Core/et.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Localization/Core/et.json b/Emby.Server.Implementations/Localization/Core/et.json index e5405e515..626d76d6b 100644 --- a/Emby.Server.Implementations/Localization/Core/et.json +++ b/Emby.Server.Implementations/Localization/Core/et.json @@ -114,5 +114,7 @@ "Artists": "Esitajad", "Application": "Rakendus", "AppDeviceValues": "Rakendus: {0}, seade: {1}", - "Albums": "Albumid" + "Albums": "Albumid", + "UserOfflineFromDevice": "{0} katkestas ühenduse {1}-ga", + "SubtitleDownloadFailureFromForItem": "Subtiitrite allalaadimine {0} > {1} nurjus" } -- cgit v1.2.3 From 4f45c526748132f3ce19fc8b357f498d8100671d Mon Sep 17 00:00:00 2001 From: cvium Date: Mon, 15 Nov 2021 15:56:02 +0100 Subject: Remove ILibraryManager as a dependency in resolvers etc. --- Emby.Server.Implementations/ApplicationHost.cs | 2 + .../Library/CoreResolutionIgnoreRule.cs | 13 +++-- .../Library/LibraryManager.cs | 47 +++++---------- .../Library/Resolvers/Audio/AudioResolver.cs | 67 +++++++++------------- .../Library/Resolvers/Audio/MusicAlbumResolver.cs | 30 ++++------ .../Library/Resolvers/Audio/MusicArtistResolver.cs | 19 ++---- .../Library/Resolvers/BaseVideoResolver.cs | 13 +++-- .../Library/Resolvers/GenericVideoResolver.cs | 6 +- .../Library/Resolvers/Movies/MovieResolver.cs | 23 ++++---- .../Library/Resolvers/PhotoAlbumResolver.cs | 11 ++-- .../Library/Resolvers/PhotoResolver.cs | 23 ++++---- .../Library/Resolvers/TV/EpisodeResolver.cs | 7 ++- .../Library/Resolvers/TV/SeasonResolver.cs | 30 +++++----- .../Library/Resolvers/TV/SeriesResolver.cs | 38 +++++++----- MediaBrowser.Controller/Library/ILibraryManager.cs | 20 ------- MediaBrowser.Controller/Library/ItemResolveArgs.cs | 35 +++++++++++ .../Library/EpisodeResolverTest.cs | 14 ++--- 17 files changed, 185 insertions(+), 213 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index c17d355e5..99ad9fdf4 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -19,6 +19,7 @@ using Emby.Dlna; using Emby.Dlna.Main; using Emby.Dlna.Ssdp; using Emby.Drawing; +using Emby.Naming.Common; using Emby.Notifications; using Emby.Photos; using Emby.Server.Implementations.Archiving; @@ -596,6 +597,7 @@ namespace Emby.Server.Implementations serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index bc5b4499f..29758a078 100644 --- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -1,8 +1,9 @@ using System; using System.IO; +using Emby.Naming.Audio; +using Emby.Naming.Common; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.IO; @@ -13,17 +14,17 @@ namespace Emby.Server.Implementations.Library /// public class CoreResolutionIgnoreRule : IResolverIgnoreRule { - private readonly ILibraryManager _libraryManager; + private readonly NamingOptions _namingOptions; private readonly IServerApplicationPaths _serverApplicationPaths; /// /// Initializes a new instance of the class. /// - /// The library manager. + /// The naming options. /// The server application paths. - public CoreResolutionIgnoreRule(ILibraryManager libraryManager, IServerApplicationPaths serverApplicationPaths) + public CoreResolutionIgnoreRule(NamingOptions namingOptions, IServerApplicationPaths serverApplicationPaths) { - _libraryManager = libraryManager; + _namingOptions = namingOptions; _serverApplicationPaths = serverApplicationPaths; } @@ -78,7 +79,7 @@ namespace Emby.Server.Implementations.Library { // Don't resolve these into audio files if (Path.GetFileNameWithoutExtension(filename.AsSpan()).Equals(BaseItem.ThemeSongFileName, StringComparison.Ordinal) - && _libraryManager.IsAudioFile(filename)) + && AudioFileParser.IsAudioFile(filename, _namingOptions)) { return true; } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 559da7f5c..778b6225e 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -79,6 +79,7 @@ namespace Emby.Server.Implementations.Library private readonly IFileSystem _fileSystem; private readonly IItemRepository _itemRepository; private readonly IImageProcessor _imageProcessor; + private readonly NamingOptions _namingOptions; /// /// The _root folder sync lock. @@ -88,9 +89,6 @@ namespace Emby.Server.Implementations.Library private readonly TimeSpan _viewRefreshInterval = TimeSpan.FromHours(24); - private NamingOptions _namingOptions; - private string[] _videoFileExtensions; - /// /// The _root folder. /// @@ -116,6 +114,7 @@ namespace Emby.Server.Implementations.Library /// The item repository. /// The image processor. /// The memory cache. + /// The naming options. public LibraryManager( IServerApplicationHost appHost, ILogger logger, @@ -130,7 +129,8 @@ namespace Emby.Server.Implementations.Library IMediaEncoder mediaEncoder, IItemRepository itemRepository, IImageProcessor imageProcessor, - IMemoryCache memoryCache) + IMemoryCache memoryCache, + NamingOptions namingOptions) { _appHost = appHost; _logger = logger; @@ -146,6 +146,7 @@ namespace Emby.Server.Implementations.Library _itemRepository = itemRepository; _imageProcessor = imageProcessor; _memoryCache = memoryCache; + _namingOptions = namingOptions; _configurationManager.ConfigurationUpdated += ConfigurationUpdated; @@ -2500,16 +2501,6 @@ namespace Emby.Server.Implementations.Library return RootFolder; } - /// - public bool IsVideoFile(string path) - { - return VideoResolver.IsVideoFile(path, GetNamingOptions()); - } - - /// - public bool IsAudioFile(string path) - => AudioFileParser.IsAudioFile(path, GetNamingOptions()); - /// public int? GetSeasonNumberFromPath(string path) => SeasonPathParser.Parse(path, true, true).SeasonNumber; @@ -2525,7 +2516,7 @@ namespace Emby.Server.Implementations.Library isAbsoluteNaming = null; } - var resolver = new EpisodeResolver(GetNamingOptions()); + var resolver = new EpisodeResolver(_namingOptions); var isFolder = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd; @@ -2682,21 +2673,9 @@ namespace Emby.Server.Implementations.Library return changed; } - /// - public NamingOptions GetNamingOptions() - { - if (_namingOptions == null) - { - _namingOptions = new NamingOptions(); - _videoFileExtensions = _namingOptions.VideoFileExtensions; - } - - return _namingOptions; - } - public ItemLookupInfo ParseName(string name) { - var namingOptions = GetNamingOptions(); + var namingOptions = _namingOptions; var result = VideoResolver.CleanDateTime(name, namingOptions); return new ItemLookupInfo @@ -2708,11 +2687,11 @@ namespace Emby.Server.Implementations.Library public IEnumerable public class AudioResolver : ItemResolver, IMultiItemResolver { - private readonly ILibraryManager _libraryManager; + private readonly NamingOptions _namingOptions; - public AudioResolver(ILibraryManager libraryManager) + public AudioResolver(NamingOptions namingOptions) { - _libraryManager = libraryManager; + _namingOptions = namingOptions; } /// @@ -40,7 +43,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio string collectionType, IDirectoryService directoryService) { - var result = ResolveMultipleInternal(parent, files, collectionType, directoryService); + var result = ResolveMultipleInternal(parent, files, collectionType); if (result != null) { @@ -56,12 +59,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio private MultiItemResolverResult ResolveMultipleInternal( Folder parent, List files, - string collectionType, - IDirectoryService directoryService) + string collectionType) { if (string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase)) { - return ResolveMultipleAudio(parent, files, directoryService, false, collectionType, true); + return ResolveMultipleAudio(parent, files, true); } return null; @@ -87,14 +89,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio return null; } - var files = args.FileSystemChildren - .Where(i => !_libraryManager.IgnoreFile(i, args.Parent)) - .ToList(); - - return FindAudio(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false); + return FindAudioBook(args, false); } - if (_libraryManager.IsAudioFile(args.Path)) + if (AudioFileParser.IsAudioFile(args.Path, _namingOptions)) { var extension = Path.GetExtension(args.Path); @@ -107,7 +105,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio var isMixedCollectionType = string.IsNullOrEmpty(collectionType); // For conflicting extensions, give priority to videos - if (isMixedCollectionType && _libraryManager.IsVideoFile(args.Path)) + if (isMixedCollectionType && VideoResolver.IsVideoFile(args.Path, _namingOptions)) { return null; } @@ -141,29 +139,23 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio return null; } - private T FindAudio(ItemResolveArgs args, string path, Folder parent, List fileSystemEntries, IDirectoryService directoryService, string collectionType, bool parseName) - where T : MediaBrowser.Controller.Entities.Audio.Audio, new() + private AudioBook FindAudioBook(ItemResolveArgs args, bool parseName) { // TODO: Allow GetMultiDiscMovie in here - const bool supportsMultiVersion = false; + var result = ResolveMultipleAudio(args.Parent, args.GetActualFileSystemChildren(), parseName); - var result = ResolveMultipleAudio(parent, fileSystemEntries, directoryService, supportsMultiVersion, collectionType, parseName) ?? - new MultiItemResolverResult(); - - if (result.Items.Count == 1) + if (result == null || result.Items.Count != 1 || result.Items[0] is not AudioBook item) { - // If we were supporting this we'd be checking filesFromOtherItems - var item = (T)result.Items[0]; - item.IsInMixedFolder = false; - item.Name = Path.GetFileName(item.ContainingFolderPath); - return item; + return null; } - return null; + // If we were supporting this we'd be checking filesFromOtherItems + item.IsInMixedFolder = false; + item.Name = Path.GetFileName(item.ContainingFolderPath); + return item; } - private MultiItemResolverResult ResolveMultipleAudio(Folder parent, IEnumerable fileSystemEntries, IDirectoryService directoryService, bool suppportMultiEditions, string collectionType, bool parseName) - where T : MediaBrowser.Controller.Entities.Audio.Audio, new() + private MultiItemResolverResult ResolveMultipleAudio(Folder parent, IEnumerable fileSystemEntries, bool parseName) { var files = new List(); var items = new List(); @@ -176,15 +168,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio { leftOver.Add(child); } - else if (!IsIgnored(child.Name)) + else { files.Add(child); } } - var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(); - - var resolver = new AudioBookListResolver(namingOptions); + var resolver = new AudioBookListResolver(_namingOptions); var resolverResult = resolver.Resolve(files).ToList(); var result = new MultiItemResolverResult @@ -210,7 +200,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio var firstMedia = resolvedItem.Files[0]; - var libraryItem = new T + var libraryItem = new AudioBook { Path = firstMedia.Path, IsInMixedFolder = isInMixedFolder, @@ -230,12 +220,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio return result; } - private bool ContainsFile(List result, FileSystemMetadata file) + private static bool ContainsFile(IEnumerable result, FileSystemMetadata file) { return result.Any(i => ContainsFile(i, file)); } - private bool ContainsFile(AudioBookInfo result, FileSystemMetadata file) + private static bool ContainsFile(AudioBookInfo result, FileSystemMetadata file) { return result.Files.Any(i => ContainsFile(i, file)) || result.AlternateVersions.Any(i => ContainsFile(i, file)) || @@ -246,10 +236,5 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio { return string.Equals(result.Path, file.FullName, StringComparison.OrdinalIgnoreCase); } - - private static bool IsIgnored(string filename) - { - return false; - } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index 9e3f62276..a9819a364 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Emby.Naming.Audio; +using Emby.Naming.Common; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; @@ -22,20 +23,17 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio public class MusicAlbumResolver : ItemResolver { private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly ILibraryManager _libraryManager; + private readonly NamingOptions _namingOptions; /// /// Initializes a new instance of the class. /// /// The logger. - /// The file system. - /// The library manager. - public MusicAlbumResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager) + /// The naming options. + public MusicAlbumResolver(ILogger logger, NamingOptions namingOptions) { _logger = logger; - _fileSystem = fileSystem; - _libraryManager = libraryManager; + _namingOptions = namingOptions; } /// @@ -87,7 +85,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio /// true if the provided path points to a music album, false otherwise. public bool IsMusicAlbum(string path, IDirectoryService directoryService) { - return ContainsMusic(directoryService.GetFileSystemEntries(path), true, directoryService, _logger, _fileSystem, _libraryManager); + return ContainsMusic(directoryService.GetFileSystemEntries(path), true, directoryService); } /// @@ -101,7 +99,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio if (args.IsDirectory) { // if (args.Parent is MusicArtist) return true; // saves us from testing children twice - if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, _libraryManager)) + if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService)) { return true; } @@ -116,13 +114,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio private bool ContainsMusic( IEnumerable list, bool allowSubfolders, - IDirectoryService directoryService, - ILogger logger, - IFileSystem fileSystem, - ILibraryManager libraryManager) + IDirectoryService directoryService) { // check for audio files before digging down into directories - var foundAudioFile = list.Any(fileSystemInfo => !fileSystemInfo.IsDirectory && libraryManager.IsAudioFile(fileSystemInfo.FullName)); + var foundAudioFile = list.Any(fileSystemInfo => !fileSystemInfo.IsDirectory && AudioFileParser.IsAudioFile(fileSystemInfo.FullName, _namingOptions)); if (foundAudioFile) { // at least one audio file exists @@ -137,21 +132,20 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio var discSubfolderCount = 0; - var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(); - var parser = new AlbumParser(namingOptions); + var parser = new AlbumParser(_namingOptions); var directories = list.Where(fileSystemInfo => fileSystemInfo.IsDirectory); var result = Parallel.ForEach(directories, (fileSystemInfo, state) => { var path = fileSystemInfo.FullName; - var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager); + var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService); if (hasMusic) { if (parser.IsMultiPart(path)) { - logger.LogDebug("Found multi-disc folder: {Path}", path); + _logger.LogDebug("Found multi-disc folder: {Path}", path); Interlocked.Increment(ref discSubfolderCount); } else diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs index 3d2ae95d2..27e18be42 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs @@ -3,6 +3,7 @@ using System; using System.Linq; using System.Threading.Tasks; +using Emby.Naming.Common; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; @@ -19,27 +20,19 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio public class MusicArtistResolver : ItemResolver { private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly ILibraryManager _libraryManager; - private readonly IServerConfigurationManager _config; + private NamingOptions _namingOptions; /// /// Initializes a new instance of the class. /// /// The logger for the created instances. - /// The file system. - /// The library manager. - /// The configuration manager. + /// The naming options. public MusicArtistResolver( ILogger logger, - IFileSystem fileSystem, - ILibraryManager libraryManager, - IServerConfigurationManager config) + NamingOptions namingOptions) { _logger = logger; - _fileSystem = fileSystem; - _libraryManager = libraryManager; - _config = config; + _namingOptions = namingOptions; } /// @@ -89,7 +82,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio var directoryService = args.DirectoryService; - var albumResolver = new MusicAlbumResolver(_logger, _fileSystem, _libraryManager); + var albumResolver = new MusicAlbumResolver(_logger, _namingOptions); // If we contain an album assume we are an artist folder var directories = args.FileSystemChildren.Where(i => i.IsDirectory); diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index 9ff99fa43..0ebf0e530 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -6,6 +6,7 @@ using System; using System.IO; using System.Linq; using DiscUtils.Udf; +using Emby.Naming.Common; using Emby.Naming.Video; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -21,12 +22,12 @@ namespace Emby.Server.Implementations.Library.Resolvers public abstract class BaseVideoResolver : MediaBrowser.Controller.Resolvers.ItemResolver where T : Video, new() { - protected BaseVideoResolver(ILibraryManager libraryManager) + protected BaseVideoResolver(NamingOptions namingOptions) { - LibraryManager = libraryManager; + NamingOptions = namingOptions; } - protected ILibraryManager LibraryManager { get; } + protected NamingOptions NamingOptions { get; } /// /// Resolves the specified args. @@ -48,7 +49,7 @@ namespace Emby.Server.Implementations.Library.Resolvers protected virtual TVideoType ResolveVideo(ItemResolveArgs args, bool parseName) where TVideoType : Video, new() { - var namingOptions = LibraryManager.GetNamingOptions(); + var namingOptions = NamingOptions; // If the path is a file check for a matching extensions if (args.IsDirectory) @@ -138,7 +139,7 @@ namespace Emby.Server.Implementations.Library.Resolvers return null; } - if (LibraryManager.IsVideoFile(args.Path) || videoInfo.IsStub) + if (VideoResolver.IsVideoFile(args.Path, NamingOptions) || videoInfo.IsStub) { var path = args.Path; @@ -267,7 +268,7 @@ namespace Emby.Server.Implementations.Library.Resolvers protected void Set3DFormat(Video video) { - var result = Format3DParser.Parse(video.Path, LibraryManager.GetNamingOptions()); + var result = Format3DParser.Parse(video.Path, NamingOptions); Set3DFormat(video, result.Is3D, result.Format3D); } diff --git a/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs index 9599faea4..72341d9db 100644 --- a/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs @@ -2,16 +2,16 @@ #pragma warning disable CS1591 +using Emby.Naming.Common; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; namespace Emby.Server.Implementations.Library.Resolvers { public class GenericVideoResolver : BaseVideoResolver where T : Video, new() { - public GenericVideoResolver(ILibraryManager libraryManager) - : base(libraryManager) + public GenericVideoResolver(NamingOptions namingOptions) + : base(namingOptions) { } } diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index f3b6ef0a2..732be0fe5 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; +using Emby.Naming.Common; using Emby.Naming.Video; using Jellyfin.Extensions; using MediaBrowser.Controller.Drawing; @@ -25,6 +26,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies public class MovieResolver : BaseVideoResolver