Add `TorrentState` enum, update qbittorrent, bugfixes
This commit is contained in:
parent
edf45342fb
commit
2b4cd84d7f
|
@ -599,7 +599,6 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"serde_with",
|
"serde_with",
|
||||||
"tokio",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit e3e9e26be49aeb34b3985dafbfd043ba6fcc51e2
|
Subproject commit c3395926894fda44c6a203f8293beac609cabb5e
|
|
@ -1,4 +1,7 @@
|
||||||
pub mod qbittorrent;
|
mod qbittorrent_client;
|
||||||
|
pub use qbittorrent_client::*;
|
||||||
|
|
||||||
|
use crate::common;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
@ -10,10 +13,11 @@ pub type ClientResult<T> = Result<T, ClientError>;
|
||||||
pub trait TorrentClient {
|
pub trait TorrentClient {
|
||||||
async fn login(&mut self, url: &str, username: &str, password: &str) -> ClientResult<()>;
|
async fn login(&mut self, url: &str, username: &str, password: &str) -> ClientResult<()>;
|
||||||
|
|
||||||
async fn get_torrent_list(&self) -> ClientResult<Vec<TorrentInfo>>;
|
async fn get_torrent_list(&self, params: Option<common::GetTorrentListParams>) -> ClientResult<Vec<TorrentInfo>>;
|
||||||
|
|
||||||
async fn get_torrent_trackers(&self, torrent: &TorrentInfo) -> ClientResult<Vec<TorrentTracker>>;
|
async fn get_torrent_trackers(&self, torrent: &TorrentInfo) -> ClientResult<Vec<TorrentTracker>>;
|
||||||
async fn add_torrent_tracker(&self, torrent: &TorrentInfo, tracker_url: String) -> ClientResult<()>;
|
async fn add_torrent_tracker(&self, torrent: &TorrentInfo, tracker_url: String) -> ClientResult<()>;
|
||||||
|
async fn add_torrent_trackers(&self, torrent: &TorrentInfo, trackers: Vec<String>) -> ClientResult<()>;
|
||||||
async fn replace_torrent_tracker(&self, torrent: &TorrentInfo, old_url: String, new_url: String) -> 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<()>;
|
async fn remove_torrent_tracker(&self, torrent: &TorrentInfo, tracker_url: String) -> ClientResult<()>;
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,29 @@
|
||||||
use crate::torrent::{TorrentInfo, TorrentTracker, TorrentUpload};
|
use crate::torrent::{TorrentInfo, TorrentTracker, TorrentUpload};
|
||||||
use super::{TorrentClient, ClientResult};
|
use super::{TorrentClient, ClientResult};
|
||||||
use qbittorrent::QBittorrentClient;
|
|
||||||
|
pub use qbittorrent;
|
||||||
|
|
||||||
|
use qbittorrent::{client::QBittorrentClient, common::GetTorrentListParams};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
impl From<&qbittorrent::TorrentInfo> for TorrentInfo {
|
impl From<&qbittorrent::torrent::TorrentInfo> for TorrentInfo {
|
||||||
fn from(torrent: &qbittorrent::TorrentInfo) -> Self {
|
fn from(torrent: &qbittorrent::torrent::TorrentInfo) -> Self {
|
||||||
TorrentInfo {
|
TorrentInfo {
|
||||||
name: torrent.name.clone(),
|
name: torrent.name.clone(),
|
||||||
trackers: vec![torrent.tracker.clone()], // NOTE: qBittorrent only gives us one tracker.
|
trackers: vec![torrent.tracker.clone()], // NOTE: qBittorrent only gives us one tracker.
|
||||||
category: torrent.category.clone(),
|
category: torrent.category.clone(),
|
||||||
tags: torrent.tags.clone(),
|
tags: torrent.tags.clone(),
|
||||||
hash: torrent.hash.clone(),
|
hash: torrent.hash.clone(),
|
||||||
|
state: torrent.state.clone().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For some reason I have to implement this twice smh
|
// For some reason I have to implement this twice smh
|
||||||
impl Into<qbittorrent::TorrentInfo> for &TorrentInfo {
|
impl Into<qbittorrent::torrent::TorrentInfo> for &TorrentInfo {
|
||||||
fn into(self) -> qbittorrent::TorrentInfo {
|
fn into(self) -> qbittorrent::torrent::TorrentInfo {
|
||||||
let mut t = qbittorrent::TorrentInfo::default();
|
let mut t = qbittorrent::torrent::TorrentInfo::default();
|
||||||
t.name = self.name.clone();
|
t.name = self.name.clone();
|
||||||
t.tracker = self.trackers.first().unwrap_or(&String::new()).clone();
|
t.tracker = self.trackers.first().unwrap_or(&String::new()).clone();
|
||||||
t.category = self.category.clone();
|
t.category = self.category.clone();
|
||||||
|
@ -31,9 +35,9 @@ impl Into<qbittorrent::TorrentInfo> for &TorrentInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
// For some reason I have to implement this twice smh
|
// For some reason I have to implement this twice smh
|
||||||
impl Into<qbittorrent::TorrentInfo> for TorrentInfo {
|
impl Into<qbittorrent::torrent::TorrentInfo> for TorrentInfo {
|
||||||
fn into(self) -> qbittorrent::TorrentInfo {
|
fn into(self) -> qbittorrent::torrent::TorrentInfo {
|
||||||
let mut t = qbittorrent::TorrentInfo::default();
|
let mut t = qbittorrent::torrent::TorrentInfo::default();
|
||||||
t.name = self.name.clone();
|
t.name = self.name.clone();
|
||||||
t.tracker = self.trackers.first().unwrap_or(&String::new()).clone();
|
t.tracker = self.trackers.first().unwrap_or(&String::new()).clone();
|
||||||
t.category = self.category.clone();
|
t.category = self.category.clone();
|
||||||
|
@ -44,8 +48,8 @@ impl Into<qbittorrent::TorrentInfo> for TorrentInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<qbittorrent::TorrentUpload> for TorrentUpload {
|
impl From<qbittorrent::torrent::TorrentUpload> for TorrentUpload {
|
||||||
fn from(upload: qbittorrent::TorrentUpload) -> Self {
|
fn from(upload: qbittorrent::torrent::TorrentUpload) -> Self {
|
||||||
TorrentUpload {
|
TorrentUpload {
|
||||||
urls: upload.urls,
|
urls: upload.urls,
|
||||||
torrents: upload.torrents,
|
torrents: upload.torrents,
|
||||||
|
@ -56,9 +60,9 @@ impl From<qbittorrent::TorrentUpload> for TorrentUpload {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<qbittorrent::TorrentUpload> for &TorrentUpload {
|
impl Into<qbittorrent::torrent::TorrentUpload> for &TorrentUpload {
|
||||||
fn into(self) -> qbittorrent::TorrentUpload {
|
fn into(self) -> qbittorrent::torrent::TorrentUpload {
|
||||||
let mut t = qbittorrent::TorrentUpload::default();
|
let mut t = qbittorrent::torrent::TorrentUpload::default();
|
||||||
t.urls = self.urls.clone();
|
t.urls = self.urls.clone();
|
||||||
t.torrents = self.torrents.clone();
|
t.torrents = self.torrents.clone();
|
||||||
t.tags = self.tags.clone();
|
t.tags = self.tags.clone();
|
||||||
|
@ -69,8 +73,8 @@ impl Into<qbittorrent::TorrentUpload> for &TorrentUpload {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&qbittorrent::TorrentTracker> for TorrentTracker {
|
impl From<&qbittorrent::torrent::TorrentTracker> for TorrentTracker {
|
||||||
fn from(tracker: &qbittorrent::TorrentTracker) -> Self {
|
fn from(tracker: &qbittorrent::torrent::TorrentTracker) -> Self {
|
||||||
TorrentTracker {
|
TorrentTracker {
|
||||||
url: tracker.url.clone(),
|
url: tracker.url.clone(),
|
||||||
status: tracker.status.clone().into(),
|
status: tracker.status.clone().into(),
|
||||||
|
@ -79,14 +83,36 @@ impl From<&qbittorrent::TorrentTracker> for TorrentTracker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<qbittorrent::TrackerStatus> for crate::torrent::TrackerStatus {
|
impl From<qbittorrent::torrent::TrackerStatus> for crate::torrent::TrackerStatus {
|
||||||
fn from(status: qbittorrent::TrackerStatus) -> Self {
|
fn from(status: qbittorrent::torrent::TrackerStatus) -> Self {
|
||||||
|
use qbittorrent::torrent::TrackerStatus as QBStatus;
|
||||||
|
|
||||||
match status {
|
match status {
|
||||||
qbittorrent::TrackerStatus::Disabled => crate::torrent::TrackerStatus::Disabled,
|
QBStatus::Disabled => Self::Disabled,
|
||||||
qbittorrent::TrackerStatus::NotContacted => crate::torrent::TrackerStatus::NotContacted,
|
QBStatus::NotContacted => Self::NotContacted,
|
||||||
qbittorrent::TrackerStatus::Working => crate::torrent::TrackerStatus::Working,
|
QBStatus::Working => Self::Working,
|
||||||
qbittorrent::TrackerStatus::Updating => crate::torrent::TrackerStatus::Updating,
|
QBStatus::Updating => Self::Updating,
|
||||||
qbittorrent::TrackerStatus::NotWorking => crate::torrent::TrackerStatus::NotWorking,
|
QBStatus::NotWorking => Self::NotWorking,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<qbittorrent::torrent::TorrentState> 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?)
|
Ok(Self::login(&mut self, url, username, password).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_torrent_list(&self) -> ClientResult<Vec<TorrentInfo>> {
|
async fn get_torrent_list(&self, params: Option<GetTorrentListParams>) -> ClientResult<Vec<TorrentInfo>> {
|
||||||
Ok(Self::get_torrent_list(self).await?.iter().map(|t| t.into()).collect())
|
Ok(Self::get_torrent_list(self, params).await?.iter().map(|t| t.into()).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_torrent_trackers(&self, torrent: &TorrentInfo) -> ClientResult<Vec<TorrentTracker>> {
|
async fn get_torrent_trackers(&self, torrent: &TorrentInfo) -> ClientResult<Vec<TorrentTracker>> {
|
||||||
|
@ -109,6 +135,10 @@ impl TorrentClient for QBittorrentClient {
|
||||||
Ok(Self::add_torrent_tracker(self, &torrent.into(), tracker_url).await?)
|
Ok(Self::add_torrent_tracker(self, &torrent.into(), tracker_url).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn add_torrent_trackers(&self, torrent: &TorrentInfo, trackers: Vec<String>) -> 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<()> {
|
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?)
|
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<TorrentInfo>, delete_files: bool) -> ClientResult<()> {
|
async fn remove_torrents(&self, torrents: Vec<TorrentInfo>, delete_files: bool) -> ClientResult<()> {
|
||||||
let torrents: Vec<qbittorrent::TorrentInfo> = torrents.iter().map(|t| t.into()).collect();
|
let torrents: Vec<qbittorrent::torrent::TorrentInfo> = torrents.iter().map(|t| t.into()).collect();
|
||||||
Ok(Self::remove_torrents(self, torrents, delete_files).await?)
|
Ok(Self::remove_torrents(self, torrents, delete_files).await?)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,13 @@ use qbittorrent::error::ClientError as QClientError;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ClientError {
|
pub enum ClientError {
|
||||||
/// Http error
|
/// Http error
|
||||||
Http(Box<dyn Error>),
|
Http(Box<dyn Error + Send + Sync>),
|
||||||
|
|
||||||
/// Authorization error
|
/// Authorization error
|
||||||
Authorization,
|
Authorization,
|
||||||
|
|
||||||
/// Parsing error (json for qBittorrent)
|
/// Parsing error (json for qBittorrent)
|
||||||
Parsing(Box<dyn Error>),
|
Parsing(Box<dyn Error + Send + Sync>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<QClientError> for ClientError {
|
impl From<QClientError> for ClientError {
|
||||||
|
|
|
@ -4,4 +4,6 @@ pub mod torrent;
|
||||||
pub mod client;
|
pub mod client;
|
||||||
//pub use client::*;
|
//pub use client::*;
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
|
pub use qbittorrent::common;
|
|
@ -1,10 +1,56 @@
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct TorrentInfo {
|
pub struct TorrentInfo {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub trackers: Vec<String>,
|
pub trackers: Vec<String>,
|
||||||
pub category: String,
|
pub category: String,
|
||||||
pub tags: Vec<String>,
|
pub tags: Vec<String>,
|
||||||
pub hash: String,
|
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)]
|
#[derive(Debug, Default, Clone)]
|
||||||
|
@ -81,8 +127,9 @@ impl TorrentUploadBuilder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn paused(&mut self, paused: bool) -> &mut Self {
|
/// Set the upload to be paused by default.
|
||||||
self.params.paused = Some(paused);
|
pub fn paused(&mut self) -> &mut Self {
|
||||||
|
self.params.paused = Some(true);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue