amu uptime checker
All checks were successful
arche-build-and-publish / gractwo-arche-build-test (push) Successful in 5m6s

This commit is contained in:
2026-04-06 21:33:02 +02:00
parent 22a08693ad
commit 6613ccb239
4 changed files with 740 additions and 33 deletions

692
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,7 @@ chrono = "0.4.41"
chrono-tz = "0.10.3"
dotenvy = "0.15.7"
rand = "0.9.1"
reqwest = "0.13.2"
serenity = "0.12.4"
tokio = { version = "1.44.2", features = ["full"] }
tower = "0.5.2"

58
src/router/amu_uptime.rs Normal file
View File

@@ -0,0 +1,58 @@
use std::time::{Duration, Instant};
use axum::extract::State;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use crate::router::ApiSharedState;
pub async fn amu_uptime_route(State(state): State<ApiSharedState>) -> Response {
let current = state.amu_uptime.read().await.clone();
match current {
Some((last_check, cached)) if last_check.elapsed() <= Duration::from_secs(30) => {
cached.into_response()
}
_ => get_amu_uptime(&state).await,
}
}
async fn get_amu_uptime(state: &ApiSharedState) -> Response {
let keywords = "Trwają prace serwisowe";
let cl = reqwest::Client::builder()
.timeout(Duration::from_secs(10))
.build()
.unwrap();
let result = match cl.get("https://amu.edu.pl").send().await {
Ok(res) if res.status().is_success() => match res.text().await {
Ok(text) => match text.contains(keywords) {
true => (
StatusCode::SERVICE_UNAVAILABLE,
"AMU is up and wrongly uses 200 OK.".into(),
),
false => (
StatusCode::OK,
"AMU is up and doesn't contain the keywords. Could it be up for real?".into(),
),
},
Err(_) => (
StatusCode::SERVICE_UNAVAILABLE,
"Failed to read response text from AMU.".into(),
),
},
Ok(res) => (
res.status(),
format!("AMU website returned an error status: {}", res.status()),
),
Err(e) => (
StatusCode::SERVICE_UNAVAILABLE,
format!("Failed to connect to AMU: {}", e),
),
};
let mut lock = state.amu_uptime.write().await;
*lock = Some((Instant::now(), result.clone()));
drop(lock);
result.into_response()
}

View File

@@ -1,10 +1,16 @@
use std::{sync::Arc, time::Instant};
use axum::{Router, http::StatusCode, routing::get};
use tokio::sync::RwLock;
use tower::service_fn;
use crate::{
days::days_of_community_existence, router::redirects::redirects, website::website_service,
days::days_of_community_existence,
router::{amu_uptime::amu_uptime_route, redirects::redirects},
website::website_service,
};
mod amu_uptime;
mod redirects;
pub fn init() -> Router {
@@ -20,7 +26,21 @@ fn api() -> Router {
.route("/live", get(async || StatusCode::OK))
.route("/discord-member-count", get(get_member_count))
.route("/days-community", get(get_days_since_community_formation))
.route("/amu-uptime", get(amu_uptime_route))
.fallback(api_fallback)
.with_state(ApiSharedState::new())
}
#[derive(Debug, Clone)]
struct ApiSharedState {
amu_uptime: Arc<RwLock<Option<(Instant, (StatusCode, String))>>>,
}
impl ApiSharedState {
pub fn new() -> Self {
Self {
amu_uptime: Arc::new(RwLock::new(None)),
}
}
}
async fn api_fallback() -> (StatusCode, String) {