From a3609696c7f930c754d6d6e99aea2aeace061a6e Mon Sep 17 00:00:00 2001 From: lonelyhentxi Date: Sat, 5 Apr 2025 14:24:47 +0800 Subject: [PATCH] feat: finsih qbit adapter --- .../src/downloader/bittorrent/downloader.rs | 9 +- .../src/downloader/bittorrent/source.rs | 2 +- apps/recorder/src/downloader/qbit/mod.rs | 105 ++++-------------- packages/testing-torrents/README.md | 2 +- 4 files changed, 29 insertions(+), 89 deletions(-) diff --git a/apps/recorder/src/downloader/bittorrent/downloader.rs b/apps/recorder/src/downloader/bittorrent/downloader.rs index 0744305..0cdc5e3 100644 --- a/apps/recorder/src/downloader/bittorrent/downloader.rs +++ b/apps/recorder/src/downloader/bittorrent/downloader.rs @@ -23,8 +23,7 @@ where &self, selector: Self::Selector, ) -> Result { - let hashes = - ::query_torrent_hashes(&self, selector).await?; + let hashes = ::query_torrent_hashes(self, selector).await?; self.pause_torrents(hashes).await } @@ -32,16 +31,14 @@ where &self, selector: Self::Selector, ) -> Result { - let hashes = - ::query_torrent_hashes(&self, selector).await?; + let hashes = ::query_torrent_hashes(self, selector).await?; self.resume_torrents(hashes).await } async fn remove_downloads( &self, selector: Self::Selector, ) -> Result { - let hashes = - ::query_torrent_hashes(&self, selector).await?; + let hashes = ::query_torrent_hashes(self, selector).await?; self.remove_torrents(hashes).await } diff --git a/apps/recorder/src/downloader/bittorrent/source.rs b/apps/recorder/src/downloader/bittorrent/source.rs index 9c96fa7..75032ab 100644 --- a/apps/recorder/src/downloader/bittorrent/source.rs +++ b/apps/recorder/src/downloader/bittorrent/source.rs @@ -131,7 +131,7 @@ impl TorrentFileSource { .boxed() .and_then(|s| { s.path_segments() - .and_then(|p| p.last()) + .and_then(|mut p| p.next_back()) .map(String::from) .ok_or_else(|| anyhow::anyhow!("invalid url")) .to_dyn_boxed() diff --git a/apps/recorder/src/downloader/qbit/mod.rs b/apps/recorder/src/downloader/qbit/mod.rs index 5438d6f..caecad8 100644 --- a/apps/recorder/src/downloader/qbit/mod.rs +++ b/apps/recorder/src/downloader/qbit/mod.rs @@ -2,7 +2,6 @@ use std::{ borrow::Cow, collections::{HashMap, HashSet}, fmt::Debug, - io, sync::{Arc, Weak}, time::Duration, }; @@ -167,6 +166,7 @@ impl TorrentTaskTrait for QBittorrentTask { .as_deref() .unwrap_or("") .split(',') + .map(|s| s.trim()) .filter(|s| !s.is_empty()) .map(Cow::Borrowed) } @@ -357,7 +357,7 @@ impl QBittorrentDownloader { save_path: creation.save_path.into(), wait_sync_timeout: creation .wait_sync_timeout - .unwrap_or(Duration::from_millis(10000)), + .unwrap_or(Duration::from_secs(10)), downloader_id: creation.downloader_id, sync_watch: watch::channel(Utc::now()).0, sync_data: Arc::new(RwLock::new(QBittorrentSyncData::default())), @@ -433,8 +433,12 @@ impl QBittorrentDownloader { category: &str, ) -> Result<(), DownloaderError> { { - let sync_data = self.sync_data.read().await; - if !sync_data.categories.contains_key(category) { + let category_no_exists = { + let sync_data = self.sync_data.read().await; + !sync_data.categories.contains_key(category) + }; + + if category_no_exists { self.add_category(category).await?; } } @@ -495,49 +499,6 @@ impl QBittorrentDownloader { Ok(()) } - #[instrument(level = "debug", skip(self, replacer))] - pub async fn move_torrent_contents String>( - &self, - hash: &str, - replacer: F, - ) -> Result<(), DownloaderError> { - let old_path = { - let sync_data = self.sync_data.read().await; - sync_data - .torrents - .get(hash) - .and_then(|t| t.content_path.as_deref()) - .ok_or_else(|| { - io::Error::new( - io::ErrorKind::NotFound, - "no torrent or torrent does not contain content path", - ) - })? - .to_string() - }; - let new_path = replacer(old_path.clone()); - self.client - .rename_file(hash, old_path.clone(), new_path.to_string()) - .await?; - self.wait_sync_until( - |sync_data| { - let torrents = &sync_data.torrents; - torrents.get(hash).is_some_and(|t| { - t.content_path.as_deref().is_some_and(|p| { - path_equals_as_file_url(p, &new_path) - .inspect_err(|error| { - tracing::warn!(name = "path_equals_as_file_url", error = ?error); - }) - .unwrap_or(false) - }) - }) - }, - None, - ) - .await?; - Ok(()) - } - #[instrument(level = "debug", skip(self))] pub async fn move_torrents( &self, @@ -608,17 +569,23 @@ impl QBittorrentDownloader { where S: Fn(&QBittorrentSyncData) -> bool, { + { + let sync_data = &self.sync_data.read().await; + if stop_wait_fn(sync_data) { + return Ok(()); + } + } + let timeout = timeout.unwrap_or(self.wait_sync_timeout); let start_time = Utc::now(); let mut receiver = self.sync_watch.subscribe(); + while let Ok(()) = receiver.changed().await { let has_timeout = { let sync_time = *receiver.borrow(); - sync_time - .signed_duration_since(start_time) - .num_milliseconds() - > timeout.as_millis() as i64 + let diff_time = sync_time - start_time; + diff_time.num_milliseconds() > timeout.as_millis() as i64 }; if has_timeout { tracing::warn!(name = "wait_until timeout", timeout = ?timeout); @@ -958,7 +925,7 @@ pub mod tests { .init(); let torrents_image = create_torrents_testcontainers().await?; - let torrents_container = torrents_image.start().await?; + let _torrents_container = torrents_image.start().await?; let torrents_req = MockRequest { id: "f10ebdda-dd2e-43f8-b80c-bf0884d071c4".into(), @@ -1022,8 +989,6 @@ pub mod tests { ) .await?; - torrents_container.stop().await?; - Ok(()) } @@ -1090,12 +1055,11 @@ pub mod tests { assert!(!files.is_empty()); let first_file = files.first().expect("should have first file"); - assert_eq!( - &first_file.name, - r#"[Nekomoe kissaten&LoliHouse] Boku no Kokoro no Yabai Yatsu - 20 [WebRip 1080p HEVC-10bit AAC ASSx2].mkv"# + assert!( + &first_file.name.ends_with(r#"[Nekomoe kissaten&LoliHouse] Boku no Kokoro no Yabai Yatsu - 20 [WebRip 1080p HEVC-10bit AAC ASSx2].mkv"#) ); - let test_tag = format!("test_tag_{}", Utc::now().timestamp()); + let test_tag = "test_tag".to_string(); downloader .add_torrent_tags(vec![torrent_hash.clone()], vec![test_tag.clone()]) @@ -1138,29 +1102,6 @@ pub mod tests { )? ); - downloader - .move_torrent_contents(&torrent_hash, |f| { - f.replace(&folder_name, &format!("moved_{}", &folder_name)) - }) - .await?; - - let target_torrent = get_torrent().await?; - - let actual_content_path = &target_torrent - .torrent - .content_path - .expect("failed to get actual content path"); - - assert!( - path_equals_as_file_url( - actual_content_path, - base_save_path.join(actual_content_path) - ) - .whatever_context::<_, RError>( - "failed to compare actual content path and found expected content path" - )? - ); - downloader .remove_torrents(vec![torrent_hash.clone()].into()) .await?; @@ -1175,6 +1116,8 @@ pub mod tests { assert!(torrent_infos1.is_empty()); + tracing::info!("test finished"); + Ok(()) } } diff --git a/packages/testing-torrents/README.md b/packages/testing-torrents/README.md index ac11b0a..f4ebf3a 100644 --- a/packages/testing-torrents/README.md +++ b/packages/testing-torrents/README.md @@ -15,7 +15,7 @@ docker buildx build --platform linux/amd64 --tag konobangu-testing-torrents:late ## Run ```bash -docker run --network_mode=host --name konobangu-testing-torrents konobangu-testing-torrents:latest +docker run -p 6080:6080 -p 6081:6081 -p 6082:6082 --name konobangu-testing-torrents konobangu-testing-torrents:latest ``` ## Publish