Initial Radarr ui!

This commit is contained in:
2023-08-08 10:50:04 -06:00
parent 3ae7e15961
commit 1ebf481326
11 changed files with 245 additions and 82 deletions
+2
View File
@@ -6,12 +6,14 @@ use tokio::sync::Mutex;
use crate::app::App;
pub(crate) mod radarr;
mod utils;
#[derive(Debug, Eq, PartialEq, Hash)]
pub enum RadarrEvent {
HealthCheck,
GetOverview,
GetStatus,
GetMovies,
}
pub struct Network<'a> {
+67 -56
View File
@@ -1,11 +1,14 @@
use anyhow::Result;
use chrono::{DateTime, Utc};
use derivative::Derivative;
use log::{debug, error};
use reqwest::RequestBuilder;
use serde::{Deserialize, Serialize};
use serde::de::DeserializeOwned;
use serde::Deserialize;
use serde_json::Number;
use crate::app::RadarrConfig;
use crate::network::{Network, RadarrEvent};
use tokio::sync::MutexGuard;
use crate::app::{App, RadarrConfig};
use crate::network::{Network, RadarrEvent, utils};
impl RadarrEvent {
const fn resource(self) -> &'static str {
@@ -13,11 +16,12 @@ impl RadarrEvent {
RadarrEvent::HealthCheck => "/health",
RadarrEvent::GetOverview => "/diskspace",
RadarrEvent::GetStatus => "/system/status",
RadarrEvent::GetMovies => "/movie",
}
}
}
#[derive(Serialize, Deserialize, Debug)]
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
struct DiskSpace {
pub path: String,
@@ -33,41 +37,30 @@ struct SystemStatus {
start_time: DateTime<Utc>,
}
#[derive(Derivative, Deserialize, Debug)]
#[derivative(Default)]
#[serde(rename_all = "camelCase")]
pub struct Movie {
#[derivative(Default(value = "Number::from(0)"))]
pub id: Number,
pub title: String,
#[derivative(Default(value = "Number::from(0)"))]
pub year: Number,
pub monitored: bool,
pub has_file: bool,
}
impl<'a> Network<'a> {
pub async fn handle_radarr_event(&self, radarr_event: RadarrEvent) {
match radarr_event {
RadarrEvent::HealthCheck => {
self.healthcheck(RadarrEvent::HealthCheck.resource()).await;
}
RadarrEvent::GetOverview => match self.diskspace(RadarrEvent::GetOverview.resource()).await {
Ok(disk_space_vec) => {
let mut app = self.app.lock().await;
let DiskSpace {
free_space,
total_space,
..
} = &disk_space_vec[0];
app.data.radarr_data.free_space = free_space.as_u64().unwrap();
app.data.radarr_data.total_space = total_space.as_u64().unwrap();
}
Err(e) => {
error!("Failed to fetch disk space. {:?}", e);
}
},
RadarrEvent::GetStatus => match self.status(RadarrEvent::GetStatus.resource()).await {
Ok(system_status) => {
let mut app = self.app.lock().await;
app.data.radarr_data.version = system_status.version;
app.data.radarr_data.start_time = system_status.start_time;
}
Err(e) => {
error!("Failed to fetch system status. {:?}", e);
}
},
RadarrEvent::HealthCheck => self.healthcheck(RadarrEvent::HealthCheck.resource()).await,
RadarrEvent::GetOverview => self.diskspace(RadarrEvent::GetOverview.resource()).await,
RadarrEvent::GetStatus => self.status(RadarrEvent::GetStatus.resource()).await,
RadarrEvent::GetMovies => self.movies(RadarrEvent::GetMovies.resource()).await
}
let mut app = self.app.lock().await;
app.reset();
app.reset_tick_count();
}
async fn healthcheck(&self, resource: &str) {
@@ -76,32 +69,30 @@ impl<'a> Network<'a> {
}
}
async fn diskspace(&self, resource: &str) -> Result<Vec<DiskSpace>> {
debug!("Handling diskspace event: {:?}", resource);
async fn diskspace(&self, resource: &str) {
self.handle_get_request::<Vec<DiskSpace>>(resource, | disk_space_vec, mut app | {
let DiskSpace {
free_space,
total_space,
..
} = &disk_space_vec[0];
Ok(
self
.call_radarr_api(resource)
.await
.send()
.await?
.json::<Vec<DiskSpace>>()
.await?,
)
app.data.radarr_data.free_space = free_space.as_u64().unwrap();
app.data.radarr_data.total_space = total_space.as_u64().unwrap();
}).await;
}
async fn status(&self, resource: &str) -> Result<SystemStatus> {
debug!("Handling system status event: {:?}", resource);
async fn status(&self, resource: &str) {
self.handle_get_request::<SystemStatus>(resource, | system_status, mut app | {
app.data.radarr_data.version = system_status.version;
app.data.radarr_data.start_time = system_status.start_time;
}).await;
}
Ok(
self
.call_radarr_api(resource)
.await
.send()
.await?
.json::<SystemStatus>()
.await?,
)
async fn movies(&self, resource: &str) {
self.handle_get_request::<Vec<Movie>>(resource, |movie_vec, mut app| {
app.data.radarr_data.movies.set_items(movie_vec);
}).await;
}
async fn call_radarr_api(&self, resource: &str) -> RequestBuilder {
@@ -123,4 +114,24 @@ impl<'a> Network<'a> {
))
.header("X-Api-Key", api_token)
}
async fn handle_get_request<T>(&self, resource: &str, mut app_update_fn: impl FnMut(T, MutexGuard<App>))
where
T: DeserializeOwned {
match self.call_radarr_api(resource)
.await
.send()
.await {
Ok(response) => {
match utils::parse_response::<T>(response).await {
Ok(value) => {
let app = self.app.lock().await;
app_update_fn(value, app);
}
Err(e) => error!("Failed to parse movie response! {:?}", e)
}
}
Err(e) => error!("Failed to fetch movies. {:?}", e)
}
}
}
+6
View File
@@ -0,0 +1,6 @@
use reqwest::Response;
use serde::de::DeserializeOwned;
pub async fn parse_response<T: DeserializeOwned>(response: Response) -> Result<T, reqwest::Error> {
response.json::<T>().await
}