Example #1
0
        public CalibreImportJob AddBook(BookFile book, CalibreSettings settings)
        {
            var jobid         = (int)(DateTime.UtcNow.Ticks % 1000000000);
            var addDuplicates = false;
            var path          = book.Path;
            var filename      = $"$dummy{Path.GetExtension(path)}";
            var body          = File.ReadAllBytes(path);

            _logger.Trace($"Read {body.Length} bytes from {path}");

            try
            {
                var builder = GetBuilder($"cdb/add-book/{jobid}/{addDuplicates}/{filename}/{settings.Library}", settings);

                var request = builder.Build();
                request.SetContent(body);

                var response = _httpClient.Post <CalibreImportJob>(request).Resource;

                if (response.Id == 0)
                {
                    throw new CalibreException("Calibre rejected duplicate book");
                }

                return(response);
            }
            catch (HttpException ex)
            {
                throw new CalibreException("Unable to add file to Calibre library: {0}", ex, ex.Message);
            }
        }
Example #2
0
        private void PollEmbedStatus(BookFile file, CalibreSettings settings)
        {
            var previous = new FileInfo(file.Path);

            Thread.Sleep(100);

            FileInfo current = null;

            var i = 0;

            while (i++ < 20)
            {
                current = new FileInfo(file.Path);

                if (current.LastWriteTimeUtc == previous.LastWriteTimeUtc &&
                    current.LastWriteTimeUtc != file.Modified)
                {
                    break;
                }

                previous = current;
                Thread.Sleep(1000);
            }

            file.Size     = current.Length;
            file.Modified = current.LastWriteTimeUtc;

            if (file.Id > 0)
            {
                _mediaFileService.Update(file);
            }
        }
