aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Naming/TV/SeasonPathParser.cs2
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs4
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs5
-rw-r--r--Emby.Server.Implementations/Localization/Core/bg-BG.json22
-rw-r--r--Jellyfin.Api/Attributes/AcceptsFileAttribute.cs28
-rw-r--r--Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs18
-rw-r--r--Jellyfin.Api/Controllers/ArtistsController.cs18
-rw-r--r--Jellyfin.Api/Controllers/CollectionController.cs1
-rw-r--r--Jellyfin.Api/Controllers/DashboardController.cs6
-rw-r--r--Jellyfin.Api/Controllers/DynamicHlsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/FilterController.cs37
-rw-r--r--Jellyfin.Api/Controllers/GenresController.cs9
-rw-r--r--Jellyfin.Api/Controllers/HlsSegmentController.cs2
-rw-r--r--Jellyfin.Api/Controllers/ImageController.cs4
-rw-r--r--Jellyfin.Api/Controllers/InstantMixController.cs1
-rw-r--r--Jellyfin.Api/Controllers/ItemLookupController.cs2
-rw-r--r--Jellyfin.Api/Controllers/ItemsController.cs27
-rw-r--r--Jellyfin.Api/Controllers/LibraryController.cs1
-rw-r--r--Jellyfin.Api/Controllers/MusicGenresController.cs9
-rw-r--r--Jellyfin.Api/Controllers/PackageController.cs1
-rw-r--r--Jellyfin.Api/Controllers/PersonsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/PlaylistsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/PluginsController.cs6
-rw-r--r--Jellyfin.Api/Controllers/SearchController.cs9
-rw-r--r--Jellyfin.Api/Controllers/StudiosController.cs9
-rw-r--r--Jellyfin.Api/Controllers/SuggestionsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/SyncPlayController.cs1
-rw-r--r--Jellyfin.Api/Controllers/SystemController.cs1
-rw-r--r--Jellyfin.Api/Controllers/TimeSyncController.cs1
-rw-r--r--Jellyfin.Api/Controllers/TrailersController.cs4
-rw-r--r--Jellyfin.Api/Controllers/TvShowsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/UserLibraryController.cs5
-rw-r--r--Jellyfin.Api/Controllers/UserViewsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/VideoHlsController.cs1
-rw-r--r--Jellyfin.Api/Controllers/YearsController.cs15
-rw-r--r--Jellyfin.Api/Helpers/RequestHelpers.cs16
-rw-r--r--Jellyfin.Api/Jellyfin.Api.csproj6
-rw-r--r--Jellyfin.Data/Enums/BaseItemKind.cs190
-rw-r--r--Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs1
-rw-r--r--Jellyfin.Server/Filters/FileRequestFilter.cs43
-rw-r--r--Jellyfin.sln (renamed from MediaBrowser.sln)0
-rw-r--r--MediaBrowser.Common/Json/JsonDefaults.cs1
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs5
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs9
-rw-r--r--MediaBrowser.Model/Dto/BaseItemDto.cs3
-rw-r--r--tests/Jellyfin.Api.Tests/Helpers/RequestHelpersTests.cs34
46 files changed, 435 insertions, 128 deletions
diff --git a/Emby.Naming/TV/SeasonPathParser.cs b/Emby.Naming/TV/SeasonPathParser.cs
index d11c7c99e..6236f86c4 100644
--- a/Emby.Naming/TV/SeasonPathParser.cs
+++ b/Emby.Naming/TV/SeasonPathParser.cs
@@ -60,7 +60,7 @@ namespace Emby.Naming.TV
bool supportSpecialAliases,
bool supportNumericSeasonFolders)
{
- var filename = Path.GetFileName(path) ?? string.Empty;
+ string filename = Path.GetFileName(path);
if (supportSpecialAliases)
{
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index e3ab0d6ea..54b18a8c8 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -249,7 +249,7 @@ namespace Emby.Server.Implementations.Dto
var activeRecording = liveTvManager.GetActiveRecordingInfo(item.Path);
if (activeRecording != null)
{
- dto.Type = "Recording";
+ dto.Type = BaseItemKind.Recording;
dto.CanDownload = false;
dto.RunTimeTicks = null;
@@ -904,7 +904,7 @@ namespace Emby.Server.Implementations.Dto
}
}
- dto.Type = item.GetClientTypeName();
+ dto.Type = item.GetBaseItemKind();
if ((item.CommunityRating ?? 0) > 0)
{
dto.CommunityRating = item.CommunityRating;
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
index e9e688fa6..60f82806f 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
@@ -79,11 +79,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
return new MusicArtist();
}
- if (_config.Configuration.EnableSimpleArtistDetection)
- {
- return null;
- }
-
// Avoid mis-identifying top folders
if (args.Parent.IsRoot)
{
diff --git a/Emby.Server.Implementations/Localization/Core/bg-BG.json b/Emby.Server.Implementations/Localization/Core/bg-BG.json
index 7ff30df71..9db3b50d9 100644
--- a/Emby.Server.Implementations/Localization/Core/bg-BG.json
+++ b/Emby.Server.Implementations/Localization/Core/bg-BG.json
@@ -55,26 +55,26 @@
"NotificationOptionPluginInstalled": "Приставката е инсталирана",
"NotificationOptionPluginUninstalled": "Приставката е деинсталирана",
"NotificationOptionPluginUpdateInstalled": "Обновлението на приставката е инсталирано",
- "NotificationOptionServerRestartRequired": "Нужно е повторно пускане на сървъра",
+ "NotificationOptionServerRestartRequired": "Сървърът трябва да се рестартира",
"NotificationOptionTaskFailed": "Грешка в планирана задача",
- "NotificationOptionUserLockedOut": "Потребителя е заключен",
+ "NotificationOptionUserLockedOut": "Потребителят е заключен",
"NotificationOptionVideoPlayback": "Възпроизвеждането на видео започна",
"NotificationOptionVideoPlaybackStopped": "Възпроизвеждането на видео е спряно",
"Photos": "Снимки",
"Playlists": "Списъци",
"Plugin": "Приставка",
- "PluginInstalledWithName": "{0} е инсталирано",
- "PluginUninstalledWithName": "{0} е деинсталирано",
- "PluginUpdatedWithName": "{0} е обновено",
+ "PluginInstalledWithName": "{0} е инсталиранa",
+ "PluginUninstalledWithName": "{0} е деинсталиранa",
+ "PluginUpdatedWithName": "{0} е обновенa",
"ProviderValue": "Доставчик: {0}",
"ScheduledTaskFailedWithName": "{0} се провали",
"ScheduledTaskStartedWithName": "{0} започна",
- "ServerNameNeedsToBeRestarted": "{0} е нужно да се рестартира",
+ "ServerNameNeedsToBeRestarted": "{0} трябва да се рестартира",
"Shows": "Сериали",
"Songs": "Песни",
"StartupEmbyServerIsLoading": "Сървърът зарежда. Моля, опитайте отново след малко.",
"SubtitleDownloadFailureForItem": "Неуспешно изтегляне на субтитри за {0}",
- "SubtitleDownloadFailureFromForItem": "Поднадписите за {1} от {0} не можаха да се изтеглят",
+ "SubtitleDownloadFailureFromForItem": "Субтитрите за {1} от {0} не можаха да бъдат изтеглени",
"Sync": "Синхронизиране",
"System": "Система",
"TvShows": "Телевизионни сериали",
@@ -92,12 +92,12 @@
"ValueHasBeenAddedToLibrary": "{0} беше добавен във Вашата библиотека",
"ValueSpecialEpisodeName": "Специални - {0}",
"VersionNumber": "Версия {0}",
- "TaskDownloadMissingSubtitlesDescription": "Търси Интернет за липсващи поднадписи, на база конфигурацията за мета-данни.",
- "TaskDownloadMissingSubtitles": "Изтегляне на липсващи поднадписи",
+ "TaskDownloadMissingSubtitlesDescription": "Търси Интернет за липсващи субтитри, на база конфигурацията за мета-данни.",
+ "TaskDownloadMissingSubtitles": "Изтегляне на липсващи субтитри",
"TaskRefreshChannelsDescription": "Обновява информацията за интернет канала.",
"TaskRefreshChannels": "Обновяване на Канали",
- "TaskCleanTranscodeDescription": "Изтрива прекодирани файлове по-стари от един ден.",
- "TaskCleanTranscode": "Изчиства директорията за прекодиране",
+ "TaskCleanTranscodeDescription": "Изтрива транскодирани файлове по-стари от един ден.",
+ "TaskCleanTranscode": "Изчиства директорията за транскодиране",
"TaskUpdatePluginsDescription": "Изтегля и инсталира актуализации за добавките, които са настроени за автоматична актуализация.",
"TaskUpdatePlugins": "Актуализира добавките",
"TaskRefreshPeopleDescription": "Актуализира мета-данните за артистите и режисьорите за Вашата медийна библиотека.",
diff --git a/Jellyfin.Api/Attributes/AcceptsFileAttribute.cs b/Jellyfin.Api/Attributes/AcceptsFileAttribute.cs
new file mode 100644
index 000000000..49b6689cd
--- /dev/null
+++ b/Jellyfin.Api/Attributes/AcceptsFileAttribute.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Jellyfin.Api.Attributes
+{
+ /// <summary>
+ /// Internal produces image attribute.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Method)]
+ public class AcceptsFileAttribute : Attribute
+ {
+ private readonly string[] _contentTypes;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AcceptsFileAttribute"/> class.
+ /// </summary>
+ /// <param name="contentTypes">Content types this endpoint produces.</param>
+ public AcceptsFileAttribute(params string[] contentTypes)
+ {
+ _contentTypes = contentTypes;
+ }
+
+ /// <summary>
+ /// Gets the configured content types.
+ /// </summary>
+ /// <returns>the configured content types.</returns>
+ public string[] GetContentTypes() => _contentTypes;
+ }
+}
diff --git a/Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs b/Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs
new file mode 100644
index 000000000..001f27409
--- /dev/null
+++ b/Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs
@@ -0,0 +1,18 @@
+namespace Jellyfin.Api.Attributes
+{
+ /// <summary>
+ /// Produces file attribute of "image/*".
+ /// </summary>
+ public class AcceptsImageFileAttribute : AcceptsFileAttribute
+ {
+ private const string ContentType = "image/*";
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AcceptsImageFileAttribute"/> class.
+ /// </summary>
+ public AcceptsImageFileAttribute()
+ : base(ContentType)
+ {
+ }
+ }
+}
diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs
index fed7ed3e5..4b2e5e7ea 100644
--- a/Jellyfin.Api/Controllers/ArtistsController.cs
+++ b/Jellyfin.Api/Controllers/ArtistsController.cs
@@ -3,8 +3,10 @@ using System.ComponentModel.DataAnnotations;
using System.Linq;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
+using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
@@ -88,8 +90,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? searchTerm,
[FromQuery] Guid? parentId,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
[FromQuery] bool? isFavorite,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes,
@@ -127,8 +129,8 @@ namespace Jellyfin.Api.Controllers
var query = new InternalItemsQuery(user)
{
- ExcludeItemTypes = excludeItemTypes,
- IncludeItemTypes = includeItemTypes,
+ ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes),
+ IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes),
MediaTypes = mediaTypes,
StartIndex = startIndex,
Limit = limit,
@@ -287,8 +289,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? searchTerm,
[FromQuery] Guid? parentId,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
[FromQuery] bool? isFavorite,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes,
@@ -326,8 +328,8 @@ namespace Jellyfin.Api.Controllers
var query = new InternalItemsQuery(user)
{
- ExcludeItemTypes = excludeItemTypes,
- IncludeItemTypes = includeItemTypes,
+ ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes),
+ IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes),
MediaTypes = mediaTypes,
StartIndex = startIndex,
Limit = limit,
diff --git a/Jellyfin.Api/Controllers/CollectionController.cs b/Jellyfin.Api/Controllers/CollectionController.cs
index 2a7b2b5c6..852d1e9cb 100644
--- a/Jellyfin.Api/Controllers/CollectionController.cs
+++ b/Jellyfin.Api/Controllers/CollectionController.cs
@@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
-using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Dto;
diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs
index ff7895373..b2baa9cea 100644
--- a/Jellyfin.Api/Controllers/DashboardController.cs
+++ b/Jellyfin.Api/Controllers/DashboardController.cs
@@ -7,17 +7,11 @@ using Jellyfin.Api.Attributes;
using Jellyfin.Api.Models;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Controller;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Extensions;
-using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Plugins;
using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
-using Microsoft.Net.Http.Headers;
namespace Jellyfin.Api.Controllers
{
diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index 6e85737d2..e375645cf 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -15,7 +15,6 @@ using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.PlaybackDtos;
using Jellyfin.Api.Models.StreamingDtos;
using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna;
diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs
index 9220b988f..223b2a2b6 100644
--- a/Jellyfin.Api/Controllers/FilterController.cs
+++ b/Jellyfin.Api/Controllers/FilterController.cs
@@ -1,13 +1,12 @@
using System;
using System.Linq;
using Jellyfin.Api.Constants;
+using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
+using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using Microsoft.AspNetCore.Authorization;
@@ -51,7 +50,7 @@ namespace Jellyfin.Api.Controllers
public ActionResult<QueryFiltersLegacy> GetQueryFiltersLegacy(
[FromQuery] Guid? userId,
[FromQuery] Guid? parentId,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes)
{
var user = userId.HasValue && !userId.Equals(Guid.Empty)
@@ -60,10 +59,10 @@ namespace Jellyfin.Api.Controllers
BaseItem? item = null;
if (includeItemTypes.Length != 1
- || !(string.Equals(includeItemTypes[0], nameof(BoxSet), StringComparison.OrdinalIgnoreCase)
- || string.Equals(includeItemTypes[0], nameof(Playlist), StringComparison.OrdinalIgnoreCase)
- || string.Equals(includeItemTypes[0], nameof(Trailer), StringComparison.OrdinalIgnoreCase)
- || string.Equals(includeItemTypes[0], "Program", StringComparison.OrdinalIgnoreCase)))
+ || !(includeItemTypes[0] == BaseItemKind.BoxSet
+ || includeItemTypes[0] == BaseItemKind.Playlist
+ || includeItemTypes[0] == BaseItemKind.Trailer
+ || includeItemTypes[0] == BaseItemKind.Program))
{
item = _libraryManager.GetParentItem(parentId, user?.Id);
}
@@ -72,7 +71,7 @@ namespace Jellyfin.Api.Controllers
{
User = user,
MediaTypes = mediaTypes,
- IncludeItemTypes = includeItemTypes,
+ IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes),
Recursive = true,
EnableTotalRecordCount = false,
DtoOptions = new DtoOptions
@@ -137,7 +136,7 @@ namespace Jellyfin.Api.Controllers
public ActionResult<QueryFilters> GetQueryFilters(
[FromQuery] Guid? userId,
[FromQuery] Guid? parentId,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery] bool? isAiring,
[FromQuery] bool? isMovie,
[FromQuery] bool? isSports,
@@ -152,10 +151,10 @@ namespace Jellyfin.Api.Controllers
BaseItem? parentItem = null;
if (includeItemTypes.Length == 1
- && (string.Equals(includeItemTypes[0], nameof(BoxSet), StringComparison.OrdinalIgnoreCase)
- || string.Equals(includeItemTypes[0], nameof(Playlist), StringComparison.OrdinalIgnoreCase)
- || string.Equals(includeItemTypes[0], nameof(Trailer), StringComparison.OrdinalIgnoreCase)
- || string.Equals(includeItemTypes[0], "Program", StringComparison.OrdinalIgnoreCase)))
+ && (includeItemTypes[0] == BaseItemKind.BoxSet
+ || includeItemTypes[0] == BaseItemKind.Playlist
+ || includeItemTypes[0] == BaseItemKind.Trailer
+ || includeItemTypes[0] == BaseItemKind.Program))
{
parentItem = null;
}
@@ -167,7 +166,7 @@ namespace Jellyfin.Api.Controllers
var filters = new QueryFilters();
var genreQuery = new InternalItemsQuery(user)
{
- IncludeItemTypes = includeItemTypes,
+ IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes),
DtoOptions = new DtoOptions
{
Fields = Array.Empty<ItemFields>(),
@@ -192,10 +191,10 @@ namespace Jellyfin.Api.Controllers
}
if (includeItemTypes.Length == 1
- && (string.Equals(includeItemTypes[0], nameof(MusicAlbum), StringComparison.OrdinalIgnoreCase)
- || string.Equals(includeItemTypes[0], nameof(MusicVideo), StringComparison.OrdinalIgnoreCase)
- || string.Equals(includeItemTypes[0], nameof(MusicArtist), StringComparison.OrdinalIgnoreCase)
- || string.Equals(includeItemTypes[0], nameof(Audio), StringComparison.OrdinalIgnoreCase)))
+ && (includeItemTypes[0] == BaseItemKind.MusicAlbum
+ || includeItemTypes[0] == BaseItemKind.MusicVideo
+ || includeItemTypes[0] == BaseItemKind.MusicArtist
+ || includeItemTypes[0] == BaseItemKind.Audio))
{
filters.Genres = _libraryManager.GetMusicGenres(genreQuery).Items.Select(i => new NameGuidPair
{
diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs
index b6755ed5e..7bcf4674c 100644
--- a/Jellyfin.Api/Controllers/GenresController.cs
+++ b/Jellyfin.Api/Controllers/GenresController.cs
@@ -6,6 +6,7 @@ using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
@@ -74,8 +75,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? searchTerm,
[FromQuery] Guid? parentId,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery] bool? isFavorite,
[FromQuery] int? imageTypeLimit,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes,
@@ -96,8 +97,8 @@ namespace Jellyfin.Api.Controllers
var query = new InternalItemsQuery(user)
{
- ExcludeItemTypes = excludeItemTypes,
- IncludeItemTypes = includeItemTypes,
+ ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes),
+ IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes),
StartIndex = startIndex,
Limit = limit,
IsFavorite = isFavorite,
diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs
index f51987732..25abe73ed 100644
--- a/Jellyfin.Api/Controllers/HlsSegmentController.cs
+++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs
@@ -2,13 +2,11 @@ using System;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.IO;
-using System.Linq;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers;
using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.IO;
diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs
index c606d327c..dc3634970 100644
--- a/Jellyfin.Api/Controllers/ImageController.cs
+++ b/Jellyfin.Api/Controllers/ImageController.cs
@@ -87,6 +87,7 @@ namespace Jellyfin.Api.Controllers
/// <returns>A <see cref="NoContentResult"/>.</returns>
[HttpPost("Users/{userId}/Images/{imageType}")]
[Authorize(Policy = Policies.DefaultAuthorization)]
+ [AcceptsImageFile]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")]
@@ -133,6 +134,7 @@ namespace Jellyfin.Api.Controllers
/// <returns>A <see cref="NoContentResult"/>.</returns>
[HttpPost("Users/{userId}/Images/{imageType}/{index}")]
[Authorize(Policy = Policies.DefaultAuthorization)]
+ [AcceptsImageFile]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")]
@@ -312,6 +314,7 @@ namespace Jellyfin.Api.Controllers
/// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if item not found.</returns>
[HttpPost("Items/{itemId}/Images/{imageType}")]
[Authorize(Policy = Policies.RequiresElevation)]
+ [AcceptsImageFile]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
@@ -346,6 +349,7 @@ namespace Jellyfin.Api.Controllers
/// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if item not found.</returns>
[HttpPost("Items/{itemId}/Images/{imageType}/{imageIndex}")]
[Authorize(Policy = Policies.RequiresElevation)]
+ [AcceptsImageFile]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")]
diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs
index 244625752..f061755c3 100644
--- a/Jellyfin.Api/Controllers/InstantMixController.cs
+++ b/Jellyfin.Api/Controllers/InstantMixController.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
-using System.Linq;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders;
diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs
index 6c38f77ce..dfc68ffce 100644
--- a/Jellyfin.Api/Controllers/ItemLookupController.cs
+++ b/Jellyfin.Api/Controllers/ItemLookupController.cs
@@ -2,8 +2,6 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
-using System.Linq;
-using System.Net.Mime;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index 7d7747495..2c9760f6d 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -1,6 +1,5 @@
using System;
using System.ComponentModel.DataAnnotations;
-using System.Globalization;
using System.Linq;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
@@ -178,8 +177,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder,
[FromQuery] Guid? parentId,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
[FromQuery] bool? isFavorite,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes,
@@ -233,8 +232,8 @@ namespace Jellyfin.Api.Controllers
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
if (includeItemTypes.Length == 1
- && (includeItemTypes[0].Equals("Playlist", StringComparison.OrdinalIgnoreCase)
- || includeItemTypes[0].Equals("BoxSet", StringComparison.OrdinalIgnoreCase)))
+ && (includeItemTypes[0] == BaseItemKind.Playlist
+ || includeItemTypes[0] == BaseItemKind.BoxSet))
{
parentId = null;
}
@@ -251,7 +250,7 @@ namespace Jellyfin.Api.Controllers
&& string.Equals(hasCollectionType.CollectionType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
{
recursive = true;
- includeItemTypes = new[] { "Playlist" };
+ includeItemTypes = new[] { BaseItemKind.Playlist };
}
var enabledChannels = user!.GetPreferenceValues<Guid>(PreferenceKind.EnabledChannels);
@@ -286,8 +285,8 @@ namespace Jellyfin.Api.Controllers
{
IsPlayed = isPlayed,
MediaTypes = mediaTypes,
- IncludeItemTypes = includeItemTypes,
- ExcludeItemTypes = excludeItemTypes,
+ IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes),
+ ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes),
Recursive = recursive ?? false,
OrderBy = RequestHelpers.GetOrderBy(sortBy, sortOrder),
IsFavorite = isFavorite,
@@ -611,8 +610,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder,
[FromQuery] Guid? parentId,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
[FromQuery] bool? isFavorite,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes,
@@ -773,8 +772,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableUserData,
[FromQuery] int? imageTypeLimit,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery] bool enableTotalRecordCount = true,
[FromQuery] bool? enableImages = true)
{
@@ -810,8 +809,8 @@ namespace Jellyfin.Api.Controllers
CollapseBoxSetItems = false,
EnableTotalRecordCount = enableTotalRecordCount,
AncestorIds = ancestorIds,
- IncludeItemTypes = includeItemTypes,
- ExcludeItemTypes = excludeItemTypes,
+ IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes),
+ ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes),
SearchTerm = searchTerm
});
diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs
index 28d359ac3..db4aa9668 100644
--- a/Jellyfin.Api/Controllers/LibraryController.cs
+++ b/Jellyfin.Api/Controllers/LibraryController.cs
@@ -11,7 +11,6 @@ using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
-using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Api.Models.LibraryDtos;
using Jellyfin.Data.Entities;
diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs
index 2608a9cd0..7f7058b5e 100644
--- a/Jellyfin.Api/Controllers/MusicGenresController.cs
+++ b/Jellyfin.Api/Controllers/MusicGenresController.cs
@@ -6,6 +6,7 @@ using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -74,8 +75,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? searchTerm,
[FromQuery] Guid? parentId,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery] bool? isFavorite,
[FromQuery] int? imageTypeLimit,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes,
@@ -96,8 +97,8 @@ namespace Jellyfin.Api.Controllers
var query = new InternalItemsQuery(user)
{
- ExcludeItemTypes = excludeItemTypes,
- IncludeItemTypes = includeItemTypes,
+ ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes),
+ IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes),
StartIndex = startIndex,
Limit = limit,
IsFavorite = isFavorite,
diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs
index c589f54ac..5dd49ef2f 100644
--- a/Jellyfin.Api/Controllers/PackageController.cs
+++ b/Jellyfin.Api/Controllers/PackageController.cs
@@ -4,7 +4,6 @@ using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Jellyfin.Api.Constants;
-using MediaBrowser.Common.Json;
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.Updates;
diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs
index 17e631197..70a94e27c 100644
--- a/Jellyfin.Api/Controllers/PersonsController.cs
+++ b/Jellyfin.Api/Controllers/PersonsController.cs
@@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations;
using System.Linq;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
-using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Dto;
diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs
index a55e4ad2f..1667d6ede 100644
--- a/Jellyfin.Api/Controllers/PlaylistsController.cs
+++ b/Jellyfin.Api/Controllers/PlaylistsController.cs
@@ -6,7 +6,6 @@ using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
-using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Api.Models.PlaylistDtos;
using MediaBrowser.Controller.Dto;
diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs
index b73611c97..a5aa9bfca 100644
--- a/Jellyfin.Api/Controllers/PluginsController.cs
+++ b/Jellyfin.Api/Controllers/PluginsController.cs
@@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
-using System.Globalization;
using System.IO;
using System.Linq;
-using System.Net.Mime;
using System.Text.Json;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
@@ -300,9 +298,7 @@ namespace Jellyfin.Api.Controllers
}
var imagePath = Path.Combine(plugin.Path, plugin.Manifest.ImagePath ?? string.Empty);
- if (((ServerConfiguration)_config.CommonConfiguration).DisablePluginImages
- || plugin.Manifest.ImagePath == null
- || !System.IO.File.Exists(imagePath))
+ if (plugin.Manifest.ImagePath == null || !System.IO.File.Exists(imagePath))
{
return NotFound();
}
diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs
index 08255ff8f..6c22050a7 100644
--- a/Jellyfin.Api/Controllers/SearchController.cs
+++ b/Jellyfin.Api/Controllers/SearchController.cs
@@ -6,6 +6,7 @@ using System.Linq;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
+using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
@@ -83,8 +84,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? limit,
[FromQuery] Guid? userId,
[FromQuery, Required] string searchTerm,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes,
[FromQuery] Guid? parentId,
[FromQuery] bool? isMovie,
@@ -109,8 +110,8 @@ namespace Jellyfin.Api.Controllers
IncludeStudios = includeStudios,
StartIndex = startIndex,
UserId = userId ?? Guid.Empty,
- IncludeItemTypes = includeItemTypes,
- ExcludeItemTypes = excludeItemTypes,
+ IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes),
+ ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes),
MediaTypes = mediaTypes,
ParentId = parentId,
diff --git a/Jellyfin.Api/Controllers/StudiosController.cs b/Jellyfin.Api/Controllers/StudiosController.cs
index bb54c59f6..da8f8b199 100644
--- a/Jellyfin.Api/Controllers/StudiosController.cs
+++ b/Jellyfin.Api/Controllers/StudiosController.cs
@@ -5,6 +5,7 @@ using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Entities;
+using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
@@ -73,8 +74,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? searchTerm,
[FromQuery] Guid? parentId,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery] bool? isFavorite,
[FromQuery] bool? enableUserData,
[FromQuery] int? imageTypeLimit,
@@ -96,8 +97,8 @@ namespace Jellyfin.Api.Controllers
var query = new InternalItemsQuery(user)
{
- ExcludeItemTypes = excludeItemTypes,
- IncludeItemTypes = includeItemTypes,
+ ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes),
+ IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes),
StartIndex = startIndex,
Limit = limit,
IsFavorite = isFavorite,
diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs
index 9f1dec712..a55f13e66 100644
--- a/Jellyfin.Api/Controllers/SuggestionsController.cs
+++ b/Jellyfin.Api/Controllers/SuggestionsController.cs
@@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations;
using System.Linq;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
-using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
diff --git a/Jellyfin.Api/Controllers/SyncPlayController.cs b/Jellyfin.Api/Controllers/SyncPlayController.cs
index 82cbe58df..f878f2329 100644
--- a/Jellyfin.Api/Controllers/SyncPlayController.cs
+++ b/Jellyfin.Api/Controllers/SyncPlayController.cs
@@ -1,4 +1,3 @@
-using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading;
diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs
index e67a27ae3..bbbe5fb8d 100644
--- a/Jellyfin.Api/Controllers/SystemController.cs
+++ b/Jellyfin.Api/Controllers/SystemController.cs
@@ -5,7 +5,6 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mime;
-using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants;
diff --git a/Jellyfin.Api/Controllers/TimeSyncController.cs b/Jellyfin.Api/Controllers/TimeSyncController.cs
index c730ac12b..7df51c7af 100644
--- a/Jellyfin.Api/Controllers/TimeSyncController.cs
+++ b/Jellyfin.Api/Controllers/TimeSyncController.cs
@@ -1,5 +1,4 @@
using System;
-using System.Globalization;
using MediaBrowser.Model.SyncPlay;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
diff --git a/Jellyfin.Api/Controllers/TrailersController.cs b/Jellyfin.Api/Controllers/TrailersController.cs
index 242b8f068..dd3836551 100644
--- a/Jellyfin.Api/Controllers/TrailersController.cs
+++ b/Jellyfin.Api/Controllers/TrailersController.cs
@@ -148,7 +148,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder,
[FromQuery] Guid? parentId,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
[FromQuery] bool? isFavorite,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes,
@@ -194,7 +194,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true,
[FromQuery] bool? enableImages = true)
{
- var includeItemTypes = new[] { "Trailer" };
+ var includeItemTypes = new[] { BaseItemKind.Trailer };
return _itemsController
.GetItems(
diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs
index 223f58859..e1c67f830 100644
--- a/Jellyfin.Api/Controllers/TvShowsController.cs
+++ b/Jellyfin.Api/Controllers/TvShowsController.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
-using System.Globalization;
using System.Linq;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs
index 0e65591cc..1d70406ac 100644
--- a/Jellyfin.Api/Controllers/UserLibraryController.cs
+++ b/Jellyfin.Api/Controllers/UserLibraryController.cs
@@ -8,6 +8,7 @@ using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
+using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
@@ -269,7 +270,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid userId,
[FromQuery] Guid? parentId,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery] bool? isPlayed,
[FromQuery] bool? enableImages,
[FromQuery] int? imageTypeLimit,
@@ -296,7 +297,7 @@ namespace Jellyfin.Api.Controllers
new LatestItemsQuery
{
GroupItems = groupItems,
- IncludeItemTypes = includeItemTypes,
+ IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes),
IsPlayed = isPlayed,
Limit = limit,
ParentId = parentId ?? Guid.Empty,
diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs
index e1483ce9d..7bc5ecdf1 100644
--- a/Jellyfin.Api/Controllers/UserViewsController.cs
+++ b/Jellyfin.Api/Controllers/UserViewsController.cs
@@ -4,7 +4,6 @@ using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using Jellyfin.Api.Extensions;
-using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Api.Models.UserViewDtos;
using MediaBrowser.Controller.Dto;
diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs
index 7e743ee0c..ba51aa43e 100644
--- a/Jellyfin.Api/Controllers/VideoHlsController.cs
+++ b/Jellyfin.Api/Controllers/VideoHlsController.cs
@@ -12,7 +12,6 @@ using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.PlaybackDtos;
using Jellyfin.Api.Models.StreamingDtos;
using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna;
diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs
index 7c27752f7..d6dc6650c 100644
--- a/Jellyfin.Api/Controllers/YearsController.cs
+++ b/Jellyfin.Api/Controllers/YearsController.cs
@@ -74,8 +74,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder,
[FromQuery] Guid? parentId,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
[FromQuery] bool? enableUserData,
@@ -101,8 +101,8 @@ namespace Jellyfin.Api.Controllers
var query = new InternalItemsQuery(user)
{
- ExcludeItemTypes = excludeItemTypes,
- IncludeItemTypes = includeItemTypes,
+ ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes),
+ IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes),
MediaTypes = mediaTypes,
DtoOptions = dtoOptions
};
@@ -193,16 +193,17 @@ namespace Jellyfin.Api.Controllers
return _dtoService.GetBaseItemDto(item, dtoOptions);
}
- private bool FilterItem(BaseItem f, IReadOnlyCollection<string> excludeItemTypes, IReadOnlyCollection<string> includeItemTypes, IReadOnlyCollection<string> mediaTypes)
+ private bool FilterItem(BaseItem f, IReadOnlyCollection<BaseItemKind> excludeItemTypes, IReadOnlyCollection<BaseItemKind> includeItemTypes, IReadOnlyCollection<string> mediaTypes)
{
+ var baseItemKind = f.GetBaseItemKind();
// Exclude item types
- if (excludeItemTypes.Count > 0 && excludeItemTypes.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase))
+ if (excludeItemTypes.Count > 0 && excludeItemTypes.Contains(baseItemKind))
{
return false;
}
// Include item types
- if (includeItemTypes.Count > 0 && !includeItemTypes.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase))
+ if (includeItemTypes.Count > 0 && !includeItemTypes.Contains(baseItemKind))
{
return false;
}
diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs
index db0ccc657..94856e03e 100644
--- a/Jellyfin.Api/Helpers/RequestHelpers.cs
+++ b/Jellyfin.Api/Helpers/RequestHelpers.cs
@@ -129,5 +129,21 @@ namespace Jellyfin.Api.Helpers
TotalRecordCount = result.TotalRecordCount
};
}
+
+ internal static string[] GetItemTypeStrings(IReadOnlyList<BaseItemKind> itemKinds)
+ {
+ if (itemKinds.Count == 0)
+ {
+ return Array.Empty<string>();
+ }
+
+ var itemTypes = new string[itemKinds.Count];
+ for (var i = 0; i < itemKinds.Count; i++)
+ {
+ itemTypes[i] = itemKinds[i].ToString();
+ }
+
+ return itemTypes;
+ }
}
}
diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj
index c2f4ab522..ef105fdce 100644
--- a/Jellyfin.Api/Jellyfin.Api.csproj
+++ b/Jellyfin.Api/Jellyfin.Api.csproj
@@ -38,4 +38,10 @@
<CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
+ <ItemGroup>
+ <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
+ <_Parameter1>Jellyfin.Api.Tests</_Parameter1>
+ </AssemblyAttribute>
+ </ItemGroup>
+
</Project>
diff --git a/Jellyfin.Data/Enums/BaseItemKind.cs b/Jellyfin.Data/Enums/BaseItemKind.cs
new file mode 100644
index 000000000..aac30279e
--- /dev/null
+++ b/Jellyfin.Data/Enums/BaseItemKind.cs
@@ -0,0 +1,190 @@
+namespace Jellyfin.Data.Enums
+{
+ /// <summary>
+ /// The base item kind.
+ /// </summary>
+ /// <remarks>
+ /// This enum is generated from all classes that inherit from <c>BaseItem</c>.
+ /// </remarks>
+ public enum BaseItemKind
+ {
+ /// <summary>
+ /// Item is aggregate folder.
+ /// </summary>
+ AggregateFolder,
+
+ /// <summary>
+ /// Item is audio.
+ /// </summary>
+ Audio,
+
+ /// <summary>
+ /// Item is audio book.
+ /// </summary>
+ AudioBook,
+
+ /// <summary>
+ /// Item is base plugin folder.
+ /// </summary>
+ BasePluginFolder,
+
+ /// <summary>
+ /// Item is book.
+ /// </summary>
+ Book,
+
+ /// <summary>
+ /// Item is box set.
+ /// </summary>
+ BoxSet,
+
+ /// <summary>
+ /// Item is channel.
+ /// </summary>
+ Channel,
+
+ /// <summary>
+ /// Item is channel folder item.
+ /// </summary>
+ ChannelFolderItem,
+
+ /// <summary>
+ /// Item is collection folder.
+ /// </summary>
+ CollectionFolder,
+
+ /// <summary>
+ /// Item is episode.
+ /// </summary>
+ Episode,
+
+ /// <summary>
+ /// Item is folder.
+ /// </summary>
+ Folder,
+
+ /// <summary>
+ /// Item is genre.
+ /// </summary>
+ Genre,
+
+ /// <summary>
+ /// Item is manual playlists folder.
+ /// </summary>
+ ManualPlaylistsFolder,
+
+ /// <summary>
+ /// Item is movie.
+ /// </summary>
+ Movie,
+
+ /// <summary>
+ /// Item is music album.
+ /// </summary>
+ MusicAlbum,
+
+ /// <summary>
+ /// Item is music artist.
+ /// </summary>
+ MusicArtist,
+
+ /// <summary>
+ /// Item is music genre.
+ /// </summary>
+ MusicGenre,
+
+ /// <summary>
+ /// Item is music video.
+ /// </summary>
+ MusicVideo,
+
+ /// <summary>
+ /// Item is person.
+ /// </summary>
+ Person,
+
+ /// <summary>
+ /// Item is photo.
+ /// </summary>
+ Photo,
+
+ /// <summary>
+ /// Item is photo album.
+ /// </summary>
+ PhotoAlbum,
+
+ /// <summary>
+ /// Item is playlist.
+ /// </summary>
+ Playlist,
+
+ /// <summary>
+ /// Item is program
+ /// </summary>
+ Program,
+
+ /// <summary>
+ /// Item is recording.
+ /// </summary>
+ /// <remarks>
+ /// Manually added.
+ /// </remarks>
+ Recording,
+
+ /// <summary>
+ /// Item is season.
+ /// </summary>
+ Season,
+
+ /// <summary>
+ /// Item is series.
+ /// </summary>
+ Series,
+
+ /// <summary>
+ /// Item is studio.
+ /// </summary>
+ Studio,
+
+ /// <summary>
+ /// Item is trailer.
+ /// </summary>
+ Trailer,
+
+ /// <summary>
+ /// Item is live tv channel.
+ /// </summary>
+ /// <remarks>
+ /// Type is overridden.
+ /// </remarks>
+ TvChannel,
+
+ /// <summary>
+ /// Item is live tv program.
+ /// </summary>
+ /// <remarks>
+ /// Type is overridden.
+ /// </remarks>
+ TvProgram,
+
+ /// <summary>
+ /// Item is user root folder.
+ /// </summary>
+ UserRootFolder,
+
+ /// <summary>
+ /// Item is user view.
+ /// </summary>
+ UserView,
+
+ /// <summary>
+ /// Item is video.
+ /// </summary>
+ Video,
+
+ /// <summary>
+ /// Item is year.
+ /// </summary>
+ Year
+ }
+} \ No newline at end of file
diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
index da4cc267b..545937207 100644
--- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
+++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs
@@ -316,6 +316,7 @@ namespace Jellyfin.Server.Extensions
c.OperationFilter<SecurityRequirementsOperationFilter>();
c.OperationFilter<FileResponseFilter>();
+ c.OperationFilter<FileRequestFilter>();
c.OperationFilter<ParameterObsoleteFilter>();
c.DocumentFilter<WebsocketModelFilter>();
});
diff --git a/Jellyfin.Server/Filters/FileRequestFilter.cs b/Jellyfin.Server/Filters/FileRequestFilter.cs
new file mode 100644
index 000000000..69e10994f
--- /dev/null
+++ b/Jellyfin.Server/Filters/FileRequestFilter.cs
@@ -0,0 +1,43 @@
+using System.Collections.Generic;
+using Jellyfin.Api.Attributes;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.SwaggerGen;
+
+namespace Jellyfin.Server.Filters
+{
+ /// <inheritdoc />
+ public class FileRequestFilter : IOperationFilter
+ {
+ /// <inheritdoc />
+ public void Apply(OpenApiOperation operation, OperationFilterContext context)
+ {
+ foreach (var attribute in context.ApiDescription.ActionDescriptor.EndpointMetadata)
+ {
+ if (attribute is AcceptsFileAttribute acceptsFileAttribute)
+ {
+ operation.RequestBody = GetRequestBody(acceptsFileAttribute.GetContentTypes());
+ break;
+ }
+ }
+ }
+
+ private static OpenApiRequestBody GetRequestBody(IEnumerable<string> contentTypes)
+ {
+ var body = new OpenApiRequestBody();
+ var mediaType = new OpenApiMediaType
+ {
+ Schema = new OpenApiSchema
+ {
+ Type = "string",
+ Format = "binary"
+ }
+ };
+ foreach (var contentType in contentTypes)
+ {
+ body.Content.Add(contentType, mediaType);
+ }
+
+ return body;
+ }
+ }
+}
diff --git a/MediaBrowser.sln b/Jellyfin.sln
index 4e6687cce..4e6687cce 100644
--- a/MediaBrowser.sln
+++ b/Jellyfin.sln
diff --git a/MediaBrowser.Common/Json/JsonDefaults.cs b/MediaBrowser.Common/Json/JsonDefaults.cs
index 9a2ea6875..2ef24a884 100644
--- a/MediaBrowser.Common/Json/JsonDefaults.cs
+++ b/MediaBrowser.Common/Json/JsonDefaults.cs
@@ -31,7 +31,6 @@ namespace MediaBrowser.Common.Json
WriteIndented = false,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
NumberHandling = JsonNumberHandling.AllowReadingFromString,
- PropertyNameCaseInsensitive = true,
Converters =
{
new JsonGuidConverter(),
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index cbb02aabd..7598b29e6 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -1998,6 +1998,11 @@ namespace MediaBrowser.Controller.Entities
return GetType().Name;
}
+ public BaseItemKind GetBaseItemKind()
+ {
+ return Enum.Parse<BaseItemKind>(GetClientTypeName());
+ }
+
/// <summary>
/// Gets the linked child.
/// </summary>
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 0f0ad0f9a..d1e999666 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -254,7 +254,7 @@ namespace MediaBrowser.Model.Configuration
/// Gets or sets the preferred metadata language.
/// </summary>
/// <value>The preferred metadata language.</value>
- public string PreferredMetadataLanguage { get; set; } = string.Empty;
+ public string PreferredMetadataLanguage { get; set; } = "en";
/// <summary>
/// Gets or sets the metadata country code.
@@ -418,8 +418,6 @@ namespace MediaBrowser.Model.Configuration
public PathSubstitution[] PathSubstitutions { get; set; } = Array.Empty<PathSubstitution>();
- public bool EnableSimpleArtistDetection { get; set; } = false;
-
public string[] UninstalledPlugins { get; set; } = Array.Empty<string>();
/// <summary>
@@ -461,10 +459,5 @@ namespace MediaBrowser.Model.Configuration
/// Gets or sets a value indicating whether older plugins should automatically be deleted from the plugin folder.
/// </summary>
public bool RemoveOldPlugins { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether plugin image should be disabled.
- /// </summary>
- public bool DisablePluginImages { get; set; }
}
}
diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs
index 3f7aac9cd..2f9f9d3cd 100644
--- a/MediaBrowser.Model/Dto/BaseItemDto.cs
+++ b/MediaBrowser.Model/Dto/BaseItemDto.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using Jellyfin.Data.Enums;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Library;
@@ -276,7 +277,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the type.
/// </summary>
/// <value>The type.</value>
- public string Type { get; set; }
+ public BaseItemKind Type { get; set; }
/// <summary>
/// Gets or sets the people.
diff --git a/tests/Jellyfin.Api.Tests/Helpers/RequestHelpersTests.cs b/tests/Jellyfin.Api.Tests/Helpers/RequestHelpersTests.cs
index 606041c7f..97e441b1d 100644
--- a/tests/Jellyfin.Api.Tests/Helpers/RequestHelpersTests.cs
+++ b/tests/Jellyfin.Api.Tests/Helpers/RequestHelpersTests.cs
@@ -6,11 +6,11 @@ using Xunit;
namespace Jellyfin.Api.Tests.Helpers
{
- public class RequestHelpersTests
+ public static class RequestHelpersTests
{
[Theory]
[MemberData(nameof(GetOrderBy_Success_TestData))]
- public void GetOrderBy_Success(IReadOnlyList<string> sortBy, IReadOnlyList<SortOrder> requestedSortOrder, (string, SortOrder)[] expected)
+ public static void GetOrderBy_Success(IReadOnlyList<string> sortBy, IReadOnlyList<SortOrder> requestedSortOrder, (string, SortOrder)[] expected)
{
Assert.Equal(expected, RequestHelpers.GetOrderBy(sortBy, requestedSortOrder));
}
@@ -55,5 +55,35 @@ namespace Jellyfin.Api.Tests.Helpers
}
};
}
+
+ [Fact]
+ public static void GetItemTypeStrings_Empty_Empty()
+ {
+ Assert.Empty(RequestHelpers.GetItemTypeStrings(Array.Empty<BaseItemKind>()));
+ }
+
+ [Fact]
+ public static void GetItemTypeStrings_Valid_Success()
+ {
+ BaseItemKind[] input =
+ {
+ BaseItemKind.AggregateFolder,
+ BaseItemKind.Audio,
+ BaseItemKind.BasePluginFolder,
+ BaseItemKind.CollectionFolder
+ };
+
+ string[] expected =
+ {
+ "AggregateFolder",
+ "Audio",
+ "BasePluginFolder",
+ "CollectionFolder"
+ };
+
+ var res = RequestHelpers.GetItemTypeStrings(input);
+
+ Assert.Equal(expected, res);
+ }
}
}