diff options
Diffstat (limited to 'Jellyfin.Api')
| -rw-r--r-- | Jellyfin.Api/Controllers/DashboardController.cs | 43 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/ImageController.cs | 4 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/PluginsController.cs | 4 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/UniversalAudioController.cs | 4 | ||||
| -rw-r--r-- | Jellyfin.Api/Extensions/DtoExtensions.cs | 9 | ||||
| -rw-r--r-- | Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 13 | ||||
| -rw-r--r-- | Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs | 2 | ||||
| -rw-r--r-- | Jellyfin.Api/Helpers/MediaInfoHelper.cs | 2 | ||||
| -rw-r--r-- | Jellyfin.Api/Helpers/StreamingHelpers.cs | 4 | ||||
| -rw-r--r-- | Jellyfin.Api/Jellyfin.Api.csproj | 10 | ||||
| -rw-r--r-- | Jellyfin.Api/Models/ConfigurationPageInfo.cs | 9 | ||||
| -rw-r--r-- | Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs | 2 |
12 files changed, 45 insertions, 61 deletions
diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs index b2baa9cea..a2c2ecd66 100644 --- a/Jellyfin.Api/Controllers/DashboardController.cs +++ b/Jellyfin.Api/Controllers/DashboardController.cs @@ -6,7 +6,6 @@ using System.Net.Mime; using Jellyfin.Api.Attributes; using Jellyfin.Api.Models; using MediaBrowser.Common.Plugins; -using MediaBrowser.Controller; using MediaBrowser.Model.Net; using MediaBrowser.Model.Plugins; using Microsoft.AspNetCore.Http; @@ -22,22 +21,18 @@ namespace Jellyfin.Api.Controllers public class DashboardController : BaseJellyfinApiController { private readonly ILogger<DashboardController> _logger; - private readonly IServerApplicationHost _appHost; private readonly IPluginManager _pluginManager; /// <summary> /// Initializes a new instance of the <see cref="DashboardController"/> class. /// </summary> /// <param name="logger">Instance of <see cref="ILogger{DashboardController}"/> interface.</param> - /// <param name="appHost">Instance of <see cref="IServerApplicationHost"/> interface.</param> /// <param name="pluginManager">Instance of <see cref="IPluginManager"/> interface.</param> public DashboardController( ILogger<DashboardController> logger, - IServerApplicationHost appHost, IPluginManager pluginManager) { _logger = logger; - _appHost = appHost; _pluginManager = pluginManager; } @@ -51,7 +46,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("web/ConfigurationPages")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult<IEnumerable<ConfigurationPageInfo?>> GetConfigurationPages( + public ActionResult<IEnumerable<ConfigurationPageInfo>> GetConfigurationPages( [FromQuery] bool? enableInMainMenu) { var configPages = _pluginManager.Plugins.SelectMany(GetConfigPages).ToList(); @@ -77,38 +72,22 @@ namespace Jellyfin.Api.Controllers [ProducesFile(MediaTypeNames.Text.Html, "application/x-javascript")] public ActionResult GetDashboardConfigurationPage([FromQuery] string? name) { - IPlugin? plugin = null; - Stream? stream = null; - - var isJs = false; - var isTemplate = false; - var altPage = GetPluginPages().FirstOrDefault(p => string.Equals(p.Item1.Name, name, StringComparison.OrdinalIgnoreCase)); - if (altPage != null) + if (altPage == null) { - plugin = altPage.Item2; - stream = plugin.GetType().Assembly.GetManifestResourceStream(altPage.Item1.EmbeddedResourcePath); - - isJs = string.Equals(Path.GetExtension(altPage.Item1.EmbeddedResourcePath), ".js", StringComparison.OrdinalIgnoreCase); - isTemplate = altPage.Item1.EmbeddedResourcePath.EndsWith(".template.html", StringComparison.Ordinal); + return NotFound(); } - if (plugin != null && stream != null) + IPlugin plugin = altPage.Item2; + string resourcePath = altPage.Item1.EmbeddedResourcePath; + Stream? stream = plugin.GetType().Assembly.GetManifestResourceStream(resourcePath); + if (stream == null) { - if (isJs) - { - return File(stream, MimeTypes.GetMimeType("page.js")); - } - - if (isTemplate) - { - return File(stream, MimeTypes.GetMimeType("page.html")); - } - - return File(stream, MimeTypes.GetMimeType("page.html")); + _logger.LogError("Failed to get resource {Resource} from plugin {Plugin}", resourcePath, plugin.Name); + return NotFound(); } - return NotFound(); + return File(stream, MimeTypes.GetMimeType(resourcePath)); } private IEnumerable<ConfigurationPageInfo> GetConfigPages(LocalPlugin plugin) @@ -120,7 +99,7 @@ namespace Jellyfin.Api.Controllers { if (plugin?.Instance is not IHasWebPages hasWebPages) { - return new List<Tuple<PluginPageInfo, IPlugin>>(); + return Enumerable.Empty<Tuple<PluginPageInfo, IPlugin>>(); } return hasWebPages.GetPages().Select(i => new Tuple<PluginPageInfo, IPlugin>(i, plugin.Instance)); diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index dc3634970..a50d6e46b 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -113,7 +113,7 @@ namespace Jellyfin.Api.Controllers await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false); } - user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType))); + user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType ?? string.Empty))); await _providerManager .SaveImage(memoryStream, mimeType, user.ProfileImage.Path) @@ -160,7 +160,7 @@ namespace Jellyfin.Api.Controllers await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false); } - user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType))); + user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType ?? string.Empty))); await _providerManager .SaveImage(memoryStream, mimeType, user.ProfileImage.Path) diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index b2e8bee91..a5aa9bfca 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -298,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/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index bacd95bac..5aa033ccf 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -223,7 +223,7 @@ namespace Jellyfin.Api.Controllers DeInterlace = true, RequireNonAnamorphic = true, EnableMpegtsM2TsMode = true, - TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()), + TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(',', mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()), Context = EncodingContext.Static, StreamOptions = new Dictionary<string, string>(), EnableAdaptiveBitrateStreaming = true @@ -254,7 +254,7 @@ namespace Jellyfin.Api.Controllers CopyTimestamps = true, StartTimeTicks = startTimeTicks, SubtitleMethod = SubtitleDeliveryMethod.Embed, - TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(",", mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()), + TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(',', mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()), Context = EncodingContext.Static }; diff --git a/Jellyfin.Api/Extensions/DtoExtensions.cs b/Jellyfin.Api/Extensions/DtoExtensions.cs index f2abd515d..e0c744325 100644 --- a/Jellyfin.Api/Extensions/DtoExtensions.cs +++ b/Jellyfin.Api/Extensions/DtoExtensions.cs @@ -113,14 +113,5 @@ namespace Jellyfin.Api.Extensions return dtoOptions; } - - /// <summary> - /// Check if DtoOptions contains field. - /// </summary> - /// <param name="dtoOptions">DtoOptions object.</param> - /// <param name="field">Field to check.</param> - /// <returns>Field existence.</returns> - internal static bool ContainsField(this DtoOptions dtoOptions, ItemFields field) - => dtoOptions.Fields != null && dtoOptions.Fields.Contains(field); } } diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 92ff42b49..16380f0bb 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; +using System.Net.Mime; using System.Security.Claims; using System.Text; using System.Threading; @@ -171,13 +172,15 @@ namespace Jellyfin.Api.Helpers var queryString = _httpContextAccessor.HttpContext.Request.QueryString.ToString(); // from universal audio service - if (queryString.IndexOf("SegmentContainer", StringComparison.OrdinalIgnoreCase) == -1 && !string.IsNullOrWhiteSpace(state.Request.SegmentContainer)) + if (!string.IsNullOrWhiteSpace(state.Request.SegmentContainer) + && !queryString.Contains("SegmentContainer", StringComparison.OrdinalIgnoreCase)) { queryString += "&SegmentContainer=" + state.Request.SegmentContainer; } // from universal audio service - if (!string.IsNullOrWhiteSpace(state.Request.TranscodeReasons) && queryString.IndexOf("TranscodeReasons=", StringComparison.OrdinalIgnoreCase) == -1) + if (!string.IsNullOrWhiteSpace(state.Request.TranscodeReasons) + && !queryString.Contains("TranscodeReasons=", StringComparison.OrdinalIgnoreCase)) { queryString += "&TranscodeReasons=" + state.Request.TranscodeReasons; } @@ -222,7 +225,7 @@ namespace Jellyfin.Api.Helpers { // Force HEVC Main Profile and disable video stream copy. state.OutputVideoCodec = "hevc"; - var sdrVideoUrl = ReplaceProfile(playlistUrl, "hevc", string.Join(",", requestedVideoProfiles), "main"); + var sdrVideoUrl = ReplaceProfile(playlistUrl, "hevc", string.Join(',', requestedVideoProfiles), "main"); sdrVideoUrl += "&AllowVideoStreamCopy=false"; EncodingHelper encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration); @@ -560,13 +563,13 @@ namespace Jellyfin.Api.Helpers profileString = state.GetRequestedProfiles(codec).FirstOrDefault() ?? string.Empty; if (string.Equals(state.ActualOutputVideoCodec, "h264", StringComparison.OrdinalIgnoreCase)) { - profileString = profileString ?? "high"; + profileString ??= "high"; } if (string.Equals(state.ActualOutputVideoCodec, "h265", StringComparison.OrdinalIgnoreCase) || string.Equals(state.ActualOutputVideoCodec, "hevc", StringComparison.OrdinalIgnoreCase)) { - profileString = profileString ?? "main"; + profileString ??= "main"; } } diff --git a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs index cfa2c1229..89d36ab09 100644 --- a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs +++ b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs @@ -39,7 +39,7 @@ namespace Jellyfin.Api.Helpers } // Can't dispose the response as it's required up the call chain. - var response = await httpClient.GetAsync(new Uri(state.MediaPath)).ConfigureAwait(false); + var response = await httpClient.GetAsync(new Uri(state.MediaPath), cancellationToken).ConfigureAwait(false); var contentType = response.Content.Headers.ContentType?.ToString(); httpContext.Response.Headers[HeaderNames.AcceptRanges] = "none"; diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs index 0d8315dee..ce6740fc9 100644 --- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs +++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs @@ -523,7 +523,7 @@ namespace Jellyfin.Api.Helpers /// <param name="type">Dlna profile type.</param> public void NormalizeMediaSourceContainer(MediaSourceInfo mediaSource, DeviceProfile profile, DlnaProfileType type) { - mediaSource.Container = StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(mediaSource.Container, mediaSource.Path, profile, type); + mediaSource.Container = StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(mediaSource.Container, profile, type); } private void SetDeviceSpecificSubtitleInfo(StreamInfo info, MediaSourceInfo mediaSource, string accessToken) diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 4957ee8b8..d20a02cf5 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -183,7 +183,7 @@ namespace Jellyfin.Api.Helpers if (string.IsNullOrEmpty(containerInternal)) { containerInternal = streamingRequest.Static ? - StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(state.InputContainer, state.MediaPath, null, DlnaProfileType.Audio) + StreamBuilder.NormalizeMediaSourceFormatIntoSingleContainer(state.InputContainer, null, DlnaProfileType.Audio) : GetOutputFileExtension(state); } @@ -245,7 +245,7 @@ namespace Jellyfin.Api.Helpers var ext = string.IsNullOrWhiteSpace(state.OutputContainer) ? GetOutputFileExtension(state) - : ('.' + state.OutputContainer); + : ("." + state.OutputContainer); state.OutputFilePath = GetOutputFilePath(state, ext!, serverConfigurationManager, streamingRequest.DeviceId, streamingRequest.PlaySessionId); diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index c2f4ab522..67d0a3b5a 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -17,8 +17,8 @@ <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="5.0.3" /> <PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" /> - <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" /> - <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="6.0.2" /> + <PackageReference Include="Swashbuckle.AspNetCore" Version="6.0.7" /> + <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="6.0.7" /> </ItemGroup> <ItemGroup> @@ -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.Api/Models/ConfigurationPageInfo.cs b/Jellyfin.Api/Models/ConfigurationPageInfo.cs index a7bbe42fe..ec4a0d1a1 100644 --- a/Jellyfin.Api/Models/ConfigurationPageInfo.cs +++ b/Jellyfin.Api/Models/ConfigurationPageInfo.cs @@ -1,6 +1,5 @@ using System; using MediaBrowser.Common.Plugins; -using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Plugins; namespace Jellyfin.Api.Models @@ -26,6 +25,14 @@ namespace Jellyfin.Api.Models } /// <summary> + /// Initializes a new instance of the <see cref="ConfigurationPageInfo"/> class. + /// </summary> + public ConfigurationPageInfo() + { + Name = string.Empty; + } + + /// <summary> /// Gets or sets the name. /// </summary> /// <value>The name.</value> diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs index 872a46824..e33e552ed 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs @@ -98,7 +98,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos private EncodingOptions GetOptions() { - return _config.GetConfiguration<EncodingOptions>("encoding"); + return _config.GetEncodingOptions(); } private async void TimerCallback(object? state) |
