mirror of
https://github.com/kristoferssolo/transmission-rpc.git
synced 2025-10-21 20:10:37 +00:00
init
This commit is contained in:
parent
ac3cefea36
commit
baad21f277
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/target
|
||||||
|
Cargo.lock
|
||||||
|
.env
|
||||||
24
Cargo.toml
Normal file
24
Cargo.toml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
[package]
|
||||||
|
name = "transmission-rpc"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["red <red.avtovo@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
dotenv = "0.15.0"
|
||||||
|
reqwest = { version = "0.10.4", features = ["json", "rustls-tls"] }
|
||||||
|
tokio = { version = "0.2", features = ["full"] }
|
||||||
|
tokio-postgres = "0.5.2"
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
futures = "0.3.3"
|
||||||
|
serde_json = "1.0"
|
||||||
|
ajson = "0.2"
|
||||||
|
|
||||||
|
log = "0.4.8"
|
||||||
|
env_logger = "0.7.1"
|
||||||
|
|
||||||
|
bb8-postgres = "0.4.0"
|
||||||
|
bb8 = "0.4.1"
|
||||||
|
|
||||||
|
rustc-serialize = "0.3.24"
|
||||||
19
README.md
Normal file
19
README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
Library to communicate with transmission rpc
|
||||||
|
|
||||||
|
spec: https://github.com/transmission/transmission/blob/master/extras/rpc-spec.txt
|
||||||
|
|
||||||
|
Supported Methods:
|
||||||
|
|
||||||
|
- [ ] torrent-set
|
||||||
|
- [ ] torrent-get
|
||||||
|
- [ ] torrent-add
|
||||||
|
- [ ] torrent-remove
|
||||||
|
- [ ] torrent-set-location
|
||||||
|
- [ ] torrent-rename-path
|
||||||
|
- [ ] session-set
|
||||||
|
- [X] session-get
|
||||||
|
- [ ] session-stats
|
||||||
|
- [ ] blocklist-update
|
||||||
|
- [ ] port-test
|
||||||
|
- [ ] session-close
|
||||||
|
- [ ] free-space
|
||||||
109
src/main.rs
Normal file
109
src/main.rs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#[allow(unused_imports)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
|
||||||
|
extern crate ajson;
|
||||||
|
extern crate bb8;
|
||||||
|
extern crate bb8_postgres;
|
||||||
|
extern crate env_logger;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
|
extern crate reqwest;
|
||||||
|
extern crate tokio_postgres;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use dotenv::dotenv;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use reqwest::header::CONTENT_TYPE;
|
||||||
|
|
||||||
|
pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct BasicAuth {
|
||||||
|
user: String,
|
||||||
|
password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
mod models;
|
||||||
|
use models::request::SessionGet;
|
||||||
|
use models::response::RpcResponse;
|
||||||
|
use models::entity::SessionInfo;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
not_main().await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn not_main() -> Result<()> {
|
||||||
|
dotenv().ok();
|
||||||
|
env_logger::init();
|
||||||
|
|
||||||
|
let url= env::var("URL")?;
|
||||||
|
let basic_auth = Some(BasicAuth{user: env::var("TUSER")?, password: env::var("TPWD")?});
|
||||||
|
info!("Loaded auth: {:?}", &basic_auth);
|
||||||
|
let rq: reqwest::RequestBuilder = rpc_request(url.as_ref(), &basic_auth)
|
||||||
|
.header("X-Transmission-Session-Id", get_session_id(url.as_ref(), &basic_auth).await)
|
||||||
|
.json(&SessionGet::default());
|
||||||
|
debug!("Request body: {:?}", rq.try_clone().unwrap().body_string()?);
|
||||||
|
|
||||||
|
// let p2 = Point{ x: 34, ..Default::default() };
|
||||||
|
|
||||||
|
let resp: reqwest::Response = rq.send().await?;
|
||||||
|
// print!("{:?}", resp.text().await);
|
||||||
|
let rpc_response: RpcResponse<SessionInfo> = resp.json().await?;
|
||||||
|
info!("{:#?}", rpc_response);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
trait BodyString {
|
||||||
|
fn body_string(self) -> Result<String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BodyString for reqwest::RequestBuilder {
|
||||||
|
fn body_string(self) -> Result<String> {
|
||||||
|
let rq = self.build()?;
|
||||||
|
let body = rq.body().unwrap().as_bytes().unwrap();
|
||||||
|
Ok(std::str::from_utf8(body)?.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rpc_request(url: &str, basic_auth: &Option<BasicAuth>) -> reqwest::RequestBuilder {
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
if let Some(auth) = basic_auth {
|
||||||
|
client.post(url.clone())
|
||||||
|
.basic_auth(&auth.user, Some(&auth.password))
|
||||||
|
} else {
|
||||||
|
client.post(url.clone())
|
||||||
|
}
|
||||||
|
.header(CONTENT_TYPE, "application/json")
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_session_id(url: &str, basic_auth: &Option<BasicAuth>) -> String {
|
||||||
|
let mut map = HashMap::new();
|
||||||
|
map.insert("method", "session-get");
|
||||||
|
info!("Requesting session id info");
|
||||||
|
let response: reqwest::Response = rpc_request(url, basic_auth)
|
||||||
|
.json(&map)
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let session_id = response.headers()
|
||||||
|
.get("x-transmission-session-id")
|
||||||
|
.expect("Unable to get session id")
|
||||||
|
.to_str()
|
||||||
|
.unwrap()
|
||||||
|
.to_owned();
|
||||||
|
info!("Received session id: {}", session_id);
|
||||||
|
session_id
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::not_main;
|
||||||
|
use crate::Result;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn it_works() -> Result<()> {
|
||||||
|
dotenv().ok();
|
||||||
|
not_main().await
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/models/entity.rs
Normal file
14
src/models/entity.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct SessionInfo {
|
||||||
|
#[serde(rename="blocklist-enabled")]
|
||||||
|
blocklist_enabled: bool,
|
||||||
|
#[serde(rename="download-dir")]
|
||||||
|
download_dir: String,
|
||||||
|
encryption: String,
|
||||||
|
#[serde(rename="rpc-version")]
|
||||||
|
rpc_version: i32,
|
||||||
|
#[serde(rename="rpc-version-minimum")]
|
||||||
|
rpc_version_minimum: i32,
|
||||||
|
version: String,
|
||||||
|
}
|
||||||
4
src/models/mod.rs
Normal file
4
src/models/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
pub mod request;
|
||||||
|
pub mod response;
|
||||||
|
pub mod entity;
|
||||||
12
src/models/request.rs
Normal file
12
src/models/request.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug, RustcEncodable)]
|
||||||
|
pub struct SessionGet {
|
||||||
|
method: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SessionGet{
|
||||||
|
fn default() -> SessionGet {
|
||||||
|
SessionGet { method: String::from("session-get") }
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/models/response.rs
Normal file
6
src/models/response.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct RpcResponse<T> {
|
||||||
|
arguments: T,
|
||||||
|
result: String
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user