diff --git a/Cargo.lock b/Cargo.lock index 6510e80..4fb05b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1582,6 +1582,7 @@ dependencies = [ "serde_json", "sys-locale", "unic-langid", + "url", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 8ae1124..fd071b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,4 @@ sys-locale = "0.3.2" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.146" once_cell = "1.19" +url = "2.5.7" diff --git a/src/api/client.rs b/src/api/client.rs new file mode 100644 index 0000000..69c26c3 --- /dev/null +++ b/src/api/client.rs @@ -0,0 +1,40 @@ +use anyhow::Result; +use reqwest::blocking::Client; + +use crate::{ + api::endpoints::UptimeKumaEndpoints, + data::{self, heartbeat::HeartbeatResponse, status_page::model::StatusPageResponse}, +}; + +pub struct UptimeKumaClient { + client: Client, +} + +impl UptimeKumaClient { + pub fn new() -> Self { + Self { + client: Client::new(), + } + } + + pub fn fetch_heartbeat(&self, endpoints: &UptimeKumaEndpoints) -> Result { + let response = self.client.get(endpoints.heartbeat_url()).send()?; + + if response.status().is_success() { + let json_text = response.text()?; + data::heartbeat::parse_response(&json_text) + } else { + return Err(anyhow::anyhow!(response.status())); + } + } + + pub fn fetch_status_page(&self, endpoints: &UptimeKumaEndpoints) -> Result { + let response = self.client.get(endpoints.status_page_url()).send()?; + if response.status().is_success() { + let json_text = response.text()?; + data::status_page::parse_response(&json_text) + } else { + return Err(anyhow::anyhow!(response.status())); + } + } +} diff --git a/src/api/endpoints.rs b/src/api/endpoints.rs new file mode 100644 index 0000000..884472c --- /dev/null +++ b/src/api/endpoints.rs @@ -0,0 +1,25 @@ +use url::Url; + +#[derive(Debug, Clone)] +pub struct UptimeKumaEndpoints { + base_url: Url, + slug: String, +} + +impl UptimeKumaEndpoints { + pub fn new(base_url: &str, slug: &str) -> Result { + let base_url = Url::parse(base_url.trim_end_matches("/"))?; + Ok(Self { + base_url, + slug: slug.to_string(), + }) + } + + pub fn heartbeat_url(&self) -> String { + format!("{}api/status-page/heartbeat/{}", self.base_url, self.slug) + } + + pub fn status_page_url(&self) -> String { + format!("{}api/status-page/{}", self.base_url, self.slug) + } +} diff --git a/src/api/mod.rs b/src/api/mod.rs new file mode 100644 index 0000000..b6335aa --- /dev/null +++ b/src/api/mod.rs @@ -0,0 +1,5 @@ +pub mod client; +pub mod endpoints; + +pub use client::UptimeKumaClient; +pub use endpoints::UptimeKumaEndpoints; diff --git a/src/data/unified/model.rs b/src/core/data.rs similarity index 64% rename from src/data/unified/model.rs rename to src/core/data.rs index a4a16e9..3abe547 100644 --- a/src/data/unified/model.rs +++ b/src/core/data.rs @@ -1,20 +1,8 @@ -use crate::data::heartbeat; -use crate::data::heartbeat::model::{HeartbeatEntry, HeartbeatResponse, UptimeData}; -use crate::data::status_page::model::{MonitorInfo, StatusPageResponse}; +use crate::core::models::{UnifiedData, UnifiedMonitorData}; +use crate::data::heartbeat::model::{HeartbeatResponse}; +use crate::data::status_page::model::{StatusPageResponse}; -#[derive(Debug, Clone)] -pub struct UnifiedMonitorData { - pub monitor_info: MonitorInfo, - pub heartbeats: Vec, - pub uptime_data: Option, -} -#[derive(Debug, Clone)] -pub struct UnifiedData { - pub status_page_title: String, - pub status_page_description: Option, - pub monitors: Vec, -} pub fn unify_data(status_page: &StatusPageResponse, heartbeat: &HeartbeatResponse) -> UnifiedData { let mut monitors = Vec::new(); diff --git a/src/core/mod.rs b/src/core/mod.rs new file mode 100644 index 0000000..2fa14ca --- /dev/null +++ b/src/core/mod.rs @@ -0,0 +1,5 @@ +pub mod data; +pub mod models; + +pub use data::unify_data; +pub use models::{UnifiedData, UnifiedMonitorData}; diff --git a/src/core/models.rs b/src/core/models.rs new file mode 100644 index 0000000..f4a2f6d --- /dev/null +++ b/src/core/models.rs @@ -0,0 +1,16 @@ +use crate::data::heartbeat::model::{HeartbeatEntry, HeartbeatResponse, UptimeData}; +use crate::data::status_page::model::{MonitorInfo, StatusPageResponse}; + +#[derive(Debug, Clone)] +pub struct UnifiedMonitorData { + pub monitor_info: MonitorInfo, + pub heartbeats: Vec, + pub uptime_data: Option, +} + +#[derive(Debug, Clone)] +pub struct UnifiedData { + pub status_page_title: String, + pub status_page_description: Option, + pub monitors: Vec, +} diff --git a/src/data/mod.rs b/src/data/mod.rs index bd7d20d..3e4a2e7 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -1,4 +1,2 @@ -pub mod unified; -pub use unified::model::unify_data; pub mod heartbeat; pub mod status_page; diff --git a/src/data/unified/mod.rs b/src/data/unified/mod.rs deleted file mode 100644 index 65880be..0000000 --- a/src/data/unified/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod model; diff --git a/src/main.rs b/src/main.rs index d798c8b..3d03e6e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,13 @@ use anyhow::Result; use clap::Parser; -use reqwest::blocking::Client; use std::result::Result::Ok; mod i18n; use i18n::init_locales; - -use crate::data::unify_data; +mod api; +use crate::core::unify_data; +use api::UptimeKumaClient; +use api::UptimeKumaEndpoints; +mod core; mod data; #[derive(Debug, Parser)] @@ -21,33 +23,13 @@ struct Args { fn main() -> Result<()> { init_locales()?; let args = Args::parse(); - let base_url = args.base_url.trim_end_matches("/"); - let heartbeat_url = format!("{}/api/status-page/heartbeat/{}", base_url, args.slug); - let status_page_url = format!("{}/api/status-page/{}", base_url, args.slug); + let client = UptimeKumaClient::new(); + let endpoints = UptimeKumaEndpoints::new(&args.base_url, &args.slug)?; - let client = Client::new(); + let heartbeat_data = client.fetch_heartbeat(&endpoints)?; - println!("Heartbeat URL: {}", heartbeat_url); - - let heartbeat_response = client.get(heartbeat_url).send()?; - - let heartbeat_data = if heartbeat_response.status().is_success() { - let json_text = heartbeat_response.text()?; - data::heartbeat::parse_response(&json_text)? - } else { - return Err(anyhow::anyhow!(heartbeat_response.status())); - }; - - println!("Status Page URL: {}", status_page_url); - - let status_page_response = client.get(status_page_url).send()?; - let status_page_data = if status_page_response.status().is_success() { - let json_text = status_page_response.text()?; - data::status_page::parse_response(&json_text)? - } else { - return Err(anyhow::anyhow!(status_page_response.status())); - }; + let status_page_data = client.fetch_status_page(&endpoints)?; let unified_data = unify_data(&status_page_data, &heartbeat_data);