use hyper::{Body, Request, Response, Server, service::{make_service_fn, service_fn}}; use serde_json::Value; use std::collections::HashMap; use std::sync::{Arc, Mutex}; use serde::{Deserialize, Serialize}; use webhook::client::WebhookClient; use std::error::Error; const IMAGE_URL: &str = "https://www.counter-strike.net/favicon.ico"; #[derive(Debug, Deserialize)] struct MatchData { map: Option, round: Option, player_id: Option, player_state: Option, player_weapons: Option, player_match_stats: Option, allplayers_id: Option, } #[derive(Debug, Deserialize)] struct MapData { name: Option, } #[derive(Debug, Deserialize)] struct RoundData { phase: Option, } #[derive(Debug, Deserialize)] struct PlayerIdData { id: Option, } #[derive(Debug, Deserialize)] struct PlayerStateData { health: Option, armor: Option, flashed: Option, } #[derive(Debug, Deserialize)] struct PlayerWeaponsData { primary: Option, secondary: Option, } #[derive(Debug, Deserialize)] struct PlayerMatchStatsData { kills: Option, deaths: Option, } #[derive(Debug, Deserialize)] struct AllPlayersIdData { players: Vec, } #[derive(Serialize)] struct Message { content: String, } // Define the state type type State = Arc>>>; async fn handle_request(req: Request, state: State) -> Result, Box> { if req.method() == hyper::Method::POST { let whole_body = hyper::body::to_bytes(req.into_body()).await?; // Attempt to parse the JSON match serde_json::from_slice::(&whole_body) { Ok(json) => { // Print the raw JSON for debugging // println!("Received JSON: {}", json); // Lock the state for reading and writing let mut previous_state = state.lock().unwrap(); // Check if the JSON value is an object if let Some(map) = json.as_object() { if let Some(player) = map.get("player") { if let Some(player_obj) = player.as_object() { // Extract weapon information if let Some(weapons) = player_obj.get("weapons") { if let Some(weapons_obj) = weapons.as_object() { for (weapon_key, weapon_value) in weapons_obj { if let Some(weapon_obj) = weapon_value.as_object() { if let Some(name) = weapon_obj.get("name") { if let Some(name_str) = name.as_str() { if let Some(ammo_clip) = weapon_obj.get("ammo_clip") { if let Some(ammo_clip_value) = ammo_clip.as_i64() { // Update previous state let mut weapon_state = previous_state.entry(weapon_key.clone()).or_insert_with(HashMap::new); let prev_ammo_clip = weapon_state.entry("ammo_clip".to_string()).or_insert(0); // Print debug information println!("Weapon: {}, Ammo Clip (prev): {}, Ammo Clip (current): {}", name_str, prev_ammo_clip, ammo_clip_value); // Compare ammo_clip with previous state if ammo_clip_value < *prev_ammo_clip { println!("Weapon {}: {} fired! Ammo Clip: {} -> {}", weapon_key, name_str, prev_ammo_clip, ammo_clip_value); let url = "https://discord.com/api/webhooks/1277517311347261470/4-UgsyHK3-AcWai9xWsOMHkpnpAHuFc0Izp3fRCb7M0NaHNng9h6tKmS3x_k4X-4tdMS"; // Send the webhook message in an async block let client = WebhookClient::new(&url); let webhook_info = client.get_information().await?; println!("webhook: {:?}", webhook_info); client.send(|message| message .content("@everyone") .username("Thoo") .avatar_url(IMAGE_URL) .embed(|embed| embed .title("Webhook") .description("Hello, World!") .footer("Footer", Some(String::from(IMAGE_URL))) .image(IMAGE_URL) .thumbnail(IMAGE_URL) .author("Lmao#0001", Some(String::from(IMAGE_URL)), Some(String::from(IMAGE_URL))) .field("name", "value", false))).await?; } // Update previous ammo_clip *prev_ammo_clip = ammo_clip_value; } else { println!("Ammo clip is not an integer for weapon {}", name_str); } } else { println!("Ammo clip field is missing for weapon {}", name_str); } } else { println!("Weapon name is not a string"); } } else { println!("Weapon object does not contain a name field"); } } else { println!("Weapon value is not an object"); } } } else { println!("Weapons field is not an object"); } } else { println!("Player object does not contain weapons field"); } } else { println!("Player field is not an object"); } } else { println!("JSON does not contain player field"); } } else { println!("JSON is not an object"); } Ok(Response::new(Body::from("Received"))) }, Err(e) => { eprintln!("Failed to parse JSON: {}", e); Ok(Response::new(Body::from("Invalid JSON"))) } } } else { Ok(Response::new(Body::from("Unsupported HTTP method"))) } } #[tokio::main] async fn main() { // Initialize the global state let state = Arc::new(Mutex::new(HashMap::new())); let make_svc = make_service_fn(move |_conn| { let state = state.clone(); async move { Ok::<_, Box>(service_fn(move |req| handle_request(req, state.clone()))) } }); let addr = ([0, 0, 0, 0], 5000).into(); // Listen on all interfaces on port 5000 let server = Server::bind(&addr).serve(make_svc); println!("Listening on http://{}", addr); if let Err(e) = server.await { eprintln!("server error: {}", e); } }