mcstatusface/src/main.rs

92 lines
3 KiB
Rust

use std::io::{Result};
use std::net::{ToSocketAddrs};
use std::env;
use mcstatusface::http::{HttpServer, StatusCode};
use mcstatusface::{MinecraftStatus};
fn main() -> Result<()> {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("Usage: {} [serve] <address[:port]>", args[0]);
std::process::exit(1);
}
if args[1] != "serve" {
let mut address = String::from(args[1].as_str());
if !address.contains(":") {
address += ":25565";
}
let mut addrs_iter = args[1].to_socket_addrs().unwrap();
let address = addrs_iter.next().unwrap();
let status = MinecraftStatus::fetch(address).unwrap();
println!("\nVersion: {} ({})", status.version.name, status.version.protocol);
println!("Players: {}/{}", status.players.online, status.players.max);
println!("MOTD:");
println!("{}", status.parse_description());
return Ok(());
}
let mut address = "0.0.0.0:8080".to_string();
if args.len() > 2 { address = args[2].to_string() }
HttpServer::new(address, 64).start(|request, mut response| {
response.status(StatusCode::OK);
response.set_header("x-powered-by", "GIRL FUEL".to_string());
if request.method() != "GET" {
response.status(StatusCode::NotFound);
return response.send()
}
if !request.query().contains_key("s") {
response.status(StatusCode::BadRequest);
// TODO: nice index landing page for browsers
response.body("?s=<server address>\n".to_string());
return response.send()
}
let mut address = request.query().get("s").unwrap().to_string();
if !address.contains(":") { address.push_str(":25565"); }
let mut addrs_iter = address.to_socket_addrs().unwrap();
let address = addrs_iter.next().unwrap();
let status = MinecraftStatus::fetch(address).unwrap();
#[derive(serde::Serialize)]
struct MinecraftStatusResponse<'a> {
version: &'a String,
players: u32,
max_players: u32,
motd: String,
}
let minecraft_status = MinecraftStatusResponse{
version: &status.version.name,
players: status.players.online,
max_players: status.players.max,
motd: status.parse_description(),
};
match serde_json::to_string(&minecraft_status) {
Ok(json) => {
response.status(StatusCode::OK);
response.set_header("Content-Type", "application/json".to_string());
response.body(json);
}
Err(e) => {
eprintln!("Request to {address} failed: {e}");
response.status(StatusCode::InternalServerError);
response.set_header("Content-Type", "text/plain".to_string());
response.body("Unable to reach the requested server.\n".to_string());
}
}
response.send()
}).unwrap();
Ok(())
}