mirror of
https://github.com/kristoferssolo/transmission-rpc.git
synced 2025-10-21 20:10:37 +00:00
added torrent-get
This commit is contained in:
parent
4a9077b95f
commit
0083488ddb
@ -5,7 +5,7 @@ spec: https://github.com/transmission/transmission/blob/master/extras/rpc-spec.t
|
|||||||
Supported Methods:
|
Supported Methods:
|
||||||
|
|
||||||
- [ ] torrent-set
|
- [ ] torrent-set
|
||||||
- [ ] torrent-get
|
- [X] torrent-get
|
||||||
- [ ] torrent-add
|
- [ ] torrent-add
|
||||||
- [ ] torrent-remove
|
- [ ] torrent-remove
|
||||||
- [ ] torrent-set-location
|
- [ ] torrent-set-location
|
||||||
|
|||||||
@ -3,7 +3,7 @@ extern crate transmission_rpc;
|
|||||||
use std::env;
|
use std::env;
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
use transmission_rpc::TransClient;
|
use transmission_rpc::TransClient;
|
||||||
use transmission_rpc::types::{Result, RpcResponse, SessionInfo, BasicAuth};
|
use transmission_rpc::types::{Result, RpcResponse, SessionGet, BasicAuth};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
@ -12,10 +12,11 @@ async fn main() -> Result<()> {
|
|||||||
let url= env::var("TURL")?;
|
let url= env::var("TURL")?;
|
||||||
let basic_auth = BasicAuth{user: env::var("TUSER")?, password: env::var("TPWD")?};
|
let basic_auth = BasicAuth{user: env::var("TUSER")?, password: env::var("TPWD")?};
|
||||||
let client = TransClient::with_auth(&url, basic_auth);
|
let client = TransClient::with_auth(&url, basic_auth);
|
||||||
let response: Result<RpcResponse<SessionInfo>> = client.session_get().await;
|
let response: Result<RpcResponse<SessionGet>> = client.session_get().await;
|
||||||
match response {
|
match response {
|
||||||
Ok(_) => println!("Yay!"),
|
Ok(_) => println!("Yay!"),
|
||||||
Err(_) => panic!("Oh no!")
|
Err(_) => panic!("Oh no!")
|
||||||
}
|
}
|
||||||
|
println!("Rpc reqsponse is ok: {}", response?.is_ok());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
20
examples/torrent-get.rs
Normal file
20
examples/torrent-get.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::{Torrents, Torrent, TorrentGetField};
|
||||||
|
|
||||||
|
#[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<Torrents<Torrent>> = client.torrent_get(vec![TorrentGetField::ID, TorrentGetField::NAME]).await?;
|
||||||
|
let names: Vec<&String> = res.arguments.torrents.iter().map(|it| it.clone().name.as_ref().unwrap()).collect();
|
||||||
|
println!("{:#?}", names);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
BIN
src/.DS_Store
vendored
Normal file
BIN
src/.DS_Store
vendored
Normal file
Binary file not shown.
33
src/lib.rs
33
src/lib.rs
@ -10,13 +10,14 @@ extern crate log;
|
|||||||
extern crate reqwest;
|
extern crate reqwest;
|
||||||
extern crate tokio_postgres;
|
extern crate tokio_postgres;
|
||||||
|
|
||||||
use serde::Serialize;
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use reqwest::header::CONTENT_TYPE;
|
use reqwest::header::CONTENT_TYPE;
|
||||||
|
|
||||||
pub mod types;
|
pub mod types;
|
||||||
use types::{Result, RpcRequestArgument, RpcResponse, RpcResponseArgument, SessionGet, SessionInfo};
|
|
||||||
use types::BasicAuth;
|
use types::BasicAuth;
|
||||||
|
use types::{Result, RpcResponse, RpcResponseArgument, RpcRequest};
|
||||||
|
use types::SessionGet;
|
||||||
|
use types::{TorrentGetField, Torrents, Torrent};
|
||||||
|
|
||||||
pub struct TransClient {
|
pub struct TransClient {
|
||||||
url: String,
|
url: String,
|
||||||
@ -52,7 +53,7 @@ impl TransClient {
|
|||||||
async fn get_session_id(&self) -> String {
|
async fn get_session_id(&self) -> String {
|
||||||
info!("Requesting session id info");
|
info!("Requesting session id info");
|
||||||
let response: reqwest::Response = self.rpc_request()
|
let response: reqwest::Response = self.rpc_request()
|
||||||
.json(&SessionGet::new())
|
.json(&RpcRequest::session_get())
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -67,15 +68,16 @@ impl TransClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn session_get(&self) -> Result<RpcResponse<SessionInfo>> {
|
pub async fn session_get(&self) -> Result<RpcResponse<SessionGet>> {
|
||||||
self.call(SessionGet::new()).await
|
self.call(RpcRequest::session_get()).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn torrent_get(&self) -> Result<RpcResponse<>>{}
|
pub async fn torrent_get(&self, fields: Vec<TorrentGetField>) -> Result<RpcResponse<Torrents<Torrent>>> {
|
||||||
|
self.call(RpcRequest::torrent_get(fields)).await
|
||||||
|
}
|
||||||
|
|
||||||
async fn call<T, U> (&self, request: T) -> Result<RpcResponse<U>>
|
async fn call<RS> (&self, request: RpcRequest) -> Result<RpcResponse<RS>>
|
||||||
where T : RpcRequestArgument + Serialize,
|
where RS : RpcResponseArgument + DeserializeOwned + std::fmt::Debug
|
||||||
U : RpcResponseArgument + DeserializeOwned + std::fmt::Debug
|
|
||||||
{
|
{
|
||||||
info!("Loaded auth: {:?}", &self.auth);
|
info!("Loaded auth: {:?}", &self.auth);
|
||||||
let rq: reqwest::RequestBuilder = self.rpc_request()
|
let rq: reqwest::RequestBuilder = self.rpc_request()
|
||||||
@ -83,9 +85,8 @@ impl TransClient {
|
|||||||
.json(&request);
|
.json(&request);
|
||||||
info!("Request body: {:?}", rq.try_clone().unwrap().body_string()?);
|
info!("Request body: {:?}", rq.try_clone().unwrap().body_string()?);
|
||||||
let resp: reqwest::Response = rq.send().await?;
|
let resp: reqwest::Response = rq.send().await?;
|
||||||
// print!("{:?}", resp.text().await);
|
let rpc_response: RpcResponse<RS> = resp.json().await?;
|
||||||
let rpc_response: RpcResponse<U> = resp.json().await?;
|
info!("Response body: {:#?}", rpc_response);
|
||||||
info!("{:#?}", rpc_response);
|
|
||||||
Ok(rpc_response)
|
Ok(rpc_response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,7 +106,8 @@ impl BodyString for reqwest::RequestBuilder {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use crate::{TransClient, BasicAuth};
|
use crate::{TransClient, BasicAuth, TorrentGetField};
|
||||||
|
use crate::{RpcResponse, Torrents, Torrent};
|
||||||
use std::env;
|
use std::env;
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
|
|
||||||
@ -115,7 +117,10 @@ mod tests {
|
|||||||
env_logger::init();
|
env_logger::init();
|
||||||
let url= env::var("TURL")?;
|
let url= env::var("TURL")?;
|
||||||
let basic_auth = BasicAuth{user: env::var("TUSER")?, password: env::var("TPWD")?};
|
let basic_auth = BasicAuth{user: env::var("TUSER")?, password: env::var("TPWD")?};
|
||||||
TransClient::with_auth(&url, basic_auth).session_get().await;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,10 +10,12 @@ pub struct BasicAuth {
|
|||||||
pub password: String,
|
pub password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) use self::request::RpcRequestArgument;
|
pub(crate) use self::request::RpcRequest;
|
||||||
pub(crate) use self::request::SessionGet;
|
pub use self::request::ArgumentFields;
|
||||||
|
pub use self::request::TorrentGetField;
|
||||||
|
|
||||||
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::SessionInfo;
|
pub use self::response::SessionGet;
|
||||||
|
pub use self::response::Torrents;
|
||||||
|
pub use self::response::Torrent;
|
||||||
@ -1,16 +1,105 @@
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Serialize, Debug, RustcEncodable)]
|
#[derive(Serialize, Debug, RustcEncodable)]
|
||||||
pub struct SessionGet {
|
pub struct RpcRequest {
|
||||||
method: String
|
method: String,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
arguments: Option<Fields<String>>,
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
ids: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SessionGet{
|
impl RpcRequest {
|
||||||
pub fn new() -> SessionGet {
|
pub fn session_get() -> RpcRequest {
|
||||||
SessionGet { method: String::from("session-get") }
|
RpcRequest {
|
||||||
|
method: String::from("session-get"),
|
||||||
|
arguments: None,
|
||||||
|
ids: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn torrent_get(fields: Vec<TorrentGetField>) -> RpcRequest {
|
||||||
|
let string_fields = fields.iter().map(|f| f.to_str()).collect();
|
||||||
|
RpcRequest {
|
||||||
|
method: String::from("torrent-get"),
|
||||||
|
arguments: Some (Fields { fields: string_fields }),
|
||||||
|
ids: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub trait ArgumentFields {}
|
||||||
|
impl ArgumentFields for TorrentGetField{}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, RustcEncodable)]
|
||||||
|
struct Fields<T> {
|
||||||
|
fields: Vec<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TorrentGetField {
|
||||||
|
ID,
|
||||||
|
ADDEDDATE,
|
||||||
|
NAME,
|
||||||
|
TOTALSIZE,
|
||||||
|
ERROR,
|
||||||
|
ERRORSTRING,
|
||||||
|
ETA,
|
||||||
|
ISFINISHED,
|
||||||
|
ISSTALLED,
|
||||||
|
LEFTUNTILDONE,
|
||||||
|
METADATAPERCENTCOMPLETE,
|
||||||
|
PEERSCONNECTED,
|
||||||
|
PEERSGETTINGFROMUS,
|
||||||
|
PEERSSENDINGTOUS,
|
||||||
|
PERCENTDONE,
|
||||||
|
QUEUEPOSITION,
|
||||||
|
RATEDOWNLOAD,
|
||||||
|
RATEUPLOAD,
|
||||||
|
RECHECKPROGRESS,
|
||||||
|
SEEDRATIOMODE,
|
||||||
|
SEEDRATIOLIMIT,
|
||||||
|
SIZEWHENDONE,
|
||||||
|
STATUS,
|
||||||
|
TRACKERS,
|
||||||
|
DOWNLOADDIR,
|
||||||
|
UPLOADEDEVER,
|
||||||
|
UPLOADRATIO,
|
||||||
|
WEBSEEDSSENDINGTOUS,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TorrentGetField {
|
||||||
|
pub fn to_str(&self) -> String {
|
||||||
|
match self {
|
||||||
|
TorrentGetField::ID => "id",
|
||||||
|
TorrentGetField::ADDEDDATE => "addedDate",
|
||||||
|
TorrentGetField::NAME => "name",
|
||||||
|
TorrentGetField::TOTALSIZE => "totalSize",
|
||||||
|
TorrentGetField::ERROR => "error",
|
||||||
|
TorrentGetField::ERRORSTRING => "errorString",
|
||||||
|
TorrentGetField::ETA => "eta",
|
||||||
|
TorrentGetField::ISFINISHED => "isFinished",
|
||||||
|
TorrentGetField::ISSTALLED => "isStalled",
|
||||||
|
TorrentGetField::LEFTUNTILDONE => "leftUntilDone",
|
||||||
|
TorrentGetField::METADATAPERCENTCOMPLETE => "metadataPercentComplete",
|
||||||
|
TorrentGetField::PEERSCONNECTED => "peersConnected",
|
||||||
|
TorrentGetField::PEERSGETTINGFROMUS => "peersGettingFromUs",
|
||||||
|
TorrentGetField::PEERSSENDINGTOUS => "peersSendingToUs",
|
||||||
|
TorrentGetField::PERCENTDONE => "percentDone",
|
||||||
|
TorrentGetField::QUEUEPOSITION => "queuePosition",
|
||||||
|
TorrentGetField::RATEDOWNLOAD => "rateDownload",
|
||||||
|
TorrentGetField::RATEUPLOAD => "rateUpload",
|
||||||
|
TorrentGetField::RECHECKPROGRESS => "recheckProgress",
|
||||||
|
TorrentGetField::SEEDRATIOMODE => "seedRatioMode",
|
||||||
|
TorrentGetField::SEEDRATIOLIMIT => "seedRatioLimit",
|
||||||
|
TorrentGetField::SIZEWHENDONE => "sizeWhenDone",
|
||||||
|
TorrentGetField::STATUS => "status",
|
||||||
|
TorrentGetField::TRACKERS => "trackers",
|
||||||
|
TorrentGetField::DOWNLOADDIR => "downloadDir",
|
||||||
|
TorrentGetField::UPLOADEDEVER => "uploadedEver",
|
||||||
|
TorrentGetField::UPLOADRATIO => "uploadRatio",
|
||||||
|
TorrentGetField::WEBSEEDSSENDINGTOUS => "webseedsSendingToUs",
|
||||||
|
}.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub trait RpcRequestArgument {}
|
|
||||||
impl RpcRequestArgument for SessionGet{}
|
|
||||||
@ -1,23 +1,81 @@
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct RpcResponse<T> {
|
pub struct RpcResponse<T: RpcResponseArgument> {
|
||||||
arguments: T,
|
pub arguments: T,
|
||||||
result: String
|
pub result: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: RpcResponseArgument> RpcResponse<T> {
|
||||||
|
pub fn is_ok(&self) -> bool {
|
||||||
|
self.result == "success"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub trait RpcResponseArgument {}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct SessionInfo {
|
pub struct SessionGet {
|
||||||
#[serde(rename="blocklist-enabled")]
|
#[serde(rename="blocklist-enabled")]
|
||||||
blocklist_enabled: bool,
|
pub blocklist_enabled: bool,
|
||||||
#[serde(rename="download-dir")]
|
#[serde(rename="download-dir")]
|
||||||
download_dir: String,
|
pub download_dir: String,
|
||||||
encryption: String,
|
pub encryption: String,
|
||||||
#[serde(rename="rpc-version")]
|
#[serde(rename="rpc-version")]
|
||||||
rpc_version: i32,
|
pub rpc_version: i32,
|
||||||
#[serde(rename="rpc-version-minimum")]
|
#[serde(rename="rpc-version-minimum")]
|
||||||
rpc_version_minimum: i32,
|
pub rpc_version_minimum: i32,
|
||||||
version: String,
|
pub version: String,
|
||||||
}
|
}
|
||||||
|
impl RpcResponseArgument for SessionGet{}
|
||||||
|
|
||||||
pub trait RpcResponseArgument {}
|
#[derive(Deserialize, Debug)]
|
||||||
impl RpcResponseArgument for SessionInfo{}
|
pub struct Torrent {
|
||||||
|
#[serde(rename="addedDate")]
|
||||||
|
pub added_date: Option<i64>,
|
||||||
|
#[serde(rename="downloadDir")]
|
||||||
|
pub download_dir: Option<String>,
|
||||||
|
pub error: Option<i64>,
|
||||||
|
#[serde(rename="errorString")]
|
||||||
|
pub error_string: Option<String>,
|
||||||
|
pub eta: Option<i64>,
|
||||||
|
pub id: Option<i64>,
|
||||||
|
#[serde(rename="isFinished")]
|
||||||
|
pub is_finished: Option<bool>,
|
||||||
|
#[serde(rename="isStalled")]
|
||||||
|
pub is_stalled: Option<bool>,
|
||||||
|
#[serde(rename="leftUntilDone")]
|
||||||
|
pub left_until_done: Option<i64>,
|
||||||
|
#[serde(rename="metadataPercentComplete")]
|
||||||
|
pub metadata_percent_complete: Option<f32>,
|
||||||
|
pub name: Option<String>,
|
||||||
|
#[serde(rename="peersConnected")]
|
||||||
|
pub peers_connected: Option<i64>,
|
||||||
|
#[serde(rename="peersGettingFromUs")]
|
||||||
|
pub peers_getting_from_us: Option<i64>,
|
||||||
|
#[serde(rename="peersSendingToUs")]
|
||||||
|
pub peers_sending_to_us: Option<i64>,
|
||||||
|
#[serde(rename="percentDone")]
|
||||||
|
pub percent_done: Option<f32>,
|
||||||
|
#[serde(rename="rateDownload")]
|
||||||
|
pub rate_download: Option<i64>,
|
||||||
|
#[serde(rename="rateUpload")]
|
||||||
|
pub rate_upload: Option<i64>,
|
||||||
|
#[serde(rename="recheckProgress")]
|
||||||
|
pub recheck_progress: Option<f32>,
|
||||||
|
#[serde(rename="seedRatioLimit")]
|
||||||
|
pub seed_ratio_limit: Option<f32>,
|
||||||
|
#[serde(rename="sizeWhenDone")]
|
||||||
|
pub size_when_done: Option<i64>,
|
||||||
|
pub status: Option<i64>,
|
||||||
|
#[serde(rename="totalSize")]
|
||||||
|
pub total_size: Option<i64>,
|
||||||
|
#[serde(rename="uploadRatio")]
|
||||||
|
pub upload_ratio: Option<f32>,
|
||||||
|
#[serde(rename="uploadedEver")]
|
||||||
|
pub uploaded_ever: Option<i64>,
|
||||||
|
}
|
||||||
|
impl RpcResponseArgument for Torrents<Torrent>{}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, RustcEncodable)]
|
||||||
|
pub struct Torrents<T> {
|
||||||
|
pub torrents: Vec<T>
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user