public override IEnumerable <ExtraFile> ProcessFiles(Author author, List <string> filesOnDisk, List <string> importedFiles)
        {
            _logger.Debug("Looking for existing metadata in {0}", author.Path);

            var metadataFiles = new List <MetadataFile>();
            var filterResult  = FilterAndClean(author, filesOnDisk, importedFiles);

            foreach (var possibleMetadataFile in filterResult.FilesOnDisk)
            {
                foreach (var consumer in _consumers)
                {
                    var metadata = consumer.FindMetadataFile(author, possibleMetadataFile);

                    if (metadata == null)
                    {
                        continue;
                    }

                    if (metadata.Type == MetadataType.BookImage || metadata.Type == MetadataType.BookMetadata)
                    {
                        var localAlbum = _parsingService.GetLocalAlbum(possibleMetadataFile, author);

                        if (localAlbum == null)
                        {
                            _logger.Debug("Extra file folder has multiple Books: {0}", possibleMetadataFile);
                            continue;
                        }

                        metadata.BookId = localAlbum.Id;
                    }

                    if (metadata.Type == MetadataType.BookMetadata)
                    {
                        var localTrack = new LocalBook
                        {
                            FileTrackInfo = Parser.Parser.ParseMusicPath(possibleMetadataFile),
                            Author        = author,
                            Path          = possibleMetadataFile
                        };

                        try
                        {
                            _augmentingService.Augment(localTrack, false);
                        }
                        catch (AugmentingFailedException)
                        {
                            _logger.Debug("Unable to parse extra file: {0}", possibleMetadataFile);
                            continue;
                        }

                        if (localTrack.Book == null)
                        {
                            _logger.Debug("Cannot find related book for: {0}", possibleMetadataFile);
                            continue;
                        }
                    }

                    metadata.Extension = Path.GetExtension(possibleMetadataFile);

                    metadataFiles.Add(metadata);
                }
            }

            _logger.Info("Found {0} existing metadata files", metadataFiles.Count);
            _metadataFileService.Upsert(metadataFiles);

            // Return files that were just imported along with files that were
            // previously imported so previously imported files aren't imported twice
            return(metadataFiles.Concat(filterResult.PreviouslyImported));
        }
Exemple #2
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             series          = _seriesService.GetSeries(file.SeriesId);
                var             episodes        = _episodeService.GetEpisodes(file.EpisodeIds);
                var             fileEpisodeInfo = Parser.Parser.ParsePath(file.Path) ?? new ParsedEpisodeInfo();
                var             existingFile    = series.Path.IsParentPath(file.Path);
                TrackedDownload trackedDownload = null;

                var localEpisode = new LocalEpisode
                {
                    ExistingFile    = false,
                    Episodes        = episodes,
                    FileEpisodeInfo = fileEpisodeInfo,
                    Path            = file.Path,
                    Quality         = file.Quality,
                    Series          = series,
                    Size            = 0
                };

                if (file.DownloadId.IsNotNullOrWhiteSpace())
                {
                    trackedDownload = _trackedDownloadService.Find(file.DownloadId);
                    if (trackedDownload != null)
                    {
                        localEpisode.DownloadClientEpisodeInfo = trackedDownload.RemoteEpisode.ParsedEpisodeInfo;
                    }
                }

                if (file.FolderName.IsNotNullOrWhiteSpace())
                {
                    localEpisode.FolderEpisodeInfo = Parser.Parser.ParseTitle(file.FolderName);
                }

                localEpisode = _augmentingService.Augment(localEpisode, false);

                // Apply the user-chosen values.
                localEpisode.Series   = series;
                localEpisode.Episodes = episodes;
                localEpisode.Quality  = file.Quality;

                //TODO: Cleanup non-tracked downloads

                var importDecision = new ImportDecision(localEpisode);

                if (trackedDownload == null)
                {
                    imported.AddRange(_importApprovedEpisodes.Import(new List <ImportDecision> {
                        importDecision
                    }, !existingFile, null, message.ImportMode));
                }
                else
                {
                    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.CanMoveFiles)
                    {
                        _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));
                }
            }
        }
