rwho: render --json response as dict
This commit is contained in:
+37
-16
@@ -1,3 +1,5 @@
|
|||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use clap::{CommandFactory, Parser};
|
use clap::{CommandFactory, Parser};
|
||||||
use clap_complete::{Shell, generate};
|
use clap_complete::{Shell, generate};
|
||||||
@@ -63,7 +65,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
.await
|
.await
|
||||||
.expect("Failed to connect to rwhod server");
|
.expect("Failed to connect to rwhod server");
|
||||||
|
|
||||||
let mut reply = conn
|
let reply = conn
|
||||||
.rwho(max_idle_seconds)
|
.rwho(max_idle_seconds)
|
||||||
.await
|
.await
|
||||||
.context("Failed to send rwho request")?
|
.context("Failed to send rwho request")?
|
||||||
@@ -79,23 +81,42 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
reply.sort_by(|(host, user), (host2, user2)| {
|
|
||||||
user.user_id
|
|
||||||
.cmp(&user2.user_id)
|
|
||||||
.then_with(|| host.cmp(host2))
|
|
||||||
.then_with(|| user.tty.cmp(&user2.tty))
|
|
||||||
});
|
|
||||||
|
|
||||||
if args.json {
|
if args.json {
|
||||||
println!("{}", serde_json::to_string_pretty(&reply).unwrap());
|
let sorted: BTreeMap<String, Vec<WhodUserEntry>> = reply
|
||||||
} else if args.old {
|
.into_iter()
|
||||||
old_format_user_entries(&reply)
|
.map(|(hostname, mut users)| {
|
||||||
.iter()
|
users.sort_by(|a, b| a.user_id.cmp(&b.user_id).then_with(|| a.tty.cmp(&b.tty)));
|
||||||
.for_each(|line| println!("{}", line));
|
(hostname, users)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
println!("{}", serde_json::to_string_pretty(&sorted).unwrap());
|
||||||
} else {
|
} else {
|
||||||
old_format_user_entries(&reply)
|
let mut entries: Vec<(String, WhodUserEntry)> = reply
|
||||||
.iter()
|
.into_iter()
|
||||||
.for_each(|line| println!("{}", line));
|
.flat_map(|(hostname, users)| {
|
||||||
|
users
|
||||||
|
.into_iter()
|
||||||
|
.map(move |user| (hostname.clone(), user))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
entries.sort_by(|(host, user), (host2, user2)| {
|
||||||
|
user.user_id
|
||||||
|
.cmp(&user2.user_id)
|
||||||
|
.then_with(|| host.cmp(host2))
|
||||||
|
.then_with(|| user.tty.cmp(&user2.tty))
|
||||||
|
});
|
||||||
|
|
||||||
|
if args.old {
|
||||||
|
old_format_user_entries(&entries)
|
||||||
|
.iter()
|
||||||
|
.for_each(|line| println!("{}", line));
|
||||||
|
} else {
|
||||||
|
// TODO: add a newer and nicer format here
|
||||||
|
old_format_user_entries(&entries)
|
||||||
|
.iter()
|
||||||
|
.for_each(|line| println!("{}", line));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
+10
-10
@@ -1,4 +1,4 @@
|
|||||||
use std::{os::fd::OwnedFd, time::Duration};
|
use std::{collections::HashMap, os::fd::OwnedFd, time::Duration};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use futures_util::stream;
|
use futures_util::stream;
|
||||||
@@ -66,7 +66,7 @@ pub enum VarlinkRwhodClientResponse {
|
|||||||
Ruptime(VarlinkRuptimeResponse),
|
Ruptime(VarlinkRuptimeResponse),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type VarlinkRwhoResponse = Vec<(String, WhodUserEntry)>;
|
pub type VarlinkRwhoResponse = HashMap<String, Vec<WhodUserEntry>>;
|
||||||
pub type VarlinkRuptimeResponse = Vec<WhodStatusUpdate>;
|
pub type VarlinkRuptimeResponse = Vec<WhodStatusUpdate>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, ReplyError)]
|
#[derive(Debug, Clone, PartialEq, ReplyError)]
|
||||||
@@ -180,19 +180,19 @@ impl VarlinkRoowhoo2ClientServer {
|
|||||||
tracing::debug!(?max_idle_time, "Handling Rwho request");
|
tracing::debug!(?max_idle_time, "Handling Rwho request");
|
||||||
let store = self.whod_status_store.read().await;
|
let store = self.whod_status_store.read().await;
|
||||||
|
|
||||||
let mut all_user_entries = Vec::with_capacity(store.len());
|
store
|
||||||
for status_update in store.values() {
|
.values()
|
||||||
all_user_entries.extend(
|
.filter_map(|status_update| {
|
||||||
status_update
|
let users: Vec<WhodUserEntry> = status_update
|
||||||
.users
|
.users
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|user| max_idle_time.is_none_or(|max| user.idle_time < max))
|
.filter(|user| max_idle_time.is_none_or(|max| user.idle_time < max))
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|user| (status_update.hostname.clone(), user)),
|
.collect();
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
all_user_entries
|
(!users.is_empty()).then(|| (status_update.hostname.clone(), users))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_ruptime_request(
|
async fn handle_ruptime_request(
|
||||||
|
|||||||
Reference in New Issue
Block a user