using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.UserViewDtos; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Library; using MediaBrowser.Model.Querying; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Api.Controllers; /// /// User views controller. /// [Route("")] [Authorize] public class UserViewsController : BaseJellyfinApiController { private readonly IUserManager _userManager; private readonly IUserViewManager _userViewManager; private readonly IDtoService _dtoService; private readonly ILibraryManager _libraryManager; /// /// Initializes a new instance of the class. /// /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. public UserViewsController( IUserManager userManager, IUserViewManager userViewManager, IDtoService dtoService, ILibraryManager libraryManager) { _userManager = userManager; _userViewManager = userViewManager; _dtoService = dtoService; _libraryManager = libraryManager; } /// /// Get user views. /// /// User id. /// Whether or not to include external views such as channels or live tv. /// Preset views. /// Whether or not to include hidden content. /// User views returned. /// An containing the user views. [HttpGet("UserViews")] [ProducesResponseType(StatusCodes.Status200OK)] public QueryResult GetUserViews( [FromQuery] Guid? userId, [FromQuery] bool? includeExternalContent, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] CollectionType?[] presetViews, [FromQuery] bool includeHidden = false) { userId = RequestHelpers.GetUserId(User, userId); var query = new UserViewQuery { UserId = userId.Value, IncludeHidden = includeHidden }; if (includeExternalContent.HasValue) { query.IncludeExternalContent = includeExternalContent.Value; } if (presetViews.Length != 0) { query.PresetViews = presetViews; } var folders = _userViewManager.GetUserViews(query); var dtoOptions = new DtoOptions().AddClientFields(User); dtoOptions.Fields = [..dtoOptions.Fields, ItemFields.PrimaryImageAspectRatio, ItemFields.DisplayPreferencesId]; var user = _userManager.GetUserById(userId.Value); var dtos = Array.ConvertAll(folders, i => _dtoService.GetBaseItemDto(i, dtoOptions, user)); return new QueryResult(dtos); } /// /// Get user views. /// /// User id. /// Whether or not to include external views such as channels or live tv. /// Preset views. /// Whether or not to include hidden content. /// User views returned. /// An containing the user views. [HttpGet("Users/{userId}/Views")] [ProducesResponseType(StatusCodes.Status200OK)] [Obsolete("Kept for backwards compatibility")] [ApiExplorerSettings(IgnoreApi = true)] public QueryResult GetUserViewsLegacy( [FromRoute, Required] Guid userId, [FromQuery] bool? includeExternalContent, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] CollectionType?[] presetViews, [FromQuery] bool includeHidden = false) => GetUserViews(userId, includeExternalContent, presetViews, includeHidden); /// /// Get user view grouping options. /// /// User id. /// User view grouping options returned. /// User not found. /// /// An containing the user view grouping options /// or a if user not found. /// [HttpGet("UserViews/GroupingOptions")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult> GetGroupingOptions([FromQuery] Guid? userId) { userId = RequestHelpers.GetUserId(User, userId); var user = _userManager.GetUserById(userId.Value); if (user is null) { return NotFound(); } return Ok(_libraryManager.GetUserRootFolder() .GetChildren(user, true) .OfType() .Where(UserView.IsEligibleForGrouping) .Select(i => new SpecialViewOptionDto { Name = i.Name, Id = i.Id.ToString("N", CultureInfo.InvariantCulture) }) .OrderBy(i => i.Name) .AsEnumerable()); } /// /// Get user view grouping options. /// /// User id. /// User view grouping options returned. /// User not found. /// /// An containing the user view grouping options /// or a if user not found. /// [HttpGet("Users/{userId}/GroupingOptions")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Obsolete("Kept for backwards compatibility")] [ApiExplorerSettings(IgnoreApi = true)] public ActionResult> GetGroupingOptionsLegacy( [FromRoute, Required] Guid userId) => GetGroupingOptions(userId); }