From 64072f70b63b570c3f7724073ddf87dce1791437 Mon Sep 17 00:00:00 2001 From: red Date: Sat, 25 Apr 2020 18:34:45 +0200 Subject: [PATCH] added id filtering by id or hashstring --- Cargo.toml | 3 ++- examples/torrent-action.rs | 6 +++--- examples/torrent-get.rs | 21 ++++++++++++++++-- examples/torrent-remove.rs | 4 ++-- src/lib.rs | 12 ++++++----- src/types/mod.rs | 1 + src/types/request.rs | 44 ++++++++++++++++++++++++++++++-------- 7 files changed, 69 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1c3ffb9..96bfe24 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "transmission-rpc" -version = "0.2.0" +version = "0.2.1" authors = ["red "] edition = "2018" repository = "https://github.com/j0rsa/transmission-rpc" @@ -19,6 +19,7 @@ reqwest = { version = "0.10.4", features = ["json", "rustls-tls"] } tokio = { version = "0.2", features = ["macros"] } serde = { version = "1.0", features = ["derive"] } rustc-serialize = "0.3.24" +enum-iterator = "0.6.0" dotenv = "0.15.0" log = "0.4.8" diff --git a/examples/torrent-action.rs b/examples/torrent-action.rs index f625baf..2a4dffb 100644 --- a/examples/torrent-action.rs +++ b/examples/torrent-action.rs @@ -4,7 +4,7 @@ use std::env; use dotenv::dotenv; use transmission_rpc::TransClient; use transmission_rpc::types::{Result, RpcResponse, BasicAuth}; -use transmission_rpc::types::{TorrentAction, Nothing}; +use transmission_rpc::types::{TorrentAction, Nothing, Id}; #[tokio::main] async fn main() -> Result<()> { @@ -13,9 +13,9 @@ async fn main() -> Result<()> { let url= env::var("TURL")?; let basic_auth = BasicAuth{user: env::var("TUSER")?, password: env::var("TPWD")?}; let client = TransClient::with_auth(&url, basic_auth); - let res1: RpcResponse = client.torrent_action(TorrentAction::Start, vec![1]).await?; + let res1: RpcResponse = client.torrent_action(TorrentAction::Start, vec![Id::Id(1)]).await?; println!("Start result: {:?}", &res1.is_ok()); - let res2: RpcResponse = client.torrent_action(TorrentAction::Stop, vec![1]).await?; + let res2: RpcResponse = client.torrent_action(TorrentAction::Stop, vec![Id::Id(1)]).await?; println!("Stop result: {:?}", &res2.is_ok()); Ok(()) diff --git a/examples/torrent-get.rs b/examples/torrent-get.rs index cbb363f..aab9ec7 100644 --- a/examples/torrent-get.rs +++ b/examples/torrent-get.rs @@ -4,7 +4,7 @@ use std::env; use dotenv::dotenv; use transmission_rpc::TransClient; use transmission_rpc::types::{Result, RpcResponse, BasicAuth}; -use transmission_rpc::types::{Torrents, Torrent, TorrentGetField}; +use transmission_rpc::types::{Torrents, Torrent, TorrentGetField, Id}; #[tokio::main] async fn main() -> Result<()> { @@ -13,9 +13,26 @@ async fn main() -> Result<()> { let url= env::var("TURL")?; let basic_auth = BasicAuth{user: env::var("TUSER")?, password: env::var("TPWD")?}; let client = TransClient::with_auth(&url, basic_auth); - let res: RpcResponse> = client.torrent_get(vec![TorrentGetField::Id, TorrentGetField::Name]).await?; + + let res: RpcResponse> = client.torrent_get(None, None).await?; let names: Vec<&String> = res.arguments.torrents.iter().map(|it| it.name.as_ref().unwrap()).collect(); println!("{:#?}", names); + + let res1: RpcResponse> = client.torrent_get(Some(vec![TorrentGetField::Id, TorrentGetField::Name]), Some(vec![Id::Id(1), Id::Id(2), Id::Id(3)])).await?; + let first_three: Vec = res1.arguments.torrents.iter().map(|it| + format!("{}. {}",&it.id.as_ref().unwrap(), &it.name.as_ref().unwrap()) + ).collect(); + println!("{:#?}", first_three); + + + let res2: RpcResponse> = client.torrent_get(Some(vec![TorrentGetField::Id, TorrentGetField::HashString, TorrentGetField::Name]), Some(vec![Id::Hash(String::from("64b0d9a53ac9cd1002dad1e15522feddb00152fe"))])).await?; + let info: Vec = res2.arguments.torrents.iter().map(|it| + format!("{:5}. {:^45} {}", + &it.id.as_ref().unwrap(), + &it.hash_string.as_ref().unwrap(), + &it.name.as_ref().unwrap()) + ).collect(); + println!("{:#?}", info); Ok(()) } \ No newline at end of file diff --git a/examples/torrent-remove.rs b/examples/torrent-remove.rs index 831b206..083042b 100644 --- a/examples/torrent-remove.rs +++ b/examples/torrent-remove.rs @@ -4,7 +4,7 @@ use std::env; use dotenv::dotenv; use transmission_rpc::TransClient; use transmission_rpc::types::{Result, RpcResponse, BasicAuth}; -use transmission_rpc::types::{Nothing}; +use transmission_rpc::types::{Nothing, Id}; #[tokio::main] async fn main() -> Result<()> { @@ -13,7 +13,7 @@ async fn main() -> Result<()> { let url= env::var("TURL")?; let basic_auth = BasicAuth{user: env::var("TUSER")?, password: env::var("TPWD")?}; let client = TransClient::with_auth(&url, basic_auth); - let res: RpcResponse = client.torrent_remove(vec![1], false).await?; + let res: RpcResponse = client.torrent_remove(vec![Id::Id(1)], false).await?; println!("Remove result: {:?}", &res.is_ok()); Ok(()) diff --git a/src/lib.rs b/src/lib.rs index 4f1e2c5..4059010 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,7 @@ pub mod types; use types::BasicAuth; use types::{Result, RpcResponse, RpcResponseArgument, RpcRequest, Nothing}; use types::SessionGet; -use types::{TorrentGetField, Torrents, Torrent}; +use types::{TorrentGetField, Torrents, Torrent, Id}; use types::TorrentAction; use types::{TorrentAddArgs, TorrentAdded}; @@ -88,6 +88,8 @@ impl TransClient { } /// Performs a torrent get call + /// fileds - if None then ALL fields + /// ids - if None then All items /// /// # Errors /// @@ -96,8 +98,8 @@ impl TransClient { /// # Example /// /// in examples/torrent-get.rs - pub async fn torrent_get(&self, fields: Vec) -> Result>> { - self.call(RpcRequest::torrent_get(fields)).await + pub async fn torrent_get(&self, fields: Option>, ids: Option>) -> Result>> { + self.call(RpcRequest::torrent_get(fields, ids)).await } /// Performs a torrent action call @@ -109,7 +111,7 @@ impl TransClient { /// # Example /// /// in examples/torrent-action.rs - pub async fn torrent_action(&self, action: TorrentAction, ids: Vec) -> Result> { + pub async fn torrent_action(&self, action: TorrentAction, ids: Vec) -> Result> { self.call(RpcRequest::torrent_action(action, ids)).await } @@ -122,7 +124,7 @@ impl TransClient { /// # Example /// /// in examples/torrent-remove.rs - pub async fn torrent_remove(&self, ids: Vec, delete_local_data: bool) -> Result> { + pub async fn torrent_remove(&self, ids: Vec, delete_local_data: bool) -> Result> { self.call( RpcRequest::torrent_remove(ids, delete_local_data)).await } diff --git a/src/types/mod.rs b/src/types/mod.rs index da626d7..09d7a10 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -16,6 +16,7 @@ pub use self::request::TorrentGetField; pub use self::request::TorrentAction; pub use self::request::TorrentAddArgs; pub use self::request::File; +pub use self::request::Id; pub use self::response::RpcResponse; pub(crate) use self::response::RpcResponseArgument; diff --git a/src/types/request.rs b/src/types/request.rs index a8723e7..223bd6d 100644 --- a/src/types/request.rs +++ b/src/types/request.rs @@ -1,4 +1,5 @@ use serde::Serialize; +use enum_iterator::IntoEnumIterator; #[derive(Serialize, Debug, RustcEncodable)] pub struct RpcRequest { @@ -15,15 +16,15 @@ impl RpcRequest { } } - pub fn torrent_get(fields: Vec) -> RpcRequest { - let string_fields = fields.iter().map(|f| f.to_str()).collect(); + pub fn torrent_get(fields: Option>, ids: Option>) -> RpcRequest { + let string_fields = fields.unwrap_or(TorrentGetField::all()).iter().map(|f| f.to_str()).collect(); RpcRequest { method: String::from("torrent-get"), - arguments: Some ( Args::TorrentGetArgs(TorrentGetArgs { fields: Some(string_fields)} )), + arguments: Some ( Args::TorrentGetArgs(TorrentGetArgs { fields: Some(string_fields), ids } )), } } - pub fn torrent_remove(ids: Vec, delete_local_data: bool) -> RpcRequest { + pub fn torrent_remove(ids: Vec, delete_local_data: bool) -> RpcRequest { RpcRequest { method: String::from("torrent-remove"), arguments: Some ( Args::TorrentRemoveArgs(TorrentRemoveArgs {ids, delete_local_data} ) ) @@ -37,7 +38,7 @@ impl RpcRequest { } } - pub fn torrent_action(action: TorrentAction, ids: Vec) -> RpcRequest { + pub fn torrent_action(action: TorrentAction, ids: Vec) -> RpcRequest { RpcRequest { method: action.to_str(), arguments: Some ( Args::TorrentActionArgs(TorrentActionArgs { ids })), @@ -59,20 +60,39 @@ pub enum Args{ #[derive(Serialize, Debug, RustcEncodable, Clone)] pub struct TorrentGetArgs { #[serde(skip_serializing_if="Option::is_none")] - fields: Option> + fields: Option>, + #[serde(skip_serializing_if="Option::is_none")] + ids: Option>, +} + +impl Default for TorrentGetArgs { + fn default() -> Self { + let all_fields = TorrentGetField::into_enum_iter().map (|it| it.to_str()).collect(); + TorrentGetArgs { + fields: Some(all_fields), + ids: None + } + } } #[derive(Serialize, Debug, RustcEncodable, Clone)] pub struct TorrentActionArgs { - ids: Vec, + ids: Vec, } #[derive(Serialize, Debug, RustcEncodable, Clone)] pub struct TorrentRemoveArgs { - ids: Vec, + ids: Vec, #[serde(rename="delete-local-data")] delete_local_data: bool } +#[derive(Serialize, Debug, RustcEncodable, Clone)] +#[serde(untagged)] +pub enum Id { + Id(i64), + Hash(String) +} + #[derive(Serialize, Debug, RustcEncodable, Clone)] pub struct TorrentAddArgs { #[serde(skip_serializing_if="Option::is_none")] @@ -129,7 +149,7 @@ impl Default for TorrentAddArgs { pub struct File { //todo } - +#[derive(Clone, IntoEnumIterator)] pub enum TorrentGetField { Id, Addeddate, @@ -162,6 +182,12 @@ pub enum TorrentGetField { Webseedssendingtous, } +impl TorrentGetField { + pub fn all() -> Vec { + TorrentGetField::into_enum_iter().collect() + } +} + impl TorrentGetField { pub fn to_str(&self) -> String { match self {