Merge pull request #6430 from Bond-009/minor17

Minor improvements
This commit is contained in:
Claus Vium 2021-08-16 08:59:43 +02:00 committed by GitHub
commit fa77902955
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 156 additions and 200 deletions

View File

@ -880,7 +880,7 @@ namespace Emby.Server.Implementations.Channels
} }
} }
private async Task CacheResponse(object result, string path) private async Task CacheResponse(ChannelItemResult result, string path)
{ {
try try
{ {

View File

@ -1,5 +1,3 @@
#nullable disable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -63,13 +61,13 @@ namespace Emby.Server.Implementations.Collections
} }
/// <inheritdoc /> /// <inheritdoc />
public event EventHandler<CollectionCreatedEventArgs> CollectionCreated; public event EventHandler<CollectionCreatedEventArgs>? CollectionCreated;
/// <inheritdoc /> /// <inheritdoc />
public event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection; public event EventHandler<CollectionModifiedEventArgs>? ItemsAddedToCollection;
/// <inheritdoc /> /// <inheritdoc />
public event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection; public event EventHandler<CollectionModifiedEventArgs>? ItemsRemovedFromCollection;
private IEnumerable<Folder> FindFolders(string path) private IEnumerable<Folder> FindFolders(string path)
{ {
@ -80,7 +78,7 @@ namespace Emby.Server.Implementations.Collections
.Where(i => _fileSystem.AreEqual(path, i.Path) || _fileSystem.ContainsSubPath(i.Path, path)); .Where(i => _fileSystem.AreEqual(path, i.Path) || _fileSystem.ContainsSubPath(i.Path, path));
} }
internal async Task<Folder> EnsureLibraryFolder(string path, bool createIfNeeded) internal async Task<Folder?> EnsureLibraryFolder(string path, bool createIfNeeded)
{ {
var existingFolder = FindFolders(path).FirstOrDefault(); var existingFolder = FindFolders(path).FirstOrDefault();
if (existingFolder != null) if (existingFolder != null)
@ -114,7 +112,7 @@ namespace Emby.Server.Implementations.Collections
return Path.Combine(_appPaths.DataPath, "collections"); return Path.Combine(_appPaths.DataPath, "collections");
} }
private Task<Folder> GetCollectionsFolder(bool createIfNeeded) private Task<Folder?> GetCollectionsFolder(bool createIfNeeded)
{ {
return EnsureLibraryFolder(GetCollectionsFolderPath(), createIfNeeded); return EnsureLibraryFolder(GetCollectionsFolderPath(), createIfNeeded);
} }
@ -203,8 +201,7 @@ namespace Emby.Server.Implementations.Collections
private async Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent, MetadataRefreshOptions refreshOptions) private async Task AddToCollectionAsync(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent, MetadataRefreshOptions refreshOptions)
{ {
var collection = _libraryManager.GetItemById(collectionId) as BoxSet; if (_libraryManager.GetItemById(collectionId) is not BoxSet collection)
if (collection == null)
{ {
throw new ArgumentException("No collection exists with the supplied Id"); throw new ArgumentException("No collection exists with the supplied Id");
} }
@ -256,9 +253,7 @@ namespace Emby.Server.Implementations.Collections
/// <inheritdoc /> /// <inheritdoc />
public async Task RemoveFromCollectionAsync(Guid collectionId, IEnumerable<Guid> itemIds) public async Task RemoveFromCollectionAsync(Guid collectionId, IEnumerable<Guid> itemIds)
{ {
var collection = _libraryManager.GetItemById(collectionId) as BoxSet; if (_libraryManager.GetItemById(collectionId) is not BoxSet collection)
if (collection == null)
{ {
throw new ArgumentException("No collection exists with the supplied Id"); throw new ArgumentException("No collection exists with the supplied Id");
} }
@ -312,11 +307,7 @@ namespace Emby.Server.Implementations.Collections
foreach (var item in items) foreach (var item in items)
{ {
if (item is not ISupportsBoxSetGrouping) if (item is ISupportsBoxSetGrouping)
{
results[item.Id] = item;
}
else
{ {
var itemId = item.Id; var itemId = item.Id;
@ -340,6 +331,7 @@ namespace Emby.Server.Implementations.Collections
} }
var alreadyInResults = false; var alreadyInResults = false;
// this is kind of a performance hack because only Video has alternate versions that should be in a box set? // this is kind of a performance hack because only Video has alternate versions that should be in a box set?
if (item is Video video) if (item is Video video)
{ {
@ -355,11 +347,13 @@ namespace Emby.Server.Implementations.Collections
} }
} }
if (!alreadyInResults) if (alreadyInResults)
{ {
results[itemId] = item; continue;
} }
} }
results[item.Id] = item;
} }
return results.Values; return results.Values;

View File

@ -1,5 +1,3 @@
#nullable disable
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@ -38,10 +36,10 @@ namespace Emby.Server.Implementations.Localization
private readonly ConcurrentDictionary<string, Dictionary<string, string>> _dictionaries = private readonly ConcurrentDictionary<string, Dictionary<string, string>> _dictionaries =
new ConcurrentDictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); new ConcurrentDictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase);
private List<CultureDto> _cultures;
private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options; private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
private List<CultureDto> _cultures = new List<CultureDto>();
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="LocalizationManager" /> class. /// Initializes a new instance of the <see cref="LocalizationManager" /> class.
/// </summary> /// </summary>
@ -72,8 +70,8 @@ namespace Emby.Server.Implementations.Localization
string countryCode = resource.Substring(RatingsPath.Length, 2); string countryCode = resource.Substring(RatingsPath.Length, 2);
var dict = new Dictionary<string, ParentalRating>(StringComparer.OrdinalIgnoreCase); var dict = new Dictionary<string, ParentalRating>(StringComparer.OrdinalIgnoreCase);
await using var str = _assembly.GetManifestResourceStream(resource); await using var stream = _assembly.GetManifestResourceStream(resource);
using var reader = new StreamReader(str); using var reader = new StreamReader(stream!); // shouldn't be null here, we just got the resource path from Assembly.GetManifestResourceNames()
await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false))
{ {
if (string.IsNullOrWhiteSpace(line)) if (string.IsNullOrWhiteSpace(line))
@ -113,7 +111,8 @@ namespace Emby.Server.Implementations.Localization
{ {
List<CultureDto> list = new List<CultureDto>(); List<CultureDto> list = new List<CultureDto>();
await using var stream = _assembly.GetManifestResourceStream(CulturesPath); await using var stream = _assembly.GetManifestResourceStream(CulturesPath)
?? throw new InvalidOperationException($"Invalid resource path: '{CulturesPath}'");
using var reader = new StreamReader(stream); using var reader = new StreamReader(stream);
await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false)) await foreach (var line in reader.ReadAllLinesAsync().ConfigureAwait(false))
{ {
@ -162,7 +161,7 @@ namespace Emby.Server.Implementations.Localization
} }
/// <inheritdoc /> /// <inheritdoc />
public CultureDto FindLanguageInfo(string language) public CultureDto? FindLanguageInfo(string language)
{ {
// TODO language should ideally be a ReadOnlySpan but moq cannot mock ref structs // TODO language should ideally be a ReadOnlySpan but moq cannot mock ref structs
for (var i = 0; i < _cultures.Count; i++) for (var i = 0; i < _cultures.Count; i++)
@ -183,9 +182,10 @@ namespace Emby.Server.Implementations.Localization
/// <inheritdoc /> /// <inheritdoc />
public IEnumerable<CountryInfo> GetCountries() public IEnumerable<CountryInfo> GetCountries()
{ {
using StreamReader reader = new StreamReader(_assembly.GetManifestResourceStream(CountriesPath)); using StreamReader reader = new StreamReader(
_assembly.GetManifestResourceStream(CountriesPath) ?? throw new InvalidOperationException($"Invalid resource path: '{CountriesPath}'"));
return JsonSerializer.Deserialize<IEnumerable<CountryInfo>>(reader.ReadToEnd(), _jsonOptions); return JsonSerializer.Deserialize<IEnumerable<CountryInfo>>(reader.ReadToEnd(), _jsonOptions)
?? throw new InvalidOperationException($"Resource contains invalid data: '{CountriesPath}'");
} }
/// <inheritdoc /> /// <inheritdoc />
@ -205,7 +205,9 @@ namespace Emby.Server.Implementations.Localization
countryCode = "us"; countryCode = "us";
} }
return GetRatings(countryCode) ?? GetRatings("us"); return GetRatings(countryCode)
?? GetRatings("us")
?? throw new InvalidOperationException($"Invalid resource path: '{CountriesPath}'");
} }
/// <summary> /// <summary>
@ -213,7 +215,7 @@ namespace Emby.Server.Implementations.Localization
/// </summary> /// </summary>
/// <param name="countryCode">The country code.</param> /// <param name="countryCode">The country code.</param>
/// <returns>The ratings.</returns> /// <returns>The ratings.</returns>
private Dictionary<string, ParentalRating> GetRatings(string countryCode) private Dictionary<string, ParentalRating>? GetRatings(string countryCode)
{ {
_allParentalRatings.TryGetValue(countryCode, out var value); _allParentalRatings.TryGetValue(countryCode, out var value);
@ -238,7 +240,7 @@ namespace Emby.Server.Implementations.Localization
var ratingsDictionary = GetParentalRatingsDictionary(); var ratingsDictionary = GetParentalRatingsDictionary();
if (ratingsDictionary.TryGetValue(rating, out ParentalRating value)) if (ratingsDictionary.TryGetValue(rating, out ParentalRating? value))
{ {
return value.Value; return value.Value;
} }
@ -268,20 +270,6 @@ namespace Emby.Server.Implementations.Localization
return null; return null;
} }
/// <inheritdoc />
public bool HasUnicodeCategory(string value, UnicodeCategory category)
{
foreach (var chr in value)
{
if (char.GetUnicodeCategory(chr) == category)
{
return true;
}
}
return false;
}
/// <inheritdoc /> /// <inheritdoc />
public string GetLocalizedString(string phrase) public string GetLocalizedString(string phrase)
{ {
@ -347,20 +335,23 @@ namespace Emby.Server.Implementations.Localization
{ {
await using var stream = _assembly.GetManifestResourceStream(resourcePath); await using var stream = _assembly.GetManifestResourceStream(resourcePath);
// If a Culture doesn't have a translation the stream will be null and it defaults to en-us further up the chain // If a Culture doesn't have a translation the stream will be null and it defaults to en-us further up the chain
if (stream != null) if (stream == null)
{ {
_logger.LogError("Missing translation/culture resource: {ResourcePath}", resourcePath);
return;
}
var dict = await JsonSerializer.DeserializeAsync<Dictionary<string, string>>(stream, _jsonOptions).ConfigureAwait(false); var dict = await JsonSerializer.DeserializeAsync<Dictionary<string, string>>(stream, _jsonOptions).ConfigureAwait(false);
if (dict == null)
{
throw new InvalidOperationException($"Resource contains invalid data: '{stream}'");
}
foreach (var key in dict.Keys) foreach (var key in dict.Keys)
{ {
dictionary[key] = dict[key]; dictionary[key] = dict[key];
} }
} }
else
{
_logger.LogError("Missing translation/culture resource: {ResourcePath}", resourcePath);
}
}
private static string GetResourceFilename(string culture) private static string GetResourceFilename(string culture)
{ {

View File

@ -47,10 +47,10 @@ namespace MediaBrowser.Common.Plugins
var assemblyFilePath = assembly.Location; var assemblyFilePath = assembly.Location;
var dataFolderPath = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(assemblyFilePath)); var dataFolderPath = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(assemblyFilePath));
if (!Directory.Exists(dataFolderPath) && Version != null) if (Version != null && !Directory.Exists(dataFolderPath))
{ {
// Try again with the version number appended to the folder name. // Try again with the version number appended to the folder name.
dataFolderPath = dataFolderPath + "_" + Version.ToString(); dataFolderPath += "_" + Version.ToString();
} }
SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version); SetAttributes(assemblyFilePath, dataFolderPath, assemblyName.Version);

View File

@ -1,6 +1,5 @@
#nullable disable
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Jellyfin.Extensions; using Jellyfin.Extensions;
@ -16,7 +15,7 @@ namespace MediaBrowser.Controller.BaseItemManager
{ {
private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IServerConfigurationManager _serverConfigurationManager;
private int _metadataRefreshConcurrency = 0; private int _metadataRefreshConcurrency;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="BaseItemManager"/> class. /// Initializes a new instance of the <see cref="BaseItemManager"/> class.
@ -101,7 +100,7 @@ namespace MediaBrowser.Controller.BaseItemManager
/// Called when the configuration is updated. /// Called when the configuration is updated.
/// It will refresh the metadata throttler if the relevant config changed. /// It will refresh the metadata throttler if the relevant config changed.
/// </summary> /// </summary>
private void OnConfigurationUpdated(object sender, EventArgs e) private void OnConfigurationUpdated(object? sender, EventArgs e)
{ {
int newMetadataRefreshConcurrency = GetMetadataRefreshConcurrency(); int newMetadataRefreshConcurrency = GetMetadataRefreshConcurrency();
if (_metadataRefreshConcurrency != newMetadataRefreshConcurrency) if (_metadataRefreshConcurrency != newMetadataRefreshConcurrency)
@ -114,6 +113,7 @@ namespace MediaBrowser.Controller.BaseItemManager
/// <summary> /// <summary>
/// Creates the metadata refresh throttler. /// Creates the metadata refresh throttler.
/// </summary> /// </summary>
[MemberNotNull(nameof(MetadataRefreshThrottler))]
private void SetupMetadataThrottler() private void SetupMetadataThrottler()
{ {
MetadataRefreshThrottler = new SemaphoreSlim(_metadataRefreshConcurrency); MetadataRefreshThrottler = new SemaphoreSlim(_metadataRefreshConcurrency);

View File

@ -1,5 +1,3 @@
#nullable disable
using System.Threading; using System.Threading;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;

View File

@ -1,7 +1,6 @@
#nullable disable #pragma warning disable CS1591
#pragma warning disable CA1002, CA2227, CS1591
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace MediaBrowser.Controller.Channels namespace MediaBrowser.Controller.Channels
@ -10,10 +9,10 @@ namespace MediaBrowser.Controller.Channels
{ {
public ChannelItemResult() public ChannelItemResult()
{ {
Items = new List<ChannelItemInfo>(); Items = Array.Empty<ChannelItemInfo>();
} }
public List<ChannelItemInfo> Items { get; set; } public IReadOnlyList<ChannelItemInfo> Items { get; set; }
public int? TotalRecordCount { get; set; } public int? TotalRecordCount { get; set; }
} }

View File

@ -1,6 +1,6 @@
#nullable disable #nullable disable
#pragma warning disable CA2227, CS1591 #pragma warning disable CS1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -1,5 +1,3 @@
#nullable disable
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;

View File

@ -1,5 +1,3 @@
#nullable disable
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;
@ -16,17 +14,17 @@ namespace MediaBrowser.Controller.Collections
/// <summary> /// <summary>
/// Occurs when [collection created]. /// Occurs when [collection created].
/// </summary> /// </summary>
event EventHandler<CollectionCreatedEventArgs> CollectionCreated; event EventHandler<CollectionCreatedEventArgs>? CollectionCreated;
/// <summary> /// <summary>
/// Occurs when [items added to collection]. /// Occurs when [items added to collection].
/// </summary> /// </summary>
event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection; event EventHandler<CollectionModifiedEventArgs>? ItemsAddedToCollection;
/// <summary> /// <summary>
/// Occurs when [items removed from collection]. /// Occurs when [items removed from collection].
/// </summary> /// </summary>
event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection; event EventHandler<CollectionModifiedEventArgs>? ItemsRemovedFromCollection;
/// <summary> /// <summary>
/// Creates the collection. /// Creates the collection.

View File

@ -1,5 +1,3 @@
#nullable disable
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;

View File

@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
@ -16,9 +15,7 @@ using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.MediaInfo;
using Microsoft.Extensions.Configuration;
namespace MediaBrowser.Controller.MediaEncoding namespace MediaBrowser.Controller.MediaEncoding
{ {

View File

@ -1,4 +1,3 @@
#nullable disable
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -56,19 +55,11 @@ namespace MediaBrowser.Model.Globalization
/// <returns><see cref="IEnumerable{LocalizatonOption}" />.</returns> /// <returns><see cref="IEnumerable{LocalizatonOption}" />.</returns>
IEnumerable<LocalizationOption> GetLocalizationOptions(); IEnumerable<LocalizationOption> GetLocalizationOptions();
/// <summary>
/// Checks if the string contains a character with the specified unicode category.
/// </summary>
/// <param name="value">The string.</param>
/// <param name="category">The unicode category.</param>
/// <returns>Wether or not the string contains a character with the specified unicode category.</returns>
bool HasUnicodeCategory(string value, UnicodeCategory category);
/// <summary> /// <summary>
/// Returns the correct <see cref="CultureInfo" /> for the given language. /// Returns the correct <see cref="CultureInfo" /> for the given language.
/// </summary> /// </summary>
/// <param name="language">The language.</param> /// <param name="language">The language.</param>
/// <returns>The correct <see cref="CultureInfo" /> for the given language.</returns> /// <returns>The correct <see cref="CultureInfo" /> for the given language.</returns>
CultureDto FindLanguageInfo(string language); CultureDto? FindLanguageInfo(string language);
} }
} }

View File

@ -148,15 +148,12 @@ namespace MediaBrowser.XbmcMetadata.Parsers
return; return;
} }
using (var fileStream = File.OpenRead(metadataFile))
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{
item.ResetPeople(); item.ResetPeople();
// Need to handle a url after the xml data // Need to handle a url after the xml data
// http://kodi.wiki/view/NFO_files/movies // http://kodi.wiki/view/NFO_files/movies
var xml = streamReader.ReadToEnd(); var xml = File.ReadAllText(metadataFile);
// Find last closing Tag // Find last closing Tag
// Need to do this in two steps to account for random > characters after the closing xml // Need to do this in two steps to account for random > characters after the closing xml
@ -170,7 +167,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
if (index != -1) if (index != -1)
{ {
var endingXml = xml.Substring(index); var endingXml = xml.AsSpan().Slice(index);
ParseProviderLinks(item.Item, endingXml); ParseProviderLinks(item.Item, endingXml);
@ -219,9 +216,8 @@ namespace MediaBrowser.XbmcMetadata.Parsers
{ {
} }
} }
}
protected void ParseProviderLinks(T item, string xml) protected void ParseProviderLinks(T item, ReadOnlySpan<char> xml)
{ {
if (ProviderIdParsers.TryFindImdbId(xml, out var imdbId)) if (ProviderIdParsers.TryFindImdbId(xml, out var imdbId))
{ {

View File

@ -39,13 +39,10 @@ namespace MediaBrowser.XbmcMetadata.Parsers
/// <inheritdoc /> /// <inheritdoc />
protected override void Fetch(MetadataResult<Episode> item, string metadataFile, XmlReaderSettings settings, CancellationToken cancellationToken) protected override void Fetch(MetadataResult<Episode> item, string metadataFile, XmlReaderSettings settings, CancellationToken cancellationToken)
{
using (var fileStream = File.OpenRead(metadataFile))
using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{ {
item.ResetPeople(); item.ResetPeople();
var xmlFile = streamReader.ReadToEnd(); var xmlFile = File.ReadAllText(metadataFile);
var srch = "</episodedetails>"; var srch = "</episodedetails>";
var index = xmlFile.IndexOf(srch, StringComparison.OrdinalIgnoreCase); var index = xmlFile.IndexOf(srch, StringComparison.OrdinalIgnoreCase);
@ -107,7 +104,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers
{ {
} }
} }
}
/// <inheritdoc /> /// <inheritdoc />
protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<Episode> itemResult) protected override void FetchDataFromXmlNode(XmlReader reader, MetadataResult<Episode> itemResult)

View File

@ -66,7 +66,7 @@ namespace Jellyfin.Server.Implementations.Tests.Localization
var germany = localizationManager.FindLanguageInfo(identifier); var germany = localizationManager.FindLanguageInfo(identifier);
Assert.NotNull(germany); Assert.NotNull(germany);
Assert.Equal("ger", germany.ThreeLetterISOLanguageName); Assert.Equal("ger", germany!.ThreeLetterISOLanguageName);
Assert.Equal("German", germany.DisplayName); Assert.Equal("German", germany.DisplayName);
Assert.Equal("German", germany.Name); Assert.Equal("German", germany.Name);
Assert.Contains("deu", germany.ThreeLetterISOLanguageNames); Assert.Contains("deu", germany.ThreeLetterISOLanguageNames);