From e9c70bc75475c7cc92f2bda950e82be9db8eedf3 Mon Sep 17 00:00:00 2001 From: trivernis Date: Thu, 8 Apr 2021 18:36:31 +0200 Subject: [PATCH] Add stats command Signed-off-by: trivernis --- Cargo.lock | 104 ++++++++++++++++++++++++++++++++++++- Cargo.toml | 3 +- src/client.rs | 7 +++ src/commands/misc/mod.rs | 4 +- src/commands/misc/stats.rs | 66 +++++++++++++++++++++++ 5 files changed, 181 insertions(+), 3 deletions(-) create mode 100644 src/commands/misc/stats.rs diff --git a/Cargo.lock b/Cargo.lock index 4a77dfc..871d90c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -293,6 +293,40 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils 0.8.3", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-epoch", + "crossbeam-utils 0.8.3", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils 0.8.3", + "lazy_static", + "memoffset", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.7.2" @@ -303,6 +337,17 @@ dependencies = [ "cfg-if 0.1.10", ] +[[package]] +name = "crossbeam-utils" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" +dependencies = [ + "autocfg", + "cfg-if 1.0.0", + "lazy_static", +] + [[package]] name = "dashmap" version = "4.0.2" @@ -334,6 +379,12 @@ dependencies = [ "syntex", ] +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + [[package]] name = "dotenv" version = "0.15.0" @@ -923,6 +974,15 @@ version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" +[[package]] +name = "memoffset" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.16" @@ -1327,6 +1387,31 @@ dependencies = [ "rand_core 0.6.2", ] +[[package]] +name = "rayon" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils 0.8.3", + "lazy_static", + "num_cpus", +] + [[package]] name = "redox_syscall" version = "0.2.5" @@ -1753,7 +1838,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa50ae63198c9af3ffb3a1fa8877d54bb1a569a2a61cb519097c7989f1a151ff" dependencies = [ - "crossbeam-utils", + "crossbeam-utils 0.7.2", "futures-util", "loom", ] @@ -1824,6 +1909,22 @@ dependencies = [ "unicode-xid 0.0.3", ] +[[package]] +name = "sysinfo" +version = "0.16.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567e910ef0207be81a4e1bb0491e9a8d9866cf45b20fe1a52c03d347da9ea51b" +dependencies = [ + "cfg-if 1.0.0", + "core-foundation-sys", + "doc-comment", + "libc", + "ntapi", + "once_cell", + "rayon", + "winapi 0.3.9", +] + [[package]] name = "tempfile" version = "3.2.0" @@ -1916,6 +2017,7 @@ dependencies = [ "serde_rusqlite", "serenity", "songbird", + "sysinfo", "thiserror", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index 29ec9f3..863f32f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,4 +26,5 @@ futures = "0.3.13" log = "0.4.14" fern = "0.6.0" chrono = "0.4.19" -colored = "2.0.0" \ No newline at end of file +colored = "2.0.0" +sysinfo = "0.16.5" \ No newline at end of file diff --git a/src/client.rs b/src/client.rs index 7b5b3f7..17a509e 100644 --- a/src/client.rs +++ b/src/client.rs @@ -11,6 +11,8 @@ use crate::database::get_database; use crate::handler::Handler; use crate::utils::error::{BotError, BotResult}; use crate::utils::store::{Store, StoreData}; +use serenity::model::id::UserId; +use std::collections::HashSet; pub async fn get_client() -> BotResult { let token = dotenv::var("BOT_TOKEN").map_err(|_| BotError::MissingToken)?; @@ -30,6 +32,10 @@ pub async fn get_client() -> BotResult { } pub fn get_framework() -> StandardFramework { + let mut owners = HashSet::new(); + if let Some(owner) = dotenv::var("BOT_OWNER").ok().and_then(|o| o.parse().ok()) { + owners.insert(UserId(owner)); + } StandardFramework::default() .configure(|c| { c.prefix( @@ -39,6 +45,7 @@ pub fn get_framework() -> StandardFramework { ) .allow_dm(true) .ignore_bots(true) + .owners(owners) }) .group(&MINECRAFT_GROUP) .group(&MISC_GROUP) diff --git a/src/commands/misc/mod.rs b/src/commands/misc/mod.rs index f175978..769be02 100644 --- a/src/commands/misc/mod.rs +++ b/src/commands/misc/mod.rs @@ -1,10 +1,12 @@ use serenity::framework::standard::macros::group; use ping::PING_COMMAND; +use stats::STATS_COMMAND; pub(crate) mod help; mod ping; +mod stats; #[group] -#[commands(ping)] +#[commands(ping, stats)] pub struct Misc; diff --git a/src/commands/misc/stats.rs b/src/commands/misc/stats.rs new file mode 100644 index 0000000..be0a0ac --- /dev/null +++ b/src/commands/misc/stats.rs @@ -0,0 +1,66 @@ +use chrono::Duration as ChronoDuration; +use serenity::framework::standard::macros::command; +use serenity::framework::standard::CommandResult; +use serenity::model::channel::Message; +use serenity::prelude::*; +use std::process; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; +use sysinfo::{ProcessExt, SystemExt}; + +#[command] +#[description("Shows some statistics about the bot")] +#[usage("stats")] +#[example("stats")] +async fn stats(ctx: &Context, msg: &Message) -> CommandResult { + let mut system = sysinfo::System::new_all(); + system.refresh_all(); + let kernel_version = system.get_kernel_version().unwrap_or("n/a".to_string()); + let own_process = system.get_process(process::id() as i32).unwrap(); + let memory_usage = own_process.memory(); + let cpu_usage = own_process.cpu_usage(); + let thread_count = own_process.tasks.len(); + let current_user = ctx.http.get_current_user().await?; + let guild_count: usize = current_user.guilds(ctx).await?.len(); + let bot_info = ctx.http.get_current_application_info().await?; + + let current_time_seconds = SystemTime::now().duration_since(UNIX_EPOCH).unwrap(); + let uptime = current_time_seconds - Duration::from_secs(own_process.start_time()); + let uptime = ChronoDuration::from_std(uptime).unwrap(); + + let discord_info = format!( + r#" + Owner: <@{}> + Guilds: {} + "#, + bot_info.owner.id, guild_count + ); + + let system_info = format!( + r#" + Kernel Version: {} + Memory Usage: {:.2} MiB + CPU Usage: {:.2} % + Thread Count: {} + Uptime: {}d {}h {}m + "#, + kernel_version, + memory_usage as f64 / 1024f64, + cpu_usage, + thread_count, + uptime.num_days(), + uptime.num_hours() % 24, + uptime.num_minutes() % 60 + ); + + msg.channel_id + .send_message(ctx, |m| { + m.embed(|e| { + e.title("Bot Stats") + .field("Bot Information", discord_info, true) + .field("System information", system_info, true) + }) + }) + .await?; + + Ok(()) +}