public LocalEpisode Augment(LocalEpisode localEpisode, DownloadClientItem downloadClientItem, bool otherFiles)
        {
            var isMediaFile = MediaFileExtensions.Extensions.Contains(Path.GetExtension(localEpisode.Path));

            if (localEpisode.DownloadClientEpisodeInfo == null &&
                localEpisode.FolderEpisodeInfo == null &&
                localEpisode.FileEpisodeInfo == null)
            {
                if (isMediaFile)
                {
                    throw new AugmentingFailedException("Unable to parse episode info from path: {0}", localEpisode.Path);
                }
            }

            localEpisode.Size = _diskProvider.GetFileSize(localEpisode.Path);

            if (isMediaFile && (!localEpisode.ExistingFile || _configService.EnableMediaInfo))
            {
                localEpisode.MediaInfo = _videoFileInfoReader.GetMediaInfo(localEpisode.Path);
            }

            foreach (var augmenter in _augmenters)
            {
                try
                {
                    augmenter.Aggregate(localEpisode, downloadClientItem, otherFiles);
                }
                catch (Exception ex)
                {
                    _logger.Warn(ex, ex.Message);
                }
            }

            return(localEpisode);
        }
Example #2
0
        private IEnumerable <ImportDecision> GetDecisions(IEnumerable <String> videoFiles, Series series, bool sceneSource, QualityModel quality = null)
        {
            foreach (var file in videoFiles)
            {
                ImportDecision decision = null;

                try
                {
                    var localEpisode = _parsingService.GetLocalEpisode(file, series, sceneSource);

                    if (localEpisode != null)
                    {
                        if (quality != null &&
                            new QualityModelComparer(localEpisode.Series.Profile).Compare(quality,
                                                                                          localEpisode.Quality) > 0)
                        {
                            _logger.Debug("Using quality from folder: {0}", quality);
                            localEpisode.Quality = quality;
                        }

                        localEpisode.Size = _diskProvider.GetFileSize(file);
                        _logger.Debug("Size: {0}", localEpisode.Size);

                        //TODO: make it so media info doesn't ruin the import process of a new series
                        if (sceneSource)
                        {
                            localEpisode.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
                        }

                        decision = GetDecision(localEpisode);
                    }

                    else
                    {
                        localEpisode      = new LocalEpisode();
                        localEpisode.Path = file;

                        decision = new ImportDecision(localEpisode, "Unable to parse file");
                    }
                }
                catch (EpisodeNotFoundException e)
                {
                    var localEpisode = new LocalEpisode();
                    localEpisode.Path = file;

                    decision = new ImportDecision(localEpisode, e.Message);
                }
                catch (Exception e)
                {
                    _logger.ErrorException("Couldn't import file. " + file, e);
                }

                if (decision != null)
                {
                    yield return(decision);
                }
            }
        }
Example #3
0
        private ImportDecision GetDecision(string file, Series series, DownloadClientItem downloadClientItem, ParsedEpisodeInfo folderInfo, bool sceneSource, bool shouldUseFolderName)
        {
            ImportDecision decision = null;

            try
            {
                var localEpisode = _parsingService.GetLocalEpisode(file, series, shouldUseFolderName ? folderInfo : null, sceneSource);

                if (localEpisode != null)
                {
                    localEpisode.Quality = GetQuality(folderInfo, localEpisode.Quality, series);
                    localEpisode.Size    = _diskProvider.GetFileSize(file);

                    _logger.Debug("Size: {0}", localEpisode.Size);

                    //TODO: make it so media info doesn't ruin the import process of a new series
                    if (sceneSource)
                    {
                        localEpisode.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
                    }

                    if (localEpisode.Episodes.Empty())
                    {
                        decision = new ImportDecision(localEpisode, new Rejection("Invalid season or episode"));
                    }
                    else
                    {
                        decision = GetDecision(localEpisode, downloadClientItem);
                    }
                }

                else
                {
                    localEpisode      = new LocalEpisode();
                    localEpisode.Path = file;

                    decision = new ImportDecision(localEpisode, new Rejection("Unable to parse file"));
                }
            }
            catch (Exception e)
            {
                _logger.Error(e, "Couldn't import file. {0}", file);

                var localEpisode = new LocalEpisode {
                    Path = file
                };
                decision = new ImportDecision(localEpisode, new Rejection("Unexpected error processing file"));
            }

            if (decision == null)
            {
                _logger.Error("Unable to make a decision on {0}", file);
            }

            return(decision);
        }