Exemple #3
0
        public Tuple <List <LocalBook>, List <ImportDecision <LocalBook> > > GetLocalTracks(List <IFileInfo> musicFiles, DownloadClientItem downloadClientItem, ParsedTrackInfo folderInfo, FilterFilesType filter)
        {
            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();

            var files = _mediaFileService.FilterUnchangedFiles(musicFiles, filter);

            var localTracks = new List <LocalBook>();
            var decisions   = new List <ImportDecision <LocalBook> >();

            _logger.Debug("Analyzing {0}/{1} files.", files.Count, musicFiles.Count);

            if (!files.Any())
            {
                return(Tuple.Create(localTracks, decisions));
            }

            ParsedBookInfo downloadClientItemInfo = null;

            if (downloadClientItem != null)
            {
                downloadClientItemInfo = Parser.Parser.ParseBookTitle(downloadClientItem.Title);
            }

            var i = 1;

            foreach (var file in files)
            {
                _logger.ProgressInfo($"Reading file {i++}/{files.Count}");

                var localTrack = new LocalBook
                {
                    DownloadClientAlbumInfo = downloadClientItemInfo,
                    FolderTrackInfo         = folderInfo,
                    Path           = file.FullName,
                    Size           = file.Length,
                    Modified       = file.LastWriteTimeUtc,
                    FileTrackInfo  = _eBookTagService.ReadTags(file),
                    AdditionalFile = false
                };

                try
                {
                    // TODO fix otherfiles?
                    _augmentingService.Augment(localTrack, true);
                    localTracks.Add(localTrack);
                }
                catch (AugmentingFailedException)
                {
                    decisions.Add(new ImportDecision <LocalBook>(localTrack, new Rejection("Unable to parse file")));
                }
                catch (Exception e)
                {
                    _logger.Error(e, "Couldn't import file. {0}", localTrack.Path);

                    decisions.Add(new ImportDecision <LocalBook>(localTrack, new Rejection("Unexpected error processing file")));
                }
            }

            _logger.Debug($"Tags parsed for {files.Count} files in {watch.ElapsedMilliseconds}ms");

            return(Tuple.Create(localTracks, decisions));
        }
        public override IEnumerable <ExtraFile> ProcessFiles(Artist artist, List <string> filesOnDisk, List <string> importedFiles)
        {
            _logger.Debug("Looking for existing lyrics files in {0}", artist.Path);

            var subtitleFiles = new List <LyricFile>();
            var filterResult  = FilterAndClean(artist, filesOnDisk, importedFiles);

            foreach (var possibleLyricFile in filterResult.FilesOnDisk)
            {
                var extension = Path.GetExtension(possibleLyricFile);

                if (LyricFileExtensions.Extensions.Contains(extension))
                {
                    var localTrack = new LocalTrack
                    {
                        FileTrackInfo = Parser.Parser.ParseMusicPath(possibleLyricFile),
                        Artist        = artist,
                        Path          = possibleLyricFile
                    };

                    try
                    {
                        _augmentingService.Augment(localTrack, false);
                    }
                    catch (AugmentingFailedException)
                    {
                        _logger.Debug("Unable to parse lyric file: {0}", possibleLyricFile);
                        continue;
                    }

                    if (localTrack.Tracks.Empty())
                    {
                        _logger.Debug("Cannot find related tracks for: {0}", possibleLyricFile);
                        continue;
                    }

                    if (localTrack.Tracks.DistinctBy(e => e.TrackFileId).Count() > 1)
                    {
                        _logger.Debug("Lyric file: {0} does not match existing files.", possibleLyricFile);
                        continue;
                    }

                    var subtitleFile = new LyricFile
                    {
                        ArtistId     = artist.Id,
                        AlbumId      = localTrack.Album.Id,
                        TrackFileId  = localTrack.Tracks.First().TrackFileId,
                        RelativePath = artist.Path.GetRelativePath(possibleLyricFile),
                        Extension    = extension
                    };

                    subtitleFiles.Add(subtitleFile);
                }
            }

            _logger.Info("Found {0} existing lyric files", subtitleFiles.Count);
            _lyricFileService.Upsert(subtitleFiles);

            // Return files that were just imported along with files that were
            // previously imported so previously imported files aren't imported twice

            return(subtitleFiles.Concat(filterResult.PreviouslyImported));
        }
        public override IEnumerable <ExtraFile> ProcessFiles(Series series, List <string> filesOnDisk, List <string> importedFiles)
        {
            _logger.Debug("Looking for existing metadata in {0}", series.Path);

            var metadataFiles = new List <MetadataFile>();
            var filterResult  = FilterAndClean(series, filesOnDisk, importedFiles);

            foreach (var possibleMetadataFile in filterResult.FilesOnDisk)
            {
                // Don't process files that have known Subtitle file extensions (saves a bit of unecessary processing)

                if (SubtitleFileExtensions.Extensions.Contains(Path.GetExtension(possibleMetadataFile)))
                {
                    continue;
                }

                foreach (var consumer in _consumers)
                {
                    var metadata = consumer.FindMetadataFile(series, possibleMetadataFile);

                    if (metadata == null)
                    {
                        continue;
                    }

                    if (metadata.Type == MetadataType.EpisodeImage ||
                        metadata.Type == MetadataType.EpisodeMetadata)
                    {
                        var localEpisode = new LocalEpisode
                        {
                            FileEpisodeInfo = Parser.Parser.ParsePath(possibleMetadataFile),
                            Series          = series,
                            Path            = possibleMetadataFile
                        };

                        try
                        {
                            _augmentingService.Augment(localEpisode, false);
                        }
                        catch (AugmentingFailedException ex)
                        {
                            _logger.Debug("Unable to parse extra file: {0}", possibleMetadataFile);
                            continue;
                        }

                        if (localEpisode.Episodes.Empty())
                        {
                            _logger.Debug("Cannot find related episodes for: {0}", possibleMetadataFile);
                            continue;
                        }

                        if (localEpisode.Episodes.DistinctBy(e => e.EpisodeFileId).Count() > 1)
                        {
                            _logger.Debug("Extra file: {0} does not match existing files.", possibleMetadataFile);
                            continue;
                        }

                        metadata.SeasonNumber  = localEpisode.SeasonNumber;
                        metadata.EpisodeFileId = localEpisode.Episodes.First().EpisodeFileId;
                    }

                    metadata.Extension = Path.GetExtension(possibleMetadataFile);

                    metadataFiles.Add(metadata);
                }
            }

            _logger.Info("Found {0} existing metadata files", metadataFiles.Count);
            _metadataFileService.Upsert(metadataFiles);

            // Return files that were just imported along with files that were
            // previously imported so previously imported files aren't imported twice

            return(metadataFiles.Concat(filterResult.PreviouslyImported));
        }
