Пример #1
0
        public BookFile Add(BookFile bookFile)
        {
            var addedFile = _mediaFileRepository.Insert(bookFile);

            _eventAggregator.PublishEvent(new BookFileAddedEvent(addedFile));
            return(addedFile);
        }
Пример #2
0
        public void WriteTags(BookFile trackfile, bool newDownload, bool force = false)
        {
            if (!force)
            {
                if (_configService.WriteAudioTags == WriteAudioTagsType.No ||
                    (_configService.WriteAudioTags == WriteAudioTagsType.NewFiles && !newDownload))
                {
                    return;
                }
            }

            var newTags = GetTrackMetadata(trackfile);
            var path    = trackfile.Path;

            var diff = ReadAudioTag(path).Diff(newTags);

            _rootFolderWatchingService.ReportFileSystemChangeBeginning(path);

            if (_configService.ScrubAudioTags)
            {
                _logger.Debug($"Scrubbing tags for {trackfile}");
                RemoveAllTags(path);
            }

            _logger.Debug($"Writing tags for {trackfile}");

            newTags.Write(path);

            UpdateTrackfileSizeAndModified(trackfile, path);

            _eventAggregator.PublishEvent(new BookFileRetaggedEvent(trackfile.Author.Value, trackfile, diff, _configService.ScrubAudioTags));
        }
Пример #3
0
        public void DeleteTrackFile(Author author, BookFile bookFile)
        {
            var fullPath   = bookFile.Path;
            var rootFolder = _diskProvider.GetParentFolder(author.Path);

            if (!_diskProvider.FolderExists(rootFolder))
            {
                _logger.Warn("Author's root folder ({0}) doesn't exist.", rootFolder);
                throw new NzbDroneClientException(HttpStatusCode.Conflict, "Author's root folder ({0}) doesn't exist.", rootFolder);
            }

            if (_diskProvider.GetDirectories(rootFolder).Empty())
            {
                _logger.Warn("Author's root folder ({0}) is empty.", rootFolder);
                throw new NzbDroneClientException(HttpStatusCode.Conflict, "Author's root folder ({0}) is empty.", rootFolder);
            }

            if (_diskProvider.FolderExists(author.Path))
            {
                var subfolder = _diskProvider.GetParentFolder(author.Path).GetRelativePath(_diskProvider.GetParentFolder(fullPath));
                DeleteTrackFile(bookFile, subfolder);
            }
            else
            {
                // delete from db even if the author folder is missing
                _mediaFileService.Delete(bookFile, DeleteMediaFileReason.Manual);
            }
        }
Пример #4
0
        public void Delete(BookFile bookFile, DeleteMediaFileReason reason)
        {
            _mediaFileRepository.Delete(bookFile);

            // If the trackfile wasn't mapped to a track, don't publish an event
            if (bookFile.EditionId > 0)
            {
                _eventAggregator.PublishEvent(new BookFileDeletedEvent(bookFile, reason));
            }
        }
Пример #5
0
        public BookFile CalibreAddAndConvert(BookFile file, CalibreSettings settings)
        {
            _logger.Trace($"Importing to calibre: {file.Path}");

            if (file.CalibreId == 0)
            {
                var import = _calibre.AddBook(file, settings);
                file.CalibreId = import.Id;
            }
            else
            {
                _calibre.AddFormat(file, settings);
            }

            _calibre.SetFields(file, settings);

            var updated = _calibre.GetBook(file.CalibreId, settings);
            var path    = updated.Formats.Values.OrderByDescending(x => x.LastModified).First().Path;

            file.Path = path;

            _rootFolderWatchingService.ReportFileSystemChangeBeginning(file.Path);

            if (settings.OutputFormat.IsNotNullOrWhiteSpace())
            {
                _logger.Trace($"Getting book data for {file.CalibreId}");
                var options     = _calibre.GetBookData(file.CalibreId, settings);
                var inputFormat = file.Quality.Quality.Name.ToUpper();

                options.Conversion_options.Input_fmt = inputFormat;

                var formats = settings.OutputFormat.Split(',').Select(x => x.Trim());
                foreach (var format in formats)
                {
                    if (format.ToLower() == inputFormat ||
                        options.Input_formats.Contains(format, StringComparer.OrdinalIgnoreCase))
                    {
                        continue;
                    }

                    options.Conversion_options.Output_fmt = format;

                    if (settings.OutputProfile != (int)CalibreProfile.Default)
                    {
                        options.Conversion_options.Options.Output_profile = ((CalibreProfile)settings.OutputProfile).ToString();
                    }

                    _logger.Trace($"Starting conversion to {format}");
                    _calibre.ConvertBook(file.CalibreId, options.Conversion_options, settings);
                }
            }

            return(file);
        }
