Track media server songs list
This commit is contained in:
@ -1,2 +1,59 @@
|
||||
struct NavidromeBuilder {
|
||||
use crate::client::Navidrome;
|
||||
use std::error::Error;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
|
||||
pub struct NavidromeBuilder {
|
||||
base: Option<String>,
|
||||
token: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum NavidromeBuilderError {
|
||||
MissingParam,
|
||||
Reqwest(reqwest::Error),
|
||||
}
|
||||
|
||||
impl Display for NavidromeBuilderError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for NavidromeBuilderError {}
|
||||
|
||||
impl NavidromeBuilder {
|
||||
pub fn new() -> NavidromeBuilder {
|
||||
return NavidromeBuilder {
|
||||
base: None,
|
||||
token: None,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn base(&mut self, base: impl ToString) -> &mut NavidromeBuilder {
|
||||
self.base = Some(base.to_string());
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn token(&mut self, token: impl ToString) -> &mut NavidromeBuilder {
|
||||
self.token = Some(token.to_string());
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn build(&self) -> Result<Navidrome, NavidromeBuilderError> {
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.build()
|
||||
.map_err(|e| NavidromeBuilderError::Reqwest(e))?;
|
||||
|
||||
return Ok(Navidrome {
|
||||
base: self
|
||||
.base
|
||||
.clone()
|
||||
.ok_or(NavidromeBuilderError::MissingParam)?,
|
||||
http: client,
|
||||
token: self
|
||||
.token
|
||||
.clone()
|
||||
.ok_or(NavidromeBuilderError::MissingParam)?,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
22
navidrome/src/client/library.rs
Normal file
22
navidrome/src/client/library.rs
Normal file
@ -0,0 +1,22 @@
|
||||
use crate::client::{MediaResult as Result, Navidrome, QualifyPath};
|
||||
use crate::models::generic::Playlist;
|
||||
use crate::models::navidrome::{NavidromePlaylist, NavidromeTrack};
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
pub trait Library {
|
||||
async fn tracks(&self) -> Result<Vec<NavidromeTrack>>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Library for Navidrome {
|
||||
async fn tracks(&self) -> Result<Vec<NavidromeTrack>> {
|
||||
self.http
|
||||
.get(self.path("api/song"))
|
||||
.header("X-Nd-Authorization", format!("Bearer {}", self.token))
|
||||
.send()
|
||||
.await?
|
||||
.json::<Vec<NavidromeTrack>>()
|
||||
.await
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
pub mod builder;
|
||||
pub mod library;
|
||||
pub mod playlists;
|
||||
|
||||
trait QualifyPath {
|
||||
fn path(&self, path: &str) -> String;
|
||||
fn path(&self, path: impl Display) -> String;
|
||||
}
|
||||
|
||||
pub type MediaResult<U> = Result<U, reqwest::Error>;
|
||||
@ -14,7 +17,7 @@ pub struct Navidrome {
|
||||
}
|
||||
|
||||
impl QualifyPath for Navidrome {
|
||||
fn path(&self, path: &str) -> String {
|
||||
fn path(&self, path: impl Display) -> String {
|
||||
format!("{}/{}", self.base, path)
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
use crate::client::{MediaResult as Result, Navidrome, QualifyPath};
|
||||
use crate::models::generic::Playlist;
|
||||
use crate::models::navidrome::NavidromePlaylist;
|
||||
use crate::models::navidrome::{NavidromePlaylist, NavidromeTrack};
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
pub trait Playlists {
|
||||
async fn playlists(&self) -> Result<Vec<Playlist>>;
|
||||
async fn playlist(&self, id: String) -> Result<Playlist>;
|
||||
async fn tracks(&self, id: String) -> Result<Vec<NavidromeTrack>>;
|
||||
async fn create_playlist(&self) -> Result<Playlist>;
|
||||
async fn delete_playlist(&self) -> Result<()>;
|
||||
async fn update_playlists(&self) -> Result<()>;
|
||||
@ -26,7 +27,24 @@ impl Playlists for Navidrome {
|
||||
}
|
||||
|
||||
async fn playlist(&self, id: String) -> Result<Playlist> {
|
||||
todo!()
|
||||
self.http
|
||||
.get(self.path(format!("api/playlist/{}", id)))
|
||||
.header("X-Nd-Authorization", format!("Bearer {}", self.token))
|
||||
.send()
|
||||
.await?
|
||||
.json::<NavidromePlaylist>()
|
||||
.await
|
||||
.map(|pv| (&pv).into())
|
||||
}
|
||||
|
||||
async fn tracks(&self, id: String) -> Result<Vec<NavidromeTrack>> {
|
||||
self.http
|
||||
.get(self.path(format!("api/playlist/{}/tracks", id)))
|
||||
.header("X-Nd-Authorization", format!("Bearer {}", self.token))
|
||||
.send()
|
||||
.await?
|
||||
.json::<Vec<NavidromeTrack>>()
|
||||
.await
|
||||
}
|
||||
|
||||
async fn create_playlist(&self) -> Result<Playlist> {
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::models::generic::Playlist;
|
||||
use chrono::NaiveDateTime;
|
||||
use serde::Deserialize;
|
||||
use std::iter::Iterator;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct LoginResponse {
|
||||
@ -34,8 +33,6 @@ pub(crate) struct NavidromePlaylist {
|
||||
owner_id: String,
|
||||
#[serde(rename = "ownerName")]
|
||||
owner_name: String,
|
||||
#[serde(skip)] // todo fix
|
||||
rules: Option<NavidromePlaylistRule>,
|
||||
#[serde(rename = "songCount")]
|
||||
song_count: u64,
|
||||
sync: bool,
|
||||
@ -54,5 +51,20 @@ impl From<&NavidromePlaylist> for Playlist {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct NavidromePlaylistRule {}
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct NavidromeTrack {
|
||||
title: String,
|
||||
artist: String,
|
||||
#[serde(rename = "albumArtist")]
|
||||
album_artist: String,
|
||||
album: String,
|
||||
#[serde(rename = "albumId")]
|
||||
album_id: String,
|
||||
#[serde(rename = "artistId")]
|
||||
artist_id: String,
|
||||
id: String,
|
||||
#[serde(rename = "mbzTrackId")]
|
||||
pub musicbrainz_track_id: Option<String>,
|
||||
#[serde(rename = "mbzReleaseTrackId")]
|
||||
musicbrainz_release_track_id: Option<String>,
|
||||
}
|
||||
|
Reference in New Issue
Block a user