zulip-api 0.0.8

Client library for interacting with the Zulip API
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
//! Message types for the Zulip API.

use serde::{Deserialize, Serialize};

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

mod attachment;
mod basic_channel;
mod bot;
mod bot_service;
mod bot_type;
mod channel_folder;
mod channel_permission;
mod client_capabilities;
mod content_type;
mod cross_realm_bot;
mod custom_profile;
mod default_channel_group;
mod display_recipient;
mod draft;
mod edit_history;
mod event_type;
mod flag;
mod giphy_rating_option;
mod group_permission_setting;
mod group_setting;
mod include_subscribers;
mod msg_type;
mod muted_topic;
mod muted_user;
mod navigation_view;
mod never_subscribed;
mod onboarding_step;
mod operation;
mod presence;
mod profile_data;
mod propagate_mode;
mod push_device;
mod reaction;
mod realm_authentication_method;
mod realm_available_video_chat_provider;
mod realm_billing;
mod realm_create_private_stream_policy;
mod realm_create_public_stream_policy;
mod realm_create_web_public_stream_policy;
mod realm_default_external_account;
mod realm_domain;
mod realm_embedded_bot;
mod realm_emoji;
mod realm_filter;
mod realm_incoming_webhook_bot;
mod realm_linkifier;
mod realm_message_edit_history_visibility_policy;
mod realm_organization_type;
mod realm_plan_type;
mod realm_playground;
mod realm_user_settings_default;
mod realm_video_chat_provider;
mod realm_wildcard_mention_policy;
mod recent_private_conversation;
mod report_type;
mod role;
mod saved_snippet;
mod scheduled_message;
mod server_supported_permission_setting;
mod server_thumbnail_format;
mod submessage;
mod subscription;
mod to;
mod topic_link;
mod topics_policy;
mod unread_msgs;
mod user;
mod user_group;
mod user_settings;
mod user_status;
mod user_topic;
mod webhook_config;

pub mod delete_message;
pub mod edit_message;
pub mod emoji_reaction;
pub mod fetch_api_key;
pub mod get_file_temporary_url;
pub mod get_message;
pub mod get_message_history;
pub mod get_messages;
pub mod get_read_receipts;
pub mod mark_all_as_read;
pub mod mark_stream_as_read;
pub mod mark_topic_as_read;
pub mod matches_narrow;
pub mod register;
pub mod render;
pub mod report_message;
pub mod response;
pub mod send_message;
pub mod update_message_flags;
pub mod update_message_flags_narrow;
pub mod upload_file;