Example #3
0
        /// <summary>
        /// Seeks book data from mods.
        /// If a book file with the given name is found, data is loaded on the given book instance.
        /// If no data is found, the instance is left unaltered.
        /// </summary>
        /// <param name="name">Name of book including .TXT extension</param>
        /// <param name="book">Book instance on which imported data is loaded.</param>
        /// <returns>True if book is found.</returns>
        public static bool TryImportBook(string name, BookFile book)
        {
            if (DaggerfallUnity.Settings.AssetInjection)
            {
                // Seek from loose files
                string path = Path.Combine(booksPath, name);
                if (File.Exists(path))
                {
                    if (book.OpenBook(File.ReadAllBytes(path), name))
                    {
                        return(true);
                    }
                }

                // Seek from mods
                TextAsset textAsset;
                if (ModManager.Instance != null && ModManager.Instance.TryGetAsset(name, false, out textAsset))
                {
                    if (book.OpenBook(textAsset.bytes, name))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        public ActionResult Save(Book book, BookFile bookFile, HttpPostedFileBase file)
        {
            if (file != null)
            {
                var extension = Path.GetExtension(file.FileName).ToLower();
                var FileName  = file.FileName;
                file.SaveAs(HttpContext.Server.MapPath("~/Books/") + FileName);

                bookFile.FilePath = FileName;
                book.File         = bookFile;

                db.BookFiles.Add(bookFile);
                db.SaveChanges();
                book.File = db.BookFiles.SingleOrDefault(f => f.FilePath == FileName);
            }
            var email = User.Identity.GetUserName();
            var Acc   = db.Account.SingleOrDefault(a => a.Email == email);

            book.Author = Acc;

            db.Book.Add(book);
            db.SaveChanges();
            return(RedirectToAction("BooksList", "Books"));


            //return View("Create",book);
        }
Example #5
0
        public void GetBookList_SameBookWithAndWithoutIsbn_ReturnsFilesGroupedByIsbn()
        {
            var files = new BookFile[]
            {
                new BookFile {
                    Isbn = "1000000000001", Title = "Book1", Author = "Author1", FilePath = "File1.mobi"
                },
                new BookFile {
                    Isbn = null, Title = "Book1", Author = "Author1", FilePath = "File2.mobi"
                },
                new BookFile {
                    Isbn = "1000000000003", Title = "Book3", Author = "Author3", FilePath = "File3.mobi"
                },
            };

            var agg = new Aggregator();

            BookInfo[] books  = agg.GetBookList(files).ToArray();
            var        lookup = agg.GetBookContentInfoLookup();

            Assert.IsNotNull(books);
            Assert.AreEqual(2, books.Length);
            Assert.AreEqual(2, lookup.Count);

            AssertBookInfoTitleAndAuthor(books[0], "Book1", "Author1");
            AssertBookInfoTitleAndAuthor(books[1], "Book3", "Author3");

            AssertBookInfoTitleAndAuthor(lookup[books[0].Id].Book, "Book1", "Author1");
            AssertBookInfoTitleAndAuthor(lookup[books[1].Id].Book, "Book3", "Author3");

            AssertBookFiles(lookup[books[0].Id], new[] { "File1.mobi", "File2.mobi" });
            AssertBookFiles(lookup[books[1].Id], new[] { "File3.mobi" });
        }
Example #6
0
        public void Setup()
        {
            _author = Builder <Author>
                      .CreateNew()
                      .With(s => s.Name = "Avenged Sevenfold")
                      .Build();

            _book = Builder <Book>
                    .CreateNew()
                    .With(s => s.Title = "Hail to the King")
                    .Build();

            _edition = Builder <Edition>
                       .CreateNew()
                       .With(s => s.Title = _book.Title)
                       .With(s => s.Book  = _book)
                       .Build();

            _trackFile = new BookFile {
                Quality = new QualityModel(Quality.MP3_320), ReleaseGroup = "ReadarrTest"
            };

            _namingConfig             = NamingConfig.Default;
            _namingConfig.RenameBooks = true;

            Mocker.GetMock <INamingConfigService>()
            .Setup(c => c.GetConfig()).Returns(_namingConfig);

            Mocker.GetMock <IQualityDefinitionService>()
            .Setup(v => v.Get(Moq.It.IsAny <Quality>()))
            .Returns <Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v));
        }
Example #7
0
        protected TExtraFile ImportFile(Author author, BookFile bookFile, string path, bool readOnly, string extension, string fileNameSuffix = null)
        {
            var newFolder       = Path.GetDirectoryName(bookFile.Path);
            var filenameBuilder = new StringBuilder(Path.GetFileNameWithoutExtension(bookFile.Path));

            if (fileNameSuffix.IsNotNullOrWhiteSpace())
            {
                filenameBuilder.Append(fileNameSuffix);
            }

            filenameBuilder.Append(extension);

            var newFileName  = Path.Combine(newFolder, filenameBuilder.ToString());
            var transferMode = TransferMode.Move;

            if (readOnly)
            {
                transferMode = _configService.CopyUsingHardlinks ? TransferMode.HardLinkOrCopy : TransferMode.Copy;
            }

            _diskTransferService.TransferFile(path, newFileName, transferMode, true);

            return(new TExtraFile
            {
                AuthorId = author.Id,
                BookId = bookFile.EditionId,
                BookFileId = bookFile.Id,
                RelativePath = author.Path.GetRelativePath(newFileName),
                Extension = extension
            });
        }
Example #8
0
 private void CreateAfterImport(Author author, BookFile bookFile)
 {
     foreach (var extraFileManager in _extraFileManagers)
     {
         extraFileManager.CreateAfterBookImport(author, bookFile);
     }
 }
Example #9
0
        public void Setup()
        {
            _localTrack        = new LocalBook();
            _localTrack.Author = new Author
            {
                Path = _rootPath
            };

            _trackFile = Builder <BookFile>
                         .CreateNew()
                         .Build();

            Mocker.GetMock <IDiskProvider>()
            .Setup(c => c.FileExists(It.IsAny <string>()))
            .Returns(true);

            Mocker.GetMock <IDiskProvider>()
            .Setup(c => c.FolderExists(It.IsAny <string>()))
            .Returns(true);

            Mocker.GetMock <IDiskProvider>()
            .Setup(c => c.GetParentFolder(It.IsAny <string>()))
            .Returns <string>(c => Path.GetDirectoryName(c));

            Mocker.GetMock <IRootFolderService>()
            .Setup(c => c.GetBestRootFolder(It.IsAny <string>()))
            .Returns(new RootFolder());
        }
Example #10
0
        protected TExtraFile MoveFile(Author author, BookFile bookFile, TExtraFile extraFile, string fileNameSuffix = null)
        {
            var newFolder       = Path.GetDirectoryName(bookFile.Path);
            var filenameBuilder = new StringBuilder(Path.GetFileNameWithoutExtension(bookFile.Path));

            if (fileNameSuffix.IsNotNullOrWhiteSpace())
            {
                filenameBuilder.Append(fileNameSuffix);
            }

            filenameBuilder.Append(extraFile.Extension);

            var existingFileName = Path.Combine(author.Path, extraFile.RelativePath);
            var newFileName      = Path.Combine(newFolder, filenameBuilder.ToString());

            if (newFileName.PathNotEquals(existingFileName))
            {
                try
                {
                    _diskProvider.MoveFile(existingFileName, newFileName);
                    extraFile.RelativePath = author.Path.GetRelativePath(newFileName);

                    return(extraFile);
                }
                catch (Exception ex)
                {
                    _logger.Warn(ex, "Unable to move file after rename: {0}", existingFileName);
                }
            }

            return(null);
        }
Example #11
0
        public void Setup()
        {
            _artist = Builder <Author>
                      .CreateNew()
                      .With(s => s.Name = "Alien Ant Farm")
                      .Build();

            _album = Builder <Book>
                     .CreateNew()
                     .With(s => s.Title = "Anthology")
                     .Build();

            _edition = Builder <Edition>
                       .CreateNew()
                       .With(s => s.Title = _album.Title)
                       .With(s => s.Book  = _album)
                       .Build();

            _trackFile = new BookFile {
                Quality = new QualityModel(Quality.MP3_320), ReleaseGroup = "ReadarrTest"
            };

            _namingConfig             = NamingConfig.Default;
            _namingConfig.RenameBooks = true;

            Mocker.GetMock <INamingConfigService>()
            .Setup(c => c.GetConfig()).Returns(_namingConfig);

            Mocker.GetMock <IQualityDefinitionService>()
            .Setup(v => v.Get(Moq.It.IsAny <Quality>()))
            .Returns <Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v));
        }
        public void Setup()
        {
            _author = Builder <Author> .CreateNew()
                      .With(a => a.AuthorMetadataId = 10)
                      .BuildNew();

            Db.Insert(_author);

            _book = Builder <Book> .CreateNew()
                    .With(e => e.ReleaseDate      = DateTime.Today.AddDays(-5))
                    .With(e => e.AuthorMetadataId = 10)
                    .BuildNew();

            Db.Insert(_book);

            _edition = Builder <Edition> .CreateNew()
                       .With(e => e.BookId    = _book.Id)
                       .With(e => e.Monitored = true)
                       .BuildNew();

            Db.Insert(_edition);

            _trackFile = Builder <BookFile> .CreateNew()
                         .With(e => e.Author  = _author)
                         .With(e => e.Edition = _edition)
                         .With(e => e.EditionId == _edition.Id)
                         .With(e => e.Quality = new QualityModel(Quality.MP3_320))
                         .BuildNew();
        }
