Player list support

This commit is contained in:
August 2026-05-06 15:09:36 -04:00
parent c56f4c7772
commit a493259f7f
Signed by: shibedrill
SSH Key Fingerprint: SHA256:M0m3JW1s38BgO2t0fG146Yxd9OJ2IOqkvCAsuRHQ6Pw
5 changed files with 540 additions and 1428 deletions

1920
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -4,13 +4,8 @@ version = "0.6.1"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
anyhow = "1.0.93" anyhow = "1.0.102"
dotenvy = "0.15.7" reqwest = {version = "0.13.3", features = ["json"]}
log = "0.4.22"
poise = "0.6.1"
pretty_env_logger = "0.5.0"
reqwest = {version = "0.12.9", features = ["json"]}
serde = {version = "1.0.215", features = ["derive", "serde_derive"]} serde = {version = "1.0.215", features = ["derive", "serde_derive"]}
serde_json = {version = "1.0.132", features = []}
tokio = {version = "1.41.1", features = ["full"]} tokio = {version = "1.41.1", features = ["full"]}
url = "2.5.3" url = "2.5.3"

View File

@ -2,7 +2,7 @@ use reqwest::{header::HeaderValue, Client};
use serde::Deserialize; use serde::Deserialize;
use url::Url; use url::Url;
use crate::types::{ServerInfo, ServerOnlineResponse, ServerResponse}; use crate::types::{PlayerList, ServerInfo, ServerOnlineResponse, ServerResponse};
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
struct ApiResponse { struct ApiResponse {
@ -12,10 +12,18 @@ struct ApiResponse {
motd: Option<Motd>, motd: Option<Motd>,
} }
#[derive(Deserialize, Debug, Clone, Copy)] #[derive(Deserialize, Debug, Clone)]
struct ApiResponsePlayers { struct ApiResponsePlayers {
online: u64, online: u64,
max: u64, max: u64,
list: Option<Vec<ApiResponsePlayerEntry>>,
}
#[derive(Deserialize, Debug, Clone)]
struct ApiResponsePlayerEntry {
name: String,
#[allow(dead_code)]
uuid: String,
} }
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
@ -35,6 +43,7 @@ pub struct OnlineResponse {
players_online: u64, players_online: u64,
player_limit: u64, player_limit: u64,
version: String, version: String,
players: Vec<String>,
} }
impl ServerOnlineResponse for OnlineResponse { impl ServerOnlineResponse for OnlineResponse {
@ -59,6 +68,12 @@ impl ServerOnlineResponse for OnlineResponse {
} }
} }
impl PlayerList for OnlineResponse {
fn players(&self) -> &Vec<String> {
&self.players
}
}
pub struct Server { pub struct Server {
#[allow(dead_code)] #[allow(dead_code)]
token: String, token: String,
@ -100,14 +115,21 @@ impl ServerInfo for Server {
match json.online { match json.online {
true => { true => {
let players = json.players.unwrap();
let motd = json.motd.as_ref().unwrap(); let motd = json.motd.as_ref().unwrap();
self::ServerResponse::Online(OnlineResponse { self::ServerResponse::Online(OnlineResponse {
searchable_name: self.addr.host().unwrap().to_string(), searchable_name: self.addr.host().unwrap().to_string(),
reported_name: motd.clean.first().unwrap().into(), reported_name: motd.clean.first().unwrap().into(),
clean_name: motd.clean.first().unwrap().into(), clean_name: motd.clean.first().unwrap().into(),
players_online: json.players.unwrap().online, players_online: players.online,
player_limit: json.players.unwrap().max, player_limit: players.max,
version: json.version.unwrap(), version: json.version.unwrap(),
players: players
.list
.unwrap_or(Vec::<ApiResponsePlayerEntry>::new())
.iter()
.map(|e| e.name.clone())
.collect(),
}) })
} }
false => ServerResponse::Offline, false => ServerResponse::Offline,

View File

@ -3,7 +3,7 @@ mod types;
use crate::{ use crate::{
handlers::minecraft, handlers::minecraft,
types::{ServerInfo, ServerOnlineResponse, ServerResponse}, types::{PlayerList, ServerInfo, ServerOnlineResponse, ServerResponse},
}; };
#[tokio::main] #[tokio::main]
@ -24,7 +24,8 @@ async fn main() {
online_info.version(), online_info.version(),
online_info.players_online(), online_info.players_online(),
online_info.player_limit() online_info.player_limit()
) );
println!("Players online: {}", online_info.players().join(", "));
} }
} }
} }

View File

@ -15,6 +15,10 @@ pub trait ServerOnlineResponse {
fn readable_name(&self) -> &String; fn readable_name(&self) -> &String;
} }
pub trait PlayerList {
fn players(&self) -> &Vec<String>;
}
#[allow(dead_code)] #[allow(dead_code)]
pub trait ServerInfo { pub trait ServerInfo {
fn new(token: String, addr: Url) -> Self; fn new(token: String, addr: Url) -> Self;