pub use attachment::{Attachment, AttachmentMessage};
pub use basic_channel::BasicChannel;
pub use bot::Bot;
pub use bot_service::{
    BotService, BotServiceEmbedded, BotServiceOutgoingWebhook, OutgoingWebhookInterface,
};
pub use bot_type::BotType;
pub use channel_folder::ChannelFolder;
pub use channel_permission::{
    CanAddSubscribersGroup, CanAdministerChannelGroup, CanDeleteAnyMessageGroup,
    CanDeleteOwnMessageGroup, CanMoveMessagesOutOfChannelGroup, CanMoveMessagesWithinChannelGroup,
    CanRemoveSubscribersGroup, CanResolveTopicsGroup, CanSendMessageGroup, CanSubscribeGroup,
};
pub use client_capabilities::ClientCapabilities;
pub use content_type::ContentType;
pub use cross_realm_bot::CrossRealmBot;
pub use custom_profile::{CustomProfileField, CustomProfileFieldType};
pub use default_channel_group::DefaultChannelGroup;
pub use display_recipient::{DisplayRecipient, UserRecipient};
pub use draft::{Draft, DraftType};
pub use edit_history::EditHistory;
pub use event_type::EventType;
pub use flag::Flag;
pub use giphy_rating_option::GiphyRatingOption;
pub use group_permission_setting::GroupPermissionSetting;
pub use group_setting::{GroupSetting, GroupSettingIds};
pub use include_subscribers::IncludeSubscribers;
pub use msg_type::MessageType;
pub use muted_topic::MutedTopic;
pub use muted_user::MutedUser;
pub use navigation_view::NavigationView;
pub use never_subscribed::NeverSubscribed;
pub use onboarding_step::{OnboardingStep, OnboardingType};
pub use operation::Operation;
pub use presence::{
    LegacyPresenceFormat, LegacyPresenceStatus, ModernPresenceFormat, Presence, PresenceList,
};
pub use profile_data::ProfileData;
pub use propagate_mode::PropagateMode;
pub use push_device::{PushDevice, PushDeviceStatus};
pub use reaction::{Reaction, ReactionType};
pub use realm_authentication_method::RealmAuthenticationMethod;
pub use realm_available_video_chat_provider::RealmAvailableVideoChatProvider;
pub use realm_billing::RealmBilling;
pub use realm_create_private_stream_policy::RealmCreatePrivateStreamPolicy;
pub use realm_create_public_stream_policy::RealmCreatePublicStreamPolicy;
pub use realm_create_web_public_stream_policy::RealmCreateWebPublicStreamPolicy;
pub use realm_default_external_account::RealmDefaultExternalAccount;
pub use realm_domain::RealmDomain;
pub use realm_embedded_bot::RealmEmbeddedBot;
pub use realm_emoji::RealmEmoji;
pub use realm_filter::RealmFilter;
pub use realm_incoming_webhook_bot::RealmIncomingWebhookBot;
pub use realm_linkifier::RealmLinkifier;
pub use realm_message_edit_history_visibility_policy::RealmMessageEditHistoryVisibilityPolicy;
pub use realm_organization_type::RealmOrganizationType;
pub use realm_plan_type::RealmPlanType;
pub use realm_playground::RealmPlayground;
pub use realm_user_settings_default::*;
pub use realm_video_chat_provider::RealmVideoChatProvider;
pub use realm_wildcard_mention_policy::RealmWildcardMentionPolicy;
pub use recent_private_conversation::RecentPrivateConversation;
pub use report_type::ReportType;
pub use role::Role;
pub use saved_snippet::SavedSnippet;
pub use scheduled_message::{ScheduledMessage, ScheduledMessageTo, ScheduledMessageType};
pub use server_supported_permission_setting::ServerSupportedPermissionSetting;
pub use server_thumbnail_format::ServerThumbnailFormat;
pub use submessage::Submessage;
pub use subscription::*;
pub use to::MessageTo;
pub use topic_link::TopicLink;
pub use topics_policy::TopicsPolicy;
pub use unread_msgs::{UnreadMsgs, UnreadMsgsHuddle, UnreadMsgsPm, UnreadMsgsStream};
pub use user::User;
pub use user_group::UserGroup;
pub use user_settings::{UserSettings, UserSettingsEmojisetChoice};
pub use user_status::UserStatus;
pub use user_topic::UserTopic;
pub use webhook_config::{WebhookConfigOption, WebhookUrlOption};

/// Represents a message returned by the Zulip API server.
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct Message {
    #[serde(skip_serializing_if = "Option::is_none")]
    avatar_url: Option<String>,
    client: String,
    content: String,
    content_type: ContentType,
    display_recipient: DisplayRecipient,
    edit_history: Option<Vec<EditHistory>>,
    id: u64,
    is_me_message: bool,
    last_edit_timestamp: Option<u64>,
    last_moved_timestamp: Option<u64>,
    reactions: Vec<Reaction>,
    recipient_id: u64,
    sender_email: String,
    sender_full_name: String,
    sender_id: u64,
    sender_realm_str: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    stream_id: Option<u64>,
    subject: String,
    submessages: Vec<Submessage>,
    timestamp: u64,
    #[serde(rename = "type")]
    msg_type: MessageType,
    flags: Vec<Flag>,
    #[serde(skip_serializing_if = "Option::is_none")]
    match_content: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    match_subject: Option<String>,
}