Exemple #6
0
        public override IEnumerable <ExtraFile> ProcessFiles(Artist artist, List <string> filesOnDisk, List <string> importedFiles)
        {
            _logger.Debug("Looking for existing metadata in {0}", artist.Path);

            var metadataFiles = new List <MetadataFile>();
            var filterResult  = FilterAndClean(artist, filesOnDisk, importedFiles);

            foreach (var possibleMetadataFile in filterResult.FilesOnDisk)
            {
                // Don't process files that have known Subtitle file extensions (saves a bit of unecessary processing)
                if (LyricFileExtensions.Extensions.Contains(Path.GetExtension(possibleMetadataFile)))
                {
                    continue;
                }

                foreach (var consumer in _consumers)
                {
                    var metadata = consumer.FindMetadataFile(artist, possibleMetadataFile);

                    if (metadata == null)
                    {
                        continue;
                    }

                    if (metadata.Type == MetadataType.AlbumImage || metadata.Type == MetadataType.AlbumMetadata)
                    {
                        var localAlbum = _parsingService.GetLocalAlbum(possibleMetadataFile, artist);

                        if (localAlbum == null)
                        {
                            _logger.Debug("Extra file folder has multiple Albums: {0}", possibleMetadataFile);
                            continue;
                        }

                        metadata.AlbumId = localAlbum.Id;
                    }

                    if (metadata.Type == MetadataType.TrackMetadata)
                    {
                        var localTrack = new LocalTrack
                        {
                            FileTrackInfo = Parser.Parser.ParseMusicPath(possibleMetadataFile),
                            Artist        = artist,
                            Path          = possibleMetadataFile
                        };

                        try
                        {
                            _augmentingService.Augment(localTrack, false);
                        }
                        catch (AugmentingFailedException)
                        {
                            _logger.Debug("Unable to parse extra file: {0}", possibleMetadataFile);
                            continue;
                        }

                        if (localTrack.Tracks.Empty())
                        {
                            _logger.Debug("Cannot find related tracks for: {0}", possibleMetadataFile);
                            continue;
                        }

                        if (localTrack.Tracks.DistinctBy(e => e.TrackFileId).Count() > 1)
                        {
                            _logger.Debug("Extra file: {0} does not match existing files.", possibleMetadataFile);
                            continue;
                        }

                        metadata.TrackFileId = localTrack.Tracks.First().TrackFileId;
                    }

                    metadata.Extension = Path.GetExtension(possibleMetadataFile);

                    metadataFiles.Add(metadata);
                }
            }

            _logger.Info("Found {0} existing metadata files", metadataFiles.Count);
            _metadataFileService.Upsert(metadataFiles);

            // Return files that were just imported along with files that were
            // previously imported so previously imported files aren't imported twice
            return(metadataFiles.Concat(filterResult.PreviouslyImported));
        }
        public List <ImportDecision <LocalTrack> > GetImportDecisions(List <IFileInfo> musicFiles, Artist artist, Album album, AlbumRelease albumRelease, DownloadClientItem downloadClientItem, ParsedTrackInfo folderInfo, FilterFilesType filter, bool newDownload, bool singleRelease, bool includeExisting)
        {
            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();

            var files = filter != FilterFilesType.None && (artist != null) ? _mediaFileService.FilterUnchangedFiles(musicFiles, artist, filter) : musicFiles;

            var localTracks = new List <LocalTrack>();
            var decisions   = new List <ImportDecision <LocalTrack> >();

            _logger.Debug("Analyzing {0}/{1} files.", files.Count, musicFiles.Count);

            if (!files.Any())
            {
                return(decisions);
            }

            ParsedAlbumInfo downloadClientItemInfo = null;

            if (downloadClientItem != null)
            {
                downloadClientItemInfo = Parser.Parser.ParseAlbumTitle(downloadClientItem.Title);
            }

            foreach (var file in files)
            {
                var localTrack = new LocalTrack
                {
                    Artist = artist,
                    Album  = album,
                    DownloadClientAlbumInfo = downloadClientItemInfo,
                    FolderTrackInfo         = folderInfo,
                    Path           = file.FullName,
                    Size           = file.Length,
                    Modified       = file.LastWriteTimeUtc,
                    FileTrackInfo  = _audioTagService.ReadTags(file.FullName),
                    ExistingFile   = !newDownload,
                    AdditionalFile = false
                };

                try
                {
                    // TODO fix otherfiles?
                    _augmentingService.Augment(localTrack, true);
                    localTracks.Add(localTrack);
                }
                catch (AugmentingFailedException)
                {
                    decisions.Add(new ImportDecision <LocalTrack>(localTrack, new Rejection("Unable to parse file")));
                }
                catch (Exception e)
                {
                    _logger.Error(e, "Couldn't import file. {0}", localTrack.Path);

                    decisions.Add(new ImportDecision <LocalTrack>(localTrack, new Rejection("Unexpected error processing file")));
                }
            }

            _logger.Debug($"Tags parsed for {files.Count} files in {watch.ElapsedMilliseconds}ms");

            var releases = _identificationService.Identify(localTracks, artist, album, albumRelease, newDownload, singleRelease, includeExisting);

            foreach (var release in releases)
            {
                release.NewDownload = newDownload;
                var releaseDecision = GetDecision(release);

                foreach (var localTrack in release.LocalTracks)
                {
                    if (releaseDecision.Approved)
                    {
                        decisions.AddIfNotNull(GetDecision(localTrack));
                    }
                    else
                    {
                        decisions.Add(new ImportDecision <LocalTrack>(localTrack, releaseDecision.Rejections.ToArray()));
                    }
                }
            }

            return(decisions);
        }
