270 lines
7.9 KiB
Rust
270 lines
7.9 KiB
Rust
use anyhow::Result;
|
|
use log::info;
|
|
use serde_json::{Value, json};
|
|
|
|
use super::{NetworkEvent, NetworkResource};
|
|
use crate::models::readarr_models::{AddReadarrRootFolderBody, ReadarrSerdeable, ReadarrTaskName};
|
|
use crate::models::servarr_models::{MetadataProfile, QualityProfile, Tag};
|
|
use crate::network::{Network, RequestMethod};
|
|
|
|
mod root_folders;
|
|
mod system;
|
|
|
|
#[cfg(test)]
|
|
#[path = "readarr_network_tests.rs"]
|
|
mod readarr_network_tests;
|
|
|
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
|
pub enum ReadarrEvent {
|
|
AddRootFolder(AddReadarrRootFolderBody),
|
|
AddTag(String),
|
|
DeleteTag(i64),
|
|
GetDiskSpace,
|
|
GetHostConfig,
|
|
GetLogs(u64),
|
|
GetMetadataProfiles,
|
|
GetQualityProfiles,
|
|
GetQueuedEvents,
|
|
GetRootFolders,
|
|
GetSecurityConfig,
|
|
GetStatus,
|
|
GetTags,
|
|
GetTasks,
|
|
GetUpdates,
|
|
HealthCheck,
|
|
StartTask(ReadarrTaskName),
|
|
}
|
|
|
|
impl NetworkResource for ReadarrEvent {
|
|
fn resource(&self) -> &'static str {
|
|
match &self {
|
|
ReadarrEvent::GetQueuedEvents | ReadarrEvent::StartTask(_) => "/command",
|
|
ReadarrEvent::GetHostConfig | ReadarrEvent::GetSecurityConfig => "/config/host",
|
|
ReadarrEvent::GetDiskSpace => "/diskspace",
|
|
ReadarrEvent::HealthCheck => "/health",
|
|
ReadarrEvent::GetLogs(_) => "/log",
|
|
ReadarrEvent::GetMetadataProfiles => "/metadataprofile",
|
|
ReadarrEvent::GetQualityProfiles => "/qualityprofile",
|
|
ReadarrEvent::AddRootFolder(_) | ReadarrEvent::GetRootFolders => "/rootfolder",
|
|
ReadarrEvent::GetStatus => "/system/status",
|
|
ReadarrEvent::GetTasks => "/system/task",
|
|
ReadarrEvent::AddTag(_) | ReadarrEvent::DeleteTag(_) | ReadarrEvent::GetTags => "/tag",
|
|
ReadarrEvent::GetUpdates => "/update",
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<ReadarrEvent> for NetworkEvent {
|
|
fn from(readarr_event: ReadarrEvent) -> Self {
|
|
NetworkEvent::Readarr(readarr_event)
|
|
}
|
|
}
|
|
|
|
impl Network<'_, '_> {
|
|
pub async fn handle_readarr_event(
|
|
&mut self,
|
|
readarr_event: ReadarrEvent,
|
|
) -> Result<ReadarrSerdeable> {
|
|
match readarr_event {
|
|
ReadarrEvent::AddRootFolder(add_root_folder_body) => self
|
|
.add_readarr_root_folder(add_root_folder_body)
|
|
.await
|
|
.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::AddTag(tag) => self.add_readarr_tag(tag).await.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::DeleteTag(tag_id) => self
|
|
.delete_readarr_tag(tag_id)
|
|
.await
|
|
.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::GetDiskSpace => self
|
|
.get_readarr_diskspace()
|
|
.await
|
|
.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::GetHostConfig => self
|
|
.get_readarr_host_config()
|
|
.await
|
|
.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::GetLogs(events) => self
|
|
.get_readarr_logs(events)
|
|
.await
|
|
.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::GetMetadataProfiles => self
|
|
.get_readarr_metadata_profiles()
|
|
.await
|
|
.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::GetQualityProfiles => self
|
|
.get_readarr_quality_profiles()
|
|
.await
|
|
.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::GetQueuedEvents => self
|
|
.get_queued_readarr_events()
|
|
.await
|
|
.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::GetRootFolders => self
|
|
.get_readarr_root_folders()
|
|
.await
|
|
.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::GetSecurityConfig => self
|
|
.get_readarr_security_config()
|
|
.await
|
|
.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::GetStatus => self.get_readarr_status().await.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::GetTags => self.get_readarr_tags().await.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::GetTasks => self.get_readarr_tasks().await.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::GetUpdates => self.get_readarr_updates().await.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::HealthCheck => self
|
|
.get_readarr_healthcheck()
|
|
.await
|
|
.map(ReadarrSerdeable::from),
|
|
ReadarrEvent::StartTask(task_name) => self
|
|
.start_readarr_task(task_name)
|
|
.await
|
|
.map(ReadarrSerdeable::from),
|
|
}
|
|
}
|
|
|
|
pub(in crate::network::readarr_network) async fn get_readarr_healthcheck(
|
|
&mut self,
|
|
) -> Result<()> {
|
|
info!("Performing Readarr health check");
|
|
let event = ReadarrEvent::HealthCheck;
|
|
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, None)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), ()>(request_props, |_, _| ())
|
|
.await
|
|
}
|
|
|
|
async fn get_readarr_metadata_profiles(&mut self) -> Result<Vec<MetadataProfile>> {
|
|
info!("Fetching Readarr metadata profiles");
|
|
let event = ReadarrEvent::GetMetadataProfiles;
|
|
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, None)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), Vec<MetadataProfile>>(request_props, |metadata_profiles, mut app| {
|
|
app.data.readarr_data.metadata_profile_map = metadata_profiles
|
|
.into_iter()
|
|
.map(|profile| (profile.id, profile.name))
|
|
.collect();
|
|
})
|
|
.await
|
|
}
|
|
|
|
async fn get_readarr_quality_profiles(&mut self) -> Result<Vec<QualityProfile>> {
|
|
info!("Fetching Readarr quality profiles");
|
|
let event = ReadarrEvent::GetQualityProfiles;
|
|
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, None)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), Vec<QualityProfile>>(request_props, |quality_profiles, mut app| {
|
|
app.data.readarr_data.quality_profile_map = quality_profiles
|
|
.into_iter()
|
|
.map(|profile| (profile.id, profile.name))
|
|
.collect();
|
|
})
|
|
.await
|
|
}
|
|
|
|
async fn get_readarr_tags(&mut self) -> Result<Vec<Tag>> {
|
|
info!("Fetching Readarr tags");
|
|
let event = ReadarrEvent::GetTags;
|
|
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, None)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), Vec<Tag>>(request_props, |tags_vec, mut app| {
|
|
app.data.readarr_data.tags_map = tags_vec
|
|
.into_iter()
|
|
.map(|tag| (tag.id, tag.label))
|
|
.collect();
|
|
})
|
|
.await
|
|
}
|
|
|
|
async fn add_readarr_tag(&mut self, tag: String) -> Result<Tag> {
|
|
info!("Adding a new Readarr tag");
|
|
let event = ReadarrEvent::AddTag(String::new());
|
|
|
|
let request_props = self
|
|
.request_props_from(
|
|
event,
|
|
RequestMethod::Post,
|
|
Some(json!({ "label": tag })),
|
|
None,
|
|
None,
|
|
)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<Value, Tag>(request_props, |tag, mut app| {
|
|
app.data.readarr_data.tags_map.insert(tag.id, tag.label);
|
|
})
|
|
.await
|
|
}
|
|
|
|
async fn delete_readarr_tag(&mut self, id: i64) -> Result<()> {
|
|
info!("Deleting Readarr tag with ID: {id}");
|
|
let event = ReadarrEvent::DeleteTag(id);
|
|
|
|
let request_props = self
|
|
.request_props_from(
|
|
event,
|
|
RequestMethod::Delete,
|
|
None::<()>,
|
|
Some(format!("/{id}")),
|
|
None,
|
|
)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), ()>(request_props, |_, _| ())
|
|
.await
|
|
}
|
|
|
|
pub(in crate::network::readarr_network) async fn extract_and_add_readarr_tag_ids_vec(
|
|
&mut self,
|
|
edit_tags: &str,
|
|
) -> Vec<i64> {
|
|
let missing_tags_vec = {
|
|
let tags_map = &self.app.lock().await.data.readarr_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_readarr_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
|
|
.readarr_data
|
|
.tags_map
|
|
.get_by_right(tag.to_lowercase().trim())
|
|
.unwrap()
|
|
})
|
|
.collect()
|
|
}
|
|
}
|