@ -32,6 +32,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private readonly ILogger _logger ;
private readonly IItemRepository _itemRepo ;
private readonly IUserManager _userManager ;
private readonly IUserDataManager _userDataManager ;
private readonly ILibraryManager _libraryManager ;
private readonly IMediaEncoder _mediaEncoder ;
@ -54,6 +55,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
_userManager = userManager ;
_libraryManager = libraryManager ;
_mediaEncoder = mediaEncoder ;
_userDataManager = userDataManager ;
_tvDtoService = new LiveTvDtoService ( dtoService , userDataManager , imageProcessor , logger , _itemRepo ) ;
}
@ -428,7 +430,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
var returnArray = programs
. OrderBy ( i = > i . ProgramInfo . StartDate )
. Select ( i = >
{
var channel = GetChannel ( i ) ;
@ -450,6 +451,138 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return result ;
}
public async Task < QueryResult < ProgramInfoDto > > GetRecommendedPrograms ( RecommendedProgramQuery query , CancellationToken cancellationToken )
{
IEnumerable < LiveTvProgram > programs = _programs . Values ;
var user = _userManager . GetUserById ( new Guid ( query . UserId ) ) ;
// Avoid implicitly captured closure
var currentUser = user ;
programs = programs . Where ( i = > i . IsParentalAllowed ( currentUser ) ) ;
if ( query . IsAiring . HasValue )
{
var val = query . IsAiring . Value ;
programs = programs . Where ( i = > i . IsAiring = = val ) ;
}
if ( query . HasAired . HasValue )
{
var val = query . HasAired . Value ;
programs = programs . Where ( i = > i . HasAired = = val ) ;
}
var serviceName = ActiveService . Name ;
var programList = programs . ToList ( ) ;
var genres = programList . SelectMany ( i = > i . Genres )
. Distinct ( StringComparer . OrdinalIgnoreCase )
. Select ( i = > _libraryManager . GetGenre ( i ) )
. ToDictionary ( i = > i . Name , StringComparer . OrdinalIgnoreCase ) ;
programs = programList . OrderByDescending ( i = > GetRecommendationScore ( i . ProgramInfo , user . Id , serviceName , genres ) )
. ThenBy ( i = > i . ProgramInfo . StartDate ) ;
if ( query . Limit . HasValue )
{
programs = programs . Take ( query . Limit . Value )
. OrderBy ( i = > i . ProgramInfo . StartDate ) ;
}
var returnArray = programs
. Select ( i = >
{
var channel = GetChannel ( i ) ;
var channelName = channel = = null ? null : channel . ChannelInfo . Name ;
return _tvDtoService . GetProgramInfoDto ( i , channelName , user ) ;
} )
. ToArray ( ) ;
await AddRecordingInfo ( returnArray , cancellationToken ) . ConfigureAwait ( false ) ;
var result = new QueryResult < ProgramInfoDto >
{
Items = returnArray ,
TotalRecordCount = returnArray . Length
} ;
return result ;
}
private int GetRecommendationScore ( ProgramInfo program , Guid userId , string serviceName , Dictionary < string , Genre > genres )
{
var score = 0 ;
if ( program . IsLive )
{
score + + ;
}
if ( program . IsSeries & & ! program . IsRepeat )
{
score + + ;
}
var internalChannelId = _tvDtoService . GetInternalChannelId ( serviceName , program . ChannelId ) ;
var channel = GetInternalChannel ( internalChannelId ) ;
var channelUserdata = _userDataManager . GetUserData ( userId , channel . GetUserDataKey ( ) ) ;
if ( ( channelUserdata . Likes ? ? false ) )
{
score + = 2 ;
}
else if ( ! ( channelUserdata . Likes ? ? true ) )
{
score - = 2 ;
}
if ( channelUserdata . IsFavorite )
{
score + = 3 ;
}
score + = GetGenreScore ( program . Genres , userId , genres ) ;
return score ;
}
private int GetGenreScore ( IEnumerable < string > programGenres , Guid userId , Dictionary < string , Genre > genres )
{
return programGenres . Select ( i = >
{
var score = 0 ;
Genre genre ;
if ( genres . TryGetValue ( i , out genre ) )
{
var genreUserdata = _userDataManager . GetUserData ( userId , genre . GetUserDataKey ( ) ) ;
if ( ( genreUserdata . Likes ? ? false ) )
{
score + + ;
}
else if ( ! ( genreUserdata . Likes ? ? true ) )
{
score - - ;
}
if ( genreUserdata . IsFavorite )
{
score + = 2 ;
}
}
return score ;
} ) . Sum ( ) ;
}
private async Task AddRecordingInfo ( IEnumerable < ProgramInfoDto > programs , CancellationToken cancellationToken )
{
var timers = await ActiveService . GetTimersAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
@ -533,7 +666,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv
try
{
var channelPrograms = await service . GetProgramsAsync ( currentChannel . ChannelInfo . Id , cancellationToken ) . ConfigureAwait ( false ) ;
var start = DateTime . UtcNow ;
var end = start . AddDays ( 3 ) ;
var channelPrograms = await service . GetProgramsAsync ( currentChannel . ChannelInfo . Id , start , end , cancellationToken ) . ConfigureAwait ( false ) ;
var programTasks = channelPrograms . Select ( program = > GetProgram ( program , currentChannel . ChannelInfo . ChannelType , service . Name , cancellationToken ) ) ;
var programEntities = await Task . WhenAll ( programTasks ) . ConfigureAwait ( false ) ;