From a9620b3e347ffca930c78c52b248104f87588018 Mon Sep 17 00:00:00 2001 From: Martin Brodbeck Date: Fri, 12 Feb 2021 09:13:31 +0100 Subject: [PATCH] Fixes and improvements - Fix reading file-as from XML - Now fixing first_author_letter --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/epub.rs | 15 ++++++------ src/main.rs | 67 +++++++++++++++++++++++++++++++++++++++-------------- 4 files changed, 58 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d848cc..1c65061 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,7 +148,7 @@ dependencies = [ [[package]] name = "pbdbfixer" -version = "0.5.0" +version = "0.6.0" dependencies = [ "quick-xml", "rusqlite", diff --git a/Cargo.toml b/Cargo.toml index f7b9656..05c3b23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pbdbfixer" -version = "0.5.0" +version = "0.6.0" authors = ["Martin Brodbeck "] edition = "2018" diff --git a/src/epub.rs b/src/epub.rs index bc2ab90..ed63f75 100644 --- a/src/epub.rs +++ b/src/epub.rs @@ -139,24 +139,19 @@ pub fn get_epub_metadata(filename: &str) -> Option { .filter(|attr| attr.as_ref().unwrap().key.ends_with(b"file-as")) .next() { - let ns = - String::from_utf8(file_as_val.as_ref().unwrap().key.to_vec()).unwrap(); - curr_id = "none".to_string() + ns.split(':').collect::>()[0]; + curr_id = "none".to_string() + xml_authors.len().to_string().as_str(); let entry = xml_authors.entry(curr_id.clone()).or_insert(XmlAut::new()); entry.sort = file_as_val .unwrap() .unescape_and_decode_value(&reader) .unwrap_or_default(); entry.role = "aut".to_string(); - } - if let Some(role_val) = e + } else if let Some(_role_val) = e .attributes() .filter(|attr| attr.as_ref().unwrap().key.ends_with(b"role")) .next() { - let ns = - String::from_utf8(role_val.as_ref().unwrap().key.to_vec()).unwrap(); - curr_id = "none".to_string() + ns.split(':').collect::>()[0]; + curr_id = "none".to_string() + xml_authors.len().to_string().as_str(); } } } @@ -217,6 +212,8 @@ pub fn get_epub_metadata(filename: &str) -> Option { } } + //println!("Meta: {:?}", &xml_authors); + epub_meta.authors = xml_authors .into_iter() .filter(|&(_, ref xml_author)| &xml_author.role == "aut" && &xml_author.name.len() > &0) @@ -226,5 +223,7 @@ pub fn get_epub_metadata(filename: &str) -> Option { }) .collect(); + //println!("Meta: {:?}", &epub_meta); + Some(epub_meta) } diff --git a/src/main.rs b/src/main.rs index d997046..6bc4afd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ struct BookEntry { firstauthor: String, has_drm: bool, genre: String, + first_author_letter: String, } fn get_epubs_from_database(tx: &Transaction) -> Vec { @@ -18,8 +19,9 @@ fn get_epubs_from_database(tx: &Transaction) -> Vec { let mut stmt = tx .prepare( - r" - SELECT books.id, folders.name, files.filename, books.firstauthor, books.author, genres.name + r#" + SELECT books.id, folders.name, files.filename, books.firstauthor, + books.author, genres.name, first_author_letter FROM books_impl books JOIN files ON books.id = files.book_id JOIN folders @@ -29,7 +31,7 @@ fn get_epubs_from_database(tx: &Transaction) -> Vec { LEFT OUTER JOIN genres ON genres.id = btg.genreid WHERE files.storageid = 1 AND books.ext = 'epub' - ORDER BY books.id", + ORDER BY books.id"#, ) .unwrap(); @@ -47,6 +49,7 @@ fn get_epubs_from_database(tx: &Transaction) -> Vec { _ => false, }; let genre: String = row.get(5).unwrap_or_default(); + let first_author_letter = row.get(6).unwrap_or_default(); let entry = BookEntry { id: book_id, @@ -55,6 +58,7 @@ fn get_epubs_from_database(tx: &Transaction) -> Vec { author, has_drm, genre, + first_author_letter, }; book_entries.push(entry); @@ -66,7 +70,7 @@ fn get_epubs_from_database(tx: &Transaction) -> Vec { fn remove_ghost_books_from_db(tx: &Transaction) -> usize { let mut stmt = tx .prepare( - r" + r#" DELETE FROM books_impl WHERE id IN ( SELECT books.id @@ -74,34 +78,34 @@ fn remove_ghost_books_from_db(tx: &Transaction) -> usize { LEFT OUTER JOIN files ON books.id = files.book_id WHERE files.filename is NULL - )", + )"#, ) .unwrap(); let num = stmt.execute(NO_PARAMS).unwrap(); tx.execute( - r"DELETE FROM books_settings WHERE bookid NOT IN ( SELECT id FROM books_impl )", + r#"DELETE FROM books_settings WHERE bookid NOT IN ( SELECT id FROM books_impl )"#, NO_PARAMS, ) .unwrap(); tx.execute( - r"DELETE FROM books_uids WHERE book_id NOT IN ( SELECT id FROM books_impl )", + r#"DELETE FROM books_uids WHERE book_id NOT IN ( SELECT id FROM books_impl )"#, NO_PARAMS, ) .unwrap(); tx.execute( - r"DELETE FROM bookshelfs_books WHERE bookid NOT IN ( SELECT id FROM books_impl )", + r#"DELETE FROM bookshelfs_books WHERE bookid NOT IN ( SELECT id FROM books_impl )"#, NO_PARAMS, ) .unwrap(); tx.execute( - r"DELETE FROM booktogenre WHERE bookid NOT IN ( SELECT id FROM books_impl )", + r#"DELETE FROM booktogenre WHERE bookid NOT IN ( SELECT id FROM books_impl )"#, NO_PARAMS, ) .unwrap(); tx.execute( - r"DELETE FROM social WHERE bookid NOT IN ( SELECT id FROM books_impl )", + r#"DELETE FROM social WHERE bookid NOT IN ( SELECT id FROM books_impl )"#, NO_PARAMS, ) .unwrap(); @@ -114,6 +118,7 @@ struct Statistics { ghost_books_cleaned: usize, drm_skipped: usize, genres_fixed: usize, + sorting_fixed: usize, } fn fix_db_entries(tx: &Transaction, book_entries: &Vec) -> Statistics { @@ -122,6 +127,7 @@ fn fix_db_entries(tx: &Transaction, book_entries: &Vec) -> Statistics ghost_books_cleaned: 0, drm_skipped: 0, genres_fixed: 0, + sorting_fixed: 0, }; for entry in book_entries { @@ -131,17 +137,14 @@ fn fix_db_entries(tx: &Transaction, book_entries: &Vec) -> Statistics } if let Some(epub_metadata) = epub::get_epub_metadata(&entry.filepath) { - let authors = epub_metadata + // Fix firstauthor… + let mut firstauthors = epub_metadata .authors .iter() .filter(|aut| aut.firstauthor.len() > 0) - .collect::>(); - - // Fix firstauthor… - let firstauthors = authors - .iter() .map(|aut| aut.firstauthor.clone()) .collect::>(); + firstauthors.sort(); if !firstauthors.iter().all(|s| entry.firstauthor.contains(s)) { let mut stmt = tx .prepare("UPDATE books_impl SET firstauthor = :file_as WHERE id = :book_id") @@ -153,8 +156,28 @@ fn fix_db_entries(tx: &Transaction, book_entries: &Vec) -> Statistics stat.authors_fixed = stat.authors_fixed + 1; } + // Fix first_author_letter + let first_author_letter = firstauthors + .join(" & ") + .chars() + .next() + .unwrap_or_default() + .to_string() + .to_uppercase(); + if entry.first_author_letter != first_author_letter { + let mut stmt = tx + .prepare("UPDATE books_impl SET first_author_letter = :first_letter WHERE id = :book_id") + .unwrap(); + stmt.execute_named( + named_params![":first_letter": first_author_letter,":book_id": entry.id], + ) + .unwrap(); + stat.sorting_fixed = stat.sorting_fixed + 1; + } + // Fix author names… - let authornames = authors + let authornames = epub_metadata + .authors .iter() .map(|aut| aut.name.clone()) .collect::>(); @@ -169,6 +192,7 @@ fn fix_db_entries(tx: &Transaction, book_entries: &Vec) -> Statistics stat.authors_fixed = stat.authors_fixed + 1; } + // Fix genre… if entry.genre.is_empty() && epub_metadata.genre.len() > 0 { let mut stmt = tx .prepare(r#"INSERT INTO genres (name) SELECT :genre ON CONFLICT DO NOTHING"#) @@ -255,10 +279,12 @@ fn main() { pocketbook::Icon::Info, &format!( "Authors fixed: {}\n\ + Sorting fixed: {}\n\ Genres fixed: {}\n\ Books skipped (DRM): {}\n\ Books cleaned from DB: {}", &stat.authors_fixed, + &stat.sorting_fixed, &stat.genres_fixed, &stat.drm_skipped, &stat.ghost_books_cleaned @@ -269,10 +295,15 @@ fn main() { } else { println!( "Authors fixed: {}\n\ + Sorting fixed: {}\n\ Genres fixed: {}\n\ Books skipped (DRM): {}\n\ Books cleaned from DB: {}", - &stat.authors_fixed, &stat.genres_fixed, &stat.drm_skipped, &stat.ghost_books_cleaned + &stat.authors_fixed, + &stat.sorting_fixed, + &stat.genres_fixed, + &stat.drm_skipped, + &stat.ghost_books_cleaned ); } }