diff --git a/Cargo.lock b/Cargo.lock index f5ab057..443253b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -270,10 +270,32 @@ dependencies = [ ] [[package]] -name = "crossbeam-utils" -version = "0.8.16" +name = "crossbeam-deque" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" dependencies = [ "cfg-if", ] @@ -374,6 +396,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + [[package]] name = "encoding_rs" version = "0.8.33" @@ -700,7 +728,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.51.1", ] [[package]] @@ -874,6 +902,15 @@ dependencies = [ "tempfile", ] +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + [[package]] name = "num-traits" version = "0.2.17" @@ -1110,6 +1147,26 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -1231,8 +1288,10 @@ dependencies = [ "reqwest", "serde_json", "serenity 0.12.0", + "sysinfo", "tempfile", "tokio", + "uptime_lib", ] [[package]] @@ -1633,6 +1692,21 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sysinfo" +version = "0.30.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb4f3438c8f6389c864e61221cbc97e9bca98b4daf39a5beb7bea660f528bb2" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "windows", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -2006,6 +2080,17 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "uptime_lib" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e71ddbefed856d5881821d6ada4e606bbb91fd332296963ed596e2ad2100f3" +dependencies = [ + "libc", + "thiserror", + "windows", +] + [[package]] name = "url" version = "2.5.0" @@ -2212,6 +2297,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core 0.52.0", + "windows-targets 0.52.0", +] + [[package]] name = "windows-core" version = "0.51.1" @@ -2221,6 +2316,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index b14eef7..8e92e6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,9 @@ reqwest = "0.11.23" serde_json = "1.0.111" serenity = "0.12.0" tempfile = "3.9.0" +sysinfo = "0.30.5" tokio = { version = "1.35.1", features = ["macros", "signal", "rt-multi-thread"] } +uptime_lib = "0.3.0" [[bin]] name = "rustbot" diff --git a/src/commands/mod.rs b/src/commands/mod.rs index a9156ea..75125a7 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,3 +1,4 @@ pub mod ping; pub mod eval; pub mod data; +pub mod uptime; diff --git a/src/commands/uptime.rs b/src/commands/uptime.rs new file mode 100644 index 0000000..287cafd --- /dev/null +++ b/src/commands/uptime.rs @@ -0,0 +1,52 @@ +use crate::Error; + +use sysinfo::System; +use uptime_lib::get; +use std::time::{ + Duration, + SystemTime, + UNIX_EPOCH +}; + +/// Retrieve host and bot uptimes +#[poise::command(slash_command)] +pub async fn uptime(ctx: poise::Context<'_, (), Error>) -> Result<(), Error> { + let mut sys = System::new_all(); + sys.refresh_all(); + + // Fetch system's uptime + let sys_uptime = get().unwrap().as_secs(); + + // Fetch bot's process uptime + let curr_pid = sysinfo::get_current_pid().unwrap(); + let now = SystemTime::now(); + let mut proc_uptime = 0; + if let Some(process) = sys.process(curr_pid) { + let time_started = UNIX_EPOCH + Duration::from_secs(process.start_time()); + proc_uptime = now.duration_since(time_started).unwrap().as_secs(); + } + + ctx.reply(format!("System: `{}`\nProcess: `{}`", format_duration(sys_uptime), format_duration(proc_uptime))).await?; + Ok(()) +} + +fn format_duration(secs: u64) -> String { + let days = secs / 86400; + let hours = (secs % 86400) / 3600; + let minutes = (secs % 3600) / 60; + let seconds = secs % 60; + + let mut formatted_string = String::new(); + if days > 0 { + formatted_string.push_str(&format!("{}d, ", days)); + } + if hours > 0 || days > 0 { + formatted_string.push_str(&format!("{}h, ", hours)); + } + if minutes > 0 || hours > 0 { + formatted_string.push_str(&format!("{}m, ", minutes)); + } + formatted_string.push_str(&format!("{}s", seconds)); + + formatted_string +} diff --git a/src/main.rs b/src/main.rs index ed33e7b..50f092b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -50,7 +50,8 @@ async fn main() { commands: vec![ commands::ping::ping(), commands::eval::eval(), - commands::data::data() + commands::data::data(), + commands::uptime::uptime() ], pre_command: |ctx| Box::pin(async move { let get_guild_name = match ctx.guild() {