html terminal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use super::{get_nextblock, Context, SUCCESS};
use crate::emoji::named::*;
use anyhow::Result;
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()
            .any(|&x| x == 1133416252791074877),
        _ => 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 {
            let mut ips = found
                .ips
                .into_iter()
                .map(|x| x.to_string())
                .intersperse("|".to_string())
                .fold(String::new(), |acc, x| acc + &x);
            if ips.len() > 1000 {
                ips = format!("{} … ({} more chars)", &ips[..1000], ips.len() - 1000);
            }
            e = e
                .field("uuid", found.id, true)
                .field("last used ip", found.last_ip.to_string(), true)
                .field("all ips used", ips, true);
        }
        r = r.embed(e);
    }
    poise::send_reply(ctx, r).await?;
    Ok(())
}