mirror of
https://github.com/kristoferssolo/transmission-rpc.git
synced 2025-10-21 20:10:37 +00:00
added transmission-{remove,add}
refactored request argument object
This commit is contained in:
parent
e27e3b2d04
commit
d17ee2cea8
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "transmission-rpc"
|
name = "transmission-rpc"
|
||||||
version = "0.1.1"
|
version = "0.2.0"
|
||||||
authors = ["red <red.avtovo@gmail.com>"]
|
authors = ["red <red.avtovo@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
repository = "https://github.com/j0rsa/transmission-rpc"
|
repository = "https://github.com/j0rsa/transmission-rpc"
|
||||||
|
|||||||
@ -16,8 +16,8 @@ spec: https://github.com/transmission/transmission/blob/master/extras/rpc-spec.t
|
|||||||
|
|
||||||
- [ ] torrent-set
|
- [ ] torrent-set
|
||||||
- [X] torrent-get
|
- [X] torrent-get
|
||||||
- [ ] torrent-add
|
- [X] torrent-add
|
||||||
- [ ] torrent-remove
|
- [X] torrent-remove
|
||||||
- [ ] torrent-set-location
|
- [ ] torrent-set-location
|
||||||
- [ ] torrent-rename-path
|
- [ ] torrent-rename-path
|
||||||
- [ ] session-set
|
- [ ] session-set
|
||||||
|
|||||||
25
examples/torrent-add.rs
Normal file
25
examples/torrent-add.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
extern crate transmission_rpc;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use dotenv::dotenv;
|
||||||
|
use transmission_rpc::TransClient;
|
||||||
|
use transmission_rpc::types::{Result, RpcResponse, BasicAuth};
|
||||||
|
use transmission_rpc::types::{TorrentAddArgs, TorrentAdded};
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
dotenv().ok();
|
||||||
|
env_logger::init();
|
||||||
|
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 add: TorrentAddArgs = TorrentAddArgs {
|
||||||
|
filename: Some("https://releases.ubuntu.com/20.04/ubuntu-20.04-desktop-amd64.iso.torrent".to_string()),
|
||||||
|
..TorrentAddArgs::default()
|
||||||
|
};
|
||||||
|
let res: RpcResponse<TorrentAdded> = client.torrent_add(add).await?;
|
||||||
|
println!("Add result: {:?}", &res.is_ok());
|
||||||
|
println!("response: {:?}", &res);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -16,5 +16,6 @@ async fn main() -> Result<()> {
|
|||||||
let res: RpcResponse<Torrents<Torrent>> = client.torrent_get(vec![TorrentGetField::Id, TorrentGetField::Name]).await?;
|
let res: RpcResponse<Torrents<Torrent>> = client.torrent_get(vec![TorrentGetField::Id, TorrentGetField::Name]).await?;
|
||||||
let names: Vec<&String> = res.arguments.torrents.iter().map(|it| it.name.as_ref().unwrap()).collect();
|
let names: Vec<&String> = res.arguments.torrents.iter().map(|it| it.name.as_ref().unwrap()).collect();
|
||||||
println!("{:#?}", names);
|
println!("{:#?}", names);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
20
examples/torrent-remove.rs
Normal file
20
examples/torrent-remove.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
extern crate transmission_rpc;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use dotenv::dotenv;
|
||||||
|
use transmission_rpc::TransClient;
|
||||||
|
use transmission_rpc::types::{Result, RpcResponse, BasicAuth};
|
||||||
|
use transmission_rpc::types::{Nothing};
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
dotenv().ok();
|
||||||
|
env_logger::init();
|
||||||
|
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<Nothing> = client.torrent_remove(vec![1], false).await?;
|
||||||
|
println!("Remove result: {:?}", &res.is_ok());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
54
src/lib.rs
54
src/lib.rs
@ -15,6 +15,7 @@ use types::{Result, RpcResponse, RpcResponseArgument, RpcRequest, Nothing};
|
|||||||
use types::SessionGet;
|
use types::SessionGet;
|
||||||
use types::{TorrentGetField, Torrents, Torrent};
|
use types::{TorrentGetField, Torrents, Torrent};
|
||||||
use types::TorrentAction;
|
use types::TorrentAction;
|
||||||
|
use types::{TorrentAddArgs, TorrentAdded};
|
||||||
|
|
||||||
pub struct TransClient {
|
pub struct TransClient {
|
||||||
url: String,
|
url: String,
|
||||||
@ -112,7 +113,36 @@ impl TransClient {
|
|||||||
self.call(RpcRequest::torrent_action(action, ids)).await
|
self.call(RpcRequest::torrent_action(action, ids)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs an JRPC call to the server
|
/// Performs a torrent remove call
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Any IO Error or Deserialization error
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// in examples/torrent-remove.rs
|
||||||
|
pub async fn torrent_remove(&self, ids: Vec<i64>, delete_local_data: bool) -> Result<RpcResponse<Nothing>> {
|
||||||
|
self.call( RpcRequest::torrent_remove(ids, delete_local_data)).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs a torrent add call
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
///
|
||||||
|
/// Any IO Error or Deserialization error
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// in examples/torrent-add.rs
|
||||||
|
pub async fn torrent_add(&self, add: TorrentAddArgs) -> Result<RpcResponse<TorrentAdded>> {
|
||||||
|
if add.metainfo == None && add.filename == None {
|
||||||
|
panic!("Metainfo or Filename should be provided")
|
||||||
|
}
|
||||||
|
self.call( RpcRequest::torrent_add(add)).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs a JRPC call to the server
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
@ -143,25 +173,3 @@ impl BodyString for reqwest::RequestBuilder {
|
|||||||
Ok(std::str::from_utf8(body)?.to_string())
|
Ok(std::str::from_utf8(body)?.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::Result;
|
|
||||||
use crate::{TransClient, BasicAuth, TorrentGetField};
|
|
||||||
use crate::{RpcResponse, Torrents, Torrent};
|
|
||||||
use std::env;
|
|
||||||
use dotenv::dotenv;
|
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn it_works() -> Result<()> {
|
|
||||||
dotenv().ok();
|
|
||||||
env_logger::init();
|
|
||||||
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<Torrents<Torrent>> = client.torrent_get(vec![TorrentGetField::Id, TorrentGetField::Name]).await?;
|
|
||||||
let names: Vec<&String> = res.arguments.torrents.iter().map(|it| it.name.as_ref().unwrap()).collect();
|
|
||||||
println!("{:#?}", names);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -14,10 +14,13 @@ pub(crate) use self::request::RpcRequest;
|
|||||||
pub use self::request::ArgumentFields;
|
pub use self::request::ArgumentFields;
|
||||||
pub use self::request::TorrentGetField;
|
pub use self::request::TorrentGetField;
|
||||||
pub use self::request::TorrentAction;
|
pub use self::request::TorrentAction;
|
||||||
|
pub use self::request::TorrentAddArgs;
|
||||||
|
pub use self::request::File;
|
||||||
|
|
||||||
pub use self::response::RpcResponse;
|
pub use self::response::RpcResponse;
|
||||||
pub(crate) use self::response::RpcResponseArgument;
|
pub(crate) use self::response::RpcResponseArgument;
|
||||||
pub use self::response::SessionGet;
|
pub use self::response::SessionGet;
|
||||||
pub use self::response::Torrents;
|
pub use self::response::Torrents;
|
||||||
pub use self::response::Torrent;
|
pub use self::response::Torrent;
|
||||||
|
pub use self::response::TorrentAdded;
|
||||||
pub use self::response::Nothing;
|
pub use self::response::Nothing;
|
||||||
@ -19,34 +19,122 @@ impl RpcRequest {
|
|||||||
let string_fields = fields.iter().map(|f| f.to_str()).collect();
|
let string_fields = fields.iter().map(|f| f.to_str()).collect();
|
||||||
RpcRequest {
|
RpcRequest {
|
||||||
method: String::from("torrent-get"),
|
method: String::from("torrent-get"),
|
||||||
arguments: Some (Args { fields: Some(string_fields), ids: None }),
|
arguments: Some ( Args::TorrentGetArgs(TorrentGetArgs { fields: Some(string_fields)} )),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn torrent_remove(ids: Vec<i64>, delete_local_data: bool) -> RpcRequest {
|
||||||
|
RpcRequest {
|
||||||
|
method: String::from("torrent-remove"),
|
||||||
|
arguments: Some ( Args::TorrentRemoveArgs(TorrentRemoveArgs {ids, delete_local_data} ) )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn torrent_add(add: TorrentAddArgs) -> RpcRequest {
|
||||||
|
RpcRequest {
|
||||||
|
method: String::from("torrent-add"),
|
||||||
|
arguments: Some ( Args::TorrentAddArgs(add) )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn torrent_action(action: TorrentAction, ids: Vec<i64>) -> RpcRequest {
|
pub fn torrent_action(action: TorrentAction, ids: Vec<i64>) -> RpcRequest {
|
||||||
RpcRequest {
|
RpcRequest {
|
||||||
method: action.to_str(),
|
method: action.to_str(),
|
||||||
arguments: Some (Args { fields: None, ids: Some(ids) }),
|
arguments: Some ( Args::TorrentActionArgs(TorrentActionArgs { ids })),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub trait ArgumentFields {}
|
||||||
|
impl ArgumentFields for TorrentGetField{}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, RustcEncodable, Clone)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Args{
|
||||||
|
TorrentGetArgs(TorrentGetArgs),
|
||||||
|
TorrentActionArgs(TorrentActionArgs),
|
||||||
|
TorrentRemoveArgs(TorrentRemoveArgs),
|
||||||
|
TorrentAddArgs(TorrentAddArgs),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, RustcEncodable, Clone)]
|
||||||
|
pub struct TorrentGetArgs {
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
fields: Option<Vec<String>>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, RustcEncodable, Clone)]
|
||||||
|
pub struct TorrentActionArgs {
|
||||||
|
ids: Vec<i64>,
|
||||||
|
}
|
||||||
|
#[derive(Serialize, Debug, RustcEncodable, Clone)]
|
||||||
|
pub struct TorrentRemoveArgs {
|
||||||
|
ids: Vec<i64>,
|
||||||
|
#[serde(rename="delete-local-data")]
|
||||||
|
delete_local_data: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, RustcEncodable, Clone)]
|
||||||
|
pub struct TorrentAddArgs {
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
pub cookies: Option<String>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none", rename="download-dir")]
|
||||||
|
pub download_dir: Option<String>,
|
||||||
|
/// Either "filename" OR "metainfo" MUST be included
|
||||||
|
/// semi-optional
|
||||||
|
/// filename or URL of the .torrent file
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
pub filename: Option<String>,
|
||||||
|
/// semi-optional
|
||||||
|
/// base64-encoded .torrent content
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
pub metainfo: Option<String>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
pub paused: Option<bool>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none", rename="peer-limit")]
|
||||||
|
pub peer_limit: Option<i64>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none", rename="bandwidthPriority")]
|
||||||
|
pub bandwidth_priority: Option<i64>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none", rename="files-wanted")]
|
||||||
|
pub files_wanted: Option<Vec<File>>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none", rename="files-unwanted")]
|
||||||
|
pub files_unwanted: Option<Vec<File>>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none", rename="priority-high")]
|
||||||
|
pub priority_high: Option<Vec<File>>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none", rename="priority-low")]
|
||||||
|
pub priority_low: Option<Vec<File>>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none", rename="priority-normal")]
|
||||||
|
pub priority_normal: Option<Vec<File>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TorrentAddArgs {
|
||||||
|
fn default() -> Self {
|
||||||
|
TorrentAddArgs {
|
||||||
|
cookies: None,
|
||||||
|
download_dir: None,
|
||||||
|
filename: None,
|
||||||
|
metainfo: None,
|
||||||
|
paused: None,
|
||||||
|
peer_limit: None,
|
||||||
|
bandwidth_priority: None,
|
||||||
|
files_wanted: None,
|
||||||
|
files_unwanted: None,
|
||||||
|
priority_high: None,
|
||||||
|
priority_low: None,
|
||||||
|
priority_normal: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, RustcEncodable, Clone)]
|
||||||
pub trait ArgumentFields {}
|
pub struct File {
|
||||||
impl ArgumentFields for TorrentGetField{}
|
//todo
|
||||||
|
|
||||||
#[derive(Serialize, Debug, RustcEncodable)]
|
|
||||||
struct Args {
|
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
|
||||||
fields: Option<Vec<String>>,
|
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
|
||||||
ids: Option<Vec<i64>>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum TorrentGetField {
|
pub enum TorrentGetField {
|
||||||
Id,
|
Id,
|
||||||
Addeddate,
|
Addeddate,
|
||||||
Name,
|
Name,
|
||||||
|
HashString,
|
||||||
Totalsize,
|
Totalsize,
|
||||||
Error,
|
Error,
|
||||||
Errorstring,
|
Errorstring,
|
||||||
@ -80,6 +168,7 @@ impl TorrentGetField {
|
|||||||
TorrentGetField::Id => "id",
|
TorrentGetField::Id => "id",
|
||||||
TorrentGetField::Addeddate => "addedDate",
|
TorrentGetField::Addeddate => "addedDate",
|
||||||
TorrentGetField::Name => "name",
|
TorrentGetField::Name => "name",
|
||||||
|
TorrentGetField::HashString => "hashString",
|
||||||
TorrentGetField::Totalsize => "totalSize",
|
TorrentGetField::Totalsize => "totalSize",
|
||||||
TorrentGetField::Error => "error",
|
TorrentGetField::Error => "error",
|
||||||
TorrentGetField::Errorstring => "errorString",
|
TorrentGetField::Errorstring => "errorString",
|
||||||
|
|||||||
@ -27,7 +27,7 @@ pub struct SessionGet {
|
|||||||
}
|
}
|
||||||
impl RpcResponseArgument for SessionGet{}
|
impl RpcResponseArgument for SessionGet{}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug, RustcEncodable)]
|
||||||
pub struct Torrent {
|
pub struct Torrent {
|
||||||
#[serde(rename="addedDate")]
|
#[serde(rename="addedDate")]
|
||||||
pub added_date: Option<i64>,
|
pub added_date: Option<i64>,
|
||||||
@ -47,6 +47,8 @@ pub struct Torrent {
|
|||||||
#[serde(rename="metadataPercentComplete")]
|
#[serde(rename="metadataPercentComplete")]
|
||||||
pub metadata_percent_complete: Option<f32>,
|
pub metadata_percent_complete: Option<f32>,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
|
#[serde(rename="hashString")]
|
||||||
|
pub hash_string: Option<String>,
|
||||||
#[serde(rename="peersConnected")]
|
#[serde(rename="peersConnected")]
|
||||||
pub peers_connected: Option<i64>,
|
pub peers_connected: Option<i64>,
|
||||||
#[serde(rename="peersGettingFromUs")]
|
#[serde(rename="peersGettingFromUs")]
|
||||||
@ -74,12 +76,12 @@ pub struct Torrent {
|
|||||||
#[serde(rename="uploadedEver")]
|
#[serde(rename="uploadedEver")]
|
||||||
pub uploaded_ever: Option<i64>,
|
pub uploaded_ever: Option<i64>,
|
||||||
}
|
}
|
||||||
impl RpcResponseArgument for Torrents<Torrent>{}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, RustcEncodable)]
|
#[derive(Deserialize, Debug, RustcEncodable)]
|
||||||
pub struct Torrents<T> {
|
pub struct Torrents<T> {
|
||||||
pub torrents: Vec<T>
|
pub torrents: Vec<T>
|
||||||
}
|
}
|
||||||
|
impl RpcResponseArgument for Torrents<Torrent>{}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, RustcEncodable)]
|
#[derive(Deserialize, Debug, RustcEncodable)]
|
||||||
pub struct Trackers {
|
pub struct Trackers {
|
||||||
@ -90,3 +92,10 @@ pub struct Trackers {
|
|||||||
#[derive(Deserialize, Debug, RustcEncodable)]
|
#[derive(Deserialize, Debug, RustcEncodable)]
|
||||||
pub struct Nothing{}
|
pub struct Nothing{}
|
||||||
impl RpcResponseArgument for Nothing {}
|
impl RpcResponseArgument for Nothing {}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, RustcEncodable)]
|
||||||
|
pub struct TorrentAdded {
|
||||||
|
#[serde(rename="torrent-added")]
|
||||||
|
pub torrent_added: Torrent
|
||||||
|
}
|
||||||
|
impl RpcResponseArgument for TorrentAdded{}
|
||||||
Loading…
Reference in New Issue
Block a user