Make device/session code async

This commit is contained in:
Patrick Barron 2021-04-10 16:57:25 -04:00
parent 44e71774b1
commit 8607b52541
14 changed files with 160 additions and 132 deletions

View File

@ -171,7 +171,9 @@ namespace Emby.Dlna.PlayTo
uuid = uri.ToString().GetMD5().ToString("N", CultureInfo.InvariantCulture); uuid = uri.ToString().GetMD5().ToString("N", CultureInfo.InvariantCulture);
} }
var sessionInfo = _sessionManager.LogSessionActivity("DLNA", _appHost.ApplicationVersionString, uuid, null, uri.OriginalString, null); var sessionInfo = await _sessionManager
.LogSessionActivity("DLNA", _appHost.ApplicationVersionString, uuid, null, uri.OriginalString, null)
.ConfigureAwait(false);
var controller = sessionInfo.SessionControllers.OfType<PlayToController>().FirstOrDefault(); var controller = sessionInfo.SessionControllers.OfType<PlayToController>().FirstOrDefault();

View File

@ -1,6 +1,7 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System; using System;
using System.Threading.Tasks;
using Jellyfin.Data.Entities; using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
@ -23,7 +24,7 @@ namespace Emby.Server.Implementations.HttpServer.Security
_sessionManager = sessionManager; _sessionManager = sessionManager;
} }
public SessionInfo GetSession(HttpContext requestContext) public Task<SessionInfo> GetSession(HttpContext requestContext)
{ {
var authorization = _authContext.GetAuthorizationInfo(requestContext); var authorization = _authContext.GetAuthorizationInfo(requestContext);
@ -31,19 +32,19 @@ namespace Emby.Server.Implementations.HttpServer.Security
return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.GetNormalizedRemoteIp(), user); return _sessionManager.LogSessionActivity(authorization.Client, authorization.Version, authorization.DeviceId, authorization.Device, requestContext.GetNormalizedRemoteIp(), user);
} }
public SessionInfo GetSession(object requestContext) public Task<SessionInfo> GetSession(object requestContext)
{ {
return GetSession((HttpContext)requestContext); return GetSession((HttpContext)requestContext);
} }
public User GetUser(HttpContext requestContext) public async Task<User> GetUser(HttpContext requestContext)
{ {
var session = GetSession(requestContext); var session = await GetSession(requestContext).ConfigureAwait(false);
return session == null || session.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(session.UserId); return session == null || session.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(session.UserId);
} }
public User GetUser(object requestContext) public Task<User> GetUser(object requestContext)
{ {
return GetUser(((HttpRequest)requestContext).HttpContext); return GetUser(((HttpRequest)requestContext).HttpContext);
} }

View File

