diff --git a/src/models/servarr_data/sonarr/sonarr_data.rs b/src/models/servarr_data/sonarr/sonarr_data.rs index 11baf20..bd2962f 100644 --- a/src/models/servarr_data/sonarr/sonarr_data.rs +++ b/src/models/servarr_data/sonarr/sonarr_data.rs @@ -127,7 +127,6 @@ pub enum ActiveSonarrBlock { DeleteSeriesToggleAddListExclusion, DeleteSeriesToggleDeleteFile, Downloads, - EditEpisodePrompt, EditIndexerPrompt, EditSeriesPrompt, EpisodeDetails, diff --git a/src/network/sonarr_network.rs b/src/network/sonarr_network.rs index c205179..27ba7fc 100644 --- a/src/network/sonarr_network.rs +++ b/src/network/sonarr_network.rs @@ -44,6 +44,7 @@ pub enum SonarrEvent { ClearBlocklist, DeleteBlocklistItem(Option), DeleteDownload(Option), + DeleteEpisodeFile(Option), DeleteIndexer(Option), DeleteRootFolder(Option), DeleteSeries(Option), @@ -99,6 +100,7 @@ impl NetworkResource for SonarrEvent { SonarrEvent::GetAllIndexerSettings | SonarrEvent::EditAllIndexerSettings(_) => { "/config/indexer" } + SonarrEvent::DeleteEpisodeFile(_) => "/episodefile", SonarrEvent::GetBlocklist => "/blocklist?page=1&pageSize=10000", SonarrEvent::GetDownloads | SonarrEvent::DeleteDownload(_) => "/queue", SonarrEvent::GetEpisodes(_) | SonarrEvent::GetEpisodeDetails(_) => "/episode", @@ -175,6 +177,10 @@ impl<'a, 'b> Network<'a, 'b> { .delete_sonarr_download(download_id) .await .map(SonarrSerdeable::from), + SonarrEvent::DeleteEpisodeFile(episode_file_id) => self + .delete_sonarr_episode_file(episode_file_id) + .await + .map(SonarrSerdeable::from), SonarrEvent::DeleteIndexer(indexer_id) => self .delete_sonarr_indexer(indexer_id) .await @@ -532,6 +538,42 @@ impl<'a, 'b> Network<'a, 'b> { .await } + async fn delete_sonarr_episode_file(&mut self, episode_file_id: Option) -> Result<()> { + let event = SonarrEvent::DeleteEpisodeFile(None); + let id = if let Some(ep_id) = episode_file_id { + ep_id + } else { + self + .app + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_ref() + .expect("Season details have not been loaded") + .episodes + .current_selection() + .episode_file_id + }; + + info!("Deleting Sonarr episode file for episode file with id: {id}"); + + let request_props = self + .request_props_from( + event, + RequestMethod::Delete, + None::<()>, + Some(format!("/{id}")), + None, + ) + .await; + + self + .handle_request::<(), ()>(request_props, |_, _| ()) + .await + } + async fn delete_sonarr_download(&mut self, download_id: Option) -> Result<()> { let event = SonarrEvent::DeleteDownload(None); let id = if let Some(dl_id) = download_id { diff --git a/src/network/sonarr_network_tests.rs b/src/network/sonarr_network_tests.rs index 55f5861..4952610 100644 --- a/src/network/sonarr_network_tests.rs +++ b/src/network/sonarr_network_tests.rs @@ -251,6 +251,7 @@ mod test { #[rstest] #[case(SonarrEvent::ClearBlocklist, "/blocklist/bulk")] #[case(SonarrEvent::DeleteBlocklistItem(None), "/blocklist")] + #[case(SonarrEvent::DeleteEpisodeFile(None), "/episodefile")] #[case(SonarrEvent::HealthCheck, "/health")] #[case(SonarrEvent::GetBlocklist, "/blocklist?page=1&pageSize=10000")] #[case(SonarrEvent::GetDiskSpace, "/diskspace")] @@ -712,6 +713,83 @@ mod test { async_server.assert_async().await; } + #[tokio::test] + async fn test_handle_delete_sonarr_episode_file_event() { + let (async_server, app_arc, _server) = mock_servarr_api( + RequestMethod::Delete, + None, + None, + None, + SonarrEvent::DeleteEpisodeFile(None), + Some("/1"), + None, + ) + .await; + app_arc.lock().await.data.sonarr_data.season_details_modal = + Some(SeasonDetailsModal::default()); + app_arc + .lock() + .await + .data + .sonarr_data + .season_details_modal + .as_mut() + .unwrap() + .episodes + .set_items(vec![episode()]); + let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + + assert!(network + .handle_sonarr_event(SonarrEvent::DeleteEpisodeFile(None)) + .await + .is_ok()); + + async_server.assert_async().await; + } + + #[tokio::test] + async fn test_handle_delete_sonarr_episode_file_event_uses_provided_id() { + let (async_server, app_arc, _server) = mock_servarr_api( + RequestMethod::Delete, + None, + None, + None, + SonarrEvent::DeleteEpisodeFile(None), + Some("/1"), + None, + ) + .await; + let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + + assert!(network + .handle_sonarr_event(SonarrEvent::DeleteEpisodeFile(Some(1))) + .await + .is_ok()); + + async_server.assert_async().await; + } + + #[tokio::test] + #[should_panic(expected = "Season details have not been loaded")] + async fn test_handle_delete_sonarr_episode_file_event_empty_season_details_modal_panics() { + let (_async_server, app_arc, _server) = mock_servarr_api( + RequestMethod::Delete, + None, + None, + None, + SonarrEvent::DeleteEpisodeFile(None), + Some("/1"), + None, + ) + .await; + let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new()); + + network + .handle_sonarr_event(SonarrEvent::DeleteEpisodeFile(None)) + .await + .unwrap(); + } + #[tokio::test] async fn test_handle_delete_sonarr_download_event() { let (async_server, app_arc, _server) = mock_servarr_api(