diff --git a/euphoxide-bot/src/bot.rs b/euphoxide-bot/src/bot.rs index 3f681c8..f2a5574 100644 --- a/euphoxide-bot/src/bot.rs +++ b/euphoxide-bot/src/bot.rs @@ -1,7 +1,6 @@ use std::{fmt::Debug, sync::Arc}; use euphoxide_client::{MultiClient, MultiClientConfig, MultiClientEvent, ServerConfig}; -use jiff::Timestamp; use log::error; use tokio::sync::mpsc; @@ -12,7 +11,6 @@ pub struct Bot { pub server_config: ServerConfig, pub commands: Arc>, pub clients: MultiClient, - pub start_time: Timestamp, } impl Bot { @@ -37,10 +35,10 @@ impl Bot { server_config, commands: Arc::new(commands), clients: MultiClient::new_with_config(clients_config, event_tx), - start_time: Timestamp::now(), } } } + impl Bot where E: Debug + 'static, @@ -61,7 +59,6 @@ impl Clone for Bot { server_config: self.server_config.clone(), commands: self.commands.clone(), clients: self.clients.clone(), - start_time: self.start_time, } } } diff --git a/euphoxide-bot/src/command/botrulez/uptime.rs b/euphoxide-bot/src/command/botrulez/uptime.rs index ed01c9e..e8b1d8b 100644 --- a/euphoxide-bot/src/command/botrulez/uptime.rs +++ b/euphoxide-bot/src/command/botrulez/uptime.rs @@ -62,8 +62,14 @@ pub trait HasStartTime { } impl Uptime { - fn formulate_reply(&self, ctx: &Context, bot: &Bot, connected: bool) -> String { - let start = bot.start_time; + fn formulate_reply( + &self, + ctx: &Context, + bot: &Bot, + joined: bool, + connected: bool, + ) -> String { + let start = bot.clients.start_time(); let now = Timestamp::now(); let mut reply = format!( @@ -72,6 +78,15 @@ impl Uptime { format_relative_time(start - now), ); + if joined { + let since = ctx.client.start_time(); + reply.push_str(&format!( + ", present since {} ({})", + format_time(since), + format_relative_time(since - now), + )); + } + if connected { let since = ctx.joined.since; reply.push_str(&format!( @@ -98,7 +113,7 @@ where bot: &Bot, ) -> Result { if arg.trim().is_empty() { - let reply = self.formulate_reply(ctx, bot, false); + let reply = self.formulate_reply(ctx, bot, false, false); ctx.reply_only(msg.id, reply).await?; Ok(Propagate::No) } else { @@ -111,6 +126,9 @@ where #[cfg(feature = "clap")] #[derive(Parser)] pub struct UptimeArgs { + /// Show how long the bot has been in this room. + #[arg(long, short)] + pub present: bool, /// Show how long the bot has been connected without interruption. #[arg(long, short)] pub connected: bool, @@ -131,7 +149,7 @@ where ctx: &Context, bot: &Bot, ) -> Result { - let reply = self.formulate_reply(ctx, bot, args.connected); + let reply = self.formulate_reply(ctx, bot, args.present, args.connected); ctx.reply_only(msg.id, reply).await?; Ok(Propagate::No) } diff --git a/euphoxide-client/Cargo.toml b/euphoxide-client/Cargo.toml index 097db45..864b940 100644 --- a/euphoxide-client/Cargo.toml +++ b/euphoxide-client/Cargo.toml @@ -6,6 +6,7 @@ edition = { workspace = true } [dependencies] cookie = { workspace = true } euphoxide = { workspace = true } +jiff = { workspace = true } log = { workspace = true } tokio = { workspace = true, features = ["rt"] } tokio-tungstenite = { workspace = true } diff --git a/euphoxide-client/src/multi.rs b/euphoxide-client/src/multi.rs index 95ea996..f3f9559 100644 --- a/euphoxide-client/src/multi.rs +++ b/euphoxide-client/src/multi.rs @@ -4,6 +4,7 @@ use euphoxide::{ api::ParsedPacket, client::{conn::ClientConnHandle, state::State}, }; +use jiff::Timestamp; use tokio::{ select, sync::{mpsc, oneshot}, @@ -160,6 +161,7 @@ impl MultiClientTask { pub struct MultiClient { config: Arc, cmd_tx: mpsc::Sender, + start_time: Timestamp, } impl MultiClient { @@ -171,6 +173,8 @@ impl MultiClient { config: MultiClientConfig, event_tx: mpsc::Sender, ) -> Self { + let start_time = Timestamp::now(); + let config = Arc::new(config); let out_tx = event_tx; @@ -188,7 +192,15 @@ impl MultiClient { tokio::task::spawn(task.run()); - Self { config, cmd_tx } + Self { + config, + cmd_tx, + start_time, + } + } + + pub fn start_time(&self) -> Timestamp { + self.start_time } pub async fn get_clients(&self) -> Vec { diff --git a/euphoxide-client/src/single.rs b/euphoxide-client/src/single.rs index b6b54c6..6b54a3c 100644 --- a/euphoxide-client/src/single.rs +++ b/euphoxide-client/src/single.rs @@ -8,6 +8,7 @@ use euphoxide::{ state::State, }, }; +use jiff::Timestamp; use log::warn; use tokio::{ select, @@ -337,6 +338,7 @@ impl ClientTask { pub struct Client { id: usize, cmd_tx: mpsc::Sender, + start_time: Timestamp, } impl fmt::Debug for Client { @@ -349,6 +351,8 @@ impl fmt::Debug for Client { impl Client { pub fn new(id: usize, config: ClientConfig, event_tx: mpsc::Sender) -> Self { + let start_time = Timestamp::now(); + let (cmd_tx, cmd_rx) = mpsc::channel(config.server.cmd_channel_bufsize); let task = ClientTask { @@ -362,13 +366,21 @@ impl Client { tokio::task::spawn(task.run()); - Self { id, cmd_tx } + Self { + id, + cmd_tx, + start_time, + } } pub fn id(&self) -> usize { self.id } + pub fn start_time(&self) -> Timestamp { + self.start_time + } + pub fn stopped(&self) -> bool { self.cmd_tx.is_closed() }