2020-09-04 02:50:56 +00:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Threading.Tasks ;
using NLog ;
using NzbDrone.Common.Instrumentation.Extensions ;
using NzbDrone.Common.TPL ;
using NzbDrone.Core.ImportLists.ImportListMovies ;
using NzbDrone.Core.MetadataSource ;
using NzbDrone.Core.Movies ;
namespace NzbDrone.Core.ImportLists
{
public interface IFetchAndParseImportList
{
ImportListFetchResult Fetch ( ) ;
ImportListFetchResult FetchSingleList ( ImportListDefinition definition ) ;
}
public class FetchAndParseImportListService : IFetchAndParseImportList
{
private readonly IImportListFactory _importListFactory ;
private readonly IImportListStatusService _importListStatusService ;
private readonly IImportListMovieService _listMovieService ;
private readonly ISearchForNewMovie _movieSearch ;
2022-07-15 04:17:27 +00:00
private readonly IProvideMovieInfo _movieInfoService ;
2022-03-20 15:55:47 +00:00
private readonly IMovieMetadataService _movieMetadataService ;
2020-09-04 02:50:56 +00:00
private readonly Logger _logger ;
public FetchAndParseImportListService ( IImportListFactory importListFactory ,
IImportListStatusService importListStatusService ,
IImportListMovieService listMovieService ,
ISearchForNewMovie movieSearch ,
2022-07-15 04:17:27 +00:00
IProvideMovieInfo movieInfoService ,
2022-03-20 15:55:47 +00:00
IMovieMetadataService movieMetadataService ,
2020-09-04 02:50:56 +00:00
Logger logger )
{
_importListFactory = importListFactory ;
_importListStatusService = importListStatusService ;
_listMovieService = listMovieService ;
_movieSearch = movieSearch ;
2022-07-15 04:17:27 +00:00
_movieInfoService = movieInfoService ;
2022-03-20 15:55:47 +00:00
_movieMetadataService = movieMetadataService ;
2020-09-04 02:50:56 +00:00
_logger = logger ;
}
public ImportListFetchResult Fetch ( )
{
var result = new ImportListFetchResult ( ) ;
var importLists = _importListFactory . Enabled ( ) ;
if ( ! importLists . Any ( ) )
{
_logger . Debug ( "No available import lists. check your configuration." ) ;
return result ;
}
_logger . Debug ( "Available import lists {0}" , importLists . Count ) ;
var taskList = new List < Task > ( ) ;
var taskFactory = new TaskFactory ( TaskCreationOptions . LongRunning , TaskContinuationOptions . None ) ;
foreach ( var importList in importLists )
{
var importListLocal = importList ;
2023-07-04 16:17:28 +00:00
var importListStatus = _importListStatusService . GetLastSyncListInfo ( importListLocal . Definition . Id ) ;
2023-07-10 01:33:20 +00:00
if ( importListStatus . HasValue )
2023-07-04 16:17:28 +00:00
{
2023-07-10 01:33:20 +00:00
var importListNextSync = importListStatus . Value + importListLocal . MinRefreshInterval ;
if ( DateTime . UtcNow < importListNextSync )
{
2023-07-11 04:22:59 +00:00
_logger . Trace ( "Skipping refresh of Import List {0} ({1}) due to minimum refresh interval. Next Sync after {2}" , importList . Name , importListLocal . Definition . Name , importListNextSync ) ;
2023-07-10 17:57:51 +00:00
2023-07-10 16:44:11 +00:00
continue ;
2023-07-10 01:33:20 +00:00
}
2023-07-04 16:17:28 +00:00
}
2023-07-10 17:57:51 +00:00
2023-07-11 04:22:59 +00:00
_logger . ProgressInfo ( "Syncing Movies for Import List {0} ({1})" , importList . Name , importListLocal . Definition . Name ) ;
2023-07-04 16:17:28 +00:00
2020-09-04 02:50:56 +00:00
var blockedLists = _importListStatusService . GetBlockedProviders ( ) . ToDictionary ( v = > v . ProviderId , v = > v ) ;
2023-05-23 10:52:39 +00:00
if ( blockedLists . TryGetValue ( importList . Definition . Id , out var blockedListStatus ) )
2020-09-04 02:50:56 +00:00
{
2023-07-11 04:22:59 +00:00
_logger . Debug ( "Temporarily ignoring Import List {0} ({1}) till {2} due to recent failures." , importList . Name , importListLocal . Definition . Name , blockedListStatus . DisabledTill . Value . ToLocalTime ( ) ) ;
2022-11-20 18:27:45 +00:00
result . AnyFailure | = true ; // Ensure we don't clean if a list is down
2020-09-04 02:50:56 +00:00
continue ;
}
var task = taskFactory . StartNew ( ( ) = >
{
try
{
var importListReports = importListLocal . Fetch ( ) ;
lock ( result )
{
2023-07-11 04:22:59 +00:00
_logger . Debug ( "Found {0} from Import List {1} ({2})" , importListReports . Movies . Count , importList . Name , importListLocal . Definition . Name ) ;
2020-09-04 02:50:56 +00:00
if ( ! importListReports . AnyFailure )
{
2022-07-15 04:17:27 +00:00
var alreadyMapped = result . Movies . Where ( x = > importListReports . Movies . Any ( r = > r . TmdbId = = x . TmdbId ) ) ;
2023-07-04 16:17:28 +00:00
var listMovies = MapMovieReports ( importListReports . Movies . Where ( x = > result . Movies . All ( r = > r . TmdbId ! = x . TmdbId ) ) . ToList ( ) ) . Where ( x = > x . TmdbId > 0 ) . ToList ( ) ;
2020-09-04 02:50:56 +00:00
2022-07-15 04:17:27 +00:00
listMovies . AddRange ( alreadyMapped ) ;
2020-09-04 02:50:56 +00:00
listMovies = listMovies . DistinctBy ( x = > x . TmdbId ) . ToList ( ) ;
listMovies . ForEach ( m = > m . ListId = importList . Definition . Id ) ;
result . Movies . AddRange ( listMovies ) ;
_listMovieService . SyncMoviesForList ( listMovies , importList . Definition . Id ) ;
}
result . AnyFailure | = importListReports . AnyFailure ;
2023-08-18 02:50:22 +00:00
result . SyncedLists + + ;
2023-07-04 16:17:28 +00:00
_importListStatusService . UpdateListSyncStatus ( importList . Definition . Id ) ;
2020-09-04 02:50:56 +00:00
}
}
catch ( Exception e )
{
2023-07-11 04:22:59 +00:00
_logger . Error ( e , "Error during Import List Sync of {0} ({1})" , importList . Name , importListLocal . Definition . Name ) ;
2020-09-04 02:50:56 +00:00
}
} ) . LogExceptions ( ) ;
taskList . Add ( task ) ;
}
Task . WaitAll ( taskList . ToArray ( ) ) ;
2023-07-04 16:17:28 +00:00
result . Movies = result . Movies . DistinctBy ( r = > new { r . TmdbId , r . ImdbId , r . Title } ) . ToList ( ) ;
2023-08-18 02:50:22 +00:00
_logger . Debug ( "Found {0} total reports from {1} lists" , result . Movies . Count , result . SyncedLists ) ;
2020-09-04 02:50:56 +00:00
return result ;
}
public ImportListFetchResult FetchSingleList ( ImportListDefinition definition )
{
var result = new ImportListFetchResult ( ) ;
var importList = _importListFactory . GetInstance ( definition ) ;
if ( importList = = null | | ! definition . Enable )
{
2023-07-11 04:22:59 +00:00
_logger . Debug ( "Import List {0} ({1}) is not enabled, skipping." , importList . Name , importList . Definition . Name ) ;
2020-09-04 02:50:56 +00:00
return result ;
}
var importListLocal = importList ;
try
{
var importListReports = importListLocal . Fetch ( ) ;
lock ( result )
{
2023-07-11 04:22:59 +00:00
_logger . Debug ( "Found {0} movies from {1} ({2})" , importListReports . Movies . Count , importList . Name , importListLocal . Definition . Name ) ;
2020-09-04 02:50:56 +00:00
if ( ! importListReports . AnyFailure )
{
2022-07-15 04:17:27 +00:00
var listMovies = MapMovieReports ( importListReports . Movies ) . Where ( x = > x . TmdbId > 0 ) . ToList ( ) ;
2020-09-04 02:50:56 +00:00
listMovies = listMovies . DistinctBy ( x = > x . TmdbId ) . ToList ( ) ;
2022-07-17 17:55:13 +00:00
listMovies . ForEach ( m = > m . ListId = importList . Definition . Id ) ;
2020-09-04 02:50:56 +00:00
result . Movies . AddRange ( listMovies ) ;
_listMovieService . SyncMoviesForList ( listMovies , importList . Definition . Id ) ;
}
result . AnyFailure | = importListReports . AnyFailure ;
2023-07-04 16:17:28 +00:00
_importListStatusService . UpdateListSyncStatus ( importList . Definition . Id ) ;
2020-09-04 02:50:56 +00:00
}
}
catch ( Exception e )
{
2023-07-11 04:22:59 +00:00
_logger . Error ( e , "Error during Import List Sync of {0} ({1})" , importList . Name , importListLocal . Definition . Name ) ;
2020-09-04 02:50:56 +00:00
}
2023-07-04 16:17:28 +00:00
result . Movies = result . Movies . DistinctBy ( r = > new { r . TmdbId , r . ImdbId , r . Title } ) . ToList ( ) ;
2023-07-11 04:22:59 +00:00
_logger . Debug ( "Found {0} movies from {1} ({2})" , result . Movies . Count , importList . Name , importListLocal . Definition . Name ) ;
2020-09-04 02:50:56 +00:00
return result ;
}
2022-07-15 04:17:27 +00:00
private List < ImportListMovie > MapMovieReports ( List < ImportListMovie > reports )
2020-09-04 02:50:56 +00:00
{
2022-07-15 04:17:27 +00:00
var mappedMovies = reports . Select ( m = > _movieSearch . MapMovieToTmdbMovie ( new MovieMetadata { Title = m . Title , TmdbId = m . TmdbId , ImdbId = m . ImdbId , Year = m . Year } ) )
2023-07-04 16:17:28 +00:00
. Where ( x = > x ! = null )
. DistinctBy ( x = > x . TmdbId )
. ToList ( ) ;
2022-07-15 04:17:27 +00:00
_movieMetadataService . UpsertMany ( mappedMovies ) ;
2022-03-20 15:55:47 +00:00
2022-07-15 04:17:27 +00:00
var mappedListMovies = new List < ImportListMovie > ( ) ;
2020-09-04 02:50:56 +00:00
2022-07-17 17:55:13 +00:00
foreach ( var movieMeta in mappedMovies )
2020-09-04 02:50:56 +00:00
{
2022-07-17 17:55:13 +00:00
var mappedListMovie = new ImportListMovie ( ) ;
2022-07-15 04:17:27 +00:00
if ( movieMeta ! = null )
{
mappedListMovie . MovieMetadata = movieMeta ;
mappedListMovie . MovieMetadataId = movieMeta . Id ;
}
2022-05-12 00:46:41 +00:00
2022-07-15 04:17:27 +00:00
mappedListMovies . Add ( mappedListMovie ) ;
2020-09-04 02:50:56 +00:00
}
2022-07-15 04:17:27 +00:00
return mappedListMovies ;
2020-09-04 02:50:56 +00:00
}
}
}