Add who command.
This commit is contained in:
parent
29b02407fa
commit
2053c9cbb3
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -131,6 +131,7 @@ dependencies = [
|
||||
"deadpool",
|
||||
"deadpool-postgres",
|
||||
"futures",
|
||||
"humantime",
|
||||
"itertools",
|
||||
"log",
|
||||
"nix",
|
||||
@ -683,6 +684,12 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.14.23"
|
||||
|
@ -37,3 +37,4 @@ once_cell = "1.16.0"
|
||||
rand = "0.8.5"
|
||||
async-recursion = "1.0.0"
|
||||
rand_distr = "0.4.3"
|
||||
humantime = "2.1.0"
|
||||
|
@ -18,8 +18,10 @@ use crate::models::{
|
||||
use tokio_postgres::types::ToSql;
|
||||
use std::collections::BTreeSet;
|
||||
use std::sync::Arc;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use serde_json::{self, Value};
|
||||
use futures::FutureExt;
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DBPool {
|
||||
@ -53,6 +55,12 @@ impl From<Row> for SendqueueItem {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct OnlineInfo {
|
||||
pub username: String,
|
||||
pub time: Option<DateTime<Utc>>
|
||||
}
|
||||
|
||||
impl DBPool {
|
||||
pub async fn record_listener_ping(self: &DBPool, listener: Uuid) -> DResult<()> {
|
||||
self.get_conn().await?.execute(
|
||||
@ -176,6 +184,14 @@ impl DBPool {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn bump_session_time(&self, session: &ListenerSession) -> DResult<()> {
|
||||
self.get_conn().await?.query(
|
||||
"UPDATE sessions SET details=JSONB_SET(details, '{last_active}', to_json(NOW())::jsonb) \
|
||||
WHERE session = $1", &[&session.session]
|
||||
).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_conn(self: &DBPool) ->
|
||||
DResult<Object> {
|
||||
let conn = self.pool.get().await?;
|
||||
@ -591,6 +607,20 @@ impl DBTrans {
|
||||
pub async fn alloc_item_code(&self) -> DResult<i64> {
|
||||
Ok(self.pg_trans()?.query_one("SELECT NEXTVAL('item_seq')", &[]).await?.get(0))
|
||||
}
|
||||
|
||||
pub async fn get_online_info(&self) ->DResult<Vec<OnlineInfo>> {
|
||||
Ok(self.pg_trans()?.query(
|
||||
"SELECT jsonb_build_object(\
|
||||
'username', u.details->>'username',\
|
||||
'time', s.details->>'last_active'\
|
||||
) FROM sessions s \
|
||||
JOIN users u ON u.current_session = s.session \
|
||||
ORDER BY s.details->>'last_active' DESC", &[]
|
||||
).await?
|
||||
.into_iter()
|
||||
.filter_map(|row| serde_json::from_value(row.get(0)).ok())
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub async fn commit(mut self: Self) -> DResult<()> {
|
||||
let trans_opt = self.with_trans_mut(|t| std::mem::replace(t, None));
|
||||
|
@ -24,6 +24,7 @@ mod quit;
|
||||
mod register;
|
||||
pub mod say;
|
||||
mod whisper;
|
||||
mod who;
|
||||
|
||||
pub struct VerbContext<'l> {
|
||||
pub session: &'l ListenerSession,
|
||||
@ -114,6 +115,8 @@ static REGISTERED_COMMANDS: UserVerbRegistry = phf_map! {
|
||||
"-" => whisper::VERB,
|
||||
"whisper" => whisper::VERB,
|
||||
"tell" => whisper::VERB,
|
||||
|
||||
"who" => who::VERB,
|
||||
};
|
||||
|
||||
fn resolve_handler(ctx: &VerbContext, cmd: &str) -> Option<&'static UserVerbRef> {
|
||||
@ -173,6 +176,7 @@ pub async fn handle(session: &ListenerSession, msg: &str, pool: &DBPool) -> DRes
|
||||
}
|
||||
}
|
||||
}
|
||||
pool.bump_session_time(&session).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
31
blastmud_game/src/message_handler/user_commands/who.rs
Normal file
31
blastmud_game/src/message_handler/user_commands/who.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use super::{VerbContext, UserVerb, UserVerbRef, UResult};
|
||||
use async_trait::async_trait;
|
||||
use ansi::{ignore_special_characters, ansi};
|
||||
use chrono::Utc;
|
||||
|
||||
pub struct Verb;
|
||||
#[async_trait]
|
||||
impl UserVerb for Verb {
|
||||
async fn handle(self: &Self, ctx: &mut VerbContext, _verb: &str, _remaining: &str) -> UResult<()> {
|
||||
let mut msg = String::new();
|
||||
msg.push_str(&format!(ansi!("<bold><bgblue><white>| {:20} | {:15} |<reset>\n"),
|
||||
ansi!("Username"),
|
||||
ansi!("Idle")));
|
||||
for online in ctx.trans.get_online_info().await? {
|
||||
if let Some(online_time) = online.time {
|
||||
let diff =
|
||||
humantime::format_duration(
|
||||
std::time::Duration::from_secs(
|
||||
(Utc::now() - online_time).num_seconds() as u64));
|
||||
msg.push_str(&format!(
|
||||
"| {:20} | {:15} |\n", &ignore_special_characters(&online.username),
|
||||
&format!("{}", &diff)));
|
||||
}
|
||||
}
|
||||
msg.push_str("\n");
|
||||
ctx.trans.queue_for_session(ctx.session, Some(&msg)).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
static VERB_INT: Verb = Verb;
|
||||
pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;
|
@ -1,6 +1,7 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::collections::VecDeque;
|
||||
use crate::regular_tasks::queued_command::QueueCommand;
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(default)]
|
||||
@ -8,6 +9,7 @@ pub struct Session {
|
||||
pub source: String,
|
||||
pub less_explicit_mode: bool,
|
||||
pub queue: VecDeque<QueueCommand>,
|
||||
pub last_active: Option<DateTime<Utc>>,
|
||||
// Reminder: Consider backwards compatibility when updating this. New fields should generally
|
||||
// be an Option, or you should ensure the default value is sensible, or things will
|
||||
// crash out for existing sessions.
|
||||
@ -26,6 +28,6 @@ impl Session {
|
||||
impl Default for Session {
|
||||
fn default() -> Self {
|
||||
Session { source: "unknown".to_owned(), less_explicit_mode: false,
|
||||
queue: VecDeque::new() }
|
||||
queue: VecDeque::new(), last_active: None }
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user