mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-12-18 15:03:06 +03:00
Compare commits
4 Commits
renovate/s
...
openapi-ca
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
641a097707 | ||
|
|
6c507b77ae | ||
|
|
6ed0ccd37c | ||
|
|
80e1e42947 |
4
.github/workflows/ci-openapi.yml
vendored
4
.github/workflows/ci-openapi.yml
vendored
@@ -172,7 +172,7 @@ jobs:
|
|||||||
strip_components: 1
|
strip_components: 1
|
||||||
target: "/srv/incoming/openapi/unstable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}"
|
target: "/srv/incoming/openapi/unstable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}"
|
||||||
- name: Move openapi.json (unstable) into place
|
- name: Move openapi.json (unstable) into place
|
||||||
uses: appleboy/ssh-action@91f3272fc5907f4699dcf59761eb622a07342f5a # v1.2.3
|
uses: appleboy/ssh-action@823bd89e131d8d508129f9443cad5855e9ba96f0 # v1.2.4
|
||||||
with:
|
with:
|
||||||
host: "${{ secrets.REPO_HOST }}"
|
host: "${{ secrets.REPO_HOST }}"
|
||||||
username: "${{ secrets.REPO_USER }}"
|
username: "${{ secrets.REPO_USER }}"
|
||||||
@@ -234,7 +234,7 @@ jobs:
|
|||||||
strip_components: 1
|
strip_components: 1
|
||||||
target: "/srv/incoming/openapi/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}"
|
target: "/srv/incoming/openapi/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}"
|
||||||
- name: Move openapi.json (stable) into place
|
- name: Move openapi.json (stable) into place
|
||||||
uses: appleboy/ssh-action@91f3272fc5907f4699dcf59761eb622a07342f5a # v1.2.3
|
uses: appleboy/ssh-action@823bd89e131d8d508129f9443cad5855e9ba96f0 # v1.2.4
|
||||||
with:
|
with:
|
||||||
host: "${{ secrets.REPO_HOST }}"
|
host: "${{ secrets.REPO_HOST }}"
|
||||||
username: "${{ secrets.REPO_USER }}"
|
username: "${{ secrets.REPO_USER }}"
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
<PackageVersion Include="prometheus-net.DotNetRuntime" Version="4.4.1" />
|
<PackageVersion Include="prometheus-net.DotNetRuntime" Version="4.4.1" />
|
||||||
<PackageVersion Include="prometheus-net" Version="8.2.1" />
|
<PackageVersion Include="prometheus-net" Version="8.2.1" />
|
||||||
<PackageVersion Include="Polly" Version="8.6.5" />
|
<PackageVersion Include="Polly" Version="8.6.5" />
|
||||||
<PackageVersion Include="Serilog.AspNetCore" Version="10.0.0" />
|
<PackageVersion Include="Serilog.AspNetCore" Version="9.0.0" />
|
||||||
<PackageVersion Include="Serilog.Enrichers.Thread" Version="4.0.0" />
|
<PackageVersion Include="Serilog.Enrichers.Thread" Version="4.0.0" />
|
||||||
<PackageVersion Include="Serilog.Expressions" Version="5.0.0" />
|
<PackageVersion Include="Serilog.Expressions" Version="5.0.0" />
|
||||||
<PackageVersion Include="Serilog.Settings.Configuration" Version="9.0.0" />
|
<PackageVersion Include="Serilog.Settings.Configuration" Version="9.0.0" />
|
||||||
|
|||||||
1
Emby.Server.Implementations/Localization/Core/oc.json
Normal file
1
Emby.Server.Implementations/Localization/Core/oc.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -122,7 +122,6 @@ public class ArtistsController : BaseJellyfinApiController
|
|||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
User? user = null;
|
User? user = null;
|
||||||
@@ -326,7 +325,6 @@ public class ArtistsController : BaseJellyfinApiController
|
|||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
User? user = null;
|
User? user = null;
|
||||||
@@ -467,7 +465,7 @@ public class ArtistsController : BaseJellyfinApiController
|
|||||||
public ActionResult<BaseItemDto> GetArtistByName([FromRoute, Required] string name, [FromQuery] Guid? userId)
|
public ActionResult<BaseItemDto> GetArtistByName([FromRoute, Required] string name, [FromQuery] Guid? userId)
|
||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
|
|
||||||
var item = _libraryManager.GetArtist(name, dtoOptions);
|
var item = _libraryManager.GetArtist(name, dtoOptions);
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class CollectionController : BaseJellyfinApiController
|
|||||||
UserIds = new[] { userId }
|
UserIds = new[] { userId }
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
|
|
||||||
var dto = _dtoService.GetBaseItemDto(item, dtoOptions);
|
var dto = _dtoService.GetBaseItemDto(item, dtoOptions);
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ public class GenresController : BaseJellyfinApiController
|
|||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
User? user = userId.IsNullOrEmpty()
|
User? user = userId.IsNullOrEmpty()
|
||||||
@@ -159,8 +158,7 @@ public class GenresController : BaseJellyfinApiController
|
|||||||
public ActionResult<BaseItemDto> GetGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId)
|
public ActionResult<BaseItemDto> GetGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId)
|
||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions()
|
var dtoOptions = new DtoOptions();
|
||||||
.AddClientFields(User);
|
|
||||||
|
|
||||||
Genre? item;
|
Genre? item;
|
||||||
if (genreName.Contains(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase))
|
if (genreName.Contains(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase))
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ public class InstantMixController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
|
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
|
||||||
return GetResult(items, user, limit, dtoOptions);
|
return GetResult(items, user, limit, dtoOptions);
|
||||||
@@ -134,7 +133,6 @@ public class InstantMixController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
|
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
|
||||||
return GetResult(items, user, limit, dtoOptions);
|
return GetResult(items, user, limit, dtoOptions);
|
||||||
@@ -178,7 +176,6 @@ public class InstantMixController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
|
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
|
||||||
return GetResult(items, user, limit, dtoOptions);
|
return GetResult(items, user, limit, dtoOptions);
|
||||||
@@ -214,7 +211,6 @@ public class InstantMixController : BaseJellyfinApiController
|
|||||||
? null
|
? null
|
||||||
: _userManager.GetUserById(userId.Value);
|
: _userManager.GetUserById(userId.Value);
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
var items = _musicManager.GetInstantMixFromGenres(new[] { name }, user, dtoOptions);
|
var items = _musicManager.GetInstantMixFromGenres(new[] { name }, user, dtoOptions);
|
||||||
return GetResult(items, user, limit, dtoOptions);
|
return GetResult(items, user, limit, dtoOptions);
|
||||||
@@ -258,7 +254,6 @@ public class InstantMixController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
|
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
|
||||||
return GetResult(items, user, limit, dtoOptions);
|
return GetResult(items, user, limit, dtoOptions);
|
||||||
@@ -302,7 +297,6 @@ public class InstantMixController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
|
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
|
||||||
return GetResult(items, user, limit, dtoOptions);
|
return GetResult(items, user, limit, dtoOptions);
|
||||||
@@ -385,7 +379,6 @@ public class InstantMixController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
|
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
|
||||||
return GetResult(items, user, limit, dtoOptions);
|
return GetResult(items, user, limit, dtoOptions);
|
||||||
|
|||||||
@@ -268,7 +268,6 @@ public class ItemsController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
if (includeItemTypes.Length == 1
|
if (includeItemTypes.Length == 1
|
||||||
@@ -849,7 +848,6 @@ public class ItemsController : BaseJellyfinApiController
|
|||||||
|
|
||||||
var parentIdGuid = parentId ?? Guid.Empty;
|
var parentIdGuid = parentId ?? Guid.Empty;
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
var ancestorIds = Array.Empty<Guid>();
|
var ancestorIds = Array.Empty<Guid>();
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ public class LibraryController : BaseJellyfinApiController
|
|||||||
item = parent;
|
item = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
var items = themeItems
|
var items = themeItems
|
||||||
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
|
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@@ -260,7 +260,7 @@ public class LibraryController : BaseJellyfinApiController
|
|||||||
item = parent;
|
item = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
var items = themeItems
|
var items = themeItems
|
||||||
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
|
.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@@ -496,7 +496,7 @@ public class LibraryController : BaseJellyfinApiController
|
|||||||
|
|
||||||
var baseItemDtos = new List<BaseItemDto>();
|
var baseItemDtos = new List<BaseItemDto>();
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
BaseItem? parent = item.GetParent();
|
BaseItem? parent = item.GetParent();
|
||||||
|
|
||||||
while (parent is not null)
|
while (parent is not null)
|
||||||
@@ -556,7 +556,7 @@ public class LibraryController : BaseJellyfinApiController
|
|||||||
items = items.Where(i => i.IsHidden == val).ToList();
|
items = items.Where(i => i.IsHidden == val).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
var resultArray = _dtoService.GetBaseItemDtos(items, dtoOptions);
|
var resultArray = _dtoService.GetBaseItemDtos(items, dtoOptions);
|
||||||
return new QueryResult<BaseItemDto>(resultArray);
|
return new QueryResult<BaseItemDto>(resultArray);
|
||||||
}
|
}
|
||||||
@@ -747,8 +747,7 @@ public class LibraryController : BaseJellyfinApiController
|
|||||||
return new QueryResult<BaseItemDto>();
|
return new QueryResult<BaseItemDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields };
|
||||||
.AddClientFields(User);
|
|
||||||
|
|
||||||
var program = item as IHasProgramAttributes;
|
var program = item as IHasProgramAttributes;
|
||||||
bool? isMovie = item is Movie || (program is not null && program.IsMovie) || item is Trailer;
|
bool? isMovie = item is Movie || (program is not null && program.IsMovie) || item is Trailer;
|
||||||
|
|||||||
@@ -170,7 +170,6 @@ public class LiveTvController : BaseJellyfinApiController
|
|||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
var channelResult = _liveTvManager.GetInternalChannels(
|
var channelResult = _liveTvManager.GetInternalChannels(
|
||||||
@@ -242,8 +241,7 @@ public class LiveTvController : BaseJellyfinApiController
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions()
|
var dtoOptions = new DtoOptions();
|
||||||
.AddClientFields(User);
|
|
||||||
return _dtoService.GetBaseItemDto(item, dtoOptions, user);
|
return _dtoService.GetBaseItemDto(item, dtoOptions, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,7 +295,6 @@ public class LiveTvController : BaseJellyfinApiController
|
|||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
return await _liveTvManager.GetRecordingsAsync(
|
return await _liveTvManager.GetRecordingsAsync(
|
||||||
@@ -444,8 +441,7 @@ public class LiveTvController : BaseJellyfinApiController
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions()
|
var dtoOptions = new DtoOptions();
|
||||||
.AddClientFields(User);
|
|
||||||
|
|
||||||
return _dtoService.GetBaseItemDto(item, dtoOptions, user);
|
return _dtoService.GetBaseItemDto(item, dtoOptions, user);
|
||||||
}
|
}
|
||||||
@@ -635,7 +631,6 @@ public class LiveTvController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false);
|
return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -690,7 +685,6 @@ public class LiveTvController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = body.Fields ?? [] }
|
var dtoOptions = new DtoOptions { Fields = body.Fields ?? [] }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(body.EnableImages, body.EnableUserData, body.ImageTypeLimit, body.EnableImageTypes ?? []);
|
.AddAdditionalDtoOptions(body.EnableImages, body.EnableUserData, body.ImageTypeLimit, body.EnableImageTypes ?? []);
|
||||||
return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false);
|
return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -760,7 +754,6 @@ public class LiveTvController : BaseJellyfinApiController
|
|||||||
};
|
};
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
return await _liveTvManager.GetRecommendedProgramsAsync(query, dtoOptions, CancellationToken.None).ConfigureAwait(false);
|
return await _liveTvManager.GetRecommendedProgramsAsync(query, dtoOptions, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,8 +74,7 @@ public class MoviesController : BaseJellyfinApiController
|
|||||||
var user = userId.IsNullOrEmpty()
|
var user = userId.IsNullOrEmpty()
|
||||||
? null
|
? null
|
||||||
: _userManager.GetUserById(userId.Value);
|
: _userManager.GetUserById(userId.Value);
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields };
|
||||||
.AddClientFields(User);
|
|
||||||
|
|
||||||
var categories = new List<RecommendationDto>();
|
var categories = new List<RecommendationDto>();
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,6 @@ public class MusicGenresController : BaseJellyfinApiController
|
|||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
User? user = userId.IsNullOrEmpty()
|
User? user = userId.IsNullOrEmpty()
|
||||||
@@ -148,7 +147,7 @@ public class MusicGenresController : BaseJellyfinApiController
|
|||||||
public ActionResult<BaseItemDto> GetMusicGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId)
|
public ActionResult<BaseItemDto> GetMusicGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId)
|
||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
|
|
||||||
MusicGenre? item;
|
MusicGenre? item;
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,6 @@ public class PersonsController : BaseJellyfinApiController
|
|||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
User? user = userId.IsNullOrEmpty()
|
User? user = userId.IsNullOrEmpty()
|
||||||
@@ -121,8 +120,7 @@ public class PersonsController : BaseJellyfinApiController
|
|||||||
public ActionResult<BaseItemDto> GetPerson([FromRoute, Required] string name, [FromQuery] Guid? userId)
|
public ActionResult<BaseItemDto> GetPerson([FromRoute, Required] string name, [FromQuery] Guid? userId)
|
||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions()
|
var dtoOptions = new DtoOptions();
|
||||||
.AddClientFields(User);
|
|
||||||
|
|
||||||
var item = _libraryManager.GetPerson(name);
|
var item = _libraryManager.GetPerson(name);
|
||||||
if (item is null)
|
if (item is null)
|
||||||
|
|||||||
@@ -548,7 +548,6 @@ public class PlaylistsController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user);
|
var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user);
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ public class StudiosController : BaseJellyfinApiController
|
|||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
User? user = userId.IsNullOrEmpty()
|
User? user = userId.IsNullOrEmpty()
|
||||||
@@ -142,7 +141,7 @@ public class StudiosController : BaseJellyfinApiController
|
|||||||
public ActionResult<BaseItemDto> GetStudio([FromRoute, Required] string name, [FromQuery] Guid? userId)
|
public ActionResult<BaseItemDto> GetStudio([FromRoute, Required] string name, [FromQuery] Guid? userId)
|
||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
|
|
||||||
var item = _libraryManager.GetStudio(name);
|
var item = _libraryManager.GetStudio(name);
|
||||||
if (!userId.IsNullOrEmpty())
|
if (!userId.IsNullOrEmpty())
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class SuggestionsController : BaseJellyfinApiController
|
|||||||
user = _userManager.GetUserById(requestUserId);
|
user = _userManager.GetUserById(requestUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
var result = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
|
var result = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
|
||||||
{
|
{
|
||||||
OrderBy = new[] { (ItemSortBy.Random, SortOrder.Descending) },
|
OrderBy = new[] { (ItemSortBy.Random, SortOrder.Descending) },
|
||||||
|
|||||||
@@ -99,7 +99,6 @@ public class TvShowsController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var options = new DtoOptions { Fields = fields }
|
var options = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
var result = _tvSeriesManager.GetNextUp(
|
var result = _tvSeriesManager.GetNextUp(
|
||||||
@@ -161,7 +160,6 @@ public class TvShowsController : BaseJellyfinApiController
|
|||||||
var parentIdGuid = parentId ?? Guid.Empty;
|
var parentIdGuid = parentId ?? Guid.Empty;
|
||||||
|
|
||||||
var options = new DtoOptions { Fields = fields }
|
var options = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
@@ -231,7 +229,6 @@ public class TvShowsController : BaseJellyfinApiController
|
|||||||
List<BaseItem> episodes;
|
List<BaseItem> episodes;
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
var shouldIncludeMissingEpisodes = (user is not null && user.DisplayMissingEpisodes) || User.GetIsApiKey();
|
var shouldIncludeMissingEpisodes = (user is not null && user.DisplayMissingEpisodes) || User.GetIsApiKey();
|
||||||
|
|
||||||
@@ -360,7 +357,6 @@ public class TvShowsController : BaseJellyfinApiController
|
|||||||
});
|
});
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user);
|
var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user);
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public class UserLibraryController : BaseJellyfinApiController
|
|||||||
|
|
||||||
await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false);
|
await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false);
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
|
|
||||||
return _dtoService.GetBaseItemDto(item, dtoOptions, user);
|
return _dtoService.GetBaseItemDto(item, dtoOptions, user);
|
||||||
}
|
}
|
||||||
@@ -133,7 +133,7 @@ public class UserLibraryController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var item = _libraryManager.GetUserRootFolder();
|
var item = _libraryManager.GetUserRootFolder();
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
return _dtoService.GetBaseItemDto(item, dtoOptions, user);
|
return _dtoService.GetBaseItemDto(item, dtoOptions, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ public class UserLibraryController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false);
|
var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false);
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray();
|
var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray();
|
||||||
|
|
||||||
return new QueryResult<BaseItemDto>(dtos);
|
return new QueryResult<BaseItemDto>(dtos);
|
||||||
@@ -422,7 +422,7 @@ public class UserLibraryController : BaseJellyfinApiController
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
if (item is IHasTrailers hasTrailers)
|
if (item is IHasTrailers hasTrailers)
|
||||||
{
|
{
|
||||||
var trailers = hasTrailers.LocalTrailers;
|
var trailers = hasTrailers.LocalTrailers;
|
||||||
@@ -478,7 +478,7 @@ public class UserLibraryController : BaseJellyfinApiController
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
|
|
||||||
return Ok(item
|
return Ok(item
|
||||||
.GetExtras()
|
.GetExtras()
|
||||||
@@ -549,7 +549,6 @@ public class UserLibraryController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
var list = _userViewManager.GetLatestItems(
|
var list = _userViewManager.GetLatestItems(
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ public class UserViewsController : BaseJellyfinApiController
|
|||||||
|
|
||||||
var folders = _userViewManager.GetUserViews(query);
|
var folders = _userViewManager.GetUserViews(query);
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions().AddClientFields(User);
|
var dtoOptions = new DtoOptions();
|
||||||
dtoOptions.Fields = [..dtoOptions.Fields, ItemFields.PrimaryImageAspectRatio, ItemFields.DisplayPreferencesId];
|
dtoOptions.Fields = [..dtoOptions.Fields, ItemFields.PrimaryImageAspectRatio, ItemFields.DisplayPreferencesId];
|
||||||
|
|
||||||
var dtos = Array.ConvertAll(folders, i => _dtoService.GetBaseItemDto(i, dtoOptions, user));
|
var dtos = Array.ConvertAll(folders, i => _dtoService.GetBaseItemDto(i, dtoOptions, user));
|
||||||
|
|||||||
@@ -111,7 +111,6 @@ public class VideosController : BaseJellyfinApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions();
|
var dtoOptions = new DtoOptions();
|
||||||
dtoOptions = dtoOptions.AddClientFields(User);
|
|
||||||
|
|
||||||
BaseItemDto[] items;
|
BaseItemDto[] items;
|
||||||
if (item is Video video)
|
if (item is Video video)
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ public class YearsController : BaseJellyfinApiController
|
|||||||
{
|
{
|
||||||
userId = RequestHelpers.GetUserId(User, userId);
|
userId = RequestHelpers.GetUserId(User, userId);
|
||||||
var dtoOptions = new DtoOptions { Fields = fields }
|
var dtoOptions = new DtoOptions { Fields = fields }
|
||||||
.AddClientFields(User)
|
|
||||||
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
|
||||||
|
|
||||||
User? user = userId.IsNullOrEmpty()
|
User? user = userId.IsNullOrEmpty()
|
||||||
@@ -182,8 +181,7 @@ public class YearsController : BaseJellyfinApiController
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dtoOptions = new DtoOptions()
|
var dtoOptions = new DtoOptions();
|
||||||
.AddClientFields(User);
|
|
||||||
|
|
||||||
if (!userId.IsNullOrEmpty())
|
if (!userId.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Security.Claims;
|
|
||||||
using Jellyfin.Extensions;
|
|
||||||
using MediaBrowser.Controller.Dto;
|
using MediaBrowser.Controller.Dto;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Querying;
|
|
||||||
|
|
||||||
namespace Jellyfin.Api.Extensions;
|
namespace Jellyfin.Api.Extensions;
|
||||||
|
|
||||||
@@ -13,55 +9,6 @@ namespace Jellyfin.Api.Extensions;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class DtoExtensions
|
public static class DtoExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Add additional fields depending on client.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Use in place of GetDtoOptions.
|
|
||||||
/// Legacy order: 2.
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="dtoOptions">DtoOptions object.</param>
|
|
||||||
/// <param name="user">Current claims principal.</param>
|
|
||||||
/// <returns>Modified DtoOptions object.</returns>
|
|
||||||
internal static DtoOptions AddClientFields(
|
|
||||||
this DtoOptions dtoOptions, ClaimsPrincipal user)
|
|
||||||
{
|
|
||||||
string? client = user.GetClient();
|
|
||||||
|
|
||||||
// No client in claim
|
|
||||||
if (string.IsNullOrEmpty(client))
|
|
||||||
{
|
|
||||||
return dtoOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dtoOptions.ContainsField(ItemFields.RecursiveItemCount))
|
|
||||||
{
|
|
||||||
if (client.Contains("kodi", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
client.Contains("wmc", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
client.Contains("media center", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
client.Contains("classic", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
dtoOptions.Fields = [..dtoOptions.Fields, ItemFields.RecursiveItemCount];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dtoOptions.ContainsField(ItemFields.ChildCount))
|
|
||||||
{
|
|
||||||
if (client.Contains("kodi", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
client.Contains("wmc", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
client.Contains("media center", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
client.Contains("classic", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
client.Contains("roku", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
client.Contains("samsung", StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
client.Contains("androidtv", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
dtoOptions.Fields = [..dtoOptions.Fields, ItemFields.ChildCount];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dtoOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add additional DtoOptions.
|
/// Add additional DtoOptions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -33,9 +33,11 @@ using Microsoft.AspNetCore.Builder;
|
|||||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
using Microsoft.AspNetCore.Cors.Infrastructure;
|
||||||
using Microsoft.AspNetCore.HttpOverrides;
|
using Microsoft.AspNetCore.HttpOverrides;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Microsoft.OpenApi.Any;
|
using Microsoft.OpenApi.Any;
|
||||||
using Microsoft.OpenApi.Interfaces;
|
using Microsoft.OpenApi.Interfaces;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Swashbuckle.AspNetCore.Swagger;
|
||||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
using AuthenticationSchemes = Jellyfin.Api.Constants.AuthenticationSchemes;
|
using AuthenticationSchemes = Jellyfin.Api.Constants.AuthenticationSchemes;
|
||||||
|
|
||||||
@@ -259,7 +261,8 @@ namespace Jellyfin.Server.Extensions
|
|||||||
c.OperationFilter<FileRequestFilter>();
|
c.OperationFilter<FileRequestFilter>();
|
||||||
c.OperationFilter<ParameterObsoleteFilter>();
|
c.OperationFilter<ParameterObsoleteFilter>();
|
||||||
c.DocumentFilter<AdditionalModelFilter>();
|
c.DocumentFilter<AdditionalModelFilter>();
|
||||||
});
|
})
|
||||||
|
.Replace(ServiceDescriptor.Transient<ISwaggerProvider, CachingOpenApiProvider>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddPolicy(this AuthorizationOptions authorizationOptions, string policyName, IAuthorizationRequirement authorizationRequirement)
|
private static void AddPolicy(this AuthorizationOptions authorizationOptions, string policyName, IAuthorizationRequirement authorizationRequirement)
|
||||||
|
|||||||
89
Jellyfin.Server/Filters/CachingOpenApiProvider.cs
Normal file
89
Jellyfin.Server/Filters/CachingOpenApiProvider.cs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Swashbuckle.AspNetCore.Swagger;
|
||||||
|
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||||
|
|
||||||
|
namespace Jellyfin.Server.Filters;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OpenApi provider with caching.
|
||||||
|
/// </summary>
|
||||||
|
internal sealed class CachingOpenApiProvider : ISwaggerProvider
|
||||||
|
{
|
||||||
|
private const string CacheKey = "openapi.json";
|
||||||
|
|
||||||
|
private static readonly MemoryCacheEntryOptions _cacheOptions = new() { SlidingExpiration = TimeSpan.FromMinutes(5) };
|
||||||
|
private static readonly SemaphoreSlim _lock = new(1, 1);
|
||||||
|
private static readonly TimeSpan _lockTimeout = TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
|
private readonly IMemoryCache _memoryCache;
|
||||||
|
private readonly SwaggerGenerator _swaggerGenerator;
|
||||||
|
private readonly SwaggerGeneratorOptions _swaggerGeneratorOptions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CachingOpenApiProvider"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="optionsAccessor">The options accessor.</param>
|
||||||
|
/// <param name="apiDescriptionsProvider">The api descriptions provider.</param>
|
||||||
|
/// <param name="schemaGenerator">The schema generator.</param>
|
||||||
|
/// <param name="memoryCache">The memory cache.</param>
|
||||||
|
public CachingOpenApiProvider(
|
||||||
|
IOptions<SwaggerGeneratorOptions> optionsAccessor,
|
||||||
|
IApiDescriptionGroupCollectionProvider apiDescriptionsProvider,
|
||||||
|
ISchemaGenerator schemaGenerator,
|
||||||
|
IMemoryCache memoryCache)
|
||||||
|
{
|
||||||
|
_swaggerGeneratorOptions = optionsAccessor.Value;
|
||||||
|
_swaggerGenerator = new SwaggerGenerator(_swaggerGeneratorOptions, apiDescriptionsProvider, schemaGenerator);
|
||||||
|
_memoryCache = memoryCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public OpenApiDocument GetSwagger(string documentName, string? host = null, string? basePath = null)
|
||||||
|
{
|
||||||
|
if (_memoryCache.TryGetValue(CacheKey, out OpenApiDocument? openApiDocument) && openApiDocument is not null)
|
||||||
|
{
|
||||||
|
return AdjustDocument(openApiDocument, host, basePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
var acquired = _lock.Wait(_lockTimeout);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_memoryCache.TryGetValue(CacheKey, out openApiDocument) && openApiDocument is not null)
|
||||||
|
{
|
||||||
|
return AdjustDocument(openApiDocument, host, basePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!acquired)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("OpenApi document is generating");
|
||||||
|
}
|
||||||
|
|
||||||
|
openApiDocument = _swaggerGenerator.GetSwagger(documentName);
|
||||||
|
_memoryCache.Set(CacheKey, openApiDocument, _cacheOptions);
|
||||||
|
return AdjustDocument(openApiDocument, host, basePath);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (acquired)
|
||||||
|
{
|
||||||
|
_lock.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private OpenApiDocument AdjustDocument(OpenApiDocument document, string? host, string? basePath)
|
||||||
|
{
|
||||||
|
document.Servers = _swaggerGeneratorOptions.Servers.Count != 0
|
||||||
|
? _swaggerGeneratorOptions.Servers
|
||||||
|
: string.IsNullOrEmpty(host) && string.IsNullOrEmpty(basePath)
|
||||||
|
? []
|
||||||
|
: [new OpenApiServer { Url = $"{host}{basePath}" }];
|
||||||
|
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user