Пример #6
0
        public BookFile MoveBookFile(BookFile bookFile, LocalBook localBook)
        {
            var newFileName = _buildFileNames.BuildBookFileName(localBook.Author, localBook.Edition, bookFile);
            var filePath    = _buildFileNames.BuildBookFilePath(localBook.Author, localBook.Edition, newFileName, Path.GetExtension(localBook.Path));

            EnsureTrackFolder(bookFile, localBook, filePath);

            _logger.Debug("Moving book file: {0} to {1}", bookFile.Path, filePath);

            return(TransferFile(bookFile, localBook.Author, localBook.Book, filePath, TransferMode.Move));
        }
Пример #7
0
        private void WriteTagsInternal(BookFile file, bool updateCover, bool embedMetadata)
        {
            if (file.CalibreId == 0)
            {
                _logger.Trace($"No calibre id for {file.Path}, skipping writing tags");
            }

            var rootFolder = _rootFolderService.GetBestRootFolder(file.Path);

            _calibre.SetFields(file, rootFolder.CalibreSettings, updateCover, embedMetadata);
        }
Пример #8
0
        public BookFile MoveBookFile(BookFile bookFile, Author author)
        {
            var edition     = _editionService.GetEdition(bookFile.EditionId);
            var newFileName = _buildFileNames.BuildBookFileName(author, edition, bookFile);
            var filePath    = _buildFileNames.BuildBookFilePath(author, edition, newFileName, Path.GetExtension(bookFile.Path));

            EnsureBookFolder(bookFile, author, edition.Book.Value, filePath);

            _logger.Debug("Renaming book file: {0} to {1}", bookFile, filePath);

            return(TransferFile(bookFile, author, bookFile.Edition.Value.Book.Value, filePath, TransferMode.Move));
        }
Пример #9
0
        public void WriteTags(BookFile bookFile, bool newDownload, bool force = false)
        {
            var extension = Path.GetExtension(bookFile.Path);

            if (MediaFileExtensions.AudioExtensions.Contains(extension))
            {
                _audioTagService.WriteTags(bookFile, newDownload, force);
            }
            else if (bookFile.CalibreId > 0)
            {
                _eBookTagService.WriteTags(bookFile, newDownload, force);
            }
        }
Пример #10
0
        private void UpdateTrackfileSizeAndModified(BookFile trackfile, string path)
        {
            // update the saved file size so that the importer doesn't get confused on the next scan
            var fileInfo = _diskProvider.GetFileInfo(path);

            trackfile.Size     = fileInfo.Length;
            trackfile.Modified = fileInfo.LastWriteTimeUtc;

            if (trackfile.Id > 0)
            {
                _mediaFileService.Update(trackfile);
            }
        }
Пример #11
0
        public void DeleteTrackFile(BookFile bookFile, string subfolder = "")
        {
            var fullPath = bookFile.Path;

            if (_diskProvider.FileExists(fullPath))
            {
                _logger.Info("Deleting book file: {0}", fullPath);
                DeleteFile(bookFile, subfolder);
            }

            // Delete the track file from the database to clean it up even if the file was already deleted
            _mediaFileService.Delete(bookFile, DeleteMediaFileReason.Manual);
        }
