html terminal
Diffstat (limited to 'src/bot/status.rs')
-rw-r--r--src/bot/status.rs91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/bot/status.rs b/src/bot/status.rs
new file mode 100644
index 0000000..6926ab0
--- /dev/null
+++ b/src/bot/status.rs
@@ -0,0 +1,91 @@
+use super::{get_nextblock, Context, FAIL, SUCCESS};
+use crate::send_ctx;
+use anyhow::Result;
+use itertools::Itertools;
+use std::str::FromStr;
+
+fn parse(line: &str) -> Option<(u32, u32, u32)> {
+ line.split('/')
+ .map(|s| u32::from_str(s.trim().split_once(' ').unwrap().0).unwrap())
+ .collect_tuple()
+}
+
+#[allow(dead_code)]
+pub enum Size {
+ Gb(f64),
+ Mb(f64),
+ Kb(f64),
+ B(f64),
+}
+const UNIT: f64 = 1024.0;
+
+impl Size {
+ pub fn bytes(self) -> f64 {
+ match self {
+ Self::B(x) => x,
+ Self::Kb(x) => x * UNIT,
+ Self::Mb(x) => x * UNIT * UNIT,
+ Self::Gb(x) => x * UNIT * UNIT * UNIT,
+ }
+ }
+}
+// https://git.sr.ht/~f9/human_bytes
+pub fn humanize_bytes<T: Into<Size>>(bytes: T) -> String {
+ const SUFFIX: [&str; 4] = ["B", "KB", "MB", "GB"];
+ let size = dbg!(bytes.into().bytes());
+
+ if size <= 0.0 {
+ return "0 B".to_string();
+ }
+
+ let base = size.log10() / UNIT.log10();
+
+ let result = format!("{:.1}", UNIT.powf(base - base.floor()),)
+ .trim_end_matches(".0")
+ .to_owned();
+
+ // Add suffix
+ [&result, SUFFIX[base.floor() as usize]].join(" ")
+}
+
+#[poise::command(prefix_command, slash_command, category = "Info", rename = "status")]
+/// server status.
+pub async fn command(ctx: Context<'_>) -> Result<()> {
+ let _ = ctx.defer_or_broadcast().await;
+ send_ctx!(ctx, "status")?;
+ let block = tokio::select! {
+ block = get_nextblock() => block,
+ _ = async_std::task::sleep(std::time::Duration::from_secs(5)) =>
+ { poise::send_reply(ctx, |m| m.embed(|e| e.title("server down").color(FAIL))).await?; return Ok(()) },
+ };
+ let (tps, mem, pcount) =
+ parse(&block).ok_or(anyhow::anyhow!("couldnt split block {block}."))?;
+ poise::send_reply(ctx, |m| {
+ m.embed(|e| {
+ if pcount > 0 {
+ e.footer(|f| f.text("see /players for player list"));
+ }
+ e.title("server online")
+ .field("tps", tps, true)
+ .field("memory use", humanize_bytes(Size::Mb(mem as f64)), true)
+ .field("players", pcount, true)
+ .color(SUCCESS)
+ })
+ })
+ .await?;
+ Ok(())
+}
+
+#[test]
+fn test_parse() {
+ assert!(parse("57 TPS / 274 MB / 7 PLAYERS") == Some((57, 274, 7)));
+}
+
+#[test]
+fn test_bytes() {
+ assert!(humanize_bytes(Size::B(0.0)) == "0 B");
+ assert!(humanize_bytes(Size::B(550.0)) == "550 B");
+ assert!(humanize_bytes(Size::Kb(550.0)) == "550 KB");
+ assert!(humanize_bytes(Size::Mb(650.0)) == "650 MB");
+ assert!(humanize_bytes(Size::Gb(15.3)) == "15.3 GB");
+}