Example #4
0
        private ImportDecision GetDecision(string file, Series series, ParsedEpisodeInfo folderInfo, bool sceneSource, bool shouldUseFolderName)
        {
            ImportDecision decision = null;

            try
            {
                var localEpisode = _parsingService.GetLocalEpisode(file, series, shouldUseFolderName ? folderInfo : null, sceneSource);

                if (localEpisode != null)
                {
                    localEpisode.Quality = GetQuality(folderInfo, localEpisode.Quality, series);
                    localEpisode.Size    = _diskProvider.GetFileSize(file);

                    _logger.Debug("Size: {0}", localEpisode.Size);

                    //TODO: make it so media info doesn't ruin the import process of a new series
                    if (sceneSource)
                    {
                        localEpisode.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
                    }

                    decision = GetDecision(localEpisode);
                }

                else
                {
                    localEpisode      = new LocalEpisode();
                    localEpisode.Path = file;

                    decision = new ImportDecision(localEpisode, new Rejection("Unable to parse file"));
                }
            }
            catch (EpisodeNotFoundException e)
            {
                var localEpisode = new LocalEpisode();
                localEpisode.Path = file;

                decision = new ImportDecision(localEpisode, new Rejection(e.Message));
            }
            catch (Exception e)
            {
                _logger.ErrorException("Couldn't import file. " + file, e);
            }

            return(decision);
        }
        private void UpdateMediaInfo(EpisodeFile episodeFile, Series series)
        {
            var path = Path.Combine(series.Path, episodeFile.RelativePath);

            if (!_diskProvider.FileExists(path))
            {
                _logger.Debug("Can't update MediaInfo because '{0}' does not exist", path);
                return;
            }

            var updatedMediaInfo = _videoFileInfoReader.GetMediaInfo(path);

            if (updatedMediaInfo != null)
            {
                episodeFile.MediaInfo = updatedMediaInfo;
                _mediaFileService.Update(episodeFile);
                _logger.Debug("Updated MediaInfo for '{0}'", path);
            }
        }
Example #6
0
        private void UpdateMediaInfo(Series series, List <EpisodeFile> mediaFiles)
        {
            foreach (var mediaFile in mediaFiles)
            {
                var path = Path.Combine(series.Path, mediaFile.RelativePath);

                if (!_diskProvider.FileExists(path))
                {
                    _logger.Debug("Can't update MediaInfo because '{0}' does not exist", path);
                    continue;
                }

                mediaFile.MediaInfo = _videoFileInfoReader.GetMediaInfo(path);

                if (mediaFile.MediaInfo != null)
                {
                    _mediaFileService.Update(mediaFile);
                    _logger.Debug("Updated MediaInfo for '{0}'", path);
                }
            }
        }
        private void UpdateMediaInfo(Movie series, List <MovieFile> mediaFiles)
        {
            foreach (var mediaFile in mediaFiles)
            {
                var path = Path.Combine(series.Path, mediaFile.RelativePath);

                if (!_diskProvider.FileExists(path))
                {
                    _logger.Debug("Can't update MediaInfo because '{0}' does not exist", path);
                    continue;
                }

                mediaFile.MediaInfo = _videoFileInfoReader.GetMediaInfo(path);

                if (mediaFile.MediaInfo != null)
                {
                    mediaFile.MediaInfo.SchemaRevision = CURRENT_MEDIA_INFO_SCHEMA_REVISION;
                    _mediaFileService.Update(mediaFile);
                    _logger.Debug("Updated MediaInfo for '{0}'", path);
                }
            }
        }
        private bool UpdateMediaInfo(MovieFile movieFile, Movie movie)
        {
            var path = Path.Combine(movie.Path, movieFile.RelativePath);

            if (!_diskProvider.FileExists(path))
            {
                _logger.Debug("Can't update MediaInfo because '{0}' does not exist", path);
                return(false);
            }

            var updatedMediaInfo = _videoFileInfoReader.GetMediaInfo(path);

            if (updatedMediaInfo == null)
            {
                return(false);
            }

            movieFile.MediaInfo = updatedMediaInfo;
            _mediaFileService.Update(movieFile);
            _logger.Debug("Updated MediaInfo for '{0}'", path);

            return(true);
        }
