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:
2024-11-23 12:15:41 -07:00
parent 3be9321df6
commit 4d92c350de
17 changed files with 336 additions and 174 deletions
+6 -6
View File
@@ -10,8 +10,8 @@ use crate::models::radarr_models::{
AddMovieBody, AddMovieSearchResult, AddOptions, BlocklistResponse, Collection, CollectionMovie,
Credit, CreditType, DeleteMovieParams, DownloadRecord, DownloadsResponse, EditCollectionParams,
EditIndexerParams, EditMovieParams, IndexerSettings, IndexerTestResult, Movie, MovieCommandBody,
MovieHistoryItem, RadarrReleaseDownloadBody, RadarrSerdeable, RadarrTask, RadarrTaskName,
SystemStatus,
MovieHistoryItem, RadarrRelease, RadarrReleaseDownloadBody, RadarrSerdeable, RadarrTask,
RadarrTaskName, SystemStatus,
};
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
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_models::{
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::{HorizontallyScrollableText, Route, Scrollable, ScrollableText};
@@ -675,7 +675,7 @@ impl<'a, 'b> Network<'a, 'b> {
let (movie_id, _) = self.extract_movie_id(None).await;
let (guid, title, indexer_id) = {
let app = self.app.lock().await;
let Release {
let RadarrRelease {
guid,
title,
indexer_id,
@@ -1770,7 +1770,7 @@ impl<'a, 'b> Network<'a, 'b> {
.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;
info!("Fetching releases for movie with ID: {id}");
let event = RadarrEvent::GetReleases(None);
@@ -1786,7 +1786,7 @@ impl<'a, 'b> Network<'a, 'b> {
.await;
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() {
app.data.radarr_data.movie_details_modal = Some(MovieDetailsModal::default());
}
+2 -2
View File
@@ -5221,8 +5221,8 @@ mod test {
QualityWrapper { quality: quality() }
}
fn release() -> Release {
Release {
fn release() -> RadarrRelease {
RadarrRelease {
guid: "1234".to_owned(),
protocol: "torrent".to_owned(),
age: 1,
+13 -8
View File
@@ -15,12 +15,12 @@ use crate::{
},
servarr_models::{
AddRootFolderBody, CommandBody, DiskSpace, HostConfig, Indexer, LogResponse, QualityProfile,
QueueEvent, Release, RootFolder, SecurityConfig, Tag, Update,
QueueEvent, RootFolder, SecurityConfig, Tag, Update,
},
sonarr_models::{
BlocklistResponse, DownloadRecord, DownloadsResponse, Episode, IndexerSettings, Series,
SonarrCommandBody, SonarrHistoryItem, SonarrHistoryWrapper, SonarrReleaseDownloadBody,
SonarrSerdeable, SonarrTask, SonarrTaskName, SystemStatus,
SonarrCommandBody, SonarrHistoryItem, SonarrHistoryWrapper, SonarrRelease,
SonarrReleaseDownloadBody, SonarrSerdeable, SonarrTask, SonarrTaskName, SystemStatus,
},
stateful_table::StatefulTable,
HorizontallyScrollableText, Route, Scrollable, ScrollableText,
@@ -1009,7 +1009,7 @@ impl<'a, 'b> Network<'a, 'b> {
.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 id = self.extract_episode_id(episode_id).await;
@@ -1026,7 +1026,7 @@ impl<'a, 'b> Network<'a, 'b> {
.await;
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() {
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(
&mut self,
series_season_id_tuple: Option<(i64, i64)>,
) -> Result<Vec<Release>> {
) -> Result<Vec<SonarrRelease>> {
let event = SonarrEvent::GetSeasonReleases(None);
let (series_id, season_number) =
if let Some((series_id, season_number)) = series_season_id_tuple {
@@ -1092,11 +1092,16 @@ impl<'a, 'b> Network<'a, 'b> {
.await;
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() {
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
.data
.sonarr_data
@@ -1104,7 +1109,7 @@ impl<'a, 'b> Network<'a, 'b> {
.as_mut()
.unwrap()
.season_releases
.set_items(release_vec);
.set_items(season_releases_vec);
})
.await
}
+191 -72
View File
@@ -21,11 +21,11 @@ mod test {
use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
use crate::models::servarr_models::{
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::{
BlocklistItem, DownloadRecord, DownloadsResponse, Episode, EpisodeFile, MediaInfo,
SonarrReleaseDownloadBody, SonarrTaskName,
SonarrRelease, SonarrReleaseDownloadBody, SonarrTaskName,
};
use crate::models::sonarr_models::{
BlocklistResponse, SonarrHistoryData, SonarrHistoryItem, SonarrHistoryWrapper,
@@ -612,7 +612,7 @@ mod test {
Some(json!({
"guid": "1234",
"indexerId": 2,
"seriesId": 1
"seriesId": 1,
})),
Some(json!({})),
None,
@@ -2712,21 +2712,53 @@ mod test {
#[tokio::test]
async fn test_handle_get_season_releases_event() {
let release_json = json!([{
"guid": "1234",
"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 release_json = json!([
{
"guid": "1234",
"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" }},
"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(
RequestMethod::Get,
None,
@@ -2772,29 +2804,51 @@ mod test {
.unwrap()
.season_releases
.items,
vec![release()]
vec![expected_filtered_sonarr_release]
);
assert_eq!(releases_vec, vec![release()]);
assert_eq!(releases_vec, expected_raw_sonarr_releases);
}
}
#[tokio::test]
async fn test_handle_get_season_releases_event_empty_season_details_modal() {
let release_json = json!([{
"guid": "1234",
"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 release_json = json!([
{
"guid": "1234",
"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" }},
"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(
RequestMethod::Get,
None,
@@ -2838,27 +2892,59 @@ mod test {
.unwrap()
.season_releases
.items,
vec![release()]
vec![expected_sonarr_release]
);
}
#[tokio::test]
async fn test_handle_get_season_releases_event_uses_provided_series_id_and_season_number() {
let release_json = json!([{
"guid": "1234",
"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 release_json = json!([
{
"guid": "1234",
"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" }},
"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(
RequestMethod::Get,
None,
@@ -2904,29 +2990,61 @@ mod test {
.unwrap()
.season_releases
.items,
vec![release()]
vec![expected_filtered_sonarr_release]
);
assert_eq!(releases_vec, vec![release()]);
assert_eq!(releases_vec, expected_raw_sonarr_releases);
}
}
#[tokio::test]
async fn test_handle_get_season_releases_event_filtered_series_and_filtered_seasons() {
let release_json = json!([{
"guid": "1234",
"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 release_json = json!([
{
"guid": "1234",
"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" }},
"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(
RequestMethod::Get,
None,
@@ -2970,9 +3088,9 @@ mod test {
.unwrap()
.season_releases
.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 {
Release {
fn release() -> SonarrRelease {
SonarrRelease {
guid: "1234".to_owned(),
protocol: "torrent".to_owned(),
age: 1,
@@ -5112,6 +5230,7 @@ mod test {
leechers: Some(Number::from(1)),
languages: Some(vec![language()]),
quality: quality_wrapper(),
full_season: false,
}
}