141 lines
3.9 KiB
Rust
141 lines
3.9 KiB
Rust
use reqwest::{header::HeaderValue, Client};
|
|
use serde::Deserialize;
|
|
use url::Url;
|
|
|
|
use crate::types::{PlayerList, ServerInfo, ServerOnlineResponse, ServerResponse};
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
struct ApiResponse {
|
|
online: bool,
|
|
version: Option<String>,
|
|
players: Option<ApiResponsePlayers>,
|
|
motd: Option<Motd>,
|
|
}
|
|
|
|
#[derive(Deserialize, Debug, Clone)]
|
|
struct ApiResponsePlayers {
|
|
online: u64,
|
|
max: u64,
|
|
list: Option<Vec<ApiResponsePlayerEntry>>,
|
|
}
|
|
|
|
#[derive(Deserialize, Debug, Clone)]
|
|
struct ApiResponsePlayerEntry {
|
|
name: String,
|
|
#[allow(dead_code)]
|
|
uuid: String,
|
|
}
|
|
|
|
#[derive(Deserialize, Debug)]
|
|
#[allow(dead_code)]
|
|
struct Motd {
|
|
raw: Vec<String>,
|
|
clean: Vec<String>,
|
|
html: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
#[allow(dead_code)]
|
|
pub struct OnlineResponse {
|
|
searchable_name: String,
|
|
reported_name: String,
|
|
clean_name: String,
|
|
players_online: u64,
|
|
player_limit: u64,
|
|
version: String,
|
|
players: Vec<String>,
|
|
}
|
|
|
|
impl ServerOnlineResponse for OnlineResponse {
|
|
fn players_online(&self) -> u64 {
|
|
self.players_online
|
|
}
|
|
|
|
fn player_limit(&self) -> u64 {
|
|
self.player_limit
|
|
}
|
|
|
|
fn version(&self) -> &String {
|
|
&self.version
|
|
}
|
|
|
|
fn readable_name(&self) -> &String {
|
|
&self.clean_name
|
|
}
|
|
|
|
fn searchable_name(&self) -> &String {
|
|
&self.searchable_name
|
|
}
|
|
}
|
|
|
|
impl PlayerList for OnlineResponse {
|
|
fn players(&self) -> &Vec<String> {
|
|
&self.players
|
|
}
|
|
}
|
|
|
|
pub struct Server {
|
|
#[allow(dead_code)]
|
|
token: String,
|
|
addr: Url,
|
|
}
|
|
|
|
impl ServerInfo for Server {
|
|
fn new(token: String, addr: Url) -> Self {
|
|
Server { token, addr }
|
|
}
|
|
|
|
type OnlineResponse = OnlineResponse;
|
|
|
|
type AddressableName = Url;
|
|
|
|
fn addressable_name(&self) -> &Self::AddressableName {
|
|
&self.addr
|
|
}
|
|
|
|
fn app_token(&self) -> String {
|
|
self.token.clone()
|
|
}
|
|
|
|
async fn poll(&self) -> ServerResponse<Self::OnlineResponse> {
|
|
use reqwest;
|
|
let url_string = format!("https://api.mcsrvstat.us/3/{}", self.addr.host().unwrap());
|
|
let url = Url::try_from(url_string.as_str()).unwrap();
|
|
let mut request = reqwest::Request::new(reqwest::Method::GET, url);
|
|
request.headers_mut().append("User-Agent", HeaderValue::from_str("Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Mobile Safari/537.36").unwrap());
|
|
|
|
let client = Client::new();
|
|
|
|
match client.execute(request).await {
|
|
Err(error) => ServerResponse::Error(anyhow::anyhow!(error)),
|
|
Ok(answer) => {
|
|
let json = answer.json::<ApiResponse>().await.unwrap();
|
|
//println!("{}", answer.text().await.unwrap());
|
|
//ServerResponse::Offline
|
|
|
|
match json.online {
|
|
true => {
|
|
let players = json.players.unwrap();
|
|
let motd = json.motd.as_ref().unwrap();
|
|
self::ServerResponse::Online(OnlineResponse {
|
|
searchable_name: self.addr.host().unwrap().to_string(),
|
|
reported_name: motd.clean.first().unwrap().into(),
|
|
clean_name: motd.clean.first().unwrap().into(),
|
|
players_online: players.online,
|
|
player_limit: players.max,
|
|
version: json.version.unwrap(),
|
|
players: players
|
|
.list
|
|
.unwrap_or(Vec::<ApiResponsePlayerEntry>::new())
|
|
.iter()
|
|
.map(|e| e.name.clone())
|
|
.collect(),
|
|
})
|
|
}
|
|
false => ServerResponse::Offline,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|