Пример #12
0
        public AudioTag GetTrackMetadata(BookFile trackfile)
        {
            var edition   = trackfile.Edition.Value;
            var book      = edition.Book.Value;
            var author    = book.Author.Value;
            var partCount = edition.BookFiles.Value.Count;

            var fileTags = ReadAudioTag(trackfile.Path);

            var    cover     = edition.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Cover);
            string imageFile = null;
            long   imageSize = 0;

            if (cover != null)
            {
                imageFile = _mediaCoverService.GetCoverPath(book.Id, MediaCoverEntity.Book, cover.CoverType, cover.Extension, null);
                _logger.Trace($"Embedding: {imageFile}");
                var fileInfo = _diskProvider.GetFileInfo(imageFile);
                if (fileInfo.Exists)
                {
                    imageSize = fileInfo.Length;
                }
                else
                {
                    imageFile = null;
                }
            }

            return(new AudioTag
            {
                Title = edition.Title,
                Performers = new[] { author.Name },
                BookAuthors = new[] { author.Name },
                Track = (uint)trackfile.Part,
                TrackCount = (uint)partCount,
                Book = book.Title,
                Disc = fileTags.Disc,
                DiscCount = fileTags.DiscCount,

                // We may have omitted media so index in the list isn't the same as medium number
                Media = fileTags.Media,
                Date = edition.ReleaseDate,
                Year = (uint)(edition.ReleaseDate?.Year ?? 0),
                OriginalReleaseDate = book.ReleaseDate,
                OriginalYear = (uint)(book.ReleaseDate?.Year ?? 0),
                Publisher = edition.Publisher,
                Genres = new string[0],
                ImageFile = imageFile,
                ImageSize = imageSize,
            });
        }
Пример #13
0
        public void WriteTags(BookFile bookFile, bool newDownload, bool force = false)
        {
            if (!force)
            {
                if (_configService.WriteBookTags == WriteBookTagsType.NewFiles && !newDownload)
                {
                    return;
                }
            }

            _logger.Debug($"Writing tags for {bookFile}");

            WriteTagsInternal(bookFile, _configService.UpdateCovers, _configService.EmbedMetadata);
        }
Пример #14
0
        public BookFile CopyBookFile(BookFile bookFile, LocalBook localBook)
        {
            var newFileName = _buildFileNames.BuildBookFileName(localBook.Author, localBook.Edition, bookFile);
            var filePath    = _buildFileNames.BuildBookFilePath(localBook.Author, localBook.Edition, newFileName, Path.GetExtension(localBook.Path));

            EnsureTrackFolder(bookFile, localBook, filePath);

            if (_configService.CopyUsingHardlinks)
            {
                _logger.Debug("Hardlinking book file: {0} to {1}", bookFile.Path, filePath);
                return(TransferFile(bookFile, localBook.Author, localBook.Book, filePath, TransferMode.HardLinkOrCopy));
            }

            _logger.Debug("Copying book file: {0} to {1}", bookFile.Path, filePath);
            return(TransferFile(bookFile, localBook.Author, localBook.Book, filePath, TransferMode.Copy));
        }
Пример #15
0
        public void WriteTags(BookFile bookFile, bool newDownload, bool force = false)
        {
            if (!force)
            {
                if (_configService.WriteBookTags == WriteBookTagsType.NewFiles && !newDownload)
                {
                    return;
                }
            }

            _logger.Debug($"Writing tags for {bookFile}");

            var rootFolder = _rootFolderService.GetBestRootFolder(bookFile.Path);

            _calibre.SetFields(bookFile, rootFolder.CalibreSettings, _configService.UpdateCovers, _configService.EmbedMetadata);
        }
Пример #16
0
        private bool ChangeFileDate(BookFile bookFile, Book book)
        {
            var bookFilePath = bookFile.Path;

            switch (_configService.FileDate)
            {
            case FileDateType.BookReleaseDate:
            {
                if (!book.ReleaseDate.HasValue)
                {
                    _logger.Debug("Could not create valid date to change file [{0}]", bookFilePath);
                    return(false);
                }

                var relDate = book.ReleaseDate.Value;

                // avoiding false +ve checks and set date skewing by not using UTC (Windows)
                var oldDateTime = _diskProvider.FileGetLastWrite(bookFilePath);

                if (OsInfo.IsNotWindows && relDate < EpochTime)
                {
                    _logger.Debug("Setting date of file to 1970-01-01 as actual airdate is before that time and will not be set properly");
                    relDate = EpochTime;
                }

                if (!DateTime.Equals(relDate, oldDateTime))
                {
                    try
                    {
                        _diskProvider.FileSetLastWriteTime(bookFilePath, relDate);
                        _logger.Debug("Date of file [{0}] changed from '{1}' to '{2}'", bookFilePath, oldDateTime, relDate);

                        return(true);
                    }
                    catch (Exception ex)
                    {
                        _logger.Warn(ex, "Unable to set date of file [" + bookFilePath + "]");
                    }
                }

                return(false);
            }
            }

            return(false);
        }
