diff --git a/src/models/radarr_models_tests.rs b/src/models/radarr_models_tests.rs index e562eb1..90ce5e2 100644 --- a/src/models/radarr_models_tests.rs +++ b/src/models/radarr_models_tests.rs @@ -10,6 +10,7 @@ mod tests { LogResponse, MinimumAvailability, Monitor, Movie, MovieHistoryItem, QualityProfile, QueueEvent, RadarrSerdeable, Release, RootFolder, SystemStatus, Tag, Task, TaskName, Update, }, + servarr_models::{HostConfig, SecurityConfig}, Serdeable, }; @@ -178,6 +179,18 @@ mod tests { assert_eq!(radarr_serdeable, RadarrSerdeable::DiskSpaces(disk_spaces)); } + #[test] + fn test_radarr_serdeable_from_host_config() { + let host_config = HostConfig { + port: 1234, + ..HostConfig::default() + }; + + let radarr_serdeable: RadarrSerdeable = host_config.clone().into(); + + assert_eq!(radarr_serdeable, RadarrSerdeable::HostConfig(host_config)); + } + #[test] fn test_radarr_serdeable_from_downloads_response() { let downloads_response = DownloadsResponse { @@ -326,6 +339,21 @@ mod tests { assert_eq!(radarr_serdeable, RadarrSerdeable::RootFolders(root_folders)); } + #[test] + fn test_radarr_serdeable_from_security_config() { + let security_config = SecurityConfig { + username: Some("Test".to_owned()), + ..SecurityConfig::default() + }; + + let radarr_serdeable: RadarrSerdeable = security_config.clone().into(); + + assert_eq!( + radarr_serdeable, + RadarrSerdeable::SecurityConfig(security_config) + ); + } + #[test] fn test_radarr_serdeable_from_system_status() { let system_status = SystemStatus { diff --git a/src/models/servarr_data/sonarr/sonarr_data.rs b/src/models/servarr_data/sonarr/sonarr_data.rs index dd53909..b2eeee9 100644 --- a/src/models/servarr_data/sonarr/sonarr_data.rs +++ b/src/models/servarr_data/sonarr/sonarr_data.rs @@ -4,7 +4,7 @@ use strum::EnumIter; use crate::models::{ servarr_models::Indexer, - sonarr_models::{BlocklistItem, DownloadRecord, Episode, Series}, + sonarr_models::{BlocklistItem, DownloadRecord, Episode, IndexerSettings, Series}, stateful_list::StatefulList, stateful_table::StatefulTable, stateful_tree::StatefulTree, @@ -29,6 +29,7 @@ pub struct SonarrData { pub episode_details_modal: Option, pub quality_profile_map: BiMap, pub indexers: StatefulTable, + pub indexer_settings: Option, } impl Default for SonarrData { @@ -45,6 +46,7 @@ impl Default for SonarrData { episode_details_modal: None, quality_profile_map: BiMap::new(), indexers: StatefulTable::default(), + indexer_settings: None, } } } diff --git a/src/models/servarr_data/sonarr/sonarr_data_tests.rs b/src/models/servarr_data/sonarr/sonarr_data_tests.rs index 2f44e42..66ba96c 100644 --- a/src/models/servarr_data/sonarr/sonarr_data_tests.rs +++ b/src/models/servarr_data/sonarr/sonarr_data_tests.rs @@ -45,6 +45,7 @@ mod tests { assert!(sonarr_data.episode_details_modal.is_none()); assert!(sonarr_data.quality_profile_map.is_empty()); assert!(sonarr_data.indexers.is_empty()); + assert!(sonarr_data.indexer_settings.is_none()); } } } diff --git a/src/models/sonarr_models.rs b/src/models/sonarr_models.rs index 03f6937..cdec965 100644 --- a/src/models/sonarr_models.rs +++ b/src/models/sonarr_models.rs @@ -106,6 +106,21 @@ pub struct EpisodeFile { pub media_info: Option, } +#[derive(Default, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct IndexerSettings { + #[serde(deserialize_with = "super::from_i64")] + pub id: i64, + #[serde(deserialize_with = "super::from_i64")] + pub mimimum_age: i64, + #[serde(deserialize_with = "super::from_i64")] + pub retention: i64, + #[serde(deserialize_with = "super::from_i64")] + pub maximum_size: i64, + #[serde(deserialize_with = "super::from_i64")] + pub rss_sync_interval: i64, +} + #[derive(Serialize, Deserialize, Default, Debug, Hash, Clone, PartialEq, Eq, Ord, PartialOrd)] pub struct Language { pub name: String, @@ -334,6 +349,7 @@ pub enum SonarrSerdeable { Episode(Episode), Episodes(Vec), HostConfig(HostConfig), + IndexerSettings(IndexerSettings), Indexers(Vec), QualityProfiles(Vec), SecurityConfig(SecurityConfig), @@ -362,6 +378,7 @@ serde_enum_from!( Episode(Episode), Episodes(Vec), HostConfig(HostConfig), + IndexerSettings(IndexerSettings), Indexers(Vec), QualityProfiles(Vec), SecurityConfig(SecurityConfig), diff --git a/src/models/sonarr_models_tests.rs b/src/models/sonarr_models_tests.rs index 424e7f0..d561b7f 100644 --- a/src/models/sonarr_models_tests.rs +++ b/src/models/sonarr_models_tests.rs @@ -4,9 +4,11 @@ mod tests { use serde_json::json; use crate::models::{ + servarr_models::{HostConfig, Indexer, SecurityConfig}, sonarr_models::{ - BlocklistItem, BlocklistResponse, DownloadRecord, DownloadsResponse, Episode, Log, - LogResponse, QualityProfile, Series, SeriesStatus, SeriesType, SonarrSerdeable, SystemStatus, + BlocklistItem, BlocklistResponse, DownloadRecord, DownloadsResponse, Episode, + IndexerSettings, Log, LogResponse, QualityProfile, Series, SeriesStatus, SeriesType, + SonarrSerdeable, SystemStatus, }, Serdeable, }; @@ -101,6 +103,45 @@ mod tests { assert_eq!(sonarr_serdeable, SonarrSerdeable::Episodes(episodes)); } + #[test] + fn test_sonarr_serdeable_from_host_config() { + let host_config = HostConfig { + port: 1234, + ..HostConfig::default() + }; + + let sonarr_serdeable: SonarrSerdeable = host_config.clone().into(); + + assert_eq!(sonarr_serdeable, SonarrSerdeable::HostConfig(host_config)); + } + + #[test] + fn test_sonarr_serdeable_from_indexers() { + let indexers = vec![Indexer { + id: 1, + ..Indexer::default() + }]; + + let sonarr_serdeable: SonarrSerdeable = indexers.clone().into(); + + assert_eq!(sonarr_serdeable, SonarrSerdeable::Indexers(indexers)); + } + + #[test] + fn test_sonarr_serdeable_from_indexer_settings() { + let indexer_settings = IndexerSettings { + id: 1, + ..IndexerSettings::default() + }; + + let sonarr_serdeable: SonarrSerdeable = indexer_settings.clone().into(); + + assert_eq!( + sonarr_serdeable, + SonarrSerdeable::IndexerSettings(indexer_settings) + ); + } + #[test] fn test_sonarr_serdeable_from_series() { let series = vec![Series { @@ -189,4 +230,19 @@ mod tests { SonarrSerdeable::QualityProfiles(quality_profiles) ); } + + #[test] + fn test_sonarr_serdeable_from_security_config() { + let security_config = SecurityConfig { + username: Some("Test".to_owned()), + ..SecurityConfig::default() + }; + + let sonarr_serdeable: SonarrSerdeable = security_config.clone().into(); + + assert_eq!( + sonarr_serdeable, + SonarrSerdeable::SecurityConfig(security_config) + ); + } } diff --git a/src/network/radarr_network.rs b/src/network/radarr_network.rs index 99490ad..9a48bb8 100644 --- a/src/network/radarr_network.rs +++ b/src/network/radarr_network.rs @@ -187,7 +187,7 @@ impl<'a, 'b> Network<'a, 'b> { } RadarrEvent::EditMovie(params) => self.edit_movie(params).await.map(RadarrSerdeable::from), RadarrEvent::GetAllIndexerSettings => self - .get_all_indexer_settings() + .get_all_radarr_indexer_settings() .await .map(RadarrSerdeable::from), RadarrEvent::GetBlocklist => self.get_radarr_blocklist().await.map(RadarrSerdeable::from), @@ -1417,7 +1417,7 @@ impl<'a, 'b> Network<'a, 'b> { .await } - async fn get_all_indexer_settings(&mut self) -> Result { + async fn get_all_radarr_indexer_settings(&mut self) -> Result { info!("Fetching Radarr indexer settings"); let event = RadarrEvent::GetAllIndexerSettings; diff --git a/src/network/sonarr_network.rs b/src/network/sonarr_network.rs index 25aedef..0ba51a4 100644 --- a/src/network/sonarr_network.rs +++ b/src/network/sonarr_network.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use anyhow::Result; use indoc::formatdoc; -use log::info; +use log::{debug, info}; use managarr_tree_widget::TreeItem; use serde_json::{json, Value}; @@ -11,8 +11,8 @@ use crate::{ servarr_data::sonarr::{modals::EpisodeDetailsModal, sonarr_data::ActiveSonarrBlock}, servarr_models::{HostConfig, Indexer, SecurityConfig}, sonarr_models::{ - BlocklistResponse, DownloadRecord, DownloadsResponse, Episode, LogResponse, QualityProfile, - Series, SonarrSerdeable, SystemStatus, + BlocklistResponse, DownloadRecord, DownloadsResponse, Episode, IndexerSettings, LogResponse, + QualityProfile, Series, SonarrSerdeable, SystemStatus, }, HorizontallyScrollableText, Route, Scrollable, ScrollableText, }, @@ -29,6 +29,7 @@ mod sonarr_network_tests; pub enum SonarrEvent { ClearBlocklist, DeleteBlocklistItem(Option), + GetAllIndexerSettings, GetBlocklist, GetDownloads, GetHostConfig, @@ -48,6 +49,7 @@ impl NetworkResource for SonarrEvent { match &self { SonarrEvent::ClearBlocklist => "/blocklist/bulk", SonarrEvent::DeleteBlocklistItem(_) => "/blocklist", + SonarrEvent::GetAllIndexerSettings => "/config/indexer", SonarrEvent::GetBlocklist => "/blocklist?page=1&pageSize=10000", SonarrEvent::GetDownloads => "/queue", SonarrEvent::GetEpisodes(_) | SonarrEvent::GetEpisodeDetails(_) => "/episode", @@ -78,6 +80,10 @@ impl<'a, 'b> Network<'a, 'b> { .clear_sonarr_blocklist() .await .map(SonarrSerdeable::from), + SonarrEvent::GetAllIndexerSettings => self + .get_all_sonarr_indexer_settings() + .await + .map(SonarrSerdeable::from), SonarrEvent::DeleteBlocklistItem(blocklist_item_id) => self .delete_sonarr_blocklist_item(blocklist_item_id) .await @@ -182,6 +188,25 @@ impl<'a, 'b> Network<'a, 'b> { .await } + async fn get_all_sonarr_indexer_settings(&mut self) -> Result { + info!("Fetching Sonarr indexer settings"); + let event = SonarrEvent::GetAllIndexerSettings; + + let request_props = self + .request_props_from(event, RequestMethod::Get, None::<()>, None, None) + .await; + + self + .handle_request::<(), IndexerSettings>(request_props, |indexer_settings, mut app| { + if app.data.sonarr_data.indexer_settings.is_none() { + app.data.sonarr_data.indexer_settings = Some(indexer_settings); + } else { + debug!("Indexer Settings are being modified. Ignoring update..."); + } + }) + .await + } + async fn get_sonarr_healthcheck(&mut self) -> Result<()> { info!("Performing Sonarr health check"); let event = SonarrEvent::HealthCheck;