// 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}"); } } }