Пример #17
0
        private void EnsureBookFolder(BookFile bookFile, Author author, Book book, string filePath)
        {
            var trackFolder  = Path.GetDirectoryName(filePath);
            var bookFolder   = _buildFileNames.BuildBookPath(author);
            var authorFolder = author.Path;
            var rootFolder   = new OsPath(authorFolder).Directory.FullPath;

            if (!_diskProvider.FolderExists(rootFolder))
            {
                throw new RootFolderNotFoundException(string.Format("Root folder '{0}' was not found.", rootFolder));
            }

            var changed  = false;
            var newEvent = new TrackFolderCreatedEvent(author, bookFile);

            _rootFolderWatchingService.ReportFileSystemChangeBeginning(authorFolder, bookFolder, trackFolder);

            if (!_diskProvider.FolderExists(authorFolder))
            {
                CreateFolder(authorFolder);
                newEvent.AuthorFolder = authorFolder;
                changed = true;
            }

            if (authorFolder != bookFolder && !_diskProvider.FolderExists(bookFolder))
            {
                CreateFolder(bookFolder);
                newEvent.BookFolder = bookFolder;
                changed             = true;
            }

            if (bookFolder != trackFolder && !_diskProvider.FolderExists(trackFolder))
            {
                CreateFolder(trackFolder);
                newEvent.TrackFolder = trackFolder;
                changed = true;
            }

            if (changed)
            {
                _eventAggregator.PublishEvent(newEvent);
            }
        }
Пример #18
0
        private void DeleteFile(BookFile bookFile, string subfolder = "")
        {
            var rootFolder = _rootFolderService.GetBestRootFolder(bookFile.Path);
            var isCalibre  = rootFolder.IsCalibreLibrary && rootFolder.CalibreSettings != null;

            try
            {
                if (!isCalibre)
                {
                    _recycleBinProvider.DeleteFile(bookFile.Path, subfolder);
                }
                else
                {
                    _calibre.DeleteBook(bookFile, rootFolder.CalibreSettings);
                }
            }
            catch (Exception e)
            {
                _logger.Error(e, "Unable to delete book file");
                throw new NzbDroneClientException(HttpStatusCode.InternalServerError, "Unable to delete book file");
            }
        }
Пример #19
0
        public void DeleteTrackFile(BookFile bookFile, string subfolder = "")
        {
            var fullPath = bookFile.Path;

            if (_diskProvider.FileExists(fullPath))
            {
                _logger.Info("Deleting book file: {0}", fullPath);

                try
                {
                    _recycleBinProvider.DeleteFile(fullPath, subfolder);
                }
                catch (Exception e)
                {
                    _logger.Error(e, "Unable to delete book file");
                    throw new NzbDroneClientException(HttpStatusCode.InternalServerError, "Unable to delete book file");
                }
            }

            // Delete the track file from the database to clean it up even if the file was already deleted
            _mediaFileService.Delete(bookFile, DeleteMediaFileReason.Manual);
        }
Пример #20
0
        private BookFile TransferFile(BookFile bookFile, Author author, Book book, string destinationFilePath, TransferMode mode)
        {
            Ensure.That(bookFile, () => bookFile).IsNotNull();
            Ensure.That(author, () => author).IsNotNull();
            Ensure.That(destinationFilePath, () => destinationFilePath).IsValidPath();

            var bookFilePath = bookFile.Path;

            if (!_diskProvider.FileExists(bookFilePath))
            {
                throw new FileNotFoundException("Book file path does not exist", bookFilePath);
            }

            if (bookFilePath == destinationFilePath)
            {
                throw new SameFilenameException("File not moved, source and destination are the same", bookFilePath);
            }

            _rootFolderWatchingService.ReportFileSystemChangeBeginning(bookFilePath, destinationFilePath);
            _diskTransferService.TransferFile(bookFilePath, destinationFilePath, mode);

            bookFile.Path = destinationFilePath;

            _updateBookFileService.ChangeFileDateForFile(bookFile, author, book);

            try
            {
                _mediaFileAttributeService.SetFolderLastWriteTime(author.Path, bookFile.DateAdded);
            }
            catch (Exception ex)
            {
                _logger.Warn(ex, "Unable to set last write time");
            }

            _mediaFileAttributeService.SetFilePermissions(destinationFilePath);

            return(bookFile);
        }
