aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api/Controllers
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api/Controllers')
-rw-r--r--Jellyfin.Api/Controllers/ApiKeyController.cs2
-rw-r--r--Jellyfin.Api/Controllers/DynamicHlsController.cs13
-rw-r--r--Jellyfin.Api/Controllers/ImageController.cs148
-rw-r--r--Jellyfin.Api/Controllers/LiveTvController.cs3
-rw-r--r--Jellyfin.Api/Controllers/NotificationsController.cs87
-rw-r--r--Jellyfin.Api/Controllers/PackageController.cs4
-rw-r--r--Jellyfin.Api/Controllers/PluginsController.cs3
-rw-r--r--Jellyfin.Api/Controllers/SubtitleController.cs40
-rw-r--r--Jellyfin.Api/Controllers/SyncPlayController.cs3
-rw-r--r--Jellyfin.Api/Controllers/SystemController.cs3
-rw-r--r--Jellyfin.Api/Controllers/UserLibraryController.cs2
11 files changed, 120 insertions, 188 deletions
diff --git a/Jellyfin.Api/Controllers/ApiKeyController.cs b/Jellyfin.Api/Controllers/ApiKeyController.cs
index 593846adc..024a15349 100644
--- a/Jellyfin.Api/Controllers/ApiKeyController.cs
+++ b/Jellyfin.Api/Controllers/ApiKeyController.cs
@@ -36,7 +36,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<QueryResult<AuthenticationInfo>>> GetKeys()
{
- var keys = await _authenticationManager.GetApiKeys();
+ var keys = await _authenticationManager.GetApiKeys().ConfigureAwait(false);
return new QueryResult<AuthenticationInfo>(keys);
}
diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index af43bb578..ba9a57f1d 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -22,6 +22,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using Microsoft.AspNetCore.Authorization;
@@ -1704,11 +1705,12 @@ namespace Jellyfin.Api.Controllers
return audioTranscodeParams;
}
- // flac and opus are experimental in mp4 muxer
+ // dts, flac and opus are experimental in mp4 muxer
var strictArgs = string.Empty;
if (string.Equals(state.ActualOutputAudioCodec, "flac", StringComparison.OrdinalIgnoreCase)
- || string.Equals(state.ActualOutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase))
+ || string.Equals(state.ActualOutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase)
+ || string.Equals(state.ActualOutputAudioCodec, "dts", StringComparison.OrdinalIgnoreCase))
{
strictArgs = " -strict -2";
}
@@ -1731,7 +1733,12 @@ namespace Jellyfin.Api.Controllers
var channels = state.OutputAudioChannels;
- if (channels.HasValue)
+ if (channels.HasValue
+ && (channels.Value != 2
+ || (state.AudioStream is not null
+ && state.AudioStream.Channels.HasValue
+ && state.AudioStream.Channels.Value > 5
+ && _encodingOptions.DownMixStereoAlgorithm == DownMixStereoAlgorithms.None)))
{
args += " -ac " + channels.Value;
}
diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs
index 49342ad5c..f866655c0 100644
--- a/Jellyfin.Api/Controllers/ImageController.cs
+++ b/Jellyfin.Api/Controllers/ImageController.cs
@@ -28,7 +28,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
namespace Jellyfin.Api.Controllers
@@ -106,24 +105,26 @@ namespace Jellyfin.Api.Controllers
}
var user = _userManager.GetUserById(userId);
- await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
-
- // Handle image/png; charset=utf-8
- var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
- var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username);
- if (user.ProfileImage is not null)
+ var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
+ await using (memoryStream.ConfigureAwait(false))
{
- await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false);
- }
+ // Handle image/png; charset=utf-8
+ var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
+ var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username);
+ if (user.ProfileImage is not null)
+ {
+ await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false);
+ }
- user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType ?? string.Empty)));
+ user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType ?? string.Empty)));
- await _providerManager
- .SaveImage(memoryStream, mimeType, user.ProfileImage.Path)
- .ConfigureAwait(false);
- await _userManager.UpdateUserAsync(user).ConfigureAwait(false);
+ await _providerManager
+ .SaveImage(memoryStream, mimeType, user.ProfileImage.Path)
+ .ConfigureAwait(false);
+ await _userManager.UpdateUserAsync(user).ConfigureAwait(false);
- return NoContent();
+ return NoContent();
+ }
}
/// <summary>
@@ -153,24 +154,26 @@ namespace Jellyfin.Api.Controllers
}
var user = _userManager.GetUserById(userId);
- await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
-
- // Handle image/png; charset=utf-8
- var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
- var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username);
- if (user.ProfileImage is not null)
+ var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
+ await using (memoryStream.ConfigureAwait(false))
{
- await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false);
- }
+ // Handle image/png; charset=utf-8
+ var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
+ var userDataPath = Path.Combine(_serverConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, user.Username);
+ if (user.ProfileImage is not null)
+ {
+ await _userManager.ClearProfileImageAsync(user).ConfigureAwait(false);
+ }
- user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType ?? string.Empty)));
+ user.ProfileImage = new Data.Entities.ImageInfo(Path.Combine(userDataPath, "profile" + MimeTypes.ToExtension(mimeType ?? string.Empty)));
- await _providerManager
- .SaveImage(memoryStream, mimeType, user.ProfileImage.Path)
- .ConfigureAwait(false);
- await _userManager.UpdateUserAsync(user).ConfigureAwait(false);
+ await _providerManager
+ .SaveImage(memoryStream, mimeType, user.ProfileImage.Path)
+ .ConfigureAwait(false);
+ await _userManager.UpdateUserAsync(user).ConfigureAwait(false);
- return NoContent();
+ return NoContent();
+ }
}
/// <summary>
@@ -341,14 +344,16 @@ namespace Jellyfin.Api.Controllers
return NotFound();
}
- await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
-
- // Handle image/png; charset=utf-8
- var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
- await _providerManager.SaveImage(item, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
- await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
+ var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
+ await using (memoryStream.ConfigureAwait(false))
+ {
+ // Handle image/png; charset=utf-8
+ var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
+ await _providerManager.SaveImage(item, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
+ await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
- return NoContent();
+ return NoContent();
+ }
}
/// <summary>
@@ -377,14 +382,16 @@ namespace Jellyfin.Api.Controllers
return NotFound();
}
- await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
-
- // Handle image/png; charset=utf-8
- var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
- await _providerManager.SaveImage(item, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
- await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
+ var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
+ await using (memoryStream.ConfigureAwait(false))
+ {
+ // Handle image/png; charset=utf-8
+ var mimeType = Request.ContentType?.Split(';').FirstOrDefault();
+ await _providerManager.SaveImage(item, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false);
+ await item.UpdateToRepositoryAsync(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false);
- return NoContent();
+ return NoContent();
+ }
}
/// <summary>
@@ -1788,32 +1795,35 @@ namespace Jellyfin.Api.Controllers
[AcceptsImageFile]
public async Task<ActionResult> UploadCustomSplashscreen()
{
- await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
+ var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
+ await using (memoryStream.ConfigureAwait(false))
+ {
+ var mimeType = MediaTypeHeaderValue.Parse(Request.ContentType).MediaType;
- var mimeType = MediaTypeHeaderValue.Parse(Request.ContentType).MediaType;
+ if (!mimeType.HasValue)
+ {
+ return BadRequest("Error reading mimetype from uploaded image");
+ }
- if (!mimeType.HasValue)
- {
- return BadRequest("Error reading mimetype from uploaded image");
- }
+ var extension = MimeTypes.ToExtension(mimeType.Value);
+ if (string.IsNullOrEmpty(extension))
+ {
+ return BadRequest("Error converting mimetype to an image extension");
+ }
- var extension = MimeTypes.ToExtension(mimeType.Value);
- if (string.IsNullOrEmpty(extension))
- {
- return BadRequest("Error converting mimetype to an image extension");
- }
+ var filePath = Path.Combine(_appPaths.DataPath, "splashscreen-upload" + extension);
+ var brandingOptions = _serverConfigurationManager.GetConfiguration<BrandingOptions>("branding");
+ brandingOptions.SplashscreenLocation = filePath;
+ _serverConfigurationManager.SaveConfiguration("branding", brandingOptions);
- var filePath = Path.Combine(_appPaths.DataPath, "splashscreen-upload" + extension);
- var brandingOptions = _serverConfigurationManager.GetConfiguration<BrandingOptions>("branding");
- brandingOptions.SplashscreenLocation = filePath;
- _serverConfigurationManager.SaveConfiguration("branding", brandingOptions);
+ var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
+ await using (fs.ConfigureAwait(false))
+ {
+ await memoryStream.CopyToAsync(fs, CancellationToken.None).ConfigureAwait(false);
+ }
- await using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
- {
- await memoryStream.CopyToAsync(fs, CancellationToken.None).ConfigureAwait(false);
+ return NoContent();
}
-
- return NoContent();
}
/// <summary>
@@ -2027,13 +2037,8 @@ namespace Jellyfin.Api.Controllers
}
var acceptParam = Request.Query[HeaderNames.Accept];
- if (StringValues.IsNullOrEmpty(acceptParam))
- {
- return Array.Empty<ImageFormat>();
- }
- // Can't be null, checked above
- var supportsWebP = SupportsFormat(supportedFormats, acceptParam!, ImageFormat.Webp, false);
+ var supportsWebP = SupportsFormat(supportedFormats, acceptParam, ImageFormat.Webp, false);
if (!supportsWebP)
{
@@ -2055,8 +2060,7 @@ namespace Jellyfin.Api.Controllers
formats.Add(ImageFormat.Jpg);
formats.Add(ImageFormat.Png);
- // Can't be null, checked above
- if (SupportsFormat(supportedFormats, acceptParam!, ImageFormat.Gif, true))
+ if (SupportsFormat(supportedFormats, acceptParam, ImageFormat.Gif, true))
{
formats.Add(ImageFormat.Gif);
}
@@ -2064,7 +2068,7 @@ namespace Jellyfin.Api.Controllers
return formats.ToArray();
}
- private bool SupportsFormat(IReadOnlyCollection<string> requestAcceptTypes, string acceptParam, ImageFormat format, bool acceptAll)
+ private bool SupportsFormat(IReadOnlyCollection<string> requestAcceptTypes, string? acceptParam, ImageFormat format, bool acceptAll)
{
if (requestAcceptTypes.Contains(format.GetMimeType()))
{
diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs
index 94710d78f..5228e0bab 100644
--- a/Jellyfin.Api/Controllers/LiveTvController.cs
+++ b/Jellyfin.Api/Controllers/LiveTvController.cs
@@ -1011,10 +1011,9 @@ namespace Jellyfin.Api.Controllers
{
if (!string.IsNullOrEmpty(pw))
{
- using var sha = SHA1.Create();
// TODO: remove ToLower when Convert.ToHexString supports lowercase
// Schedules Direct requires the hex to be lowercase
- listingsProviderInfo.Password = Convert.ToHexString(sha.ComputeHash(Encoding.UTF8.GetBytes(pw))).ToLowerInvariant();
+ listingsProviderInfo.Password = Convert.ToHexString(SHA1.HashData(Encoding.UTF8.GetBytes(pw))).ToLowerInvariant();
}
return await _liveTvManager.SaveListingProvider(listingsProviderInfo, validateLogin, validateListings).ConfigureAwait(false);
diff --git a/Jellyfin.Api/Controllers/NotificationsController.cs b/Jellyfin.Api/Controllers/NotificationsController.cs
index 420630cdf..a28556476 100644
--- a/Jellyfin.Api/Controllers/NotificationsController.cs
+++ b/Jellyfin.Api/Controllers/NotificationsController.cs
@@ -1,12 +1,5 @@
-using System;
using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.Linq;
-using System.Threading;
using Jellyfin.Api.Constants;
-using Jellyfin.Api.Models.NotificationDtos;
-using Jellyfin.Data.Enums;
-using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Notifications;
@@ -23,41 +16,14 @@ namespace Jellyfin.Api.Controllers
public class NotificationsController : BaseJellyfinApiController
{
private readonly INotificationManager _notificationManager;
- private readonly IUserManager _userManager;
/// <summary>
/// Initializes a new instance of the <see cref="NotificationsController" /> class.
/// </summary>
/// <param name="notificationManager">The notification manager.</param>
- /// <param name="userManager">The user manager.</param>
- public NotificationsController(INotificationManager notificationManager, IUserManager userManager)
+ public NotificationsController(INotificationManager notificationManager)
{
_notificationManager = notificationManager;
- _userManager = userManager;
- }
-
- /// <summary>
- /// Gets a user's notifications.
- /// </summary>
- /// <response code="200">Notifications returned.</response>
- /// <returns>An <see cref="OkResult"/> containing a list of notifications.</returns>
- [HttpGet("{userId}")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- public ActionResult<NotificationResultDto> GetNotifications()
- {
- return new NotificationResultDto();
- }
-
- /// <summary>
- /// Gets a user's notification summary.
- /// </summary>
- /// <response code="200">Summary of user's notifications returned.</response>
- /// <returns>An <cref see="OkResult"/> containing a summary of the users notifications.</returns>
- [HttpGet("{userId}/Summary")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- public ActionResult<NotificationsSummaryDto> GetNotificationsSummary()
- {
- return new NotificationsSummaryDto();
}
/// <summary>
@@ -83,56 +49,5 @@ namespace Jellyfin.Api.Controllers
{
return _notificationManager.GetNotificationServices();
}
-
- /// <summary>
- /// Sends a notification to all admins.
- /// </summary>
- /// <param name="notificationDto">The notification request.</param>
- /// <response code="204">Notification sent.</response>
- /// <returns>A <cref see="NoContentResult"/>.</returns>
- [HttpPost("Admin")]
- [ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult CreateAdminNotification([FromBody, Required] AdminNotificationDto notificationDto)
- {
- var notification = new NotificationRequest
- {
- Name = notificationDto.Name,
- Description = notificationDto.Description,
- Url = notificationDto.Url,
- Level = notificationDto.NotificationLevel ?? NotificationLevel.Normal,
- UserIds = _userManager.Users
- .Where(user => user.HasPermission(PermissionKind.IsAdministrator))
- .Select(user => user.Id)
- .ToArray(),
- Date = DateTime.UtcNow,
- };
-
- _notificationManager.SendNotification(notification, CancellationToken.None);
- return NoContent();
- }
-
- /// <summary>
- /// Sets notifications as read.
- /// </summary>
- /// <response code="204">Notifications set as read.</response>
- /// <returns>A <cref see="NoContentResult"/>.</returns>
- [HttpPost("{userId}/Read")]
- [ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult SetRead()
- {
- return NoContent();
- }
-
- /// <summary>
- /// Sets notifications as unread.
- /// </summary>
- /// <response code="204">Notifications set as unread.</response>
- /// <returns>A <cref see="NoContentResult"/>.</returns>
- [HttpPost("{userId}/Unread")]
- [ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult SetUnread()
- {
- return NoContent();
- }
}
}
diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs
index 0aa7c2ac9..10f967dcd 100644
--- a/Jellyfin.Api/Controllers/PackageController.cs
+++ b/Jellyfin.Api/Controllers/PackageController.cs
@@ -145,7 +145,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<IEnumerable<RepositoryInfo>> GetRepositories()
{
- return _serverConfigurationManager.Configuration.PluginRepositories;
+ return Ok(_serverConfigurationManager.Configuration.PluginRepositories.AsEnumerable());
}
/// <summary>
@@ -157,7 +157,7 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Repositories")]
[Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult SetRepositories([FromBody, Required] List<RepositoryInfo> repositoryInfos)
+ public ActionResult SetRepositories([FromBody, Required] RepositoryInfo[] repositoryInfos)
{
_serverConfigurationManager.Configuration.PluginRepositories = repositoryInfos;
_serverConfigurationManager.SaveConfiguration();
diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs
index 6a729b237..b8a09990a 100644
--- a/Jellyfin.Api/Controllers/PluginsController.cs
+++ b/Jellyfin.Api/Controllers/PluginsController.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Text.Json;
@@ -143,7 +144,7 @@ namespace Jellyfin.Api.Controllers
public ActionResult UninstallPlugin([FromRoute, Required] Guid pluginId)
{
// If no version is given, return the current instance.
- var plugins = _pluginManager.Plugins.Where(p => p.Id.Equals(pluginId));
+ var plugins = _pluginManager.Plugins.Where(p => p.Id.Equals(pluginId)).ToList();
// Select the un-instanced one first.
var plugin = plugins.FirstOrDefault(p => p.Instance is null) ?? plugins.OrderBy(p => p.Manifest.Status).FirstOrDefault();
diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs
index ff9bd095b..c3ce1868e 100644
--- a/Jellyfin.Api/Controllers/SubtitleController.cs
+++ b/Jellyfin.Api/Controllers/SubtitleController.cs
@@ -236,14 +236,17 @@ namespace Jellyfin.Api.Controllers
if (string.Equals(format, "vtt", StringComparison.OrdinalIgnoreCase) && addVttTimeMap)
{
- await using Stream stream = await EncodeSubtitles(itemId.Value, mediaSourceId, index.Value, format, startPositionTicks, endPositionTicks, copyTimestamps).ConfigureAwait(false);
- using var reader = new StreamReader(stream);
+ Stream stream = await EncodeSubtitles(itemId.Value, mediaSourceId, index.Value, format, startPositionTicks, endPositionTicks, copyTimestamps).ConfigureAwait(false);
+ await using (stream.ConfigureAwait(false))
+ {
+ using var reader = new StreamReader(stream);
- var text = await reader.ReadToEndAsync().ConfigureAwait(false);
+ var text = await reader.ReadToEndAsync().ConfigureAwait(false);
- text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000", StringComparison.Ordinal);
+ text = text.Replace("WEBVTT", "WEBVTT\nX-TIMESTAMP-MAP=MPEGTS:900000,LOCAL:00:00:00.000", StringComparison.Ordinal);
- return File(Encoding.UTF8.GetBytes(text), MimeTypes.GetMimeType("file." + format));
+ return File(Encoding.UTF8.GetBytes(text), MimeTypes.GetMimeType("file." + format));
+ }
}
return File(
@@ -403,19 +406,22 @@ namespace Jellyfin.Api.Controllers
{
var video = (Video)_libraryManager.GetItemById(itemId);
var data = Convert.FromBase64String(body.Data);
- await using var memoryStream = new MemoryStream(data);
- await _subtitleManager.UploadSubtitle(
- video,
- new SubtitleResponse
- {
- Format = body.Format,
- Language = body.Language,
- IsForced = body.IsForced,
- Stream = memoryStream
- }).ConfigureAwait(false);
- _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.High);
+ var memoryStream = new MemoryStream(data, 0, data.Length, false, true);
+ await using (memoryStream.ConfigureAwait(false))
+ {
+ await _subtitleManager.UploadSubtitle(
+ video,
+ new SubtitleResponse
+ {
+ Format = body.Format,
+ Language = body.Language,
+ IsForced = body.IsForced,
+ Stream = memoryStream
+ }).ConfigureAwait(false);
+ _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.High);
- return NoContent();
+ return NoContent();
+ }
}
/// <summary>
diff --git a/Jellyfin.Api/Controllers/SyncPlayController.cs b/Jellyfin.Api/Controllers/SyncPlayController.cs
index e194fc556..99347246e 100644
--- a/Jellyfin.Api/Controllers/SyncPlayController.cs
+++ b/Jellyfin.Api/Controllers/SyncPlayController.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Api.Constants;
@@ -107,7 +108,7 @@ namespace Jellyfin.Api.Controllers
{
var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);
var syncPlayRequest = new ListGroupsRequest();
- return Ok(_syncPlayManager.ListGroups(currentSession, syncPlayRequest));
+ return Ok(_syncPlayManager.ListGroups(currentSession, syncPlayRequest).AsEnumerable());
}
/// <summary>
diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs
index 411c987f3..2d594293e 100644
--- a/Jellyfin.Api/Controllers/SystemController.cs
+++ b/Jellyfin.Api/Controllers/SystemController.cs
@@ -216,8 +216,7 @@ namespace Jellyfin.Api.Controllers
public ActionResult<IEnumerable<WakeOnLanInfo>> GetWakeOnLanInfo()
{
var result = _network.GetMacAddresses()
- .Select(i => new WakeOnLanInfo(i))
- .ToList();
+ .Select(i => new WakeOnLanInfo(i));
return Ok(result);
}
}
diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs
index c18fa29af..cd21c5f6f 100644
--- a/Jellyfin.Api/Controllers/UserLibraryController.cs
+++ b/Jellyfin.Api/Controllers/UserLibraryController.cs
@@ -211,7 +211,7 @@ namespace Jellyfin.Api.Controllers
if (item is IHasTrailers hasTrailers)
{
var trailers = hasTrailers.LocalTrailers;
- return Ok(_dtoService.GetBaseItemDtos(trailers, dtoOptions, user, item));
+ return Ok(_dtoService.GetBaseItemDtos(trailers, dtoOptions, user, item).AsEnumerable());
}
return Ok(item.GetExtras()