diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
index 665d70a41..b01fd93a7 100644
--- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
+++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
@@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.Library
}
///
- public bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent)
+ public bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem? parent)
{
// Don't ignore application folders
if (fileInfo.FullName.Contains(_serverApplicationPaths.RootFolderPath, StringComparison.InvariantCulture))
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index 0a4432bec..03002300c 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
#pragma warning disable CS1591
using System;
@@ -90,8 +88,8 @@ namespace Emby.Server.Implementations.Library
///
/// The _root folder.
///
- private volatile AggregateFolder _rootFolder;
- private volatile UserRootFolder _userRootFolder;
+ private volatile AggregateFolder? _rootFolder;
+ private volatile UserRootFolder? _userRootFolder;
private bool _wizardCompleted;
@@ -156,17 +154,17 @@ namespace Emby.Server.Implementations.Library
///
/// Occurs when [item added].
///
- public event EventHandler ItemAdded;
+ public event EventHandler? ItemAdded;
///
/// Occurs when [item updated].
///
- public event EventHandler ItemUpdated;
+ public event EventHandler? ItemUpdated;
///
/// Occurs when [item removed].
///
- public event EventHandler ItemRemoved;
+ public event EventHandler? ItemRemoved;
///
/// Gets the root folder.
@@ -265,7 +263,7 @@ namespace Emby.Server.Implementations.Library
///
/// The sender.
/// The instance containing the event data.
- private void ConfigurationUpdated(object sender, EventArgs e)
+ private void ConfigurationUpdated(object? sender, EventArgs e)
{
var config = _configurationManager.Configuration;
@@ -480,7 +478,7 @@ namespace Emby.Server.Implementations.Library
/// The args.
/// The resolvers.
/// BaseItem.
- private BaseItem ResolveItem(ItemResolveArgs args, IItemResolver[] resolvers)
+ private BaseItem? ResolveItem(ItemResolveArgs args, IItemResolver[]? resolvers)
{
var item = (resolvers ?? EntityResolvers).Select(r => Resolve(args, r))
.FirstOrDefault(i => i is not null);
@@ -493,7 +491,7 @@ namespace Emby.Server.Implementations.Library
return item;
}
- private BaseItem Resolve(ItemResolveArgs args, IItemResolver resolver)
+ private BaseItem? Resolve(ItemResolveArgs args, IItemResolver resolver)
{
try
{
@@ -535,16 +533,16 @@ namespace Emby.Server.Implementations.Library
return key.GetMD5();
}
- public BaseItem ResolvePath(FileSystemMetadata fileInfo, Folder parent = null, IDirectoryService directoryService = null)
+ public BaseItem? ResolvePath(FileSystemMetadata fileInfo, Folder? parent = null, IDirectoryService? directoryService = null)
=> ResolvePath(fileInfo, directoryService ?? new DirectoryService(_fileSystem), null, parent);
- private BaseItem ResolvePath(
+ private BaseItem? ResolvePath(
FileSystemMetadata fileInfo,
IDirectoryService directoryService,
- IItemResolver[] resolvers,
- Folder parent = null,
+ IItemResolver[]? resolvers,
+ Folder? parent = null,
CollectionType? collectionType = null,
- LibraryOptions libraryOptions = null)
+ LibraryOptions? libraryOptions = null)
{
ArgumentNullException.ThrowIfNull(fileInfo);
@@ -617,7 +615,7 @@ namespace Emby.Server.Implementations.Library
return ResolveItem(args, resolvers);
}
- public bool IgnoreFile(FileSystemMetadata file, BaseItem parent)
+ public bool IgnoreFile(FileSystemMetadata file, BaseItem? parent)
=> EntityResolutionIgnoreRules.Any(r => r.ShouldIgnore(file, parent));
public List NormalizeRootPathList(IEnumerable paths)
@@ -692,16 +690,16 @@ namespace Emby.Server.Implementations.Library
private IEnumerable ResolveFileList(
IReadOnlyList fileList,
IDirectoryService directoryService,
- Folder parent,
+ Folder? parent,
CollectionType? collectionType,
- IItemResolver[] resolvers,
+ IItemResolver[]? resolvers,
LibraryOptions libraryOptions)
{
// Given that fileList is a list we can save enumerator allocations by indexing
for (var i = 0; i < fileList.Count; i++)
{
var file = fileList[i];
- BaseItem result = null;
+ BaseItem? result = null;
try
{
result = ResolvePath(file, directoryService, resolvers, parent, collectionType, libraryOptions);
@@ -730,7 +728,7 @@ namespace Emby.Server.Implementations.Library
Directory.CreateDirectory(rootFolderPath);
var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ??
- ((Folder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath)))
+ (ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath)) as Folder ?? throw new InvalidOperationException("Something went very wong"))
.DeepCopy();
// In case program data folder was moved
@@ -796,7 +794,7 @@ namespace Emby.Server.Implementations.Library
Directory.CreateDirectory(userRootPath);
var newItemId = GetNewItemId(userRootPath, typeof(UserRootFolder));
- UserRootFolder tmpItem = null;
+ UserRootFolder? tmpItem = null;
try
{
tmpItem = GetItemById(newItemId) as UserRootFolder;
@@ -809,7 +807,8 @@ namespace Emby.Server.Implementations.Library
if (tmpItem is null)
{
_logger.LogDebug("Creating new userRootFolder with DeepCopy");
- tmpItem = ((Folder)ResolvePath(_fileSystem.GetDirectoryInfo(userRootPath))).DeepCopy();
+ tmpItem = (ResolvePath(_fileSystem.GetDirectoryInfo(userRootPath)) as Folder ?? throw new InvalidOperationException("Failed to get user root path"))
+ .DeepCopy();
}
// In case program data folder was moved
@@ -828,7 +827,8 @@ namespace Emby.Server.Implementations.Library
return _userRootFolder;
}
- public BaseItem FindByPath(string path, bool? isFolder)
+ ///
+ public BaseItem? FindByPath(string path, bool? isFolder)
{
// If this returns multiple items it could be tricky figuring out which one is correct.
// In most cases, the newest one will be and the others obsolete but not yet cleaned up
@@ -847,12 +847,8 @@ namespace Emby.Server.Implementations.Library
.FirstOrDefault();
}
- ///
- /// Gets the person.
- ///
- /// The name.
- /// Task{Person}.
- public Person GetPerson(string name)
+ ///
+ public Person? GetPerson(string name)
{
var path = Person.GetPath(name);
var id = GetItemByNameId(path);
@@ -1159,7 +1155,7 @@ namespace Emby.Server.Implementations.Library
.ToList();
}
- private VirtualFolderInfo GetVirtualFolderInfo(string dir, List allCollectionFolders, HashSet refreshQueue)
+ private VirtualFolderInfo GetVirtualFolderInfo(string dir, List allCollectionFolders, HashSet? refreshQueue)
{
var info = new VirtualFolderInfo
{
@@ -1224,14 +1220,14 @@ namespace Emby.Server.Implementations.Library
}
///
- public BaseItem GetItemById(Guid id)
+ public BaseItem? GetItemById(Guid id)
{
if (id.IsEmpty())
{
throw new ArgumentException("Guid can't be empty", nameof(id));
}
- if (_cache.TryGetValue(id, out BaseItem item))
+ if (_cache.TryGetValue(id, out BaseItem? item))
{
return item;
}
@@ -1247,7 +1243,7 @@ namespace Emby.Server.Implementations.Library
}
///
- public T GetItemById(Guid id)
+ public T? GetItemById(Guid id)
where T : BaseItem
{
var item = GetItemById(id);
@@ -1260,7 +1256,7 @@ namespace Emby.Server.Implementations.Library
}
///
- public T GetItemById(Guid id, Guid userId)
+ public T? GetItemById(Guid id, Guid userId)
where T : BaseItem
{
var user = userId.IsEmpty() ? null : _userManager.GetUserById(userId);
@@ -1268,7 +1264,7 @@ namespace Emby.Server.Implementations.Library
}
///
- public T GetItemById(Guid id, User user)
+ public T? GetItemById(Guid id, User? user)
where T : BaseItem
{
var item = GetItemById(id);
@@ -1435,7 +1431,7 @@ namespace Emby.Server.Implementations.Library
var parents = new BaseItem[len];
for (int i = 0; i < len; i++)
{
- parents[i] = GetItemById(ancestorIds[i]);
+ parents[i] = GetItemById(ancestorIds[i]) ?? throw new ArgumentException($"Failed to find parent with id: {ancestorIds[i]}");
if (parents[i] is not (ICollectionFolder or UserView))
{
return;
@@ -1449,7 +1445,7 @@ namespace Emby.Server.Implementations.Library
// Prevent searching in all libraries due to empty filter
if (query.TopParentIds.Length == 0)
{
- query.TopParentIds = new[] { Guid.NewGuid() };
+ query.TopParentIds = [Guid.NewGuid()];
}
}
@@ -1546,7 +1542,7 @@ namespace Emby.Server.Implementations.Library
}
}
- private IEnumerable GetTopParentIdsForQuery(BaseItem item, User user)
+ private IEnumerable GetTopParentIdsForQuery(BaseItem item, User? user)
{
if (item is UserView view)
{
@@ -1624,7 +1620,7 @@ namespace Emby.Server.Implementations.Library
return items
.SelectMany(i => i.ToArray())
.Select(ResolveIntro)
- .Where(i => i is not null);
+ .Where(i => i is not null)!; // null values got filtered out
}
///
@@ -1653,9 +1649,9 @@ namespace Emby.Server.Implementations.Library
///
/// The info.
/// Video.
- private Video ResolveIntro(IntroInfo info)
+ private Video? ResolveIntro(IntroInfo info)
{
- Video video = null;
+ Video? video = null;
if (info.ItemId.HasValue)
{
@@ -1706,29 +1702,26 @@ namespace Emby.Server.Implementations.Library
return video;
}
- ///
- /// Sorts the specified sort by.
- ///
- /// The items.
- /// The user.
- /// The sort by.
- /// The sort order.
- /// IEnumerable{BaseItem}.
- public IEnumerable Sort(IEnumerable items, User user, IEnumerable sortBy, SortOrder sortOrder)
+ ///
+ public IEnumerable Sort(IEnumerable items, User? user, IEnumerable sortBy, SortOrder sortOrder)
{
var isFirst = true;
- IOrderedEnumerable orderedItems = null;
+ IOrderedEnumerable? orderedItems = null;
foreach (var orderBy in sortBy.Select(o => GetComparer(o, user)).Where(c => c is not null))
{
if (isFirst)
{
- orderedItems = sortOrder == SortOrder.Descending ? items.OrderByDescending(i => i, orderBy) : items.OrderBy(i => i, orderBy);
+ orderedItems = sortOrder == SortOrder.Descending
+ ? items.OrderByDescending(i => i, orderBy)
+ : items.OrderBy(i => i, orderBy);
}
else
{
- orderedItems = sortOrder == SortOrder.Descending ? orderedItems.ThenByDescending(i => i, orderBy) : orderedItems.ThenBy(i => i, orderBy);
+ orderedItems = sortOrder == SortOrder.Descending
+ ? orderedItems!.ThenByDescending(i => i, orderBy)
+ : orderedItems!.ThenBy(i => i, orderBy); // orderedItems is set during the first iteration
}
isFirst = false;
@@ -1737,11 +1730,12 @@ namespace Emby.Server.Implementations.Library
return orderedItems ?? items;
}
- public IEnumerable Sort(IEnumerable items, User user, IEnumerable<(ItemSortBy OrderBy, SortOrder SortOrder)> orderBy)
+ ///
+ public IEnumerable Sort(IEnumerable items, User? user, IEnumerable<(ItemSortBy OrderBy, SortOrder SortOrder)> orderBy)
{
var isFirst = true;
- IOrderedEnumerable orderedItems = null;
+ IOrderedEnumerable? orderedItems = null;
foreach (var (name, sortOrder) in orderBy)
{
@@ -1753,11 +1747,15 @@ namespace Emby.Server.Implementations.Library
if (isFirst)
{
- orderedItems = sortOrder == SortOrder.Descending ? items.OrderByDescending(i => i, comparer) : items.OrderBy(i => i, comparer);
+ orderedItems = sortOrder == SortOrder.Descending
+ ? items.OrderByDescending(i => i, comparer)
+ : items.OrderBy(i => i, comparer);
}
else
{
- orderedItems = sortOrder == SortOrder.Descending ? orderedItems.ThenByDescending(i => i, comparer) : orderedItems.ThenBy(i => i, comparer);
+ orderedItems = sortOrder == SortOrder.Descending
+ ? orderedItems!.ThenByDescending(i => i, comparer)
+ : orderedItems!.ThenBy(i => i, comparer); // orderedItems is set during the first iteration
}
isFirst = false;
@@ -1772,14 +1770,14 @@ namespace Emby.Server.Implementations.Library
/// The name.
/// The user.
/// IBaseItemComparer.
- private IBaseItemComparer GetComparer(ItemSortBy name, User user)
+ private IBaseItemComparer? GetComparer(ItemSortBy name, User? user)
{
var comparer = Comparers.FirstOrDefault(c => name == c.Type);
// If it requires a user, create a new one, and assign the user
if (comparer is IUserBaseItemComparer)
{
- var userComparer = (IUserBaseItemComparer)Activator.CreateInstance(comparer.GetType());
+ var userComparer = (IUserBaseItemComparer)Activator.CreateInstance(comparer.GetType())!; // only null for Nullable instances
userComparer.User = user;
userComparer.UserManager = _userManager;
@@ -1791,23 +1789,14 @@ namespace Emby.Server.Implementations.Library
return comparer;
}
- ///
- /// Creates the item.
- ///
- /// The item.
- /// The parent item.
- public void CreateItem(BaseItem item, BaseItem parent)
+ ///
+ public void CreateItem(BaseItem item, BaseItem? parent)
{
CreateItems(new[] { item }, parent, CancellationToken.None);
}
- ///
- /// Creates the items.
- ///
- /// The items.
- /// The parent item.
- /// The cancellation token.
- public void CreateItems(IReadOnlyList items, BaseItem parent, CancellationToken cancellationToken)
+ ///
+ public void CreateItems(IReadOnlyList items, BaseItem? parent, CancellationToken cancellationToken)
{
_itemRepository.SaveItems(items, cancellationToken);
@@ -2089,16 +2078,16 @@ namespace Emby.Server.Implementations.Library
public LibraryOptions GetLibraryOptions(BaseItem item)
{
- if (item is not CollectionFolder collectionFolder)
+ if (item is CollectionFolder collectionFolder)
{
- // List.Find is more performant than FirstOrDefault due to enumerator allocation
- collectionFolder = GetCollectionFolders(item)
- .Find(folder => folder is CollectionFolder) as CollectionFolder;
+ return collectionFolder.GetLibraryOptions();
}
- return collectionFolder is null
- ? new LibraryOptions()
- : collectionFolder.GetLibraryOptions();
+ // List.Find is more performant than FirstOrDefault due to enumerator allocation
+ return GetCollectionFolders(item)
+ .Find(folder => folder is CollectionFolder) is CollectionFolder collectionFolder2
+ ? collectionFolder2.GetLibraryOptions()
+ : new LibraryOptions();
}
public CollectionType? GetContentType(BaseItem item)
@@ -2452,7 +2441,7 @@ namespace Emby.Server.Implementations.Library
{
if (parentId.HasValue)
{
- return GetItemById(parentId.Value);
+ return GetItemById(parentId.Value) ?? throw new ArgumentException($"Invalid parent id: {parentId.Value}");
}
if (!userId.IsNullOrEmpty())
@@ -2489,7 +2478,7 @@ namespace Emby.Server.Implementations.Library
var isFolder = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd;
// TODO nullable - what are we trying to do there with empty episodeInfo?
- EpisodeInfo episodeInfo = null;
+ EpisodeInfo? episodeInfo = null;
if (episode.IsFileProtocol)
{
episodeInfo = resolver.Resolve(episode.Path, isFolder, null, null, isAbsoluteNaming);
@@ -2692,7 +2681,7 @@ namespace Emby.Server.Implementations.Library
}
}
- BaseItem GetExtra(FileSystemMetadata file, ExtraType extraType)
+ BaseItem? GetExtra(FileSystemMetadata file, ExtraType extraType)
{
var extra = ResolvePath(_fileSystem.GetFileInfo(file.FullName), directoryService, _extraResolver.GetResolversForExtraType(extraType));
if (extra is not Video && extra is not Audio)
@@ -2719,9 +2708,9 @@ namespace Emby.Server.Implementations.Library
}
}
- public string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem)
+ public string GetPathAfterNetworkSubstitution(string path, BaseItem? ownerItem)
{
- string newPath;
+ string? newPath;
if (ownerItem is not null)
{
var libraryOptions = GetLibraryOptions(ownerItem);
@@ -2795,8 +2784,8 @@ namespace Emby.Server.Implementations.Library
}
})
.Where(i => i is not null)
- .Where(i => query.User is null || i.IsVisible(query.User))
- .ToList();
+ .Where(i => query.User is null || i!.IsVisible(query.User))
+ .ToList()!; // null values are filtered out
}
public List GetPeopleNames(InternalPeopleQuery query)
@@ -2898,7 +2887,7 @@ namespace Emby.Server.Implementations.Library
if (collectionType is not null)
{
- var path = Path.Combine(virtualFolderPath, collectionType.ToString().ToLowerInvariant() + ".collection");
+ var path = Path.Combine(virtualFolderPath, collectionType.ToString()!.ToLowerInvariant() + ".collection"); // Can't be null with legal values?
await File.WriteAllBytesAsync(path, Array.Empty()).ConfigureAwait(false);
}
@@ -2932,7 +2921,7 @@ namespace Emby.Server.Implementations.Library
private async Task SavePeopleMetadataAsync(IEnumerable people, CancellationToken cancellationToken)
{
- List personsToSave = null;
+ List? personsToSave = null;
foreach (var person in people)
{
@@ -3150,7 +3139,7 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentNullException(nameof(path));
}
- List removeList = null;
+ List? removeList = null;
foreach (var contentType in _configurationManager.Configuration.ContentTypes)
{
@@ -3204,7 +3193,7 @@ namespace Emby.Server.Implementations.Library
CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions);
}
- private static bool ItemIsVisible(BaseItem item, User user)
+ private static bool ItemIsVisible(BaseItem? item, User? user)
{
if (item is null)
{
diff --git a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs
index 601aab5b9..725b8f76c 100644
--- a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs
+++ b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs
@@ -64,6 +64,11 @@ namespace Emby.Server.Implementations.Library.Validators
try
{
var item = _libraryManager.GetPerson(person);
+ if (item is null)
+ {
+ _logger.LogWarning("Failed to get person: {Name}", person);
+ continue;
+ }
var options = new MetadataRefreshOptions(new DirectoryService(_fileSystem))
{
@@ -92,7 +97,7 @@ namespace Emby.Server.Implementations.Library.Validators
var deadEntities = _libraryManager.GetItemList(new InternalItemsQuery
{
- IncludeItemTypes = new[] { BaseItemKind.Person },
+ IncludeItemTypes = [BaseItemKind.Person],
IsDeadPerson = true,
IsLocked = false
});
diff --git a/Jellyfin.Api/Controllers/LibraryStructureController.cs b/Jellyfin.Api/Controllers/LibraryStructureController.cs
index c1d01a5c2..f685eeaa0 100644
--- a/Jellyfin.Api/Controllers/LibraryStructureController.cs
+++ b/Jellyfin.Api/Controllers/LibraryStructureController.cs
@@ -75,7 +75,7 @@ public class LibraryStructureController : BaseJellyfinApiController
[HttpPost]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task AddVirtualFolder(
- [FromQuery] string? name,
+ [FromQuery] string name,
[FromQuery] CollectionTypeOptions? collectionType,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] paths,
[FromBody] AddVirtualFolderDto? libraryOptionsDto,
@@ -103,7 +103,7 @@ public class LibraryStructureController : BaseJellyfinApiController
[HttpDelete]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task RemoveVirtualFolder(
- [FromQuery] string? name,
+ [FromQuery] string name,
[FromQuery] bool refreshLibrary = false)
{
await _libraryManager.RemoveVirtualFolder(name, refreshLibrary).ConfigureAwait(false);
@@ -267,18 +267,16 @@ public class LibraryStructureController : BaseJellyfinApiController
/// Whether to refresh the library.
/// A .
/// Media path removed.
- /// The name of the library may not be empty.
+ /// The name of the library and path may not be empty.
[HttpDelete("Paths")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult RemoveMediaPath(
- [FromQuery] string? name,
- [FromQuery] string? path,
+ [FromQuery] string name,
+ [FromQuery] string path,
[FromQuery] bool refreshLibrary = false)
{
- if (string.IsNullOrWhiteSpace(name))
- {
- throw new ArgumentNullException(nameof(name));
- }
+ ArgumentException.ThrowIfNullOrWhiteSpace(name);
+ ArgumentException.ThrowIfNullOrWhiteSpace(path);
_libraryMonitor.Stop();
diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs
index 52e2e1df5..212d678a8 100644
--- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs
+++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs
@@ -24,6 +24,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Session;
using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.Extensions.Logging;
namespace Jellyfin.Api.Helpers;
@@ -398,7 +399,8 @@ public class MediaInfoHelper
if (profile is not null)
{
- var item = _libraryManager.GetItemById(request.ItemId);
+ var item = _libraryManager.GetItemById(request.ItemId)
+ ?? throw new ResourceNotFoundException();
SetDeviceSpecificData(
item,
diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs
index ab4826369..d6d7a56eb 100644
--- a/Jellyfin.Api/Helpers/StreamingHelpers.cs
+++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs
@@ -19,6 +19,7 @@ using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.Net.Http.Headers;
namespace Jellyfin.Api.Helpers;
@@ -108,7 +109,8 @@ public static class StreamingHelpers
?? state.SupportedSubtitleCodecs.FirstOrDefault();
}
- var item = libraryManager.GetItemById(streamingRequest.Id);
+ var item = libraryManager.GetItemById(streamingRequest.Id)
+ ?? throw new ResourceNotFoundException();
state.IsInputVideo = item.MediaType == MediaType.Video;
diff --git a/Jellyfin.Api/Models/LibraryStructureDto/MediaPathDto.cs b/Jellyfin.Api/Models/LibraryStructureDto/MediaPathDto.cs
index 94ffc5238..7a549aada 100644
--- a/Jellyfin.Api/Models/LibraryStructureDto/MediaPathDto.cs
+++ b/Jellyfin.Api/Models/LibraryStructureDto/MediaPathDto.cs
@@ -12,7 +12,7 @@ public class MediaPathDto
/// Gets or sets the name of the library.
///
[Required]
- public string? Name { get; set; }
+ public required string Name { get; set; }
///
/// Gets or sets the path to add.
diff --git a/Jellyfin.Server/Migrations/Routines/RemoveDownloadImagesInAdvance.cs b/Jellyfin.Server/Migrations/Routines/RemoveDownloadImagesInAdvance.cs
index 9137ea234..52fb93d59 100644
--- a/Jellyfin.Server/Migrations/Routines/RemoveDownloadImagesInAdvance.cs
+++ b/Jellyfin.Server/Migrations/Routines/RemoveDownloadImagesInAdvance.cs
@@ -42,7 +42,7 @@ namespace Jellyfin.Server.Migrations.Routines
}
var libraryOptions = virtualFolder.LibraryOptions;
- var collectionFolder = (CollectionFolder)_libraryManager.GetItemById(folderId);
+ var collectionFolder = _libraryManager.GetItemById(folderId) ?? throw new InvalidOperationException("Failed to find CollectionFolder");
// The property no longer exists in LibraryOptions, so we just re-save the options to get old data removed.
collectionFolder.UpdateLibraryOptions(libraryOptions);
_logger.LogInformation("Removed from '{VirtualFolder}'", virtualFolder.Name);
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index f0680f101..37703ceee 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
#pragma warning disable CA1002, CS1591
using System;
@@ -33,17 +31,17 @@ namespace MediaBrowser.Controller.Library
///
/// Occurs when [item added].
///
- event EventHandler ItemAdded;
+ event EventHandler? ItemAdded;
///
/// Occurs when [item updated].
///
- event EventHandler ItemUpdated;
+ event EventHandler? ItemUpdated;
///
/// Occurs when [item removed].
///
- event EventHandler ItemRemoved;
+ event EventHandler? ItemRemoved;
///
/// Gets the root folder.
@@ -60,10 +58,10 @@ namespace MediaBrowser.Controller.Library
/// The parent.
/// An instance of .
/// BaseItem.
- BaseItem ResolvePath(
+ BaseItem? ResolvePath(
FileSystemMetadata fileInfo,
- Folder parent = null,
- IDirectoryService directoryService = null);
+ Folder? parent = null,
+ IDirectoryService? directoryService = null);
///
/// Resolves a set of files into a list of BaseItem.
@@ -86,7 +84,7 @@ namespace MediaBrowser.Controller.Library
///
/// The name of the person.
/// Task{Person}.
- Person GetPerson(string name);
+ Person? GetPerson(string name);
///
/// Finds the by path.
@@ -94,7 +92,7 @@ namespace MediaBrowser.Controller.Library
/// The path.
/// true is the path is a directory; otherwise false.
/// BaseItem.
- BaseItem FindByPath(string path, bool? isFolder);
+ BaseItem? FindByPath(string path, bool? isFolder);
///
/// Gets the artist.
@@ -166,7 +164,8 @@ namespace MediaBrowser.Controller.Library
///
/// The id.
/// BaseItem.
- BaseItem GetItemById(Guid id);
+ /// is null.
+ BaseItem? GetItemById(Guid id);
///
/// Gets the item by id, as T.
@@ -174,7 +173,7 @@ namespace MediaBrowser.Controller.Library
/// The item id.
/// The type of item.
/// The item.
- T GetItemById(Guid id)
+ T? GetItemById(Guid id)
where T : BaseItem;
///
@@ -184,7 +183,7 @@ namespace MediaBrowser.Controller.Library
/// The user id to validate against.
/// The type of item.
/// The item if found.
- public T GetItemById(Guid id, Guid userId)
+ public T? GetItemById(Guid id, Guid userId)
where T : BaseItem;
///
@@ -194,7 +193,7 @@ namespace MediaBrowser.Controller.Library
/// The user to validate against.
/// The type of item.
/// The item if found.
- public T GetItemById(Guid id, User user)
+ public T? GetItemById(Guid id, User? user)
where T : BaseItem;
///
@@ -228,9 +227,9 @@ namespace MediaBrowser.Controller.Library
/// The sort by.
/// The sort order.
/// IEnumerable{BaseItem}.
- IEnumerable Sort(IEnumerable items, User user, IEnumerable sortBy, SortOrder sortOrder);
+ IEnumerable Sort(IEnumerable items, User? user, IEnumerable sortBy, SortOrder sortOrder);
- IEnumerable Sort(IEnumerable items, User user, IEnumerable<(ItemSortBy OrderBy, SortOrder SortOrder)> orderBy);
+ IEnumerable Sort(IEnumerable items, User? user, IEnumerable<(ItemSortBy OrderBy, SortOrder SortOrder)> orderBy);
///
/// Gets the user root folder.
@@ -243,7 +242,7 @@ namespace MediaBrowser.Controller.Library
///
/// Item to create.
/// Parent of new item.
- void CreateItem(BaseItem item, BaseItem parent);
+ void CreateItem(BaseItem item, BaseItem? parent);
///
/// Creates the items.
@@ -251,7 +250,7 @@ namespace MediaBrowser.Controller.Library
/// Items to create.
/// Parent of new items.
/// CancellationToken to use for operation.
- void CreateItems(IReadOnlyList items, BaseItem parent, CancellationToken cancellationToken);
+ void CreateItems(IReadOnlyList items, BaseItem? parent, CancellationToken cancellationToken);
///
/// Updates the item.
@@ -529,7 +528,7 @@ namespace MediaBrowser.Controller.Library
/// QueryResult<BaseItem>.
QueryResult QueryItems(InternalItemsQuery query);
- string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem = null);
+ string GetPathAfterNetworkSubstitution(string path, BaseItem? ownerItem = null);
///
/// Converts the image to local.
diff --git a/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs b/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs
index a07b3e898..733d40ba1 100644
--- a/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs
+++ b/MediaBrowser.Controller/Resolvers/IResolverIgnoreRule.cs
@@ -14,6 +14,6 @@ namespace MediaBrowser.Controller.Resolvers
/// The file information.
/// The parent BaseItem.
/// True if the file should be ignored.
- bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem parent);
+ bool ShouldIgnore(FileSystemMetadata fileInfo, BaseItem? parent);
}
}
diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
index 1399ac307..b25cfc83f 100644
--- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
+++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
@@ -947,7 +947,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
if (saveImagePath)
{
var personEntity = libraryManager.GetPerson(person.Name);
- var image = personEntity.GetImageInfo(ImageType.Primary, 0);
+ var image = personEntity?.GetImageInfo(ImageType.Primary, 0);
if (image is not null)
{