feat(network): Support for deleting an episode file from disk in Sonarr

This commit is contained in:
2024-11-25 14:43:53 -07:00
parent 3968983002
commit 4f86cce497
3 changed files with 120 additions and 1 deletions
@@ -127,7 +127,6 @@ pub enum ActiveSonarrBlock {
DeleteSeriesToggleAddListExclusion, DeleteSeriesToggleAddListExclusion,
DeleteSeriesToggleDeleteFile, DeleteSeriesToggleDeleteFile,
Downloads, Downloads,
EditEpisodePrompt,
EditIndexerPrompt, EditIndexerPrompt,
EditSeriesPrompt, EditSeriesPrompt,
EpisodeDetails, EpisodeDetails,
+42
View File
@@ -44,6 +44,7 @@ pub enum SonarrEvent {
ClearBlocklist, ClearBlocklist,
DeleteBlocklistItem(Option<i64>), DeleteBlocklistItem(Option<i64>),
DeleteDownload(Option<i64>), DeleteDownload(Option<i64>),
DeleteEpisodeFile(Option<i64>),
DeleteIndexer(Option<i64>), DeleteIndexer(Option<i64>),
DeleteRootFolder(Option<i64>), DeleteRootFolder(Option<i64>),
DeleteSeries(Option<DeleteSeriesParams>), DeleteSeries(Option<DeleteSeriesParams>),
@@ -99,6 +100,7 @@ impl NetworkResource for SonarrEvent {
SonarrEvent::GetAllIndexerSettings | SonarrEvent::EditAllIndexerSettings(_) => { SonarrEvent::GetAllIndexerSettings | SonarrEvent::EditAllIndexerSettings(_) => {
"/config/indexer" "/config/indexer"
} }
SonarrEvent::DeleteEpisodeFile(_) => "/episodefile",
SonarrEvent::GetBlocklist => "/blocklist?page=1&pageSize=10000", SonarrEvent::GetBlocklist => "/blocklist?page=1&pageSize=10000",
SonarrEvent::GetDownloads | SonarrEvent::DeleteDownload(_) => "/queue", SonarrEvent::GetDownloads | SonarrEvent::DeleteDownload(_) => "/queue",
SonarrEvent::GetEpisodes(_) | SonarrEvent::GetEpisodeDetails(_) => "/episode", SonarrEvent::GetEpisodes(_) | SonarrEvent::GetEpisodeDetails(_) => "/episode",
@@ -175,6 +177,10 @@ impl<'a, 'b> Network<'a, 'b> {
.delete_sonarr_download(download_id) .delete_sonarr_download(download_id)
.await .await
.map(SonarrSerdeable::from), .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 SonarrEvent::DeleteIndexer(indexer_id) => self
.delete_sonarr_indexer(indexer_id) .delete_sonarr_indexer(indexer_id)
.await .await
@@ -532,6 +538,42 @@ impl<'a, 'b> Network<'a, 'b> {
.await .await
} }
async fn delete_sonarr_episode_file(&mut self, episode_file_id: Option<i64>) -> 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<i64>) -> Result<()> { async fn delete_sonarr_download(&mut self, download_id: Option<i64>) -> Result<()> {
let event = SonarrEvent::DeleteDownload(None); let event = SonarrEvent::DeleteDownload(None);
let id = if let Some(dl_id) = download_id { let id = if let Some(dl_id) = download_id {
+78
View File
@@ -251,6 +251,7 @@ mod test {
#[rstest] #[rstest]
#[case(SonarrEvent::ClearBlocklist, "/blocklist/bulk")] #[case(SonarrEvent::ClearBlocklist, "/blocklist/bulk")]
#[case(SonarrEvent::DeleteBlocklistItem(None), "/blocklist")] #[case(SonarrEvent::DeleteBlocklistItem(None), "/blocklist")]
#[case(SonarrEvent::DeleteEpisodeFile(None), "/episodefile")]
#[case(SonarrEvent::HealthCheck, "/health")] #[case(SonarrEvent::HealthCheck, "/health")]
#[case(SonarrEvent::GetBlocklist, "/blocklist?page=1&pageSize=10000")] #[case(SonarrEvent::GetBlocklist, "/blocklist?page=1&pageSize=10000")]
#[case(SonarrEvent::GetDiskSpace, "/diskspace")] #[case(SonarrEvent::GetDiskSpace, "/diskspace")]
@@ -712,6 +713,83 @@ mod test {
async_server.assert_async().await; 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] #[tokio::test]
async fn test_handle_delete_sonarr_download_event() { async fn test_handle_delete_sonarr_download_event() {
let (async_server, app_arc, _server) = mock_servarr_api( let (async_server, app_arc, _server) = mock_servarr_api(