From 5a41d92319dd0b7dec3a65fabf045e36249d7c94 Mon Sep 17 00:00:00 2001 From: funtimes909 Date: Sat, 3 May 2025 18:49:33 +1200 Subject: [PATCH] Initial work to update code to use new database format --- Cargo.lock | 19 +++++++++++- Cargo.toml | 4 +-- src/database.rs | 77 ++++++++++++++++++++----------------------------- src/response.rs | 18 +++++++----- 4 files changed, 61 insertions(+), 57 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c8a9ba..f6cf8f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,6 @@ name = "ServerSeekerV2-Rust" version = "0.1.0" dependencies = [ "anyhow", - "futures-core", "futures-util", "indicatif", "serde", @@ -677,6 +676,12 @@ dependencies = [ "web-time", ] +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + [[package]] name = "itoa" version = "1.0.15" @@ -1266,6 +1271,7 @@ dependencies = [ "hashbrown", "hashlink", "indexmap", + "ipnet", "log", "memchr", "once_cell", @@ -1279,6 +1285,7 @@ dependencies = [ "tokio-stream", "tracing", "url", + "uuid", ] [[package]] @@ -1359,6 +1366,7 @@ dependencies = [ "stringprep", "thiserror", "tracing", + "uuid", "whoami", ] @@ -1382,6 +1390,7 @@ dependencies = [ "hkdf", "hmac", "home", + "ipnet", "itoa", "log", "md-5", @@ -1396,6 +1405,7 @@ dependencies = [ "stringprep", "thiserror", "tracing", + "uuid", "whoami", ] @@ -1421,6 +1431,7 @@ dependencies = [ "thiserror", "tracing", "url", + "uuid", ] [[package]] @@ -1737,6 +1748,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "uuid" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" + [[package]] name = "valuable" version = "0.1.1" diff --git a/Cargo.toml b/Cargo.toml index 2e111eb..04fcc30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,9 +13,8 @@ toml = "0.8" tokio = { version = "1", features = ["full"] } tracing = { version = "0.1", features = ["release_max_level_info"] } tracing-subscriber = "0.3" -sqlx = { version = "0.8", features = ["postgres", "runtime-tokio"] } +sqlx = { version = "0.8", features = ["postgres", "runtime-tokio", "ipnet", "uuid", "json"] } indicatif = { version = "0.17" } -futures-core = "0.3" futures-util = "0.3" anyhow = "1.0.98" @@ -23,3 +22,4 @@ anyhow = "1.0.98" strip = true lto = "fat" opt-level = 3 +codegen-units = 1 diff --git a/src/database.rs b/src/database.rs index 0072526..ebc0654 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,11 +1,12 @@ use crate::response::Server; use sqlx::postgres::PgRow; +use sqlx::types::ipnet::IpNet; +use sqlx::types::Uuid; use sqlx::{Error, PgConnection, Pool, Postgres}; use std::time::{SystemTime, UNIX_EPOCH}; -use tracing::{debug, info}; pub async fn fetch_servers(pool: &Pool) -> Vec { - sqlx::query("SELECT address FROM servers ORDER BY lastseen ASC") + sqlx::query("SELECT address FROM servers ORDER BY last_seen ASC") .fetch_all(pool) .await .expect("failed to fetch servers") @@ -16,86 +17,70 @@ pub async fn update( (address, port): &(String, u16), transaction: &mut PgConnection, ) -> Result<(), Error> { - // Remove from database if server has opted out - if server.check_opt_out() { - sqlx::query("DELETE FROM servers WHERE address = $1") - .bind(address) - .execute(&mut *transaction) - .await?; - - info!("Removing {address} from database due to opt-out"); - return Ok(()); - } + let (address, port) = ( + address.parse::().expect("Failed to parse address"), + *port as i32, + ); let timestamp = SystemTime::now() .duration_since(UNIX_EPOCH) .expect("system time is before the unix epoch") .as_secs() as i32; - // TODO: Can't be used in the database yet - // let server_type = server.get_type(); - - let description: String = match server.description { - Some(description) => description.into(), - None => { - debug!("Server {address} failed while updating database: Missing MOTD"); - return Ok(()); - } - }; - // Update server sqlx::query( "UPDATE servers SET version = $1, protocol = $2, icon = $3, - motd = $4, - preventsreports = $5, - enforcesecure = $6, - lastseen = $7, - onlineplayers = $8, - maxplayers = $9 + description = $4, + prevents_chat_reports = $5, + enforces_secure_chat = $6, + last_seen = $7, + online_players = $8, + max_players = $9 WHERE address = $10 AND port = $11", ) + .bind(address) + .bind(port) .bind(server.version.name) .bind(server.version.protocol) .bind(server.favicon) - .bind(description) + .bind(server.description) .bind(server.prevents_reports) .bind(server.enforces_secure_chat) .bind(timestamp) .bind(server.players.online) .bind(server.players.max) - .bind(address) - .bind(*port as i64) .execute(&mut *transaction) .await?; // Update players if let Some(sample) = server.players.sample { for player in sample { - sqlx::query("INSERT INTO playerhistory (address, port, playeruuid, playername, firstseen, lastseen) VALUES ($1, $2, $3, $4, $5, $6) - ON CONFLICT (address, port, playeruuid) DO UPDATE SET - lastseen = EXCLUDED.lastseen, - playername = EXCLUDED.playername") - .bind(address) - .bind(*port as i64) - .bind(player.id) - .bind(player.name) - .bind(timestamp) - .bind(timestamp) - .execute(&mut *transaction) - .await?; + if let Ok(uuid) = Uuid::parse_str(&player.id) { + sqlx::query("INSERT INTO players (address, port, uuid, name, first_seen, last_seen) VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT (address, port, uuid) DO UPDATE SET + last_seen = EXCLUDED.last_seen") + .bind(address) + .bind(port) + .bind(uuid) + .bind(player.name) + .bind(timestamp) + .bind(timestamp) + .execute(&mut *transaction) + .await?; + } } } // Update mods if let Some(mods_sample) = server.forge_data { for mods in mods_sample.mods { - sqlx::query("INSERT INTO mods (address, port, modid, modmarker) VALUES ($1, $2, $3, $4) ON CONFLICT (address, port, modid) DO NOTHING") + sqlx::query("INSERT INTO mods (address, port, id, mod_marker) VALUES ($1, $2, $3, $4) ON CONFLICT (address, port, id) DO NOTHING") .bind(address) - .bind(*port as i64) + .bind(port) .bind(mods.id) .bind(mods.marker) .bind(timestamp) diff --git a/src/response.rs b/src/response.rs index f85b8b9..b07ccf8 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,7 +1,9 @@ use crate::config::PlayerTracking; use serde::Deserialize; +use serde_json::Value; -#[derive(Debug)] +#[derive(Debug, sqlx::Type)] +#[sqlx(type_name = "software")] pub enum ServerType { Java, Neoforge, @@ -24,7 +26,7 @@ pub struct Server { pub version: Version, pub favicon: Option, pub players: Players, - pub description: Option, + pub description: Option, #[serde(rename = "preventsChatReports")] pub prevents_reports: Option, #[serde(rename = "enforcesSecureChat")] @@ -126,12 +128,12 @@ impl Server { } // Has the user opted out of scanning? - pub fn check_opt_out(&self) -> bool { - match &self.description { - Some(description) => String::from(description.clone()).contains("§b§d§f§d§b"), - None => false, - } - } + // pub fn check_opt_out(&self) -> bool { + // match &self.description { + // Some(description) => String::from(description.clone()).contains("§b§d§f§d§b"), + // None => false, + // } + // } } impl Players {