@ -14,6 +14,7 @@ using System;
using System.Collections.Generic ;
using System.Linq ;
using System.Threading.Tasks ;
using MediaBrowser.Controller.LiveTv ;
namespace MediaBrowser.Api.Movies
{
@ -110,18 +111,16 @@ namespace MediaBrowser.Api.Movies
/// </summary>
/// <param name="request">The request.</param>
/// <returns>System.Object.</returns>
public async Task < object > Get ( GetSimilarMovies request )
public object Get ( GetSimilarMovies request )
{
var result = await GetSimilarItemsResult (
request , SimilarItemsHelper . GetSimiliarityScore ) . ConfigureAwait ( false ) ;
var result = GetSimilarItemsResult ( request ) ;
return ToOptimizedSerializedResultUsingCache ( result ) ;
}
public async Task < object > Get ( GetSimilarTrailers request )
public object Get ( GetSimilarTrailers request )
{
var result = await GetSimilarItemsResult (
request , SimilarItemsHelper . GetSimiliarityScore ) . ConfigureAwait ( false ) ;
var result = GetSimilarItemsResult ( request ) ;
return ToOptimizedSerializedResultUsingCache ( result ) ;
}
@ -130,148 +129,85 @@ namespace MediaBrowser.Api.Movies
{
var user = _userManager . GetUserById ( request . UserId ) ;
var query = new InternalItemsQuery ( user )
{
IncludeItemTypes = new [ ] { typeof ( Movie ) . Name }
} ;
if ( user . Configuration . IncludeTrailersInSuggestions )
{
var includeList = query . IncludeItemTypes . ToList ( ) ;
includeList . Add ( typeof ( Trailer ) . Name ) ;
query . IncludeItemTypes = includeList . ToArray ( ) ;
}
var parentIds = string . IsNullOrWhiteSpace ( request . ParentId ) ? new string [ ] { } : new [ ] { request . ParentId } ;
var movies = _libraryManager . GetItemList ( query , parentIds )
. OrderBy ( i = > ( int ) i . SourceType ) ;
var listEligibleForCategories = new List < BaseItem > ( ) ;
var listEligibleForSuggestion = new List < BaseItem > ( ) ;
var list = movies . ToList ( ) ;
listEligibleForCategories . AddRange ( list ) ;
listEligibleForSuggestion . AddRange ( list ) ;
listEligibleForCategories = listEligibleForCategories
// Exclude trailers from the suggestion categories
. Where ( i = > i is Movie )
. DistinctBy ( i = > i . Name , StringComparer . OrdinalIgnoreCase )
. DistinctBy ( i = > i . GetProviderId ( MetadataProviders . Imdb ) ? ? Guid . NewGuid ( ) . ToString ( ) , StringComparer . OrdinalIgnoreCase )
. ToList ( ) ;
listEligibleForSuggestion = listEligibleForSuggestion
. DistinctBy ( i = > i . Name , StringComparer . OrdinalIgnoreCase )
. DistinctBy ( i = > i . GetProviderId ( MetadataProviders . Imdb ) ? ? Guid . NewGuid ( ) . ToString ( ) , StringComparer . OrdinalIgnoreCase )
. ToList ( ) ;
var dtoOptions = GetDtoOptions ( request ) ;
dtoOptions . Fields = request . GetItemFields ( ) . ToList ( ) ;
var result = GetRecommendationCategories ( user , listEligibleForCategories, listEligibleForSuggestion , request . CategoryLimit , request . ItemLimit , dtoOptions ) ;
var result = GetRecommendationCategories ( user , request . ParentId , request . CategoryLimit , request . ItemLimit , dtoOptions ) ;
return ToOptimizedResult ( result ) ;
}
private async Task < ItemsResult > GetSimilarItemsResult ( BaseGetSimilarItemsFromItem request , Func < BaseItem , List < PersonInfo > , List < PersonInfo > , BaseItem , int > getSimilarityScore )
private QueryResult < BaseItemDto > GetSimilarItemsResult ( BaseGetSimilarItemsFromItem request )
{
var user = ! string . IsNullOrWhiteSpace ( request . UserId ) ? _userManager . GetUserById ( request . UserId ) : null ;
var item = string . IsNullOrEmpty ( request . Id ) ?
( ! string . IsNullOrWhiteSpace ( request . UserId ) ? user . RootFolder :
_libraryManager . RootFolder ) : _libraryManager . GetItemById ( request . Id ) ;
var query = new InternalItemsQuery ( user )
{
IncludeItemTypes = new [ ] { typeof ( Movie ) . Name }
} ;
if ( user = = null | | user . Configuration . IncludeTrailersInSuggestions )
{
var includeList = query . IncludeItemTypes . ToList ( ) ;
includeList . Add ( typeof ( Trailer ) . Name ) ;
query . IncludeItemTypes = includeList . ToArray ( ) ;
}
var list = _libraryManager . GetItemList ( query )
. OrderBy ( i = > ( int ) i . SourceType )
. DistinctBy ( i = > i . GetProviderId ( MetadataProviders . Imdb ) ? ? Guid . NewGuid ( ) . ToString ( "N" ) )
. ToList ( ) ;
if ( item is Video )
var itemsResult = _libraryManager . GetItemList ( new InternalItemsQuery ( user )
{
var imdbId = item . GetProviderId ( MetadataProviders . Imdb ) ;
// Use imdb id to try to filter duplicates of the same item
if ( ! string . IsNullOrWhiteSpace ( imdbId ) )
Limit = request . Limit ,
IncludeItemTypes = new [ ]
{
list = list
. Where ( i = > ! string . Equals ( imdbId , i . GetProviderId ( MetadataProviders . Imdb ) , StringComparison . OrdinalIgnoreCase ) )
. ToList ( ) ;
}
}
var items = SimilarItemsHelper . GetSimilaritems ( item , _libraryManager , list , getSimilarityScore ) . ToList ( ) ;
IEnumerable < BaseItem > returnItems = items ;
if ( request . Limit . HasValue )
{
returnItems = returnItems . Take ( request . Limit . Value ) ;
}
typeof ( Movie ) . Name ,
typeof ( Trailer ) . Name ,
typeof ( LiveTvProgram ) . Name
} ,
IsMovie = true ,
SimilarTo = item
} ) . ToList ( ) ;
var dtoOptions = GetDtoOptions ( request ) ;
var result = new ItemsResult
var result = new QueryResult < BaseItemDto >
{
Items = _dtoService . GetBaseItemDtos ( returnItems , dtoOptions , user ) . ToArray ( ) ,
Items = _dtoService . GetBaseItemDtos ( itemsResult , dtoOptions , user ) . ToArray ( ) ,
TotalRecordCount = items . Count
TotalRecordCount = items Result . Count
} ;
return result ;
}
private IEnumerable < RecommendationDto > GetRecommendationCategories ( User user , List < BaseItem > allMoviesForCategories , List < BaseItem > allMovies , int categoryLimit , int itemLimit , DtoOptions dtoOptions )
private IEnumerable < RecommendationDto > GetRecommendationCategories ( User user , string parentId , int categoryLimit , int itemLimit , DtoOptions dtoOptions )
{
var categories = new List < RecommendationDto > ( ) ;
var recentlyPlayedMovies = allMoviesForCategories
. Select ( i = >
var parentIds = string . IsNullOrWhiteSpace ( parentId ) ? new string [ ] { } : new [ ] { parentId } ;
var query = new InternalItemsQuery ( user )
{
IncludeItemTypes = new [ ]
{
var userdata = _userDataRepository . GetUserData ( user , i ) ;
return new Tuple < BaseItem , bool , DateTime > ( i , userdata . Played , userdata . LastPlayedDate ? ? DateTime . MinValue ) ;
} )
. Where ( i = > i . Item2 )
. OrderByDescending ( i = > i . Item3 )
. Select ( i = > i . Item1 )
. ToList ( ) ;
typeof ( Movie ) . Name ,
//typeof(Trailer).Name,
//typeof(LiveTvProgram).Name
} ,
// IsMovie = true
SortBy = new [ ] { ItemSortBy . DatePlayed , ItemSortBy . Random } ,
SortOrder = SortOrder . Descending ,
Limit = 7
} ;
var excludeFromLiked = recentlyPlayedMovies . Take ( 10 ) ;
var likedMovies = allMovies
. Select ( i = >
{
var score = 0 ;
var userData = _userDataRepository . GetUserData ( user , i ) ;
var recentlyPlayedMovies = _libraryManager . GetItemList ( query , parentIds ) . ToList ( ) ;
if ( userData . IsFavorite )
{
score = 2 ;
}
else
{
score = userData . Likes . HasValue ? userData . Likes . Value ? 1 : - 1 : 0 ;
}
var likedMovies = _libraryManager . GetItemList ( new InternalItemsQuery ( user )
{
IncludeItemTypes = new [ ]
{
typeof ( Movie ) . Name ,
typeof ( Trailer ) . Name ,
typeof ( LiveTvProgram ) . Name
} ,
IsMovie = true ,
SortBy = new [ ] { ItemSortBy . Random } ,
SortOrder = SortOrder . Descending ,
Limit = 10 ,
IsFavoriteOrLiked = true ,
ExcludeItemIds = recentlyPlayedMovies . Select ( i = > i . Id . ToString ( "N" ) ) . ToArray ( )
return new Tuple < BaseItem , int > ( i , score ) ;
} )
. OrderByDescending ( i = > i . Item2 )
. ThenBy ( i = > Guid . NewGuid ( ) )
. Where ( i = > i . Item2 > 0 )
. Select ( i = > i . Item1 )
. Where ( i = > ! excludeFromLiked . Contains ( i ) ) ;
} , parentIds ) . ToList ( ) ;
var mostRecentMovies = recentlyPlayedMovies . Take ( 6 ) . ToList ( ) ;
// Get recently played directors
@ -284,11 +220,11 @@ namespace MediaBrowser.Api.Movies
. OrderBy ( i = > Guid . NewGuid ( ) )
. ToList ( ) ;
var similarToRecentlyPlayed = GetSimilarTo ( user , allMovies, recentlyPlayedMovies. Take ( 7 ) . OrderBy ( i = > Guid . NewGuid ( ) ) , itemLimit , dtoOptions , RecommendationType . SimilarToRecentlyPlayed ) . GetEnumerator ( ) ;
var similarToLiked = GetSimilarTo ( user , allMovies, likedMovies, itemLimit , dtoOptions , RecommendationType . SimilarToLikedItem ) . GetEnumerator ( ) ;
var similarToRecentlyPlayed = GetSimilarTo ( user , recentlyPlayedMovies, itemLimit , dtoOptions , RecommendationType . SimilarToRecentlyPlayed ) . GetEnumerator ( ) ;
var similarToLiked = GetSimilarTo ( user , likedMovies, itemLimit , dtoOptions , RecommendationType . SimilarToLikedItem ) . GetEnumerator ( ) ;
var hasDirectorFromRecentlyPlayed = GetWithDirector ( user , allMovies, recentDirectors, itemLimit , dtoOptions , RecommendationType . HasDirectorFromRecentlyPlayed ) . GetEnumerator ( ) ;
var hasActorFromRecentlyPlayed = GetWithActor ( user , allMovies, recentActors, itemLimit , dtoOptions , RecommendationType . HasActorFromRecentlyPlayed ) . 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 > >
{
@ -331,23 +267,34 @@ namespace MediaBrowser.Api.Movies
return categories . OrderBy ( i = > i . RecommendationType ) . ThenBy ( i = > Guid . NewGuid ( ) ) ;
}
private IEnumerable < RecommendationDto > GetWithDirector ( User user , List< BaseItem > allMovies , IEnumerable< string > director s, int itemLimit , DtoOptions dtoOptions , RecommendationType type )
private IEnumerable < RecommendationDto > GetWithDirector ( User user , IEnumerable< string > name s, int itemLimit , DtoOptions dtoOptions , RecommendationType type )
{
var userId = user . Id ;
foreach ( var director in directors )
foreach ( var name in names )
{
var items = allMovies
. Where ( i = > _libraryManager . GetPeople ( i ) . Any ( p = > string . Equals ( p . Type , PersonType . Director , StringComparison . OrdinalIgnoreCase ) & & string . Equals ( p . Name , director , StringComparison . OrdinalIgnoreCase ) ) )
. Take ( itemLimit )
. ToList ( ) ;
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 = new [ ]
{
typeof ( Movie ) . Name ,
typeof ( Trailer ) . Name ,
typeof ( LiveTvProgram ) . Name
} ,
IsMovie = true
} ) . DistinctBy ( i = > i . GetProviderId ( MetadataProviders . Imdb ) ? ? Guid . NewGuid ( ) . ToString ( "N" ) )
. Take ( itemLimit )
. ToList ( ) ;
if ( items . Count > 0 )
{
yield return new RecommendationDto
{
BaselineItemName = director ,
CategoryId = director . GetMD5 ( ) . ToString ( "N" ) ,
BaselineItemName = name ,
CategoryId = name . GetMD5 ( ) . ToString ( "N" ) ,
RecommendationType = type ,
Items = _dtoService . GetBaseItemDtos ( items , dtoOptions , user ) . ToArray ( )
} ;
@ -355,20 +302,26 @@ namespace MediaBrowser.Api.Movies
}
}
private IEnumerable < RecommendationDto > GetWithActor ( User user , List< BaseItem > allMovies , IEnumerable< string > names , int itemLimit , DtoOptions dtoOptions , RecommendationType type )
private IEnumerable < RecommendationDto > GetWithActor ( User user , IEnumerable< string > names , int itemLimit , DtoOptions dtoOptions , RecommendationType type )
{
foreach ( var name in names )
{
var items WithActor = _libraryManager . GetItem Ids ( new InternalItemsQuery ( user )
var items = _libraryManager . GetItem List ( new InternalItemsQuery ( user )
{
Person = name
} ) ;
var items = allMovies
. Where ( i = > itemsWithActor . Contains ( i . Id ) )
. Take ( itemLimit )
. ToList ( ) ;
Person = name ,
// Account for duplicates by imdb id, since the database doesn't support this yet
Limit = itemLimit + 2 ,
IncludeItemTypes = new [ ]
{
typeof ( Movie ) . Name ,
typeof ( Trailer ) . Name ,
typeof ( LiveTvProgram ) . Name
} ,
IsMovie = true
} ) . DistinctBy ( i = > i . GetProviderId ( MetadataProviders . Imdb ) ? ? Guid . NewGuid ( ) . ToString ( "N" ) )
. Take ( itemLimit )
. ToList ( ) ;
if ( items . Count > 0 )
{
@ -383,14 +336,23 @@ namespace MediaBrowser.Api.Movies
}
}
private IEnumerable < RecommendationDto > GetSimilarTo ( User user , List < BaseItem > allMovies, IEnumerable < BaseItem > baselineItems, int itemLimit , DtoOptions dtoOptions , RecommendationType type )
private IEnumerable < RecommendationDto > GetSimilarTo ( User user , List < BaseItem > baselineItems, int itemLimit , DtoOptions dtoOptions , RecommendationType type )
{
foreach ( var item in baselineItems )
{
var similar = SimilarItemsHelper
. GetSimilaritems ( item , _libraryManager , allMovies , SimilarItemsHelper . GetSimiliarityScore )
. Take ( itemLimit )
. ToList ( ) ;
var similar = _libraryManager . GetItemList ( new InternalItemsQuery ( user )
{
Limit = itemLimit ,
IncludeItemTypes = new [ ]
{
typeof ( Movie ) . Name ,
typeof ( Trailer ) . Name ,
typeof ( LiveTvProgram ) . Name
} ,
IsMovie = true ,
SimilarTo = item
} ) . ToList ( ) ;
if ( similar . Count > 0 )
{