diff --git a/Cargo.lock b/Cargo.lock index 21f59b4..0fbae01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -573,10 +573,12 @@ dependencies = [ "color-eyre", "froxy-scraper", "froxy-templates", + "indexmap", "log", "minijinja", "rustc-hash", "serde", + "serde_json", "smol_str", "tokio", "tower-http", @@ -1774,6 +1776,7 @@ version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ + "indexmap", "itoa", "memchr", "serde", diff --git a/mapping.json b/mapping.json new file mode 100644 index 0000000..3eb79db --- /dev/null +++ b/mapping.json @@ -0,0 +1,42 @@ +{ + "f4": { + "rows": [ +{ "range": "", "col": ["d", "x", "x", "x", "x", "x", "x", "x", "x","x", "x", "x", "x", "x", "x", "x", "d"] }, +{ "range": "R14", "col": ["f4r14s1", "f4r14s2", "f4r14s3", "f4r14s4", "f4r14s5", "f4r14s6", "f4r14s7", "f4r14s8", "", "f4r14s9", "f4r14s10", "f4r14s11", "f4r14s12", "f4r14s13", "f4r14s14", "f4r14s15", "f4r14s16"] }, +{ "range": "R13", "col": ["f4r13s1", "f4r13s2", "f4r13s3", "f4r13s4", "f4r13s5", "f4r13s6", "f4r13s7", "f4r13s8", "", "f4r13s9", "f4r13s10", "f4r13s11", "f4r13s12", "f4r13s13", "f4r13s14", "f4r13s15", "f4r13s16"] }, +{ "range": "R12", "col": ["f4r12s1", "f4r12s2", "f4r12s3", "f4r12s4", "f4r12s5", "f4r12s6", "f4r12s7", "f4r12s8", "", "f4r12s9", "f4r12s10", "f4r12s11", "f4r12s12", "f4r12s13", "f4r12s14", "f4r12s15", "f4r12s16"] }, +{ "range": "R11", "col": ["f4r11s1", "f4r11s2", "f4r11s3", "f4r11s4", "f4r11s5", "f4r11s6", "f4r11s7", "f4r11s8", "", "f4r11s9", "f4r11s10", "f4r11s11", "f4r11s12", "f4r11s13", "f4r11s14", "f4r11s15", "f4r11s16"] }, +{ "range": "R10", "col": ["f4r10s1", "f4r10s2", "f4r10s3", "f4r10s4", "f4r10s5", "f4r10s6", "f4r10s7", "f4r10s8", "", "f4r10s9", "f4r10s10", "f4r10s11", "f4r10s12", "f4r10s13", "f4r10s14", "f4r10s15", "f4r10s16"] }, +{ "range": "R9", "col": ["f", "f", "f", "f", "f", "f", "f", "f", "", "f", "f", "f", "f", "f", "f", "f", "f"] }, +{ "range": "R8", "col": ["f", "f", "f", "f", "f", "f", "f", "f", "", "f", "f", "f", "f", "f", "f", "f", "f"] }, +{ "range": "", "col": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""] }, +{ "range": "R7", "col": ["f4r7s1", "f4r7s2", "f4r7s3", "f4r7s4", "f4r7s5", "f4r7s6", "f4r7s7", "f4r7s8", "", "f4r7s9", "f4r7s10", "f4r7s11", "f4r7s12", "f4r7s13", "f4r7s14", "f4r7s15", "f4r7s16"] }, +{ "range": "R6", "col": ["f4r6s1", "f4r6s2", "f4r6s3", "f4r6s4", "f4r6s5", "f4r6s6", "f4r6s7", "f4r6s8", "", "f4r6s9", "f4r6s10", "f4r6s11", "f4r6s12", "f4r6s13", "f4r6s14", "f4r6s15", "f4r6s16"] }, +{ "range": "R5", "col": ["f4r5s1", "f4r5s2", "f4r5s3", "f4r5s4", "f4r5s5", "f4r5s6", "f4r5s7", "f4r5s8", "", "f4r5s9", "f4r5s10", "f4r5s11", "f4r5s12", "f4r5s13", "f4r5s14", "f4r5s15", "f4r5s16"] }, +{ "range": "R4", "col": ["f4r4s1", "f4r4s2", "f4r4s3", "f4r4s4", "f4r4s5", "f4r4s6", "f4r4s7", "f4r4s8", "", "f4r4s9", "f4r4s10", "f4r4s11", "f4r4s12", "f4r4s13", "f4r4s14", "f4r4s15", "f4r4s16"] }, +{ "range": "R4", "col": ["f4r4s1", "f4r4s2", "f4r4s3", "f4r4s4", "f4r4s5", "f4r4s6", "f4r4s7", "f4r4s8", "", "f4r4s9", "f4r4s10", "f4r4s11", "f4r4s12", "f4r4s13", "f4r4s14", "f4r4s15", "f4r4s16"] }, +{ "range": "R3", "col": ["f4r3s1", "f4r3s2", "f4r3s3", "f4r3s4", "f4r3s5", "f4r3s6", "f4r3s7", "f4r3s8", "", "f4r3s9", "f4r3s10", "f4r3s11", "f4r3s12", "f4r3s13", "f4r3s14", "f4r3s15", "f4r3s16"] }, +{ "range": "R1", "col": ["f4r1s1", "f4r1s2", "f4r1s3", "f4r1s4", "f4r1s5", "f4r1s6", "f4r1s7", "f4r1s8", "", "f4r1s9", "f4r1s10", "f4r1s11", "f4r1s12", "f4r1s13", "f4r1s14", "f4r1s15", "f4r1s16"] }, +{ "range": "", "col": ["d", "x", "x", "x", "x", "x", "x", "x", "x","x", "x", "x", "x", "x", "x", "x", "d"] } + ] + }, + "f6": { + "rows": [ +{ "range": "R14", "col": ["f", "f", "f", "f", "f", "f", "f", "f", "", "f", "f", "f", "f", "f", "f", "f", "f"] }, +{ "range": "R13", "col": ["f6r13s1", "f6r13s2", "f6r13s3", "f6r13s4", "f6r13s5", "f6r13s6", "f6r13s7", "f6r13s8", "", "f6r13s9", "f6r13s10", "f6r13s11", "f6r13s12", "f6r13s13", "f6r13s14", "f6r13s15", "f6r13s16"] }, +{ "range": "R12", "col": ["f6r12s1", "f6r12s2", "f6r12s3", "f6r12s4", "f6r12s5", "f6r12s6", "f6r12s7", "f6r12s8", "", "f6r12s9", "f6r12s10", "f6r12s11", "f6r12s12", "f6r12s13", "f6r12s14", "f6r12s15", "f6r12s16"] }, +{ "range": "R11", "col": ["f6r11s1", "f6r11s2", "f6r11s3", "f6r11s4", "f6r11s5", "f6r11s6", "f6r11s7", "f6r11s8", "", "f6r11s9", "f6r11s10", "f6r11s11", "f6r11s12", "f6r11s13", "f6r11s14", "f6r11s15", "f6r11s16"] }, +{ "range": "R10", "col": ["f6r10s1", "f6r10s2", "f6r10s3", "f6r10s4", "f6r10s5", "f6r10s6", "f6r10s7", "f6r10s8", "", "f6r10s9", "f6r10s10", "f6r10s11", "f6r10s12", "f6r10s13", "f6r10s14", "f6r10s15", "f6r10s16"] }, +{ "range": "R9", "col": ["f6r9s1", "f6r9s2", "f6r9s3", "f6r9s4", "f6r9s5", "f6r9s6", "f6r9s7", "f6r9s8", "", "f6r9s9", "f6r9s10", "f6r9s11", "f6r9s12", "f6r9s13", "f6r9s14", "f6r9s15", "f6r9s16"] }, +{ "range": "R8", "col": ["f6r8s1", "f6r8s2", "f6r8s3", "f6r8s4", "f6r8s5", "f6r8s6", "f6r8s7", "f6r8s8", "", "f6r8s9", "f6r8s10", "f6r8s11", "f6r8s12", "f6r8s13", "f6r8s14", "f6r8s15", "f6r8s16"] }, +{ "range": "", "col": ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""] }, +{ "range": "R7", "col": ["f6r7s1", "f6r7s2", "f6r7s3", "f6r7s4", "f6r7s5", "f6r7s6", "f6r7s7", "f6r7s8", "", "f6r7s9", "f6r7s10", "f6r7s11", "f6r7s12", "f6r7s13", "f6r7s14", "f6r7s15", "f6r7s16"] }, +{ "range": "R6", "col": ["f6r6s1", "f6r6s2", "f6r6s3", "f6r6s4", "f6r6s5", "f6r6s6", "f6r6s7", "f6r6s8", "", "f6r6s9", "f6r6s10", "f6r6s11", "f6r6s12", "f6r6s13", "f6r6s14", "f6r6s15", "f6r6s16"] }, +{ "range": "R5", "col": ["f6r5s1", "f6r5s2", "f6r5s3", "f6r5s4", "f6r5s5", "f6r5s6", "f6r5s7", "f6r5s8", "", "f6r5s9", "f6r5s10", "f6r5s11", "f6r5s12", "f6r5s13", "f6r5s14", "f6r5s15", "f6r5s16"] }, +{ "range": "R4", "col": ["f6r4s1", "f6r4s2", "f6r4s3", "f6r4s4", "f6r4s5", "f6r4s6", "f6r4s7", "f6r4s8", "", "f6r4s9", "f6r4s10", "f6r4s11", "f6r4s12", "f6r4s13", "f6r4s14", "f6r4s15", "f6r4s16"] }, +{ "range": "R3", "col": ["f6r3s1", "f6r3s2", "f6r3s3", "f6r3s4", "f6r3s5", "f6r3s6", "f6r3s7", "f6r3s8", "", "f6r3s9", "f6r3s10", "f6r3s11", "f6r3s12", "f6r3s13", "f6r3s14", "f6r3s15", "f6r3s16"] }, +{ "range": "R2", "col": ["f6r2s1", "f6r2s2", "f6r2s3", "f6r2s4", "f6r2s5", "f6r2s6", "f6r2s7", "f6r2s8", "", "f6r2s9", "f6r2s10", "f6r2s11", "f6r2s12", "f6r2s13", "f6r2s14", "f6r2s15", "f6r2s16"] }, +{ "range": "R1", "col": ["f", "f", "f", "f", "f", "f", "f", "f", "", "f", "f", "f", "f", "f", "f", "f", "f"] } + ] + } +} diff --git a/scraper/examples/get_frontpage.rs b/scraper/examples/get_frontpage.rs index 5605e0d..33aefb7 100644 --- a/scraper/examples/get_frontpage.rs +++ b/scraper/examples/get_frontpage.rs @@ -1,4 +1,4 @@ -use froxy_scrapper::{state::State, types::ClusterLocation}; +use froxy_scraper::{state::State, types::ClusterLocation}; #[tokio::main(flavor = "current_thread")] async fn main() { @@ -10,12 +10,12 @@ async fn main() { let text = res.text().await.unwrap(); - let location = froxy_scrapper::parsing::get_cluster_location("F4", &text); + let location = froxy_scraper::parsing::get_cluster_location("F4", &text); for l in &location.locations { match &l.data { - froxy_scrapper::types::ClusterLocationData::Empty => {} - froxy_scrapper::types::ClusterLocationData::User { + froxy_scraper::types::ClusterLocationData::Empty => {} + froxy_scraper::types::ClusterLocationData::User { login, image, relation, @@ -29,7 +29,7 @@ async fn main() { .unwrap_or_else(|| "NO IMAGE".to_string()) ) } - froxy_scrapper::types::ClusterLocationData::Normal { status } => { + froxy_scraper::types::ClusterLocationData::Normal { status } => { // eprintln!("[{:<10}] {status:?}", l.location) } } diff --git a/server/Cargo.toml b/server/Cargo.toml index 50ee086..ad1d88d 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -21,3 +21,5 @@ froxy-scraper = { workspace = true } color-eyre = "0.6.5" cached = { version = "0.56.0", features = ["async", "async_tokio_rt_multi_thread"] } rustc-hash = "2.1.1" +serde_json = { version = "1.0.149", features = ["preserve_order"] } +indexmap = { version = "2.13.0", features = ["serde"] } diff --git a/server/src/cluster.rs b/server/src/cluster.rs new file mode 100644 index 0000000..7f4d9fc --- /dev/null +++ b/server/src/cluster.rs @@ -0,0 +1,119 @@ +use std::collections::HashMap; + +use axum::{ + Router, + extract::{Query, State}, + http::StatusCode, + response::Html, +}; +use froxy_scraper::types::{ClusterLocationData, ClusterLocationStatus}; +use froxy_templates::index::{ClusterData, LocationData, PcIssue}; +use indexmap::IndexMap; +use log::trace; +use serde::{Deserialize, Serialize}; +use smol_str::SmolStr; + +pub fn router() -> Router { + Router::new().route("/", axum::routing::get(handle_cluster)) +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +struct ClusterQuery { + cluster: Option, + p: Option, +} + +#[cfg_attr(debug_assertions, axum::debug_handler)] +async fn handle_cluster( + State(state): State, + Query(ClusterQuery { cluster, p }): Query, +) -> Result, StatusCode> { + let current_cluster = cluster.unwrap_or(SmolStr::new_static("f6")); + let map: HashMap = + serde_json::from_str(include_str!("../../mapping.json")).unwrap(); + + let res = state.scraper.get("/", Some("cluster=f6")).await.unwrap(); + let text = res.text().await.unwrap(); + let location = froxy_scraper::parsing::get_cluster_location("f6", &text); + + let issues: IndexMap<_, _> = location + .locations + .iter() + .filter(|s| matches!(s.data, ClusterLocationData::Normal { .. })) + .cloned() + .filter_map(|s| { + Some(( + s.location.clone(), + match s.data { + ClusterLocationData::Normal { + status: ClusterLocationStatus::Dead, + } => PcIssue::Dead, + ClusterLocationData::Normal { + status: ClusterLocationStatus::Damaged, + } => PcIssue::Attention, + _ => return None, + }, + )) + }) + .collect::<_>(); + + let loc: IndexMap<_, _> = location + .locations + .iter() + .filter(|s| matches!(s.data, ClusterLocationData::User { .. })) + .cloned() + .map(|s| { + let ClusterLocationData::User { + login, + image, + relation, + } = s.data + else { + unreachable!() + }; + ( + s.location.clone(), + LocationData { + login, + image: image.map(|u| u.to_string()).unwrap_or_default(), + me: matches!(relation, froxy_scraper::types::Relation::Me), + friend: matches!(relation, froxy_scraper::types::Relation::Friend), + close_friend: matches!(relation, froxy_scraper::types::Relation::CloseFriend), + pooled: matches!(relation, froxy_scraper::types::Relation::Pooled), + }, + ) + }) + .collect::<_>(); + + trace!("location: {loc:?}"); + + state + .render_index(froxy_templates::index::IndexData { + locations: loc, + clusters: [( + SmolStr::new_static("f6"), + ClusterData { + users: 10, + max_pc: map[&SmolStr::new_static("f6")] + .rows + .iter() + .flat_map(|s| s.col.iter()) + .filter(|s| matches!(s, froxy_templates::index::MapPos::Pc(_))) + .count() as u32, + silent: false, + piscine: false, + dead_pc: issues + .values() + .filter(|v| matches!(v, PcIssue::Dead)) + .count() as u32, + map: map[&SmolStr::new_static("f6")].clone(), + issues, + }, + )] + .into_iter() + .collect(), + current_cluster, + }) + .map_err(crate::report_error) + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR) +} diff --git a/server/src/main.rs b/server/src/main.rs index 4d1f10b..6a6f85b 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -36,6 +36,7 @@ use log::info; use tower_http::trace::TraceLayer; use tracing_subscriber::EnvFilter; +mod cluster; mod friends; mod state; mod static_; @@ -60,6 +61,7 @@ async fn main() { let global_state = GlobalState::new(); let app = Router::new() + .merge(cluster::router()) .merge(friends::router()) .merge(user::router()) .merge(static_::router(&global_state))