Example #13
0
        public void AddFormat(BookFile file, CalibreSettings settings)
        {
            var format   = Path.GetExtension(file.Path);
            var bookData = Convert.ToBase64String(File.ReadAllBytes(file.Path));

            var payload = new CalibreChangesPayload
            {
                LoadedBookIds = new List <int> {
                    file.CalibreId
                },
                Changes = new CalibreChanges
                {
                    AddedFormats = new List <CalibreAddFormat>
                    {
                        new CalibreAddFormat
                        {
                            Ext  = format,
                            Data = bookData
                        }
                    }
                }
            };

            ExecuteSetFields(file.CalibreId, payload, settings);
        }
Example #14
0
        public static BookFile CreateNew(string file)
        {
            var bookFile = new BookFile();

            bookFile.FileNameWithExtension = Path.GetFileName(file);
            return(bookFile);
        }
Example #15
0
        IEnumerable <BookInfo> GetBookListInt(IEnumerable <BookFile> bookFiles)
        {
            var booksNoIsbn =
                from m in bookFiles
                group m by new
            {
                m.Title,
                m.Author
            }
            into g
                select new { Title = g.Key.Title, Author = g.Key.Author, Files = g };

            var bookListNoIsbn = booksNoIsbn.Select(b =>
            {
                BookFile first = b.Files.FirstOrDefault(f => !string.IsNullOrEmpty(f.Isbn));

                if (first == null)
                {
                    first = b.Files.First();
                }

                var files = b.Files.Select(f => f.FilePath);

                return(GetBook(first, files));
            });

            return(bookListNoIsbn);
        }
