html terminal
-rw-r--r--Cargo.toml2
-rw-r--r--src/bot/mod.rs2
-rw-r--r--src/bot/rules.rs2
-rw-r--r--src/bot/trace.rs92
-rw-r--r--src/main.rs2
5 files changed, 96 insertions, 4 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 3990149..1565c31 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -27,7 +27,6 @@ serenity = { version = "0.12", features = [
"client",
"utils",
"rustls_backend",
- "cache",
"gateway",
], default-features = false }
poise = { git = "https://github.com/serenity-rs/poise" }
@@ -48,7 +47,6 @@ phf = { version = "0.11.2", features = ["macros"] }
itertools = "0.11.0"
emoji = { git = "https://github.com/Apricot-Conservation-Project/emoji" }
serde_derive = "1.0.193"
-deser-hjson = "2.2.4"
serde_json = "1.0.109"
strconv = "0.1.0"
diff --git a/src/bot/mod.rs b/src/bot/mod.rs
index 592859f..b207868 100644
--- a/src/bot/mod.rs
+++ b/src/bot/mod.rs
@@ -6,6 +6,7 @@ pub mod maps;
mod player;
mod rules;
mod status;
+mod trace;
mod voting;
use crate::webhook::Webhook;
@@ -209,6 +210,7 @@ impl Bot {
rules::list(),
rules::set(),
rules::del(),
+ trace::trace(),
start(),
end(),
help(),
diff --git a/src/bot/rules.rs b/src/bot/rules.rs
index ddf11ee..ae34acc 100644
--- a/src/bot/rules.rs
+++ b/src/bot/rules.rs
@@ -198,7 +198,7 @@ pub async fn rules(stdin: &broadcast::Sender<String>) -> tokio::sync::MutexGuard
.get_or_init(|| async move {
send!(stdin, "rules").unwrap();
let res = get_nextblock().await;
- Mutex::new(deser_hjson::from_str(&res).unwrap())
+ Mutex::new(serde_json::from_str(&res).unwrap())
})
.await
.lock()
diff --git a/src/bot/trace.rs b/src/bot/trace.rs
new file mode 100644
index 0000000..f514169
--- /dev/null
+++ b/src/bot/trace.rs
@@ -0,0 +1,92 @@
+use super::{get_nextblock, Context, SUCCESS};
+use anyhow::Result;
+use emoji::named::*;
+use poise::serenity_prelude::*;
+use std::net::Ipv4Addr;
+
+#[derive(serde_derive::Deserialize)]
+struct PlayerInfo {
+ #[serde(rename = "i")]
+ id: String,
+ #[serde(rename = "ln")]
+ last_name: String,
+ #[serde(rename = "lp")]
+ last_ip: Ipv4Addr,
+ #[serde(rename = "is")]
+ ips: Vec<Ipv4Addr>,
+ #[serde(rename = "ns")]
+ names: Vec<String>,
+ #[serde(rename = "t")]
+ times_joined: usize,
+ #[serde(rename = "a")]
+ admin: bool,
+}
+
+#[poise::command(slash_command, category = "Info")]
+/// trace a player
+/// find out all about them
+pub async fn trace(
+ ctx: Context<'_>,
+ #[autocomplete = "super::player::autocomplete"] player: String,
+) -> Result<()> {
+ super::send_ctx!(ctx, "trace {player}").unwrap();
+ let res = get_nextblock().await;
+ let info = res
+ .lines()
+ .filter(|x| !x.is_empty())
+ .map(serde_json::from_str::<PlayerInfo>)
+ .map(Result::unwrap);
+ let authorized = match ctx {
+ poise::Context::Application(x) => x
+ .author_member()
+ .await
+ .map(|x| x.roles.clone())
+ .unwrap_or(vec![])
+ .iter()
+ .find(|&&x| x == 1133416252791074877)
+ .is_some(),
+ _ => unreachable!(),
+ };
+ let mut r = poise::CreateReply::default().ephemeral(authorized);
+ for found in info {
+ let mut e = CreateEmbed::new()
+ .field(
+ "name",
+ if found.admin {
+ format!("{} <{ADMIN}>", found.last_name)
+ } else {
+ found.last_name
+ },
+ true,
+ )
+ .field(
+ "all names used",
+ found
+ .names
+ .into_iter()
+ .intersperse("|".to_string())
+ .fold(String::new(), |acc, x| acc + &x),
+ true,
+ )
+ .field("has joined", found.times_joined.to_string(), true)
+ .color(SUCCESS);
+ if authorized {
+ e = e
+ .field("uuid", found.id, true)
+ .field("last used ip", found.last_ip.to_string(), true)
+ .field(
+ "all ips used",
+ found
+ .ips
+ .into_iter()
+ .map(|x| x.to_string())
+ .intersperse("|".to_string())
+ .fold(String::new(), |acc, x| acc + &x),
+ true,
+ );
+ }
+ r = r.embed(e);
+ }
+ poise::send_reply(ctx, r).await?;
+ Ok(())
+}
diff --git a/src/main.rs b/src/main.rs
index 8b08b11..a954441 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,4 @@
-#![feature(lazy_cell, let_chains)]
+#![feature(lazy_cell, let_chains, iter_intersperse)]
use std::str::FromStr;
#[macro_use]
mod logging;