From 2b4cd84d7faf49d37492c6ff5708454beea7857a Mon Sep 17 00:00:00 2001 From: seanomik Date: Wed, 22 Jun 2022 22:05:52 -0400 Subject: [PATCH] Add `TorrentState` enum, update qbittorrent, bugfixes --- Cargo.lock | 1 - qbittorrent-rs | 2 +- src/client/mod.rs | 8 +- .../{qbittorrent.rs => qbittorrent_client.rs} | 82 +++++++++++++------ src/error.rs | 4 +- src/lib.rs | 4 +- src/torrent.rs | 53 +++++++++++- 7 files changed, 118 insertions(+), 36 deletions(-) rename src/client/{qbittorrent.rs => qbittorrent_client.rs} (54%) diff --git a/Cargo.lock b/Cargo.lock index af7948b..3ed4872 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -599,7 +599,6 @@ dependencies = [ "serde_json", "serde_repr", "serde_with", - "tokio", ] [[package]] diff --git a/qbittorrent-rs b/qbittorrent-rs index e3e9e26..c339592 160000 --- a/qbittorrent-rs +++ b/qbittorrent-rs @@ -1 +1 @@ -Subproject commit e3e9e26be49aeb34b3985dafbfd043ba6fcc51e2 +Subproject commit c3395926894fda44c6a203f8293beac609cabb5e diff --git a/src/client/mod.rs b/src/client/mod.rs index 29cc12c..8a31832 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1,4 +1,7 @@ -pub mod qbittorrent; +mod qbittorrent_client; +pub use qbittorrent_client::*; + +use crate::common; use async_trait::async_trait; @@ -10,10 +13,11 @@ pub type ClientResult = Result; pub trait TorrentClient { async fn login(&mut self, url: &str, username: &str, password: &str) -> ClientResult<()>; - async fn get_torrent_list(&self) -> ClientResult>; + async fn get_torrent_list(&self, params: Option) -> ClientResult>; async fn get_torrent_trackers(&self, torrent: &TorrentInfo) -> ClientResult>; async fn add_torrent_tracker(&self, torrent: &TorrentInfo, tracker_url: String) -> ClientResult<()>; + async fn add_torrent_trackers(&self, torrent: &TorrentInfo, trackers: Vec) -> ClientResult<()>; async fn replace_torrent_tracker(&self, torrent: &TorrentInfo, old_url: String, new_url: String) -> ClientResult<()>; async fn remove_torrent_tracker(&self, torrent: &TorrentInfo, tracker_url: String) -> ClientResult<()>; diff --git a/src/client/qbittorrent.rs b/src/client/qbittorrent_client.rs similarity index 54% rename from src/client/qbittorrent.rs rename to src/client/qbittorrent_client.rs index 9b86363..1efa6ea 100644 --- a/src/client/qbittorrent.rs +++ b/src/client/qbittorrent_client.rs @@ -1,25 +1,29 @@ use crate::torrent::{TorrentInfo, TorrentTracker, TorrentUpload}; use super::{TorrentClient, ClientResult}; -use qbittorrent::QBittorrentClient; + +pub use qbittorrent; + +use qbittorrent::{client::QBittorrentClient, common::GetTorrentListParams}; use async_trait::async_trait; -impl From<&qbittorrent::TorrentInfo> for TorrentInfo { - fn from(torrent: &qbittorrent::TorrentInfo) -> Self { +impl From<&qbittorrent::torrent::TorrentInfo> for TorrentInfo { + fn from(torrent: &qbittorrent::torrent::TorrentInfo) -> Self { TorrentInfo { name: torrent.name.clone(), trackers: vec![torrent.tracker.clone()], // NOTE: qBittorrent only gives us one tracker. category: torrent.category.clone(), tags: torrent.tags.clone(), hash: torrent.hash.clone(), + state: torrent.state.clone().into(), } } } // For some reason I have to implement this twice smh -impl Into for &TorrentInfo { - fn into(self) -> qbittorrent::TorrentInfo { - let mut t = qbittorrent::TorrentInfo::default(); +impl Into for &TorrentInfo { + fn into(self) -> qbittorrent::torrent::TorrentInfo { + let mut t = qbittorrent::torrent::TorrentInfo::default(); t.name = self.name.clone(); t.tracker = self.trackers.first().unwrap_or(&String::new()).clone(); t.category = self.category.clone(); @@ -31,9 +35,9 @@ impl Into for &TorrentInfo { } // For some reason I have to implement this twice smh -impl Into for TorrentInfo { - fn into(self) -> qbittorrent::TorrentInfo { - let mut t = qbittorrent::TorrentInfo::default(); +impl Into for TorrentInfo { + fn into(self) -> qbittorrent::torrent::TorrentInfo { + let mut t = qbittorrent::torrent::TorrentInfo::default(); t.name = self.name.clone(); t.tracker = self.trackers.first().unwrap_or(&String::new()).clone(); t.category = self.category.clone(); @@ -44,8 +48,8 @@ impl Into for TorrentInfo { } } -impl From for TorrentUpload { - fn from(upload: qbittorrent::TorrentUpload) -> Self { +impl From for TorrentUpload { + fn from(upload: qbittorrent::torrent::TorrentUpload) -> Self { TorrentUpload { urls: upload.urls, torrents: upload.torrents, @@ -56,9 +60,9 @@ impl From for TorrentUpload { } } -impl Into for &TorrentUpload { - fn into(self) -> qbittorrent::TorrentUpload { - let mut t = qbittorrent::TorrentUpload::default(); +impl Into for &TorrentUpload { + fn into(self) -> qbittorrent::torrent::TorrentUpload { + let mut t = qbittorrent::torrent::TorrentUpload::default(); t.urls = self.urls.clone(); t.torrents = self.torrents.clone(); t.tags = self.tags.clone(); @@ -69,8 +73,8 @@ impl Into for &TorrentUpload { } } -impl From<&qbittorrent::TorrentTracker> for TorrentTracker { - fn from(tracker: &qbittorrent::TorrentTracker) -> Self { +impl From<&qbittorrent::torrent::TorrentTracker> for TorrentTracker { + fn from(tracker: &qbittorrent::torrent::TorrentTracker) -> Self { TorrentTracker { url: tracker.url.clone(), status: tracker.status.clone().into(), @@ -79,14 +83,36 @@ impl From<&qbittorrent::TorrentTracker> for TorrentTracker { } } -impl From for crate::torrent::TrackerStatus { - fn from(status: qbittorrent::TrackerStatus) -> Self { +impl From for crate::torrent::TrackerStatus { + fn from(status: qbittorrent::torrent::TrackerStatus) -> Self { + use qbittorrent::torrent::TrackerStatus as QBStatus; + match status { - qbittorrent::TrackerStatus::Disabled => crate::torrent::TrackerStatus::Disabled, - qbittorrent::TrackerStatus::NotContacted => crate::torrent::TrackerStatus::NotContacted, - qbittorrent::TrackerStatus::Working => crate::torrent::TrackerStatus::Working, - qbittorrent::TrackerStatus::Updating => crate::torrent::TrackerStatus::Updating, - qbittorrent::TrackerStatus::NotWorking => crate::torrent::TrackerStatus::NotWorking, + QBStatus::Disabled => Self::Disabled, + QBStatus::NotContacted => Self::NotContacted, + QBStatus::Working => Self::Working, + QBStatus::Updating => Self::Updating, + QBStatus::NotWorking => Self::NotWorking, + } + } +} + +impl From for crate::torrent::TorrentState { + fn from(state: qbittorrent::torrent::TorrentState) -> Self { + use qbittorrent::torrent::TorrentState as QBState; + + match state { + QBState::Error => Self::Error, + QBState::MissingFiles => Self::MissingFiles, + QBState::Uploading | QBState::StalledUP | QBState::ForcedUP | QBState::CheckingUP => Self::Uploading, + QBState::PausedUP => Self::PausedUploading, + QBState::QueuedUP => Self::QueuedUploading, + QBState::Downloading | QBState::StalledDL | QBState::ForcedDL | + QBState::Allocating | QBState::MetaDownloading | QBState::CheckingDL | + QBState::CheckingResumeData | QBState::Moving => Self::Downloading, + QBState::PausedDL => Self::PausedDownloading, + QBState::QueuedDL => Self::QueuedDownloading, + QBState::Unknown => Self::Unknown, } } } @@ -97,8 +123,8 @@ impl TorrentClient for QBittorrentClient { Ok(Self::login(&mut self, url, username, password).await?) } - async fn get_torrent_list(&self) -> ClientResult> { - Ok(Self::get_torrent_list(self).await?.iter().map(|t| t.into()).collect()) + async fn get_torrent_list(&self, params: Option) -> ClientResult> { + Ok(Self::get_torrent_list(self, params).await?.iter().map(|t| t.into()).collect()) } async fn get_torrent_trackers(&self, torrent: &TorrentInfo) -> ClientResult> { @@ -109,6 +135,10 @@ impl TorrentClient for QBittorrentClient { Ok(Self::add_torrent_tracker(self, &torrent.into(), tracker_url).await?) } + async fn add_torrent_trackers(&self, torrent: &TorrentInfo, trackers: Vec) -> ClientResult<()> { + Ok(Self::add_torrent_trackers(self, &torrent.into(), trackers).await?) + } + async fn replace_torrent_tracker(&self, torrent: &TorrentInfo, old_url: String, new_url: String) -> ClientResult<()> { Ok(Self::replace_torrent_tracker(self, &torrent.into(), old_url, new_url).await?) } @@ -126,7 +156,7 @@ impl TorrentClient for QBittorrentClient { } async fn remove_torrents(&self, torrents: Vec, delete_files: bool) -> ClientResult<()> { - let torrents: Vec = torrents.iter().map(|t| t.into()).collect(); + let torrents: Vec = torrents.iter().map(|t| t.into()).collect(); Ok(Self::remove_torrents(self, torrents, delete_files).await?) } diff --git a/src/error.rs b/src/error.rs index d80bc55..43106b0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,13 +5,13 @@ use qbittorrent::error::ClientError as QClientError; #[derive(Debug)] pub enum ClientError { /// Http error - Http(Box), + Http(Box), /// Authorization error Authorization, /// Parsing error (json for qBittorrent) - Parsing(Box), + Parsing(Box), } impl From for ClientError { diff --git a/src/lib.rs b/src/lib.rs index e86b9dd..12be93e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,4 +4,6 @@ pub mod torrent; pub mod client; //pub use client::*; -pub mod error; \ No newline at end of file +pub mod error; + +pub use qbittorrent::common; \ No newline at end of file diff --git a/src/torrent.rs b/src/torrent.rs index e6071b7..75e7ed6 100644 --- a/src/torrent.rs +++ b/src/torrent.rs @@ -1,10 +1,56 @@ -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct TorrentInfo { pub name: String, pub trackers: Vec, pub category: String, pub tags: Vec, pub hash: String, + pub state: TorrentState, +} + +impl TorrentInfo { + pub fn from_hash(hash: String) -> TorrentInfo { + let mut def = TorrentInfo::default(); + def.hash = hash; + + def + } +} + +#[derive(Debug, Clone)] +pub enum TorrentState { + /// Some error occurred + Error, + + /// Torrent data files is missing + MissingFiles, + + /// Torrent is being seeded and data is being transferred + Uploading, + + /// Torrent is paused but in a seeding state. + PausedUploading, + + /// Torrent is queued but in a seeding state. + QueuedUploading, + + /// Torrent is being downloaded and data is being transferred + Downloading, + + /// Torrent is paused but in a downloading state. + PausedDownloading, + + /// Torrent is queued but in a downloading state. + QueuedDownloading, + + /// The state is unknown + Unknown, +} + +impl Default for TorrentState { + fn default() -> Self { + Self::Unknown + } } #[derive(Debug, Default, Clone)] @@ -81,8 +127,9 @@ impl TorrentUploadBuilder { self } - pub fn paused(&mut self, paused: bool) -> &mut Self { - self.params.paused = Some(paused); + /// Set the upload to be paused by default. + pub fn paused(&mut self) -> &mut Self { + self.params.paused = Some(true); self }