mirror of
https://git.funtimes909.xyz/ServerSeekerV2/ServerSeekerV2.git
synced 2026-10-10 12:13:08 +08:00
Continued work on everything.
Replace diesel with sqlx Cleaned up config.rs Slight changes to response handling (still needs a rewrite)
This commit is contained in:
Generated
+1443
-80
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -9,5 +9,5 @@ serde = { version = "1.0.217", features = ["derive"] }
|
||||
serde_json = "1.0.138"
|
||||
toml = "0.8.19"
|
||||
tokio = { version = "1.0.0", features = ["rt", "rt-multi-thread", "macros"] }
|
||||
diesel = { version = "2.2.7", features = ["postgres", "numeric"] }
|
||||
bigdecimal = "0.4.7"
|
||||
sqlx = { version = "0.8.3", features = ["postgres", "runtime-tokio"] }
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
# For documentation on how to configure this file,
|
||||
# see https://diesel.rs/guides/configuring-diesel-cli
|
||||
|
||||
[print_schema]
|
||||
file = "src/schema.rs"
|
||||
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
|
||||
|
||||
[migrations_directory]
|
||||
dir = "/home/funtimes909/Documents/Code/ServerSeekerV2-Rescanner/migrations"
|
||||
+7
-7
@@ -17,19 +17,19 @@ pub struct Database {
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Rescanner {
|
||||
pub rescan_delay: u16,
|
||||
pub speed: u16,
|
||||
pub repeat: bool,
|
||||
pub port_range: String
|
||||
pub rescan_delay: u16,
|
||||
pub port_range_start: u16,
|
||||
pub port_range_end: u16,
|
||||
}
|
||||
|
||||
impl Default for Rescanner {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
rescan_delay: 60,
|
||||
speed: 1000,
|
||||
repeat: true,
|
||||
port_range: "25560 - 25570".to_string()
|
||||
rescan_delay: 60,
|
||||
port_range_start: 25560,
|
||||
port_range_end: 25570,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,5 +47,5 @@ pub fn load_config(path: String) -> Config {
|
||||
let mut contents = String::new();
|
||||
file.read_to_string(&mut contents).unwrap_or_default();
|
||||
|
||||
toml::from_str(&contents).unwrap()
|
||||
toml::from_str(&contents).expect("Failed to parse config!")
|
||||
}
|
||||
+46
-4
@@ -1,7 +1,49 @@
|
||||
use sqlx::{Connection, Error, PgConnection, Postgres, QueryBuilder, Row};
|
||||
use sqlx::postgres::PgQueryResult;
|
||||
use crate::response::Server;
|
||||
use diesel::{Connection, PgConnection};
|
||||
use diesel::connection::SimpleConnection;
|
||||
|
||||
pub fn connect(database_url: &str) -> PgConnection {
|
||||
PgConnection::establish(&database_url).unwrap_or_else(|err| {panic!("Fatal Error! {}", err)})
|
||||
pub async fn connect(database_url: &str) -> PgConnection {
|
||||
PgConnection::connect(&database_url).await.unwrap()
|
||||
}
|
||||
|
||||
// TODO! Return a stream of results instead of a Vec for performance
|
||||
pub async fn fetch_servers(conn: &mut PgConnection) -> Vec<String> {
|
||||
// Sort results by
|
||||
sqlx::query("SELECT address FROM servers ORDER BY lastseen ASC")
|
||||
.fetch_all(conn)
|
||||
.await
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|row| {
|
||||
row.try_get(0).unwrap()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub async fn update_server(server: &Server, conn: &mut PgConnection, address: &str) -> Result<PgQueryResult, Error> {
|
||||
let mut query: QueryBuilder<Postgres> = QueryBuilder::new("UPDATE servers SET");
|
||||
|
||||
query.push(" version = ");
|
||||
query.push_bind(&server.version);
|
||||
|
||||
query.push(", protocol = ");
|
||||
query.push_bind(server.protocol);
|
||||
|
||||
query.push(", icon = ");
|
||||
query.push_bind(&server.icon);
|
||||
|
||||
query.push(", motd = ");
|
||||
query.push_bind(&server.motd);
|
||||
|
||||
query.push(", preventsreports = ");
|
||||
query.push_bind(server.prevents_reports);
|
||||
|
||||
query.push(", enforcesecure = ");
|
||||
query.push_bind(server.enforces_secure_chat);
|
||||
|
||||
query.push(" WHERE address = ");
|
||||
query.push_bind(address);
|
||||
|
||||
let mut query = query.build();
|
||||
query.execute(conn).await
|
||||
}
|
||||
+17
-11
@@ -2,15 +2,14 @@ mod database;
|
||||
mod config;
|
||||
mod ping;
|
||||
mod response;
|
||||
mod models;
|
||||
mod schema;
|
||||
|
||||
use std::io::Error;
|
||||
use config::{load_config, Config};
|
||||
use database::connect;
|
||||
use diesel::prelude::*;
|
||||
use std::io::{Read, Write};
|
||||
use std::str::FromStr;
|
||||
use crate::database::{connect, fetch_servers, update_server};
|
||||
use crate::ping::ping_server;
|
||||
use crate::response::Server;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
@@ -24,13 +23,20 @@ async fn main() {
|
||||
config.database.password,
|
||||
config.database.url);
|
||||
|
||||
// let address: &str = "192.168.1.220";
|
||||
let address: &str = "51.161.87.128";
|
||||
// let address: &str = "127.0.0.1";
|
||||
let port: u16 = 25565;
|
||||
let server = ping_server(&address, &port).await;
|
||||
let mut conn = connect(database_url.as_str()).await;
|
||||
let servers = fetch_servers(&mut conn).await;
|
||||
|
||||
if let Ok(server) = server {
|
||||
println!("Server {:?} responded! Version: {:?}, MOTD: {:?}, Chat Reports: {:?}", &address, &server.version, &server.motd, &server.prevents_reports);
|
||||
for address in servers {
|
||||
println!("Pinging: {}", &address);
|
||||
|
||||
let server_response: Result<Server, Error> = ping_server(&address, 25565u16).await;
|
||||
|
||||
if let Ok(server) = server_response {
|
||||
if let Err(error) = update_server(&server, &mut conn, &*address).await {
|
||||
println!("Failed to update server: {}", error);
|
||||
} else {
|
||||
println!("Server updated");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
use diesel::prelude::*;
|
||||
|
||||
#[derive(Queryable, Selectable)]
|
||||
#[diesel(table_name = crate::schema::servers)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
#[allow(dead_code)]
|
||||
pub struct Server {
|
||||
pub id: i32,
|
||||
pub address: String,
|
||||
pub port: bigdecimal::BigDecimal,
|
||||
pub firstseen: i32,
|
||||
pub lastseen: i32,
|
||||
pub country: String,
|
||||
pub asn: String,
|
||||
pub reversedns: String,
|
||||
pub organization: String,
|
||||
pub version: String,
|
||||
pub protocol: i32,
|
||||
pub fmlnetworkversion: i32,
|
||||
pub motd: String,
|
||||
pub icon: String,
|
||||
pub timesseen: i32,
|
||||
pub preventsreports: bool,
|
||||
pub enforcesecure: bool,
|
||||
pub whitelist: bool,
|
||||
pub cracked: bool,
|
||||
pub maxplayers: i32,
|
||||
pub onlineplayers: i32,
|
||||
pub software: String,
|
||||
}
|
||||
+2
-3
@@ -15,7 +15,7 @@ const REQUEST: [u8; 9] = [
|
||||
0, // ID
|
||||
];
|
||||
|
||||
pub async fn ping_server(address: &str, port: &u16) -> Result<Server, Error> {
|
||||
pub async fn ping_server(address: &str, port: u16) -> Result<Server, Error> {
|
||||
let address = format!("{}:{}", address, port);
|
||||
let socket = SocketAddr::from_str(address.as_str()).unwrap();
|
||||
|
||||
@@ -45,8 +45,7 @@ pub async fn ping_server(address: &str, port: &u16) -> Result<Server, Error> {
|
||||
let response: String = String::from_utf8_lossy(
|
||||
&out_buff[
|
||||
(buff_size.1 + 1 + json_bytes.1).into()
|
||||
..
|
||||
]
|
||||
..]
|
||||
).to_string();
|
||||
|
||||
Ok(parse_response(response.as_str())?)
|
||||
|
||||
+5
-60
@@ -1,6 +1,5 @@
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::str::FromStr;
|
||||
use diesel::row::NamedRow;
|
||||
use serde_json::Value;
|
||||
|
||||
pub struct Server {
|
||||
@@ -12,6 +11,8 @@ pub struct Server {
|
||||
pub enforces_secure_chat: Option<bool>,
|
||||
pub mods: Option<Vec<Mod>>,
|
||||
pub players: Option<Vec<Player>>,
|
||||
pub online_players: Option<i32>,
|
||||
pub max_players: Option<i32>,
|
||||
}
|
||||
|
||||
pub struct Player {
|
||||
@@ -25,53 +26,6 @@ pub struct Mod {
|
||||
pub mod_name: String,
|
||||
}
|
||||
|
||||
// Lifetimes *should* solve this mess
|
||||
// Recursive JSON array/object parser
|
||||
fn parse_motd(motd: &Value, mut current_motd: String) -> Result<String, Error> {
|
||||
let mut current_motd = current_motd.clone();
|
||||
|
||||
if let Some(object) = motd.as_object() {
|
||||
if object.contains_key("color") {
|
||||
¤t_motd.push_str(&object["color"].to_string());
|
||||
}
|
||||
|
||||
if object.contains_key("bold") {
|
||||
¤t_motd.push_str("§l");
|
||||
}
|
||||
|
||||
if object.contains_key("underlined") {
|
||||
¤t_motd.push_str("§n");
|
||||
}
|
||||
|
||||
if object.contains_key("text") {
|
||||
if let Some(text) = object["text"].as_str() {
|
||||
current_motd.push_str(text);
|
||||
}
|
||||
}
|
||||
|
||||
if object.contains_key("extra") {
|
||||
match object.get("extra") {
|
||||
Some(extra) => parse_motd(extra, current_motd.clone())?,
|
||||
None => Err(Error::new(ErrorKind::InvalidData, "Extra array malformed"))?,
|
||||
};
|
||||
}
|
||||
|
||||
Ok(current_motd)
|
||||
} else {
|
||||
if let Some(array) = motd.as_array() {
|
||||
for value in array {
|
||||
if value.is_object() || value.is_array() {
|
||||
parse_motd(value, current_motd.clone())?;
|
||||
} else {
|
||||
¤t_motd.push_str(value.as_str().unwrap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(current_motd)
|
||||
}
|
||||
}
|
||||
|
||||
// I no longer care about trying to make the parsing code good,
|
||||
// there is no proper standard for how servers should respond so this is what you get
|
||||
pub fn parse_response(response: &str) -> Result<Server, Error> {
|
||||
@@ -83,13 +37,9 @@ pub fn parse_response(response: &str) -> Result<Server, Error> {
|
||||
let mut version: Option<String> = None;
|
||||
let mut protocol: Option<i64> = None;
|
||||
let mut icon: Option<String> = None;
|
||||
let mut motd: Option<String> = None;
|
||||
let mut prevents_reports: Option<bool> = None;
|
||||
let mut enforces_secure_chat: Option<bool> = None;
|
||||
let mut mods: Option<Vec<Mod>> = None;
|
||||
let mut players: Option<Vec<Player>> = None;
|
||||
|
||||
// TODO! I think I can make this all better
|
||||
if let Some(value) = json.get("version") {
|
||||
if let Some(name) = value.get("name") {
|
||||
version = name.as_str().map(|s| s.to_string());
|
||||
@@ -104,13 +54,6 @@ pub fn parse_response(response: &str) -> Result<Server, Error> {
|
||||
icon = value.as_str().map(|s| s.to_string())
|
||||
}
|
||||
|
||||
if let Some(value) = json.get("description") {
|
||||
motd = match parse_motd(value, "".to_string()) {
|
||||
Ok(description) => Some(description),
|
||||
Err(_) => None,
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(value) = json.get("preventsChatReports") {
|
||||
prevents_reports = value.as_bool();
|
||||
}
|
||||
@@ -123,10 +66,12 @@ pub fn parse_response(response: &str) -> Result<Server, Error> {
|
||||
version,
|
||||
protocol,
|
||||
icon,
|
||||
motd,
|
||||
motd: None,
|
||||
prevents_reports,
|
||||
enforces_secure_chat,
|
||||
mods: None,
|
||||
players: None,
|
||||
online_players: None,
|
||||
max_players: None,
|
||||
})
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
diesel::table! {
|
||||
servers (id) {
|
||||
id -> Integer,
|
||||
address -> Text,
|
||||
port -> Numeric,
|
||||
firstseen -> Integer,
|
||||
lastseen -> Integer,
|
||||
country -> Text,
|
||||
asn -> Text,
|
||||
reversedns -> Text,
|
||||
organization -> Text,
|
||||
version -> Text,
|
||||
protocol -> Integer,
|
||||
fmlnetworkversion -> Integer,
|
||||
motd -> Text,
|
||||
icon -> Text,
|
||||
timesseen -> Integer,
|
||||
preventsreports -> Bool,
|
||||
enforcesecure -> Bool,
|
||||
whitelist -> Bool,
|
||||
cracked -> Bool,
|
||||
maxplayers -> Integer,
|
||||
onlineplayers -> Integer,
|
||||
#[sql_name = "type"]
|
||||
software -> Text,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user