impl Message {
    /// Creates a new [Message].
    pub const fn new() -> Self {
        Self {
            avatar_url: None,
            client: String::new(),
            content: String::new(),
            content_type: ContentType::new(),
            display_recipient: DisplayRecipient::new(),
            edit_history: None,
            id: 0,
            is_me_message: false,
            last_edit_timestamp: None,
            last_moved_timestamp: None,
            reactions: Vec::new(),
            recipient_id: 0,
            sender_email: String::new(),
            sender_full_name: String::new(),
            sender_id: 0,
            sender_realm_str: String::new(),
            stream_id: None,
            subject: String::new(),
            submessages: Vec::new(),
            timestamp: 0,
            msg_type: MessageType::new(),
            flags: Vec::new(),
            match_content: None,
            match_subject: None,
        }
    }
}

field_access! {
    Message {
        avatar_url: option_cow_deref { str, String },
        match_content: option_cow_deref { str, String },
        match_subject: option_cow_deref { str, String },
        edit_history: option_cow_deref { [EditHistory], Vec<EditHistory> },
    }
}

field_access! {
    Message {
        client: cow { str },
        content: cow { str },
        display_recipient: cow { DisplayRecipient },
    }
}

field_access! {
    Message {
        content_type: ContentType,
        id: u64,
        is_me_message: bool,
        recipient_id: u64,
        sender_id: u64,
        timestamp: u64,
        msg_type: MessageType,
    }
}

field_access! {
    Message {
        last_edit_timestamp: option { u64 },
        last_moved_timestamp: option { u64 },
        stream_id: option { u64 },
    }
}

field_access! {
    Message {
        reactions: cow { [Reaction] },
        sender_email: cow { str },
        sender_full_name: cow { str },
        sender_realm_str: cow { str },
        subject: cow { str },
        submessages: cow { [Submessage] },
        flags: cow { [Flag] },
    }
}

