@ -22,6 +22,7 @@ using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository ;
using Ombi.Store.Repository ;
using Ombi.Core.Models ;
using Ombi.Core.Models ;
using System.Threading ;
using System.Threading ;
using Ombi.Core.Services ;
namespace Ombi.Core.Engine
namespace Ombi.Core.Engine
{
{
@ -30,7 +31,8 @@ namespace Ombi.Core.Engine
public MovieRequestEngine ( IMovieDbApi movieApi , IRequestServiceMain requestService , IPrincipal user ,
public MovieRequestEngine ( IMovieDbApi movieApi , IRequestServiceMain requestService , IPrincipal user ,
INotificationHelper helper , IRuleEvaluator r , IMovieSender sender , ILogger < MovieRequestEngine > log ,
INotificationHelper helper , IRuleEvaluator r , IMovieSender sender , ILogger < MovieRequestEngine > log ,
OmbiUserManager manager , IRepository < RequestLog > rl , ICacheService cache ,
OmbiUserManager manager , IRepository < RequestLog > rl , ICacheService cache ,
ISettingsService < OmbiSettings > ombiSettings , IRepository < RequestSubscription > sub , IMediaCacheService mediaCacheService )
ISettingsService < OmbiSettings > ombiSettings , IRepository < RequestSubscription > sub , IMediaCacheService mediaCacheService ,
IFeatureService featureService )
: base ( user , requestService , r , manager , cache , ombiSettings , sub )
: base ( user , requestService , r , manager , cache , ombiSettings , sub )
{
{
MovieApi = movieApi ;
MovieApi = movieApi ;
@ -39,6 +41,7 @@ namespace Ombi.Core.Engine
Logger = log ;
Logger = log ;
_requestLog = rl ;
_requestLog = rl ;
_mediaCacheService = mediaCacheService ;
_mediaCacheService = mediaCacheService ;
_featureService = featureService ;
}
}
private IMovieDbApi MovieApi { get ; }
private IMovieDbApi MovieApi { get ; }
@ -47,6 +50,7 @@ namespace Ombi.Core.Engine
private ILogger < MovieRequestEngine > Logger { get ; }
private ILogger < MovieRequestEngine > Logger { get ; }
private readonly IRepository < RequestLog > _requestLog ;
private readonly IRepository < RequestLog > _requestLog ;
private readonly IMediaCacheService _mediaCacheService ;
private readonly IMediaCacheService _mediaCacheService ;
private readonly IFeatureService _featureService ;
/// <summary>
/// <summary>
/// Requests the movie.
/// Requests the movie.
@ -72,7 +76,8 @@ namespace Ombi.Core.Engine
var userDetails = await GetUser ( ) ;
var userDetails = await GetUser ( ) ;
var canRequestOnBehalf = model . RequestOnBehalf . HasValue ( ) ;
var canRequestOnBehalf = model . RequestOnBehalf . HasValue ( ) ;
var isAdmin = await UserManager . IsInRoleAsync ( userDetails , OmbiRoles . PowerUser ) | | await UserManager . IsInRoleAsync ( userDetails , OmbiRoles . Admin ) ;
var isAdmin = await UserManager . IsInRoleAsync ( userDetails , OmbiRoles . PowerUser )
| | await UserManager . IsInRoleAsync ( userDetails , OmbiRoles . Admin ) ;
if ( canRequestOnBehalf & & ! isAdmin )
if ( canRequestOnBehalf & & ! isAdmin )
{
{
return new RequestEngineResult
return new RequestEngineResult
@ -93,27 +98,53 @@ namespace Ombi.Core.Engine
} ;
} ;
}
}
var requestModel = new MovieRequests
var is4kFeatureEnabled = await _featureService . FeatureEnabled ( FeatureNames . Movie4KRequests ) ;
var is4kRequest = is4kFeatureEnabled & & model . Is4kRequest ;
MovieRequests requestModel ;
bool isExisting = false ;
// Do we already have a request? 4k or non 4k
var existingRequest = await MovieRepository . GetRequestAsync ( movieInfo . Id ) ;
if ( existingRequest ! = null & & is4kFeatureEnabled )
{
{
TheMovieDbId = movieInfo . Id ,
if ( model . Is4kRequest )
RequestType = RequestType . Movie ,
{
Overview = movieInfo . Overview ,
existingRequest . Is4kRequest = true ;
ImdbId = movieInfo . ImdbId ,
existingRequest . RequestedDate4k = DateTime . Now ;
PosterPath = PosterPathHelper . FixPosterPath ( movieInfo . PosterPath ) ,
}
Title = movieInfo . Title ,
else
ReleaseDate = ! string . IsNullOrEmpty ( movieInfo . ReleaseDate )
{
? DateTime . Parse ( movieInfo . ReleaseDate )
existingRequest . RequestedDate = DateTime . Now ;
: DateTime . MinValue ,
}
Status = movieInfo . Status ,
isExisting = true ;
RequestedDate = DateTime . UtcNow ,
requestModel = existingRequest ;
Approved = false ,
}
RequestedUserId = canRequestOnBehalf ? model . RequestOnBehalf : userDetails . Id ,
else
Background = movieInfo . BackdropPath ,
{
LangCode = model . LanguageCode ,
requestModel = new MovieRequests
RequestedByAlias = model . RequestedByAlias ,
{
RootPathOverride = model . RootFolderOverride . GetValueOrDefault ( ) ,
TheMovieDbId = movieInfo . Id ,
QualityOverride = model . QualityPathOverride . GetValueOrDefault ( )
RequestType = RequestType . Movie ,
} ;
Overview = movieInfo . Overview ,
ImdbId = movieInfo . ImdbId ,
PosterPath = PosterPathHelper . FixPosterPath ( movieInfo . PosterPath ) ,
Title = movieInfo . Title ,
ReleaseDate = ! string . IsNullOrEmpty ( movieInfo . ReleaseDate )
? DateTime . Parse ( movieInfo . ReleaseDate )
: DateTime . MinValue ,
Status = movieInfo . Status ,
RequestedDate = model . Is4kRequest ? DateTime . MinValue : DateTime . Now ,
Approved = false ,
RequestedUserId = canRequestOnBehalf ? model . RequestOnBehalf : userDetails . Id ,
Background = movieInfo . BackdropPath ,
LangCode = model . LanguageCode ,
RequestedByAlias = model . RequestedByAlias ,
RootPathOverride = model . RootFolderOverride . GetValueOrDefault ( ) ,
QualityOverride = model . QualityPathOverride . GetValueOrDefault ( ) ,
RequestedDate4k = model . Is4kRequest ? DateTime . Now : DateTime . MinValue ,
Is4kRequest = model . Is4kRequest
} ;
}
var usDates = movieInfo . ReleaseDates ? . Results ? . FirstOrDefault ( x = > x . IsoCode = = "US" ) ;
var usDates = movieInfo . ReleaseDates ? . Results ? . FirstOrDefault ( x = > x . IsoCode = = "US" ) ;
requestModel . DigitalReleaseDate = usDates ? . ReleaseDate
requestModel . DigitalReleaseDate = usDates ? . ReleaseDate
@ -132,10 +163,10 @@ namespace Ombi.Core.Engine
if ( requestModel . Approved ) // The rules have auto approved this
if ( requestModel . Approved ) // The rules have auto approved this
{
{
var requestEngineResult = await AddMovieRequest ( requestModel , fullMovieName , model . RequestOnBehalf );
var requestEngineResult = await AddMovieRequest ( requestModel , fullMovieName , model . RequestOnBehalf , isExisting , is4kRequest );
if ( requestEngineResult . Result )
if ( requestEngineResult . Result )
{
{
var result = await ApproveMovie ( requestModel );
var result = await ApproveMovie ( requestModel , model . Is4kRequest );
if ( result . IsError )
if ( result . IsError )
{
{
Logger . LogWarning ( "Tried auto sending movie but failed. Message: {0}" , result . Message ) ;
Logger . LogWarning ( "Tried auto sending movie but failed. Message: {0}" , result . Message ) ;
@ -153,7 +184,7 @@ namespace Ombi.Core.Engine
// If there are no providers then it's successful but movie has not been sent
// If there are no providers then it's successful but movie has not been sent
}
}
return await AddMovieRequest ( requestModel , fullMovieName , model . RequestOnBehalf );
return await AddMovieRequest ( requestModel , fullMovieName , model . RequestOnBehalf , isExisting , is4kRequest );
}
}
@ -508,13 +539,13 @@ namespace Ombi.Core.Engine
return results ;
return results ;
}
}
public async Task < RequestEngineResult > ApproveMovieById ( int requestId )
public async Task < RequestEngineResult > ApproveMovieById ( int requestId , bool is4K )
{
{
var request = await MovieRepository . Find ( requestId ) ;
var request = await MovieRepository . Find ( requestId ) ;
return await ApproveMovie ( request );
return await ApproveMovie ( request , is4K );
}
}
public async Task < RequestEngineResult > DenyMovieById ( int modelId , string denyReason )
public async Task < RequestEngineResult > DenyMovieById ( int modelId , string denyReason , bool is4K )
{
{
var request = await MovieRepository . Find ( modelId ) ;
var request = await MovieRepository . Find ( modelId ) ;
if ( request = = null )
if ( request = = null )
@ -525,8 +556,16 @@ namespace Ombi.Core.Engine
} ;
} ;
}
}
request . Denied = true ;
if ( is4K )
request . DeniedReason = denyReason ;
{
request . Denied4K = true ;
request . DeniedReason4K = denyReason ;
}
else
{
request . Denied = true ;
request . DeniedReason = denyReason ;
}
await MovieRepository . Update ( request ) ;
await MovieRepository . Update ( request ) ;
await _mediaCacheService . Purge ( ) ;
await _mediaCacheService . Purge ( ) ;
@ -540,7 +579,7 @@ namespace Ombi.Core.Engine
} ;
} ;
}
}
public async Task < RequestEngineResult > ApproveMovie ( MovieRequests request )
public async Task < RequestEngineResult > ApproveMovie ( MovieRequests request , bool is4K )
{
{
if ( request = = null )
if ( request = = null )
{
{
@ -550,9 +589,18 @@ namespace Ombi.Core.Engine
} ;
} ;
}
}
request . MarkedAsApproved = DateTime . Now ;
if ( is4K )
request . Approved = true ;
{
request . Denied = false ;
request . MarkedAsApproved4K = DateTime . Now ;
request . Approved4K = true ;
request . Denied4K = false ;
}
else
{
request . MarkedAsApproved = DateTime . Now ;
request . Approved = true ;
request . Denied = false ;
}
await MovieRepository . Update ( request ) ;
await MovieRepository . Update ( request ) ;
var canNotify = await RunSpecificRule ( request , SpecificRules . CanSendNotification , string . Empty ) ;
var canNotify = await RunSpecificRule ( request , SpecificRules . CanSendNotification , string . Empty ) ;
@ -562,7 +610,7 @@ namespace Ombi.Core.Engine
}
}
await _mediaCacheService . Purge ( ) ;
await _mediaCacheService . Purge ( ) ;
return await ProcessSendingMovie ( request );
return await ProcessSendingMovie ( request , is4K );
}
}
public async Task < RequestEngineResult > RequestCollection ( int collectionId , CancellationToken cancellationToken )
public async Task < RequestEngineResult > RequestCollection ( int collectionId , CancellationToken cancellationToken )
@ -590,11 +638,11 @@ namespace Ombi.Core.Engine
return new RequestEngineResult { Result = true , Message = $"The collection {collections.name} has been successfully added!" , RequestId = results . FirstOrDefault ( ) . RequestId } ;
return new RequestEngineResult { Result = true , Message = $"The collection {collections.name} has been successfully added!" , RequestId = results . FirstOrDefault ( ) . RequestId } ;
}
}
private async Task < RequestEngineResult > ProcessSendingMovie ( MovieRequests request )
private async Task < RequestEngineResult > ProcessSendingMovie ( MovieRequests request , bool is4K )
{
{
if ( request . Approved )
if ( request . Approved )
{
{
var result = await Sender . Send ( request );
var result = await Sender . Send ( request , is4K );
if ( result . Success & & result . Sent )
if ( result . Success & & result . Sent )
{
{
return new RequestEngineResult
return new RequestEngineResult
@ -662,7 +710,7 @@ namespace Ombi.Core.Engine
var result = await CheckCanManageRequest ( request ) ;
var result = await CheckCanManageRequest ( request ) ;
if ( result . IsError )
if ( result . IsError )
return result ;
return result ;
await MovieRepository . Delete ( request ) ;
await MovieRepository . Delete ( request ) ;
await _mediaCacheService . Purge ( ) ;
await _mediaCacheService . Purge ( ) ;
return new RequestEngineResult
return new RequestEngineResult
@ -683,7 +731,7 @@ namespace Ombi.Core.Engine
return await MovieRepository . GetAll ( ) . AnyAsync ( x = > x . RequestedUserId = = userId ) ;
return await MovieRepository . GetAll ( ) . AnyAsync ( x = > x . RequestedUserId = = userId ) ;
}
}
public async Task < RequestEngineResult > ReProcessRequest ( int requestId , CancellationToken cancellationToken )
public async Task < RequestEngineResult > ReProcessRequest ( int requestId , bool is4K , CancellationToken cancellationToken )
{
{
var request = await MovieRepository . Find ( requestId ) ;
var request = await MovieRepository . Find ( requestId ) ;
if ( request = = null )
if ( request = = null )
@ -695,10 +743,10 @@ namespace Ombi.Core.Engine
} ;
} ;
}
}
return await ProcessSendingMovie ( request );
return await ProcessSendingMovie ( request , is4K );
}
}
public async Task < RequestEngineResult > MarkUnavailable ( int modelId )
public async Task < RequestEngineResult > MarkUnavailable ( int modelId , bool is4K )
{
{
var request = await MovieRepository . Find ( modelId ) ;
var request = await MovieRepository . Find ( modelId ) ;
if ( request = = null )
if ( request = = null )
@ -709,7 +757,14 @@ namespace Ombi.Core.Engine
} ;
} ;
}
}
request . Available = false ;
if ( is4K )
{
request . Available4K = false ;
}
else
{
request . Available = false ;
}
await MovieRepository . Update ( request ) ;
await MovieRepository . Update ( request ) ;
await _mediaCacheService . Purge ( ) ;
await _mediaCacheService . Purge ( ) ;
@ -720,7 +775,7 @@ namespace Ombi.Core.Engine
} ;
} ;
}
}
public async Task < RequestEngineResult > MarkAvailable ( int modelId )
public async Task < RequestEngineResult > MarkAvailable ( int modelId , bool is4K )
{
{
var request = await MovieRepository . Find ( modelId ) ;
var request = await MovieRepository . Find ( modelId ) ;
if ( request = = null )
if ( request = = null )
@ -730,9 +785,16 @@ namespace Ombi.Core.Engine
ErrorMessage = "Request does not exist"
ErrorMessage = "Request does not exist"
} ;
} ;
}
}
if ( ! is4K )
request . Available = true ;
{
request . MarkedAsAvailable = DateTime . Now ;
request . Available = true ;
request . MarkedAsAvailable = DateTime . Now ;
}
else
{
request . Available4K = true ;
request . MarkedAsAvailable4K = DateTime . Now ;
}
await NotificationHelper . Notify ( request , NotificationType . RequestAvailable ) ;
await NotificationHelper . Notify ( request , NotificationType . RequestAvailable ) ;
await MovieRepository . Update ( request ) ;
await MovieRepository . Update ( request ) ;
await _mediaCacheService . Purge ( ) ;
await _mediaCacheService . Purge ( ) ;
@ -744,9 +806,20 @@ namespace Ombi.Core.Engine
} ;
} ;
}
}
private async Task < RequestEngineResult > AddMovieRequest ( MovieRequests model , string movieName , string requestOnBehalf )
private async Task < RequestEngineResult > AddMovieRequest ( MovieRequests model , string movieName , string requestOnBehalf , bool isExisting , bool is4k )
{
{
await MovieRepository . Add ( model ) ;
if ( is4k )
{
model . Has4KRequest = true ;
}
if ( ! isExisting )
{
await MovieRepository . Add ( model ) ;
}
else
{
await MovieRepository . Update ( model ) ;
}
var result = await RunSpecificRule ( model , SpecificRules . CanSendNotification , requestOnBehalf ) ;
var result = await RunSpecificRule ( model , SpecificRules . CanSendNotification , requestOnBehalf ) ;
if ( result . Success )
if ( result . Success )