Skip to main content

roowho2_lib/server/varlink_api/
rwhod.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4use zlink::ReplyError;
5
6use crate::{
7    proto::{WhodStatusUpdate, WhodUserEntry},
8    server::rwhod::RwhodStatusStore,
9};
10
11#[zlink::proxy("no.ntnu.pvv.roowho2.rwhod")]
12pub trait VarlinkRwhodClientProxy {
13    /// `max_idle_seconds` is the maximum idle time (in seconds) for a user
14    /// to be included in the response. `None` means no limit (i.e. the old
15    /// `all: true`). The client is expected to always send an explicit
16    /// value, defaulting to whatever it considers reasonable if the user
17    /// didn't ask for a specific limit.
18    async fn rwho(
19        &mut self,
20        max_idle_seconds: Option<i64>,
21    ) -> zlink::Result<Result<VarlinkRwhoResponse, VarlinkRwhodClientError>>;
22
23    /// See [`VarlinkRwhodClientProxy::rwho`] for the meaning of `max_idle_seconds`.
24    async fn ruptime(
25        &mut self,
26        max_idle_seconds: Option<i64>,
27    ) -> zlink::Result<Result<VarlinkRuptimeResponse, VarlinkRwhodClientError>>;
28}
29
30#[derive(Debug, Deserialize)]
31#[serde(tag = "method", content = "parameters")]
32pub enum VarlinkRwhodClientRequest {
33    #[serde(rename = "no.ntnu.pvv.roowho2.rwhod.Rwho")]
34    Rwho {
35        /// Maximum idle time (in seconds) for a user to be included.
36        /// `None` means no limit (i.e. return all users).
37        max_idle_seconds: Option<i64>,
38    },
39
40    #[serde(rename = "no.ntnu.pvv.roowho2.rwhod.Ruptime")]
41    Ruptime {
42        /// Maximum idle time (in seconds) for a user to be counted.
43        /// `None` means no limit (i.e. return all users).
44        max_idle_seconds: Option<i64>,
45    },
46}
47
48#[derive(Debug, Clone, PartialEq, Serialize)]
49#[serde(untagged)]
50pub enum VarlinkRwhodClientResponse {
51    Rwho(VarlinkRwhoResponse),
52    Ruptime(VarlinkRuptimeResponse),
53}
54
55pub type VarlinkRwhoResponse = HashMap<String, Vec<WhodUserEntry>>;
56pub type VarlinkRuptimeResponse = Vec<WhodStatusUpdate>;
57
58#[derive(Debug, Clone, PartialEq, ReplyError)]
59#[zlink(interface = "no.ntnu.pvv.roowho2.rwhod")]
60pub enum VarlinkRwhodClientError {
61    InvalidRequest,
62    TimedOut,
63    Disabled,
64}
65
66pub async fn handle_rwho_request(
67    whod_status_store: &RwhodStatusStore,
68    max_idle_time: Option<chrono::TimeDelta>,
69) -> VarlinkRwhoResponse {
70    tracing::debug!(?max_idle_time, "Handling Rwho request");
71    let store = whod_status_store.read().await;
72
73    store
74        .values()
75        .filter_map(|status_update| {
76            let users: Vec<WhodUserEntry> = status_update
77                .users
78                .iter()
79                .filter(|user| max_idle_time.is_none_or(|max| user.idle_time < max))
80                .cloned()
81                .collect();
82
83            (!users.is_empty()).then(|| (status_update.hostname.clone(), users))
84        })
85        .collect()
86}
87
88pub async fn handle_ruptime_request(
89    whod_status_store: &RwhodStatusStore,
90    max_idle_time: Option<chrono::TimeDelta>,
91) -> VarlinkRuptimeResponse {
92    tracing::debug!(?max_idle_time, "Handling Ruptime request");
93    let store = whod_status_store.read().await;
94
95    store
96        .values()
97        .cloned()
98        .map(|mut status_update| {
99            if let Some(max_idle_time) = max_idle_time {
100                status_update
101                    .users
102                    .retain(|user| user.idle_time < max_idle_time);
103            }
104            status_update
105        })
106        .collect()
107}