use reqwest::Client as HTTPClient; use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION, CONTENT_TYPE}; use serde_json::{Value, json}; use std::collections::HashMap; use std::error::Error; use std::env; pub async fn get_auth_id(token: &str) -> Result> { let auth_api_base = env::var("AUTH_URL")?; let (query_name, query_type) = match auth_api_base.contains("auth.discours.io") { _ => ("getSession", "mutation"), // v2 true => ("session", "query") // authorizer }; let operation = "GetUserId"; let mut headers = HeaderMap::new(); headers.insert(AUTHORIZATION, HeaderValue::from_str(token)?); headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json")); let gql = json!({ "query": format!("{} {} {{ {} {{ user {{ id }} }} }}", query_type, operation, query_name), "operationName": operation, "variables": HashMap::::new() }); let client = reqwest::Client::new(); let response = client.post(&auth_api_base) .headers(headers) .json(&gql) .send() .await?; if response.status().is_success() { let r: HashMap = response.json().await?; let user_id = r.get("data") .and_then(|data| data.get(query_name)) .and_then(|query| query.get("user")) .and_then(|user| user.get("id")) .and_then(|id| id.as_i64()); match user_id { Some(id) => { println!("User ID retrieved: {}", id); Ok(id as i32) }, None => { println!("No user ID found in the response"); Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "No user ID found in the response"))) } } } else { println!("Request failed with status: {}", response.status()); Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, format!("Request failed with status: {}", response.status())))) } } async fn get_shout_followers(shout_id: &str) -> Result, Box> { let api_base = env::var("API_BASE")?; let query = r#"query ShoutFollowers($shout: Int!) { shoutFollowers(shout: $shout) { follower { id } } } "#; let shout_id = shout_id.parse::()?; let variables = json!({ "shout": shout_id }); let body = json!({ "query": query, "operationName": "ShoutFollowers", "variables": variables }); let client = reqwest::Client::new(); let response = client .post(&api_base) .json(&body) .send() .await?; if response.status().is_success() { let response_body: serde_json::Value = response.json().await?; let ids: Vec = response_body["data"]["shoutFollowers"] .as_array() .ok_or("Failed to parse follower array")? .iter() .filter_map(|f| f["follower"]["id"].as_i64().map(|id| id as i32)) .collect(); Ok(ids) } else { println!("Request failed with status: {}", response.status()); Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, format!("Request failed with status: {}", response.status())))) } } pub async fn is_fitting(listener_id: i32, payload: HashMap) -> Result { match payload.get("kind") { Some(kind) => { match kind.as_str() { "new_follower" => { // payload is AuthorFollower Ok(payload.get("author").unwrap().to_string() == listener_id.to_string()) }, "new_reaction" => { // payload is Reaction let shout_id = payload.get("shout").unwrap(); let recipients = get_shout_followers(shout_id).await.unwrap(); Ok(recipients.contains(&listener_id)) }, "new_shout" => { // payload is Shout // TODO: check all community subscribers if no then // check all topics subscribers if no then // check all authors subscribers Ok(true) }, "new_message" => { // payload is Chat let members_str = payload.get("members").unwrap(); let members = serde_json::from_str::>(members_str).unwrap(); Ok(members.contains(&listener_id.to_string())) }, _ => { eprintln!("unknown payload kind"); eprintln!("{:?}", payload); Ok(false) }, } }, None => { eprintln!("payload has no kind"); eprintln!("{:?}", payload); Ok(false) }, } }