aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api/Controllers/MoviesController.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api/Controllers/MoviesController.cs')
-rw-r--r--Jellyfin.Api/Controllers/MoviesController.cs472
1 files changed, 236 insertions, 236 deletions
diff --git a/Jellyfin.Api/Controllers/MoviesController.cs b/Jellyfin.Api/Controllers/MoviesController.cs
index 3cf079362..e1145481f 100644
--- a/Jellyfin.Api/Controllers/MoviesController.cs
+++ b/Jellyfin.Api/Controllers/MoviesController.cs
@@ -2,8 +2,8 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
+using Jellyfin.Api.Helpers;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
@@ -18,122 +18,123 @@ using MediaBrowser.Model.Querying;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-namespace Jellyfin.Api.Controllers
+namespace Jellyfin.Api.Controllers;
+
+/// <summary>
+/// Movies controller.
+/// </summary>
+[Authorize]
+public class MoviesController : BaseJellyfinApiController
{
+ private readonly IUserManager _userManager;
+ private readonly ILibraryManager _libraryManager;
+ private readonly IDtoService _dtoService;
+ private readonly IServerConfigurationManager _serverConfigurationManager;
+
/// <summary>
- /// Movies controller.
+ /// Initializes a new instance of the <see cref="MoviesController"/> class.
/// </summary>
- [Authorize(Policy = Policies.DefaultAuthorization)]
- public class MoviesController : BaseJellyfinApiController
+ /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
+ /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
+ /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
+ /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
+ public MoviesController(
+ IUserManager userManager,
+ ILibraryManager libraryManager,
+ IDtoService dtoService,
+ IServerConfigurationManager serverConfigurationManager)
{
- private readonly IUserManager _userManager;
- private readonly ILibraryManager _libraryManager;
- private readonly IDtoService _dtoService;
- private readonly IServerConfigurationManager _serverConfigurationManager;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="MoviesController"/> class.
- /// </summary>
- /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
- /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
- /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
- /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
- public MoviesController(
- IUserManager userManager,
- ILibraryManager libraryManager,
- IDtoService dtoService,
- IServerConfigurationManager serverConfigurationManager)
- {
- _userManager = userManager;
- _libraryManager = libraryManager;
- _dtoService = dtoService;
- _serverConfigurationManager = serverConfigurationManager;
- }
-
- /// <summary>
- /// Gets movie recommendations.
- /// </summary>
- /// <param name="userId">Optional. Filter by user id, and attach user data.</param>
- /// <param name="parentId">Specify this to localize the search to a specific item or folder. Omit to use the root.</param>
- /// <param name="fields">Optional. The fields to return.</param>
- /// <param name="categoryLimit">The max number of categories to return.</param>
- /// <param name="itemLimit">The max number of items to return per category.</param>
- /// <response code="200">Movie recommendations returned.</response>
- /// <returns>The list of movie recommendations.</returns>
- [HttpGet("Recommendations")]
- public ActionResult<IEnumerable<RecommendationDto>> GetMovieRecommendations(
- [FromQuery] Guid? userId,
- [FromQuery] Guid? parentId,
- [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
- [FromQuery] int categoryLimit = 5,
- [FromQuery] int itemLimit = 8)
- {
- var user = userId is null || userId.Value.Equals(default)
- ? null
- : _userManager.GetUserById(userId.Value);
- var dtoOptions = new DtoOptions { Fields = fields }
- .AddClientFields(User);
-
- var categories = new List<RecommendationDto>();
-
- var parentIdGuid = parentId ?? Guid.Empty;
+ _userManager = userManager;
+ _libraryManager = libraryManager;
+ _dtoService = dtoService;
+ _serverConfigurationManager = serverConfigurationManager;
+ }
- var query = new InternalItemsQuery(user)
- {
- IncludeItemTypes = new[]
- {
- BaseItemKind.Movie,
- // nameof(Trailer),
- // nameof(LiveTvProgram)
- },
- // IsMovie = true
- OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.Random, SortOrder.Descending) },
- Limit = 7,
- ParentId = parentIdGuid,
- Recursive = true,
- IsPlayed = true,
- DtoOptions = dtoOptions
- };
+ /// <summary>
+ /// Gets movie recommendations.
+ /// </summary>
+ /// <param name="userId">Optional. Filter by user id, and attach user data.</param>
+ /// <param name="parentId">Specify this to localize the search to a specific item or folder. Omit to use the root.</param>
+ /// <param name="fields">Optional. The fields to return.</param>
+ /// <param name="categoryLimit">The max number of categories to return.</param>
+ /// <param name="itemLimit">The max number of items to return per category.</param>
+ /// <response code="200">Movie recommendations returned.</response>
+ /// <returns>The list of movie recommendations.</returns>
+ [HttpGet("Recommendations")]
+ public ActionResult<IEnumerable<RecommendationDto>> GetMovieRecommendations(
+ [FromQuery] Guid? userId,
+ [FromQuery] Guid? parentId,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
+ [FromQuery] int categoryLimit = 5,
+ [FromQuery] int itemLimit = 8)
+ {
+ userId = RequestHelpers.GetUserId(User, userId);
+ var user = userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
+ var dtoOptions = new DtoOptions { Fields = fields }
+ .AddClientFields(User);
- var recentlyPlayedMovies = _libraryManager.GetItemList(query);
+ var categories = new List<RecommendationDto>();
- var itemTypes = new List<BaseItemKind> { BaseItemKind.Movie };
- if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
- {
- itemTypes.Add(BaseItemKind.Trailer);
- itemTypes.Add(BaseItemKind.LiveTvProgram);
- }
+ var parentIdGuid = parentId ?? Guid.Empty;
- var likedMovies = _libraryManager.GetItemList(new InternalItemsQuery(user)
+ var query = new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[]
{
- IncludeItemTypes = itemTypes.ToArray(),
- IsMovie = true,
- OrderBy = new[] { (ItemSortBy.Random, SortOrder.Descending) },
- Limit = 10,
- IsFavoriteOrLiked = true,
- ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id).ToArray(),
- EnableGroupByMetadataKey = true,
- ParentId = parentIdGuid,
- Recursive = true,
- DtoOptions = dtoOptions
- });
-
- var mostRecentMovies = recentlyPlayedMovies.GetRange(0, Math.Min(recentlyPlayedMovies.Count, 6));
- // Get recently played directors
- var recentDirectors = GetDirectors(mostRecentMovies)
- .ToList();
-
- // Get recently played actors
- var recentActors = GetActors(mostRecentMovies)
- .ToList();
-
- var similarToRecentlyPlayed = GetSimilarTo(user, recentlyPlayedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
- var similarToLiked = GetSimilarTo(user, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator();
-
- var hasDirectorFromRecentlyPlayed = GetWithDirector(user, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
- var hasActorFromRecentlyPlayed = GetWithActor(user, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
+ BaseItemKind.Movie,
+ // nameof(Trailer),
+ // nameof(LiveTvProgram)
+ },
+ // IsMovie = true
+ OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.Random, SortOrder.Descending) },
+ Limit = 7,
+ ParentId = parentIdGuid,
+ Recursive = true,
+ IsPlayed = true,
+ DtoOptions = dtoOptions
+ };
+
+ var recentlyPlayedMovies = _libraryManager.GetItemList(query);
+
+ var itemTypes = new List<BaseItemKind> { BaseItemKind.Movie };
+ if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
+ {
+ itemTypes.Add(BaseItemKind.Trailer);
+ itemTypes.Add(BaseItemKind.LiveTvProgram);
+ }
- var categoryTypes = new List<IEnumerator<RecommendationDto>>
+ var likedMovies = _libraryManager.GetItemList(new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = itemTypes.ToArray(),
+ IsMovie = true,
+ OrderBy = new[] { (ItemSortBy.Random, SortOrder.Descending) },
+ Limit = 10,
+ IsFavoriteOrLiked = true,
+ ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id).ToArray(),
+ EnableGroupByMetadataKey = true,
+ ParentId = parentIdGuid,
+ Recursive = true,
+ DtoOptions = dtoOptions
+ });
+
+ var mostRecentMovies = recentlyPlayedMovies.GetRange(0, Math.Min(recentlyPlayedMovies.Count, 6));
+ // Get recently played directors
+ var recentDirectors = GetDirectors(mostRecentMovies)
+ .ToList();
+
+ // Get recently played actors
+ var recentActors = GetActors(mostRecentMovies)
+ .ToList();
+
+ var similarToRecentlyPlayed = GetSimilarTo(user, recentlyPlayedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
+ var similarToLiked = GetSimilarTo(user, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator();
+
+ var hasDirectorFromRecentlyPlayed = GetWithDirector(user, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
+ var hasActorFromRecentlyPlayed = GetWithActor(user, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
+
+ var categoryTypes = new List<IEnumerator<RecommendationDto>>
{
// Give this extra weight
similarToRecentlyPlayed,
@@ -146,181 +147,180 @@ namespace Jellyfin.Api.Controllers
hasActorFromRecentlyPlayed
};
- while (categories.Count < categoryLimit)
- {
- var allEmpty = true;
+ while (categories.Count < categoryLimit)
+ {
+ var allEmpty = true;
- foreach (var category in categoryTypes)
+ foreach (var category in categoryTypes)
+ {
+ if (category.MoveNext())
{
- if (category.MoveNext())
- {
- categories.Add(category.Current);
- allEmpty = false;
+ categories.Add(category.Current);
+ allEmpty = false;
- if (categories.Count >= categoryLimit)
- {
- break;
- }
+ if (categories.Count >= categoryLimit)
+ {
+ break;
}
}
-
- if (allEmpty)
- {
- break;
- }
}
- return Ok(categories.OrderBy(i => i.RecommendationType).AsEnumerable());
- }
-
- private IEnumerable<RecommendationDto> GetWithDirector(
- User? user,
- IEnumerable<string> names,
- int itemLimit,
- DtoOptions dtoOptions,
- RecommendationType type)
- {
- var itemTypes = new List<BaseItemKind> { BaseItemKind.Movie };
- if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
+ if (allEmpty)
{
- itemTypes.Add(BaseItemKind.Trailer);
- itemTypes.Add(BaseItemKind.LiveTvProgram);
+ break;
}
+ }
- foreach (var name in names)
- {
- var items = _libraryManager.GetItemList(
- new InternalItemsQuery(user)
- {
- Person = name,
- // Account for duplicates by IMDb id, since the database doesn't support this yet
- Limit = itemLimit + 2,
- PersonTypes = new[] { PersonType.Director },
- IncludeItemTypes = itemTypes.ToArray(),
- IsMovie = true,
- EnableGroupByMetadataKey = true,
- DtoOptions = dtoOptions
- }).DistinctBy(i => i.GetProviderId(MediaBrowser.Model.Entities.MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture))
- .Take(itemLimit)
- .ToList();
-
- if (items.Count > 0)
- {
- var returnItems = _dtoService.GetBaseItemDtos(items, dtoOptions, user);
+ return Ok(categories.OrderBy(i => i.RecommendationType).AsEnumerable());
+ }
- yield return new RecommendationDto
- {
- BaselineItemName = name,
- CategoryId = name.GetMD5(),
- RecommendationType = type,
- Items = returnItems
- };
- }
- }
+ private IEnumerable<RecommendationDto> GetWithDirector(
+ User? user,
+ IEnumerable<string> names,
+ int itemLimit,
+ DtoOptions dtoOptions,
+ RecommendationType type)
+ {
+ var itemTypes = new List<BaseItemKind> { BaseItemKind.Movie };
+ if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
+ {
+ itemTypes.Add(BaseItemKind.Trailer);
+ itemTypes.Add(BaseItemKind.LiveTvProgram);
}
- private IEnumerable<RecommendationDto> GetWithActor(User? user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
+ foreach (var name in names)
{
- var itemTypes = new List<BaseItemKind> { BaseItemKind.Movie };
- if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
- {
- itemTypes.Add(BaseItemKind.Trailer);
- itemTypes.Add(BaseItemKind.LiveTvProgram);
- }
-
- foreach (var name in names)
- {
- var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
+ var items = _libraryManager.GetItemList(
+ new InternalItemsQuery(user)
{
Person = name,
// Account for duplicates by IMDb id, since the database doesn't support this yet
Limit = itemLimit + 2,
+ PersonTypes = new[] { PersonType.Director },
IncludeItemTypes = itemTypes.ToArray(),
IsMovie = true,
EnableGroupByMetadataKey = true,
DtoOptions = dtoOptions
}).DistinctBy(i => i.GetProviderId(MediaBrowser.Model.Entities.MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture))
- .Take(itemLimit)
- .ToList();
+ .Take(itemLimit)
+ .ToList();
- if (items.Count > 0)
- {
- var returnItems = _dtoService.GetBaseItemDtos(items, dtoOptions, user);
+ if (items.Count > 0)
+ {
+ var returnItems = _dtoService.GetBaseItemDtos(items, dtoOptions, user);
- yield return new RecommendationDto
- {
- BaselineItemName = name,
- CategoryId = name.GetMD5(),
- RecommendationType = type,
- Items = returnItems
- };
- }
+ yield return new RecommendationDto
+ {
+ BaselineItemName = name,
+ CategoryId = name.GetMD5(),
+ RecommendationType = type,
+ Items = returnItems
+ };
}
}
+ }
+
+ private IEnumerable<RecommendationDto> GetWithActor(User? user, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
+ {
+ var itemTypes = new List<BaseItemKind> { BaseItemKind.Movie };
+ if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
+ {
+ itemTypes.Add(BaseItemKind.Trailer);
+ itemTypes.Add(BaseItemKind.LiveTvProgram);
+ }
- private IEnumerable<RecommendationDto> GetSimilarTo(User? user, IEnumerable<BaseItem> baselineItems, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
+ foreach (var name in names)
{
- var itemTypes = new List<BaseItemKind> { BaseItemKind.Movie };
- if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
+ var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
- itemTypes.Add(BaseItemKind.Trailer);
- itemTypes.Add(BaseItemKind.LiveTvProgram);
- }
+ Person = name,
+ // Account for duplicates by IMDb id, since the database doesn't support this yet
+ Limit = itemLimit + 2,
+ IncludeItemTypes = itemTypes.ToArray(),
+ IsMovie = true,
+ EnableGroupByMetadataKey = true,
+ DtoOptions = dtoOptions
+ }).DistinctBy(i => i.GetProviderId(MediaBrowser.Model.Entities.MetadataProvider.Imdb) ?? Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture))
+ .Take(itemLimit)
+ .ToList();
- foreach (var item in baselineItems)
+ if (items.Count > 0)
{
- var similar = _libraryManager.GetItemList(new InternalItemsQuery(user)
- {
- Limit = itemLimit,
- IncludeItemTypes = itemTypes.ToArray(),
- IsMovie = true,
- SimilarTo = item,
- EnableGroupByMetadataKey = true,
- DtoOptions = dtoOptions
- });
+ var returnItems = _dtoService.GetBaseItemDtos(items, dtoOptions, user);
- if (similar.Count > 0)
+ yield return new RecommendationDto
{
- var returnItems = _dtoService.GetBaseItemDtos(similar, dtoOptions, user);
-
- yield return new RecommendationDto
- {
- BaselineItemName = item.Name,
- CategoryId = item.Id,
- RecommendationType = type,
- Items = returnItems
- };
- }
+ BaselineItemName = name,
+ CategoryId = name.GetMD5(),
+ RecommendationType = type,
+ Items = returnItems
+ };
}
}
+ }
- private IEnumerable<string> GetActors(IEnumerable<BaseItem> items)
+ private IEnumerable<RecommendationDto> GetSimilarTo(User? user, IEnumerable<BaseItem> baselineItems, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
+ {
+ var itemTypes = new List<BaseItemKind> { BaseItemKind.Movie };
+ if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
{
- var people = _libraryManager.GetPeople(new InternalPeopleQuery(Array.Empty<string>(), new[] { PersonType.Director })
+ itemTypes.Add(BaseItemKind.Trailer);
+ itemTypes.Add(BaseItemKind.LiveTvProgram);
+ }
+
+ foreach (var item in baselineItems)
+ {
+ var similar = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
- MaxListOrder = 3
+ Limit = itemLimit,
+ IncludeItemTypes = itemTypes.ToArray(),
+ IsMovie = true,
+ SimilarTo = item,
+ EnableGroupByMetadataKey = true,
+ DtoOptions = dtoOptions
});
- var itemIds = items.Select(i => i.Id).ToList();
+ if (similar.Count > 0)
+ {
+ var returnItems = _dtoService.GetBaseItemDtos(similar, dtoOptions, user);
- return people
- .Where(i => itemIds.Contains(i.ItemId))
- .Select(i => i.Name)
- .DistinctNames();
+ yield return new RecommendationDto
+ {
+ BaselineItemName = item.Name,
+ CategoryId = item.Id,
+ RecommendationType = type,
+ Items = returnItems
+ };
+ }
}
+ }
- private IEnumerable<string> GetDirectors(IEnumerable<BaseItem> items)
+ private IEnumerable<string> GetActors(IEnumerable<BaseItem> items)
+ {
+ var people = _libraryManager.GetPeople(new InternalPeopleQuery(Array.Empty<string>(), new[] { PersonType.Director })
{
- var people = _libraryManager.GetPeople(new InternalPeopleQuery(
- new[] { PersonType.Director },
- Array.Empty<string>()));
+ MaxListOrder = 3
+ });
- var itemIds = items.Select(i => i.Id).ToList();
+ var itemIds = items.Select(i => i.Id).ToList();
- return people
- .Where(i => itemIds.Contains(i.ItemId))
- .Select(i => i.Name)
- .DistinctNames();
- }
+ return people
+ .Where(i => itemIds.Contains(i.ItemId))
+ .Select(i => i.Name)
+ .DistinctNames();
+ }
+
+ private IEnumerable<string> GetDirectors(IEnumerable<BaseItem> items)
+ {
+ var people = _libraryManager.GetPeople(new InternalPeopleQuery(
+ new[] { PersonType.Director },
+ Array.Empty<string>()));
+
+ var itemIds = items.Select(i => i.Id).ToList();
+
+ return people
+ .Where(i => itemIds.Contains(i.ItemId))
+ .Select(i => i.Name)
+ .DistinctNames();
}
}