browser-friendly frontend :3
This commit is contained in:
parent
bac3204572
commit
6bd7379df3
5 changed files with 259 additions and 46 deletions
191
src/main.rs
191
src/main.rs
|
|
@ -1,10 +1,18 @@
|
|||
use std::io::{Result};
|
||||
use std::net::{ToSocketAddrs};
|
||||
use std::env;
|
||||
use std::{env, fs};
|
||||
|
||||
use mcstatusface::http::{HttpServer, StatusCode};
|
||||
use mcstatusface::{MinecraftStatus};
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct MinecraftStatusResponse<'a> {
|
||||
version: &'a String,
|
||||
players: u32,
|
||||
max_players: u32,
|
||||
motd: String,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
if args.len() < 2 {
|
||||
|
|
@ -41,6 +49,7 @@ env!("CARGO_PKG_VERSION"));
|
|||
|
||||
HttpServer::new(address, 64).start(|request, mut response| {
|
||||
response.status(StatusCode::OK);
|
||||
response.set_header("Content-Type", "text/plain".to_string());
|
||||
response.set_header("x-powered-by", "GIRL FUEL".to_string());
|
||||
|
||||
if request.method() != "GET" {
|
||||
|
|
@ -48,51 +57,149 @@ env!("CARGO_PKG_VERSION"));
|
|||
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());
|
||||
if request.path() == "/style/index.css" {
|
||||
match fs::read_to_string("./public/style/index.css") {
|
||||
Ok(content) => {
|
||||
response.set_header("Content-Type", "text/css".to_string());
|
||||
response.status(StatusCode::OK);
|
||||
response.body(content.to_string());
|
||||
return response.send();
|
||||
}
|
||||
Err(err) => {
|
||||
eprint!("failed to load index.css: {}\n", err.to_string());
|
||||
response.status(StatusCode::InternalServerError);
|
||||
response.body("Internal Server Error\n".to_string());
|
||||
return response.send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.send()
|
||||
if request.path() == "/" {
|
||||
if request.headers().get("Accept").is_some_and(
|
||||
|accept| accept.contains("text/html")
|
||||
) {
|
||||
// HTML response
|
||||
match fs::read_to_string("./views/index.html") {
|
||||
Ok(mut content) => {
|
||||
response.set_header("Content-Type", "text/html".to_string());
|
||||
response.status(StatusCode::OK);
|
||||
let query_response: String;
|
||||
match request.query().get("s") {
|
||||
Some(query_address) => {
|
||||
let mut address = query_address.to_string();
|
||||
if !address.contains(":") { address.push_str(":25565"); }
|
||||
match address.to_socket_addrs() {
|
||||
Err(_) => {
|
||||
response.set_header("Content-Type", "text/html".to_string());
|
||||
response.status(StatusCode::BadRequest);
|
||||
response.body("Server address is invalid or unreachable.\n".to_string());
|
||||
return response.send();
|
||||
}
|
||||
Ok(mut addrs_iter) => {
|
||||
let address = addrs_iter.next().unwrap();
|
||||
|
||||
let status = MinecraftStatus::fetch(address).unwrap();
|
||||
|
||||
let minecraft_status = MinecraftStatusResponse{
|
||||
version: &status.version.name,
|
||||
players: status.players.online,
|
||||
max_players: status.players.max,
|
||||
motd: status.parse_description(),
|
||||
};
|
||||
|
||||
query_response = format!(
|
||||
"<hr/>
|
||||
<h2>Server Details</h2>
|
||||
<p>
|
||||
<strong>Version:</strong> <code>{}</code><br/>
|
||||
<strong>Players:</strong> <code>{}/{}</code><br/>
|
||||
<strong>MOTD:</strong>
|
||||
</p>
|
||||
<pre><code id=\"motd\">{}</code></pre>",
|
||||
sanitize_html(minecraft_status.version).to_string(),
|
||||
minecraft_status.players,
|
||||
minecraft_status.max_players,
|
||||
sanitize_html(&minecraft_status.motd).to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
query_response = String::from("");
|
||||
}
|
||||
}
|
||||
|
||||
content = content
|
||||
.replace("{{response}}", &query_response)
|
||||
.replace("{{host}}", match request.headers().get("Host") {
|
||||
Some(host) => { host }
|
||||
None => { "mcq.bliss.town" }
|
||||
});
|
||||
response.body(content.to_string());
|
||||
return response.send();
|
||||
}
|
||||
Err(err) => {
|
||||
eprint!("failed to load index.html: {}\n", err.to_string());
|
||||
response.status(StatusCode::InternalServerError);
|
||||
response.body("Internal Server Error\n".to_string());
|
||||
return response.send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// JSON response
|
||||
match request.query().get("s") {
|
||||
None => {
|
||||
response.status(StatusCode::BadRequest);
|
||||
response.body("?s=<server address>\n".to_string());
|
||||
return response.send();
|
||||
}
|
||||
Some(query_address) => {
|
||||
let mut address = query_address.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();
|
||||
|
||||
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 + "\n");
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Request to {address} failed: {e}");
|
||||
response.status(StatusCode::InternalServerError);
|
||||
response.body("Unable to reach the requested server.\n".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
return response.send()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.status(StatusCode::NotFound);
|
||||
response.body("Not Found".to_string());
|
||||
return response.send();
|
||||
}).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sanitize_html(input: &String) -> String {
|
||||
input
|
||||
.replace("&", "&")
|
||||
.replace("<", "<")
|
||||
.replace(">", ">")
|
||||
.replace("\"", """)
|
||||
.replace("'", "'")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue