testing
This commit is contained in:
@@ -3,7 +3,7 @@ use log::{debug, info, warn};
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use crate::models::Route;
|
||||
use crate::models::lidarr_models::{Artist, DeleteArtistParams};
|
||||
use crate::models::lidarr_models::{Artist, DeleteArtistParams, EditArtistParams};
|
||||
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
|
||||
use crate::models::servarr_models::CommandBody;
|
||||
use crate::network::lidarr_network::LidarrEvent;
|
||||
@@ -168,4 +168,119 @@ impl Network<'_, '_> {
|
||||
.handle_request::<CommandBody, Value>(request_props, |_, _| ())
|
||||
.await
|
||||
}
|
||||
|
||||
pub(in crate::network::lidarr_network) async fn edit_artist(
|
||||
&mut self,
|
||||
mut edit_artist_params: EditArtistParams,
|
||||
) -> Result<()> {
|
||||
info!("Editing Lidarr artist");
|
||||
if let Some(tag_input_str) = edit_artist_params.tag_input_string.as_ref() {
|
||||
let tag_ids_vec = self.extract_and_add_lidarr_tag_ids_vec(tag_input_str).await;
|
||||
edit_artist_params.tags = Some(tag_ids_vec);
|
||||
}
|
||||
let artist_id = edit_artist_params.artist_id;
|
||||
let detail_event = LidarrEvent::GetArtistDetails(artist_id);
|
||||
let event = LidarrEvent::EditArtist(EditArtistParams::default());
|
||||
info!("Fetching artist details for artist with ID: {artist_id}");
|
||||
|
||||
let request_props = self
|
||||
.request_props_from(
|
||||
detail_event,
|
||||
RequestMethod::Get,
|
||||
None::<()>,
|
||||
Some(format!("/{artist_id}")),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut response = String::new();
|
||||
|
||||
self
|
||||
.handle_request::<(), Value>(request_props, |detailed_artist_body, _| {
|
||||
response = detailed_artist_body.to_string()
|
||||
})
|
||||
.await?;
|
||||
|
||||
info!("Constructing edit artist body");
|
||||
|
||||
let mut detailed_artist_body: Value = serde_json::from_str(&response)?;
|
||||
let (
|
||||
monitored,
|
||||
monitor_new_items,
|
||||
quality_profile_id,
|
||||
metadata_profile_id,
|
||||
root_folder_path,
|
||||
tags,
|
||||
) = {
|
||||
let monitored = edit_artist_params.monitored.unwrap_or(
|
||||
detailed_artist_body["monitored"]
|
||||
.as_bool()
|
||||
.expect("Unable to deserialize 'monitored'"),
|
||||
);
|
||||
let monitor_new_items = edit_artist_params.monitor_new_items.unwrap_or_else(|| {
|
||||
serde_json::from_value(detailed_artist_body["monitorNewItems"].clone())
|
||||
.expect("Unable to deserialize 'monitorNewItems'")
|
||||
});
|
||||
let quality_profile_id = edit_artist_params.quality_profile_id.unwrap_or_else(|| {
|
||||
detailed_artist_body["qualityProfileId"]
|
||||
.as_i64()
|
||||
.expect("Unable to deserialize 'qualityProfileId'")
|
||||
});
|
||||
let metadata_profile_id = edit_artist_params.metadata_profile_id.unwrap_or_else(|| {
|
||||
detailed_artist_body["metadataProfileId"]
|
||||
.as_i64()
|
||||
.expect("Unable to deserialize 'metadataProfileId'")
|
||||
});
|
||||
let root_folder_path = edit_artist_params.root_folder_path.unwrap_or_else(|| {
|
||||
detailed_artist_body["path"]
|
||||
.as_str()
|
||||
.expect("Unable to deserialize 'path'")
|
||||
.to_owned()
|
||||
});
|
||||
let tags = if edit_artist_params.clear_tags {
|
||||
vec![]
|
||||
} else {
|
||||
edit_artist_params.tags.unwrap_or(
|
||||
detailed_artist_body["tags"]
|
||||
.as_array()
|
||||
.expect("Unable to deserialize 'tags'")
|
||||
.iter()
|
||||
.map(|item| item.as_i64().expect("Unable to deserialize tag ID"))
|
||||
.collect(),
|
||||
)
|
||||
};
|
||||
|
||||
(
|
||||
monitored,
|
||||
monitor_new_items,
|
||||
quality_profile_id,
|
||||
metadata_profile_id,
|
||||
root_folder_path,
|
||||
tags,
|
||||
)
|
||||
};
|
||||
|
||||
*detailed_artist_body.get_mut("monitored").unwrap() = json!(monitored);
|
||||
*detailed_artist_body.get_mut("monitorNewItems").unwrap() = json!(monitor_new_items);
|
||||
*detailed_artist_body.get_mut("qualityProfileId").unwrap() = json!(quality_profile_id);
|
||||
*detailed_artist_body.get_mut("metadataProfileId").unwrap() = json!(metadata_profile_id);
|
||||
*detailed_artist_body.get_mut("path").unwrap() = json!(root_folder_path);
|
||||
*detailed_artist_body.get_mut("tags").unwrap() = json!(tags);
|
||||
|
||||
debug!("Edit artist body: {detailed_artist_body:?}");
|
||||
|
||||
let request_props = self
|
||||
.request_props_from(
|
||||
event,
|
||||
RequestMethod::Put,
|
||||
Some(detailed_artist_body),
|
||||
Some(format!("/{artist_id}")),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
self
|
||||
.handle_request::<Value, ()>(request_props, |_, _| ())
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
#[cfg(test)]
|
||||
#[allow(dead_code)] // TODO: maybe remove?
|
||||
pub mod test_utils {
|
||||
use crate::models::lidarr_models::{Artist, ArtistStatistics, ArtistStatus, DownloadRecord, DownloadStatus, DownloadsResponse, Member, MetadataProfile, NewItemMonitorType, Ratings, SystemStatus};
|
||||
use crate::models::servarr_models::{QualityProfile, RootFolder, Tag};
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
use bimap::BiMap;
|
||||
use chrono::DateTime;
|
||||
use serde_json::Number;
|
||||
|
||||
pub fn member() -> Member {
|
||||
Member {
|
||||
name: Some("alex".to_owned()),
|
||||
instrument: Some("piano".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ratings() -> Ratings {
|
||||
Ratings {
|
||||
votes: 15,
|
||||
value: 8.4
|
||||
}
|
||||
}
|
||||
|
||||
pub fn artist_statistics() -> ArtistStatistics {
|
||||
ArtistStatistics {
|
||||
album_count: 1,
|
||||
track_file_count: 15,
|
||||
track_count: 15,
|
||||
total_track_count: 15,
|
||||
size_on_disk: 12345,
|
||||
percent_of_tracks: 99.9
|
||||
}
|
||||
}
|
||||
|
||||
pub fn artist() -> Artist {
|
||||
Artist {
|
||||
id: 1,
|
||||
artist_name: "Alex".into(),
|
||||
foreign_artist_id: "test-foreign-id".to_owned(),
|
||||
status: ArtistStatus::Continuing,
|
||||
overview: Some("some interesting description of the artist".to_owned()),
|
||||
artist_type: Some("Person".to_owned()),
|
||||
disambiguation: Some("American pianist".to_owned()),
|
||||
members: Some(vec![member()]),
|
||||
path: "/nfs/music/test-artist".to_owned(),
|
||||
quality_profile_id: quality_profile().id,
|
||||
metadata_profile_id: metadata_profile().id,
|
||||
monitored: true,
|
||||
monitor_new_items: NewItemMonitorType::All,
|
||||
genres: vec!["soundtrack".to_owned()],
|
||||
tags: vec![Number::from(tag().id)],
|
||||
added: DateTime::from(DateTime::parse_from_rfc3339("2023-01-01T00:00:00Z").unwrap()),
|
||||
ratings: Some(ratings()),
|
||||
statistics: Some(artist_statistics())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn quality_profile() -> QualityProfile {
|
||||
QualityProfile {
|
||||
id: 1,
|
||||
name: "Lossless".to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn quality_profile_map() -> BiMap<i64, String> {
|
||||
let quality_profile = quality_profile();
|
||||
BiMap::from_iter(vec![(quality_profile.id, quality_profile.name)])
|
||||
}
|
||||
|
||||
pub fn metadata_profile() -> MetadataProfile {
|
||||
MetadataProfile {
|
||||
id: 1,
|
||||
name: "Standard".to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata_profile_map() -> BiMap<i64, String> {
|
||||
let metadata_profile = metadata_profile();
|
||||
BiMap::from_iter(vec![(metadata_profile.id, metadata_profile.name)])
|
||||
}
|
||||
|
||||
pub fn tag() -> Tag {
|
||||
Tag {
|
||||
id: 1,
|
||||
label: "alex".to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tags_map() -> BiMap<i64, String> {
|
||||
let tag = tag();
|
||||
BiMap::from_iter(vec![(tag.id, tag.label)])
|
||||
}
|
||||
|
||||
pub fn download_record() -> DownloadRecord {
|
||||
DownloadRecord {
|
||||
title: "Test download title".to_owned(),
|
||||
status: DownloadStatus::Downloading,
|
||||
id: 1,
|
||||
album_id: Some(Number::from(1i64)),
|
||||
artist_id: Some(Number::from(1i64)),
|
||||
size: 3543348019f64,
|
||||
sizeleft: 1771674009f64,
|
||||
output_path: Some(HorizontallyScrollableText::from("/nfs/music/alex/album")),
|
||||
indexer: "kickass torrents".to_owned(),
|
||||
download_client: Some("transmission".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn downloads_response() -> DownloadsResponse {
|
||||
DownloadsResponse {
|
||||
records: vec![download_record()]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn system_status() -> SystemStatus {
|
||||
SystemStatus {
|
||||
version: "1.0".to_owned(),
|
||||
start_time: DateTime::from(DateTime::parse_from_rfc3339("2023-01-01T00:00:00Z").unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn root_folder() -> RootFolder {
|
||||
RootFolder {
|
||||
id: 1,
|
||||
path: "/nfs".to_owned(),
|
||||
accessible: true,
|
||||
free_space: 219902325555200,
|
||||
unmapped_folders: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,9 @@ use anyhow::Result;
|
||||
use log::info;
|
||||
|
||||
use super::{NetworkEvent, NetworkResource};
|
||||
use crate::models::lidarr_models::{DeleteArtistParams, LidarrSerdeable, MetadataProfile};
|
||||
use crate::models::lidarr_models::{
|
||||
DeleteArtistParams, EditArtistParams, LidarrSerdeable, MetadataProfile,
|
||||
};
|
||||
use crate::models::servarr_models::{QualityProfile, Tag};
|
||||
use crate::network::{Network, RequestMethod};
|
||||
|
||||
@@ -15,9 +17,15 @@ mod system;
|
||||
#[path = "lidarr_network_tests.rs"]
|
||||
mod lidarr_network_tests;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "lidarr_network_test_utils.rs"]
|
||||
pub mod lidarr_network_test_utils;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub enum LidarrEvent {
|
||||
AddTag(String),
|
||||
DeleteArtist(DeleteArtistParams),
|
||||
EditArtist(EditArtistParams),
|
||||
GetArtistDetails(i64),
|
||||
GetDiskSpace,
|
||||
GetDownloads(u64),
|
||||
@@ -37,7 +45,9 @@ pub enum LidarrEvent {
|
||||
impl NetworkResource for LidarrEvent {
|
||||
fn resource(&self) -> &'static str {
|
||||
match &self {
|
||||
LidarrEvent::AddTag(_) | LidarrEvent::GetTags => "/tag",
|
||||
LidarrEvent::DeleteArtist(_)
|
||||
| LidarrEvent::EditArtist(_)
|
||||
| LidarrEvent::GetArtistDetails(_)
|
||||
| LidarrEvent::ListArtists
|
||||
| LidarrEvent::ToggleArtistMonitoring(_) => "/artist",
|
||||
@@ -49,7 +59,6 @@ impl NetworkResource for LidarrEvent {
|
||||
LidarrEvent::GetQualityProfiles => "/qualityprofile",
|
||||
LidarrEvent::GetRootFolders => "/rootfolder",
|
||||
LidarrEvent::GetStatus => "/system/status",
|
||||
LidarrEvent::GetTags => "/tag",
|
||||
LidarrEvent::HealthCheck => "/health",
|
||||
}
|
||||
}
|
||||
@@ -67,6 +76,7 @@ impl Network<'_, '_> {
|
||||
lidarr_event: LidarrEvent,
|
||||
) -> Result<LidarrSerdeable> {
|
||||
match lidarr_event {
|
||||
LidarrEvent::AddTag(tag) => self.add_lidarr_tag(tag).await.map(LidarrSerdeable::from),
|
||||
LidarrEvent::DeleteArtist(params) => {
|
||||
self.delete_artist(params).await.map(LidarrSerdeable::from)
|
||||
}
|
||||
@@ -111,6 +121,7 @@ impl Network<'_, '_> {
|
||||
.await
|
||||
.map(LidarrSerdeable::from),
|
||||
LidarrEvent::UpdateAllArtists => self.update_all_artists().await.map(LidarrSerdeable::from),
|
||||
LidarrEvent::EditArtist(params) => self.edit_artist(params).await.map(LidarrSerdeable::from),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,4 +191,61 @@ impl Network<'_, '_> {
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn add_lidarr_tag(&mut self, tag: String) -> Result<Tag> {
|
||||
info!("Adding a new Lidarr tag");
|
||||
let event = LidarrEvent::AddTag(String::new());
|
||||
|
||||
let request_props = self
|
||||
.request_props_from(
|
||||
event,
|
||||
RequestMethod::Post,
|
||||
Some(serde_json::json!({ "label": tag })),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
self
|
||||
.handle_request::<serde_json::Value, Tag>(request_props, |tag, mut app| {
|
||||
app.data.lidarr_data.tags_map.insert(tag.id, tag.label);
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub(in crate::network::lidarr_network) async fn extract_and_add_lidarr_tag_ids_vec(
|
||||
&mut self,
|
||||
edit_tags: &str,
|
||||
) -> Vec<i64> {
|
||||
let missing_tags_vec = {
|
||||
let tags_map = &self.app.lock().await.data.lidarr_data.tags_map;
|
||||
edit_tags
|
||||
.split(',')
|
||||
.filter(|&tag| {
|
||||
!tag.is_empty() && tags_map.get_by_right(tag.to_lowercase().trim()).is_none()
|
||||
})
|
||||
.collect::<Vec<&str>>()
|
||||
};
|
||||
|
||||
for tag in missing_tags_vec {
|
||||
self
|
||||
.add_lidarr_tag(tag.trim().to_owned())
|
||||
.await
|
||||
.expect("Unable to add tag");
|
||||
}
|
||||
|
||||
let app = self.app.lock().await;
|
||||
edit_tags
|
||||
.split(',')
|
||||
.filter(|tag| !tag.is_empty())
|
||||
.map(|tag| {
|
||||
*app
|
||||
.data
|
||||
.lidarr_data
|
||||
.tags_map
|
||||
.get_by_right(tag.to_lowercase().trim())
|
||||
.unwrap()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user