fix(network): Added filtering for full seasons specifically in the UI when performing a manual full season search and added a message to the CLI that noes to only try to download a full season if that release includes 'fullSeason: true'
This commit is contained in:
@@ -6,10 +6,9 @@ mod tests {
|
|||||||
|
|
||||||
use crate::app::radarr::ActiveRadarrBlock;
|
use crate::app::radarr::ActiveRadarrBlock;
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::models::radarr_models::{Collection, CollectionMovie, Credit};
|
use crate::models::radarr_models::{Collection, CollectionMovie, Credit, RadarrRelease};
|
||||||
use crate::models::servarr_data::radarr::modals::MovieDetailsModal;
|
use crate::models::servarr_data::radarr::modals::MovieDetailsModal;
|
||||||
|
|
||||||
use crate::models::servarr_models::Release;
|
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::network::NetworkEvent;
|
use crate::network::NetworkEvent;
|
||||||
|
|
||||||
@@ -431,7 +430,7 @@ mod tests {
|
|||||||
let mut movie_details_modal = MovieDetailsModal::default();
|
let mut movie_details_modal = MovieDetailsModal::default();
|
||||||
movie_details_modal
|
movie_details_modal
|
||||||
.movie_releases
|
.movie_releases
|
||||||
.set_items(vec![Release::default()]);
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
||||||
|
|
||||||
app
|
app
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ pub enum SonarrManualSearchCommand {
|
|||||||
episode_id: i64,
|
episode_id: i64,
|
||||||
},
|
},
|
||||||
#[command(
|
#[command(
|
||||||
about = "Trigger a manual search of releases for the given season corresponding to the series with the given ID"
|
about = "Trigger a manual search of releases for the given season corresponding to the series with the given ID.\nNote that when downloading a season release, ensure that the release includes 'fullSeason: true', otherwise you'll run into issues"
|
||||||
)]
|
)]
|
||||||
Season {
|
Season {
|
||||||
#[arg(
|
#[arg(
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
|
use crate::models::radarr_models::RadarrRelease;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{
|
use crate::models::servarr_data::radarr::radarr_data::{
|
||||||
ActiveRadarrBlock, EDIT_MOVIE_SELECTION_BLOCKS, MOVIE_DETAILS_BLOCKS,
|
ActiveRadarrBlock, EDIT_MOVIE_SELECTION_BLOCKS, MOVIE_DETAILS_BLOCKS,
|
||||||
};
|
};
|
||||||
use crate::models::servarr_models::{Language, Release};
|
use crate::models::servarr_models::Language;
|
||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
use crate::models::{BlockSelectionState, Scrollable};
|
use crate::models::{BlockSelectionState, Scrollable};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
@@ -505,7 +506,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn releases_sorting_options() -> Vec<SortOption<Release>> {
|
fn releases_sorting_options() -> Vec<SortOption<RadarrRelease>> {
|
||||||
vec![
|
vec![
|
||||||
SortOption {
|
SortOption {
|
||||||
name: "Source",
|
name: "Source",
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ mod tests {
|
|||||||
releases_sorting_options, MovieDetailsHandler,
|
releases_sorting_options, MovieDetailsHandler,
|
||||||
};
|
};
|
||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
|
use crate::models::radarr_models::RadarrRelease;
|
||||||
use crate::models::radarr_models::{Credit, MovieHistoryItem};
|
use crate::models::radarr_models::{Credit, MovieHistoryItem};
|
||||||
use crate::models::servarr_data::radarr::modals::MovieDetailsModal;
|
use crate::models::servarr_data::radarr::modals::MovieDetailsModal;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS};
|
||||||
use crate::models::servarr_models::{Language, Quality, QualityWrapper, Release};
|
use crate::models::servarr_models::{Language, Quality, QualityWrapper};
|
||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
use crate::models::{HorizontallyScrollableText, ScrollableText};
|
use crate::models::{HorizontallyScrollableText, ScrollableText};
|
||||||
|
|
||||||
@@ -405,7 +406,7 @@ mod tests {
|
|||||||
movie_details_modal
|
movie_details_modal
|
||||||
.movie_releases
|
.movie_releases
|
||||||
.set_items(simple_stateful_iterable_vec!(
|
.set_items(simple_stateful_iterable_vec!(
|
||||||
Release,
|
RadarrRelease,
|
||||||
HorizontallyScrollableText
|
HorizontallyScrollableText
|
||||||
));
|
));
|
||||||
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
||||||
@@ -453,7 +454,7 @@ mod tests {
|
|||||||
movie_details_modal
|
movie_details_modal
|
||||||
.movie_releases
|
.movie_releases
|
||||||
.set_items(simple_stateful_iterable_vec!(
|
.set_items(simple_stateful_iterable_vec!(
|
||||||
Release,
|
RadarrRelease,
|
||||||
HorizontallyScrollableText
|
HorizontallyScrollableText
|
||||||
));
|
));
|
||||||
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
||||||
@@ -996,7 +997,7 @@ mod tests {
|
|||||||
movie_details_modal
|
movie_details_modal
|
||||||
.movie_releases
|
.movie_releases
|
||||||
.set_items(extended_stateful_iterable_vec!(
|
.set_items(extended_stateful_iterable_vec!(
|
||||||
Release,
|
RadarrRelease,
|
||||||
HorizontallyScrollableText
|
HorizontallyScrollableText
|
||||||
));
|
));
|
||||||
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
||||||
@@ -1054,7 +1055,7 @@ mod tests {
|
|||||||
movie_details_modal
|
movie_details_modal
|
||||||
.movie_releases
|
.movie_releases
|
||||||
.set_items(extended_stateful_iterable_vec!(
|
.set_items(extended_stateful_iterable_vec!(
|
||||||
Release,
|
RadarrRelease,
|
||||||
HorizontallyScrollableText
|
HorizontallyScrollableText
|
||||||
));
|
));
|
||||||
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
app.data.radarr_data.movie_details_modal = Some(movie_details_modal);
|
||||||
@@ -1249,7 +1250,9 @@ mod tests {
|
|||||||
movie_details: ScrollableText::with_string("test".to_owned()),
|
movie_details: ScrollableText::with_string("test".to_owned()),
|
||||||
..MovieDetailsModal::default()
|
..MovieDetailsModal::default()
|
||||||
};
|
};
|
||||||
modal.movie_releases.set_items(vec![Release::default()]);
|
modal
|
||||||
|
.movie_releases
|
||||||
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::ManualSearch.into());
|
app.push_navigation_stack(ActiveRadarrBlock::ManualSearch.into());
|
||||||
|
|
||||||
@@ -1487,6 +1490,8 @@ mod tests {
|
|||||||
)]
|
)]
|
||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
|
use crate::models::radarr_models::RadarrRelease;
|
||||||
|
|
||||||
let mut app = App::default();
|
let mut app = App::default();
|
||||||
let mut modal = MovieDetailsModal {
|
let mut modal = MovieDetailsModal {
|
||||||
movie_details: ScrollableText::with_string("Test".to_owned()),
|
movie_details: ScrollableText::with_string("Test".to_owned()),
|
||||||
@@ -1497,7 +1502,9 @@ mod tests {
|
|||||||
.set_items(vec![MovieHistoryItem::default()]);
|
.set_items(vec![MovieHistoryItem::default()]);
|
||||||
modal.movie_cast.set_items(vec![Credit::default()]);
|
modal.movie_cast.set_items(vec![Credit::default()]);
|
||||||
modal.movie_crew.set_items(vec![Credit::default()]);
|
modal.movie_crew.set_items(vec![Credit::default()]);
|
||||||
modal.movie_releases.set_items(vec![Release::default()]);
|
modal
|
||||||
|
.movie_releases
|
||||||
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::with(
|
||||||
@@ -1687,7 +1694,9 @@ mod tests {
|
|||||||
.set_items(vec![MovieHistoryItem::default()]);
|
.set_items(vec![MovieHistoryItem::default()]);
|
||||||
modal.movie_cast.set_items(vec![Credit::default()]);
|
modal.movie_cast.set_items(vec![Credit::default()]);
|
||||||
modal.movie_crew.set_items(vec![Credit::default()]);
|
modal.movie_crew.set_items(vec![Credit::default()]);
|
||||||
modal.movie_releases.set_items(vec![Release::default()]);
|
modal
|
||||||
|
.movie_releases
|
||||||
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::with(
|
||||||
@@ -1757,7 +1766,9 @@ mod tests {
|
|||||||
.set_items(vec![MovieHistoryItem::default()]);
|
.set_items(vec![MovieHistoryItem::default()]);
|
||||||
modal.movie_cast.set_items(vec![Credit::default()]);
|
modal.movie_cast.set_items(vec![Credit::default()]);
|
||||||
modal.movie_crew.set_items(vec![Credit::default()]);
|
modal.movie_crew.set_items(vec![Credit::default()]);
|
||||||
modal.movie_releases.set_items(vec![Release::default()]);
|
modal
|
||||||
|
.movie_releases
|
||||||
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
MovieDetailsHandler::with(
|
MovieDetailsHandler::with(
|
||||||
@@ -1851,7 +1862,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_releases_sorting_options_source() {
|
fn test_releases_sorting_options_source() {
|
||||||
let expected_cmp_fn: fn(&Release, &Release) -> Ordering = |a, b| a.protocol.cmp(&b.protocol);
|
let expected_cmp_fn: fn(&RadarrRelease, &RadarrRelease) -> Ordering =
|
||||||
|
|a, b| a.protocol.cmp(&b.protocol);
|
||||||
let mut expected_releases_vec = release_vec();
|
let mut expected_releases_vec = release_vec();
|
||||||
expected_releases_vec.sort_by(expected_cmp_fn);
|
expected_releases_vec.sort_by(expected_cmp_fn);
|
||||||
|
|
||||||
@@ -1865,7 +1877,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_releases_sorting_options_age() {
|
fn test_releases_sorting_options_age() {
|
||||||
let expected_cmp_fn: fn(&Release, &Release) -> Ordering = |a, b| a.age.cmp(&b.age);
|
let expected_cmp_fn: fn(&RadarrRelease, &RadarrRelease) -> Ordering = |a, b| a.age.cmp(&b.age);
|
||||||
let mut expected_releases_vec = release_vec();
|
let mut expected_releases_vec = release_vec();
|
||||||
expected_releases_vec.sort_by(expected_cmp_fn);
|
expected_releases_vec.sort_by(expected_cmp_fn);
|
||||||
|
|
||||||
@@ -1879,7 +1891,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_releases_sorting_options_rejected() {
|
fn test_releases_sorting_options_rejected() {
|
||||||
let expected_cmp_fn: fn(&Release, &Release) -> Ordering = |a, b| a.rejected.cmp(&b.rejected);
|
let expected_cmp_fn: fn(&RadarrRelease, &RadarrRelease) -> Ordering =
|
||||||
|
|a, b| a.rejected.cmp(&b.rejected);
|
||||||
let mut expected_releases_vec = release_vec();
|
let mut expected_releases_vec = release_vec();
|
||||||
expected_releases_vec.sort_by(expected_cmp_fn);
|
expected_releases_vec.sort_by(expected_cmp_fn);
|
||||||
|
|
||||||
@@ -1893,7 +1906,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_releases_sorting_options_title() {
|
fn test_releases_sorting_options_title() {
|
||||||
let expected_cmp_fn: fn(&Release, &Release) -> Ordering = |a, b| {
|
let expected_cmp_fn: fn(&RadarrRelease, &RadarrRelease) -> Ordering = |a, b| {
|
||||||
a.title
|
a.title
|
||||||
.text
|
.text
|
||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
@@ -1912,7 +1925,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_releases_sorting_options_indexer() {
|
fn test_releases_sorting_options_indexer() {
|
||||||
let expected_cmp_fn: fn(&Release, &Release) -> Ordering =
|
let expected_cmp_fn: fn(&RadarrRelease, &RadarrRelease) -> Ordering =
|
||||||
|a, b| a.indexer.to_lowercase().cmp(&b.indexer.to_lowercase());
|
|a, b| a.indexer.to_lowercase().cmp(&b.indexer.to_lowercase());
|
||||||
let mut expected_releases_vec = release_vec();
|
let mut expected_releases_vec = release_vec();
|
||||||
expected_releases_vec.sort_by(expected_cmp_fn);
|
expected_releases_vec.sort_by(expected_cmp_fn);
|
||||||
@@ -1927,7 +1940,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_releases_sorting_options_size() {
|
fn test_releases_sorting_options_size() {
|
||||||
let expected_cmp_fn: fn(&Release, &Release) -> Ordering = |a, b| a.size.cmp(&b.size);
|
let expected_cmp_fn: fn(&RadarrRelease, &RadarrRelease) -> Ordering =
|
||||||
|
|a, b| a.size.cmp(&b.size);
|
||||||
let mut expected_releases_vec = release_vec();
|
let mut expected_releases_vec = release_vec();
|
||||||
expected_releases_vec.sort_by(expected_cmp_fn);
|
expected_releases_vec.sort_by(expected_cmp_fn);
|
||||||
|
|
||||||
@@ -1941,7 +1955,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_releases_sorting_options_peers() {
|
fn test_releases_sorting_options_peers() {
|
||||||
let expected_cmp_fn: fn(&Release, &Release) -> Ordering = |a, b| {
|
let expected_cmp_fn: fn(&RadarrRelease, &RadarrRelease) -> Ordering = |a, b| {
|
||||||
let default_number = Number::from(i64::MAX);
|
let default_number = Number::from(i64::MAX);
|
||||||
let seeder_a = a
|
let seeder_a = a
|
||||||
.seeders
|
.seeders
|
||||||
@@ -1971,7 +1985,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_releases_sorting_options_language() {
|
fn test_releases_sorting_options_language() {
|
||||||
let expected_cmp_fn: fn(&Release, &Release) -> Ordering = |a, b| {
|
let expected_cmp_fn: fn(&RadarrRelease, &RadarrRelease) -> Ordering = |a, b| {
|
||||||
let default_language_vec = vec![Language {
|
let default_language_vec = vec![Language {
|
||||||
name: "_".to_owned(),
|
name: "_".to_owned(),
|
||||||
}];
|
}];
|
||||||
@@ -1993,7 +2007,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_releases_sorting_options_quality() {
|
fn test_releases_sorting_options_quality() {
|
||||||
let expected_cmp_fn: fn(&Release, &Release) -> Ordering = |a, b| a.quality.cmp(&b.quality);
|
let expected_cmp_fn: fn(&RadarrRelease, &RadarrRelease) -> Ordering =
|
||||||
|
|a, b| a.quality.cmp(&b.quality);
|
||||||
let mut expected_releases_vec = release_vec();
|
let mut expected_releases_vec = release_vec();
|
||||||
expected_releases_vec.sort_by(expected_cmp_fn);
|
expected_releases_vec.sort_by(expected_cmp_fn);
|
||||||
|
|
||||||
@@ -2040,7 +2055,9 @@ mod tests {
|
|||||||
.set_items(vec![MovieHistoryItem::default()]);
|
.set_items(vec![MovieHistoryItem::default()]);
|
||||||
modal.movie_cast.set_items(vec![Credit::default()]);
|
modal.movie_cast.set_items(vec![Credit::default()]);
|
||||||
modal.movie_crew.set_items(vec![Credit::default()]);
|
modal.movie_crew.set_items(vec![Credit::default()]);
|
||||||
modal.movie_releases.set_items(vec![Release::default()]);
|
modal
|
||||||
|
.movie_releases
|
||||||
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
let handler = MovieDetailsHandler::with(
|
let handler = MovieDetailsHandler::with(
|
||||||
@@ -2149,7 +2166,9 @@ mod tests {
|
|||||||
let mut app = App::default();
|
let mut app = App::default();
|
||||||
app.is_loading = false;
|
app.is_loading = false;
|
||||||
let mut modal = MovieDetailsModal::default();
|
let mut modal = MovieDetailsModal::default();
|
||||||
modal.movie_releases.set_items(vec![Release::default()]);
|
modal
|
||||||
|
.movie_releases
|
||||||
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
app.data.radarr_data.movie_details_modal = Some(modal);
|
app.data.radarr_data.movie_details_modal = Some(modal);
|
||||||
|
|
||||||
let handler = MovieDetailsHandler::with(
|
let handler = MovieDetailsHandler::with(
|
||||||
@@ -2162,8 +2181,8 @@ mod tests {
|
|||||||
assert!(handler.is_ready());
|
assert!(handler.is_ready());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release_vec() -> Vec<Release> {
|
fn release_vec() -> Vec<RadarrRelease> {
|
||||||
let release_a = Release {
|
let release_a = RadarrRelease {
|
||||||
protocol: "Protocol A".to_owned(),
|
protocol: "Protocol A".to_owned(),
|
||||||
age: 1,
|
age: 1,
|
||||||
title: HorizontallyScrollableText::from("Title A"),
|
title: HorizontallyScrollableText::from("Title A"),
|
||||||
@@ -2179,9 +2198,9 @@ mod tests {
|
|||||||
name: "Quality A".to_owned(),
|
name: "Quality A".to_owned(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
..Release::default()
|
..RadarrRelease::default()
|
||||||
};
|
};
|
||||||
let release_b = Release {
|
let release_b = RadarrRelease {
|
||||||
protocol: "Protocol B".to_owned(),
|
protocol: "Protocol B".to_owned(),
|
||||||
age: 2,
|
age: 2,
|
||||||
title: HorizontallyScrollableText::from("title B"),
|
title: HorizontallyScrollableText::from("title B"),
|
||||||
@@ -2197,9 +2216,9 @@ mod tests {
|
|||||||
name: "Quality B".to_owned(),
|
name: "Quality B".to_owned(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
..Release::default()
|
..RadarrRelease::default()
|
||||||
};
|
};
|
||||||
let release_c = Release {
|
let release_c = RadarrRelease {
|
||||||
protocol: "Protocol C".to_owned(),
|
protocol: "Protocol C".to_owned(),
|
||||||
age: 3,
|
age: 3,
|
||||||
title: HorizontallyScrollableText::from("Title C"),
|
title: HorizontallyScrollableText::from("Title C"),
|
||||||
@@ -2213,13 +2232,13 @@ mod tests {
|
|||||||
name: "Quality C".to_owned(),
|
name: "Quality C".to_owned(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
..Release::default()
|
..RadarrRelease::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
vec![release_a, release_b, release_c]
|
vec![release_a, release_b, release_c]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sort_options() -> Vec<SortOption<Release>> {
|
fn sort_options() -> Vec<SortOption<RadarrRelease>> {
|
||||||
vec![SortOption {
|
vec![SortOption {
|
||||||
name: "Test 1",
|
name: "Test 1",
|
||||||
cmp_fn: Some(|a, b| a.age.cmp(&b.age)),
|
cmp_fn: Some(|a, b| a.age.cmp(&b.age)),
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use crate::{models::HorizontallyScrollableText, serde_enum_from};
|
|||||||
|
|
||||||
use super::servarr_models::{
|
use super::servarr_models::{
|
||||||
DiskSpace, HostConfig, Indexer, Language, LogResponse, QualityProfile, QualityWrapper,
|
DiskSpace, HostConfig, Indexer, Language, LogResponse, QualityProfile, QualityWrapper,
|
||||||
QueueEvent, Release, RootFolder, SecurityConfig, Tag, Update,
|
QueueEvent, RootFolder, SecurityConfig, Tag, Update,
|
||||||
};
|
};
|
||||||
use super::{EnumDisplayStyle, Serdeable};
|
use super::{EnumDisplayStyle, Serdeable};
|
||||||
|
|
||||||
@@ -412,6 +412,28 @@ pub struct RatingsList {
|
|||||||
pub rotten_tomatoes: Option<Rating>,
|
pub rotten_tomatoes: Option<Rating>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct RadarrRelease {
|
||||||
|
pub guid: String,
|
||||||
|
pub protocol: String,
|
||||||
|
#[serde(deserialize_with = "super::from_i64")]
|
||||||
|
pub age: i64,
|
||||||
|
pub title: HorizontallyScrollableText,
|
||||||
|
pub indexer: String,
|
||||||
|
#[serde(deserialize_with = "super::from_i64")]
|
||||||
|
pub indexer_id: i64,
|
||||||
|
#[serde(deserialize_with = "super::from_i64")]
|
||||||
|
pub size: i64,
|
||||||
|
pub rejected: bool,
|
||||||
|
pub rejections: Option<Vec<String>>,
|
||||||
|
pub seeders: Option<Number>,
|
||||||
|
pub leechers: Option<Number>,
|
||||||
|
pub languages: Option<Vec<Language>>,
|
||||||
|
pub quality: QualityWrapper,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Serialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Default, Serialize, Debug, PartialEq, Eq, Clone)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct RadarrReleaseDownloadBody {
|
pub struct RadarrReleaseDownloadBody {
|
||||||
@@ -485,7 +507,7 @@ pub enum RadarrSerdeable {
|
|||||||
Movies(Vec<Movie>),
|
Movies(Vec<Movie>),
|
||||||
QualityProfiles(Vec<QualityProfile>),
|
QualityProfiles(Vec<QualityProfile>),
|
||||||
QueueEvents(Vec<QueueEvent>),
|
QueueEvents(Vec<QueueEvent>),
|
||||||
Releases(Vec<Release>),
|
Releases(Vec<RadarrRelease>),
|
||||||
RootFolders(Vec<RootFolder>),
|
RootFolders(Vec<RootFolder>),
|
||||||
SecurityConfig(SecurityConfig),
|
SecurityConfig(SecurityConfig),
|
||||||
SystemStatus(SystemStatus),
|
SystemStatus(SystemStatus),
|
||||||
@@ -526,7 +548,7 @@ serde_enum_from!(
|
|||||||
Movies(Vec<Movie>),
|
Movies(Vec<Movie>),
|
||||||
QualityProfiles(Vec<QualityProfile>),
|
QualityProfiles(Vec<QualityProfile>),
|
||||||
QueueEvents(Vec<QueueEvent>),
|
QueueEvents(Vec<QueueEvent>),
|
||||||
Releases(Vec<Release>),
|
Releases(Vec<RadarrRelease>),
|
||||||
RootFolders(Vec<RootFolder>),
|
RootFolders(Vec<RootFolder>),
|
||||||
SecurityConfig(SecurityConfig),
|
SecurityConfig(SecurityConfig),
|
||||||
SystemStatus(SystemStatus),
|
SystemStatus(SystemStatus),
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ mod tests {
|
|||||||
radarr_models::{
|
radarr_models::{
|
||||||
AddMovieSearchResult, BlocklistItem, BlocklistResponse, Collection, Credit, DiskSpace,
|
AddMovieSearchResult, BlocklistItem, BlocklistResponse, Collection, Credit, DiskSpace,
|
||||||
DownloadRecord, DownloadsResponse, Indexer, IndexerSettings, IndexerTestResult,
|
DownloadRecord, DownloadsResponse, Indexer, IndexerSettings, IndexerTestResult,
|
||||||
MinimumAvailability, Monitor, Movie, MovieHistoryItem, QualityProfile, RadarrSerdeable,
|
MinimumAvailability, Monitor, Movie, MovieHistoryItem, QualityProfile, RadarrRelease,
|
||||||
RadarrTask, RadarrTaskName, Release, SystemStatus, Tag, Update,
|
RadarrSerdeable, RadarrTask, RadarrTaskName, SystemStatus, Tag, Update,
|
||||||
},
|
},
|
||||||
servarr_models::{HostConfig, Log, LogResponse, QueueEvent, RootFolder, SecurityConfig},
|
servarr_models::{HostConfig, Log, LogResponse, QueueEvent, RootFolder, SecurityConfig},
|
||||||
EnumDisplayStyle, Serdeable,
|
EnumDisplayStyle, Serdeable,
|
||||||
@@ -317,9 +317,9 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_radarr_serdeable_from_releases() {
|
fn test_radarr_serdeable_from_releases() {
|
||||||
let releases = vec![Release {
|
let releases = vec![RadarrRelease {
|
||||||
size: 1,
|
size: 1,
|
||||||
..Release::default()
|
..RadarrRelease::default()
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let radarr_serdeable: RadarrSerdeable = releases.clone().into();
|
let radarr_serdeable: RadarrSerdeable = releases.clone().into();
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::models::radarr_models::{
|
use crate::models::radarr_models::{
|
||||||
Collection, Credit, MinimumAvailability, Monitor, Movie, MovieHistoryItem,
|
Collection, Credit, MinimumAvailability, Monitor, Movie, MovieHistoryItem, RadarrRelease,
|
||||||
};
|
};
|
||||||
use crate::models::servarr_data::radarr::radarr_data::RadarrData;
|
use crate::models::servarr_data::radarr::radarr_data::RadarrData;
|
||||||
use crate::models::servarr_models::{Indexer, Release, RootFolder};
|
use crate::models::servarr_models::{Indexer, RootFolder};
|
||||||
use crate::models::stateful_list::StatefulList;
|
use crate::models::stateful_list::StatefulList;
|
||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::models::{HorizontallyScrollableText, ScrollableText};
|
use crate::models::{HorizontallyScrollableText, ScrollableText};
|
||||||
@@ -22,7 +22,7 @@ pub struct MovieDetailsModal {
|
|||||||
pub movie_history: StatefulTable<MovieHistoryItem>,
|
pub movie_history: StatefulTable<MovieHistoryItem>,
|
||||||
pub movie_cast: StatefulTable<Credit>,
|
pub movie_cast: StatefulTable<Credit>,
|
||||||
pub movie_crew: StatefulTable<Credit>,
|
pub movie_crew: StatefulTable<Credit>,
|
||||||
pub movie_releases: StatefulTable<Release>,
|
pub movie_releases: StatefulTable<RadarrRelease>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, PartialEq, Eq)]
|
#[derive(Default, Debug, PartialEq, Eq)]
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod utils {
|
pub mod utils {
|
||||||
use crate::models::radarr_models::{
|
use crate::models::radarr_models::{
|
||||||
AddMovieSearchResult, CollectionMovie, Credit, MovieHistoryItem,
|
AddMovieSearchResult, CollectionMovie, Credit, MovieHistoryItem, RadarrRelease,
|
||||||
};
|
};
|
||||||
use crate::models::servarr_data::radarr::modals::MovieDetailsModal;
|
use crate::models::servarr_data::radarr::modals::MovieDetailsModal;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::RadarrData;
|
use crate::models::servarr_data::radarr::radarr_data::RadarrData;
|
||||||
use crate::models::servarr_models::Release;
|
|
||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::models::{HorizontallyScrollableText, ScrollableText};
|
use crate::models::{HorizontallyScrollableText, ScrollableText};
|
||||||
|
|
||||||
@@ -25,7 +24,7 @@ pub mod utils {
|
|||||||
.set_items(vec![Credit::default()]);
|
.set_items(vec![Credit::default()]);
|
||||||
movie_details_modal
|
movie_details_modal
|
||||||
.movie_releases
|
.movie_releases
|
||||||
.set_items(vec![Release::default()]);
|
.set_items(vec![RadarrRelease::default()]);
|
||||||
|
|
||||||
let mut radarr_data = RadarrData {
|
let mut radarr_data = RadarrData {
|
||||||
delete_movie_files: true,
|
delete_movie_files: true,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use crate::models::{
|
use crate::models::{
|
||||||
servarr_models::Release,
|
sonarr_models::{Episode, SonarrHistoryItem, SonarrRelease},
|
||||||
sonarr_models::{Episode, SonarrHistoryItem},
|
|
||||||
stateful_table::StatefulTable,
|
stateful_table::StatefulTable,
|
||||||
ScrollableText,
|
ScrollableText,
|
||||||
};
|
};
|
||||||
@@ -12,12 +11,12 @@ pub struct EpisodeDetailsModal {
|
|||||||
pub audio_details: String,
|
pub audio_details: String,
|
||||||
pub video_details: String,
|
pub video_details: String,
|
||||||
pub episode_history: StatefulTable<SonarrHistoryItem>,
|
pub episode_history: StatefulTable<SonarrHistoryItem>,
|
||||||
pub episode_releases: StatefulTable<Release>,
|
pub episode_releases: StatefulTable<SonarrRelease>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct SeasonDetailsModal {
|
pub struct SeasonDetailsModal {
|
||||||
pub episodes: StatefulTable<Episode>,
|
pub episodes: StatefulTable<Episode>,
|
||||||
pub episode_details_modal: Option<EpisodeDetailsModal>,
|
pub episode_details_modal: Option<EpisodeDetailsModal>,
|
||||||
pub season_releases: StatefulTable<Release>,
|
pub season_releases: StatefulTable<SonarrRelease>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,28 +195,6 @@ pub struct QueueEvent {
|
|||||||
pub duration: Option<String>,
|
pub duration: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
#[serde(default)]
|
|
||||||
pub struct Release {
|
|
||||||
pub guid: String,
|
|
||||||
pub protocol: String,
|
|
||||||
#[serde(deserialize_with = "super::from_i64")]
|
|
||||||
pub age: i64,
|
|
||||||
pub title: HorizontallyScrollableText,
|
|
||||||
pub indexer: String,
|
|
||||||
#[serde(deserialize_with = "super::from_i64")]
|
|
||||||
pub indexer_id: i64,
|
|
||||||
#[serde(deserialize_with = "super::from_i64")]
|
|
||||||
pub size: i64,
|
|
||||||
pub rejected: bool,
|
|
||||||
pub rejections: Option<Vec<String>>,
|
|
||||||
pub seeders: Option<Number>,
|
|
||||||
pub leechers: Option<Number>,
|
|
||||||
pub languages: Option<Vec<Language>>,
|
|
||||||
pub quality: QualityWrapper,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
#[derive(Default, Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct RootFolder {
|
pub struct RootFolder {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use super::{
|
|||||||
radarr_models::IndexerTestResult,
|
radarr_models::IndexerTestResult,
|
||||||
servarr_models::{
|
servarr_models::{
|
||||||
DiskSpace, HostConfig, Indexer, Language, LogResponse, QualityProfile, QualityWrapper,
|
DiskSpace, HostConfig, Indexer, Language, LogResponse, QualityProfile, QualityWrapper,
|
||||||
QueueEvent, Release, RootFolder, SecurityConfig, Tag, Update,
|
QueueEvent, RootFolder, SecurityConfig, Tag, Update,
|
||||||
},
|
},
|
||||||
EnumDisplayStyle, HorizontallyScrollableText, Serdeable,
|
EnumDisplayStyle, HorizontallyScrollableText, Serdeable,
|
||||||
};
|
};
|
||||||
@@ -401,6 +401,28 @@ pub struct SonarrCommandBody {
|
|||||||
pub episode_ids: Option<Vec<i64>>,
|
pub episode_ids: Option<Vec<i64>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub struct SonarrRelease {
|
||||||
|
pub guid: String,
|
||||||
|
pub protocol: String,
|
||||||
|
#[serde(deserialize_with = "super::from_i64")]
|
||||||
|
pub age: i64,
|
||||||
|
pub title: HorizontallyScrollableText,
|
||||||
|
pub indexer: String,
|
||||||
|
#[serde(deserialize_with = "super::from_i64")]
|
||||||
|
pub indexer_id: i64,
|
||||||
|
#[serde(deserialize_with = "super::from_i64")]
|
||||||
|
pub size: i64,
|
||||||
|
pub rejected: bool,
|
||||||
|
pub rejections: Option<Vec<String>>,
|
||||||
|
pub seeders: Option<Number>,
|
||||||
|
pub leechers: Option<Number>,
|
||||||
|
pub languages: Option<Vec<Language>>,
|
||||||
|
pub quality: QualityWrapper,
|
||||||
|
pub full_season: bool,
|
||||||
|
}
|
||||||
#[derive(Default, Serialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Default, Serialize, Debug, PartialEq, Eq, Clone)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct SonarrReleaseDownloadBody {
|
pub struct SonarrReleaseDownloadBody {
|
||||||
@@ -467,7 +489,7 @@ pub enum SonarrSerdeable {
|
|||||||
LogResponse(LogResponse),
|
LogResponse(LogResponse),
|
||||||
QualityProfiles(Vec<QualityProfile>),
|
QualityProfiles(Vec<QualityProfile>),
|
||||||
QueueEvents(Vec<QueueEvent>),
|
QueueEvents(Vec<QueueEvent>),
|
||||||
Releases(Vec<Release>),
|
Releases(Vec<SonarrRelease>),
|
||||||
RootFolders(Vec<RootFolder>),
|
RootFolders(Vec<RootFolder>),
|
||||||
SecurityConfig(SecurityConfig),
|
SecurityConfig(SecurityConfig),
|
||||||
SeriesVec(Vec<Series>),
|
SeriesVec(Vec<Series>),
|
||||||
@@ -508,7 +530,7 @@ serde_enum_from!(
|
|||||||
LogResponse(LogResponse),
|
LogResponse(LogResponse),
|
||||||
QualityProfiles(Vec<QualityProfile>),
|
QualityProfiles(Vec<QualityProfile>),
|
||||||
QueueEvents(Vec<QueueEvent>),
|
QueueEvents(Vec<QueueEvent>),
|
||||||
Releases(Vec<Release>),
|
Releases(Vec<SonarrRelease>),
|
||||||
RootFolders(Vec<RootFolder>),
|
RootFolders(Vec<RootFolder>),
|
||||||
SecurityConfig(SecurityConfig),
|
SecurityConfig(SecurityConfig),
|
||||||
SeriesVec(Vec<Series>),
|
SeriesVec(Vec<Series>),
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ mod tests {
|
|||||||
use crate::models::{
|
use crate::models::{
|
||||||
radarr_models::IndexerTestResult,
|
radarr_models::IndexerTestResult,
|
||||||
servarr_models::{
|
servarr_models::{
|
||||||
DiskSpace, HostConfig, Indexer, Log, LogResponse, QualityProfile, QueueEvent, Release,
|
DiskSpace, HostConfig, Indexer, Log, LogResponse, QualityProfile, QueueEvent, RootFolder,
|
||||||
RootFolder, SecurityConfig, Tag, Update,
|
SecurityConfig, Tag, Update,
|
||||||
},
|
},
|
||||||
sonarr_models::{
|
sonarr_models::{
|
||||||
BlocklistItem, BlocklistResponse, DownloadRecord, DownloadsResponse, Episode,
|
BlocklistItem, BlocklistResponse, DownloadRecord, DownloadsResponse, Episode,
|
||||||
IndexerSettings, Series, SeriesStatus, SeriesType, SonarrHistoryEventType, SonarrHistoryItem,
|
IndexerSettings, Series, SeriesStatus, SeriesType, SonarrHistoryEventType, SonarrHistoryItem,
|
||||||
SonarrSerdeable, SonarrTask, SonarrTaskName, SystemStatus,
|
SonarrRelease, SonarrSerdeable, SonarrTask, SonarrTaskName, SystemStatus,
|
||||||
},
|
},
|
||||||
EnumDisplayStyle, Serdeable,
|
EnumDisplayStyle, Serdeable,
|
||||||
};
|
};
|
||||||
@@ -355,9 +355,9 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sonarr_serdeable_from_releases() {
|
fn test_sonarr_serdeable_from_releases() {
|
||||||
let releases = vec![Release {
|
let releases = vec![SonarrRelease {
|
||||||
size: 1,
|
size: 1,
|
||||||
..Release::default()
|
..SonarrRelease::default()
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let sonarr_serdeable: SonarrSerdeable = releases.clone().into();
|
let sonarr_serdeable: SonarrSerdeable = releases.clone().into();
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ use crate::models::radarr_models::{
|
|||||||
AddMovieBody, AddMovieSearchResult, AddOptions, BlocklistResponse, Collection, CollectionMovie,
|
AddMovieBody, AddMovieSearchResult, AddOptions, BlocklistResponse, Collection, CollectionMovie,
|
||||||
Credit, CreditType, DeleteMovieParams, DownloadRecord, DownloadsResponse, EditCollectionParams,
|
Credit, CreditType, DeleteMovieParams, DownloadRecord, DownloadsResponse, EditCollectionParams,
|
||||||
EditIndexerParams, EditMovieParams, IndexerSettings, IndexerTestResult, Movie, MovieCommandBody,
|
EditIndexerParams, EditMovieParams, IndexerSettings, IndexerTestResult, Movie, MovieCommandBody,
|
||||||
MovieHistoryItem, RadarrReleaseDownloadBody, RadarrSerdeable, RadarrTask, RadarrTaskName,
|
MovieHistoryItem, RadarrRelease, RadarrReleaseDownloadBody, RadarrSerdeable, RadarrTask,
|
||||||
SystemStatus,
|
RadarrTaskName, SystemStatus,
|
||||||
};
|
};
|
||||||
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
||||||
use crate::models::servarr_data::radarr::modals::{
|
use crate::models::servarr_data::radarr::modals::{
|
||||||
@@ -20,7 +20,7 @@ use crate::models::servarr_data::radarr::modals::{
|
|||||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||||
use crate::models::servarr_models::{
|
use crate::models::servarr_models::{
|
||||||
AddRootFolderBody, CommandBody, DiskSpace, HostConfig, Indexer, LogResponse, QualityProfile,
|
AddRootFolderBody, CommandBody, DiskSpace, HostConfig, Indexer, LogResponse, QualityProfile,
|
||||||
QueueEvent, Release, RootFolder, SecurityConfig, Tag, Update,
|
QueueEvent, RootFolder, SecurityConfig, Tag, Update,
|
||||||
};
|
};
|
||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::models::{HorizontallyScrollableText, Route, Scrollable, ScrollableText};
|
use crate::models::{HorizontallyScrollableText, Route, Scrollable, ScrollableText};
|
||||||
@@ -675,7 +675,7 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
let (movie_id, _) = self.extract_movie_id(None).await;
|
let (movie_id, _) = self.extract_movie_id(None).await;
|
||||||
let (guid, title, indexer_id) = {
|
let (guid, title, indexer_id) = {
|
||||||
let app = self.app.lock().await;
|
let app = self.app.lock().await;
|
||||||
let Release {
|
let RadarrRelease {
|
||||||
guid,
|
guid,
|
||||||
title,
|
title,
|
||||||
indexer_id,
|
indexer_id,
|
||||||
@@ -1770,7 +1770,7 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_movie_releases(&mut self, movie_id: Option<i64>) -> Result<Vec<Release>> {
|
async fn get_movie_releases(&mut self, movie_id: Option<i64>) -> Result<Vec<RadarrRelease>> {
|
||||||
let (id, movie_id_param) = self.extract_movie_id(movie_id).await;
|
let (id, movie_id_param) = self.extract_movie_id(movie_id).await;
|
||||||
info!("Fetching releases for movie with ID: {id}");
|
info!("Fetching releases for movie with ID: {id}");
|
||||||
let event = RadarrEvent::GetReleases(None);
|
let event = RadarrEvent::GetReleases(None);
|
||||||
@@ -1786,7 +1786,7 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
self
|
self
|
||||||
.handle_request::<(), Vec<Release>>(request_props, |release_vec, mut app| {
|
.handle_request::<(), Vec<RadarrRelease>>(request_props, |release_vec, mut app| {
|
||||||
if app.data.radarr_data.movie_details_modal.is_none() {
|
if app.data.radarr_data.movie_details_modal.is_none() {
|
||||||
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal::default());
|
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal::default());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5221,8 +5221,8 @@ mod test {
|
|||||||
QualityWrapper { quality: quality() }
|
QualityWrapper { quality: quality() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release() -> Release {
|
fn release() -> RadarrRelease {
|
||||||
Release {
|
RadarrRelease {
|
||||||
guid: "1234".to_owned(),
|
guid: "1234".to_owned(),
|
||||||
protocol: "torrent".to_owned(),
|
protocol: "torrent".to_owned(),
|
||||||
age: 1,
|
age: 1,
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ use crate::{
|
|||||||
},
|
},
|
||||||
servarr_models::{
|
servarr_models::{
|
||||||
AddRootFolderBody, CommandBody, DiskSpace, HostConfig, Indexer, LogResponse, QualityProfile,
|
AddRootFolderBody, CommandBody, DiskSpace, HostConfig, Indexer, LogResponse, QualityProfile,
|
||||||
QueueEvent, Release, RootFolder, SecurityConfig, Tag, Update,
|
QueueEvent, RootFolder, SecurityConfig, Tag, Update,
|
||||||
},
|
},
|
||||||
sonarr_models::{
|
sonarr_models::{
|
||||||
BlocklistResponse, DownloadRecord, DownloadsResponse, Episode, IndexerSettings, Series,
|
BlocklistResponse, DownloadRecord, DownloadsResponse, Episode, IndexerSettings, Series,
|
||||||
SonarrCommandBody, SonarrHistoryItem, SonarrHistoryWrapper, SonarrReleaseDownloadBody,
|
SonarrCommandBody, SonarrHistoryItem, SonarrHistoryWrapper, SonarrRelease,
|
||||||
SonarrSerdeable, SonarrTask, SonarrTaskName, SystemStatus,
|
SonarrReleaseDownloadBody, SonarrSerdeable, SonarrTask, SonarrTaskName, SystemStatus,
|
||||||
},
|
},
|
||||||
stateful_table::StatefulTable,
|
stateful_table::StatefulTable,
|
||||||
HorizontallyScrollableText, Route, Scrollable, ScrollableText,
|
HorizontallyScrollableText, Route, Scrollable, ScrollableText,
|
||||||
@@ -1009,7 +1009,7 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_episode_releases(&mut self, episode_id: Option<i64>) -> Result<Vec<Release>> {
|
async fn get_episode_releases(&mut self, episode_id: Option<i64>) -> Result<Vec<SonarrRelease>> {
|
||||||
let event = SonarrEvent::GetEpisodeReleases(None);
|
let event = SonarrEvent::GetEpisodeReleases(None);
|
||||||
let id = self.extract_episode_id(episode_id).await;
|
let id = self.extract_episode_id(episode_id).await;
|
||||||
|
|
||||||
@@ -1026,7 +1026,7 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
self
|
self
|
||||||
.handle_request::<(), Vec<Release>>(request_props, |release_vec, mut app| {
|
.handle_request::<(), Vec<SonarrRelease>>(request_props, |release_vec, mut app| {
|
||||||
if app.data.sonarr_data.season_details_modal.is_none() {
|
if app.data.sonarr_data.season_details_modal.is_none() {
|
||||||
app.data.sonarr_data.season_details_modal = Some(SeasonDetailsModal::default());
|
app.data.sonarr_data.season_details_modal = Some(SeasonDetailsModal::default());
|
||||||
}
|
}
|
||||||
@@ -1067,7 +1067,7 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
async fn get_season_releases(
|
async fn get_season_releases(
|
||||||
&mut self,
|
&mut self,
|
||||||
series_season_id_tuple: Option<(i64, i64)>,
|
series_season_id_tuple: Option<(i64, i64)>,
|
||||||
) -> Result<Vec<Release>> {
|
) -> Result<Vec<SonarrRelease>> {
|
||||||
let event = SonarrEvent::GetSeasonReleases(None);
|
let event = SonarrEvent::GetSeasonReleases(None);
|
||||||
let (series_id, season_number) =
|
let (series_id, season_number) =
|
||||||
if let Some((series_id, season_number)) = series_season_id_tuple {
|
if let Some((series_id, season_number)) = series_season_id_tuple {
|
||||||
@@ -1092,11 +1092,16 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
self
|
self
|
||||||
.handle_request::<(), Vec<Release>>(request_props, |release_vec, mut app| {
|
.handle_request::<(), Vec<SonarrRelease>>(request_props, |release_vec, mut app| {
|
||||||
if app.data.sonarr_data.season_details_modal.is_none() {
|
if app.data.sonarr_data.season_details_modal.is_none() {
|
||||||
app.data.sonarr_data.season_details_modal = Some(SeasonDetailsModal::default());
|
app.data.sonarr_data.season_details_modal = Some(SeasonDetailsModal::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let season_releases_vec = release_vec
|
||||||
|
.into_iter()
|
||||||
|
.filter(|release| release.full_season)
|
||||||
|
.collect();
|
||||||
|
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.sonarr_data
|
.sonarr_data
|
||||||
@@ -1104,7 +1109,7 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.season_releases
|
.season_releases
|
||||||
.set_items(release_vec);
|
.set_items(season_releases_vec);
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ mod test {
|
|||||||
use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
|
use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
|
||||||
use crate::models::servarr_models::{
|
use crate::models::servarr_models::{
|
||||||
DiskSpace, HostConfig, Indexer, IndexerField, Language, LogResponse, Quality, QualityProfile,
|
DiskSpace, HostConfig, Indexer, IndexerField, Language, LogResponse, Quality, QualityProfile,
|
||||||
QualityWrapper, QueueEvent, Release, RootFolder, SecurityConfig, Tag, Update,
|
QualityWrapper, QueueEvent, RootFolder, SecurityConfig, Tag, Update,
|
||||||
};
|
};
|
||||||
use crate::models::sonarr_models::{
|
use crate::models::sonarr_models::{
|
||||||
BlocklistItem, DownloadRecord, DownloadsResponse, Episode, EpisodeFile, MediaInfo,
|
BlocklistItem, DownloadRecord, DownloadsResponse, Episode, EpisodeFile, MediaInfo,
|
||||||
SonarrReleaseDownloadBody, SonarrTaskName,
|
SonarrRelease, SonarrReleaseDownloadBody, SonarrTaskName,
|
||||||
};
|
};
|
||||||
use crate::models::sonarr_models::{
|
use crate::models::sonarr_models::{
|
||||||
BlocklistResponse, SonarrHistoryData, SonarrHistoryItem, SonarrHistoryWrapper,
|
BlocklistResponse, SonarrHistoryData, SonarrHistoryItem, SonarrHistoryWrapper,
|
||||||
@@ -612,7 +612,7 @@ mod test {
|
|||||||
Some(json!({
|
Some(json!({
|
||||||
"guid": "1234",
|
"guid": "1234",
|
||||||
"indexerId": 2,
|
"indexerId": 2,
|
||||||
"seriesId": 1
|
"seriesId": 1,
|
||||||
})),
|
})),
|
||||||
Some(json!({})),
|
Some(json!({})),
|
||||||
None,
|
None,
|
||||||
@@ -2712,7 +2712,8 @@ mod test {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_get_season_releases_event() {
|
async fn test_handle_get_season_releases_event() {
|
||||||
let release_json = json!([{
|
let release_json = json!([
|
||||||
|
{
|
||||||
"guid": "1234",
|
"guid": "1234",
|
||||||
"protocol": "torrent",
|
"protocol": "torrent",
|
||||||
"age": 1,
|
"age": 1,
|
||||||
@@ -2725,8 +2726,39 @@ mod test {
|
|||||||
"seeders": 2,
|
"seeders": 2,
|
||||||
"leechers": 1,
|
"leechers": 1,
|
||||||
"languages": [ { "name": "English" } ],
|
"languages": [ { "name": "English" } ],
|
||||||
"quality": { "quality": { "name": "Bluray-1080p" }}
|
"quality": { "quality": { "name": "Bluray-1080p" }},
|
||||||
}]);
|
"fullSeason": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"guid": "4567",
|
||||||
|
"protocol": "torrent",
|
||||||
|
"age": 1,
|
||||||
|
"title": "Test Release",
|
||||||
|
"indexer": "kickass torrents",
|
||||||
|
"indexerId": 2,
|
||||||
|
"size": 1234,
|
||||||
|
"rejected": true,
|
||||||
|
"rejections": [ "Unknown quality profile", "Release is already mapped" ],
|
||||||
|
"seeders": 2,
|
||||||
|
"leechers": 1,
|
||||||
|
"languages": [ { "name": "English" } ],
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" }},
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
let expected_filtered_sonarr_release = SonarrRelease {
|
||||||
|
full_season: true,
|
||||||
|
..release()
|
||||||
|
};
|
||||||
|
let expected_raw_sonarr_releases = vec![
|
||||||
|
SonarrRelease {
|
||||||
|
full_season: true,
|
||||||
|
..release()
|
||||||
|
},
|
||||||
|
SonarrRelease {
|
||||||
|
guid: "4567".to_owned(),
|
||||||
|
..release()
|
||||||
|
},
|
||||||
|
];
|
||||||
let (async_server, app_arc, _server) = mock_servarr_api(
|
let (async_server, app_arc, _server) = mock_servarr_api(
|
||||||
RequestMethod::Get,
|
RequestMethod::Get,
|
||||||
None,
|
None,
|
||||||
@@ -2772,15 +2804,16 @@ mod test {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.season_releases
|
.season_releases
|
||||||
.items,
|
.items,
|
||||||
vec![release()]
|
vec![expected_filtered_sonarr_release]
|
||||||
);
|
);
|
||||||
assert_eq!(releases_vec, vec![release()]);
|
assert_eq!(releases_vec, expected_raw_sonarr_releases);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_get_season_releases_event_empty_season_details_modal() {
|
async fn test_handle_get_season_releases_event_empty_season_details_modal() {
|
||||||
let release_json = json!([{
|
let release_json = json!([
|
||||||
|
{
|
||||||
"guid": "1234",
|
"guid": "1234",
|
||||||
"protocol": "torrent",
|
"protocol": "torrent",
|
||||||
"age": 1,
|
"age": 1,
|
||||||
@@ -2793,8 +2826,29 @@ mod test {
|
|||||||
"seeders": 2,
|
"seeders": 2,
|
||||||
"leechers": 1,
|
"leechers": 1,
|
||||||
"languages": [ { "name": "English" } ],
|
"languages": [ { "name": "English" } ],
|
||||||
"quality": { "quality": { "name": "Bluray-1080p" }}
|
"quality": { "quality": { "name": "Bluray-1080p" }},
|
||||||
}]);
|
"fullSeason": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"guid": "4567",
|
||||||
|
"protocol": "usenet",
|
||||||
|
"age": 1,
|
||||||
|
"title": "Test Release",
|
||||||
|
"indexer": "kickass torrents",
|
||||||
|
"indexerId": 2,
|
||||||
|
"size": 1234,
|
||||||
|
"rejected": true,
|
||||||
|
"rejections": [ "Unknown quality profile", "Release is already mapped" ],
|
||||||
|
"seeders": 2,
|
||||||
|
"leechers": 1,
|
||||||
|
"languages": [ { "name": "English" } ],
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" }},
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
let expected_sonarr_release = SonarrRelease {
|
||||||
|
full_season: true,
|
||||||
|
..release()
|
||||||
|
};
|
||||||
let (async_server, app_arc, _server) = mock_servarr_api(
|
let (async_server, app_arc, _server) = mock_servarr_api(
|
||||||
RequestMethod::Get,
|
RequestMethod::Get,
|
||||||
None,
|
None,
|
||||||
@@ -2838,13 +2892,14 @@ mod test {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.season_releases
|
.season_releases
|
||||||
.items,
|
.items,
|
||||||
vec![release()]
|
vec![expected_sonarr_release]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_get_season_releases_event_uses_provided_series_id_and_season_number() {
|
async fn test_handle_get_season_releases_event_uses_provided_series_id_and_season_number() {
|
||||||
let release_json = json!([{
|
let release_json = json!([
|
||||||
|
{
|
||||||
"guid": "1234",
|
"guid": "1234",
|
||||||
"protocol": "torrent",
|
"protocol": "torrent",
|
||||||
"age": 1,
|
"age": 1,
|
||||||
@@ -2857,8 +2912,39 @@ mod test {
|
|||||||
"seeders": 2,
|
"seeders": 2,
|
||||||
"leechers": 1,
|
"leechers": 1,
|
||||||
"languages": [ { "name": "English" } ],
|
"languages": [ { "name": "English" } ],
|
||||||
"quality": { "quality": { "name": "Bluray-1080p" }}
|
"quality": { "quality": { "name": "Bluray-1080p" }},
|
||||||
}]);
|
"fullSeason": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"guid": "4567",
|
||||||
|
"protocol": "torrent",
|
||||||
|
"age": 1,
|
||||||
|
"title": "Test Release",
|
||||||
|
"indexer": "kickass torrents",
|
||||||
|
"indexerId": 2,
|
||||||
|
"size": 1234,
|
||||||
|
"rejected": true,
|
||||||
|
"rejections": [ "Unknown quality profile", "Release is already mapped" ],
|
||||||
|
"seeders": 2,
|
||||||
|
"leechers": 1,
|
||||||
|
"languages": [ { "name": "English" } ],
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" }},
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
let expected_filtered_sonarr_release = SonarrRelease {
|
||||||
|
full_season: true,
|
||||||
|
..release()
|
||||||
|
};
|
||||||
|
let expected_raw_sonarr_releases = vec![
|
||||||
|
SonarrRelease {
|
||||||
|
full_season: true,
|
||||||
|
..release()
|
||||||
|
},
|
||||||
|
SonarrRelease {
|
||||||
|
guid: "4567".to_owned(),
|
||||||
|
..release()
|
||||||
|
},
|
||||||
|
];
|
||||||
let (async_server, app_arc, _server) = mock_servarr_api(
|
let (async_server, app_arc, _server) = mock_servarr_api(
|
||||||
RequestMethod::Get,
|
RequestMethod::Get,
|
||||||
None,
|
None,
|
||||||
@@ -2904,15 +2990,16 @@ mod test {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.season_releases
|
.season_releases
|
||||||
.items,
|
.items,
|
||||||
vec![release()]
|
vec![expected_filtered_sonarr_release]
|
||||||
);
|
);
|
||||||
assert_eq!(releases_vec, vec![release()]);
|
assert_eq!(releases_vec, expected_raw_sonarr_releases);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_get_season_releases_event_filtered_series_and_filtered_seasons() {
|
async fn test_handle_get_season_releases_event_filtered_series_and_filtered_seasons() {
|
||||||
let release_json = json!([{
|
let release_json = json!([
|
||||||
|
{
|
||||||
"guid": "1234",
|
"guid": "1234",
|
||||||
"protocol": "torrent",
|
"protocol": "torrent",
|
||||||
"age": 1,
|
"age": 1,
|
||||||
@@ -2925,8 +3012,39 @@ mod test {
|
|||||||
"seeders": 2,
|
"seeders": 2,
|
||||||
"leechers": 1,
|
"leechers": 1,
|
||||||
"languages": [ { "name": "English" } ],
|
"languages": [ { "name": "English" } ],
|
||||||
"quality": { "quality": { "name": "Bluray-1080p" }}
|
"quality": { "quality": { "name": "Bluray-1080p" }},
|
||||||
}]);
|
"fullSeason": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"guid": "4567",
|
||||||
|
"protocol": "torrent",
|
||||||
|
"age": 1,
|
||||||
|
"title": "Test Release",
|
||||||
|
"indexer": "kickass torrents",
|
||||||
|
"indexerId": 2,
|
||||||
|
"size": 1234,
|
||||||
|
"rejected": true,
|
||||||
|
"rejections": [ "Unknown quality profile", "Release is already mapped" ],
|
||||||
|
"seeders": 2,
|
||||||
|
"leechers": 1,
|
||||||
|
"languages": [ { "name": "English" } ],
|
||||||
|
"quality": { "quality": { "name": "Bluray-1080p" }},
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
let expected_filtered_sonarr_release = SonarrRelease {
|
||||||
|
full_season: true,
|
||||||
|
..release()
|
||||||
|
};
|
||||||
|
let expected_raw_sonarr_releases = vec![
|
||||||
|
SonarrRelease {
|
||||||
|
full_season: true,
|
||||||
|
..release()
|
||||||
|
},
|
||||||
|
SonarrRelease {
|
||||||
|
guid: "4567".to_owned(),
|
||||||
|
..release()
|
||||||
|
},
|
||||||
|
];
|
||||||
let (async_server, app_arc, _server) = mock_servarr_api(
|
let (async_server, app_arc, _server) = mock_servarr_api(
|
||||||
RequestMethod::Get,
|
RequestMethod::Get,
|
||||||
None,
|
None,
|
||||||
@@ -2970,9 +3088,9 @@ mod test {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.season_releases
|
.season_releases
|
||||||
.items,
|
.items,
|
||||||
vec![release()]
|
vec![expected_filtered_sonarr_release]
|
||||||
);
|
);
|
||||||
assert_eq!(releases_vec, vec![release()]);
|
assert_eq!(releases_vec, expected_raw_sonarr_releases);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5097,8 +5215,8 @@ mod test {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release() -> Release {
|
fn release() -> SonarrRelease {
|
||||||
Release {
|
SonarrRelease {
|
||||||
guid: "1234".to_owned(),
|
guid: "1234".to_owned(),
|
||||||
protocol: "torrent".to_owned(),
|
protocol: "torrent".to_owned(),
|
||||||
age: 1,
|
age: 1,
|
||||||
@@ -5112,6 +5230,7 @@ mod test {
|
|||||||
leechers: Some(Number::from(1)),
|
leechers: Some(Number::from(1)),
|
||||||
languages: Some(vec![language()]),
|
languages: Some(vec![language()]),
|
||||||
quality: quality_wrapper(),
|
quality: quality_wrapper(),
|
||||||
|
full_season: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,9 @@ use ratatui::widgets::{Cell, Paragraph, Row, Wrap};
|
|||||||
use ratatui::Frame;
|
use ratatui::Frame;
|
||||||
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::models::radarr_models::{Credit, MovieHistoryItem};
|
use crate::models::radarr_models::{Credit, MovieHistoryItem, RadarrRelease};
|
||||||
use crate::models::servarr_data::radarr::modals::MovieDetailsModal;
|
use crate::models::servarr_data::radarr::modals::MovieDetailsModal;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, MOVIE_DETAILS_BLOCKS};
|
||||||
use crate::models::servarr_models::Release;
|
|
||||||
use crate::models::Route;
|
use crate::models::Route;
|
||||||
use crate::ui::radarr_ui::library::draw_library;
|
use crate::ui::radarr_ui::library::draw_library;
|
||||||
use crate::ui::styles::ManagarrStyle;
|
use crate::ui::styles::ManagarrStyle;
|
||||||
@@ -381,7 +380,7 @@ fn draw_movie_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.clone(),
|
.clone(),
|
||||||
movie_details_modal.movie_releases.items.is_empty(),
|
movie_details_modal.movie_releases.items.is_empty(),
|
||||||
),
|
),
|
||||||
_ => (Release::default(), true),
|
_ => (RadarrRelease::default(), true),
|
||||||
};
|
};
|
||||||
let current_route = *app.get_current_route();
|
let current_route = *app.get_current_route();
|
||||||
let mut default_movie_details_modal = MovieDetailsModal::default();
|
let mut default_movie_details_modal = MovieDetailsModal::default();
|
||||||
@@ -399,8 +398,8 @@ fn draw_movie_releases(f: &mut Frame<'_>, app: &mut App<'_>, area: Rect) {
|
|||||||
.unwrap_or(&mut default_movie_details_modal)
|
.unwrap_or(&mut default_movie_details_modal)
|
||||||
.movie_releases,
|
.movie_releases,
|
||||||
);
|
);
|
||||||
let releases_row_mapping = |release: &Release| {
|
let releases_row_mapping = |release: &RadarrRelease| {
|
||||||
let Release {
|
let RadarrRelease {
|
||||||
protocol,
|
protocol,
|
||||||
age,
|
age,
|
||||||
title,
|
title,
|
||||||
|
|||||||
Reference in New Issue
Block a user