From 77b8b61079e45718c97f21759d45c65c140885e6 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Tue, 17 Dec 2024 17:29:21 -0700 Subject: [PATCH] fix(radarr): Construct and pass params when publishing the EditIndexer event to the networking channel --- src/app/radarr/radarr_tests.rs | 2 +- src/cli/radarr/add_command_handler.rs | 2 +- src/cli/radarr/add_command_handler_tests.rs | 2 +- src/cli/radarr/edit_command_handler.rs | 3 +- src/cli/radarr/edit_command_handler_tests.rs | 9 +- src/cli/sonarr/edit_command_handler.rs | 1 + src/cli/sonarr/edit_command_handler_tests.rs | 1 + .../indexers/edit_indexer_handler.rs | 60 ++- .../indexers/edit_indexer_handler_tests.rs | 108 ++++- .../library/add_movie_handler.rs | 2 +- .../radarr_handler_test_utils.rs | 2 +- src/models/radarr_models.rs | 2 +- src/models/servarr_models.rs | 2 + src/network/radarr_network.rs | 109 ++--- src/network/radarr_network_tests.rs | 378 +++++++++--------- 15 files changed, 396 insertions(+), 287 deletions(-) diff --git a/src/app/radarr/radarr_tests.rs b/src/app/radarr/radarr_tests.rs index 5745f52..bd76b96 100644 --- a/src/app/radarr/radarr_tests.rs +++ b/src/app/radarr/radarr_tests.rs @@ -93,7 +93,7 @@ mod tests { monitored: true, quality_profile_id: 2222, tags: vec![1, 2], - tag_input_string: String::new(), + tag_input_string: None, add_options: AddMovieOptions { monitor: "movieOnly".to_owned(), search_for_movie: true, diff --git a/src/cli/radarr/add_command_handler.rs b/src/cli/radarr/add_command_handler.rs index c41bd64..e96cceb 100644 --- a/src/cli/radarr/add_command_handler.rs +++ b/src/cli/radarr/add_command_handler.rs @@ -125,7 +125,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrAddCommand> for RadarrAddCommandHan minimum_availability: minimum_availability.to_string(), monitored: !disable_monitoring, tags, - tag_input_string: String::new(), + tag_input_string: None, add_options: AddMovieOptions { monitor: monitor.to_string(), search_for_movie: !no_search_for_movie, diff --git a/src/cli/radarr/add_command_handler_tests.rs b/src/cli/radarr/add_command_handler_tests.rs index e1bbf53..ac5af65 100644 --- a/src/cli/radarr/add_command_handler_tests.rs +++ b/src/cli/radarr/add_command_handler_tests.rs @@ -382,7 +382,7 @@ mod tests { minimum_availability: "released".to_owned(), monitored: false, tags: vec![1, 2], - tag_input_string: String::new(), + tag_input_string: None, add_options: AddMovieOptions { monitor: "movieAndCollection".to_owned(), search_for_movie: false, diff --git a/src/cli/radarr/edit_command_handler.rs b/src/cli/radarr/edit_command_handler.rs index 186a9c3..275575b 100644 --- a/src/cli/radarr/edit_command_handler.rs +++ b/src/cli/radarr/edit_command_handler.rs @@ -455,13 +455,14 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrEditCommand> for RadarrEditCommandH api_key, seed_ratio, tags: tag, + tag_input_string: None, priority, clear_tags, }; self .network - .handle_network_event(RadarrEvent::EditIndexer(Some(edit_indexer_params)).into()) + .handle_network_event(RadarrEvent::EditIndexer(edit_indexer_params).into()) .await?; "Indexer updated".to_owned() } diff --git a/src/cli/radarr/edit_command_handler_tests.rs b/src/cli/radarr/edit_command_handler_tests.rs index 4345e3a..489ff93 100644 --- a/src/cli/radarr/edit_command_handler_tests.rs +++ b/src/cli/radarr/edit_command_handler_tests.rs @@ -1171,6 +1171,7 @@ mod tests { api_key: Some("testKey".to_owned()), seed_ratio: Some("1.2".to_owned()), tags: Some(vec![1, 2]), + tag_input_string: None, priority: Some(25), clear_tags: false, }; @@ -1178,7 +1179,7 @@ mod tests { mock_network .expect_handle_network_event() .with(eq::( - RadarrEvent::EditIndexer(Some(expected_edit_indexer_params)).into(), + RadarrEvent::EditIndexer(expected_edit_indexer_params).into(), )) .times(1) .returning(|_| { @@ -1224,6 +1225,7 @@ mod tests { api_key: Some("testKey".to_owned()), seed_ratio: Some("1.2".to_owned()), tags: Some(vec![1, 2]), + tag_input_string: None, priority: Some(25), clear_tags: false, }; @@ -1231,7 +1233,7 @@ mod tests { mock_network .expect_handle_network_event() .with(eq::( - RadarrEvent::EditIndexer(Some(expected_edit_indexer_params)).into(), + RadarrEvent::EditIndexer(expected_edit_indexer_params).into(), )) .times(1) .returning(|_| { @@ -1277,6 +1279,7 @@ mod tests { api_key: Some("testKey".to_owned()), seed_ratio: Some("1.2".to_owned()), tags: Some(vec![1, 2]), + tag_input_string: None, priority: Some(25), clear_tags: false, }; @@ -1284,7 +1287,7 @@ mod tests { mock_network .expect_handle_network_event() .with(eq::( - RadarrEvent::EditIndexer(Some(expected_edit_indexer_params)).into(), + RadarrEvent::EditIndexer(expected_edit_indexer_params).into(), )) .times(1) .returning(|_| { diff --git a/src/cli/sonarr/edit_command_handler.rs b/src/cli/sonarr/edit_command_handler.rs index bd879c3..cd2becf 100644 --- a/src/cli/sonarr/edit_command_handler.rs +++ b/src/cli/sonarr/edit_command_handler.rs @@ -312,6 +312,7 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrEditCommand> for SonarrEditCommandH api_key, seed_ratio, tags: tag, + tag_input_string: None, priority, clear_tags, }; diff --git a/src/cli/sonarr/edit_command_handler_tests.rs b/src/cli/sonarr/edit_command_handler_tests.rs index eaef63f..4e146a3 100644 --- a/src/cli/sonarr/edit_command_handler_tests.rs +++ b/src/cli/sonarr/edit_command_handler_tests.rs @@ -689,6 +689,7 @@ mod tests { api_key: Some("testKey".to_owned()), seed_ratio: Some("1.2".to_owned()), tags: Some(vec![1, 2]), + tag_input_string: None, priority: Some(25), clear_tags: false, }; diff --git a/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs b/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs index 7c0f936..44556a6 100644 --- a/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs +++ b/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs @@ -2,7 +2,9 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS; use crate::app::App; use crate::event::Key; use crate::handlers::{handle_prompt_toggle, KeyEventHandler}; +use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS}; +use crate::models::servarr_models::EditIndexerParams; use crate::network::radarr_network::RadarrEvent; use crate::{handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys}; @@ -17,6 +19,55 @@ pub(super) struct EditIndexerHandler<'a, 'b> { _context: Option, } +impl<'a, 'b> EditIndexerHandler<'a, 'b> { + fn build_edit_indexer_params(&mut self) -> EditIndexerParams { + let indexer_id = self.app.data.radarr_data.indexers.current_selection().id; + let tags = self + .app + .data + .radarr_data + .edit_indexer_modal + .as_ref() + .unwrap() + .tags + .text + .clone(); + + let params = { + let EditIndexerModal { + name, + enable_rss, + enable_automatic_search, + enable_interactive_search, + url, + api_key, + seed_ratio, + priority, + .. + } = self.app.data.radarr_data.edit_indexer_modal.as_ref().unwrap(); + + EditIndexerParams { + indexer_id, + name: Some(name.text.clone()), + enable_rss: Some(enable_rss.unwrap_or_default()), + enable_automatic_search: Some(enable_automatic_search.unwrap_or_default()), + enable_interactive_search: Some(enable_interactive_search.unwrap_or_default()), + url: Some(url.text.clone()), + api_key: Some(api_key.text.clone()), + seed_ratio: Some(seed_ratio.text.clone()), + tags: None, + tag_input_string: Some(tags), + priority: Some(*priority), + clear_tags: false, + } + }; + + self.app.data.radarr_data.edit_indexer_modal = None; + + params + } +} + impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'a, 'b> { fn accepts(active_block: ActiveRadarrBlock) -> bool { EDIT_INDEXER_BLOCKS.contains(&active_block) @@ -297,12 +348,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<' let selected_block = self.app.data.radarr_data.selected_block.get_active_block(); match selected_block { ActiveRadarrBlock::EditIndexerConfirmPrompt => { - let radarr_data = &mut self.app.data.radarr_data; - if radarr_data.prompt_confirm { - radarr_data.prompt_confirm_action = Some(RadarrEvent::EditIndexer(None)); + if self.app.data.radarr_data.prompt_confirm { + self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditIndexer(self.build_edit_indexer_params())); self.app.should_refresh = true; } else { - radarr_data.edit_indexer_modal = None; + self.app.data.radarr_data.edit_indexer_modal = None; } self.app.pop_navigation_stack(); @@ -464,7 +514,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<' && self.key == DEFAULT_KEYBINDINGS.confirm.key { self.app.data.radarr_data.prompt_confirm = true; - self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditIndexer(None)); + self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditIndexer(self.build_edit_indexer_params())); self.app.should_refresh = true; self.app.pop_navigation_stack(); diff --git a/src/handlers/radarr_handlers/indexers/edit_indexer_handler_tests.rs b/src/handlers/radarr_handlers/indexers/edit_indexer_handler_tests.rs index 9325c65..7bd6f11 100644 --- a/src/handlers/radarr_handlers/indexers/edit_indexer_handler_tests.rs +++ b/src/handlers/radarr_handlers/indexers/edit_indexer_handler_tests.rs @@ -4,9 +4,12 @@ mod tests { use crate::app::App; use crate::event::Key; use crate::handlers::radarr_handlers::indexers::edit_indexer_handler::EditIndexerHandler; + use crate::handlers::radarr_handlers::radarr_handler_test_utils::utils::indexer; use crate::handlers::KeyEventHandler; use crate::models::servarr_data::modals::EditIndexerModal; use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS}; + use crate::models::servarr_models::EditIndexerParams; + use pretty_assertions::assert_eq; use strum::IntoEnumIterator; mod test_handle_scroll_up_and_down { @@ -896,7 +899,32 @@ mod tests { .radarr_data .selected_block .set_index(0, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS.len() - 1); - app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default()); + let edit_indexer_modal = EditIndexerModal { + name: "Test Update".into(), + enable_rss: Some(false), + enable_automatic_search: Some(false), + enable_interactive_search: Some(false), + url: "https://localhost:9696/1/".into(), + api_key: "test1234".into(), + seed_ratio: "1.3".into(), + tags: "usenet, testing".into(), + priority: 25, + }; + app.data.radarr_data.edit_indexer_modal = Some(edit_indexer_modal); + app.data.radarr_data.indexers.set_items(vec![indexer()]); + let expected_edit_indexer_params = EditIndexerParams { + indexer_id: 1, + name: Some("Test Update".to_owned()), + enable_rss: Some(false), + enable_automatic_search: Some(false), + enable_interactive_search: Some(false), + url: Some("https://localhost:9696/1/".to_owned()), + api_key: Some("test1234".to_owned()), + seed_ratio: Some("1.3".to_owned()), + tag_input_string: Some("usenet, testing".to_owned()), + priority: Some(25), + ..EditIndexerParams::default() + }; app.data.radarr_data.prompt_confirm = true; EditIndexerHandler::with( @@ -908,11 +936,11 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); - assert!(app.data.radarr_data.edit_indexer_modal.is_some()); + assert!(app.data.radarr_data.edit_indexer_modal.is_none()); assert!(app.should_refresh); assert_eq!( app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::EditIndexer(None)) + Some(RadarrEvent::EditIndexer(expected_edit_indexer_params)) ); } @@ -1408,7 +1436,7 @@ mod tests { use crate::models::servarr_data::radarr::radarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS; use crate::models::BlockSelectionState; use crate::network::radarr_network::RadarrEvent; - use pretty_assertions::assert_str_eq; + use pretty_assertions::{assert_eq, assert_str_eq}; use super::*; @@ -1709,7 +1737,32 @@ mod tests { .radarr_data .selected_block .set_index(0, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS.len() - 1); - app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default()); + let edit_indexer_modal = EditIndexerModal { + name: "Test Update".into(), + enable_rss: Some(false), + enable_automatic_search: Some(false), + enable_interactive_search: Some(false), + url: "https://localhost:9696/1/".into(), + api_key: "test1234".into(), + seed_ratio: "1.3".into(), + tags: "usenet, testing".into(), + priority: 25, + }; + app.data.radarr_data.edit_indexer_modal = Some(edit_indexer_modal); + app.data.radarr_data.indexers.set_items(vec![indexer()]); + let expected_edit_indexer_params = EditIndexerParams { + indexer_id: 1, + name: Some("Test Update".to_owned()), + enable_rss: Some(false), + enable_automatic_search: Some(false), + enable_interactive_search: Some(false), + url: Some("https://localhost:9696/1/".to_owned()), + api_key: Some("test1234".to_owned()), + seed_ratio: Some("1.3".to_owned()), + tag_input_string: Some("usenet, testing".to_owned()), + priority: Some(25), + ..EditIndexerParams::default() + }; EditIndexerHandler::with( DEFAULT_KEYBINDINGS.confirm.key, @@ -1720,11 +1773,11 @@ mod tests { .handle(); assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into()); - assert!(app.data.radarr_data.edit_indexer_modal.is_some()); + assert!(app.data.radarr_data.edit_indexer_modal.is_none()); assert!(app.should_refresh); assert_eq!( app.data.radarr_data.prompt_confirm_action, - Some(RadarrEvent::EditIndexer(None)) + Some(RadarrEvent::EditIndexer(expected_edit_indexer_params)) ); } } @@ -1740,6 +1793,47 @@ mod tests { }) } + #[test] + fn test_build_edit_indexer_params() { + let mut app = App::default(); + let edit_indexer_modal = EditIndexerModal { + name: "Test Update".into(), + enable_rss: Some(false), + enable_automatic_search: Some(false), + enable_interactive_search: Some(false), + url: "https://localhost:9696/1/".into(), + api_key: "test1234".into(), + seed_ratio: "1.3".into(), + tags: "usenet, testing".into(), + priority: 25, + }; + app.data.radarr_data.edit_indexer_modal = Some(edit_indexer_modal); + app.data.radarr_data.indexers.set_items(vec![indexer()]); + let expected_edit_indexer_params = EditIndexerParams { + indexer_id: 1, + name: Some("Test Update".to_owned()), + enable_rss: Some(false), + enable_automatic_search: Some(false), + enable_interactive_search: Some(false), + url: Some("https://localhost:9696/1/".to_owned()), + api_key: Some("test1234".to_owned()), + seed_ratio: Some("1.3".to_owned()), + tag_input_string: Some("usenet, testing".to_owned()), + priority: Some(25), + ..EditIndexerParams::default() + }; + + let edit_indexer_params = EditIndexerHandler::with( + DEFAULT_KEYBINDINGS.esc.key, + &mut app, + ActiveRadarrBlock::EditIndexerPrompt, + None, + ).build_edit_indexer_params(); + + assert_eq!(edit_indexer_params, expected_edit_indexer_params); + assert!(app.data.radarr_data.edit_indexer_modal.is_none()); + } + #[test] fn test_edit_indexer_handler_is_not_ready_when_loading() { let mut app = App::default(); diff --git a/src/handlers/radarr_handlers/library/add_movie_handler.rs b/src/handlers/radarr_handlers/library/add_movie_handler.rs index a30e641..b2d61e0 100644 --- a/src/handlers/radarr_handlers/library/add_movie_handler.rs +++ b/src/handlers/radarr_handlers/library/add_movie_handler.rs @@ -110,7 +110,7 @@ impl<'a, 'b> AddMovieHandler<'a, 'b> { monitored: true, quality_profile_id, tags: Vec::new(), - tag_input_string: tags, + tag_input_string: Some(tags), add_options: AddMovieOptions { monitor, search_for_movie: true, diff --git a/src/handlers/radarr_handlers/radarr_handler_test_utils.rs b/src/handlers/radarr_handlers/radarr_handler_test_utils.rs index 9f3fbde..d9d3cfc 100644 --- a/src/handlers/radarr_handlers/radarr_handler_test_utils.rs +++ b/src/handlers/radarr_handlers/radarr_handler_test_utils.rs @@ -533,7 +533,7 @@ pub(in crate::handlers::radarr_handlers) mod utils { monitored: true, quality_profile_id: 2222, tags: Vec::new(), - tag_input_string: "usenet, testing".into(), + tag_input_string: Some("usenet, testing".into()), add_options: AddMovieOptions { monitor: "movieOnly".to_owned(), search_for_movie: true, diff --git a/src/models/radarr_models.rs b/src/models/radarr_models.rs index 29157a0..4d5ccb2 100644 --- a/src/models/radarr_models.rs +++ b/src/models/radarr_models.rs @@ -30,7 +30,7 @@ pub struct AddMovieBody { pub monitored: bool, pub tags: Vec, #[serde(skip_serializing, skip_deserializing)] - pub tag_input_string: String, + pub tag_input_string: Option, pub add_options: AddMovieOptions, } diff --git a/src/models/servarr_models.rs b/src/models/servarr_models.rs index 8625e74..3a8b740 100644 --- a/src/models/servarr_models.rs +++ b/src/models/servarr_models.rs @@ -101,6 +101,8 @@ pub struct EditIndexerParams { pub api_key: Option, pub seed_ratio: Option, pub tags: Option>, + #[serde(skip_serializing, skip_deserializing)] + pub tag_input_string: Option, pub priority: Option, pub clear_tags: bool, } diff --git a/src/network/radarr_network.rs b/src/network/radarr_network.rs index 2f3669e..da95b9f 100644 --- a/src/network/radarr_network.rs +++ b/src/network/radarr_network.rs @@ -13,7 +13,7 @@ use crate::models::radarr_models::{ MovieCommandBody, MovieHistoryItem, RadarrRelease, RadarrReleaseDownloadBody, RadarrSerdeable, RadarrTask, RadarrTaskName, SystemStatus, }; -use crate::models::servarr_data::modals::{EditIndexerModal, IndexerTestResultModalItem}; +use crate::models::servarr_data::modals::IndexerTestResultModalItem; use crate::models::servarr_data::radarr::modals::{EditMovieModal, MovieDetailsModal}; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::servarr_models::{ @@ -46,7 +46,7 @@ pub enum RadarrEvent { DownloadRelease(RadarrReleaseDownloadBody), EditAllIndexerSettings(IndexerSettings), EditCollection(EditCollectionParams), - EditIndexer(Option), + EditIndexer(EditIndexerParams), EditMovie(Option), GetBlocklist, GetCollections, @@ -283,10 +283,12 @@ impl<'a, 'b> Network<'a, 'b> { async fn add_movie(&mut self, mut add_movie_body: AddMovieBody) -> Result { info!("Adding new movie to Radarr"); let event = RadarrEvent::AddMovie(add_movie_body.clone()); - let tag_ids_vec = self - .extract_and_add_radarr_tag_ids_vec(add_movie_body.tag_input_string.clone()) - .await; - add_movie_body.tags = tag_ids_vec; + if let Some(tag_input_string) = add_movie_body.tag_input_string.as_ref() { + let tag_ids_vec = self + .extract_and_add_radarr_tag_ids_vec(tag_input_string.clone()) + .await; + add_movie_body.tags = tag_ids_vec; + } debug!("Add movie body: {add_movie_body:?}"); @@ -617,25 +619,19 @@ impl<'a, 'b> Network<'a, 'b> { async fn edit_radarr_indexer( &mut self, - edit_indexer_params: Option, + mut edit_indexer_params: EditIndexerParams, ) -> Result<()> { let detail_event = RadarrEvent::GetIndexers; - let event = RadarrEvent::EditIndexer(None); - let id = if let Some(ref params) = edit_indexer_params { - params.indexer_id - } else { - self - .app - .lock() - .await - .data - .radarr_data - .indexers - .current_selection() - .id - }; + let event = RadarrEvent::EditIndexer(edit_indexer_params.clone()); + let id = edit_indexer_params.indexer_id; + if let Some(tag_input_string) = edit_indexer_params.tag_input_string.as_ref() { + let tag_ids_vec = self + .extract_and_add_radarr_tag_ids_vec(tag_input_string.clone()) + .await; + edit_indexer_params.tags = Some(tag_ids_vec); + } info!("Updating Radarr indexer with ID: {id}"); - + info!("Fetching indexer details for indexer with ID: {id}"); let request_props = self @@ -670,7 +666,7 @@ impl<'a, 'b> Network<'a, 'b> { seed_ratio, tags, priority, - ) = if let Some(params) = edit_indexer_params { + ) = { let priority = detailed_indexer_body["priority"] .as_i64() .expect("Unable to deserialize 'priority'"); @@ -679,28 +675,28 @@ impl<'a, 'b> Network<'a, 'b> { .unwrap() .iter() .find(|field| field["name"] == "seedCriteria.seedRatio"); - let name = params.name.unwrap_or( + let name = edit_indexer_params.name.unwrap_or( detailed_indexer_body["name"] .as_str() .expect("Unable to deserialize 'name'") .to_owned(), ); - let enable_rss = params.enable_rss.unwrap_or( + let enable_rss = edit_indexer_params.enable_rss.unwrap_or( detailed_indexer_body["enableRss"] .as_bool() .expect("Unable to deserialize 'enableRss'"), ); - let enable_automatic_search = params.enable_automatic_search.unwrap_or( + let enable_automatic_search = edit_indexer_params.enable_automatic_search.unwrap_or( detailed_indexer_body["enableAutomaticSearch"] .as_bool() .expect("Unable to deserialize 'enableAutomaticSearch"), ); - let enable_interactive_search = params.enable_interactive_search.unwrap_or( + let enable_interactive_search = edit_indexer_params.enable_interactive_search.unwrap_or( detailed_indexer_body["enableInteractiveSearch"] .as_bool() .expect("Unable to deserialize 'enableInteractiveSearch'"), ); - let url = params.url.unwrap_or( + let url = edit_indexer_params.url.unwrap_or( detailed_indexer_body["fields"] .as_array() .expect("Unable to deserialize 'fields'") @@ -713,7 +709,7 @@ impl<'a, 'b> Network<'a, 'b> { .expect("Unable to deserialize 'baseUrl value'") .to_owned(), ); - let api_key = params.api_key.unwrap_or( + let api_key = edit_indexer_params.api_key.unwrap_or( detailed_indexer_body["fields"] .as_array() .expect("Unable to deserialize 'fields'") @@ -726,7 +722,7 @@ impl<'a, 'b> Network<'a, 'b> { .expect("Unable to deserialize 'apiKey value'") .to_owned(), ); - let seed_ratio = params.seed_ratio.unwrap_or_else(|| { + let seed_ratio = edit_indexer_params.seed_ratio.unwrap_or_else(|| { if let Some(seed_ratio_field) = seed_ratio_field_option { return seed_ratio_field .get("value") @@ -738,10 +734,10 @@ impl<'a, 'b> Network<'a, 'b> { String::new() }); - let tags = if params.clear_tags { + let tags = if edit_indexer_params.clear_tags { vec![] } else { - params.tags.unwrap_or( + edit_indexer_params.tags.unwrap_or( detailed_indexer_body["tags"] .as_array() .expect("Unable to deserialize 'tags'") @@ -750,7 +746,7 @@ impl<'a, 'b> Network<'a, 'b> { .collect(), ) }; - let priority = params.priority.unwrap_or(priority); + let priority = edit_indexer_params.priority.unwrap_or(priority); ( name, @@ -763,51 +759,6 @@ impl<'a, 'b> Network<'a, 'b> { tags, priority, ) - } else { - let tags = self - .app - .lock() - .await - .data - .radarr_data - .edit_indexer_modal - .as_ref() - .unwrap() - .tags - .text - .clone(); - let tag_ids_vec = self.extract_and_add_radarr_tag_ids_vec(tags).await; - let mut app = self.app.lock().await; - - let params = { - let EditIndexerModal { - name, - enable_rss, - enable_automatic_search, - enable_interactive_search, - url, - api_key, - seed_ratio, - priority, - .. - } = app.data.radarr_data.edit_indexer_modal.as_ref().unwrap(); - - ( - name.text.clone(), - enable_rss.unwrap_or_default(), - enable_automatic_search.unwrap_or_default(), - enable_interactive_search.unwrap_or_default(), - url.text.clone(), - api_key.text.clone(), - seed_ratio.text.clone(), - tag_ids_vec, - *priority, - ) - }; - - app.data.radarr_data.edit_indexer_modal = None; - - params }; *detailed_indexer_body.get_mut("name").unwrap() = json!(name); @@ -862,7 +813,7 @@ impl<'a, 'b> Network<'a, 'b> { RequestMethod::Put, Some(detailed_indexer_body), Some(format!("/{id}")), - None, + Some("forceSave=true".to_owned()), ) .await; diff --git a/src/network/radarr_network_tests.rs b/src/network/radarr_network_tests.rs index e155f14..9a18592 100644 --- a/src/network/radarr_network_tests.rs +++ b/src/network/radarr_network_tests.rs @@ -20,6 +20,7 @@ mod test { }; use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock; use crate::models::servarr_models::{ + EditIndexerParams, HostConfig, IndexerField, Language, Quality, QualityWrapper, }; use crate::models::stateful_table::SortOption; @@ -137,7 +138,7 @@ mod test { #[rstest] fn test_resource_indexer( - #[values(RadarrEvent::GetIndexers, RadarrEvent::DeleteIndexer(0))] event: RadarrEvent, + #[values(RadarrEvent::GetIndexers, RadarrEvent::DeleteIndexer(0), RadarrEvent::EditIndexer(EditIndexerParams::default()))] event: RadarrEvent, ) { assert_str_eq!(event.resource(), "/indexer"); } @@ -3281,7 +3282,7 @@ mod test { monitored: true, quality_profile_id: 2222, tags: vec![1, 2], - tag_input_string: "usenet, testing".into(), + tag_input_string: Some("usenet, testing".into()), add_options: AddMovieOptions { monitor: "movieOnly".to_owned(), search_for_movie: true, @@ -3298,6 +3299,56 @@ mod test { async_server.assert_async().await; } + #[tokio::test] + async fn test_handle_add_movie_event_does_not_overwrite_tags_field_if_tag_input_string_is_none() { + let (async_server, app_arc, _server) = mock_servarr_api( + RequestMethod::Post, + Some(json!({ + "tmdbId": 1234, + "title": "Test", + "rootFolderPath": "/nfs2", + "minimumAvailability": "announced", + "monitored": true, + "qualityProfileId": 2222, + "tags": [1, 2], + "addOptions": { + "monitor": "movieOnly", + "searchForMovie": true + } + })), + Some(json!({})), + None, + RadarrEvent::AddMovie(AddMovieBody::default()), + None, + None, + ) + .await; + app_arc.lock().await.data.radarr_data.tags_map = + BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); + let add_movie_body = AddMovieBody { + tmdb_id: 1234, + title: "Test".to_owned(), + root_folder_path: "/nfs2".to_owned(), + minimum_availability: "announced".to_owned(), + monitored: true, + quality_profile_id: 2222, + tags: vec![1, 2], + tag_input_string: None, + add_options: AddMovieOptions { + monitor: "movieOnly".to_owned(), + search_for_movie: true, + }, + }; + let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + + assert!(network + .handle_radarr_event(RadarrEvent::AddMovie(add_movie_body)) + .await + .is_ok()); + + async_server.assert_async().await; + } + #[tokio::test] async fn test_handle_add_radarr_root_folder_event() { let (async_server, app_arc, _server) = mock_servarr_api( @@ -3571,7 +3622,19 @@ mod test { "tags": [1, 2], "id": 1 }); - + let edit_indexer_params = EditIndexerParams { + indexer_id: 1, + name: Some("Test Update".to_owned()), + enable_rss: Some(false), + enable_automatic_search: Some(false), + enable_interactive_search: Some(false), + url: Some("https://localhost:9696/1/".to_owned()), + api_key: Some("test1234".to_owned()), + seed_ratio: Some("1.3".to_owned()), + tag_input_string: Some("usenet, testing".to_owned()), + priority: Some(0), + ..EditIndexerParams::default() + }; let (async_details_server, app_arc, mut server) = mock_servarr_api( RequestMethod::Get, None, @@ -3585,43 +3648,118 @@ mod test { let async_edit_server = server .mock( "PUT", - format!("/api/v3{}/1", RadarrEvent::EditIndexer(None).resource()).as_str(), + format!("/api/v3{}/1?forceSave=true", RadarrEvent::EditIndexer(edit_indexer_params.clone()).resource()).as_str(), ) .with_status(202) .match_header("X-Api-Key", "test1234") .match_body(Matcher::Json(expected_indexer_edit_body_json)) .create_async() .await; - { - let mut app = app_arc.lock().await; - app.data.radarr_data.tags_map = - BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - let edit_indexer_modal = EditIndexerModal { - name: "Test Update".into(), - enable_rss: Some(false), - enable_automatic_search: Some(false), - enable_interactive_search: Some(false), - url: "https://localhost:9696/1/".into(), - api_key: "test1234".into(), - seed_ratio: "1.3".into(), - tags: "usenet, testing".into(), - priority: 0, - }; - app.data.radarr_data.edit_indexer_modal = Some(edit_indexer_modal); - app.data.radarr_data.indexers.set_items(vec![indexer()]); - } + app_arc.lock().await.data.radarr_data.tags_map = + BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); assert!(network - .handle_radarr_event(RadarrEvent::EditIndexer(None)) + .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) .await .is_ok()); async_details_server.assert_async().await; async_edit_server.assert_async().await; + } - let app = app_arc.lock().await; - assert!(app.data.radarr_data.edit_indexer_modal.is_none()); + #[tokio::test] + async fn test_handle_edit_radarr_indexer_event_does_not_overwrite_tags_vec_if_tag_input_string_is_none() { + let indexer_details_json = json!({ + "enableRss": true, + "enableAutomaticSearch": true, + "enableInteractiveSearch": true, + "name": "Test Indexer", + "priority": 1, + "fields": [ + { + "name": "baseUrl", + "value": "https://test.com", + }, + { + "name": "apiKey", + "value": "", + }, + { + "name": "seedCriteria.seedRatio", + "value": "1.2", + }, + ], + "tags": [1], + "id": 1 + }); + let expected_indexer_edit_body_json = json!({ + "enableRss": false, + "enableAutomaticSearch": false, + "enableInteractiveSearch": false, + "name": "Test Update", + "priority": 0, + "fields": [ + { + "name": "baseUrl", + "value": "https://localhost:9696/1/", + }, + { + "name": "apiKey", + "value": "test1234", + }, + { + "name": "seedCriteria.seedRatio", + "value": "1.3", + }, + ], + "tags": [1, 2], + "id": 1 + }); + let edit_indexer_params = EditIndexerParams { + indexer_id: 1, + name: Some("Test Update".to_owned()), + enable_rss: Some(false), + enable_automatic_search: Some(false), + enable_interactive_search: Some(false), + url: Some("https://localhost:9696/1/".to_owned()), + api_key: Some("test1234".to_owned()), + seed_ratio: Some("1.3".to_owned()), + tags: Some(vec![1, 2]), + priority: Some(0), + ..EditIndexerParams::default() + }; + let (async_details_server, app_arc, mut server) = mock_servarr_api( + RequestMethod::Get, + None, + Some(indexer_details_json), + None, + RadarrEvent::GetIndexers, + Some("/1"), + None, + ) + .await; + let async_edit_server = server + .mock( + "PUT", + format!("/api/v3{}/1?forceSave=true", RadarrEvent::EditIndexer(edit_indexer_params.clone()).resource()).as_str(), + ) + .with_status(202) + .match_header("X-Api-Key", "test1234") + .match_body(Matcher::Json(expected_indexer_edit_body_json)) + .create_async() + .await; + app_arc.lock().await.data.radarr_data.tags_map = + BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); + let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + + assert!(network + .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) + .await + .is_ok()); + + async_details_server.assert_async().await; + async_edit_server.assert_async().await; } #[tokio::test] @@ -3665,7 +3803,19 @@ mod test { "tags": [1, 2], "id": 1 }); - + let edit_indexer_params = EditIndexerParams { + indexer_id: 1, + name: Some("Test Update".to_owned()), + enable_rss: Some(false), + enable_automatic_search: Some(false), + enable_interactive_search: Some(false), + url: Some("https://localhost:9696/1/".to_owned()), + api_key: Some("test1234".to_owned()), + seed_ratio: Some("1.3".to_owned()), + tag_input_string: Some("usenet, testing".to_owned()), + priority: Some(0), + ..EditIndexerParams::default() + }; let (async_details_server, app_arc, mut server) = mock_servarr_api( RequestMethod::Get, None, @@ -3679,52 +3829,24 @@ mod test { let async_edit_server = server .mock( "PUT", - format!("/api/v3{}/1", RadarrEvent::EditIndexer(None).resource()).as_str(), + format!("/api/v3{}/1?forceSave=true", RadarrEvent::EditIndexer(edit_indexer_params.clone()).resource()).as_str(), ) .with_status(202) .match_header("X-Api-Key", "test1234") .match_body(Matcher::Json(expected_indexer_edit_body_json)) .create_async() .await; - { - let mut app = app_arc.lock().await; - app.data.radarr_data.tags_map = - BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - let edit_indexer_modal = EditIndexerModal { - name: "Test Update".into(), - enable_rss: Some(false), - enable_automatic_search: Some(false), - enable_interactive_search: Some(false), - url: "https://localhost:9696/1/".into(), - api_key: "test1234".into(), - seed_ratio: "1.3".into(), - tags: "usenet, testing".into(), - priority: 0, - }; - app.data.radarr_data.edit_indexer_modal = Some(edit_indexer_modal); - let mut indexer = indexer(); - indexer.fields = Some( - indexer - .fields - .unwrap() - .into_iter() - .filter(|field| field.name != Some("seedCriteria.seedRatio".to_string())) - .collect(), - ); - app.data.radarr_data.indexers.set_items(vec![indexer]); - } + app_arc.lock().await.data.radarr_data.tags_map = + BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); assert!(network - .handle_radarr_event(RadarrEvent::EditIndexer(None)) + .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) .await .is_ok()); async_details_server.assert_async().await; async_edit_server.assert_async().await; - - let app = app_arc.lock().await; - assert!(app.data.radarr_data.edit_indexer_modal.is_none()); } #[tokio::test] @@ -3775,123 +3897,6 @@ mod test { "tags": [1, 2], "id": 1 }); - - let (async_details_server, app_arc, mut server) = mock_servarr_api( - RequestMethod::Get, - None, - Some(indexer_details_json), - None, - RadarrEvent::GetIndexers, - Some("/1"), - None, - ) - .await; - let async_edit_server = server - .mock( - "PUT", - format!("/api/v3{}/1", RadarrEvent::EditIndexer(None).resource()).as_str(), - ) - .with_status(202) - .match_header("X-Api-Key", "test1234") - .match_body(Matcher::Json(expected_indexer_edit_body_json)) - .create_async() - .await; - { - let mut app = app_arc.lock().await; - app.data.radarr_data.tags_map = - BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); - let edit_indexer_modal = EditIndexerModal { - name: "Test Update".into(), - enable_rss: Some(false), - enable_automatic_search: Some(false), - enable_interactive_search: Some(false), - url: "https://localhost:9696/1/".into(), - api_key: "test1234".into(), - seed_ratio: "1.3".into(), - tags: "usenet, testing".into(), - priority: 0, - }; - app.data.radarr_data.edit_indexer_modal = Some(edit_indexer_modal); - let mut indexer = indexer(); - indexer.fields = Some( - indexer - .fields - .unwrap() - .into_iter() - .map(|mut field| { - if field.name == Some("seedCriteria.seedRatio".to_string()) { - field.value = None; - field - } else { - field - } - }) - .collect(), - ); - app.data.radarr_data.indexers.set_items(vec![indexer]); - } - let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); - - assert!(network - .handle_radarr_event(RadarrEvent::EditIndexer(None)) - .await - .is_ok()); - - async_details_server.assert_async().await; - async_edit_server.assert_async().await; - - let app = app_arc.lock().await; - assert!(app.data.radarr_data.edit_indexer_modal.is_none()); - } - - #[tokio::test] - async fn test_handle_edit_radarr_indexer_event_uses_provided_parameters() { - let indexer_details_json = json!({ - "enableRss": true, - "enableAutomaticSearch": true, - "enableInteractiveSearch": true, - "name": "Test Indexer", - "priority": 1, - "fields": [ - { - "name": "baseUrl", - "value": "https://test.com", - }, - { - "name": "apiKey", - "value": "", - }, - { - "name": "seedCriteria.seedRatio", - "value": "1.2", - }, - ], - "tags": [1], - "id": 1 - }); - let expected_indexer_edit_body_json = json!({ - "enableRss": false, - "enableAutomaticSearch": false, - "enableInteractiveSearch": false, - "name": "Test Update", - "priority": 25, - "fields": [ - { - "name": "baseUrl", - "value": "https://localhost:9696/1/", - }, - { - "name": "apiKey", - "value": "test1234", - }, - { - "name": "seedCriteria.seedRatio", - "value": "1.3", - }, - ], - "tags": [1, 2], - "id": 1 - }); let edit_indexer_params = EditIndexerParams { indexer_id: 1, name: Some("Test Update".to_owned()), @@ -3901,11 +3906,10 @@ mod test { url: Some("https://localhost:9696/1/".to_owned()), api_key: Some("test1234".to_owned()), seed_ratio: Some("1.3".to_owned()), - tags: Some(vec![1, 2]), - priority: Some(25), + tag_input_string: Some("usenet, testing".to_owned()), + priority: Some(0), ..EditIndexerParams::default() }; - let (async_details_server, app_arc, mut server) = mock_servarr_api( RequestMethod::Get, None, @@ -3919,17 +3923,19 @@ mod test { let async_edit_server = server .mock( "PUT", - format!("/api/v3{}/1", RadarrEvent::EditIndexer(None).resource()).as_str(), + format!("/api/v3{}/1?forceSave=true", RadarrEvent::EditIndexer(edit_indexer_params.clone()).resource()).as_str(), ) .with_status(202) .match_header("X-Api-Key", "test1234") .match_body(Matcher::Json(expected_indexer_edit_body_json)) .create_async() .await; + app_arc.lock().await.data.radarr_data.tags_map = + BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]); let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); assert!(network - .handle_radarr_event(RadarrEvent::EditIndexer(Some(edit_indexer_params))) + .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) .await .is_ok()); @@ -3938,7 +3944,7 @@ mod test { } #[tokio::test] - async fn test_handle_edit_radarr_indexer_event_uses_provided_parameters_defaults_to_previous_values( + async fn test_handle_edit_radarr_indexer_event_defaults_to_previous_values( ) { let indexer_details_json = json!({ "enableRss": true, @@ -3981,7 +3987,7 @@ mod test { let async_edit_server = server .mock( "PUT", - format!("/api/v3{}/1", RadarrEvent::EditIndexer(None).resource()).as_str(), + format!("/api/v3{}/1?forceSave=true", RadarrEvent::EditIndexer(edit_indexer_params.clone()).resource()).as_str(), ) .with_status(202) .match_header("X-Api-Key", "test1234") @@ -3991,7 +3997,7 @@ mod test { let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); assert!(network - .handle_radarr_event(RadarrEvent::EditIndexer(Some(edit_indexer_params))) + .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) .await .is_ok()); @@ -4000,7 +4006,7 @@ mod test { } #[tokio::test] - async fn test_handle_edit_radarr_indexer_event_uses_provided_parameters_clears_tags_when_clear_tags_is_true( + async fn test_handle_edit_radarr_indexer_event_clears_tags_when_clear_tags_is_true( ) { let indexer_details_json = json!({ "enableRss": true, @@ -4067,7 +4073,7 @@ mod test { let async_edit_server = server .mock( "PUT", - format!("/api/v3{}/1", RadarrEvent::EditIndexer(None).resource()).as_str(), + format!("/api/v3{}/1?forceSave=true", RadarrEvent::EditIndexer(edit_indexer_params.clone()).resource()).as_str(), ) .with_status(202) .match_header("X-Api-Key", "test1234") @@ -4077,7 +4083,7 @@ mod test { let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); assert!(network - .handle_radarr_event(RadarrEvent::EditIndexer(Some(edit_indexer_params))) + .handle_radarr_event(RadarrEvent::EditIndexer(edit_indexer_params)) .await .is_ok());