public override void DeleteBook(int id) { Database.BookEntry bookEntry = Database.BOOKS.FirstOrDefault(x => x.Id == id); if (bookEntry == null) { throw new Database.IDNotFoundException(); } Database.RemoveBook(bookEntry); string filePath = AbsoluteFilePath(bookEntry); try { File.Delete(filePath); } catch (FileNotFoundException) { } catch (DirectoryNotFoundException) { } catch (Exception e) { throw new Exception($"{bookEntry.Title} was removed from database but the file could not be deleted. {e.Message}"); } Utils.Files.CleanBackward(Path.GetDirectoryName(filePath), LibraryRoot); }
public virtual void UpdateBookMetadata(BookBase donor) { Database.BookEntry entry = Database.BOOKS.FirstOrDefault(x => x.Id == donor.Id); if (entry == null) { return; } BookBase recip = BookBase.Auto(AbsoluteFilePath(entry)); recip.UpdateMetadata(donor); Database.UpdateBook(donor); string origPath = recip.FilePath; string targetPath = FormatFilePath(FilePathTemplate(), recip); if (origPath != targetPath) { try { Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); File.Move(origPath, targetPath); donor.FilePath = targetPath; Database.UpdateBook(donor); } catch (Exception e) { throw new Exception($"Could not rename file in library directory. {e.Message}"); } } }
public MetadataEditor(Database.BookEntry book, HashSet <string> authors, HashSet <string> series, HashSet <string> publishers) { this.DataContext = this; this.AuthorsList = App.LocalLibrary.Database.ListAuthors(); this.SeriesList = App.LocalLibrary.Database.ListSeries(); this.ModBook = new Database.BookEntry(book); AuthorsList = authors.ToArray(); SeriesList = series.ToArray(); PublisherList = publishers.ToArray(); InitializeComponent(); }
// todo test this whole region #region book import methods /// <summary> /// Used to import from another device's library. /// </summary> private void ImportBook(Database.BookEntry remoteEntry) { Logger.Info("Importing {}.", remoteEntry.Title); BookBase localBook = CombinedLibrary.FirstOrDefault(x => x.IsLocal && x.Id == remoteEntry.Id); if (localBook != null) { Logger.Info("{}[{}] already exists in library, copying metadata from Kindle.", localBook.Title, localBook.Id); try { localBook.UpdateMetadata(remoteEntry); } catch (LiteDB.LiteException e) { Logger.Error(e, "Unable to update metadata in database."); throw new Exception($"Unable to update metadata in database; {e.Message}"); } catch (Exception e) { Logger.Error(e, "Unable to write metadata to disk."); throw new Exception($"Unable to write metadata to disk; {e.Message}"); } } Dictionary <string, string> remoteMetadata = remoteEntry.Props(); string localFile = Path.Combine(App.Config.LibraryRoot, App.Config.LibraryRoot, "{Title}").DictFormat(remoteMetadata); localFile = Utils.Files.MakeFilesystemSafe(localFile + Path.GetExtension(remoteEntry.FilePath)); try { Directory.CreateDirectory(Path.GetDirectoryName(localFile)); } catch (Exception e) { Logger.Error(e, "Unable to create directories."); throw new Exception($"Unable to create directories; {e.Message}"); } Database.BookEntry localEntry; if (File.Exists(localFile)) { localEntry = CombinedLibrary.FirstOrDefault(x => x.IsLocal && x.FilePath == localFile); if (localEntry == null) // target file exists but is *not* in local db { Logger.Info("{} exists but is not in local database. File will be overwritten with remote copy.", localFile); try { File.Delete(localFile); File.Copy(remoteEntry.FilePath, localFile); } catch (Exception e) { Logger.Error(e, "Unable to overwrite file."); throw new Exception($"Unable to overwrite file; {e.Message}"); } try { App.LocalLibrary.ImportBook(remoteEntry); } catch (Exception e) { Logger.Error(e, "Unable to update library database."); throw new Exception($"Unable to update library; {e.Message}"); } } else // target file exists and *is* in local db { string msg = $"{localEntry.Title} exists in local library. Metadata will be copied from Kindle"; if (SelectedDevice != null && localEntry.Id != remoteEntry.Id) { Logger.Info(msg + " ID [{}] on {} will be changed from to [{}] to match local database.", remoteEntry.Id, SelectedDevice.Name, localEntry.Id); try { SelectedDevice.Database.ChangeBookId(remoteEntry, localEntry.Id); } catch (Exception e) { Logger.Error(e, "Unable to write to database."); throw new Exception($"Unable to write to database; {e.Message}"); } } Logger.Info(msg, remoteEntry.Title); try { localEntry.UpdateMetadata(remoteEntry); App.LocalLibrary.Database.UpdateBook(localEntry); } catch (LiteDB.LiteException e) { Logger.Error(e, "Unable to write metadata to database."); throw new Exception($"Unable to write metadata database; {e.Message}"); } catch (Exception e) { Logger.Error(e, "Unable to write metadata to disk."); throw new Exception($"Unable to write metadata disk; {e.Message}"); } } } else { localEntry = CombinedLibrary.FirstOrDefault(x => x.IsLocal && x.Id == remoteEntry.Id); if (localEntry != null) { Logger.Info("{} found in database but not on disk, removing database entry before importing.", localEntry.Title); try { App.LocalLibrary.Database.RemoveBook(localEntry); } catch (LiteDB.LiteException e) { Logger.Error(e, "Unable to write to database."); throw new Exception($"Unable to write to database; {e.Message}"); } } try { App.LocalLibrary.ImportBook(remoteEntry); } catch (LiteDB.LiteException e) { Logger.Error(e, "Unable to write to database."); throw new Exception($"Unable to write to database; {e.Message}"); } catch (Exception e) { Logger.Error(e, "Unable to import book."); throw new Exception($"Unable to import book; {e.Message}"); } } }
public async void _RemoveBook() { if (SelectedTableRow == null) { return; } Database.BookEntry book = SelectedTableRow; bool onDevice = SelectedDevice == null ? false : CombinedLibrary.Any(x => x.IsRemote && x.Id == book.Id); bool onPC = CombinedLibrary.Any(x => x.IsLocal && x.Id == book.Id); var dlg = new Dialogs.DeleteConfirm(book.Title, onDevice, onPC); await MaterialDesignThemes.Wpf.DialogHost.Show(dlg); if (dlg.DialogResult == false) { return; } if (dlg.DeleteFrom == 0 || dlg.DeleteFrom == 1) // device { Database.BookEntry remoteBook = SelectedDevice.Database.BOOKS.FirstOrDefault(x => x.Id == book.Id); try { SelectedDevice.DeleteBook(book.Id); } catch (Exception e) { var errDlg = new Dialogs.Error($"Unable to delete book from {SelectedDevice.Name}", e.Message); await MaterialDesignThemes.Wpf.DialogHost.Show(errDlg); return; } } if (dlg.DeleteFrom == 0 || dlg.DeleteFrom == 2) // pc { Database.BookEntry localBook = CombinedLibrary.FirstOrDefault(x => x.IsLocal && x.Id == book.Id); try { if (localBook != null) { try { App.LocalLibrary.DeleteBook(localBook); } catch (FileNotFoundException) { } catch (DirectoryNotFoundException) { } Utils.Files.CleanBackward(Path.GetDirectoryName(localBook.FilePath), App.LibraryDirectory); } App.LocalLibrary.Database.RemoveBook(book); } catch (Exception e) { var errDlg = new Dialogs.Error("Unable to delete book from library", e.Message); await MaterialDesignThemes.Wpf.DialogHost.Show(errDlg); return; } } string msg = dlg.DeleteFrom == 0 ? "PC & Kindle" : (dlg.DeleteFrom == 2 ? "PC" : "Kindle"); SnackBarQueue.Enqueue($"{book.Title} deleted from {msg}."); }
public async void _SyncDeviceLibrary() { if (SelectedDevice == null) { var errDlg = new Dialogs.Error("No Kindle Selected", "Connect to Kindle Before Transferring Books"); await MaterialDesignThemes.Wpf.DialogHost.Show(errDlg); return; } List <Database.BookEntry> toTransfer = new List <Database.BookEntry>(); foreach (Database.BookEntry book in App.LocalLibrary.Database.BOOKS) { if (!SelectedDevice.Database.BOOKS.Any(x => x.Id == book.Id)) { toTransfer.Add(book); } } var dlg = new Dialogs.SyncConfirm(toTransfer, SelectedDevice.Name); await MaterialDesignThemes.Wpf.DialogHost.Show(dlg); if (dlg.DialogResult == false) { return; } var a = dlg.UserSelectedBooks; foreach (var b in dlg.UserSelectedBooks) { if (!b.Checked) { Database.BookEntry t = toTransfer.FirstOrDefault(x => x.Id == b.Id); if (t != null) { toTransfer.Remove(t); } } } var prgDlg = new Dialogs.Progress("Syncing Kindle Library", false); OpenBottomDrawer(prgDlg.Content); _ = Task.Run(() => { List <Exception> errs = new List <Exception>(); int step = 100 / toTransfer.Count; for (int i = 0; i < toTransfer.Count; i++) { Database.BookEntry book = toTransfer[i]; try { prgDlg.Current = $"Copying {book.Title}"; prgDlg.Percent += step; book.FilePath = App.LocalLibrary.AbsoluteFilePath(book); SelectedDevice.ImportBook(book); } catch (Exception e) { e.Data.Add("item", book.Title); errs.Add(e); } } if (errs.Count > 0) { prgDlg.Finish("Library sync finished with errors:"); prgDlg.ShowError(new AggregateException(errs.ToArray())); } else { prgDlg.Close(); SnackBarQueue.Enqueue($"{SelectedDevice.Name} library synced"); } }); }
public Unit _ReceiveBook(IList bookList) { if (bookList.Count == 0) { return(Unit.Default); } Database.BookEntry[] dbRows = new Database.BookEntry[bookList.Count]; bookList.CopyTo(dbRows, 0); Task.Run(() => { if (bookList.Count == 1) { Database.BookEntry book = (Database.BookEntry)bookList[0]; try { book.FilePath = SelectedDevice.AbsoluteFilePath(book); ImportBook(book); } catch (Exception e) { App.Current.Dispatcher.Invoke(() => { var dlg = new Dialogs.Error("Error transferring book", e.Message); MaterialDesignThemes.Wpf.DialogHost.Show(dlg); }); return; } SnackBarQueue.Enqueue($"{book.Title} copied to library."); } else { List <Exception> errs = new List <Exception>(); var prgDlg = new Dialogs.Progress("Syncing Library", false); OpenBottomDrawer(prgDlg.Content); int step = 100 / bookList.Count; foreach (Database.BookEntry b in bookList) { Database.BookEntry book = new Database.BookEntry(b); try { book.FilePath = SelectedDevice.AbsoluteFilePath(book); ImportBook(book); } catch (Exception e) { e.Data["item"] = book.Title; errs.Add(e); } } if (errs.Count > 0) { prgDlg.Finish("Book transfer finished with errors:"); prgDlg.ShowError(new AggregateException(errs.ToArray())); } else { prgDlg.Close(); SnackBarQueue.Enqueue("Book transfer finished"); } } }); return(Unit.Default); }