feat(network): Added network support for fetching host and security configs from Sonarr

This commit is contained in:
2024-11-18 20:49:07 -07:00
parent f094cf5ad3
commit a012945df2
17 changed files with 328 additions and 205 deletions
+1
View File
@@ -10,6 +10,7 @@ use servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
use sonarr_models::SonarrSerdeable;
pub mod radarr_models;
pub mod servarr_data;
pub mod servarr_models;
pub mod sonarr_models;
pub mod stateful_list;
pub mod stateful_table;
+1 -114
View File
@@ -9,6 +9,7 @@ use strum_macros::EnumIter;
use crate::{models::HorizontallyScrollableText, serde_enum_from};
use super::servarr_models::{HostConfig, Indexer, SecurityConfig};
use super::Serdeable;
#[cfg(test)]
@@ -57,44 +58,6 @@ pub struct AddRootFolderBody {
pub path: String,
}
#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone, Copy, Debug, ValueEnum)]
#[serde(rename_all = "camelCase")]
pub enum AuthenticationMethod {
#[default]
Basic,
Forms,
None,
}
impl Display for AuthenticationMethod {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let authentication_method = match self {
AuthenticationMethod::Basic => "basic",
AuthenticationMethod::Forms => "forms",
AuthenticationMethod::None => "none",
};
write!(f, "{authentication_method}")
}
}
#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone, Copy, Debug, ValueEnum)]
#[serde(rename_all = "camelCase")]
pub enum AuthenticationRequired {
Enabled,
#[default]
DisabledForLocalAddresses,
}
impl Display for AuthenticationRequired {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let authentication_required = match self {
AuthenticationRequired::Enabled => "enabled",
AuthenticationRequired::DisabledForLocalAddresses => "disabledForLocalAddresses",
};
write!(f, "{authentication_required}")
}
}
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct BlocklistResponse {
pub records: Vec<BlocklistItem>,
@@ -123,26 +86,6 @@ pub struct BlocklistItemMovie {
pub title: HorizontallyScrollableText,
}
#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone, Copy, Debug, ValueEnum)]
#[serde(rename_all = "camelCase")]
pub enum CertificateValidation {
#[default]
Enabled,
DisabledForLocalAddresses,
Disabled,
}
impl Display for CertificateValidation {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let certificate_validation = match self {
CertificateValidation::Enabled => "enabled",
CertificateValidation::DisabledForLocalAddresses => "disabledForLocalAddresses",
CertificateValidation::Disabled => "disabled",
};
write!(f, "{certificate_validation}")
}
}
#[derive(Serialize, Deserialize, Derivative, Default, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct Collection {
@@ -281,51 +224,6 @@ pub struct EditMovieParams {
pub clear_tags: bool,
}
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct HostConfig {
pub bind_address: HorizontallyScrollableText,
#[serde(deserialize_with = "super::from_i64")]
pub port: i64,
pub url_base: Option<HorizontallyScrollableText>,
pub instance_name: Option<HorizontallyScrollableText>,
pub application_url: Option<HorizontallyScrollableText>,
pub enable_ssl: bool,
#[serde(deserialize_with = "super::from_i64")]
pub ssl_port: i64,
pub ssl_cert_path: Option<String>,
pub ssl_cert_password: Option<String>,
}
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Indexer {
#[serde(deserialize_with = "super::from_i64")]
pub id: i64,
pub name: Option<String>,
pub implementation: Option<String>,
pub implementation_name: Option<String>,
pub config_contract: Option<String>,
pub supports_rss: bool,
pub supports_search: bool,
pub fields: Option<Vec<IndexerField>>,
pub enable_rss: bool,
pub enable_automatic_search: bool,
pub enable_interactive_search: bool,
pub protocol: String,
#[serde(deserialize_with = "super::from_i64")]
pub priority: i64,
#[serde(deserialize_with = "super::from_i64")]
pub download_client_id: i64,
pub tags: Vec<Number>,
}
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
pub struct IndexerField {
pub name: Option<String>,
pub value: Option<Value>,
}
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct IndexerSettings {
@@ -634,17 +532,6 @@ pub struct RootFolder {
pub unmapped_folders: Option<Vec<UnmappedFolder>>,
}
#[derive(Default, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct SecurityConfig {
pub authentication_method: AuthenticationMethod,
pub authentication_required: AuthenticationRequired,
pub username: String,
pub password: Option<String>,
pub api_key: String,
pub certificate_validation: CertificateValidation,
}
#[derive(Default, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct SystemStatus {
+4 -31
View File
@@ -5,41 +5,14 @@ mod tests {
use crate::models::{
radarr_models::{
AddMovieSearchResult, AuthenticationMethod, AuthenticationRequired, BlocklistItem,
BlocklistResponse, CertificateValidation, Collection, Credit, DiskSpace, DownloadRecord,
DownloadsResponse, Indexer, IndexerSettings, IndexerTestResult, Log, LogResponse,
MinimumAvailability, Monitor, Movie, MovieHistoryItem, QualityProfile, QueueEvent,
RadarrSerdeable, Release, RootFolder, SystemStatus, Tag, Task, TaskName, Update,
AddMovieSearchResult, BlocklistItem, BlocklistResponse, Collection, Credit, DiskSpace,
DownloadRecord, DownloadsResponse, Indexer, IndexerSettings, IndexerTestResult, Log,
LogResponse, MinimumAvailability, Monitor, Movie, MovieHistoryItem, QualityProfile,
QueueEvent, RadarrSerdeable, Release, RootFolder, SystemStatus, Tag, Task, TaskName, Update,
},
Serdeable,
};
#[test]
fn test_authentication_method_display() {
assert_str_eq!(AuthenticationMethod::Basic.to_string(), "basic");
assert_str_eq!(AuthenticationMethod::Forms.to_string(), "forms");
assert_str_eq!(AuthenticationMethod::None.to_string(), "none");
}
#[test]
fn test_authentication_required_display() {
assert_str_eq!(AuthenticationRequired::Enabled.to_string(), "enabled");
assert_str_eq!(
AuthenticationRequired::DisabledForLocalAddresses.to_string(),
"disabledForLocalAddresses"
);
}
#[test]
fn test_certificate_validation_display() {
assert_str_eq!(CertificateValidation::Enabled.to_string(), "enabled");
assert_str_eq!(
CertificateValidation::DisabledForLocalAddresses.to_string(),
"disabledForLocalAddresses"
);
assert_str_eq!(CertificateValidation::Disabled.to_string(), "disabled");
}
#[test]
fn test_task_name_display() {
assert_str_eq!(
+2 -2
View File
@@ -1,10 +1,10 @@
use strum::IntoEnumIterator;
use crate::models::radarr_models::{
Collection, Credit, Indexer, MinimumAvailability, Monitor, Movie, MovieHistoryItem, Release,
RootFolder,
Collection, Credit, MinimumAvailability, Monitor, Movie, MovieHistoryItem, Release, RootFolder,
};
use crate::models::servarr_data::radarr::radarr_data::RadarrData;
use crate::models::servarr_models::Indexer;
use crate::models::stateful_list::StatefulList;
use crate::models::stateful_table::StatefulTable;
use crate::models::{HorizontallyScrollableText, ScrollableText};
@@ -1,13 +1,12 @@
#[cfg(test)]
mod test {
use crate::models::radarr_models::{
Collection, Indexer, IndexerField, MinimumAvailability, Monitor, Movie, RootFolder,
};
use crate::models::radarr_models::{Collection, MinimumAvailability, Monitor, Movie, RootFolder};
use crate::models::servarr_data::radarr::modals::{
AddMovieModal, EditCollectionModal, EditIndexerModal, EditMovieModal,
};
use crate::models::servarr_data::radarr::radarr_data::radarr_test_utils::utils::create_test_radarr_data;
use crate::models::servarr_data::radarr::radarr_data::RadarrData;
use crate::models::servarr_models::{Indexer, IndexerField};
use crate::models::stateful_table::StatefulTable;
use bimap::BiMap;
use pretty_assertions::{assert_eq, assert_str_eq};
@@ -17,6 +16,8 @@ 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()
@@ -7,12 +7,13 @@ use crate::app::radarr::radarr_context_clues::{
};
use crate::models::radarr_models::{
AddMovieSearchResult, BlocklistItem, Collection, CollectionMovie, DiskSpace, DownloadRecord,
Indexer, IndexerSettings, Movie, QueueEvent, RootFolder, Task,
IndexerSettings, Movie, QueueEvent, RootFolder, Task,
};
use crate::models::servarr_data::radarr::modals::{
AddMovieModal, EditCollectionModal, EditIndexerModal, EditMovieModal, IndexerTestResultModalItem,
MovieDetailsModal,
};
use crate::models::servarr_models::Indexer;
use crate::models::stateful_list::StatefulList;
use crate::models::stateful_table::StatefulTable;
use crate::models::{
@@ -3,7 +3,8 @@ use chrono::{DateTime, Utc};
use strum::EnumIter;
use crate::models::{
sonarr_models::{BlocklistItem, DownloadRecord, Episode, Indexer, Series},
servarr_models::Indexer,
sonarr_models::{BlocklistItem, DownloadRecord, Episode, Series},
stateful_list::StatefulList,
stateful_table::StatefulTable,
stateful_tree::StatefulTree,
+125
View File
@@ -0,0 +1,125 @@
use std::fmt::{Display, Formatter, Result};
use clap::ValueEnum;
use serde::{Deserialize, Serialize};
use serde_json::{Number, Value};
use super::HorizontallyScrollableText;
#[cfg(test)]
#[path = "servarr_models_tests.rs"]
mod servarr_models_tests;
#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone, Copy, Debug, ValueEnum)]
#[serde(rename_all = "camelCase")]
pub enum AuthenticationMethod {
#[default]
Basic,
Forms,
None,
}
impl Display for AuthenticationMethod {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let authentication_method = match self {
AuthenticationMethod::Basic => "basic",
AuthenticationMethod::Forms => "forms",
AuthenticationMethod::None => "none",
};
write!(f, "{authentication_method}")
}
}
#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone, Copy, Debug, ValueEnum)]
#[serde(rename_all = "camelCase")]
pub enum AuthenticationRequired {
Enabled,
#[default]
DisabledForLocalAddresses,
}
impl Display for AuthenticationRequired {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let authentication_required = match self {
AuthenticationRequired::Enabled => "enabled",
AuthenticationRequired::DisabledForLocalAddresses => "disabledForLocalAddresses",
};
write!(f, "{authentication_required}")
}
}
#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone, Copy, Debug, ValueEnum)]
#[serde(rename_all = "camelCase")]
pub enum CertificateValidation {
#[default]
Enabled,
DisabledForLocalAddresses,
Disabled,
}
impl Display for CertificateValidation {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let certificate_validation = match self {
CertificateValidation::Enabled => "enabled",
CertificateValidation::DisabledForLocalAddresses => "disabledForLocalAddresses",
CertificateValidation::Disabled => "disabled",
};
write!(f, "{certificate_validation}")
}
}
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct HostConfig {
pub bind_address: HorizontallyScrollableText,
#[serde(deserialize_with = "super::from_i64")]
pub port: i64,
pub url_base: Option<HorizontallyScrollableText>,
pub instance_name: Option<HorizontallyScrollableText>,
pub application_url: Option<HorizontallyScrollableText>,
pub enable_ssl: bool,
#[serde(deserialize_with = "super::from_i64")]
pub ssl_port: i64,
pub ssl_cert_path: Option<String>,
pub ssl_cert_password: Option<String>,
}
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Indexer {
#[serde(deserialize_with = "super::from_i64")]
pub id: i64,
pub name: Option<String>,
pub implementation: Option<String>,
pub implementation_name: Option<String>,
pub config_contract: Option<String>,
pub supports_rss: bool,
pub supports_search: bool,
pub fields: Option<Vec<IndexerField>>,
pub enable_rss: bool,
pub enable_automatic_search: bool,
pub enable_interactive_search: bool,
pub protocol: String,
#[serde(deserialize_with = "super::from_i64")]
pub priority: i64,
#[serde(deserialize_with = "super::from_i64")]
pub download_client_id: i64,
pub tags: Vec<Number>,
}
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
pub struct IndexerField {
pub name: Option<String>,
pub value: Option<Value>,
}
#[derive(Default, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct SecurityConfig {
pub authentication_method: AuthenticationMethod,
pub authentication_required: AuthenticationRequired,
pub username: String,
pub password: Option<String>,
pub api_key: String,
pub certificate_validation: CertificateValidation,
}
+34
View File
@@ -0,0 +1,34 @@
#[cfg(test)]
mod tests {
use pretty_assertions::assert_str_eq;
use crate::models::servarr_models::{
AuthenticationMethod, AuthenticationRequired, CertificateValidation,
};
#[test]
fn test_authentication_method_display() {
assert_str_eq!(AuthenticationMethod::Basic.to_string(), "basic");
assert_str_eq!(AuthenticationMethod::Forms.to_string(), "forms");
assert_str_eq!(AuthenticationMethod::None.to_string(), "none");
}
#[test]
fn test_authentication_required_display() {
assert_str_eq!(AuthenticationRequired::Enabled.to_string(), "enabled");
assert_str_eq!(
AuthenticationRequired::DisabledForLocalAddresses.to_string(),
"disabledForLocalAddresses"
);
}
#[test]
fn test_certificate_validation_display() {
assert_str_eq!(CertificateValidation::Enabled.to_string(), "enabled");
assert_str_eq!(
CertificateValidation::DisabledForLocalAddresses.to_string(),
"disabledForLocalAddresses"
);
assert_str_eq!(CertificateValidation::Disabled.to_string(), "disabled");
}
}
+8 -30
View File
@@ -9,7 +9,10 @@ use strum::EnumIter;
use crate::serde_enum_from;
use super::{HorizontallyScrollableText, Serdeable};
use super::{
servarr_models::{HostConfig, Indexer, SecurityConfig},
HorizontallyScrollableText, Serdeable,
};
#[cfg(test)]
#[path = "sonarr_models_tests.rs"]
@@ -103,35 +106,6 @@ pub struct EpisodeFile {
pub media_info: Option<MediaInfo>,
}
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Indexer {
#[serde(deserialize_with = "super::from_i64")]
pub id: i64,
pub name: Option<String>,
pub implementation: Option<String>,
pub implementation_name: Option<String>,
pub config_contract: Option<String>,
pub supports_rss: bool,
pub supports_search: bool,
pub fields: Option<Vec<IndexerField>>,
pub enable_rss: bool,
pub enable_automatic_search: bool,
pub enable_interactive_search: bool,
pub protocol: String,
#[serde(deserialize_with = "super::from_i64")]
pub priority: i64,
#[serde(deserialize_with = "super::from_i64")]
pub download_client_id: i64,
pub tags: Vec<Number>,
}
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
pub struct IndexerField {
pub name: Option<String>,
pub value: Option<Value>,
}
#[derive(Serialize, Deserialize, Default, Debug, Hash, Clone, PartialEq, Eq, Ord, PartialOrd)]
pub struct Language {
pub name: String,
@@ -359,8 +333,10 @@ pub enum SonarrSerdeable {
DownloadsResponse(DownloadsResponse),
Episode(Episode),
Episodes(Vec<Episode>),
HostConfig(HostConfig),
Indexers(Vec<Indexer>),
QualityProfiles(Vec<QualityProfile>),
SecurityConfig(SecurityConfig),
SeriesVec(Vec<Series>),
SystemStatus(SystemStatus),
BlocklistResponse(BlocklistResponse),
@@ -385,8 +361,10 @@ serde_enum_from!(
DownloadsResponse(DownloadsResponse),
Episode(Episode),
Episodes(Vec<Episode>),
HostConfig(HostConfig),
Indexers(Vec<Indexer>),
QualityProfiles(Vec<QualityProfile>),
SecurityConfig(SecurityConfig),
SeriesVec(Vec<Series>),
SystemStatus(SystemStatus),
BlocklistResponse(BlocklistResponse),