Example #16
0
        public void SetFields(BookFile file, CalibreSettings settings)
        {
            var edition    = file.Edition.Value;
            var book       = edition.Book.Value;
            var serieslink = book.SeriesLinks.Value.FirstOrDefault();

            var    series      = serieslink?.Series.Value;
            double?seriesIndex = null;

            if (double.TryParse(serieslink?.Position, out var index))
            {
                _logger.Trace($"Parsed {serieslink?.Position} as {index}");
                seriesIndex = index;
            }

            _logger.Trace($"Book: {book} Series: {series?.Title}, Position: {seriesIndex}");

            var    cover = edition.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Cover);
            string image = null;

            if (cover != null)
            {
                var imageFile = _mediaCoverService.GetCoverPath(edition.BookId, MediaCoverEntity.Book, cover.CoverType, cover.Extension, null);

                if (File.Exists(imageFile))
                {
                    var imageData = File.ReadAllBytes(imageFile);
                    image = Convert.ToBase64String(imageData);
                }
            }

            var payload = new CalibreChangesPayload
            {
                LoadedBookIds = new List <int> {
                    file.CalibreId
                },
                Changes = new CalibreChanges
                {
                    Title   = edition.Title,
                    Authors = new List <string> {
                        file.Author.Value.Name
                    },
                    Cover       = image,
                    PubDate     = book.ReleaseDate,
                    Comments    = edition.Overview,
                    Rating      = edition.Ratings.Value * 2,
                    Identifiers = new Dictionary <string, string>
                    {
                        { "isbn", edition.Isbn13 },
                        { "asin", edition.Asin },
                        { "goodreads", edition.ForeignEditionId }
                    },
                    Series      = series?.Title,
                    SeriesIndex = seriesIndex
                }
            };

            ExecuteSetFields(file.CalibreId, payload, settings);
        }
        public void Setup()
        {
            Mocker.Resolve <UpgradableSpecification>();

            _firstFile = new BookFile {
                Quality = new QualityModel(Quality.FLAC, new Revision(version: 2)), DateAdded = DateTime.Now
            };
            _secondFile = new BookFile {
                Quality = new QualityModel(Quality.FLAC, new Revision(version: 2)), DateAdded = DateTime.Now
            };

            var singleBookList = new List <Book> {
                new Book {
                    BookFiles = new List <BookFile>()
                }
            };
            var doubleBookList = new List <Book> {
                new Book {
                    BookFiles = new List <BookFile>()
                }, new Book {
                    BookFiles = new List <BookFile>()
                }, new Book {
                    BookFiles = new List <BookFile>()
                }
            };

            var fakeAuthor = Builder <Author> .CreateNew()
                             .With(c => c.QualityProfile = new QualityProfile
            {
                UpgradeAllowed = true,
                Cutoff         = Quality.MP3_320.Id,
                Items          = Qualities.QualityFixture.GetDefaultQualities()
            })
                             .Build();

            Mocker.GetMock <IMediaFileService>()
            .Setup(c => c.GetFilesByBook(It.IsAny <int>()))
            .Returns(new List <BookFile> {
                _firstFile, _secondFile
            });

            _parseResultMulti = new RemoteBook
            {
                Author         = fakeAuthor,
                ParsedBookInfo = new ParsedBookInfo {
                    Quality = new QualityModel(Quality.MP3_320, new Revision(version: 2))
                },
                Books = doubleBookList
            };

            _parseResultSingle = new RemoteBook
            {
                Author         = fakeAuthor,
                ParsedBookInfo = new ParsedBookInfo {
                    Quality = new QualityModel(Quality.MP3_320, new Revision(version: 2))
                },
                Books = singleBookList
            };
        }
