feat: finsih qbit adapter
This commit is contained in:
parent
b0c12acbc6
commit
a3609696c7
@ -23,8 +23,7 @@ where
|
|||||||
&self,
|
&self,
|
||||||
selector: Self::Selector,
|
selector: Self::Selector,
|
||||||
) -> Result<Self::IdSelector, DownloaderError> {
|
) -> Result<Self::IdSelector, DownloaderError> {
|
||||||
let hashes =
|
let hashes = <Self as TorrentDownloaderTrait>::query_torrent_hashes(self, selector).await?;
|
||||||
<Self as TorrentDownloaderTrait>::query_torrent_hashes(&self, selector).await?;
|
|
||||||
self.pause_torrents(hashes).await
|
self.pause_torrents(hashes).await
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,16 +31,14 @@ where
|
|||||||
&self,
|
&self,
|
||||||
selector: Self::Selector,
|
selector: Self::Selector,
|
||||||
) -> Result<Self::IdSelector, DownloaderError> {
|
) -> Result<Self::IdSelector, DownloaderError> {
|
||||||
let hashes =
|
let hashes = <Self as TorrentDownloaderTrait>::query_torrent_hashes(self, selector).await?;
|
||||||
<Self as TorrentDownloaderTrait>::query_torrent_hashes(&self, selector).await?;
|
|
||||||
self.resume_torrents(hashes).await
|
self.resume_torrents(hashes).await
|
||||||
}
|
}
|
||||||
async fn remove_downloads(
|
async fn remove_downloads(
|
||||||
&self,
|
&self,
|
||||||
selector: Self::Selector,
|
selector: Self::Selector,
|
||||||
) -> Result<Self::IdSelector, DownloaderError> {
|
) -> Result<Self::IdSelector, DownloaderError> {
|
||||||
let hashes =
|
let hashes = <Self as TorrentDownloaderTrait>::query_torrent_hashes(self, selector).await?;
|
||||||
<Self as TorrentDownloaderTrait>::query_torrent_hashes(&self, selector).await?;
|
|
||||||
self.remove_torrents(hashes).await
|
self.remove_torrents(hashes).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ impl TorrentFileSource {
|
|||||||
.boxed()
|
.boxed()
|
||||||
.and_then(|s| {
|
.and_then(|s| {
|
||||||
s.path_segments()
|
s.path_segments()
|
||||||
.and_then(|p| p.last())
|
.and_then(|mut p| p.next_back())
|
||||||
.map(String::from)
|
.map(String::from)
|
||||||
.ok_or_else(|| anyhow::anyhow!("invalid url"))
|
.ok_or_else(|| anyhow::anyhow!("invalid url"))
|
||||||
.to_dyn_boxed()
|
.to_dyn_boxed()
|
||||||
|
@ -2,7 +2,6 @@ use std::{
|
|||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
io,
|
|
||||||
sync::{Arc, Weak},
|
sync::{Arc, Weak},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
@ -167,6 +166,7 @@ impl TorrentTaskTrait for QBittorrentTask {
|
|||||||
.as_deref()
|
.as_deref()
|
||||||
.unwrap_or("")
|
.unwrap_or("")
|
||||||
.split(',')
|
.split(',')
|
||||||
|
.map(|s| s.trim())
|
||||||
.filter(|s| !s.is_empty())
|
.filter(|s| !s.is_empty())
|
||||||
.map(Cow::Borrowed)
|
.map(Cow::Borrowed)
|
||||||
}
|
}
|
||||||
@ -357,7 +357,7 @@ impl QBittorrentDownloader {
|
|||||||
save_path: creation.save_path.into(),
|
save_path: creation.save_path.into(),
|
||||||
wait_sync_timeout: creation
|
wait_sync_timeout: creation
|
||||||
.wait_sync_timeout
|
.wait_sync_timeout
|
||||||
.unwrap_or(Duration::from_millis(10000)),
|
.unwrap_or(Duration::from_secs(10)),
|
||||||
downloader_id: creation.downloader_id,
|
downloader_id: creation.downloader_id,
|
||||||
sync_watch: watch::channel(Utc::now()).0,
|
sync_watch: watch::channel(Utc::now()).0,
|
||||||
sync_data: Arc::new(RwLock::new(QBittorrentSyncData::default())),
|
sync_data: Arc::new(RwLock::new(QBittorrentSyncData::default())),
|
||||||
@ -433,8 +433,12 @@ impl QBittorrentDownloader {
|
|||||||
category: &str,
|
category: &str,
|
||||||
) -> Result<(), DownloaderError> {
|
) -> Result<(), DownloaderError> {
|
||||||
{
|
{
|
||||||
|
let category_no_exists = {
|
||||||
let sync_data = self.sync_data.read().await;
|
let sync_data = self.sync_data.read().await;
|
||||||
if !sync_data.categories.contains_key(category) {
|
!sync_data.categories.contains_key(category)
|
||||||
|
};
|
||||||
|
|
||||||
|
if category_no_exists {
|
||||||
self.add_category(category).await?;
|
self.add_category(category).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -495,49 +499,6 @@ impl QBittorrentDownloader {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, replacer))]
|
|
||||||
pub async fn move_torrent_contents<F: FnOnce(String) -> 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))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub async fn move_torrents(
|
pub async fn move_torrents(
|
||||||
&self,
|
&self,
|
||||||
@ -608,17 +569,23 @@ impl QBittorrentDownloader {
|
|||||||
where
|
where
|
||||||
S: Fn(&QBittorrentSyncData) -> bool,
|
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 timeout = timeout.unwrap_or(self.wait_sync_timeout);
|
||||||
let start_time = Utc::now();
|
let start_time = Utc::now();
|
||||||
|
|
||||||
let mut receiver = self.sync_watch.subscribe();
|
let mut receiver = self.sync_watch.subscribe();
|
||||||
|
|
||||||
while let Ok(()) = receiver.changed().await {
|
while let Ok(()) = receiver.changed().await {
|
||||||
let has_timeout = {
|
let has_timeout = {
|
||||||
let sync_time = *receiver.borrow();
|
let sync_time = *receiver.borrow();
|
||||||
sync_time
|
let diff_time = sync_time - start_time;
|
||||||
.signed_duration_since(start_time)
|
diff_time.num_milliseconds() > timeout.as_millis() as i64
|
||||||
.num_milliseconds()
|
|
||||||
> timeout.as_millis() as i64
|
|
||||||
};
|
};
|
||||||
if has_timeout {
|
if has_timeout {
|
||||||
tracing::warn!(name = "wait_until timeout", timeout = ?timeout);
|
tracing::warn!(name = "wait_until timeout", timeout = ?timeout);
|
||||||
@ -958,7 +925,7 @@ pub mod tests {
|
|||||||
.init();
|
.init();
|
||||||
|
|
||||||
let torrents_image = create_torrents_testcontainers().await?;
|
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 {
|
let torrents_req = MockRequest {
|
||||||
id: "f10ebdda-dd2e-43f8-b80c-bf0884d071c4".into(),
|
id: "f10ebdda-dd2e-43f8-b80c-bf0884d071c4".into(),
|
||||||
@ -1022,8 +989,6 @@ pub mod tests {
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
torrents_container.stop().await?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1090,12 +1055,11 @@ pub mod tests {
|
|||||||
assert!(!files.is_empty());
|
assert!(!files.is_empty());
|
||||||
|
|
||||||
let first_file = files.first().expect("should have first file");
|
let first_file = files.first().expect("should have first file");
|
||||||
assert_eq!(
|
assert!(
|
||||||
&first_file.name,
|
&first_file.name.ends_with(r#"[Nekomoe kissaten&LoliHouse] Boku no Kokoro no Yabai Yatsu - 20 [WebRip 1080p HEVC-10bit AAC ASSx2].mkv"#)
|
||||||
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
|
downloader
|
||||||
.add_torrent_tags(vec![torrent_hash.clone()], vec![test_tag.clone()])
|
.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
|
downloader
|
||||||
.remove_torrents(vec![torrent_hash.clone()].into())
|
.remove_torrents(vec![torrent_hash.clone()].into())
|
||||||
.await?;
|
.await?;
|
||||||
@ -1175,6 +1116,8 @@ pub mod tests {
|
|||||||
|
|
||||||
assert!(torrent_infos1.is_empty());
|
assert!(torrent_infos1.is_empty());
|
||||||
|
|
||||||
|
tracing::info!("test finished");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ docker buildx build --platform linux/amd64 --tag konobangu-testing-torrents:late
|
|||||||
## Run
|
## Run
|
||||||
|
|
||||||
```bash
|
```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
|
## Publish
|
||||||
|
Loading…
Reference in New Issue
Block a user