Example #9
0
        public void Execute(ManualImportCommand message)
        {
            _logger.ProgressTrace("Manually importing {0} files", message.Files.Count);

            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: Option to copy instead of import
                //TODO: Cleanup non-tracked downloads

                var importDecision = new ImportDecision(localEpisode);

                if (file.DownloadId.IsNullOrWhiteSpace())
                {
                    imported.AddRange(_importApprovedEpisodes.Import(new List <ImportDecision> {
                        importDecision
                    }, !existingFile));
                }

                else
                {
                    var trackedDownload = _trackedDownloadService.Find(file.DownloadId);
                    var importResult    = _importApprovedEpisodes.Import(new List <ImportDecision> {
                        importDecision
                    }, true, trackedDownload.DownloadItem).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));
                }
            }
        }
Example #10
0
        private ImportDecision GetDecision(string file, Movie movie, DownloadClientItem downloadClientItem, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldUseFolderName, bool shouldCheckQuality = false)
        {
            ImportDecision decision = null;

            try
            {
                var minimalInfo = shouldUseFolderName
                    ? folderInfo.JsonClone()
                    : _parsingService.ParseMinimalPathMovieInfo(file);

                LocalMovie localMovie = null;
                //var localMovie = _parsingService.GetLocalMovie(file, movie, shouldUseFolderName ? folderInfo : null, sceneSource);

                if (minimalInfo != null)
                {
                    //TODO: make it so media info doesn't ruin the import process of a new movie
                    var mediaInfo        = _config.EnableMediaInfo ? _videoFileInfoReader.GetMediaInfo(file) : null;
                    var size             = _diskProvider.GetFileSize(file);
                    var historyItems     = _historyService.FindByDownloadId(downloadClientItem?.DownloadId ?? "");
                    var firstHistoryItem = historyItems.OrderByDescending(h => h.Date).FirstOrDefault();
                    var sizeMovie        = new LocalMovie();
                    sizeMovie.Size = size;
                    localMovie     = _parsingService.GetLocalMovie(file, minimalInfo, movie, new List <object> {
                        mediaInfo, firstHistoryItem, sizeMovie
                    }, sceneSource);
                    localMovie.Quality = GetQuality(folderInfo, localMovie.Quality, movie);
                    localMovie.Size    = size;

                    _logger.Debug("Size: {0}", localMovie.Size);

                    decision = GetDecision(localMovie, downloadClientItem);
                }

                else
                {
                    localMovie      = new LocalMovie();
                    localMovie.Path = file;

                    if (MediaFileExtensions.Extensions.Contains(Path.GetExtension(file)))
                    {
                        _logger.Warn("Unable to parse movie info from path {0}", file);
                    }

                    decision = new ImportDecision(localMovie, new Rejection("Unable to parse file"));
                }
            }
            catch (Exception e)
            {
                _logger.Error(e, "Couldn't import file. " + file);

                var localMovie = new LocalMovie {
                    Path = file
                };
                decision = new ImportDecision(localMovie, new Rejection("Unexpected error processing file"));
            }

            //LocalMovie nullMovie = null;

            //decision = new ImportDecision(nullMovie, new Rejection("IMPLEMENTATION MISSING!!!"));

            return(decision);
        }
