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 metadata for a attachment in a Zulip message.
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct Attachment {
    #[serde(skip_serializing_if = "Option::is_none")]
    id: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    name: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    path_id: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    size: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    create_time: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    messages: Option<Vec<AttachmentMessage>>,
}

impl Attachment {
    /// Creates a new [Attachment].
    pub const fn new() -> Self {
        Self {
            id: None,
            name: None,
            path_id: None,
            size: None,
            create_time: None,
            messages: None,
        }
    }
}

field_access! {
    Attachment {
        /// The unique ID for the attachment.
        id: option { u64 },
        /// Size of the file in bytes.
        size: option { u64 },
        /// Time when the attachment was uploaded as a UNIX timestamp
        /// multiplied by 1000 (matching the format of getTime() in JavaScript).
        ///
        /// **Changes**: Changed in Zulip 3.0 (feature level 22). This field was
        /// previously a floating point number.
        create_time: option { u64 },
    }
}

field_access! {
    Attachment {
        /// Name of the uploaded file.
        name: option_cow_deref { str, String },
        /// A representation of the path of the file within the
        /// repository of user-uploaded files. If the `path_id` of a
        /// file is `{realm_id}/ab/cdef/temp_file.py`, its URL will be:
        /// `{server_url}/user_uploads/{realm_id}/ab/cdef/temp_file.py`.
        path_id: option_cow_deref { str, String },
        /// Contains basic details on any Zulip messages that have been
        /// sent referencing this [uploaded file](/api/upload-file).
        /// This includes messages sent by any user in the Zulip
        /// organization who sent a message containing a link to the
        /// uploaded file.
        messages: option_cow_deref { [AttachmentMessage], Vec<AttachmentMessage> },
    }
}

impl_default!(Attachment);
impl_display!(Attachment);

/// Represents metadata for a attachment message in a Zulip message.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct AttachmentMessage {
    #[serde(skip_serializing_if = "Option::is_none")]
    date_sent: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    id: Option<u64>,
}

impl AttachmentMessage {
    /// Creates a new [AttachmentMessage].
    pub const fn new() -> Self {
        Self {
            date_sent: None,
            id: None,
        }
    }
}

field_access! {
    AttachmentMessage {
        date_sent: option { u64 },
        id: option { u64 },
    }
}

impl_default!(AttachmentMessage);
impl_display!(AttachmentMessage);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_attachment() {
        let id = 1;
        let id_json = serde_json::to_string(&id).unwrap();

        let name = "name";
        let name_json = serde_json::to_string(&name).unwrap();

        let path_id = "path_id";
        let path_id_json = serde_json::to_string(&path_id).unwrap();

        let size = 2;
        let size_json = serde_json::to_string(&size).unwrap();

        let create_time = 3;
        let create_time_json = serde_json::to_string(&create_time).unwrap();

        let msg_date_sent = 4;
        let msg_id = 5;

        let detached_msg = AttachmentMessage::new()
            .with_date_sent(msg_date_sent)
            .with_id(msg_id);

        let messages = vec![detached_msg];
        let messages_json = serde_json::to_string(&messages).unwrap();

        let detached = Attachment::new()
            .with_id(id)
            .with_name(name)
            .with_path_id(path_id)
            .with_size(size)
            .with_create_time(create_time)
            .with_messages(messages.as_slice());

        let detached_json = format!(
            r#"{{"id":{id_json},"name":{name_json},"path_id":{path_id_json},"size":{size_json},"create_time":{create_time_json},"messages":{messages_json}}}"#
        );

        assert_eq!(detached.id(), Some(id));
        assert_eq!(detached.name(), Some(name));
        assert_eq!(detached.path_id(), Some(path_id));
        assert_eq!(detached.size(), Some(size));
        assert_eq!(detached.create_time(), Some(create_time));
        assert_eq!(detached.messages(), Some(messages.as_slice()));

        assert_eq!(serde_json::to_string(&detached).unwrap(), detached_json);
        assert_eq!(
            serde_json::from_str::<Attachment>(&detached_json).unwrap(),
            detached
        );
    }

    #[test]
    fn test_attachment_message() {
        let date_sent = 1;
        let date_sent_json = serde_json::to_string(&date_sent).unwrap();

        let id = 2;
        let id_json = serde_json::to_string(&id).unwrap();

        let detached = AttachmentMessage::new()
            .with_date_sent(date_sent)
            .with_id(id);

        let detached_json = format!(r#"{{"date_sent":{date_sent_json},"id":{id_json}}}"#);

        assert_eq!(detached.date_sent(), Some(date_sent));
        assert_eq!(detached.id(), Some(id));

        assert_eq!(serde_json::to_string(&detached).unwrap(), detached_json);
        assert_eq!(
            serde_json::from_str::<AttachmentMessage>(&detached_json).unwrap(),
            detached
        );
    }
}