Exemple #8
0
        public override IEnumerable <ExtraFile> ProcessFiles(Series series, List <string> filesOnDisk, List <string> importedFiles)
        {
            _logger.Debug("Looking for existing subtitle files in {0}", series.Path);

            var subtitleFiles = new List <SubtitleFile>();
            var filterResult  = FilterAndClean(series, filesOnDisk, importedFiles);

            foreach (var possibleSubtitleFile in filterResult.FilesOnDisk)
            {
                var extension = Path.GetExtension(possibleSubtitleFile);

                if (SubtitleFileExtensions.Extensions.Contains(extension))
                {
                    var localEpisode = new LocalEpisode
                    {
                        FileEpisodeInfo = Parser.Parser.ParsePath(possibleSubtitleFile),
                        Series          = series,
                        Path            = possibleSubtitleFile
                    };

                    try
                    {
                        _augmentingService.Augment(localEpisode, false);
                    }
                    catch (AugmentingFailedException ex)
                    {
                        _logger.Debug("Unable to parse extra file: {0}", possibleSubtitleFile);
                        continue;
                    }

                    if (localEpisode.Episodes.Empty())
                    {
                        _logger.Debug("Cannot find related episodes for: {0}", possibleSubtitleFile);
                        continue;
                    }

                    if (localEpisode.Episodes.DistinctBy(e => e.EpisodeFileId).Count() > 1)
                    {
                        _logger.Debug("Subtitle file: {0} does not match existing files.", possibleSubtitleFile);
                        continue;
                    }

                    var subtitleFile = new SubtitleFile
                    {
                        SeriesId      = series.Id,
                        SeasonNumber  = localEpisode.SeasonNumber,
                        EpisodeFileId = localEpisode.Episodes.First().EpisodeFileId,
                        RelativePath  = series.Path.GetRelativePath(possibleSubtitleFile),
                        Language      = LanguageParser.ParseSubtitleLanguage(possibleSubtitleFile),
                        Extension     = extension
                    };

                    subtitleFiles.Add(subtitleFile);
                }
            }

            _logger.Info("Found {0} existing subtitle files", subtitleFiles.Count);
            _subtitleFileService.Upsert(subtitleFiles);

            // Return files that were just imported along with files that were
            // previously imported so previously imported files aren't imported twice

            return(subtitleFiles.Concat(filterResult.PreviouslyImported));
        }