impl_cow!(Message);
impl_default!(Message);
impl_display!(Message);

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

    #[test]
    fn test_message_minimal() {
        let client = "client";
        let content = "content";
        let content_type = ContentType::Markdown;
        let display_recipient = DisplayRecipient::Channel("recipient channel".into());
        let id = 1;
        let is_me_message = false;
        let recipient_id = 4;
        let sender_email = "sender@example.com";
        let sender_full_name = "sender full name";
        let sender_id = 5;
        let sender_realm_str = "sender realm";
        let subject = "test subject";
        let timestamp = 7;
        let msg_type = MessageType::Channel;

        let message = Message::new()
            .with_client(client)
            .with_content(content)
            .with_content_type(content_type)
            .with_display_recipient(&display_recipient)
            .with_id(id)
            .with_is_me_message(is_me_message)
            .with_recipient_id(recipient_id)
            .with_sender_email(sender_email)
            .with_sender_full_name(sender_full_name)
            .with_sender_id(sender_id)
            .with_sender_realm_str(sender_realm_str)
            .with_subject(subject)
            .with_timestamp(timestamp)
            .with_msg_type(msg_type);

        let message_json = message.to_string();

        assert_eq!(message.client(), client);
        assert_eq!(message.content(), content);
        assert_eq!(message.content_type(), content_type);
        assert_eq!(message.display_recipient(), &display_recipient);
        assert_eq!(message.id(), id);
        assert_eq!(message.is_me_message(), is_me_message);
        assert_eq!(message.recipient_id(), recipient_id);
        assert_eq!(message.sender_email(), sender_email);
        assert_eq!(message.sender_full_name(), sender_full_name);
        assert_eq!(message.sender_id(), sender_id);
        assert_eq!(message.sender_realm_str(), sender_realm_str);
        assert_eq!(message.subject(), subject);
        assert_eq!(message.timestamp(), timestamp);
        assert_eq!(message.msg_type(), msg_type);

        assert_eq!(serde_json::to_string(&message).unwrap(), message_json);
        assert_eq!(
            serde_json::from_str::<Message>(&message_json).unwrap(),
            message
        );
    }

    #[test]
    fn test_message_full() {
        let avatar_url = "https://example.com/avatar";
        let client = "client";
        let content = "content";
        let content_type = ContentType::Markdown;
        let display_recipient = DisplayRecipient::Channel("recipient channel".into());
        let id = 1;
        let edit_history = [EditHistory::new()];
        let is_me_message = false;
        let last_edit_timestamp = 2;
        let last_moved_timestamp = 3;
        let reactions = [Reaction::new()];
        let recipient_id = 4;
        let sender_email = "sender@example.com";
        let sender_full_name = "sender full name";
        let sender_id = 5;
        let sender_realm_str = "sender realm";
        let stream_id = 6;
        let subject = "test subject";
        let submessages = [Submessage::new()];
        let timestamp = 7;
        let msg_type = MessageType::Channel;
        let flags = [Flag::Historical];
        let match_content = "match content";
        let match_subject = "match subject";

        let message = Message::new()
            .with_avatar_url(avatar_url)
            .with_client(client)
            .with_content(content)
            .with_content_type(content_type)
            .with_display_recipient(&display_recipient)
            .with_id(id)
            .with_edit_history(edit_history.as_ref())
            .with_is_me_message(is_me_message)
            .with_last_edit_timestamp(last_edit_timestamp)
            .with_last_moved_timestamp(last_moved_timestamp)
            .with_reactions(reactions.as_ref())
            .with_recipient_id(recipient_id)
            .with_sender_email(sender_email)
            .with_sender_full_name(sender_full_name)
            .with_sender_id(sender_id)
            .with_sender_realm_str(sender_realm_str)
            .with_stream_id(stream_id)
            .with_subject(subject)
            .with_submessages(submessages.as_ref())
            .with_timestamp(timestamp)
            .with_msg_type(msg_type)
            .with_flags(flags.as_ref())
            .with_match_content(match_content)
            .with_match_subject(match_subject);

        let message_json = message.to_string();

        assert_eq!(message.avatar_url(), Some(avatar_url));
        assert_eq!(message.client(), client);
        assert_eq!(message.content(), content);
        assert_eq!(message.content_type(), content_type);
        assert_eq!(message.display_recipient(), &display_recipient);
        assert_eq!(message.id(), id);
        assert_eq!(message.edit_history(), Some(edit_history.as_ref()));
        assert_eq!(message.is_me_message(), is_me_message);
        assert_eq!(message.last_edit_timestamp(), Some(last_edit_timestamp));
        assert_eq!(message.last_moved_timestamp(), Some(last_moved_timestamp));
        assert_eq!(message.reactions(), reactions.as_ref());
        assert_eq!(message.recipient_id(), recipient_id);
        assert_eq!(message.sender_email(), sender_email);
        assert_eq!(message.sender_full_name(), sender_full_name);
        assert_eq!(message.sender_id(), sender_id);
        assert_eq!(message.sender_realm_str(), sender_realm_str);
        assert_eq!(message.stream_id(), Some(stream_id));
        assert_eq!(message.subject(), subject);
        assert_eq!(message.submessages(), submessages.as_ref());
        assert_eq!(message.timestamp(), timestamp);
        assert_eq!(message.msg_type(), msg_type);
        assert_eq!(message.flags(), flags.as_ref());
        assert_eq!(message.match_content(), Some(match_content));
        assert_eq!(message.match_subject(), Some(match_subject));

        assert_eq!(serde_json::to_string(&message).unwrap(), message_json);
        assert_eq!(
            serde_json::from_str::<Message>(&message_json).unwrap(),
            message
        );
    }
}