@ -254,7 +254,7 @@ namespace Emby.Server.Implementations.Session
/// <param name="remoteEndPoint">The remote end point.</param> /// <param name="remoteEndPoint">The remote end point.</param>
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
/// <returns>SessionInfo.</returns> /// <returns>SessionInfo.</returns>
public SessionInfo LogSessionActivity( public async Task<SessionInfo> LogSessionActivity(
string appName, string appName,
string appVersion, string appVersion,
string deviceId, string deviceId,
@ -280,7 +280,7 @@ namespace Emby.Server.Implementations.Session
} }
var activityDate = DateTime.UtcNow; var activityDate = DateTime.UtcNow;
var session = GetSessionInfo(appName, appVersion, deviceId, deviceName, remoteEndPoint, user); var session = await GetSessionInfo(appName, appVersion, deviceId, deviceName, remoteEndPoint, user).ConfigureAwait(false);
var lastActivityDate = session.LastActivityDate; var lastActivityDate = session.LastActivityDate;
session.LastActivityDate = activityDate; session.LastActivityDate = activityDate;
@ -458,7 +458,7 @@ namespace Emby.Server.Implementations.Session
/// <param name="remoteEndPoint">The remote end point.</param> /// <param name="remoteEndPoint">The remote end point.</param>
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
/// <returns>SessionInfo.</returns> /// <returns>SessionInfo.</returns>
private SessionInfo GetSessionInfo( private async Task<SessionInfo> GetSessionInfo(
string appName, string appName,
string appVersion, string appVersion,
string deviceId, string deviceId,
@ -477,9 +477,11 @@ namespace Emby.Server.Implementations.Session
CheckDisposed(); CheckDisposed();
var sessionInfo = _activeConnections.GetOrAdd( if (!_activeConnections.TryGetValue(key, out var sessionInfo))
key, {
k => CreateSession(k, appName, appVersion, deviceId, deviceName, remoteEndPoint, user)); _activeConnections[key] = await CreateSession(key, appName, appVersion, deviceId, deviceName, remoteEndPoint, user).ConfigureAwait(false);
sessionInfo = _activeConnections[key];
}
sessionInfo.UserId = user?.Id ?? Guid.Empty; sessionInfo.UserId = user?.Id ?? Guid.Empty;
sessionInfo.UserName = user?.Username; sessionInfo.UserName = user?.Username;
@ -502,7 +504,7 @@ namespace Emby.Server.Implementations.Session
return sessionInfo; return sessionInfo;
} }
private SessionInfo CreateSession( private async Task<SessionInfo> CreateSession(
string key, string key,
string appName, string appName,
string appVersion, string appVersion,
@ -532,7 +534,7 @@ namespace Emby.Server.Implementations.Session
deviceName = "Network Device"; deviceName = "Network Device";
} }
var deviceOptions = _deviceManager.GetDeviceOptions(deviceId); var deviceOptions = await _deviceManager.GetDeviceOptions(deviceId).ConfigureAwait(false);
if (string.IsNullOrEmpty(deviceOptions.CustomName)) if (string.IsNullOrEmpty(deviceOptions.CustomName))
{ {
sessionInfo.DeviceName = deviceName; sessionInfo.DeviceName = deviceName;
@ -1507,13 +1509,13 @@ namespace Emby.Server.Implementations.Session
var token = GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName); var token = GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName);
var session = LogSessionActivity( var session = await LogSessionActivity(
request.App, request.App,
request.AppVersion, request.AppVersion,
request.DeviceId, request.DeviceId,
request.DeviceName, request.DeviceName,
request.RemoteEndPoint, request.RemoteEndPoint,
user); user).ConfigureAwait(false);
var returnResult = new AuthenticationResult var returnResult = new AuthenticationResult
{ {
@ -1811,7 +1813,7 @@ namespace Emby.Server.Implementations.Session
} }
/// <inheritdoc /> /// <inheritdoc />
public SessionInfo GetSessionByAuthenticationToken(AuthenticationInfo info, string deviceId, string remoteEndpoint, string appVersion) public Task<SessionInfo> GetSessionByAuthenticationToken(AuthenticationInfo info, string deviceId, string remoteEndpoint, string appVersion)
{ {
if (info == null) if (info == null)
{ {
@ -1844,7 +1846,7 @@ namespace Emby.Server.Implementations.Session
} }
/// <inheritdoc /> /// <inheritdoc />
public SessionInfo GetSessionByAuthenticationToken(string token, string deviceId, string remoteEndpoint) public Task<SessionInfo> GetSessionByAuthenticationToken(string token, string deviceId, string remoteEndpoint)
{ {
var items = _authRepo.Get(new AuthenticationInfoQuery var items = _authRepo.Get(new AuthenticationInfoQuery
{ {

View File

@ -97,7 +97,7 @@ namespace Emby.Server.Implementations.Session
/// <inheritdoc /> /// <inheritdoc />
public async Task ProcessWebSocketConnectedAsync(IWebSocketConnection connection) public async Task ProcessWebSocketConnectedAsync(IWebSocketConnection connection)
{ {
var session = GetSession(connection.QueryString, connection.RemoteEndPoint.ToString()); var session = await GetSession(connection.QueryString, connection.RemoteEndPoint.ToString()).ConfigureAwait(false);
if (session != null) if (session != null)
{ {
EnsureController(session, connection); EnsureController(session, connection);
@ -109,7 +109,7 @@ namespace Emby.Server.Implementations.Session
} }
} }
private SessionInfo GetSession(IQueryCollection queryString, string remoteEndpoint) private Task<SessionInfo> GetSession(IQueryCollection queryString, string remoteEndpoint)
{ {
if (queryString == null) if (queryString == null)
{ {

View File

@ -86,9 +86,9 @@ namespace Jellyfin.Api.Controllers
[HttpGet("Options")] [HttpGet("Options")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<DeviceOptions> GetDeviceOptions([FromQuery, Required] string id) public async Task<ActionResult<DeviceOptions>> GetDeviceOptions([FromQuery, Required] string id)
{ {
var deviceInfo = _deviceManager.GetDeviceOptions(id); var deviceInfo = await _deviceManager.GetDeviceOptions(id).ConfigureAwait(false);
if (deviceInfo == null) if (deviceInfo == null)
{ {
return NotFound(); return NotFound();

View File

@ -429,10 +429,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Tuners/{tunerId}/Reset")] [HttpPost("Tuners/{tunerId}/Reset")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
public ActionResult ResetTuner([FromRoute, Required] string tunerId) public async Task<ActionResult> ResetTuner([FromRoute, Required] string tunerId)
{ {
AssertUserCanManageLiveTv(); await AssertUserCanManageLiveTv().ConfigureAwait(false);
_liveTvManager.ResetTuner(tunerId, CancellationToken.None); await _liveTvManager.ResetTuner(tunerId, CancellationToken.None).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -761,9 +761,9 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult DeleteRecording([FromRoute, Required] Guid recordingId) public async Task<ActionResult> DeleteRecording([FromRoute, Required] Guid recordingId)
{ {
AssertUserCanManageLiveTv(); await AssertUserCanManageLiveTv().ConfigureAwait(false);
var item = _libraryManager.GetItemById(recordingId); var item = _libraryManager.GetItemById(recordingId);
if (item == null) if (item == null)
@ -790,7 +790,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<ActionResult> CancelTimer([FromRoute, Required] string timerId) public async Task<ActionResult> CancelTimer([FromRoute, Required] string timerId)
{ {
AssertUserCanManageLiveTv(); await AssertUserCanManageLiveTv().ConfigureAwait(false);
await _liveTvManager.CancelTimer(timerId).ConfigureAwait(false); await _liveTvManager.CancelTimer(timerId).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -808,7 +808,7 @@ namespace Jellyfin.Api.Controllers
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")]
public async Task<ActionResult> UpdateTimer([FromRoute, Required] string timerId, [FromBody] TimerInfoDto timerInfo) public async Task<ActionResult> UpdateTimer([FromRoute, Required] string timerId, [FromBody] TimerInfoDto timerInfo)
{ {
AssertUserCanManageLiveTv(); await AssertUserCanManageLiveTv().ConfigureAwait(false);
await _liveTvManager.UpdateTimer(timerInfo, CancellationToken.None).ConfigureAwait(false); await _liveTvManager.UpdateTimer(timerInfo, CancellationToken.None).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -824,7 +824,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<ActionResult> CreateTimer([FromBody] TimerInfoDto timerInfo) public async Task<ActionResult> CreateTimer([FromBody] TimerInfoDto timerInfo)
{ {
AssertUserCanManageLiveTv(); await AssertUserCanManageLiveTv().ConfigureAwait(false);
await _liveTvManager.CreateTimer(timerInfo, CancellationToken.None).ConfigureAwait(false); await _liveTvManager.CreateTimer(timerInfo, CancellationToken.None).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -882,7 +882,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<ActionResult> CancelSeriesTimer([FromRoute, Required] string timerId) public async Task<ActionResult> CancelSeriesTimer([FromRoute, Required] string timerId)
{ {
AssertUserCanManageLiveTv(); await AssertUserCanManageLiveTv().ConfigureAwait(false);
await _liveTvManager.CancelSeriesTimer(timerId).ConfigureAwait(false); await _liveTvManager.CancelSeriesTimer(timerId).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -900,7 +900,7 @@ namespace Jellyfin.Api.Controllers
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")]
public async Task<ActionResult> UpdateSeriesTimer([FromRoute, Required] string timerId, [FromBody] SeriesTimerInfoDto seriesTimerInfo) public async Task<ActionResult> UpdateSeriesTimer([FromRoute, Required] string timerId, [FromBody] SeriesTimerInfoDto seriesTimerInfo)
{ {
AssertUserCanManageLiveTv(); await AssertUserCanManageLiveTv().ConfigureAwait(false);
await _liveTvManager.UpdateSeriesTimer(seriesTimerInfo, CancellationToken.None).ConfigureAwait(false); await _liveTvManager.UpdateSeriesTimer(seriesTimerInfo, CancellationToken.None).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -916,7 +916,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<ActionResult> CreateSeriesTimer([FromBody] SeriesTimerInfoDto seriesTimerInfo) public async Task<ActionResult> CreateSeriesTimer([FromBody] SeriesTimerInfoDto seriesTimerInfo)
{ {
AssertUserCanManageLiveTv(); await AssertUserCanManageLiveTv().ConfigureAwait(false);
await _liveTvManager.CreateSeriesTimer(seriesTimerInfo, CancellationToken.None).ConfigureAwait(false); await _liveTvManager.CreateSeriesTimer(seriesTimerInfo, CancellationToken.None).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -1215,9 +1215,9 @@ namespace Jellyfin.Api.Controllers
return new FileStreamResult(liveStream, MimeTypes.GetMimeType("file." + container)); return new FileStreamResult(liveStream, MimeTypes.GetMimeType("file." + container));
} }
private void AssertUserCanManageLiveTv() private async Task AssertUserCanManageLiveTv()
{ {
var user = _sessionContext.GetUser(Request); var user = await _sessionContext.GetUser(Request).ConfigureAwait(false);
if (user == null) if (user == null)
{ {

View File

@ -72,13 +72,13 @@ namespace Jellyfin.Api.Controllers
/// <returns>An <see cref="OkResult"/> containing the <see cref="UserItemDataDto"/>.</returns> /// <returns>An <see cref="OkResult"/> containing the <see cref="UserItemDataDto"/>.</returns>
[HttpPost("Users/{userId}/PlayedItems/{itemId}")] [HttpPost("Users/{userId}/PlayedItems/{itemId}")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<UserItemDataDto> MarkPlayedItem( public async Task<ActionResult<UserItemDataDto>> MarkPlayedItem(
[FromRoute, Required] Guid userId, [FromRoute, Required] Guid userId,
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? datePlayed) [FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? datePlayed)
{ {
var user = _userManager.GetUserById(userId); var user = _userManager.GetUserById(userId);
var session = RequestHelpers.GetSession(_sessionManager, _authContext, Request); var session = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false);
var dto = UpdatePlayedStatus(user, itemId, true, datePlayed); var dto = UpdatePlayedStatus(user, itemId, true, datePlayed);
foreach (var additionalUserInfo in session.AdditionalUsers) foreach (var additionalUserInfo in session.AdditionalUsers)
{ {
@ -98,10 +98,10 @@ namespace Jellyfin.Api.Controllers
/// <returns>A <see cref="OkResult"/> containing the <see cref="UserItemDataDto"/>.</returns> /// <returns>A <see cref="OkResult"/> containing the <see cref="UserItemDataDto"/>.</returns>
[HttpDelete("Users/{userId}/PlayedItems/{itemId}")] [HttpDelete("Users/{userId}/PlayedItems/{itemId}")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<UserItemDataDto> MarkUnplayedItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) public async Task<ActionResult<UserItemDataDto>> MarkUnplayedItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId)
{ {
var user = _userManager.GetUserById(userId); var user = _userManager.GetUserById(userId);
var session = RequestHelpers.GetSession(_sessionManager, _authContext, Request); var session = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false);
var dto = UpdatePlayedStatus(user, itemId, false, null); var dto = UpdatePlayedStatus(user, itemId, false, null);
foreach (var additionalUserInfo in session.AdditionalUsers) foreach (var additionalUserInfo in session.AdditionalUsers)
{ {
@ -123,7 +123,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> ReportPlaybackStart([FromBody] PlaybackStartInfo playbackStartInfo) public async Task<ActionResult> ReportPlaybackStart([FromBody] PlaybackStartInfo playbackStartInfo)
{ {
playbackStartInfo.PlayMethod = ValidatePlayMethod(playbackStartInfo.PlayMethod, playbackStartInfo.PlaySessionId); playbackStartInfo.PlayMethod = ValidatePlayMethod(playbackStartInfo.PlayMethod, playbackStartInfo.PlaySessionId);
playbackStartInfo.SessionId = RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id; playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false);
await _sessionManager.OnPlaybackStart(playbackStartInfo).ConfigureAwait(false); await _sessionManager.OnPlaybackStart(playbackStartInfo).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -139,7 +139,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> ReportPlaybackProgress([FromBody] PlaybackProgressInfo playbackProgressInfo) public async Task<ActionResult> ReportPlaybackProgress([FromBody] PlaybackProgressInfo playbackProgressInfo)
{ {
playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId); playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId);
playbackProgressInfo.SessionId = RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id; playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false);
await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false); await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -174,7 +174,7 @@ namespace Jellyfin.Api.Controllers
await _transcodingJobHelper.KillTranscodingJobs(_authContext.GetAuthorizationInfo(Request).DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); await _transcodingJobHelper.KillTranscodingJobs(_authContext.GetAuthorizationInfo(Request).DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false);
} }
playbackStopInfo.SessionId = RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id; playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false);
await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false); await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -220,7 +220,7 @@ namespace Jellyfin.Api.Controllers
}; };
playbackStartInfo.PlayMethod = ValidatePlayMethod(playbackStartInfo.PlayMethod, playbackStartInfo.PlaySessionId); playbackStartInfo.PlayMethod = ValidatePlayMethod(playbackStartInfo.PlayMethod, playbackStartInfo.PlaySessionId);
playbackStartInfo.SessionId = RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id; playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false);
await _sessionManager.OnPlaybackStart(playbackStartInfo).ConfigureAwait(false); await _sessionManager.OnPlaybackStart(playbackStartInfo).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -278,7 +278,7 @@ namespace Jellyfin.Api.Controllers
}; };
playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId); playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId);
playbackProgressInfo.SessionId = RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id; playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false);
await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false); await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -323,7 +323,7 @@ namespace Jellyfin.Api.Controllers
await _transcodingJobHelper.KillTranscodingJobs(_authContext.GetAuthorizationInfo(Request).DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); await _transcodingJobHelper.KillTranscodingJobs(_authContext.GetAuthorizationInfo(Request).DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false);
} }
playbackStopInfo.SessionId = RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id; playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false);
await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false); await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false);
return NoContent(); return NoContent();
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders; using Jellyfin.Api.ModelBinders;
@ -124,7 +125,7 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Sessions/{sessionId}/Viewing")] [HttpPost("Sessions/{sessionId}/Viewing")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult DisplayContent( public async Task<ActionResult> DisplayContent(
[FromRoute, Required] string sessionId, [FromRoute, Required] string sessionId,
[FromQuery, Required] string itemType, [FromQuery, Required] string itemType,
[FromQuery, Required] string itemId, [FromQuery, Required] string itemId,
@ -137,11 +138,12 @@ namespace Jellyfin.Api.Controllers
ItemType = itemType ItemType = itemType
}; };
_sessionManager.SendBrowseCommand( await _sessionManager.SendBrowseCommand(
RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id, await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false),
sessionId, sessionId,
command, command,
CancellationToken.None); CancellationToken.None)
.ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -158,7 +160,7 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Sessions/{sessionId}/Playing")] [HttpPost("Sessions/{sessionId}/Playing")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult Play( public async Task<ActionResult> Play(
[FromRoute, Required] string sessionId, [FromRoute, Required] string sessionId,
[FromQuery, Required] PlayCommand playCommand, [FromQuery, Required] PlayCommand playCommand,
[FromQuery, Required, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] itemIds, [FromQuery, Required, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] itemIds,
@ -171,11 +173,12 @@ namespace Jellyfin.Api.Controllers
PlayCommand = playCommand PlayCommand = playCommand
}; };
_sessionManager.SendPlayCommand( await _sessionManager.SendPlayCommand(
RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id, await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false),
sessionId, sessionId,
playRequest, playRequest,
CancellationToken.None); CancellationToken.None)
.ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -192,14 +195,14 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Sessions/{sessionId}/Playing/{command}")] [HttpPost("Sessions/{sessionId}/Playing/{command}")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendPlaystateCommand( public async Task<ActionResult> SendPlaystateCommand(
[FromRoute, Required] string sessionId, [FromRoute, Required] string sessionId,
[FromRoute, Required] PlaystateCommand command, [FromRoute, Required] PlaystateCommand command,
[FromQuery] long? seekPositionTicks, [FromQuery] long? seekPositionTicks,
[FromQuery] string? controllingUserId) [FromQuery] string? controllingUserId)
{ {
_sessionManager.SendPlaystateCommand( await _sessionManager.SendPlaystateCommand(
RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id, await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false),
sessionId, sessionId,
new PlaystateRequest() new PlaystateRequest()
{ {
@ -207,7 +210,8 @@ namespace Jellyfin.Api.Controllers
ControllingUserId = controllingUserId, ControllingUserId = controllingUserId,
SeekPositionTicks = seekPositionTicks, SeekPositionTicks = seekPositionTicks,
}, },
CancellationToken.None); CancellationToken.None)
.ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -222,18 +226,18 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Sessions/{sessionId}/System/{command}")] [HttpPost("Sessions/{sessionId}/System/{command}")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendSystemCommand( public async Task<ActionResult> SendSystemCommand(
[FromRoute, Required] string sessionId, [FromRoute, Required] string sessionId,
[FromRoute, Required] GeneralCommandType command) [FromRoute, Required] GeneralCommandType command)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false);
var generalCommand = new GeneralCommand var generalCommand = new GeneralCommand
{ {
Name = command, Name = command,
ControllingUserId = currentSession.UserId ControllingUserId = currentSession.UserId
}; };
_sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None); await _sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None);
return NoContent(); return NoContent();
} }
@ -248,11 +252,11 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Sessions/{sessionId}/Command/{command}")] [HttpPost("Sessions/{sessionId}/Command/{command}")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendGeneralCommand( public async Task<ActionResult> SendGeneralCommand(
[FromRoute, Required] string sessionId, [FromRoute, Required] string sessionId,
[FromRoute, Required] GeneralCommandType command) [FromRoute, Required] GeneralCommandType command)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false);
var generalCommand = new GeneralCommand var generalCommand = new GeneralCommand
{ {
@ -260,7 +264,8 @@ namespace Jellyfin.Api.Controllers
ControllingUserId = currentSession.UserId ControllingUserId = currentSession.UserId
}; };
_sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None); await _sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None)
.ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -275,11 +280,12 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Sessions/{sessionId}/Command")] [HttpPost("Sessions/{sessionId}/Command")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendFullGeneralCommand( public async Task<ActionResult> SendFullGeneralCommand(
[FromRoute, Required] string sessionId, [FromRoute, Required] string sessionId,
[FromBody, Required] GeneralCommand command) [FromBody, Required] GeneralCommand command)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authContext, Request)
.ConfigureAwait(false);
if (command == null) if (command == null)
{ {
@ -288,11 +294,12 @@ namespace Jellyfin.Api.Controllers
command.ControllingUserId = currentSession.UserId; command.ControllingUserId = currentSession.UserId;
_sessionManager.SendGeneralCommand( await _sessionManager.SendGeneralCommand(
currentSession.Id, currentSession.Id,
sessionId, sessionId,
command, command,
CancellationToken.None); CancellationToken.None)
.ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -309,7 +316,7 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Sessions/{sessionId}/Message")] [HttpPost("Sessions/{sessionId}/Message")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendMessageCommand( public async Task<ActionResult> SendMessageCommand(
[FromRoute, Required] string sessionId, [FromRoute, Required] string sessionId,
[FromQuery, Required] string text, [FromQuery, Required] string text,
[FromQuery] string? header, [FromQuery] string? header,
@ -322,7 +329,12 @@ namespace Jellyfin.Api.Controllers
Text = text Text = text
}; };
_sessionManager.SendMessageCommand(RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id, sessionId, command, CancellationToken.None); await _sessionManager.SendMessageCommand(
await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false),
sessionId,
command,
CancellationToken.None)
.ConfigureAwait(false);
return NoContent(); return NoContent();
} }
@ -377,7 +389,7 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Sessions/Capabilities")] [HttpPost("Sessions/Capabilities")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult PostCapabilities( public async Task<ActionResult> PostCapabilities(
[FromQuery] string? id, [FromQuery] string? id,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] playableMediaTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] playableMediaTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] GeneralCommandType[] supportedCommands, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] GeneralCommandType[] supportedCommands,
@ -387,7 +399,7 @@ namespace Jellyfin.Api.Controllers
{ {
if (string.IsNullOrWhiteSpace(id)) if (string.IsNullOrWhiteSpace(id))
{ {
id = RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id; id = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false);
} }
_sessionManager.ReportCapabilities(id, new ClientCapabilities _sessionManager.ReportCapabilities(id, new ClientCapabilities
@ -411,13 +423,13 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Sessions/Capabilities/Full")] [HttpPost("Sessions/Capabilities/Full")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult PostFullCapabilities( public async Task<ActionResult> PostFullCapabilities(
[FromQuery] string? id, [FromQuery] string? id,
[FromBody, Required] ClientCapabilitiesDto capabilities) [FromBody, Required] ClientCapabilitiesDto capabilities)
{ {
if (string.IsNullOrWhiteSpace(id)) if (string.IsNullOrWhiteSpace(id))
{ {
id = RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id; id = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false);
} }
_sessionManager.ReportCapabilities(id, capabilities.ToClientCapabilities()); _sessionManager.ReportCapabilities(id, capabilities.ToClientCapabilities());
@ -435,11 +447,11 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Sessions/Viewing")] [HttpPost("Sessions/Viewing")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult ReportViewing( public async Task<ActionResult> ReportViewing(
[FromQuery] string? sessionId, [FromQuery] string? sessionId,
[FromQuery, Required] string? itemId) [FromQuery, Required] string? itemId)
{ {
string session = sessionId ?? RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id; string session = sessionId ?? await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false);
_sessionManager.ReportNowViewingItem(session, itemId); _sessionManager.ReportNowViewingItem(session, itemId);
return NoContent(); return NoContent();

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Api.Constants; using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers; using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.SyncPlayDtos; using Jellyfin.Api.Models.SyncPlayDtos;
@ -51,10 +52,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("New")] [HttpPost("New")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayCreateGroup)] [Authorize(Policy = Policies.SyncPlayCreateGroup)]
public ActionResult SyncPlayCreateGroup( public async Task<ActionResult> SyncPlayCreateGroup(
[FromBody, Required] NewGroupRequestDto requestData) [FromBody, Required] NewGroupRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new NewGroupRequest(requestData.GroupName); var syncPlayRequest = new NewGroupRequest(requestData.GroupName);
_syncPlayManager.NewGroup(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.NewGroup(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -69,10 +70,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Join")] [HttpPost("Join")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayJoinGroup)] [Authorize(Policy = Policies.SyncPlayJoinGroup)]
public ActionResult SyncPlayJoinGroup( public async Task<ActionResult> SyncPlayJoinGroup(
[FromBody, Required] JoinGroupRequestDto requestData) [FromBody, Required] JoinGroupRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new JoinGroupRequest(requestData.GroupId); var syncPlayRequest = new JoinGroupRequest(requestData.GroupId);
_syncPlayManager.JoinGroup(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.JoinGroup(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -86,9 +87,9 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Leave")] [HttpPost("Leave")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlayLeaveGroup() public async Task<ActionResult> SyncPlayLeaveGroup()
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new LeaveGroupRequest(); var syncPlayRequest = new LeaveGroupRequest();
_syncPlayManager.LeaveGroup(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.LeaveGroup(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -102,9 +103,9 @@ namespace Jellyfin.Api.Controllers
[HttpGet("List")] [HttpGet("List")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[Authorize(Policy = Policies.SyncPlayJoinGroup)] [Authorize(Policy = Policies.SyncPlayJoinGroup)]
public ActionResult<IEnumerable<GroupInfoDto>> SyncPlayGetGroups() public async Task<ActionResult<IEnumerable<GroupInfoDto>>> SyncPlayGetGroups()
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new ListGroupsRequest(); var syncPlayRequest = new ListGroupsRequest();
return Ok(_syncPlayManager.ListGroups(currentSession, syncPlayRequest)); return Ok(_syncPlayManager.ListGroups(currentSession, syncPlayRequest));
} }
@ -118,10 +119,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("SetNewQueue")] [HttpPost("SetNewQueue")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlaySetNewQueue( public async Task<ActionResult> SyncPlaySetNewQueue(
[FromBody, Required] PlayRequestDto requestData) [FromBody, Required] PlayRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new PlayGroupRequest( var syncPlayRequest = new PlayGroupRequest(
requestData.PlayingQueue, requestData.PlayingQueue,
requestData.PlayingItemPosition, requestData.PlayingItemPosition,
@ -139,10 +140,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("SetPlaylistItem")] [HttpPost("SetPlaylistItem")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlaySetPlaylistItem( public async Task<ActionResult> SyncPlaySetPlaylistItem(
[FromBody, Required] SetPlaylistItemRequestDto requestData) [FromBody, Required] SetPlaylistItemRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new SetPlaylistItemGroupRequest(requestData.PlaylistItemId); var syncPlayRequest = new SetPlaylistItemGroupRequest(requestData.PlaylistItemId);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -157,10 +158,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("RemoveFromPlaylist")] [HttpPost("RemoveFromPlaylist")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlayRemoveFromPlaylist( public async Task<ActionResult> SyncPlayRemoveFromPlaylist(
[FromBody, Required] RemoveFromPlaylistRequestDto requestData) [FromBody, Required] RemoveFromPlaylistRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new RemoveFromPlaylistGroupRequest(requestData.PlaylistItemIds); var syncPlayRequest = new RemoveFromPlaylistGroupRequest(requestData.PlaylistItemIds);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -175,10 +176,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("MovePlaylistItem")] [HttpPost("MovePlaylistItem")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlayMovePlaylistItem( public async Task<ActionResult> SyncPlayMovePlaylistItem(
[FromBody, Required] MovePlaylistItemRequestDto requestData) [FromBody, Required] MovePlaylistItemRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new MovePlaylistItemGroupRequest(requestData.PlaylistItemId, requestData.NewIndex); var syncPlayRequest = new MovePlaylistItemGroupRequest(requestData.PlaylistItemId, requestData.NewIndex);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -193,10 +194,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Queue")] [HttpPost("Queue")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlayQueue( public async Task<ActionResult> SyncPlayQueue(
[FromBody, Required] QueueRequestDto requestData) [FromBody, Required] QueueRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new QueueGroupRequest(requestData.ItemIds, requestData.Mode); var syncPlayRequest = new QueueGroupRequest(requestData.ItemIds, requestData.Mode);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -210,9 +211,9 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Unpause")] [HttpPost("Unpause")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlayUnpause() public async Task<ActionResult> SyncPlayUnpause()
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new UnpauseGroupRequest(); var syncPlayRequest = new UnpauseGroupRequest();
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -226,9 +227,9 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Pause")] [HttpPost("Pause")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlayPause() public async Task<ActionResult> SyncPlayPause()
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new PauseGroupRequest(); var syncPlayRequest = new PauseGroupRequest();
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -242,9 +243,9 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Stop")] [HttpPost("Stop")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlayStop() public async Task<ActionResult> SyncPlayStop()
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new StopGroupRequest(); var syncPlayRequest = new StopGroupRequest();
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -259,10 +260,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Seek")] [HttpPost("Seek")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlaySeek( public async Task<ActionResult> SyncPlaySeek(
[FromBody, Required] SeekRequestDto requestData) [FromBody, Required] SeekRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new SeekGroupRequest(requestData.PositionTicks); var syncPlayRequest = new SeekGroupRequest(requestData.PositionTicks);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -277,10 +278,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Buffering")] [HttpPost("Buffering")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlayBuffering( public async Task<ActionResult> SyncPlayBuffering(
[FromBody, Required] BufferRequestDto requestData) [FromBody, Required] BufferRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new BufferGroupRequest( var syncPlayRequest = new BufferGroupRequest(
requestData.When, requestData.When,
requestData.PositionTicks, requestData.PositionTicks,
@ -299,10 +300,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Ready")] [HttpPost("Ready")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlayReady( public async Task<ActionResult> SyncPlayReady(
[FromBody, Required] ReadyRequestDto requestData) [FromBody, Required] ReadyRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new ReadyGroupRequest( var syncPlayRequest = new ReadyGroupRequest(
requestData.When, requestData.When,
requestData.PositionTicks, requestData.PositionTicks,
@ -321,10 +322,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("SetIgnoreWait")] [HttpPost("SetIgnoreWait")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlaySetIgnoreWait( public async Task<ActionResult> SyncPlaySetIgnoreWait(
[FromBody, Required] IgnoreWaitRequestDto requestData) [FromBody, Required] IgnoreWaitRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new IgnoreWaitGroupRequest(requestData.IgnoreWait); var syncPlayRequest = new IgnoreWaitGroupRequest(requestData.IgnoreWait);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -339,10 +340,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("NextItem")] [HttpPost("NextItem")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlayNextItem( public async Task<ActionResult> SyncPlayNextItem(
[FromBody, Required] NextItemRequestDto requestData) [FromBody, Required] NextItemRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new NextItemGroupRequest(requestData.PlaylistItemId); var syncPlayRequest = new NextItemGroupRequest(requestData.PlaylistItemId);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -357,10 +358,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("PreviousItem")] [HttpPost("PreviousItem")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlayPreviousItem( public async Task<ActionResult> SyncPlayPreviousItem(
[FromBody, Required] PreviousItemRequestDto requestData) [FromBody, Required] PreviousItemRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new PreviousItemGroupRequest(requestData.PlaylistItemId); var syncPlayRequest = new PreviousItemGroupRequest(requestData.PlaylistItemId);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -375,10 +376,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("SetRepeatMode")] [HttpPost("SetRepeatMode")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlaySetRepeatMode( public async Task<ActionResult> SyncPlaySetRepeatMode(
[FromBody, Required] SetRepeatModeRequestDto requestData) [FromBody, Required] SetRepeatModeRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new SetRepeatModeGroupRequest(requestData.Mode); var syncPlayRequest = new SetRepeatModeGroupRequest(requestData.Mode);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -393,10 +394,10 @@ namespace Jellyfin.Api.Controllers
[HttpPost("SetShuffleMode")] [HttpPost("SetShuffleMode")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[Authorize(Policy = Policies.SyncPlayIsInGroup)] [Authorize(Policy = Policies.SyncPlayIsInGroup)]
public ActionResult SyncPlaySetShuffleMode( public async Task<ActionResult> SyncPlaySetShuffleMode(
[FromBody, Required] SetShuffleModeRequestDto requestData) [FromBody, Required] SetShuffleModeRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new SetShuffleModeGroupRequest(requestData.Mode); var syncPlayRequest = new SetShuffleModeGroupRequest(requestData.Mode);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();
@ -410,10 +411,10 @@ namespace Jellyfin.Api.Controllers
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns> /// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
[HttpPost("Ping")] [HttpPost("Ping")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SyncPlayPing( public async Task<ActionResult> SyncPlayPing(
[FromBody, Required] PingRequestDto requestData) [FromBody, Required] PingRequestDto requestData)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false);
var syncPlayRequest = new PingGroupRequest(requestData.Ping); var syncPlayRequest = new PingGroupRequest(requestData.Ping);
_syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
return NoContent(); return NoContent();

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Jellyfin.Data.Entities; using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums; using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
@ -75,17 +76,17 @@ namespace Jellyfin.Api.Helpers
return true; return true;
} }
internal static SessionInfo GetSession(ISessionManager sessionManager, IAuthorizationContext authContext, HttpRequest request) internal static async Task<SessionInfo> GetSession(ISessionManager sessionManager, IAuthorizationContext authContext, HttpRequest request)
{ {
var authorization = authContext.GetAuthorizationInfo(request); var authorization = authContext.GetAuthorizationInfo(request);
var user = authorization.User; var user = authorization.User;
var session = sessionManager.LogSessionActivity( var session = await sessionManager.LogSessionActivity(
authorization.Client, authorization.Client,
authorization.Version, authorization.Version,
authorization.DeviceId, authorization.DeviceId,
authorization.Device, authorization.Device,
request.HttpContext.GetNormalizedRemoteIp(), request.HttpContext.GetNormalizedRemoteIp(),
user); user).ConfigureAwait(false);
if (session == null) if (session == null)
{ {
@ -95,6 +96,13 @@ namespace Jellyfin.Api.Helpers
return session; return session;
} }
internal static async Task<string> GetSessionId(ISessionManager sessionManager, IAuthorizationContext authContext, HttpRequest request)
{
var session = await GetSession(sessionManager, authContext, request).ConfigureAwait(false);
return session.Id;
}
internal static QueryResult<BaseItemDto> CreateQueryResult( internal static QueryResult<BaseItemDto> CreateQueryResult(
QueryResult<(BaseItem, ItemCounts)> result, QueryResult<(BaseItem, ItemCounts)> result,
DtoOptions dtoOptions, DtoOptions dtoOptions,

View File

@ -53,12 +53,13 @@ namespace Jellyfin.Server.Implementations.Devices
} }
/// <inheritdoc /> /// <inheritdoc />
public DeviceOptions? GetDeviceOptions(string deviceId) public async Task<DeviceOptions?> GetDeviceOptions(string deviceId)
{ {
using var dbContext = _dbProvider.CreateContext(); await using var dbContext = _dbProvider.CreateContext();
return dbContext.DeviceOptions return await dbContext.DeviceOptions
.AsQueryable() .AsQueryable()
.FirstOrDefault(d => d.DeviceId == deviceId); .FirstOrDefaultAsync(d => d.DeviceId == deviceId)
.ConfigureAwait(false);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -50,6 +50,6 @@ namespace MediaBrowser.Controller.Devices
Task UpdateDeviceOptions(string deviceId, DeviceOptions options); Task UpdateDeviceOptions(string deviceId, DeviceOptions options);
DeviceOptions GetDeviceOptions(string deviceId); Task<DeviceOptions> GetDeviceOptions(string deviceId);
} }
} }

View File

@ -1,5 +1,6 @@
#pragma warning disable CS1591 #pragma warning disable CS1591
using System.Threading.Tasks;
using Jellyfin.Data.Entities; using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -8,12 +9,12 @@ namespace MediaBrowser.Controller.Net
{ {
public interface ISessionContext public interface ISessionContext
{ {
SessionInfo GetSession(object requestContext); Task<SessionInfo> GetSession(object requestContext);
User GetUser(object requestContext); Task<User> GetUser(object requestContext);
SessionInfo GetSession(HttpContext requestContext); Task<SessionInfo> GetSession(HttpContext requestContext);
User GetUser(HttpContext requestContext); Task<User> GetUser(HttpContext requestContext);
} }
} }

View File

@ -80,7 +80,7 @@ namespace MediaBrowser.Controller.Session
/// <param name="deviceName">Name of the device.</param> /// <param name="deviceName">Name of the device.</param>
/// <param name="remoteEndPoint">The remote end point.</param> /// <param name="remoteEndPoint">The remote end point.</param>
/// <param name="user">The user.</param> /// <param name="user">The user.</param>
SessionInfo LogSessionActivity(string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, Jellyfin.Data.Entities.User user); Task<SessionInfo> LogSessionActivity(string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, Jellyfin.Data.Entities.User user);
/// <summary> /// <summary>
/// Used to report that a session controller has connected. /// Used to report that a session controller has connected.
@ -313,7 +313,7 @@ namespace MediaBrowser.Controller.Session
/// <param name="deviceId">The device identifier.</param> /// <param name="deviceId">The device identifier.</param>
/// <param name="remoteEndpoint">The remote endpoint.</param> /// <param name="remoteEndpoint">The remote endpoint.</param>
/// <returns>SessionInfo.</returns> /// <returns>SessionInfo.</returns>
SessionInfo GetSessionByAuthenticationToken(string token, string deviceId, string remoteEndpoint); Task<SessionInfo> GetSessionByAuthenticationToken(string token, string deviceId, string remoteEndpoint);
/// <summary> /// <summary>
/// Gets the session by authentication token. /// Gets the session by authentication token.
@ -323,7 +323,7 @@ namespace MediaBrowser.Controller.Session
/// <param name="remoteEndpoint">The remote endpoint.</param> /// <param name="remoteEndpoint">The remote endpoint.</param>
/// <param name="appVersion">The application version.</param> /// <param name="appVersion">The application version.</param>
/// <returns>Task&lt;SessionInfo&gt;.</returns> /// <returns>Task&lt;SessionInfo&gt;.</returns>
SessionInfo GetSessionByAuthenticationToken(AuthenticationInfo info, string deviceId, string remoteEndpoint, string appVersion); Task<SessionInfo> GetSessionByAuthenticationToken(AuthenticationInfo info, string deviceId, string remoteEndpoint, string appVersion);
/// <summary> /// <summary>
/// Logouts the specified access token. /// Logouts the specified access token.