refactor
This commit is contained in:
parent
87ad77907b
commit
db325e7700
12 changed files with 36 additions and 41 deletions
|
@ -65,7 +65,7 @@ impl ToAPI for Album {
|
||||||
json!({
|
json!({
|
||||||
"id": &self._id,
|
"id": &self._id,
|
||||||
"title": &self.title,
|
"title": &self.title,
|
||||||
"artist": self.artist_id.as_ref().map(|x| x.id()),
|
"artist": self.artist_id.as_ref().map(mongod::Reference::id),
|
||||||
"cover_url": if self.get_cover().await.is_some() {
|
"cover_url": if self.get_cover().await.is_some() {
|
||||||
Some(format!("/album/{}/cover", self._id))
|
Some(format!("/album/{}/cover", self._id))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,15 +5,15 @@ use serde::{Deserialize, Serialize};
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub struct AudioMetadata(pub serde_json::Value);
|
pub struct AudioMetadata(pub serde_json::Value);
|
||||||
|
|
||||||
impl Into<mongodb::bson::Bson> for AudioMetadata {
|
impl From<AudioMetadata> for mongodb::bson::Bson {
|
||||||
fn into(self) -> mongodb::bson::Bson {
|
fn from(val: AudioMetadata) -> Self {
|
||||||
mongodb::bson::to_bson(&self.0).unwrap()
|
mongodb::bson::to_bson(&val.0).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioMetadata {
|
impl AudioMetadata {
|
||||||
fn get_key(&self, key: &str) -> Option<&str> {
|
fn get_key(&self, key: &str) -> Option<&str> {
|
||||||
Some(self.0.as_object()?.get(key)?.as_str()?)
|
self.0.as_object()?.get(key)?.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn title(&self) -> Option<&str> {
|
pub fn title(&self) -> Option<&str> {
|
||||||
|
|
|
@ -31,7 +31,7 @@ pub struct Libary {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Libary {
|
impl Libary {
|
||||||
pub async fn new(root_dir: PathBuf) -> Self {
|
pub const fn new(root_dir: PathBuf) -> Self {
|
||||||
Self { root_dir }
|
Self { root_dir }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,9 +53,13 @@ impl Libary {
|
||||||
|
|
||||||
pub async fn add_path_to_library(&self, path: &str) {
|
pub async fn add_path_to_library(&self, path: &str) {
|
||||||
// search for path already present
|
// search for path already present
|
||||||
if let Some(_) = Track::find_one_partial(doc! { "path": path }, json!({})).await {
|
if Track::find_one_partial(doc! { "path": path }, json!({}))
|
||||||
|
.await
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("Adding {path} to library");
|
log::info!("Adding {path} to library");
|
||||||
|
|
||||||
// add track to library
|
// add track to library
|
||||||
|
@ -124,7 +128,7 @@ impl Libary {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Track::create(&entry.as_object().unwrap()).await;
|
Track::create(entry.as_object().unwrap()).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_artists(&self) -> Vec<Artist> {
|
pub async fn get_artists(&self) -> Vec<Artist> {
|
||||||
|
@ -164,8 +168,8 @@ impl Libary {
|
||||||
log::info!("Rescanning library");
|
log::info!("Rescanning library");
|
||||||
for entry in WalkDir::new(self.root_dir.clone())
|
for entry in WalkDir::new(self.root_dir.clone())
|
||||||
.follow_links(true)
|
.follow_links(true)
|
||||||
.into_iter() // todo : remove
|
.into_iter()
|
||||||
.filter_map(|e| e.ok())
|
.filter_map(std::result::Result::ok)
|
||||||
{
|
{
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if path.is_file() && is_music_file(path) {
|
if path.is_file() && is_music_file(path) {
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl Playlist {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub enum Visibility {
|
pub enum Visibility {
|
||||||
Private,
|
Private,
|
||||||
Public,
|
Public,
|
||||||
|
@ -67,7 +67,7 @@ impl ToAPI for Playlist {
|
||||||
"owner": self.owner.id(),
|
"owner": self.owner.id(),
|
||||||
"visibility": serde_json::to_value(&self.visibility).unwrap(),
|
"visibility": serde_json::to_value(&self.visibility).unwrap(),
|
||||||
"title": self.title,
|
"title": self.title,
|
||||||
"tracks": self.tracks.iter().map(|x| x.id()).collect::<Vec<_>>()
|
"tracks": self.tracks.iter().map(mongod::Reference::id).collect::<Vec<_>>()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ impl Track {
|
||||||
meta: data.get("meta").map(|x| AudioMetadata(x.clone())),
|
meta: data.get("meta").map(|x| AudioMetadata(x.clone())),
|
||||||
};
|
};
|
||||||
t.insert().await.unwrap();
|
t.insert().await.unwrap();
|
||||||
t.update(&serde_json::to_value(&data).unwrap())
|
t.update(&serde_json::to_value(data).unwrap())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -88,12 +88,12 @@ impl Track {
|
||||||
|
|
||||||
impl ToAPI for Track {
|
impl ToAPI for Track {
|
||||||
async fn api(&self) -> serde_json::Value {
|
async fn api(&self) -> serde_json::Value {
|
||||||
let (cover, album_title) = if let Some(album_ref) = &self.album_id {
|
let (cover, album_title, album_id) = if let Some(album_ref) = &self.album_id {
|
||||||
let album = album_ref.get::<Album>().await;
|
let album = album_ref.get::<Album>().await;
|
||||||
|
|
||||||
(album.get_cover().await.is_some(), album.title)
|
(album.get_cover().await.is_some(), album.title, album._id)
|
||||||
} else {
|
} else {
|
||||||
(false, String::new())
|
(false, String::new(), String::new())
|
||||||
};
|
};
|
||||||
|
|
||||||
let artist_title = if let Some(artist_ref) = &self.artist_id {
|
let artist_title = if let Some(artist_ref) = &self.artist_id {
|
||||||
|
@ -108,12 +108,12 @@ impl ToAPI for Track {
|
||||||
json!({
|
json!({
|
||||||
"id": self._id,
|
"id": self._id,
|
||||||
"title": self.title,
|
"title": self.title,
|
||||||
"track_number": self.meta.as_ref().map(|x| x.track_number()),
|
"track_number": self.meta.as_ref().map(super::metadata::AudioMetadata::track_number),
|
||||||
"meta": serde_json::to_value(&self.meta).unwrap(),
|
"meta": serde_json::to_value(&self.meta).unwrap(),
|
||||||
"album_id": self.album_id.as_ref().map(|x| x.id().to_string()),
|
"album_id": self.album_id.as_ref().map(|x| x.id().to_string()),
|
||||||
"album": album_title,
|
"album": album_title,
|
||||||
"cover": if cover {
|
"cover": if cover {
|
||||||
Some(format!("/album/{}/cover", self._id))
|
Some(format!("/album/{album_id}/cover"))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
|
|
@ -41,14 +41,14 @@ impl Validate for User {
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
pub async fn create(username: &str, password: &str, role: UserRole) -> Option<Self> {
|
pub async fn create(username: &str, password: &str, role: UserRole) -> Option<Self> {
|
||||||
if User::find_one_partial(doc! { "username": username }, json!({}))
|
if Self::find_one_partial(doc! { "username": username }, json!({}))
|
||||||
.await
|
.await
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let u = User {
|
let u = Self {
|
||||||
_id: uuid::Uuid::new_v4().to_string(),
|
_id: uuid::Uuid::new_v4().to_string(),
|
||||||
username: username.to_string(),
|
username: username.to_string(),
|
||||||
password: bcrypt::hash(password, bcrypt::DEFAULT_COST).unwrap(),
|
password: bcrypt::hash(password, bcrypt::DEFAULT_COST).unwrap(),
|
||||||
|
@ -61,7 +61,7 @@ impl User {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn login(username: &str, password: &str) -> Option<(Session, UserRole)> {
|
pub async fn login(username: &str, password: &str) -> Option<(Session, UserRole)> {
|
||||||
let u = User::find_one(doc! { "username": username }).await?;
|
let u = Self::find_one(doc! { "username": username }).await?;
|
||||||
|
|
||||||
if !u.verify_pw(password) {
|
if !u.verify_pw(password) {
|
||||||
return None;
|
return None;
|
||||||
|
@ -99,7 +99,7 @@ impl User {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_admin(&self) -> bool {
|
pub const fn is_admin(&self) -> bool {
|
||||||
matches!(self.role, UserRole::Admin)
|
matches!(self.role, UserRole::Admin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ async fn rocket() -> _ {
|
||||||
.to_cors()
|
.to_cors()
|
||||||
.expect("error creating CORS options");
|
.expect("error creating CORS options");
|
||||||
|
|
||||||
let lib = Libary::new("./media".into()).await;
|
let lib = Libary::new("./media".into());
|
||||||
|
|
||||||
lib.rescan().await;
|
lib.rescan().await;
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,9 @@ use std::cmp::Ordering;
|
||||||
use super::api_error;
|
use super::api_error;
|
||||||
use super::FallibleApiResponse;
|
use super::FallibleApiResponse;
|
||||||
use super::ToAPI;
|
use super::ToAPI;
|
||||||
use mongod::Referencable;
|
|
||||||
use mongodb::bson::doc;
|
use mongodb::bson::doc;
|
||||||
use rocket::fs::NamedFile;
|
use rocket::fs::NamedFile;
|
||||||
use rocket::*;
|
use rocket::{get, State};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::cache::RouteCache;
|
use crate::cache::RouteCache;
|
||||||
|
@ -69,17 +68,9 @@ pub async fn album_route(
|
||||||
.await
|
.await
|
||||||
.ok_or_else(|| api_error("No album with that ID found"))?;
|
.ok_or_else(|| api_error("No album with that ID found"))?;
|
||||||
|
|
||||||
let mut tracks = Album::get_tracks_of_album(&format!("album::{}", album._id))
|
let tracks = Album::get_tracks_of_album(&format!("album::{}", album._id)).await;
|
||||||
.await
|
|
||||||
.into_iter()
|
let mut tracks = to_api(&tracks).await;
|
||||||
.map(|x| {
|
|
||||||
json!({
|
|
||||||
"id": x.id(),
|
|
||||||
"title": x.title,
|
|
||||||
"tracknumber": x.meta.map(|x| x.track_number())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
tracks.sort_by(sort_by_tracknumber);
|
tracks.sort_by(sort_by_tracknumber);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use super::ToAPI;
|
||||||
use fs::NamedFile;
|
use fs::NamedFile;
|
||||||
use mongod::Model;
|
use mongod::Model;
|
||||||
use mongodb::bson::doc;
|
use mongodb::bson::doc;
|
||||||
use rocket::*;
|
use rocket::{fs, get, State};
|
||||||
|
|
||||||
use crate::cache::RouteCache;
|
use crate::cache::RouteCache;
|
||||||
use crate::library::artist::Artist;
|
use crate::library::artist::Artist;
|
||||||
|
|
|
@ -38,11 +38,11 @@ pub async fn to_api(albums: &[impl ToAPI]) -> Vec<serde_json::Value> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
pub async fn index_redir() -> Redirect {
|
pub fn index_redir() -> Redirect {
|
||||||
Redirect::to(uri!("/web"))
|
Redirect::to(uri!("/web"))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/manifest.json")]
|
#[get("/manifest.json")]
|
||||||
pub async fn manifest_redir() -> Redirect {
|
pub fn manifest_redir() -> Redirect {
|
||||||
Redirect::to(uri!("/web/manifest.json"))
|
Redirect::to(uri!("/web/manifest.json"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use super::FallibleApiResponse;
|
||||||
use super::ToAPI;
|
use super::ToAPI;
|
||||||
use fs::NamedFile;
|
use fs::NamedFile;
|
||||||
use mongodb::bson::doc;
|
use mongodb::bson::doc;
|
||||||
use rocket::*;
|
use rocket::{fs, get, State};
|
||||||
|
|
||||||
use crate::library::Libary;
|
use crate::library::Libary;
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ pub struct PasswdData {
|
||||||
pub async fn passwd_route(passwd: Json<PasswdData>, mut u: User) -> FallibleApiResponse {
|
pub async fn passwd_route(passwd: Json<PasswdData>, mut u: User) -> FallibleApiResponse {
|
||||||
u.passwd(&passwd.old, &passwd.new)
|
u.passwd(&passwd.old, &passwd.new)
|
||||||
.await
|
.await
|
||||||
.map_err(|_| api_error("Password change failed"))?;
|
.map_err(|()| api_error("Password change failed"))?;
|
||||||
|
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
"ok": 1
|
"ok": 1
|
||||||
|
|
Loading…
Reference in a new issue