Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More refurbishment #4

Merged
merged 7 commits into from
May 27, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ failure = "0.1.3"
log = "0.4.6"
md5 = "0.6.0"
rand = "0.6.1"
readonly = "0.2"
serde = "1.0.80"
serde_derive = "1.0.80"
serde_json = "1.0.33"
Expand Down
16 changes: 7 additions & 9 deletions src/client.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
use std::io::Read;
use std::iter;

use md5;
use media::NowPlaying;
use query::Query;
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use reqwest::Client as ReqwestClient;
use reqwest::Url;
use response::Response;
Expand Down Expand Up @@ -73,11 +78,6 @@ impl SubsonicAuth {
fn to_url(&self, ver: Version) -> String {
// First md5 support.
let auth = if ver >= "1.13.0".into() {
use std::iter;

use md5;
use rand::{distributions::Alphanumeric, thread_rng, Rng};

let mut rng = thread_rng();
let salt: String = iter::repeat(())
.map(|()| rng.sample(Alphanumeric))
Expand Down Expand Up @@ -205,15 +205,13 @@ impl Client {

/// Returns a response as a vector of bytes rather than serialising it.
pub(crate) fn get_bytes(&self, query: &str, args: Query) -> Result<Vec<u8>> {
use std::io::Read;
let uri: Url = self.build_url(query, args)?.parse().unwrap();
let res = self.reqclient.get(uri).send()?;
Ok(res.bytes().map(|b| b.unwrap()).collect())
}

/// Returns the raw bytes of a HLS slice.
pub fn hls_bytes(&self, hls: &Hls) -> Result<Vec<u8>> {
use std::io::Read;
let url: Url = self.url.join(&hls.url)?;
let res = self.reqclient.get(url).send()?;
Ok(res.bytes().map(|b| b.unwrap()).collect())
Expand Down Expand Up @@ -424,8 +422,8 @@ mod tests {
fn demo_scan_status() {
let cli = test_util::demo_site().unwrap();
let (status, n) = cli.scan_status().unwrap();
assert_eq!(status, false);
assert_eq!(n, 521);
xeals marked this conversation as resolved.
Show resolved Hide resolved
assert!(!status);
assert_eq!(n, 525);
}

#[test]
Expand Down
15 changes: 8 additions & 7 deletions src/collections/album.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,18 @@ impl IntoArg for ListType {
}

#[derive(Debug, Clone)]
#[readonly::make]
pub struct Album {
pub id: u64,
pub name: String,
pub artist: Option<String>,
artist_id: Option<u64>,
cover_id: Option<String>,
pub artist_id: Option<u64>,
pub cover_id: Option<String>,
pub duration: u64,
pub year: Option<u64>,
pub genre: Option<String>,
pub song_count: u64,
songs: Vec<Song>,
pub songs: Vec<Song>,
}

impl Album {
Expand Down Expand Up @@ -121,7 +122,7 @@ impl<'de> Deserialize<'de> for Album {
where
D: Deserializer<'de>,
{
#[derive(Debug, Deserialize)]
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct _Album {
id: String,
Expand All @@ -131,7 +132,7 @@ impl<'de> Deserialize<'de> for Album {
cover_art: Option<String>,
song_count: u64,
duration: u64,
created: String,
// created: String,
year: Option<u64>,
genre: Option<String>,
#[serde(default)]
Expand Down Expand Up @@ -252,8 +253,8 @@ mod tests {

#[test]
fn demo_get_albums() {
let mut srv = test_util::demo_site().unwrap();
let albums = get_albums(&mut srv, ListType::AlphaByArtist, None, None, None).unwrap();
let srv = test_util::demo_site().unwrap();
let albums = get_albums(&srv, ListType::AlphaByArtist, None, None, None).unwrap();

assert!(!albums.is_empty())
}
Expand Down
8 changes: 4 additions & 4 deletions src/collections/artist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,9 @@ mod tests {

#[test]
fn remote_artist_album_list() {
let mut srv = test_util::demo_site().unwrap();
let srv = test_util::demo_site().unwrap();
let parsed = serde_json::from_value::<Artist>(raw()).unwrap();
let albums = parsed.albums(&mut srv).unwrap();
let albums = parsed.albums(&srv).unwrap();

assert_eq!(albums[0].id, 1);
assert_eq!(albums[0].name, String::from("Bellevue"));
Expand All @@ -223,11 +223,11 @@ mod tests {

#[test]
fn remote_artist_cover_art() {
let mut srv = test_util::demo_site().unwrap();
let srv = test_util::demo_site().unwrap();
let parsed = serde_json::from_value::<Artist>(raw()).unwrap();
assert_eq!(parsed.cover_id, Some(String::from("ar-1")));

let cover = parsed.cover_art(&mut srv, None).unwrap();
let cover = parsed.cover_art(&srv, None).unwrap();
assert!(!cover.is_empty())
}

Expand Down
6 changes: 3 additions & 3 deletions src/collections/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ use std::result;

use serde::de::{Deserialize, Deserializer};

mod album;
mod artist;
mod playlist;
pub mod album;
pub mod artist;
pub mod playlist;

pub use self::album::{Album, AlbumInfo, ListType};
pub use self::artist::{Artist, ArtistInfo};
Expand Down
48 changes: 24 additions & 24 deletions src/collections/playlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ use serde_json;
use {Client, Error, Media, Result, Song};

#[derive(Debug)]
#[readonly::make]
pub struct Playlist {
id: u64,
name: String,
duration: u64,
cover_id: String,
song_count: u64,
songs: Vec<Song>,
pub id: u64,
pub name: String,
pub duration: u64,
pub cover_id: String,
pub song_count: u64,
pub songs: Vec<Song>,
}

impl Playlist {
Expand All @@ -31,18 +32,18 @@ impl<'de> Deserialize<'de> for Playlist {
where
D: Deserializer<'de>,
{
#[derive(Debug, Deserialize)]
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct _Playlist {
id: String,
name: String,
#[serde(default)]
comment: String,
owner: String,
// #[serde(default)]
// comment: String,
// owner: String,
song_count: u64,
duration: u64,
created: String,
changed: String,
// created: String,
// changed: String,
cover_art: String,
#[serde(default)]
songs: Vec<Song>,
Expand Down Expand Up @@ -85,12 +86,12 @@ impl Media for Playlist {
}
}

fn get_playlists(client: &Client, user: Option<String>) -> Result<Vec<Playlist>> {
pub fn get_playlists(client: &Client, user: Option<String>) -> Result<Vec<Playlist>> {
let playlist = client.get("getPlaylists", Query::with("username", user))?;
Ok(get_list_as!(playlist, Playlist))
}

fn get_playlist(client: &Client, id: u64) -> Result<Playlist> {
pub fn get_playlist(client: &Client, id: u64) -> Result<Playlist> {
let res = client.get("getPlaylist", Query::with("id", id))?;
Ok(serde_json::from_value::<Playlist>(res)?)
}
Expand All @@ -99,7 +100,7 @@ fn get_playlist(client: &Client, id: u64) -> Result<Playlist> {
///
/// Since API version 1.14.0, the newly created playlist is returned. In earlier
/// versions, an empty response is returned.
fn create_playlist(client: &Client, name: String, songs: &[u64]) -> Result<Option<Playlist>> {
pub fn create_playlist(client: &Client, name: String, songs: &[u64]) -> Result<Option<Playlist>> {
let args = Query::new()
.arg("name", name)
.arg_list("songId", songs)
Expand All @@ -116,7 +117,7 @@ fn create_playlist(client: &Client, name: String, songs: &[u64]) -> Result<Optio
}

/// Updates a playlist. Only the owner of the playlist is privileged to do so.
fn update_playlist<'a, B, S>(
pub fn update_playlist<'a, B, S>(
client: &Client,
id: u64,
name: S,
Expand All @@ -142,7 +143,7 @@ where
Ok(())
}

fn delete_playlist(client: &Client, id: u64) -> Result<()> {
pub fn delete_playlist(client: &Client, id: u64) -> Result<()> {
client.get("deletePlaylist", Query::with("id", id))?;
Ok(())
}
Expand All @@ -157,14 +158,13 @@ mod tests {
#[test]
fn remote_playlist_songs() {
let parsed = serde_json::from_value::<Playlist>(raw()).unwrap();
let mut srv = test_util::demo_site().unwrap();
let songs = parsed.songs(&mut srv);
let srv = test_util::demo_site().unwrap();
let songs = parsed.songs(&srv);

match songs {
Err(::error::Error::Api(::error::ApiError::NotAuthorized(_))) => assert!(true),
Err(e) => panic!("unexpected error: {}", e),
Ok(_) => panic!("test should have failed; insufficient privilege"),
}
assert!(matches!(
songs,
Err(::error::Error::Api(::error::ApiError::NotAuthorized(_)))
));
}

fn raw() -> serde_json::Value {
Expand Down
19 changes: 8 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
#![warn(missing_docs)]
#![doc(html_root_url = "https://docs.rs/sunk/0.1.2")]

woodruffw marked this conversation as resolved.
Show resolved Hide resolved
//! # sunk
//!
//! `sunk` provides natural Rust bindings to the [Subsonic] music server API.
Expand Down Expand Up @@ -118,16 +115,16 @@ mod macros;
mod client;
mod error;

mod collections;
mod media;
pub mod collections;
pub mod media;

mod annotate;
mod jukebox;
mod query;
mod response;
pub mod annotate;
pub mod jukebox;
pub mod query;
pub mod response;
pub mod search;
mod user;
mod version;
pub mod user;
pub mod version;

#[cfg(test)]
mod test_util;
Expand Down
27 changes: 16 additions & 11 deletions src/media/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,11 @@ impl HlsPlaylist {
self.hls.len()
}

/// Returns whether this playlist is empty.
pub fn is_empty(&self) -> bool {
self.hls.is_empty()
}

/// Returns the total duration of the playlist.
pub fn duration(&self) -> usize {
self.hls.iter().fold(0, |c, h| c + h.inc)
Expand Down Expand Up @@ -298,18 +303,18 @@ impl<'de> Deserialize<'de> for NowPlaying {
minutes_ago: usize,
player_id: usize,
id: String,
is_dir: bool,
title: String,
size: usize,
content_type: String,
suffix: String,
transcoded_content_type: Option<String>,
transcoded_suffix: Option<String>,
path: String,
// is_dir: bool,
// title: String,
// size: usize,
// content_type: String,
// suffix: String,
// transcoded_content_type: Option<String>,
// transcoded_suffix: Option<String>,
// path: String,
is_video: bool,
created: String,
#[serde(rename = "type")]
media_type: String,
// created: String,
// #[serde(rename = "type")]
// media_type: String,
}

let raw = _NowPlaying::deserialize(de)?;
Expand Down
Loading