SystemStatus was declared three times, byte for byte identically, in radarr_models, sonarr_models, and lidarr_models. MetadataProfile and the Lidarr release download body were each declared in a single servarr module despite having nothing servarr specific about them: MetadataProfile is an id and name pair structurally identical to QualityProfile, which already lives in servarr_models, and a download body of a guid plus an indexer id is the generic form of that request. Move all three into servarr_models, preserving that file's alphabetical ordering, and drop the prefix from LidarrReleaseDownloadBody now that it is no longer owned by one servarr. RadarrReleaseDownloadBody and SonarrReleaseDownloadBody deliberately stay where they are. Radarr's carries a movie id and Sonarr's carries optional series, episode, and season fields, so the three types are not interchangeable and only the Lidarr shape is the common one. Behavior is unchanged. Every remaining edit is an import path update or the rename at a call site.
276 lines
8.1 KiB
Rust
276 lines
8.1 KiB
Rust
use crate::models::lidarr_models::{LidarrTask, LidarrTaskName};
|
|
use crate::models::servarr_models::{
|
|
CommandBody, DiskSpace, HostConfig, LogResponse, QueueEvent, SecurityConfig, SystemStatus, Update,
|
|
};
|
|
use crate::models::{HorizontallyScrollableText, Scrollable, ScrollableText};
|
|
use crate::network::lidarr_network::LidarrEvent;
|
|
use crate::network::{Network, RequestMethod};
|
|
use anyhow::Result;
|
|
use indoc::formatdoc;
|
|
use log::info;
|
|
use serde_json::Value;
|
|
|
|
#[cfg(test)]
|
|
#[path = "lidarr_system_network_tests.rs"]
|
|
mod lidarr_system_network_tests;
|
|
|
|
impl Network<'_, '_> {
|
|
pub(in crate::network::lidarr_network) async fn get_lidarr_host_config(
|
|
&mut self,
|
|
) -> Result<HostConfig> {
|
|
info!("Fetching Lidarr host config");
|
|
let event = LidarrEvent::GetHostConfig;
|
|
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, None)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), HostConfig>(request_props, |_, _| ())
|
|
.await
|
|
}
|
|
|
|
pub(in crate::network::lidarr_network) async fn get_lidarr_logs(
|
|
&mut self,
|
|
events: u64,
|
|
) -> Result<LogResponse> {
|
|
info!("Fetching Lidarr logs");
|
|
let event = LidarrEvent::GetLogs(events);
|
|
|
|
let params = format!("pageSize={events}&sortDirection=descending&sortKey=time");
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, Some(params))
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), LogResponse>(request_props, |log_response, mut app| {
|
|
let mut logs = log_response.records;
|
|
logs.reverse();
|
|
|
|
let log_lines = logs
|
|
.into_iter()
|
|
.map(|log| {
|
|
if let Some(exception) = log.exception {
|
|
HorizontallyScrollableText::from(format!(
|
|
"{}|{}|{}|{}|{}",
|
|
log.time,
|
|
log.level.to_uppercase(),
|
|
log
|
|
.logger
|
|
.as_ref()
|
|
.expect("logger must exist when exception is present"),
|
|
log
|
|
.exception_type
|
|
.as_ref()
|
|
.expect("exception_type must exist when exception is present"),
|
|
exception
|
|
))
|
|
} else {
|
|
HorizontallyScrollableText::from(format!(
|
|
"{}|{}|{}|{}",
|
|
log.time,
|
|
log.level.to_uppercase(),
|
|
log.logger.as_ref().expect("logger must exist in log entry"),
|
|
log
|
|
.message
|
|
.as_ref()
|
|
.expect("message must exist when exception is not present")
|
|
))
|
|
}
|
|
})
|
|
.collect();
|
|
|
|
app.data.lidarr_data.logs.set_items(log_lines);
|
|
app.data.lidarr_data.logs.scroll_to_bottom();
|
|
})
|
|
.await
|
|
}
|
|
|
|
pub(in crate::network::lidarr_network) async fn get_lidarr_diskspace(
|
|
&mut self,
|
|
) -> Result<Vec<DiskSpace>> {
|
|
info!("Fetching Lidarr disk space");
|
|
let event = LidarrEvent::GetDiskSpace;
|
|
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, None)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), Vec<DiskSpace>>(request_props, |disk_space_vec, mut app| {
|
|
app.data.lidarr_data.disk_space_vec = disk_space_vec;
|
|
})
|
|
.await
|
|
}
|
|
|
|
pub(in crate::network::lidarr_network) async fn get_queued_lidarr_events(
|
|
&mut self,
|
|
) -> Result<Vec<QueueEvent>> {
|
|
info!("Fetching Lidarr queued events");
|
|
let event = LidarrEvent::GetQueuedEvents;
|
|
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, None)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), Vec<QueueEvent>>(request_props, |queued_events_vec, mut app| {
|
|
app
|
|
.data
|
|
.lidarr_data
|
|
.queued_events
|
|
.set_items(queued_events_vec);
|
|
})
|
|
.await
|
|
}
|
|
|
|
pub(in crate::network::lidarr_network) async fn get_lidarr_security_config(
|
|
&mut self,
|
|
) -> Result<SecurityConfig> {
|
|
info!("Fetching Lidarr security config");
|
|
let event = LidarrEvent::GetSecurityConfig;
|
|
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, None)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), SecurityConfig>(request_props, |_, _| ())
|
|
.await
|
|
}
|
|
|
|
pub(in crate::network::lidarr_network) async fn get_lidarr_status(
|
|
&mut self,
|
|
) -> Result<SystemStatus> {
|
|
info!("Fetching Lidarr system status");
|
|
let event = LidarrEvent::GetStatus;
|
|
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, None)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), SystemStatus>(request_props, |system_status, mut app| {
|
|
app.data.lidarr_data.version = system_status.version;
|
|
app.data.lidarr_data.start_time = system_status.start_time;
|
|
})
|
|
.await
|
|
}
|
|
|
|
pub(in crate::network::lidarr_network) async fn get_lidarr_tasks(
|
|
&mut self,
|
|
) -> Result<Vec<LidarrTask>> {
|
|
info!("Fetching Lidarr tasks");
|
|
let event = LidarrEvent::GetTasks;
|
|
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, None)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), Vec<LidarrTask>>(request_props, |tasks_vec, mut app| {
|
|
app.data.lidarr_data.tasks.set_items(tasks_vec);
|
|
})
|
|
.await
|
|
}
|
|
|
|
pub(in crate::network::lidarr_network) async fn get_lidarr_updates(
|
|
&mut self,
|
|
) -> Result<Vec<Update>> {
|
|
info!("Fetching Lidarr updates");
|
|
let event = LidarrEvent::GetUpdates;
|
|
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Get, None::<()>, None, None)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<(), Vec<Update>>(request_props, |updates_vec, mut app| {
|
|
let latest_installed = if updates_vec
|
|
.iter()
|
|
.any(|update| update.latest && update.installed_on.is_some())
|
|
{
|
|
"already".to_owned()
|
|
} else {
|
|
"not".to_owned()
|
|
};
|
|
let updates = updates_vec
|
|
.into_iter()
|
|
.map(|update| {
|
|
let install_status = if update.installed_on.is_some() {
|
|
if update.installed {
|
|
" (Currently Installed)".to_owned()
|
|
} else {
|
|
" (Previously Installed)".to_owned()
|
|
}
|
|
} else {
|
|
String::new()
|
|
};
|
|
let vec_to_bullet_points = |vec: Vec<String>| {
|
|
vec
|
|
.iter()
|
|
.map(|change| format!(" * {change}"))
|
|
.collect::<Vec<String>>()
|
|
.join("\n")
|
|
};
|
|
|
|
let mut update_info = formatdoc!(
|
|
"{} - {}{install_status}
|
|
{}",
|
|
update.version,
|
|
update.release_date,
|
|
"-".repeat(200)
|
|
);
|
|
|
|
if let Some(new_changes) = update.changes.new {
|
|
let changes = vec_to_bullet_points(new_changes);
|
|
update_info = formatdoc!(
|
|
"{update_info}
|
|
New:
|
|
{changes}"
|
|
)
|
|
}
|
|
|
|
if let Some(fixes) = update.changes.fixed {
|
|
let fixes = vec_to_bullet_points(fixes);
|
|
update_info = formatdoc!(
|
|
"{update_info}
|
|
Fixed:
|
|
{fixes}"
|
|
);
|
|
}
|
|
|
|
update_info
|
|
})
|
|
.reduce(|version_1, version_2| format!("{version_1}\n\n\n{version_2}"))
|
|
.unwrap();
|
|
|
|
app.data.lidarr_data.updates = ScrollableText::with_string(formatdoc!(
|
|
"The latest version of Lidarr is {latest_installed} installed
|
|
|
|
{updates}"
|
|
));
|
|
})
|
|
.await
|
|
}
|
|
|
|
pub(in crate::network::lidarr_network) async fn start_lidarr_task(
|
|
&mut self,
|
|
task: LidarrTaskName,
|
|
) -> Result<Value> {
|
|
let event = LidarrEvent::StartTask(task);
|
|
let task_name = task.to_string();
|
|
info!("Starting Lidarr task: {task_name}");
|
|
|
|
let body = CommandBody { name: task_name };
|
|
|
|
let request_props = self
|
|
.request_props_from(event, RequestMethod::Post, Some(body), None, None)
|
|
.await;
|
|
|
|
self
|
|
.handle_request::<CommandBody, Value>(request_props, |_, _| ())
|
|
.await
|
|
}
|
|
}
|