Compare commits
2 Commits
f78257a1fc
...
68360c0286
Author | SHA1 | Date | |
---|---|---|---|
68360c0286 | |||
7ebcbab9ac |
105
src/async_api.rs
Normal file
105
src/async_api.rs
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
use snafu::ResultExt;
|
||||||
|
use qbittorrent_web_api::Api;
|
||||||
|
use qbittorrent_web_api::api_impl::Error as QBittorrentError;
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
|
use crate::error::{Error, InternalApiSnafu as ApiError};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct UnauthenticatedRawApiClient;
|
||||||
|
|
||||||
|
impl UnauthenticatedRawApiClient {
|
||||||
|
/// Initialize a blocking runtime for the API client
|
||||||
|
pub fn new() -> UnauthenticatedRawApiClient {
|
||||||
|
UnauthenticatedRawApiClient
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Login into a qBittorrent backend and return a proper ApiClient instance
|
||||||
|
pub async fn login(self, host: &str, login: &str, password: &str) -> Result<RawApiClient, QBittorrentError> {
|
||||||
|
let api = Api::login(host, login, password).await?;
|
||||||
|
Ok(RawApiClient {
|
||||||
|
api,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RawApiClient {
|
||||||
|
api: qbittorrent_web_api::api_impl::Authenticated,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawApiClient {
|
||||||
|
pub async fn add(&self, magnet: &str, paused: bool) -> Result<String, QBittorrentError> {
|
||||||
|
let base_call = self.api.torrent_management();
|
||||||
|
let call = if paused {
|
||||||
|
base_call.add(magnet).paused("true")
|
||||||
|
} else {
|
||||||
|
base_call.add(magnet)
|
||||||
|
};
|
||||||
|
call.send_raw().await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get(&self, hash: &str) -> Result<String, QBittorrentError> {
|
||||||
|
self.api.torrent_management().properties_raw(hash).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list(&self) -> Result<String, QBittorrentError> {
|
||||||
|
self.api.torrent_management().info().send_raw().await
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
/// ApiClient is a convenience struct around qbittorrent_web_api for use in async programs, using qbt::Error error types.
|
||||||
|
pub struct ApiClient {
|
||||||
|
pub raw_api: RawApiClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApiClient {
|
||||||
|
/// Login to a qBittorrent backend and return a handle to the ApiClient
|
||||||
|
pub async fn new(host: &str, login: &str, password: &str) -> Result<ApiClient, Error> {
|
||||||
|
let unauthenticated = UnauthenticatedRawApiClient::new();
|
||||||
|
let authenticated = unauthenticated.login(host, login, password).await.map_err(|e| {
|
||||||
|
match e {
|
||||||
|
QBittorrentError::HttpError(_) => {
|
||||||
|
Error::FailedToReachAPI { source: e }
|
||||||
|
}, QBittorrentError::InvalidUsernameOrPassword => {
|
||||||
|
Error::FailedLogin { user: login.to_string() }
|
||||||
|
} _ => {
|
||||||
|
panic!("Cookie error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
Ok(ApiClient {
|
||||||
|
raw_api: authenticated,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn from_config(config: &Config) -> Result<ApiClient, Error> {
|
||||||
|
Self::new(&config.format_host(), &config.qbittorrent.login, &config.qbittorrent.password).await
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn add(&self, magnet: &str, paused: bool) -> Result<(), Error> {
|
||||||
|
let res = self.raw_api.add(magnet, paused).await.context(ApiError)?;
|
||||||
|
if res == "Ok." {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Error::message(res.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get(&self, hash: &str) -> Result<Option<String>, Error> {
|
||||||
|
let res = self.raw_api.get(hash).await.context(ApiError)?;
|
||||||
|
if res == "" {
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
Ok(Some(res))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list(&self) -> Result<String, Error> {
|
||||||
|
self.raw_api.list().await.context(ApiError)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod action;
|
pub mod action;
|
||||||
pub mod api;
|
pub mod api;
|
||||||
|
pub mod async_api;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub use config::Config;
|
pub use config::Config;
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
|
|
|
@ -79,6 +79,7 @@ pub fn torrent_to_magnet<T: AsRef<Path>>(torrent: T) -> Result<String, Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallible: only used in tests
|
// Fallible: only used in tests
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn find_free_port() -> u16 {
|
pub fn find_free_port() -> u16 {
|
||||||
let bind = TcpListener::bind("127.0.0.1:0").unwrap();
|
let bind = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||||
bind.local_addr().unwrap().port()
|
bind.local_addr().unwrap().port()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user