Example #18
0
        public override ExtraFile Import(Author author, BookFile bookFile, string path, string extension, bool readOnly)
        {
            var extraFile = ImportFile(author, bookFile, path, readOnly, extension, null);

            _otherExtraFileService.Upsert(extraFile);

            return(extraFile);
        }
Example #19
0
            public override string BookAuthor()
            {   // %ba
                BookFile bookFile = new BookFile();

                bookFile.OpenBook(DaggerfallUnity.Instance.Arena2Path, BookFile.messageToBookFilename(parent.message));
                // Should the bookfile get closed?
                return(bookFile.Author);
            }
Example #20
0
        private void WithExistingFile(BookFile trackFile)
        {
            var path = trackFile.Path;

            Mocker.GetMock <IDiskProvider>()
            .Setup(v => v.FileExists(path))
            .Returns(true);
        }
Example #21
0
        public virtual string GetFilenameAfterMove(Author author, BookFile bookFile, MetadataFile metadataFile)
        {
            var existingFilename = Path.Combine(author.Path, metadataFile.RelativePath);
            var extension        = Path.GetExtension(existingFilename).TrimStart('.');
            var newFileName      = Path.ChangeExtension(bookFile.Path, extension);

            return(newFileName);
        }
Example #22
0
        public string BuildBookFileName(Author author, Edition edition, BookFile bookFile, NamingConfig namingConfig = null, List <string> preferredWords = null, string bookPart = null)
        {
            if (author is null)
            {
                throw new ArgumentNullException(nameof(author));
            }

            if (edition is null)
            {
                throw new ArgumentNullException(nameof(edition));
            }

            if (bookFile is null)
            {
                throw new ArgumentNullException(nameof(bookFile));
            }

            if (namingConfig == null)
            {
                namingConfig = _namingConfigService.GetConfig();
            }

            if (!namingConfig.RenameBooks)
            {
                return(GetOriginalFileName(bookFile));
            }

            if (namingConfig.StandardBookFormat.IsNullOrWhiteSpace())
            {
                throw new NamingFormatException("File name format cannot be empty");
            }

            var pattern = namingConfig.StandardBookFormat;

            var subFolders  = pattern.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
            var safePattern = subFolders.Aggregate("", (current, folderLevel) => Path.Combine(current, folderLevel));

            var tokenHandlers = new Dictionary <string, Func <TokenMatch, string> >(FileNameBuilderTokenEqualityComparer.Instance);

            AddAuthorTokens(tokenHandlers, author);
            AddBookTokens(tokenHandlers, edition);
            AddBookFileTokens(tokenHandlers, bookFile);
            AddQualityTokens(tokenHandlers, author, bookFile);
            AddMediaInfoTokens(tokenHandlers, bookFile);
            AddPreferredWords(tokenHandlers, author, bookFile, preferredWords);

            var fileName = ReplaceTokens(safePattern, tokenHandlers, namingConfig).Trim();

            fileName = FileNameCleanupRegex.Replace(fileName, match => match.Captures[0].Value[0].ToString());
            fileName = TrimSeparatorsRegex.Replace(fileName, string.Empty);

            if (bookPart.IsNotNullOrWhiteSpace())
            {
                fileName = fileName + " (" + bookPart + ")";
            }

            return(fileName);
        }
