From 5781d4cbe5f1cc6a64f41717c738399635751c2e Mon Sep 17 00:00:00 2001 From: Antoine Gersant Date: Sun, 7 May 2017 23:32:37 -0700 Subject: [PATCH] Added support for fetching recently added albums --- src/api.rs | 16 +++++++++++++++ src/collection.rs | 4 ++++ src/errors.rs | 2 ++ src/index.rs | 52 +++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/api.rs b/src/api.rs index fc46e2e..23f9230 100644 --- a/src/api.rs +++ b/src/api.rs @@ -66,6 +66,12 @@ pub fn get_api_handler(collection: Arc) -> Mount { self::random(request, collection.deref()) }); } + { + let collection = collection.clone(); + auth_api_mount.mount("/recent/", move |request: &mut Request| { + self::recent(request, collection.deref()) + }); + } { let collection = collection.clone(); auth_api_mount.mount("/serve/", move |request: &mut Request| { @@ -225,6 +231,16 @@ fn random(_: &mut Request, collection: &Collection) -> IronResult { Ok(Response::with((status::Ok, result_json))) } +fn recent(_: &mut Request, collection: &Collection) -> IronResult { + let recent_result = collection.get_recent_albums(20)?; + let result_json = json::encode(&recent_result); + let result_json = match result_json { + Ok(j) => j, + Err(e) => return Err(IronError::new(e, status::InternalServerError)), + }; + Ok(Response::with((status::Ok, result_json))) +} + fn serve(request: &mut Request, collection: &Collection) -> IronResult { let virtual_path = path_from_request(request); let virtual_path = match virtual_path { diff --git a/src/collection.rs b/src/collection.rs index 09c2848..be762eb 100644 --- a/src/collection.rs +++ b/src/collection.rs @@ -62,6 +62,10 @@ impl Collection { self.index.deref().get_random_albums(count) } + pub fn get_recent_albums(&self, count: u32) -> Result> { + self.index.deref().get_recent_albums(count) + } + pub fn locate(&self, virtual_path: &Path) -> Result { self.vfs.virtual_to_real(virtual_path) } diff --git a/src/errors.rs b/src/errors.rs index 9161b3b..60aac6a 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -20,6 +20,7 @@ error_chain! { Id3(id3::Error); Image(image::ImageError); Io(std::io::Error); + Time(std::time::SystemTimeError); Regex(regex::Error); SQLite(sqlite::Error); Vorbis(lewton::VorbisError); @@ -32,6 +33,7 @@ error_chain! { IncorrectCredentials {} CannotServeDirectory {} UnsupportedFileType {} + MissingIndexVersion {} } } diff --git a/src/index.rs b/src/index.rs index ce5c56f..c313337 100644 --- a/src/index.rs +++ b/src/index.rs @@ -102,7 +102,7 @@ impl<'db> IndexBuilder<'db> { queue: queue, db: db, insert_directory: db.prepare("INSERT OR REPLACE INTO directories (path, parent, artwork, year, \ - artist, album) VALUES (?, ?, ?, ?, ?, ?)")?, + artist, album, date_added) VALUES (?, ?, ?, ?, ?, ?, ?)")?, insert_song: db.prepare("INSERT OR REPLACE INTO songs (path, parent, disc_number, track_number, \ title, year, album_artist, artist, album, artwork) VALUES (?, ?, ?, ?, \ ?, ?, ?, ?, ?, ?)")?, @@ -126,6 +126,13 @@ impl<'db> IndexBuilder<'db> { // Insert directory CollectionFile::Directory(directory) => { + + let metadata = fs::metadata(directory.path.as_str())?; + let created = metadata + .created()? + .duration_since(time::UNIX_EPOCH)? + .as_secs(); + let parent = IndexBuilder::get_parent(directory.path.as_str()); self.insert_directory.reset()?; self.insert_directory @@ -140,6 +147,8 @@ impl<'db> IndexBuilder<'db> { .bind(5, &string_option_to_value(directory.artist))?; self.insert_directory .bind(6, &string_option_to_value(directory.album))?; + self.insert_directory + .bind(7, &Value::Integer(created as i64))?; self.insert_directory.next()?; } @@ -198,11 +207,10 @@ impl Index { sleep_duration: config.sleep_duration, }; - if path.exists() { - // Migration - } else { + if !path.exists() { index.init()?; } + index.migrate()?; Ok(index) } @@ -260,6 +268,34 @@ impl Index { Ok(()) } + fn migrate(&self) -> Result<()> { + let version = self.read_version()?; + if version < 2 { + println!("Migrating Index from version: {}", version); + self.migrate_to_version2()? + } + Ok(()) + } + + fn read_version(&self) -> Result { + let db = self.connect()?; + let mut select = db.prepare("SELECT MAX(number) FROM version")?; + if let Ok(State::Row) = select.next() { + let version = select.read(0)?; + return Ok(version); + } + Err(Error::from(ErrorKind::MissingIndexVersion).into()) + } + + fn migrate_to_version2(&self) -> Result<()> { + let db = self.connect()?; + db.execute("BEGIN TRANSACTION")?; + db.execute("ALTER TABLE directories ADD COLUMN date_added INTEGER DEFAULT 0 NOT NULL")?; + db.execute("UPDATE version SET number = 2")?; + db.execute("END TRANSACTION")?; + Ok(()) + } + fn connect(&self) -> Result { let mut db = sqlite::open(self.path.clone())?; db.set_busy_timeout(INDEX_LOCK_TIMEOUT)?; @@ -617,6 +653,14 @@ impl Index { select.bind(1, &Value::Integer(count as i64))?; self.select_directories(&mut select) } + + pub fn get_recent_albums(&self, count: u32) -> Result> { + let db = self.connect()?; + let mut select = db.prepare("SELECT path, artwork, year, artist, album FROM directories WHERE album \ + IS NOT NULL ORDER BY date_added DESC LIMIT ?")?; + select.bind(1, &Value::Integer(count as i64))?; + self.select_directories(&mut select) + } } fn _get_test_index(name: &str) -> Index {