2015-03-04 00:42:37 +00:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using NLog ;
using NzbDrone.Common.Disk ;
using NzbDrone.Common.Extensions ;
using NzbDrone.Common.Instrumentation.Extensions ;
2017-06-17 13:02:58 +00:00
using NzbDrone.Core.Configuration ;
2015-03-04 00:42:37 +00:00
using NzbDrone.Core.DecisionEngine ;
using NzbDrone.Core.Download ;
using NzbDrone.Core.Download.TrackedDownloads ;
using NzbDrone.Core.MediaFiles.MediaInfo ;
using NzbDrone.Core.Messaging.Commands ;
using NzbDrone.Core.Messaging.Events ;
using NzbDrone.Core.Parser ;
using NzbDrone.Core.Parser.Model ;
using NzbDrone.Core.Tv ;
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Manual
{
public interface IManualImportService
{
List < ManualImportItem > GetMediaFiles ( string path , string downloadId ) ;
}
public class ManualImportService : IExecute < ManualImportCommand > , IManualImportService
{
private readonly IDiskProvider _diskProvider ;
private readonly IParsingService _parsingService ;
private readonly IDiskScanService _diskScanService ;
private readonly IMakeImportDecision _importDecisionMaker ;
private readonly ISeriesService _seriesService ;
2017-01-11 02:12:47 +00:00
private readonly IMovieService _movieService ;
2015-03-04 00:42:37 +00:00
private readonly IEpisodeService _episodeService ;
private readonly IVideoFileInfoReader _videoFileInfoReader ;
private readonly IImportApprovedEpisodes _importApprovedEpisodes ;
2017-01-11 02:12:47 +00:00
private readonly IImportApprovedMovie _importApprovedMovie ;
2015-03-04 00:42:37 +00:00
private readonly ITrackedDownloadService _trackedDownloadService ;
2017-01-11 02:12:47 +00:00
private readonly IDownloadedMovieImportService _downloadedMovieImportService ;
2015-03-04 00:42:37 +00:00
private readonly IEventAggregator _eventAggregator ;
2017-06-17 13:02:58 +00:00
private readonly IConfigService _config ;
2015-03-04 00:42:37 +00:00
private readonly Logger _logger ;
public ManualImportService ( IDiskProvider diskProvider ,
IParsingService parsingService ,
IDiskScanService diskScanService ,
IMakeImportDecision importDecisionMaker ,
ISeriesService seriesService ,
2017-01-11 02:12:47 +00:00
IMovieService movieService ,
2015-03-04 00:42:37 +00:00
IEpisodeService episodeService ,
IVideoFileInfoReader videoFileInfoReader ,
IImportApprovedEpisodes importApprovedEpisodes ,
2017-01-11 02:12:47 +00:00
IImportApprovedMovie importApprovedMovie ,
2015-03-04 00:42:37 +00:00
ITrackedDownloadService trackedDownloadService ,
2017-01-11 02:12:47 +00:00
IDownloadedMovieImportService downloadedMovieImportService ,
2015-03-04 00:42:37 +00:00
IEventAggregator eventAggregator ,
2017-06-17 13:02:58 +00:00
IConfigService config ,
2015-03-04 00:42:37 +00:00
Logger logger )
{
_diskProvider = diskProvider ;
_parsingService = parsingService ;
_diskScanService = diskScanService ;
_importDecisionMaker = importDecisionMaker ;
_seriesService = seriesService ;
2017-01-11 02:12:47 +00:00
_movieService = movieService ;
2015-03-04 00:42:37 +00:00
_episodeService = episodeService ;
_videoFileInfoReader = videoFileInfoReader ;
_importApprovedEpisodes = importApprovedEpisodes ;
2017-01-11 02:12:47 +00:00
_importApprovedMovie = importApprovedMovie ;
2015-03-04 00:42:37 +00:00
_trackedDownloadService = trackedDownloadService ;
2017-01-11 02:12:47 +00:00
_downloadedMovieImportService = downloadedMovieImportService ;
2015-03-04 00:42:37 +00:00
_eventAggregator = eventAggregator ;
2017-06-17 13:02:58 +00:00
_config = config ;
2015-03-04 00:42:37 +00:00
_logger = logger ;
}
public List < ManualImportItem > GetMediaFiles ( string path , string downloadId )
{
if ( downloadId . IsNotNullOrWhiteSpace ( ) )
{
var trackedDownload = _trackedDownloadService . Find ( downloadId ) ;
if ( trackedDownload = = null )
{
return new List < ManualImportItem > ( ) ;
}
path = trackedDownload . DownloadItem . OutputPath . FullPath ;
}
if ( ! _diskProvider . FolderExists ( path ) )
{
if ( ! _diskProvider . FileExists ( path ) )
{
return new List < ManualImportItem > ( ) ;
}
return new List < ManualImportItem > { ProcessFile ( path , downloadId ) } ;
}
return ProcessFolder ( path , downloadId ) ;
}
private List < ManualImportItem > ProcessFolder ( string folder , string downloadId )
{
var directoryInfo = new DirectoryInfo ( folder ) ;
2017-02-11 17:26:35 +00:00
var series = _parsingService . GetMovie ( directoryInfo . Name ) ;
2015-03-04 00:42:37 +00:00
if ( series = = null & & downloadId . IsNotNullOrWhiteSpace ( ) )
{
var trackedDownload = _trackedDownloadService . Find ( downloadId ) ;
2017-02-11 17:26:35 +00:00
series = trackedDownload . RemoteMovie . Movie ;
2015-03-04 00:42:37 +00:00
}
if ( series = = null )
{
var files = _diskScanService . GetVideoFiles ( folder ) ;
return files . Select ( file = > ProcessFile ( file , downloadId , folder ) ) . Where ( i = > i ! = null ) . ToList ( ) ;
}
2017-06-17 13:02:58 +00:00
var folderInfo = Parser . Parser . ParseMovieTitle ( directoryInfo . Name , _config . ParsingLeniency > 0 ) ;
2015-03-04 00:42:37 +00:00
var seriesFiles = _diskScanService . GetVideoFiles ( folder ) . ToList ( ) ;
2017-02-11 17:26:35 +00:00
var decisions = _importDecisionMaker . GetImportDecisions ( seriesFiles , series , folderInfo , SceneSource ( series , folder ) , false ) ;
2015-03-04 00:42:37 +00:00
return decisions . Select ( decision = > MapItem ( decision , folder , downloadId ) ) . ToList ( ) ;
}
private ManualImportItem ProcessFile ( string file , string downloadId , string folder = null )
{
if ( folder . IsNullOrWhiteSpace ( ) )
{
folder = new FileInfo ( file ) . Directory . FullName ;
}
2016-08-14 19:05:35 +00:00
var relativeFile = folder . GetRelativePath ( file ) ;
2017-01-11 02:12:47 +00:00
var movie = _parsingService . GetMovie ( relativeFile . Split ( '\\' , '/' ) [ 0 ] ) ;
2016-08-14 19:05:35 +00:00
2017-01-11 02:12:47 +00:00
if ( movie = = null )
2016-08-14 19:05:35 +00:00
{
2017-01-11 02:12:47 +00:00
movie = _parsingService . GetMovie ( relativeFile ) ;
2016-08-14 19:05:35 +00:00
}
2015-03-04 00:42:37 +00:00
2017-01-11 02:12:47 +00:00
if ( movie = = null & & downloadId . IsNotNullOrWhiteSpace ( ) )
2015-03-04 00:42:37 +00:00
{
var trackedDownload = _trackedDownloadService . Find ( downloadId ) ;
2017-01-11 02:12:47 +00:00
movie = trackedDownload . RemoteMovie . Movie ;
2015-03-04 00:42:37 +00:00
}
2017-01-11 02:12:47 +00:00
if ( movie = = null )
2015-03-04 00:42:37 +00:00
{
2017-01-11 02:12:47 +00:00
var localMovie = new LocalMovie ( )
{
Path = file ,
Quality = QualityParser . ParseQuality ( file ) ,
Size = _diskProvider . GetFileSize ( file )
} ;
2015-03-04 00:42:37 +00:00
2017-01-11 02:12:47 +00:00
return MapItem ( new ImportDecision ( localMovie , new Rejection ( "Unknown Movie" ) ) , folder , downloadId ) ;
2015-03-04 00:42:37 +00:00
}
2017-01-11 02:12:47 +00:00
var importDecisions = _importDecisionMaker . GetImportDecisions ( new List < string > { file } ,
2017-01-14 12:33:30 +00:00
movie , null , SceneSource ( movie , folder ) , true ) ;
2015-03-04 00:42:37 +00:00
2017-06-13 06:40:51 +00:00
return importDecisions . Any ( ) ? MapItem ( importDecisions . First ( ) , folder , downloadId ) : new ManualImportItem
{
DownloadId = downloadId ,
Path = file ,
RelativePath = folder . GetRelativePath ( file ) ,
Name = Path . GetFileNameWithoutExtension ( file ) ,
Rejections = new List < Rejection >
{
new Rejection ( "Unable to process file" )
}
} ;
2015-03-04 00:42:37 +00:00
}
2017-01-11 02:12:47 +00:00
//private ManualImportItem ProcessFile(string file, string downloadId, string folder = null)
//{
// if (folder.IsNullOrWhiteSpace())
// {
// folder = new FileInfo(file).Directory.FullName;
// }
// var relativeFile = folder.GetRelativePath(file);
// var series = _parsingService.GetSeries(relativeFile.Split('\\', '/')[0]);
// if (series == null)
// {
// series = _parsingService.GetSeries(relativeFile);
// }
// if (series == null && downloadId.IsNotNullOrWhiteSpace())
// {
// var trackedDownload = _trackedDownloadService.Find(downloadId);
// series = trackedDownload.RemoteEpisode.Series;
// }
// if (series == null)
// {
// var localEpisode = new LocalEpisode();
// localEpisode.Path = file;
// localEpisode.Quality = QualityParser.ParseQuality(file);
// localEpisode.Size = _diskProvider.GetFileSize(file);
// return MapItem(new ImportDecision(localEpisode, new Rejection("Unknown Series")), folder, downloadId);
// }
// var importDecisions = _importDecisionMaker.GetImportDecisions(new List<string> {file},
// series, null, SceneSource(series, folder));
// return importDecisions.Any() ? MapItem(importDecisions.First(), folder, downloadId) : null;
//}
2015-03-04 00:42:37 +00:00
private bool SceneSource ( Series series , string folder )
{
return ! ( series . Path . PathEquals ( folder ) | | series . Path . IsParentPath ( folder ) ) ;
}
2017-01-11 02:12:47 +00:00
private bool SceneSource ( Movie movie , string folder )
{
return ! ( movie . Path . PathEquals ( folder ) | | movie . Path . IsParentPath ( folder ) ) ;
}
//private ManualImportItem MapItem(ImportDecision decision, string folder, string downloadId)
//{
// var item = new ManualImportItem();
// item.Path = decision.LocalEpisode.Path;
// item.RelativePath = folder.GetRelativePath(decision.LocalEpisode.Path);
// item.Name = Path.GetFileNameWithoutExtension(decision.LocalEpisode.Path);
// item.DownloadId = downloadId;
// if (decision.LocalEpisode.Series != null)
// {
// item.Series = decision.LocalEpisode.Series;
// }
// if (decision.LocalEpisode.Episodes.Any())
// {
// item.SeasonNumber = decision.LocalEpisode.SeasonNumber;
// item.Episodes = decision.LocalEpisode.Episodes;
// }
// item.Quality = decision.LocalEpisode.Quality;
// item.Size = _diskProvider.GetFileSize(decision.LocalEpisode.Path);
// item.Rejections = decision.Rejections;
// return item;
//}
2015-03-04 00:42:37 +00:00
private ManualImportItem MapItem ( ImportDecision decision , string folder , string downloadId )
{
var item = new ManualImportItem ( ) ;
2017-01-11 02:12:47 +00:00
item . Path = decision . LocalMovie . Path ;
item . RelativePath = folder . GetRelativePath ( decision . LocalMovie . Path ) ;
item . Name = Path . GetFileNameWithoutExtension ( decision . LocalMovie . Path ) ;
2015-03-04 00:42:37 +00:00
item . DownloadId = downloadId ;
2017-01-11 02:12:47 +00:00
if ( decision . LocalMovie . Movie ! = null )
2015-03-04 00:42:37 +00:00
{
2017-01-11 02:12:47 +00:00
item . Movie = decision . LocalMovie . Movie ;
2015-03-04 00:42:37 +00:00
}
2017-01-11 02:12:47 +00:00
item . Quality = decision . LocalMovie . Quality ;
item . Size = _diskProvider . GetFileSize ( decision . LocalMovie . Path ) ;
2015-03-04 00:42:37 +00:00
item . Rejections = decision . Rejections ;
return item ;
}
public void Execute ( ManualImportCommand message )
{
2016-10-18 19:17:50 +00:00
_logger . ProgressTrace ( "Manually importing {0} files using mode {1}" , message . Files . Count , message . ImportMode ) ;
2015-03-04 00:42:37 +00:00
var imported = new List < ImportResult > ( ) ;
var importedTrackedDownload = new List < ManuallyImportedFile > ( ) ;
for ( int i = 0 ; i < message . Files . Count ; i + + )
{
2015-05-17 23:07:27 +00:00
_logger . ProgressTrace ( "Processing file {0} of {1}" , i + 1 , message . Files . Count ) ;
2016-08-14 19:05:35 +00:00
2015-03-04 00:42:37 +00:00
var file = message . Files [ i ] ;
2017-01-11 02:12:47 +00:00
var movie = _movieService . GetMovie ( file . MovieId ) ;
2017-06-17 13:02:58 +00:00
var parsedMovieInfo = Parser . Parser . ParseMoviePath ( file . Path , _config . ParsingLeniency > 0 ) ? ? new ParsedMovieInfo ( ) ;
2015-03-04 00:42:37 +00:00
var mediaInfo = _videoFileInfoReader . GetMediaInfo ( file . Path ) ;
2017-01-11 02:12:47 +00:00
var existingFile = movie . Path . IsParentPath ( file . Path ) ;
2015-03-04 00:42:37 +00:00
2017-01-11 02:12:47 +00:00
var localMovie = new LocalMovie
2015-03-04 00:42:37 +00:00
{
ExistingFile = false ,
MediaInfo = mediaInfo ,
2017-01-11 02:12:47 +00:00
ParsedMovieInfo = parsedMovieInfo ,
2015-03-04 00:42:37 +00:00
Path = file . Path ,
Quality = file . Quality ,
2017-01-11 02:12:47 +00:00
Movie = movie ,
2015-03-04 00:42:37 +00:00
Size = 0
} ;
//TODO: Cleanup non-tracked downloads
2017-01-11 02:12:47 +00:00
var importDecision = new ImportDecision ( localMovie ) ;
2015-03-04 00:42:37 +00:00
if ( file . DownloadId . IsNullOrWhiteSpace ( ) )
{
2017-01-11 02:12:47 +00:00
imported . AddRange ( _importApprovedMovie . Import ( new List < ImportDecision > { importDecision } , ! existingFile , null , message . ImportMode ) ) ;
2015-03-04 00:42:37 +00:00
}
else
{
var trackedDownload = _trackedDownloadService . Find ( file . DownloadId ) ;
2017-01-11 02:12:47 +00:00
var importResult = _importApprovedMovie . Import ( new List < ImportDecision > { importDecision } , true , trackedDownload . DownloadItem , message . ImportMode ) . First ( ) ;
2015-03-04 00:42:37 +00:00
imported . Add ( importResult ) ;
importedTrackedDownload . Add ( new ManuallyImportedFile
2017-01-11 02:12:47 +00:00
{
TrackedDownload = trackedDownload ,
ImportResult = importResult
} ) ;
2015-03-04 00:42:37 +00:00
}
}
2015-05-17 23:07:27 +00:00
_logger . ProgressTrace ( "Manually imported {0} files" , imported . Count ) ;
2015-03-04 00:42:37 +00:00
foreach ( var groupedTrackedDownload in importedTrackedDownload . GroupBy ( i = > i . TrackedDownload . DownloadItem . DownloadId ) . ToList ( ) )
{
var trackedDownload = groupedTrackedDownload . First ( ) . TrackedDownload ;
if ( _diskProvider . FolderExists ( trackedDownload . DownloadItem . OutputPath . FullPath ) )
{
2017-01-11 02:12:47 +00:00
if ( _downloadedMovieImportService . ShouldDeleteFolder (
2015-03-04 00:42:37 +00:00
new DirectoryInfo ( trackedDownload . DownloadItem . OutputPath . FullPath ) ,
2017-01-11 02:12:47 +00:00
trackedDownload . RemoteMovie . Movie ) & & ! trackedDownload . DownloadItem . IsReadOnly )
2015-03-04 00:42:37 +00:00
{
_diskProvider . DeleteFolder ( trackedDownload . DownloadItem . OutputPath . FullPath , true ) ;
}
}
2017-01-11 02:12:47 +00:00
if ( groupedTrackedDownload . Select ( c = > c . ImportResult ) . Count ( c = > c . Result = = ImportResultType . Imported ) > = Math . Max ( 1 , 1 ) ) //TODO: trackedDownload.RemoteMovie.Movie.Count is always 1?
2015-03-04 00:42:37 +00:00
{
trackedDownload . State = TrackedDownloadStage . Imported ;
_eventAggregator . PublishEvent ( new DownloadCompletedEvent ( trackedDownload ) ) ;
}
}
}
2017-01-11 02:12:47 +00:00
//public void Execute(ManualImportCommand message)
//{
// _logger.ProgressTrace("Manually importing {0} files using mode {1}", message.Files.Count, message.ImportMode);
// var imported = new List<ImportResult>();
// var importedTrackedDownload = new List<ManuallyImportedFile>();
// for (int i = 0; i < message.Files.Count; i++)
// {
// _logger.ProgressTrace("Processing file {0} of {1}", i + 1, message.Files.Count);
// var file = message.Files[i];
// var series = _seriesService.GetSeries(file.SeriesId);
// var episodes = _episodeService.GetEpisodes(file.EpisodeIds);
// var parsedEpisodeInfo = Parser.Parser.ParsePath(file.Path) ?? new ParsedEpisodeInfo();
// var mediaInfo = _videoFileInfoReader.GetMediaInfo(file.Path);
// var existingFile = series.Path.IsParentPath(file.Path);
// var localEpisode = new LocalEpisode
// {
// ExistingFile = false,
// Episodes = episodes,
// MediaInfo = mediaInfo,
// ParsedEpisodeInfo = parsedEpisodeInfo,
// Path = file.Path,
// Quality = file.Quality,
// Series = series,
// Size = 0
// };
// //TODO: Cleanup non-tracked downloads
// var importDecision = new ImportDecision(localEpisode);
// if (file.DownloadId.IsNullOrWhiteSpace())
// {
// imported.AddRange(_importApprovedEpisodes.Import(new List<ImportDecision> { importDecision }, !existingFile, null, message.ImportMode));
// }
// else
// {
// var trackedDownload = _trackedDownloadService.Find(file.DownloadId);
// var importResult = _importApprovedEpisodes.Import(new List<ImportDecision> { importDecision }, true, trackedDownload.DownloadItem, message.ImportMode).First();
// imported.Add(importResult);
// importedTrackedDownload.Add(new ManuallyImportedFile
// {
// TrackedDownload = trackedDownload,
// ImportResult = importResult
// });
// }
// }
// _logger.ProgressTrace("Manually imported {0} files", imported.Count);
// foreach (var groupedTrackedDownload in importedTrackedDownload.GroupBy(i => i.TrackedDownload.DownloadItem.DownloadId).ToList())
// {
// var trackedDownload = groupedTrackedDownload.First().TrackedDownload;
// if (_diskProvider.FolderExists(trackedDownload.DownloadItem.OutputPath.FullPath))
// {
// if (_downloadedEpisodesImportService.ShouldDeleteFolder(
// new DirectoryInfo(trackedDownload.DownloadItem.OutputPath.FullPath),
// trackedDownload.RemoteEpisode.Series) && !trackedDownload.DownloadItem.IsReadOnly)
// {
// _diskProvider.DeleteFolder(trackedDownload.DownloadItem.OutputPath.FullPath, true);
// }
// }
// if (groupedTrackedDownload.Select(c => c.ImportResult).Count(c => c.Result == ImportResultType.Imported) >= Math.Max(1, trackedDownload.RemoteEpisode.Episodes.Count))
// {
// trackedDownload.State = TrackedDownloadStage.Imported;
// _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
// }
// }
//}
2015-03-04 00:42:37 +00:00
}
}