Huge refactor for server response parsing (still WIP)

This commit is contained in:
Funtimes909
2025-02-16 21:09:15 +13:00
parent e9ffab7130
commit aa06a5ebee
3 changed files with 84 additions and 63 deletions
+9 -6
View File
@@ -16,18 +16,21 @@ use crate::ping::ping_server;
async fn main() {
// Handle config file
let config_file: String = std::env::args().nth(1).unwrap_or("config.toml".to_string());
let config: Config = load_config(config_file);
let config: &Config = &load_config(config_file);
// Create database URL
let database_url = format!("postgresql://{}:{}@{}/postgres",
&config.database.user,
&config.database.password,
&config.database.url);
let mut conn: PgConnection = connect(&database_url);
config.database.user,
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;
if let Ok(server) = server {
println!("Server {:?} responded! Version: {:?}, MOTD: {:?}, Chat Reports: {:?}", &address, &server.version, &server.motd, &server.prevents_reports);
}
}
+1 -1
View File
@@ -49,7 +49,7 @@ pub async fn ping_server(address: &str, port: &u16) -> Result<Server, Error> {
]
).to_string();
Ok(parse_response(response.as_str()))
Ok(parse_response(response.as_str())?)
}
Err(_) => {
Err(Error::new(ErrorKind::NetworkUnreachable, "Server did not respond."))
+74 -56
View File
@@ -5,7 +5,7 @@ use serde_json::Value;
pub struct Server {
pub version: Option<String>,
pub protocol: Option<i32>,
pub protocol: Option<i64>,
pub icon: Option<String>,
pub motd: Option<String>,
pub prevents_reports: Option<bool>,
@@ -25,88 +25,106 @@ pub struct Mod {
pub mod_name: String,
}
// None values should insert NULL into the database if no value is found
impl Default for Server {
fn default() -> Self {
Server {
version: None,
protocol: None,
icon: None,
motd: None,
prevents_reports: None,
enforces_secure_chat: None,
mods: None,
players: None,
// 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") {
&current_motd.push_str(&object["color"].to_string());
}
}
}
// Lifetimes will solve this mess
fn parse_motd(motd: Value) -> Result<String, ErrorKind::InvalidData> {
if motd.is_array() {
for value in motd.as_array() {
// Recursion
if value.is_object() || value.is_array() {
parse_motd(value.clone())?;
} else {}
if object.contains_key("bold") {
&current_motd.push_str("§l");
}
} else {
if let Some(object) = motd.as_object() {
for value in object {
// Recursion
if value.is_object() || value.is_array() {
parse_motd(value.clone())?;
}
if let Some(color) = value.get("color") {}
if object.contains_key("underlined") {
&current_motd.push_str("§n");
}
if let Some(bold) = value.get("bold") {}
if let Some(text) = value.get("text") {}
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 {
&current_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> {
let json = Value::from_str(response)?;
let json = match Value::from_str(response) {
Ok(json) => json,
Err(err) => return Err(Error::new(ErrorKind::InvalidData, format!("{:?}", err)))
};
let mut version = ();
let mut protocol = ();
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) = json.get("name") {
version = version.as_str();
if let Some(name) = value.get("name") {
version = name.as_str().map(|s| s.to_string());
}
if let Some(value) = json.get("protocol") {
if let Some(value) = value.get("protocol") {
protocol = value.as_i64()
}
}
let protocol = json["version"]["protocol"].as_i64();
let icon = json["favicon"].to_string();
let prevents_reports = json["preventsReports"].as_bool();
let enforces_secure_chat = json["enforceSecure"].as_bool();
let motd: String;
if json["description"].is_object() {
// motd = parse_motd(json.get("description").clone(), &mut "".to_string());
} else {
motd = json.get("description").unwrap().to_string();
if let Some(value) = json.get("icon") {
icon = value.as_str().map(|s| s.to_string())
}
println!("{}", motd);
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();
}
if let Some(value) = json.get("enforceSecureChat") {
enforces_secure_chat = value.as_bool();
}
Ok(Server {
version: None,
protocol: None,
icon: None,
motd: None,
prevents_reports: None,
version,
protocol,
icon,
motd,
prevents_reports,
enforces_secure_chat,
mods: None,
players: None,