Add new WG servers
This commit is contained in:
parent
1b7969aac2
commit
903c4a9afa
15
Cargo.lock
generated
15
Cargo.lock
generated
@ -513,6 +513,7 @@ checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
@ -535,6 +536,17 @@ version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-executor"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.31"
|
||||
@ -1079,9 +1091,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "kon_cmds"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
dependencies = [
|
||||
"dashmap 6.1.0",
|
||||
"futures",
|
||||
"kon_libs",
|
||||
"kon_tokens",
|
||||
"lazy_static",
|
||||
|
@ -16,12 +16,13 @@ bb8 = "0.9.0"
|
||||
bb8-redis = "0.21.0"
|
||||
cargo_toml = "0.22.1"
|
||||
dashmap = "6.1.0"
|
||||
poise = "0.6.1"
|
||||
futures = "0.3.31"
|
||||
reqwest = { version = "0.12.15", features = ["json", "native-tls-vendored"] }
|
||||
serde = "1.0.219"
|
||||
serde_json = "1.0.140"
|
||||
sysinfo = "0.34.2"
|
||||
lazy_static = "1.5.0"
|
||||
poise = "0.6.1"
|
||||
tokio = { version = "1.44.2", features = ["macros", "signal", "rt-multi-thread"] }
|
||||
uptime_lib = "0.3.1"
|
||||
kon_libs = { path = "libs" }
|
||||
|
@ -1,9 +1,11 @@
|
||||
[package]
|
||||
name = "kon_cmds"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
dashmap = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
kon_libs = { workspace = true }
|
||||
kon_tokens = { workspace = true }
|
||||
lazy_static = { workspace = true }
|
||||
@ -14,4 +16,3 @@ serde_json = { workspace = true }
|
||||
sysinfo = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
uptime_lib = { workspace = true }
|
||||
dashmap = { workspace = true }
|
||||
|
@ -1,7 +1,7 @@
|
||||
mod ilo;
|
||||
mod status;
|
||||
mod translate;
|
||||
mod uptime;
|
||||
mod wargaming;
|
||||
|
||||
use kon_libs::{
|
||||
KonData,
|
||||
@ -12,9 +12,9 @@ use kon_libs::{
|
||||
|
||||
use {
|
||||
ilo::ilo,
|
||||
status::status,
|
||||
translate::translate,
|
||||
uptime::uptime
|
||||
uptime::uptime,
|
||||
wargaming::wargaming
|
||||
};
|
||||
|
||||
macro_rules! commands {
|
||||
@ -23,7 +23,7 @@ macro_rules! commands {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_cmds() -> Vec<poise::Command<KonData, KonError>> { commands!(deploy, ping, ilo, status, translate, uptime) }
|
||||
pub fn register_cmds() -> Vec<poise::Command<KonData, KonError>> { commands!(deploy, ping, ilo, wargaming, translate, uptime) }
|
||||
|
||||
/// Deploy the commands globally or in a guild
|
||||
#[poise::command(prefix_command, owners_only, guild_only)]
|
||||
|
@ -1,100 +0,0 @@
|
||||
use {
|
||||
kon_tokens::token_path,
|
||||
poise::{
|
||||
CreateReply,
|
||||
serenity_prelude::builder::CreateEmbed
|
||||
},
|
||||
serde_json::Value,
|
||||
std::collections::HashMap,
|
||||
tokio::join
|
||||
};
|
||||
|
||||
use kon_libs::{
|
||||
BINARY_PROPERTIES,
|
||||
HttpClient,
|
||||
KonResult
|
||||
};
|
||||
|
||||
async fn pms_serverstatus(url: &str) -> KonResult<Vec<(String, Vec<Value>)>> {
|
||||
let client = HttpClient::new();
|
||||
let req = client.get(url, "PMS-Status").await?;
|
||||
|
||||
let response = req.json::<HashMap<String, Value>>().await?;
|
||||
let data = response["data"].as_array().unwrap();
|
||||
|
||||
let mut servers = Vec::new();
|
||||
for item in data {
|
||||
if let Some(title) = item["title"].as_str() {
|
||||
if let Some(servers_statuses) = item["servers_statuses"]["data"].as_array() {
|
||||
if !servers_statuses.is_empty() {
|
||||
servers.push((title.to_owned(), servers_statuses.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(servers)
|
||||
}
|
||||
|
||||
fn process_pms_statuses(servers: Vec<(String, Vec<Value>)>) -> Vec<(String, String, bool)> {
|
||||
let mut server_map: HashMap<String, Vec<(String, String)>> = HashMap::new();
|
||||
let id_name_map: HashMap<&str, &str> = [("wotbsg", "ASIA"), ("wowssg", "WoWS (ASIA)"), ("wowseu", "WoWS (EU)")]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
for (title, mapped_servers) in servers {
|
||||
for server in mapped_servers {
|
||||
let name = server["name"].as_str().unwrap();
|
||||
let id = server["id"].as_str().unwrap().split(":").next().unwrap_or("");
|
||||
let status = match server["availability"].as_str().unwrap() {
|
||||
"1" => "Online",
|
||||
"-1" => "Offline",
|
||||
_ => "Unknown"
|
||||
};
|
||||
let name = id_name_map.get(id).unwrap_or(&name);
|
||||
server_map
|
||||
.entry(title.clone())
|
||||
.or_default()
|
||||
.push((name.to_owned().to_string(), status.to_owned()));
|
||||
}
|
||||
}
|
||||
|
||||
let mut statuses = Vec::new();
|
||||
for (title, servers) in server_map {
|
||||
let servers_str = servers
|
||||
.iter()
|
||||
.map(|(name, status)| format!("{name}: {status}"))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
statuses.push((title, servers_str, true));
|
||||
}
|
||||
statuses
|
||||
}
|
||||
|
||||
/// Query the server statuses
|
||||
#[poise::command(
|
||||
slash_command,
|
||||
install_context = "Guild|User",
|
||||
interaction_context = "Guild|BotDm|PrivateChannel",
|
||||
subcommands("wg")
|
||||
)]
|
||||
pub async fn status(_: super::PoiseCtx<'_>) -> KonResult<()> { Ok(()) }
|
||||
|
||||
/// Retrieve the server statuses from Wargaming
|
||||
#[poise::command(slash_command)]
|
||||
async fn wg(ctx: super::PoiseCtx<'_>) -> KonResult<()> {
|
||||
let pms_asia = token_path().await.wg_pms;
|
||||
let pms_eu = pms_asia.replace("asia", "eu");
|
||||
let embed = CreateEmbed::new().color(BINARY_PROPERTIES.embed_color);
|
||||
|
||||
let (servers_asia, servers_eu) = join!(pms_serverstatus(&pms_asia), pms_serverstatus(&pms_eu));
|
||||
let joined_pms_servers = [servers_eu.unwrap(), servers_asia.unwrap()].concat();
|
||||
let pms_servers = process_pms_statuses(joined_pms_servers.to_vec());
|
||||
|
||||
ctx
|
||||
.send(CreateReply::default().embed(embed.title("Wargaming Server Status").fields(pms_servers)))
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
142
cmds/src/dispatch/wargaming.rs
Normal file
142
cmds/src/dispatch/wargaming.rs
Normal file
@ -0,0 +1,142 @@
|
||||
use {
|
||||
futures::future,
|
||||
kon_libs::{
|
||||
BINARY_PROPERTIES,
|
||||
HttpClient,
|
||||
KonResult
|
||||
},
|
||||
kon_tokens::token_path,
|
||||
poise::{
|
||||
CreateReply,
|
||||
serenity_prelude::builder::CreateEmbed
|
||||
},
|
||||
serde_json::Value,
|
||||
std::{
|
||||
collections::HashMap,
|
||||
time::Duration
|
||||
}
|
||||
};
|
||||
|
||||
async fn pms_serverstatus(url: String) -> Result<Vec<(String, Vec<Value>)>, String> {
|
||||
let client = HttpClient::new();
|
||||
let duration = Duration::from_secs(5);
|
||||
let req = match tokio::time::timeout(duration, client.get(url.as_str(), "PMS-Status")).await {
|
||||
Ok(result) => match result {
|
||||
Ok(req) => req,
|
||||
Err(e) => return Err(format!("Failed to connect: {e}"))
|
||||
},
|
||||
Err(_) => return Err("Request timed out".to_string())
|
||||
};
|
||||
|
||||
let response = match tokio::time::timeout(duration, req.json::<HashMap<String, Value>>()).await {
|
||||
Ok(result) => match result {
|
||||
Ok(data) => data,
|
||||
Err(e) => return Err(format!("Failed to parse response: {e}"))
|
||||
},
|
||||
Err(_) => return Err("Response parsing timed out".to_string())
|
||||
};
|
||||
|
||||
let data = match response.get("data").and_then(|d| d.as_array()) {
|
||||
Some(d) => d,
|
||||
None => return Err("Invalid response format".to_string())
|
||||
};
|
||||
|
||||
let mut servers = Vec::new();
|
||||
for item in data {
|
||||
if let Some(title) = item["title"].as_str() {
|
||||
if let Some(servers_statuses) = item["servers_statuses"]["data"].as_array() {
|
||||
if !servers_statuses.is_empty() {
|
||||
servers.push((title.to_owned(), servers_statuses.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(servers)
|
||||
}
|
||||
|
||||
fn process_pms_statuses(servers: Vec<(String, Vec<Value>)>) -> Vec<(String, String, bool)> {
|
||||
let mut server_map: HashMap<String, Vec<(String, String)>> = HashMap::new();
|
||||
let id_name_map: HashMap<&str, &str> = [("wotbsg", "ASIA"), ("wowssg", "ASIA"), ("wowseu", "EU")].iter().cloned().collect();
|
||||
|
||||
for (title, mapped_servers) in servers {
|
||||
for server in mapped_servers {
|
||||
let name = server["name"].as_str().unwrap();
|
||||
let id = server["id"].as_str().unwrap().split(":").next().unwrap_or("");
|
||||
let status = match server["availability"].as_str().unwrap() {
|
||||
"1" => "Online",
|
||||
"-1" => "Offline",
|
||||
_ => "Unknown"
|
||||
};
|
||||
let name = id_name_map.get(id).unwrap_or(&name);
|
||||
server_map
|
||||
.entry(title.clone())
|
||||
.or_default()
|
||||
.push((name.to_owned().to_string(), status.to_owned()));
|
||||
}
|
||||
}
|
||||
|
||||
let mut statuses = Vec::new();
|
||||
for (title, servers) in server_map {
|
||||
let servers_str = servers
|
||||
.iter()
|
||||
.map(|(name, status)| format!("**{name}:** {status}"))
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n");
|
||||
statuses.push((title, servers_str, true));
|
||||
}
|
||||
statuses
|
||||
}
|
||||
|
||||
/// Query the server statuses from Wargaming
|
||||
#[poise::command(slash_command, install_context = "Guild|User", interaction_context = "Guild|BotDm|PrivateChannel")]
|
||||
pub async fn wargaming(ctx: super::PoiseCtx<'_>) -> KonResult<()> {
|
||||
ctx.defer().await?;
|
||||
|
||||
let regions = [
|
||||
("asia", "Asia (WoT)"),
|
||||
("eu", "Europe (WoT)"),
|
||||
("wgcb", "Console (WoTX)"),
|
||||
("lg", "Europe (WoWL)")
|
||||
];
|
||||
|
||||
let pms_base = token_path().await.wg_pms;
|
||||
let mut embed = CreateEmbed::new().color(BINARY_PROPERTIES.embed_color);
|
||||
|
||||
let mut futures = Vec::new();
|
||||
let mut region_names = Vec::new();
|
||||
|
||||
for (region, name) in ®ions {
|
||||
let url = if *region == "asia" {
|
||||
pms_base.clone()
|
||||
} else {
|
||||
pms_base.replace("asia", region)
|
||||
};
|
||||
|
||||
futures.push(pms_serverstatus(url));
|
||||
region_names.push(name);
|
||||
}
|
||||
|
||||
let results = future::join_all(futures).await;
|
||||
|
||||
let mut pms_servers = Vec::new();
|
||||
let mut errors = Vec::new();
|
||||
|
||||
for (i, result) in results.into_iter().enumerate() {
|
||||
match result {
|
||||
Ok(servers) => pms_servers.extend(servers),
|
||||
Err(e) => errors.push(format!("**{}:** {e}", region_names[i]))
|
||||
}
|
||||
}
|
||||
|
||||
let status_fields = process_pms_statuses(pms_servers);
|
||||
embed = embed.title("Wargaming Server Status");
|
||||
|
||||
if !errors.is_empty() {
|
||||
embed = embed.description(format!("No response from certain servers:\n{}", errors.join("\n")));
|
||||
}
|
||||
|
||||
ctx.send(CreateReply::default().embed(embed.fields(status_fields))).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user