zulip-api 0.0.8

Client library for interacting with the Zulip API
Documentation
use serde::{Deserialize, Serialize};

use crate::{field_access, impl_default, impl_display};

/// Represents the collection of [Presence] entries.
pub type PresenceList = std::collections::HashMap<String, Presence>;

/// Represents one of these two formats (modern or legacy) for user presence data:
///
/// - [ModernPresenceFormat]
/// - [LegacyPresenceFormat]
///
/// Modified from `openapi-generator-cli` output:
///
/// ```shell,no_build,no_run
/// $ openapi-generator-cli generate -g rust -i ./zerver/openapi/zulip.yaml -o zulip-openapi --skip-validate-spec
/// ```
///
/// ```text
/// /*
/// * Zulip REST API
/// *
/// * Powerful open source group chat
/// *
/// * The version of the OpenAPI document: 1.0.0
/// *
/// * Generated by: https://openapi-generator.tech
/// */
/// ```
///
/// See [zerver/openapi/zulip.yaml](https://github.com/zulip/zulip/blob/main/zerver/openapi/zulip.yaml) for the original OpenAPI configuration.
///
/// Configuration slightly modified to work with the Rust generator of [`openapi-generator-cli`](https://openapi-generator.tech).
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Presence {
    /// Modern presence format.
    ModernPresenceFormat(ModernPresenceFormat),
    /// Presence data (legacy format) for the user with the specified Zulip API email in the parent collection.
    ///
    /// The key is the `client-key` used to identify which client sent presence information.
    LegacyPresenceFormat(std::collections::HashMap<String, LegacyPresenceFormat>),
}

impl Presence {
    /// Creates a new [Presence].
    pub const fn new() -> Self {
        Self::ModernPresenceFormat(ModernPresenceFormat::new())
    }
}

impl_default!(Presence);
impl_display!(Presence);

/// Represents presence data (modern format) for the user with the specified ID.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ModernPresenceFormat {
    #[serde(skip_serializing_if = "Option::is_none")]
    active_timestamp: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    idle_timestamp: Option<u64>,
}

impl ModernPresenceFormat {
    /// Creates a new [ModernPresenceFormat].
    pub const fn new() -> Self {
        Self {
            active_timestamp: None,
            idle_timestamp: None,
        }
    }
}

field_access! {
    ModernPresenceFormat {
        /// The UNIX timestamp of the last time a client connected to Zulip reported that the user was actually present
        /// (e.g. via focusing a browser window or interacting with a computer running the desktop app).
        ///
        /// Clients should display users with a current `active_timestamp` as fully present.
        active_timestamp: option { u64 },
        /// The UNIX timestamp of the last time the user had a client connected to Zulip,
        /// including idle clients where the user hasn't interacted with the system recently.
        ///
        /// The Zulip server has no way of distinguishing whether an idle web app user is at their computer,
        /// but hasn't interacted with the Zulip tab recently, or simply left their desktop computer on when they left.
        ///
        /// Thus, clients should display users with a current `idle_timestamp` but no current `active_timestamp` as potentially present.
        idle_timestamp: option { u64 },
    }
}

impl_default!(ModernPresenceFormat);
impl_display!(ModernPresenceFormat);

/// Represents the details of the user's presence.
///
/// **Changes**: Starting with Zulip 7.0 (feature level 178), this will always contain two keys,
/// `\"website\"` and `\"aggregated\"`, with identical data. The server no longer stores which client submitted presence updates.
///
/// 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`.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct LegacyPresenceFormat {
    #[serde(skip_serializing_if = "Option::is_none")]
    client: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    status: Option<LegacyPresenceStatus>,
    #[serde(skip_serializing_if = "Option::is_none")]
    timestamp: Option<i32>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pushable: Option<bool>,
}

impl LegacyPresenceFormat {
    /// creates a new [LegacyPresenceFormat].
    pub const fn new() -> Self {
        Self {
            client: None,
            status: None,
            timestamp: None,
            pushable: None,
        }
    }
}

field_access! {
    LegacyPresenceFormat {
        /// The client's platform name.
        ///
        /// **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.
        client: option_cow_deref { str, String },
    }
}

field_access! {
    LegacyPresenceFormat {
        /// The status of the user on this client. Will be either `"idle"` or `"active"`.
        status: option { LegacyPresenceStatus },
        /// The UNIX timestamp of when this client sent the user's presence to the server with the precision of a second.
        timestamp: option { i32 },
        /// Whether the client is capable of showing mobile/push notifications to the user.
        ///
        /// Not present in objects with the `\"aggregated\"` key.
        ///
        /// **Changes**: Starting with Zulip 7.0 (feature level 178), always `false` when present as the server no longer stores which client submitted presence data.
        pushable: option { bool },
    }
}

impl_default!(LegacyPresenceFormat);
impl_display!(LegacyPresenceFormat);

/// The status of the user on this client. Will be either `"idle"` or `"active"`.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum LegacyPresenceStatus {
    Idle,
    Active,
}

impl LegacyPresenceStatus {
    /// Creates a new [LegacyPresenceStatus].
    pub const fn new() -> Self {
        Self::Idle
    }
}

impl_default!(LegacyPresenceStatus);
impl_display!(LegacyPresenceStatus);