feat(network): Support for editing a sonarr indexer
This commit is contained in:
@@ -9,9 +9,9 @@ use crate::{
|
||||
cli::{mutex_flags_or_default, mutex_flags_or_option, CliCommandHandler, Command},
|
||||
models::{
|
||||
radarr_models::{
|
||||
EditCollectionParams, EditIndexerParams, EditMovieParams, IndexerSettings,
|
||||
MinimumAvailability, RadarrSerdeable,
|
||||
EditCollectionParams, EditMovieParams, IndexerSettings, MinimumAvailability, RadarrSerdeable,
|
||||
},
|
||||
servarr_models::EditIndexerParams,
|
||||
Serdeable,
|
||||
},
|
||||
network::{radarr_network::RadarrEvent, NetworkTrait},
|
||||
|
||||
@@ -810,9 +810,10 @@ mod tests {
|
||||
},
|
||||
models::{
|
||||
radarr_models::{
|
||||
EditCollectionParams, EditIndexerParams, EditMovieParams, IndexerSettings,
|
||||
MinimumAvailability, RadarrSerdeable,
|
||||
EditCollectionParams, EditMovieParams, IndexerSettings, MinimumAvailability,
|
||||
RadarrSerdeable,
|
||||
},
|
||||
servarr_models::EditIndexerParams,
|
||||
Serdeable,
|
||||
},
|
||||
network::{radarr_network::RadarrEvent, MockNetworkTrait, NetworkEvent},
|
||||
|
||||
@@ -5,7 +5,7 @@ mod tests {
|
||||
use crate::event::Key;
|
||||
use crate::handlers::radarr_handlers::indexers::edit_indexer_handler::EditIndexerHandler;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::servarr_data::radarr::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS};
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@@ -14,7 +14,7 @@ mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
|
||||
use crate::models::servarr_data::radarr::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS;
|
||||
use crate::models::BlockSelectionState;
|
||||
|
||||
@@ -69,7 +69,7 @@ mod tests {
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use crate::app::App;
|
||||
use crate::models::servarr_data::radarr::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
use super::*;
|
||||
@@ -334,7 +334,7 @@ mod tests {
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use crate::app::App;
|
||||
use crate::models::servarr_data::radarr::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{
|
||||
EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS,
|
||||
};
|
||||
@@ -759,7 +759,7 @@ mod tests {
|
||||
use rstest::rstest;
|
||||
|
||||
use crate::app::App;
|
||||
use crate::models::servarr_data::radarr::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use crate::models::{
|
||||
servarr_data::radarr::radarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS, BlockSelectionState,
|
||||
};
|
||||
@@ -1224,7 +1224,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::app::App;
|
||||
use crate::event::Key;
|
||||
use crate::models::servarr_data::radarr::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use pretty_assertions::assert_eq;
|
||||
use rstest::rstest;
|
||||
|
||||
@@ -1281,7 +1281,7 @@ mod tests {
|
||||
|
||||
mod test_handle_key_char {
|
||||
use crate::app::App;
|
||||
use crate::models::servarr_data::radarr::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::EDIT_INDEXER_TORRENT_SELECTION_BLOCKS;
|
||||
use crate::models::BlockSelectionState;
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
|
||||
@@ -237,7 +237,7 @@ mod tests {
|
||||
}
|
||||
|
||||
mod test_handle_submit {
|
||||
use crate::models::servarr_data::radarr::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{
|
||||
RadarrData, EDIT_INDEXER_NZB_SELECTION_BLOCKS, EDIT_INDEXER_TORRENT_SELECTION_BLOCKS,
|
||||
};
|
||||
|
||||
@@ -179,22 +179,6 @@ pub struct EditCollectionParams {
|
||||
pub search_on_add: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Serialize, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EditIndexerParams {
|
||||
pub indexer_id: i64,
|
||||
pub name: Option<String>,
|
||||
pub enable_rss: Option<bool>,
|
||||
pub enable_automatic_search: Option<bool>,
|
||||
pub enable_interactive_search: Option<bool>,
|
||||
pub url: Option<String>,
|
||||
pub api_key: Option<String>,
|
||||
pub seed_ratio: Option<String>,
|
||||
pub tags: Option<Vec<i64>>,
|
||||
pub priority: Option<i64>,
|
||||
pub clear_tags: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Serialize, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EditMovieParams {
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
|
||||
#[derive(Default, Debug, PartialEq, Eq)]
|
||||
pub struct EditIndexerModal {
|
||||
pub name: HorizontallyScrollableText,
|
||||
pub enable_rss: Option<bool>,
|
||||
pub enable_automatic_search: Option<bool>,
|
||||
pub enable_interactive_search: Option<bool>,
|
||||
pub url: HorizontallyScrollableText,
|
||||
pub api_key: HorizontallyScrollableText,
|
||||
pub seed_ratio: HorizontallyScrollableText,
|
||||
pub tags: HorizontallyScrollableText,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Eq, PartialEq, Debug)]
|
||||
pub struct IndexerTestResultModalItem {
|
||||
pub name: String,
|
||||
|
||||
@@ -3,6 +3,7 @@ use strum::IntoEnumIterator;
|
||||
use crate::models::radarr_models::{
|
||||
Collection, Credit, MinimumAvailability, Movie, MovieHistoryItem, MovieMonitor, RadarrRelease,
|
||||
};
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::RadarrData;
|
||||
use crate::models::servarr_models::{Indexer, RootFolder};
|
||||
use crate::models::stateful_list::StatefulList;
|
||||
@@ -25,18 +26,6 @@ pub struct MovieDetailsModal {
|
||||
pub movie_releases: StatefulTable<RadarrRelease>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, PartialEq, Eq)]
|
||||
pub struct EditIndexerModal {
|
||||
pub name: HorizontallyScrollableText,
|
||||
pub enable_rss: Option<bool>,
|
||||
pub enable_automatic_search: Option<bool>,
|
||||
pub enable_interactive_search: Option<bool>,
|
||||
pub url: HorizontallyScrollableText,
|
||||
pub api_key: HorizontallyScrollableText,
|
||||
pub seed_ratio: HorizontallyScrollableText,
|
||||
pub tags: HorizontallyScrollableText,
|
||||
}
|
||||
|
||||
impl From<&RadarrData<'_>> for EditIndexerModal {
|
||||
fn from(radarr_data: &RadarrData<'_>) -> EditIndexerModal {
|
||||
let mut edit_indexer_modal = EditIndexerModal::default();
|
||||
|
||||
@@ -16,8 +16,6 @@ mod test {
|
||||
|
||||
#[rstest]
|
||||
fn test_edit_indexer_modal_from_radarr_data(#[values(true, false)] seed_ratio_present: bool) {
|
||||
use crate::models::servarr_models::{Indexer, IndexerField};
|
||||
|
||||
let mut radarr_data = RadarrData {
|
||||
tags_map: BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]),
|
||||
..RadarrData::default()
|
||||
|
||||
@@ -9,9 +9,9 @@ use crate::models::radarr_models::{
|
||||
AddMovieSearchResult, BlocklistItem, Collection, CollectionMovie, DownloadRecord,
|
||||
IndexerSettings, Movie, RadarrTask,
|
||||
};
|
||||
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
||||
use crate::models::servarr_data::modals::{EditIndexerModal, IndexerTestResultModalItem};
|
||||
use crate::models::servarr_data::radarr::modals::{
|
||||
AddMovieModal, EditCollectionModal, EditIndexerModal, EditMovieModal, MovieDetailsModal,
|
||||
AddMovieModal, EditCollectionModal, EditMovieModal, MovieDetailsModal,
|
||||
};
|
||||
use crate::models::servarr_models::{DiskSpace, Indexer, QueueEvent, RootFolder};
|
||||
use crate::models::stateful_list::StatefulList;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::models::{
|
||||
servarr_models::RootFolder,
|
||||
servarr_data::modals::EditIndexerModal,
|
||||
servarr_models::{Indexer, RootFolder},
|
||||
sonarr_models::{Episode, SeriesMonitor, SeriesType, SonarrHistoryItem, SonarrRelease},
|
||||
stateful_list::StatefulList,
|
||||
stateful_table::StatefulTable,
|
||||
@@ -63,6 +64,84 @@ impl From<&SonarrData> for AddSeriesModal {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&SonarrData> for EditIndexerModal {
|
||||
fn from(sonarr_data: &SonarrData) -> EditIndexerModal {
|
||||
let mut edit_indexer_modal = EditIndexerModal::default();
|
||||
let Indexer {
|
||||
name,
|
||||
enable_rss,
|
||||
enable_automatic_search,
|
||||
enable_interactive_search,
|
||||
tags,
|
||||
fields,
|
||||
..
|
||||
} = sonarr_data.indexers.current_selection();
|
||||
let seed_ratio_field_option = fields
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|field| field.name.as_ref().unwrap() == "seedCriteria.seedRatio");
|
||||
let seed_ratio_value_option = if let Some(seed_ratio_field) = seed_ratio_field_option {
|
||||
seed_ratio_field.value.clone()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
edit_indexer_modal.name = name.clone().unwrap().into();
|
||||
edit_indexer_modal.enable_rss = Some(*enable_rss);
|
||||
edit_indexer_modal.enable_automatic_search = Some(*enable_automatic_search);
|
||||
edit_indexer_modal.enable_interactive_search = Some(*enable_interactive_search);
|
||||
edit_indexer_modal.url = fields
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|field| field.name.as_ref().unwrap() == "baseUrl")
|
||||
.unwrap()
|
||||
.value
|
||||
.clone()
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.into();
|
||||
edit_indexer_modal.api_key = fields
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|field| field.name.as_ref().unwrap() == "apiKey")
|
||||
.unwrap()
|
||||
.value
|
||||
.clone()
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
if seed_ratio_value_option.is_some() {
|
||||
edit_indexer_modal.seed_ratio = seed_ratio_value_option
|
||||
.unwrap()
|
||||
.as_f64()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.into();
|
||||
}
|
||||
|
||||
edit_indexer_modal.tags = tags
|
||||
.iter()
|
||||
.map(|tag_id| {
|
||||
sonarr_data
|
||||
.tags_map
|
||||
.get_by_left(&tag_id.as_i64().unwrap())
|
||||
.unwrap()
|
||||
.clone()
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ")
|
||||
.into();
|
||||
|
||||
edit_indexer_modal
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct EpisodeDetailsModal {
|
||||
pub episode_details: ScrollableText,
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bimap::BiMap;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use rstest::rstest;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
use crate::models::servarr_models::{Indexer, IndexerField};
|
||||
use crate::models::{
|
||||
servarr_data::sonarr::{modals::AddSeriesModal, sonarr_data::SonarrData},
|
||||
servarr_models::RootFolder,
|
||||
sonarr_models::{SeriesMonitor, SeriesType},
|
||||
};
|
||||
use serde_json::{Number, Value};
|
||||
|
||||
use crate::models::servarr_data::modals::EditIndexerModal;
|
||||
|
||||
#[test]
|
||||
fn test_add_series_modal_from_sonarr_data() {
|
||||
@@ -55,4 +61,55 @@ mod tests {
|
||||
assert!(add_series_modal.tags.text.is_empty());
|
||||
assert!(add_series_modal.use_season_folder);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_edit_indexer_modal_from_sonarr_data(#[values(true, false)] seed_ratio_present: bool) {
|
||||
let mut sonarr_data = SonarrData {
|
||||
tags_map: BiMap::from_iter([(1, "usenet".to_owned()), (2, "test".to_owned())]),
|
||||
..SonarrData::default()
|
||||
};
|
||||
let mut fields = vec![
|
||||
IndexerField {
|
||||
name: Some("baseUrl".to_owned()),
|
||||
value: Some(Value::String("https://test.com".to_owned())),
|
||||
},
|
||||
IndexerField {
|
||||
name: Some("apiKey".to_owned()),
|
||||
value: Some(Value::String("1234".to_owned())),
|
||||
},
|
||||
];
|
||||
|
||||
if seed_ratio_present {
|
||||
fields.push(IndexerField {
|
||||
name: Some("seedCriteria.seedRatio".to_owned()),
|
||||
value: Some(Value::from(1.2f64)),
|
||||
});
|
||||
}
|
||||
|
||||
let indexer = Indexer {
|
||||
name: Some("Test".to_owned()),
|
||||
enable_rss: true,
|
||||
enable_automatic_search: true,
|
||||
enable_interactive_search: true,
|
||||
tags: vec![Number::from(1), Number::from(2)],
|
||||
fields: Some(fields),
|
||||
..Indexer::default()
|
||||
};
|
||||
sonarr_data.indexers.set_items(vec![indexer]);
|
||||
|
||||
let edit_indexer_modal = EditIndexerModal::from(&sonarr_data);
|
||||
|
||||
assert_str_eq!(edit_indexer_modal.name.text, "Test");
|
||||
assert_eq!(edit_indexer_modal.enable_rss, Some(true));
|
||||
assert_eq!(edit_indexer_modal.enable_automatic_search, Some(true));
|
||||
assert_eq!(edit_indexer_modal.enable_interactive_search, Some(true));
|
||||
assert_str_eq!(edit_indexer_modal.url.text, "https://test.com");
|
||||
assert_str_eq!(edit_indexer_modal.api_key.text, "1234");
|
||||
|
||||
if seed_ratio_present {
|
||||
assert_str_eq!(edit_indexer_modal.seed_ratio.text, "1.2");
|
||||
} else {
|
||||
assert!(edit_indexer_modal.seed_ratio.text.is_empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
|
||||
use strum::EnumIter;
|
||||
|
||||
use crate::models::{
|
||||
servarr_data::modals::IndexerTestResultModalItem,
|
||||
servarr_data::modals::{EditIndexerModal, IndexerTestResultModalItem},
|
||||
servarr_models::{DiskSpace, Indexer, QueueEvent, RootFolder},
|
||||
sonarr_models::{
|
||||
AddSeriesSearchResult, BlocklistItem, DownloadRecord, IndexerSettings, Season, Series,
|
||||
@@ -29,6 +29,7 @@ pub struct SonarrData {
|
||||
pub delete_series_files: bool,
|
||||
pub downloads: StatefulTable<DownloadRecord>,
|
||||
pub disk_space_vec: Vec<DiskSpace>,
|
||||
pub edit_indexer_modal: Option<EditIndexerModal>,
|
||||
pub edit_root_folder: Option<HorizontallyScrollableText>,
|
||||
pub history: StatefulTable<SonarrHistoryItem>,
|
||||
pub indexers: StatefulTable<Indexer>,
|
||||
@@ -69,6 +70,7 @@ impl Default for SonarrData {
|
||||
downloads: StatefulTable::default(),
|
||||
delete_series_files: false,
|
||||
disk_space_vec: Vec::new(),
|
||||
edit_indexer_modal: None,
|
||||
edit_root_folder: None,
|
||||
history: StatefulTable::default(),
|
||||
indexers: StatefulTable::default(),
|
||||
|
||||
@@ -56,6 +56,7 @@ mod tests {
|
||||
assert!(!sonarr_data.delete_series_files);
|
||||
assert!(sonarr_data.downloads.is_empty());
|
||||
assert!(sonarr_data.disk_space_vec.is_empty());
|
||||
assert!(sonarr_data.edit_indexer_modal.is_none());
|
||||
assert!(sonarr_data.edit_root_folder.is_none());
|
||||
assert!(sonarr_data.history.is_empty());
|
||||
assert!(sonarr_data.indexers.is_empty());
|
||||
|
||||
@@ -89,6 +89,22 @@ pub struct DiskSpace {
|
||||
pub total_space: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Serialize, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EditIndexerParams {
|
||||
pub indexer_id: i64,
|
||||
pub name: Option<String>,
|
||||
pub enable_rss: Option<bool>,
|
||||
pub enable_automatic_search: Option<bool>,
|
||||
pub enable_interactive_search: Option<bool>,
|
||||
pub url: Option<String>,
|
||||
pub api_key: Option<String>,
|
||||
pub seed_ratio: Option<String>,
|
||||
pub tags: Option<Vec<i64>>,
|
||||
pub priority: Option<i64>,
|
||||
pub clear_tags: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HostConfig {
|
||||
|
||||
@@ -9,18 +9,18 @@ use urlencoding::encode;
|
||||
use crate::models::radarr_models::{
|
||||
AddMovieBody, AddMovieOptions, AddMovieSearchResult, BlocklistResponse, Collection,
|
||||
CollectionMovie, Credit, CreditType, DeleteMovieParams, DownloadRecord, DownloadsResponse,
|
||||
EditCollectionParams, EditIndexerParams, EditMovieParams, IndexerSettings, IndexerTestResult,
|
||||
Movie, MovieCommandBody, MovieHistoryItem, RadarrRelease, RadarrReleaseDownloadBody,
|
||||
RadarrSerdeable, RadarrTask, RadarrTaskName, SystemStatus,
|
||||
EditCollectionParams, EditMovieParams, IndexerSettings, IndexerTestResult, Movie,
|
||||
MovieCommandBody, MovieHistoryItem, RadarrRelease, RadarrReleaseDownloadBody, RadarrSerdeable,
|
||||
RadarrTask, RadarrTaskName, SystemStatus,
|
||||
};
|
||||
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
||||
use crate::models::servarr_data::modals::{EditIndexerModal, IndexerTestResultModalItem};
|
||||
use crate::models::servarr_data::radarr::modals::{
|
||||
AddMovieModal, EditCollectionModal, EditIndexerModal, EditMovieModal, MovieDetailsModal,
|
||||
AddMovieModal, EditCollectionModal, EditMovieModal, MovieDetailsModal,
|
||||
};
|
||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||
use crate::models::servarr_models::{
|
||||
AddRootFolderBody, CommandBody, DiskSpace, HostConfig, Indexer, LogResponse, QualityProfile,
|
||||
QueueEvent, RootFolder, SecurityConfig, Tag, Update,
|
||||
AddRootFolderBody, CommandBody, DiskSpace, EditIndexerParams, HostConfig, Indexer, LogResponse,
|
||||
QualityProfile, QueueEvent, RootFolder, SecurityConfig, Tag, Update,
|
||||
};
|
||||
use crate::models::stateful_table::StatefulTable;
|
||||
use crate::models::{HorizontallyScrollableText, Route, Scrollable, ScrollableText};
|
||||
@@ -188,9 +188,10 @@ impl<'a, 'b> Network<'a, 'b> {
|
||||
.edit_collection(params)
|
||||
.await
|
||||
.map(RadarrSerdeable::from),
|
||||
RadarrEvent::EditIndexer(params) => {
|
||||
self.edit_indexer(params).await.map(RadarrSerdeable::from)
|
||||
}
|
||||
RadarrEvent::EditIndexer(params) => self
|
||||
.edit_radarr_indexer(params)
|
||||
.await
|
||||
.map(RadarrSerdeable::from),
|
||||
RadarrEvent::EditMovie(params) => self.edit_movie(params).await.map(RadarrSerdeable::from),
|
||||
RadarrEvent::GetAllIndexerSettings => self
|
||||
.get_all_radarr_indexer_settings()
|
||||
@@ -882,7 +883,10 @@ impl<'a, 'b> Network<'a, 'b> {
|
||||
.await
|
||||
}
|
||||
|
||||
async fn edit_indexer(&mut self, edit_indexer_params: Option<EditIndexerParams>) -> Result<()> {
|
||||
async fn edit_radarr_indexer(
|
||||
&mut self,
|
||||
edit_indexer_params: Option<EditIndexerParams>,
|
||||
) -> Result<()> {
|
||||
let detail_event = RadarrEvent::GetIndexers;
|
||||
let event = RadarrEvent::EditIndexer(None);
|
||||
let id = if let Some(ref params) = edit_indexer_params {
|
||||
|
||||
@@ -4053,7 +4053,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_edit_indexer_event() {
|
||||
async fn test_handle_edit_radarr_indexer_event() {
|
||||
let indexer_details_json = json!({
|
||||
"enableRss": true,
|
||||
"enableAutomaticSearch": true,
|
||||
@@ -4153,7 +4153,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_edit_indexer_event_does_not_add_seed_ratio_when_seed_ratio_field_is_none_in_details(
|
||||
async fn test_handle_edit_radarr_indexer_event_does_not_add_seed_ratio_when_seed_ratio_field_is_none_in_details(
|
||||
) {
|
||||
let indexer_details_json = json!({
|
||||
"enableRss": true,
|
||||
@@ -4255,7 +4255,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_edit_indexer_event_populates_the_seed_ratio_value_when_seed_ratio_field_is_present_in_details(
|
||||
async fn test_handle_edit_radarr_indexer_event_populates_the_seed_ratio_value_when_seed_ratio_field_is_present_in_details(
|
||||
) {
|
||||
let indexer_details_json = json!({
|
||||
"enableRss": true,
|
||||
@@ -4371,7 +4371,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_edit_indexer_event_uses_provided_parameters() {
|
||||
async fn test_handle_edit_radarr_indexer_event_uses_provided_parameters() {
|
||||
let indexer_details_json = json!({
|
||||
"enableRss": true,
|
||||
"enableAutomaticSearch": true,
|
||||
@@ -4464,7 +4464,8 @@ mod test {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_edit_indexer_event_uses_provided_parameters_defaults_to_previous_values() {
|
||||
async fn test_handle_edit_radarr_indexer_event_uses_provided_parameters_defaults_to_previous_values(
|
||||
) {
|
||||
let indexer_details_json = json!({
|
||||
"enableRss": true,
|
||||
"enableAutomaticSearch": true,
|
||||
@@ -4525,7 +4526,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_edit_indexer_event_uses_provided_parameters_clears_tags_when_clear_tags_is_true(
|
||||
async fn test_handle_edit_radarr_indexer_event_uses_provided_parameters_clears_tags_when_clear_tags_is_true(
|
||||
) {
|
||||
let indexer_details_json = json!({
|
||||
"enableRss": true,
|
||||
|
||||
@@ -8,15 +8,15 @@ use crate::{
|
||||
models::{
|
||||
radarr_models::IndexerTestResult,
|
||||
servarr_data::{
|
||||
modals::IndexerTestResultModalItem,
|
||||
modals::{EditIndexerModal, IndexerTestResultModalItem},
|
||||
sonarr::{
|
||||
modals::{AddSeriesModal, EpisodeDetailsModal, SeasonDetailsModal},
|
||||
sonarr_data::ActiveSonarrBlock,
|
||||
},
|
||||
},
|
||||
servarr_models::{
|
||||
AddRootFolderBody, CommandBody, DiskSpace, HostConfig, Indexer, Language, LogResponse,
|
||||
QualityProfile, QueueEvent, RootFolder, SecurityConfig, Tag, Update,
|
||||
AddRootFolderBody, CommandBody, DiskSpace, EditIndexerParams, HostConfig, Indexer, Language,
|
||||
LogResponse, QualityProfile, QueueEvent, RootFolder, SecurityConfig, Tag, Update,
|
||||
},
|
||||
sonarr_models::{
|
||||
AddSeriesBody, AddSeriesOptions, AddSeriesSearchResult, BlocklistResponse,
|
||||
@@ -51,6 +51,7 @@ pub enum SonarrEvent {
|
||||
DeleteTag(i64),
|
||||
DownloadRelease(SonarrReleaseDownloadBody),
|
||||
EditAllIndexerSettings(Option<IndexerSettings>),
|
||||
EditIndexer(Option<EditIndexerParams>),
|
||||
GetAllIndexerSettings,
|
||||
GetBlocklist,
|
||||
GetDownloads,
|
||||
@@ -106,7 +107,9 @@ impl NetworkResource for SonarrEvent {
|
||||
SonarrEvent::GetEpisodes(_) | SonarrEvent::GetEpisodeDetails(_) => "/episode",
|
||||
SonarrEvent::GetHistory(_) | SonarrEvent::GetEpisodeHistory(_) => "/history",
|
||||
SonarrEvent::GetHostConfig | SonarrEvent::GetSecurityConfig => "/config/host",
|
||||
SonarrEvent::GetIndexers | SonarrEvent::DeleteIndexer(_) => "/indexer",
|
||||
SonarrEvent::GetIndexers | SonarrEvent::DeleteIndexer(_) | SonarrEvent::EditIndexer(_) => {
|
||||
"/indexer"
|
||||
}
|
||||
SonarrEvent::GetLanguageProfiles => "/languageprofile",
|
||||
SonarrEvent::GetLogs(_) => "/log",
|
||||
SonarrEvent::GetDiskSpace => "/diskspace",
|
||||
@@ -204,6 +207,10 @@ impl<'a, 'b> Network<'a, 'b> {
|
||||
.edit_all_sonarr_indexer_settings(params)
|
||||
.await
|
||||
.map(SonarrSerdeable::from),
|
||||
SonarrEvent::EditIndexer(params) => self
|
||||
.edit_sonarr_indexer(params)
|
||||
.await
|
||||
.map(SonarrSerdeable::from),
|
||||
SonarrEvent::GetBlocklist => self.get_sonarr_blocklist().await.map(SonarrSerdeable::from),
|
||||
SonarrEvent::GetDownloads => self.get_sonarr_downloads().await.map(SonarrSerdeable::from),
|
||||
SonarrEvent::GetEpisodes(series_id) => self
|
||||
@@ -800,6 +807,261 @@ impl<'a, 'b> Network<'a, 'b> {
|
||||
resp
|
||||
}
|
||||
|
||||
async fn edit_sonarr_indexer(
|
||||
&mut self,
|
||||
edit_indexer_params: Option<EditIndexerParams>,
|
||||
) -> Result<()> {
|
||||
let detail_event = SonarrEvent::GetIndexers;
|
||||
let event = SonarrEvent::EditIndexer(None);
|
||||
let id = if let Some(ref params) = edit_indexer_params {
|
||||
params.indexer_id
|
||||
} else {
|
||||
self
|
||||
.app
|
||||
.lock()
|
||||
.await
|
||||
.data
|
||||
.sonarr_data
|
||||
.indexers
|
||||
.current_selection()
|
||||
.id
|
||||
};
|
||||
info!("Updating Sonarr indexer with ID: {id}");
|
||||
|
||||
info!("Fetching indexer details for indexer with ID: {id}");
|
||||
|
||||
let request_props = self
|
||||
.request_props_from(
|
||||
detail_event,
|
||||
RequestMethod::Get,
|
||||
None::<()>,
|
||||
Some(format!("/{id}")),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut response = String::new();
|
||||
|
||||
self
|
||||
.handle_request::<(), Value>(request_props, |detailed_indexer_body, _| {
|
||||
response = detailed_indexer_body.to_string()
|
||||
})
|
||||
.await?;
|
||||
|
||||
info!("Constructing edit indexer body");
|
||||
|
||||
let mut detailed_indexer_body: Value = serde_json::from_str(&response).unwrap();
|
||||
let priority = detailed_indexer_body["priority"]
|
||||
.as_i64()
|
||||
.expect("Unable to deserialize 'priority'");
|
||||
|
||||
let (
|
||||
name,
|
||||
enable_rss,
|
||||
enable_automatic_search,
|
||||
enable_interactive_search,
|
||||
url,
|
||||
api_key,
|
||||
seed_ratio,
|
||||
tags,
|
||||
priority,
|
||||
) = if let Some(params) = edit_indexer_params {
|
||||
let seed_ratio_field_option = detailed_indexer_body["fields"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|field| field["name"] == "seedCriteria.seedRatio");
|
||||
let name = 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(
|
||||
detailed_indexer_body["enableRss"]
|
||||
.as_bool()
|
||||
.expect("Unable to deserialize 'enableRss'"),
|
||||
);
|
||||
let enable_automatic_search = 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(
|
||||
detailed_indexer_body["enableInteractiveSearch"]
|
||||
.as_bool()
|
||||
.expect("Unable to deserialize 'enableInteractiveSearch'"),
|
||||
);
|
||||
let url = params.url.unwrap_or(
|
||||
detailed_indexer_body["fields"]
|
||||
.as_array()
|
||||
.expect("Unable to deserialize 'fields'")
|
||||
.iter()
|
||||
.find(|field| field["name"] == "baseUrl")
|
||||
.expect("Field 'baseUrl' was not found in the 'fields' array")
|
||||
.get("value")
|
||||
.unwrap_or(&json!(""))
|
||||
.as_str()
|
||||
.expect("Unable to deserialize 'baseUrl value'")
|
||||
.to_owned(),
|
||||
);
|
||||
let api_key = params.api_key.unwrap_or(
|
||||
detailed_indexer_body["fields"]
|
||||
.as_array()
|
||||
.expect("Unable to deserialize 'fields'")
|
||||
.iter()
|
||||
.find(|field| field["name"] == "apiKey")
|
||||
.expect("Field 'apiKey' was not found in the 'fields' array")
|
||||
.get("value")
|
||||
.unwrap_or(&json!(""))
|
||||
.as_str()
|
||||
.expect("Unable to deserialize 'apiKey value'")
|
||||
.to_owned(),
|
||||
);
|
||||
let seed_ratio = params.seed_ratio.unwrap_or_else(|| {
|
||||
if let Some(seed_ratio_field) = seed_ratio_field_option {
|
||||
return seed_ratio_field
|
||||
.get("value")
|
||||
.unwrap_or(&json!(""))
|
||||
.as_str()
|
||||
.expect("Unable to deserialize 'seedCriteria.seedRatio value'")
|
||||
.to_owned();
|
||||
}
|
||||
|
||||
String::new()
|
||||
});
|
||||
let tags = if params.clear_tags {
|
||||
vec![]
|
||||
} else {
|
||||
params.tags.unwrap_or(
|
||||
detailed_indexer_body["tags"]
|
||||
.as_array()
|
||||
.expect("Unable to deserialize 'tags'")
|
||||
.iter()
|
||||
.map(|item| item.as_i64().expect("Unable to deserialize tag ID"))
|
||||
.collect(),
|
||||
)
|
||||
};
|
||||
let priority = params.priority.unwrap_or(priority);
|
||||
|
||||
(
|
||||
name,
|
||||
enable_rss,
|
||||
enable_automatic_search,
|
||||
enable_interactive_search,
|
||||
url,
|
||||
api_key,
|
||||
seed_ratio,
|
||||
tags,
|
||||
priority,
|
||||
)
|
||||
} else {
|
||||
let tags = self
|
||||
.app
|
||||
.lock()
|
||||
.await
|
||||
.data
|
||||
.sonarr_data
|
||||
.edit_indexer_modal
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.tags
|
||||
.text
|
||||
.clone();
|
||||
let tag_ids_vec = self.extract_and_add_sonarr_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,
|
||||
..
|
||||
} = app.data.sonarr_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.sonarr_data.edit_indexer_modal = None;
|
||||
|
||||
params
|
||||
};
|
||||
|
||||
*detailed_indexer_body.get_mut("name").unwrap() = json!(name);
|
||||
*detailed_indexer_body.get_mut("priority").unwrap() = json!(priority);
|
||||
*detailed_indexer_body.get_mut("enableRss").unwrap() = json!(enable_rss);
|
||||
*detailed_indexer_body
|
||||
.get_mut("enableAutomaticSearch")
|
||||
.unwrap() = json!(enable_automatic_search);
|
||||
*detailed_indexer_body
|
||||
.get_mut("enableInteractiveSearch")
|
||||
.unwrap() = json!(enable_interactive_search);
|
||||
*detailed_indexer_body
|
||||
.get_mut("fields")
|
||||
.unwrap()
|
||||
.as_array_mut()
|
||||
.unwrap()
|
||||
.iter_mut()
|
||||
.find(|field| field["name"] == "baseUrl")
|
||||
.unwrap()
|
||||
.get_mut("value")
|
||||
.unwrap() = json!(url);
|
||||
*detailed_indexer_body
|
||||
.get_mut("fields")
|
||||
.unwrap()
|
||||
.as_array_mut()
|
||||
.unwrap()
|
||||
.iter_mut()
|
||||
.find(|field| field["name"] == "apiKey")
|
||||
.unwrap()
|
||||
.get_mut("value")
|
||||
.unwrap() = json!(api_key);
|
||||
*detailed_indexer_body.get_mut("tags").unwrap() = json!(tags);
|
||||
let seed_ratio_field_option = detailed_indexer_body
|
||||
.get_mut("fields")
|
||||
.unwrap()
|
||||
.as_array_mut()
|
||||
.unwrap()
|
||||
.iter_mut()
|
||||
.find(|field| field["name"] == "seedCriteria.seedRatio");
|
||||
if let Some(seed_ratio_field) = seed_ratio_field_option {
|
||||
seed_ratio_field
|
||||
.as_object_mut()
|
||||
.unwrap()
|
||||
.insert("value".to_string(), json!(seed_ratio));
|
||||
}
|
||||
|
||||
debug!("Edit indexer body: {detailed_indexer_body:?}");
|
||||
|
||||
let request_props = self
|
||||
.request_props_from(
|
||||
event,
|
||||
RequestMethod::Put,
|
||||
Some(detailed_indexer_body),
|
||||
Some(format!("/{id}")),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
self
|
||||
.handle_request::<Value, ()>(request_props, |_, _| ())
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_all_sonarr_indexer_settings(&mut self) -> Result<IndexerSettings> {
|
||||
info!("Fetching Sonarr indexer settings");
|
||||
let event = SonarrEvent::GetAllIndexerSettings;
|
||||
|
||||
@@ -22,14 +22,14 @@ mod test {
|
||||
|
||||
use crate::app::{App, ServarrConfig};
|
||||
use crate::models::radarr_models::IndexerTestResult;
|
||||
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
||||
use crate::models::servarr_data::modals::{EditIndexerModal, IndexerTestResultModalItem};
|
||||
use crate::models::servarr_data::sonarr::modals::{
|
||||
AddSeriesModal, EpisodeDetailsModal, SeasonDetailsModal,
|
||||
};
|
||||
use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
|
||||
use crate::models::servarr_models::{
|
||||
DiskSpace, HostConfig, Indexer, IndexerField, Language, LogResponse, Quality, QualityProfile,
|
||||
QualityWrapper, QueueEvent, RootFolder, SecurityConfig, Tag, Update,
|
||||
DiskSpace, EditIndexerParams, HostConfig, Indexer, IndexerField, Language, LogResponse,
|
||||
Quality, QualityProfile, QualityWrapper, QueueEvent, RootFolder, SecurityConfig, Tag, Update,
|
||||
};
|
||||
use crate::models::sonarr_models::{
|
||||
BlocklistItem, DeleteSeriesParams, DownloadRecord, DownloadsResponse, Episode, EpisodeFile,
|
||||
@@ -205,7 +205,12 @@ mod test {
|
||||
|
||||
#[rstest]
|
||||
fn test_resource_indexer(
|
||||
#[values(SonarrEvent::GetIndexers, SonarrEvent::DeleteIndexer(None))] event: SonarrEvent,
|
||||
#[values(
|
||||
SonarrEvent::GetIndexers,
|
||||
SonarrEvent::DeleteIndexer(None),
|
||||
SonarrEvent::EditIndexer(None)
|
||||
)]
|
||||
event: SonarrEvent,
|
||||
) {
|
||||
assert_str_eq!(event.resource(), "/indexer");
|
||||
}
|
||||
@@ -1126,6 +1131,565 @@ mod test {
|
||||
async_server.assert_async().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_edit_sonarr_indexer_event() {
|
||||
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": 1,
|
||||
"fields": [
|
||||
{
|
||||
"name": "baseUrl",
|
||||
"value": "https://localhost:9696/1/",
|
||||
},
|
||||
{
|
||||
"name": "apiKey",
|
||||
"value": "test1234",
|
||||
},
|
||||
{
|
||||
"name": "seedCriteria.seedRatio",
|
||||
"value": "1.3",
|
||||
},
|
||||
],
|
||||
"tags": [1, 2],
|
||||
"id": 1
|
||||
});
|
||||
|
||||
let (async_details_server, app_arc, mut server) = mock_servarr_api(
|
||||
RequestMethod::Get,
|
||||
None,
|
||||
Some(indexer_details_json),
|
||||
None,
|
||||
SonarrEvent::GetIndexers,
|
||||
Some("/1"),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let async_edit_server = server
|
||||
.mock(
|
||||
"PUT",
|
||||
format!("/api/v3{}/1", SonarrEvent::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.sonarr_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(),
|
||||
};
|
||||
app.data.sonarr_data.edit_indexer_modal = Some(edit_indexer_modal);
|
||||
app.data.sonarr_data.indexers.set_items(vec![indexer()]);
|
||||
}
|
||||
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||
|
||||
assert!(network
|
||||
.handle_sonarr_event(SonarrEvent::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.sonarr_data.edit_indexer_modal.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_edit_sonarr_indexer_event_does_not_add_seed_ratio_when_seed_ratio_field_is_none_in_details(
|
||||
) {
|
||||
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": "",
|
||||
},
|
||||
],
|
||||
"tags": [1],
|
||||
"id": 1
|
||||
});
|
||||
let expected_indexer_edit_body_json = json!({
|
||||
"enableRss": false,
|
||||
"enableAutomaticSearch": false,
|
||||
"enableInteractiveSearch": false,
|
||||
"name": "Test Update",
|
||||
"priority": 1,
|
||||
"fields": [
|
||||
{
|
||||
"name": "baseUrl",
|
||||
"value": "https://localhost:9696/1/",
|
||||
},
|
||||
{
|
||||
"name": "apiKey",
|
||||
"value": "test1234",
|
||||
},
|
||||
],
|
||||
"tags": [1, 2],
|
||||
"id": 1
|
||||
});
|
||||
|
||||
let (async_details_server, app_arc, mut server) = mock_servarr_api(
|
||||
RequestMethod::Get,
|
||||
None,
|
||||
Some(indexer_details_json),
|
||||
None,
|
||||
SonarrEvent::GetIndexers,
|
||||
Some("/1"),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let async_edit_server = server
|
||||
.mock(
|
||||
"PUT",
|
||||
format!("/api/v3{}/1", SonarrEvent::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.sonarr_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(),
|
||||
};
|
||||
app.data.sonarr_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.sonarr_data.indexers.set_items(vec![indexer]);
|
||||
}
|
||||
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||
|
||||
assert!(network
|
||||
.handle_sonarr_event(SonarrEvent::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.sonarr_data.edit_indexer_modal.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_edit_sonarr_indexer_event_populates_the_seed_ratio_value_when_seed_ratio_field_is_present_in_details(
|
||||
) {
|
||||
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",
|
||||
},
|
||||
],
|
||||
"tags": [1],
|
||||
"id": 1
|
||||
});
|
||||
let expected_indexer_edit_body_json = json!({
|
||||
"enableRss": false,
|
||||
"enableAutomaticSearch": false,
|
||||
"enableInteractiveSearch": false,
|
||||
"name": "Test Update",
|
||||
"priority": 1,
|
||||
"fields": [
|
||||
{
|
||||
"name": "baseUrl",
|
||||
"value": "https://localhost:9696/1/",
|
||||
},
|
||||
{
|
||||
"name": "apiKey",
|
||||
"value": "test1234",
|
||||
},
|
||||
{
|
||||
"name": "seedCriteria.seedRatio",
|
||||
"value": "1.3",
|
||||
},
|
||||
],
|
||||
"tags": [1, 2],
|
||||
"id": 1
|
||||
});
|
||||
|
||||
let (async_details_server, app_arc, mut server) = mock_servarr_api(
|
||||
RequestMethod::Get,
|
||||
None,
|
||||
Some(indexer_details_json),
|
||||
None,
|
||||
SonarrEvent::GetIndexers,
|
||||
Some("/1"),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let async_edit_server = server
|
||||
.mock(
|
||||
"PUT",
|
||||
format!("/api/v3{}/1", SonarrEvent::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.sonarr_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(),
|
||||
};
|
||||
app.data.sonarr_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.sonarr_data.indexers.set_items(vec![indexer]);
|
||||
}
|
||||
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||
|
||||
assert!(network
|
||||
.handle_sonarr_event(SonarrEvent::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.sonarr_data.edit_indexer_modal.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_edit_sonarr_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()),
|
||||
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(25),
|
||||
..EditIndexerParams::default()
|
||||
};
|
||||
|
||||
let (async_details_server, app_arc, mut server) = mock_servarr_api(
|
||||
RequestMethod::Get,
|
||||
None,
|
||||
Some(indexer_details_json),
|
||||
None,
|
||||
SonarrEvent::GetIndexers,
|
||||
Some("/1"),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let async_edit_server = server
|
||||
.mock(
|
||||
"PUT",
|
||||
format!("/api/v3{}/1", SonarrEvent::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 network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||
|
||||
assert!(network
|
||||
.handle_sonarr_event(SonarrEvent::EditIndexer(Some(edit_indexer_params)))
|
||||
.await
|
||||
.is_ok());
|
||||
|
||||
async_details_server.assert_async().await;
|
||||
async_edit_server.assert_async().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_edit_sonarr_indexer_event_uses_provided_parameters_defaults_to_previous_values(
|
||||
) {
|
||||
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 edit_indexer_params = EditIndexerParams {
|
||||
indexer_id: 1,
|
||||
..EditIndexerParams::default()
|
||||
};
|
||||
|
||||
let (async_details_server, app_arc, mut server) = mock_servarr_api(
|
||||
RequestMethod::Get,
|
||||
None,
|
||||
Some(indexer_details_json.clone()),
|
||||
None,
|
||||
SonarrEvent::GetIndexers,
|
||||
Some("/1"),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let async_edit_server = server
|
||||
.mock(
|
||||
"PUT",
|
||||
format!("/api/v3{}/1", SonarrEvent::EditIndexer(None).resource()).as_str(),
|
||||
)
|
||||
.with_status(202)
|
||||
.match_header("X-Api-Key", "test1234")
|
||||
.match_body(Matcher::Json(indexer_details_json))
|
||||
.create_async()
|
||||
.await;
|
||||
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||
|
||||
assert!(network
|
||||
.handle_sonarr_event(SonarrEvent::EditIndexer(Some(edit_indexer_params)))
|
||||
.await
|
||||
.is_ok());
|
||||
|
||||
async_details_server.assert_async().await;
|
||||
async_edit_server.assert_async().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_edit_sonarr_indexer_event_uses_provided_parameters_clears_tags_when_clear_tags_is_true(
|
||||
) {
|
||||
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, 2],
|
||||
"id": 1
|
||||
});
|
||||
let expected_edit_indexer_body = 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": [],
|
||||
"id": 1
|
||||
});
|
||||
let edit_indexer_params = EditIndexerParams {
|
||||
indexer_id: 1,
|
||||
clear_tags: true,
|
||||
..EditIndexerParams::default()
|
||||
};
|
||||
|
||||
let (async_details_server, app_arc, mut server) = mock_servarr_api(
|
||||
RequestMethod::Get,
|
||||
None,
|
||||
Some(indexer_details_json),
|
||||
None,
|
||||
SonarrEvent::GetIndexers,
|
||||
Some("/1"),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let async_edit_server = server
|
||||
.mock(
|
||||
"PUT",
|
||||
format!("/api/v3{}/1", SonarrEvent::EditIndexer(None).resource()).as_str(),
|
||||
)
|
||||
.with_status(202)
|
||||
.match_header("X-Api-Key", "test1234")
|
||||
.match_body(Matcher::Json(expected_edit_indexer_body))
|
||||
.create_async()
|
||||
.await;
|
||||
let mut network = Network::new(&app_arc, CancellationToken::new(), Client::new());
|
||||
|
||||
assert!(network
|
||||
.handle_sonarr_event(SonarrEvent::EditIndexer(Some(edit_indexer_params)))
|
||||
.await
|
||||
.is_ok());
|
||||
|
||||
async_details_server.assert_async().await;
|
||||
async_edit_server.assert_async().await;
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[tokio::test]
|
||||
async fn test_handle_get_sonarr_blocklist_event(#[values(true, false)] use_custom_sorting: bool) {
|
||||
|
||||
Reference in New Issue
Block a user