diff --git a/.github/workflows/automation.yml b/.github/workflows/automation.yml index 8da2349c8b..38415f1c60 100644 --- a/.github/workflows/automation.yml +++ b/.github/workflows/automation.yml @@ -11,6 +11,7 @@ jobs: label: name: Labeling runs-on: ubuntu-latest + if: ${{ github.repository == 'jellyfin/jellyfin' }} steps: - name: Apply label uses: eps1lon/actions-label-merge-conflict@v2.0.1 @@ -22,6 +23,7 @@ jobs: project: name: Project board runs-on: ubuntu-latest + if: ${{ github.repository == 'jellyfin/jellyfin' }} steps: - name: Remove from 'Current Release' project uses: alex-page/github-project-automation-plus@v0.7.1 diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index a1b1067040..b08f7590d4 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -14,9 +14,9 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using Emby.Dlna.Profiles; using Emby.Dlna.Server; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; using MediaBrowser.Controller; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Drawing; diff --git a/Emby.Dlna/Service/BaseControlHandler.cs b/Emby.Dlna/Service/BaseControlHandler.cs index 904c23d997..b3ee860f4b 100644 --- a/Emby.Dlna/Service/BaseControlHandler.cs +++ b/Emby.Dlna/Service/BaseControlHandler.cs @@ -6,9 +6,9 @@ using System.IO; using System.Text; using System.Threading.Tasks; using System.Xml; +using Diacritics.Extensions; using Emby.Dlna.Didl; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Extensions; using Microsoft.Extensions.Logging; namespace Emby.Dlna.Service diff --git a/Emby.Naming/Audio/AudioFileParser.cs b/Emby.Naming/Audio/AudioFileParser.cs index af4aa0059f..2b610ec796 100644 --- a/Emby.Naming/Audio/AudioFileParser.cs +++ b/Emby.Naming/Audio/AudioFileParser.cs @@ -1,7 +1,7 @@ using System; using System.IO; using Emby.Naming.Common; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; namespace Emby.Naming.Audio { diff --git a/Emby.Naming/Video/VideoResolver.cs b/Emby.Naming/Video/VideoResolver.cs index c4ac5fdc60..3b1d906c64 100644 --- a/Emby.Naming/Video/VideoResolver.cs +++ b/Emby.Naming/Video/VideoResolver.cs @@ -2,7 +2,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.IO; using Emby.Naming.Common; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; namespace Emby.Naming.Video { diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 448f124034..093607dd5e 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -11,7 +11,7 @@ using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Progress; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 9b147b5d7a..2cb10765ff 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -11,10 +11,12 @@ using System.Linq; using System.Text; using System.Text.Json; using System.Threading; +using Diacritics.Extensions; using Emby.Server.Implementations.Playlists; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; using MediaBrowser.Controller; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 8f7d606692..5d38ea0ca6 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -7,7 +7,7 @@ using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Net; using MediaBrowser.Model.Session; diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 64d802457e..ca028a3ca2 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -6,8 +6,8 @@ using System.Globalization; using System.IO; using System.Linq; using System.Runtime.InteropServices; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 0286735294..d806373329 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -21,6 +21,7 @@ using Emby.Server.Implementations.Playlists; using Emby.Server.Implementations.ScheduledTasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Progress; using MediaBrowser.Controller; diff --git a/Emby.Server.Implementations/Library/LiveStreamHelper.cs b/Emby.Server.Implementations/Library/LiveStreamHelper.cs index 4ef7923db3..8062691827 100644 --- a/Emby.Server.Implementations/Library/LiveStreamHelper.cs +++ b/Emby.Server.Implementations/Library/LiveStreamHelper.cs @@ -12,7 +12,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index b812b6b61b..91c9e61cf3 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -15,7 +15,7 @@ using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 97f96f7469..889e29a6ba 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -6,7 +6,7 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; using Emby.Naming.Video; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index 26e615fa08..9d0a24a88a 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -5,12 +5,12 @@ using System; using System.Collections.Generic; using System.Linq; +using Diacritics.Extensions; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Search; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 26e4ef1ed9..93781cb7ba 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -11,9 +11,9 @@ using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index bdab8c3e4b..4a031e4752 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.Json; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.EmbyTV diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index bd4b5639cd..b7639a51ce 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -15,7 +15,7 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Cryptography; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 54de841fef..011748d1d6 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -12,8 +12,9 @@ using System.Net.Http; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 40a1628902..c9657f6057 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -10,6 +10,7 @@ using System.Net.Http; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index b1ff28c2c5..a9e3bfdb0e 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -8,8 +8,8 @@ using System.IO; using System.Reflection; using System.Text.Json; using System.Threading.Tasks; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions; +using Jellyfin.Extensions.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index 8fd61f2bcb..fc0920edfa 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -10,8 +10,8 @@ using System.Text.Json; using System.Threading.Tasks; using MediaBrowser.Common; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Configuration; diff --git a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs index 783185e7de..afc08fc261 100644 --- a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs +++ b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs @@ -1,15 +1,12 @@ -#nullable disable - using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Security.Cryptography; +using System.Threading.Tasks; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.QuickConnect; using MediaBrowser.Controller.Session; using MediaBrowser.Model.QuickConnect; @@ -22,9 +19,18 @@ namespace Emby.Server.Implementations.QuickConnect /// public class QuickConnectManager : IQuickConnect, IDisposable { - private readonly RNGCryptoServiceProvider _rng = new (); - private readonly ConcurrentDictionary _currentRequests = new (); - private readonly ConcurrentDictionary _quickConnectTokens = new (); + /// + /// The length of user facing codes. + /// + private const int CodeLength = 6; + + /// + /// The time (in minutes) that the quick connect token is valid. + /// + private const int Timeout = 10; + + private readonly RNGCryptoServiceProvider _rng = new(); + private readonly ConcurrentDictionary _currentRequests = new(); private readonly IServerConfigurationManager _config; private readonly ILogger _logger; @@ -34,80 +40,42 @@ namespace Emby.Server.Implementations.QuickConnect /// Initializes a new instance of the class. /// Should only be called at server startup when a singleton is created. /// - /// The server configuration manager. - /// The logger. - /// The session manager. - public QuickConnectManager(IServerConfigurationManager config, ILogger logger, ISessionManager sessionManager) + /// Configuration. + /// Logger. + /// Session Manager. + public QuickConnectManager( + IServerConfigurationManager config, + ILogger logger, + ISessionManager sessionManager) { _config = config; _logger = logger; _sessionManager = sessionManager; - - ReloadConfiguration(); } - /// - public int CodeLength { get; set; } = 6; + /// + public bool IsEnabled => _config.Configuration.QuickConnectAvailable; - /// - public string TokenName { get; set; } = "QuickConnect"; - - /// - public QuickConnectState State { get; private set; } = QuickConnectState.Unavailable; - - /// - public int Timeout { get; set; } = 5; - - private DateTime DateActivated { get; set; } - - /// - public void AssertActive() + /// + /// Assert that quick connect is currently active and throws an exception if it is not. + /// + private void AssertActive() { - if (State != QuickConnectState.Active) + if (!IsEnabled) { - throw new ArgumentException("Quick connect is not active on this server"); + throw new AuthenticationException("Quick connect is not active on this server"); } } - /// - public void Activate() - { - DateActivated = DateTime.UtcNow; - SetState(QuickConnectState.Active); - } - - /// - public void SetState(QuickConnectState newState) - { - _logger.LogDebug("Changed quick connect state from {State} to {newState}", State, newState); - - ExpireRequests(true); - - State = newState; - _config.Configuration.QuickConnectAvailable = newState == QuickConnectState.Available || newState == QuickConnectState.Active; - _config.SaveConfiguration(); - - _logger.LogDebug("Configuration saved"); - } - /// public QuickConnectResult TryConnect() { + AssertActive(); ExpireRequests(); - if (State != QuickConnectState.Active) - { - _logger.LogDebug("Refusing quick connect initiation request, current state is {State}", State); - throw new AuthenticationException("Quick connect is not active on this server"); - } - + var secret = GenerateSecureRandom(); var code = GenerateCode(); - var result = new QuickConnectResult() - { - Secret = GenerateSecureRandom(), - DateAdded = DateTime.UtcNow, - Code = code - }; + var result = new QuickConnectResult(secret, code, DateTime.UtcNow); _currentRequests[code] = result; return result; @@ -116,12 +84,12 @@ namespace Emby.Server.Implementations.QuickConnect /// public QuickConnectResult CheckRequestStatus(string secret) { - ExpireRequests(); AssertActive(); + ExpireRequests(); string code = _currentRequests.Where(x => x.Value.Secret == secret).Select(x => x.Value.Code).DefaultIfEmpty(string.Empty).First(); - if (!_currentRequests.TryGetValue(code, out QuickConnectResult result)) + if (!_currentRequests.TryGetValue(code, out QuickConnectResult? result)) { throw new ResourceNotFoundException("Unable to find request with provided secret"); } @@ -129,22 +97,11 @@ namespace Emby.Server.Implementations.QuickConnect return result; } - /// - public void AuthenticateRequest(AuthenticationRequest request, string token) - { - if (!_quickConnectTokens.TryGetValue(token, out var entry)) - { - throw new SecurityException("Unknown quick connect token"); - } - - request.UserId = entry.UserId; - _quickConnectTokens.Remove(token, out _); - - _sessionManager.AuthenticateQuickConnect(request, token); - } - - /// - public string GenerateCode() + /// + /// Generates a short code to display to the user to uniquely identify this request. + /// + /// A short, unique alphanumeric string. + private string GenerateCode() { Span raw = stackalloc byte[4]; @@ -163,12 +120,12 @@ namespace Emby.Server.Implementations.QuickConnect } /// - public bool AuthorizeRequest(Guid userId, string code) + public async Task AuthorizeRequest(Guid userId, string code) { - ExpireRequests(); AssertActive(); + ExpireRequests(); - if (!_currentRequests.TryGetValue(code, out QuickConnectResult result)) + if (!_currentRequests.TryGetValue(code, out QuickConnectResult? result)) { throw new ResourceNotFoundException("Unable to find request"); } @@ -178,37 +135,19 @@ namespace Emby.Server.Implementations.QuickConnect throw new InvalidOperationException("Request is already authorized"); } - result.Authentication = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); + var token = Guid.NewGuid(); + result.Authentication = token; // Change the time on the request so it expires one minute into the future. It can't expire immediately as otherwise some clients wouldn't ever see that they have been authenticated. - var added = result.DateAdded ?? DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(Timeout)); - result.DateAdded = added.Subtract(TimeSpan.FromMinutes(Timeout - 1)); + result.DateAdded = DateTime.Now.Add(TimeSpan.FromMinutes(1)); - _quickConnectTokens[result.Authentication] = (TokenName, userId); + await _sessionManager.AuthenticateQuickConnect(userId).ConfigureAwait(false); _logger.LogDebug("Authorizing device with code {Code} to login as user {userId}", code, userId); return true; } - /// - public int DeleteAllDevices(Guid user) - { - var tokens = _quickConnectTokens - .Where(entry => entry.Value.Token.StartsWith(TokenName, StringComparison.Ordinal) && entry.Value.UserId == user) - .ToList(); - - var removed = 0; - foreach (var token in tokens) - { - _quickConnectTokens.Remove(token.Key, out _); - _logger.LogDebug("Deleted token {AccessToken}", token.Key); - removed++; - } - - return removed; - } - /// /// Dispose. /// @@ -226,7 +165,7 @@ namespace Emby.Server.Implementations.QuickConnect { if (disposing) { - _rng?.Dispose(); + _rng.Dispose(); } } @@ -238,22 +177,19 @@ namespace Emby.Server.Implementations.QuickConnect return Convert.ToHexString(bytes); } - /// - public void ExpireRequests(bool expireAll = false) + /// + /// Expire quick connect requests that are over the time limit. If is true, all requests are unconditionally expired. + /// + /// If true, all requests will be expired. + private void ExpireRequests(bool expireAll = false) { - // Check if quick connect should be deactivated - if (State == QuickConnectState.Active && DateTime.UtcNow > DateActivated.AddMinutes(Timeout) && !expireAll) - { - _logger.LogDebug("Quick connect time expired, deactivating"); - SetState(QuickConnectState.Available); - expireAll = true; - } + // All requests before this timestamp have expired + var minTime = DateTime.UtcNow.AddMinutes(-Timeout); // Expire stale connection requests foreach (var (_, currentRequest) in _currentRequests) { - var added = currentRequest.DateAdded ?? DateTime.UnixEpoch; - if (expireAll || DateTime.UtcNow > added.AddMinutes(Timeout)) + if (expireAll || currentRequest.DateAdded > minTime) { var code = currentRequest.Code; _logger.LogDebug("Removing expired request {Code}", code); @@ -265,10 +201,5 @@ namespace Emby.Server.Implementations.QuickConnect } } } - - private void ReloadConfiguration() - { - State = _config.Configuration.QuickConnectAvailable ? QuickConnectState.Available : QuickConnectState.Unavailable; - } } } diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index d7e3207549..b343250419 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -12,7 +12,7 @@ using System.Threading.Tasks; using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Progress; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 544c8e5fdf..29b545583a 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -14,6 +14,7 @@ using Jellyfin.Data.Entities.Security; using Jellyfin.Data.Enums; using Jellyfin.Data.Events; using Jellyfin.Data.Queries; +using Jellyfin.Extensions; using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; @@ -1438,9 +1439,9 @@ namespace Emby.Server.Implementations.Session return AuthenticateNewSessionInternal(request, true); } - public Task AuthenticateQuickConnect(AuthenticationRequest request, string token) + public Task AuthenticateQuickConnect(Guid userId) { - return AuthenticateNewSessionInternal(request, false); + return AuthenticateNewSessionInternal(new AuthenticationRequest { UserId = userId }, false); } private async Task AuthenticateNewSessionInternal(AuthenticationRequest request, bool enforcePassword) diff --git a/Emby.Server.Implementations/Sorting/StudioComparer.cs b/Emby.Server.Implementations/Sorting/StudioComparer.cs index 01445c5254..6826aee3b1 100644 --- a/Emby.Server.Implementations/Sorting/StudioComparer.cs +++ b/Emby.Server.Implementations/Sorting/StudioComparer.cs @@ -4,6 +4,7 @@ using System; using System.Linq; +using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Querying; @@ -30,7 +31,7 @@ namespace Emby.Server.Implementations.Sorting throw new ArgumentNullException(nameof(y)); } - return AlphanumComparator.CompareValues(x.Studios.FirstOrDefault() ?? string.Empty, y.Studios.FirstOrDefault() ?? string.Empty); + return AlphanumericComparator.CompareValues(x.Studios.FirstOrDefault(), y.Studios.FirstOrDefault()); } /// diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index b0921cbd82..7b0afa4e24 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -11,7 +11,7 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Events; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; diff --git a/Jellyfin.Api/BaseJellyfinApiController.cs b/Jellyfin.Api/BaseJellyfinApiController.cs index 1c1fc71d79..59d6b75137 100644 --- a/Jellyfin.Api/BaseJellyfinApiController.cs +++ b/Jellyfin.Api/BaseJellyfinApiController.cs @@ -1,5 +1,5 @@ using System.Net.Mime; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Api diff --git a/Jellyfin.Api/Controllers/ConfigurationController.cs b/Jellyfin.Api/Controllers/ConfigurationController.cs index b6309baab0..60529e9904 100644 --- a/Jellyfin.Api/Controllers/ConfigurationController.cs +++ b/Jellyfin.Api/Controllers/ConfigurationController.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Models.ConfigurationDtos; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Configuration; diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index 7a61307195..0ae6109bcc 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -8,8 +8,8 @@ using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Models.PluginDtos; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Json; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; using MediaBrowser.Model.Net; diff --git a/Jellyfin.Api/Controllers/QuickConnectController.cs b/Jellyfin.Api/Controllers/QuickConnectController.cs index 4ac8491815..56fef08a99 100644 --- a/Jellyfin.Api/Controllers/QuickConnectController.cs +++ b/Jellyfin.Api/Controllers/QuickConnectController.cs @@ -1,7 +1,9 @@ using System.ComponentModel.DataAnnotations; +using System.Threading.Tasks; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.QuickConnect; using MediaBrowser.Model.QuickConnect; using Microsoft.AspNetCore.Authorization; @@ -30,13 +32,12 @@ namespace Jellyfin.Api.Controllers /// Gets the current quick connect state. /// /// Quick connect state returned. - /// The current . - [HttpGet("Status")] + /// Whether Quick Connect is enabled on the server or not. + [HttpGet("Enabled")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetStatus() + public ActionResult GetEnabled() { - _quickConnect.ExpireRequests(); - return _quickConnect.State; + return _quickConnect.IsEnabled; } /// @@ -49,7 +50,14 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult Initiate() { - return _quickConnect.TryConnect(); + try + { + return _quickConnect.TryConnect(); + } + catch (AuthenticationException) + { + return Unauthorized("Quick connect is disabled"); + } } /// @@ -72,42 +80,10 @@ namespace Jellyfin.Api.Controllers { return NotFound("Unknown secret"); } - } - - /// - /// Temporarily activates quick connect for five minutes. - /// - /// Quick connect has been temporarily activated. - /// Quick connect is unavailable on this server. - /// An on success. - [HttpPost("Activate")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(StatusCodes.Status403Forbidden)] - public ActionResult Activate() - { - if (_quickConnect.State == QuickConnectState.Unavailable) + catch (AuthenticationException) { - return StatusCode(StatusCodes.Status403Forbidden, "Quick connect is unavailable"); + return Unauthorized("Quick connect is disabled"); } - - _quickConnect.Activate(); - return NoContent(); - } - - /// - /// Enables or disables quick connect. - /// - /// New . - /// Quick connect state set successfully. - /// An on success. - [HttpPost("Available")] - [Authorize(Policy = Policies.RequiresElevation)] - [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult Available([FromQuery] QuickConnectState status = QuickConnectState.Available) - { - _quickConnect.SetState(status); - return NoContent(); } /// @@ -121,7 +97,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] - public ActionResult Authorize([FromQuery, Required] string code) + public async Task> Authorize([FromQuery, Required] string code) { var userId = ClaimHelpers.GetUserId(Request.HttpContext.User); if (!userId.HasValue) @@ -129,26 +105,14 @@ namespace Jellyfin.Api.Controllers return StatusCode(StatusCodes.Status403Forbidden, "Unknown user id"); } - return _quickConnect.AuthorizeRequest(userId.Value, code); - } - - /// - /// Deauthorize all quick connect devices for the current user. - /// - /// All quick connect devices were deleted. - /// The number of devices that were deleted. - [HttpPost("Deauthorize")] - [Authorize(Policy = Policies.DefaultAuthorization)] - [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult Deauthorize() - { - var userId = ClaimHelpers.GetUserId(Request.HttpContext.User); - if (!userId.HasValue) + try { - return 0; + return await _quickConnect.AuthorizeRequest(userId.Value, code).ConfigureAwait(false); + } + catch (AuthenticationException) + { + return Unauthorized("Quick connect is disabled"); } - - return _quickConnect.DeleteAllDevices(userId.Value); } } } diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index ffb726fab7..51d40994e1 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -6,7 +6,7 @@ using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index 1d70406acc..a33a0826c9 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -9,7 +9,7 @@ using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; diff --git a/Jellyfin.Api/Extensions/DtoExtensions.cs b/Jellyfin.Api/Extensions/DtoExtensions.cs index 06173315aa..5e338b67da 100644 --- a/Jellyfin.Api/Extensions/DtoExtensions.cs +++ b/Jellyfin.Api/Extensions/DtoExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using Jellyfin.Api.Helpers; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; diff --git a/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs b/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs index 8913180e48..411e4c550c 100644 --- a/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs +++ b/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text.Json.Serialization; using Jellyfin.Data.Enums; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; diff --git a/Jellyfin.Api/Models/PlaylistDtos/CreatePlaylistDto.cs b/Jellyfin.Api/Models/PlaylistDtos/CreatePlaylistDto.cs index 65d4b644e4..0761b20855 100644 --- a/Jellyfin.Api/Models/PlaylistDtos/CreatePlaylistDto.cs +++ b/Jellyfin.Api/Models/PlaylistDtos/CreatePlaylistDto.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; namespace Jellyfin.Api.Models.PlaylistDtos { diff --git a/Jellyfin.Api/Models/SessionDtos/ClientCapabilitiesDto.cs b/Jellyfin.Api/Models/SessionDtos/ClientCapabilitiesDto.cs index e58095536a..fa62472e1e 100644 --- a/Jellyfin.Api/Models/SessionDtos/ClientCapabilitiesDto.cs +++ b/Jellyfin.Api/Models/SessionDtos/ClientCapabilitiesDto.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Session; @@ -85,4 +85,4 @@ namespace Jellyfin.Api.Models.SessionDtos }; } } -} \ No newline at end of file +} diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index 8f0fae3beb..6d0a5ac2b9 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -3,10 +3,10 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using BlurHashSharp.SkiaSharp; +using Diacritics.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Extensions; using MediaBrowser.Model.Drawing; using Microsoft.Extensions.Logging; using SkiaSharp; @@ -142,9 +142,6 @@ namespace Jellyfin.Drawing.Skia return BlurHashEncoder.Encode(xComp, yComp, path, 128, 128); } - private static bool HasDiacritics(string text) - => !string.Equals(text, text.RemoveDiacritics(), StringComparison.Ordinal); - private bool RequiresSpecialCharacterHack(string path) { for (int i = 0; i < path.Length; i++) @@ -155,7 +152,7 @@ namespace Jellyfin.Drawing.Skia } } - return HasDiacritics(path); + return path.HasDiacritics(); } private string NormalizePath(string path) diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index 97704386a0..08970f84de 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading.Tasks; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using Microsoft.AspNetCore.Http; diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 924b250cec..15dc438561 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -21,11 +21,11 @@ using Jellyfin.Api.Constants; using Jellyfin.Api.Controllers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; +using Jellyfin.Extensions.Json; using Jellyfin.Networking.Configuration; using Jellyfin.Server.Configuration; using Jellyfin.Server.Filters; using Jellyfin.Server.Formatters; -using MediaBrowser.Common.Json; using MediaBrowser.Common.Net; using MediaBrowser.Model.Entities; using Microsoft.AspNetCore.Authentication; diff --git a/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs b/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs index c349e3dca2..ea8c5ecdb1 100644 --- a/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs +++ b/Jellyfin.Server/Formatters/CamelCaseJsonProfileFormatter.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.Net.Http.Headers; diff --git a/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs b/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs index 0480f5e0ec..03ca7dda72 100644 --- a/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs +++ b/Jellyfin.Server/Formatters/PascalCaseJsonProfileFormatter.cs @@ -1,5 +1,5 @@ using System.Net.Mime; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.Net.Http.Headers; diff --git a/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs b/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs index 310a3d31ad..c1f5b5dfaf 100644 --- a/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs +++ b/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Web; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.Extensions.Primitives; diff --git a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs index 96bd2ccc40..d9524645a1 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs @@ -4,9 +4,9 @@ using Emby.Server.Implementations.Data; using Emby.Server.Implementations.Serialization; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions.Json; using Jellyfin.Server.Implementations; using Jellyfin.Server.Implementations.Users; -using MediaBrowser.Common.Json; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Configuration; diff --git a/Jellyfin.sln b/Jellyfin.sln index 9fbd9d266e..4626601c3d 100644 --- a/Jellyfin.sln +++ b/Jellyfin.sln @@ -83,6 +83,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Server.Integration EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Providers.Tests", "tests\Jellyfin.Providers.Tests\Jellyfin.Providers.Tests.csproj", "{A964008C-2136-4716-B6CB-B3426C22320A}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Extensions", "src\Jellyfin.Extensions\Jellyfin.Extensions.csproj", "{750B8757-BE3D-4F8C-941A-FBAD94904ADA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Extensions.Tests", "tests\Jellyfin.Extensions.Tests\Jellyfin.Extensions.Tests.csproj", "{332A5C7A-F907-47CA-910E-BE6F7371B9E0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -229,6 +235,14 @@ Global {A964008C-2136-4716-B6CB-B3426C22320A}.Debug|Any CPU.Build.0 = Debug|Any CPU {A964008C-2136-4716-B6CB-B3426C22320A}.Release|Any CPU.ActiveCfg = Release|Any CPU {A964008C-2136-4716-B6CB-B3426C22320A}.Release|Any CPU.Build.0 = Release|Any CPU + {750B8757-BE3D-4F8C-941A-FBAD94904ADA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {750B8757-BE3D-4F8C-941A-FBAD94904ADA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {750B8757-BE3D-4F8C-941A-FBAD94904ADA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {750B8757-BE3D-4F8C-941A-FBAD94904ADA}.Release|Any CPU.Build.0 = Release|Any CPU + {332A5C7A-F907-47CA-910E-BE6F7371B9E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {332A5C7A-F907-47CA-910E-BE6F7371B9E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {332A5C7A-F907-47CA-910E-BE6F7371B9E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {332A5C7A-F907-47CA-910E-BE6F7371B9E0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -247,6 +261,8 @@ Global {3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {68B0B823-A5AC-4E8B-82EA-965AAC7BF76E} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {A964008C-2136-4716-B6CB-B3426C22320A} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} + {750B8757-BE3D-4F8C-941A-FBAD94904ADA} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C} + {332A5C7A-F907-47CA-910E-BE6F7371B9E0} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {3448830C-EBDC-426C-85CD-7BBB9651A7FE} diff --git a/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs b/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs index ffc274c5de..97f40b5372 100644 --- a/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs +++ b/MediaBrowser.Controller/BaseItemManager/BaseItemManager.cs @@ -3,7 +3,7 @@ using System; using System.Linq; using System.Threading; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index c0cd81110e..53fcdbf428 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -8,9 +8,9 @@ using System.Linq; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; +using Diacritics.Extensions; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; -using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index a682a2e58c..b1559ff245 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Text.Json.Serialization; -using MediaBrowser.Controller.Extensions; +using Diacritics.Extensions; using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Entities.Audio diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 6137ddbf7e..e5be5421a2 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -11,13 +11,14 @@ using System.Text; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; +using Diacritics.Extensions; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 4a721ca44f..4f367fe2b5 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -10,7 +10,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs index 244cc00bea..d8bc0069c7 100644 --- a/MediaBrowser.Controller/Entities/Extensions.cs +++ b/MediaBrowser.Controller/Entities/Extensions.cs @@ -2,7 +2,7 @@ using System; using System.Linq; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Entities diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index b80a5be3b9..338f96204d 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -5,8 +5,8 @@ using System; using System.Collections.Generic; using System.Text.Json.Serialization; +using Diacritics.Extensions; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Extensions; using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Entities diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 913f76d3bd..b0ab280af4 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Text.Json.Serialization; -using MediaBrowser.Controller.Extensions; +using Diacritics.Extensions; using MediaBrowser.Controller.Providers; using Microsoft.Extensions.Logging; diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index 6fd0a6c6c3..888b300012 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -5,7 +5,7 @@ using System; using System.Collections.Generic; using System.Text.Json.Serialization; -using MediaBrowser.Controller.Extensions; +using Diacritics.Extensions; using Microsoft.Extensions.Logging; namespace MediaBrowser.Controller.Entities diff --git a/MediaBrowser.Controller/Extensions/StringExtensions.cs b/MediaBrowser.Controller/Extensions/StringExtensions.cs deleted file mode 100644 index f1af013451..0000000000 --- a/MediaBrowser.Controller/Extensions/StringExtensions.cs +++ /dev/null @@ -1,73 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; - -namespace MediaBrowser.Controller.Extensions -{ - /// - /// Class BaseExtensions. - /// - public static class StringExtensions - { - public static string RemoveDiacritics(this string text) - { - var chars = Normalize(text, NormalizationForm.FormD) - .Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) != UnicodeCategory.NonSpacingMark); - - return Normalize(string.Concat(chars), NormalizationForm.FormC); - } - - /// - /// Counts the number of occurrences of [needle] in the string. - /// - /// The haystack to search in. - /// The character to search for. - /// The number of occurrences of the [needle] character. - public static int Count(this ReadOnlySpan value, char needle) - { - var count = 0; - var length = value.Length; - for (var i = 0; i < length; i++) - { - if (value[i] == needle) - { - count++; - } - } - - return count; - } - - private static string Normalize(string text, NormalizationForm form, bool stripStringOnFailure = true) - { - if (stripStringOnFailure) - { - try - { - return text.Normalize(form); - } - catch (ArgumentException) - { - // will throw if input contains invalid unicode chars - // https://mnaoumov.wordpress.com/2014/06/14/stripping-invalid-characters-from-utf-16-strings/ - text = Regex.Replace(text, "([\ud800-\udbff](?![\udc00-\udfff]))|((? + diff --git a/MediaBrowser.Controller/QuickConnect/IQuickConnect.cs b/MediaBrowser.Controller/QuickConnect/IQuickConnect.cs index 59003b1873..616409533e 100644 --- a/MediaBrowser.Controller/QuickConnect/IQuickConnect.cs +++ b/MediaBrowser.Controller/QuickConnect/IQuickConnect.cs @@ -1,6 +1,5 @@ -#nullable disable - using System; +using System.Threading.Tasks; using MediaBrowser.Controller.Session; using MediaBrowser.Model.QuickConnect; @@ -12,40 +11,9 @@ namespace MediaBrowser.Controller.QuickConnect public interface IQuickConnect { /// - /// Gets or sets the length of user facing codes. + /// Gets a value indicating whether quick connect is enabled or not. /// - int CodeLength { get; set; } - - /// - /// Gets or sets the name of internal access tokens. - /// - string TokenName { get; set; } - - /// - /// Gets the current state of quick connect. - /// - QuickConnectState State { get; } - - /// - /// Gets or sets the time (in minutes) before quick connect will automatically deactivate. - /// - int Timeout { get; set; } - - /// - /// Assert that quick connect is currently active and throws an exception if it is not. - /// - void AssertActive(); - - /// - /// Temporarily activates quick connect for a short amount of time. - /// - void Activate(); - - /// - /// Changes the state of quick connect. - /// - /// New state to change to. - void SetState(QuickConnectState newState); + bool IsEnabled { get; } /// /// Initiates a new quick connect request. @@ -60,38 +28,12 @@ namespace MediaBrowser.Controller.QuickConnect /// Quick connect result. QuickConnectResult CheckRequestStatus(string secret); - /// - /// Authenticates a QuickConnect request. - /// - /// The request. - /// The token. - void AuthenticateRequest(AuthenticationRequest request, string token); - /// /// Authorizes a quick connect request to connect as the calling user. /// /// User id. /// Identifying code for the request. /// A boolean indicating if the authorization completed successfully. - bool AuthorizeRequest(Guid userId, string code); - - /// - /// Expire quick connect requests that are over the time limit. If is true, all requests are unconditionally expired. - /// - /// If true, all requests will be expired. - void ExpireRequests(bool expireAll = false); - - /// - /// Deletes all quick connect access tokens for the provided user. - /// - /// Guid of the user to delete tokens for. - /// A count of the deleted tokens. - int DeleteAllDevices(Guid user); - - /// - /// Generates a short code to display to the user to uniquely identify this request. - /// - /// A short, unique alphanumeric string. - string GenerateCode(); + Task AuthorizeRequest(Guid userId, string code); } } diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 1000da2473..8be9ff5219 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -276,10 +276,9 @@ namespace MediaBrowser.Controller.Session /// /// Authenticates a new session with quick connect. /// - /// The request. - /// Quick connect access token. + /// The user id. /// Task{SessionInfo}. - Task AuthenticateQuickConnect(AuthenticationRequest request, string token); + Task AuthenticateQuickConnect(Guid userId); /// /// Reports the capabilities. diff --git a/MediaBrowser.Controller/Sorting/SortExtensions.cs b/MediaBrowser.Controller/Sorting/SortExtensions.cs index aa6ec513f3..f9c0d39ddd 100644 --- a/MediaBrowser.Controller/Sorting/SortExtensions.cs +++ b/MediaBrowser.Controller/Sorting/SortExtensions.cs @@ -1,16 +1,15 @@ -#nullable disable - #pragma warning disable CS1591 using System; using System.Collections.Generic; using System.Linq; +using Jellyfin.Extensions; namespace MediaBrowser.Controller.Sorting { public static class SortExtensions { - private static readonly AlphanumComparator _comparer = new AlphanumComparator(); + private static readonly AlphanumericComparator _comparer = new AlphanumericComparator(); public static IEnumerable OrderByString(this IEnumerable list, Func getName) { diff --git a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs index fdba64c4a5..dc13bf4f6d 100644 --- a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 3af618af85..412a953216 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -11,9 +11,9 @@ using System.Text.Json; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.MediaEncoding.Probing; diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index 639a34d993..24ceb1b571 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -2,7 +2,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Threading; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging; using Nikse.SubtitleEdit.Core; diff --git a/MediaBrowser.Model/Dlna/SubtitleDeliveryMethod.cs b/MediaBrowser.Model/Dlna/SubtitleDeliveryMethod.cs index e7fe8d6af2..9b39f9e11a 100644 --- a/MediaBrowser.Model/Dlna/SubtitleDeliveryMethod.cs +++ b/MediaBrowser.Model/Dlna/SubtitleDeliveryMethod.cs @@ -2,25 +2,28 @@ namespace MediaBrowser.Model.Dlna { + /// + /// Delivery method to use during playback of a specific subtitle format. + /// public enum SubtitleDeliveryMethod { /// - /// The encode. + /// Burn the subtitles in the video track. /// Encode = 0, /// - /// The embed. + /// Embed the subtitles in the file or stream. /// Embed = 1, /// - /// The external. + /// Serve the subtitles as an external file. /// External = 2, /// - /// The HLS. + /// Serve the subtitles as a separate HLS stream. /// Hls = 3 } diff --git a/MediaBrowser.Model/Entities/VirtualFolderInfo.cs b/MediaBrowser.Model/Entities/VirtualFolderInfo.cs index 8fed392b9d..2b2bda12c3 100644 --- a/MediaBrowser.Model/Entities/VirtualFolderInfo.cs +++ b/MediaBrowser.Model/Entities/VirtualFolderInfo.cs @@ -3,6 +3,7 @@ using System; using System.Text.Json.Serialization; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Model.Configuration; namespace MediaBrowser.Model.Entities diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 4db99f0b08..c475d905a9 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -50,7 +50,8 @@ - + + diff --git a/MediaBrowser.Model/QuickConnect/QuickConnectResult.cs b/MediaBrowser.Model/QuickConnect/QuickConnectResult.cs index 0fa40b6a72..d180d29860 100644 --- a/MediaBrowser.Model/QuickConnect/QuickConnectResult.cs +++ b/MediaBrowser.Model/QuickConnect/QuickConnectResult.cs @@ -3,38 +3,46 @@ using System; namespace MediaBrowser.Model.QuickConnect { /// - /// Stores the result of an incoming quick connect request. + /// Stores the state of an quick connect request. /// public class QuickConnectResult { + /// + /// Initializes a new instance of the class. + /// + /// The secret used to query the request state. + /// The code used to allow the request. + /// The time when the request was created. + public QuickConnectResult(string secret, string code, DateTime dateAdded) + { + Secret = secret; + Code = code; + DateAdded = dateAdded; + } + /// /// Gets a value indicating whether this request is authorized. /// - public bool Authenticated => !string.IsNullOrEmpty(Authentication); + public bool Authenticated => Authentication != null; /// - /// Gets or sets the secret value used to uniquely identify this request. Can be used to retrieve authentication information. + /// Gets the secret value used to uniquely identify this request. Can be used to retrieve authentication information. /// - public string? Secret { get; set; } + public string Secret { get; } /// - /// Gets or sets the user facing code used so the user can quickly differentiate this request from others. + /// Gets the user facing code used so the user can quickly differentiate this request from others. /// - public string? Code { get; set; } + public string Code { get; } /// /// Gets or sets the private access token. /// - public string? Authentication { get; set; } - - /// - /// Gets or sets an error message. - /// - public string? Error { get; set; } + public Guid? Authentication { get; set; } /// /// Gets or sets the DateTime that this request was created. /// - public DateTime? DateAdded { get; set; } + public DateTime DateAdded { get; set; } } } diff --git a/MediaBrowser.Model/QuickConnect/QuickConnectState.cs b/MediaBrowser.Model/QuickConnect/QuickConnectState.cs deleted file mode 100644 index f1074f25f2..0000000000 --- a/MediaBrowser.Model/QuickConnect/QuickConnectState.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace MediaBrowser.Model.QuickConnect -{ - /// - /// Quick connect state. - /// - public enum QuickConnectState - { - /// - /// This feature has not been opted into and is unavailable until the server administrator chooses to opt-in. - /// - Unavailable = 0, - - /// - /// The feature is enabled for use on the server but is not currently accepting connection requests. - /// - Available = 1, - - /// - /// The feature is actively accepting connection requests. - /// - Active = 2 - } -} diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs index e5aa64b281..aceba22158 100644 --- a/MediaBrowser.Providers/Manager/ProviderUtils.cs +++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs @@ -3,9 +3,9 @@ using System; using System.Collections.Generic; using System.Linq; +using Diacritics.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs index 85a28747f5..36d8eeb401 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumImageProvider.cs @@ -6,7 +6,7 @@ using System.Net.Http; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs index 25bb3f9ce3..9539c396d9 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/AlbumProvider.cs @@ -11,7 +11,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs index db8536cc92..aa61a56f66 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistImageProvider.cs @@ -6,7 +6,7 @@ using System.Net.Http; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs index cbb61fa353..b2f05d76de 100644 --- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs @@ -10,7 +10,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs index 2eab95294a..0cae7768a7 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs @@ -11,8 +11,8 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; +using Diacritics.Extensions; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; @@ -53,7 +53,7 @@ namespace MediaBrowser.Providers.Music } } - if (HasDiacritics(searchInfo.Name)) + if (searchInfo.Name.HasDiacritics()) { // Try again using the search with accent characters url url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); @@ -251,16 +251,6 @@ namespace MediaBrowser.Providers.Music return result; } - /// - /// Determines whether the specified text has diacritics. - /// - /// The text. - /// true if the specified text has diacritics; otherwise, false. - private bool HasDiacritics(string text) - { - return !string.Equals(text, text.RemoveDiacritics(), StringComparison.Ordinal); - } - /// /// Encodes an URL. /// diff --git a/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableInt32Converter.cs b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs similarity index 94% rename from MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableInt32Converter.cs rename to MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs index 3d97a9de55..268538815e 100644 --- a/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableInt32Converter.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableInt32Converter.cs @@ -1,9 +1,11 @@ -using System; +#nullable enable + +using System; using System.ComponentModel; using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace MediaBrowser.Providers.Plugins.Omdb { /// /// Converts a string N/A to string.Empty. diff --git a/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableStringConverter.cs similarity index 93% rename from MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs rename to MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableStringConverter.cs index 77cf46b706..c19589d45b 100644 --- a/MediaBrowser.Common/Json/Converters/JsonOmdbNotAvailableStringConverter.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/JsonOmdbNotAvailableStringConverter.cs @@ -1,8 +1,10 @@ -using System; +#nullable enable + +using System; using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace MediaBrowser.Providers.Plugins.Omdb { /// /// Converts a string N/A to string.Empty. diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs index 428b0ded11..78eea02e03 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs @@ -10,8 +10,8 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; -using MediaBrowser.Common.Json; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs index 46d3038905..5d9fd36d35 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbProvider.cs @@ -10,8 +10,8 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common; -using MediaBrowser.Common.Json; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Providers/Properties/AssemblyInfo.cs b/MediaBrowser.Providers/Properties/AssemblyInfo.cs index fe4749c799..bd301b5f08 100644 --- a/MediaBrowser.Providers/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Providers/Properties/AssemblyInfo.cs @@ -15,7 +15,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] -[assembly: InternalsVisibleTo("Jellyfin.Common.Tests")] +[assembly: InternalsVisibleTo("Jellyfin.Providers.Tests")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index f6153dd532..63e78d15e8 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -8,7 +8,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Extensions; +using Jellyfin.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; diff --git a/debian/rules b/debian/rules index 96541f41b8..64e2b48ea8 100755 --- a/debian/rules +++ b/debian/rules @@ -39,7 +39,7 @@ override_dh_auto_test: override_dh_clistrip: override_dh_auto_build: - dotnet publish --configuration $(CONFIG) --output='$(CURDIR)/usr/lib/jellyfin/bin' --self-contained --runtime $(DOTNETRUNTIME) \ + dotnet publish -maxcpucount:1 --configuration $(CONFIG) --output='$(CURDIR)/usr/lib/jellyfin/bin' --self-contained --runtime $(DOTNETRUNTIME) \ "-p:DebugSymbols=false;DebugType=none" Jellyfin.Server override_dh_auto_clean: diff --git a/MediaBrowser.Controller/Sorting/AlphanumComparator.cs b/src/Jellyfin.Extensions/AlphanumericComparator.cs similarity index 87% rename from MediaBrowser.Controller/Sorting/AlphanumComparator.cs rename to src/Jellyfin.Extensions/AlphanumericComparator.cs index e00cadca21..e3c81eba8c 100644 --- a/MediaBrowser.Controller/Sorting/AlphanumComparator.cs +++ b/src/Jellyfin.Extensions/AlphanumericComparator.cs @@ -1,12 +1,19 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; -namespace MediaBrowser.Controller.Sorting +namespace Jellyfin.Extensions { - public class AlphanumComparator : IComparer + /// + /// Alphanumeric . + /// + public class AlphanumericComparator : IComparer { + /// + /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other. + /// + /// The first object to compare. + /// The second object to compare. + /// A signed integer that indicates the relative values of x and y. public static int CompareValues(string? s1, string? s2) { if (s1 == null && s2 == null) diff --git a/MediaBrowser.Common/Extensions/CopyToExtensions.cs b/src/Jellyfin.Extensions/CopyToExtensions.cs similarity index 96% rename from MediaBrowser.Common/Extensions/CopyToExtensions.cs rename to src/Jellyfin.Extensions/CopyToExtensions.cs index 2ecbc6539b..72d37b5b6a 100644 --- a/MediaBrowser.Common/Extensions/CopyToExtensions.cs +++ b/src/Jellyfin.Extensions/CopyToExtensions.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace MediaBrowser.Common.Extensions +namespace Jellyfin.Extensions { /// /// Provides CopyTo extensions methods for . diff --git a/MediaBrowser.Common/Extensions/EnumerableExtensions.cs b/src/Jellyfin.Extensions/EnumerableExtensions.cs similarity index 96% rename from MediaBrowser.Common/Extensions/EnumerableExtensions.cs rename to src/Jellyfin.Extensions/EnumerableExtensions.cs index 2b8a6c395b..b5fe933571 100644 --- a/MediaBrowser.Common/Extensions/EnumerableExtensions.cs +++ b/src/Jellyfin.Extensions/EnumerableExtensions.cs @@ -1,7 +1,7 @@ -using System; +using System; using System.Collections.Generic; -namespace MediaBrowser.Common.Extensions +namespace Jellyfin.Extensions { /// /// Static extensions for the interface. diff --git a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj new file mode 100644 index 0000000000..f343be1e31 --- /dev/null +++ b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj @@ -0,0 +1,30 @@ + + + + net5.0 + false + true + true + enable + AllEnabledByDefault + ../../jellyfin.ruleset + + + + Jellyfin Contributors + https://github.com/jellyfin/jellyfin + GPL-3.0-only + + + + + + + + + + + + + + diff --git a/MediaBrowser.Common/Json/Converters/JsonBoolNumberConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonBoolNumberConverter.cs similarity index 94% rename from MediaBrowser.Common/Json/Converters/JsonBoolNumberConverter.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonBoolNumberConverter.cs index b29e6a71a6..c2543cf7ce 100644 --- a/MediaBrowser.Common/Json/Converters/JsonBoolNumberConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonBoolNumberConverter.cs @@ -2,7 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Converts a number to a boolean. @@ -27,4 +27,4 @@ namespace MediaBrowser.Common.Json.Converters writer.WriteBooleanValue(value); } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverter.cs similarity index 93% rename from MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverter.cs index 127a41a06b..44980ec02f 100644 --- a/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverter.cs @@ -3,7 +3,7 @@ using System.ComponentModel; using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Convert comma delimited string to array of type. diff --git a/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs b/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs similarity index 95% rename from MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs index de41348dda..cc9311a24c 100644 --- a/MediaBrowser.Common/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs @@ -2,7 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Json comma delimited array converter factory. diff --git a/MediaBrowser.Common/Json/Converters/JsonDateTimeConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonDateTimeConverter.cs similarity index 95% rename from MediaBrowser.Common/Json/Converters/JsonDateTimeConverter.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonDateTimeConverter.cs index 73e3a0493d..8ae080b15a 100644 --- a/MediaBrowser.Common/Json/Converters/JsonDateTimeConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonDateTimeConverter.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Legacy DateTime converter. @@ -31,4 +31,4 @@ namespace MediaBrowser.Common.Json.Converters } } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Common/Json/Converters/JsonDelimitedArrayConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs similarity index 98% rename from MediaBrowser.Common/Json/Converters/JsonDelimitedArrayConverter.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs index b691798c98..c39805aa35 100644 --- a/MediaBrowser.Common/Json/Converters/JsonDelimitedArrayConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs @@ -3,7 +3,7 @@ using System.ComponentModel; using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Convert delimited string to array of type. diff --git a/MediaBrowser.Common/Json/Converters/JsonGuidConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonGuidConverter.cs similarity index 94% rename from MediaBrowser.Common/Json/Converters/JsonGuidConverter.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonGuidConverter.cs index bd96001105..be94dd5192 100644 --- a/MediaBrowser.Common/Json/Converters/JsonGuidConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonGuidConverter.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Converts a GUID object or value to/from JSON. diff --git a/MediaBrowser.Model/Entities/JsonLowerCaseConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonLowerCaseConverter.cs similarity index 65% rename from MediaBrowser.Model/Entities/JsonLowerCaseConverter.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonLowerCaseConverter.cs index 7c627f0e39..cd582ced64 100644 --- a/MediaBrowser.Model/Entities/JsonLowerCaseConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonLowerCaseConverter.cs @@ -1,12 +1,8 @@ -#nullable disable -// THIS IS A HACK -// TODO: @bond Move to separate project - using System; using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Model.Entities +namespace Jellyfin.Extensions.Json.Converters { /// /// Converts an object to a lowercase string. @@ -15,7 +11,7 @@ namespace MediaBrowser.Model.Entities public class JsonLowerCaseConverter : JsonConverter { /// - public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return JsonSerializer.Deserialize(ref reader, options); } @@ -23,7 +19,7 @@ namespace MediaBrowser.Model.Entities /// public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { - writer.WriteStringValue(value?.ToString().ToLowerInvariant()); + writer.WriteStringValue(value?.ToString()?.ToLowerInvariant()); } } } diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableGuidConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonNullableGuidConverter.cs similarity index 95% rename from MediaBrowser.Common/Json/Converters/JsonNullableGuidConverter.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonNullableGuidConverter.cs index 6d96d5496f..6192d1598d 100644 --- a/MediaBrowser.Common/Json/Converters/JsonNullableGuidConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonNullableGuidConverter.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Converts a GUID object or value to/from JSON. diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableStructConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverter.cs similarity index 96% rename from MediaBrowser.Common/Json/Converters/JsonNullableStructConverter.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverter.cs index 0501f7b2a1..6de238b39e 100644 --- a/MediaBrowser.Common/Json/Converters/JsonNullableStructConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverter.cs @@ -2,7 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Converts a nullable struct or value to/from JSON. diff --git a/MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs b/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverterFactory.cs similarity index 95% rename from MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverterFactory.cs index e2a3d798a2..e7749589ae 100644 --- a/MediaBrowser.Common/Json/Converters/JsonNullableStructConverterFactory.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonNullableStructConverterFactory.cs @@ -2,7 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Json nullable struct converter factory. diff --git a/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverter.cs similarity index 93% rename from MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverter.cs index a8f6cfbecf..e3e492e24d 100644 --- a/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverter.cs @@ -3,7 +3,7 @@ using System.ComponentModel; using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Convert Pipe delimited string to array of type. diff --git a/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs b/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs similarity index 95% rename from MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs index 1bebc49ecc..579674f18c 100644 --- a/MediaBrowser.Common/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs @@ -2,7 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Json Pipe delimited array converter factory. diff --git a/MediaBrowser.Common/Json/Converters/JsonStringConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonStringConverter.cs similarity index 96% rename from MediaBrowser.Common/Json/Converters/JsonStringConverter.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonStringConverter.cs index 6cd980e48a..1a7a8c4f55 100644 --- a/MediaBrowser.Common/Json/Converters/JsonStringConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonStringConverter.cs @@ -4,7 +4,7 @@ using System.Text; using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Converter to allow the serializer to read strings. diff --git a/MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonVersionConverter.cs similarity index 94% rename from MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs rename to src/Jellyfin.Extensions/Json/Converters/JsonVersionConverter.cs index 81c093c541..51ffec1cbf 100644 --- a/MediaBrowser.Common/Json/Converters/JsonVersionConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonVersionConverter.cs @@ -2,7 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace MediaBrowser.Common.Json.Converters +namespace Jellyfin.Extensions.Json.Converters { /// /// Converts a Version object or value to/from JSON. diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/src/Jellyfin.Extensions/Json/JsonDefaults.cs similarity index 97% rename from MediaBrowser.Common/Json/JsonDefaults.cs rename to src/Jellyfin.Extensions/Json/JsonDefaults.cs index 405d6125f4..f4ec911231 100644 --- a/MediaBrowser.Common/Json/JsonDefaults.cs +++ b/src/Jellyfin.Extensions/Json/JsonDefaults.cs @@ -1,8 +1,8 @@ using System.Text.Json; using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; -namespace MediaBrowser.Common.Json +namespace Jellyfin.Extensions.Json { /// /// Helper class for having compatible JSON throughout the codebase. diff --git a/MediaBrowser.Common/Extensions/ShuffleExtensions.cs b/src/Jellyfin.Extensions/ShuffleExtensions.cs similarity index 96% rename from MediaBrowser.Common/Extensions/ShuffleExtensions.cs rename to src/Jellyfin.Extensions/ShuffleExtensions.cs index 2604abf85c..4e481983f3 100644 --- a/MediaBrowser.Common/Extensions/ShuffleExtensions.cs +++ b/src/Jellyfin.Extensions/ShuffleExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace MediaBrowser.Common.Extensions +namespace Jellyfin.Extensions { /// /// Provides Shuffle extensions methods for . diff --git a/MediaBrowser.Common/Extensions/SplitStringExtensions.cs b/src/Jellyfin.Extensions/SplitStringExtensions.cs similarity index 65% rename from MediaBrowser.Common/Extensions/SplitStringExtensions.cs rename to src/Jellyfin.Extensions/SplitStringExtensions.cs index 9c9108495f..5fa5c01235 100644 --- a/MediaBrowser.Common/Extensions/SplitStringExtensions.cs +++ b/src/Jellyfin.Extensions/SplitStringExtensions.cs @@ -1,4 +1,4 @@ -/* +/* MIT License Copyright (c) 2019 Gérald Barré @@ -22,13 +22,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#pragma warning disable CS1591 -#pragma warning disable CA1034 +// TODO: remove when analyzer is fixed: https://github.com/dotnet/roslyn-analyzers/issues/5158 +#pragma warning disable CA1034 // Nested types should not be visible + using System; using System.Diagnostics.Contracts; using System.Runtime.InteropServices; -namespace MediaBrowser.Common.Extensions +namespace Jellyfin.Extensions { /// /// Extension class for splitting lines without unnecessary allocations. @@ -42,7 +43,7 @@ namespace MediaBrowser.Common.Extensions /// The separator to split on. /// The enumerator struct. [Pure] - public static SplitEnumerator SpanSplit(this string str, char separator) => new (str.AsSpan(), separator); + public static Enumerator SpanSplit(this string str, char separator) => new (str.AsSpan(), separator); /// /// Creates a new span split enumerator. @@ -51,25 +52,44 @@ namespace MediaBrowser.Common.Extensions /// The separator to split on. /// The enumerator struct. [Pure] - public static SplitEnumerator Split(this ReadOnlySpan str, char separator) => new (str, separator); + public static Enumerator Split(this ReadOnlySpan str, char separator) => new (str, separator); + /// + /// Provides an enumerator for the substrings seperated by the separator. + /// [StructLayout(LayoutKind.Auto)] - public ref struct SplitEnumerator + public ref struct Enumerator { private readonly char _separator; private ReadOnlySpan _str; - public SplitEnumerator(ReadOnlySpan str, char separator) + /// + /// Initializes a new instance of the struct. + /// + /// The span to split. + /// The separator to split on. + public Enumerator(ReadOnlySpan str, char separator) { _str = str; _separator = separator; Current = default; } + /// + /// Gets a reference to the item at the current position of the enumerator. + /// public ReadOnlySpan Current { get; private set; } - public readonly SplitEnumerator GetEnumerator() => this; + /// + /// Returns this. + /// + /// this. + public readonly Enumerator GetEnumerator() => this; + /// + /// Advances the enumerator to the next item. + /// + /// true if there is a next element; otherwise false. public bool MoveNext() { if (_str.Length == 0) diff --git a/MediaBrowser.Common/Extensions/StreamExtensions.cs b/src/Jellyfin.Extensions/StreamExtensions.cs similarity index 98% rename from MediaBrowser.Common/Extensions/StreamExtensions.cs rename to src/Jellyfin.Extensions/StreamExtensions.cs index 5cbf57d988..9751d9d42a 100644 --- a/MediaBrowser.Common/Extensions/StreamExtensions.cs +++ b/src/Jellyfin.Extensions/StreamExtensions.cs @@ -3,7 +3,7 @@ using System.IO; using System.Linq; using System.Text; -namespace MediaBrowser.Common.Extensions +namespace Jellyfin.Extensions { /// /// Class BaseExtensions. diff --git a/MediaBrowser.Common/Extensions/StringBuilderExtensions.cs b/src/Jellyfin.Extensions/StringBuilderExtensions.cs similarity index 93% rename from MediaBrowser.Common/Extensions/StringBuilderExtensions.cs rename to src/Jellyfin.Extensions/StringBuilderExtensions.cs index 75d654f23b..02ff7cc1f9 100644 --- a/MediaBrowser.Common/Extensions/StringBuilderExtensions.cs +++ b/src/Jellyfin.Extensions/StringBuilderExtensions.cs @@ -1,7 +1,7 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Text; -namespace MediaBrowser.Common.Extensions +namespace Jellyfin.Extensions { /// /// Extension methods for the class. diff --git a/src/Jellyfin.Extensions/StringExtensions.cs b/src/Jellyfin.Extensions/StringExtensions.cs new file mode 100644 index 0000000000..acc695ed2f --- /dev/null +++ b/src/Jellyfin.Extensions/StringExtensions.cs @@ -0,0 +1,31 @@ +using System; + +namespace Jellyfin.Extensions +{ + /// + /// Provides extensions methods for . + /// + public static class StringExtensions + { + /// + /// Counts the number of occurrences of [needle] in the string. + /// + /// The haystack to search in. + /// The character to search for. + /// The number of occurrences of the [needle] character. + public static int Count(this ReadOnlySpan value, char needle) + { + var count = 0; + var length = value.Length; + for (var i = 0; i < length; i++) + { + if (value[i] == needle) + { + count++; + } + } + + return count; + } + } +} diff --git a/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs b/tests/Jellyfin.Extensions.Tests/AlphanumericComparatorTests.cs similarity index 83% rename from tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs rename to tests/Jellyfin.Extensions.Tests/AlphanumericComparatorTests.cs index 0adf098c33..7730841a1c 100644 --- a/tests/Jellyfin.Controller.Tests/AlphanumComparatorTests.cs +++ b/tests/Jellyfin.Extensions.Tests/AlphanumericComparatorTests.cs @@ -1,11 +1,10 @@ using System; using System.Linq; -using MediaBrowser.Controller.Sorting; using Xunit; -namespace Jellyfin.Controller.Tests +namespace Jellyfin.Extensions.Tests { - public class AlphanumComparatorTests + public class AlphanumericComparatorTests { // InlineData is pre-sorted [Theory] @@ -20,10 +19,10 @@ namespace Jellyfin.Controller.Tests [InlineData("12345678912345678912345678913234567891", "12345678912345678912345678913234567892")] [InlineData("12345678912345678912345678913234567891a", "12345678912345678912345678913234567891a")] [InlineData("12345678912345678912345678913234567891a", "12345678912345678912345678913234567891b")] - public void AlphanumComparatorTest(params string?[] strings) + public void AlphanumericComparatorTest(params string?[] strings) { var copy = strings.Reverse().ToArray(); - Array.Sort(copy, new AlphanumComparator()); + Array.Sort(copy, new AlphanumericComparator()); Assert.True(strings.SequenceEqual(copy)); } } diff --git a/tests/Jellyfin.Common.Tests/Extensions/CopyToExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs similarity index 95% rename from tests/Jellyfin.Common.Tests/Extensions/CopyToExtensionsTests.cs rename to tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs index 9903409fa6..6fdca46944 100644 --- a/tests/Jellyfin.Common.Tests/Extensions/CopyToExtensionsTests.cs +++ b/tests/Jellyfin.Extensions.Tests/CopyToExtensionsTests.cs @@ -1,9 +1,8 @@ using System; using System.Collections.Generic; -using MediaBrowser.Common.Extensions; using Xunit; -namespace Jellyfin.Common.Tests.Extensions +namespace Jellyfin.Extensions.Tests { public static class CopyToExtensionsTests { diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj new file mode 100644 index 0000000000..4b6dca3777 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj @@ -0,0 +1,38 @@ + + + + net5.0 + false + true + enable + AllEnabledByDefault + ../jellyfin-tests.ruleset + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + + + + + diff --git a/tests/Jellyfin.Common.Tests/Json/JsonBoolNumberTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs similarity index 90% rename from tests/Jellyfin.Common.Tests/Json/JsonBoolNumberTests.cs rename to tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs index 7629d9912c..d0e3e94568 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonBoolNumberTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonBoolNumberTests.cs @@ -1,11 +1,11 @@ -using System.Globalization; +using System.Globalization; using System.Text.Json; using FsCheck; using FsCheck.Xunit; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; using Xunit; -namespace Jellyfin.Common.Tests.Json +namespace Jellyfin.Extensions.Tests.Json.Converters { public class JsonBoolNumberTests { diff --git a/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedArrayTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs similarity index 98% rename from tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedArrayTests.cs rename to tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs index ca300401da..f2ca2ff081 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedArrayTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs @@ -1,11 +1,11 @@ -using System; +using System; using System.Text.Json; using System.Text.Json.Serialization; -using Jellyfin.Common.Tests.Models; +using Jellyfin.Extensions.Tests.Json.Models; using MediaBrowser.Model.Session; using Xunit; -namespace Jellyfin.Common.Tests.Json +namespace Jellyfin.Extensions.Tests.Json.Converters { public static class JsonCommaDelimitedArrayTests { diff --git a/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedIReadOnlyListTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs similarity index 96% rename from tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedIReadOnlyListTests.cs rename to tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs index 34ad9bac79..92886dcd28 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonCommaDelimitedIReadOnlyListTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedIReadOnlyListTests.cs @@ -1,10 +1,10 @@ -using System.Text.Json; +using System.Text.Json; using System.Text.Json.Serialization; -using Jellyfin.Common.Tests.Models; +using Jellyfin.Extensions.Tests.Json.Models; using MediaBrowser.Model.Session; using Xunit; -namespace Jellyfin.Common.Tests.Json +namespace Jellyfin.Extensions.Tests.Json.Converters { public static class JsonCommaDelimitedIReadOnlyListTests { diff --git a/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonGuidConverterTests.cs similarity index 95% rename from tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs rename to tests/Jellyfin.Extensions.Tests/Json/Converters/JsonGuidConverterTests.cs index dbfad3c2ff..8465d465ab 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonGuidConverterTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonGuidConverterTests.cs @@ -1,9 +1,9 @@ using System; using System.Text.Json; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; using Xunit; -namespace Jellyfin.Common.Tests.Json +namespace Jellyfin.Extensions.Tests.Json.Converters { public class JsonGuidConverterTests { diff --git a/tests/Jellyfin.Model.Tests/Entities/JsonLowerCaseConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonLowerCaseConverterTests.cs similarity index 96% rename from tests/Jellyfin.Model.Tests/Entities/JsonLowerCaseConverterTests.cs rename to tests/Jellyfin.Extensions.Tests/Json/Converters/JsonLowerCaseConverterTests.cs index 955d296cc8..af9227de27 100644 --- a/tests/Jellyfin.Model.Tests/Entities/JsonLowerCaseConverterTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonLowerCaseConverterTests.cs @@ -1,9 +1,10 @@ using System.Text.Json; using System.Text.Json.Serialization; +using Jellyfin.Extensions.Json.Converters; using MediaBrowser.Model.Entities; using Xunit; -namespace Jellyfin.Model.Tests.Entities +namespace Jellyfin.Extensions.Tests.Json.Converters { public class JsonLowerCaseConverterTests { diff --git a/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonNullableGuidConverterTests.cs similarity index 96% rename from tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs rename to tests/Jellyfin.Extensions.Tests/Json/Converters/JsonNullableGuidConverterTests.cs index cb3b66c4c5..b0dbc09e4f 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonNullableGuidConverterTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonNullableGuidConverterTests.cs @@ -1,9 +1,9 @@ using System; using System.Text.Json; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; using Xunit; -namespace Jellyfin.Common.Tests.Json +namespace Jellyfin.Extensions.Tests.Json.Converters { public class JsonNullableGuidConverterTests { diff --git a/tests/Jellyfin.Common.Tests/Json/JsonStringConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs similarity index 89% rename from tests/Jellyfin.Common.Tests/Json/JsonStringConverterTests.cs rename to tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs index 2b23c6705b..655e070742 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonStringConverterTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs @@ -1,8 +1,8 @@ -using System.Text.Json; -using MediaBrowser.Common.Json.Converters; +using System.Text.Json; +using Jellyfin.Extensions.Json.Converters; using Xunit; -namespace Jellyfin.Common.Tests.Json +namespace Jellyfin.Extensions.Tests.Json.Converters { public class JsonStringConverterTests { diff --git a/tests/Jellyfin.Common.Tests/Json/JsonVersionConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonVersionConverterTests.cs similarity index 89% rename from tests/Jellyfin.Common.Tests/Json/JsonVersionConverterTests.cs rename to tests/Jellyfin.Extensions.Tests/Json/Converters/JsonVersionConverterTests.cs index f2cefdbf8e..5fbac7eab0 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonVersionConverterTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonVersionConverterTests.cs @@ -1,9 +1,9 @@ -using System; +using System; using System.Text.Json; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; using Xunit; -namespace Jellyfin.Common.Tests.Json +namespace Jellyfin.Extensions.Tests.Json.Converters { public class JsonVersionConverterTests { diff --git a/tests/Jellyfin.Common.Tests/Models/GenericBodyArrayModel.cs b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs similarity index 81% rename from tests/Jellyfin.Common.Tests/Models/GenericBodyArrayModel.cs rename to tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs index 276e1bfbe2..ef135278fd 100644 --- a/tests/Jellyfin.Common.Tests/Models/GenericBodyArrayModel.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyArrayModel.cs @@ -1,8 +1,8 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; -namespace Jellyfin.Common.Tests.Models +namespace Jellyfin.Extensions.Tests.Json.Models { /// /// The generic body model. diff --git a/tests/Jellyfin.Common.Tests/Models/GenericBodyIReadOnlyListModel.cs b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs similarity index 78% rename from tests/Jellyfin.Common.Tests/Models/GenericBodyIReadOnlyListModel.cs rename to tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs index 627454b25f..8e7b5a35b4 100644 --- a/tests/Jellyfin.Common.Tests/Models/GenericBodyIReadOnlyListModel.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Models/GenericBodyIReadOnlyListModel.cs @@ -1,8 +1,8 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; +using Jellyfin.Extensions.Json.Converters; -namespace Jellyfin.Common.Tests.Models +namespace Jellyfin.Extensions.Tests.Json.Models { /// /// The generic body IReadOnlyList model. diff --git a/tests/Jellyfin.Common.Tests/Extensions/ShuffleExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs similarity index 85% rename from tests/Jellyfin.Common.Tests/Extensions/ShuffleExtensionsTests.cs rename to tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs index cbdbcf112c..c72216d94b 100644 --- a/tests/Jellyfin.Common.Tests/Extensions/ShuffleExtensionsTests.cs +++ b/tests/Jellyfin.Extensions.Tests/ShuffleExtensionsTests.cs @@ -1,8 +1,7 @@ using System; -using MediaBrowser.Common.Extensions; using Xunit; -namespace Jellyfin.Common.Tests.Extensions +namespace Jellyfin.Extensions.Tests { public static class ShuffleExtensionsTests { diff --git a/tests/Jellyfin.Controller.Tests/Extensions/StringExtensionsTests.cs b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs similarity index 83% rename from tests/Jellyfin.Controller.Tests/Extensions/StringExtensionsTests.cs rename to tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs index 576c0a49b2..d1aa2e4764 100644 --- a/tests/Jellyfin.Controller.Tests/Extensions/StringExtensionsTests.cs +++ b/tests/Jellyfin.Extensions.Tests/StringExtensionsTests.cs @@ -1,8 +1,7 @@ using System; -using MediaBrowser.Controller.Extensions; using Xunit; -namespace Jellyfin.Controller.Extensions.Tests +namespace Jellyfin.Extensions.Tests { public class StringExtensionsTests { diff --git a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs index 415682e855..45808375f1 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/FFprobeParserTests.cs @@ -1,7 +1,7 @@ using System.IO; using System.Text.Json; using System.Threading.Tasks; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.MediaEncoding.Probing; using Xunit; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs index 98fbb00d52..d8089eea2d 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Probing/ProbeResultNormalizerTests.cs @@ -2,7 +2,7 @@ using System; using System.Globalization; using System.IO; using System.Text.Json; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.MediaEncoding.Probing; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; diff --git a/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs b/tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs similarity index 98% rename from tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs rename to tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs index efe8063a07..25900bc09e 100644 --- a/tests/Jellyfin.Common.Tests/Json/JsonOmdbConverterTests.cs +++ b/tests/Jellyfin.Providers.Tests/Omdb/JsonOmdbConverterTests.cs @@ -1,10 +1,9 @@ using System.Text.Json; using System.Text.Json.Serialization; -using MediaBrowser.Common.Json.Converters; using MediaBrowser.Providers.Plugins.Omdb; using Xunit; -namespace Jellyfin.Common.Tests.Json +namespace Jellyfin.Providers.Tests.Omdb { public class JsonOmdbConverterTests { diff --git a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs index ea6838682a..4ea05397dd 100644 --- a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs +++ b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs @@ -7,7 +7,7 @@ using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Models.StartupDtos; using Jellyfin.Api.Models.UserDtos; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Xunit; namespace Jellyfin.Server.Integration.Tests diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs index f5411dcb8d..8273653637 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs @@ -5,7 +5,7 @@ using System.Text; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Models; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Xunit; namespace Jellyfin.Server.Integration.Tests.Controllers diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs index 169a5a6c52..9c0fc72f65 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs @@ -6,7 +6,7 @@ using System.Net.Mime; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Models.StartupDtos; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using Xunit; using Xunit.Priority; diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs index 6584490de5..8866ab53cd 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs @@ -8,7 +8,7 @@ using System.Net.Mime; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Models.UserDtos; -using MediaBrowser.Common.Json; +using Jellyfin.Extensions.Json; using MediaBrowser.Model.Dto; using Xunit; using Xunit.Priority;