refactor: Improved error handling project-wide and cleaned up some regexes with unnecessary escapes (tail_logs and interpolate_env_vars)
This commit is contained in:
+10
-6
@@ -200,10 +200,14 @@ impl App<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_current_route(&self) -> Route {
|
pub fn get_current_route(&self) -> Route {
|
||||||
*self
|
*self.navigation_stack.last().unwrap_or(
|
||||||
.navigation_stack
|
&self
|
||||||
.last()
|
.server_tabs
|
||||||
.unwrap_or(&self.server_tabs.tabs.first().unwrap().route)
|
.tabs
|
||||||
|
.first()
|
||||||
|
.expect("At least one server tab must exist")
|
||||||
|
.route,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,8 +478,8 @@ where
|
|||||||
|
|
||||||
fn interpolate_env_vars(s: &str) -> String {
|
fn interpolate_env_vars(s: &str) -> String {
|
||||||
let result = s.to_string();
|
let result = s.to_string();
|
||||||
let scrubbing_regex = Regex::new(r#"[\s\{\}!\$^\(\)\[\]\\\|`'"]+"#).unwrap();
|
let scrubbing_regex = Regex::new(r#"[\s{}!$^()\[\]\\|`'"]+"#).unwrap();
|
||||||
let var_regex = Regex::new(r"\$\{(.*?)\}").unwrap();
|
let var_regex = Regex::new(r"\$\{(.*?)}").unwrap();
|
||||||
|
|
||||||
var_regex
|
var_regex
|
||||||
.replace_all(s, |caps: ®ex::Captures<'_>| {
|
.replace_all(s, |caps: ®ex::Captures<'_>| {
|
||||||
|
|||||||
@@ -56,12 +56,16 @@ macro_rules! handle_table_events {
|
|||||||
_ if $crate::matches_key!(submit, $self.key) => $self.[<handle_ $name _table_submit>](config),
|
_ if $crate::matches_key!(submit, $self.key) => $self.[<handle_ $name _table_submit>](config),
|
||||||
_ if $crate::matches_key!(esc, $self.key) => $self.[<handle_ $name _table_esc>](config),
|
_ if $crate::matches_key!(esc, $self.key) => $self.[<handle_ $name _table_esc>](config),
|
||||||
_ if config.searching_block.is_some()
|
_ if config.searching_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.searching_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("searching_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$self.[<handle_ $name _table_search_box_input>]()
|
$self.[<handle_ $name _table_search_box_input>]()
|
||||||
}
|
}
|
||||||
_ if config.filtering_block.is_some()
|
_ if config.filtering_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.filtering_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("filtering_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$self.[<handle_ $name _table_filter_box_input>]()
|
$self.[<handle_ $name _table_filter_box_input>]()
|
||||||
}
|
}
|
||||||
@@ -87,7 +91,9 @@ macro_rules! handle_table_events {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if config.sorting_block.is_some()
|
_ if config.sorting_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.sorting_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("sorting_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$table.sort.as_mut().unwrap().scroll_up();
|
$table.sort.as_mut().unwrap().scroll_up();
|
||||||
true
|
true
|
||||||
@@ -105,7 +111,9 @@ macro_rules! handle_table_events {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if config.sorting_block.is_some()
|
_ if config.sorting_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.sorting_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("sorting_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$table
|
$table
|
||||||
.sort
|
.sort
|
||||||
@@ -151,7 +159,9 @@ macro_rules! handle_table_events {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if config.sorting_block.is_some()
|
_ if config.sorting_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.sorting_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("sorting_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$table
|
$table
|
||||||
.sort
|
.sort
|
||||||
@@ -161,7 +171,9 @@ macro_rules! handle_table_events {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if config.searching_block.is_some()
|
_ if config.searching_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.searching_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("searching_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$table
|
$table
|
||||||
.search
|
.search
|
||||||
@@ -171,7 +183,9 @@ macro_rules! handle_table_events {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if config.filtering_block.is_some()
|
_ if config.filtering_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.filtering_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("filtering_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$table
|
$table
|
||||||
.filter
|
.filter
|
||||||
@@ -193,7 +207,9 @@ macro_rules! handle_table_events {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if config.sorting_block.is_some()
|
_ if config.sorting_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.sorting_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("sorting_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$table
|
$table
|
||||||
.sort
|
.sort
|
||||||
@@ -203,7 +219,9 @@ macro_rules! handle_table_events {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if config.searching_block.is_some()
|
_ if config.searching_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.searching_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("searching_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$table
|
$table
|
||||||
.search
|
.search
|
||||||
@@ -213,7 +231,9 @@ macro_rules! handle_table_events {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if config.filtering_block.is_some()
|
_ if config.filtering_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.filtering_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("filtering_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$table
|
$table
|
||||||
.filter
|
.filter
|
||||||
@@ -229,7 +249,9 @@ macro_rules! handle_table_events {
|
|||||||
fn [<handle_ $name _table_left_right>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
fn [<handle_ $name _table_left_right>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||||
match $self.app.get_current_route() {
|
match $self.app.get_current_route() {
|
||||||
_ if config.searching_block.is_some()
|
_ if config.searching_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.searching_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("searching_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$crate::handle_text_box_left_right_keys!(
|
$crate::handle_text_box_left_right_keys!(
|
||||||
$self,
|
$self,
|
||||||
@@ -239,7 +261,9 @@ macro_rules! handle_table_events {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if config.filtering_block.is_some()
|
_ if config.filtering_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.filtering_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("filtering_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$crate::handle_text_box_left_right_keys!(
|
$crate::handle_text_box_left_right_keys!(
|
||||||
$self,
|
$self,
|
||||||
@@ -255,7 +279,9 @@ macro_rules! handle_table_events {
|
|||||||
fn [<handle _$name _table_submit>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
fn [<handle _$name _table_submit>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||||
match $self.app.get_current_route() {
|
match $self.app.get_current_route() {
|
||||||
_ if config.sorting_block.is_some()
|
_ if config.sorting_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.sorting_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("sorting_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
if let Some(sort_by_fn) = config.sort_by_fn {
|
if let Some(sort_by_fn) = config.sort_by_fn {
|
||||||
$table.items.sort_by(sort_by_fn);
|
$table.items.sort_by(sort_by_fn);
|
||||||
@@ -267,7 +293,9 @@ macro_rules! handle_table_events {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if config.searching_block.is_some()
|
_ if config.searching_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.searching_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("searching_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$self.app.pop_navigation_stack();
|
$self.app.pop_navigation_stack();
|
||||||
$self.app.ignore_special_keys_for_textbox_input = false;
|
$self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
@@ -290,7 +318,9 @@ macro_rules! handle_table_events {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if config.filtering_block.is_some()
|
_ if config.filtering_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.filtering_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("filtering_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$self.app.pop_navigation_stack();
|
$self.app.pop_navigation_stack();
|
||||||
$self.app.ignore_special_keys_for_textbox_input = false;
|
$self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
@@ -319,15 +349,21 @@ macro_rules! handle_table_events {
|
|||||||
fn [<handle_ $name _table_esc>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
fn [<handle_ $name _table_esc>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||||
match $self.app.get_current_route() {
|
match $self.app.get_current_route() {
|
||||||
_ if config.sorting_block.is_some()
|
_ if config.sorting_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.sorting_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("sorting_block must be configured for this table") =>
|
||||||
{
|
{
|
||||||
$self.app.pop_navigation_stack();
|
$self.app.pop_navigation_stack();
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if (config.searching_block.is_some()
|
_ if (config.searching_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap())
|
&& $self.app.get_current_route() == *config.searching_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("searching_block must be configured for this table"))
|
||||||
|| (config.search_error_block.is_some()
|
|| (config.search_error_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.search_error_block.as_ref().unwrap()) =>
|
&& $self.app.get_current_route() == *config.search_error_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("search_error_block must be configured for this table")) =>
|
||||||
{
|
{
|
||||||
$self.app.pop_navigation_stack();
|
$self.app.pop_navigation_stack();
|
||||||
$table.reset_search();
|
$table.reset_search();
|
||||||
@@ -335,9 +371,13 @@ macro_rules! handle_table_events {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if (config.filtering_block.is_some()
|
_ if (config.filtering_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap())
|
&& $self.app.get_current_route() == *config.filtering_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("filtering_block must be configured for this table"))
|
||||||
|| (config.filter_error_block.is_some()
|
|| (config.filter_error_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.filter_error_block.as_ref().unwrap()) =>
|
&& $self.app.get_current_route() == *config.filter_error_block
|
||||||
|
.as_ref()
|
||||||
|
.expect("filter_error_block must be configured for this table")) =>
|
||||||
{
|
{
|
||||||
$self.app.pop_navigation_stack();
|
$self.app.pop_navigation_stack();
|
||||||
$table.reset_filter();
|
$table.reset_filter();
|
||||||
|
|||||||
@@ -41,47 +41,53 @@ impl From<&RadarrData<'_>> for EditIndexerModal {
|
|||||||
} = radarr_data.indexers.current_selection();
|
} = radarr_data.indexers.current_selection();
|
||||||
let seed_ratio_field_option = fields
|
let seed_ratio_field_option = fields
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("indexer fields must exist")
|
||||||
.iter()
|
.iter()
|
||||||
.find(|field| field.name.as_ref().unwrap() == "seedCriteria.seedRatio");
|
.find(|field| {
|
||||||
|
field.name.as_ref().expect("indexer field name must exist") == "seedCriteria.seedRatio"
|
||||||
|
});
|
||||||
let seed_ratio_value_option = if let Some(seed_ratio_field) = seed_ratio_field_option {
|
let seed_ratio_value_option = if let Some(seed_ratio_field) = seed_ratio_field_option {
|
||||||
seed_ratio_field.value.clone()
|
seed_ratio_field.value.clone()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
edit_indexer_modal.name = name.clone().unwrap().into();
|
edit_indexer_modal.name = name.clone().expect("indexer name must exist").into();
|
||||||
edit_indexer_modal.enable_rss = Some(*enable_rss);
|
edit_indexer_modal.enable_rss = Some(*enable_rss);
|
||||||
edit_indexer_modal.enable_automatic_search = Some(*enable_automatic_search);
|
edit_indexer_modal.enable_automatic_search = Some(*enable_automatic_search);
|
||||||
edit_indexer_modal.enable_interactive_search = Some(*enable_interactive_search);
|
edit_indexer_modal.enable_interactive_search = Some(*enable_interactive_search);
|
||||||
edit_indexer_modal.priority = *priority;
|
edit_indexer_modal.priority = *priority;
|
||||||
edit_indexer_modal.url = fields
|
edit_indexer_modal.url = fields
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("indexer fields must exist")
|
||||||
.iter()
|
.iter()
|
||||||
.find(|field| field.name.as_ref().unwrap() == "baseUrl")
|
.find(|field| field.name.as_ref().expect("indexer field name must exist") == "baseUrl")
|
||||||
.unwrap()
|
.expect("baseUrl field must exist")
|
||||||
.value
|
.value
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap()
|
.expect("baseUrl field value must exist")
|
||||||
.as_str()
|
.as_str()
|
||||||
.unwrap()
|
.expect("baseUrl field value must be a string")
|
||||||
.into();
|
.into();
|
||||||
edit_indexer_modal.api_key = fields
|
edit_indexer_modal.api_key = fields
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("indexer fields must exist")
|
||||||
.iter()
|
.iter()
|
||||||
.find(|field| field.name.as_ref().unwrap() == "apiKey")
|
.find(|field| field.name.as_ref().expect("indexer field name must exist") == "apiKey")
|
||||||
.unwrap()
|
.expect("apiKey field must exist")
|
||||||
.value
|
.value
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap()
|
.expect("apiKey field value must exist")
|
||||||
.as_str()
|
.as_str()
|
||||||
.unwrap()
|
.expect("apiKey field value must be a string")
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
if let Some(seed_ratio_value) = seed_ratio_value_option {
|
if let Some(seed_ratio_value) = seed_ratio_value_option {
|
||||||
edit_indexer_modal.seed_ratio = seed_ratio_value.as_f64().unwrap().to_string().into();
|
edit_indexer_modal.seed_ratio = seed_ratio_value
|
||||||
|
.as_f64()
|
||||||
|
.expect("Seed ratio value must be a valid f64")
|
||||||
|
.to_string()
|
||||||
|
.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
edit_indexer_modal.tags = tags
|
edit_indexer_modal.tags = tags
|
||||||
@@ -89,8 +95,8 @@ impl From<&RadarrData<'_>> for EditIndexerModal {
|
|||||||
.map(|tag_id| {
|
.map(|tag_id| {
|
||||||
radarr_data
|
radarr_data
|
||||||
.tags_map
|
.tags_map
|
||||||
.get_by_left(&tag_id.as_i64().unwrap())
|
.get_by_left(&tag_id.as_i64().expect("Tag ID must be a valid i64"))
|
||||||
.unwrap()
|
.expect("Tag ID must exist in tags map")
|
||||||
.clone()
|
.clone()
|
||||||
})
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
@@ -131,8 +137,8 @@ impl From<&RadarrData<'_>> for EditMovieModal {
|
|||||||
.map(|tag_id| {
|
.map(|tag_id| {
|
||||||
radarr_data
|
radarr_data
|
||||||
.tags_map
|
.tags_map
|
||||||
.get_by_left(&tag_id.as_i64().unwrap())
|
.get_by_left(&tag_id.as_i64().expect("Tag ID must be a valid i64"))
|
||||||
.unwrap()
|
.expect("Tag ID must exist in tags map")
|
||||||
.clone()
|
.clone()
|
||||||
})
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
|
|||||||
@@ -86,47 +86,53 @@ impl From<&SonarrData<'_>> for EditIndexerModal {
|
|||||||
} = sonarr_data.indexers.current_selection();
|
} = sonarr_data.indexers.current_selection();
|
||||||
let seed_ratio_field_option = fields
|
let seed_ratio_field_option = fields
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("indexer fields must exist")
|
||||||
.iter()
|
.iter()
|
||||||
.find(|field| field.name.as_ref().unwrap() == "seedCriteria.seedRatio");
|
.find(|field| {
|
||||||
|
field.name.as_ref().expect("indexer field name must exist") == "seedCriteria.seedRatio"
|
||||||
|
});
|
||||||
let seed_ratio_value_option = if let Some(seed_ratio_field) = seed_ratio_field_option {
|
let seed_ratio_value_option = if let Some(seed_ratio_field) = seed_ratio_field_option {
|
||||||
seed_ratio_field.value.clone()
|
seed_ratio_field.value.clone()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
edit_indexer_modal.name = name.clone().unwrap().into();
|
edit_indexer_modal.name = name.clone().expect("indexer name must exist").into();
|
||||||
edit_indexer_modal.enable_rss = Some(*enable_rss);
|
edit_indexer_modal.enable_rss = Some(*enable_rss);
|
||||||
edit_indexer_modal.enable_automatic_search = Some(*enable_automatic_search);
|
edit_indexer_modal.enable_automatic_search = Some(*enable_automatic_search);
|
||||||
edit_indexer_modal.enable_interactive_search = Some(*enable_interactive_search);
|
edit_indexer_modal.enable_interactive_search = Some(*enable_interactive_search);
|
||||||
edit_indexer_modal.priority = *priority;
|
edit_indexer_modal.priority = *priority;
|
||||||
edit_indexer_modal.url = fields
|
edit_indexer_modal.url = fields
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("indexer fields must exist")
|
||||||
.iter()
|
.iter()
|
||||||
.find(|field| field.name.as_ref().unwrap() == "baseUrl")
|
.find(|field| field.name.as_ref().expect("indexer field name must exist") == "baseUrl")
|
||||||
.unwrap()
|
.expect("baseUrl field must exist")
|
||||||
.value
|
.value
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap()
|
.expect("baseUrl field value must exist")
|
||||||
.as_str()
|
.as_str()
|
||||||
.unwrap()
|
.expect("baseUrl field value must be a string")
|
||||||
.into();
|
.into();
|
||||||
edit_indexer_modal.api_key = fields
|
edit_indexer_modal.api_key = fields
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("indexer fields must exist")
|
||||||
.iter()
|
.iter()
|
||||||
.find(|field| field.name.as_ref().unwrap() == "apiKey")
|
.find(|field| field.name.as_ref().expect("indexer field name must exist") == "apiKey")
|
||||||
.unwrap()
|
.expect("apiKey field must exist")
|
||||||
.value
|
.value
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap()
|
.expect("apiKey field value must exist")
|
||||||
.as_str()
|
.as_str()
|
||||||
.unwrap()
|
.expect("apiKey field value must be a string")
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
if let Some(seed_ratio_value) = seed_ratio_value_option {
|
if let Some(seed_ratio_value) = seed_ratio_value_option {
|
||||||
edit_indexer_modal.seed_ratio = seed_ratio_value.as_f64().unwrap().to_string().into();
|
edit_indexer_modal.seed_ratio = seed_ratio_value
|
||||||
|
.as_f64()
|
||||||
|
.expect("Seed ratio value must be a valid f64")
|
||||||
|
.to_string()
|
||||||
|
.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
edit_indexer_modal.tags = tags
|
edit_indexer_modal.tags = tags
|
||||||
@@ -134,8 +140,8 @@ impl From<&SonarrData<'_>> for EditIndexerModal {
|
|||||||
.map(|tag_id| {
|
.map(|tag_id| {
|
||||||
sonarr_data
|
sonarr_data
|
||||||
.tags_map
|
.tags_map
|
||||||
.get_by_left(&tag_id.as_i64().unwrap())
|
.get_by_left(&tag_id.as_i64().expect("Tag ID must be a valid i64"))
|
||||||
.unwrap()
|
.expect("Tag ID must exist in tags map")
|
||||||
.clone()
|
.clone()
|
||||||
})
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
@@ -180,8 +186,8 @@ impl From<&SonarrData<'_>> for EditSeriesModal {
|
|||||||
.map(|tag_id| {
|
.map(|tag_id| {
|
||||||
sonarr_data
|
sonarr_data
|
||||||
.tags_map
|
.tags_map
|
||||||
.get_by_left(&tag_id.as_i64().unwrap())
|
.get_by_left(&tag_id.as_i64().expect("Tag ID must be a valid i64"))
|
||||||
.unwrap()
|
.expect("Tag ID must exist in tags map")
|
||||||
.clone()
|
.clone()
|
||||||
})
|
})
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
|
|||||||
@@ -55,15 +55,32 @@ where
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.filtered_state.as_ref().unwrap().selected() {
|
match self
|
||||||
|
.filtered_state
|
||||||
|
.as_ref()
|
||||||
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
|
.selected()
|
||||||
|
{
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
if i >= filtered_items.len() - 1 {
|
if i >= filtered_items.len() - 1 {
|
||||||
self.filtered_state.as_mut().unwrap().select_first();
|
self
|
||||||
|
.filtered_state
|
||||||
|
.as_mut()
|
||||||
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
|
.select_first();
|
||||||
} else {
|
} else {
|
||||||
self.filtered_state.as_mut().unwrap().select_next();
|
self
|
||||||
|
.filtered_state
|
||||||
|
.as_mut()
|
||||||
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
|
.select_next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => self.filtered_state.as_mut().unwrap().select_first(),
|
None => self
|
||||||
|
.filtered_state
|
||||||
|
.as_mut()
|
||||||
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
|
.select_first(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -91,19 +108,32 @@ where
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.filtered_state.as_ref().unwrap().selected() {
|
match self
|
||||||
|
.filtered_state
|
||||||
|
.as_ref()
|
||||||
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
|
.selected()
|
||||||
|
{
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
self
|
self
|
||||||
.filtered_state
|
.filtered_state
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
.select(Some(filtered_items.len() - 1));
|
.select(Some(filtered_items.len() - 1));
|
||||||
} else {
|
} else {
|
||||||
self.filtered_state.as_mut().unwrap().select_previous();
|
self
|
||||||
|
.filtered_state
|
||||||
|
.as_mut()
|
||||||
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
|
.select_previous();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => self.filtered_state.as_mut().unwrap().select_first(),
|
None => self
|
||||||
|
.filtered_state
|
||||||
|
.as_mut()
|
||||||
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
|
.select_first(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -131,7 +161,11 @@ where
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.filtered_state.as_mut().unwrap().select_first();
|
self
|
||||||
|
.filtered_state
|
||||||
|
.as_mut()
|
||||||
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
|
.select_first();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +185,7 @@ where
|
|||||||
self
|
self
|
||||||
.filtered_state
|
.filtered_state
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
.select(Some(filtered_items.len() - 1));
|
.select(Some(filtered_items.len() - 1));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -174,15 +208,24 @@ where
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.filtered_state.as_ref().unwrap().selected() {
|
match self
|
||||||
|
.filtered_state
|
||||||
|
.as_ref()
|
||||||
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
|
.selected()
|
||||||
|
{
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
self
|
self
|
||||||
.filtered_state
|
.filtered_state
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
.select(Some(i.saturating_add(20) % (filtered_items.len() - 1)));
|
.select(Some(i.saturating_add(20) % (filtered_items.len() - 1)));
|
||||||
}
|
}
|
||||||
None => self.filtered_state.as_mut().unwrap().select_first(),
|
None => self
|
||||||
|
.filtered_state
|
||||||
|
.as_mut()
|
||||||
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
|
.select_first(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -208,16 +251,25 @@ where
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.filtered_state.as_ref().unwrap().selected() {
|
match self
|
||||||
|
.filtered_state
|
||||||
|
.as_ref()
|
||||||
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
|
.selected()
|
||||||
|
{
|
||||||
Some(i) => {
|
Some(i) => {
|
||||||
let len = filtered_items.len() - 1;
|
let len = filtered_items.len() - 1;
|
||||||
self
|
self
|
||||||
.filtered_state
|
.filtered_state
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
.select(Some((i + len - (20 % len)) % len));
|
.select(Some((i + len - (20 % len)) % len));
|
||||||
}
|
}
|
||||||
None => self.filtered_state.as_mut().unwrap().select_last(),
|
None => self
|
||||||
|
.filtered_state
|
||||||
|
.as_mut()
|
||||||
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
|
.select_last(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -278,7 +330,7 @@ where
|
|||||||
&filtered_items[self
|
&filtered_items[self
|
||||||
.filtered_state
|
.filtered_state
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("filtered_state must exist when filtered_items exists")
|
||||||
.selected()
|
.selected()
|
||||||
.unwrap_or(0)]
|
.unwrap_or(0)]
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::models::servarr_models::{EditIndexerParams, Indexer, IndexerTestResul
|
|||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::network::{Network, RequestMethod};
|
use crate::network::{Network, RequestMethod};
|
||||||
use anyhow::Result;
|
use anyhow::{Context, Result};
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
|
|
||||||
@@ -103,57 +103,57 @@ impl Network<'_, '_> {
|
|||||||
) = {
|
) = {
|
||||||
let priority = detailed_indexer_body["priority"]
|
let priority = detailed_indexer_body["priority"]
|
||||||
.as_i64()
|
.as_i64()
|
||||||
.expect("Unable to deserialize 'priority'");
|
.context("Failed to deserialize indexer 'priority' field")?;
|
||||||
let seed_ratio_field_option = detailed_indexer_body["fields"]
|
let seed_ratio_field_option = detailed_indexer_body["fields"]
|
||||||
.as_array()
|
.as_array()
|
||||||
.unwrap()
|
.context("Failed to get indexer 'fields' array")?
|
||||||
.iter()
|
.iter()
|
||||||
.find(|field| field["name"] == "seedCriteria.seedRatio");
|
.find(|field| field["name"] == "seedCriteria.seedRatio");
|
||||||
let name = edit_indexer_params.name.unwrap_or(
|
let name = edit_indexer_params.name.unwrap_or(
|
||||||
detailed_indexer_body["name"]
|
detailed_indexer_body["name"]
|
||||||
.as_str()
|
.as_str()
|
||||||
.expect("Unable to deserialize 'name'")
|
.context("Failed to deserialize indexer 'name' field")?
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
);
|
);
|
||||||
let enable_rss = edit_indexer_params.enable_rss.unwrap_or(
|
let enable_rss = edit_indexer_params.enable_rss.unwrap_or(
|
||||||
detailed_indexer_body["enableRss"]
|
detailed_indexer_body["enableRss"]
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.expect("Unable to deserialize 'enableRss'"),
|
.context("Failed to deserialize indexer 'enableRss' field")?,
|
||||||
);
|
);
|
||||||
let enable_automatic_search = edit_indexer_params.enable_automatic_search.unwrap_or(
|
let enable_automatic_search = edit_indexer_params.enable_automatic_search.unwrap_or(
|
||||||
detailed_indexer_body["enableAutomaticSearch"]
|
detailed_indexer_body["enableAutomaticSearch"]
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.expect("Unable to deserialize 'enableAutomaticSearch"),
|
.context("Failed to deserialize indexer 'enableAutomaticSearch' field")?,
|
||||||
);
|
);
|
||||||
let enable_interactive_search = edit_indexer_params.enable_interactive_search.unwrap_or(
|
let enable_interactive_search = edit_indexer_params.enable_interactive_search.unwrap_or(
|
||||||
detailed_indexer_body["enableInteractiveSearch"]
|
detailed_indexer_body["enableInteractiveSearch"]
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.expect("Unable to deserialize 'enableInteractiveSearch'"),
|
.context("Failed to deserialize indexer 'enableInteractiveSearch' field")?,
|
||||||
);
|
);
|
||||||
let url = edit_indexer_params.url.unwrap_or(
|
let url = edit_indexer_params.url.unwrap_or(
|
||||||
detailed_indexer_body["fields"]
|
detailed_indexer_body["fields"]
|
||||||
.as_array()
|
.as_array()
|
||||||
.expect("Unable to deserialize 'fields'")
|
.context("Failed to get indexer 'fields' array for baseUrl")?
|
||||||
.iter()
|
.iter()
|
||||||
.find(|field| field["name"] == "baseUrl")
|
.find(|field| field["name"] == "baseUrl")
|
||||||
.expect("Field 'baseUrl' was not found in the 'fields' array")
|
.context("Field 'baseUrl' was not found in the indexer fields array")?
|
||||||
.get("value")
|
.get("value")
|
||||||
.unwrap_or(&json!(""))
|
.unwrap_or(&json!(""))
|
||||||
.as_str()
|
.as_str()
|
||||||
.expect("Unable to deserialize 'baseUrl value'")
|
.context("Failed to deserialize indexer 'baseUrl' value")?
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
);
|
);
|
||||||
let api_key = edit_indexer_params.api_key.unwrap_or(
|
let api_key = edit_indexer_params.api_key.unwrap_or(
|
||||||
detailed_indexer_body["fields"]
|
detailed_indexer_body["fields"]
|
||||||
.as_array()
|
.as_array()
|
||||||
.expect("Unable to deserialize 'fields'")
|
.context("Failed to get indexer 'fields' array for apiKey")?
|
||||||
.iter()
|
.iter()
|
||||||
.find(|field| field["name"] == "apiKey")
|
.find(|field| field["name"] == "apiKey")
|
||||||
.expect("Field 'apiKey' was not found in the 'fields' array")
|
.context("Field 'apiKey' was not found in the indexer fields array")?
|
||||||
.get("value")
|
.get("value")
|
||||||
.unwrap_or(&json!(""))
|
.unwrap_or(&json!(""))
|
||||||
.as_str()
|
.as_str()
|
||||||
.expect("Unable to deserialize 'apiKey value'")
|
.context("Failed to deserialize indexer 'apiKey' value")?
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
);
|
);
|
||||||
let seed_ratio = edit_indexer_params.seed_ratio.unwrap_or_else(|| {
|
let seed_ratio = edit_indexer_params.seed_ratio.unwrap_or_else(|| {
|
||||||
@@ -162,7 +162,7 @@ impl Network<'_, '_> {
|
|||||||
.get("value")
|
.get("value")
|
||||||
.unwrap_or(&json!(""))
|
.unwrap_or(&json!(""))
|
||||||
.as_str()
|
.as_str()
|
||||||
.expect("Unable to deserialize 'seedCriteria.seedRatio value'")
|
.unwrap_or("")
|
||||||
.to_owned();
|
.to_owned();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,10 +174,14 @@ impl Network<'_, '_> {
|
|||||||
edit_indexer_params.tags.unwrap_or(
|
edit_indexer_params.tags.unwrap_or(
|
||||||
detailed_indexer_body["tags"]
|
detailed_indexer_body["tags"]
|
||||||
.as_array()
|
.as_array()
|
||||||
.expect("Unable to deserialize 'tags'")
|
.context("Failed to get indexer 'tags' array")?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|item| item.as_i64().expect("Unable to deserialize tag ID"))
|
.map(|item| {
|
||||||
.collect(),
|
item
|
||||||
|
.as_i64()
|
||||||
|
.context("Failed to deserialize indexer tag ID")
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>>>()?,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let priority = edit_indexer_params.priority.unwrap_or(priority);
|
let priority = edit_indexer_params.priority.unwrap_or(priority);
|
||||||
@@ -195,47 +199,54 @@ impl Network<'_, '_> {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
*detailed_indexer_body.get_mut("name").unwrap() = json!(name);
|
*detailed_indexer_body
|
||||||
*detailed_indexer_body.get_mut("priority").unwrap() = json!(priority);
|
.get_mut("name")
|
||||||
*detailed_indexer_body.get_mut("enableRss").unwrap() = json!(enable_rss);
|
.context("Failed to get mutable reference to indexer 'name' field")? = json!(name);
|
||||||
|
*detailed_indexer_body
|
||||||
|
.get_mut("priority")
|
||||||
|
.context("Failed to get mutable reference to indexer 'priority' field")? = json!(priority);
|
||||||
|
*detailed_indexer_body
|
||||||
|
.get_mut("enableRss")
|
||||||
|
.context("Failed to get mutable reference to indexer 'enableRss' field")? = json!(enable_rss);
|
||||||
*detailed_indexer_body
|
*detailed_indexer_body
|
||||||
.get_mut("enableAutomaticSearch")
|
.get_mut("enableAutomaticSearch")
|
||||||
.unwrap() = json!(enable_automatic_search);
|
.context("Failed to get mutable reference to indexer 'enableAutomaticSearch' field")? =
|
||||||
|
json!(enable_automatic_search);
|
||||||
*detailed_indexer_body
|
*detailed_indexer_body
|
||||||
.get_mut("enableInteractiveSearch")
|
.get_mut("enableInteractiveSearch")
|
||||||
.unwrap() = json!(enable_interactive_search);
|
.context("Failed to get mutable reference to indexer 'enableInteractiveSearch' field")? =
|
||||||
|
json!(enable_interactive_search);
|
||||||
*detailed_indexer_body
|
*detailed_indexer_body
|
||||||
.get_mut("fields")
|
.get_mut("fields")
|
||||||
.unwrap()
|
.and_then(|f| f.as_array_mut())
|
||||||
.as_array_mut()
|
.context("Failed to get mutable reference to indexer 'fields' array")?
|
||||||
.unwrap()
|
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|field| field["name"] == "baseUrl")
|
.find(|field| field["name"] == "baseUrl")
|
||||||
.unwrap()
|
.context("Failed to find 'baseUrl' field in indexer fields array")?
|
||||||
.get_mut("value")
|
.get_mut("value")
|
||||||
.unwrap() = json!(url);
|
.context("Failed to get mutable reference to 'baseUrl' value")? = json!(url);
|
||||||
*detailed_indexer_body
|
*detailed_indexer_body
|
||||||
.get_mut("fields")
|
.get_mut("fields")
|
||||||
.unwrap()
|
.and_then(|f| f.as_array_mut())
|
||||||
.as_array_mut()
|
.context("Failed to get mutable reference to indexer 'fields' array for apiKey")?
|
||||||
.unwrap()
|
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|field| field["name"] == "apiKey")
|
.find(|field| field["name"] == "apiKey")
|
||||||
.unwrap()
|
.context("Failed to find 'apiKey' field in indexer fields array")?
|
||||||
.get_mut("value")
|
.get_mut("value")
|
||||||
.unwrap() = json!(api_key);
|
.context("Failed to get mutable reference to 'apiKey' value")? = json!(api_key);
|
||||||
*detailed_indexer_body.get_mut("tags").unwrap() = json!(tags);
|
*detailed_indexer_body
|
||||||
|
.get_mut("tags")
|
||||||
|
.context("Failed to get mutable reference to indexer 'tags' field")? = json!(tags);
|
||||||
let seed_ratio_field_option = detailed_indexer_body
|
let seed_ratio_field_option = detailed_indexer_body
|
||||||
.get_mut("fields")
|
.get_mut("fields")
|
||||||
.unwrap()
|
.and_then(|f| f.as_array_mut())
|
||||||
.as_array_mut()
|
.context("Failed to get mutable reference to indexer 'fields' array for seed ratio")?
|
||||||
.unwrap()
|
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|field| field["name"] == "seedCriteria.seedRatio");
|
.find(|field| field["name"] == "seedCriteria.seedRatio");
|
||||||
if let Some(seed_ratio_field) = seed_ratio_field_option {
|
if let Some(seed_ratio_field) = seed_ratio_field_option {
|
||||||
seed_ratio_field
|
seed_ratio_field
|
||||||
.as_object_mut()
|
.as_object_mut()
|
||||||
.unwrap()
|
.context("Failed to get mutable reference to 'seedCriteria.seedRatio' object")?
|
||||||
.insert("value".to_string(), json!(seed_ratio));
|
.insert("value".to_string(), json!(seed_ratio));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,12 +343,13 @@ impl Network<'_, '_> {
|
|||||||
self
|
self
|
||||||
.handle_request::<Value, Value>(request_props, |test_results, mut app| {
|
.handle_request::<Value, Value>(request_props, |test_results, mut app| {
|
||||||
if test_results.as_object().is_none() {
|
if test_results.as_object().is_none() {
|
||||||
app.data.radarr_data.indexer_test_errors = Some(
|
let error_message = test_results
|
||||||
test_results.as_array().unwrap()[0]
|
.as_array()
|
||||||
.get("errorMessage")
|
.and_then(|arr| arr.first())
|
||||||
.unwrap()
|
.and_then(|item| item.get("errorMessage"))
|
||||||
.to_string(),
|
.map(|msg| msg.to_string())
|
||||||
);
|
.unwrap_or_else(|| "Unknown indexer test error".to_string());
|
||||||
|
app.data.radarr_data.indexer_test_errors = Some(error_message);
|
||||||
} else {
|
} else {
|
||||||
app.data.radarr_data.indexer_test_errors = Some(String::new());
|
app.data.radarr_data.indexer_test_errors = Some(String::new());
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -72,17 +72,29 @@ impl Network<'_, '_> {
|
|||||||
"{}|{}|{}|{}|{}",
|
"{}|{}|{}|{}|{}",
|
||||||
log.time,
|
log.time,
|
||||||
log.level.to_uppercase(),
|
log.level.to_uppercase(),
|
||||||
log.logger.as_ref().unwrap(),
|
log
|
||||||
log.exception_type.as_ref().unwrap(),
|
.logger
|
||||||
log.exception.as_ref().unwrap()
|
.as_ref()
|
||||||
|
.expect("logger must exist when exception is present"),
|
||||||
|
log
|
||||||
|
.exception_type
|
||||||
|
.as_ref()
|
||||||
|
.expect("exception_type must exist when exception is present"),
|
||||||
|
log
|
||||||
|
.exception
|
||||||
|
.as_ref()
|
||||||
|
.expect("exception must exist in this branch")
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
HorizontallyScrollableText::from(format!(
|
HorizontallyScrollableText::from(format!(
|
||||||
"{}|{}|{}|{}",
|
"{}|{}|{}|{}",
|
||||||
log.time,
|
log.time,
|
||||||
log.level.to_uppercase(),
|
log.level.to_uppercase(),
|
||||||
log.logger.as_ref().unwrap(),
|
log.logger.as_ref().expect("logger must exist in log entry"),
|
||||||
log.message.as_ref().unwrap()
|
log
|
||||||
|
.message
|
||||||
|
.as_ref()
|
||||||
|
.expect("message must exist when exception is not present")
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::models::sonarr_models::IndexerSettings;
|
|||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
use crate::network::{Network, RequestMethod};
|
use crate::network::{Network, RequestMethod};
|
||||||
use anyhow::Result;
|
use anyhow::{Context, Result};
|
||||||
use log::{debug, info};
|
use log::{debug, info};
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
|
|
||||||
@@ -101,57 +101,57 @@ impl Network<'_, '_> {
|
|||||||
) = {
|
) = {
|
||||||
let priority = detailed_indexer_body["priority"]
|
let priority = detailed_indexer_body["priority"]
|
||||||
.as_i64()
|
.as_i64()
|
||||||
.expect("Unable to deserialize 'priority'");
|
.context("Failed to deserialize indexer 'priority' field")?;
|
||||||
let seed_ratio_field_option = detailed_indexer_body["fields"]
|
let seed_ratio_field_option = detailed_indexer_body["fields"]
|
||||||
.as_array()
|
.as_array()
|
||||||
.unwrap()
|
.context("Failed to get indexer 'fields' array")?
|
||||||
.iter()
|
.iter()
|
||||||
.find(|field| field["name"] == "seedCriteria.seedRatio");
|
.find(|field| field["name"] == "seedCriteria.seedRatio");
|
||||||
let name = edit_indexer_params.name.unwrap_or(
|
let name = edit_indexer_params.name.unwrap_or(
|
||||||
detailed_indexer_body["name"]
|
detailed_indexer_body["name"]
|
||||||
.as_str()
|
.as_str()
|
||||||
.expect("Unable to deserialize 'name'")
|
.context("Failed to deserialize indexer 'name' field")?
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
);
|
);
|
||||||
let enable_rss = edit_indexer_params.enable_rss.unwrap_or(
|
let enable_rss = edit_indexer_params.enable_rss.unwrap_or(
|
||||||
detailed_indexer_body["enableRss"]
|
detailed_indexer_body["enableRss"]
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.expect("Unable to deserialize 'enableRss'"),
|
.context("Failed to deserialize indexer 'enableRss' field")?,
|
||||||
);
|
);
|
||||||
let enable_automatic_search = edit_indexer_params.enable_automatic_search.unwrap_or(
|
let enable_automatic_search = edit_indexer_params.enable_automatic_search.unwrap_or(
|
||||||
detailed_indexer_body["enableAutomaticSearch"]
|
detailed_indexer_body["enableAutomaticSearch"]
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.expect("Unable to deserialize 'enableAutomaticSearch"),
|
.context("Failed to deserialize indexer 'enableAutomaticSearch' field")?,
|
||||||
);
|
);
|
||||||
let enable_interactive_search = edit_indexer_params.enable_interactive_search.unwrap_or(
|
let enable_interactive_search = edit_indexer_params.enable_interactive_search.unwrap_or(
|
||||||
detailed_indexer_body["enableInteractiveSearch"]
|
detailed_indexer_body["enableInteractiveSearch"]
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.expect("Unable to deserialize 'enableInteractiveSearch'"),
|
.context("Failed to deserialize indexer 'enableInteractiveSearch' field")?,
|
||||||
);
|
);
|
||||||
let url = edit_indexer_params.url.unwrap_or(
|
let url = edit_indexer_params.url.unwrap_or(
|
||||||
detailed_indexer_body["fields"]
|
detailed_indexer_body["fields"]
|
||||||
.as_array()
|
.as_array()
|
||||||
.expect("Unable to deserialize 'fields'")
|
.context("Failed to get indexer 'fields' array for baseUrl")?
|
||||||
.iter()
|
.iter()
|
||||||
.find(|field| field["name"] == "baseUrl")
|
.find(|field| field["name"] == "baseUrl")
|
||||||
.expect("Field 'baseUrl' was not found in the 'fields' array")
|
.context("Field 'baseUrl' was not found in the indexer fields array")?
|
||||||
.get("value")
|
.get("value")
|
||||||
.unwrap_or(&json!(""))
|
.unwrap_or(&json!(""))
|
||||||
.as_str()
|
.as_str()
|
||||||
.expect("Unable to deserialize 'baseUrl value'")
|
.context("Failed to deserialize indexer 'baseUrl' value")?
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
);
|
);
|
||||||
let api_key = edit_indexer_params.api_key.unwrap_or(
|
let api_key = edit_indexer_params.api_key.unwrap_or(
|
||||||
detailed_indexer_body["fields"]
|
detailed_indexer_body["fields"]
|
||||||
.as_array()
|
.as_array()
|
||||||
.expect("Unable to deserialize 'fields'")
|
.context("Failed to get indexer 'fields' array for apiKey")?
|
||||||
.iter()
|
.iter()
|
||||||
.find(|field| field["name"] == "apiKey")
|
.find(|field| field["name"] == "apiKey")
|
||||||
.expect("Field 'apiKey' was not found in the 'fields' array")
|
.context("Field 'apiKey' was not found in the indexer fields array")?
|
||||||
.get("value")
|
.get("value")
|
||||||
.unwrap_or(&json!(""))
|
.unwrap_or(&json!(""))
|
||||||
.as_str()
|
.as_str()
|
||||||
.expect("Unable to deserialize 'apiKey value'")
|
.context("Failed to deserialize indexer 'apiKey' value")?
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
);
|
);
|
||||||
let seed_ratio = edit_indexer_params.seed_ratio.unwrap_or_else(|| {
|
let seed_ratio = edit_indexer_params.seed_ratio.unwrap_or_else(|| {
|
||||||
@@ -160,7 +160,7 @@ impl Network<'_, '_> {
|
|||||||
.get("value")
|
.get("value")
|
||||||
.unwrap_or(&json!(""))
|
.unwrap_or(&json!(""))
|
||||||
.as_str()
|
.as_str()
|
||||||
.expect("Unable to deserialize 'seedCriteria.seedRatio value'")
|
.unwrap_or("")
|
||||||
.to_owned();
|
.to_owned();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,10 +172,14 @@ impl Network<'_, '_> {
|
|||||||
edit_indexer_params.tags.unwrap_or(
|
edit_indexer_params.tags.unwrap_or(
|
||||||
detailed_indexer_body["tags"]
|
detailed_indexer_body["tags"]
|
||||||
.as_array()
|
.as_array()
|
||||||
.expect("Unable to deserialize 'tags'")
|
.context("Failed to get indexer 'tags' array")?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|item| item.as_i64().expect("Unable to deserialize tag ID"))
|
.map(|item| {
|
||||||
.collect(),
|
item
|
||||||
|
.as_i64()
|
||||||
|
.context("Failed to deserialize indexer tag ID")
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<_>>>()?,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let priority = edit_indexer_params.priority.unwrap_or(priority);
|
let priority = edit_indexer_params.priority.unwrap_or(priority);
|
||||||
@@ -193,47 +197,54 @@ impl Network<'_, '_> {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
*detailed_indexer_body.get_mut("name").unwrap() = json!(name);
|
*detailed_indexer_body
|
||||||
*detailed_indexer_body.get_mut("priority").unwrap() = json!(priority);
|
.get_mut("name")
|
||||||
*detailed_indexer_body.get_mut("enableRss").unwrap() = json!(enable_rss);
|
.context("Failed to get mutable reference to indexer 'name' field")? = json!(name);
|
||||||
|
*detailed_indexer_body
|
||||||
|
.get_mut("priority")
|
||||||
|
.context("Failed to get mutable reference to indexer 'priority' field")? = json!(priority);
|
||||||
|
*detailed_indexer_body
|
||||||
|
.get_mut("enableRss")
|
||||||
|
.context("Failed to get mutable reference to indexer 'enableRss' field")? = json!(enable_rss);
|
||||||
*detailed_indexer_body
|
*detailed_indexer_body
|
||||||
.get_mut("enableAutomaticSearch")
|
.get_mut("enableAutomaticSearch")
|
||||||
.unwrap() = json!(enable_automatic_search);
|
.context("Failed to get mutable reference to indexer 'enableAutomaticSearch' field")? =
|
||||||
|
json!(enable_automatic_search);
|
||||||
*detailed_indexer_body
|
*detailed_indexer_body
|
||||||
.get_mut("enableInteractiveSearch")
|
.get_mut("enableInteractiveSearch")
|
||||||
.unwrap() = json!(enable_interactive_search);
|
.context("Failed to get mutable reference to indexer 'enableInteractiveSearch' field")? =
|
||||||
|
json!(enable_interactive_search);
|
||||||
*detailed_indexer_body
|
*detailed_indexer_body
|
||||||
.get_mut("fields")
|
.get_mut("fields")
|
||||||
.unwrap()
|
.and_then(|f| f.as_array_mut())
|
||||||
.as_array_mut()
|
.context("Failed to get mutable reference to indexer 'fields' array")?
|
||||||
.unwrap()
|
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|field| field["name"] == "baseUrl")
|
.find(|field| field["name"] == "baseUrl")
|
||||||
.unwrap()
|
.context("Failed to find 'baseUrl' field in indexer fields array")?
|
||||||
.get_mut("value")
|
.get_mut("value")
|
||||||
.unwrap() = json!(url);
|
.context("Failed to get mutable reference to 'baseUrl' value")? = json!(url);
|
||||||
*detailed_indexer_body
|
*detailed_indexer_body
|
||||||
.get_mut("fields")
|
.get_mut("fields")
|
||||||
.unwrap()
|
.and_then(|f| f.as_array_mut())
|
||||||
.as_array_mut()
|
.context("Failed to get mutable reference to indexer 'fields' array for apiKey")?
|
||||||
.unwrap()
|
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|field| field["name"] == "apiKey")
|
.find(|field| field["name"] == "apiKey")
|
||||||
.unwrap()
|
.context("Failed to find 'apiKey' field in indexer fields array")?
|
||||||
.get_mut("value")
|
.get_mut("value")
|
||||||
.unwrap() = json!(api_key);
|
.context("Failed to get mutable reference to 'apiKey' value")? = json!(api_key);
|
||||||
*detailed_indexer_body.get_mut("tags").unwrap() = json!(tags);
|
*detailed_indexer_body
|
||||||
|
.get_mut("tags")
|
||||||
|
.context("Failed to get mutable reference to indexer 'tags' field")? = json!(tags);
|
||||||
let seed_ratio_field_option = detailed_indexer_body
|
let seed_ratio_field_option = detailed_indexer_body
|
||||||
.get_mut("fields")
|
.get_mut("fields")
|
||||||
.unwrap()
|
.and_then(|f| f.as_array_mut())
|
||||||
.as_array_mut()
|
.context("Failed to get mutable reference to indexer 'fields' array for seed ratio")?
|
||||||
.unwrap()
|
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.find(|field| field["name"] == "seedCriteria.seedRatio");
|
.find(|field| field["name"] == "seedCriteria.seedRatio");
|
||||||
if let Some(seed_ratio_field) = seed_ratio_field_option {
|
if let Some(seed_ratio_field) = seed_ratio_field_option {
|
||||||
seed_ratio_field
|
seed_ratio_field
|
||||||
.as_object_mut()
|
.as_object_mut()
|
||||||
.unwrap()
|
.context("Failed to get mutable reference to 'seedCriteria.seedRatio' object")?
|
||||||
.insert("value".to_string(), json!(seed_ratio));
|
.insert("value".to_string(), json!(seed_ratio));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,12 +341,13 @@ impl Network<'_, '_> {
|
|||||||
self
|
self
|
||||||
.handle_request::<Value, Value>(request_props, |test_results, mut app| {
|
.handle_request::<Value, Value>(request_props, |test_results, mut app| {
|
||||||
if test_results.as_object().is_none() {
|
if test_results.as_object().is_none() {
|
||||||
app.data.sonarr_data.indexer_test_errors = Some(
|
let error_message = test_results
|
||||||
test_results.as_array().unwrap()[0]
|
.as_array()
|
||||||
.get("errorMessage")
|
.and_then(|arr| arr.first())
|
||||||
.unwrap()
|
.and_then(|item| item.get("errorMessage"))
|
||||||
.to_string(),
|
.map(|msg| msg.to_string())
|
||||||
);
|
.unwrap_or_else(|| "Unknown indexer test error".to_string());
|
||||||
|
app.data.sonarr_data.indexer_test_errors = Some(error_message);
|
||||||
} else {
|
} else {
|
||||||
app.data.sonarr_data.indexer_test_errors = Some(String::new());
|
app.data.sonarr_data.indexer_test_errors = Some(String::new());
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -55,17 +55,29 @@ impl Network<'_, '_> {
|
|||||||
"{}|{}|{}|{}|{}",
|
"{}|{}|{}|{}|{}",
|
||||||
log.time,
|
log.time,
|
||||||
log.level.to_uppercase(),
|
log.level.to_uppercase(),
|
||||||
log.logger.as_ref().unwrap(),
|
log
|
||||||
log.exception_type.as_ref().unwrap(),
|
.logger
|
||||||
log.exception.as_ref().unwrap()
|
.as_ref()
|
||||||
|
.expect("logger must exist when exception is present"),
|
||||||
|
log
|
||||||
|
.exception_type
|
||||||
|
.as_ref()
|
||||||
|
.expect("exception_type must exist when exception is present"),
|
||||||
|
log
|
||||||
|
.exception
|
||||||
|
.as_ref()
|
||||||
|
.expect("exception must exist in this branch")
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
HorizontallyScrollableText::from(format!(
|
HorizontallyScrollableText::from(format!(
|
||||||
"{}|{}|{}|{}",
|
"{}|{}|{}|{}",
|
||||||
log.time,
|
log.time,
|
||||||
log.level.to_uppercase(),
|
log.level.to_uppercase(),
|
||||||
log.logger.as_ref().unwrap(),
|
log.logger.as_ref().expect("logger must exist in log entry"),
|
||||||
log.message.as_ref().unwrap()
|
log
|
||||||
|
.message
|
||||||
|
.as_ref()
|
||||||
|
.expect("message must exist when exception is not present")
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -80,13 +80,19 @@ fn draw_add_movie_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
Layout::vertical([Constraint::Length(3), Constraint::Fill(0)])
|
Layout::vertical([Constraint::Length(3), Constraint::Fill(0)])
|
||||||
.margin(1)
|
.margin(1)
|
||||||
.areas(area);
|
.areas(area);
|
||||||
let block_content = &app.data.radarr_data.add_movie_search.as_ref().unwrap().text;
|
let block_content = &app
|
||||||
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.add_movie_search
|
||||||
|
.as_ref()
|
||||||
|
.expect("add_movie_search must be populated")
|
||||||
|
.text;
|
||||||
let offset = app
|
let offset = app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.add_movie_search
|
.add_movie_search
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("add_movie_search must be populated")
|
||||||
.offset
|
.offset
|
||||||
.load(Ordering::SeqCst);
|
.load(Ordering::SeqCst);
|
||||||
let search_results_row_mapping = |movie: &AddMovieSearchResult| {
|
let search_results_row_mapping = |movie: &AddMovieSearchResult| {
|
||||||
@@ -260,7 +266,7 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.radarr_data
|
.radarr_data
|
||||||
.add_searched_movies
|
.add_searched_movies
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("add_searched_movies must be populated")
|
||||||
.current_selection()
|
.current_selection()
|
||||||
.title
|
.title
|
||||||
.text,
|
.text,
|
||||||
@@ -269,7 +275,7 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.radarr_data
|
.radarr_data
|
||||||
.add_searched_movies
|
.add_searched_movies
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("add_searched_movies must be populated")
|
||||||
.current_selection()
|
.current_selection()
|
||||||
.overview
|
.overview
|
||||||
.clone(),
|
.clone(),
|
||||||
@@ -287,7 +293,12 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
root_folder_list,
|
root_folder_list,
|
||||||
tags,
|
tags,
|
||||||
..
|
..
|
||||||
} = app.data.radarr_data.add_movie_modal.as_ref().unwrap();
|
} = app
|
||||||
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.add_movie_modal
|
||||||
|
.as_ref()
|
||||||
|
.expect("add_movie_modal must exist in this context");
|
||||||
|
|
||||||
let selected_monitor = monitor_list.current_selection();
|
let selected_monitor = monitor_list.current_selection();
|
||||||
let selected_minimum_availability = minimum_availability_list.current_selection();
|
let selected_minimum_availability = minimum_availability_list.current_selection();
|
||||||
@@ -378,7 +389,7 @@ fn draw_add_movie_select_monitor_popup(f: &mut Frame<'_>, app: &mut App<'_>) {
|
|||||||
.radarr_data
|
.radarr_data
|
||||||
.add_movie_modal
|
.add_movie_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("add_movie_modal must exist in this context")
|
||||||
.monitor_list,
|
.monitor_list,
|
||||||
|monitor| ListItem::new(monitor.to_display_str().to_owned()),
|
|monitor| ListItem::new(monitor.to_display_str().to_owned()),
|
||||||
);
|
);
|
||||||
@@ -394,7 +405,7 @@ fn draw_add_movie_select_minimum_availability_popup(f: &mut Frame<'_>, app: &mut
|
|||||||
.radarr_data
|
.radarr_data
|
||||||
.add_movie_modal
|
.add_movie_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("add_movie_modal must exist in this context")
|
||||||
.minimum_availability_list,
|
.minimum_availability_list,
|
||||||
|minimum_availability| ListItem::new(minimum_availability.to_display_str().to_owned()),
|
|minimum_availability| ListItem::new(minimum_availability.to_display_str().to_owned()),
|
||||||
);
|
);
|
||||||
@@ -410,7 +421,7 @@ fn draw_add_movie_select_quality_profile_popup(f: &mut Frame<'_>, app: &mut App<
|
|||||||
.radarr_data
|
.radarr_data
|
||||||
.add_movie_modal
|
.add_movie_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("add_movie_modal must exist in this context")
|
||||||
.quality_profile_list,
|
.quality_profile_list,
|
||||||
|quality_profile| ListItem::new(quality_profile.clone()),
|
|quality_profile| ListItem::new(quality_profile.clone()),
|
||||||
);
|
);
|
||||||
@@ -426,7 +437,7 @@ fn draw_add_movie_select_root_folder_popup(f: &mut Frame<'_>, app: &mut App<'_>)
|
|||||||
.radarr_data
|
.radarr_data
|
||||||
.add_movie_modal
|
.add_movie_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("add_movie_modal must exist in this context")
|
||||||
.root_folder_list,
|
.root_folder_list,
|
||||||
|root_folder| ListItem::new(root_folder.path.to_owned()),
|
|root_folder| ListItem::new(root_folder.path.to_owned()),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -87,7 +87,12 @@ fn draw_edit_movie_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, are
|
|||||||
monitored,
|
monitored,
|
||||||
path,
|
path,
|
||||||
tags,
|
tags,
|
||||||
} = app.data.radarr_data.edit_movie_modal.as_ref().unwrap();
|
} = app
|
||||||
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.edit_movie_modal
|
||||||
|
.as_ref()
|
||||||
|
.expect("edit_movie_modal must exist in this context");
|
||||||
let selected_minimum_availability = minimum_availability_list.current_selection();
|
let selected_minimum_availability = minimum_availability_list.current_selection();
|
||||||
let selected_quality_profile = quality_profile_list.current_selection();
|
let selected_quality_profile = quality_profile_list.current_selection();
|
||||||
|
|
||||||
@@ -175,7 +180,7 @@ fn draw_edit_movie_select_minimum_availability_popup(f: &mut Frame<'_>, app: &mu
|
|||||||
.radarr_data
|
.radarr_data
|
||||||
.edit_movie_modal
|
.edit_movie_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("edit_movie_modal must exist in this context")
|
||||||
.minimum_availability_list,
|
.minimum_availability_list,
|
||||||
|minimum_availability| ListItem::new(minimum_availability.to_display_str().to_owned()),
|
|minimum_availability| ListItem::new(minimum_availability.to_display_str().to_owned()),
|
||||||
);
|
);
|
||||||
@@ -191,7 +196,7 @@ fn draw_edit_movie_select_quality_profile_popup(f: &mut Frame<'_>, app: &mut App
|
|||||||
.radarr_data
|
.radarr_data
|
||||||
.edit_movie_modal
|
.edit_movie_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("edit_movie_modal must exist in this context")
|
||||||
.quality_profile_list,
|
.quality_profile_list,
|
||||||
|quality_profile| ListItem::new(quality_profile.clone()),
|
|quality_profile| ListItem::new(quality_profile.clone()),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ fn draw_library(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
let certification = movie.certification.clone().unwrap_or_default();
|
let certification = movie.certification.clone().unwrap_or_default();
|
||||||
let quality_profile = quality_profile_map
|
let quality_profile = quality_profile_map
|
||||||
.get_by_left(&movie.quality_profile_id)
|
.get_by_left(&movie.quality_profile_id)
|
||||||
.unwrap()
|
.expect("Quality profile ID must exist in quality_profile_map")
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let empty_tag = String::new();
|
let empty_tag = String::new();
|
||||||
let tags = if !movie.tags.is_empty() {
|
let tags = if !movie.tags.is_empty() {
|
||||||
@@ -108,7 +108,7 @@ fn draw_library(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|tag_id| {
|
.map(|tag_id| {
|
||||||
tags_map
|
tags_map
|
||||||
.get_by_left(&tag_id.as_i64().unwrap())
|
.get_by_left(&tag_id.as_i64().expect("Tag ID must be a valid i64"))
|
||||||
.unwrap_or(&empty_tag)
|
.unwrap_or(&empty_tag)
|
||||||
.clone()
|
.clone()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -472,7 +472,7 @@ fn draw_manual_search_confirm_prompt(f: &mut Frame<'_>, app: &mut App<'_>) {
|
|||||||
.radarr_data
|
.radarr_data
|
||||||
.movie_details_modal
|
.movie_details_modal
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("movie_details_modal must exist in this context")
|
||||||
.movie_releases
|
.movie_releases
|
||||||
.current_selection();
|
.current_selection();
|
||||||
let title = if current_selection.rejected {
|
let title = if current_selection.rejected {
|
||||||
|
|||||||
@@ -80,14 +80,14 @@ fn draw_add_series_search(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.add_series_search
|
.add_series_search
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("add_series_search must be populated")
|
||||||
.text;
|
.text;
|
||||||
let offset = app
|
let offset = app
|
||||||
.data
|
.data
|
||||||
.sonarr_data
|
.sonarr_data
|
||||||
.add_series_search
|
.add_series_search
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("add_series_search must be populated")
|
||||||
.offset
|
.offset
|
||||||
.load(Ordering::SeqCst);
|
.load(Ordering::SeqCst);
|
||||||
let search_results_row_mapping = |series: &AddSeriesSearchResult| {
|
let search_results_row_mapping = |series: &AddSeriesSearchResult| {
|
||||||
@@ -232,7 +232,7 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.add_searched_series
|
.add_searched_series
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("add_searched_series must be populated")
|
||||||
.current_selection()
|
.current_selection()
|
||||||
.title
|
.title
|
||||||
.text,
|
.text,
|
||||||
@@ -241,7 +241,7 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.add_searched_series
|
.add_searched_series
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("add_searched_series must be populated")
|
||||||
.current_selection()
|
.current_selection()
|
||||||
.overview
|
.overview
|
||||||
.clone()
|
.clone()
|
||||||
@@ -261,7 +261,12 @@ fn draw_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
use_season_folder,
|
use_season_folder,
|
||||||
tags,
|
tags,
|
||||||
..
|
..
|
||||||
} = app.data.sonarr_data.add_series_modal.as_ref().unwrap();
|
} = app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.add_series_modal
|
||||||
|
.as_ref()
|
||||||
|
.expect("add_series_modal must exist in this context");
|
||||||
|
|
||||||
let selected_monitor = monitor_list.current_selection();
|
let selected_monitor = monitor_list.current_selection();
|
||||||
let selected_series_type = series_type_list.current_selection();
|
let selected_series_type = series_type_list.current_selection();
|
||||||
@@ -367,7 +372,7 @@ fn draw_add_series_select_monitor_popup(f: &mut Frame<'_>, app: &mut App<'_>) {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.add_series_modal
|
.add_series_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("add_series_modal must exist in this context")
|
||||||
.monitor_list,
|
.monitor_list,
|
||||||
|monitor| ListItem::new(monitor.to_display_str().to_owned()),
|
|monitor| ListItem::new(monitor.to_display_str().to_owned()),
|
||||||
);
|
);
|
||||||
@@ -383,7 +388,7 @@ fn draw_add_series_select_series_type_popup(f: &mut Frame<'_>, app: &mut App<'_>
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.add_series_modal
|
.add_series_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("add_series_modal must exist in this context")
|
||||||
.series_type_list,
|
.series_type_list,
|
||||||
|series_type| ListItem::new(series_type.to_display_str().to_owned()),
|
|series_type| ListItem::new(series_type.to_display_str().to_owned()),
|
||||||
);
|
);
|
||||||
@@ -399,7 +404,7 @@ fn draw_add_series_select_quality_profile_popup(f: &mut Frame<'_>, app: &mut App
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.add_series_modal
|
.add_series_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("add_series_modal must exist in this context")
|
||||||
.quality_profile_list,
|
.quality_profile_list,
|
||||||
|quality_profile| ListItem::new(quality_profile.clone()),
|
|quality_profile| ListItem::new(quality_profile.clone()),
|
||||||
);
|
);
|
||||||
@@ -415,7 +420,7 @@ fn draw_add_series_select_language_profile_popup(f: &mut Frame<'_>, app: &mut Ap
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.add_series_modal
|
.add_series_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("add_series_modal must exist in this context")
|
||||||
.language_profile_list,
|
.language_profile_list,
|
||||||
|language_profile| ListItem::new(language_profile.clone()),
|
|language_profile| ListItem::new(language_profile.clone()),
|
||||||
);
|
);
|
||||||
@@ -431,7 +436,7 @@ fn draw_add_series_select_root_folder_popup(f: &mut Frame<'_>, app: &mut App<'_>
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.add_series_modal
|
.add_series_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("add_series_modal must exist in this context")
|
||||||
.root_folder_list,
|
.root_folder_list,
|
||||||
|root_folder| ListItem::new(root_folder.path.to_owned()),
|
|root_folder| ListItem::new(root_folder.path.to_owned()),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -99,7 +99,12 @@ fn draw_edit_series_confirmation_prompt(f: &mut Frame<'_>, app: &mut App<'_>, ar
|
|||||||
use_season_folders,
|
use_season_folders,
|
||||||
path,
|
path,
|
||||||
tags,
|
tags,
|
||||||
} = app.data.sonarr_data.edit_series_modal.as_ref().unwrap();
|
} = app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.edit_series_modal
|
||||||
|
.as_ref()
|
||||||
|
.expect("edit_series_modal must exist in this context");
|
||||||
let selected_series_type = series_type_list.current_selection();
|
let selected_series_type = series_type_list.current_selection();
|
||||||
let selected_quality_profile = quality_profile_list.current_selection();
|
let selected_quality_profile = quality_profile_list.current_selection();
|
||||||
let selected_language_profile = language_profile_list.current_selection();
|
let selected_language_profile = language_profile_list.current_selection();
|
||||||
@@ -202,7 +207,7 @@ fn draw_edit_series_select_series_type_popup(f: &mut Frame<'_>, app: &mut App<'_
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.edit_series_modal
|
.edit_series_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("edit_series_modal must exist in this context")
|
||||||
.series_type_list,
|
.series_type_list,
|
||||||
|series_type| ListItem::new(series_type.to_display_str().to_owned()),
|
|series_type| ListItem::new(series_type.to_display_str().to_owned()),
|
||||||
);
|
);
|
||||||
@@ -218,7 +223,7 @@ fn draw_edit_series_select_quality_profile_popup(f: &mut Frame<'_>, app: &mut Ap
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.edit_series_modal
|
.edit_series_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("edit_series_modal must exist in this context")
|
||||||
.quality_profile_list,
|
.quality_profile_list,
|
||||||
|quality_profile| ListItem::new(quality_profile.clone()),
|
|quality_profile| ListItem::new(quality_profile.clone()),
|
||||||
);
|
);
|
||||||
@@ -234,7 +239,7 @@ fn draw_edit_series_select_language_profile_popup(f: &mut Frame<'_>, app: &mut A
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.edit_series_modal
|
.edit_series_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("edit_series_modal must exist in this context")
|
||||||
.language_profile_list,
|
.language_profile_list,
|
||||||
|language_profile| ListItem::new(language_profile.clone()),
|
|language_profile| ListItem::new(language_profile.clone()),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -60,10 +60,10 @@ impl DrawUi for EpisodeDetailsUi {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.episode_details_modal
|
.episode_details_modal
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("episode_details_modal must exist in this context")
|
||||||
.episode_details_tabs,
|
.episode_details_tabs,
|
||||||
);
|
);
|
||||||
draw_episode_details_tabs(f, app, content_area);
|
draw_episode_details_tabs(f, app, content_area);
|
||||||
@@ -77,7 +77,7 @@ impl DrawUi for EpisodeDetailsUi {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.episodes
|
.episodes
|
||||||
.current_selection()
|
.current_selection()
|
||||||
.title
|
.title
|
||||||
@@ -181,7 +181,7 @@ fn draw_episode_details(f: &mut Frame<'_>, app: &App<'_>, area: Rect) {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.episode_details_modal
|
.episode_details_modal
|
||||||
.is_none(),
|
.is_none(),
|
||||||
block,
|
block,
|
||||||
@@ -303,10 +303,10 @@ fn draw_episode_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect)
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.episode_details_modal
|
.episode_details_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("episode_details_modal must exist in this context")
|
||||||
.episode_history;
|
.episode_history;
|
||||||
let history_table =
|
let history_table =
|
||||||
ManagarrTable::new(Some(&mut episode_history_table), history_row_mapping)
|
ManagarrTable::new(Some(&mut episode_history_table), history_row_mapping)
|
||||||
@@ -332,7 +332,7 @@ fn draw_episode_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect)
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.episode_details_modal
|
.episode_details_modal
|
||||||
.is_none(),
|
.is_none(),
|
||||||
layout_block_top_border(),
|
layout_block_top_border(),
|
||||||
@@ -474,10 +474,10 @@ fn draw_episode_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.episode_details_modal
|
.episode_details_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("episode_details_modal must exist in this context")
|
||||||
.episode_releases;
|
.episode_releases;
|
||||||
let release_table = ManagarrTable::new(
|
let release_table = ManagarrTable::new(
|
||||||
Some(&mut episode_release_table),
|
Some(&mut episode_release_table),
|
||||||
@@ -513,7 +513,7 @@ fn draw_episode_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.episode_details_modal
|
.episode_details_modal
|
||||||
.is_none(),
|
.is_none(),
|
||||||
layout_block_top_border(),
|
layout_block_top_border(),
|
||||||
@@ -529,10 +529,10 @@ fn draw_manual_episode_search_confirm_prompt(f: &mut Frame<'_>, app: &mut App<'_
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.episode_details_modal
|
.episode_details_modal
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("episode_details_modal must exist in this context")
|
||||||
.episode_releases
|
.episode_releases
|
||||||
.current_selection();
|
.current_selection();
|
||||||
let title = if current_selection.rejected {
|
let title = if current_selection.rejected {
|
||||||
|
|||||||
@@ -106,11 +106,11 @@ fn draw_library(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.map_or(0f64, |stats| convert_to_gb(stats.size_on_disk));
|
.map_or(0f64, |stats| convert_to_gb(stats.size_on_disk));
|
||||||
let quality_profile = quality_profile_map
|
let quality_profile = quality_profile_map
|
||||||
.get_by_left(&series.quality_profile_id)
|
.get_by_left(&series.quality_profile_id)
|
||||||
.unwrap()
|
.expect("Quality profile ID must exist in quality_profile_map")
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let language_profile = language_profile_map
|
let language_profile = language_profile_map
|
||||||
.get_by_left(&series.language_profile_id)
|
.get_by_left(&series.language_profile_id)
|
||||||
.unwrap()
|
.expect("Language profile ID must exist in language_profile_map")
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let empty_tag = String::new();
|
let empty_tag = String::new();
|
||||||
let tags = if !series.tags.is_empty() {
|
let tags = if !series.tags.is_empty() {
|
||||||
@@ -119,7 +119,7 @@ fn draw_library(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|tag_id| {
|
.map(|tag_id| {
|
||||||
tags_map
|
tags_map
|
||||||
.get_by_left(&tag_id.as_i64().unwrap())
|
.get_by_left(&tag_id.as_i64().expect("Tag ID must be a valid i64"))
|
||||||
.unwrap_or(&empty_tag)
|
.unwrap_or(&empty_tag)
|
||||||
.clone()
|
.clone()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ impl DrawUi for SeasonDetailsUi {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.season_details_tabs,
|
.season_details_tabs,
|
||||||
);
|
);
|
||||||
draw_season_details(f, app, content_area);
|
draw_season_details(f, app, content_area);
|
||||||
@@ -103,7 +103,7 @@ impl DrawUi for SeasonDetailsUi {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.episodes
|
.episodes
|
||||||
.current_selection()
|
.current_selection()
|
||||||
.title
|
.title
|
||||||
@@ -294,7 +294,7 @@ fn draw_season_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.season_history;
|
.season_history;
|
||||||
let history_table =
|
let history_table =
|
||||||
ManagarrTable::new(Some(&mut season_history_table), history_row_mapping)
|
ManagarrTable::new(Some(&mut season_history_table), history_row_mapping)
|
||||||
@@ -426,7 +426,7 @@ fn draw_season_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.season_releases;
|
.season_releases;
|
||||||
let release_table =
|
let release_table =
|
||||||
ManagarrTable::new(Some(&mut season_release_table), season_release_row_mapping)
|
ManagarrTable::new(Some(&mut season_release_table), season_release_row_mapping)
|
||||||
@@ -467,7 +467,7 @@ fn draw_manual_season_search_confirm_prompt(f: &mut Frame<'_>, app: &mut App<'_>
|
|||||||
.sonarr_data
|
.sonarr_data
|
||||||
.season_details_modal
|
.season_details_modal
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("season_details_modal must exist in this context")
|
||||||
.season_releases
|
.season_releases
|
||||||
.current_selection();
|
.current_selection();
|
||||||
let title = if current_selection.rejected {
|
let title = if current_selection.rejected {
|
||||||
|
|||||||
@@ -333,7 +333,12 @@ fn draw_series_history_table(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
])
|
])
|
||||||
.primary()
|
.primary()
|
||||||
};
|
};
|
||||||
let mut series_history_table = app.data.sonarr_data.series_history.as_mut().unwrap();
|
let mut series_history_table = app
|
||||||
|
.data
|
||||||
|
.sonarr_data
|
||||||
|
.series_history
|
||||||
|
.as_mut()
|
||||||
|
.expect("series_history must be populated");
|
||||||
let history_table =
|
let history_table =
|
||||||
ManagarrTable::new(Some(&mut series_history_table), history_row_mapping)
|
ManagarrTable::new(Some(&mut series_history_table), history_row_mapping)
|
||||||
.block(layout_block_top_border())
|
.block(layout_block_top_border())
|
||||||
|
|||||||
+160
-16
@@ -40,31 +40,94 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn awaiting_import(self) -> T {
|
fn awaiting_import(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().awaiting_import.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.awaiting_import
|
||||||
|
.expect("awaiting_import style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("awaiting_import color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn indeterminate(self) -> T {
|
fn indeterminate(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().indeterminate.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.indeterminate
|
||||||
|
.expect("indeterminate style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("indeterminate color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default(self) -> T {
|
fn default(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().default.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.default
|
||||||
|
.expect("default style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("default color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn downloaded(self) -> T {
|
fn downloaded(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().downloaded.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.downloaded
|
||||||
|
.expect("downloaded style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("downloaded color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn downloading(self) -> T {
|
fn downloading(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().downloading.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.downloading
|
||||||
|
.expect("downloading style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("downloading color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn failure(self) -> T {
|
fn failure(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().failure.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.failure
|
||||||
|
.expect("failure style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("failure color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn help(self) -> T {
|
fn help(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().help.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.help
|
||||||
|
.expect("help style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("help color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn highlight(self) -> T {
|
fn highlight(self) -> T {
|
||||||
@@ -72,38 +135,119 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn missing(self) -> T {
|
fn missing(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().missing.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.missing
|
||||||
|
.expect("missing style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("missing color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn primary(self) -> T {
|
fn primary(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().primary.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.primary
|
||||||
|
.expect("primary style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("primary color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn secondary(self) -> T {
|
fn secondary(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().secondary.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.secondary
|
||||||
|
.expect("secondary style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("secondary color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn success(self) -> T {
|
fn success(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().success.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.success
|
||||||
|
.expect("success style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("success color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn system_function(self) -> T {
|
fn system_function(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().system_function.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.system_function
|
||||||
|
.expect("system_function style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("system_function color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unmonitored(self) -> T {
|
fn unmonitored(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().unmonitored.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.unmonitored
|
||||||
|
.expect("unmonitored style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("unmonitored color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unmonitored_missing(self) -> T {
|
fn unmonitored_missing(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().unmonitored_missing.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.unmonitored_missing
|
||||||
|
.expect("unmonitored_missing style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("unmonitored_missing color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unreleased(self) -> T {
|
fn unreleased(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().unreleased.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.unreleased
|
||||||
|
.expect("unreleased style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("unreleased color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn warning(self) -> T {
|
fn warning(self) -> T {
|
||||||
THEME.with(|theme| self.fg(theme.get().warning.unwrap().color.unwrap()))
|
THEME.with(|theme| {
|
||||||
|
self.fg(
|
||||||
|
theme
|
||||||
|
.get()
|
||||||
|
.warning
|
||||||
|
.expect("warning style must be defined in theme")
|
||||||
|
.color
|
||||||
|
.expect("warning color must be defined"),
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -80,7 +80,7 @@ pub fn convert_runtime(runtime: i64) -> (i64, i64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn tail_logs(no_color: bool) {
|
pub async fn tail_logs(no_color: bool) {
|
||||||
let re = Regex::new(r"^(?P<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})\s+<(?P<opid>[^\s>]+)>\s+\[(?P<level>[A-Z]+)\]\s+(?P<logger>[^:]+):(?P<line>\d+)\s+-\s+(?P<message>.*)$").unwrap();
|
let re = Regex::new(r"^(?P<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})\s+<(?P<opid>[^\s>]+)>\s+\[(?P<level>[A-Z]+)]\s+(?P<logger>[^:]+):(?P<line>\d+)\s+-\s+(?P<message>.*)$").unwrap();
|
||||||
let file_path = get_log_path();
|
let file_path = get_log_path();
|
||||||
let file = File::open(&file_path).expect("Cannot open file");
|
let file = File::open(&file_path).expect("Cannot open file");
|
||||||
let mut reader = BufReader::new(file);
|
let mut reader = BufReader::new(file);
|
||||||
@@ -311,11 +311,13 @@ pub fn select_cli_configuration(
|
|||||||
} else {
|
} else {
|
||||||
match command {
|
match command {
|
||||||
Command::Radarr(_) => {
|
Command::Radarr(_) => {
|
||||||
let default_radarr_config = config.radarr.as_ref().unwrap()[0].clone();
|
let default_radarr_config =
|
||||||
|
config.radarr.as_ref().expect("Radarr config must exist")[0].clone();
|
||||||
app.server_tabs.select_tab_by_config(&default_radarr_config);
|
app.server_tabs.select_tab_by_config(&default_radarr_config);
|
||||||
}
|
}
|
||||||
Command::Sonarr(_) => {
|
Command::Sonarr(_) => {
|
||||||
let default_sonarr_config = config.sonarr.as_ref().unwrap()[0].clone();
|
let default_sonarr_config =
|
||||||
|
config.sonarr.as_ref().expect("Sonarr config must exist")[0].clone();
|
||||||
app.server_tabs.select_tab_by_config(&default_sonarr_config);
|
app.server_tabs.select_tab_by_config(&default_sonarr_config);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|||||||
Reference in New Issue
Block a user