From e57bb34a354713275a5466ba490ba41e3e74b516 Mon Sep 17 00:00:00 2001 From: Maieul BOYER Date: Sun, 8 Feb 2026 17:01:27 +0100 Subject: [PATCH] feat(scraper): getuser fetching done --- Cargo.lock | 22 ++++++++++ froxy-scraper/Cargo.toml | 5 ++- froxy-scraper/examples/get_frontpage.rs | 2 +- froxy-scraper/examples/get_user.rs | 14 +++++++ froxy-scraper/src/state.rs | 36 +++++++++++++++++ froxy-scraper/src/types.rs | 54 +++++++++++++++++++++++++ 6 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 froxy-scraper/examples/get_user.rs diff --git a/Cargo.lock b/Cargo.lock index 53505cb..0fe8edc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -276,7 +276,10 @@ dependencies = [ "reqwest", "scraper", "secrecy", + "serde", + "serde_json", "smol_str", + "thiserror 2.0.18", "tokio", "url", ] @@ -1305,6 +1308,19 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + [[package]] name = "servo_arc" version = "0.4.3" @@ -2197,3 +2213,9 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zmij" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445" diff --git a/froxy-scraper/Cargo.toml b/froxy-scraper/Cargo.toml index fcc1dc3..ef12a53 100644 --- a/froxy-scraper/Cargo.toml +++ b/froxy-scraper/Cargo.toml @@ -8,7 +8,10 @@ constcat = "0.6.1" reqwest = "0.13.1" scraper = "0.25.0" secrecy = "0.10.3" -smol_str = "0.3.5" +serde = { version = "1.0.228", features = ["derive"] } +serde_json = "1.0.149" +smol_str = { version = "0.3.5", features = ["serde"] } +thiserror = "2.0.18" url = "2.5.8" [dev-dependencies] diff --git a/froxy-scraper/examples/get_frontpage.rs b/froxy-scraper/examples/get_frontpage.rs index 89e6241..5605e0d 100644 --- a/froxy-scraper/examples/get_frontpage.rs +++ b/froxy-scraper/examples/get_frontpage.rs @@ -30,7 +30,7 @@ async fn main() { ) } froxy_scrapper::types::ClusterLocationData::Normal { status } => { - //eprintln!("[{:<10}] {status:?}", l.location) + // eprintln!("[{:<10}] {status:?}", l.location) } } } diff --git a/froxy-scraper/examples/get_user.rs b/froxy-scraper/examples/get_user.rs new file mode 100644 index 0000000..7dd6cfa --- /dev/null +++ b/froxy-scraper/examples/get_user.rs @@ -0,0 +1,14 @@ +use froxy_scrapper::{state::State, types::ClusterLocation}; + +#[tokio::main(flavor = "current_thread")] +async fn main() { + let session = std::env::var("FROXY_COOKIE") + .expect("provide `FROXY_COOKIE` with the session cookie from you friends42 instance"); + let state = State::new(session); + + for a in std::env::args().skip(1) { + let res = state.getuser(&a).await.unwrap(); + serde_json::to_writer_pretty(&mut std::io::stdout(), &res).unwrap(); + println!(); + } +} diff --git a/froxy-scraper/src/state.rs b/froxy-scraper/src/state.rs index 356e213..d675007 100644 --- a/froxy-scraper/src/state.rs +++ b/froxy-scraper/src/state.rs @@ -135,4 +135,40 @@ impl State { self.request(Method::POST, url.as_ref(), qs, Some(body)) .await } + + pub async fn getuser(&self, name: &str) -> Result, GetUserError> { + let req = self.get(format!("/getuser/{name}"), None).await?; + let text = req.text().await?; + let json = serde_json::from_str::(&text)?; + + Ok(Some(crate::types::Profile { + admin: json.admin, + campus: json.campus, + id: json.id, + userid: json.userid, + pool: json.pool.filter(|s| !s.contains("None")), + image: json.image, + image_medium: json.image_medium, + is_friend: match json.is_friend { + crate::types::IsFriend::U32(u) => u != 0, + crate::types::IsFriend::Bool(b) => b, + }, + lang: json.lang, + name: json.name, + position: json.position, + active: json.active, + website: json.website.filter(|s| !s.is_empty()), + recit: json.recit.filter(|s| !s.is_empty()), + discord: json.discord.filter(|s| !s.is_empty()), + github: json.github.filter(|s| !s.is_empty()), + })) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum GetUserError { + #[error("RequestError: {0}")] + RequestError(#[from] reqwest::Error), + #[error("JsonError: {0}")] + JsonError(#[from] serde_json::Error), } diff --git a/froxy-scraper/src/types.rs b/froxy-scraper/src/types.rs index 692b79e..5afda35 100644 --- a/froxy-scraper/src/types.rs +++ b/froxy-scraper/src/types.rs @@ -61,3 +61,57 @@ pub struct Friend { pub struct Friends { pub friends: Vec, } + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +#[serde(untagged)] +pub(crate) enum IsFriend { + U32(u32), + Bool(bool), +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub(crate) struct ProfileRaw { + pub(crate) admin: bool, + pub(crate) active: Option, + pub(crate) campus: u64, + pub(crate) id: u64, + pub(crate) userid: Option, + pub(crate) image: String, + pub(crate) image_medium: String, + pub(crate) is_friend: IsFriend, + pub(crate) lang: SmolStr, + pub(crate) name: SmolStr, + pub(crate) pool: Option, + pub(crate) position: Option, + + pub(crate) recit: Option, + pub(crate) website: Option, + pub(crate) discord: Option, + pub(crate) github: Option, +} + +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +pub struct Profile { + pub admin: bool, + + pub campus: u64, + pub id: u64, + pub userid: Option, + pub pool: Option, + + pub image: String, + pub image_medium: String, + + pub is_friend: bool, + + pub lang: SmolStr, + pub name: SmolStr, + + pub position: Option, + pub active: Option, + + pub website: Option, + pub recit: Option, + pub discord: Option, + pub github: Option, +}