feat: Downloads tab support in Lidarr

This commit is contained in:
2026-01-13 13:40:18 -07:00
parent e1a25bfaf2
commit c68cd75015
32 changed files with 1551 additions and 165 deletions
@@ -2,10 +2,37 @@
mod tests {
use crate::models::lidarr_models::{DownloadsResponse, LidarrSerdeable};
use crate::network::lidarr_network::LidarrEvent;
use crate::network::lidarr_network::lidarr_network_test_utils::test_utils::download_record;
use crate::network::network_tests::test_utils::{MockServarrApi, test_network};
use pretty_assertions::assert_eq;
use serde_json::json;
#[tokio::test]
async fn test_handle_delete_lidarr_download_event() {
let (mock, app, _server) = MockServarrApi::delete()
.path("/1")
.build_for(LidarrEvent::DeleteDownload(1))
.await;
app
.lock()
.await
.data
.lidarr_data
.downloads
.set_items(vec![download_record()]);
app.lock().await.server_tabs.set_index(2);
let mut network = test_network(&app);
assert!(
network
.handle_lidarr_event(LidarrEvent::DeleteDownload(1))
.await
.is_ok()
);
mock.assert_async().await;
}
#[tokio::test]
async fn test_handle_get_downloads_event() {
let downloads_json = json!({
@@ -40,4 +67,26 @@ mod tests {
assert_eq!(downloads_response, response);
assert!(!app.lock().await.data.lidarr_data.downloads.is_empty());
}
#[tokio::test]
async fn test_handle_update_lidarr_downloads_event() {
let (mock, app, _server) = MockServarrApi::post()
.with_request_body(json!({
"name": "RefreshMonitoredDownloads"
}))
.returns(json!({}))
.build_for(LidarrEvent::UpdateDownloads)
.await;
app.lock().await.server_tabs.set_index(2);
let mut network = test_network(&app);
assert!(
network
.handle_lidarr_event(LidarrEvent::UpdateDownloads)
.await
.is_ok()
);
mock.assert_async().await;
}
}
+44 -3
View File
@@ -1,15 +1,38 @@
use anyhow::Result;
use log::info;
use crate::models::lidarr_models::DownloadsResponse;
use crate::models::servarr_models::CommandBody;
use crate::network::lidarr_network::LidarrEvent;
use crate::network::{Network, RequestMethod};
use anyhow::Result;
use log::info;
use serde_json::Value;
#[cfg(test)]
#[path = "lidarr_downloads_network_tests.rs"]
mod lidarr_downloads_network_tests;
impl Network<'_, '_> {
pub(in crate::network::lidarr_network) async fn delete_lidarr_download(
&mut self,
download_id: i64,
) -> Result<()> {
let event = LidarrEvent::DeleteDownload(download_id);
info!("Deleting Lidarr download for download with id: {download_id}");
let request_props = self
.request_props_from(
event,
RequestMethod::Delete,
None::<()>,
Some(format!("/{download_id}")),
None,
)
.await;
self
.handle_request::<(), ()>(request_props, |_, _| ())
.await
}
pub(in crate::network::lidarr_network) async fn get_lidarr_downloads(
&mut self,
count: u64,
@@ -37,4 +60,22 @@ impl Network<'_, '_> {
})
.await
}
pub(in crate::network::lidarr_network) async fn update_lidarr_downloads(
&mut self,
) -> Result<Value> {
info!("Updating Lidarr downloads");
let event = LidarrEvent::UpdateDownloads;
let body = CommandBody {
name: "RefreshMonitoredDownloads".to_owned(),
};
let request_props = self
.request_props_from(event, RequestMethod::Post, Some(body), None, None)
.await;
self
.handle_request::<CommandBody, Value>(request_props, |_, _| ())
.await
}
}
@@ -30,6 +30,13 @@ mod tests {
assert_str_eq!(event.resource(), "/artist");
}
#[rstest]
fn test_resource_downloads(
#[values(LidarrEvent::GetDownloads(0), LidarrEvent::DeleteDownload(0))] event: LidarrEvent,
) {
assert_str_eq!(event.resource(), "/queue");
}
#[rstest]
fn test_resource_history(#[values(LidarrEvent::GetHistory(0))] event: LidarrEvent) {
assert_str_eq!(event.resource(), "/history");
@@ -59,7 +66,8 @@ mod tests {
#[values(
LidarrEvent::UpdateAllArtists,
LidarrEvent::TriggerAutomaticArtistSearch(0),
LidarrEvent::UpdateAndScanArtist(0)
LidarrEvent::UpdateAndScanArtist(0),
LidarrEvent::UpdateDownloads
)]
event: LidarrEvent,
) {
@@ -81,7 +89,6 @@ mod tests {
#[rstest]
#[case(LidarrEvent::GetDiskSpace, "/diskspace")]
#[case(LidarrEvent::GetDownloads(500), "/queue")]
#[case(LidarrEvent::GetMetadataProfiles, "/metadataprofile")]
#[case(LidarrEvent::GetQualityProfiles, "/qualityprofile")]
#[case(LidarrEvent::GetRootFolders, "/rootfolder")]
+13 -2
View File
@@ -28,6 +28,7 @@ pub enum LidarrEvent {
AddTag(String),
DeleteAlbum(DeleteParams),
DeleteArtist(DeleteParams),
DeleteDownload(i64),
DeleteTag(i64),
EditArtist(EditArtistParams),
GetAlbums(i64),
@@ -52,6 +53,7 @@ pub enum LidarrEvent {
TriggerAutomaticArtistSearch(i64),
UpdateAllArtists,
UpdateAndScanArtist(i64),
UpdateDownloads,
}
impl NetworkResource for LidarrEvent {
@@ -69,13 +71,14 @@ impl NetworkResource for LidarrEvent {
| LidarrEvent::GetAlbumDetails(_)
| LidarrEvent::DeleteAlbum(_) => "/album",
LidarrEvent::GetDiskSpace => "/diskspace",
LidarrEvent::GetDownloads(_) => "/queue",
LidarrEvent::GetDownloads(_) | LidarrEvent::DeleteDownload(_) => "/queue",
LidarrEvent::GetHistory(_) => "/history",
LidarrEvent::MarkHistoryItemAsFailed(_) => "/history/failed",
LidarrEvent::GetHostConfig | LidarrEvent::GetSecurityConfig => "/config/host",
LidarrEvent::TriggerAutomaticArtistSearch(_)
| LidarrEvent::UpdateAllArtists
| LidarrEvent::UpdateAndScanArtist(_) => "/command",
| LidarrEvent::UpdateAndScanArtist(_)
| LidarrEvent::UpdateDownloads => "/command",
LidarrEvent::GetMetadataProfiles => "/metadataprofile",
LidarrEvent::GetQualityProfiles => "/qualityprofile",
LidarrEvent::GetRootFolders => "/rootfolder",
@@ -105,6 +108,10 @@ impl Network<'_, '_> {
LidarrEvent::DeleteArtist(params) => {
self.delete_artist(params).await.map(LidarrSerdeable::from)
}
LidarrEvent::DeleteDownload(download_id) => self
.delete_lidarr_download(download_id)
.await
.map(LidarrSerdeable::from),
LidarrEvent::DeleteTag(tag_id) => self
.delete_lidarr_tag(tag_id)
.await
@@ -182,6 +189,10 @@ impl Network<'_, '_> {
.map(LidarrSerdeable::from),
LidarrEvent::EditArtist(params) => self.edit_artist(params).await.map(LidarrSerdeable::from),
LidarrEvent::AddArtist(body) => self.add_artist(body).await.map(LidarrSerdeable::from),
LidarrEvent::UpdateDownloads => self
.update_lidarr_downloads()
.await
.map(LidarrSerdeable::from),
}
}