Skip to main content

zulip_api/message/
presence.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{field_access, impl_default, impl_display};
4
5/// Represents the collection of [Presence] entries.
6pub type PresenceList = std::collections::HashMap<String, Presence>;
7
8/// Represents one of these two formats (modern or legacy) for user presence data:
9///
10/// - [ModernPresenceFormat]
11/// - [LegacyPresenceFormat]
12///
13/// Modified from `openapi-generator-cli` output:
14///
15/// ```shell,no_build,no_run
16/// $ openapi-generator-cli generate -g rust -i ./zerver/openapi/zulip.yaml -o zulip-openapi --skip-validate-spec
17/// ```
18///
19/// ```text
20/// /*
21/// * Zulip REST API
22/// *
23/// * Powerful open source group chat
24/// *
25/// * The version of the OpenAPI document: 1.0.0
26/// *
27/// * Generated by: https://openapi-generator.tech
28/// */
29/// ```
30///
31/// See [zerver/openapi/zulip.yaml](https://github.com/zulip/zulip/blob/main/zerver/openapi/zulip.yaml) for the original OpenAPI configuration.
32///
33/// Configuration slightly modified to work with the Rust generator of [`openapi-generator-cli`](https://openapi-generator.tech).
34#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
35#[serde(untagged)]
36pub enum Presence {
37    /// Modern presence format.
38    ModernPresenceFormat(ModernPresenceFormat),
39    /// Presence data (legacy format) for the user with the specified Zulip API email in the parent collection.
40    ///
41    /// The key is the `client-key` used to identify which client sent presence information.
42    LegacyPresenceFormat(std::collections::HashMap<String, LegacyPresenceFormat>),
43}
44
45impl Presence {
46    /// Creates a new [Presence].
47    pub const fn new() -> Self {
48        Self::ModernPresenceFormat(ModernPresenceFormat::new())
49    }
50}
51
52impl_default!(Presence);
53impl_display!(Presence);
54
55/// Represents presence data (modern format) for the user with the specified ID.
56#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
57pub struct ModernPresenceFormat {
58    #[serde(skip_serializing_if = "Option::is_none")]
59    active_timestamp: Option<u64>,
60    #[serde(skip_serializing_if = "Option::is_none")]
61    idle_timestamp: Option<u64>,
62}
63
64impl ModernPresenceFormat {
65    /// Creates a new [ModernPresenceFormat].
66    pub const fn new() -> Self {
67        Self {
68            active_timestamp: None,
69            idle_timestamp: None,
70        }
71    }
72}
73
74field_access! {
75    ModernPresenceFormat {
76        /// The UNIX timestamp of the last time a client connected to Zulip reported that the user was actually present
77        /// (e.g. via focusing a browser window or interacting with a computer running the desktop app).
78        ///
79        /// Clients should display users with a current `active_timestamp` as fully present.
80        active_timestamp: option { u64 },
81        /// The UNIX timestamp of the last time the user had a client connected to Zulip,
82        /// including idle clients where the user hasn't interacted with the system recently.
83        ///
84        /// The Zulip server has no way of distinguishing whether an idle web app user is at their computer,
85        /// but hasn't interacted with the Zulip tab recently, or simply left their desktop computer on when they left.
86        ///
87        /// Thus, clients should display users with a current `idle_timestamp` but no current `active_timestamp` as potentially present.
88        idle_timestamp: option { u64 },
89    }
90}
91
92impl_default!(ModernPresenceFormat);
93impl_display!(ModernPresenceFormat);
94
95/// Represents the details of the user's presence.
96///
97/// **Changes**: Starting with Zulip 7.0 (feature level 178), this will always contain two keys,
98/// `\"website\"` and `\"aggregated\"`, with identical data. The server no longer stores which client submitted presence updates.
99///
100/// Previously, the `{client_name}` keys for these objects were the names of the different clients where the user was logged in, for example `website` or `ZulipDesktop`.
101#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
102pub struct LegacyPresenceFormat {
103    #[serde(skip_serializing_if = "Option::is_none")]
104    client: Option<String>,
105    #[serde(skip_serializing_if = "Option::is_none")]
106    status: Option<LegacyPresenceStatus>,
107    #[serde(skip_serializing_if = "Option::is_none")]
108    timestamp: Option<i32>,
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pushable: Option<bool>,
111}
112
113impl LegacyPresenceFormat {
114    /// creates a new [LegacyPresenceFormat].
115    pub const fn new() -> Self {
116        Self {
117            client: None,
118            status: None,
119            timestamp: None,
120            pushable: None,
121        }
122    }
123}
124
125field_access! {
126    LegacyPresenceFormat {
127        /// The client's platform name.
128        ///
129        /// **Changes**: Starting with Zulip 7.0 (feature level 178), this will always be `\"website\"` as the server no longer stores which client submitted presence data.
130        client: option_cow_deref { str, String },
131    }
132}
133
134field_access! {
135    LegacyPresenceFormat {
136        /// The status of the user on this client. Will be either `"idle"` or `"active"`.
137        status: option { LegacyPresenceStatus },
138        /// The UNIX timestamp of when this client sent the user's presence to the server with the precision of a second.
139        timestamp: option { i32 },
140        /// Whether the client is capable of showing mobile/push notifications to the user.
141        ///
142        /// Not present in objects with the `\"aggregated\"` key.
143        ///
144        /// **Changes**: Starting with Zulip 7.0 (feature level 178), always `false` when present as the server no longer stores which client submitted presence data.
145        pushable: option { bool },
146    }
147}
148
149impl_default!(LegacyPresenceFormat);
150impl_display!(LegacyPresenceFormat);
151
152/// The status of the user on this client. Will be either `"idle"` or `"active"`.
153#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
154#[serde(rename_all = "snake_case")]
155pub enum LegacyPresenceStatus {
156    Idle,
157    Active,
158}
159
160impl LegacyPresenceStatus {
161    /// Creates a new [LegacyPresenceStatus].
162    pub const fn new() -> Self {
163        Self::Idle
164    }
165}
166
167impl_default!(LegacyPresenceStatus);
168impl_display!(LegacyPresenceStatus);