Example #11
0
        private ImportDecision GetDecision(string file, Movie movie, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldUseFolderName, bool shouldCheckQuality = false)
        {
            ImportDecision decision = null;

            try
            {
                var localMovie = _parsingService.GetLocalMovie(file, movie, shouldUseFolderName ? folderInfo : null, sceneSource);

                if (localMovie != null)
                {
                    localMovie.Quality = GetQuality(folderInfo, localMovie.Quality, movie);
                    localMovie.Size    = _diskProvider.GetFileSize(file);

                    _logger.Debug("Size: {0}", localMovie.Size);
                    var current = localMovie.Quality;
                    //TODO: make it so media info doesn't ruin the import process of a new series
                    if (sceneSource && ShouldCheckQualityForParsedQuality(current.Quality))
                    {
                        localMovie.MediaInfo = _videoFileInfoReader.GetMediaInfo(file);
                        if (shouldCheckQuality)
                        {
                            _logger.Debug("Checking quality for this video file to make sure nothing mismatched.");
                            var width = localMovie.MediaInfo.Width;

                            var          qualityName = current.Quality.Name.ToLower();
                            QualityModel updated     = null;
                            if (width > 2000)
                            {
                                if (qualityName.Contains("bluray"))
                                {
                                    updated = new QualityModel(Quality.Bluray2160p);
                                }

                                else if (qualityName.Contains("webdl"))
                                {
                                    updated = new QualityModel(Quality.WEBDL2160p);
                                }

                                else if (qualityName.Contains("hdtv"))
                                {
                                    updated = new QualityModel(Quality.HDTV2160p);
                                }

                                else
                                {
                                    var def = _qualitiesService.Get(Quality.HDTV2160p);
                                    if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
                                    {
                                        updated = new QualityModel(Quality.HDTV2160p);
                                    }
                                    def = _qualitiesService.Get(Quality.WEBDL2160p);
                                    if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
                                    {
                                        updated = new QualityModel(Quality.WEBDL2160p);
                                    }
                                    def = _qualitiesService.Get(Quality.Bluray2160p);
                                    if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
                                    {
                                        updated = new QualityModel(Quality.Bluray2160p);
                                    }
                                    if (updated == null)
                                    {
                                        updated = new QualityModel(Quality.Bluray2160p);
                                    }
                                }
                            }
                            else if (width > 1400)
                            {
                                if (qualityName.Contains("bluray"))
                                {
                                    updated = new QualityModel(Quality.Bluray1080p);
                                }

                                else if (qualityName.Contains("webdl"))
                                {
                                    updated = new QualityModel(Quality.WEBDL1080p);
                                }

                                else if (qualityName.Contains("hdtv"))
                                {
                                    updated = new QualityModel(Quality.HDTV1080p);
                                }

                                else
                                {
                                    var def = _qualitiesService.Get(Quality.HDTV1080p);
                                    if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
                                    {
                                        updated = new QualityModel(Quality.HDTV1080p);
                                    }
                                    def = _qualitiesService.Get(Quality.WEBDL1080p);
                                    if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
                                    {
                                        updated = new QualityModel(Quality.WEBDL1080p);
                                    }
                                    def = _qualitiesService.Get(Quality.Bluray1080p);
                                    if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
                                    {
                                        updated = new QualityModel(Quality.Bluray1080p);
                                    }
                                    if (updated == null)
                                    {
                                        updated = new QualityModel(Quality.Bluray1080p);
                                    }
                                }
                            }
                            else
                            if (width > 900)
                            {
                                if (qualityName.Contains("bluray"))
                                {
                                    updated = new QualityModel(Quality.Bluray720p);
                                }

                                else if (qualityName.Contains("webdl"))
                                {
                                    updated = new QualityModel(Quality.WEBDL720p);
                                }

                                else if (qualityName.Contains("hdtv"))
                                {
                                    updated = new QualityModel(Quality.HDTV720p);
                                }

                                else
                                {
                                    var def = _qualitiesService.Get(Quality.HDTV720p);
                                    if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
                                    {
                                        updated = new QualityModel(Quality.HDTV720p);
                                    }
                                    def = _qualitiesService.Get(Quality.WEBDL720p);
                                    if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
                                    {
                                        updated = new QualityModel(Quality.WEBDL720p);
                                    }
                                    def = _qualitiesService.Get(Quality.Bluray720p);
                                    if (localMovie.Size > def.MinSize && def.MaxSize > localMovie.Size)
                                    {
                                        updated = new QualityModel(Quality.Bluray720p);
                                    }
                                    if (updated == null)
                                    {
                                        updated = new QualityModel(Quality.Bluray720p);
                                    }
                                }
                            }
                            if (updated != null && updated != current)
                            {
                                _logger.Debug("Quality ({0}) of the file is different than the one we have ({1})", updated, current);
                                updated.QualitySource = QualitySource.MediaInfo;
                                localMovie.Quality    = updated;
                            }
                        }



                        decision = GetDecision(localMovie);
                    }
                    else
                    {
                        decision = GetDecision(localMovie);
                    }
                }

                else
                {
                    localMovie      = new LocalMovie();
                    localMovie.Path = file;

                    decision = new ImportDecision(localMovie, new Rejection("Unable to parse file"));
                }
            }
            catch (Exception e)
            {
                _logger.Error(e, "Couldn't import file. " + file);

                var localMovie = new LocalMovie {
                    Path = file
                };
                decision = new ImportDecision(localMovie, new Rejection("Unexpected error processing file"));
            }

            //LocalMovie nullMovie = null;

            //decision = new ImportDecision(nullMovie, new Rejection("IMPLEMENTATION MISSING!!!"));

            return(decision);
        }
