From 567476e0838267c8bd1f690ff2076efcd8698e76 Mon Sep 17 00:00:00 2001 From: funtimes909 Date: Sun, 4 May 2025 00:52:10 +1200 Subject: [PATCH] ServerType enum now imports server software type into database --- src/database.rs | 72 +++++++++++++++++++++++++++---------------------- src/scan.rs | 3 ++- src/utils.rs | 5 ++-- 3 files changed, 44 insertions(+), 36 deletions(-) diff --git a/src/database.rs b/src/database.rs index ebc0654..1353822 100644 --- a/src/database.rs +++ b/src/database.rs @@ -2,11 +2,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 sqlx::{PgConnection, Pool, Postgres}; +use std::str::FromStr; use std::time::{SystemTime, UNIX_EPOCH}; pub async fn fetch_servers(pool: &Pool) -> Vec { - sqlx::query("SELECT address FROM servers ORDER BY last_seen ASC") + sqlx::query("SELECT address FROM servers ORDER BY last_seen ASC LIMIT 30") .fetch_all(pool) .await .expect("failed to fetch servers") @@ -16,34 +17,42 @@ pub async fn update( server: Server, (address, port): &(String, u16), transaction: &mut PgConnection, -) -> Result<(), Error> { - let (address, port) = ( - address.parse::().expect("Failed to parse address"), - *port as i32, - ); +) -> anyhow::Result<()> { + let port = *port as i32; + // SQLx requires each IP address to be in CIDR notation to add to Postgres + let address = IpNet::from_str((address.to_owned() + "/32").as_str())?; + let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i32; - let timestamp = SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("system time is before the unix epoch") - .as_secs() as i32; - - // Update server sqlx::query( - "UPDATE servers SET - version = $1, - protocol = $2, - icon = $3, - 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", + "INSERT INTO servers ( + address, + port, + software, + version, + protocol, + icon, + description, + prevents_chat_reports, + enforces_secure_chat, + first_seen, + last_seen, + online_players, + max_players) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) + ON CONFLICT (address, port) DO UPDATE SET + software = EXCLUDED.software, + version = EXCLUDED.version, + protocol = EXCLUDED.protocol, + icon = EXCLUDED.icon, + description = EXCLUDED.description, + prevents_chat_reports = EXCLUDED.prevents_chat_reports, + enforces_secure_chat = EXCLUDED.enforces_secure_chat, + last_seen = EXCLUDED.last_seen, + online_players = EXCLUDED.online_players, + max_players = EXCLUDED.max_players", ) - .bind(address) + .bind(&address) .bind(port) + .bind(server.get_type()) .bind(server.version.name) .bind(server.version.protocol) .bind(server.favicon) @@ -51,19 +60,19 @@ pub async fn update( .bind(server.prevents_reports) .bind(server.enforces_secure_chat) .bind(timestamp) + .bind(timestamp) .bind(server.players.online) .bind(server.players.max) .execute(&mut *transaction) .await?; - // Update players if let Some(sample) = server.players.sample { for player in sample { 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) + ON CONFLICT (address, port, uuid) DO UPDATE SET + last_seen = EXCLUDED.last_seen") + .bind(&address) .bind(port) .bind(uuid) .bind(player.name) @@ -75,11 +84,10 @@ pub async fn update( } } - // Update mods if let Some(mods_sample) = server.forge_data { for mods in mods_sample.mods { 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(&address) .bind(port) .bind(mods.id) .bind(mods.marker) diff --git a/src/scan.rs b/src/scan.rs index 9286708..023beef 100644 --- a/src/scan.rs +++ b/src/scan.rs @@ -3,6 +3,7 @@ use crate::utils::handle_scan_results; use crate::{database, utils}; use futures_util::future::join_all; use indicatif::{ProgressBar, ProgressStyle}; +use sqlx::types::ipnet::IpNet; use sqlx::{Pool, Postgres, Row}; use std::sync::Arc; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -36,7 +37,7 @@ pub async fn rescan_servers(pool: Pool, config: Config, style: Progres .as_secs(); for row in servers { - let address = row.get::(0); + let address = row.get::(0).addr().to_string(); (port_start..=port_end).into_iter().for_each(|port| { handles.push(task::spawn(utils::run( diff --git a/src/utils.rs b/src/utils.rs index 6c3e1c5..d120cc5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -40,7 +40,7 @@ pub async fn handle_scan_results( warn!("{} I/0 Errors", counts[1]); warn!("{} malformed responses", counts[2]); warn!("{} errors while parsing responses", counts[3]); - warn!("{} errors while connecting (timeouts)", counts[4]); + warn!("{} servers timed out", counts[4]); } // Transactions allow adding multiple statements to a single query @@ -53,8 +53,7 @@ pub async fn handle_scan_results( .filter_map(Result::ok) .collect::>(); - info!("Attempting to commit results to DB, This could take a really long time"); - + info!("Commiting results to database..."); let bar = ProgressBar::new(completed_servers.len() as u64).with_style(style); for server in completed_servers.into_iter().progress_with(bar) {