diff --git a/Cargo.lock b/Cargo.lock index e58c42d..7a402b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,6 +49,7 @@ dependencies = [ "axum", "chrono", "lazy_static", + "openssl", "reqwest", "serde", "serde_json", @@ -842,6 +843,19 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" +dependencies = [ + "http", + "hyper", + "rustls 0.21.1", + "tokio", + "tokio-rustls 0.24.0", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -1143,6 +1157,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "openssl-src" +version = "111.25.0+1.1.1t" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3173cd3626c43e3854b1b727422a276e568d9ec5fe8cec197822cf52cfb743d6" +dependencies = [ + "cc", +] + [[package]] name = "openssl-sys" version = "0.9.77" @@ -1152,6 +1175,7 @@ dependencies = [ "autocfg", "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] @@ -1401,6 +1425,7 @@ dependencies = [ "http", "http-body", "hyper", + "hyper-rustls", "hyper-tls", "ipnet", "js-sys", @@ -1410,16 +1435,20 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls 0.21.1", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", + "tokio-rustls 0.24.0", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", "winreg", ] @@ -1450,6 +1479,18 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + [[package]] name = "rustls-pemfile" version = "1.0.1" @@ -1459,6 +1500,16 @@ dependencies = [ "base64 0.13.1", ] +[[package]] +name = "rustls-webpki" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.9" @@ -1705,7 +1756,7 @@ dependencies = [ "paste", "percent-encoding", "rand", - "rustls", + "rustls 0.20.7", "rustls-pemfile", "serde", "serde_json", @@ -1748,7 +1799,7 @@ checksum = "24c5b2d25fa654cc5f841750b8e1cdedbe21189bf9a9382ee90bfa9dd3562396" dependencies = [ "once_cell", "tokio", - "tokio-rustls", + "tokio-rustls 0.23.4", ] [[package]] @@ -1930,11 +1981,21 @@ version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ - "rustls", + "rustls 0.20.7", "tokio", "webpki", ] +[[package]] +name = "tokio-rustls" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5" +dependencies = [ + "rustls 0.21.1", + "tokio", +] + [[package]] name = "tokio-stream" version = "0.1.11" @@ -1954,9 +2015,9 @@ checksum = "54319c93411147bced34cb5609a80e0a8e44c5999c93903a81cd866630ec0bfd" dependencies = [ "futures-util", "log", - "rustls", + "rustls 0.20.7", "tokio", - "tokio-rustls", + "tokio-rustls 0.23.4", "tungstenite", "webpki", "webpki-roots", @@ -2072,7 +2133,7 @@ dependencies = [ "httparse", "log", "rand", - "rustls", + "rustls 0.20.7", "sha1", "thiserror", "url", diff --git a/services/api/Cargo.toml b/services/api/Cargo.toml index e849c91..92b5e99 100644 --- a/services/api/Cargo.toml +++ b/services/api/Cargo.toml @@ -14,5 +14,11 @@ sqlx = { version = "0.6.2", default_features = false, features = [ "runtime-toki tokio = { version = "1.24.2", features = ["macros", "rt-multi-thread"] } tower-http = { version = "0.3.5", features = ["cors"] } lazy_static = "1.4.0" -reqwest = "0.11.14" -chrono = "0.4.23" \ No newline at end of file +reqwest = { version = "0.11.14", features = ["rustls-tls-webpki-roots"] } +chrono = "0.4.23" + +[dependencies.openssl] +version = "0.10.29" +features = [ + "vendored" +] \ No newline at end of file diff --git a/services/api/src/analytics.rs b/services/api/src/analytics.rs index a1edb5f..1967569 100644 --- a/services/api/src/analytics.rs +++ b/services/api/src/analytics.rs @@ -24,7 +24,7 @@ impl Analytics { ) -> Vec { let pool = ctx.data::>().unwrap(); - let sql = format!("SELECT time_bucket_gapfill('{} seconds', time, start => now() - '{}'::interval, finish => now()) AS bucket, CASE WHEN count(*) IS NULL THEN 0 ELSE count(*) END AS count, event_name, world_id FROM analytics WHERE time > now() - '{}'::interval {} GROUP BY bucket, world_id, event_name ORDER BY bucket ASC", + let sql = format!("SELECT time_bucket_gapfill('{} seconds', time, start => now() - '{}'::interval, finish => now()) AS bucket, CASE WHEN count(*) IS NULL THEN 0 ELSE count(*) END AS count, event_name, world_id FROM analytics WHERE event_name IN ('Death', 'VehicleDestroy', 'GainExperience') AND time > now() - '{}'::interval {} GROUP BY bucket, world_id, event_name ORDER BY bucket ASC", if hi_precision { 5 } else { diff --git a/services/api/src/html/ingest.html b/services/api/src/html/ingest.html index ae5d958..5a68ff4 100644 --- a/services/api/src/html/ingest.html +++ b/services/api/src/html/ingest.html @@ -207,7 +207,7 @@ acc[ev.eventName][ev.time] = (acc[ev.time] || 0) + ev.count; return acc; }, - { Death: {}, VehicleDestroy: {} } + { Death: {}, VehicleDestroy: {}, GainExperience: {} } ); new Chart(document.getElementById(id), { @@ -228,6 +228,10 @@ label: "Vehicle Destroys", data: allEvents.VehicleDestroy, }, + { + label: "Experience Events", + data: allEvents.GainExperience, + }, ], }, }); diff --git a/services/websocket/src/main.rs b/services/websocket/src/main.rs index 465b83a..4fbd046 100644 --- a/services/websocket/src/main.rs +++ b/services/websocket/src/main.rs @@ -26,11 +26,20 @@ async fn send_init(tx: futures::channel::mpsc::UnboundedSender) { let worlds_raw = env::var("WORLDS").unwrap_or("all".to_string()); let worlds: Vec<&str> = worlds_raw.split(',').collect(); + let experience_ids = vec![5, 6, 7, 36, 53, 54, 201, 233, 293, 294, 353, 354, 355]; + let mut events = experience_ids + .iter() + .map(|id| format!("GainExperience_experience_id_{}", id)) + .collect::>(); + + events.push("Death".to_string()); + events.push("VehicleDestroy".to_string()); + // Send setup message let setup_msg = json!({ "action": "subscribe", "worlds": worlds, - "eventNames": ["Death", "VehicleDestroy"], + "eventNames": events, "characters": ["all"], "logicalAndCharactersWithWorlds": true, "service": "event", @@ -176,7 +185,7 @@ async fn track_analytics(analytics_event: AnalyticsEvent) { .unwrap(); } -async fn process_event(event: &Event) { +async fn process_death_event(event: &Event) { let mut set = JoinSet::new(); // println!("[ws/process_event] EVENT: {:?}", event); @@ -250,12 +259,57 @@ async fn process_event(event: &Event) { while let Some(_) = set.join_next().await {} } +async fn process_exp_event(event: &Event) { + let mut set = JoinSet::new(); + // println!("[ws/process_event] EVENT: {:?}", event); + + set.spawn(track_analytics(AnalyticsEvent { + world_id: event.world_id.clone(), + event_name: event.event_name.clone(), + })); + + set.spawn(track_class(ClassEvent { + world_id: event.world_id.clone(), + character_id: event.character_id.clone(), + loadout_id: event.loadout_id.clone(), + zone_id: event.zone_id.clone(), + team_id: event.team_id.clone(), + })); + + // Vehicle EXP events + match event.experience_id { + 201 => { + // Galaxy Spawn Bonus + set.spawn(track_vehicle(VehicleEvent { + world_id: event.world_id.clone(), + vehicle_id: "11".to_string(), + character_id: event.character_id.clone(), + zone_id: event.zone_id.clone(), + team_id: event.team_id.clone(), + })); + } + 233 => { + // Sunderer Spawn Bonus + set.spawn(track_vehicle(VehicleEvent { + world_id: event.world_id.clone(), + vehicle_id: "2".to_string(), + character_id: event.character_id.clone(), + zone_id: event.zone_id.clone(), + team_id: event.team_id.clone(), + })); + } + _ => {} + } + + while let Some(_) = set.join_next().await {} +} #[derive(Deserialize, Debug, Clone, Default)] struct Event { event_name: String, #[serde(deserialize_with = "deserialize_number_from_string")] world_id: i32, character_id: String, + #[serde(default)] attacker_character_id: String, #[serde(default, deserialize_with = "deserialize_number_from_string")] attacker_team_id: i32, @@ -275,6 +329,11 @@ struct Event { vehicle_id: String, #[serde(default)] attacker_vehicle_id: String, + + #[serde(default, deserialize_with = "deserialize_number_from_string")] + experience_id: i32, + #[serde(default)] + other_id: String, } #[derive(Deserialize, Debug, Clone)] @@ -336,7 +395,15 @@ async fn main() { return; } - process_event(&data.payload).await; + if data.payload.event_name == "Death" || data.payload.event_name == "VehicleDestroy" { + process_death_event(&data.payload).await; + return; + } + + if data.payload.event_name == "GainExperience" { + process_exp_event(&data.payload).await; + return; + } }) .fuse();