diff --git a/src/application/parsers/fb2.rs b/src/application/parsers/fb2.rs index 594402f..1ed0a7b 100644 --- a/src/application/parsers/fb2.rs +++ b/src/application/parsers/fb2.rs @@ -1,11 +1,10 @@ +use crate::domain::author; +use crate::domain::book::Book; use quick_xml::events::Event; use quick_xml::Reader; -use uuid::Uuid; use std::fs::File; use std::io::BufReader; use std::path::Path; -use crate::domain::author; -use crate::domain::book::Book; /// Parses an XML file located at the given path and extracts information about books. /// @@ -101,7 +100,10 @@ pub fn parse(path: &Path) -> Result, String> { b"book-title" => in_title = true, b"lang" => in_lang = true, b"keywords" => in_keywords = true, - b"annotation" => { in_description = true; description.clear(); }, + b"annotation" => { + in_description = true; + description.clear(); + } b"author" => { let mut buf_author = Vec::new(); let mut first_name = String::new(); @@ -113,30 +115,56 @@ pub fn parse(path: &Path) -> Result, String> { match reader.read_event_into(&mut buf_author) { Ok(Event::Start(c)) => match c.name().as_ref() { b"first-name" => { - if let Ok(Event::Text(t)) = reader.read_event_into(&mut buf_author) { - first_name = t.xml_content().map_err(|e| e.to_string())?.into_owned(); + if let Ok(Event::Text(t)) = + reader.read_event_into(&mut buf_author) + { + first_name = t + .xml_content() + .map_err(|e| e.to_string())? + .into_owned(); } } b"last-name" => { - if let Ok(Event::Text(t)) = reader.read_event_into(&mut buf_author) { - let val = t.xml_content().map_err(|e| e.to_string())?.into_owned(); - if !val.is_empty() { last_name = Some(val); } + if let Ok(Event::Text(t)) = + reader.read_event_into(&mut buf_author) + { + let val = t + .xml_content() + .map_err(|e| e.to_string())? + .into_owned(); + if !val.is_empty() { + last_name = Some(val); + } } } b"middle-name" => { - if let Ok(Event::Text(t)) = reader.read_event_into(&mut buf_author) { - let val = t.xml_content().map_err(|e| e.to_string())?.into_owned(); - if !val.is_empty() { middle_name = Some(val); } + if let Ok(Event::Text(t)) = + reader.read_event_into(&mut buf_author) + { + let val = t + .xml_content() + .map_err(|e| e.to_string())? + .into_owned(); + if !val.is_empty() { + middle_name = Some(val); + } } } b"nickname" => { - if let Ok(Event::Text(t)) = reader.read_event_into(&mut buf_author) { - let val = t.xml_content().map_err(|e| e.to_string())?.into_owned(); - if !val.is_empty() { nickname = Some(val); } + if let Ok(Event::Text(t)) = + reader.read_event_into(&mut buf_author) + { + let val = t + .xml_content() + .map_err(|e| e.to_string())? + .into_owned(); + if !val.is_empty() { + nickname = Some(val); + } } } _ => {} - } + }, Ok(Event::End(c)) if c.name().as_ref() == b"author" => break, Ok(Event::Eof) => break, _ => {} @@ -168,16 +196,16 @@ pub fn parse(path: &Path) -> Result, String> { }, Ok(Event::Text(t)) if in_title => { title = t.xml_content().map_err(|e| e.to_string())?.into_owned(); - }, + } Ok(Event::Text(t)) if in_lang => { lang = t.xml_content().map_err(|e| e.to_string())?.into_owned(); - }, + } Ok(Event::Text(t)) if in_keywords => { let raw = t.xml_content().map_err(|e| e.to_string())?; for tag in raw.split(',').map(str::trim).filter(|s| !s.is_empty()) { keywords.push(tag.to_string()); } - }, + } Ok(Event::Text(t)) if in_description => { let txt = t.xml_content().map_err(|e| e.to_string())?; if !txt.trim().is_empty() { @@ -186,7 +214,7 @@ pub fn parse(path: &Path) -> Result, String> { } description.push_str(&txt); } - }, + } Ok(Event::End(e)) => match e.name().as_ref() { b"book-title" => in_title = false, b"lang" => in_lang = false, @@ -201,15 +229,14 @@ pub fn parse(path: &Path) -> Result, String> { buf.clear(); } - Ok(vec![Book{ - id: Uuid::new_v4(), - title, - author: authors, - language: lang, - description, - tags: keywords, - published_at, - publisher, - updated: chrono::Utc::now().to_rfc3339(), - }]) + let mut book = Book::new(); + book.title = title; + book.author = authors; + book.language = lang; + book.description = description; + book.tags = keywords; + book.published_at = published_at; + book.publisher = publisher; + + Ok(vec![book]) } diff --git a/src/domain/book.rs b/src/domain/book.rs index 4ac5f04..4c938da 100644 --- a/src/domain/book.rs +++ b/src/domain/book.rs @@ -1,5 +1,6 @@ use crate::domain::author; use std::fmt; +use chrono::{DateTime, Utc}; use uuid::Uuid; #[derive(Clone, PartialEq, Eq)] @@ -12,7 +13,7 @@ pub struct Book { pub tags: Vec, pub published_at: String, pub publisher: String, - pub updated: String, + pub updated: DateTime, } impl Book { @@ -26,7 +27,7 @@ impl Book { tags: vec![], published_at: "".to_string(), publisher: "".to_string(), - updated: "".to_string(), + updated: chrono::Utc::now(), } } diff --git a/src/domain/feed.rs b/src/domain/feed.rs index 3eed4bb..2bbdd9c 100644 --- a/src/domain/feed.rs +++ b/src/domain/feed.rs @@ -90,7 +90,7 @@ impl From<&Book> for Entry { Entry{ title: book.title.clone(), id: book.id.to_string().clone(), - updated: book.updated.clone(), + updated: book.updated.to_rfc3339(), author: book.author.clone().into_iter().map(|a| a.into()).collect(), language: (!book.language.is_empty()).then(|| book.language.clone()), issued: (!book.published_at.is_empty()).then(|| book.published_at.clone()), diff --git a/src/infrastructure/repository/inmem/books.rs b/src/infrastructure/repository/inmem/books.rs index 29aa927..c998064 100644 --- a/src/infrastructure/repository/inmem/books.rs +++ b/src/infrastructure/repository/inmem/books.rs @@ -87,7 +87,7 @@ impl From for Book { tags: book.tags, published_at: book.published_at, publisher: book.publisher, - updated: book.updated, + updated: book.updated.to_rfc3339(), } } } @@ -113,7 +113,7 @@ impl Into for Book { tags: self.tags, published_at: self.published_at, publisher: self.publisher, - updated: self.updated, + updated: chrono::DateTime::parse_from_rfc3339(&self.updated).unwrap_or_default().to_utc(), } } }