Пример #21
0
        public BookFileMoveResult UpgradeBookFile(BookFile bookFile, LocalBook localBook, bool copyOnly = false)
        {
            var moveFileResult = new BookFileMoveResult();
            var existingFiles  = localBook.Book.BookFiles.Value;

            var rootFolderPath = _diskProvider.GetParentFolder(localBook.Author.Path);
            var rootFolder     = _rootFolderService.GetBestRootFolder(rootFolderPath);
            var isCalibre      = rootFolder.IsCalibreLibrary && rootFolder.CalibreSettings != null;

            var settings = rootFolder.CalibreSettings;

            // If there are existing book files and the root folder is missing, throw, so the old file isn't left behind during the import process.
            if (existingFiles.Any() && !_diskProvider.FolderExists(rootFolderPath))
            {
                throw new RootFolderNotFoundException($"Root folder '{rootFolderPath}' was not found.");
            }

            foreach (var file in existingFiles)
            {
                var bookFilePath = file.Path;
                var subfolder    = rootFolderPath.GetRelativePath(_diskProvider.GetParentFolder(bookFilePath));

                bookFile.CalibreId = file.CalibreId;

                if (_diskProvider.FileExists(bookFilePath))
                {
                    _logger.Debug("Removing existing book file: {0} CalibreId: {1}", file, file.CalibreId);

                    if (!isCalibre)
                    {
                        _recycleBinProvider.DeleteFile(bookFilePath, subfolder);
                    }
                    else
                    {
                        var existing        = _calibre.GetBook(file.CalibreId, settings);
                        var existingFormats = existing.Formats.Keys;
                        _logger.Debug($"Removing existing formats {existingFormats.ConcatToString()} from calibre");
                        _calibre.RemoveFormats(file.CalibreId, existingFormats, settings);
                    }
                }

                moveFileResult.OldFiles.Add(file);
                _mediaFileService.Delete(file, DeleteMediaFileReason.Upgrade);
            }

            if (!isCalibre)
            {
                if (copyOnly)
                {
                    moveFileResult.BookFile = _bookFileMover.CopyBookFile(bookFile, localBook);
                }
                else
                {
                    moveFileResult.BookFile = _bookFileMover.MoveBookFile(bookFile, localBook);
                }

                _metadataTagService.WriteTags(bookFile, true);
            }
            else
            {
                var source = bookFile.Path;

                moveFileResult.BookFile = _calibre.AddAndConvert(bookFile, settings);

                if (!copyOnly)
                {
                    _diskProvider.DeleteFile(source);
                }
            }

            return(moveFileResult);
        }
Пример #22
0
 private void EnsureTrackFolder(BookFile bookFile, LocalBook localBook, string filePath)
 {
     EnsureBookFolder(bookFile, localBook.Author, localBook.Book, filePath);
 }
Пример #23
0
 public AudioTag GetTrackMetadata(BookFile trackfile)
 {
     return(new AudioTag());
 }
Пример #24
0
 public void Update(BookFile bookFile)
 {
     _mediaFileRepository.Update(bookFile);
 }
Пример #25
0
 public void ChangeFileDateForFile(BookFile bookFile, Author author, Book book)
 {
     ChangeFileDate(bookFile, book);
 }
Пример #26
0
 public AudioTag GetTrackMetadata(BookFile trackfile)
 {
     //TODO do something to get track metadata, for now jsut return existing track metadata
     //   return new AudioTag();
     return(ReadAudioTag(trackfile.Path));
 }