use std::cmp::Ordering; use mongodb::bson::doc; use rocket::*; use serde_json::json; use rocket::fs::NamedFile; use mongod::Referencable; use super::FallibleApiResponse; use super::api_error; use crate::library::Libary; #[get("/artist//albums")] pub async fn albums_route(artist_id: &str, lib: &State) -> FallibleApiResponse { let albums = lib.get_albums_by_artist(artist_id).await; Ok(json!({ "artist": artist_id, "albums": &albums })) } fn sort_by_tracknumber(a: &serde_json::Value, b: &serde_json::Value) -> Ordering { a.get("tracknumber") .unwrap() .as_i64() .unwrap() .cmp(&b.get("tracknumber").unwrap().as_i64().unwrap()) } #[get("/album//cover")] pub async fn album_cover_route(album_id: &str, lib: &State) -> Option { let album = lib.get_album_by_id(album_id).await?; let track_path = lib .get_tracks_of_album(&format!("album::{}", album._id)) .await .first()? .path .clone(); let track_path = std::path::Path::new(&track_path); for ext in ["png", "jpg", "jpeg", "avif"] { let cover_file = track_path.parent()?.join(format!("cover.{ext}")); if cover_file.exists() { return NamedFile::open(cover_file).await.ok(); } } None } #[get("/album/")] pub async fn album_route(album_id: &str, lib: &State) -> FallibleApiResponse { let album = lib .get_album_by_id(album_id) .await .ok_or_else(|| api_error("No album with that ID found"))?; let mut tracks = lib .get_tracks_of_album(&format!("album::{}", album._id)) .await .into_iter() .map(|x| { json!({ "id": x.id(), "title": x.title, "tracknumber": x.meta.map(|x| x.track_number()) }) }) .collect::>(); tracks.sort_by(sort_by_tracknumber); let mut album = serde_json::to_value(album).unwrap(); album .as_object_mut() .unwrap() .insert("tracks".into(), tracks.into()); Ok(album) }