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);