diff --git a/src/cli/sonarr/mod.rs b/src/cli/sonarr/mod.rs index d5b69af..5b42ee3 100644 --- a/src/cli/sonarr/mod.rs +++ b/src/cli/sonarr/mod.rs @@ -285,7 +285,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrCommand> for SonarrCliHandler<'a, ' let resp = self .network .handle_network_event( - SonarrEvent::ToggleSeasonMonitoring(Some((series_id, season_number))).into(), + SonarrEvent::ToggleSeasonMonitoring((series_id, season_number)).into(), ) .await?; serde_json::to_string_pretty(&resp)? diff --git a/src/cli/sonarr/sonarr_command_tests.rs b/src/cli/sonarr/sonarr_command_tests.rs index 7b4da78..e6a06c3 100644 --- a/src/cli/sonarr/sonarr_command_tests.rs +++ b/src/cli/sonarr/sonarr_command_tests.rs @@ -729,8 +729,7 @@ mod tests { mock_network .expect_handle_network_event() .with(eq::( - SonarrEvent::ToggleSeasonMonitoring(Some((expected_series_id, expected_season_number))) - .into(), + SonarrEvent::ToggleSeasonMonitoring((expected_series_id, expected_season_number)).into(), )) .times(1) .returning(|_| { diff --git a/src/handlers/sonarr_handlers/library/series_details_handler.rs b/src/handlers/sonarr_handlers/library/series_details_handler.rs index d3201d2..e2caa39 100644 --- a/src/handlers/sonarr_handlers/library/series_details_handler.rs +++ b/src/handlers/sonarr_handlers/library/series_details_handler.rs @@ -37,6 +37,18 @@ impl<'a, 'b> SeriesDetailsHandler<'a, 'b> { .expect("Series history is undefined"), SonarrHistoryItem ); + fn extract_series_id_season_number_tuple(&self) -> (i64, i64) { + let series_id = self.app.data.sonarr_data.series.current_selection().id; + let season_number = self + .app + .data + .sonarr_data + .seasons + .current_selection() + .season_number; + + (series_id, season_number) + } } impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler<'a, 'b> { @@ -259,8 +271,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler } _ if key == DEFAULT_KEYBINDINGS.toggle_monitoring.key => { self.app.data.sonarr_data.prompt_confirm = true; - self.app.data.sonarr_data.prompt_confirm_action = - Some(SonarrEvent::ToggleSeasonMonitoring(None)); + self.app.data.sonarr_data.prompt_confirm_action = Some( + SonarrEvent::ToggleSeasonMonitoring(self.extract_series_id_season_number_tuple()), + ); self .app diff --git a/src/handlers/sonarr_handlers/library/series_details_handler_tests.rs b/src/handlers/sonarr_handlers/library/series_details_handler_tests.rs index 3973547..e1ca9b6 100644 --- a/src/handlers/sonarr_handlers/library/series_details_handler_tests.rs +++ b/src/handlers/sonarr_handlers/library/series_details_handler_tests.rs @@ -4,6 +4,7 @@ mod tests { use crate::app::App; use crate::event::Key; use crate::handlers::sonarr_handlers::library::series_details_handler::SeriesDetailsHandler; + use crate::handlers::sonarr_handlers::sonarr_handler_test_utils::utils::{season, series}; use crate::handlers::KeyEventHandler; use crate::models::servarr_data::sonarr::sonarr_data::{ ActiveSonarrBlock, SERIES_DETAILS_BLOCKS, @@ -11,6 +12,7 @@ mod tests { use crate::models::sonarr_models::Season; use crate::models::sonarr_models::SonarrHistoryItem; use crate::models::stateful_table::StatefulTable; + use pretty_assertions::assert_eq; use rstest::rstest; use strum::IntoEnumIterator; @@ -398,7 +400,7 @@ mod tests { assert!(app.is_routing); assert_eq!( app.data.sonarr_data.prompt_confirm_action, - Some(SonarrEvent::ToggleSeasonMonitoring(None)) + Some(SonarrEvent::ToggleSeasonMonitoring((0, 0))) ); } @@ -610,6 +612,23 @@ mod tests { }); } + #[test] + fn test_extract_series_id_season_number_tuple() { + let mut app = App::default(); + app.data.sonarr_data.series.set_items(vec![series()]); + app.data.sonarr_data.seasons.set_items(vec![season()]); + + let series_id_season_number_tuple = SeriesDetailsHandler::with( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveSonarrBlock::SeriesDetails, + None, + ) + .extract_series_id_season_number_tuple(); + + assert_eq!(series_id_season_number_tuple, (1, 1)); + } + #[test] fn test_series_details_handler_is_not_ready_when_loading() { let mut app = App::default(); diff --git a/src/network/sonarr_network.rs b/src/network/sonarr_network.rs index 26adf2f..81142b0 100644 --- a/src/network/sonarr_network.rs +++ b/src/network/sonarr_network.rs @@ -86,7 +86,7 @@ pub enum SonarrEvent { StartTask(SonarrTaskName), TestIndexer(i64), TestAllIndexers, - ToggleSeasonMonitoring(Option<(i64, i64)>), + ToggleSeasonMonitoring((i64, i64)), ToggleEpisodeMonitoring(Option), TriggerAutomaticEpisodeSearch(Option), TriggerAutomaticSeasonSearch(Option<(i64, i64)>), @@ -967,86 +967,81 @@ impl<'a, 'b> Network<'a, 'b> { async fn toggle_sonarr_season_monitoring( &mut self, - series_id_season_number_tuple: Option<(i64, i64)>, + series_id_season_number_tuple: (i64, i64), ) -> Result<()> { let event = SonarrEvent::ToggleSeasonMonitoring(series_id_season_number_tuple); - let (series_id, season_number) = - if let Some((series_id, season_number)) = series_id_season_number_tuple { - (Some(series_id), Some(season_number)) - } else { - (None, None) - }; + let (series_id, season_number) = series_id_season_number_tuple; - let (series_id, _) = self.extract_series_id(series_id).await; let detail_event = SonarrEvent::GetSeriesDetails(series_id); - if let Ok((season_number, _)) = self.extract_season_number(season_number).await { - info!("Toggling season monitoring for season {season_number} in series with ID: {series_id}"); - info!("Fetching series details for series with ID: {series_id}"); + info!("Toggling season monitoring for season {season_number} in series with ID: {series_id}"); + info!("Fetching series details for series with ID: {series_id}"); - let request_props = self - .request_props_from( - detail_event, - RequestMethod::Get, - None::<()>, - Some(format!("/{series_id}")), - None, - ) - .await; + let request_props = self + .request_props_from( + detail_event, + RequestMethod::Get, + None::<()>, + Some(format!("/{series_id}")), + None, + ) + .await; - let mut response = String::new(); + let mut response = String::new(); - self - .handle_request::<(), Value>(request_props, |detailed_series_body, _| { - response = detailed_series_body.to_string() - }) - .await?; + self + .handle_request::<(), Value>(request_props, |detailed_series_body, _| { + response = detailed_series_body.to_string() + }) + .await?; - info!("Constructing toggle season monitoring body"); + info!("Constructing toggle season monitoring body"); - let mut detailed_series_body: Value = - serde_json::from_str(&response).expect("Request for detailed series body was interrupted"); - let monitored = detailed_series_body - .get("seasons") - .unwrap() - .as_array() - .unwrap() - .iter() - .find(|season| season["seasonNumber"] == season_number) - .unwrap() - .get("monitored") - .unwrap() - .as_bool() - .unwrap(); + match serde_json::from_str::(&response) { + Ok(mut detailed_series_body) => { + let monitored = detailed_series_body + .get("seasons") + .unwrap() + .as_array() + .unwrap() + .iter() + .find(|season| season["seasonNumber"] == season_number) + .unwrap() + .get("monitored") + .unwrap() + .as_bool() + .unwrap(); - *detailed_series_body - .get_mut("seasons") - .unwrap() - .as_array_mut() - .unwrap() - .iter_mut() - .find(|season| season["seasonNumber"] == season_number) - .unwrap() - .get_mut("monitored") - .unwrap() = json!(!monitored); + *detailed_series_body + .get_mut("seasons") + .unwrap() + .as_array_mut() + .unwrap() + .iter_mut() + .find(|season| season["seasonNumber"] == season_number) + .unwrap() + .get_mut("monitored") + .unwrap() = json!(!monitored); - debug!("Toggle season monitoring body: {detailed_series_body:?}"); + debug!("Toggle season monitoring body: {detailed_series_body:?}"); - let request_props = self - .request_props_from( - event, - RequestMethod::Put, - Some(detailed_series_body), - Some(format!("/{series_id}")), - None, - ) - .await; + let request_props = self + .request_props_from( + event, + RequestMethod::Put, + Some(detailed_series_body), + Some(format!("/{series_id}")), + None, + ) + .await; - self - .handle_request::(request_props, |_, _| ()) - .await - } else { - warn!("Season number was not provided. Aborting..."); - Ok(()) + self + .handle_request::(request_props, |_, _| ()) + .await + } + Err(_) => { + warn!("Request for detailed series body was interrupted"); + Ok(()) + } } } diff --git a/src/network/sonarr_network_tests.rs b/src/network/sonarr_network_tests.rs index 9a69e68..43c6d5c 100644 --- a/src/network/sonarr_network_tests.rs +++ b/src/network/sonarr_network_tests.rs @@ -162,7 +162,7 @@ mod test { SonarrEvent::GetSeriesDetails(0), SonarrEvent::DeleteSeries(DeleteSeriesParams::default()), SonarrEvent::EditSeries(EditSeriesParams::default()), - SonarrEvent::ToggleSeasonMonitoring(None) + SonarrEvent::ToggleSeasonMonitoring((0, 0)) )] event: SonarrEvent, ) { @@ -5145,7 +5145,7 @@ mod test { "PUT", format!( "/api/v3{}/1", - SonarrEvent::ToggleSeasonMonitoring(None).resource() + SonarrEvent::ToggleSeasonMonitoring((1, 1)).resource() ) .as_str(), ) @@ -5162,72 +5162,7 @@ mod test { let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); assert!(network - .handle_sonarr_event(SonarrEvent::ToggleSeasonMonitoring(None)) - .await - .is_ok()); - - async_details_server.assert_async().await; - async_toggle_server.assert_async().await; - } - - #[tokio::test] - async fn test_handle_toggle_season_monitoring_event_uses_provided_series_id_and_season_number() { - let mut detailed_response: Value = serde_json::from_str(SERIES_JSON).unwrap(); - *detailed_response - .get_mut("seasons") - .unwrap() - .as_array_mut() - .unwrap() - .iter_mut() - .find(|season| season["seasonNumber"] == 1) - .unwrap() - .get_mut("seasonNumber") - .unwrap() = json!(2); - let mut expected_body: Value = detailed_response.clone(); - *expected_body - .get_mut("seasons") - .unwrap() - .as_array_mut() - .unwrap() - .iter_mut() - .find(|season| season["seasonNumber"] == 2) - .unwrap() - .get_mut("monitored") - .unwrap() = json!(false); - - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(detailed_response), - None, - SonarrEvent::GetSeriesDetails(2), - Some("/2"), - None, - ) - .await; - let async_toggle_server = server - .mock( - "PUT", - format!( - "/api/v3{}/2", - SonarrEvent::ToggleSeasonMonitoring(Some((2, 2))).resource() - ) - .as_str(), - ) - .with_status(202) - .match_header("X-Api-Key", "test1234") - .match_body(Matcher::Json(expected_body)) - .create_async() - .await; - { - let mut app = app_arc.lock().await; - app.data.sonarr_data.series.set_items(vec![series()]); - app.data.sonarr_data.seasons.set_items(vec![season()]); - } - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); - - assert!(network - .handle_sonarr_event(SonarrEvent::ToggleSeasonMonitoring(Some((2, 2)))) + .handle_sonarr_event(SonarrEvent::ToggleSeasonMonitoring((1, 1))) .await .is_ok());