Example #23
0
        // Notes:
        //  Book files have text pre-paginated based on classic 320x200.
        //  This has no meaning with custom fonts and languages as book might require more or fewer pages.
        //  Reformat process will structure book instead as a list of word-wrapped labels and breaks.
        //  Book reader UI can then break these back into pages based on fixed text height.
        //  For some reason the first line of first paragraph of many books is centre justified.
        //  After reformatting this results in entire first paragraph being centre justified.

        public bool ReformatBook(int id)
        {
            if (DaggerfallUnity.Settings.CustomBooksImport)
            {
                return(ReformatBook(DaggerfallUnity.Instance.ItemHelper.GetBookFileName(id)));
            }

            return(ReformatBook(BookFile.messageToBookFilename(id)));
        }
Example #24
0
        public virtual bool OpenBook(int message)
        {
            if (DaggerfallUnity.Settings.CustomBooksImport)
            {
                return(OpenBook(DaggerfallUnity.Instance.ItemHelper.GetBookFileNameByMessage(message)));
            }

            return(OpenBook(BookFile.messageToBookFilename(message)));
        }
Example #25
0
        private string GetOriginalTitle(BookFile bookFile)
        {
            if (bookFile.SceneName.IsNullOrWhiteSpace())
            {
                return(GetOriginalFileName(bookFile));
            }

            return(bookFile.SceneName);
        }
Example #26
0
 public WebhookBookFile(BookFile bookFile)
 {
     Id             = bookFile.Id;
     Path           = bookFile.Path;
     Quality        = bookFile.Quality.Quality.Name;
     QualityVersion = bookFile.Quality.Revision.Version;
     ReleaseGroup   = bookFile.ReleaseGroup;
     SceneName      = bookFile.SceneName;
 }
Example #27
0
 public BookFileRetaggedEvent(Author author,
                              BookFile bookFile,
                              Dictionary <string, Tuple <string, string> > diff,
                              bool scrubbed)
 {
     Author   = author;
     BookFile = bookFile;
     Diff     = diff;
     Scrubbed = scrubbed;
 }
Example #28
0
        public void null_string_as_arg_should_not_fail()
        {
            var epFile = new BookFile();

            _logger.Debug("File {0} no longer exists on disk. removing from database.", epFile.Path);

            Thread.Sleep(1000);

            epFile.Path.Should().BeNull();
        }
            public override string BookAuthor()
            {   // %ba
                BookFile bookFile = new BookFile();
                string   name     = BookFile.messageToBookFilename(parent.message);

                if (!BookReplacement.TryImportBook(name, bookFile))
                {
                    bookFile.OpenBook(DaggerfallUnity.Instance.Arena2Path, name);
                }
                return(bookFile.Author);
            }
Example #30
0
 private string BuildTrackSample(Author author, BookFile bookFile, NamingConfig nameSpec)
 {
     try
     {
         return(_buildFileNames.BuildBookFileName(author, bookFile.Edition.Value, bookFile, nameSpec, _preferredWords));
     }
     catch (NamingFormatException)
     {
         return(string.Empty);
     }
 }
Example #31
0
 public static BookFile CreateNew(string file)
 {
     var bookFile = new BookFile();
     bookFile.FileNameWithExtension = Path.GetFileName(file);
     return bookFile;
 }