use crate::state::ArchStatusColor;
use std::fmt::Write;
mod api;
mod html;
pub mod translate;
mod utils;
use api::{parse_status_api_summary, parse_uptimerobot_api};
use html::{is_aur_down_in_monitors, parse_arch_status_from_html};
use utils::{extract_aur_today_percent, extract_aur_today_rect_color, severity_max};
type Result<T> = super::Result<T>;
#[allow(clippy::missing_const_for_fn)]
pub async fn fetch_arch_status_text() -> Result<(String, ArchStatusColor)> {
let api_url = "https://status.archlinux.org/api/v2/summary.json";
let api_result =
tokio::task::spawn_blocking(move || crate::util::curl::curl_json(api_url)).await;
if let Ok(Ok(v)) = api_result {
let (mut text, mut color, suffix) = parse_status_api_summary(&v);
if let Ok(Ok(html)) = tokio::task::spawn_blocking(|| {
crate::util::curl::curl_text("https://status.archlinux.org")
})
.await
{
if is_aur_down_in_monitors(&html) {
let aur_pct_opt = extract_aur_today_percent(&html);
let aur_pct_suffix = aur_pct_opt
.map(|p| format!(" — AUR today: {p}%"))
.unwrap_or_default();
let text = format!("Status: AUR Down{aur_pct_suffix}");
return Ok((text, ArchStatusColor::IncidentSevereToday));
}
let aur_pct_opt = extract_aur_today_percent(&html);
if let Some(p) = aur_pct_opt {
let _ = write!(text, " — AUR today: {p}%");
}
if let Some(rect_color) = extract_aur_today_rect_color(&html) {
let api_says_operational = matches!(
v.get("components")
.and_then(|c| c.as_array())
.and_then(|arr| arr.iter().find(|c| {
c.get("name")
.and_then(|n| n.as_str())
.is_some_and(|n| n.to_lowercase().contains("aur"))
}))
.and_then(|c| c.get("status").and_then(|s| s.as_str())),
Some("operational")
);
if api_says_operational
&& matches!(
rect_color,
ArchStatusColor::IncidentToday | ArchStatusColor::IncidentSevereToday
)
{
color = rect_color;
let text_lower = text.to_lowercase();
let pct_suffix = if text_lower.contains("aur today") {
String::new() } else {
aur_pct_opt
.map(|p| format!(" — AUR today: {p}%"))
.unwrap_or_default()
};
match rect_color {
ArchStatusColor::IncidentSevereToday => {
if !text_lower.contains("outage") && !text_lower.contains("issues") {
text = format!("AUR issues detected (see status){pct_suffix}");
}
}
ArchStatusColor::IncidentToday => {
if !text_lower.contains("degraded")
&& !text_lower.contains("outage")
&& !text_lower.contains("issues")
{
text = format!("AUR degraded (see status){pct_suffix}");
}
}
_ => {}
}
} else {
color = severity_max(color, rect_color);
}
}
}
if let Some(sfx) = suffix
&& !text.to_lowercase().contains(&sfx.to_lowercase())
{
text = format!("{text} {sfx}");
}
return Ok((text, color));
}
let uptimerobot_api_url = "https://status.archlinux.org/api/getMonitorList/vmM5ruWEAB";
let uptimerobot_result =
tokio::task::spawn_blocking(move || crate::util::curl::curl_json(uptimerobot_api_url))
.await;
if let Ok(Ok(v)) = uptimerobot_result
&& let Some((mut text, mut color)) = parse_uptimerobot_api(&v)
{
if let Ok(Ok(html)) = tokio::task::spawn_blocking(|| {
crate::util::curl::curl_text("https://status.archlinux.org")
})
.await
&& is_aur_down_in_monitors(&html)
{
let aur_pct_opt = extract_aur_today_percent(&html);
let aur_pct_suffix = aur_pct_opt
.map(|p| format!(" — AUR today: {p}%"))
.unwrap_or_default();
text = format!("Status: AUR Down{aur_pct_suffix}");
color = ArchStatusColor::IncidentSevereToday;
}
return Ok((text, color));
}
let url = "https://status.archlinux.org";
let body = tokio::task::spawn_blocking(move || crate::util::curl::curl_text(url)).await??;
let (text, color) = parse_arch_status_from_html(&body);
Ok((text, color))
}