From 33db3efacfb977c7269b9163247f96f5c1c4ee84 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Fri, 22 Nov 2024 16:57:09 -0700 Subject: [PATCH] feat(network): Support for starting a Sonarr task --- src/models/radarr_models.rs | 6 --- src/models/servarr_models.rs | 6 +++ src/network/radarr_network.rs | 20 ++++----- src/network/radarr_network_tests.rs | 4 +- src/network/sonarr_network.rs | 43 ++++++++++++++++-- src/network/sonarr_network_tests.rs | 68 ++++++++++++++++++++++++++++- 6 files changed, 125 insertions(+), 22 deletions(-) diff --git a/src/models/radarr_models.rs b/src/models/radarr_models.rs index 28fa649..080ae3f 100644 --- a/src/models/radarr_models.rs +++ b/src/models/radarr_models.rs @@ -116,12 +116,6 @@ pub struct CollectionMovie { pub ratings: RatingsList, } -#[derive(Default, Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct CommandBody { - pub name: String, -} - #[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct Credit { diff --git a/src/models/servarr_models.rs b/src/models/servarr_models.rs index 9c95dcb..3c2b5c1 100644 --- a/src/models/servarr_models.rs +++ b/src/models/servarr_models.rs @@ -74,6 +74,12 @@ impl Display for CertificateValidation { } } +#[derive(Default, Serialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct CommandBody { + pub name: String, +} + #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] #[serde(rename_all = "camelCase")] pub struct DiskSpace { diff --git a/src/network/radarr_network.rs b/src/network/radarr_network.rs index 1bf6b7e..e2c629b 100644 --- a/src/network/radarr_network.rs +++ b/src/network/radarr_network.rs @@ -8,10 +8,9 @@ use urlencoding::encode; use crate::models::radarr_models::{ AddMovieBody, AddMovieSearchResult, AddOptions, BlocklistResponse, Collection, CollectionMovie, - CommandBody, Credit, CreditType, DeleteMovieParams, DownloadRecord, DownloadsResponse, - EditCollectionParams, EditIndexerParams, EditMovieParams, IndexerSettings, IndexerTestResult, - Movie, MovieCommandBody, MovieHistoryItem, RadarrSerdeable, RadarrTask, RadarrTaskName, - ReleaseDownloadBody, SystemStatus, + Credit, CreditType, DeleteMovieParams, DownloadRecord, DownloadsResponse, EditCollectionParams, + EditIndexerParams, EditMovieParams, IndexerSettings, IndexerTestResult, Movie, MovieCommandBody, + MovieHistoryItem, RadarrSerdeable, RadarrTask, RadarrTaskName, ReleaseDownloadBody, SystemStatus, }; use crate::models::servarr_data::radarr::modals::{ AddMovieModal, EditCollectionModal, EditIndexerModal, EditMovieModal, IndexerTestResultModalItem, @@ -19,8 +18,8 @@ use crate::models::servarr_data::radarr::modals::{ }; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::servarr_models::{ - AddRootFolderBody, DiskSpace, HostConfig, Indexer, LogResponse, QualityProfile, QueueEvent, - Release, RootFolder, SecurityConfig, Tag, Update, + AddRootFolderBody, CommandBody, DiskSpace, HostConfig, Indexer, LogResponse, QualityProfile, + QueueEvent, Release, RootFolder, SecurityConfig, Tag, Update, }; use crate::models::stateful_table::StatefulTable; use crate::models::{HorizontallyScrollableText, Route, Scrollable, ScrollableText}; @@ -252,9 +251,10 @@ impl<'a, 'b> Network<'a, 'b> { RadarrEvent::SearchNewMovie(query) => { self.search_movie(query).await.map(RadarrSerdeable::from) } - RadarrEvent::StartTask(task_name) => { - self.start_task(task_name).await.map(RadarrSerdeable::from) - } + RadarrEvent::StartTask(task_name) => self + .start_radarr_task(task_name) + .await + .map(RadarrSerdeable::from), RadarrEvent::TestIndexer(indexer_id) => self .test_indexer(indexer_id) .await @@ -2006,7 +2006,7 @@ impl<'a, 'b> Network<'a, 'b> { } } - async fn start_task(&mut self, task: Option) -> Result { + async fn start_radarr_task(&mut self, task: Option) -> Result { let event = RadarrEvent::StartTask(None); let task_name = if let Some(t_name) = task { t_name diff --git a/src/network/radarr_network_tests.rs b/src/network/radarr_network_tests.rs index 1f0dc5f..edda118 100644 --- a/src/network/radarr_network_tests.rs +++ b/src/network/radarr_network_tests.rs @@ -713,7 +713,7 @@ mod test { } #[tokio::test] - async fn test_handle_start_task_event() { + async fn test_handle_start_radarr_task_event() { let response = json!({ "test": "test"}); let (async_server, app_arc, _server) = mock_servarr_api( RequestMethod::Post, @@ -750,7 +750,7 @@ mod test { } #[tokio::test] - async fn test_handle_start_task_event_uses_provided_task_name() { + async fn test_handle_start_radarr_task_event_uses_provided_task_name() { let response = json!({ "test": "test"}); let (async_server, app_arc, _server) = mock_servarr_api( RequestMethod::Post, diff --git a/src/network/sonarr_network.rs b/src/network/sonarr_network.rs index adb9f8e..9aa4b62 100644 --- a/src/network/sonarr_network.rs +++ b/src/network/sonarr_network.rs @@ -10,12 +10,13 @@ use crate::{ sonarr_data::ActiveSonarrBlock, }, servarr_models::{ - AddRootFolderBody, DiskSpace, HostConfig, Indexer, LogResponse, QualityProfile, QueueEvent, - Release, RootFolder, SecurityConfig, Tag, Update, + AddRootFolderBody, CommandBody, DiskSpace, HostConfig, Indexer, LogResponse, QualityProfile, + QueueEvent, Release, RootFolder, SecurityConfig, Tag, Update, }, sonarr_models::{ BlocklistResponse, DownloadRecord, DownloadsResponse, Episode, IndexerSettings, Series, - SonarrHistoryItem, SonarrHistoryWrapper, SonarrSerdeable, SonarrTask, SystemStatus, + SonarrHistoryItem, SonarrHistoryWrapper, SonarrSerdeable, SonarrTask, SonarrTaskName, + SystemStatus, }, stateful_table::StatefulTable, HorizontallyScrollableText, Route, Scrollable, ScrollableText, @@ -65,6 +66,7 @@ pub enum SonarrEvent { HealthCheck, ListSeries, MarkHistoryItemAsFailed(i64), + StartTask(Option), } impl NetworkResource for SonarrEvent { @@ -95,6 +97,7 @@ impl NetworkResource for SonarrEvent { SonarrEvent::HealthCheck => "/health", SonarrEvent::ListSeries | SonarrEvent::GetSeriesDetails(_) => "/series", SonarrEvent::MarkHistoryItemAsFailed(_) => "/history/failed", + SonarrEvent::StartTask(_) => "/command", } } } @@ -217,6 +220,10 @@ impl<'a, 'b> Network<'a, 'b> { .mark_sonarr_history_item_as_failed(history_item_id) .await .map(SonarrSerdeable::from), + SonarrEvent::StartTask(task_name) => self + .start_sonarr_task(task_name) + .await + .map(SonarrSerdeable::from), } } @@ -1274,6 +1281,36 @@ impl<'a, 'b> Network<'a, 'b> { .await } + async fn start_sonarr_task(&mut self, task: Option) -> Result { + let event = SonarrEvent::StartTask(None); + let task_name = if let Some(t_name) = task { + t_name + } else { + self + .app + .lock() + .await + .data + .sonarr_data + .tasks + .current_selection() + .task_name + } + .to_string(); + + info!("Starting Sonarr task: {task_name}"); + + let body = CommandBody { name: task_name }; + + let request_props = self + .request_props_from(event, RequestMethod::Post, Some(body), None, None) + .await; + + self + .handle_request::(request_props, |_, _| ()) + .await + } + async fn extract_series_id(&mut self, series_id: Option) -> (i64, String) { let series_id = if let Some(id) = series_id { id diff --git a/src/network/sonarr_network_tests.rs b/src/network/sonarr_network_tests.rs index 9834011..39dfccf 100644 --- a/src/network/sonarr_network_tests.rs +++ b/src/network/sonarr_network_tests.rs @@ -159,7 +159,9 @@ mod test { } #[rstest] - fn test_resource_command(#[values(SonarrEvent::GetQueuedEvents)] event: SonarrEvent) { + fn test_resource_command( + #[values(SonarrEvent::GetQueuedEvents, SonarrEvent::StartTask(None))] event: SonarrEvent, + ) { assert_str_eq!(event.resource(), "/command"); } @@ -3861,6 +3863,70 @@ mod test { async_server.assert_async().await; } + #[tokio::test] + async fn test_handle_start_sonarr_task_event() { + let response = json!({ "test": "test"}); + let (async_server, app_arc, _server) = mock_servarr_api( + RequestMethod::Post, + Some(json!({ + "name": "ApplicationUpdateCheck" + })), + Some(response.clone()), + None, + SonarrEvent::StartTask(None), + None, + None, + ) + .await; + app_arc + .lock() + .await + .data + .sonarr_data + .tasks + .set_items(vec![SonarrTask { + task_name: SonarrTaskName::default(), + ..SonarrTask::default() + }]); + let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + + if let SonarrSerdeable::Value(value) = network + .handle_sonarr_event(SonarrEvent::StartTask(None)) + .await + .unwrap() + { + async_server.assert_async().await; + assert_eq!(value, response); + } + } + + #[tokio::test] + async fn test_handle_start_sonarr_task_event_uses_provided_task_name() { + let response = json!({ "test": "test"}); + let (async_server, app_arc, _server) = mock_servarr_api( + RequestMethod::Post, + Some(json!({ + "name": "ApplicationUpdateCheck" + })), + Some(response.clone()), + None, + SonarrEvent::StartTask(None), + None, + None, + ) + .await; + let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + + if let SonarrSerdeable::Value(value) = network + .handle_sonarr_event(SonarrEvent::StartTask(Some(SonarrTaskName::default()))) + .await + .unwrap() + { + async_server.assert_async().await; + assert_eq!(value, response); + } + } + #[tokio::test] async fn test_extract_series_id() { let app_arc = Arc::new(Mutex::new(App::default()));