diff --git a/.dockerignore b/.dockerignore index 3fddeae..f6f90e4 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,4 +2,6 @@ target .env .gitignore +docker-compose.yml renovate.json +run.sh diff --git a/Cargo.lock b/Cargo.lock index a98e041..d09ce63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -155,6 +155,16 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +[[package]] +name = "bzip2-rs" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beeb59e7e4c811ab37cc73680c798c7a5da77fc9989c62b09138e31ee740f735" +dependencies = [ + "crc32fast", + "tinyvec", +] + [[package]] name = "camino" version = "1.1.6" @@ -550,6 +560,19 @@ dependencies = [ "byteorder", ] +[[package]] +name = "gamedig" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe80214345cf917eff180f20b889a8e951d285b40215501c12eb754142359b" +dependencies = [ + "byteorder", + "bzip2-rs", + "crc32fast", + "phf", + "serde_json", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -771,9 +794,10 @@ dependencies = [ [[package]] name = "kon" -version = "0.1.2" +version = "0.1.3" dependencies = [ "cargo_toml", + "gamedig", "lazy_static", "poise", "reqwest", @@ -1013,6 +1037,48 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -1557,6 +1623,12 @@ dependencies = [ "libc", ] +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "skeptic" version = "0.13.7" diff --git a/Cargo.toml b/Cargo.toml index 0b7b2ef..2854c3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "kon" -version = "0.1.2" +version = "0.1.3" rust-version = "1.74" edition = "2021" @@ -8,6 +8,7 @@ edition = "2021" [dependencies] cargo_toml = "0.17.2" +gamedig = "0.4.1" lazy_static = "1.4.0" poise = "0.5.7" reqwest = "0.11.23" diff --git a/Dockerfile b/Dockerfile index 20505c6..46eb87a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.75-alpine3.18@sha256:fc996ca91d162fe869ca93c1bbc641ef77279c02a9bfead2732f237dd10d16ee AS compiler +FROM rust:1.75-alpine3.19 AS compiler ENV RUSTFLAGS="-C target-feature=-crt-static" RUN apk add --no-cache openssl-dev musl-dev WORKDIR /usr/src/kon diff --git a/src/commands/ats_status.rs b/src/commands/ats_status.rs new file mode 100644 index 0000000..7bb6f06 --- /dev/null +++ b/src/commands/ats_status.rs @@ -0,0 +1,65 @@ +use crate::{Error, COLOR}; + +use gamedig::protocols::{ + valve::{ + Engine, GatheringSettings, Response + }, + types::TimeoutSettings, + valve, +}; +use std::{ + str::FromStr, + net::SocketAddr, + time::Duration, + env::var +}; + +#[allow(dead_code)] // Smh... +fn query_server() -> Result { + let server_ip = var("ATS_SERVER_IP").expect("Expected a \"ATS_SERVER_IP\" in the envvar but none was found"); + let addr = SocketAddr::from_str(&server_ip).unwrap(); + let engine = Engine::Source(None); + let gather_settings = GatheringSettings { + players: true, + rules: false, + check_app_id: false + }; + + let read_timeout = Duration::from_secs(2); + let write_timeout = Duration::from_secs(2); + let retries = 1; + let timeout_settings = TimeoutSettings::new( + Some(read_timeout), + Some(write_timeout), + retries + ).unwrap(); + + let response = valve::query( + &addr, + engine, + Some(gather_settings), + Some(timeout_settings) + ); + + Ok(response?) +} + +/// Retrieve the server status from ATS +#[poise::command(slash_command)] +pub async fn ats_status(ctx: poise::Context<'_, (), Error>) -> Result<(), Error> { + match query_server() { + Ok(response) => { + ctx.send(|m| m.embed(|e| + e.color(COLOR) + .title("American Truck Simulator Server Status") + .fields(vec![ + ("Name", format!("{}", response.info.name), true), + ("Players", format!("{}/{}", response.info.players_online, response.info.players_maximum), true) + ]) + )).await?; + } + Err(why) => println!("Error querying the server: {:?}", why) + } + + Ok(()) +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 2ac1c6c..ae30187 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,2 +1,3 @@ pub mod ping; -pub mod status; +pub mod wg_status; +pub mod ats_status; diff --git a/src/commands/status.rs b/src/commands/wg_status.rs similarity index 84% rename from src/commands/status.rs rename to src/commands/wg_status.rs index 545e8bd..5e87a60 100644 --- a/src/commands/status.rs +++ b/src/commands/wg_status.rs @@ -1,18 +1,24 @@ use crate::{Error, COLOR}; +use reqwest::{ + Client, + header::USER_AGENT +}; +use std::{ + collections::HashMap, + env::var +}; use cargo_toml::Manifest; -use reqwest::{Client, header::USER_AGENT}; -use std::collections::HashMap; use serde_json::Value; use tokio::join; lazy_static::lazy_static! { - static ref PMS_BASE: String = std::env::var("WG_PMS").expect("Expected a \"WG_PMS\" in the envvar but none was found"); + static ref PMS_BASE: String = var("WG_PMS").expect("Expected a \"WG_PMS\" in the envvar but none was found"); } /// Retrieve the server statuses from Wargaming #[poise::command(slash_command)] -pub async fn status(ctx: poise::Context<'_, (), Error>) -> Result<(), Error> { +pub async fn wg_status(ctx: poise::Context<'_, (), Error>) -> Result<(), Error> { let pms_asia = &PMS_BASE; let pms_eu = PMS_BASE.replace("asia", "eu"); diff --git a/src/main.rs b/src/main.rs index 0dc6f41..521543b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -52,7 +52,8 @@ async fn main() { .options(poise::FrameworkOptions { commands: vec![ commands::ping::ping(), - commands::status::status() + commands::wg_status::wg_status(), + commands::ats_status::ats_status() ], pre_command: |ctx| Box::pin(async move { let get_guild_name = match ctx.guild() {