Example #12
0
        private ImportDecision GetDecision(string file, Movie movie, DownloadClientItem downloadClientItem, ParsedMovieInfo folderInfo, bool sceneSource, bool shouldUseFolderName, bool shouldCheckQuality = false)
        {
            ImportDecision decision = null;

            try
            {
                ParsedMovieInfo modifiedFolderInfo = null;
                if (folderInfo != null)
                {
                    modifiedFolderInfo = folderInfo.JsonClone();
                    // We want the filename to be used for parsing quality, etc. even if we didn't get any movie info from there.
                    modifiedFolderInfo.SimpleReleaseTitle = Path.GetFileName(file);
                }

                var minimalInfo = _parsingService.ParseMinimalPathMovieInfo(file) ?? modifiedFolderInfo;

                LocalMovie localMovie = null;

                if (minimalInfo != null)
                {
                    //TODO: make it so media info doesn't ruin the import process of a new movie
                    var mediaInfo        = (_config.EnableMediaInfo || !movie.Path?.IsParentPath(file) == true) ? _videoFileInfoReader.GetMediaInfo(file) : null;
                    var size             = _diskProvider.GetFileSize(file);
                    var historyItems     = _historyService.FindByDownloadId(downloadClientItem?.DownloadId ?? "");
                    var firstHistoryItem = historyItems?.OrderByDescending(h => h.Date)?.FirstOrDefault();
                    var sizeMovie        = new LocalMovie();
                    sizeMovie.Size = size;
                    localMovie     = _parsingService.GetLocalMovie(file, minimalInfo, movie, new List <object> {
                        mediaInfo, firstHistoryItem, sizeMovie, folderInfo
                    }, sceneSource);
                    localMovie.Quality = GetQuality(folderInfo, localMovie.Quality, movie);
                    localMovie.Size    = size;

                    _logger.Debug("Size: {0}", localMovie.Size);

                    decision = GetDecision(localMovie, downloadClientItem);
                }
                else
                {
                    localMovie      = new LocalMovie();
                    localMovie.Path = file;

                    if (MediaFileExtensions.Extensions.Contains(Path.GetExtension(file)))
                    {
                        if (_warnedFiles.Find(file) == null)
                        {
                            _warnedFiles.Set(file, "warned");
                            _logger.Warn("Unable to parse movie info from path {0}", file);
                        }
                        else
                        {
                            _logger.Trace("Already warned user that we are unable to parse movie info from path: {0}", file);
                        }
                    }

                    decision = new ImportDecision(localMovie, new Rejection("Unable to parse file"));
                }
            }
            catch (Exception e)
            {
                _logger.Error(e, "Couldn't import file. {0}", file);

                var localMovie = new LocalMovie {
                    Path = file
                };
                decision = new ImportDecision(localMovie, new Rejection("Unexpected error processing file"));
            }

            //LocalMovie nullMovie = null;

            //decision = new ImportDecision(nullMovie, new Rejection("IMPLEMENTATION MISSING!!!"));

            return(decision);
        }
Example #13
0
        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 movie           = _movieService.GetMovie(file.MovieId);
                var parsedMovieInfo = _parsingService.ParseMoviePathInfo(file.Path, new List <object>()) ?? new ParsedMovieInfo();
                var mediaInfo       = _videoFileInfoReader.GetMediaInfo(file.Path);
                var existingFile    = movie.Path.IsParentPath(file.Path);

                var localMovie = new LocalMovie
                {
                    ExistingFile    = false,
                    MediaInfo       = mediaInfo,
                    ParsedMovieInfo = parsedMovieInfo,
                    Path            = file.Path,
                    Quality         = file.Quality,
                    Movie           = movie,
                    Size            = 0
                };

                //TODO: Cleanup non-tracked downloads

                var importDecision = new ImportDecision(localMovie);

                if (file.DownloadId.IsNullOrWhiteSpace())
                {
                    imported.AddRange(_importApprovedMovie.Import(new List <ImportDecision> {
                        importDecision
                    }, !existingFile, null, message.ImportMode));
                }

                else
                {
                    var trackedDownload = _trackedDownloadService.Find(file.DownloadId);
                    var importResult    = _importApprovedMovie.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 (_downloadedMovieImportService.ShouldDeleteFolder(
                            new DirectoryInfo(trackedDownload.DownloadItem.OutputPath.FullPath),
                            trackedDownload.RemoteMovie.Movie) && trackedDownload.DownloadItem.CanMoveFiles)
                    {
                        _diskProvider.DeleteFolder(trackedDownload.DownloadItem.OutputPath.FullPath, true);
                    }
                }

                if (groupedTrackedDownload.Select(c => c.ImportResult).Count(c => c.Result == ImportResultType.Imported) >= Math.Max(1, 1)) //TODO: trackedDownload.RemoteMovie.Movie.Count is always 1?
                {
                    trackedDownload.State = TrackedDownloadStage.Imported;
                    _eventAggregator.PublishEvent(new DownloadCompletedEvent(trackedDownload));
                }
            }
        }